1 // 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.
6 #include "base/callback.h"
7 #include "base/command_line.h"
8 #include "base/run_loop.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/browser/fileapi/chrome_blob_storage_context.h"
11 #include "content/browser/service_worker/embedded_worker_instance.h"
12 #include "content/browser/service_worker/embedded_worker_registry.h"
13 #include "content/browser/service_worker/service_worker_context_core.h"
14 #include "content/browser/service_worker/service_worker_context_observer.h"
15 #include "content/browser/service_worker/service_worker_context_wrapper.h"
16 #include "content/browser/service_worker/service_worker_registration.h"
17 #include "content/browser/service_worker/service_worker_test_utils.h"
18 #include "content/browser/service_worker/service_worker_version.h"
19 #include "content/common/service_worker/service_worker_messages.h"
20 #include "content/common/service_worker/service_worker_status_code.h"
21 #include "content/common/service_worker/service_worker_types.h"
22 #include "content/public/browser/browser_context.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/navigation_entry.h"
25 #include "content/public/browser/render_process_host.h"
26 #include "content/public/browser/storage_partition.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/content_switches.h"
29 #include "content/public/common/referrer.h"
30 #include "content/public/common/security_style.h"
31 #include "content/public/common/ssl_status.h"
32 #include "content/public/test/browser_test_utils.h"
33 #include "content/public/test/content_browser_test.h"
34 #include "content/public/test/content_browser_test_utils.h"
35 #include "content/shell/browser/shell.h"
36 #include "content/shell/browser/shell_content_browser_client.h"
37 #include "net/test/embedded_test_server/embedded_test_server.h"
38 #include "net/test/embedded_test_server/http_request.h"
39 #include "net/test/embedded_test_server/http_response.h"
40 #include "net/url_request/url_request_filter.h"
41 #include "net/url_request/url_request_interceptor.h"
42 #include "net/url_request/url_request_test_job.h"
43 #include "storage/browser/blob/blob_data_handle.h"
44 #include "storage/browser/blob/blob_data_snapshot.h"
45 #include "storage/browser/blob/blob_storage_context.h"
52 ServiceWorkerStatusCode status
;
53 ServiceWorkerFetchEventResult result
;
54 ServiceWorkerResponse response
;
55 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
58 void RunAndQuit(const base::Closure
& closure
,
59 const base::Closure
& quit
,
60 base::MessageLoopProxy
* original_message_loop
) {
62 original_message_loop
->PostTask(FROM_HERE
, quit
);
65 void RunOnIOThreadWithDelay(const base::Closure
& closure
,
66 base::TimeDelta delay
) {
67 base::RunLoop run_loop
;
68 BrowserThread::PostDelayedTask(
69 BrowserThread::IO
, FROM_HERE
,
70 base::Bind(&RunAndQuit
, closure
, run_loop
.QuitClosure(),
71 base::MessageLoopProxy::current()),
76 void RunOnIOThread(const base::Closure
& closure
) {
77 RunOnIOThreadWithDelay(closure
, base::TimeDelta());
81 const base::Callback
<void(const base::Closure
& continuation
)>& closure
) {
82 base::RunLoop run_loop
;
83 base::Closure quit_on_original_thread
=
84 base::Bind(base::IgnoreResult(&base::MessageLoopProxy::PostTask
),
85 base::MessageLoopProxy::current().get(),
87 run_loop
.QuitClosure());
88 BrowserThread::PostTask(BrowserThread::IO
,
90 base::Bind(closure
, quit_on_original_thread
));
94 void ReceivePrepareResult(bool* is_prepared
) {
98 base::Closure
CreatePrepareReceiver(bool* is_prepared
) {
99 return base::Bind(&ReceivePrepareResult
, is_prepared
);
102 // Contrary to the style guide, the output parameter of this function comes
103 // before input parameters so Bind can be used on it to create a FetchCallback
104 // to pass to DispatchFetchEvent.
105 void ReceiveFetchResult(BrowserThread::ID run_quit_thread
,
106 const base::Closure
& quit
,
107 ChromeBlobStorageContext
* blob_context
,
108 FetchResult
* out_result
,
109 ServiceWorkerStatusCode actual_status
,
110 ServiceWorkerFetchEventResult actual_result
,
111 const ServiceWorkerResponse
& actual_response
) {
112 out_result
->status
= actual_status
;
113 out_result
->result
= actual_result
;
114 out_result
->response
= actual_response
;
115 if (!actual_response
.blob_uuid
.empty()) {
116 out_result
->blob_data_handle
=
117 blob_context
->context()->GetBlobDataFromUUID(
118 actual_response
.blob_uuid
);
121 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, quit
);
124 ServiceWorkerVersion::FetchCallback
CreateResponseReceiver(
125 BrowserThread::ID run_quit_thread
,
126 const base::Closure
& quit
,
127 ChromeBlobStorageContext
* blob_context
,
128 FetchResult
* result
) {
129 return base::Bind(&ReceiveFetchResult
, run_quit_thread
, quit
,
130 make_scoped_refptr
<ChromeBlobStorageContext
>(blob_context
),
134 void ReadResponseBody(std::string
* body
,
135 storage::BlobDataHandle
* blob_data_handle
) {
136 ASSERT_TRUE(blob_data_handle
);
137 scoped_ptr
<storage::BlobDataSnapshot
> data
=
138 blob_data_handle
->CreateSnapshot();
139 ASSERT_EQ(1U, data
->items().size());
140 *body
= std::string(data
->items()[0]->bytes(), data
->items()[0]->length());
143 void ExpectResultAndRun(bool expected
,
144 const base::Closure
& continuation
,
146 EXPECT_EQ(expected
, actual
);
150 class WorkerActivatedObserver
151 : public ServiceWorkerContextObserver
,
152 public base::RefCountedThreadSafe
<WorkerActivatedObserver
> {
154 explicit WorkerActivatedObserver(ServiceWorkerContextWrapper
* context
)
155 : context_(context
) {}
157 RunOnIOThread(base::Bind(&WorkerActivatedObserver::InitOnIOThread
, this));
159 // ServiceWorkerContextObserver overrides.
160 void OnVersionStateChanged(int64 version_id
,
161 ServiceWorkerVersion::Status
) override
{
162 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
163 const ServiceWorkerVersion
* version
=
164 context_
->context()->GetLiveVersion(version_id
);
165 if (version
->status() == ServiceWorkerVersion::ACTIVATED
) {
166 context_
->RemoveObserver(this);
167 BrowserThread::PostTask(BrowserThread::UI
,
169 base::Bind(&WorkerActivatedObserver::Quit
, this));
172 void Wait() { run_loop_
.Run(); }
175 friend class base::RefCountedThreadSafe
<WorkerActivatedObserver
>;
176 ~WorkerActivatedObserver() override
{}
177 void InitOnIOThread() { context_
->AddObserver(this); }
178 void Quit() { run_loop_
.Quit(); }
180 base::RunLoop run_loop_
;
181 ServiceWorkerContextWrapper
* context_
;
182 DISALLOW_COPY_AND_ASSIGN(WorkerActivatedObserver
);
185 scoped_ptr
<net::test_server::HttpResponse
> VerifyServiceWorkerHeaderInRequest(
186 const net::test_server::HttpRequest
& request
) {
187 EXPECT_EQ(request
.relative_url
, "/service_worker/generated_sw.js");
188 std::map
<std::string
, std::string
>::const_iterator it
=
189 request
.headers
.find("Service-Worker");
190 EXPECT_TRUE(it
!= request
.headers
.end());
191 EXPECT_EQ("script", it
->second
);
193 scoped_ptr
<net::test_server::BasicHttpResponse
> http_response(
194 new net::test_server::BasicHttpResponse());
195 http_response
->set_content_type("text/javascript");
196 return http_response
.Pass();
199 // The ImportsBustMemcache test requires that the imported script
200 // would naturally be cached in blink's memcache, but the embedded
201 // test server doesn't produce headers that allow the blink's memcache
202 // to do that. This interceptor injects headers that give the import
203 // an experiration far in the future.
204 class LongLivedResourceInterceptor
: public net::URLRequestInterceptor
{
206 LongLivedResourceInterceptor(const std::string
& body
)
208 ~LongLivedResourceInterceptor() override
{}
210 // net::URLRequestInterceptor implementation
211 net::URLRequestJob
* MaybeInterceptRequest(
212 net::URLRequest
* request
,
213 net::NetworkDelegate
* network_delegate
) const override
{
214 const char kHeaders
[] =
216 "Content-Type: text/javascript\0"
217 "Expires: Thu, 1 Jan 2100 20:00:00 GMT\0"
219 std::string
headers(kHeaders
, arraysize(kHeaders
));
220 return new net::URLRequestTestJob(
221 request
, network_delegate
, headers
, body_
, true);
226 DISALLOW_COPY_AND_ASSIGN(LongLivedResourceInterceptor
);
229 void CreateLongLivedResourceInterceptors(
230 const GURL
& worker_url
, const GURL
& import_url
) {
231 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
232 scoped_ptr
<net::URLRequestInterceptor
> interceptor
;
234 interceptor
.reset(new LongLivedResourceInterceptor(
235 "importScripts('long_lived_import.js');"));
236 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
237 worker_url
, interceptor
.Pass());
239 interceptor
.reset(new LongLivedResourceInterceptor(
240 "// the imported script does nothing"));
241 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
242 import_url
, interceptor
.Pass());
245 void CountScriptResources(
246 ServiceWorkerContextWrapper
* wrapper
,
248 int* num_resources
) {
251 std::vector
<ServiceWorkerRegistrationInfo
> infos
=
252 wrapper
->context()->GetAllLiveRegistrationInfo();
257 size_t index
= infos
.size() - 1;
258 if (infos
[index
].installing_version
.version_id
!=
259 kInvalidServiceWorkerVersionId
)
260 version_id
= infos
[index
].installing_version
.version_id
;
261 else if (infos
[index
].waiting_version
.version_id
!=
262 kInvalidServiceWorkerVersionId
)
263 version_id
= infos
[1].waiting_version
.version_id
;
264 else if (infos
[index
].active_version
.version_id
!=
265 kInvalidServiceWorkerVersionId
)
266 version_id
= infos
[index
].active_version
.version_id
;
270 ServiceWorkerVersion
* version
=
271 wrapper
->context()->GetLiveVersion(version_id
);
272 *num_resources
= static_cast<int>(version
->script_cache_map()->size());
277 class ServiceWorkerBrowserTest
: public ContentBrowserTest
{
279 using self
= ServiceWorkerBrowserTest
;
281 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
282 command_line
->AppendSwitch(
283 switches::kEnableExperimentalWebPlatformFeatures
);
286 void SetUpOnMainThread() override
{
287 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
288 StoragePartition
* partition
= BrowserContext::GetDefaultStoragePartition(
289 shell()->web_contents()->GetBrowserContext());
290 wrapper_
= static_cast<ServiceWorkerContextWrapper
*>(
291 partition
->GetServiceWorkerContext());
293 // Navigate to the page to set up a renderer page (where we can embed
295 NavigateToURLBlockUntilNavigationsComplete(
297 embedded_test_server()->GetURL("/service_worker/empty.html"), 1);
299 RunOnIOThread(base::Bind(&self::SetUpOnIOThread
, this));
302 void TearDownOnMainThread() override
{
303 RunOnIOThread(base::Bind(&self::TearDownOnIOThread
, this));
307 virtual void SetUpOnIOThread() {}
308 virtual void TearDownOnIOThread() {}
310 ServiceWorkerContextWrapper
* wrapper() { return wrapper_
.get(); }
311 ServiceWorkerContext
* public_context() { return wrapper(); }
313 void AssociateRendererProcessToPattern(const GURL
& pattern
) {
314 wrapper_
->process_manager()->AddProcessReferenceToPattern(
315 pattern
, shell()->web_contents()->GetRenderProcessHost()->GetID());
319 scoped_refptr
<ServiceWorkerContextWrapper
> wrapper_
;
322 class EmbeddedWorkerBrowserTest
: public ServiceWorkerBrowserTest
,
323 public EmbeddedWorkerInstance::Listener
{
325 using self
= EmbeddedWorkerBrowserTest
;
327 EmbeddedWorkerBrowserTest()
328 : last_worker_status_(EmbeddedWorkerInstance::STOPPED
),
329 pause_mode_(DONT_PAUSE
) {}
330 ~EmbeddedWorkerBrowserTest() override
{}
332 void TearDownOnIOThread() override
{
334 worker_
->RemoveListener(this);
339 void StartOnIOThread() {
340 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
341 worker_
= wrapper()->context()->embedded_worker_registry()->CreateWorker();
342 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker_
->status());
343 worker_
->AddListener(this);
345 const int64 service_worker_version_id
= 33L;
346 const GURL pattern
= embedded_test_server()->GetURL("/");
347 const GURL script_url
= embedded_test_server()->GetURL(
348 "/service_worker/worker.js");
349 AssociateRendererProcessToPattern(pattern
);
350 int process_id
= shell()->web_contents()->GetRenderProcessHost()->GetID();
351 wrapper()->process_manager()->AddProcessReferenceToPattern(
352 pattern
, process_id
);
354 service_worker_version_id
,
357 pause_mode_
!= DONT_PAUSE
,
358 base::Bind(&EmbeddedWorkerBrowserTest::StartOnIOThread2
, this));
360 void StartOnIOThread2(ServiceWorkerStatusCode status
) {
361 last_worker_status_
= worker_
->status();
362 EXPECT_EQ(SERVICE_WORKER_OK
, status
);
363 EXPECT_EQ(EmbeddedWorkerInstance::STARTING
, last_worker_status_
);
365 if (status
!= SERVICE_WORKER_OK
&& !done_closure_
.is_null())
369 void StopOnIOThread() {
370 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
371 EXPECT_EQ(EmbeddedWorkerInstance::RUNNING
, worker_
->status());
373 ServiceWorkerStatusCode status
= worker_
->Stop();
375 last_worker_status_
= worker_
->status();
376 EXPECT_EQ(SERVICE_WORKER_OK
, status
);
377 EXPECT_EQ(EmbeddedWorkerInstance::STOPPING
, last_worker_status_
);
379 if (status
!= SERVICE_WORKER_OK
&& !done_closure_
.is_null())
384 // EmbeddedWorkerInstance::Observer overrides:
385 void OnStarted() override
{
386 ASSERT_TRUE(worker_
!= NULL
);
387 ASSERT_FALSE(done_closure_
.is_null());
388 last_worker_status_
= worker_
->status();
389 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, done_closure_
);
391 void OnStopped(EmbeddedWorkerInstance::Status old_status
) override
{
392 ASSERT_TRUE(worker_
!= NULL
);
393 ASSERT_FALSE(done_closure_
.is_null());
394 last_worker_status_
= worker_
->status();
395 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, done_closure_
);
397 void OnPausedAfterDownload() override
{
398 if (pause_mode_
== PAUSE_THEN_RESUME
)
399 worker_
->ResumeAfterDownload();
400 else if (pause_mode_
== PAUSE_THEN_STOP
)
405 void OnReportException(const base::string16
& error_message
,
408 const GURL
& source_url
) override
{}
409 void OnReportConsoleMessage(int source_identifier
,
411 const base::string16
& message
,
413 const GURL
& source_url
) override
{}
414 bool OnMessageReceived(const IPC::Message
& message
) override
{ return false; }
416 scoped_ptr
<EmbeddedWorkerInstance
> worker_
;
417 EmbeddedWorkerInstance::Status last_worker_status_
;
425 // Called by EmbeddedWorkerInstance::Observer overrides so that
426 // test code can wait for the worker status notifications.
427 base::Closure done_closure_
;
430 class ConsoleListener
: public EmbeddedWorkerInstance::Listener
{
432 void OnReportConsoleMessage(int source_identifier
,
434 const base::string16
& message
,
436 const GURL
& source_url
) override
{
437 messages_
.push_back(message
);
438 if (!quit_
.is_null() && messages_
.size() == expected_message_count_
) {
439 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, quit_
);
444 void WaitForConsoleMessages(size_t expected_message_count
) {
445 if (messages_
.size() >= expected_message_count
)
448 expected_message_count_
= expected_message_count
;
449 base::RunLoop console_run_loop
;
450 quit_
= console_run_loop
.QuitClosure();
451 console_run_loop
.Run();
453 ASSERT_EQ(messages_
.size(), expected_message_count
);
456 bool OnMessageReceived(const IPC::Message
& message
) override
{ return false; }
457 const std::vector
<base::string16
>& messages() const { return messages_
; }
460 std::vector
<base::string16
> messages_
;
461 size_t expected_message_count_
;
465 class ServiceWorkerVersionBrowserTest
: public ServiceWorkerBrowserTest
{
467 using self
= ServiceWorkerVersionBrowserTest
;
469 ~ServiceWorkerVersionBrowserTest() override
{}
471 void TearDownOnIOThread() override
{
472 registration_
= NULL
;
476 void InstallTestHelper(const std::string
& worker_url
,
477 ServiceWorkerStatusCode expected_status
) {
478 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
481 // Dispatch install on a worker.
482 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
483 base::RunLoop install_run_loop
;
484 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
485 base::Bind(&self::InstallOnIOThread
, this,
486 install_run_loop
.QuitClosure(),
488 install_run_loop
.Run();
489 ASSERT_EQ(expected_status
, status
);
492 status
= SERVICE_WORKER_ERROR_FAILED
;
493 base::RunLoop stop_run_loop
;
494 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
495 base::Bind(&self::StopOnIOThread
, this,
496 stop_run_loop
.QuitClosure(),
499 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
502 void ActivateTestHelper(
503 const std::string
& worker_url
,
504 ServiceWorkerStatusCode expected_status
) {
506 base::Bind(&self::SetUpRegistrationOnIOThread
, this, worker_url
));
507 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
508 base::RunLoop run_loop
;
509 BrowserThread::PostTask(
513 &self::ActivateOnIOThread
, this, run_loop
.QuitClosure(), &status
));
515 ASSERT_EQ(expected_status
, status
);
518 void FetchOnRegisteredWorker(
519 ServiceWorkerFetchEventResult
* result
,
520 ServiceWorkerResponse
* response
,
521 scoped_ptr
<storage::BlobDataHandle
>* blob_data_handle
) {
522 blob_context_
= ChromeBlobStorageContext::GetFor(
523 shell()->web_contents()->GetBrowserContext());
524 bool prepare_result
= false;
525 FetchResult fetch_result
;
526 fetch_result
.status
= SERVICE_WORKER_ERROR_FAILED
;
527 base::RunLoop fetch_run_loop
;
528 BrowserThread::PostTask(BrowserThread::IO
,
530 base::Bind(&self::FetchOnIOThread
,
532 fetch_run_loop
.QuitClosure(),
535 fetch_run_loop
.Run();
536 ASSERT_TRUE(prepare_result
);
537 *result
= fetch_result
.result
;
538 *response
= fetch_result
.response
;
539 *blob_data_handle
= fetch_result
.blob_data_handle
.Pass();
540 ASSERT_EQ(SERVICE_WORKER_OK
, fetch_result
.status
);
543 void FetchTestHelper(const std::string
& worker_url
,
544 ServiceWorkerFetchEventResult
* result
,
545 ServiceWorkerResponse
* response
,
546 scoped_ptr
<storage::BlobDataHandle
>* blob_data_handle
) {
548 base::Bind(&self::SetUpRegistrationOnIOThread
, this, worker_url
));
549 FetchOnRegisteredWorker(result
, response
, blob_data_handle
);
552 void SetUpRegistrationOnIOThread(const std::string
& worker_url
) {
553 const GURL pattern
= embedded_test_server()->GetURL("/service_worker/");
554 registration_
= new ServiceWorkerRegistration(
556 wrapper()->context()->storage()->NewRegistrationId(),
557 wrapper()->context()->AsWeakPtr());
558 version_
= new ServiceWorkerVersion(
560 embedded_test_server()->GetURL(worker_url
),
561 wrapper()->context()->storage()->NewVersionId(),
562 wrapper()->context()->AsWeakPtr());
564 // Make the registration findable via storage functions.
565 wrapper()->context()->storage()->NotifyInstallingRegistration(
566 registration_
.get());
568 AssociateRendererProcessToPattern(pattern
);
571 void TimeoutWorkerOnIOThread() {
572 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
573 version_
->PingWorker();
574 version_
->OnPingTimeout();
577 void StartWorker(ServiceWorkerStatusCode expected_status
) {
578 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
579 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
580 base::RunLoop start_run_loop
;
581 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
582 base::Bind(&self::StartOnIOThread
, this,
583 start_run_loop
.QuitClosure(),
585 start_run_loop
.Run();
586 ASSERT_EQ(expected_status
, status
);
589 void StopWorker(ServiceWorkerStatusCode expected_status
) {
590 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
591 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
592 base::RunLoop stop_run_loop
;
593 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
594 base::Bind(&self::StopOnIOThread
, this,
595 stop_run_loop
.QuitClosure(),
598 ASSERT_EQ(expected_status
, status
);
601 void StartOnIOThread(const base::Closure
& done
,
602 ServiceWorkerStatusCode
* result
) {
603 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
604 version_
->StartWorker(CreateReceiver(BrowserThread::UI
, done
, result
));
607 void InstallOnIOThread(const base::Closure
& done
,
608 ServiceWorkerStatusCode
* result
) {
609 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
610 version_
->SetStatus(ServiceWorkerVersion::INSTALLING
);
611 version_
->DispatchInstallEvent(
612 CreateReceiver(BrowserThread::UI
, done
, result
));
615 void ActivateOnIOThread(const base::Closure
& done
,
616 ServiceWorkerStatusCode
* result
) {
617 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
618 version_
->SetStatus(ServiceWorkerVersion::ACTIVATING
);
619 version_
->DispatchActivateEvent(
620 CreateReceiver(BrowserThread::UI
, done
, result
));
623 void FetchOnIOThread(const base::Closure
& done
,
624 bool* prepare_result
,
625 FetchResult
* result
) {
626 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
627 ServiceWorkerFetchRequest
request(
628 embedded_test_server()->GetURL("/service_worker/empty.html"),
630 ServiceWorkerHeaderMap(),
633 version_
->SetStatus(ServiceWorkerVersion::ACTIVATED
);
634 version_
->DispatchFetchEvent(
636 CreatePrepareReceiver(prepare_result
),
637 CreateResponseReceiver(
638 BrowserThread::UI
, done
, blob_context_
.get(), result
));
641 void StopOnIOThread(const base::Closure
& done
,
642 ServiceWorkerStatusCode
* result
) {
643 ASSERT_TRUE(version_
.get());
644 version_
->StopWorker(CreateReceiver(BrowserThread::UI
, done
, result
));
647 void SyncEventOnIOThread(const base::Closure
& done
,
648 ServiceWorkerStatusCode
* result
) {
649 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
650 version_
->SetStatus(ServiceWorkerVersion::ACTIVATED
);
651 version_
->DispatchSyncEvent(
652 CreateReceiver(BrowserThread::UI
, done
, result
));
656 scoped_refptr
<ServiceWorkerRegistration
> registration_
;
657 scoped_refptr
<ServiceWorkerVersion
> version_
;
658 scoped_refptr
<ChromeBlobStorageContext
> blob_context_
;
661 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
, StartAndStop
) {
662 // Start a worker and wait until OnStarted() is called.
663 base::RunLoop start_run_loop
;
664 done_closure_
= start_run_loop
.QuitClosure();
665 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
666 base::Bind(&self::StartOnIOThread
, this));
667 start_run_loop
.Run();
669 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING
, last_worker_status_
);
671 // Stop a worker and wait until OnStopped() is called.
672 base::RunLoop stop_run_loop
;
673 done_closure_
= stop_run_loop
.QuitClosure();
674 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
675 base::Bind(&self::StopOnIOThread
, this));
678 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED
, last_worker_status_
);
681 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
, StartPaused_ThenResume
) {
682 pause_mode_
= PAUSE_THEN_RESUME
;
683 base::RunLoop start_run_loop
;
684 done_closure_
= start_run_loop
.QuitClosure();
685 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
686 base::Bind(&self::StartOnIOThread
, this));
687 start_run_loop
.Run();
688 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING
, last_worker_status_
);
691 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
,
692 StartPaused_ThenStop
) {
693 pause_mode_
= PAUSE_THEN_STOP
;
694 base::RunLoop start_run_loop
;
695 done_closure_
= start_run_loop
.QuitClosure();
696 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
697 base::Bind(&self::StartOnIOThread
, this));
698 start_run_loop
.Run();
699 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED
, last_worker_status_
);
702 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, StartAndStop
) {
703 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
704 "/service_worker/worker.js"));
707 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
708 base::RunLoop start_run_loop
;
709 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
710 base::Bind(&self::StartOnIOThread
, this,
711 start_run_loop
.QuitClosure(),
713 start_run_loop
.Run();
714 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
717 status
= SERVICE_WORKER_ERROR_FAILED
;
718 base::RunLoop stop_run_loop
;
719 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
720 base::Bind(&self::StopOnIOThread
, this,
721 stop_run_loop
.QuitClosure(),
724 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
727 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, StartNotFound
) {
728 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
729 "/service_worker/nonexistent.js"));
731 // Start a worker for nonexistent URL.
732 StartWorker(SERVICE_WORKER_ERROR_NETWORK
);
735 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, Install
) {
736 InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK
);
739 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
740 InstallWithWaitUntil_Fulfilled
) {
741 InstallTestHelper("/service_worker/worker_install_fulfilled.js",
745 // Check that ServiceWorker script requests set a "Service-Worker: script"
747 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
748 ServiceWorkerScriptHeader
) {
749 embedded_test_server()->RegisterRequestHandler(
750 base::Bind(&VerifyServiceWorkerHeaderInRequest
));
751 InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK
);
754 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
755 Activate_NoEventListener
) {
756 ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK
);
757 ASSERT_EQ(ServiceWorkerVersion::ACTIVATING
, version_
->status());
760 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, Activate_Rejected
) {
761 ActivateTestHelper("/service_worker/worker_activate_rejected.js",
762 SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED
);
765 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
766 InstallWithWaitUntil_Rejected
) {
767 InstallTestHelper("/service_worker/worker_install_rejected.js",
768 SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
);
771 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
772 InstallWithWaitUntil_RejectConsoleMessage
) {
773 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
774 "/service_worker/worker_install_rejected.js"));
776 ConsoleListener console_listener
;
777 version_
->embedded_worker()->AddListener(&console_listener
);
779 // Dispatch install on a worker.
780 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
781 base::RunLoop install_run_loop
;
782 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
783 base::Bind(&self::InstallOnIOThread
, this,
784 install_run_loop
.QuitClosure(), &status
));
785 install_run_loop
.Run();
786 ASSERT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
, status
);
788 const base::string16 expected
=
789 base::ASCIIToUTF16("Rejecting oninstall event");
790 console_listener
.WaitForConsoleMessages(1);
791 ASSERT_NE(base::string16::npos
,
792 console_listener
.messages()[0].find(expected
));
793 version_
->embedded_worker()->RemoveListener(&console_listener
);
796 class WaitForLoaded
: public EmbeddedWorkerInstance::Listener
{
798 WaitForLoaded(const base::Closure
& quit
) : quit_(quit
) {}
800 void OnScriptLoaded() override
{
801 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, quit_
);
803 bool OnMessageReceived(const IPC::Message
& message
) override
{ return false; }
809 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, TimeoutStartingWorker
) {
810 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
811 "/service_worker/while_true_worker.js"));
813 // Start a worker, waiting until the script is loaded.
814 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
815 base::RunLoop start_run_loop
;
816 base::RunLoop load_run_loop
;
817 WaitForLoaded
wait_for_load(load_run_loop
.QuitClosure());
818 version_
->embedded_worker()->AddListener(&wait_for_load
);
819 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
820 base::Bind(&self::StartOnIOThread
, this,
821 start_run_loop
.QuitClosure(), &status
));
823 version_
->embedded_worker()->RemoveListener(&wait_for_load
);
825 // The script has loaded but start has not completed yet.
826 ASSERT_EQ(SERVICE_WORKER_ERROR_FAILED
, status
);
827 EXPECT_EQ(ServiceWorkerVersion::STARTING
, version_
->running_status());
829 // Simulate execution timeout. Use a delay to prevent killing the worker
830 // before it's started execution.
831 EXPECT_TRUE(version_
->timeout_timer_
.IsRunning());
832 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread
, this),
833 base::TimeDelta::FromMilliseconds(100));
834 start_run_loop
.Run();
836 EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT
, status
);
839 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, TimeoutWorkerInEvent
) {
840 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
841 "/service_worker/while_true_in_install_worker.js"));
844 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
845 base::RunLoop start_run_loop
;
846 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
847 base::Bind(&self::StartOnIOThread
, this,
848 start_run_loop
.QuitClosure(), &status
));
849 start_run_loop
.Run();
850 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
852 // Dispatch an event.
853 base::RunLoop install_run_loop
;
854 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
855 base::Bind(&self::InstallOnIOThread
, this,
856 install_run_loop
.QuitClosure(), &status
));
858 // Simulate execution timeout. Use a delay to prevent killing the worker
859 // before it's started execution.
860 EXPECT_TRUE(version_
->timeout_timer_
.IsRunning());
861 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread
, this),
862 base::TimeDelta::FromMilliseconds(100));
863 install_run_loop
.Run();
865 EXPECT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
, status
);
868 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, FetchEvent_Response
) {
869 ServiceWorkerFetchEventResult result
;
870 ServiceWorkerResponse response
;
871 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
872 FetchTestHelper("/service_worker/fetch_event.js",
873 &result
, &response
, &blob_data_handle
);
874 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
, result
);
875 EXPECT_EQ(301, response
.status_code
);
876 EXPECT_EQ("Moved Permanently", response
.status_text
);
877 ServiceWorkerHeaderMap expected_headers
;
878 expected_headers
["content-language"] = "fi";
879 expected_headers
["content-type"] = "text/html; charset=UTF-8";
880 EXPECT_EQ(expected_headers
, response
.headers
);
884 base::Bind(&ReadResponseBody
,
885 &body
, base::Owned(blob_data_handle
.release())));
886 EXPECT_EQ("This resource is gone. Gone, gone, gone.", body
);
889 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
890 FetchEvent_respondWithRejection
) {
891 ServiceWorkerFetchEventResult result
;
892 ServiceWorkerResponse response
;
893 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
895 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
896 "/service_worker/fetch_event_rejected.js"));
898 ConsoleListener console_listener
;
899 version_
->embedded_worker()->AddListener(&console_listener
);
901 FetchOnRegisteredWorker(&result
, &response
, &blob_data_handle
);
902 const base::string16 expected
=
903 base::ASCIIToUTF16("Rejecting respondWith promise");
904 console_listener
.WaitForConsoleMessages(1);
905 ASSERT_NE(base::string16::npos
,
906 console_listener
.messages()[0].find(expected
));
907 version_
->embedded_worker()->RemoveListener(&console_listener
);
909 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
, result
);
910 EXPECT_EQ(0, response
.status_code
);
912 ASSERT_FALSE(blob_data_handle
);
915 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
916 SyncAbortedWithoutFlag
) {
917 RunOnIOThread(base::Bind(
918 &self::SetUpRegistrationOnIOThread
, this, "/service_worker/sync.js"));
920 // Run the sync event.
921 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
922 base::RunLoop sync_run_loop
;
923 BrowserThread::PostTask(BrowserThread::IO
,
925 base::Bind(&self::SyncEventOnIOThread
,
927 sync_run_loop
.QuitClosure(),
930 ASSERT_EQ(SERVICE_WORKER_ERROR_ABORT
, status
);
933 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, SyncEventHandled
) {
934 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
935 command_line
->AppendSwitch(switches::kEnableServiceWorkerSync
);
937 RunOnIOThread(base::Bind(
938 &self::SetUpRegistrationOnIOThread
, this, "/service_worker/sync.js"));
939 ServiceWorkerFetchEventResult result
;
940 ServiceWorkerResponse response
;
941 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
942 // Should 404 before sync event.
943 FetchOnRegisteredWorker(&result
, &response
, &blob_data_handle
);
944 EXPECT_EQ(404, response
.status_code
);
946 // Run the sync event.
947 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
948 base::RunLoop sync_run_loop
;
949 BrowserThread::PostTask(BrowserThread::IO
,
951 base::Bind(&self::SyncEventOnIOThread
,
953 sync_run_loop
.QuitClosure(),
956 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
958 // Should 200 after sync event.
959 FetchOnRegisteredWorker(&result
, &response
, &blob_data_handle
);
960 EXPECT_EQ(200, response
.status_code
);
963 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, Reload
) {
964 const char kPageUrl
[] = "/service_worker/reload.html";
965 const char kWorkerUrl
[] = "/service_worker/fetch_event_reload.js";
966 scoped_refptr
<WorkerActivatedObserver
> observer
=
967 new WorkerActivatedObserver(wrapper());
969 public_context()->RegisterServiceWorker(
970 embedded_test_server()->GetURL(kPageUrl
),
971 embedded_test_server()->GetURL(kWorkerUrl
),
972 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
975 const base::string16 title1
= base::ASCIIToUTF16("reload=false");
976 TitleWatcher
title_watcher1(shell()->web_contents(), title1
);
977 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
978 EXPECT_EQ(title1
, title_watcher1
.WaitAndGetTitle());
980 const base::string16 title2
= base::ASCIIToUTF16("reload=true");
981 TitleWatcher
title_watcher2(shell()->web_contents(), title2
);
982 ReloadBlockUntilNavigationsComplete(shell(), 1);
983 EXPECT_EQ(title2
, title_watcher2
.WaitAndGetTitle());
987 base::RunLoop run_loop
;
988 public_context()->UnregisterServiceWorker(
989 embedded_test_server()->GetURL(kPageUrl
),
990 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
994 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
,
995 ResponseFromHTTPSServiceWorkerIsMarkedAsSecure
) {
996 const char kPageUrl
[] = "files/service_worker/fetch_event_blob.html";
997 const char kWorkerUrl
[] = "files/service_worker/fetch_event_blob.js";
998 net::SpawnedTestServer
https_server(
999 net::SpawnedTestServer::TYPE_HTTPS
,
1000 net::BaseTestServer::SSLOptions(
1001 net::BaseTestServer::SSLOptions::CERT_OK
),
1002 base::FilePath(FILE_PATH_LITERAL("content/test/data/")));
1003 ASSERT_TRUE(https_server
.Start());
1005 scoped_refptr
<WorkerActivatedObserver
> observer
=
1006 new WorkerActivatedObserver(wrapper());
1008 public_context()->RegisterServiceWorker(
1009 https_server
.GetURL(kPageUrl
),
1010 https_server
.GetURL(kWorkerUrl
),
1011 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
1014 const base::string16 title
= base::ASCIIToUTF16("Title");
1015 TitleWatcher
title_watcher(shell()->web_contents(), title
);
1016 NavigateToURL(shell(), https_server
.GetURL(kPageUrl
));
1017 EXPECT_EQ(title
, title_watcher
.WaitAndGetTitle());
1018 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
1019 NavigationEntry
* entry
=
1020 shell()->web_contents()->GetController().GetVisibleEntry();
1021 EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED
, entry
->GetSSL().security_style
);
1025 base::RunLoop run_loop
;
1026 public_context()->UnregisterServiceWorker(
1027 https_server
.GetURL(kPageUrl
),
1028 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1032 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
,
1033 ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure
) {
1034 const char kPageUrl
[] = "/service_worker/fetch_event_blob.html";
1035 const char kWorkerUrl
[] = "/service_worker/fetch_event_blob.js";
1036 scoped_refptr
<WorkerActivatedObserver
> observer
=
1037 new WorkerActivatedObserver(wrapper());
1039 public_context()->RegisterServiceWorker(
1040 embedded_test_server()->GetURL(kPageUrl
),
1041 embedded_test_server()->GetURL(kWorkerUrl
),
1042 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
1045 const base::string16 title
= base::ASCIIToUTF16("Title");
1046 TitleWatcher
title_watcher(shell()->web_contents(), title
);
1047 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
1048 EXPECT_EQ(title
, title_watcher
.WaitAndGetTitle());
1049 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
1050 NavigationEntry
* entry
=
1051 shell()->web_contents()->GetController().GetVisibleEntry();
1052 EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED
, entry
->GetSSL().security_style
);
1056 base::RunLoop run_loop
;
1057 public_context()->UnregisterServiceWorker(
1058 embedded_test_server()->GetURL(kPageUrl
),
1059 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1063 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, ImportsBustMemcache
) {
1064 const char kScopeUrl
[] = "/service_worker/imports_bust_memcache_scope/";
1065 const char kPageUrl
[] = "/service_worker/imports_bust_memcache.html";
1066 const char kScriptUrl
[] = "/service_worker/worker_with_one_import.js";
1067 const char kImportUrl
[] = "/service_worker/long_lived_import.js";
1068 const base::string16
kOKTitle(base::ASCIIToUTF16("OK"));
1069 const base::string16
kFailTitle(base::ASCIIToUTF16("FAIL"));
1072 base::Bind(&CreateLongLivedResourceInterceptors
,
1073 embedded_test_server()->GetURL(kScriptUrl
),
1074 embedded_test_server()->GetURL(kImportUrl
)));
1076 TitleWatcher
title_watcher(shell()->web_contents(), kOKTitle
);
1077 title_watcher
.AlsoWaitForTitle(kFailTitle
);
1078 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
1079 base::string16 title
= title_watcher
.WaitAndGetTitle();
1080 EXPECT_EQ(kOKTitle
, title
);
1082 // Verify the number of resources in the implicit script cache is correct.
1083 const int kExpectedNumResources
= 2;
1084 int num_resources
= 0;
1086 base::Bind(&CountScriptResources
,
1087 base::Unretained(wrapper()),
1088 embedded_test_server()->GetURL(kScopeUrl
),
1090 EXPECT_EQ(kExpectedNumResources
, num_resources
);
1093 class ServiceWorkerBlackBoxBrowserTest
: public ServiceWorkerBrowserTest
{
1095 using self
= ServiceWorkerBlackBoxBrowserTest
;
1097 void FindRegistrationOnIO(const GURL
& document_url
,
1098 ServiceWorkerStatusCode
* status
,
1099 const base::Closure
& continuation
) {
1100 wrapper()->context()->storage()->FindRegistrationForDocument(
1102 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO2
,
1108 void FindRegistrationOnIO2(
1109 ServiceWorkerStatusCode
* out_status
,
1110 const base::Closure
& continuation
,
1111 ServiceWorkerStatusCode status
,
1112 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
1113 *out_status
= status
;
1114 if (!registration
.get())
1115 EXPECT_NE(SERVICE_WORKER_OK
, status
);
1120 static int CountRenderProcessHosts() {
1122 for (RenderProcessHost::iterator
iter(RenderProcessHost::AllHostsIterator());
1130 // Flaky timeouts on CrOS and crash on Android: http://crbug.com/387045
1131 #if defined(OS_CHROMEOS) || defined(ANDROID)
1132 #define MAYBE_Registration DISABLED_Registration
1134 #define MAYBE_Registration Registration
1136 IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest
, MAYBE_Registration
) {
1137 // Close the only window to be sure we're not re-using its RenderProcessHost.
1139 EXPECT_EQ(0, CountRenderProcessHosts());
1141 const char kWorkerUrl
[] = "/service_worker/fetch_event.js";
1142 const char kScope
[] = "/service_worker/";
1144 // Unregistering nothing should return false.
1146 base::RunLoop run_loop
;
1147 public_context()->UnregisterServiceWorker(
1148 embedded_test_server()->GetURL("/"),
1149 base::Bind(&ExpectResultAndRun
, false, run_loop
.QuitClosure()));
1153 // If we use a worker URL that doesn't exist, registration fails.
1155 base::RunLoop run_loop
;
1156 public_context()->RegisterServiceWorker(
1157 embedded_test_server()->GetURL(kScope
),
1158 embedded_test_server()->GetURL("/does/not/exist"),
1159 base::Bind(&ExpectResultAndRun
, false, run_loop
.QuitClosure()));
1162 EXPECT_EQ(0, CountRenderProcessHosts());
1164 // Register returns when the promise would be resolved.
1166 base::RunLoop run_loop
;
1167 public_context()->RegisterServiceWorker(
1168 embedded_test_server()->GetURL(kScope
),
1169 embedded_test_server()->GetURL(kWorkerUrl
),
1170 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1173 EXPECT_EQ(1, CountRenderProcessHosts());
1175 // Registering again should succeed, although the algo still
1176 // might not be complete.
1178 base::RunLoop run_loop
;
1179 public_context()->RegisterServiceWorker(
1180 embedded_test_server()->GetURL(kScope
),
1181 embedded_test_server()->GetURL(kWorkerUrl
),
1182 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1186 // The registration algo might not be far enough along to have
1187 // stored the registration data, so it may not be findable
1190 // Unregistering something should return true.
1192 base::RunLoop run_loop
;
1193 public_context()->UnregisterServiceWorker(
1194 embedded_test_server()->GetURL(kScope
),
1195 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1198 EXPECT_GE(1, CountRenderProcessHosts()) << "Unregistering doesn't stop the "
1199 "workers eagerly, so their RPHs "
1200 "can still be running.";
1202 // Should not be able to find it.
1204 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1206 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO
,
1208 embedded_test_server()->GetURL("/service_worker/empty.html"),
1210 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, status
);
1214 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, CrossSiteTransfer
) {
1215 // The first page registers a service worker.
1216 const char kRegisterPageUrl
[] = "/service_worker/cross_site_xfer.html";
1217 const base::string16
kOKTitle1(base::ASCIIToUTF16("OK_1"));
1218 const base::string16
kFailTitle1(base::ASCIIToUTF16("FAIL_1"));
1219 content::TitleWatcher
title_watcher1(shell()->web_contents(), kOKTitle1
);
1220 title_watcher1
.AlsoWaitForTitle(kFailTitle1
);
1222 NavigateToURL(shell(), embedded_test_server()->GetURL(kRegisterPageUrl
));
1223 ASSERT_EQ(kOKTitle1
, title_watcher1
.WaitAndGetTitle());
1225 // Force process swapping behavior.
1226 ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
1228 // The second pages loads via the serviceworker including a subresource.
1229 const char kConfirmPageUrl
[] =
1230 "/service_worker/cross_site_xfer_scope/"
1231 "cross_site_xfer_confirm_via_serviceworker.html";
1232 const base::string16
kOKTitle2(base::ASCIIToUTF16("OK_2"));
1233 const base::string16
kFailTitle2(base::ASCIIToUTF16("FAIL_2"));
1234 content::TitleWatcher
title_watcher2(shell()->web_contents(), kOKTitle2
);
1235 title_watcher2
.AlsoWaitForTitle(kFailTitle2
);
1237 NavigateToURL(shell(), embedded_test_server()->GetURL(kConfirmPageUrl
));
1238 EXPECT_EQ(kOKTitle2
, title_watcher2
.WaitAndGetTitle());
1241 class ServiceWorkerVersionBrowserV8CacheTest
1242 : public ServiceWorkerVersionBrowserTest
,
1243 public ServiceWorkerVersion::Listener
{
1245 using self
= ServiceWorkerVersionBrowserV8CacheTest
;
1246 ~ServiceWorkerVersionBrowserV8CacheTest() override
{
1248 version_
->RemoveListener(this);
1250 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1251 ServiceWorkerBrowserTest::SetUpCommandLine(command_line
);
1252 command_line
->AppendSwitchASCII(switches::kV8CacheOptions
, "code");
1254 void SetUpRegistrationAndListenerOnIOThread(const std::string
& worker_url
) {
1255 SetUpRegistrationOnIOThread(worker_url
);
1256 version_
->AddListener(this);
1260 // ServiceWorkerVersion::Listener overrides
1261 void OnCachedMetadataUpdated(ServiceWorkerVersion
* version
) override
{
1262 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
1263 cache_updated_closure_
);
1266 base::Closure cache_updated_closure_
;
1269 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest
, Restart
) {
1270 RunOnIOThread(base::Bind(&self::SetUpRegistrationAndListenerOnIOThread
, this,
1271 "/service_worker/worker.js"));
1273 base::RunLoop cached_metadata_run_loop
;
1274 cache_updated_closure_
= cached_metadata_run_loop
.QuitClosure();
1277 StartWorker(SERVICE_WORKER_OK
);
1279 // Wait for the matadata is stored. This run loop should finish when
1280 // OnCachedMetadataUpdated() is called.
1281 cached_metadata_run_loop
.Run();
1283 // Activate the worker.
1284 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1285 base::RunLoop acrivate_run_loop
;
1286 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
1287 base::Bind(&self::ActivateOnIOThread
, this,
1288 acrivate_run_loop
.QuitClosure(), &status
));
1289 acrivate_run_loop
.Run();
1290 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
1292 StopWorker(SERVICE_WORKER_OK
);
1293 // Restart the worker.
1294 StartWorker(SERVICE_WORKER_OK
);
1296 StopWorker(SERVICE_WORKER_OK
);
1299 } // namespace content