1 // Copyright 2013 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.
4
5 #include "content/public/browser/service_worker_context.h"
6
7 #include <stdint.h>
8
9 #include "base/bind.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/logging.h"
12 #include "base/run_loop.h"
13 #include "base/scoped_observer.h"
14 #include "base/time/time.h"
15 #include "content/browser/service_worker/embedded_worker_test_helper.h"
16 #include "content/browser/service_worker/fake_embedded_worker_instance_client.h"
17 #include "content/browser/service_worker/service_worker_container_host.h"
18 #include "content/browser/service_worker/service_worker_context_core.h"
19 #include "content/browser/service_worker/service_worker_context_core_observer.h"
20 #include "content/browser/service_worker/service_worker_context_wrapper.h"
21 #include "content/browser/service_worker/service_worker_metrics.h"
22 #include "content/browser/service_worker/service_worker_provider_host.h"
23 #include "content/browser/service_worker/service_worker_registration.h"
24 #include "content/browser/service_worker/service_worker_storage.h"
25 #include "content/browser/service_worker/service_worker_test_utils.h"
26 #include "content/browser/service_worker/service_worker_version.h"
27 #include "content/public/browser/service_worker_context_observer.h"
28 #include "content/public/test/browser_task_environment.h"
29 #include "content/public/test/test_utils.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "third_party/blink/public/common/service_worker/service_worker_types.h"
32 #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
33 #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
34
35 namespace content {
36
37 namespace {
38
SaveResponseCallback(bool * called,int64_t * store_registration_id,blink::ServiceWorkerStatusCode status,const std::string & status_message,int64_t registration_id)39 void SaveResponseCallback(bool* called,
40 int64_t* store_registration_id,
41 blink::ServiceWorkerStatusCode status,
42 const std::string& status_message,
43 int64_t registration_id) {
44 EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status)
45 << blink::ServiceWorkerStatusToString(status);
46 *called = true;
47 *store_registration_id = registration_id;
48 }
49
MakeRegisteredCallback(bool * called,int64_t * store_registration_id)50 ServiceWorkerContextCore::RegistrationCallback MakeRegisteredCallback(
51 bool* called,
52 int64_t* store_registration_id) {
53 return base::BindOnce(&SaveResponseCallback, called, store_registration_id);
54 }
55
RegisteredCallback(base::OnceClosure quit_closure,blink::ServiceWorkerStatusCode status,const std::string & status_message,int64_t registration_id)56 void RegisteredCallback(base::OnceClosure quit_closure,
57 blink::ServiceWorkerStatusCode status,
58 const std::string& status_message,
59 int64_t registration_id) {
60 std::move(quit_closure).Run();
61 }
62
CallCompletedCallback(bool * called,blink::ServiceWorkerStatusCode)63 void CallCompletedCallback(bool* called, blink::ServiceWorkerStatusCode) {
64 *called = true;
65 }
66
MakeUnregisteredCallback(bool * called)67 ServiceWorkerContextCore::UnregistrationCallback MakeUnregisteredCallback(
68 bool* called) {
69 return base::BindOnce(&CallCompletedCallback, called);
70 }
71
ExpectRegisteredWorkers(blink::ServiceWorkerStatusCode expect_status,bool expect_waiting,bool expect_active,blink::ServiceWorkerStatusCode status,scoped_refptr<ServiceWorkerRegistration> registration)72 void ExpectRegisteredWorkers(
73 blink::ServiceWorkerStatusCode expect_status,
74 bool expect_waiting,
75 bool expect_active,
76 blink::ServiceWorkerStatusCode status,
77 scoped_refptr<ServiceWorkerRegistration> registration) {
78 ASSERT_EQ(expect_status, status);
79 if (status != blink::ServiceWorkerStatusCode::kOk) {
80 EXPECT_FALSE(registration.get());
81 return;
82 }
83
84 if (expect_waiting) {
85 EXPECT_TRUE(registration->waiting_version());
86 } else {
87 EXPECT_FALSE(registration->waiting_version());
88 }
89
90 if (expect_active) {
91 EXPECT_TRUE(registration->active_version());
92 } else {
93 EXPECT_FALSE(registration->active_version());
94 }
95
96 EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kImports,
97 registration->update_via_cache());
98 }
99
100 class InstallActivateWorker : public FakeServiceWorker {
101 public:
InstallActivateWorker(EmbeddedWorkerTestHelper * helper)102 explicit InstallActivateWorker(EmbeddedWorkerTestHelper* helper)
103 : FakeServiceWorker(helper) {}
104 ~InstallActivateWorker() override = default;
105
events() const106 const std::vector<ServiceWorkerMetrics::EventType>& events() const {
107 return events_;
108 }
109
SetToRejectInstall()110 void SetToRejectInstall() { reject_install_ = true; }
111
SetToRejectActivate()112 void SetToRejectActivate() { reject_activate_ = true; }
113
DispatchInstallEvent(blink::mojom::ServiceWorker::DispatchInstallEventCallback callback)114 void DispatchInstallEvent(
115 blink::mojom::ServiceWorker::DispatchInstallEventCallback callback)
116 override {
117 events_.emplace_back(ServiceWorkerMetrics::EventType::INSTALL);
118 std::move(callback).Run(
119 reject_install_ ? blink::mojom::ServiceWorkerEventStatus::REJECTED
120 : blink::mojom::ServiceWorkerEventStatus::COMPLETED);
121 }
122
DispatchActivateEvent(blink::mojom::ServiceWorker::DispatchActivateEventCallback callback)123 void DispatchActivateEvent(
124 blink::mojom::ServiceWorker::DispatchActivateEventCallback callback)
125 override {
126 events_.emplace_back(ServiceWorkerMetrics::EventType::ACTIVATE);
127 std::move(callback).Run(
128 reject_activate_ ? blink::mojom::ServiceWorkerEventStatus::REJECTED
129 : blink::mojom::ServiceWorkerEventStatus::COMPLETED);
130 }
131
OnConnectionError()132 void OnConnectionError() override {
133 // Do nothing. This allows the object to stay until the test is over, so
134 // |events_| can be accessed even after the worker is stopped in the case of
135 // rejected install.
136 }
137
138 private:
139 std::vector<ServiceWorkerMetrics::EventType> events_;
140 bool reject_install_ = false;
141 bool reject_activate_ = false;
142 };
143
144 enum NotificationType {
145 REGISTRATION_COMPLETED,
146 REGISTRATION_STORED,
147 REGISTRATION_DELETED,
148 STORAGE_RECOVERED,
149 };
150
151 struct NotificationLog {
152 NotificationType type;
153 GURL scope;
154 int64_t registration_id;
155 };
156
157 } // namespace
158
159 class ServiceWorkerContextTest : public ServiceWorkerContextCoreObserver,
160 public testing::Test {
161 public:
ServiceWorkerContextTest()162 ServiceWorkerContextTest()
163 : task_environment_(BrowserTaskEnvironment::IO_MAINLOOP) {}
164
SetUp()165 void SetUp() override {
166 helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
167 helper_->context_wrapper()->AddObserver(this);
168 }
169
TearDown()170 void TearDown() override {
171 helper_.reset();
172 // The helper may post tasks to release resources in |temp_dir_|. Allow
173 // them to run now so that the directory may be deleted.
174 task_environment_.RunUntilIdle();
175 EXPECT_TRUE(!temp_dir_.IsValid() || temp_dir_.Delete())
176 << temp_dir_.GetPath();
177 }
178
179 // ServiceWorkerContextCoreObserver overrides.
OnRegistrationCompleted(int64_t registration_id,const GURL & scope)180 void OnRegistrationCompleted(int64_t registration_id,
181 const GURL& scope) override {
182 NotificationLog log;
183 log.type = REGISTRATION_COMPLETED;
184 log.scope = scope;
185 log.registration_id = registration_id;
186 notifications_.push_back(log);
187 }
OnRegistrationStored(int64_t registration_id,const GURL & scope)188 void OnRegistrationStored(int64_t registration_id,
189 const GURL& scope) override {
190 NotificationLog log;
191 log.type = REGISTRATION_STORED;
192 log.scope = scope;
193 log.registration_id = registration_id;
194 notifications_.push_back(log);
195 }
OnRegistrationDeleted(int64_t registration_id,const GURL & scope)196 void OnRegistrationDeleted(int64_t registration_id,
197 const GURL& scope) override {
198 NotificationLog log;
199 log.type = REGISTRATION_DELETED;
200 log.scope = scope;
201 log.registration_id = registration_id;
202 notifications_.push_back(log);
203 }
OnStorageWiped()204 void OnStorageWiped() override {
205 NotificationLog log;
206 log.type = STORAGE_RECOVERED;
207 notifications_.push_back(log);
208 }
209
context()210 ServiceWorkerContextCore* context() { return helper_->context(); }
context_wrapper()211 ServiceWorkerContextWrapper* context_wrapper() {
212 return helper_->context_wrapper();
213 }
GetTemporaryDirectory(base::FilePath * temp_dir)214 void GetTemporaryDirectory(base::FilePath* temp_dir) {
215 ASSERT_FALSE(temp_dir_.IsValid());
216 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
217 *temp_dir = temp_dir_.GetPath();
218 }
219
220 protected:
221 base::ScopedTempDir temp_dir_;
222 BrowserTaskEnvironment task_environment_;
223 std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
224 std::vector<NotificationLog> notifications_;
225 };
226
227 class RecordableEmbeddedWorkerInstanceClient
228 : public FakeEmbeddedWorkerInstanceClient {
229 public:
230 enum class Message { StartWorker, StopWorker };
231
RecordableEmbeddedWorkerInstanceClient(EmbeddedWorkerTestHelper * helper)232 explicit RecordableEmbeddedWorkerInstanceClient(
233 EmbeddedWorkerTestHelper* helper)
234 : FakeEmbeddedWorkerInstanceClient(helper) {}
235
OnConnectionError()236 void OnConnectionError() override {
237 // Do nothing. This allows the object to stay until the test is over, so
238 // |events_| can be accessed even after the worker is stopped in the case of
239 // rejected install.
240 }
241
events() const242 const std::vector<Message>& events() const { return events_; }
243
244 protected:
StartWorker(blink::mojom::EmbeddedWorkerStartParamsPtr params)245 void StartWorker(blink::mojom::EmbeddedWorkerStartParamsPtr params) override {
246 events_.push_back(Message::StartWorker);
247 FakeEmbeddedWorkerInstanceClient::StartWorker(std::move(params));
248 }
249
StopWorker()250 void StopWorker() override {
251 events_.push_back(Message::StopWorker);
252
253 // Let stop complete, but don't call the base class's StopWorker(), which
254 // would destroy |this| before the test can retrieve events().
255 host()->OnStopped();
256 }
257
258 private:
259 std::vector<Message> events_;
260 DISALLOW_COPY_AND_ASSIGN(RecordableEmbeddedWorkerInstanceClient);
261 };
262
263 class TestServiceWorkerContextObserver : public ServiceWorkerContextObserver {
264 public:
265 enum class EventType {
266 RegistrationCompleted,
267 RegistrationStored,
268 VersionActivated,
269 VersionRedundant,
270 NoControllees,
271 VersionStartedRunning,
272 VersionStoppedRunning,
273 Destruct
274 };
275 struct EventLog {
276 EventType type;
277 base::Optional<GURL> url;
278 base::Optional<int64_t> version_id;
279 base::Optional<int64_t> registration_id;
280 base::Optional<bool> is_running;
281 };
282
TestServiceWorkerContextObserver(ServiceWorkerContext * context)283 explicit TestServiceWorkerContextObserver(ServiceWorkerContext* context)
284 : scoped_observer_(this) {
285 scoped_observer_.Add(context);
286 }
287
288 ~TestServiceWorkerContextObserver() override = default;
289
OnRegistrationCompleted(const GURL & scope)290 void OnRegistrationCompleted(const GURL& scope) override {
291 EventLog log;
292 log.type = EventType::RegistrationCompleted;
293 log.url = scope;
294 events_.push_back(log);
295 }
296
OnRegistrationStored(int64_t registration_id,const GURL & scope)297 void OnRegistrationStored(int64_t registration_id,
298 const GURL& scope) override {
299 EventLog log;
300 log.type = EventType::RegistrationStored;
301 log.registration_id = registration_id;
302 log.url = scope;
303 events_.push_back(log);
304 }
305
OnVersionActivated(int64_t version_id,const GURL & scope)306 void OnVersionActivated(int64_t version_id, const GURL& scope) override {
307 EventLog log;
308 log.type = EventType::VersionActivated;
309 log.version_id = version_id;
310 log.url = scope;
311 events_.push_back(log);
312 }
313
OnVersionRedundant(int64_t version_id,const GURL & scope)314 void OnVersionRedundant(int64_t version_id, const GURL& scope) override {
315 EventLog log;
316 log.type = EventType::VersionRedundant;
317 log.version_id = version_id;
318 log.url = scope;
319 events_.push_back(log);
320 }
321
OnNoControllees(int64_t version_id,const GURL & scope)322 void OnNoControllees(int64_t version_id, const GURL& scope) override {
323 EventLog log;
324 log.type = EventType::NoControllees;
325 log.version_id = version_id;
326 log.url = scope;
327 events_.push_back(log);
328 }
329
OnVersionStartedRunning(int64_t version_id,const ServiceWorkerRunningInfo & running_info)330 void OnVersionStartedRunning(
331 int64_t version_id,
332 const ServiceWorkerRunningInfo& running_info) override {
333 EventLog log;
334 log.type = EventType::VersionStartedRunning;
335 log.version_id = version_id;
336 events_.push_back(log);
337 }
338
OnVersionStoppedRunning(int64_t version_id)339 void OnVersionStoppedRunning(int64_t version_id) override {
340 EventLog log;
341 log.type = EventType::VersionStoppedRunning;
342 log.version_id = version_id;
343 events_.push_back(log);
344 }
345
OnDestruct(content::ServiceWorkerContext * context)346 void OnDestruct(content::ServiceWorkerContext* context) override {
347 scoped_observer_.Remove(context);
348
349 EventLog log;
350 log.type = EventType::Destruct;
351 events_.push_back(log);
352 }
353
events()354 const std::vector<EventLog>& events() { return events_; }
355
356 private:
357 ScopedObserver<ServiceWorkerContext, ServiceWorkerContextObserver>
358 scoped_observer_;
359 std::vector<EventLog> events_;
360 DISALLOW_COPY_AND_ASSIGN(TestServiceWorkerContextObserver);
361 };
362
363 // Make sure OnRegistrationCompleted is called on observer.
TEST_F(ServiceWorkerContextTest,RegistrationCompletedObserver)364 TEST_F(ServiceWorkerContextTest, RegistrationCompletedObserver) {
365 GURL scope("https://www.example.com/");
366 GURL script_url("https://www.example.com/service_worker.js");
367 blink::mojom::ServiceWorkerRegistrationOptions options;
368 options.scope = scope;
369
370 TestServiceWorkerContextObserver observer(context_wrapper());
371
372 int64_t registration_id = blink::mojom::kInvalidServiceWorkerRegistrationId;
373 bool called = false;
374 context()->RegisterServiceWorker(
375 script_url, options, blink::mojom::FetchClientSettingsObject::New(),
376 MakeRegisteredCallback(&called, ®istration_id));
377 base::RunLoop().RunUntilIdle();
378
379 ASSERT_TRUE(called);
380 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
381
382 std::vector<TestServiceWorkerContextObserver::EventLog> events;
383
384 // Filter the events to be verified.
385 for (auto event : observer.events()) {
386 if (event.type == TestServiceWorkerContextObserver::EventType::
387 RegistrationCompleted ||
388 event.type ==
389 TestServiceWorkerContextObserver::EventType::RegistrationStored ||
390 event.type ==
391 TestServiceWorkerContextObserver::EventType::VersionActivated)
392 events.push_back(event);
393 }
394 ASSERT_EQ(3u, events.size());
395 EXPECT_EQ(TestServiceWorkerContextObserver::EventType::RegistrationCompleted,
396 events[0].type);
397 EXPECT_EQ(scope, events[0].url);
398 EXPECT_EQ(TestServiceWorkerContextObserver::EventType::RegistrationStored,
399 events[1].type);
400 EXPECT_EQ(scope, events[1].url);
401 EXPECT_EQ(registration_id, events[1].registration_id);
402 EXPECT_EQ(TestServiceWorkerContextObserver::EventType::VersionActivated,
403 events[2].type);
404 EXPECT_EQ(scope, events[2].url);
405 }
406
407 // Make sure OnNoControllees is called on observer.
TEST_F(ServiceWorkerContextTest,NoControlleesObserver)408 TEST_F(ServiceWorkerContextTest, NoControlleesObserver) {
409 GURL scope("https://www.example.com/");
410 GURL script_url("https://www.example.com/service_worker.js");
411 blink::mojom::ServiceWorkerRegistrationOptions options;
412 options.scope = scope;
413
414 auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
415 options, 1l /* dummy registration id */, context()->AsWeakPtr());
416
417 auto version = base::MakeRefCounted<ServiceWorkerVersion>(
418 registration.get(), script_url, blink::mojom::ScriptType::kClassic,
419 2l /* dummy version id */, context()->AsWeakPtr());
420 version->set_fetch_handler_existence(
421 ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
422 version->SetStatus(ServiceWorkerVersion::ACTIVATED);
423
424 ServiceWorkerRemoteProviderEndpoint endpoint;
425 base::WeakPtr<ServiceWorkerContainerHost> container_host =
426 CreateContainerHostForWindow(helper_->mock_render_process_id(), true,
427 context()->AsWeakPtr(), &endpoint);
428
429 version->AddControllee(container_host.get());
430 base::RunLoop().RunUntilIdle();
431
432 TestServiceWorkerContextObserver observer(context_wrapper());
433
434 version->RemoveControllee(container_host->client_uuid());
435 base::RunLoop().RunUntilIdle();
436
437 ASSERT_EQ(1u, observer.events().size());
438 EXPECT_EQ(TestServiceWorkerContextObserver::EventType::NoControllees,
439 observer.events()[0].type);
440 EXPECT_EQ(scope, observer.events()[0].url);
441 EXPECT_EQ(2l, observer.events()[0].version_id);
442 }
443
444 // Make sure OnVersionActivated is called on observer.
TEST_F(ServiceWorkerContextTest,VersionActivatedObserver)445 TEST_F(ServiceWorkerContextTest, VersionActivatedObserver) {
446 GURL scope("https://www.example.com/");
447 GURL script_url("https://www.example.com/service_worker.js");
448 blink::mojom::ServiceWorkerRegistrationOptions options;
449 options.scope = scope;
450
451 auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
452 options, 1l /* dummy registration id */, context()->AsWeakPtr());
453
454 auto version = base::MakeRefCounted<ServiceWorkerVersion>(
455 registration.get(), script_url, blink::mojom::ScriptType::kClassic,
456 2l /* dummy version id */, context()->AsWeakPtr());
457
458 TestServiceWorkerContextObserver observer(context_wrapper());
459
460 version->set_fetch_handler_existence(
461 ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST);
462 version->SetStatus(ServiceWorkerVersion::Status::ACTIVATED);
463 base::RunLoop().RunUntilIdle();
464
465 ASSERT_EQ(1u, observer.events().size());
466 EXPECT_EQ(TestServiceWorkerContextObserver::EventType::VersionActivated,
467 observer.events()[0].type);
468 EXPECT_EQ(2l, observer.events()[0].version_id);
469 }
470
471 // Make sure OnVersionRedundant is called on observer.
TEST_F(ServiceWorkerContextTest,VersionRedundantObserver)472 TEST_F(ServiceWorkerContextTest, VersionRedundantObserver) {
473 GURL scope("https://www.example.com/");
474 GURL script_url("https://www.example.com/service_worker.js");
475 blink::mojom::ServiceWorkerRegistrationOptions options;
476 options.scope = scope;
477
478 auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
479 options, 1l /* dummy registration id */, context()->AsWeakPtr());
480
481 auto version = base::MakeRefCounted<ServiceWorkerVersion>(
482 registration.get(), script_url, blink::mojom::ScriptType::kClassic,
483 2l /* dummy version id */, context()->AsWeakPtr());
484
485 TestServiceWorkerContextObserver observer(context_wrapper());
486
487 version->set_fetch_handler_existence(
488 ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST);
489 version->SetStatus(ServiceWorkerVersion::Status::REDUNDANT);
490 base::RunLoop().RunUntilIdle();
491
492 ASSERT_EQ(1u, observer.events().size());
493 EXPECT_EQ(TestServiceWorkerContextObserver::EventType::VersionRedundant,
494 observer.events()[0].type);
495 EXPECT_EQ(2l, observer.events()[0].version_id);
496 }
497
498 // Make sure OnVersionStartedRunning and OnVersionStoppedRunning are called on
499 // observer.
TEST_F(ServiceWorkerContextTest,OnVersionRunningStatusChangedObserver)500 TEST_F(ServiceWorkerContextTest, OnVersionRunningStatusChangedObserver) {
501 GURL scope("https://www.example.com/");
502 GURL script_url("https://www.example.com/service_worker.js");
503 blink::mojom::ServiceWorkerRegistrationOptions options;
504 options.scope = scope;
505
506 TestServiceWorkerContextObserver observer(context_wrapper());
507 base::RunLoop run_loop;
508 context()->RegisterServiceWorker(
509 script_url, options, blink::mojom::FetchClientSettingsObject::New(),
510 base::BindOnce(&RegisteredCallback, run_loop.QuitClosure()));
511 run_loop.Run();
512
513 context_wrapper()->StopAllServiceWorkersForOrigin(scope);
514 base::RunLoop().RunUntilIdle();
515
516 std::vector<TestServiceWorkerContextObserver::EventLog> events;
517
518 // Filter the events to be verified.
519 for (auto event : observer.events()) {
520 if (event.type == TestServiceWorkerContextObserver::EventType::
521 VersionStartedRunning ||
522 event.type == TestServiceWorkerContextObserver::EventType::
523 VersionStoppedRunning) {
524 events.push_back(event);
525 }
526 }
527
528 ASSERT_EQ(2u, events.size());
529 EXPECT_EQ(TestServiceWorkerContextObserver::EventType::VersionStartedRunning,
530 events[0].type);
531 EXPECT_EQ(TestServiceWorkerContextObserver::EventType::VersionStoppedRunning,
532 events[1].type);
533 EXPECT_EQ(events[0].version_id, events[1].version_id);
534 }
535
536 // Make sure OnDestruct is called on observer.
TEST_F(ServiceWorkerContextTest,OnDestructObserver)537 TEST_F(ServiceWorkerContextTest, OnDestructObserver) {
538 ServiceWorkerContextWrapper* context = context_wrapper();
539 TestServiceWorkerContextObserver observer(context);
540 helper_->ShutdownContext();
541 base::RunLoop().RunUntilIdle();
542
543 ASSERT_EQ(1u, observer.events().size());
544 EXPECT_EQ(TestServiceWorkerContextObserver::EventType::Destruct,
545 observer.events()[0].type);
546 }
547
548 // Make sure basic registration is working.
TEST_F(ServiceWorkerContextTest,Register)549 TEST_F(ServiceWorkerContextTest, Register) {
550 GURL scope("https://www.example.com/");
551 GURL script_url("https://www.example.com/service_worker.js");
552 blink::mojom::ServiceWorkerRegistrationOptions options;
553 options.scope = scope;
554
555 auto* client =
556 helper_
557 ->AddNewPendingInstanceClient<RecordableEmbeddedWorkerInstanceClient>(
558 helper_.get());
559 auto* worker =
560 helper_->AddNewPendingServiceWorker<InstallActivateWorker>(helper_.get());
561
562 int64_t registration_id = blink::mojom::kInvalidServiceWorkerRegistrationId;
563 bool called = false;
564 context()->RegisterServiceWorker(
565 script_url, options, blink::mojom::FetchClientSettingsObject::New(),
566 MakeRegisteredCallback(&called, ®istration_id));
567
568 ASSERT_FALSE(called);
569 base::RunLoop().RunUntilIdle();
570 EXPECT_TRUE(called);
571
572 ASSERT_EQ(2u, worker->events().size());
573 ASSERT_EQ(1u, client->events().size());
574 EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
575 client->events()[0]);
576 EXPECT_EQ(ServiceWorkerMetrics::EventType::INSTALL, worker->events()[0]);
577 EXPECT_EQ(ServiceWorkerMetrics::EventType::ACTIVATE, worker->events()[1]);
578
579 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
580
581 ASSERT_EQ(2u, notifications_.size());
582 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
583 EXPECT_EQ(scope, notifications_[0].scope);
584 EXPECT_EQ(registration_id, notifications_[0].registration_id);
585 EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
586 EXPECT_EQ(scope, notifications_[1].scope);
587 EXPECT_EQ(registration_id, notifications_[1].registration_id);
588
589 context()->registry()->FindRegistrationForId(
590 registration_id, scope.GetOrigin(),
591 base::BindOnce(&ExpectRegisteredWorkers,
592 blink::ServiceWorkerStatusCode::kOk,
593 false /* expect_waiting */, true /* expect_active */));
594 base::RunLoop().RunUntilIdle();
595 }
596
597 // Test registration when the service worker rejects the install event. The
598 // registration callback should indicate success, but there should be no waiting
599 // or active worker in the registration.
TEST_F(ServiceWorkerContextTest,Register_RejectInstall)600 TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
601 GURL scope("https://www.example.com/");
602 GURL script_url("https://www.example.com/service_worker.js");
603 blink::mojom::ServiceWorkerRegistrationOptions options;
604 options.scope = scope;
605
606 auto* client =
607 helper_
608 ->AddNewPendingInstanceClient<RecordableEmbeddedWorkerInstanceClient>(
609 helper_.get());
610 auto* worker =
611 helper_->AddNewPendingServiceWorker<InstallActivateWorker>(helper_.get());
612 worker->SetToRejectInstall();
613
614 int64_t registration_id = blink::mojom::kInvalidServiceWorkerRegistrationId;
615 bool called = false;
616 context()->RegisterServiceWorker(
617 script_url, options, blink::mojom::FetchClientSettingsObject::New(),
618 MakeRegisteredCallback(&called, ®istration_id));
619
620 ASSERT_FALSE(called);
621 base::RunLoop().RunUntilIdle();
622 EXPECT_TRUE(called);
623
624 ASSERT_EQ(1u, worker->events().size());
625 ASSERT_EQ(2u, client->events().size());
626 EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
627 client->events()[0]);
628 EXPECT_EQ(ServiceWorkerMetrics::EventType::INSTALL, worker->events()[0]);
629 EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StopWorker,
630 client->events()[1]);
631
632 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
633
634 ASSERT_EQ(1u, notifications_.size());
635 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
636 EXPECT_EQ(scope, notifications_[0].scope);
637 EXPECT_EQ(registration_id, notifications_[0].registration_id);
638
639 context()->registry()->FindRegistrationForId(
640 registration_id, scope.GetOrigin(),
641 base::BindOnce(&ExpectRegisteredWorkers,
642 blink::ServiceWorkerStatusCode::kErrorNotFound,
643 false /* expect_waiting */, false /* expect_active */));
644 base::RunLoop().RunUntilIdle();
645 }
646
647 // Test registration when the service worker rejects the activate event. The
648 // worker should be activated anyway.
TEST_F(ServiceWorkerContextTest,Register_RejectActivate)649 TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
650 GURL scope("https://www.example.com/");
651 GURL script_url("https://www.example.com/service_worker.js");
652 blink::mojom::ServiceWorkerRegistrationOptions options;
653 options.scope = scope;
654
655 auto* client =
656 helper_
657 ->AddNewPendingInstanceClient<RecordableEmbeddedWorkerInstanceClient>(
658 helper_.get());
659 auto* worker =
660 helper_->AddNewPendingServiceWorker<InstallActivateWorker>(helper_.get());
661 worker->SetToRejectActivate();
662
663 int64_t registration_id = blink::mojom::kInvalidServiceWorkerRegistrationId;
664 bool called = false;
665 context()->RegisterServiceWorker(
666 script_url, options, blink::mojom::FetchClientSettingsObject::New(),
667 MakeRegisteredCallback(&called, ®istration_id));
668
669 ASSERT_FALSE(called);
670 base::RunLoop().RunUntilIdle();
671 EXPECT_TRUE(called);
672
673 ASSERT_EQ(2u, worker->events().size());
674 ASSERT_EQ(1u, client->events().size());
675 EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
676 client->events()[0]);
677 EXPECT_EQ(ServiceWorkerMetrics::EventType::INSTALL, worker->events()[0]);
678 EXPECT_EQ(ServiceWorkerMetrics::EventType::ACTIVATE, worker->events()[1]);
679
680 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
681
682 ASSERT_EQ(2u, notifications_.size());
683 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
684 EXPECT_EQ(scope, notifications_[0].scope);
685 EXPECT_EQ(registration_id, notifications_[0].registration_id);
686 EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
687 EXPECT_EQ(scope, notifications_[1].scope);
688 EXPECT_EQ(registration_id, notifications_[1].registration_id);
689
690 context()->registry()->FindRegistrationForId(
691 registration_id, scope.GetOrigin(),
692 base::BindOnce(&ExpectRegisteredWorkers,
693 blink::ServiceWorkerStatusCode::kOk,
694 false /* expect_waiting */, true /* expect_active */));
695 base::RunLoop().RunUntilIdle();
696 }
697
698 // Make sure registrations are cleaned up when they are unregistered.
TEST_F(ServiceWorkerContextTest,Unregister)699 TEST_F(ServiceWorkerContextTest, Unregister) {
700 GURL scope("https://www.example.com/");
701 blink::mojom::ServiceWorkerRegistrationOptions options;
702 options.scope = scope;
703
704 bool called = false;
705 int64_t registration_id = blink::mojom::kInvalidServiceWorkerRegistrationId;
706 context()->RegisterServiceWorker(
707 GURL("https://www.example.com/service_worker.js"), options,
708 blink::mojom::FetchClientSettingsObject::New(),
709 MakeRegisteredCallback(&called, ®istration_id));
710
711 ASSERT_FALSE(called);
712 base::RunLoop().RunUntilIdle();
713 ASSERT_TRUE(called);
714 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
715
716 called = false;
717 context()->UnregisterServiceWorker(scope, /*is_immediate=*/false,
718 MakeUnregisteredCallback(&called));
719
720 ASSERT_FALSE(called);
721 base::RunLoop().RunUntilIdle();
722 ASSERT_TRUE(called);
723
724 context()->registry()->FindRegistrationForId(
725 registration_id, scope.GetOrigin(),
726 base::BindOnce(&ExpectRegisteredWorkers,
727 blink::ServiceWorkerStatusCode::kErrorNotFound,
728 false /* expect_waiting */, false /* expect_active */));
729 base::RunLoop().RunUntilIdle();
730
731 ASSERT_EQ(3u, notifications_.size());
732 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
733 EXPECT_EQ(scope, notifications_[0].scope);
734 EXPECT_EQ(registration_id, notifications_[0].registration_id);
735 EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
736 EXPECT_EQ(scope, notifications_[1].scope);
737 EXPECT_EQ(registration_id, notifications_[1].registration_id);
738 EXPECT_EQ(REGISTRATION_DELETED, notifications_[2].type);
739 EXPECT_EQ(scope, notifications_[2].scope);
740 EXPECT_EQ(registration_id, notifications_[2].registration_id);
741 }
742
743 // Make sure registrations are cleaned up when they are unregistered in bulk.
TEST_F(ServiceWorkerContextTest,UnregisterMultiple)744 TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
745 GURL origin1_s1("https://www.example.com/test");
746 GURL origin1_s2("https://www.example.com/hello");
747 GURL origin2_s1("https://www.example.com:8080/again");
748 GURL origin3_s1("https://www.other.com/");
749 int64_t registration_id1 = blink::mojom::kInvalidServiceWorkerRegistrationId;
750 int64_t registration_id2 = blink::mojom::kInvalidServiceWorkerRegistrationId;
751 int64_t registration_id3 = blink::mojom::kInvalidServiceWorkerRegistrationId;
752 int64_t registration_id4 = blink::mojom::kInvalidServiceWorkerRegistrationId;
753
754 {
755 bool called = false;
756 blink::mojom::ServiceWorkerRegistrationOptions options;
757 options.scope = origin1_s1;
758 context()->RegisterServiceWorker(
759 GURL("https://www.example.com/service_worker.js"), options,
760 blink::mojom::FetchClientSettingsObject::New(),
761 MakeRegisteredCallback(&called, ®istration_id1));
762 ASSERT_FALSE(called);
763 base::RunLoop().RunUntilIdle();
764 ASSERT_TRUE(called);
765 }
766
767 {
768 bool called = false;
769 blink::mojom::ServiceWorkerRegistrationOptions options;
770 options.scope = origin1_s2;
771 context()->RegisterServiceWorker(
772 GURL("https://www.example.com/service_worker2.js"), options,
773 blink::mojom::FetchClientSettingsObject::New(),
774 MakeRegisteredCallback(&called, ®istration_id2));
775 ASSERT_FALSE(called);
776 base::RunLoop().RunUntilIdle();
777 ASSERT_TRUE(called);
778 }
779
780 {
781 bool called = false;
782 blink::mojom::ServiceWorkerRegistrationOptions options;
783 options.scope = origin2_s1;
784 context()->RegisterServiceWorker(
785 GURL("https://www.example.com:8080/service_worker3.js"), options,
786 blink::mojom::FetchClientSettingsObject::New(),
787 MakeRegisteredCallback(&called, ®istration_id3));
788 ASSERT_FALSE(called);
789 base::RunLoop().RunUntilIdle();
790 ASSERT_TRUE(called);
791 }
792
793 {
794 bool called = false;
795 blink::mojom::ServiceWorkerRegistrationOptions options;
796 options.scope = origin3_s1;
797 context()->RegisterServiceWorker(
798 GURL("https://www.other.com/service_worker4.js"), options,
799 blink::mojom::FetchClientSettingsObject::New(),
800 MakeRegisteredCallback(&called, ®istration_id4));
801 ASSERT_FALSE(called);
802 base::RunLoop().RunUntilIdle();
803 ASSERT_TRUE(called);
804 }
805
806 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
807 registration_id1);
808 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
809 registration_id2);
810 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
811 registration_id3);
812 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
813 registration_id4);
814
815 bool called = false;
816 context()->DeleteForOrigin(origin1_s1.GetOrigin(),
817 MakeUnregisteredCallback(&called));
818
819 ASSERT_FALSE(called);
820 base::RunLoop().RunUntilIdle();
821 ASSERT_TRUE(called);
822
823 context()->registry()->FindRegistrationForId(
824 registration_id1, origin1_s1.GetOrigin(),
825 base::BindOnce(&ExpectRegisteredWorkers,
826 blink::ServiceWorkerStatusCode::kErrorNotFound,
827 false /* expect_waiting */, false /* expect_active */));
828 context()->registry()->FindRegistrationForId(
829 registration_id2, origin1_s2.GetOrigin(),
830 base::BindOnce(&ExpectRegisteredWorkers,
831 blink::ServiceWorkerStatusCode::kErrorNotFound,
832 false /* expect_waiting */, false /* expect_active */));
833 context()->registry()->FindRegistrationForId(
834 registration_id3, origin2_s1.GetOrigin(),
835 base::BindOnce(&ExpectRegisteredWorkers,
836 blink::ServiceWorkerStatusCode::kOk,
837 false /* expect_waiting */, true /* expect_active */));
838
839 context()->registry()->FindRegistrationForId(
840 registration_id4, origin3_s1.GetOrigin(),
841 base::BindOnce(&ExpectRegisteredWorkers,
842 blink::ServiceWorkerStatusCode::kOk,
843 false /* expect_waiting */, true /* expect_active */));
844
845 base::RunLoop().RunUntilIdle();
846
847 ASSERT_EQ(10u, notifications_.size());
848 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
849 EXPECT_EQ(registration_id1, notifications_[0].registration_id);
850 EXPECT_EQ(origin1_s1, notifications_[0].scope);
851 EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
852 EXPECT_EQ(registration_id1, notifications_[1].registration_id);
853 EXPECT_EQ(origin1_s1, notifications_[1].scope);
854 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[2].type);
855 EXPECT_EQ(origin1_s2, notifications_[2].scope);
856 EXPECT_EQ(registration_id2, notifications_[2].registration_id);
857 EXPECT_EQ(REGISTRATION_STORED, notifications_[3].type);
858 EXPECT_EQ(origin1_s2, notifications_[3].scope);
859 EXPECT_EQ(registration_id2, notifications_[3].registration_id);
860 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[4].type);
861 EXPECT_EQ(origin2_s1, notifications_[4].scope);
862 EXPECT_EQ(registration_id3, notifications_[4].registration_id);
863 EXPECT_EQ(REGISTRATION_STORED, notifications_[5].type);
864 EXPECT_EQ(origin2_s1, notifications_[5].scope);
865 EXPECT_EQ(registration_id3, notifications_[5].registration_id);
866 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[6].type);
867 EXPECT_EQ(origin3_s1, notifications_[6].scope);
868 EXPECT_EQ(registration_id4, notifications_[6].registration_id);
869 EXPECT_EQ(REGISTRATION_STORED, notifications_[7].type);
870 EXPECT_EQ(origin3_s1, notifications_[7].scope);
871 EXPECT_EQ(registration_id4, notifications_[7].registration_id);
872 EXPECT_EQ(REGISTRATION_DELETED, notifications_[8].type);
873 EXPECT_EQ(origin1_s1, notifications_[8].scope);
874 EXPECT_EQ(registration_id1, notifications_[8].registration_id);
875 EXPECT_EQ(REGISTRATION_DELETED, notifications_[9].type);
876 EXPECT_EQ(origin1_s2, notifications_[9].scope);
877 EXPECT_EQ(registration_id2, notifications_[9].registration_id);
878 }
879
880 // Make sure registering a new script shares an existing registration.
TEST_F(ServiceWorkerContextTest,RegisterNewScript)881 TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
882 GURL scope("https://www.example.com/");
883 blink::mojom::ServiceWorkerRegistrationOptions options;
884 options.scope = scope;
885
886 bool called = false;
887 int64_t old_registration_id =
888 blink::mojom::kInvalidServiceWorkerRegistrationId;
889 context()->RegisterServiceWorker(
890 GURL("https://www.example.com/service_worker.js"), options,
891 blink::mojom::FetchClientSettingsObject::New(),
892 MakeRegisteredCallback(&called, &old_registration_id));
893
894 ASSERT_FALSE(called);
895 base::RunLoop().RunUntilIdle();
896 ASSERT_TRUE(called);
897 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
898 old_registration_id);
899
900 called = false;
901 int64_t new_registration_id =
902 blink::mojom::kInvalidServiceWorkerRegistrationId;
903 context()->RegisterServiceWorker(
904 GURL("https://www.example.com/service_worker_new.js"), options,
905 blink::mojom::FetchClientSettingsObject::New(),
906 MakeRegisteredCallback(&called, &new_registration_id));
907
908 ASSERT_FALSE(called);
909 base::RunLoop().RunUntilIdle();
910 ASSERT_TRUE(called);
911
912 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
913 new_registration_id);
914 EXPECT_EQ(old_registration_id, new_registration_id);
915
916 ASSERT_EQ(4u, notifications_.size());
917 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
918 EXPECT_EQ(scope, notifications_[0].scope);
919 EXPECT_EQ(old_registration_id, notifications_[0].registration_id);
920 EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
921 EXPECT_EQ(scope, notifications_[1].scope);
922 EXPECT_EQ(old_registration_id, notifications_[1].registration_id);
923 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[2].type);
924 EXPECT_EQ(scope, notifications_[2].scope);
925 EXPECT_EQ(new_registration_id, notifications_[2].registration_id);
926 EXPECT_EQ(REGISTRATION_STORED, notifications_[3].type);
927 EXPECT_EQ(scope, notifications_[3].scope);
928 EXPECT_EQ(new_registration_id, notifications_[3].registration_id);
929 }
930
931 // Make sure that when registering a duplicate scope+script_url
932 // combination, that the same registration is used.
TEST_F(ServiceWorkerContextTest,RegisterDuplicateScript)933 TEST_F(ServiceWorkerContextTest, RegisterDuplicateScript) {
934 GURL scope("https://www.example.com/");
935 GURL script_url("https://www.example.com/service_worker.js");
936 blink::mojom::ServiceWorkerRegistrationOptions options;
937 options.scope = scope;
938
939 bool called = false;
940 int64_t old_registration_id =
941 blink::mojom::kInvalidServiceWorkerRegistrationId;
942 context()->RegisterServiceWorker(
943 script_url, options, blink::mojom::FetchClientSettingsObject::New(),
944 MakeRegisteredCallback(&called, &old_registration_id));
945
946 ASSERT_FALSE(called);
947 base::RunLoop().RunUntilIdle();
948 ASSERT_TRUE(called);
949 EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
950 old_registration_id);
951
952 called = false;
953 int64_t new_registration_id =
954 blink::mojom::kInvalidServiceWorkerRegistrationId;
955 context()->RegisterServiceWorker(
956 script_url, options, blink::mojom::FetchClientSettingsObject::New(),
957 MakeRegisteredCallback(&called, &new_registration_id));
958
959 ASSERT_FALSE(called);
960 base::RunLoop().RunUntilIdle();
961 ASSERT_TRUE(called);
962 EXPECT_EQ(old_registration_id, new_registration_id);
963
964 ASSERT_EQ(3u, notifications_.size());
965 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
966 EXPECT_EQ(scope, notifications_[0].scope);
967 EXPECT_EQ(old_registration_id, notifications_[0].registration_id);
968 EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
969 EXPECT_EQ(scope, notifications_[1].scope);
970 EXPECT_EQ(old_registration_id, notifications_[1].registration_id);
971 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[2].type);
972 EXPECT_EQ(scope, notifications_[2].scope);
973 EXPECT_EQ(old_registration_id, notifications_[2].registration_id);
974 }
975
TEST_F(ServiceWorkerContextTest,ContainerHostIterator)976 TEST_F(ServiceWorkerContextTest, ContainerHostIterator) {
977 const int kRenderProcessId1 = 1;
978 const int kRenderProcessId2 = 2;
979 const GURL kOrigin1 = GURL("https://www.example.com/");
980 const GURL kOrigin2 = GURL("https://another-origin.example.net/");
981 std::vector<ServiceWorkerRemoteProviderEndpoint> remote_endpoints;
982
983 // Host1 : process_id=1, origin1.
984 remote_endpoints.emplace_back();
985 base::WeakPtr<ServiceWorkerContainerHost> container_host1 =
986 CreateContainerHostForWindow(
987 kRenderProcessId1, true /* is_parent_frame_secure */,
988 context()->AsWeakPtr(), &remote_endpoints.back());
989 container_host1->UpdateUrls(kOrigin1, net::SiteForCookies::FromUrl(kOrigin1),
990 url::Origin::Create(kOrigin1));
991
992 // Host2 : process_id=2, origin2.
993 remote_endpoints.emplace_back();
994 base::WeakPtr<ServiceWorkerContainerHost> container_host2 =
995 CreateContainerHostForWindow(
996 kRenderProcessId2, true /* is_parent_frame_secure */,
997 context()->AsWeakPtr(), &remote_endpoints.back());
998 container_host2->UpdateUrls(kOrigin2, net::SiteForCookies::FromUrl(kOrigin2),
999 url::Origin::Create(kOrigin2));
1000
1001 // Host3 : process_id=2, origin1.
1002 remote_endpoints.emplace_back();
1003 base::WeakPtr<ServiceWorkerContainerHost> container_host3 =
1004 CreateContainerHostForWindow(
1005 kRenderProcessId2, true /* is_parent_frame_secure */,
1006 context()->AsWeakPtr(), &remote_endpoints.back());
1007 container_host3->UpdateUrls(kOrigin1, net::SiteForCookies::FromUrl(kOrigin1),
1008 url::Origin::Create(kOrigin1));
1009
1010 // Host4 : process_id=2, origin2, for ServiceWorker.
1011 blink::mojom::ServiceWorkerRegistrationOptions registration_opt;
1012 registration_opt.scope = GURL("https://another-origin.example.net/test/");
1013 scoped_refptr<ServiceWorkerRegistration> registration =
1014 base::MakeRefCounted<ServiceWorkerRegistration>(
1015 registration_opt, 1L /* registration_id */,
1016 helper_->context()->AsWeakPtr());
1017 scoped_refptr<ServiceWorkerVersion> version =
1018 base::MakeRefCounted<ServiceWorkerVersion>(
1019 registration.get(),
1020 GURL("https://another-origin.example.net/test/script_url"),
1021 blink::mojom::ScriptType::kClassic, 1L /* version_id */,
1022 helper_->context()->AsWeakPtr());
1023 remote_endpoints.emplace_back();
1024 // ServiceWorkrProviderHost creates ServiceWorkerContainerHost for a service
1025 // worker execution context.
1026 std::unique_ptr<ServiceWorkerProviderHost> provider_host4 =
1027 CreateProviderHostForServiceWorkerContext(
1028 kRenderProcessId2, true /* is_parent_frame_secure */, version.get(),
1029 context()->AsWeakPtr(), &remote_endpoints.back());
1030 EXPECT_NE(provider_host4->provider_id(),
1031 blink::kInvalidServiceWorkerProviderId);
1032
1033 ASSERT_TRUE(container_host1);
1034 ASSERT_TRUE(container_host2);
1035 ASSERT_TRUE(container_host3);
1036 ASSERT_TRUE(provider_host4->container_host());
1037
1038 // Iterate over the client container hosts that belong to kOrigin1.
1039 std::set<ServiceWorkerContainerHost*> results;
1040 for (auto it = context()->GetClientContainerHostIterator(
1041 kOrigin1, true /* include_reserved_clients */,
1042 false /* include_back_forward_cached_clients */);
1043 !it->IsAtEnd(); it->Advance()) {
1044 results.insert(it->GetContainerHost());
1045 }
1046 EXPECT_EQ(2u, results.size());
1047 EXPECT_TRUE(base::Contains(results, container_host1.get()));
1048 EXPECT_TRUE(base::Contains(results, container_host3.get()));
1049
1050 // Iterate over the container hosts that belong to kOrigin2. This should not
1051 // include provider_host4->container_host() as it's not for controllee.
1052 results.clear();
1053 for (auto it = context()->GetClientContainerHostIterator(
1054 kOrigin2, true /* include_reserved_clients */,
1055 false /* include_back_forward_cached_clients */);
1056 !it->IsAtEnd(); it->Advance()) {
1057 results.insert(it->GetContainerHost());
1058 }
1059 EXPECT_EQ(1u, results.size());
1060 EXPECT_TRUE(base::Contains(results, container_host2.get()));
1061
1062 context()->UnregisterContainerHostByClientID(container_host1->client_uuid());
1063 context()->UnregisterContainerHostByClientID(container_host2->client_uuid());
1064 context()->UnregisterContainerHostByClientID(container_host3->client_uuid());
1065 }
1066
1067 class ServiceWorkerContextRecoveryTest
1068 : public ServiceWorkerContextTest,
1069 public testing::WithParamInterface<bool /* is_storage_on_disk */> {
1070 public:
ServiceWorkerContextRecoveryTest()1071 ServiceWorkerContextRecoveryTest() {}
~ServiceWorkerContextRecoveryTest()1072 virtual ~ServiceWorkerContextRecoveryTest() {}
1073
1074 protected:
is_storage_on_disk() const1075 bool is_storage_on_disk() const { return GetParam(); }
1076 };
1077
TEST_P(ServiceWorkerContextRecoveryTest,DeleteAndStartOver)1078 TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
1079 GURL scope("https://www.example.com/");
1080 GURL script_url("https://www.example.com/service_worker.js");
1081 blink::mojom::ServiceWorkerRegistrationOptions options;
1082 options.scope = scope;
1083
1084 if (is_storage_on_disk()) {
1085 // Reinitialize the helper to test on-disk storage.
1086 base::FilePath user_data_directory;
1087 ASSERT_NO_FATAL_FAILURE(GetTemporaryDirectory(&user_data_directory));
1088 helper_.reset(new EmbeddedWorkerTestHelper(user_data_directory));
1089 helper_->context_wrapper()->AddObserver(this);
1090 }
1091
1092 int64_t registration_id = blink::mojom::kInvalidServiceWorkerRegistrationId;
1093 bool called = false;
1094 context()->RegisterServiceWorker(
1095 script_url, options, blink::mojom::FetchClientSettingsObject::New(),
1096 MakeRegisteredCallback(&called, ®istration_id));
1097
1098 ASSERT_FALSE(called);
1099 content::RunAllTasksUntilIdle();
1100 EXPECT_TRUE(called);
1101
1102 context()->registry()->FindRegistrationForId(
1103 registration_id, scope.GetOrigin(),
1104 base::BindOnce(&ExpectRegisteredWorkers,
1105 blink::ServiceWorkerStatusCode::kOk,
1106 false /* expect_waiting */, true /* expect_active */));
1107 content::RunAllTasksUntilIdle();
1108
1109 context()->ScheduleDeleteAndStartOver();
1110
1111 // The storage is disabled while the recovery process is running, so the
1112 // operation should be aborted.
1113 context()->registry()->FindRegistrationForId(
1114 registration_id, scope.GetOrigin(),
1115 base::BindOnce(&ExpectRegisteredWorkers,
1116 blink::ServiceWorkerStatusCode::kErrorAbort,
1117 false /* expect_waiting */, true /* expect_active */));
1118 content::RunAllTasksUntilIdle();
1119
1120 // The context started over and the storage was re-initialized, so the
1121 // registration should not be found.
1122 context()->registry()->FindRegistrationForId(
1123 registration_id, scope.GetOrigin(),
1124 base::BindOnce(&ExpectRegisteredWorkers,
1125 blink::ServiceWorkerStatusCode::kErrorNotFound,
1126 false /* expect_waiting */, true /* expect_active */));
1127 content::RunAllTasksUntilIdle();
1128
1129 called = false;
1130 context()->RegisterServiceWorker(
1131 script_url, options, blink::mojom::FetchClientSettingsObject::New(),
1132 MakeRegisteredCallback(&called, ®istration_id));
1133
1134 ASSERT_FALSE(called);
1135 content::RunAllTasksUntilIdle();
1136 EXPECT_TRUE(called);
1137
1138 context()->registry()->FindRegistrationForId(
1139 registration_id, scope.GetOrigin(),
1140 base::BindOnce(&ExpectRegisteredWorkers,
1141 blink::ServiceWorkerStatusCode::kOk,
1142 false /* expect_waiting */, true /* expect_active */));
1143 content::RunAllTasksUntilIdle();
1144
1145 ASSERT_EQ(5u, notifications_.size());
1146 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
1147 EXPECT_EQ(scope, notifications_[0].scope);
1148 EXPECT_EQ(registration_id, notifications_[0].registration_id);
1149 EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
1150 EXPECT_EQ(scope, notifications_[1].scope);
1151 EXPECT_EQ(registration_id, notifications_[1].registration_id);
1152 EXPECT_EQ(STORAGE_RECOVERED, notifications_[2].type);
1153 EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[3].type);
1154 EXPECT_EQ(scope, notifications_[3].scope);
1155 EXPECT_EQ(registration_id, notifications_[3].registration_id);
1156 EXPECT_EQ(REGISTRATION_STORED, notifications_[4].type);
1157 EXPECT_EQ(scope, notifications_[4].scope);
1158 EXPECT_EQ(registration_id, notifications_[4].registration_id);
1159 }
1160
1161 INSTANTIATE_TEST_SUITE_P(ServiceWorkerContextRecoveryTest,
1162 ServiceWorkerContextRecoveryTest,
1163 testing::Bool() /* is_storage_on_disk */);
1164
1165 } // namespace content
1166