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 ServiceWorkerVersionBrowserTest
: public ServiceWorkerBrowserTest
{
432 using self
= ServiceWorkerVersionBrowserTest
;
434 ~ServiceWorkerVersionBrowserTest() override
{}
436 void TearDownOnIOThread() override
{
437 registration_
= NULL
;
441 void InstallTestHelper(const std::string
& worker_url
,
442 ServiceWorkerStatusCode expected_status
) {
443 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
446 // Dispatch install on a worker.
447 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
448 base::RunLoop install_run_loop
;
449 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
450 base::Bind(&self::InstallOnIOThread
, this,
451 install_run_loop
.QuitClosure(),
453 install_run_loop
.Run();
454 ASSERT_EQ(expected_status
, status
);
457 status
= SERVICE_WORKER_ERROR_FAILED
;
458 base::RunLoop stop_run_loop
;
459 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
460 base::Bind(&self::StopOnIOThread
, this,
461 stop_run_loop
.QuitClosure(),
464 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
467 void ActivateTestHelper(
468 const std::string
& worker_url
,
469 ServiceWorkerStatusCode expected_status
) {
471 base::Bind(&self::SetUpRegistrationOnIOThread
, this, worker_url
));
472 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
473 base::RunLoop run_loop
;
474 BrowserThread::PostTask(
478 &self::ActivateOnIOThread
, this, run_loop
.QuitClosure(), &status
));
480 ASSERT_EQ(expected_status
, status
);
483 void FetchOnRegisteredWorker(
484 ServiceWorkerFetchEventResult
* result
,
485 ServiceWorkerResponse
* response
,
486 scoped_ptr
<storage::BlobDataHandle
>* blob_data_handle
) {
487 blob_context_
= ChromeBlobStorageContext::GetFor(
488 shell()->web_contents()->GetBrowserContext());
489 bool prepare_result
= false;
490 FetchResult fetch_result
;
491 fetch_result
.status
= SERVICE_WORKER_ERROR_FAILED
;
492 base::RunLoop fetch_run_loop
;
493 BrowserThread::PostTask(BrowserThread::IO
,
495 base::Bind(&self::FetchOnIOThread
,
497 fetch_run_loop
.QuitClosure(),
500 fetch_run_loop
.Run();
501 ASSERT_TRUE(prepare_result
);
502 *result
= fetch_result
.result
;
503 *response
= fetch_result
.response
;
504 *blob_data_handle
= fetch_result
.blob_data_handle
.Pass();
505 ASSERT_EQ(SERVICE_WORKER_OK
, fetch_result
.status
);
508 void FetchTestHelper(const std::string
& worker_url
,
509 ServiceWorkerFetchEventResult
* result
,
510 ServiceWorkerResponse
* response
,
511 scoped_ptr
<storage::BlobDataHandle
>* blob_data_handle
) {
513 base::Bind(&self::SetUpRegistrationOnIOThread
, this, worker_url
));
514 FetchOnRegisteredWorker(result
, response
, blob_data_handle
);
517 void SetUpRegistrationOnIOThread(const std::string
& worker_url
) {
518 const GURL pattern
= embedded_test_server()->GetURL("/service_worker/");
519 registration_
= new ServiceWorkerRegistration(
521 wrapper()->context()->storage()->NewRegistrationId(),
522 wrapper()->context()->AsWeakPtr());
523 version_
= new ServiceWorkerVersion(
525 embedded_test_server()->GetURL(worker_url
),
526 wrapper()->context()->storage()->NewVersionId(),
527 wrapper()->context()->AsWeakPtr());
529 // Make the registration findable via storage functions.
530 wrapper()->context()->storage()->NotifyInstallingRegistration(
531 registration_
.get());
533 AssociateRendererProcessToPattern(pattern
);
536 void TimeoutWorkerOnIOThread() {
537 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
538 version_
->PingWorker();
539 version_
->OnPingTimeout();
542 void StartWorker(ServiceWorkerStatusCode expected_status
) {
543 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
544 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
545 base::RunLoop start_run_loop
;
546 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
547 base::Bind(&self::StartOnIOThread
, this,
548 start_run_loop
.QuitClosure(),
550 start_run_loop
.Run();
551 ASSERT_EQ(expected_status
, status
);
554 void StopWorker(ServiceWorkerStatusCode expected_status
) {
555 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
556 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
557 base::RunLoop stop_run_loop
;
558 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
559 base::Bind(&self::StopOnIOThread
, this,
560 stop_run_loop
.QuitClosure(),
563 ASSERT_EQ(expected_status
, status
);
566 void StartOnIOThread(const base::Closure
& done
,
567 ServiceWorkerStatusCode
* result
) {
568 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
569 version_
->StartWorker(CreateReceiver(BrowserThread::UI
, done
, result
));
572 void InstallOnIOThread(const base::Closure
& done
,
573 ServiceWorkerStatusCode
* result
) {
574 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
575 version_
->SetStatus(ServiceWorkerVersion::INSTALLING
);
576 version_
->DispatchInstallEvent(
577 CreateReceiver(BrowserThread::UI
, done
, result
));
580 void ActivateOnIOThread(const base::Closure
& done
,
581 ServiceWorkerStatusCode
* result
) {
582 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
583 version_
->SetStatus(ServiceWorkerVersion::ACTIVATING
);
584 version_
->DispatchActivateEvent(
585 CreateReceiver(BrowserThread::UI
, done
, result
));
588 void FetchOnIOThread(const base::Closure
& done
,
589 bool* prepare_result
,
590 FetchResult
* result
) {
591 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
592 ServiceWorkerFetchRequest
request(
593 embedded_test_server()->GetURL("/service_worker/empty.html"),
595 ServiceWorkerHeaderMap(),
598 version_
->SetStatus(ServiceWorkerVersion::ACTIVATED
);
599 version_
->DispatchFetchEvent(
601 CreatePrepareReceiver(prepare_result
),
602 CreateResponseReceiver(
603 BrowserThread::UI
, done
, blob_context_
.get(), result
));
606 void StopOnIOThread(const base::Closure
& done
,
607 ServiceWorkerStatusCode
* result
) {
608 ASSERT_TRUE(version_
.get());
609 version_
->StopWorker(CreateReceiver(BrowserThread::UI
, done
, result
));
612 void SyncEventOnIOThread(const base::Closure
& done
,
613 ServiceWorkerStatusCode
* result
) {
614 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
615 version_
->SetStatus(ServiceWorkerVersion::ACTIVATED
);
616 version_
->DispatchSyncEvent(
617 CreateReceiver(BrowserThread::UI
, done
, result
));
621 scoped_refptr
<ServiceWorkerRegistration
> registration_
;
622 scoped_refptr
<ServiceWorkerVersion
> version_
;
623 scoped_refptr
<ChromeBlobStorageContext
> blob_context_
;
626 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
, StartAndStop
) {
627 // Start a worker and wait until OnStarted() is called.
628 base::RunLoop start_run_loop
;
629 done_closure_
= start_run_loop
.QuitClosure();
630 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
631 base::Bind(&self::StartOnIOThread
, this));
632 start_run_loop
.Run();
634 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING
, last_worker_status_
);
636 // Stop a worker and wait until OnStopped() is called.
637 base::RunLoop stop_run_loop
;
638 done_closure_
= stop_run_loop
.QuitClosure();
639 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
640 base::Bind(&self::StopOnIOThread
, this));
643 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED
, last_worker_status_
);
646 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
, StartPaused_ThenResume
) {
647 pause_mode_
= PAUSE_THEN_RESUME
;
648 base::RunLoop start_run_loop
;
649 done_closure_
= start_run_loop
.QuitClosure();
650 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
651 base::Bind(&self::StartOnIOThread
, this));
652 start_run_loop
.Run();
653 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING
, last_worker_status_
);
656 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
,
657 StartPaused_ThenStop
) {
658 pause_mode_
= PAUSE_THEN_STOP
;
659 base::RunLoop start_run_loop
;
660 done_closure_
= start_run_loop
.QuitClosure();
661 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
662 base::Bind(&self::StartOnIOThread
, this));
663 start_run_loop
.Run();
664 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED
, last_worker_status_
);
667 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, StartAndStop
) {
668 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
669 "/service_worker/worker.js"));
672 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
673 base::RunLoop start_run_loop
;
674 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
675 base::Bind(&self::StartOnIOThread
, this,
676 start_run_loop
.QuitClosure(),
678 start_run_loop
.Run();
679 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
682 status
= SERVICE_WORKER_ERROR_FAILED
;
683 base::RunLoop stop_run_loop
;
684 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
685 base::Bind(&self::StopOnIOThread
, this,
686 stop_run_loop
.QuitClosure(),
689 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
692 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, StartNotFound
) {
693 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
694 "/service_worker/nonexistent.js"));
696 // Start a worker for nonexistent URL.
697 StartWorker(SERVICE_WORKER_ERROR_START_WORKER_FAILED
);
700 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, Install
) {
701 InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK
);
704 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
705 InstallWithWaitUntil_Fulfilled
) {
706 InstallTestHelper("/service_worker/worker_install_fulfilled.js",
710 // Check that ServiceWorker script requests set a "Service-Worker: script"
712 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
713 ServiceWorkerScriptHeader
) {
714 embedded_test_server()->RegisterRequestHandler(
715 base::Bind(&VerifyServiceWorkerHeaderInRequest
));
716 InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK
);
719 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
720 Activate_NoEventListener
) {
721 ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK
);
722 ASSERT_EQ(ServiceWorkerVersion::ACTIVATING
, version_
->status());
725 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, Activate_Rejected
) {
726 ActivateTestHelper("/service_worker/worker_activate_rejected.js",
727 SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED
);
730 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
731 InstallWithWaitUntil_Rejected
) {
732 InstallTestHelper("/service_worker/worker_install_rejected.js",
733 SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
);
736 class WaitForLoaded
: public EmbeddedWorkerInstance::Listener
{
738 WaitForLoaded(const base::Closure
& quit
) : quit_(quit
) {}
740 void OnScriptLoaded() override
{
741 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, quit_
);
743 bool OnMessageReceived(const IPC::Message
& message
) override
{ return false; }
749 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, TimeoutStartingWorker
) {
750 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
751 "/service_worker/while_true_worker.js"));
753 // Start a worker, waiting until the script is loaded.
754 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
755 base::RunLoop start_run_loop
;
756 base::RunLoop load_run_loop
;
757 WaitForLoaded
wait_for_load(load_run_loop
.QuitClosure());
758 version_
->embedded_worker()->AddListener(&wait_for_load
);
759 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
760 base::Bind(&self::StartOnIOThread
, this,
761 start_run_loop
.QuitClosure(), &status
));
763 version_
->embedded_worker()->RemoveListener(&wait_for_load
);
765 // The script has loaded but start has not completed yet.
766 ASSERT_EQ(SERVICE_WORKER_ERROR_FAILED
, status
);
767 EXPECT_EQ(ServiceWorkerVersion::STARTING
, version_
->running_status());
769 // Simulate execution timeout. Use a delay to prevent killing the worker
770 // before it's started execution.
771 EXPECT_TRUE(version_
->timeout_timer_
.IsRunning());
772 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread
, this),
773 base::TimeDelta::FromMilliseconds(100));
774 start_run_loop
.Run();
776 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED
, status
);
779 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, TimeoutWorkerInEvent
) {
780 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
781 "/service_worker/while_true_in_install_worker.js"));
784 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
785 base::RunLoop start_run_loop
;
786 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
787 base::Bind(&self::StartOnIOThread
, this,
788 start_run_loop
.QuitClosure(), &status
));
789 start_run_loop
.Run();
790 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
792 // Dispatch an event.
793 base::RunLoop install_run_loop
;
794 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
795 base::Bind(&self::InstallOnIOThread
, this,
796 install_run_loop
.QuitClosure(), &status
));
798 // Simulate execution timeout. Use a delay to prevent killing the worker
799 // before it's started execution.
800 EXPECT_TRUE(version_
->timeout_timer_
.IsRunning());
801 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread
, this),
802 base::TimeDelta::FromMilliseconds(100));
803 install_run_loop
.Run();
805 EXPECT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
, status
);
808 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, FetchEvent_Response
) {
809 ServiceWorkerFetchEventResult result
;
810 ServiceWorkerResponse response
;
811 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
812 FetchTestHelper("/service_worker/fetch_event.js",
813 &result
, &response
, &blob_data_handle
);
814 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
, result
);
815 EXPECT_EQ(301, response
.status_code
);
816 EXPECT_EQ("Moved Permanently", response
.status_text
);
817 ServiceWorkerHeaderMap expected_headers
;
818 expected_headers
["content-language"] = "fi";
819 expected_headers
["content-type"] = "text/html; charset=UTF-8";
820 EXPECT_EQ(expected_headers
, response
.headers
);
824 base::Bind(&ReadResponseBody
,
825 &body
, base::Owned(blob_data_handle
.release())));
826 EXPECT_EQ("This resource is gone. Gone, gone, gone.", body
);
829 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
830 SyncAbortedWithoutFlag
) {
831 RunOnIOThread(base::Bind(
832 &self::SetUpRegistrationOnIOThread
, this, "/service_worker/sync.js"));
834 // Run the sync event.
835 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
836 base::RunLoop sync_run_loop
;
837 BrowserThread::PostTask(BrowserThread::IO
,
839 base::Bind(&self::SyncEventOnIOThread
,
841 sync_run_loop
.QuitClosure(),
844 ASSERT_EQ(SERVICE_WORKER_ERROR_ABORT
, status
);
847 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, SyncEventHandled
) {
848 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
849 command_line
->AppendSwitch(switches::kEnableServiceWorkerSync
);
851 RunOnIOThread(base::Bind(
852 &self::SetUpRegistrationOnIOThread
, this, "/service_worker/sync.js"));
853 ServiceWorkerFetchEventResult result
;
854 ServiceWorkerResponse response
;
855 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
856 // Should 404 before sync event.
857 FetchOnRegisteredWorker(&result
, &response
, &blob_data_handle
);
858 EXPECT_EQ(404, response
.status_code
);
860 // Run the sync event.
861 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
862 base::RunLoop sync_run_loop
;
863 BrowserThread::PostTask(BrowserThread::IO
,
865 base::Bind(&self::SyncEventOnIOThread
,
867 sync_run_loop
.QuitClosure(),
870 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
872 // Should 200 after sync event.
873 FetchOnRegisteredWorker(&result
, &response
, &blob_data_handle
);
874 EXPECT_EQ(200, response
.status_code
);
877 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, Reload
) {
878 const char kPageUrl
[] = "/service_worker/reload.html";
879 const char kWorkerUrl
[] = "/service_worker/fetch_event_reload.js";
880 scoped_refptr
<WorkerActivatedObserver
> observer
=
881 new WorkerActivatedObserver(wrapper());
883 public_context()->RegisterServiceWorker(
884 embedded_test_server()->GetURL(kPageUrl
),
885 embedded_test_server()->GetURL(kWorkerUrl
),
886 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
889 const base::string16 title1
= base::ASCIIToUTF16("reload=false");
890 TitleWatcher
title_watcher1(shell()->web_contents(), title1
);
891 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
892 EXPECT_EQ(title1
, title_watcher1
.WaitAndGetTitle());
894 const base::string16 title2
= base::ASCIIToUTF16("reload=true");
895 TitleWatcher
title_watcher2(shell()->web_contents(), title2
);
896 ReloadBlockUntilNavigationsComplete(shell(), 1);
897 EXPECT_EQ(title2
, title_watcher2
.WaitAndGetTitle());
901 base::RunLoop run_loop
;
902 public_context()->UnregisterServiceWorker(
903 embedded_test_server()->GetURL(kPageUrl
),
904 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
908 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
,
909 ResponseFromHTTPSServiceWorkerIsMarkedAsSecure
) {
910 const char kPageUrl
[] = "files/service_worker/fetch_event_blob.html";
911 const char kWorkerUrl
[] = "files/service_worker/fetch_event_blob.js";
912 net::SpawnedTestServer
https_server(
913 net::SpawnedTestServer::TYPE_HTTPS
,
914 net::BaseTestServer::SSLOptions(
915 net::BaseTestServer::SSLOptions::CERT_OK
),
916 base::FilePath(FILE_PATH_LITERAL("content/test/data/")));
917 ASSERT_TRUE(https_server
.Start());
919 scoped_refptr
<WorkerActivatedObserver
> observer
=
920 new WorkerActivatedObserver(wrapper());
922 public_context()->RegisterServiceWorker(
923 https_server
.GetURL(kPageUrl
),
924 https_server
.GetURL(kWorkerUrl
),
925 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
928 const base::string16 title
= base::ASCIIToUTF16("Title");
929 TitleWatcher
title_watcher(shell()->web_contents(), title
);
930 NavigateToURL(shell(), https_server
.GetURL(kPageUrl
));
931 EXPECT_EQ(title
, title_watcher
.WaitAndGetTitle());
932 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
933 NavigationEntry
* entry
=
934 shell()->web_contents()->GetController().GetVisibleEntry();
935 EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED
, entry
->GetSSL().security_style
);
939 base::RunLoop run_loop
;
940 public_context()->UnregisterServiceWorker(
941 https_server
.GetURL(kPageUrl
),
942 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
946 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
,
947 ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure
) {
948 const char kPageUrl
[] = "/service_worker/fetch_event_blob.html";
949 const char kWorkerUrl
[] = "/service_worker/fetch_event_blob.js";
950 scoped_refptr
<WorkerActivatedObserver
> observer
=
951 new WorkerActivatedObserver(wrapper());
953 public_context()->RegisterServiceWorker(
954 embedded_test_server()->GetURL(kPageUrl
),
955 embedded_test_server()->GetURL(kWorkerUrl
),
956 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
959 const base::string16 title
= base::ASCIIToUTF16("Title");
960 TitleWatcher
title_watcher(shell()->web_contents(), title
);
961 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
962 EXPECT_EQ(title
, title_watcher
.WaitAndGetTitle());
963 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
964 NavigationEntry
* entry
=
965 shell()->web_contents()->GetController().GetVisibleEntry();
966 EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED
, entry
->GetSSL().security_style
);
970 base::RunLoop run_loop
;
971 public_context()->UnregisterServiceWorker(
972 embedded_test_server()->GetURL(kPageUrl
),
973 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
977 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, ImportsBustMemcache
) {
978 const char kScopeUrl
[] = "/service_worker/imports_bust_memcache_scope/";
979 const char kPageUrl
[] = "/service_worker/imports_bust_memcache.html";
980 const char kScriptUrl
[] = "/service_worker/worker_with_one_import.js";
981 const char kImportUrl
[] = "/service_worker/long_lived_import.js";
982 const base::string16
kOKTitle(base::ASCIIToUTF16("OK"));
983 const base::string16
kFailTitle(base::ASCIIToUTF16("FAIL"));
986 base::Bind(&CreateLongLivedResourceInterceptors
,
987 embedded_test_server()->GetURL(kScriptUrl
),
988 embedded_test_server()->GetURL(kImportUrl
)));
990 TitleWatcher
title_watcher(shell()->web_contents(), kOKTitle
);
991 title_watcher
.AlsoWaitForTitle(kFailTitle
);
992 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
993 base::string16 title
= title_watcher
.WaitAndGetTitle();
994 EXPECT_EQ(kOKTitle
, title
);
996 // Verify the number of resources in the implicit script cache is correct.
997 const int kExpectedNumResources
= 2;
998 int num_resources
= 0;
1000 base::Bind(&CountScriptResources
,
1001 base::Unretained(wrapper()),
1002 embedded_test_server()->GetURL(kScopeUrl
),
1004 EXPECT_EQ(kExpectedNumResources
, num_resources
);
1007 class ServiceWorkerBlackBoxBrowserTest
: public ServiceWorkerBrowserTest
{
1009 using self
= ServiceWorkerBlackBoxBrowserTest
;
1011 void FindRegistrationOnIO(const GURL
& document_url
,
1012 ServiceWorkerStatusCode
* status
,
1013 const base::Closure
& continuation
) {
1014 wrapper()->context()->storage()->FindRegistrationForDocument(
1016 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO2
,
1022 void FindRegistrationOnIO2(
1023 ServiceWorkerStatusCode
* out_status
,
1024 const base::Closure
& continuation
,
1025 ServiceWorkerStatusCode status
,
1026 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
1027 *out_status
= status
;
1028 if (!registration
.get())
1029 EXPECT_NE(SERVICE_WORKER_OK
, status
);
1034 static int CountRenderProcessHosts() {
1036 for (RenderProcessHost::iterator
iter(RenderProcessHost::AllHostsIterator());
1044 // Flaky timeouts on CrOS and crash on Android: http://crbug.com/387045
1045 #if defined(OS_CHROMEOS) || defined(ANDROID)
1046 #define MAYBE_Registration DISABLED_Registration
1048 #define MAYBE_Registration Registration
1050 IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest
, MAYBE_Registration
) {
1051 // Close the only window to be sure we're not re-using its RenderProcessHost.
1053 EXPECT_EQ(0, CountRenderProcessHosts());
1055 const char kWorkerUrl
[] = "/service_worker/fetch_event.js";
1056 const char kScope
[] = "/service_worker/";
1058 // Unregistering nothing should return false.
1060 base::RunLoop run_loop
;
1061 public_context()->UnregisterServiceWorker(
1062 embedded_test_server()->GetURL("/"),
1063 base::Bind(&ExpectResultAndRun
, false, run_loop
.QuitClosure()));
1067 // If we use a worker URL that doesn't exist, registration fails.
1069 base::RunLoop run_loop
;
1070 public_context()->RegisterServiceWorker(
1071 embedded_test_server()->GetURL(kScope
),
1072 embedded_test_server()->GetURL("/does/not/exist"),
1073 base::Bind(&ExpectResultAndRun
, false, run_loop
.QuitClosure()));
1076 EXPECT_EQ(0, CountRenderProcessHosts());
1078 // Register returns when the promise would be resolved.
1080 base::RunLoop run_loop
;
1081 public_context()->RegisterServiceWorker(
1082 embedded_test_server()->GetURL(kScope
),
1083 embedded_test_server()->GetURL(kWorkerUrl
),
1084 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1087 EXPECT_EQ(1, CountRenderProcessHosts());
1089 // Registering again should succeed, although the algo still
1090 // might not be complete.
1092 base::RunLoop run_loop
;
1093 public_context()->RegisterServiceWorker(
1094 embedded_test_server()->GetURL(kScope
),
1095 embedded_test_server()->GetURL(kWorkerUrl
),
1096 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1100 // The registration algo might not be far enough along to have
1101 // stored the registration data, so it may not be findable
1104 // Unregistering something should return true.
1106 base::RunLoop run_loop
;
1107 public_context()->UnregisterServiceWorker(
1108 embedded_test_server()->GetURL(kScope
),
1109 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1112 EXPECT_GE(1, CountRenderProcessHosts()) << "Unregistering doesn't stop the "
1113 "workers eagerly, so their RPHs "
1114 "can still be running.";
1116 // Should not be able to find it.
1118 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1120 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO
,
1122 embedded_test_server()->GetURL("/service_worker/empty.html"),
1124 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, status
);
1128 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, CrossSiteTransfer
) {
1129 // The first page registers a service worker.
1130 const char kRegisterPageUrl
[] = "/service_worker/cross_site_xfer.html";
1131 const base::string16
kOKTitle1(base::ASCIIToUTF16("OK_1"));
1132 const base::string16
kFailTitle1(base::ASCIIToUTF16("FAIL_1"));
1133 content::TitleWatcher
title_watcher1(shell()->web_contents(), kOKTitle1
);
1134 title_watcher1
.AlsoWaitForTitle(kFailTitle1
);
1136 NavigateToURL(shell(), embedded_test_server()->GetURL(kRegisterPageUrl
));
1137 ASSERT_EQ(kOKTitle1
, title_watcher1
.WaitAndGetTitle());
1139 // Force process swapping behavior.
1140 ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
1142 // The second pages loads via the serviceworker including a subresource.
1143 const char kConfirmPageUrl
[] =
1144 "/service_worker/cross_site_xfer_scope/"
1145 "cross_site_xfer_confirm_via_serviceworker.html";
1146 const base::string16
kOKTitle2(base::ASCIIToUTF16("OK_2"));
1147 const base::string16
kFailTitle2(base::ASCIIToUTF16("FAIL_2"));
1148 content::TitleWatcher
title_watcher2(shell()->web_contents(), kOKTitle2
);
1149 title_watcher2
.AlsoWaitForTitle(kFailTitle2
);
1151 NavigateToURL(shell(), embedded_test_server()->GetURL(kConfirmPageUrl
));
1152 EXPECT_EQ(kOKTitle2
, title_watcher2
.WaitAndGetTitle());
1155 class ServiceWorkerVersionBrowserV8CacheTest
1156 : public ServiceWorkerVersionBrowserTest
,
1157 public ServiceWorkerVersion::Listener
{
1159 using self
= ServiceWorkerVersionBrowserV8CacheTest
;
1160 ~ServiceWorkerVersionBrowserV8CacheTest() override
{
1162 version_
->RemoveListener(this);
1164 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1165 ServiceWorkerBrowserTest::SetUpCommandLine(command_line
);
1166 command_line
->AppendSwitchASCII(switches::kV8CacheOptions
, "code");
1168 void SetUpRegistrationAndListenerOnIOThread(const std::string
& worker_url
) {
1169 SetUpRegistrationOnIOThread(worker_url
);
1170 version_
->AddListener(this);
1174 // ServiceWorkerVersion::Listener overrides
1175 void OnCachedMetadataUpdated(ServiceWorkerVersion
* version
) override
{
1176 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
1177 cache_updated_closure_
);
1180 base::Closure cache_updated_closure_
;
1183 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest
, Restart
) {
1184 RunOnIOThread(base::Bind(&self::SetUpRegistrationAndListenerOnIOThread
, this,
1185 "/service_worker/worker.js"));
1187 base::RunLoop cached_metadata_run_loop
;
1188 cache_updated_closure_
= cached_metadata_run_loop
.QuitClosure();
1191 StartWorker(SERVICE_WORKER_OK
);
1193 // Wait for the matadata is stored. This run loop should finish when
1194 // OnCachedMetadataUpdated() is called.
1195 cached_metadata_run_loop
.Run();
1197 // Activate the worker.
1198 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1199 base::RunLoop acrivate_run_loop
;
1200 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
1201 base::Bind(&self::ActivateOnIOThread
, this,
1202 acrivate_run_loop
.QuitClosure(), &status
));
1203 acrivate_run_loop
.Run();
1204 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
1206 StopWorker(SERVICE_WORKER_OK
);
1207 // Restart the worker.
1208 StartWorker(SERVICE_WORKER_OK
);
1210 StopWorker(SERVICE_WORKER_OK
);
1213 } // namespace content