Android Chromoting: Remove exit-fullscreen button.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_browsertest.cc
blobc030d8cf37edad00a870f6d7095d67195f097cfe
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 =
164 context_->context()->GetLiveVersion(version_id);
165 if (version->status() == ServiceWorkerVersion::ACTIVATED) {
166 context_->RemoveObserver(this);
167 BrowserThread::PostTask(BrowserThread::UI,
168 FROM_HERE,
169 base::Bind(&WorkerActivatedObserver::Quit, this));
172 void Wait() { run_loop_.Run(); }
174 private:
175 friend class base::RefCountedThreadSafe<WorkerActivatedObserver>;
176 ~WorkerActivatedObserver() override {}
177 void InitOnIOThread() { context_->AddObserver(this); }
178 void Quit() { run_loop_.Quit(); }
180 base::RunLoop run_loop_;
181 ServiceWorkerContextWrapper* context_;
182 DISALLOW_COPY_AND_ASSIGN(WorkerActivatedObserver);
185 scoped_ptr<net::test_server::HttpResponse> VerifyServiceWorkerHeaderInRequest(
186 const net::test_server::HttpRequest& request) {
187 EXPECT_EQ(request.relative_url, "/service_worker/generated_sw.js");
188 std::map<std::string, std::string>::const_iterator it =
189 request.headers.find("Service-Worker");
190 EXPECT_TRUE(it != request.headers.end());
191 EXPECT_EQ("script", it->second);
193 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
194 new net::test_server::BasicHttpResponse());
195 http_response->set_content_type("text/javascript");
196 return http_response.Pass();
199 // The ImportsBustMemcache test requires that the imported script
200 // would naturally be cached in blink's memcache, but the embedded
201 // test server doesn't produce headers that allow the blink's memcache
202 // to do that. This interceptor injects headers that give the import
203 // an experiration far in the future.
204 class LongLivedResourceInterceptor : public net::URLRequestInterceptor {
205 public:
206 LongLivedResourceInterceptor(const std::string& body)
207 : body_(body) {}
208 ~LongLivedResourceInterceptor() override {}
210 // net::URLRequestInterceptor implementation
211 net::URLRequestJob* MaybeInterceptRequest(
212 net::URLRequest* request,
213 net::NetworkDelegate* network_delegate) const override {
214 const char kHeaders[] =
215 "HTTP/1.1 200 OK\0"
216 "Content-Type: text/javascript\0"
217 "Expires: Thu, 1 Jan 2100 20:00:00 GMT\0"
218 "\0";
219 std::string headers(kHeaders, arraysize(kHeaders));
220 return new net::URLRequestTestJob(
221 request, network_delegate, headers, body_, true);
224 private:
225 std::string body_;
226 DISALLOW_COPY_AND_ASSIGN(LongLivedResourceInterceptor);
229 void CreateLongLivedResourceInterceptors(
230 const GURL& worker_url, const GURL& import_url) {
231 DCHECK_CURRENTLY_ON(BrowserThread::IO);
232 scoped_ptr<net::URLRequestInterceptor> interceptor;
234 interceptor.reset(new LongLivedResourceInterceptor(
235 "importScripts('long_lived_import.js');"));
236 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
237 worker_url, interceptor.Pass());
239 interceptor.reset(new LongLivedResourceInterceptor(
240 "// the imported script does nothing"));
241 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
242 import_url, interceptor.Pass());
245 void CountScriptResources(
246 ServiceWorkerContextWrapper* wrapper,
247 const GURL& scope,
248 int* num_resources) {
249 *num_resources = -1;
251 std::vector<ServiceWorkerRegistrationInfo> infos =
252 wrapper->context()->GetAllLiveRegistrationInfo();
253 if (infos.empty())
254 return;
256 int version_id;
257 size_t index = infos.size() - 1;
258 if (infos[index].installing_version.version_id !=
259 kInvalidServiceWorkerVersionId)
260 version_id = infos[index].installing_version.version_id;
261 else if (infos[index].waiting_version.version_id !=
262 kInvalidServiceWorkerVersionId)
263 version_id = infos[1].waiting_version.version_id;
264 else if (infos[index].active_version.version_id !=
265 kInvalidServiceWorkerVersionId)
266 version_id = infos[index].active_version.version_id;
267 else
268 return;
270 ServiceWorkerVersion* version =
271 wrapper->context()->GetLiveVersion(version_id);
272 *num_resources = static_cast<int>(version->script_cache_map()->size());
275 } // namespace
277 class ServiceWorkerBrowserTest : public ContentBrowserTest {
278 protected:
279 using self = ServiceWorkerBrowserTest;
281 void SetUpCommandLine(base::CommandLine* command_line) override {
282 command_line->AppendSwitch(
283 switches::kEnableExperimentalWebPlatformFeatures);
286 void SetUpOnMainThread() override {
287 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
288 StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
289 shell()->web_contents()->GetBrowserContext());
290 wrapper_ = static_cast<ServiceWorkerContextWrapper*>(
291 partition->GetServiceWorkerContext());
293 // Navigate to the page to set up a renderer page (where we can embed
294 // a worker).
295 NavigateToURLBlockUntilNavigationsComplete(
296 shell(),
297 embedded_test_server()->GetURL("/service_worker/empty.html"), 1);
299 RunOnIOThread(base::Bind(&self::SetUpOnIOThread, this));
302 void TearDownOnMainThread() override {
303 RunOnIOThread(base::Bind(&self::TearDownOnIOThread, this));
304 wrapper_ = NULL;
307 virtual void SetUpOnIOThread() {}
308 virtual void TearDownOnIOThread() {}
310 ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); }
311 ServiceWorkerContext* public_context() { return wrapper(); }
313 void AssociateRendererProcessToPattern(const GURL& pattern) {
314 wrapper_->process_manager()->AddProcessReferenceToPattern(
315 pattern, shell()->web_contents()->GetRenderProcessHost()->GetID());
318 private:
319 scoped_refptr<ServiceWorkerContextWrapper> wrapper_;
322 class EmbeddedWorkerBrowserTest : public ServiceWorkerBrowserTest,
323 public EmbeddedWorkerInstance::Listener {
324 public:
325 using self = EmbeddedWorkerBrowserTest;
327 EmbeddedWorkerBrowserTest()
328 : last_worker_status_(EmbeddedWorkerInstance::STOPPED),
329 pause_mode_(DONT_PAUSE) {}
330 ~EmbeddedWorkerBrowserTest() override {}
332 void TearDownOnIOThread() override {
333 if (worker_) {
334 worker_->RemoveListener(this);
335 worker_.reset();
339 void StartOnIOThread() {
340 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
341 worker_ = wrapper()->context()->embedded_worker_registry()->CreateWorker();
342 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker_->status());
343 worker_->AddListener(this);
345 const int64 service_worker_version_id = 33L;
346 const GURL pattern = embedded_test_server()->GetURL("/");
347 const GURL script_url = embedded_test_server()->GetURL(
348 "/service_worker/worker.js");
349 AssociateRendererProcessToPattern(pattern);
350 int process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
351 wrapper()->process_manager()->AddProcessReferenceToPattern(
352 pattern, process_id);
353 worker_->Start(
354 service_worker_version_id,
355 pattern,
356 script_url,
357 pause_mode_ != DONT_PAUSE,
358 base::Bind(&EmbeddedWorkerBrowserTest::StartOnIOThread2, this));
360 void StartOnIOThread2(ServiceWorkerStatusCode status) {
361 last_worker_status_ = worker_->status();
362 EXPECT_EQ(SERVICE_WORKER_OK, status);
363 EXPECT_EQ(EmbeddedWorkerInstance::STARTING, last_worker_status_);
365 if (status != SERVICE_WORKER_OK && !done_closure_.is_null())
366 done_closure_.Run();
369 void StopOnIOThread() {
370 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
371 EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker_->status());
373 ServiceWorkerStatusCode status = worker_->Stop();
375 last_worker_status_ = worker_->status();
376 EXPECT_EQ(SERVICE_WORKER_OK, status);
377 EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, last_worker_status_);
379 if (status != SERVICE_WORKER_OK && !done_closure_.is_null())
380 done_closure_.Run();
383 protected:
384 // EmbeddedWorkerInstance::Observer overrides:
385 void OnStarted() override {
386 ASSERT_TRUE(worker_ != NULL);
387 ASSERT_FALSE(done_closure_.is_null());
388 last_worker_status_ = worker_->status();
389 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_);
391 void OnStopped(EmbeddedWorkerInstance::Status old_status) override {
392 ASSERT_TRUE(worker_ != NULL);
393 ASSERT_FALSE(done_closure_.is_null());
394 last_worker_status_ = worker_->status();
395 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_);
397 void OnPausedAfterDownload() override {
398 if (pause_mode_ == PAUSE_THEN_RESUME)
399 worker_->ResumeAfterDownload();
400 else if (pause_mode_ == PAUSE_THEN_STOP)
401 worker_->Stop();
402 else
403 ASSERT_TRUE(false);
405 void OnReportException(const base::string16& error_message,
406 int line_number,
407 int column_number,
408 const GURL& source_url) override {}
409 void OnReportConsoleMessage(int source_identifier,
410 int message_level,
411 const base::string16& message,
412 int line_number,
413 const GURL& source_url) override {}
414 bool OnMessageReceived(const IPC::Message& message) override { return false; }
416 scoped_ptr<EmbeddedWorkerInstance> worker_;
417 EmbeddedWorkerInstance::Status last_worker_status_;
419 enum {
420 DONT_PAUSE,
421 PAUSE_THEN_RESUME,
422 PAUSE_THEN_STOP,
423 } pause_mode_;
425 // Called by EmbeddedWorkerInstance::Observer overrides so that
426 // test code can wait for the worker status notifications.
427 base::Closure done_closure_;
430 class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
431 public:
432 using self = ServiceWorkerVersionBrowserTest;
434 ~ServiceWorkerVersionBrowserTest() override {}
436 void TearDownOnIOThread() override {
437 registration_ = NULL;
438 version_ = NULL;
441 void InstallTestHelper(const std::string& worker_url,
442 ServiceWorkerStatusCode expected_status) {
443 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
444 worker_url));
446 // Dispatch install on a worker.
447 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
448 base::RunLoop install_run_loop;
449 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
450 base::Bind(&self::InstallOnIOThread, this,
451 install_run_loop.QuitClosure(),
452 &status));
453 install_run_loop.Run();
454 ASSERT_EQ(expected_status, status);
456 // Stop the worker.
457 status = SERVICE_WORKER_ERROR_FAILED;
458 base::RunLoop stop_run_loop;
459 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
460 base::Bind(&self::StopOnIOThread, this,
461 stop_run_loop.QuitClosure(),
462 &status));
463 stop_run_loop.Run();
464 ASSERT_EQ(SERVICE_WORKER_OK, status);
467 void ActivateTestHelper(
468 const std::string& worker_url,
469 ServiceWorkerStatusCode expected_status) {
470 RunOnIOThread(
471 base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url));
472 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
473 base::RunLoop run_loop;
474 BrowserThread::PostTask(
475 BrowserThread::IO,
476 FROM_HERE,
477 base::Bind(
478 &self::ActivateOnIOThread, this, run_loop.QuitClosure(), &status));
479 run_loop.Run();
480 ASSERT_EQ(expected_status, status);
483 void FetchOnRegisteredWorker(
484 ServiceWorkerFetchEventResult* result,
485 ServiceWorkerResponse* response,
486 scoped_ptr<storage::BlobDataHandle>* blob_data_handle) {
487 blob_context_ = ChromeBlobStorageContext::GetFor(
488 shell()->web_contents()->GetBrowserContext());
489 bool prepare_result = false;
490 FetchResult fetch_result;
491 fetch_result.status = SERVICE_WORKER_ERROR_FAILED;
492 base::RunLoop fetch_run_loop;
493 BrowserThread::PostTask(BrowserThread::IO,
494 FROM_HERE,
495 base::Bind(&self::FetchOnIOThread,
496 this,
497 fetch_run_loop.QuitClosure(),
498 &prepare_result,
499 &fetch_result));
500 fetch_run_loop.Run();
501 ASSERT_TRUE(prepare_result);
502 *result = fetch_result.result;
503 *response = fetch_result.response;
504 *blob_data_handle = fetch_result.blob_data_handle.Pass();
505 ASSERT_EQ(SERVICE_WORKER_OK, fetch_result.status);
508 void FetchTestHelper(const std::string& worker_url,
509 ServiceWorkerFetchEventResult* result,
510 ServiceWorkerResponse* response,
511 scoped_ptr<storage::BlobDataHandle>* blob_data_handle) {
512 RunOnIOThread(
513 base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url));
514 FetchOnRegisteredWorker(result, response, blob_data_handle);
517 void SetUpRegistrationOnIOThread(const std::string& worker_url) {
518 const GURL pattern = embedded_test_server()->GetURL("/service_worker/");
519 registration_ = new ServiceWorkerRegistration(
520 pattern,
521 wrapper()->context()->storage()->NewRegistrationId(),
522 wrapper()->context()->AsWeakPtr());
523 version_ = new ServiceWorkerVersion(
524 registration_.get(),
525 embedded_test_server()->GetURL(worker_url),
526 wrapper()->context()->storage()->NewVersionId(),
527 wrapper()->context()->AsWeakPtr());
529 // Make the registration findable via storage functions.
530 wrapper()->context()->storage()->NotifyInstallingRegistration(
531 registration_.get());
533 AssociateRendererProcessToPattern(pattern);
536 void TimeoutWorkerOnIOThread() {
537 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
538 version_->PingWorker();
539 version_->OnPingTimeout();
542 void StartWorker(ServiceWorkerStatusCode expected_status) {
543 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
544 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
545 base::RunLoop start_run_loop;
546 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
547 base::Bind(&self::StartOnIOThread, this,
548 start_run_loop.QuitClosure(),
549 &status));
550 start_run_loop.Run();
551 ASSERT_EQ(expected_status, status);
554 void StopWorker(ServiceWorkerStatusCode expected_status) {
555 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
556 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
557 base::RunLoop stop_run_loop;
558 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
559 base::Bind(&self::StopOnIOThread, this,
560 stop_run_loop.QuitClosure(),
561 &status));
562 stop_run_loop.Run();
563 ASSERT_EQ(expected_status, status);
566 void StartOnIOThread(const base::Closure& done,
567 ServiceWorkerStatusCode* result) {
568 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
569 version_->StartWorker(CreateReceiver(BrowserThread::UI, done, result));
572 void InstallOnIOThread(const base::Closure& done,
573 ServiceWorkerStatusCode* result) {
574 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
575 version_->SetStatus(ServiceWorkerVersion::INSTALLING);
576 version_->DispatchInstallEvent(
577 CreateReceiver(BrowserThread::UI, done, result));
580 void ActivateOnIOThread(const base::Closure& done,
581 ServiceWorkerStatusCode* result) {
582 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
583 version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
584 version_->DispatchActivateEvent(
585 CreateReceiver(BrowserThread::UI, done, result));
588 void FetchOnIOThread(const base::Closure& done,
589 bool* prepare_result,
590 FetchResult* result) {
591 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
592 ServiceWorkerFetchRequest request(
593 embedded_test_server()->GetURL("/service_worker/empty.html"),
594 "GET",
595 ServiceWorkerHeaderMap(),
596 Referrer(),
597 false);
598 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
599 version_->DispatchFetchEvent(
600 request,
601 CreatePrepareReceiver(prepare_result),
602 CreateResponseReceiver(
603 BrowserThread::UI, done, blob_context_.get(), result));
606 void StopOnIOThread(const base::Closure& done,
607 ServiceWorkerStatusCode* result) {
608 ASSERT_TRUE(version_.get());
609 version_->StopWorker(CreateReceiver(BrowserThread::UI, done, result));
612 void SyncEventOnIOThread(const base::Closure& done,
613 ServiceWorkerStatusCode* result) {
614 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
615 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
616 version_->DispatchSyncEvent(
617 CreateReceiver(BrowserThread::UI, done, result));
620 protected:
621 scoped_refptr<ServiceWorkerRegistration> registration_;
622 scoped_refptr<ServiceWorkerVersion> version_;
623 scoped_refptr<ChromeBlobStorageContext> blob_context_;
626 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest, StartAndStop) {
627 // Start a worker and wait until OnStarted() is called.
628 base::RunLoop start_run_loop;
629 done_closure_ = start_run_loop.QuitClosure();
630 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
631 base::Bind(&self::StartOnIOThread, this));
632 start_run_loop.Run();
634 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING, last_worker_status_);
636 // Stop a worker and wait until OnStopped() is called.
637 base::RunLoop stop_run_loop;
638 done_closure_ = stop_run_loop.QuitClosure();
639 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
640 base::Bind(&self::StopOnIOThread, this));
641 stop_run_loop.Run();
643 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED, last_worker_status_);
646 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest, StartPaused_ThenResume) {
647 pause_mode_ = PAUSE_THEN_RESUME;
648 base::RunLoop start_run_loop;
649 done_closure_ = start_run_loop.QuitClosure();
650 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
651 base::Bind(&self::StartOnIOThread, this));
652 start_run_loop.Run();
653 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING, last_worker_status_);
656 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest,
657 StartPaused_ThenStop) {
658 pause_mode_ = PAUSE_THEN_STOP;
659 base::RunLoop start_run_loop;
660 done_closure_ = start_run_loop.QuitClosure();
661 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
662 base::Bind(&self::StartOnIOThread, this));
663 start_run_loop.Run();
664 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED, last_worker_status_);
667 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
668 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
669 "/service_worker/worker.js"));
671 // Start a worker.
672 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
673 base::RunLoop start_run_loop;
674 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
675 base::Bind(&self::StartOnIOThread, this,
676 start_run_loop.QuitClosure(),
677 &status));
678 start_run_loop.Run();
679 ASSERT_EQ(SERVICE_WORKER_OK, status);
681 // Stop the worker.
682 status = SERVICE_WORKER_ERROR_FAILED;
683 base::RunLoop stop_run_loop;
684 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
685 base::Bind(&self::StopOnIOThread, this,
686 stop_run_loop.QuitClosure(),
687 &status));
688 stop_run_loop.Run();
689 ASSERT_EQ(SERVICE_WORKER_OK, status);
692 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) {
693 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
694 "/service_worker/nonexistent.js"));
696 // Start a worker for nonexistent URL.
697 StartWorker(SERVICE_WORKER_ERROR_START_WORKER_FAILED);
700 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) {
701 InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
704 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
705 InstallWithWaitUntil_Fulfilled) {
706 InstallTestHelper("/service_worker/worker_install_fulfilled.js",
707 SERVICE_WORKER_OK);
710 // Check that ServiceWorker script requests set a "Service-Worker: script"
711 // header.
712 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
713 ServiceWorkerScriptHeader) {
714 embedded_test_server()->RegisterRequestHandler(
715 base::Bind(&VerifyServiceWorkerHeaderInRequest));
716 InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK);
719 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
720 Activate_NoEventListener) {
721 ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
722 ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
725 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
726 ActivateTestHelper("/service_worker/worker_activate_rejected.js",
727 SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED);
730 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
731 InstallWithWaitUntil_Rejected) {
732 InstallTestHelper("/service_worker/worker_install_rejected.js",
733 SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED);
736 class WaitForLoaded : public EmbeddedWorkerInstance::Listener {
737 public:
738 WaitForLoaded(const base::Closure& quit) : quit_(quit) {}
740 void OnScriptLoaded() override {
741 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_);
743 bool OnMessageReceived(const IPC::Message& message) override { return false; }
745 private:
746 base::Closure quit_;
749 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
750 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
751 "/service_worker/while_true_worker.js"));
753 // Start a worker, waiting until the script is loaded.
754 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
755 base::RunLoop start_run_loop;
756 base::RunLoop load_run_loop;
757 WaitForLoaded wait_for_load(load_run_loop.QuitClosure());
758 version_->embedded_worker()->AddListener(&wait_for_load);
759 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
760 base::Bind(&self::StartOnIOThread, this,
761 start_run_loop.QuitClosure(), &status));
762 load_run_loop.Run();
763 version_->embedded_worker()->RemoveListener(&wait_for_load);
765 // The script has loaded but start has not completed yet.
766 ASSERT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
767 EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
769 // Simulate execution timeout. Use a delay to prevent killing the worker
770 // before it's started execution.
771 EXPECT_TRUE(version_->timeout_timer_.IsRunning());
772 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread, this),
773 base::TimeDelta::FromMilliseconds(100));
774 start_run_loop.Run();
776 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
779 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
780 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
781 "/service_worker/while_true_in_install_worker.js"));
783 // Start a worker.
784 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
785 base::RunLoop start_run_loop;
786 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
787 base::Bind(&self::StartOnIOThread, this,
788 start_run_loop.QuitClosure(), &status));
789 start_run_loop.Run();
790 ASSERT_EQ(SERVICE_WORKER_OK, status);
792 // Dispatch an event.
793 base::RunLoop install_run_loop;
794 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
795 base::Bind(&self::InstallOnIOThread, this,
796 install_run_loop.QuitClosure(), &status));
798 // Simulate execution timeout. Use a delay to prevent killing the worker
799 // before it's started execution.
800 EXPECT_TRUE(version_->timeout_timer_.IsRunning());
801 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread, this),
802 base::TimeDelta::FromMilliseconds(100));
803 install_run_loop.Run();
805 EXPECT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED, status);
808 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
809 ServiceWorkerFetchEventResult result;
810 ServiceWorkerResponse response;
811 scoped_ptr<storage::BlobDataHandle> blob_data_handle;
812 FetchTestHelper("/service_worker/fetch_event.js",
813 &result, &response, &blob_data_handle);
814 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, result);
815 EXPECT_EQ(301, response.status_code);
816 EXPECT_EQ("Moved Permanently", response.status_text);
817 ServiceWorkerHeaderMap expected_headers;
818 expected_headers["content-language"] = "fi";
819 expected_headers["content-type"] = "text/html; charset=UTF-8";
820 EXPECT_EQ(expected_headers, response.headers);
822 std::string body;
823 RunOnIOThread(
824 base::Bind(&ReadResponseBody,
825 &body, base::Owned(blob_data_handle.release())));
826 EXPECT_EQ("This resource is gone. Gone, gone, gone.", body);
829 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
830 SyncAbortedWithoutFlag) {
831 RunOnIOThread(base::Bind(
832 &self::SetUpRegistrationOnIOThread, this, "/service_worker/sync.js"));
834 // Run the sync event.
835 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
836 base::RunLoop sync_run_loop;
837 BrowserThread::PostTask(BrowserThread::IO,
838 FROM_HERE,
839 base::Bind(&self::SyncEventOnIOThread,
840 this,
841 sync_run_loop.QuitClosure(),
842 &status));
843 sync_run_loop.Run();
844 ASSERT_EQ(SERVICE_WORKER_ERROR_ABORT, status);
847 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, SyncEventHandled) {
848 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
849 command_line->AppendSwitch(switches::kEnableServiceWorkerSync);
851 RunOnIOThread(base::Bind(
852 &self::SetUpRegistrationOnIOThread, this, "/service_worker/sync.js"));
853 ServiceWorkerFetchEventResult result;
854 ServiceWorkerResponse response;
855 scoped_ptr<storage::BlobDataHandle> blob_data_handle;
856 // Should 404 before sync event.
857 FetchOnRegisteredWorker(&result, &response, &blob_data_handle);
858 EXPECT_EQ(404, response.status_code);
860 // Run the sync event.
861 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
862 base::RunLoop sync_run_loop;
863 BrowserThread::PostTask(BrowserThread::IO,
864 FROM_HERE,
865 base::Bind(&self::SyncEventOnIOThread,
866 this,
867 sync_run_loop.QuitClosure(),
868 &status));
869 sync_run_loop.Run();
870 ASSERT_EQ(SERVICE_WORKER_OK, status);
872 // Should 200 after sync event.
873 FetchOnRegisteredWorker(&result, &response, &blob_data_handle);
874 EXPECT_EQ(200, response.status_code);
877 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, Reload) {
878 const char kPageUrl[] = "/service_worker/reload.html";
879 const char kWorkerUrl[] = "/service_worker/fetch_event_reload.js";
880 scoped_refptr<WorkerActivatedObserver> observer =
881 new WorkerActivatedObserver(wrapper());
882 observer->Init();
883 public_context()->RegisterServiceWorker(
884 embedded_test_server()->GetURL(kPageUrl),
885 embedded_test_server()->GetURL(kWorkerUrl),
886 base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
887 observer->Wait();
889 const base::string16 title1 = base::ASCIIToUTF16("reload=false");
890 TitleWatcher title_watcher1(shell()->web_contents(), title1);
891 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl));
892 EXPECT_EQ(title1, title_watcher1.WaitAndGetTitle());
894 const base::string16 title2 = base::ASCIIToUTF16("reload=true");
895 TitleWatcher title_watcher2(shell()->web_contents(), title2);
896 ReloadBlockUntilNavigationsComplete(shell(), 1);
897 EXPECT_EQ(title2, title_watcher2.WaitAndGetTitle());
899 shell()->Close();
901 base::RunLoop run_loop;
902 public_context()->UnregisterServiceWorker(
903 embedded_test_server()->GetURL(kPageUrl),
904 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
905 run_loop.Run();
908 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
909 ResponseFromHTTPSServiceWorkerIsMarkedAsSecure) {
910 const char kPageUrl[] = "files/service_worker/fetch_event_blob.html";
911 const char kWorkerUrl[] = "files/service_worker/fetch_event_blob.js";
912 net::SpawnedTestServer https_server(
913 net::SpawnedTestServer::TYPE_HTTPS,
914 net::BaseTestServer::SSLOptions(
915 net::BaseTestServer::SSLOptions::CERT_OK),
916 base::FilePath(FILE_PATH_LITERAL("content/test/data/")));
917 ASSERT_TRUE(https_server.Start());
919 scoped_refptr<WorkerActivatedObserver> observer =
920 new WorkerActivatedObserver(wrapper());
921 observer->Init();
922 public_context()->RegisterServiceWorker(
923 https_server.GetURL(kPageUrl),
924 https_server.GetURL(kWorkerUrl),
925 base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
926 observer->Wait();
928 const base::string16 title = base::ASCIIToUTF16("Title");
929 TitleWatcher title_watcher(shell()->web_contents(), title);
930 NavigateToURL(shell(), https_server.GetURL(kPageUrl));
931 EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
932 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
933 NavigationEntry* entry =
934 shell()->web_contents()->GetController().GetVisibleEntry();
935 EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, entry->GetSSL().security_style);
937 shell()->Close();
939 base::RunLoop run_loop;
940 public_context()->UnregisterServiceWorker(
941 https_server.GetURL(kPageUrl),
942 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
943 run_loop.Run();
946 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
947 ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure) {
948 const char kPageUrl[] = "/service_worker/fetch_event_blob.html";
949 const char kWorkerUrl[] = "/service_worker/fetch_event_blob.js";
950 scoped_refptr<WorkerActivatedObserver> observer =
951 new WorkerActivatedObserver(wrapper());
952 observer->Init();
953 public_context()->RegisterServiceWorker(
954 embedded_test_server()->GetURL(kPageUrl),
955 embedded_test_server()->GetURL(kWorkerUrl),
956 base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
957 observer->Wait();
959 const base::string16 title = base::ASCIIToUTF16("Title");
960 TitleWatcher title_watcher(shell()->web_contents(), title);
961 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl));
962 EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
963 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
964 NavigationEntry* entry =
965 shell()->web_contents()->GetController().GetVisibleEntry();
966 EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, entry->GetSSL().security_style);
968 shell()->Close();
970 base::RunLoop run_loop;
971 public_context()->UnregisterServiceWorker(
972 embedded_test_server()->GetURL(kPageUrl),
973 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
974 run_loop.Run();
977 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ImportsBustMemcache) {
978 const char kScopeUrl[] = "/service_worker/imports_bust_memcache_scope/";
979 const char kPageUrl[] = "/service_worker/imports_bust_memcache.html";
980 const char kScriptUrl[] = "/service_worker/worker_with_one_import.js";
981 const char kImportUrl[] = "/service_worker/long_lived_import.js";
982 const base::string16 kOKTitle(base::ASCIIToUTF16("OK"));
983 const base::string16 kFailTitle(base::ASCIIToUTF16("FAIL"));
985 RunOnIOThread(
986 base::Bind(&CreateLongLivedResourceInterceptors,
987 embedded_test_server()->GetURL(kScriptUrl),
988 embedded_test_server()->GetURL(kImportUrl)));
990 TitleWatcher title_watcher(shell()->web_contents(), kOKTitle);
991 title_watcher.AlsoWaitForTitle(kFailTitle);
992 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl));
993 base::string16 title = title_watcher.WaitAndGetTitle();
994 EXPECT_EQ(kOKTitle, title);
996 // Verify the number of resources in the implicit script cache is correct.
997 const int kExpectedNumResources = 2;
998 int num_resources = 0;
999 RunOnIOThread(
1000 base::Bind(&CountScriptResources,
1001 base::Unretained(wrapper()),
1002 embedded_test_server()->GetURL(kScopeUrl),
1003 &num_resources));
1004 EXPECT_EQ(kExpectedNumResources, num_resources);
1007 class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest {
1008 public:
1009 using self = ServiceWorkerBlackBoxBrowserTest;
1011 void FindRegistrationOnIO(const GURL& document_url,
1012 ServiceWorkerStatusCode* status,
1013 const base::Closure& continuation) {
1014 wrapper()->context()->storage()->FindRegistrationForDocument(
1015 document_url,
1016 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO2,
1017 this,
1018 status,
1019 continuation));
1022 void FindRegistrationOnIO2(
1023 ServiceWorkerStatusCode* out_status,
1024 const base::Closure& continuation,
1025 ServiceWorkerStatusCode status,
1026 const scoped_refptr<ServiceWorkerRegistration>& registration) {
1027 *out_status = status;
1028 if (!registration.get())
1029 EXPECT_NE(SERVICE_WORKER_OK, status);
1030 continuation.Run();
1034 static int CountRenderProcessHosts() {
1035 int result = 0;
1036 for (RenderProcessHost::iterator iter(RenderProcessHost::AllHostsIterator());
1037 !iter.IsAtEnd();
1038 iter.Advance()) {
1039 result++;
1041 return result;
1044 // Flaky timeouts on CrOS and crash on Android: http://crbug.com/387045
1045 #if defined(OS_CHROMEOS) || defined(ANDROID)
1046 #define MAYBE_Registration DISABLED_Registration
1047 #else
1048 #define MAYBE_Registration Registration
1049 #endif
1050 IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, MAYBE_Registration) {
1051 // Close the only window to be sure we're not re-using its RenderProcessHost.
1052 shell()->Close();
1053 EXPECT_EQ(0, CountRenderProcessHosts());
1055 const char kWorkerUrl[] = "/service_worker/fetch_event.js";
1056 const char kScope[] = "/service_worker/";
1058 // Unregistering nothing should return false.
1060 base::RunLoop run_loop;
1061 public_context()->UnregisterServiceWorker(
1062 embedded_test_server()->GetURL("/"),
1063 base::Bind(&ExpectResultAndRun, false, run_loop.QuitClosure()));
1064 run_loop.Run();
1067 // If we use a worker URL that doesn't exist, registration fails.
1069 base::RunLoop run_loop;
1070 public_context()->RegisterServiceWorker(
1071 embedded_test_server()->GetURL(kScope),
1072 embedded_test_server()->GetURL("/does/not/exist"),
1073 base::Bind(&ExpectResultAndRun, false, run_loop.QuitClosure()));
1074 run_loop.Run();
1076 EXPECT_EQ(0, CountRenderProcessHosts());
1078 // Register returns when the promise would be resolved.
1080 base::RunLoop run_loop;
1081 public_context()->RegisterServiceWorker(
1082 embedded_test_server()->GetURL(kScope),
1083 embedded_test_server()->GetURL(kWorkerUrl),
1084 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
1085 run_loop.Run();
1087 EXPECT_EQ(1, CountRenderProcessHosts());
1089 // Registering again should succeed, although the algo still
1090 // might not be complete.
1092 base::RunLoop run_loop;
1093 public_context()->RegisterServiceWorker(
1094 embedded_test_server()->GetURL(kScope),
1095 embedded_test_server()->GetURL(kWorkerUrl),
1096 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
1097 run_loop.Run();
1100 // The registration algo might not be far enough along to have
1101 // stored the registration data, so it may not be findable
1102 // at this point.
1104 // Unregistering something should return true.
1106 base::RunLoop run_loop;
1107 public_context()->UnregisterServiceWorker(
1108 embedded_test_server()->GetURL(kScope),
1109 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
1110 run_loop.Run();
1112 EXPECT_GE(1, CountRenderProcessHosts()) << "Unregistering doesn't stop the "
1113 "workers eagerly, so their RPHs "
1114 "can still be running.";
1116 // Should not be able to find it.
1118 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
1119 RunOnIOThread(
1120 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO,
1121 this,
1122 embedded_test_server()->GetURL("/service_worker/empty.html"),
1123 &status));
1124 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, status);
1128 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, CrossSiteTransfer) {
1129 // The first page registers a service worker.
1130 const char kRegisterPageUrl[] = "/service_worker/cross_site_xfer.html";
1131 const base::string16 kOKTitle1(base::ASCIIToUTF16("OK_1"));
1132 const base::string16 kFailTitle1(base::ASCIIToUTF16("FAIL_1"));
1133 content::TitleWatcher title_watcher1(shell()->web_contents(), kOKTitle1);
1134 title_watcher1.AlsoWaitForTitle(kFailTitle1);
1136 NavigateToURL(shell(), embedded_test_server()->GetURL(kRegisterPageUrl));
1137 ASSERT_EQ(kOKTitle1, title_watcher1.WaitAndGetTitle());
1139 // Force process swapping behavior.
1140 ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
1142 // The second pages loads via the serviceworker including a subresource.
1143 const char kConfirmPageUrl[] =
1144 "/service_worker/cross_site_xfer_scope/"
1145 "cross_site_xfer_confirm_via_serviceworker.html";
1146 const base::string16 kOKTitle2(base::ASCIIToUTF16("OK_2"));
1147 const base::string16 kFailTitle2(base::ASCIIToUTF16("FAIL_2"));
1148 content::TitleWatcher title_watcher2(shell()->web_contents(), kOKTitle2);
1149 title_watcher2.AlsoWaitForTitle(kFailTitle2);
1151 NavigateToURL(shell(), embedded_test_server()->GetURL(kConfirmPageUrl));
1152 EXPECT_EQ(kOKTitle2, title_watcher2.WaitAndGetTitle());
1155 class ServiceWorkerVersionBrowserV8CacheTest
1156 : public ServiceWorkerVersionBrowserTest,
1157 public ServiceWorkerVersion::Listener {
1158 public:
1159 using self = ServiceWorkerVersionBrowserV8CacheTest;
1160 ~ServiceWorkerVersionBrowserV8CacheTest() override {
1161 if (version_)
1162 version_->RemoveListener(this);
1164 void SetUpCommandLine(base::CommandLine* command_line) override {
1165 ServiceWorkerBrowserTest::SetUpCommandLine(command_line);
1166 command_line->AppendSwitchASCII(switches::kV8CacheOptions, "code");
1168 void SetUpRegistrationAndListenerOnIOThread(const std::string& worker_url) {
1169 SetUpRegistrationOnIOThread(worker_url);
1170 version_->AddListener(this);
1173 protected:
1174 // ServiceWorkerVersion::Listener overrides
1175 void OnCachedMetadataUpdated(ServiceWorkerVersion* version) override {
1176 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
1177 cache_updated_closure_);
1180 base::Closure cache_updated_closure_;
1183 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest, Restart) {
1184 RunOnIOThread(base::Bind(&self::SetUpRegistrationAndListenerOnIOThread, this,
1185 "/service_worker/worker.js"));
1187 base::RunLoop cached_metadata_run_loop;
1188 cache_updated_closure_ = cached_metadata_run_loop.QuitClosure();
1190 // Start a worker.
1191 StartWorker(SERVICE_WORKER_OK);
1193 // Wait for the matadata is stored. This run loop should finish when
1194 // OnCachedMetadataUpdated() is called.
1195 cached_metadata_run_loop.Run();
1197 // Activate the worker.
1198 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
1199 base::RunLoop acrivate_run_loop;
1200 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
1201 base::Bind(&self::ActivateOnIOThread, this,
1202 acrivate_run_loop.QuitClosure(), &status));
1203 acrivate_run_loop.Run();
1204 ASSERT_EQ(SERVICE_WORKER_OK, status);
1205 // Stop the worker.
1206 StopWorker(SERVICE_WORKER_OK);
1207 // Restart the worker.
1208 StartWorker(SERVICE_WORKER_OK);
1209 // Stop the worker.
1210 StopWorker(SERVICE_WORKER_OK);
1213 } // namespace content