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
= context_
->GetLiveVersion(version_id
);
164 if (version
->status() == ServiceWorkerVersion::ACTIVATED
) {
165 context_
->RemoveObserver(this);
166 BrowserThread::PostTask(BrowserThread::UI
,
168 base::Bind(&WorkerActivatedObserver::Quit
, this));
171 void Wait() { run_loop_
.Run(); }
174 friend class base::RefCountedThreadSafe
<WorkerActivatedObserver
>;
175 ~WorkerActivatedObserver() override
{}
176 void InitOnIOThread() { context_
->AddObserver(this); }
177 void Quit() { run_loop_
.Quit(); }
179 base::RunLoop run_loop_
;
180 ServiceWorkerContextWrapper
* context_
;
181 DISALLOW_COPY_AND_ASSIGN(WorkerActivatedObserver
);
184 scoped_ptr
<net::test_server::HttpResponse
> VerifyServiceWorkerHeaderInRequest(
185 const net::test_server::HttpRequest
& request
) {
186 EXPECT_EQ(request
.relative_url
, "/service_worker/generated_sw.js");
187 std::map
<std::string
, std::string
>::const_iterator it
=
188 request
.headers
.find("Service-Worker");
189 EXPECT_TRUE(it
!= request
.headers
.end());
190 EXPECT_EQ("script", it
->second
);
192 scoped_ptr
<net::test_server::BasicHttpResponse
> http_response(
193 new net::test_server::BasicHttpResponse());
194 http_response
->set_content_type("text/javascript");
195 return http_response
.Pass();
198 // The ImportsBustMemcache test requires that the imported script
199 // would naturally be cached in blink's memcache, but the embedded
200 // test server doesn't produce headers that allow the blink's memcache
201 // to do that. This interceptor injects headers that give the import
202 // an experiration far in the future.
203 class LongLivedResourceInterceptor
: public net::URLRequestInterceptor
{
205 LongLivedResourceInterceptor(const std::string
& body
)
207 ~LongLivedResourceInterceptor() override
{}
209 // net::URLRequestInterceptor implementation
210 net::URLRequestJob
* MaybeInterceptRequest(
211 net::URLRequest
* request
,
212 net::NetworkDelegate
* network_delegate
) const override
{
213 const char kHeaders
[] =
215 "Content-Type: text/javascript\0"
216 "Expires: Thu, 1 Jan 2100 20:00:00 GMT\0"
218 std::string
headers(kHeaders
, arraysize(kHeaders
));
219 return new net::URLRequestTestJob(
220 request
, network_delegate
, headers
, body_
, true);
225 DISALLOW_COPY_AND_ASSIGN(LongLivedResourceInterceptor
);
228 void CreateLongLivedResourceInterceptors(
229 const GURL
& worker_url
, const GURL
& import_url
) {
230 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
231 scoped_ptr
<net::URLRequestInterceptor
> interceptor
;
233 interceptor
.reset(new LongLivedResourceInterceptor(
234 "importScripts('long_lived_import.js');"));
235 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
236 worker_url
, interceptor
.Pass());
238 interceptor
.reset(new LongLivedResourceInterceptor(
239 "// the imported script does nothing"));
240 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
241 import_url
, interceptor
.Pass());
244 void CountScriptResources(
245 ServiceWorkerContextWrapper
* wrapper
,
247 int* num_resources
) {
250 std::vector
<ServiceWorkerRegistrationInfo
> infos
=
251 wrapper
->GetAllLiveRegistrationInfo();
256 size_t index
= infos
.size() - 1;
257 if (infos
[index
].installing_version
.version_id
!=
258 kInvalidServiceWorkerVersionId
)
259 version_id
= infos
[index
].installing_version
.version_id
;
260 else if (infos
[index
].waiting_version
.version_id
!=
261 kInvalidServiceWorkerVersionId
)
262 version_id
= infos
[1].waiting_version
.version_id
;
263 else if (infos
[index
].active_version
.version_id
!=
264 kInvalidServiceWorkerVersionId
)
265 version_id
= infos
[index
].active_version
.version_id
;
269 ServiceWorkerVersion
* version
= wrapper
->GetLiveVersion(version_id
);
270 *num_resources
= static_cast<int>(version
->script_cache_map()->size());
275 class ServiceWorkerBrowserTest
: public ContentBrowserTest
{
277 using self
= ServiceWorkerBrowserTest
;
279 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
280 command_line
->AppendSwitch(
281 switches::kEnableExperimentalWebPlatformFeatures
);
284 void SetUpOnMainThread() override
{
285 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
286 StoragePartition
* partition
= BrowserContext::GetDefaultStoragePartition(
287 shell()->web_contents()->GetBrowserContext());
288 wrapper_
= static_cast<ServiceWorkerContextWrapper
*>(
289 partition
->GetServiceWorkerContext());
291 // Navigate to the page to set up a renderer page (where we can embed
293 NavigateToURLBlockUntilNavigationsComplete(
295 embedded_test_server()->GetURL("/service_worker/empty.html"), 1);
297 RunOnIOThread(base::Bind(&self::SetUpOnIOThread
, this));
300 void TearDownOnMainThread() override
{
301 RunOnIOThread(base::Bind(&self::TearDownOnIOThread
, this));
305 virtual void SetUpOnIOThread() {}
306 virtual void TearDownOnIOThread() {}
308 ServiceWorkerContextWrapper
* wrapper() { return wrapper_
.get(); }
309 ServiceWorkerContext
* public_context() { return wrapper(); }
311 void AssociateRendererProcessToPattern(const GURL
& pattern
) {
312 wrapper_
->process_manager()->AddProcessReferenceToPattern(
313 pattern
, shell()->web_contents()->GetRenderProcessHost()->GetID());
317 scoped_refptr
<ServiceWorkerContextWrapper
> wrapper_
;
320 class EmbeddedWorkerBrowserTest
: public ServiceWorkerBrowserTest
,
321 public EmbeddedWorkerInstance::Listener
{
323 using self
= EmbeddedWorkerBrowserTest
;
325 EmbeddedWorkerBrowserTest()
326 : last_worker_status_(EmbeddedWorkerInstance::STOPPED
),
327 pause_mode_(DONT_PAUSE
) {}
328 ~EmbeddedWorkerBrowserTest() override
{}
330 void TearDownOnIOThread() override
{
332 worker_
->RemoveListener(this);
337 void StartOnIOThread() {
338 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
339 worker_
= wrapper()->context()->embedded_worker_registry()->CreateWorker();
340 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker_
->status());
341 worker_
->AddListener(this);
343 const int64 service_worker_version_id
= 33L;
344 const GURL pattern
= embedded_test_server()->GetURL("/");
345 const GURL script_url
= embedded_test_server()->GetURL(
346 "/service_worker/worker.js");
347 AssociateRendererProcessToPattern(pattern
);
348 int process_id
= shell()->web_contents()->GetRenderProcessHost()->GetID();
349 wrapper()->process_manager()->AddProcessReferenceToPattern(
350 pattern
, process_id
);
352 service_worker_version_id
,
355 pause_mode_
!= DONT_PAUSE
,
356 base::Bind(&EmbeddedWorkerBrowserTest::StartOnIOThread2
, this));
358 void StartOnIOThread2(ServiceWorkerStatusCode status
) {
359 last_worker_status_
= worker_
->status();
360 EXPECT_EQ(SERVICE_WORKER_OK
, status
);
361 EXPECT_EQ(EmbeddedWorkerInstance::STARTING
, last_worker_status_
);
363 if (status
!= SERVICE_WORKER_OK
&& !done_closure_
.is_null())
367 void StopOnIOThread() {
368 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
369 EXPECT_EQ(EmbeddedWorkerInstance::RUNNING
, worker_
->status());
371 ServiceWorkerStatusCode status
= worker_
->Stop();
373 last_worker_status_
= worker_
->status();
374 EXPECT_EQ(SERVICE_WORKER_OK
, status
);
375 EXPECT_EQ(EmbeddedWorkerInstance::STOPPING
, last_worker_status_
);
377 if (status
!= SERVICE_WORKER_OK
&& !done_closure_
.is_null())
382 // EmbeddedWorkerInstance::Observer overrides:
383 void OnStarted() override
{
384 ASSERT_TRUE(worker_
!= NULL
);
385 ASSERT_FALSE(done_closure_
.is_null());
386 last_worker_status_
= worker_
->status();
387 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, done_closure_
);
389 void OnStopped(EmbeddedWorkerInstance::Status old_status
) override
{
390 ASSERT_TRUE(worker_
!= NULL
);
391 ASSERT_FALSE(done_closure_
.is_null());
392 last_worker_status_
= worker_
->status();
393 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, done_closure_
);
395 void OnPausedAfterDownload() override
{
396 if (pause_mode_
== PAUSE_THEN_RESUME
)
397 worker_
->ResumeAfterDownload();
398 else if (pause_mode_
== PAUSE_THEN_STOP
)
403 void OnReportException(const base::string16
& error_message
,
406 const GURL
& source_url
) override
{}
407 void OnReportConsoleMessage(int source_identifier
,
409 const base::string16
& message
,
411 const GURL
& source_url
) override
{}
412 bool OnMessageReceived(const IPC::Message
& message
) override
{ return false; }
414 scoped_ptr
<EmbeddedWorkerInstance
> worker_
;
415 EmbeddedWorkerInstance::Status last_worker_status_
;
423 // Called by EmbeddedWorkerInstance::Observer overrides so that
424 // test code can wait for the worker status notifications.
425 base::Closure done_closure_
;
428 class ConsoleListener
: public EmbeddedWorkerInstance::Listener
{
430 void OnReportConsoleMessage(int source_identifier
,
432 const base::string16
& message
,
434 const GURL
& source_url
) override
{
435 messages_
.push_back(message
);
436 if (!quit_
.is_null() && messages_
.size() == expected_message_count_
) {
437 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, quit_
);
442 void WaitForConsoleMessages(size_t expected_message_count
) {
443 if (messages_
.size() >= expected_message_count
)
446 expected_message_count_
= expected_message_count
;
447 base::RunLoop console_run_loop
;
448 quit_
= console_run_loop
.QuitClosure();
449 console_run_loop
.Run();
451 ASSERT_EQ(messages_
.size(), expected_message_count
);
454 bool OnMessageReceived(const IPC::Message
& message
) override
{ return false; }
455 const std::vector
<base::string16
>& messages() const { return messages_
; }
458 std::vector
<base::string16
> messages_
;
459 size_t expected_message_count_
;
463 class ServiceWorkerVersionBrowserTest
: public ServiceWorkerBrowserTest
{
465 using self
= ServiceWorkerVersionBrowserTest
;
467 ~ServiceWorkerVersionBrowserTest() override
{}
469 void TearDownOnIOThread() override
{
470 registration_
= NULL
;
474 void InstallTestHelper(const std::string
& worker_url
,
475 ServiceWorkerStatusCode expected_status
) {
476 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
479 // Dispatch install on a worker.
480 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
481 base::RunLoop install_run_loop
;
482 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
483 base::Bind(&self::InstallOnIOThread
, this,
484 install_run_loop
.QuitClosure(),
486 install_run_loop
.Run();
487 ASSERT_EQ(expected_status
, status
);
490 status
= SERVICE_WORKER_ERROR_FAILED
;
491 base::RunLoop stop_run_loop
;
492 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
493 base::Bind(&self::StopOnIOThread
, this,
494 stop_run_loop
.QuitClosure(),
497 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
500 void ActivateTestHelper(
501 const std::string
& worker_url
,
502 ServiceWorkerStatusCode expected_status
) {
504 base::Bind(&self::SetUpRegistrationOnIOThread
, this, worker_url
));
505 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
506 base::RunLoop run_loop
;
507 BrowserThread::PostTask(
511 &self::ActivateOnIOThread
, this, run_loop
.QuitClosure(), &status
));
513 ASSERT_EQ(expected_status
, status
);
516 void FetchOnRegisteredWorker(
517 ServiceWorkerFetchEventResult
* result
,
518 ServiceWorkerResponse
* response
,
519 scoped_ptr
<storage::BlobDataHandle
>* blob_data_handle
) {
520 blob_context_
= ChromeBlobStorageContext::GetFor(
521 shell()->web_contents()->GetBrowserContext());
522 bool prepare_result
= false;
523 FetchResult fetch_result
;
524 fetch_result
.status
= SERVICE_WORKER_ERROR_FAILED
;
525 base::RunLoop fetch_run_loop
;
526 BrowserThread::PostTask(BrowserThread::IO
,
528 base::Bind(&self::FetchOnIOThread
,
530 fetch_run_loop
.QuitClosure(),
533 fetch_run_loop
.Run();
534 ASSERT_TRUE(prepare_result
);
535 *result
= fetch_result
.result
;
536 *response
= fetch_result
.response
;
537 *blob_data_handle
= fetch_result
.blob_data_handle
.Pass();
538 ASSERT_EQ(SERVICE_WORKER_OK
, fetch_result
.status
);
541 void FetchTestHelper(const std::string
& worker_url
,
542 ServiceWorkerFetchEventResult
* result
,
543 ServiceWorkerResponse
* response
,
544 scoped_ptr
<storage::BlobDataHandle
>* blob_data_handle
) {
546 base::Bind(&self::SetUpRegistrationOnIOThread
, this, worker_url
));
547 FetchOnRegisteredWorker(result
, response
, blob_data_handle
);
550 void SetUpRegistrationOnIOThread(const std::string
& worker_url
) {
551 const GURL pattern
= embedded_test_server()->GetURL("/service_worker/");
552 registration_
= new ServiceWorkerRegistration(
554 wrapper()->context()->storage()->NewRegistrationId(),
555 wrapper()->context()->AsWeakPtr());
556 version_
= new ServiceWorkerVersion(
558 embedded_test_server()->GetURL(worker_url
),
559 wrapper()->context()->storage()->NewVersionId(),
560 wrapper()->context()->AsWeakPtr());
562 // Make the registration findable via storage functions.
563 wrapper()->context()->storage()->NotifyInstallingRegistration(
564 registration_
.get());
566 AssociateRendererProcessToPattern(pattern
);
569 void TimeoutWorkerOnIOThread() {
570 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
571 version_
->PingWorker();
572 version_
->OnPingTimeout();
575 void StartWorker(ServiceWorkerStatusCode expected_status
) {
576 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
577 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
578 base::RunLoop start_run_loop
;
579 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
580 base::Bind(&self::StartOnIOThread
, this,
581 start_run_loop
.QuitClosure(),
583 start_run_loop
.Run();
584 ASSERT_EQ(expected_status
, status
);
587 void StopWorker(ServiceWorkerStatusCode expected_status
) {
588 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
589 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
590 base::RunLoop stop_run_loop
;
591 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
592 base::Bind(&self::StopOnIOThread
, this,
593 stop_run_loop
.QuitClosure(),
596 ASSERT_EQ(expected_status
, status
);
599 void StartOnIOThread(const base::Closure
& done
,
600 ServiceWorkerStatusCode
* result
) {
601 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
602 version_
->StartWorker(CreateReceiver(BrowserThread::UI
, done
, result
));
605 void InstallOnIOThread(const base::Closure
& done
,
606 ServiceWorkerStatusCode
* result
) {
607 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
608 version_
->SetStatus(ServiceWorkerVersion::INSTALLING
);
609 version_
->DispatchInstallEvent(
610 CreateReceiver(BrowserThread::UI
, done
, result
));
613 void ActivateOnIOThread(const base::Closure
& done
,
614 ServiceWorkerStatusCode
* result
) {
615 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
616 version_
->SetStatus(ServiceWorkerVersion::ACTIVATING
);
617 version_
->DispatchActivateEvent(
618 CreateReceiver(BrowserThread::UI
, done
, result
));
621 void FetchOnIOThread(const base::Closure
& done
,
622 bool* prepare_result
,
623 FetchResult
* result
) {
624 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
625 ServiceWorkerFetchRequest
request(
626 embedded_test_server()->GetURL("/service_worker/empty.html"),
628 ServiceWorkerHeaderMap(),
631 version_
->SetStatus(ServiceWorkerVersion::ACTIVATED
);
632 version_
->DispatchFetchEvent(
634 CreatePrepareReceiver(prepare_result
),
635 CreateResponseReceiver(
636 BrowserThread::UI
, done
, blob_context_
.get(), result
));
639 void StopOnIOThread(const base::Closure
& done
,
640 ServiceWorkerStatusCode
* result
) {
641 ASSERT_TRUE(version_
.get());
642 version_
->StopWorker(CreateReceiver(BrowserThread::UI
, done
, result
));
645 void SyncEventOnIOThread(const base::Closure
& done
,
646 ServiceWorkerStatusCode
* result
) {
647 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
648 version_
->SetStatus(ServiceWorkerVersion::ACTIVATED
);
649 version_
->DispatchSyncEvent(
650 CreateReceiver(BrowserThread::UI
, done
, result
));
654 scoped_refptr
<ServiceWorkerRegistration
> registration_
;
655 scoped_refptr
<ServiceWorkerVersion
> version_
;
656 scoped_refptr
<ChromeBlobStorageContext
> blob_context_
;
659 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
, StartAndStop
) {
660 // Start a worker and wait until OnStarted() is called.
661 base::RunLoop start_run_loop
;
662 done_closure_
= start_run_loop
.QuitClosure();
663 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
664 base::Bind(&self::StartOnIOThread
, this));
665 start_run_loop
.Run();
667 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING
, last_worker_status_
);
669 // Stop a worker and wait until OnStopped() is called.
670 base::RunLoop stop_run_loop
;
671 done_closure_
= stop_run_loop
.QuitClosure();
672 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
673 base::Bind(&self::StopOnIOThread
, this));
676 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED
, last_worker_status_
);
679 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
, StartPaused_ThenResume
) {
680 pause_mode_
= PAUSE_THEN_RESUME
;
681 base::RunLoop start_run_loop
;
682 done_closure_
= start_run_loop
.QuitClosure();
683 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
684 base::Bind(&self::StartOnIOThread
, this));
685 start_run_loop
.Run();
686 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING
, last_worker_status_
);
689 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
,
690 StartPaused_ThenStop
) {
691 pause_mode_
= PAUSE_THEN_STOP
;
692 base::RunLoop start_run_loop
;
693 done_closure_
= start_run_loop
.QuitClosure();
694 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
695 base::Bind(&self::StartOnIOThread
, this));
696 start_run_loop
.Run();
697 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED
, last_worker_status_
);
700 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, StartAndStop
) {
701 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
702 "/service_worker/worker.js"));
705 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
706 base::RunLoop start_run_loop
;
707 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
708 base::Bind(&self::StartOnIOThread
, this,
709 start_run_loop
.QuitClosure(),
711 start_run_loop
.Run();
712 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
715 status
= SERVICE_WORKER_ERROR_FAILED
;
716 base::RunLoop stop_run_loop
;
717 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
718 base::Bind(&self::StopOnIOThread
, this,
719 stop_run_loop
.QuitClosure(),
722 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
725 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, StartNotFound
) {
726 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
727 "/service_worker/nonexistent.js"));
729 // Start a worker for nonexistent URL.
730 StartWorker(SERVICE_WORKER_ERROR_NETWORK
);
733 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, Install
) {
734 InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK
);
737 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
738 InstallWithWaitUntil_Fulfilled
) {
739 InstallTestHelper("/service_worker/worker_install_fulfilled.js",
743 // Check that ServiceWorker script requests set a "Service-Worker: script"
745 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
746 ServiceWorkerScriptHeader
) {
747 embedded_test_server()->RegisterRequestHandler(
748 base::Bind(&VerifyServiceWorkerHeaderInRequest
));
749 InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK
);
752 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
753 Activate_NoEventListener
) {
754 ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK
);
755 ASSERT_EQ(ServiceWorkerVersion::ACTIVATING
, version_
->status());
758 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, Activate_Rejected
) {
759 ActivateTestHelper("/service_worker/worker_activate_rejected.js",
760 SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED
);
763 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
764 InstallWithWaitUntil_Rejected
) {
765 InstallTestHelper("/service_worker/worker_install_rejected.js",
766 SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
);
769 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
770 InstallWithWaitUntil_RejectConsoleMessage
) {
771 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
772 "/service_worker/worker_install_rejected.js"));
774 ConsoleListener console_listener
;
775 version_
->embedded_worker()->AddListener(&console_listener
);
777 // Dispatch install on a worker.
778 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
779 base::RunLoop install_run_loop
;
780 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
781 base::Bind(&self::InstallOnIOThread
, this,
782 install_run_loop
.QuitClosure(), &status
));
783 install_run_loop
.Run();
784 ASSERT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
, status
);
786 const base::string16 expected
=
787 base::ASCIIToUTF16("Rejecting oninstall event");
788 console_listener
.WaitForConsoleMessages(1);
789 ASSERT_NE(base::string16::npos
,
790 console_listener
.messages()[0].find(expected
));
791 version_
->embedded_worker()->RemoveListener(&console_listener
);
794 class WaitForLoaded
: public EmbeddedWorkerInstance::Listener
{
796 WaitForLoaded(const base::Closure
& quit
) : quit_(quit
) {}
798 void OnScriptLoaded() override
{
799 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, quit_
);
801 bool OnMessageReceived(const IPC::Message
& message
) override
{ return false; }
807 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, TimeoutStartingWorker
) {
808 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
809 "/service_worker/while_true_worker.js"));
811 // Start a worker, waiting until the script is loaded.
812 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
813 base::RunLoop start_run_loop
;
814 base::RunLoop load_run_loop
;
815 WaitForLoaded
wait_for_load(load_run_loop
.QuitClosure());
816 version_
->embedded_worker()->AddListener(&wait_for_load
);
817 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
818 base::Bind(&self::StartOnIOThread
, this,
819 start_run_loop
.QuitClosure(), &status
));
821 version_
->embedded_worker()->RemoveListener(&wait_for_load
);
823 // The script has loaded but start has not completed yet.
824 ASSERT_EQ(SERVICE_WORKER_ERROR_FAILED
, status
);
825 EXPECT_EQ(ServiceWorkerVersion::STARTING
, version_
->running_status());
827 // Simulate execution timeout. Use a delay to prevent killing the worker
828 // before it's started execution.
829 EXPECT_TRUE(version_
->timeout_timer_
.IsRunning());
830 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread
, this),
831 base::TimeDelta::FromMilliseconds(100));
832 start_run_loop
.Run();
834 EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT
, status
);
837 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, TimeoutWorkerInEvent
) {
838 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
839 "/service_worker/while_true_in_install_worker.js"));
842 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
843 base::RunLoop start_run_loop
;
844 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
845 base::Bind(&self::StartOnIOThread
, this,
846 start_run_loop
.QuitClosure(), &status
));
847 start_run_loop
.Run();
848 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
850 // Dispatch an event.
851 base::RunLoop install_run_loop
;
852 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
853 base::Bind(&self::InstallOnIOThread
, this,
854 install_run_loop
.QuitClosure(), &status
));
856 // Simulate execution timeout. Use a delay to prevent killing the worker
857 // before it's started execution.
858 EXPECT_TRUE(version_
->timeout_timer_
.IsRunning());
859 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread
, this),
860 base::TimeDelta::FromMilliseconds(100));
861 install_run_loop
.Run();
863 EXPECT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
, status
);
866 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, FetchEvent_Response
) {
867 ServiceWorkerFetchEventResult result
;
868 ServiceWorkerResponse response
;
869 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
870 FetchTestHelper("/service_worker/fetch_event.js",
871 &result
, &response
, &blob_data_handle
);
872 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
, result
);
873 EXPECT_EQ(301, response
.status_code
);
874 EXPECT_EQ("Moved Permanently", response
.status_text
);
875 ServiceWorkerHeaderMap expected_headers
;
876 expected_headers
["content-language"] = "fi";
877 expected_headers
["content-type"] = "text/html; charset=UTF-8";
878 EXPECT_EQ(expected_headers
, response
.headers
);
882 base::Bind(&ReadResponseBody
,
883 &body
, base::Owned(blob_data_handle
.release())));
884 EXPECT_EQ("This resource is gone. Gone, gone, gone.", body
);
887 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
888 FetchEvent_respondWithRejection
) {
889 ServiceWorkerFetchEventResult result
;
890 ServiceWorkerResponse response
;
891 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
893 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
894 "/service_worker/fetch_event_rejected.js"));
896 ConsoleListener console_listener
;
897 version_
->embedded_worker()->AddListener(&console_listener
);
899 FetchOnRegisteredWorker(&result
, &response
, &blob_data_handle
);
900 const base::string16 expected
=
901 base::ASCIIToUTF16("Rejecting respondWith promise");
902 console_listener
.WaitForConsoleMessages(1);
903 ASSERT_NE(base::string16::npos
,
904 console_listener
.messages()[0].find(expected
));
905 version_
->embedded_worker()->RemoveListener(&console_listener
);
907 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
, result
);
908 EXPECT_EQ(0, response
.status_code
);
910 ASSERT_FALSE(blob_data_handle
);
913 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
914 SyncAbortedWithoutFlag
) {
915 RunOnIOThread(base::Bind(
916 &self::SetUpRegistrationOnIOThread
, this, "/service_worker/sync.js"));
918 // Run the sync event.
919 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
920 base::RunLoop sync_run_loop
;
921 BrowserThread::PostTask(BrowserThread::IO
,
923 base::Bind(&self::SyncEventOnIOThread
,
925 sync_run_loop
.QuitClosure(),
928 ASSERT_EQ(SERVICE_WORKER_ERROR_ABORT
, status
);
931 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, SyncEventHandled
) {
932 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
933 command_line
->AppendSwitch(switches::kEnableServiceWorkerSync
);
935 RunOnIOThread(base::Bind(
936 &self::SetUpRegistrationOnIOThread
, this, "/service_worker/sync.js"));
937 ServiceWorkerFetchEventResult result
;
938 ServiceWorkerResponse response
;
939 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
940 // Should 404 before sync event.
941 FetchOnRegisteredWorker(&result
, &response
, &blob_data_handle
);
942 EXPECT_EQ(404, response
.status_code
);
944 // Run the sync event.
945 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
946 base::RunLoop sync_run_loop
;
947 BrowserThread::PostTask(BrowserThread::IO
,
949 base::Bind(&self::SyncEventOnIOThread
,
951 sync_run_loop
.QuitClosure(),
954 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
956 // Should 200 after sync event.
957 FetchOnRegisteredWorker(&result
, &response
, &blob_data_handle
);
958 EXPECT_EQ(200, response
.status_code
);
961 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, Reload
) {
962 const char kPageUrl
[] = "/service_worker/reload.html";
963 const char kWorkerUrl
[] = "/service_worker/fetch_event_reload.js";
964 scoped_refptr
<WorkerActivatedObserver
> observer
=
965 new WorkerActivatedObserver(wrapper());
967 public_context()->RegisterServiceWorker(
968 embedded_test_server()->GetURL(kPageUrl
),
969 embedded_test_server()->GetURL(kWorkerUrl
),
970 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
973 const base::string16 title1
= base::ASCIIToUTF16("reload=false");
974 TitleWatcher
title_watcher1(shell()->web_contents(), title1
);
975 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
976 EXPECT_EQ(title1
, title_watcher1
.WaitAndGetTitle());
978 const base::string16 title2
= base::ASCIIToUTF16("reload=true");
979 TitleWatcher
title_watcher2(shell()->web_contents(), title2
);
980 ReloadBlockUntilNavigationsComplete(shell(), 1);
981 EXPECT_EQ(title2
, title_watcher2
.WaitAndGetTitle());
985 base::RunLoop run_loop
;
986 public_context()->UnregisterServiceWorker(
987 embedded_test_server()->GetURL(kPageUrl
),
988 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
992 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
,
993 ResponseFromHTTPSServiceWorkerIsMarkedAsSecure
) {
994 const char kPageUrl
[] = "files/service_worker/fetch_event_blob.html";
995 const char kWorkerUrl
[] = "files/service_worker/fetch_event_blob.js";
996 net::SpawnedTestServer
https_server(
997 net::SpawnedTestServer::TYPE_HTTPS
,
998 net::BaseTestServer::SSLOptions(
999 net::BaseTestServer::SSLOptions::CERT_OK
),
1000 base::FilePath(FILE_PATH_LITERAL("content/test/data/")));
1001 ASSERT_TRUE(https_server
.Start());
1003 scoped_refptr
<WorkerActivatedObserver
> observer
=
1004 new WorkerActivatedObserver(wrapper());
1006 public_context()->RegisterServiceWorker(
1007 https_server
.GetURL(kPageUrl
),
1008 https_server
.GetURL(kWorkerUrl
),
1009 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
1012 const base::string16 title
= base::ASCIIToUTF16("Title");
1013 TitleWatcher
title_watcher(shell()->web_contents(), title
);
1014 NavigateToURL(shell(), https_server
.GetURL(kPageUrl
));
1015 EXPECT_EQ(title
, title_watcher
.WaitAndGetTitle());
1016 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
1017 NavigationEntry
* entry
=
1018 shell()->web_contents()->GetController().GetVisibleEntry();
1019 EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED
, entry
->GetSSL().security_style
);
1023 base::RunLoop run_loop
;
1024 public_context()->UnregisterServiceWorker(
1025 https_server
.GetURL(kPageUrl
),
1026 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1030 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
,
1031 ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure
) {
1032 const char kPageUrl
[] = "/service_worker/fetch_event_blob.html";
1033 const char kWorkerUrl
[] = "/service_worker/fetch_event_blob.js";
1034 scoped_refptr
<WorkerActivatedObserver
> observer
=
1035 new WorkerActivatedObserver(wrapper());
1037 public_context()->RegisterServiceWorker(
1038 embedded_test_server()->GetURL(kPageUrl
),
1039 embedded_test_server()->GetURL(kWorkerUrl
),
1040 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
1043 const base::string16 title
= base::ASCIIToUTF16("Title");
1044 TitleWatcher
title_watcher(shell()->web_contents(), title
);
1045 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
1046 EXPECT_EQ(title
, title_watcher
.WaitAndGetTitle());
1047 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
1048 NavigationEntry
* entry
=
1049 shell()->web_contents()->GetController().GetVisibleEntry();
1050 EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED
, entry
->GetSSL().security_style
);
1054 base::RunLoop run_loop
;
1055 public_context()->UnregisterServiceWorker(
1056 embedded_test_server()->GetURL(kPageUrl
),
1057 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1061 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, ImportsBustMemcache
) {
1062 const char kScopeUrl
[] = "/service_worker/imports_bust_memcache_scope/";
1063 const char kPageUrl
[] = "/service_worker/imports_bust_memcache.html";
1064 const char kScriptUrl
[] = "/service_worker/worker_with_one_import.js";
1065 const char kImportUrl
[] = "/service_worker/long_lived_import.js";
1066 const base::string16
kOKTitle(base::ASCIIToUTF16("OK"));
1067 const base::string16
kFailTitle(base::ASCIIToUTF16("FAIL"));
1070 base::Bind(&CreateLongLivedResourceInterceptors
,
1071 embedded_test_server()->GetURL(kScriptUrl
),
1072 embedded_test_server()->GetURL(kImportUrl
)));
1074 TitleWatcher
title_watcher(shell()->web_contents(), kOKTitle
);
1075 title_watcher
.AlsoWaitForTitle(kFailTitle
);
1076 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
1077 base::string16 title
= title_watcher
.WaitAndGetTitle();
1078 EXPECT_EQ(kOKTitle
, title
);
1080 // Verify the number of resources in the implicit script cache is correct.
1081 const int kExpectedNumResources
= 2;
1082 int num_resources
= 0;
1084 base::Bind(&CountScriptResources
,
1085 base::Unretained(wrapper()),
1086 embedded_test_server()->GetURL(kScopeUrl
),
1088 EXPECT_EQ(kExpectedNumResources
, num_resources
);
1091 class ServiceWorkerBlackBoxBrowserTest
: public ServiceWorkerBrowserTest
{
1093 using self
= ServiceWorkerBlackBoxBrowserTest
;
1095 void FindRegistrationOnIO(const GURL
& document_url
,
1096 ServiceWorkerStatusCode
* status
,
1097 const base::Closure
& continuation
) {
1098 wrapper()->FindRegistrationForDocument(
1100 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO2
,
1101 this, status
, continuation
));
1104 void FindRegistrationOnIO2(
1105 ServiceWorkerStatusCode
* out_status
,
1106 const base::Closure
& continuation
,
1107 ServiceWorkerStatusCode status
,
1108 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
1109 *out_status
= status
;
1110 if (!registration
.get())
1111 EXPECT_NE(SERVICE_WORKER_OK
, status
);
1116 static int CountRenderProcessHosts() {
1118 for (RenderProcessHost::iterator
iter(RenderProcessHost::AllHostsIterator());
1126 // Flaky timeouts on CrOS and crash on Android: http://crbug.com/387045
1127 #if defined(OS_CHROMEOS) || defined(ANDROID)
1128 #define MAYBE_Registration DISABLED_Registration
1130 #define MAYBE_Registration Registration
1132 IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest
, MAYBE_Registration
) {
1133 // Close the only window to be sure we're not re-using its RenderProcessHost.
1135 EXPECT_EQ(0, CountRenderProcessHosts());
1137 const char kWorkerUrl
[] = "/service_worker/fetch_event.js";
1138 const char kScope
[] = "/service_worker/";
1140 // Unregistering nothing should return false.
1142 base::RunLoop run_loop
;
1143 public_context()->UnregisterServiceWorker(
1144 embedded_test_server()->GetURL("/"),
1145 base::Bind(&ExpectResultAndRun
, false, run_loop
.QuitClosure()));
1149 // If we use a worker URL that doesn't exist, registration fails.
1151 base::RunLoop run_loop
;
1152 public_context()->RegisterServiceWorker(
1153 embedded_test_server()->GetURL(kScope
),
1154 embedded_test_server()->GetURL("/does/not/exist"),
1155 base::Bind(&ExpectResultAndRun
, false, run_loop
.QuitClosure()));
1158 EXPECT_EQ(0, CountRenderProcessHosts());
1160 // Register returns when the promise would be resolved.
1162 base::RunLoop run_loop
;
1163 public_context()->RegisterServiceWorker(
1164 embedded_test_server()->GetURL(kScope
),
1165 embedded_test_server()->GetURL(kWorkerUrl
),
1166 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1169 EXPECT_EQ(1, CountRenderProcessHosts());
1171 // Registering again should succeed, although the algo still
1172 // might not be complete.
1174 base::RunLoop run_loop
;
1175 public_context()->RegisterServiceWorker(
1176 embedded_test_server()->GetURL(kScope
),
1177 embedded_test_server()->GetURL(kWorkerUrl
),
1178 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1182 // The registration algo might not be far enough along to have
1183 // stored the registration data, so it may not be findable
1186 // Unregistering something should return true.
1188 base::RunLoop run_loop
;
1189 public_context()->UnregisterServiceWorker(
1190 embedded_test_server()->GetURL(kScope
),
1191 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1194 EXPECT_GE(1, CountRenderProcessHosts()) << "Unregistering doesn't stop the "
1195 "workers eagerly, so their RPHs "
1196 "can still be running.";
1198 // Should not be able to find it.
1200 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1202 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO
,
1204 embedded_test_server()->GetURL("/service_worker/empty.html"),
1206 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, status
);
1210 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, CrossSiteTransfer
) {
1211 // The first page registers a service worker.
1212 const char kRegisterPageUrl
[] = "/service_worker/cross_site_xfer.html";
1213 const base::string16
kOKTitle1(base::ASCIIToUTF16("OK_1"));
1214 const base::string16
kFailTitle1(base::ASCIIToUTF16("FAIL_1"));
1215 content::TitleWatcher
title_watcher1(shell()->web_contents(), kOKTitle1
);
1216 title_watcher1
.AlsoWaitForTitle(kFailTitle1
);
1218 NavigateToURL(shell(), embedded_test_server()->GetURL(kRegisterPageUrl
));
1219 ASSERT_EQ(kOKTitle1
, title_watcher1
.WaitAndGetTitle());
1221 // Force process swapping behavior.
1222 ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
1224 // The second pages loads via the serviceworker including a subresource.
1225 const char kConfirmPageUrl
[] =
1226 "/service_worker/cross_site_xfer_scope/"
1227 "cross_site_xfer_confirm_via_serviceworker.html";
1228 const base::string16
kOKTitle2(base::ASCIIToUTF16("OK_2"));
1229 const base::string16
kFailTitle2(base::ASCIIToUTF16("FAIL_2"));
1230 content::TitleWatcher
title_watcher2(shell()->web_contents(), kOKTitle2
);
1231 title_watcher2
.AlsoWaitForTitle(kFailTitle2
);
1233 NavigateToURL(shell(), embedded_test_server()->GetURL(kConfirmPageUrl
));
1234 EXPECT_EQ(kOKTitle2
, title_watcher2
.WaitAndGetTitle());
1237 class ServiceWorkerVersionBrowserV8CacheTest
1238 : public ServiceWorkerVersionBrowserTest
,
1239 public ServiceWorkerVersion::Listener
{
1241 using self
= ServiceWorkerVersionBrowserV8CacheTest
;
1242 ~ServiceWorkerVersionBrowserV8CacheTest() override
{
1244 version_
->RemoveListener(this);
1246 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1247 ServiceWorkerBrowserTest::SetUpCommandLine(command_line
);
1248 command_line
->AppendSwitchASCII(switches::kV8CacheOptions
, "code");
1250 void SetUpRegistrationAndListenerOnIOThread(const std::string
& worker_url
) {
1251 SetUpRegistrationOnIOThread(worker_url
);
1252 version_
->AddListener(this);
1256 // ServiceWorkerVersion::Listener overrides
1257 void OnCachedMetadataUpdated(ServiceWorkerVersion
* version
) override
{
1258 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
1259 cache_updated_closure_
);
1262 base::Closure cache_updated_closure_
;
1265 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest
, Restart
) {
1266 RunOnIOThread(base::Bind(&self::SetUpRegistrationAndListenerOnIOThread
, this,
1267 "/service_worker/worker.js"));
1269 base::RunLoop cached_metadata_run_loop
;
1270 cache_updated_closure_
= cached_metadata_run_loop
.QuitClosure();
1273 StartWorker(SERVICE_WORKER_OK
);
1275 // Wait for the matadata is stored. This run loop should finish when
1276 // OnCachedMetadataUpdated() is called.
1277 cached_metadata_run_loop
.Run();
1279 // Activate the worker.
1280 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1281 base::RunLoop acrivate_run_loop
;
1282 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
1283 base::Bind(&self::ActivateOnIOThread
, this,
1284 acrivate_run_loop
.QuitClosure(), &status
));
1285 acrivate_run_loop
.Run();
1286 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
1288 StopWorker(SERVICE_WORKER_OK
);
1289 // Restart the worker.
1290 StartWorker(SERVICE_WORKER_OK
);
1292 StopWorker(SERVICE_WORKER_OK
);
1295 } // namespace content