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/single_thread_task_runner.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "content/browser/fileapi/chrome_blob_storage_context.h"
13 #include "content/browser/service_worker/embedded_worker_instance.h"
14 #include "content/browser/service_worker/embedded_worker_registry.h"
15 #include "content/browser/service_worker/service_worker_context_core.h"
16 #include "content/browser/service_worker/service_worker_context_observer.h"
17 #include "content/browser/service_worker/service_worker_context_wrapper.h"
18 #include "content/browser/service_worker/service_worker_registration.h"
19 #include "content/browser/service_worker/service_worker_test_utils.h"
20 #include "content/browser/service_worker/service_worker_version.h"
21 #include "content/common/service_worker/service_worker_messages.h"
22 #include "content/common/service_worker/service_worker_status_code.h"
23 #include "content/common/service_worker/service_worker_types.h"
24 #include "content/public/browser/browser_context.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/navigation_entry.h"
27 #include "content/public/browser/render_process_host.h"
28 #include "content/public/browser/storage_partition.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/common/content_switches.h"
31 #include "content/public/common/referrer.h"
32 #include "content/public/common/security_style.h"
33 #include "content/public/common/ssl_status.h"
34 #include "content/public/test/browser_test_utils.h"
35 #include "content/public/test/content_browser_test.h"
36 #include "content/public/test/content_browser_test_utils.h"
37 #include "content/shell/browser/shell.h"
38 #include "content/shell/browser/shell_content_browser_client.h"
39 #include "net/test/embedded_test_server/embedded_test_server.h"
40 #include "net/test/embedded_test_server/http_request.h"
41 #include "net/test/embedded_test_server/http_response.h"
42 #include "net/url_request/url_request_filter.h"
43 #include "net/url_request/url_request_interceptor.h"
44 #include "net/url_request/url_request_test_job.h"
45 #include "storage/browser/blob/blob_data_handle.h"
46 #include "storage/browser/blob/blob_data_snapshot.h"
47 #include "storage/browser/blob/blob_storage_context.h"
54 ServiceWorkerStatusCode status
;
55 ServiceWorkerFetchEventResult result
;
56 ServiceWorkerResponse response
;
57 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
60 void RunAndQuit(const base::Closure
& closure
,
61 const base::Closure
& quit
,
62 base::SingleThreadTaskRunner
* original_message_loop
) {
64 original_message_loop
->PostTask(FROM_HERE
, quit
);
67 void RunOnIOThreadWithDelay(const base::Closure
& closure
,
68 base::TimeDelta delay
) {
69 base::RunLoop run_loop
;
70 BrowserThread::PostDelayedTask(
73 base::Bind(&RunAndQuit
,
75 run_loop
.QuitClosure(),
76 base::ThreadTaskRunnerHandle::Get()),
81 void RunOnIOThread(const base::Closure
& closure
) {
82 RunOnIOThreadWithDelay(closure
, base::TimeDelta());
86 const base::Callback
<void(const base::Closure
& continuation
)>& closure
) {
87 base::RunLoop run_loop
;
88 base::Closure quit_on_original_thread
=
89 base::Bind(base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask
),
90 base::ThreadTaskRunnerHandle::Get().get(),
92 run_loop
.QuitClosure());
93 BrowserThread::PostTask(BrowserThread::IO
,
95 base::Bind(closure
, quit_on_original_thread
));
99 void ReceivePrepareResult(bool* is_prepared
) {
103 base::Closure
CreatePrepareReceiver(bool* is_prepared
) {
104 return base::Bind(&ReceivePrepareResult
, is_prepared
);
107 // Contrary to the style guide, the output parameter of this function comes
108 // before input parameters so Bind can be used on it to create a FetchCallback
109 // to pass to DispatchFetchEvent.
110 void ReceiveFetchResult(BrowserThread::ID run_quit_thread
,
111 const base::Closure
& quit
,
112 ChromeBlobStorageContext
* blob_context
,
113 FetchResult
* out_result
,
114 ServiceWorkerStatusCode actual_status
,
115 ServiceWorkerFetchEventResult actual_result
,
116 const ServiceWorkerResponse
& actual_response
) {
117 out_result
->status
= actual_status
;
118 out_result
->result
= actual_result
;
119 out_result
->response
= actual_response
;
120 if (!actual_response
.blob_uuid
.empty()) {
121 out_result
->blob_data_handle
=
122 blob_context
->context()->GetBlobDataFromUUID(
123 actual_response
.blob_uuid
);
126 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, quit
);
129 ServiceWorkerVersion::FetchCallback
CreateResponseReceiver(
130 BrowserThread::ID run_quit_thread
,
131 const base::Closure
& quit
,
132 ChromeBlobStorageContext
* blob_context
,
133 FetchResult
* result
) {
134 return base::Bind(&ReceiveFetchResult
, run_quit_thread
, quit
,
135 make_scoped_refptr
<ChromeBlobStorageContext
>(blob_context
),
139 void ReceiveFindRegistrationStatus(
140 BrowserThread::ID run_quit_thread
,
141 const base::Closure
& quit
,
142 ServiceWorkerStatusCode
* out_status
,
143 ServiceWorkerStatusCode status
,
144 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
145 *out_status
= status
;
147 BrowserThread::PostTask(run_quit_thread
, FROM_HERE
, quit
);
150 ServiceWorkerStorage::FindRegistrationCallback
CreateFindRegistrationReceiver(
151 BrowserThread::ID run_quit_thread
,
152 const base::Closure
& quit
,
153 ServiceWorkerStatusCode
* status
) {
154 return base::Bind(&ReceiveFindRegistrationStatus
, run_quit_thread
, quit
,
158 void ReadResponseBody(std::string
* body
,
159 storage::BlobDataHandle
* blob_data_handle
) {
160 ASSERT_TRUE(blob_data_handle
);
161 scoped_ptr
<storage::BlobDataSnapshot
> data
=
162 blob_data_handle
->CreateSnapshot();
163 ASSERT_EQ(1U, data
->items().size());
164 *body
= std::string(data
->items()[0]->bytes(), data
->items()[0]->length());
167 void ExpectResultAndRun(bool expected
,
168 const base::Closure
& continuation
,
170 EXPECT_EQ(expected
, actual
);
174 class WorkerActivatedObserver
175 : public ServiceWorkerContextObserver
,
176 public base::RefCountedThreadSafe
<WorkerActivatedObserver
> {
178 explicit WorkerActivatedObserver(ServiceWorkerContextWrapper
* context
)
179 : context_(context
) {}
181 RunOnIOThread(base::Bind(&WorkerActivatedObserver::InitOnIOThread
, this));
183 // ServiceWorkerContextObserver overrides.
184 void OnVersionStateChanged(int64 version_id
,
185 ServiceWorkerVersion::Status
) override
{
186 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
187 const ServiceWorkerVersion
* version
= context_
->GetLiveVersion(version_id
);
188 if (version
->status() == ServiceWorkerVersion::ACTIVATED
) {
189 context_
->RemoveObserver(this);
190 BrowserThread::PostTask(BrowserThread::UI
,
192 base::Bind(&WorkerActivatedObserver::Quit
, this));
195 void Wait() { run_loop_
.Run(); }
198 friend class base::RefCountedThreadSafe
<WorkerActivatedObserver
>;
199 ~WorkerActivatedObserver() override
{}
200 void InitOnIOThread() { context_
->AddObserver(this); }
201 void Quit() { run_loop_
.Quit(); }
203 base::RunLoop run_loop_
;
204 ServiceWorkerContextWrapper
* context_
;
205 DISALLOW_COPY_AND_ASSIGN(WorkerActivatedObserver
);
208 scoped_ptr
<net::test_server::HttpResponse
> VerifyServiceWorkerHeaderInRequest(
209 const net::test_server::HttpRequest
& request
) {
210 EXPECT_EQ(request
.relative_url
, "/service_worker/generated_sw.js");
211 std::map
<std::string
, std::string
>::const_iterator it
=
212 request
.headers
.find("Service-Worker");
213 EXPECT_TRUE(it
!= request
.headers
.end());
214 EXPECT_EQ("script", it
->second
);
216 scoped_ptr
<net::test_server::BasicHttpResponse
> http_response(
217 new net::test_server::BasicHttpResponse());
218 http_response
->set_content_type("text/javascript");
219 return http_response
.Pass();
222 // The ImportsBustMemcache test requires that the imported script
223 // would naturally be cached in blink's memcache, but the embedded
224 // test server doesn't produce headers that allow the blink's memcache
225 // to do that. This interceptor injects headers that give the import
226 // an experiration far in the future.
227 class LongLivedResourceInterceptor
: public net::URLRequestInterceptor
{
229 LongLivedResourceInterceptor(const std::string
& body
)
231 ~LongLivedResourceInterceptor() override
{}
233 // net::URLRequestInterceptor implementation
234 net::URLRequestJob
* MaybeInterceptRequest(
235 net::URLRequest
* request
,
236 net::NetworkDelegate
* network_delegate
) const override
{
237 const char kHeaders
[] =
239 "Content-Type: text/javascript\0"
240 "Expires: Thu, 1 Jan 2100 20:00:00 GMT\0"
242 std::string
headers(kHeaders
, arraysize(kHeaders
));
243 return new net::URLRequestTestJob(
244 request
, network_delegate
, headers
, body_
, true);
249 DISALLOW_COPY_AND_ASSIGN(LongLivedResourceInterceptor
);
252 void CreateLongLivedResourceInterceptors(
253 const GURL
& worker_url
, const GURL
& import_url
) {
254 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
255 scoped_ptr
<net::URLRequestInterceptor
> interceptor
;
257 interceptor
.reset(new LongLivedResourceInterceptor(
258 "importScripts('long_lived_import.js');"));
259 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
260 worker_url
, interceptor
.Pass());
262 interceptor
.reset(new LongLivedResourceInterceptor(
263 "// the imported script does nothing"));
264 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
265 import_url
, interceptor
.Pass());
268 void CountScriptResources(
269 ServiceWorkerContextWrapper
* wrapper
,
271 int* num_resources
) {
274 std::vector
<ServiceWorkerRegistrationInfo
> infos
=
275 wrapper
->GetAllLiveRegistrationInfo();
280 size_t index
= infos
.size() - 1;
281 if (infos
[index
].installing_version
.version_id
!=
282 kInvalidServiceWorkerVersionId
)
283 version_id
= infos
[index
].installing_version
.version_id
;
284 else if (infos
[index
].waiting_version
.version_id
!=
285 kInvalidServiceWorkerVersionId
)
286 version_id
= infos
[1].waiting_version
.version_id
;
287 else if (infos
[index
].active_version
.version_id
!=
288 kInvalidServiceWorkerVersionId
)
289 version_id
= infos
[index
].active_version
.version_id
;
293 ServiceWorkerVersion
* version
= wrapper
->GetLiveVersion(version_id
);
294 *num_resources
= static_cast<int>(version
->script_cache_map()->size());
299 class ServiceWorkerBrowserTest
: public ContentBrowserTest
{
301 using self
= ServiceWorkerBrowserTest
;
303 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
304 command_line
->AppendSwitch(
305 switches::kEnableExperimentalWebPlatformFeatures
);
308 void SetUpOnMainThread() override
{
309 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
310 StoragePartition
* partition
= BrowserContext::GetDefaultStoragePartition(
311 shell()->web_contents()->GetBrowserContext());
312 wrapper_
= static_cast<ServiceWorkerContextWrapper
*>(
313 partition
->GetServiceWorkerContext());
315 // Navigate to the page to set up a renderer page (where we can embed
317 NavigateToURLBlockUntilNavigationsComplete(
319 embedded_test_server()->GetURL("/service_worker/empty.html"), 1);
321 RunOnIOThread(base::Bind(&self::SetUpOnIOThread
, this));
324 void TearDownOnMainThread() override
{
325 RunOnIOThread(base::Bind(&self::TearDownOnIOThread
, this));
329 virtual void SetUpOnIOThread() {}
330 virtual void TearDownOnIOThread() {}
332 ServiceWorkerContextWrapper
* wrapper() { return wrapper_
.get(); }
333 ServiceWorkerContext
* public_context() { return wrapper(); }
335 void AssociateRendererProcessToPattern(const GURL
& pattern
) {
336 wrapper_
->process_manager()->AddProcessReferenceToPattern(
337 pattern
, shell()->web_contents()->GetRenderProcessHost()->GetID());
341 scoped_refptr
<ServiceWorkerContextWrapper
> wrapper_
;
344 class EmbeddedWorkerBrowserTest
: public ServiceWorkerBrowserTest
,
345 public EmbeddedWorkerInstance::Listener
{
347 using self
= EmbeddedWorkerBrowserTest
;
349 EmbeddedWorkerBrowserTest()
350 : last_worker_status_(EmbeddedWorkerInstance::STOPPED
),
351 pause_mode_(DONT_PAUSE
) {}
352 ~EmbeddedWorkerBrowserTest() override
{}
354 void TearDownOnIOThread() override
{
356 worker_
->RemoveListener(this);
357 if (worker_
->status() == EmbeddedWorkerInstance::STARTING
||
358 worker_
->status() == EmbeddedWorkerInstance::RUNNING
) {
365 void StartOnIOThread() {
366 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
367 worker_
= wrapper()->context()->embedded_worker_registry()->CreateWorker();
368 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker_
->status());
369 worker_
->AddListener(this);
371 const int64 service_worker_version_id
= 33L;
372 const GURL pattern
= embedded_test_server()->GetURL("/");
373 const GURL script_url
= embedded_test_server()->GetURL(
374 "/service_worker/worker.js");
375 AssociateRendererProcessToPattern(pattern
);
376 int process_id
= shell()->web_contents()->GetRenderProcessHost()->GetID();
377 wrapper()->process_manager()->AddProcessReferenceToPattern(
378 pattern
, process_id
);
380 service_worker_version_id
,
383 pause_mode_
!= DONT_PAUSE
,
384 base::Bind(&EmbeddedWorkerBrowserTest::StartOnIOThread2
, this));
386 void StartOnIOThread2(ServiceWorkerStatusCode status
) {
387 last_worker_status_
= worker_
->status();
388 EXPECT_EQ(SERVICE_WORKER_OK
, status
);
389 EXPECT_EQ(EmbeddedWorkerInstance::STARTING
, last_worker_status_
);
391 if (status
!= SERVICE_WORKER_OK
&& !done_closure_
.is_null())
395 void StopOnIOThread() {
396 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
397 EXPECT_EQ(EmbeddedWorkerInstance::RUNNING
, worker_
->status());
399 ServiceWorkerStatusCode status
= worker_
->Stop();
401 last_worker_status_
= worker_
->status();
402 EXPECT_EQ(SERVICE_WORKER_OK
, status
);
403 EXPECT_EQ(EmbeddedWorkerInstance::STOPPING
, last_worker_status_
);
405 if (status
!= SERVICE_WORKER_OK
&& !done_closure_
.is_null())
410 // EmbeddedWorkerInstance::Observer overrides:
411 void OnStarted() override
{
412 ASSERT_TRUE(worker_
!= NULL
);
413 ASSERT_FALSE(done_closure_
.is_null());
414 last_worker_status_
= worker_
->status();
415 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, done_closure_
);
417 void OnStopped(EmbeddedWorkerInstance::Status old_status
) override
{
418 ASSERT_TRUE(worker_
!= NULL
);
419 ASSERT_FALSE(done_closure_
.is_null());
420 last_worker_status_
= worker_
->status();
421 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, done_closure_
);
423 void OnPausedAfterDownload() override
{
424 if (pause_mode_
== PAUSE_THEN_RESUME
)
425 worker_
->ResumeAfterDownload();
426 else if (pause_mode_
== PAUSE_THEN_STOP
)
431 void OnReportException(const base::string16
& error_message
,
434 const GURL
& source_url
) override
{}
435 void OnReportConsoleMessage(int source_identifier
,
437 const base::string16
& message
,
439 const GURL
& source_url
) override
{}
440 bool OnMessageReceived(const IPC::Message
& message
) override
{ return false; }
442 scoped_ptr
<EmbeddedWorkerInstance
> worker_
;
443 EmbeddedWorkerInstance::Status last_worker_status_
;
451 // Called by EmbeddedWorkerInstance::Observer overrides so that
452 // test code can wait for the worker status notifications.
453 base::Closure done_closure_
;
456 class ConsoleListener
: public EmbeddedWorkerInstance::Listener
{
458 void OnReportConsoleMessage(int source_identifier
,
460 const base::string16
& message
,
462 const GURL
& source_url
) override
{
463 messages_
.push_back(message
);
464 if (!quit_
.is_null() && messages_
.size() == expected_message_count_
) {
465 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, quit_
);
470 void WaitForConsoleMessages(size_t expected_message_count
) {
471 if (messages_
.size() >= expected_message_count
)
474 expected_message_count_
= expected_message_count
;
475 base::RunLoop console_run_loop
;
476 quit_
= console_run_loop
.QuitClosure();
477 console_run_loop
.Run();
479 ASSERT_EQ(messages_
.size(), expected_message_count
);
482 bool OnMessageReceived(const IPC::Message
& message
) override
{ return false; }
483 const std::vector
<base::string16
>& messages() const { return messages_
; }
486 std::vector
<base::string16
> messages_
;
487 size_t expected_message_count_
;
491 class ServiceWorkerVersionBrowserTest
: public ServiceWorkerBrowserTest
{
493 using self
= ServiceWorkerVersionBrowserTest
;
495 ~ServiceWorkerVersionBrowserTest() override
{}
497 void TearDownOnIOThread() override
{
498 registration_
= NULL
;
502 void InstallTestHelper(const std::string
& worker_url
,
503 ServiceWorkerStatusCode expected_status
) {
504 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
507 // Dispatch install on a worker.
508 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
509 base::RunLoop install_run_loop
;
510 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
511 base::Bind(&self::InstallOnIOThread
, this,
512 install_run_loop
.QuitClosure(),
514 install_run_loop
.Run();
515 ASSERT_EQ(expected_status
, status
);
518 status
= SERVICE_WORKER_ERROR_FAILED
;
519 base::RunLoop stop_run_loop
;
520 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
521 base::Bind(&self::StopOnIOThread
, this,
522 stop_run_loop
.QuitClosure(),
525 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
528 void ActivateTestHelper(
529 const std::string
& worker_url
,
530 ServiceWorkerStatusCode expected_status
) {
532 base::Bind(&self::SetUpRegistrationOnIOThread
, this, worker_url
));
533 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
534 base::RunLoop run_loop
;
535 BrowserThread::PostTask(
539 &self::ActivateOnIOThread
, this, run_loop
.QuitClosure(), &status
));
541 ASSERT_EQ(expected_status
, status
);
544 void FetchOnRegisteredWorker(
545 ServiceWorkerFetchEventResult
* result
,
546 ServiceWorkerResponse
* response
,
547 scoped_ptr
<storage::BlobDataHandle
>* blob_data_handle
) {
548 blob_context_
= ChromeBlobStorageContext::GetFor(
549 shell()->web_contents()->GetBrowserContext());
550 bool prepare_result
= false;
551 FetchResult fetch_result
;
552 fetch_result
.status
= SERVICE_WORKER_ERROR_FAILED
;
553 base::RunLoop fetch_run_loop
;
554 BrowserThread::PostTask(BrowserThread::IO
,
556 base::Bind(&self::FetchOnIOThread
,
558 fetch_run_loop
.QuitClosure(),
561 fetch_run_loop
.Run();
562 ASSERT_TRUE(prepare_result
);
563 *result
= fetch_result
.result
;
564 *response
= fetch_result
.response
;
565 *blob_data_handle
= fetch_result
.blob_data_handle
.Pass();
566 ASSERT_EQ(SERVICE_WORKER_OK
, fetch_result
.status
);
569 void FetchTestHelper(const std::string
& worker_url
,
570 ServiceWorkerFetchEventResult
* result
,
571 ServiceWorkerResponse
* response
,
572 scoped_ptr
<storage::BlobDataHandle
>* blob_data_handle
) {
574 base::Bind(&self::SetUpRegistrationOnIOThread
, this, worker_url
));
575 FetchOnRegisteredWorker(result
, response
, blob_data_handle
);
578 void SetUpRegistrationOnIOThread(const std::string
& worker_url
) {
579 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
580 const GURL pattern
= embedded_test_server()->GetURL("/service_worker/");
581 registration_
= new ServiceWorkerRegistration(
583 wrapper()->context()->storage()->NewRegistrationId(),
584 wrapper()->context()->AsWeakPtr());
585 version_
= new ServiceWorkerVersion(
587 embedded_test_server()->GetURL(worker_url
),
588 wrapper()->context()->storage()->NewVersionId(),
589 wrapper()->context()->AsWeakPtr());
591 // Make the registration findable via storage functions.
592 wrapper()->context()->storage()->NotifyInstallingRegistration(
593 registration_
.get());
595 AssociateRendererProcessToPattern(pattern
);
598 void TimeoutWorkerOnIOThread() {
599 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
600 version_
->SimulatePingTimeoutForTesting();
603 void AddControlleeOnIOThread() {
604 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
605 scoped_ptr
<ServiceWorkerProviderHost
> host(new ServiceWorkerProviderHost(
606 33 /* dummy render process id */,
607 MSG_ROUTING_NONE
/* render_frame_id */, 1 /* dummy provider_id */,
608 SERVICE_WORKER_PROVIDER_FOR_WINDOW
, wrapper()->context()->AsWeakPtr(),
610 host
->SetDocumentUrl(
611 embedded_test_server()->GetURL("/service_worker/host"));
612 host
->AssociateRegistration(registration_
.get(),
613 false /* notify_controllerchange */);
614 wrapper()->context()->AddProviderHost(host
.Pass());
617 void AddWaitingWorkerOnIOThread(const std::string
& worker_url
) {
618 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
619 scoped_refptr
<ServiceWorkerVersion
> waiting_version(
620 new ServiceWorkerVersion(
621 registration_
.get(), embedded_test_server()->GetURL(worker_url
),
622 wrapper()->context()->storage()->NewVersionId(),
623 wrapper()->context()->AsWeakPtr()));
624 waiting_version
->SetStatus(ServiceWorkerVersion::INSTALLED
);
625 registration_
->SetWaitingVersion(waiting_version
.get());
626 registration_
->ActivateWaitingVersionWhenReady();
629 void StartWorker(ServiceWorkerStatusCode expected_status
) {
630 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
631 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
632 base::RunLoop start_run_loop
;
633 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
634 base::Bind(&self::StartOnIOThread
, this,
635 start_run_loop
.QuitClosure(),
637 start_run_loop
.Run();
638 ASSERT_EQ(expected_status
, status
);
641 void StopWorker(ServiceWorkerStatusCode expected_status
) {
642 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
643 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
644 base::RunLoop stop_run_loop
;
645 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
646 base::Bind(&self::StopOnIOThread
, this,
647 stop_run_loop
.QuitClosure(),
650 ASSERT_EQ(expected_status
, status
);
653 void StoreRegistration(int64 version_id
,
654 ServiceWorkerStatusCode expected_status
) {
655 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
656 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
657 base::RunLoop store_run_loop
;
658 BrowserThread::PostTask(
659 BrowserThread::IO
, FROM_HERE
,
660 base::Bind(&self::StoreOnIOThread
, this, store_run_loop
.QuitClosure(),
661 &status
, version_id
));
662 store_run_loop
.Run();
663 ASSERT_EQ(expected_status
, status
);
665 RunOnIOThread(base::Bind(&self::NotifyDoneInstallingRegistrationOnIOThread
,
669 void FindRegistrationForId(int64 id
,
671 ServiceWorkerStatusCode expected_status
) {
672 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI
));
673 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
674 base::RunLoop run_loop
;
675 BrowserThread::PostTask(
676 BrowserThread::IO
, FROM_HERE
,
677 base::Bind(&self::FindRegistrationForIdOnIOThread
, this,
678 run_loop
.QuitClosure(), &status
, id
, origin
));
680 ASSERT_EQ(expected_status
, status
);
683 void FindRegistrationForIdOnIOThread(const base::Closure
& done
,
684 ServiceWorkerStatusCode
* result
,
686 const GURL
& origin
) {
687 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
688 wrapper()->context()->storage()->FindRegistrationForId(
690 CreateFindRegistrationReceiver(BrowserThread::UI
, done
, result
));
693 void NotifyDoneInstallingRegistrationOnIOThread(
694 ServiceWorkerStatusCode status
) {
695 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
696 wrapper()->context()->storage()->NotifyDoneInstallingRegistration(
697 registration_
.get(), version_
.get(), status
);
700 void RemoveLiveRegistrationOnIOThread(int64 id
) {
701 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
702 wrapper()->context()->RemoveLiveRegistration(id
);
705 void StartOnIOThread(const base::Closure
& done
,
706 ServiceWorkerStatusCode
* result
) {
707 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
708 version_
->StartWorker(CreateReceiver(BrowserThread::UI
, done
, result
));
711 void InstallOnIOThread(const base::Closure
& done
,
712 ServiceWorkerStatusCode
* result
) {
713 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
714 version_
->SetStatus(ServiceWorkerVersion::INSTALLING
);
715 version_
->DispatchInstallEvent(
716 CreateReceiver(BrowserThread::UI
, done
, result
));
719 void StoreOnIOThread(const base::Closure
& done
,
720 ServiceWorkerStatusCode
* result
,
722 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
723 ServiceWorkerVersion
* version
=
724 wrapper()->context()->GetLiveVersion(version_id
);
725 wrapper()->context()->storage()->StoreRegistration(
726 registration_
.get(), version
,
727 CreateReceiver(BrowserThread::UI
, done
, result
));
730 void ActivateOnIOThread(const base::Closure
& done
,
731 ServiceWorkerStatusCode
* result
) {
732 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
733 version_
->SetStatus(ServiceWorkerVersion::ACTIVATING
);
734 registration_
->SetActiveVersion(version_
.get());
735 version_
->DispatchActivateEvent(
736 CreateReceiver(BrowserThread::UI
, done
, result
));
739 void FetchOnIOThread(const base::Closure
& done
,
740 bool* prepare_result
,
741 FetchResult
* result
) {
742 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
743 ServiceWorkerFetchRequest
request(
744 embedded_test_server()->GetURL("/service_worker/empty.html"),
746 ServiceWorkerHeaderMap(),
749 version_
->SetStatus(ServiceWorkerVersion::ACTIVATED
);
750 version_
->DispatchFetchEvent(
752 CreatePrepareReceiver(prepare_result
),
753 CreateResponseReceiver(
754 BrowserThread::UI
, done
, blob_context_
.get(), result
));
757 void StopOnIOThread(const base::Closure
& done
,
758 ServiceWorkerStatusCode
* result
) {
759 ASSERT_TRUE(version_
.get());
760 version_
->StopWorker(CreateReceiver(BrowserThread::UI
, done
, result
));
763 void SyncEventOnIOThread(const base::Closure
& done
,
764 ServiceWorkerStatusCode
* result
) {
765 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
766 version_
->SetStatus(ServiceWorkerVersion::ACTIVATED
);
767 version_
->DispatchSyncEvent(
768 CreateReceiver(BrowserThread::UI
, done
, result
));
772 scoped_refptr
<ServiceWorkerRegistration
> registration_
;
773 scoped_refptr
<ServiceWorkerVersion
> version_
;
774 scoped_refptr
<ChromeBlobStorageContext
> blob_context_
;
777 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
, StartAndStop
) {
778 // Start a worker and wait until OnStarted() is called.
779 base::RunLoop start_run_loop
;
780 done_closure_
= start_run_loop
.QuitClosure();
781 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
782 base::Bind(&self::StartOnIOThread
, this));
783 start_run_loop
.Run();
785 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING
, last_worker_status_
);
787 // Stop a worker and wait until OnStopped() is called.
788 base::RunLoop stop_run_loop
;
789 done_closure_
= stop_run_loop
.QuitClosure();
790 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
791 base::Bind(&self::StopOnIOThread
, this));
794 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED
, last_worker_status_
);
797 #if defined(OS_LINUX)
798 // Flaky on Linux 32-bit: http://crbug.com/498688.
799 #define MAYBE_StartPaused_ThenResume DISABLED_StartPaused_ThenResume
801 #define MAYBE_StartPaused_ThenResume StartPaused_ThenResume
803 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
,
804 MAYBE_StartPaused_ThenResume
) {
805 pause_mode_
= PAUSE_THEN_RESUME
;
806 base::RunLoop start_run_loop
;
807 done_closure_
= start_run_loop
.QuitClosure();
808 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
809 base::Bind(&self::StartOnIOThread
, this));
810 start_run_loop
.Run();
811 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING
, last_worker_status_
);
814 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest
,
815 StartPaused_ThenStop
) {
816 pause_mode_
= PAUSE_THEN_STOP
;
817 base::RunLoop start_run_loop
;
818 done_closure_
= start_run_loop
.QuitClosure();
819 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
820 base::Bind(&self::StartOnIOThread
, this));
821 start_run_loop
.Run();
822 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED
, last_worker_status_
);
825 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, StartAndStop
) {
826 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
827 "/service_worker/worker.js"));
830 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
831 base::RunLoop start_run_loop
;
832 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
833 base::Bind(&self::StartOnIOThread
, this,
834 start_run_loop
.QuitClosure(),
836 start_run_loop
.Run();
837 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
840 status
= SERVICE_WORKER_ERROR_FAILED
;
841 base::RunLoop stop_run_loop
;
842 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
843 base::Bind(&self::StopOnIOThread
, this,
844 stop_run_loop
.QuitClosure(),
847 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
850 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, StartNotFound
) {
851 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
852 "/service_worker/nonexistent.js"));
854 // Start a worker for nonexistent URL.
855 StartWorker(SERVICE_WORKER_ERROR_NETWORK
);
858 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, ReadResourceFailure
) {
859 // Create a registration.
860 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
861 "/service_worker/worker.js"));
862 version_
->SetStatus(ServiceWorkerVersion::ACTIVATED
);
864 // Add a non-existent resource to the version.
865 std::vector
<ServiceWorkerDatabase::ResourceRecord
> records
;
867 ServiceWorkerDatabase::ResourceRecord(30, version_
->script_url(), 100));
868 version_
->script_cache_map()->SetResources(records
);
870 // Store the registration.
871 StoreRegistration(version_
->version_id(), SERVICE_WORKER_OK
);
873 // Start the worker. We'll fail to read the resource.
874 StartWorker(SERVICE_WORKER_ERROR_DISK_CACHE
);
875 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version_
->status());
877 // The registration should be deleted from storage since the broken worker was
879 RunOnIOThread(base::Bind(&self::RemoveLiveRegistrationOnIOThread
, this,
880 registration_
->id()));
881 FindRegistrationForId(registration_
->id(),
882 registration_
->pattern().GetOrigin(),
883 SERVICE_WORKER_ERROR_NOT_FOUND
);
886 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
887 ReadResourceFailure_WaitingWorker
) {
888 // Create a registration and active version.
889 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
890 "/service_worker/worker.js"));
891 base::RunLoop activate_run_loop
;
892 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
893 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
894 base::Bind(&self::ActivateOnIOThread
, this,
895 activate_run_loop
.QuitClosure(), &status
));
896 activate_run_loop
.Run();
897 EXPECT_EQ(SERVICE_WORKER_OK
, status
);
898 ASSERT_TRUE(registration_
->active_version());
900 // Give the version a controllee.
901 RunOnIOThread(base::Bind(&self::AddControlleeOnIOThread
, this));
903 // Add a non-existent resource to the version.
904 std::vector
<ServiceWorkerDatabase::ResourceRecord
> records
;
906 ServiceWorkerDatabase::ResourceRecord(30, version_
->script_url(), 100));
907 version_
->script_cache_map()->SetResources(records
);
909 // Make a waiting version and store it.
910 RunOnIOThread(base::Bind(&self::AddWaitingWorkerOnIOThread
, this,
911 "/service_worker/worker.js"));
912 registration_
->waiting_version()->script_cache_map()->SetResources(records
);
913 StoreRegistration(registration_
->waiting_version()->version_id(),
916 // Start the broken worker. We'll fail to read from disk and the worker should
918 StopWorker(SERVICE_WORKER_OK
); // in case it's already running
919 StartWorker(SERVICE_WORKER_ERROR_DISK_CACHE
);
920 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT
, version_
->status());
922 // The registration should still be in storage since the waiting worker was
924 RunOnIOThread(base::Bind(&self::RemoveLiveRegistrationOnIOThread
, this,
925 registration_
->id()));
926 FindRegistrationForId(registration_
->id(),
927 registration_
->pattern().GetOrigin(),
931 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, Install
) {
932 InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK
);
935 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
936 InstallWithWaitUntil_Fulfilled
) {
937 InstallTestHelper("/service_worker/worker_install_fulfilled.js",
941 // Check that ServiceWorker script requests set a "Service-Worker: script"
943 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
944 ServiceWorkerScriptHeader
) {
945 embedded_test_server()->RegisterRequestHandler(
946 base::Bind(&VerifyServiceWorkerHeaderInRequest
));
947 InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK
);
950 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
951 Activate_NoEventListener
) {
952 ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK
);
953 ASSERT_EQ(ServiceWorkerVersion::ACTIVATING
, version_
->status());
956 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, Activate_Rejected
) {
957 ActivateTestHelper("/service_worker/worker_activate_rejected.js",
958 SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED
);
961 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
962 InstallWithWaitUntil_Rejected
) {
963 InstallTestHelper("/service_worker/worker_install_rejected.js",
964 SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
);
967 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
968 InstallWithWaitUntil_RejectConsoleMessage
) {
969 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
970 "/service_worker/worker_install_rejected.js"));
972 ConsoleListener console_listener
;
973 version_
->embedded_worker()->AddListener(&console_listener
);
975 // Dispatch install on a worker.
976 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
977 base::RunLoop install_run_loop
;
978 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
979 base::Bind(&self::InstallOnIOThread
, this,
980 install_run_loop
.QuitClosure(), &status
));
981 install_run_loop
.Run();
982 ASSERT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
, status
);
984 const base::string16 expected
=
985 base::ASCIIToUTF16("Rejecting oninstall event");
986 console_listener
.WaitForConsoleMessages(1);
987 ASSERT_NE(base::string16::npos
,
988 console_listener
.messages()[0].find(expected
));
989 version_
->embedded_worker()->RemoveListener(&console_listener
);
992 class WaitForLoaded
: public EmbeddedWorkerInstance::Listener
{
994 WaitForLoaded(const base::Closure
& quit
) : quit_(quit
) {}
996 void OnScriptLoaded() override
{
997 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, quit_
);
999 bool OnMessageReceived(const IPC::Message
& message
) override
{ return false; }
1002 base::Closure quit_
;
1005 // This test has started flaking somewhat consistently on Win, Mac and Linux.
1006 // Disabling for now, see http://crbug.com/496065.
1007 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
1008 DISABLED_TimeoutStartingWorker
) {
1009 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
1010 "/service_worker/while_true_worker.js"));
1012 // Start a worker, waiting until the script is loaded.
1013 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1014 base::RunLoop start_run_loop
;
1015 base::RunLoop load_run_loop
;
1016 WaitForLoaded
wait_for_load(load_run_loop
.QuitClosure());
1017 version_
->embedded_worker()->AddListener(&wait_for_load
);
1018 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
1019 base::Bind(&self::StartOnIOThread
, this,
1020 start_run_loop
.QuitClosure(), &status
));
1021 load_run_loop
.Run();
1022 version_
->embedded_worker()->RemoveListener(&wait_for_load
);
1024 // The script has loaded but start has not completed yet.
1025 ASSERT_EQ(SERVICE_WORKER_ERROR_FAILED
, status
);
1026 EXPECT_EQ(ServiceWorkerVersion::STARTING
, version_
->running_status());
1028 // Simulate execution timeout. Use a delay to prevent killing the worker
1029 // before it's started execution.
1030 EXPECT_TRUE(version_
->timeout_timer_
.IsRunning());
1031 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread
, this),
1032 base::TimeDelta::FromMilliseconds(100));
1033 start_run_loop
.Run();
1035 EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT
, status
);
1038 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, TimeoutWorkerInEvent
) {
1039 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
1040 "/service_worker/while_true_in_install_worker.js"));
1043 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1044 base::RunLoop start_run_loop
;
1045 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
1046 base::Bind(&self::StartOnIOThread
, this,
1047 start_run_loop
.QuitClosure(), &status
));
1048 start_run_loop
.Run();
1049 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
1051 // Dispatch an event.
1052 base::RunLoop install_run_loop
;
1053 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
1054 base::Bind(&self::InstallOnIOThread
, this,
1055 install_run_loop
.QuitClosure(), &status
));
1057 // Simulate execution timeout. Use a delay to prevent killing the worker
1058 // before it's started execution.
1059 EXPECT_TRUE(version_
->timeout_timer_
.IsRunning());
1060 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread
, this),
1061 base::TimeDelta::FromMilliseconds(100));
1062 install_run_loop
.Run();
1064 EXPECT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED
, status
);
1067 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, FetchEvent_Response
) {
1068 ServiceWorkerFetchEventResult result
;
1069 ServiceWorkerResponse response
;
1070 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
1071 FetchTestHelper("/service_worker/fetch_event.js",
1072 &result
, &response
, &blob_data_handle
);
1073 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
, result
);
1074 EXPECT_EQ(301, response
.status_code
);
1075 EXPECT_EQ("Moved Permanently", response
.status_text
);
1076 ServiceWorkerHeaderMap expected_headers
;
1077 expected_headers
["content-language"] = "fi";
1078 expected_headers
["content-type"] = "text/html; charset=UTF-8";
1079 EXPECT_EQ(expected_headers
, response
.headers
);
1083 base::Bind(&ReadResponseBody
,
1084 &body
, base::Owned(blob_data_handle
.release())));
1085 EXPECT_EQ("This resource is gone. Gone, gone, gone.", body
);
1088 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
1089 FetchEvent_respondWithRejection
) {
1090 ServiceWorkerFetchEventResult result
;
1091 ServiceWorkerResponse response
;
1092 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
1094 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread
, this,
1095 "/service_worker/fetch_event_rejected.js"));
1097 ConsoleListener console_listener
;
1098 version_
->embedded_worker()->AddListener(&console_listener
);
1100 FetchOnRegisteredWorker(&result
, &response
, &blob_data_handle
);
1101 const base::string16 expected
=
1102 base::ASCIIToUTF16("Rejecting respondWith promise");
1103 console_listener
.WaitForConsoleMessages(1);
1104 ASSERT_NE(base::string16::npos
,
1105 console_listener
.messages()[0].find(expected
));
1106 version_
->embedded_worker()->RemoveListener(&console_listener
);
1108 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
, result
);
1109 EXPECT_EQ(0, response
.status_code
);
1111 ASSERT_FALSE(blob_data_handle
);
1114 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
,
1115 SyncAbortedWithoutFlag
) {
1116 RunOnIOThread(base::Bind(
1117 &self::SetUpRegistrationOnIOThread
, this, "/service_worker/sync.js"));
1119 // Run the sync event.
1120 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1121 base::RunLoop sync_run_loop
;
1122 BrowserThread::PostTask(BrowserThread::IO
,
1124 base::Bind(&self::SyncEventOnIOThread
,
1126 sync_run_loop
.QuitClosure(),
1128 sync_run_loop
.Run();
1129 ASSERT_EQ(SERVICE_WORKER_ERROR_ABORT
, status
);
1132 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest
, SyncEventHandled
) {
1133 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
1134 command_line
->AppendSwitch(switches::kEnableServiceWorkerSync
);
1136 RunOnIOThread(base::Bind(
1137 &self::SetUpRegistrationOnIOThread
, this, "/service_worker/sync.js"));
1138 ServiceWorkerFetchEventResult result
;
1139 ServiceWorkerResponse response
;
1140 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
1141 // Should 404 before sync event.
1142 FetchOnRegisteredWorker(&result
, &response
, &blob_data_handle
);
1143 EXPECT_EQ(404, response
.status_code
);
1145 // Run the sync event.
1146 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1147 base::RunLoop sync_run_loop
;
1148 BrowserThread::PostTask(BrowserThread::IO
,
1150 base::Bind(&self::SyncEventOnIOThread
,
1152 sync_run_loop
.QuitClosure(),
1154 sync_run_loop
.Run();
1155 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
1157 // Should 200 after sync event.
1158 FetchOnRegisteredWorker(&result
, &response
, &blob_data_handle
);
1159 EXPECT_EQ(200, response
.status_code
);
1162 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, Reload
) {
1163 const char kPageUrl
[] = "/service_worker/reload.html";
1164 const char kWorkerUrl
[] = "/service_worker/fetch_event_reload.js";
1165 scoped_refptr
<WorkerActivatedObserver
> observer
=
1166 new WorkerActivatedObserver(wrapper());
1168 public_context()->RegisterServiceWorker(
1169 embedded_test_server()->GetURL(kPageUrl
),
1170 embedded_test_server()->GetURL(kWorkerUrl
),
1171 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
1174 const base::string16 title1
= base::ASCIIToUTF16("reload=false");
1175 TitleWatcher
title_watcher1(shell()->web_contents(), title1
);
1176 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
1177 EXPECT_EQ(title1
, title_watcher1
.WaitAndGetTitle());
1179 const base::string16 title2
= base::ASCIIToUTF16("reload=true");
1180 TitleWatcher
title_watcher2(shell()->web_contents(), title2
);
1181 ReloadBlockUntilNavigationsComplete(shell(), 1);
1182 EXPECT_EQ(title2
, title_watcher2
.WaitAndGetTitle());
1186 base::RunLoop run_loop
;
1187 public_context()->UnregisterServiceWorker(
1188 embedded_test_server()->GetURL(kPageUrl
),
1189 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1193 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
,
1194 ResponseFromHTTPSServiceWorkerIsMarkedAsSecure
) {
1195 const char kPageUrl
[] = "files/service_worker/fetch_event_blob.html";
1196 const char kWorkerUrl
[] = "files/service_worker/fetch_event_blob.js";
1197 net::SpawnedTestServer
https_server(
1198 net::SpawnedTestServer::TYPE_HTTPS
,
1199 net::BaseTestServer::SSLOptions(
1200 net::BaseTestServer::SSLOptions::CERT_OK
),
1201 base::FilePath(FILE_PATH_LITERAL("content/test/data/")));
1202 ASSERT_TRUE(https_server
.Start());
1204 scoped_refptr
<WorkerActivatedObserver
> observer
=
1205 new WorkerActivatedObserver(wrapper());
1207 public_context()->RegisterServiceWorker(
1208 https_server
.GetURL(kPageUrl
),
1209 https_server
.GetURL(kWorkerUrl
),
1210 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
1213 const base::string16 title
= base::ASCIIToUTF16("Title");
1214 TitleWatcher
title_watcher(shell()->web_contents(), title
);
1215 NavigateToURL(shell(), https_server
.GetURL(kPageUrl
));
1216 EXPECT_EQ(title
, title_watcher
.WaitAndGetTitle());
1217 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
1218 NavigationEntry
* entry
=
1219 shell()->web_contents()->GetController().GetVisibleEntry();
1220 EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED
, entry
->GetSSL().security_style
);
1224 base::RunLoop run_loop
;
1225 public_context()->UnregisterServiceWorker(
1226 https_server
.GetURL(kPageUrl
),
1227 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1231 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
,
1232 ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure
) {
1233 const char kPageUrl
[] = "/service_worker/fetch_event_blob.html";
1234 const char kWorkerUrl
[] = "/service_worker/fetch_event_blob.js";
1235 scoped_refptr
<WorkerActivatedObserver
> observer
=
1236 new WorkerActivatedObserver(wrapper());
1238 public_context()->RegisterServiceWorker(
1239 embedded_test_server()->GetURL(kPageUrl
),
1240 embedded_test_server()->GetURL(kWorkerUrl
),
1241 base::Bind(&ExpectResultAndRun
, true, base::Bind(&base::DoNothing
)));
1244 const base::string16 title
= base::ASCIIToUTF16("Title");
1245 TitleWatcher
title_watcher(shell()->web_contents(), title
);
1246 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
1247 EXPECT_EQ(title
, title_watcher
.WaitAndGetTitle());
1248 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
1249 NavigationEntry
* entry
=
1250 shell()->web_contents()->GetController().GetVisibleEntry();
1251 EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED
, entry
->GetSSL().security_style
);
1255 base::RunLoop run_loop
;
1256 public_context()->UnregisterServiceWorker(
1257 embedded_test_server()->GetURL(kPageUrl
),
1258 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1262 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, ImportsBustMemcache
) {
1263 const char kScopeUrl
[] = "/service_worker/imports_bust_memcache_scope/";
1264 const char kPageUrl
[] = "/service_worker/imports_bust_memcache.html";
1265 const char kScriptUrl
[] = "/service_worker/worker_with_one_import.js";
1266 const char kImportUrl
[] = "/service_worker/long_lived_import.js";
1267 const base::string16
kOKTitle(base::ASCIIToUTF16("OK"));
1268 const base::string16
kFailTitle(base::ASCIIToUTF16("FAIL"));
1271 base::Bind(&CreateLongLivedResourceInterceptors
,
1272 embedded_test_server()->GetURL(kScriptUrl
),
1273 embedded_test_server()->GetURL(kImportUrl
)));
1275 TitleWatcher
title_watcher(shell()->web_contents(), kOKTitle
);
1276 title_watcher
.AlsoWaitForTitle(kFailTitle
);
1277 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl
));
1278 base::string16 title
= title_watcher
.WaitAndGetTitle();
1279 EXPECT_EQ(kOKTitle
, title
);
1281 // Verify the number of resources in the implicit script cache is correct.
1282 const int kExpectedNumResources
= 2;
1283 int num_resources
= 0;
1285 base::Bind(&CountScriptResources
,
1286 base::Unretained(wrapper()),
1287 embedded_test_server()->GetURL(kScopeUrl
),
1289 EXPECT_EQ(kExpectedNumResources
, num_resources
);
1292 class ServiceWorkerBlackBoxBrowserTest
: public ServiceWorkerBrowserTest
{
1294 using self
= ServiceWorkerBlackBoxBrowserTest
;
1296 void FindRegistrationOnIO(const GURL
& document_url
,
1297 ServiceWorkerStatusCode
* status
,
1298 const base::Closure
& continuation
) {
1299 wrapper()->FindRegistrationForDocument(
1301 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO2
,
1302 this, status
, continuation
));
1305 void FindRegistrationOnIO2(
1306 ServiceWorkerStatusCode
* out_status
,
1307 const base::Closure
& continuation
,
1308 ServiceWorkerStatusCode status
,
1309 const scoped_refptr
<ServiceWorkerRegistration
>& registration
) {
1310 *out_status
= status
;
1311 if (!registration
.get())
1312 EXPECT_NE(SERVICE_WORKER_OK
, status
);
1317 static int CountRenderProcessHosts() {
1319 for (RenderProcessHost::iterator
iter(RenderProcessHost::AllHostsIterator());
1327 // Flaky timeouts on CrOS: http://crbug.com/387045
1328 #if defined(OS_CHROMEOS)
1329 #define MAYBE_Registration DISABLED_Registration
1331 #define MAYBE_Registration Registration
1333 IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest
, MAYBE_Registration
) {
1334 // Close the only window to be sure we're not re-using its RenderProcessHost.
1336 EXPECT_EQ(0, CountRenderProcessHosts());
1338 const char kWorkerUrl
[] = "/service_worker/fetch_event.js";
1339 const char kScope
[] = "/service_worker/";
1341 // Unregistering nothing should return false.
1343 base::RunLoop run_loop
;
1344 public_context()->UnregisterServiceWorker(
1345 embedded_test_server()->GetURL("/"),
1346 base::Bind(&ExpectResultAndRun
, false, run_loop
.QuitClosure()));
1350 // If we use a worker URL that doesn't exist, registration fails.
1352 base::RunLoop run_loop
;
1353 public_context()->RegisterServiceWorker(
1354 embedded_test_server()->GetURL(kScope
),
1355 embedded_test_server()->GetURL("/does/not/exist"),
1356 base::Bind(&ExpectResultAndRun
, false, run_loop
.QuitClosure()));
1359 EXPECT_EQ(0, CountRenderProcessHosts());
1361 // Register returns when the promise would be resolved.
1363 base::RunLoop run_loop
;
1364 public_context()->RegisterServiceWorker(
1365 embedded_test_server()->GetURL(kScope
),
1366 embedded_test_server()->GetURL(kWorkerUrl
),
1367 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1370 EXPECT_EQ(1, CountRenderProcessHosts());
1372 // Registering again should succeed, although the algo still
1373 // might not be complete.
1375 base::RunLoop run_loop
;
1376 public_context()->RegisterServiceWorker(
1377 embedded_test_server()->GetURL(kScope
),
1378 embedded_test_server()->GetURL(kWorkerUrl
),
1379 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1383 // The registration algo might not be far enough along to have
1384 // stored the registration data, so it may not be findable
1387 // Unregistering something should return true.
1389 base::RunLoop run_loop
;
1390 public_context()->UnregisterServiceWorker(
1391 embedded_test_server()->GetURL(kScope
),
1392 base::Bind(&ExpectResultAndRun
, true, run_loop
.QuitClosure()));
1395 EXPECT_GE(1, CountRenderProcessHosts()) << "Unregistering doesn't stop the "
1396 "workers eagerly, so their RPHs "
1397 "can still be running.";
1399 // Should not be able to find it.
1401 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1403 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO
,
1405 embedded_test_server()->GetURL("/service_worker/empty.html"),
1407 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND
, status
);
1411 #if defined(ANDROID)
1412 #define MAYBE_CrossSiteTransfer DISABLED_CrossSiteTransfer
1414 #define MAYBE_CrossSiteTransfer CrossSiteTransfer
1416 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest
, MAYBE_CrossSiteTransfer
) {
1417 // The first page registers a service worker.
1418 const char kRegisterPageUrl
[] = "/service_worker/cross_site_xfer.html";
1419 const base::string16
kOKTitle1(base::ASCIIToUTF16("OK_1"));
1420 const base::string16
kFailTitle1(base::ASCIIToUTF16("FAIL_1"));
1421 content::TitleWatcher
title_watcher1(shell()->web_contents(), kOKTitle1
);
1422 title_watcher1
.AlsoWaitForTitle(kFailTitle1
);
1424 NavigateToURL(shell(), embedded_test_server()->GetURL(kRegisterPageUrl
));
1425 ASSERT_EQ(kOKTitle1
, title_watcher1
.WaitAndGetTitle());
1427 // Force process swapping behavior.
1428 ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
1430 // The second pages loads via the serviceworker including a subresource.
1431 const char kConfirmPageUrl
[] =
1432 "/service_worker/cross_site_xfer_scope/"
1433 "cross_site_xfer_confirm_via_serviceworker.html";
1434 const base::string16
kOKTitle2(base::ASCIIToUTF16("OK_2"));
1435 const base::string16
kFailTitle2(base::ASCIIToUTF16("FAIL_2"));
1436 content::TitleWatcher
title_watcher2(shell()->web_contents(), kOKTitle2
);
1437 title_watcher2
.AlsoWaitForTitle(kFailTitle2
);
1439 NavigateToURL(shell(), embedded_test_server()->GetURL(kConfirmPageUrl
));
1440 EXPECT_EQ(kOKTitle2
, title_watcher2
.WaitAndGetTitle());
1443 class ServiceWorkerVersionBrowserV8CacheTest
1444 : public ServiceWorkerVersionBrowserTest
,
1445 public ServiceWorkerVersion::Listener
{
1447 using self
= ServiceWorkerVersionBrowserV8CacheTest
;
1448 ~ServiceWorkerVersionBrowserV8CacheTest() override
{
1450 version_
->RemoveListener(this);
1452 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1453 ServiceWorkerBrowserTest::SetUpCommandLine(command_line
);
1454 command_line
->AppendSwitchASCII(switches::kV8CacheOptions
, "code");
1456 void SetUpRegistrationAndListenerOnIOThread(const std::string
& worker_url
) {
1457 SetUpRegistrationOnIOThread(worker_url
);
1458 version_
->AddListener(this);
1462 // ServiceWorkerVersion::Listener overrides
1463 void OnCachedMetadataUpdated(ServiceWorkerVersion
* version
) override
{
1464 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
1465 cache_updated_closure_
);
1468 base::Closure cache_updated_closure_
;
1471 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest
, Restart
) {
1472 RunOnIOThread(base::Bind(&self::SetUpRegistrationAndListenerOnIOThread
, this,
1473 "/service_worker/worker.js"));
1475 base::RunLoop cached_metadata_run_loop
;
1476 cache_updated_closure_
= cached_metadata_run_loop
.QuitClosure();
1479 StartWorker(SERVICE_WORKER_OK
);
1481 // Wait for the matadata is stored. This run loop should finish when
1482 // OnCachedMetadataUpdated() is called.
1483 cached_metadata_run_loop
.Run();
1485 // Activate the worker.
1486 ServiceWorkerStatusCode status
= SERVICE_WORKER_ERROR_FAILED
;
1487 base::RunLoop activate_run_loop
;
1488 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
1489 base::Bind(&self::ActivateOnIOThread
, this,
1490 activate_run_loop
.QuitClosure(), &status
));
1491 activate_run_loop
.Run();
1492 ASSERT_EQ(SERVICE_WORKER_OK
, status
);
1494 StopWorker(SERVICE_WORKER_OK
);
1495 // Restart the worker.
1496 StartWorker(SERVICE_WORKER_OK
);
1498 StopWorker(SERVICE_WORKER_OK
);
1501 } // namespace content