blob: b5aa3d6b34b73af9741148eb2dd02186948f68ac [file] [log] [blame]
[email protected]294bdb32014-05-30 07:01:541// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This file tests that Service Workers (a Content feature) work in the Chromium
6// embedder.
7
8#include "base/bind.h"
horo61f3f4f2016-03-09 01:26:149#include "base/command_line.h"
[email protected]294bdb32014-05-30 07:01:5410#include "base/files/scoped_temp_dir.h"
11#include "base/numerics/safe_conversions.h"
Tsuyoshi Horo757835432018-11-15 00:21:3512#include "base/path_service.h"
[email protected]294bdb32014-05-30 07:01:5413#include "base/run_loop.h"
horo61f3f4f2016-03-09 01:26:1414#include "base/strings/stringprintf.h"
15#include "base/strings/utf_string_conversions.h"
Eric Seckler8652dcd52018-09-20 10:42:2816#include "base/task/post_task.h"
Devlin Cronin626d80c2018-06-01 01:08:3617#include "base/test/metrics/histogram_tester.h"
Matt Falkenhagenc0d0bac2018-12-18 08:31:0818#include "base/test/scoped_feature_list.h"
jam3f2d3932017-04-26 20:28:5119#include "base/threading/thread_restrictions.h"
grt56c07a22016-07-19 11:52:2020#include "build/build_config.h"
shimazuce8af88122016-10-06 23:49:2121#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
22#include "chrome/browser/content_settings/tab_specific_content_settings.h"
[email protected]294bdb32014-05-30 07:01:5423#include "chrome/browser/profiles/profile.h"
24#include "chrome/browser/ui/browser.h"
falken41f4175162014-10-29 07:03:4125#include "chrome/browser/ui/browser_window.h"
[email protected]294bdb32014-05-30 07:01:5426#include "chrome/browser/ui/tabs/tab_strip_model.h"
Tsuyoshi Horo757835432018-11-15 00:21:3527#include "chrome/common/chrome_paths.h"
horo61f3f4f2016-03-09 01:26:1428#include "chrome/common/chrome_switches.h"
[email protected]294bdb32014-05-30 07:01:5429#include "chrome/test/base/in_process_browser_test.h"
Matt Falkenhagenea306042018-11-29 00:45:2530#include "chrome/test/base/test_chrome_web_ui_controller_factory.h"
falken41f4175162014-10-29 07:03:4131#include "chrome/test/base/ui_test_utils.h"
shimazuce8af88122016-10-06 23:49:2132#include "components/content_settings/core/browser/host_content_settings_map.h"
Matt Falkenhagenc0d0bac2018-12-18 08:31:0833#include "components/content_settings/core/common/pref_names.h"
Tsuyoshi Horo757835432018-11-15 00:21:3534#include "components/favicon/content/content_favicon_driver.h"
35#include "components/favicon/core/favicon_driver_observer.h"
Scott Violet9ae82892018-03-01 18:38:1236#include "components/nacl/common/buildflags.h"
[email protected]294bdb32014-05-30 07:01:5437#include "content/public/browser/browser_context.h"
Eric Seckler8652dcd52018-09-20 10:42:2838#include "content/public/browser/browser_task_traits.h"
horo61f3f4f2016-03-09 01:26:1439#include "content/public/browser/render_frame_host.h"
[email protected]294bdb32014-05-30 07:01:5440#include "content/public/browser/service_worker_context.h"
41#include "content/public/browser/storage_partition.h"
Matt Falkenhagenea306042018-11-29 00:45:2542#include "content/public/browser/url_data_source.h"
[email protected]294bdb32014-05-30 07:01:5443#include "content/public/browser/web_contents.h"
Matt Falkenhagenea306042018-11-29 00:45:2544#include "content/public/browser/web_ui_controller.h"
horo61f3f4f2016-03-09 01:26:1445#include "content/public/test/browser_test_utils.h"
Tsuyoshi Horo757835432018-11-15 00:21:3546#include "net/dns/mock_host_resolver.h"
[email protected]294bdb32014-05-30 07:01:5447#include "net/test/embedded_test_server/embedded_test_server.h"
Matt Falkenhagenc0d0bac2018-12-18 08:31:0848#include "net/test/embedded_test_server/http_request.h"
49#include "net/test/embedded_test_server/http_response.h"
horo61f3f4f2016-03-09 01:26:1450#include "ppapi/shared_impl/ppapi_switches.h"
Zhuoyu Qian47ed0fc52018-09-06 02:13:4051#include "third_party/blink/public/common/messaging/string_message_codec.h"
Leon Hand0da4722019-07-11 08:12:0452#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
[email protected]294bdb32014-05-30 07:01:5453
Matt Falkenhagenea306042018-11-29 00:45:2554namespace chrome_service_worker_browser_test {
[email protected]294bdb32014-05-30 07:01:5455
Nico Weberaf3b00b2017-09-11 17:58:1756const char kInstallAndWaitForActivatedPage[] =
Tsuyoshi Horoa1c6f542017-06-13 15:22:4157 "<script>"
58 "navigator.serviceWorker.register('./sw.js', {scope: './scope/'})"
59 " .then(function(reg) {"
60 " reg.addEventListener('updatefound', function() {"
61 " var worker = reg.installing;"
62 " worker.addEventListener('statechange', function() {"
63 " if (worker.state == 'activated')"
64 " document.title = 'READY';"
65 " });"
66 " });"
67 " });"
68 "</script>";
69
[email protected]294bdb32014-05-30 07:01:5470class ChromeServiceWorkerTest : public InProcessBrowserTest {
71 protected:
72 ChromeServiceWorkerTest() {
73 EXPECT_TRUE(service_worker_dir_.CreateUniqueTempDir());
shimazuce8af88122016-10-06 23:49:2174 EXPECT_TRUE(base::CreateDirectoryAndGetError(
75 service_worker_dir_.GetPath().Append(
76 FILE_PATH_LITERAL("scope")), nullptr));
[email protected]294bdb32014-05-30 07:01:5477 }
horo61f3f4f2016-03-09 01:26:1478 ~ChromeServiceWorkerTest() override {}
[email protected]294bdb32014-05-30 07:01:5479
80 void WriteFile(const base::FilePath::StringType& filename,
81 base::StringPiece contents) {
Francois Doraye6fb2d02017-10-18 21:29:1382 base::ScopedAllowBlockingForTesting allow_blocking;
[email protected]294bdb32014-05-30 07:01:5483 EXPECT_EQ(base::checked_cast<int>(contents.size()),
vabr96fd0c0f2016-09-13 14:21:3184 base::WriteFile(service_worker_dir_.GetPath().Append(filename),
85 contents.data(), contents.size()));
[email protected]294bdb32014-05-30 07:01:5486 }
87
Tsuyoshi Horoa1c6f542017-06-13 15:22:4188 void NavigateToPageAndWaitForReadyTitle(const std::string path) {
89 const base::string16 expected_title1 = base::ASCIIToUTF16("READY");
90 content::TitleWatcher title_watcher1(
91 browser()->tab_strip_model()->GetActiveWebContents(), expected_title1);
92 ui_test_utils::NavigateToURL(browser(),
93 embedded_test_server()->GetURL(path));
94 EXPECT_EQ(expected_title1, title_watcher1.WaitAndGetTitle());
95 }
96
97 void InitializeServer() {
98 embedded_test_server()->ServeFilesFromDirectory(
99 service_worker_dir_.GetPath());
100 ASSERT_TRUE(embedded_test_server()->Start());
101 }
102
103 content::ServiceWorkerContext* GetServiceWorkerContext() {
104 return content::BrowserContext::GetDefaultStoragePartition(
105 browser()->profile())
106 ->GetServiceWorkerContext();
107 }
108
[email protected]294bdb32014-05-30 07:01:54109 base::ScopedTempDir service_worker_dir_;
horo61f3f4f2016-03-09 01:26:14110
111 private:
112 DISALLOW_COPY_AND_ASSIGN(ChromeServiceWorkerTest);
[email protected]294bdb32014-05-30 07:01:54113};
114
Tsuyoshi Horoa1c6f542017-06-13 15:22:41115template <typename T>
116static void ExpectResultAndRun(T expected,
[email protected]294bdb32014-05-30 07:01:54117 const base::Closure& continuation,
Tsuyoshi Horoa1c6f542017-06-13 15:22:41118 T actual) {
[email protected]294bdb32014-05-30 07:01:54119 EXPECT_EQ(expected, actual);
120 continuation.Run();
121}
122
123// http://crbug.com/368570
124IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerTest,
125 CanShutDownWithRegisteredServiceWorker) {
126 WriteFile(FILE_PATH_LITERAL("service_worker.js"), "");
[email protected]294bdb32014-05-30 07:01:54127
vabr96fd0c0f2016-09-13 14:21:31128 embedded_test_server()->ServeFilesFromDirectory(
129 service_worker_dir_.GetPath());
svaldeza01f7d92015-11-18 17:47:56130 ASSERT_TRUE(embedded_test_server()->Start());
[email protected]294bdb32014-05-30 07:01:54131
[email protected]294bdb32014-05-30 07:01:54132 base::RunLoop run_loop;
Emma Haruka Iwaobc302102017-12-05 02:33:08133 blink::mojom::ServiceWorkerRegistrationOptions options(
Asami Doi5de8dea2018-09-13 10:01:07134 embedded_test_server()->GetURL("/"), blink::mojom::ScriptType::kClassic,
Emma Haruka Iwaobc302102017-12-05 02:33:08135 blink::mojom::ServiceWorkerUpdateViaCache::kImports);
136 GetServiceWorkerContext()->RegisterServiceWorker(
137 embedded_test_server()->GetURL("/service_worker.js"), options,
Tsuyoshi Horoa1c6f542017-06-13 15:22:41138 base::Bind(&ExpectResultAndRun<bool>, true, run_loop.QuitClosure()));
[email protected]294bdb32014-05-30 07:01:54139 run_loop.Run();
140
141 // Leave the Service Worker registered, and make sure that the browser can
142 // shut down without DCHECK'ing. It'd be nice to check here that the SW is
143 // actually occupying a process, but we don't yet have the public interface to
144 // do that.
145}
146
falken41f4175162014-10-29 07:03:41147// http://crbug.com/419290
148IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerTest,
149 CanCloseIncognitoWindowWithServiceWorkerController) {
150 WriteFile(FILE_PATH_LITERAL("service_worker.js"), "");
151 WriteFile(FILE_PATH_LITERAL("service_worker.js.mock-http-headers"),
zmo9528c9f42015-08-04 22:12:08152 "HTTP/1.1 200 OK\nContent-Type: text/javascript");
falken41f4175162014-10-29 07:03:41153 WriteFile(FILE_PATH_LITERAL("test.html"), "");
Tsuyoshi Horoa1c6f542017-06-13 15:22:41154 InitializeServer();
falken41f4175162014-10-29 07:03:41155
156 Browser* incognito = CreateIncognitoBrowser();
falken41f4175162014-10-29 07:03:41157
158 base::RunLoop run_loop;
Emma Haruka Iwaobc302102017-12-05 02:33:08159 blink::mojom::ServiceWorkerRegistrationOptions options(
Asami Doi5de8dea2018-09-13 10:01:07160 embedded_test_server()->GetURL("/"), blink::mojom::ScriptType::kClassic,
Emma Haruka Iwaobc302102017-12-05 02:33:08161 blink::mojom::ServiceWorkerUpdateViaCache::kImports);
162 GetServiceWorkerContext()->RegisterServiceWorker(
163 embedded_test_server()->GetURL("/service_worker.js"), options,
Tsuyoshi Horoa1c6f542017-06-13 15:22:41164 base::Bind(&ExpectResultAndRun<bool>, true, run_loop.QuitClosure()));
falken41f4175162014-10-29 07:03:41165 run_loop.Run();
166
167 ui_test_utils::NavigateToURL(incognito,
168 embedded_test_server()->GetURL("/test.html"));
169
Qiang Xu2a41181f2018-04-11 22:38:32170 CloseBrowserSynchronously(incognito);
falken41f4175162014-10-29 07:03:41171
172 // Test passes if we don't crash.
173}
174
shimazuce8af88122016-10-06 23:49:21175IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerTest,
176 FailRegisterServiceWorkerWhenJSDisabled) {
177 WriteFile(FILE_PATH_LITERAL("service_worker.js"), "");
Tsuyoshi Horoa1c6f542017-06-13 15:22:41178 InitializeServer();
shimazuce8af88122016-10-06 23:49:21179
180 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:45181 ->SetDefaultContentSetting(ContentSettingsType::JAVASCRIPT,
shimazuce8af88122016-10-06 23:49:21182 CONTENT_SETTING_BLOCK);
183
shimazuce8af88122016-10-06 23:49:21184 base::RunLoop run_loop;
Emma Haruka Iwaobc302102017-12-05 02:33:08185 blink::mojom::ServiceWorkerRegistrationOptions options(
Asami Doi5de8dea2018-09-13 10:01:07186 embedded_test_server()->GetURL("/"), blink::mojom::ScriptType::kClassic,
Emma Haruka Iwaobc302102017-12-05 02:33:08187 blink::mojom::ServiceWorkerUpdateViaCache::kImports);
188 GetServiceWorkerContext()->RegisterServiceWorker(
189 embedded_test_server()->GetURL("/service_worker.js"), options,
Tsuyoshi Horoa1c6f542017-06-13 15:22:41190 base::Bind(&ExpectResultAndRun<bool>, false, run_loop.QuitClosure()));
shimazuce8af88122016-10-06 23:49:21191 run_loop.Run();
192}
193
194IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerTest,
195 FallbackMainResourceRequestWhenJSDisabled) {
196 WriteFile(
197 FILE_PATH_LITERAL("sw.js"),
198 "self.onfetch = function(e) {"
199 " e.respondWith(new Response('<title>Fail</title>',"
200 " {headers: {'Content-Type': 'text/html'}}));"
201 "};");
202 WriteFile(FILE_PATH_LITERAL("scope/done.html"), "<title>Done</title>");
Tsuyoshi Horoa1c6f542017-06-13 15:22:41203 WriteFile(FILE_PATH_LITERAL("test.html"), kInstallAndWaitForActivatedPage);
204 InitializeServer();
205 NavigateToPageAndWaitForReadyTitle("/test.html");
shimazuce8af88122016-10-06 23:49:21206
Tsuyoshi Horoa1c6f542017-06-13 15:22:41207 GetServiceWorkerContext()->StopAllServiceWorkersForOrigin(
shimazuce8af88122016-10-06 23:49:21208 embedded_test_server()->base_url());
shimazuce8af88122016-10-06 23:49:21209 HostContentSettingsMapFactory::GetForProfile(browser()->profile())
Darin Fisher42f5e7d2019-10-30 07:15:45210 ->SetDefaultContentSetting(ContentSettingsType::JAVASCRIPT,
shimazuce8af88122016-10-06 23:49:21211 CONTENT_SETTING_BLOCK);
212
213 const base::string16 expected_title2 = base::ASCIIToUTF16("Done");
214 content::TitleWatcher title_watcher2(
215 browser()->tab_strip_model()->GetActiveWebContents(), expected_title2);
216 ui_test_utils::NavigateToURL(
217 browser(),
218 embedded_test_server()->GetURL("/scope/done.html"));
219 EXPECT_EQ(expected_title2, title_watcher2.WaitAndGetTitle());
220
221 content::WebContents* web_contents =
222 browser()->tab_strip_model()->GetActiveWebContents();
Darin Fisher42f5e7d2019-10-30 07:15:45223 EXPECT_TRUE(TabSpecificContentSettings::FromWebContents(web_contents)
224 ->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
shimazuce8af88122016-10-06 23:49:21225}
226
Jon Mannb528b402018-08-10 21:05:37227IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerTest,
Azeem Arshad336e5af2019-01-16 22:27:25228 StartServiceWorkerAndDispatchMessage) {
229 base::RunLoop run_loop;
230 blink::TransferableMessage msg;
231 const base::string16 message_data = base::UTF8ToUTF16("testMessage");
232
233 WriteFile(FILE_PATH_LITERAL("sw.js"), "self.onfetch = function(e) {};");
234 WriteFile(FILE_PATH_LITERAL("test.html"), kInstallAndWaitForActivatedPage);
235 InitializeServer();
236 NavigateToPageAndWaitForReadyTitle("/test.html");
237 msg.owned_encoded_message = blink::EncodeStringMessage(message_data);
238 msg.encoded_message = msg.owned_encoded_message;
239
Sami Kyostila5e1306d2019-08-14 11:01:29240 base::PostTask(
Azeem Arshad336e5af2019-01-16 22:27:25241 FROM_HERE, {content::BrowserThread::IO},
242 base::BindOnce(
243 &content::ServiceWorkerContext::StartServiceWorkerAndDispatchMessage,
244 base::Unretained(GetServiceWorkerContext()),
245 embedded_test_server()->GetURL("/scope/"), std::move(msg),
246 base::BindRepeating(&ExpectResultAndRun<bool>, true,
247 run_loop.QuitClosure())));
248
249 run_loop.Run();
250}
251
horo61f3f4f2016-03-09 01:26:14252class ChromeServiceWorkerFetchTest : public ChromeServiceWorkerTest {
253 protected:
254 ChromeServiceWorkerFetchTest() {}
255 ~ChromeServiceWorkerFetchTest() override {}
256
257 void SetUpOnMainThread() override {
258 WriteServiceWorkerFetchTestFiles();
vabr96fd0c0f2016-09-13 14:21:31259 embedded_test_server()->ServeFilesFromDirectory(
260 service_worker_dir_.GetPath());
horo61f3f4f2016-03-09 01:26:14261 ASSERT_TRUE(embedded_test_server()->Start());
262 InitializeServiceWorkerFetchTestPage();
263 }
264
265 std::string ExecuteScriptAndExtractString(const std::string& js) {
266 std::string result;
267 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
268 browser()->tab_strip_model()->GetActiveWebContents(), js, &result));
269 return result;
270 }
271
272 std::string RequestString(const std::string& url,
273 const std::string& mode,
274 const std::string& credentials) const {
275 return base::StringPrintf("url:%s, mode:%s, credentials:%s\n", url.c_str(),
276 mode.c_str(), credentials.c_str());
277 }
278
279 std::string GetURL(const std::string& relative_url) const {
280 return embedded_test_server()->GetURL(relative_url).spec();
281 }
282
283 private:
284 void WriteServiceWorkerFetchTestFiles() {
285 WriteFile(FILE_PATH_LITERAL("sw.js"),
286 "this.onactivate = function(event) {"
287 " event.waitUntil(self.clients.claim());"
288 "};"
289 "this.onfetch = function(event) {"
Tsuyoshi Horo49dd35bd2018-12-11 09:30:06290 // Ignore the default favicon request. The default favicon request
291 // is sent after the page loading is finished, and we can't
292 // control the timing of the request. If the request is sent after
293 // clients.claim() is called, fetch event for the default favicon
294 // request is triggered and the tests become flaky. See
295 // https://crbug.com/912543.
296 " if (event.request.url.endsWith('/favicon.ico')) {"
297 " return;"
298 " }"
horo61f3f4f2016-03-09 01:26:14299 " event.respondWith("
300 " self.clients.matchAll().then(function(clients) {"
301 " clients.forEach(function(client) {"
302 " client.postMessage("
303 " 'url:' + event.request.url + ', ' +"
304 " 'mode:' + event.request.mode + ', ' +"
305 " 'credentials:' + event.request.credentials"
306 " );"
307 " });"
308 " return fetch(event.request);"
309 " }));"
310 "};");
311 WriteFile(FILE_PATH_LITERAL("test.html"),
312 "<script>"
313 "navigator.serviceWorker.register('./sw.js', {scope: './'})"
314 " .then(function(reg) {"
315 " reg.addEventListener('updatefound', function() {"
316 " var worker = reg.installing;"
317 " worker.addEventListener('statechange', function() {"
318 " if (worker.state == 'activated')"
319 " document.title = 'READY';"
320 " });"
321 " });"
322 " });"
323 "var reportOnFetch = true;"
324 "var issuedRequests = [];"
325 "function reportRequests() {"
326 " var str = '';"
327 " issuedRequests.forEach(function(data) {"
328 " str += data + '\\n';"
329 " });"
horo61f3f4f2016-03-09 01:26:14330 " window.domAutomationController.send(str);"
331 "}"
332 "navigator.serviceWorker.addEventListener("
333 " 'message',"
334 " function(event) {"
335 " issuedRequests.push(event.data);"
336 " if (reportOnFetch) {"
337 " reportRequests();"
338 " }"
339 " }, false);"
340 "</script>");
341 }
342
343 void InitializeServiceWorkerFetchTestPage() {
344 // The message "READY" will be sent when the service worker is activated.
345 const base::string16 expected_title = base::ASCIIToUTF16("READY");
346 content::TitleWatcher title_watcher(
347 browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
348 ui_test_utils::NavigateToURL(browser(),
349 embedded_test_server()->GetURL("/test.html"));
350 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
351 }
352
353 DISALLOW_COPY_AND_ASSIGN(ChromeServiceWorkerFetchTest);
354};
355
Tsuyoshi Horo757835432018-11-15 00:21:35356class FaviconUpdateWaiter : public favicon::FaviconDriverObserver {
357 public:
Evan Stade22e3f9b2019-10-01 21:12:17358 explicit FaviconUpdateWaiter(content::WebContents* web_contents) {
Tsuyoshi Horo757835432018-11-15 00:21:35359 scoped_observer_.Add(
360 favicon::ContentFaviconDriver::FromWebContents(web_contents));
361 }
Evan Stade22e3f9b2019-10-01 21:12:17362 ~FaviconUpdateWaiter() override = default;
horo61f3f4f2016-03-09 01:26:14363
Tsuyoshi Horo757835432018-11-15 00:21:35364 void Wait() {
365 if (updated_)
366 return;
367
368 base::RunLoop run_loop;
369 quit_closure_ = run_loop.QuitClosure();
370 run_loop.Run();
371 }
372
373 private:
374 void OnFaviconUpdated(favicon::FaviconDriver* favicon_driver,
375 NotificationIconType notification_icon_type,
376 const GURL& icon_url,
377 bool icon_url_changed,
378 const gfx::Image& image) override {
379 updated_ = true;
380 if (!quit_closure_.is_null())
381 std::move(quit_closure_).Run();
382 }
383
Evan Stade22e3f9b2019-10-01 21:12:17384 bool updated_ = false;
385 ScopedObserver<favicon::FaviconDriver, favicon::FaviconDriverObserver>
386 scoped_observer_{this};
Tsuyoshi Horo757835432018-11-15 00:21:35387 base::OnceClosure quit_closure_;
388
389 DISALLOW_COPY_AND_ASSIGN(FaviconUpdateWaiter);
390};
391
392class ChromeServiceWorkerLinkFetchTest : public ChromeServiceWorkerFetchTest {
393 protected:
394 ChromeServiceWorkerLinkFetchTest() {}
395 ~ChromeServiceWorkerLinkFetchTest() override {}
396 void SetUpOnMainThread() override {
397 // Map all hosts to localhost and setup the EmbeddedTestServer for
398 // redirects.
399 host_resolver()->AddRule("*", "127.0.0.1");
400 ChromeServiceWorkerFetchTest::SetUpOnMainThread();
401 }
horo61f3f4f2016-03-09 01:26:14402 std::string ExecuteManifestFetchTest(const std::string& url,
403 const std::string& cross_origin) {
404 std::string js(
405 base::StringPrintf("reportOnFetch = false;"
406 "var link = document.createElement('link');"
407 "link.rel = 'manifest';"
408 "link.href = '%s';",
409 url.c_str()));
410 if (!cross_origin.empty()) {
411 js +=
412 base::StringPrintf("link.crossOrigin = '%s';", cross_origin.c_str());
413 }
414 js += "document.head.appendChild(link);";
415 ExecuteJavaScriptForTests(js);
horo482eeff2016-07-19 23:06:58416 return GetManifestAndIssuedRequests();
horo61f3f4f2016-03-09 01:26:14417 }
418
Tsuyoshi Horo757835432018-11-15 00:21:35419 std::string ExecuteFaviconFetchTest(const std::string& url) {
420 FaviconUpdateWaiter waiter(
421 browser()->tab_strip_model()->GetActiveWebContents());
422 std::string js(
423 base::StringPrintf("reportOnFetch = false;"
424 "var link = document.createElement('link');"
425 "link.rel = 'icon';"
426 "link.href = '%s';"
427 "document.head.appendChild(link);",
428 url.c_str()));
429 ExecuteJavaScriptForTests(js);
430 waiter.Wait();
431 return ExecuteScriptAndExtractString("reportRequests();");
432 }
433
434 void CopyTestFile(const std::string& src, const std::string& dst) {
435 base::ScopedAllowBlockingForTesting allow_blocking;
436 base::FilePath test_data_dir;
437 base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
438 EXPECT_TRUE(base::CopyFile(test_data_dir.AppendASCII(src),
439 service_worker_dir_.GetPath().AppendASCII(dst)));
440 }
441
horo61f3f4f2016-03-09 01:26:14442 private:
443 void ExecuteJavaScriptForTests(const std::string& js) {
Sam McNallycfe7a062017-11-02 00:40:07444 base::RunLoop run_loop;
horo61f3f4f2016-03-09 01:26:14445 browser()
446 ->tab_strip_model()
447 ->GetActiveWebContents()
448 ->GetMainFrame()
Sam McNallycfe7a062017-11-02 00:40:07449 ->ExecuteJavaScriptForTests(
450 base::ASCIIToUTF16(js),
Avi Drissman8e8880002019-03-12 00:33:27451 base::BindOnce([](const base::Closure& quit_callback,
452 base::Value result) { quit_callback.Run(); },
453 run_loop.QuitClosure()));
Sam McNallycfe7a062017-11-02 00:40:07454 run_loop.Run();
horo61f3f4f2016-03-09 01:26:14455 }
456
horo482eeff2016-07-19 23:06:58457 std::string GetManifestAndIssuedRequests() {
458 base::RunLoop run_loop;
459 browser()->tab_strip_model()->GetActiveWebContents()->GetManifest(
460 base::Bind(&ManifestCallbackAndRun, run_loop.QuitClosure()));
461 run_loop.Run();
horo61f3f4f2016-03-09 01:26:14462 return ExecuteScriptAndExtractString(
463 "if (issuedRequests.length != 0) reportRequests();"
464 "else reportOnFetch = true;");
465 }
horo482eeff2016-07-19 23:06:58466
467 static void ManifestCallbackAndRun(const base::Closure& continuation,
468 const GURL&,
Dmitry Gozman88ca5a992018-05-18 00:13:33469 const blink::Manifest&) {
horo482eeff2016-07-19 23:06:58470 continuation.Run();
471 }
472
Tsuyoshi Horo757835432018-11-15 00:21:35473 DISALLOW_COPY_AND_ASSIGN(ChromeServiceWorkerLinkFetchTest);
horo61f3f4f2016-03-09 01:26:14474};
475
Tsuyoshi Horo757835432018-11-15 00:21:35476IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest, ManifestSameOrigin) {
horo61f3f4f2016-03-09 01:26:14477 // <link rel="manifest" href="manifest.json">
Takeshi Yoshino2e231cf2017-06-21 04:40:12478 EXPECT_EQ(RequestString(GetURL("/manifest.json"), "cors", "omit"),
horo61f3f4f2016-03-09 01:26:14479 ExecuteManifestFetchTest("manifest.json", ""));
480}
481
Tsuyoshi Horo757835432018-11-15 00:21:35482IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest,
483 ManifestSameOriginUseCredentials) {
horo61f3f4f2016-03-09 01:26:14484 // <link rel="manifest" href="manifest.json" crossorigin="use-credentials">
485 EXPECT_EQ(RequestString(GetURL("/manifest.json"), "cors", "include"),
486 ExecuteManifestFetchTest("manifest.json", "use-credentials"));
487}
488
Tsuyoshi Horo757835432018-11-15 00:21:35489IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest, ManifestOtherOrigin) {
490 // <link rel="manifest" href="http://www.example.com:PORT/manifest.json">
491 const std::string url = embedded_test_server()
492 ->GetURL("www.example.com", "/manifest.json")
493 .spec();
494 EXPECT_EQ(RequestString(url, "cors", "omit"),
495 ExecuteManifestFetchTest(url, ""));
horo61f3f4f2016-03-09 01:26:14496}
497
Tsuyoshi Horo757835432018-11-15 00:21:35498IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest,
499 ManifestOtherOriginUseCredentials) {
500 // <link rel="manifest" href="http://www.example.com:PORT/manifest.json"
horo61f3f4f2016-03-09 01:26:14501 // crossorigin="use-credentials">
Tsuyoshi Horo757835432018-11-15 00:21:35502 const std::string url = embedded_test_server()
503 ->GetURL("www.example.com", "/manifest.json")
504 .spec();
505 EXPECT_EQ(RequestString(url, "cors", "include"),
506 ExecuteManifestFetchTest(url, "use-credentials"));
507}
508
509IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest, FaviconSameOrigin) {
510 // <link rel="favicon" href="fav.png">
511 CopyTestFile("favicon/icon.png", "fav.png");
512 EXPECT_EQ(RequestString(GetURL("/fav.png"), "no-cors", "include"),
513 ExecuteFaviconFetchTest("/fav.png"));
514}
515
516IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerLinkFetchTest, FaviconOtherOrigin) {
517 // <link rel="favicon" href="http://www.example.com:PORT/fav.png">
518 CopyTestFile("favicon/icon.png", "fav.png");
519 const std::string url =
520 embedded_test_server()->GetURL("www.example.com", "/fav.png").spec();
521 EXPECT_EQ("", ExecuteFaviconFetchTest(url));
horo61f3f4f2016-03-09 01:26:14522}
523
Nico Weberaf3b00b2017-09-11 17:58:17524#if BUILDFLAG(ENABLE_NACL)
Matt Falkenhagen7031e8b2018-02-20 03:30:33525// This test registers a service worker and then loads a controlled iframe that
526// creates a PNaCl plugin in an <embed> element. Once loaded, the PNaCl plugin
527// is ordered to do a resource request for "/echo". The service worker records
528// all the fetch events it sees. Since requests for plug-ins and requests
529// initiated by plug-ins should not be interecepted by service workers, we
530// expect that the the service worker only see the navigation request for the
531// iframe.
horo61f3f4f2016-03-09 01:26:14532class ChromeServiceWorkerFetchPPAPITest : public ChromeServiceWorkerFetchTest {
533 protected:
534 ChromeServiceWorkerFetchPPAPITest() {}
535 ~ChromeServiceWorkerFetchPPAPITest() override {}
536
Derek Schuffd71a05822019-05-30 19:50:13537 void SetUpCommandLine(base::CommandLine* command_line) override {
538 ChromeServiceWorkerFetchTest::SetUpCommandLine(command_line);
539 // Use --enable-nacl flag to ensure the PNaCl module can load (without
540 // needing to use an OT token)
541 command_line->AppendSwitch(switches::kEnableNaCl);
542 }
543
horo61f3f4f2016-03-09 01:26:14544 void SetUpOnMainThread() override {
545 base::FilePath document_root;
546 ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&document_root));
547 embedded_test_server()->AddDefaultHandlers(
548 document_root.Append(FILE_PATH_LITERAL("nacl_test_data"))
549 .Append(FILE_PATH_LITERAL("pnacl")));
550 ChromeServiceWorkerFetchTest::SetUpOnMainThread();
551 test_page_url_ = GetURL("/pnacl_url_loader.html");
552 }
553
Matt Falkenhagen7031e8b2018-02-20 03:30:33554 std::string GetNavigationRequestString(const std::string& fragment) const {
555 return RequestString(test_page_url_ + fragment, "navigate", "include");
horo61f3f4f2016-03-09 01:26:14556 }
557
558 std::string ExecutePNACLUrlLoaderTest(const std::string& mode) {
559 std::string result(ExecuteScriptAndExtractString(
560 base::StringPrintf("reportOnFetch = false;"
561 "var iframe = document.createElement('iframe');"
562 "iframe.src='%s#%s';"
563 "document.body.appendChild(iframe);",
564 test_page_url_.c_str(), mode.c_str())));
565 EXPECT_EQ(base::StringPrintf("OnOpen%s", mode.c_str()), result);
566 return ExecuteScriptAndExtractString("reportRequests();");
567 }
568
569 private:
570 std::string test_page_url_;
571
572 DISALLOW_COPY_AND_ASSIGN(ChromeServiceWorkerFetchPPAPITest);
573};
574
horo61f3f4f2016-03-09 01:26:14575IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerFetchPPAPITest,
Matt Falkenhagen7031e8b2018-02-20 03:30:33576 NotInterceptedByServiceWorker) {
577 // Only the navigation to the iframe should be intercepted by the service
578 // worker. The request for the PNaCl manifest ("/pnacl_url_loader.nmf"),
579 // the request for the compiled code ("/pnacl_url_loader_newlib_pnacl.pexe"),
580 // and any other requests initiated by the plug-in ("/echo") should not be
581 // seen by the service worker.
582 const std::string fragment =
583 "NotIntercepted"; // this string is not important.
584 EXPECT_EQ(GetNavigationRequestString("#" + fragment),
585 ExecutePNACLUrlLoaderTest(fragment));
horo61f3f4f2016-03-09 01:26:14586}
Nico Weberaf3b00b2017-09-11 17:58:17587#endif // BUILDFLAG(ENABLE_NACL)
horo61f3f4f2016-03-09 01:26:14588
Tsuyoshi Horoa1c6f542017-06-13 15:22:41589class ChromeServiceWorkerNavigationHintTest : public ChromeServiceWorkerTest {
590 protected:
591 void RunNavigationHintTest(
592 const char* scope,
Tsuyoshi Horo6ddf281f2017-07-14 04:02:48593 content::StartServiceWorkerForNavigationHintResult expected_result,
Tsuyoshi Horoa1c6f542017-06-13 15:22:41594 bool expected_started) {
Tsuyoshi Horoa1c6f542017-06-13 15:22:41595 base::RunLoop run_loop;
596 GetServiceWorkerContext()->StartServiceWorkerForNavigationHint(
597 embedded_test_server()->GetURL(scope),
Matt Falkenhagenda8af672017-09-12 02:39:23598 base::BindOnce(&ExpectResultAndRun<
599 content::StartServiceWorkerForNavigationHintResult>,
600 expected_result, run_loop.QuitClosure()));
Tsuyoshi Horoa1c6f542017-06-13 15:22:41601 run_loop.Run();
602 if (expected_started) {
Tsuyoshi Horo8290f132017-06-22 06:26:05603 histogram_tester_.ExpectBucketCount(
Tsuyoshi Horoa1c6f542017-06-13 15:22:41604 "ServiceWorker.StartWorker.Purpose",
605 27 /* ServiceWorkerMetrics::EventType::NAVIGATION_HINT */, 1);
Tsuyoshi Horo8290f132017-06-22 06:26:05606 histogram_tester_.ExpectBucketCount(
Tsuyoshi Horoa1c6f542017-06-13 15:22:41607 "ServiceWorker.StartWorker.StatusByPurpose_NAVIGATION_HINT",
608 0 /* SERVICE_WORKER_OK */, 1);
609 } else {
Tsuyoshi Horo8290f132017-06-22 06:26:05610 histogram_tester_.ExpectTotalCount("ServiceWorker.StartWorker.Purpose",
611 0);
612 histogram_tester_.ExpectTotalCount(
Tsuyoshi Horoa1c6f542017-06-13 15:22:41613 "ServiceWorker.StartWorker.StatusByPurpose_NAVIGATION_HINT", 0);
614 }
Tsuyoshi Horo6ddf281f2017-07-14 04:02:48615 histogram_tester_.ExpectBucketCount(
616 "ServiceWorker.StartForNavigationHint.Result",
617 static_cast<int>(expected_result), 1);
Tsuyoshi Horoa1c6f542017-06-13 15:22:41618 }
Tsuyoshi Horo8290f132017-06-22 06:26:05619
620 base::HistogramTester histogram_tester_;
Tsuyoshi Horoa1c6f542017-06-13 15:22:41621};
622
623IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerNavigationHintTest, Started) {
624 WriteFile(FILE_PATH_LITERAL("sw.js"), "self.onfetch = function(e) {};");
625 WriteFile(FILE_PATH_LITERAL("test.html"), kInstallAndWaitForActivatedPage);
626 InitializeServer();
627 NavigateToPageAndWaitForReadyTitle("/test.html");
628 GetServiceWorkerContext()->StopAllServiceWorkersForOrigin(
629 embedded_test_server()->base_url());
630 RunNavigationHintTest(
631 "/scope/", content::StartServiceWorkerForNavigationHintResult::STARTED,
632 true);
633}
634
635IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerNavigationHintTest, AlreadyRunning) {
636 WriteFile(FILE_PATH_LITERAL("sw.js"), "self.onfetch = function(e) {};");
637 WriteFile(FILE_PATH_LITERAL("test.html"), kInstallAndWaitForActivatedPage);
638 InitializeServer();
639 NavigateToPageAndWaitForReadyTitle("/test.html");
640 RunNavigationHintTest(
641 "/scope/",
642 content::StartServiceWorkerForNavigationHintResult::ALREADY_RUNNING,
643 false);
644}
645
646IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerNavigationHintTest,
647 NoServiceWorkerRegistration) {
648 InitializeServer();
649 RunNavigationHintTest("/scope/",
650 content::StartServiceWorkerForNavigationHintResult::
651 NO_SERVICE_WORKER_REGISTRATION,
652 false);
653}
654
655IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerNavigationHintTest,
656 NoActiveServiceWorkerVersion) {
657 WriteFile(FILE_PATH_LITERAL("sw.js"),
658 "self.oninstall = function(e) {\n"
659 " e.waitUntil(new Promise(r => { /* never resolve */ }));\n"
660 " };\n"
661 "self.onfetch = function(e) {};");
662 InitializeServer();
663 base::RunLoop run_loop;
Emma Haruka Iwaobc302102017-12-05 02:33:08664 blink::mojom::ServiceWorkerRegistrationOptions options(
Tsuyoshi Horoa1c6f542017-06-13 15:22:41665 embedded_test_server()->GetURL("/scope/"),
Asami Doi5de8dea2018-09-13 10:01:07666 blink::mojom::ScriptType::kClassic,
Emma Haruka Iwaobc302102017-12-05 02:33:08667 blink::mojom::ServiceWorkerUpdateViaCache::kImports);
668 GetServiceWorkerContext()->RegisterServiceWorker(
669 embedded_test_server()->GetURL("/sw.js"), options,
Tsuyoshi Horoa1c6f542017-06-13 15:22:41670 base::Bind(&ExpectResultAndRun<bool>, true, run_loop.QuitClosure()));
671 run_loop.Run();
672 RunNavigationHintTest("/scope/",
673 content::StartServiceWorkerForNavigationHintResult::
674 NO_ACTIVE_SERVICE_WORKER_VERSION,
675 false);
676}
677
678IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerNavigationHintTest, NoFetchHandler) {
679 WriteFile(FILE_PATH_LITERAL("sw.js"), "/* empty */");
680 WriteFile(FILE_PATH_LITERAL("test.html"), kInstallAndWaitForActivatedPage);
681 InitializeServer();
682 NavigateToPageAndWaitForReadyTitle("/test.html");
683 GetServiceWorkerContext()->StopAllServiceWorkersForOrigin(
684 embedded_test_server()->base_url());
685 RunNavigationHintTest(
686 "/scope/",
687 content::StartServiceWorkerForNavigationHintResult::NO_FETCH_HANDLER,
688 false);
689}
690
Matt Falkenhagenea306042018-11-29 00:45:25691// Copied from devtools_sanity_browsertest.cc.
692class StaticURLDataSource : public content::URLDataSource {
693 public:
694 StaticURLDataSource(const std::string& source, const std::string& content)
695 : source_(source), content_(content) {}
696 ~StaticURLDataSource() override = default;
697
698 // content::URLDataSource:
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04699 std::string GetSource() override { return source_; }
Wei-Yin Chen (陳威尹)39f4ff32019-10-22 17:59:09700 void StartDataRequest(const GURL& url,
John Abd-El-Malek92bf3602019-07-31 02:25:48701 const content::WebContents::Getter& wc_getter,
danakjf4b9e942019-11-29 15:43:04702 GotDataCallback callback) override {
Matt Falkenhagenea306042018-11-29 00:45:25703 std::string data(content_);
danakjf4b9e942019-11-29 15:43:04704 std::move(callback).Run(base::RefCountedString::TakeString(&data));
Matt Falkenhagenea306042018-11-29 00:45:25705 }
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04706 std::string GetMimeType(const std::string& path) override {
Matt Falkenhagenea306042018-11-29 00:45:25707 return "application/javascript";
708 }
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04709 bool ShouldAddContentSecurityPolicy() override { return false; }
Matt Falkenhagenea306042018-11-29 00:45:25710
711 private:
712 const std::string source_;
713 const std::string content_;
714
715 DISALLOW_COPY_AND_ASSIGN(StaticURLDataSource);
716};
717
718// Copied from devtools_sanity_browsertest.cc.
719class MockWebUIProvider
720 : public TestChromeWebUIControllerFactory::WebUIProvider {
721 public:
722 MockWebUIProvider(const std::string& source, const std::string& content)
723 : source_(source), content_(content) {}
724 ~MockWebUIProvider() override = default;
725
726 std::unique_ptr<content::WebUIController> NewWebUI(content::WebUI* web_ui,
727 const GURL& url) override {
728 content::URLDataSource::Add(
729 Profile::FromWebUI(web_ui),
730 std::make_unique<StaticURLDataSource>(source_, content_));
731 return std::make_unique<content::WebUIController>(web_ui);
732 }
733
734 private:
735 const std::string source_;
736 const std::string content_;
737 DISALLOW_COPY_AND_ASSIGN(MockWebUIProvider);
738};
739
740// Tests that registering a service worker with a chrome:// URL fails.
741IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerTest, DisallowChromeScheme) {
742 const GURL kScript("chrome://dummyurl/sw.js");
743 const GURL kScope("chrome://dummyurl");
744
745 // Make chrome://dummyurl/sw.js serve a service worker script.
746 TestChromeWebUIControllerFactory test_factory;
747 MockWebUIProvider mock_provider("serviceworker", "// empty service worker");
748 test_factory.AddFactoryOverride(kScript.host(), &mock_provider);
749 content::WebUIControllerFactory::RegisterFactory(&test_factory);
750
751 // Try to register the service worker.
752 base::RunLoop run_loop;
753 bool result = true;
754 blink::mojom::ServiceWorkerRegistrationOptions options(
755 kScope, blink::mojom::ScriptType::kClassic,
756 blink::mojom::ServiceWorkerUpdateViaCache::kImports);
757 GetServiceWorkerContext()->RegisterServiceWorker(
758 kScript, options,
759 base::BindOnce(
760 [](base::OnceClosure quit_closure, bool* out_result, bool result) {
761 *out_result = result;
762 std::move(quit_closure).Run();
763 },
764 run_loop.QuitClosure(), &result));
765 run_loop.Run();
766
767 // Registration should fail. This is the desired behavior. At the time of this
768 // writing, there are a few reasons the registration fails:
769 // * OriginCanAccessServiceWorkers() returns false for the "chrome" scheme.
770 // * Even if that returned true, the URL loader factory bundle used to make
771 // the resource request in ServiceWorkerNewScriptLoader doesn't support
772 // the "chrome" scheme. This is because:
773 // * The call to RegisterNonNetworkSubresourceURLLoaderFactories() from
774 // CreateFactoryBundle() in embedded_worker_instance.cc doesn't register
775 // the "chrome" scheme, because there is no frame/web_contents.
776 // * Even if that registered a factory, CreateFactoryBundle() would
777 // skip it because GetServiceWorkerSchemes() doesn't include "chrome".
778 //
779 // It's difficult to change all these, so the test author hasn't actually
780 // changed Chrome in a way that makes this test fail, to prove that the test
781 // would be effective at catching a regression.
782 EXPECT_FALSE(result);
783}
784
Matt Falkenhagenc0d0bac2018-12-18 08:31:08785enum class ServicifiedFeatures { kNone, kServiceWorker, kNetwork };
786
787// A simple fixture used for navigation preload tests so far. The fixture
788// stashes the HttpRequest to a certain URL, useful for inspecting the headers
789// to see if it was a navigation preload request and if it contained cookies.
790//
791// This is in //chrome instead of //content since the tests exercise the
792// kBlockThirdPartyCookies preference which is not a //content concept.
Matt Falkenhagen4332b162019-03-04 08:58:52793class ChromeServiceWorkerNavigationPreloadTest : public InProcessBrowserTest {
Matt Falkenhagenc0d0bac2018-12-18 08:31:08794 public:
795 ChromeServiceWorkerNavigationPreloadTest() = default;
796
797 void SetUp() override {
Matt Falkenhagenc0d0bac2018-12-18 08:31:08798 embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
799 &ChromeServiceWorkerNavigationPreloadTest::HandleRequest,
800 base::Unretained(this)));
801 ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
802
803 InProcessBrowserTest::SetUp();
804 }
805
806 void SetUpOnMainThread() override {
807 // Make all hosts resolve to 127.0.0.1 so the same embedded test server can
808 // be used for cross-origin URLs.
809 host_resolver()->AddRule("*", "127.0.0.1");
810
811 embedded_test_server()->StartAcceptingConnections();
812 }
813
814 std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
815 const net::test_server::HttpRequest& request) {
816 // Intercept requests to the "test" endpoint.
817 GURL url = request.base_url;
818 url = url.Resolve(request.relative_url);
819 if (url.path() != "/service_worker/test")
820 return nullptr;
821
822 // Stash the request for testing. We'd typically prefer to echo back the
823 // request and test the resulting page contents, but that becomes
824 // cumbersome if the test involves cross-origin frames.
825 EXPECT_FALSE(received_request_);
826 received_request_ = request;
827
828 // Respond with OK.
829 std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
830 new net::test_server::BasicHttpResponse());
831 http_response->set_code(net::HTTP_OK);
832 http_response->set_content("OK");
833 http_response->set_content_type("text/plain");
834 return http_response;
835 }
836
837 bool HasHeader(const net::test_server::HttpRequest& request,
838 const std::string& name) const {
839 return request.headers.find(name) != request.headers.end();
840 }
841
842 std::string GetHeader(const net::test_server::HttpRequest& request,
843 const std::string& name) const {
844 const auto& iter = request.headers.find(name);
845 EXPECT_TRUE(iter != request.headers.end());
846 if (iter == request.headers.end())
847 return std::string();
848 return iter->second;
849 }
850
851 bool has_received_request() const { return received_request_.has_value(); }
852
853 const net::test_server::HttpRequest& received_request() const {
854 return *received_request_;
855 }
856
857 private:
858 base::test::ScopedFeatureList scoped_feature_list_;
859
860 // The request that hit the "test" endpoint.
861 base::Optional<net::test_server::HttpRequest> received_request_;
862
863 DISALLOW_COPY_AND_ASSIGN(ChromeServiceWorkerNavigationPreloadTest);
864};
865
866// Tests navigation preload during a navigation in the top-level frame
867// when third-party cookies are blocked. The navigation preload request
868// should be sent with cookies as normal. Regression test for
869// https://crbug.com/913220.
Matt Falkenhagen4332b162019-03-04 08:58:52870IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerNavigationPreloadTest,
Matt Falkenhagenc0d0bac2018-12-18 08:31:08871 TopFrameWithThirdPartyBlocking) {
872 // Enable third-party cookie blocking.
873 browser()->profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies,
874 true);
875
876 // Load a page that registers a service worker.
877 ui_test_utils::NavigateToURL(
878 browser(), embedded_test_server()->GetURL(
879 "/service_worker/create_service_worker.html"));
880 EXPECT_EQ("DONE", EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
881 "register('navigation_preload_worker.js');"));
882
883 // Also set cookies.
884 EXPECT_EQ("foo=bar",
885 EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
886 "document.cookie = 'foo=bar'; document.cookie;"));
887
888 // Load the test page.
889 ui_test_utils::NavigateToURL(
890 browser(), embedded_test_server()->GetURL("/service_worker/test"));
891
892 // The navigation preload request should have occurred and included cookies.
893 ASSERT_TRUE(has_received_request());
894 EXPECT_EQ("true",
895 GetHeader(received_request(), "Service-Worker-Navigation-Preload"));
896 EXPECT_EQ("foo=bar", GetHeader(received_request(), "Cookie"));
897}
898
899// Tests navigation preload during a navigation in a third-party iframe
900// when third-party cookies are blocked. This blocks service worker as well,
901// so the navigation preload request should not be sent. And the navigation
902// request should not include cookies.
Matt Falkenhagen4332b162019-03-04 08:58:52903IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerNavigationPreloadTest,
Matt Falkenhagenc0d0bac2018-12-18 08:31:08904 SubFrameWithThirdPartyBlocking) {
905 // Enable third-party cookie blocking.
906 browser()->profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies,
907 true);
908
909 // Load a page that registers a service worker.
910 ui_test_utils::NavigateToURL(
911 browser(), embedded_test_server()->GetURL(
912 "/service_worker/create_service_worker.html"));
913 EXPECT_EQ("DONE", EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
914 "register('navigation_preload_worker.js');"));
915
916 // Also set cookies.
917 EXPECT_EQ("foo=bar",
918 EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
919 "document.cookie = 'foo=bar'; document.cookie;"));
920
921 // Generate a cross-origin URL.
922 GURL top_frame_url = embedded_test_server()->GetURL(
923 "/service_worker/page_with_third_party_iframe.html");
924 GURL::Replacements replacements;
925 replacements.SetHostStr("cross-origin.example.com");
926 top_frame_url = top_frame_url.ReplaceComponents(replacements);
927
928 // Navigate to the page and embed a third-party iframe to the test
929 // page.
930 ui_test_utils::NavigateToURL(browser(), top_frame_url);
931 GURL iframe_url = embedded_test_server()->GetURL("/service_worker/test");
932 EXPECT_EQ(true, EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
933 "addIframe('" + iframe_url.spec() + "');"));
934
935 // The request should have been received. Because the navigation was for a
936 // third-party iframe with cookies blocked, the service worker should not have
937 // handled the request so navigation preload should not have occurred.
938 // Likewise, the cookies should not have been sent.
939 ASSERT_TRUE(has_received_request());
940 EXPECT_FALSE(
941 HasHeader(received_request(), "Service-Worker-Navigation-Preload"));
942 EXPECT_FALSE(HasHeader(received_request(), "Cookie"));
943}
944
Matt Falkenhagenea306042018-11-29 00:45:25945} // namespace chrome_service_worker_browser_test