ServiceWorker: Stop exposing ServiceWorkerContextCore
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_browsertest.cc
blob3c75a907447f48439ce19a6d3756fd1923f412b8
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.
5 #include "base/bind.h"
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"
47 namespace content {
49 namespace {
51 struct FetchResult {
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) {
61 closure.Run();
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()),
72 delay);
73 run_loop.Run();
76 void RunOnIOThread(const base::Closure& closure) {
77 RunOnIOThreadWithDelay(closure, base::TimeDelta());
80 void RunOnIOThread(
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(),
86 FROM_HERE,
87 run_loop.QuitClosure());
88 BrowserThread::PostTask(BrowserThread::IO,
89 FROM_HERE,
90 base::Bind(closure, quit_on_original_thread));
91 run_loop.Run();
94 void ReceivePrepareResult(bool* is_prepared) {
95 *is_prepared = true;
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);
120 if (!quit.is_null())
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),
131 result);
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,
145 bool actual) {
146 EXPECT_EQ(expected, actual);
147 continuation.Run();
150 class WorkerActivatedObserver
151 : public ServiceWorkerContextObserver,
152 public base::RefCountedThreadSafe<WorkerActivatedObserver> {
153 public:
154 explicit WorkerActivatedObserver(ServiceWorkerContextWrapper* context)
155 : context_(context) {}
156 void Init() {
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,
167 FROM_HERE,
168 base::Bind(&WorkerActivatedObserver::Quit, this));
171 void Wait() { run_loop_.Run(); }
173 private:
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 {
204 public:
205 LongLivedResourceInterceptor(const std::string& body)
206 : body_(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[] =
214 "HTTP/1.1 200 OK\0"
215 "Content-Type: text/javascript\0"
216 "Expires: Thu, 1 Jan 2100 20:00:00 GMT\0"
217 "\0";
218 std::string headers(kHeaders, arraysize(kHeaders));
219 return new net::URLRequestTestJob(
220 request, network_delegate, headers, body_, true);
223 private:
224 std::string body_;
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,
246 const GURL& scope,
247 int* num_resources) {
248 *num_resources = -1;
250 std::vector<ServiceWorkerRegistrationInfo> infos =
251 wrapper->GetAllLiveRegistrationInfo();
252 if (infos.empty())
253 return;
255 int version_id;
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;
266 else
267 return;
269 ServiceWorkerVersion* version = wrapper->GetLiveVersion(version_id);
270 *num_resources = static_cast<int>(version->script_cache_map()->size());
273 } // namespace
275 class ServiceWorkerBrowserTest : public ContentBrowserTest {
276 protected:
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
292 // a worker).
293 NavigateToURLBlockUntilNavigationsComplete(
294 shell(),
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));
302 wrapper_ = NULL;
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());
316 private:
317 scoped_refptr<ServiceWorkerContextWrapper> wrapper_;
320 class EmbeddedWorkerBrowserTest : public ServiceWorkerBrowserTest,
321 public EmbeddedWorkerInstance::Listener {
322 public:
323 using self = EmbeddedWorkerBrowserTest;
325 EmbeddedWorkerBrowserTest()
326 : last_worker_status_(EmbeddedWorkerInstance::STOPPED),
327 pause_mode_(DONT_PAUSE) {}
328 ~EmbeddedWorkerBrowserTest() override {}
330 void TearDownOnIOThread() override {
331 if (worker_) {
332 worker_->RemoveListener(this);
333 worker_.reset();
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);
351 worker_->Start(
352 service_worker_version_id,
353 pattern,
354 script_url,
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())
364 done_closure_.Run();
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())
378 done_closure_.Run();
381 protected:
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)
399 worker_->Stop();
400 else
401 ASSERT_TRUE(false);
403 void OnReportException(const base::string16& error_message,
404 int line_number,
405 int column_number,
406 const GURL& source_url) override {}
407 void OnReportConsoleMessage(int source_identifier,
408 int message_level,
409 const base::string16& message,
410 int line_number,
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_;
417 enum {
418 DONT_PAUSE,
419 PAUSE_THEN_RESUME,
420 PAUSE_THEN_STOP,
421 } pause_mode_;
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 {
429 public:
430 void OnReportConsoleMessage(int source_identifier,
431 int message_level,
432 const base::string16& message,
433 int line_number,
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_);
438 quit_.Reset();
442 void WaitForConsoleMessages(size_t expected_message_count) {
443 if (messages_.size() >= expected_message_count)
444 return;
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_; }
457 private:
458 std::vector<base::string16> messages_;
459 size_t expected_message_count_;
460 base::Closure quit_;
463 class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
464 public:
465 using self = ServiceWorkerVersionBrowserTest;
467 ~ServiceWorkerVersionBrowserTest() override {}
469 void TearDownOnIOThread() override {
470 registration_ = NULL;
471 version_ = NULL;
474 void InstallTestHelper(const std::string& worker_url,
475 ServiceWorkerStatusCode expected_status) {
476 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
477 worker_url));
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(),
485 &status));
486 install_run_loop.Run();
487 ASSERT_EQ(expected_status, status);
489 // Stop the worker.
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(),
495 &status));
496 stop_run_loop.Run();
497 ASSERT_EQ(SERVICE_WORKER_OK, status);
500 void ActivateTestHelper(
501 const std::string& worker_url,
502 ServiceWorkerStatusCode expected_status) {
503 RunOnIOThread(
504 base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url));
505 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
506 base::RunLoop run_loop;
507 BrowserThread::PostTask(
508 BrowserThread::IO,
509 FROM_HERE,
510 base::Bind(
511 &self::ActivateOnIOThread, this, run_loop.QuitClosure(), &status));
512 run_loop.Run();
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,
527 FROM_HERE,
528 base::Bind(&self::FetchOnIOThread,
529 this,
530 fetch_run_loop.QuitClosure(),
531 &prepare_result,
532 &fetch_result));
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) {
545 RunOnIOThread(
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(
553 pattern,
554 wrapper()->context()->storage()->NewRegistrationId(),
555 wrapper()->context()->AsWeakPtr());
556 version_ = new ServiceWorkerVersion(
557 registration_.get(),
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(),
582 &status));
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(),
594 &status));
595 stop_run_loop.Run();
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"),
627 "GET",
628 ServiceWorkerHeaderMap(),
629 Referrer(),
630 false);
631 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
632 version_->DispatchFetchEvent(
633 request,
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));
653 protected:
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));
674 stop_run_loop.Run();
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"));
704 // Start a worker.
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(),
710 &status));
711 start_run_loop.Run();
712 ASSERT_EQ(SERVICE_WORKER_OK, status);
714 // Stop the worker.
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(),
720 &status));
721 stop_run_loop.Run();
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",
740 SERVICE_WORKER_OK);
743 // Check that ServiceWorker script requests set a "Service-Worker: script"
744 // header.
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 {
795 public:
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; }
803 private:
804 base::Closure quit_;
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));
820 load_run_loop.Run();
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"));
841 // Start a worker.
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);
880 std::string body;
881 RunOnIOThread(
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,
922 FROM_HERE,
923 base::Bind(&self::SyncEventOnIOThread,
924 this,
925 sync_run_loop.QuitClosure(),
926 &status));
927 sync_run_loop.Run();
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,
948 FROM_HERE,
949 base::Bind(&self::SyncEventOnIOThread,
950 this,
951 sync_run_loop.QuitClosure(),
952 &status));
953 sync_run_loop.Run();
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());
966 observer->Init();
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)));
971 observer->Wait();
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());
983 shell()->Close();
985 base::RunLoop run_loop;
986 public_context()->UnregisterServiceWorker(
987 embedded_test_server()->GetURL(kPageUrl),
988 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
989 run_loop.Run();
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());
1005 observer->Init();
1006 public_context()->RegisterServiceWorker(
1007 https_server.GetURL(kPageUrl),
1008 https_server.GetURL(kWorkerUrl),
1009 base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
1010 observer->Wait();
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);
1021 shell()->Close();
1023 base::RunLoop run_loop;
1024 public_context()->UnregisterServiceWorker(
1025 https_server.GetURL(kPageUrl),
1026 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
1027 run_loop.Run();
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());
1036 observer->Init();
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)));
1041 observer->Wait();
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);
1052 shell()->Close();
1054 base::RunLoop run_loop;
1055 public_context()->UnregisterServiceWorker(
1056 embedded_test_server()->GetURL(kPageUrl),
1057 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
1058 run_loop.Run();
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"));
1069 RunOnIOThread(
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;
1083 RunOnIOThread(
1084 base::Bind(&CountScriptResources,
1085 base::Unretained(wrapper()),
1086 embedded_test_server()->GetURL(kScopeUrl),
1087 &num_resources));
1088 EXPECT_EQ(kExpectedNumResources, num_resources);
1091 class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest {
1092 public:
1093 using self = ServiceWorkerBlackBoxBrowserTest;
1095 void FindRegistrationOnIO(const GURL& document_url,
1096 ServiceWorkerStatusCode* status,
1097 const base::Closure& continuation) {
1098 wrapper()->FindRegistrationForDocument(
1099 document_url,
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);
1112 continuation.Run();
1116 static int CountRenderProcessHosts() {
1117 int result = 0;
1118 for (RenderProcessHost::iterator iter(RenderProcessHost::AllHostsIterator());
1119 !iter.IsAtEnd();
1120 iter.Advance()) {
1121 result++;
1123 return result;
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
1129 #else
1130 #define MAYBE_Registration Registration
1131 #endif
1132 IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, MAYBE_Registration) {
1133 // Close the only window to be sure we're not re-using its RenderProcessHost.
1134 shell()->Close();
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()));
1146 run_loop.Run();
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()));
1156 run_loop.Run();
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()));
1167 run_loop.Run();
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()));
1179 run_loop.Run();
1182 // The registration algo might not be far enough along to have
1183 // stored the registration data, so it may not be findable
1184 // at this point.
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()));
1192 run_loop.Run();
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;
1201 RunOnIOThread(
1202 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO,
1203 this,
1204 embedded_test_server()->GetURL("/service_worker/empty.html"),
1205 &status));
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 {
1240 public:
1241 using self = ServiceWorkerVersionBrowserV8CacheTest;
1242 ~ServiceWorkerVersionBrowserV8CacheTest() override {
1243 if (version_)
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);
1255 protected:
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();
1272 // Start a worker.
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);
1287 // Stop the worker.
1288 StopWorker(SERVICE_WORKER_OK);
1289 // Restart the worker.
1290 StartWorker(SERVICE_WORKER_OK);
1291 // Stop the worker.
1292 StopWorker(SERVICE_WORKER_OK);
1295 } // namespace content