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 "content/browser/fileapi/chrome_blob_storage_context.h"
10 #include "content/browser/service_worker/embedded_worker_instance.h"
11 #include "content/browser/service_worker/embedded_worker_registry.h"
12 #include "content/browser/service_worker/service_worker_context_core.h"
13 #include "content/browser/service_worker/service_worker_context_wrapper.h"
14 #include "content/browser/service_worker/service_worker_registration.h"
15 #include "content/browser/service_worker/service_worker_test_utils.h"
16 #include "content/browser/service_worker/service_worker_version.h"
17 #include "content/common/service_worker/service_worker_messages.h"
18 #include "content/common/service_worker/service_worker_status_code.h"
19 #include "content/common/service_worker/service_worker_types.h"
20 #include "content/public/browser/browser_context.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/storage_partition.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/common/content_switches.h"
26 #include "content/public/test/content_browser_test.h"
27 #include "content/public/test/content_browser_test_utils.h"
28 #include "content/shell/browser/shell.h"
29 #include "net/test/embedded_test_server/embedded_test_server.h"
30 #include "webkit/browser/blob/blob_data_handle.h"
31 #include "webkit/browser/blob/blob_storage_context.h"
32 #include "webkit/common/blob/blob_data.h"
39 ServiceWorkerStatusCode status;
40 ServiceWorkerFetchEventResult result;
41 ServiceWorkerResponse response;
42 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle;
45 void RunAndQuit(const base::Closure& closure,
46 const base::Closure& quit,
47 base::MessageLoopProxy* original_message_loop) {
49 original_message_loop->PostTask(FROM_HERE, quit);
52 void RunOnIOThread(const base::Closure& closure) {
53 base::RunLoop run_loop;
54 BrowserThread::PostTask(
55 BrowserThread::IO, FROM_HERE,
56 base::Bind(&RunAndQuit, closure, run_loop.QuitClosure(),
57 base::MessageLoopProxy::current()));
62 const base::Callback<void(const base::Closure& continuation)>& closure) {
63 base::RunLoop run_loop;
64 base::Closure quit_on_original_thread =
65 base::Bind(base::IgnoreResult(&base::MessageLoopProxy::PostTask),
66 base::MessageLoopProxy::current().get(),
68 run_loop.QuitClosure());
69 BrowserThread::PostTask(BrowserThread::IO,
71 base::Bind(closure, quit_on_original_thread));
75 // Contrary to the style guide, the output parameter of this function comes
76 // before input parameters so Bind can be used on it to create a FetchCallback
77 // to pass to DispatchFetchEvent.
78 void ReceiveFetchResult(BrowserThread::ID run_quit_thread,
79 const base::Closure& quit,
80 ChromeBlobStorageContext* blob_context,
81 FetchResult* out_result,
82 ServiceWorkerStatusCode actual_status,
83 ServiceWorkerFetchEventResult actual_result,
84 const ServiceWorkerResponse& actual_response) {
85 out_result->status = actual_status;
86 out_result->result = actual_result;
87 out_result->response = actual_response;
88 if (!actual_response.blob_uuid.empty()) {
89 out_result->blob_data_handle =
90 blob_context->context()->GetBlobDataFromUUID(
91 actual_response.blob_uuid);
94 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit);
97 ServiceWorkerVersion::FetchCallback CreateResponseReceiver(
98 BrowserThread::ID run_quit_thread,
99 const base::Closure& quit,
100 ChromeBlobStorageContext* blob_context,
101 FetchResult* result) {
102 return base::Bind(&ReceiveFetchResult, run_quit_thread, quit,
103 make_scoped_refptr<ChromeBlobStorageContext>(blob_context),
107 void ReadResponseBody(std::string* body,
108 webkit_blob::BlobDataHandle* blob_data_handle) {
109 ASSERT_TRUE(blob_data_handle);
110 ASSERT_EQ(1U, blob_data_handle->data()->items().size());
111 *body = std::string(blob_data_handle->data()->items()[0].bytes(),
112 blob_data_handle->data()->items()[0].length());
117 class ServiceWorkerBrowserTest : public ContentBrowserTest {
119 typedef ServiceWorkerBrowserTest self;
121 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
122 command_line->AppendSwitch(switches::kEnableServiceWorker);
125 virtual void SetUpOnMainThread() OVERRIDE {
126 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
127 StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
128 shell()->web_contents()->GetBrowserContext());
129 wrapper_ = static_cast<ServiceWorkerContextWrapper*>(
130 partition->GetServiceWorkerContext());
132 // Navigate to the page to set up a renderer page (where we can embed
134 NavigateToURLBlockUntilNavigationsComplete(
136 embedded_test_server()->GetURL("/service_worker/empty.html"), 1);
138 RunOnIOThread(base::Bind(&self::SetUpOnIOThread, this));
141 virtual void TearDownOnMainThread() OVERRIDE {
142 RunOnIOThread(base::Bind(&self::TearDownOnIOThread, this));
146 virtual void SetUpOnIOThread() {}
147 virtual void TearDownOnIOThread() {}
149 ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); }
150 ServiceWorkerContext* public_context() { return wrapper(); }
152 void AssociateRendererProcessToWorker(EmbeddedWorkerInstance* worker) {
153 worker->AddProcessReference(
154 shell()->web_contents()->GetRenderProcessHost()->GetID());
158 scoped_refptr<ServiceWorkerContextWrapper> wrapper_;
161 class EmbeddedWorkerBrowserTest : public ServiceWorkerBrowserTest,
162 public EmbeddedWorkerInstance::Listener {
164 typedef EmbeddedWorkerBrowserTest self;
166 EmbeddedWorkerBrowserTest()
167 : last_worker_status_(EmbeddedWorkerInstance::STOPPED) {}
168 virtual ~EmbeddedWorkerBrowserTest() {}
170 virtual void TearDownOnIOThread() OVERRIDE {
172 worker_->RemoveListener(this);
177 void StartOnIOThread() {
178 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
179 worker_ = wrapper()->context()->embedded_worker_registry()->CreateWorker();
180 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker_->status());
181 worker_->AddListener(this);
183 AssociateRendererProcessToWorker(worker_.get());
185 const int64 service_worker_version_id = 33L;
186 const GURL scope = embedded_test_server()->GetURL("/*");
187 const GURL script_url = embedded_test_server()->GetURL(
188 "/service_worker/worker.js");
189 std::vector<int> processes;
191 shell()->web_contents()->GetRenderProcessHost()->GetID());
193 service_worker_version_id,
197 base::Bind(&EmbeddedWorkerBrowserTest::StartOnIOThread2, this));
199 void StartOnIOThread2(ServiceWorkerStatusCode status) {
200 last_worker_status_ = worker_->status();
201 EXPECT_EQ(SERVICE_WORKER_OK, status);
202 EXPECT_EQ(EmbeddedWorkerInstance::STARTING, last_worker_status_);
204 if (status != SERVICE_WORKER_OK && !done_closure_.is_null())
208 void StopOnIOThread() {
209 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
210 EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker_->status());
212 ServiceWorkerStatusCode status = worker_->Stop();
214 last_worker_status_ = worker_->status();
215 EXPECT_EQ(SERVICE_WORKER_OK, status);
216 EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, last_worker_status_);
218 if (status != SERVICE_WORKER_OK && !done_closure_.is_null())
223 // EmbeddedWorkerInstance::Observer overrides:
224 virtual void OnStarted() OVERRIDE {
225 ASSERT_TRUE(worker_ != NULL);
226 ASSERT_FALSE(done_closure_.is_null());
227 last_worker_status_ = worker_->status();
228 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_);
230 virtual void OnStopped() OVERRIDE {
231 ASSERT_TRUE(worker_ != NULL);
232 ASSERT_FALSE(done_closure_.is_null());
233 last_worker_status_ = worker_->status();
234 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_);
236 virtual void OnReportException(const base::string16& error_message,
239 const GURL& source_url) OVERRIDE {}
240 virtual void OnReportConsoleMessage(int source_identifier,
242 const base::string16& message,
244 const GURL& source_url) OVERRIDE {}
245 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
249 scoped_ptr<EmbeddedWorkerInstance> worker_;
250 EmbeddedWorkerInstance::Status last_worker_status_;
252 // Called by EmbeddedWorkerInstance::Observer overrides so that
253 // test code can wait for the worker status notifications.
254 base::Closure done_closure_;
257 class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
259 typedef ServiceWorkerVersionBrowserTest self;
261 virtual ~ServiceWorkerVersionBrowserTest() {}
263 virtual void TearDownOnIOThread() OVERRIDE {
264 registration_ = NULL;
268 void InstallTestHelper(const std::string& worker_url,
269 ServiceWorkerStatusCode expected_status) {
270 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
273 // Dispatch install on a worker.
274 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
275 base::RunLoop install_run_loop;
276 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
277 base::Bind(&self::InstallOnIOThread, this,
278 install_run_loop.QuitClosure(),
280 install_run_loop.Run();
281 ASSERT_EQ(expected_status, status);
284 status = SERVICE_WORKER_ERROR_FAILED;
285 base::RunLoop stop_run_loop;
286 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
287 base::Bind(&self::StopOnIOThread, this,
288 stop_run_loop.QuitClosure(),
291 ASSERT_EQ(SERVICE_WORKER_OK, status);
294 void ActivateTestHelper(
295 const std::string& worker_url,
296 ServiceWorkerStatusCode expected_status) {
298 base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url));
299 version_->SetStatus(ServiceWorkerVersion::INSTALLED);
300 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
301 base::RunLoop run_loop;
302 BrowserThread::PostTask(
306 &self::ActivateOnIOThread, this, run_loop.QuitClosure(), &status));
308 ASSERT_EQ(expected_status, status);
311 void FetchOnRegisteredWorker(
312 ServiceWorkerFetchEventResult* result,
313 ServiceWorkerResponse* response,
314 scoped_ptr<webkit_blob::BlobDataHandle>* blob_data_handle) {
315 blob_context_ = ChromeBlobStorageContext::GetFor(
316 shell()->web_contents()->GetBrowserContext());
317 FetchResult fetch_result;
318 fetch_result.status = SERVICE_WORKER_ERROR_FAILED;
319 base::RunLoop fetch_run_loop;
320 BrowserThread::PostTask(BrowserThread::IO,
322 base::Bind(&self::FetchOnIOThread,
324 fetch_run_loop.QuitClosure(),
326 fetch_run_loop.Run();
327 *result = fetch_result.result;
328 *response = fetch_result.response;
329 *blob_data_handle = fetch_result.blob_data_handle.Pass();
330 ASSERT_EQ(SERVICE_WORKER_OK, fetch_result.status);
333 void FetchTestHelper(
334 const std::string& worker_url,
335 ServiceWorkerFetchEventResult* result,
336 ServiceWorkerResponse* response,
337 scoped_ptr<webkit_blob::BlobDataHandle>* blob_data_handle) {
339 base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url));
340 FetchOnRegisteredWorker(result, response, blob_data_handle);
343 void SetUpRegistrationOnIOThread(const std::string& worker_url) {
344 registration_ = new ServiceWorkerRegistration(
345 embedded_test_server()->GetURL("/*"),
346 embedded_test_server()->GetURL(worker_url),
347 wrapper()->context()->storage()->NewRegistrationId(),
348 wrapper()->context()->AsWeakPtr());
349 version_ = new ServiceWorkerVersion(
351 wrapper()->context()->storage()->NewVersionId(),
352 wrapper()->context()->AsWeakPtr());
353 AssociateRendererProcessToWorker(version_->embedded_worker());
356 void StartOnIOThread(const base::Closure& done,
357 ServiceWorkerStatusCode* result) {
358 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
359 version_->StartWorker(CreateReceiver(BrowserThread::UI, done, result));
362 void InstallOnIOThread(const base::Closure& done,
363 ServiceWorkerStatusCode* result) {
364 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
365 version_->DispatchInstallEvent(
366 -1, CreateReceiver(BrowserThread::UI, done, result));
369 void ActivateOnIOThread(const base::Closure& done,
370 ServiceWorkerStatusCode* result) {
371 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
372 version_->SetStatus(ServiceWorkerVersion::INSTALLED);
373 version_->DispatchActivateEvent(
374 CreateReceiver(BrowserThread::UI, done, result));
377 void FetchOnIOThread(const base::Closure& done, FetchResult* result) {
378 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
379 ServiceWorkerFetchRequest request(
380 embedded_test_server()->GetURL("/service_worker/empty.html"),
382 std::map<std::string, std::string>());
383 version_->SetStatus(ServiceWorkerVersion::ACTIVE);
384 version_->DispatchFetchEvent(
385 request, CreateResponseReceiver(BrowserThread::UI, done,
386 blob_context_, result));
389 void StopOnIOThread(const base::Closure& done,
390 ServiceWorkerStatusCode* result) {
391 ASSERT_TRUE(version_);
392 version_->StopWorker(CreateReceiver(BrowserThread::UI, done, result));
395 void SyncEventOnIOThread(const base::Closure& done,
396 ServiceWorkerStatusCode* result) {
397 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
398 version_->SetStatus(ServiceWorkerVersion::ACTIVE);
399 version_->DispatchSyncEvent(
400 CreateReceiver(BrowserThread::UI, done, result));
404 scoped_refptr<ServiceWorkerRegistration> registration_;
405 scoped_refptr<ServiceWorkerVersion> version_;
406 scoped_refptr<ChromeBlobStorageContext> blob_context_;
409 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest, StartAndStop) {
410 // Start a worker and wait until OnStarted() is called.
411 base::RunLoop start_run_loop;
412 done_closure_ = start_run_loop.QuitClosure();
413 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
414 base::Bind(&self::StartOnIOThread, this));
415 start_run_loop.Run();
417 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING, last_worker_status_);
419 // Stop a worker and wait until OnStopped() is called.
420 base::RunLoop stop_run_loop;
421 done_closure_ = stop_run_loop.QuitClosure();
422 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
423 base::Bind(&self::StopOnIOThread, this));
426 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED, last_worker_status_);
429 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
430 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
431 "/service_worker/worker.js"));
434 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
435 base::RunLoop start_run_loop;
436 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
437 base::Bind(&self::StartOnIOThread, this,
438 start_run_loop.QuitClosure(),
440 start_run_loop.Run();
441 ASSERT_EQ(SERVICE_WORKER_OK, status);
444 status = SERVICE_WORKER_ERROR_FAILED;
445 base::RunLoop stop_run_loop;
446 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
447 base::Bind(&self::StopOnIOThread, this,
448 stop_run_loop.QuitClosure(),
451 ASSERT_EQ(SERVICE_WORKER_OK, status);
454 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) {
455 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
456 "/service_worker/nonexistent.js"));
458 // Start a worker for nonexistent URL.
459 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
460 base::RunLoop start_run_loop;
461 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
462 base::Bind(&self::StartOnIOThread, this,
463 start_run_loop.QuitClosure(),
465 start_run_loop.Run();
466 ASSERT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
469 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) {
470 InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
473 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
474 InstallWithWaitUntil_Fulfilled) {
475 InstallTestHelper("/service_worker/worker_install_fulfilled.js",
479 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
480 Activate_NoEventListener) {
481 ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
482 ASSERT_EQ(ServiceWorkerVersion::ACTIVE, version_->status());
485 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
486 ActivateTestHelper("/service_worker/worker_activate_rejected.js",
487 SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED);
490 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
491 InstallWithWaitUntil_Rejected) {
492 InstallTestHelper("/service_worker/worker_install_rejected.js",
493 SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED);
496 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
497 ServiceWorkerFetchEventResult result;
498 ServiceWorkerResponse response;
499 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle;
500 FetchTestHelper("/service_worker/fetch_event.js",
501 &result, &response, &blob_data_handle);
502 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, result);
503 EXPECT_EQ(301, response.status_code);
504 EXPECT_EQ("Moved Permanently", response.status_text);
505 std::map<std::string, std::string> expected_headers;
506 expected_headers["Content-Language"] = "fi";
507 expected_headers["Content-Type"] = "text/html; charset=UTF-8";
508 EXPECT_EQ(expected_headers, response.headers);
512 base::Bind(&ReadResponseBody,
513 &body, base::Owned(blob_data_handle.release())));
514 EXPECT_EQ("This resource is gone. Gone, gone, gone.", body);
517 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
518 SyncAbortedWithoutFlag) {
519 RunOnIOThread(base::Bind(
520 &self::SetUpRegistrationOnIOThread, this, "/service_worker/sync.js"));
522 // Run the sync event.
523 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
524 base::RunLoop sync_run_loop;
525 BrowserThread::PostTask(BrowserThread::IO,
527 base::Bind(&self::SyncEventOnIOThread,
529 sync_run_loop.QuitClosure(),
532 ASSERT_EQ(SERVICE_WORKER_ERROR_ABORT, status);
535 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, SyncEventHandled) {
536 CommandLine* command_line = CommandLine::ForCurrentProcess();
537 command_line->AppendSwitch(switches::kEnableServiceWorkerSync);
539 RunOnIOThread(base::Bind(
540 &self::SetUpRegistrationOnIOThread, this, "/service_worker/sync.js"));
541 ServiceWorkerFetchEventResult result;
542 ServiceWorkerResponse response;
543 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle;
544 // Should 404 before sync event.
545 FetchOnRegisteredWorker(&result, &response, &blob_data_handle);
546 EXPECT_EQ(404, response.status_code);
548 // Run the sync event.
549 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
550 base::RunLoop sync_run_loop;
551 BrowserThread::PostTask(BrowserThread::IO,
553 base::Bind(&self::SyncEventOnIOThread,
555 sync_run_loop.QuitClosure(),
558 ASSERT_EQ(SERVICE_WORKER_OK, status);
560 // Should 200 after sync event.
561 FetchOnRegisteredWorker(&result, &response, &blob_data_handle);
562 EXPECT_EQ(200, response.status_code);
565 class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest {
567 typedef ServiceWorkerBlackBoxBrowserTest self;
569 static void ExpectResultAndRun(bool expected,
570 const base::Closure& continuation,
572 EXPECT_EQ(expected, actual);
576 void FindRegistrationOnIO(const GURL& document_url,
577 ServiceWorkerStatusCode* status,
579 const base::Closure& continuation) {
580 wrapper()->context()->storage()->FindRegistrationForDocument(
582 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO2,
589 void FindRegistrationOnIO2(
590 ServiceWorkerStatusCode* out_status,
592 const base::Closure& continuation,
593 ServiceWorkerStatusCode status,
594 const scoped_refptr<ServiceWorkerRegistration>& registration) {
595 *out_status = status;
597 *script_url = registration->script_url();
599 EXPECT_NE(SERVICE_WORKER_OK, status);
605 static int CountRenderProcessHosts() {
607 for (RenderProcessHost::iterator iter(RenderProcessHost::AllHostsIterator());
615 // Crashes on Android: http://crbug.com/387045
616 #if defined(OS_ANDROID)
617 #define MAYBE_Registration DISABLED_Registration
619 #define MAYBE_Registration Registration
621 IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, MAYBE_Registration) {
622 // Close the only window to be sure we're not re-using its RenderProcessHost.
624 EXPECT_EQ(0, CountRenderProcessHosts());
626 const std::string kWorkerUrl = "/service_worker/fetch_event.js";
628 // Unregistering nothing should return true.
630 base::RunLoop run_loop;
631 public_context()->UnregisterServiceWorker(
632 embedded_test_server()->GetURL("/*"),
633 base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
635 run_loop.QuitClosure()));
639 // If we use a worker URL that doesn't exist, registration fails.
641 base::RunLoop run_loop;
642 public_context()->RegisterServiceWorker(
643 embedded_test_server()->GetURL("/*"),
644 embedded_test_server()->GetURL("/does/not/exist"),
645 base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
647 run_loop.QuitClosure()));
650 EXPECT_EQ(0, CountRenderProcessHosts());
652 // Register returns when the promise would be resolved.
654 base::RunLoop run_loop;
655 public_context()->RegisterServiceWorker(
656 embedded_test_server()->GetURL("/*"),
657 embedded_test_server()->GetURL(kWorkerUrl),
658 base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
660 run_loop.QuitClosure()));
663 EXPECT_EQ(1, CountRenderProcessHosts());
665 // Registering again should succeed, although the algo still
666 // might not be complete.
668 base::RunLoop run_loop;
669 public_context()->RegisterServiceWorker(
670 embedded_test_server()->GetURL("/*"),
671 embedded_test_server()->GetURL(kWorkerUrl),
672 base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
674 run_loop.QuitClosure()));
678 // The registration algo might not be far enough along to have
679 // stored the registration data, so it may not be findable
682 // Unregistering something should return true.
684 base::RunLoop run_loop;
685 public_context()->UnregisterServiceWorker(
686 embedded_test_server()->GetURL("/*"),
687 base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
689 run_loop.QuitClosure()));
692 EXPECT_GE(1, CountRenderProcessHosts()) << "Unregistering doesn't stop the "
693 "workers eagerly, so their RPHs "
694 "can still be running.";
696 // Should not be able to find it.
698 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
701 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO,
703 embedded_test_server()->GetURL("/service_worker/empty.html"),
706 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, status);
710 } // namespace content