[Android WebView] Upstream WebViewShell to chromium.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_browsertest.cc
blobd2b0048260ca3156931025c21ef50f74264362cb
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 ConsoleListener : public EmbeddedWorkerInstance::Listener {
431 public:
432 void OnReportConsoleMessage(int source_identifier,
433 int message_level,
434 const base::string16& message,
435 int line_number,
436 const GURL& source_url) override {
437 messages_.push_back(message);
438 if (!quit_.is_null() && messages_.size() == expected_message_count_) {
439 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_);
440 quit_.Reset();
444 void WaitForConsoleMessages(size_t expected_message_count) {
445 if (messages_.size() >= expected_message_count)
446 return;
448 expected_message_count_ = expected_message_count;
449 base::RunLoop console_run_loop;
450 quit_ = console_run_loop.QuitClosure();
451 console_run_loop.Run();
453 ASSERT_EQ(messages_.size(), expected_message_count);
456 bool OnMessageReceived(const IPC::Message& message) override { return false; }
457 const std::vector<base::string16>& messages() const { return messages_; }
459 private:
460 std::vector<base::string16> messages_;
461 size_t expected_message_count_;
462 base::Closure quit_;
465 class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
466 public:
467 using self = ServiceWorkerVersionBrowserTest;
469 ~ServiceWorkerVersionBrowserTest() override {}
471 void TearDownOnIOThread() override {
472 registration_ = NULL;
473 version_ = NULL;
476 void InstallTestHelper(const std::string& worker_url,
477 ServiceWorkerStatusCode expected_status) {
478 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
479 worker_url));
481 // Dispatch install on a worker.
482 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
483 base::RunLoop install_run_loop;
484 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
485 base::Bind(&self::InstallOnIOThread, this,
486 install_run_loop.QuitClosure(),
487 &status));
488 install_run_loop.Run();
489 ASSERT_EQ(expected_status, status);
491 // Stop the worker.
492 status = SERVICE_WORKER_ERROR_FAILED;
493 base::RunLoop stop_run_loop;
494 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
495 base::Bind(&self::StopOnIOThread, this,
496 stop_run_loop.QuitClosure(),
497 &status));
498 stop_run_loop.Run();
499 ASSERT_EQ(SERVICE_WORKER_OK, status);
502 void ActivateTestHelper(
503 const std::string& worker_url,
504 ServiceWorkerStatusCode expected_status) {
505 RunOnIOThread(
506 base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url));
507 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
508 base::RunLoop run_loop;
509 BrowserThread::PostTask(
510 BrowserThread::IO,
511 FROM_HERE,
512 base::Bind(
513 &self::ActivateOnIOThread, this, run_loop.QuitClosure(), &status));
514 run_loop.Run();
515 ASSERT_EQ(expected_status, status);
518 void FetchOnRegisteredWorker(
519 ServiceWorkerFetchEventResult* result,
520 ServiceWorkerResponse* response,
521 scoped_ptr<storage::BlobDataHandle>* blob_data_handle) {
522 blob_context_ = ChromeBlobStorageContext::GetFor(
523 shell()->web_contents()->GetBrowserContext());
524 bool prepare_result = false;
525 FetchResult fetch_result;
526 fetch_result.status = SERVICE_WORKER_ERROR_FAILED;
527 base::RunLoop fetch_run_loop;
528 BrowserThread::PostTask(BrowserThread::IO,
529 FROM_HERE,
530 base::Bind(&self::FetchOnIOThread,
531 this,
532 fetch_run_loop.QuitClosure(),
533 &prepare_result,
534 &fetch_result));
535 fetch_run_loop.Run();
536 ASSERT_TRUE(prepare_result);
537 *result = fetch_result.result;
538 *response = fetch_result.response;
539 *blob_data_handle = fetch_result.blob_data_handle.Pass();
540 ASSERT_EQ(SERVICE_WORKER_OK, fetch_result.status);
543 void FetchTestHelper(const std::string& worker_url,
544 ServiceWorkerFetchEventResult* result,
545 ServiceWorkerResponse* response,
546 scoped_ptr<storage::BlobDataHandle>* blob_data_handle) {
547 RunOnIOThread(
548 base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url));
549 FetchOnRegisteredWorker(result, response, blob_data_handle);
552 void SetUpRegistrationOnIOThread(const std::string& worker_url) {
553 const GURL pattern = embedded_test_server()->GetURL("/service_worker/");
554 registration_ = new ServiceWorkerRegistration(
555 pattern,
556 wrapper()->context()->storage()->NewRegistrationId(),
557 wrapper()->context()->AsWeakPtr());
558 version_ = new ServiceWorkerVersion(
559 registration_.get(),
560 embedded_test_server()->GetURL(worker_url),
561 wrapper()->context()->storage()->NewVersionId(),
562 wrapper()->context()->AsWeakPtr());
564 // Make the registration findable via storage functions.
565 wrapper()->context()->storage()->NotifyInstallingRegistration(
566 registration_.get());
568 AssociateRendererProcessToPattern(pattern);
571 void TimeoutWorkerOnIOThread() {
572 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
573 version_->PingWorker();
574 version_->OnPingTimeout();
577 void StartWorker(ServiceWorkerStatusCode expected_status) {
578 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
579 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
580 base::RunLoop start_run_loop;
581 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
582 base::Bind(&self::StartOnIOThread, this,
583 start_run_loop.QuitClosure(),
584 &status));
585 start_run_loop.Run();
586 ASSERT_EQ(expected_status, status);
589 void StopWorker(ServiceWorkerStatusCode expected_status) {
590 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
591 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
592 base::RunLoop stop_run_loop;
593 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
594 base::Bind(&self::StopOnIOThread, this,
595 stop_run_loop.QuitClosure(),
596 &status));
597 stop_run_loop.Run();
598 ASSERT_EQ(expected_status, status);
601 void StartOnIOThread(const base::Closure& done,
602 ServiceWorkerStatusCode* result) {
603 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
604 version_->StartWorker(CreateReceiver(BrowserThread::UI, done, result));
607 void InstallOnIOThread(const base::Closure& done,
608 ServiceWorkerStatusCode* result) {
609 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
610 version_->SetStatus(ServiceWorkerVersion::INSTALLING);
611 version_->DispatchInstallEvent(
612 CreateReceiver(BrowserThread::UI, done, result));
615 void ActivateOnIOThread(const base::Closure& done,
616 ServiceWorkerStatusCode* result) {
617 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
618 version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
619 version_->DispatchActivateEvent(
620 CreateReceiver(BrowserThread::UI, done, result));
623 void FetchOnIOThread(const base::Closure& done,
624 bool* prepare_result,
625 FetchResult* result) {
626 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
627 ServiceWorkerFetchRequest request(
628 embedded_test_server()->GetURL("/service_worker/empty.html"),
629 "GET",
630 ServiceWorkerHeaderMap(),
631 Referrer(),
632 false);
633 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
634 version_->DispatchFetchEvent(
635 request,
636 CreatePrepareReceiver(prepare_result),
637 CreateResponseReceiver(
638 BrowserThread::UI, done, blob_context_.get(), result));
641 void StopOnIOThread(const base::Closure& done,
642 ServiceWorkerStatusCode* result) {
643 ASSERT_TRUE(version_.get());
644 version_->StopWorker(CreateReceiver(BrowserThread::UI, done, result));
647 void SyncEventOnIOThread(const base::Closure& done,
648 ServiceWorkerStatusCode* result) {
649 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
650 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
651 version_->DispatchSyncEvent(
652 CreateReceiver(BrowserThread::UI, done, result));
655 protected:
656 scoped_refptr<ServiceWorkerRegistration> registration_;
657 scoped_refptr<ServiceWorkerVersion> version_;
658 scoped_refptr<ChromeBlobStorageContext> blob_context_;
661 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest, StartAndStop) {
662 // Start a worker and wait until OnStarted() is called.
663 base::RunLoop start_run_loop;
664 done_closure_ = start_run_loop.QuitClosure();
665 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
666 base::Bind(&self::StartOnIOThread, this));
667 start_run_loop.Run();
669 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING, last_worker_status_);
671 // Stop a worker and wait until OnStopped() is called.
672 base::RunLoop stop_run_loop;
673 done_closure_ = stop_run_loop.QuitClosure();
674 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
675 base::Bind(&self::StopOnIOThread, this));
676 stop_run_loop.Run();
678 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED, last_worker_status_);
681 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest, StartPaused_ThenResume) {
682 pause_mode_ = PAUSE_THEN_RESUME;
683 base::RunLoop start_run_loop;
684 done_closure_ = start_run_loop.QuitClosure();
685 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
686 base::Bind(&self::StartOnIOThread, this));
687 start_run_loop.Run();
688 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING, last_worker_status_);
691 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest,
692 StartPaused_ThenStop) {
693 pause_mode_ = PAUSE_THEN_STOP;
694 base::RunLoop start_run_loop;
695 done_closure_ = start_run_loop.QuitClosure();
696 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
697 base::Bind(&self::StartOnIOThread, this));
698 start_run_loop.Run();
699 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED, last_worker_status_);
702 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
703 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
704 "/service_worker/worker.js"));
706 // Start a worker.
707 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
708 base::RunLoop start_run_loop;
709 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
710 base::Bind(&self::StartOnIOThread, this,
711 start_run_loop.QuitClosure(),
712 &status));
713 start_run_loop.Run();
714 ASSERT_EQ(SERVICE_WORKER_OK, status);
716 // Stop the worker.
717 status = SERVICE_WORKER_ERROR_FAILED;
718 base::RunLoop stop_run_loop;
719 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
720 base::Bind(&self::StopOnIOThread, this,
721 stop_run_loop.QuitClosure(),
722 &status));
723 stop_run_loop.Run();
724 ASSERT_EQ(SERVICE_WORKER_OK, status);
727 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) {
728 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
729 "/service_worker/nonexistent.js"));
731 // Start a worker for nonexistent URL.
732 StartWorker(SERVICE_WORKER_ERROR_NETWORK);
735 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) {
736 InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
739 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
740 InstallWithWaitUntil_Fulfilled) {
741 InstallTestHelper("/service_worker/worker_install_fulfilled.js",
742 SERVICE_WORKER_OK);
745 // Check that ServiceWorker script requests set a "Service-Worker: script"
746 // header.
747 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
748 ServiceWorkerScriptHeader) {
749 embedded_test_server()->RegisterRequestHandler(
750 base::Bind(&VerifyServiceWorkerHeaderInRequest));
751 InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK);
754 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
755 Activate_NoEventListener) {
756 ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
757 ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
760 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
761 ActivateTestHelper("/service_worker/worker_activate_rejected.js",
762 SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED);
765 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
766 InstallWithWaitUntil_Rejected) {
767 InstallTestHelper("/service_worker/worker_install_rejected.js",
768 SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED);
771 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
772 InstallWithWaitUntil_RejectConsoleMessage) {
773 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
774 "/service_worker/worker_install_rejected.js"));
776 ConsoleListener console_listener;
777 version_->embedded_worker()->AddListener(&console_listener);
779 // Dispatch install on a worker.
780 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
781 base::RunLoop install_run_loop;
782 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
783 base::Bind(&self::InstallOnIOThread, this,
784 install_run_loop.QuitClosure(), &status));
785 install_run_loop.Run();
786 ASSERT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED, status);
788 const base::string16 expected =
789 base::ASCIIToUTF16("Rejecting oninstall event");
790 console_listener.WaitForConsoleMessages(1);
791 ASSERT_NE(base::string16::npos,
792 console_listener.messages()[0].find(expected));
793 version_->embedded_worker()->RemoveListener(&console_listener);
796 class WaitForLoaded : public EmbeddedWorkerInstance::Listener {
797 public:
798 WaitForLoaded(const base::Closure& quit) : quit_(quit) {}
800 void OnScriptLoaded() override {
801 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_);
803 bool OnMessageReceived(const IPC::Message& message) override { return false; }
805 private:
806 base::Closure quit_;
809 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
810 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
811 "/service_worker/while_true_worker.js"));
813 // Start a worker, waiting until the script is loaded.
814 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
815 base::RunLoop start_run_loop;
816 base::RunLoop load_run_loop;
817 WaitForLoaded wait_for_load(load_run_loop.QuitClosure());
818 version_->embedded_worker()->AddListener(&wait_for_load);
819 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
820 base::Bind(&self::StartOnIOThread, this,
821 start_run_loop.QuitClosure(), &status));
822 load_run_loop.Run();
823 version_->embedded_worker()->RemoveListener(&wait_for_load);
825 // The script has loaded but start has not completed yet.
826 ASSERT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
827 EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
829 // Simulate execution timeout. Use a delay to prevent killing the worker
830 // before it's started execution.
831 EXPECT_TRUE(version_->timeout_timer_.IsRunning());
832 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread, this),
833 base::TimeDelta::FromMilliseconds(100));
834 start_run_loop.Run();
836 EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
839 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
840 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
841 "/service_worker/while_true_in_install_worker.js"));
843 // Start a worker.
844 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
845 base::RunLoop start_run_loop;
846 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
847 base::Bind(&self::StartOnIOThread, this,
848 start_run_loop.QuitClosure(), &status));
849 start_run_loop.Run();
850 ASSERT_EQ(SERVICE_WORKER_OK, status);
852 // Dispatch an event.
853 base::RunLoop install_run_loop;
854 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
855 base::Bind(&self::InstallOnIOThread, this,
856 install_run_loop.QuitClosure(), &status));
858 // Simulate execution timeout. Use a delay to prevent killing the worker
859 // before it's started execution.
860 EXPECT_TRUE(version_->timeout_timer_.IsRunning());
861 RunOnIOThreadWithDelay(base::Bind(&self::TimeoutWorkerOnIOThread, this),
862 base::TimeDelta::FromMilliseconds(100));
863 install_run_loop.Run();
865 EXPECT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED, status);
868 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
869 ServiceWorkerFetchEventResult result;
870 ServiceWorkerResponse response;
871 scoped_ptr<storage::BlobDataHandle> blob_data_handle;
872 FetchTestHelper("/service_worker/fetch_event.js",
873 &result, &response, &blob_data_handle);
874 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, result);
875 EXPECT_EQ(301, response.status_code);
876 EXPECT_EQ("Moved Permanently", response.status_text);
877 ServiceWorkerHeaderMap expected_headers;
878 expected_headers["content-language"] = "fi";
879 expected_headers["content-type"] = "text/html; charset=UTF-8";
880 EXPECT_EQ(expected_headers, response.headers);
882 std::string body;
883 RunOnIOThread(
884 base::Bind(&ReadResponseBody,
885 &body, base::Owned(blob_data_handle.release())));
886 EXPECT_EQ("This resource is gone. Gone, gone, gone.", body);
889 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
890 FetchEvent_respondWithRejection) {
891 ServiceWorkerFetchEventResult result;
892 ServiceWorkerResponse response;
893 scoped_ptr<storage::BlobDataHandle> blob_data_handle;
895 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
896 "/service_worker/fetch_event_rejected.js"));
898 ConsoleListener console_listener;
899 version_->embedded_worker()->AddListener(&console_listener);
901 FetchOnRegisteredWorker(&result, &response, &blob_data_handle);
902 const base::string16 expected =
903 base::ASCIIToUTF16("Rejecting respondWith promise");
904 console_listener.WaitForConsoleMessages(1);
905 ASSERT_NE(base::string16::npos,
906 console_listener.messages()[0].find(expected));
907 version_->embedded_worker()->RemoveListener(&console_listener);
909 ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, result);
910 EXPECT_EQ(0, response.status_code);
912 ASSERT_FALSE(blob_data_handle);
915 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
916 SyncAbortedWithoutFlag) {
917 RunOnIOThread(base::Bind(
918 &self::SetUpRegistrationOnIOThread, this, "/service_worker/sync.js"));
920 // Run the sync event.
921 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
922 base::RunLoop sync_run_loop;
923 BrowserThread::PostTask(BrowserThread::IO,
924 FROM_HERE,
925 base::Bind(&self::SyncEventOnIOThread,
926 this,
927 sync_run_loop.QuitClosure(),
928 &status));
929 sync_run_loop.Run();
930 ASSERT_EQ(SERVICE_WORKER_ERROR_ABORT, status);
933 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, SyncEventHandled) {
934 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
935 command_line->AppendSwitch(switches::kEnableServiceWorkerSync);
937 RunOnIOThread(base::Bind(
938 &self::SetUpRegistrationOnIOThread, this, "/service_worker/sync.js"));
939 ServiceWorkerFetchEventResult result;
940 ServiceWorkerResponse response;
941 scoped_ptr<storage::BlobDataHandle> blob_data_handle;
942 // Should 404 before sync event.
943 FetchOnRegisteredWorker(&result, &response, &blob_data_handle);
944 EXPECT_EQ(404, response.status_code);
946 // Run the sync event.
947 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
948 base::RunLoop sync_run_loop;
949 BrowserThread::PostTask(BrowserThread::IO,
950 FROM_HERE,
951 base::Bind(&self::SyncEventOnIOThread,
952 this,
953 sync_run_loop.QuitClosure(),
954 &status));
955 sync_run_loop.Run();
956 ASSERT_EQ(SERVICE_WORKER_OK, status);
958 // Should 200 after sync event.
959 FetchOnRegisteredWorker(&result, &response, &blob_data_handle);
960 EXPECT_EQ(200, response.status_code);
963 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, Reload) {
964 const char kPageUrl[] = "/service_worker/reload.html";
965 const char kWorkerUrl[] = "/service_worker/fetch_event_reload.js";
966 scoped_refptr<WorkerActivatedObserver> observer =
967 new WorkerActivatedObserver(wrapper());
968 observer->Init();
969 public_context()->RegisterServiceWorker(
970 embedded_test_server()->GetURL(kPageUrl),
971 embedded_test_server()->GetURL(kWorkerUrl),
972 base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
973 observer->Wait();
975 const base::string16 title1 = base::ASCIIToUTF16("reload=false");
976 TitleWatcher title_watcher1(shell()->web_contents(), title1);
977 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl));
978 EXPECT_EQ(title1, title_watcher1.WaitAndGetTitle());
980 const base::string16 title2 = base::ASCIIToUTF16("reload=true");
981 TitleWatcher title_watcher2(shell()->web_contents(), title2);
982 ReloadBlockUntilNavigationsComplete(shell(), 1);
983 EXPECT_EQ(title2, title_watcher2.WaitAndGetTitle());
985 shell()->Close();
987 base::RunLoop run_loop;
988 public_context()->UnregisterServiceWorker(
989 embedded_test_server()->GetURL(kPageUrl),
990 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
991 run_loop.Run();
994 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
995 ResponseFromHTTPSServiceWorkerIsMarkedAsSecure) {
996 const char kPageUrl[] = "files/service_worker/fetch_event_blob.html";
997 const char kWorkerUrl[] = "files/service_worker/fetch_event_blob.js";
998 net::SpawnedTestServer https_server(
999 net::SpawnedTestServer::TYPE_HTTPS,
1000 net::BaseTestServer::SSLOptions(
1001 net::BaseTestServer::SSLOptions::CERT_OK),
1002 base::FilePath(FILE_PATH_LITERAL("content/test/data/")));
1003 ASSERT_TRUE(https_server.Start());
1005 scoped_refptr<WorkerActivatedObserver> observer =
1006 new WorkerActivatedObserver(wrapper());
1007 observer->Init();
1008 public_context()->RegisterServiceWorker(
1009 https_server.GetURL(kPageUrl),
1010 https_server.GetURL(kWorkerUrl),
1011 base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
1012 observer->Wait();
1014 const base::string16 title = base::ASCIIToUTF16("Title");
1015 TitleWatcher title_watcher(shell()->web_contents(), title);
1016 NavigateToURL(shell(), https_server.GetURL(kPageUrl));
1017 EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
1018 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
1019 NavigationEntry* entry =
1020 shell()->web_contents()->GetController().GetVisibleEntry();
1021 EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, entry->GetSSL().security_style);
1023 shell()->Close();
1025 base::RunLoop run_loop;
1026 public_context()->UnregisterServiceWorker(
1027 https_server.GetURL(kPageUrl),
1028 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
1029 run_loop.Run();
1032 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
1033 ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure) {
1034 const char kPageUrl[] = "/service_worker/fetch_event_blob.html";
1035 const char kWorkerUrl[] = "/service_worker/fetch_event_blob.js";
1036 scoped_refptr<WorkerActivatedObserver> observer =
1037 new WorkerActivatedObserver(wrapper());
1038 observer->Init();
1039 public_context()->RegisterServiceWorker(
1040 embedded_test_server()->GetURL(kPageUrl),
1041 embedded_test_server()->GetURL(kWorkerUrl),
1042 base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
1043 observer->Wait();
1045 const base::string16 title = base::ASCIIToUTF16("Title");
1046 TitleWatcher title_watcher(shell()->web_contents(), title);
1047 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl));
1048 EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
1049 EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
1050 NavigationEntry* entry =
1051 shell()->web_contents()->GetController().GetVisibleEntry();
1052 EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, entry->GetSSL().security_style);
1054 shell()->Close();
1056 base::RunLoop run_loop;
1057 public_context()->UnregisterServiceWorker(
1058 embedded_test_server()->GetURL(kPageUrl),
1059 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
1060 run_loop.Run();
1063 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ImportsBustMemcache) {
1064 const char kScopeUrl[] = "/service_worker/imports_bust_memcache_scope/";
1065 const char kPageUrl[] = "/service_worker/imports_bust_memcache.html";
1066 const char kScriptUrl[] = "/service_worker/worker_with_one_import.js";
1067 const char kImportUrl[] = "/service_worker/long_lived_import.js";
1068 const base::string16 kOKTitle(base::ASCIIToUTF16("OK"));
1069 const base::string16 kFailTitle(base::ASCIIToUTF16("FAIL"));
1071 RunOnIOThread(
1072 base::Bind(&CreateLongLivedResourceInterceptors,
1073 embedded_test_server()->GetURL(kScriptUrl),
1074 embedded_test_server()->GetURL(kImportUrl)));
1076 TitleWatcher title_watcher(shell()->web_contents(), kOKTitle);
1077 title_watcher.AlsoWaitForTitle(kFailTitle);
1078 NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl));
1079 base::string16 title = title_watcher.WaitAndGetTitle();
1080 EXPECT_EQ(kOKTitle, title);
1082 // Verify the number of resources in the implicit script cache is correct.
1083 const int kExpectedNumResources = 2;
1084 int num_resources = 0;
1085 RunOnIOThread(
1086 base::Bind(&CountScriptResources,
1087 base::Unretained(wrapper()),
1088 embedded_test_server()->GetURL(kScopeUrl),
1089 &num_resources));
1090 EXPECT_EQ(kExpectedNumResources, num_resources);
1093 class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest {
1094 public:
1095 using self = ServiceWorkerBlackBoxBrowserTest;
1097 void FindRegistrationOnIO(const GURL& document_url,
1098 ServiceWorkerStatusCode* status,
1099 const base::Closure& continuation) {
1100 wrapper()->context()->storage()->FindRegistrationForDocument(
1101 document_url,
1102 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO2,
1103 this,
1104 status,
1105 continuation));
1108 void FindRegistrationOnIO2(
1109 ServiceWorkerStatusCode* out_status,
1110 const base::Closure& continuation,
1111 ServiceWorkerStatusCode status,
1112 const scoped_refptr<ServiceWorkerRegistration>& registration) {
1113 *out_status = status;
1114 if (!registration.get())
1115 EXPECT_NE(SERVICE_WORKER_OK, status);
1116 continuation.Run();
1120 static int CountRenderProcessHosts() {
1121 int result = 0;
1122 for (RenderProcessHost::iterator iter(RenderProcessHost::AllHostsIterator());
1123 !iter.IsAtEnd();
1124 iter.Advance()) {
1125 result++;
1127 return result;
1130 // Flaky timeouts on CrOS and crash on Android: http://crbug.com/387045
1131 #if defined(OS_CHROMEOS) || defined(ANDROID)
1132 #define MAYBE_Registration DISABLED_Registration
1133 #else
1134 #define MAYBE_Registration Registration
1135 #endif
1136 IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, MAYBE_Registration) {
1137 // Close the only window to be sure we're not re-using its RenderProcessHost.
1138 shell()->Close();
1139 EXPECT_EQ(0, CountRenderProcessHosts());
1141 const char kWorkerUrl[] = "/service_worker/fetch_event.js";
1142 const char kScope[] = "/service_worker/";
1144 // Unregistering nothing should return false.
1146 base::RunLoop run_loop;
1147 public_context()->UnregisterServiceWorker(
1148 embedded_test_server()->GetURL("/"),
1149 base::Bind(&ExpectResultAndRun, false, run_loop.QuitClosure()));
1150 run_loop.Run();
1153 // If we use a worker URL that doesn't exist, registration fails.
1155 base::RunLoop run_loop;
1156 public_context()->RegisterServiceWorker(
1157 embedded_test_server()->GetURL(kScope),
1158 embedded_test_server()->GetURL("/does/not/exist"),
1159 base::Bind(&ExpectResultAndRun, false, run_loop.QuitClosure()));
1160 run_loop.Run();
1162 EXPECT_EQ(0, CountRenderProcessHosts());
1164 // Register returns when the promise would be resolved.
1166 base::RunLoop run_loop;
1167 public_context()->RegisterServiceWorker(
1168 embedded_test_server()->GetURL(kScope),
1169 embedded_test_server()->GetURL(kWorkerUrl),
1170 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
1171 run_loop.Run();
1173 EXPECT_EQ(1, CountRenderProcessHosts());
1175 // Registering again should succeed, although the algo still
1176 // might not be complete.
1178 base::RunLoop run_loop;
1179 public_context()->RegisterServiceWorker(
1180 embedded_test_server()->GetURL(kScope),
1181 embedded_test_server()->GetURL(kWorkerUrl),
1182 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
1183 run_loop.Run();
1186 // The registration algo might not be far enough along to have
1187 // stored the registration data, so it may not be findable
1188 // at this point.
1190 // Unregistering something should return true.
1192 base::RunLoop run_loop;
1193 public_context()->UnregisterServiceWorker(
1194 embedded_test_server()->GetURL(kScope),
1195 base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
1196 run_loop.Run();
1198 EXPECT_GE(1, CountRenderProcessHosts()) << "Unregistering doesn't stop the "
1199 "workers eagerly, so their RPHs "
1200 "can still be running.";
1202 // Should not be able to find it.
1204 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
1205 RunOnIOThread(
1206 base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO,
1207 this,
1208 embedded_test_server()->GetURL("/service_worker/empty.html"),
1209 &status));
1210 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, status);
1214 IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, CrossSiteTransfer) {
1215 // The first page registers a service worker.
1216 const char kRegisterPageUrl[] = "/service_worker/cross_site_xfer.html";
1217 const base::string16 kOKTitle1(base::ASCIIToUTF16("OK_1"));
1218 const base::string16 kFailTitle1(base::ASCIIToUTF16("FAIL_1"));
1219 content::TitleWatcher title_watcher1(shell()->web_contents(), kOKTitle1);
1220 title_watcher1.AlsoWaitForTitle(kFailTitle1);
1222 NavigateToURL(shell(), embedded_test_server()->GetURL(kRegisterPageUrl));
1223 ASSERT_EQ(kOKTitle1, title_watcher1.WaitAndGetTitle());
1225 // Force process swapping behavior.
1226 ShellContentBrowserClient::SetSwapProcessesForRedirect(true);
1228 // The second pages loads via the serviceworker including a subresource.
1229 const char kConfirmPageUrl[] =
1230 "/service_worker/cross_site_xfer_scope/"
1231 "cross_site_xfer_confirm_via_serviceworker.html";
1232 const base::string16 kOKTitle2(base::ASCIIToUTF16("OK_2"));
1233 const base::string16 kFailTitle2(base::ASCIIToUTF16("FAIL_2"));
1234 content::TitleWatcher title_watcher2(shell()->web_contents(), kOKTitle2);
1235 title_watcher2.AlsoWaitForTitle(kFailTitle2);
1237 NavigateToURL(shell(), embedded_test_server()->GetURL(kConfirmPageUrl));
1238 EXPECT_EQ(kOKTitle2, title_watcher2.WaitAndGetTitle());
1241 class ServiceWorkerVersionBrowserV8CacheTest
1242 : public ServiceWorkerVersionBrowserTest,
1243 public ServiceWorkerVersion::Listener {
1244 public:
1245 using self = ServiceWorkerVersionBrowserV8CacheTest;
1246 ~ServiceWorkerVersionBrowserV8CacheTest() override {
1247 if (version_)
1248 version_->RemoveListener(this);
1250 void SetUpCommandLine(base::CommandLine* command_line) override {
1251 ServiceWorkerBrowserTest::SetUpCommandLine(command_line);
1252 command_line->AppendSwitchASCII(switches::kV8CacheOptions, "code");
1254 void SetUpRegistrationAndListenerOnIOThread(const std::string& worker_url) {
1255 SetUpRegistrationOnIOThread(worker_url);
1256 version_->AddListener(this);
1259 protected:
1260 // ServiceWorkerVersion::Listener overrides
1261 void OnCachedMetadataUpdated(ServiceWorkerVersion* version) override {
1262 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
1263 cache_updated_closure_);
1266 base::Closure cache_updated_closure_;
1269 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest, Restart) {
1270 RunOnIOThread(base::Bind(&self::SetUpRegistrationAndListenerOnIOThread, this,
1271 "/service_worker/worker.js"));
1273 base::RunLoop cached_metadata_run_loop;
1274 cache_updated_closure_ = cached_metadata_run_loop.QuitClosure();
1276 // Start a worker.
1277 StartWorker(SERVICE_WORKER_OK);
1279 // Wait for the matadata is stored. This run loop should finish when
1280 // OnCachedMetadataUpdated() is called.
1281 cached_metadata_run_loop.Run();
1283 // Activate the worker.
1284 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
1285 base::RunLoop acrivate_run_loop;
1286 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
1287 base::Bind(&self::ActivateOnIOThread, this,
1288 acrivate_run_loop.QuitClosure(), &status));
1289 acrivate_run_loop.Run();
1290 ASSERT_EQ(SERVICE_WORKER_OK, status);
1291 // Stop the worker.
1292 StopWorker(SERVICE_WORKER_OK);
1293 // Restart the worker.
1294 StartWorker(SERVICE_WORKER_OK);
1295 // Stop the worker.
1296 StopWorker(SERVICE_WORKER_OK);
1299 } // namespace content