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.
4 
5 #include <stdint.h>
6 #include <tuple>
7 
8 #include "base/barrier_closure.h"
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/check.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/optional.h"
14 #include "base/run_loop.h"
15 #include "base/stl_util.h"
16 #include "base/test/bind.h"
17 #include "base/test/metrics/histogram_tester.h"
18 #include "base/test/scoped_feature_list.h"
19 #include "base/test/test_simple_task_runner.h"
20 #include "base/time/time.h"
21 #include "content/browser/renderer_host/frame_tree_node.h"
22 #include "content/browser/service_worker/embedded_worker_status.h"
23 #include "content/browser/service_worker/embedded_worker_test_helper.h"
24 #include "content/browser/service_worker/fake_embedded_worker_instance_client.h"
25 #include "content/browser/service_worker/service_worker_consts.h"
26 #include "content/browser/service_worker/service_worker_container_host.h"
27 #include "content/browser/service_worker/service_worker_context_core.h"
28 #include "content/browser/service_worker/service_worker_context_wrapper.h"
29 #include "content/browser/service_worker/service_worker_job_coordinator.h"
30 #include "content/browser/service_worker/service_worker_object_host.h"
31 #include "content/browser/service_worker/service_worker_registration.h"
32 #include "content/browser/service_worker/service_worker_registration_object_host.h"
33 #include "content/browser/service_worker/service_worker_registration_status.h"
34 #include "content/browser/service_worker/service_worker_test_utils.h"
35 #include "content/browser/service_worker/test_service_worker_observer.h"
36 #include "content/browser/storage_partition_impl.h"
37 #include "content/public/test/browser_task_environment.h"
38 #include "content/public/test/test_browser_context.h"
39 #include "content/public/test/url_loader_interceptor.h"
40 #include "content/test/fake_network.h"
41 #include "ipc/ipc_test_sink.h"
42 #include "net/base/io_buffer.h"
43 #include "net/base/net_errors.h"
44 #include "net/base/test_completion_callback.h"
45 #include "net/http/http_response_headers.h"
46 #include "services/network/public/cpp/features.h"
47 #include "testing/gtest/include/gtest/gtest.h"
48 #include "third_party/blink/public/common/features.h"
49 #include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
50 #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
51 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
52 #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
53 
54 using net::IOBuffer;
55 using net::TestCompletionCallback;
56 using net::WrappedIOBuffer;
57 
58 // Unit tests for testing all job registration tasks.
59 namespace content {
60 
61 namespace {
62 
SaveRegistrationCallback(blink::ServiceWorkerStatusCode expected_status,scoped_refptr<ServiceWorkerRegistration> * registration_out,base::OnceClosure quit_closure,blink::ServiceWorkerStatusCode status,const std::string & status_message,ServiceWorkerRegistration * registration)63 void SaveRegistrationCallback(
64     blink::ServiceWorkerStatusCode expected_status,
65     scoped_refptr<ServiceWorkerRegistration>* registration_out,
66     base::OnceClosure quit_closure,
67     blink::ServiceWorkerStatusCode status,
68     const std::string& status_message,
69     ServiceWorkerRegistration* registration) {
70   EXPECT_EQ(expected_status, status);
71   *registration_out = registration;
72   std::move(quit_closure).Run();
73 }
74 
SaveFoundRegistrationCallback(blink::ServiceWorkerStatusCode expected_status,scoped_refptr<ServiceWorkerRegistration> * registration,base::OnceClosure quit_closure,blink::ServiceWorkerStatusCode status,scoped_refptr<ServiceWorkerRegistration> result)75 void SaveFoundRegistrationCallback(
76     blink::ServiceWorkerStatusCode expected_status,
77     scoped_refptr<ServiceWorkerRegistration>* registration,
78     base::OnceClosure quit_closure,
79     blink::ServiceWorkerStatusCode status,
80     scoped_refptr<ServiceWorkerRegistration> result) {
81   EXPECT_EQ(expected_status, status);
82   *registration = std::move(result);
83   std::move(quit_closure).Run();
84 }
85 
86 // Creates a callback which keeps track of the resulting registration.
87 // When the callback is fired, it ensures that the resulting status
88 // matches the expectation.
SaveRegistration(blink::ServiceWorkerStatusCode expected_status,scoped_refptr<ServiceWorkerRegistration> * registration,base::OnceClosure quit_closure)89 ServiceWorkerRegisterJob::RegistrationCallback SaveRegistration(
90     blink::ServiceWorkerStatusCode expected_status,
91     scoped_refptr<ServiceWorkerRegistration>* registration,
92     base::OnceClosure quit_closure) {
93   return base::BindOnce(&SaveRegistrationCallback, expected_status,
94                         registration, std::move(quit_closure));
95 }
96 
SaveFoundRegistration(blink::ServiceWorkerStatusCode expected_status,scoped_refptr<ServiceWorkerRegistration> * registration,base::OnceClosure quit_closure)97 ServiceWorkerRegistry::FindRegistrationCallback SaveFoundRegistration(
98     blink::ServiceWorkerStatusCode expected_status,
99     scoped_refptr<ServiceWorkerRegistration>* registration,
100     base::OnceClosure quit_closure) {
101   return base::BindOnce(&SaveFoundRegistrationCallback, expected_status,
102                         registration, std::move(quit_closure));
103 }
104 
SaveUnregistrationCallback(blink::ServiceWorkerStatusCode expected_status,base::OnceClosure quit_closure,int64_t registration_id,blink::ServiceWorkerStatusCode status)105 void SaveUnregistrationCallback(blink::ServiceWorkerStatusCode expected_status,
106                                 base::OnceClosure quit_closure,
107                                 int64_t registration_id,
108                                 blink::ServiceWorkerStatusCode status) {
109   EXPECT_EQ(expected_status, status);
110   std::move(quit_closure).Run();
111 }
112 
SaveUnregistration(blink::ServiceWorkerStatusCode expected_status,base::OnceClosure quit_closure)113 ServiceWorkerUnregisterJob::UnregistrationCallback SaveUnregistration(
114     blink::ServiceWorkerStatusCode expected_status,
115     base::OnceClosure quit_closure) {
116   return base::BindOnce(&SaveUnregistrationCallback, expected_status,
117                         std::move(quit_closure));
118 }
119 
RequestTermination(mojo::AssociatedRemote<blink::mojom::EmbeddedWorkerInstanceHost> * host)120 void RequestTermination(
121     mojo::AssociatedRemote<blink::mojom::EmbeddedWorkerInstanceHost>* host) {
122   // We can't wait for the callback since StopWorker() arrives before it which
123   // severs the Mojo connection.
124   (*host)->RequestTermination(base::DoNothing());
125 }
126 
127 class EmbeddedWorkerStatusObserver : public ServiceWorkerVersion::Observer {
128  public:
EmbeddedWorkerStatusObserver(base::OnceClosure quit_closure,EmbeddedWorkerStatus running_status)129   EmbeddedWorkerStatusObserver(base::OnceClosure quit_closure,
130                                EmbeddedWorkerStatus running_status)
131       : quit_closure_(std::move(quit_closure)),
132         expected_running_status_(running_status) {}
133 
OnRunningStateChanged(ServiceWorkerVersion * version)134   void OnRunningStateChanged(ServiceWorkerVersion* version) override {
135     if (!quit_closure_)
136       return;
137 
138     if (version->running_status() == expected_running_status_)
139       std::move(quit_closure_).Run();
140   }
141 
142  private:
143   EmbeddedWorkerStatusObserver(const EmbeddedWorkerStatusObserver&) = delete;
144   EmbeddedWorkerStatusObserver& operator=(const EmbeddedWorkerStatusObserver&) =
145       delete;
146 
147   base::OnceClosure quit_closure_;
148 
149   EmbeddedWorkerStatus expected_running_status_;
150 };
151 
CrossOriginEmbedderPolicyNone()152 network::CrossOriginEmbedderPolicy CrossOriginEmbedderPolicyNone() {
153   return network::CrossOriginEmbedderPolicy();
154 }
155 
CrossOriginEmbedderPolicyRequireCorp()156 network::CrossOriginEmbedderPolicy CrossOriginEmbedderPolicyRequireCorp() {
157   network::CrossOriginEmbedderPolicy out;
158   out.value = network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
159   return out;
160 }
161 
162 }  // namespace
163 
164 class ServiceWorkerJobTest : public testing::Test {
165  public:
ServiceWorkerJobTest()166   ServiceWorkerJobTest()
167       : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME,
168                           BrowserTaskEnvironment::IO_MAINLOOP) {}
169 
SetUp()170   void SetUp() override {
171     helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
172   }
173 
TearDown()174   void TearDown() override { helper_.reset(); }
175 
context() const176   ServiceWorkerContextCore* context() const { return helper_->context(); }
177 
job_coordinator() const178   ServiceWorkerJobCoordinator* job_coordinator() const {
179     return context()->job_coordinator();
180   }
registry() const181   ServiceWorkerRegistry* registry() const { return context()->registry(); }
182 
183  protected:
184   scoped_refptr<ServiceWorkerRegistration> RunRegisterJob(
185       const GURL& script_url,
186       const blink::mojom::ServiceWorkerRegistrationOptions& options,
187       blink::ServiceWorkerStatusCode expected_status =
188           blink::ServiceWorkerStatusCode::kOk);
189   void RunUnregisterJob(const GURL& scope,
190                         blink::ServiceWorkerStatusCode expected_status =
191                             blink::ServiceWorkerStatusCode::kOk);
192   void WaitForVersionRunningStatus(scoped_refptr<ServiceWorkerVersion> version,
193                                    EmbeddedWorkerStatus running_status);
194   scoped_refptr<ServiceWorkerRegistration> FindRegistrationForScope(
195       const GURL& scope,
196       blink::ServiceWorkerStatusCode expected_status =
197           blink::ServiceWorkerStatusCode::kOk);
198   ServiceWorkerContainerHost* CreateControllee();
199   scoped_refptr<ServiceWorkerRegistration> CreateRegistrationWithControllee(
200       const GURL& script_url,
201       const GURL& scope_url);
202 
203   BrowserTaskEnvironment task_environment_;
204   std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
205   std::vector<ServiceWorkerRemoteContainerEndpoint> remote_endpoints_;
206 };
207 
RunRegisterJob(const GURL & script_url,const blink::mojom::ServiceWorkerRegistrationOptions & options,blink::ServiceWorkerStatusCode expected_status)208 scoped_refptr<ServiceWorkerRegistration> ServiceWorkerJobTest::RunRegisterJob(
209     const GURL& script_url,
210     const blink::mojom::ServiceWorkerRegistrationOptions& options,
211     blink::ServiceWorkerStatusCode expected_status) {
212   scoped_refptr<ServiceWorkerRegistration> registration;
213   base::RunLoop run_loop;
214   auto outside_fetch_client_settings_object =
215       blink::mojom::FetchClientSettingsObject::New();
216   outside_fetch_client_settings_object->outgoing_referrer = script_url;
217   job_coordinator()->Register(
218       script_url, options, std::move(outside_fetch_client_settings_object),
219       SaveRegistration(expected_status, &registration, run_loop.QuitClosure()));
220   run_loop.Run();
221   return registration;
222 }
223 
RunUnregisterJob(const GURL & scope,blink::ServiceWorkerStatusCode expected_status)224 void ServiceWorkerJobTest::RunUnregisterJob(
225     const GURL& scope,
226     blink::ServiceWorkerStatusCode expected_status) {
227   base::RunLoop run_loop;
228   job_coordinator()->Unregister(
229       scope, /*is_immediate=*/false,
230       SaveUnregistration(expected_status, run_loop.QuitClosure()));
231   run_loop.Run();
232 }
233 
WaitForVersionRunningStatus(scoped_refptr<ServiceWorkerVersion> version,EmbeddedWorkerStatus running_status)234 void ServiceWorkerJobTest::WaitForVersionRunningStatus(
235     scoped_refptr<ServiceWorkerVersion> version,
236     EmbeddedWorkerStatus running_status) {
237   if (version->running_status() == running_status)
238     return;
239 
240   base::RunLoop run_loop;
241   EmbeddedWorkerStatusObserver observer(run_loop.QuitClosure(), running_status);
242   version->AddObserver(&observer);
243   run_loop.Run();
244   version->RemoveObserver(&observer);
245 }
246 
247 scoped_refptr<ServiceWorkerRegistration>
FindRegistrationForScope(const GURL & scope,blink::ServiceWorkerStatusCode expected_status)248 ServiceWorkerJobTest::FindRegistrationForScope(
249     const GURL& scope,
250     blink::ServiceWorkerStatusCode expected_status) {
251   scoped_refptr<ServiceWorkerRegistration> registration;
252   base::RunLoop run_loop;
253   registry()->FindRegistrationForScope(
254       scope, SaveFoundRegistration(expected_status, &registration,
255                                    run_loop.QuitClosure()));
256   run_loop.Run();
257   return registration;
258 }
259 
CreateControllee()260 ServiceWorkerContainerHost* ServiceWorkerJobTest::CreateControllee() {
261   remote_endpoints_.emplace_back();
262   base::WeakPtr<ServiceWorkerContainerHost> container_host =
263       CreateContainerHostForWindow(
264           33 /* dummy render process id */, true /* is_parent_frame_secure */,
265           helper_->context()->AsWeakPtr(), &remote_endpoints_.back());
266   return container_host.get();
267 }
268 
269 scoped_refptr<ServiceWorkerRegistration>
CreateRegistrationWithControllee(const GURL & script_url,const GURL & scope_url)270 ServiceWorkerJobTest::CreateRegistrationWithControllee(const GURL& script_url,
271                                                        const GURL& scope_url) {
272   blink::mojom::ServiceWorkerRegistrationOptions options;
273   options.scope = scope_url;
274 
275   scoped_refptr<ServiceWorkerRegistration> registration =
276       RunRegisterJob(script_url, options);
277 
278   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
279   registration->SetTaskRunnerForTest(runner);
280 
281   TestServiceWorkerObserver observer(helper_->context_wrapper());
282   observer.RunUntilActivated(registration->installing_version(), runner);
283 
284   ServiceWorkerContainerHost* container_host = CreateControllee();
285   container_host->UpdateUrls(scope_url, net::SiteForCookies::FromUrl(scope_url),
286                              url::Origin::Create(scope_url));
287   container_host->SetControllerRegistration(registration,
288                                             /*notify_controllerchange=*/false);
289   return registration;
290 }
291 
TEST_F(ServiceWorkerJobTest,SameDocumentSameRegistration)292 TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
293   blink::mojom::ServiceWorkerRegistrationOptions options;
294   options.scope = GURL("https://www.example.com/");
295   scoped_refptr<ServiceWorkerRegistration> original_registration =
296       RunRegisterJob(GURL("https://www.example.com/service_worker.js"),
297                      options);
298   scoped_refptr<ServiceWorkerRegistration> registration1;
299   base::RunLoop run_loop;
300   base::RepeatingClosure barrier_closure =
301       base::BarrierClosure(2, run_loop.QuitClosure());
302   registry()->FindRegistrationForClientUrl(
303       GURL("https://www.example.com/"),
304       SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk, &registration1,
305                             barrier_closure));
306   scoped_refptr<ServiceWorkerRegistration> registration2;
307   registry()->FindRegistrationForClientUrl(
308       GURL("https://www.example.com/"),
309       SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk, &registration2,
310                             barrier_closure));
311   run_loop.Run();
312   ASSERT_TRUE(registration1.get());
313   ASSERT_EQ(registration1, original_registration);
314   ASSERT_EQ(registration1, registration2);
315 }
316 
TEST_F(ServiceWorkerJobTest,SameMatchSameRegistration)317 TEST_F(ServiceWorkerJobTest, SameMatchSameRegistration) {
318   blink::mojom::ServiceWorkerRegistrationOptions options;
319   options.scope = GURL("https://www.example.com/");
320   scoped_refptr<ServiceWorkerRegistration> original_registration =
321       RunRegisterJob(GURL("https://www.example.com/service_worker.js"),
322                      options);
323   ASSERT_NE(static_cast<ServiceWorkerRegistration*>(nullptr),
324             original_registration.get());
325 
326   scoped_refptr<ServiceWorkerRegistration> registration1;
327   base::RunLoop run_loop;
328   base::RepeatingClosure barrier_closure =
329       base::BarrierClosure(2, run_loop.QuitClosure());
330   registry()->FindRegistrationForClientUrl(
331       GURL("https://www.example.com/one"),
332       SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk, &registration1,
333                             barrier_closure));
334 
335   scoped_refptr<ServiceWorkerRegistration> registration2;
336   registry()->FindRegistrationForClientUrl(
337       GURL("https://www.example.com/two"),
338       SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk, &registration2,
339                             barrier_closure));
340   run_loop.Run();
341   ASSERT_EQ(registration1, original_registration);
342   ASSERT_EQ(registration1, registration2);
343 }
344 
TEST_F(ServiceWorkerJobTest,DifferentMatchDifferentRegistration)345 TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
346   const GURL scope1("https://www.example.com/one");
347   const GURL scope2("https://www.example.com/two");
348   const GURL script_url("https://www.example.com/service_worker.js");
349   blink::mojom::ServiceWorkerRegistrationOptions options1;
350   options1.scope = scope1;
351   blink::mojom::ServiceWorkerRegistrationOptions options2;
352   options2.scope = scope2;
353 
354   RunRegisterJob(script_url, options1);
355   RunRegisterJob(script_url, options2);
356 
357   scoped_refptr<ServiceWorkerRegistration> registration1;
358   base::RunLoop run_loop;
359   base::RepeatingClosure barrier_closure =
360       base::BarrierClosure(2, run_loop.QuitClosure());
361   registry()->FindRegistrationForClientUrl(
362       scope1, SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk,
363                                     &registration1, barrier_closure));
364   scoped_refptr<ServiceWorkerRegistration> registration2;
365   registry()->FindRegistrationForClientUrl(
366       scope2, SaveFoundRegistration(blink::ServiceWorkerStatusCode::kOk,
367                                     &registration2, barrier_closure));
368 
369   run_loop.Run();
370   ASSERT_NE(registration1, registration2);
371 }
372 
373 class RecordInstallActivateWorker : public FakeServiceWorker {
374  public:
RecordInstallActivateWorker(EmbeddedWorkerTestHelper * helper)375   RecordInstallActivateWorker(EmbeddedWorkerTestHelper* helper)
376       : FakeServiceWorker(helper) {}
377   ~RecordInstallActivateWorker() override = default;
378 
events() const379   const std::vector<ServiceWorkerMetrics::EventType>& events() const {
380     return events_;
381   }
382 
DispatchInstallEvent(blink::mojom::ServiceWorker::DispatchInstallEventCallback callback)383   void DispatchInstallEvent(
384       blink::mojom::ServiceWorker::DispatchInstallEventCallback callback)
385       override {
386     events_.emplace_back(ServiceWorkerMetrics::EventType::INSTALL);
387     FakeServiceWorker::DispatchInstallEvent(std::move(callback));
388   }
389 
DispatchActivateEvent(blink::mojom::ServiceWorker::DispatchActivateEventCallback callback)390   void DispatchActivateEvent(
391       blink::mojom::ServiceWorker::DispatchActivateEventCallback callback)
392       override {
393     events_.emplace_back(ServiceWorkerMetrics::EventType::ACTIVATE);
394     FakeServiceWorker::DispatchActivateEvent(std::move(callback));
395   }
396 
397  private:
398   std::vector<ServiceWorkerMetrics::EventType> events_;
399 };
400 
401 // Make sure basic registration is working.
TEST_F(ServiceWorkerJobTest,Register)402 TEST_F(ServiceWorkerJobTest, Register) {
403   blink::mojom::ServiceWorkerRegistrationOptions options;
404   options.scope = GURL("https://www.example.com/");
405   auto* worker =
406       helper_->AddNewPendingServiceWorker<RecordInstallActivateWorker>(
407           helper_.get());
408   scoped_refptr<ServiceWorkerRegistration> registration = RunRegisterJob(
409       GURL("https://www.example.com/service_worker.js"), options);
410   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
411   registration->SetTaskRunnerForTest(runner);
412   TestServiceWorkerObserver observer(helper_->context_wrapper());
413   observer.RunUntilActivated(registration->installing_version(), runner);
414   scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
415 
416   EXPECT_TRUE(registration);
417   ASSERT_EQ(2u, worker->events().size());
418   EXPECT_EQ(ServiceWorkerMetrics::EventType::INSTALL, worker->events()[0]);
419   EXPECT_EQ(ServiceWorkerMetrics::EventType::ACTIVATE, worker->events()[1]);
420 }
421 
422 // Make sure registrations are cleaned up when they are unregistered.
TEST_F(ServiceWorkerJobTest,Unregister)423 TEST_F(ServiceWorkerJobTest, Unregister) {
424   blink::mojom::ServiceWorkerRegistrationOptions options;
425   options.scope = GURL("https://www.example.com/");
426   scoped_refptr<ServiceWorkerRegistration> registration = RunRegisterJob(
427       GURL("https://www.example.com/service_worker.js"), options);
428   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
429   registration->SetTaskRunnerForTest(runner);
430   TestServiceWorkerObserver observer(helper_->context_wrapper());
431   observer.RunUntilActivated(registration->installing_version(), runner);
432   scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
433 
434   ServiceWorkerHost* worker_host =
435       registration->active_version()->worker_host();
436   ASSERT_NE(nullptr, worker_host);
437   ServiceWorkerContainerHost* container_host = worker_host->container_host();
438   // One ServiceWorkerRegistrationObjectHost should have been created for the
439   // new registration.
440   EXPECT_EQ(1UL, container_host->registration_object_hosts_.size());
441   // One ServiceWorkerObjectHost should have been created for the new service
442   // worker.
443   EXPECT_EQ(1UL, container_host->service_worker_object_hosts_.size());
444 
445   RunUnregisterJob(options.scope);
446 
447   WaitForVersionRunningStatus(version, EmbeddedWorkerStatus::STOPPED);
448   registry()->GetRemoteStorageControl().FlushForTesting();
449 
450   // The service worker registration object host and service worker object host
451   // have been destroyed together with |worker_host| by the above
452   // unregistration. Then |registration| and |version| should be the last one
453   // reference to the corresponding instance.
454   EXPECT_TRUE(registration->HasOneRef());
455   EXPECT_TRUE(version->HasOneRef());
456   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
457   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
458 
459   registration = FindRegistrationForScope(
460       options.scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
461 
462   EXPECT_FALSE(registration);
463 }
464 
TEST_F(ServiceWorkerJobTest,Unregister_NothingRegistered)465 TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) {
466   GURL scope("https://www.example.com/");
467 
468   RunUnregisterJob(scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
469 }
470 
TEST_F(ServiceWorkerJobTest,UnregisterImmediate)471 TEST_F(ServiceWorkerJobTest, UnregisterImmediate) {
472   const GURL scope("https://www.example.com/one/");
473 
474   scoped_refptr<ServiceWorkerRegistration> registration =
475       CreateRegistrationWithControllee(
476           GURL("https://www.example.com/service_worker.js"), scope);
477 
478   EXPECT_NE(nullptr, registration->active_version());
479 
480   base::RunLoop run_loop;
481   job_coordinator()->Unregister(
482       scope, /*is_immediate=*/true,
483       SaveUnregistration(blink::ServiceWorkerStatusCode::kOk,
484                          run_loop.QuitClosure()));
485 
486   run_loop.Run();
487 
488   EXPECT_TRUE(registration->is_uninstalled());
489   EXPECT_EQ(nullptr, registration->active_version());
490   EXPECT_EQ(nullptr, registration->waiting_version());
491   EXPECT_EQ(nullptr, registration->installing_version());
492 }
493 
494 // Make sure registering a new script creates a new version and shares an
495 // existing registration.
TEST_F(ServiceWorkerJobTest,RegisterNewScript)496 TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
497   blink::mojom::ServiceWorkerRegistrationOptions options;
498   options.scope = GURL("https://www.example.com/");
499   scoped_refptr<ServiceWorkerRegistration> old_registration = RunRegisterJob(
500       GURL("https://www.example.com/service_worker.js"), options);
501   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
502   old_registration->SetTaskRunnerForTest(runner);
503   TestServiceWorkerObserver observer(helper_->context_wrapper());
504   observer.RunUntilActivated(old_registration->installing_version(), runner);
505 
506   scoped_refptr<ServiceWorkerRegistration> old_registration_by_scope =
507       FindRegistrationForScope(options.scope);
508 
509   ASSERT_EQ(old_registration, old_registration_by_scope);
510   old_registration_by_scope = nullptr;
511 
512   scoped_refptr<ServiceWorkerRegistration> new_registration = RunRegisterJob(
513       GURL("https://www.example.com/service_worker_new.js"), options);
514 
515   ASSERT_EQ(old_registration, new_registration);
516 
517   scoped_refptr<ServiceWorkerRegistration> new_registration_by_scope =
518       FindRegistrationForScope(options.scope);
519 
520   ASSERT_EQ(new_registration, new_registration_by_scope);
521 }
522 
523 // Make sure that when registering a duplicate scope+script_url
524 // combination, that the same registration is used.
TEST_F(ServiceWorkerJobTest,RegisterDuplicateScript)525 TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
526   GURL script_url("https://www.example.com/service_worker.js");
527   blink::mojom::ServiceWorkerRegistrationOptions options;
528   options.scope = GURL("https://www.example.com/");
529 
530   scoped_refptr<ServiceWorkerRegistration> old_registration =
531       RunRegisterJob(script_url, options);
532   // Wait until the worker becomes active.
533   base::RunLoop().RunUntilIdle();
534 
535   // During the above registration, a service worker registration object host
536   // for ServiceWorkerGlobalScope#registration has been created/added into
537   // |worker_host|.
538   ServiceWorkerHost* worker_host =
539       old_registration->active_version()->worker_host();
540   ASSERT_NE(nullptr, worker_host);
541   ServiceWorkerContainerHost* container_host = worker_host->container_host();
542 
543   // Clear all service worker object hosts.
544   container_host->service_worker_object_hosts_.clear();
545   // Ensure that the registration's object host doesn't have the reference.
546   EXPECT_EQ(1UL, container_host->registration_object_hosts_.size());
547   container_host->registration_object_hosts_.clear();
548   EXPECT_EQ(0UL, container_host->registration_object_hosts_.size());
549   ASSERT_TRUE(old_registration->HasOneRef());
550 
551   scoped_refptr<ServiceWorkerRegistration> old_registration_by_scope =
552       FindRegistrationForScope(options.scope);
553 
554   ASSERT_TRUE(old_registration_by_scope.get());
555 
556   scoped_refptr<ServiceWorkerRegistration> new_registration =
557       RunRegisterJob(script_url, options);
558 
559   ASSERT_EQ(old_registration, new_registration);
560 
561   ASSERT_FALSE(old_registration->HasOneRef());
562 
563   scoped_refptr<ServiceWorkerRegistration> new_registration_by_scope =
564       FindRegistrationForScope(options.scope);
565 
566   EXPECT_EQ(new_registration_by_scope, old_registration);
567 }
568 
569 // An instance client that breaks the Mojo connection upon receiving the
570 // Start() message.
571 class FailStartInstanceClient : public FakeEmbeddedWorkerInstanceClient {
572  public:
FailStartInstanceClient(EmbeddedWorkerTestHelper * helper)573   FailStartInstanceClient(EmbeddedWorkerTestHelper* helper)
574       : FakeEmbeddedWorkerInstanceClient(helper) {}
575 
StartWorker(blink::mojom::EmbeddedWorkerStartParamsPtr params)576   void StartWorker(blink::mojom::EmbeddedWorkerStartParamsPtr params) override {
577     // Don't save the Mojo ptrs. The connection breaks.
578   }
579 };
580 
TEST_F(ServiceWorkerJobTest,Register_FailToStartWorker)581 TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
582   helper_->AddPendingInstanceClient(
583       std::make_unique<FailStartInstanceClient>(helper_.get()));
584 
585   blink::mojom::ServiceWorkerRegistrationOptions options;
586   options.scope = GURL("https://www.example.com/");
587   scoped_refptr<ServiceWorkerRegistration> registration =
588       RunRegisterJob(GURL("https://www.example.com/service_worker.js"), options,
589                      blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed);
590 
591   ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(nullptr), registration);
592 }
593 
594 // Register and then unregister the scope, in parallel. Job coordinator should
595 // process jobs until the last job.
TEST_F(ServiceWorkerJobTest,ParallelRegUnreg)596 TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
597   GURL script_url("https://www.example.com/service_worker.js");
598   blink::mojom::ServiceWorkerRegistrationOptions options;
599   options.scope = GURL("https://www.example.com/");
600   scoped_refptr<ServiceWorkerRegistration> registration =
601       RunRegisterJob(script_url, options);
602 
603   RunUnregisterJob(options.scope);
604 
605   registration = FindRegistrationForScope(
606       options.scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
607 
608   ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
609 }
610 
611 // Register conflicting scripts for the same scope. The most recent
612 // registration should win, and the old registration should have been
613 // shutdown.
TEST_F(ServiceWorkerJobTest,ParallelRegNewScript)614 TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
615   GURL scope("https://www.example.com/");
616 
617   GURL script_url1("https://www.example.com/service_worker1.js");
618   scoped_refptr<ServiceWorkerRegistration> registration1 = RunRegisterJob(
619       script_url1, blink::mojom::ServiceWorkerRegistrationOptions(
620                        scope, blink::mojom::ScriptType::kClassic,
621                        blink::mojom::ServiceWorkerUpdateViaCache::kNone));
622 
623   GURL script_url2("https://www.example.com/service_worker2.js");
624   scoped_refptr<ServiceWorkerRegistration> registration2 = RunRegisterJob(
625       script_url2, blink::mojom::ServiceWorkerRegistrationOptions(
626                        scope, blink::mojom::ScriptType::kClassic,
627                        blink::mojom::ServiceWorkerUpdateViaCache::kAll));
628 
629   scoped_refptr<ServiceWorkerRegistration> registration =
630       FindRegistrationForScope(scope);
631 
632   ASSERT_EQ(registration2, registration);
633 }
634 
635 // Register the exact same scope + script. Requests should be
636 // coalesced such that both callers get the exact same registration
637 // object.
TEST_F(ServiceWorkerJobTest,ParallelRegSameScript)638 TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
639   blink::mojom::ServiceWorkerRegistrationOptions options;
640   options.scope = GURL("https://www.example.com/");
641 
642   GURL script_url("https://www.example.com/service_worker1.js");
643   scoped_refptr<ServiceWorkerRegistration> registration1 =
644       RunRegisterJob(script_url, options);
645 
646   scoped_refptr<ServiceWorkerRegistration> registration2 =
647       RunRegisterJob(script_url, options);
648 
649   ASSERT_EQ(registration1, registration2);
650 
651   scoped_refptr<ServiceWorkerRegistration> registration =
652       FindRegistrationForScope(options.scope);
653 
654   ASSERT_EQ(registration, registration1);
655 }
656 
657 // Call simulataneous unregister calls.
TEST_F(ServiceWorkerJobTest,ParallelUnreg)658 TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
659   GURL scope("https://www.example.com/");
660 
661   GURL script_url("https://www.example.com/service_worker.js");
662   RunUnregisterJob(scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
663 
664   RunUnregisterJob(scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
665 
666   // There isn't really a way to test that they are being coalesced,
667   // but we can make sure they can exist simultaneously without
668   // crashing.
669   scoped_refptr<ServiceWorkerRegistration> registration =
670       FindRegistrationForScope(scope,
671                                blink::ServiceWorkerStatusCode::kErrorNotFound);
672 
673   ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
674 }
675 
TEST_F(ServiceWorkerJobTest,AbortAll_Register)676 TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
677   GURL script_url1("https://www1.example.com/service_worker.js");
678   GURL script_url2("https://www2.example.com/service_worker.js");
679 
680   blink::mojom::ServiceWorkerRegistrationOptions options1;
681   options1.scope = GURL("https://www1.example.com/");
682   blink::mojom::ServiceWorkerRegistrationOptions options2;
683   options2.scope = GURL("https://www2.example.com/");
684 
685   scoped_refptr<ServiceWorkerRegistration> registration1;
686   base::RunLoop run_loop;
687   base::RepeatingClosure barrier_closure =
688       base::BarrierClosure(2, run_loop.QuitClosure());
689   job_coordinator()->Register(
690       script_url1, options1, blink::mojom::FetchClientSettingsObject::New(),
691       SaveRegistration(blink::ServiceWorkerStatusCode::kErrorAbort,
692                        &registration1, barrier_closure));
693 
694   scoped_refptr<ServiceWorkerRegistration> registration2;
695   job_coordinator()->Register(
696       script_url2, options2, blink::mojom::FetchClientSettingsObject::New(),
697       SaveRegistration(blink::ServiceWorkerStatusCode::kErrorAbort,
698                        &registration2, barrier_closure));
699 
700   job_coordinator()->AbortAll();
701 
702   run_loop.Run();
703 
704   registration1 = FindRegistrationForScope(
705       options1.scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
706 
707   registration2 = FindRegistrationForScope(
708       options2.scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
709 
710   EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration1);
711   EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration2);
712 }
713 
TEST_F(ServiceWorkerJobTest,AbortAll_Unregister)714 TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
715   GURL scope1("https://www1.example.com/");
716   GURL scope2("https://www2.example.com/");
717 
718   scoped_refptr<ServiceWorkerRegistration> registration1;
719   base::RunLoop run_loop;
720   base::RepeatingClosure barrier_closure =
721       base::BarrierClosure(2, run_loop.QuitClosure());
722   job_coordinator()->Unregister(
723       scope1, /*is_immediate=*/false,
724       SaveUnregistration(blink::ServiceWorkerStatusCode::kErrorAbort,
725                          barrier_closure));
726 
727   job_coordinator()->Unregister(
728       scope2, /*is_immediate=*/false,
729       SaveUnregistration(blink::ServiceWorkerStatusCode::kErrorAbort,
730                          barrier_closure));
731 
732   job_coordinator()->AbortAll();
733 
734   run_loop.Run();
735 }
736 
TEST_F(ServiceWorkerJobTest,AbortAll_RegUnreg)737 TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
738   GURL script_url("https://www.example.com/service_worker.js");
739   blink::mojom::ServiceWorkerRegistrationOptions options;
740   options.scope = GURL("https://www.example.com/");
741 
742   scoped_refptr<ServiceWorkerRegistration> registration;
743   base::RunLoop run_loop;
744   base::RepeatingClosure barrier_closure =
745       base::BarrierClosure(2, run_loop.QuitClosure());
746   job_coordinator()->Register(
747       script_url, options, blink::mojom::FetchClientSettingsObject::New(),
748       SaveRegistration(blink::ServiceWorkerStatusCode::kErrorAbort,
749                        &registration, barrier_closure));
750 
751   job_coordinator()->Unregister(
752       options.scope, /*is_immediate=*/false,
753       SaveUnregistration(blink::ServiceWorkerStatusCode::kErrorAbort,
754                          barrier_closure));
755 
756   job_coordinator()->AbortAll();
757 
758   run_loop.Run();
759 
760   registration = FindRegistrationForScope(
761       options.scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
762 
763   EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
764 }
765 
TEST_F(ServiceWorkerJobTest,AbortScope)766 TEST_F(ServiceWorkerJobTest, AbortScope) {
767   GURL script_url("https://www.example.com/service_worker.js");
768   blink::mojom::ServiceWorkerRegistrationOptions options1;
769   options1.scope = GURL("https://www.example.com/1");
770   blink::mojom::ServiceWorkerRegistrationOptions options2;
771   options2.scope = GURL("https://www.example.com/2");
772 
773   scoped_refptr<ServiceWorkerRegistration> registration1;
774   base::RunLoop run_loop;
775   base::RepeatingClosure barrier_closure =
776       base::BarrierClosure(2, run_loop.QuitClosure());
777   job_coordinator()->Register(
778       script_url, options1, blink::mojom::FetchClientSettingsObject::New(),
779       SaveRegistration(blink::ServiceWorkerStatusCode::kErrorAbort,
780                        &registration1, barrier_closure));
781 
782   scoped_refptr<ServiceWorkerRegistration> registration2;
783   job_coordinator()->Register(
784       script_url, options2, blink::mojom::FetchClientSettingsObject::New(),
785       SaveRegistration(blink::ServiceWorkerStatusCode::kOk, &registration2,
786                        barrier_closure));
787 
788   job_coordinator()->Abort(options1.scope);
789 
790   run_loop.Run();
791 
792   registration1 = FindRegistrationForScope(
793       options1.scope, blink::ServiceWorkerStatusCode::kErrorNotFound);
794   EXPECT_EQ(nullptr, registration1);
795 
796   registration2 = FindRegistrationForScope(options2.scope,
797                                            blink::ServiceWorkerStatusCode::kOk);
798   EXPECT_NE(nullptr, registration2);
799 }
800 
801 // Tests that the waiting worker enters the 'redundant' state upon
802 // unregistration.
TEST_F(ServiceWorkerJobTest,UnregisterWaitingSetsRedundant)803 TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
804   GURL script_url("https://www.example.com/service_worker.js");
805   blink::mojom::ServiceWorkerRegistrationOptions options;
806   options.scope = GURL("https://www.example.com/");
807   scoped_refptr<ServiceWorkerRegistration> registration =
808       RunRegisterJob(script_url, options);
809   ASSERT_TRUE(registration.get());
810 
811   // Manually create the waiting worker since there is no way to become a
812   // waiting worker until Update is implemented.
813   scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
814       registration.get(), script_url, blink::mojom::ScriptType::kClassic, 1L,
815       mojo::PendingRemote<storage::mojom::ServiceWorkerLiveVersionRef>(),
816       helper_->context()->AsWeakPtr());
817   ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk,
818             StartServiceWorker(version.get()));
819 
820   EXPECT_EQ(version->fetch_handler_existence(),
821             ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
822   version->SetStatus(ServiceWorkerVersion::INSTALLED);
823   registration->SetWaitingVersion(version);
824   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
825   EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version->status());
826 
827   RunUnregisterJob(GURL("https://www.example.com/"));
828   WaitForVersionRunningStatus(version, EmbeddedWorkerStatus::STOPPED);
829 
830   // The version should be stopped since there is no controllee after
831   // unregistration.
832   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
833   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
834 }
835 
836 // Tests that the active worker enters the 'redundant' state upon
837 // unregistration.
TEST_F(ServiceWorkerJobTest,UnregisterActiveSetsRedundant)838 TEST_F(ServiceWorkerJobTest, UnregisterActiveSetsRedundant) {
839   blink::mojom::ServiceWorkerRegistrationOptions options;
840   options.scope = GURL("https://www.example.com/");
841   scoped_refptr<ServiceWorkerRegistration> registration = RunRegisterJob(
842       GURL("https://www.example.com/service_worker.js"), options);
843   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
844   registration->SetTaskRunnerForTest(runner);
845   TestServiceWorkerObserver observer(helper_->context_wrapper());
846   observer.RunUntilActivated(registration->installing_version(), runner);
847   ASSERT_TRUE(registration.get());
848 
849   scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
850   observer.RunUntilStatusChange(version.get(), ServiceWorkerVersion::ACTIVATED);
851   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
852   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
853 
854   RunUnregisterJob(GURL("https://www.example.com/"));
855 
856   WaitForVersionRunningStatus(version, EmbeddedWorkerStatus::STOPPED);
857 
858   // The version should be stopped since there is no controllee after
859   // unregistration.
860   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
861   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
862 }
863 
864 // Tests that the active worker enters the 'redundant' state upon
865 // unregistration.
TEST_F(ServiceWorkerJobTest,UnregisterActiveSetsRedundant_WaitForNoControllee)866 TEST_F(ServiceWorkerJobTest,
867        UnregisterActiveSetsRedundant_WaitForNoControllee) {
868   blink::mojom::ServiceWorkerRegistrationOptions options;
869   options.scope = GURL("https://www.example.com/");
870   scoped_refptr<ServiceWorkerRegistration> registration = RunRegisterJob(
871       GURL("https://www.example.com/service_worker.js"), options);
872   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
873   registration->SetTaskRunnerForTest(runner);
874   TestServiceWorkerObserver observer(helper_->context_wrapper());
875   observer.RunUntilActivated(registration->installing_version(), runner);
876   ASSERT_TRUE(registration.get());
877 
878   ServiceWorkerContainerHost* container_host = CreateControllee();
879   registration->active_version()->AddControllee(container_host);
880 
881   scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
882   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
883   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
884 
885   RunUnregisterJob(GURL("https://www.example.com/"));
886 
887   // The version should be running since there is still a controllee.
888   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
889   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
890 
891   registration->active_version()->RemoveControllee(
892       container_host->client_uuid());
893   WaitForVersionRunningStatus(version, EmbeddedWorkerStatus::STOPPED);
894 
895   // The version should be stopped since there is no controllee.
896   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
897   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
898 }
899 
TEST_F(ServiceWorkerJobTest,RegisterWhileUninstalling)900 TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
901   GURL script1("https://www.example.com/service_worker.js");
902   GURL script2("https://www.example.com/service_worker.js?new");
903   blink::mojom::ServiceWorkerRegistrationOptions options;
904   options.scope = GURL("https://www.example.com/one/");
905 
906   auto* initial_client =
907       helper_->AddNewPendingInstanceClient<FakeEmbeddedWorkerInstanceClient>(
908           helper_.get());
909   scoped_refptr<ServiceWorkerRegistration> registration =
910       RunRegisterJob(script1, options);
911   // Wait until the worker becomes active.
912   base::RunLoop().RunUntilIdle();
913   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
914   registration->SetTaskRunnerForTest(runner);
915 
916   // Add a controllee and queue an unregister to force the uninstalling state.
917   ServiceWorkerContainerHost* container_host = CreateControllee();
918   scoped_refptr<ServiceWorkerVersion> old_version =
919       registration->active_version();
920   old_version->AddControllee(container_host);
921   RunUnregisterJob(options.scope);
922 
923   // Register another script.
924   EXPECT_EQ(registration, RunRegisterJob(script2, options));
925   // Wait until the worker becomes installed.
926   base::RunLoop().RunUntilIdle();
927 
928   EXPECT_FALSE(registration->is_uninstalling());
929   EXPECT_EQ(old_version, registration->active_version());
930   scoped_refptr<ServiceWorkerVersion> new_version =
931       registration->waiting_version();
932 
933   // Verify the new version is installed but not activated yet.
934   EXPECT_EQ(nullptr, registration->installing_version());
935   EXPECT_TRUE(new_version);
936   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
937   EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
938 
939   // Make the old version eligible for eviction.
940   old_version->RemoveControllee(container_host->client_uuid());
941   RequestTermination(&initial_client->host());
942 
943   // Wait for activated.
944   TestServiceWorkerObserver observer(helper_->context_wrapper());
945   observer.RunUntilActivated(new_version.get(), runner);
946 
947   // Verify state after the new version is activated.
948   EXPECT_FALSE(registration->is_uninstalling());
949   EXPECT_FALSE(registration->is_uninstalled());
950   EXPECT_EQ(nullptr, registration->installing_version());
951   EXPECT_EQ(nullptr, registration->waiting_version());
952   EXPECT_EQ(new_version, registration->active_version());
953   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
954 }
955 
TEST_F(ServiceWorkerJobTest,RegisterAndUnregisterWhileUninstalling)956 TEST_F(ServiceWorkerJobTest, RegisterAndUnregisterWhileUninstalling) {
957   GURL script1("https://www.example.com/service_worker.js");
958   GURL script2("https://www.example.com/service_worker.js?new");
959   blink::mojom::ServiceWorkerRegistrationOptions options;
960   options.scope = GURL("https://www.example.com/one/");
961 
962   scoped_refptr<ServiceWorkerRegistration> registration =
963       RunRegisterJob(script1, options);
964   // Wait until the worker becomes active.
965   base::RunLoop().RunUntilIdle();
966 
967   // Add a controllee and queue an unregister to force the uninstalling state.
968   ServiceWorkerContainerHost* container_host = CreateControllee();
969   scoped_refptr<ServiceWorkerVersion> old_version =
970       registration->active_version();
971   old_version->AddControllee(container_host);
972   RunUnregisterJob(options.scope);
973 
974   EXPECT_EQ(registration, RunRegisterJob(script2, options));
975   // Wait until the worker becomes installed.
976   base::RunLoop().RunUntilIdle();
977 
978   EXPECT_EQ(registration, FindRegistrationForScope(options.scope));
979   scoped_refptr<ServiceWorkerVersion> new_version =
980       registration->waiting_version();
981   ASSERT_TRUE(new_version);
982 
983   // Unregister the registration (but it's still live).
984   RunUnregisterJob(options.scope);
985   // Now it's not found in the storage.
986   RunUnregisterJob(options.scope,
987                    blink::ServiceWorkerStatusCode::kErrorNotFound);
988 
989   FindRegistrationForScope(options.scope,
990                            blink::ServiceWorkerStatusCode::kErrorNotFound);
991   EXPECT_TRUE(registration->is_uninstalling());
992   EXPECT_EQ(old_version, registration->active_version());
993 
994   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, old_version->running_status());
995   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, old_version->status());
996   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
997   EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
998 
999   old_version->RemoveControllee(container_host->client_uuid());
1000 
1001   WaitForVersionRunningStatus(old_version, EmbeddedWorkerStatus::STOPPED);
1002   WaitForVersionRunningStatus(new_version, EmbeddedWorkerStatus::STOPPED);
1003 
1004   EXPECT_FALSE(registration->is_uninstalling());
1005   EXPECT_TRUE(registration->is_uninstalled());
1006 
1007   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, old_version->running_status());
1008   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, old_version->status());
1009   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, new_version->running_status());
1010   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, new_version->status());
1011 }
1012 
TEST_F(ServiceWorkerJobTest,RegisterSameScriptMultipleTimesWhileUninstalling)1013 TEST_F(ServiceWorkerJobTest, RegisterSameScriptMultipleTimesWhileUninstalling) {
1014   GURL script1("https://www.example.com/service_worker.js");
1015   GURL script2("https://www.example.com/service_worker.js?new");
1016   blink::mojom::ServiceWorkerRegistrationOptions options;
1017   options.scope = GURL("https://www.example.com/one/");
1018 
1019   auto* initial_client =
1020       helper_->AddNewPendingInstanceClient<FakeEmbeddedWorkerInstanceClient>(
1021           helper_.get());
1022   scoped_refptr<ServiceWorkerRegistration> registration =
1023       RunRegisterJob(script1, options);
1024   // Wait until the worker becomes active.
1025   base::RunLoop().RunUntilIdle();
1026   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
1027   registration->SetTaskRunnerForTest(runner);
1028 
1029   // Add a controllee and queue an unregister to force the uninstalling state.
1030   ServiceWorkerContainerHost* container_host = CreateControllee();
1031   scoped_refptr<ServiceWorkerVersion> old_version =
1032       registration->active_version();
1033   old_version->AddControllee(container_host);
1034   RunUnregisterJob(options.scope);
1035 
1036   EXPECT_EQ(registration, RunRegisterJob(script2, options));
1037   // Wait until the worker becomes installed.
1038   base::RunLoop().RunUntilIdle();
1039 
1040   scoped_refptr<ServiceWorkerVersion> new_version =
1041       registration->waiting_version();
1042   ASSERT_TRUE(new_version);
1043 
1044   RunUnregisterJob(options.scope);
1045 
1046   EXPECT_TRUE(registration->is_uninstalling());
1047 
1048   EXPECT_EQ(registration, RunRegisterJob(script2, options));
1049 
1050   EXPECT_FALSE(registration->is_uninstalling());
1051   EXPECT_EQ(new_version, registration->waiting_version());
1052 
1053   old_version->RemoveControllee(container_host->client_uuid());
1054   RequestTermination(&initial_client->host());
1055 
1056   // Wait for activated.
1057   TestServiceWorkerObserver observer(helper_->context_wrapper());
1058   observer.RunUntilActivated(new_version.get(), runner);
1059 
1060   // Verify state after the new version is activated.
1061   EXPECT_FALSE(registration->is_uninstalling());
1062   EXPECT_FALSE(registration->is_uninstalled());
1063   EXPECT_EQ(nullptr, registration->installing_version());
1064   EXPECT_EQ(nullptr, registration->waiting_version());
1065   EXPECT_EQ(new_version, registration->active_version());
1066   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, new_version->status());
1067 }
1068 
1069 // A fake instance client for toggling whether a fetch event handler exists.
1070 class FetchHandlerInstanceClient : public FakeEmbeddedWorkerInstanceClient {
1071  public:
FetchHandlerInstanceClient(EmbeddedWorkerTestHelper * helper)1072   explicit FetchHandlerInstanceClient(EmbeddedWorkerTestHelper* helper)
1073       : FakeEmbeddedWorkerInstanceClient(helper) {}
1074   ~FetchHandlerInstanceClient() override = default;
1075 
set_has_fetch_handler(bool has_fetch_handler)1076   void set_has_fetch_handler(bool has_fetch_handler) {
1077     has_fetch_handler_ = has_fetch_handler;
1078   }
1079 
1080  protected:
EvaluateScript()1081   void EvaluateScript() override {
1082     host()->OnScriptEvaluationStart();
1083     host()->OnStarted(blink::mojom::ServiceWorkerStartStatus::kNormalCompletion,
1084                       has_fetch_handler_, helper()->GetNextThreadId(),
1085                       blink::mojom::EmbeddedWorkerStartTiming::New());
1086   }
1087 
1088  private:
1089   bool has_fetch_handler_ = false;
1090 };
1091 
TEST_F(ServiceWorkerJobTest,HasFetchHandler)1092 TEST_F(ServiceWorkerJobTest, HasFetchHandler) {
1093   GURL script("https://www.example.com/service_worker.js");
1094   blink::mojom::ServiceWorkerRegistrationOptions options;
1095   options.scope = GURL("https://www.example.com/");
1096   scoped_refptr<ServiceWorkerRegistration> registration;
1097 
1098   auto* fetch_handler_worker =
1099       helper_->AddNewPendingInstanceClient<FetchHandlerInstanceClient>(
1100           helper_.get());
1101   fetch_handler_worker->set_has_fetch_handler(true);
1102   RunRegisterJob(script, options);
1103   // Wait until the worker becomes active.
1104   base::RunLoop().RunUntilIdle();
1105   registration = FindRegistrationForScope(options.scope);
1106   EXPECT_EQ(ServiceWorkerVersion::FetchHandlerExistence::EXISTS,
1107             registration->active_version()->fetch_handler_existence());
1108   RunUnregisterJob(options.scope);
1109 
1110   auto* no_fetch_handler_worker =
1111       helper_->AddNewPendingInstanceClient<FetchHandlerInstanceClient>(
1112           helper_.get());
1113   no_fetch_handler_worker->set_has_fetch_handler(false);
1114   RunRegisterJob(script, options);
1115   // Wait until the worker becomes active.
1116   base::RunLoop().RunUntilIdle();
1117   registration = FindRegistrationForScope(options.scope);
1118   EXPECT_EQ(ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST,
1119             registration->active_version()->fetch_handler_existence());
1120   RunUnregisterJob(options.scope);
1121 }
1122 
1123 // Test that clients are alerted of new registrations if they are
1124 // in-scope, so that Clients.claim() or ServiceWorkerContainer.ready work
1125 // correctly.
TEST_F(ServiceWorkerJobTest,AddRegistrationToMatchingerHosts)1126 TEST_F(ServiceWorkerJobTest, AddRegistrationToMatchingerHosts) {
1127   GURL scope("https://www.example.com/scope/");
1128   GURL in_scope("https://www.example.com/scope/page");
1129   GURL out_scope("https://www.example.com/page");
1130 
1131   // Make an in-scope client.
1132   ServiceWorkerContainerHost* client = CreateControllee();
1133   client->UpdateUrls(in_scope, net::SiteForCookies::FromUrl(in_scope),
1134                      url::Origin::Create(in_scope));
1135 
1136   // Make an in-scope reserved client.
1137   std::unique_ptr<ServiceWorkerContainerHostAndInfo> host_and_info =
1138       CreateContainerHostAndInfoForWindow(helper_->context()->AsWeakPtr(),
1139                                           /*are_ancestors_secure=*/true);
1140   base::WeakPtr<ServiceWorkerContainerHost> reserved_client =
1141       host_and_info->host;
1142   reserved_client->UpdateUrls(in_scope, net::SiteForCookies::FromUrl(in_scope),
1143                               url::Origin::Create(in_scope));
1144 
1145   // Make an out-scope client.
1146   ServiceWorkerContainerHost* out_scope_client = CreateControllee();
1147   out_scope_client->UpdateUrls(out_scope,
1148                                net::SiteForCookies::FromUrl(out_scope),
1149                                url::Origin::Create(out_scope));
1150 
1151   // Make a new registration.
1152   GURL script("https://www.example.com/service_worker.js");
1153   blink::mojom::ServiceWorkerRegistrationOptions options;
1154   options.scope = scope;
1155   scoped_refptr<ServiceWorkerRegistration> registration =
1156       RunRegisterJob(script, options);
1157 
1158   EXPECT_EQ(registration.get(), client->MatchRegistration());
1159   EXPECT_EQ(registration.get(), reserved_client->MatchRegistration());
1160   EXPECT_NE(registration.get(), out_scope_client->MatchRegistration());
1161 }
1162 
1163 namespace {  // Helpers for the update job tests.
1164 
1165 const char kNoChangeOrigin[] = "https://nochange/";
1166 const char kScope[] = "scope/";
1167 const char kScript[] = "script.js";
1168 
1169 const char kHeaders[] =
1170     "HTTP/1.1 200 OK\n"
1171     "Content-Type: application/javascript\n\n";
1172 const char kBody[] = "/* old body */";
1173 const char kNewBody[] = "/* new body */";
1174 
WriteResponse(mojo::Remote<storage::mojom::ServiceWorkerResourceWriter> & writer,const std::string & headers,mojo_base::BigBuffer body)1175 void WriteResponse(
1176     mojo::Remote<storage::mojom::ServiceWorkerResourceWriter>& writer,
1177     const std::string& headers,
1178     mojo_base::BigBuffer body) {
1179   int length = body.size();
1180   auto response_head = network::mojom::URLResponseHead::New();
1181   response_head->request_time = base::Time::Now();
1182   response_head->response_time = base::Time::Now();
1183   response_head->headers = new net::HttpResponseHeaders(headers);
1184   response_head->content_length = length;
1185 
1186   int rv = -1234;
1187   {
1188     base::RunLoop loop(base::RunLoop::Type::kNestableTasksAllowed);
1189     writer->WriteResponseHead(std::move(response_head),
1190                               base::BindLambdaForTesting([&](int result) {
1191                                 rv = result;
1192                                 loop.Quit();
1193                               }));
1194     loop.Run();
1195     EXPECT_LT(0, rv);
1196   }
1197 
1198   rv = -1234;
1199   {
1200     base::RunLoop loop(base::RunLoop::Type::kNestableTasksAllowed);
1201     writer->WriteData(std::move(body),
1202                       base::BindLambdaForTesting([&](int result) {
1203                         rv = result;
1204                         loop.Quit();
1205                       }));
1206     loop.Run();
1207     EXPECT_EQ(length, rv);
1208   }
1209 }
1210 
WriteStringResponse(mojo::Remote<storage::mojom::ServiceWorkerResourceWriter> & writer,const std::string & body)1211 void WriteStringResponse(
1212     mojo::Remote<storage::mojom::ServiceWorkerResourceWriter>& writer,
1213     const std::string& body) {
1214   mojo_base::BigBuffer body_buffer(base::as_bytes(base::make_span(body)));
1215   const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0\0";
1216   std::string headers(kHttpHeaders, base::size(kHttpHeaders));
1217   WriteResponse(writer, headers, std::move(body_buffer));
1218 }
1219 
1220 class UpdateJobTestHelper : public EmbeddedWorkerTestHelper,
1221                             public ServiceWorkerRegistration::Listener,
1222                             public ServiceWorkerContextCoreObserver {
1223  public:
1224   struct AttributeChangeLogEntry {
1225     int64_t registration_id;
1226     blink::mojom::ChangedServiceWorkerObjectsMaskPtr mask;
1227     ServiceWorkerRegistrationInfo info;
1228   };
1229 
1230   struct StateChangeLogEntry {
1231     int64_t version_id;
1232     ServiceWorkerVersion::Status status;
1233   };
1234 
UpdateJobTestHelper()1235   UpdateJobTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {
1236     context_wrapper()->AddObserver(this);
1237     interceptor_ = std::make_unique<URLLoaderInterceptor>(base::BindRepeating(
1238         &FakeNetwork::HandleRequest, base::Unretained(&fake_network_)));
1239     fake_network_.SetDefaultResponse(kHeaders, kBody,
1240                                      /*network_accessed=*/true, net::OK);
1241   }
~UpdateJobTestHelper()1242   ~UpdateJobTestHelper() override {
1243     context_wrapper()->RemoveObserver(this);
1244     if (observed_registration_.get())
1245       observed_registration_->RemoveListener(this);
1246   }
1247 
1248   class ScriptFailureEmbeddedWorkerInstanceClient
1249       : public FakeEmbeddedWorkerInstanceClient {
1250    public:
ScriptFailureEmbeddedWorkerInstanceClient(UpdateJobTestHelper * helper)1251     explicit ScriptFailureEmbeddedWorkerInstanceClient(
1252         UpdateJobTestHelper* helper)
1253         : FakeEmbeddedWorkerInstanceClient(helper) {}
1254     ~ScriptFailureEmbeddedWorkerInstanceClient() override = default;
1255 
StartWorker(blink::mojom::EmbeddedWorkerStartParamsPtr params)1256     void StartWorker(
1257         blink::mojom::EmbeddedWorkerStartParamsPtr params) override {
1258       host().Bind(std::move(params->instance_host));
1259       start_params_ = std::move(params);
1260 
1261       helper()->OnServiceWorkerReceiver(
1262           std::move(start_params_->service_worker_receiver));
1263     }
1264 
SimulateFailureOfScriptEvaluation()1265     void SimulateFailureOfScriptEvaluation() {
1266       host()->OnScriptEvaluationStart();
1267       host()->OnStarted(
1268           blink::mojom::ServiceWorkerStartStatus::kAbruptCompletion,
1269           /*has_fetch_handler=*/false, helper()->GetNextThreadId(),
1270           blink::mojom::EmbeddedWorkerStartTiming::New());
1271     }
1272 
1273    private:
1274     blink::mojom::EmbeddedWorkerStartParamsPtr start_params_;
1275   };
1276 
1277   class ScriptFailureServiceWorker : public FakeServiceWorker {
1278    public:
ScriptFailureServiceWorker(EmbeddedWorkerTestHelper * helper,ScriptFailureEmbeddedWorkerInstanceClient * client)1279     ScriptFailureServiceWorker(
1280         EmbeddedWorkerTestHelper* helper,
1281         ScriptFailureEmbeddedWorkerInstanceClient* client)
1282         : FakeServiceWorker(helper), client_(client) {}
1283 
InitializeGlobalScope(mojo::PendingAssociatedRemote<blink::mojom::ServiceWorkerHost>,blink::mojom::ServiceWorkerRegistrationObjectInfoPtr,blink::mojom::ServiceWorkerObjectInfoPtr,blink::mojom::FetchHandlerExistence,std::unique_ptr<blink::PendingURLLoaderFactoryBundle>,mojo::PendingReceiver<blink::mojom::ReportingObserver>)1284     void InitializeGlobalScope(
1285         mojo::PendingAssociatedRemote<blink::mojom::ServiceWorkerHost>,
1286         blink::mojom::ServiceWorkerRegistrationObjectInfoPtr,
1287         blink::mojom::ServiceWorkerObjectInfoPtr,
1288         blink::mojom::FetchHandlerExistence,
1289         std::unique_ptr<blink::PendingURLLoaderFactoryBundle>,
1290         mojo::PendingReceiver<blink::mojom::ReportingObserver>) override {
1291       client_->SimulateFailureOfScriptEvaluation();
1292     }
1293 
1294    private:
1295     ScriptFailureEmbeddedWorkerInstanceClient* client_;
1296   };
1297 
job_coordinator()1298   ServiceWorkerJobCoordinator* job_coordinator() {
1299     return context()->job_coordinator();
1300   }
1301 
SetupInitialRegistration(const GURL & test_origin)1302   scoped_refptr<ServiceWorkerRegistration> SetupInitialRegistration(
1303       const GURL& test_origin) {
1304     blink::mojom::ServiceWorkerRegistrationOptions options;
1305     options.scope = test_origin.Resolve(kScope);
1306     scoped_refptr<ServiceWorkerRegistration> registration;
1307 
1308     auto client = std::make_unique<FakeEmbeddedWorkerInstanceClient>(this);
1309     initial_embedded_worker_instance_client_ = client.get();
1310     AddPendingInstanceClient(std::move(client));
1311     base::RunLoop run_loop;
1312     job_coordinator()->Register(
1313         test_origin.Resolve(kScript), options,
1314         blink::mojom::FetchClientSettingsObject::New(),
1315         SaveRegistration(blink::ServiceWorkerStatusCode::kOk, &registration,
1316                          run_loop.QuitClosure()));
1317     run_loop.Run();
1318     // Wait until the worker becomes active.
1319     base::RunLoop().RunUntilIdle();
1320     EXPECT_TRUE(registration.get());
1321     EXPECT_TRUE(registration->active_version());
1322     EXPECT_FALSE(registration->installing_version());
1323     EXPECT_FALSE(registration->waiting_version());
1324     observed_registration_ = registration;
1325     return registration;
1326   }
1327 
1328   // EmbeddedWorkerTestHelper overrides:
PopulateScriptCacheMap(int64_t version_id,base::OnceClosure callback)1329   void PopulateScriptCacheMap(int64_t version_id,
1330                               base::OnceClosure callback) override {
1331     context()->GetStorageControl()->GetNewResourceId(base::BindOnce(
1332         &UpdateJobTestHelper::DidGetNewResourceIdForScriptCache,
1333         weak_factory_.GetWeakPtr(), version_id, std::move(callback)));
1334   }
1335 
DidGetNewResourceIdForScriptCache(int64_t version_id,base::OnceClosure callback,int64_t resource_id)1336   void DidGetNewResourceIdForScriptCache(int64_t version_id,
1337                                          base::OnceClosure callback,
1338                                          int64_t resource_id) {
1339     ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
1340     ASSERT_TRUE(version);
1341     ServiceWorkerRegistration* registration =
1342         context()->GetLiveRegistration(version->registration_id());
1343     ASSERT_TRUE(registration);
1344     GURL script = version->script_url();
1345     bool is_update = registration->active_version() &&
1346                      version != registration->active_version();
1347 
1348     mojo::Remote<storage::mojom::ServiceWorkerResourceWriter> writer;
1349     context()->GetStorageControl()->CreateResourceWriter(
1350         resource_id, writer.BindNewPipeAndPassReceiver());
1351     version->script_cache_map()->NotifyStartedCaching(script, resource_id);
1352     if (!is_update) {
1353       // Spoof caching the script for the initial version.
1354       WriteStringResponse(writer, kBody);
1355       version->script_cache_map()->NotifyFinishedCaching(
1356           script, base::size(kBody), net::OK, std::string());
1357     } else {
1358       EXPECT_NE(GURL(kNoChangeOrigin), script.GetOrigin());
1359       // The script must be changed.
1360       WriteStringResponse(writer, kNewBody);
1361       version->script_cache_map()->NotifyFinishedCaching(
1362           script, base::size(kNewBody), net::OK, std::string());
1363     }
1364 
1365     version->SetMainScriptResponse(CreateMainScriptResponse());
1366     std::move(callback).Run();
1367   }
1368 
1369   // ServiceWorkerContextCoreObserver overrides
OnVersionStateChanged(int64_t version_id,const GURL & scope,ServiceWorkerVersion::Status status)1370   void OnVersionStateChanged(int64_t version_id,
1371                              const GURL& scope,
1372                              ServiceWorkerVersion::Status status) override {
1373     StateChangeLogEntry entry;
1374     entry.version_id = version_id;
1375     entry.status = status;
1376     state_change_log_.push_back(std::move(entry));
1377   }
1378 
1379   // ServiceWorkerRegistration::Listener overrides
OnVersionAttributesChanged(ServiceWorkerRegistration * registration,blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask)1380   void OnVersionAttributesChanged(
1381       ServiceWorkerRegistration* registration,
1382       blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask) override {
1383     AttributeChangeLogEntry entry;
1384     entry.registration_id = registration->id();
1385     entry.mask = std::move(changed_mask);
1386     entry.info = registration->GetInfo();
1387     attribute_change_log_.push_back(std::move(entry));
1388   }
1389 
OnRegistrationFailed(ServiceWorkerRegistration * registration)1390   void OnRegistrationFailed(ServiceWorkerRegistration* registration) override {
1391     registration_failed_ = true;
1392   }
1393 
OnUpdateFound(ServiceWorkerRegistration * registration)1394   void OnUpdateFound(ServiceWorkerRegistration* registration) override {
1395     update_found_ = true;
1396   }
1397 
1398   FakeEmbeddedWorkerInstanceClient* initial_embedded_worker_instance_client_ =
1399       nullptr;
1400   scoped_refptr<ServiceWorkerRegistration> observed_registration_;
1401   std::vector<AttributeChangeLogEntry> attribute_change_log_;
1402   std::vector<StateChangeLogEntry> state_change_log_;
1403   bool update_found_ = false;
1404   bool registration_failed_ = false;
1405   bool force_start_worker_failure_ = false;
1406   base::Optional<bool> will_be_terminated_;
1407 
1408   // These are used only when ServiceWorkerImportedScriptUpdateCheck is enabled.
1409   FakeNetwork fake_network_;
1410   std::unique_ptr<URLLoaderInterceptor> interceptor_;
1411 
1412   base::WeakPtrFactory<UpdateJobTestHelper> weak_factory_{this};
1413 };
1414 
1415 }  // namespace
1416 
1417 // This class is for cases that can be impacted by different update check
1418 // types.
1419 class ServiceWorkerUpdateJobTest : public ServiceWorkerJobTest {
1420  public:
SetUp()1421   void SetUp() override {
1422     update_helper_ = new UpdateJobTestHelper();
1423     helper_.reset(update_helper_);
1424 
1425     // Create a StoragePartition with the testing browser context so that the
1426     // ServiceWorkerUpdateChecker can find the BrowserContext through it.
1427     storage_partition_impl_ = StoragePartitionImpl::Create(
1428         helper_->browser_context(), /* in_memory= */ true, base::FilePath(),
1429         /* partition_domain= */ "");
1430     storage_partition_impl_->Initialize();
1431     helper_->context_wrapper()->set_storage_partition(
1432         storage_partition_impl_.get());
1433   }
1434 
1435  protected:
1436   std::unique_ptr<StoragePartitionImpl> storage_partition_impl_;
1437   UpdateJobTestHelper* update_helper_;
1438 };
1439 
1440 // Make sure that the same registration is used and the update_via_cache value
1441 // is updated when registering a service worker with the same parameter except
1442 // for updateViaCache.
TEST_F(ServiceWorkerUpdateJobTest,RegisterWithDifferentUpdateViaCache)1443 TEST_F(ServiceWorkerUpdateJobTest, RegisterWithDifferentUpdateViaCache) {
1444   const GURL script_url("https://www.example.com/service_worker.js");
1445   blink::mojom::ServiceWorkerRegistrationOptions options;
1446   options.scope = GURL("https://www.example.com/");
1447 
1448   scoped_refptr<ServiceWorkerRegistration> old_registration =
1449       RunRegisterJob(script_url, options);
1450   // Wait until the worker becomes active.
1451   base::RunLoop().RunUntilIdle();
1452 
1453   EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kImports,
1454             old_registration->update_via_cache());
1455 
1456   // During the above registration, a service worker registration object host
1457   // for ServiceWorkerGlobalScope#registration has been created/added into
1458   // |worker_host|.
1459   ServiceWorkerHost* worker_host =
1460       old_registration->active_version()->worker_host();
1461   ASSERT_TRUE(worker_host);
1462   ServiceWorkerContainerHost* container_host = worker_host->container_host();
1463 
1464   // Remove references to |old_registration| so that |old_registration| is the
1465   // only reference to the registration.
1466   container_host->service_worker_object_hosts_.clear();
1467   EXPECT_EQ(1UL, container_host->registration_object_hosts_.size());
1468   container_host->registration_object_hosts_.clear();
1469   EXPECT_EQ(0UL, container_host->registration_object_hosts_.size());
1470   EXPECT_TRUE(old_registration->HasOneRef());
1471 
1472   EXPECT_TRUE(FindRegistrationForScope(options.scope));
1473 
1474   base::HistogramTester histogram_tester;
1475   options.update_via_cache = blink::mojom::ServiceWorkerUpdateViaCache::kNone;
1476   scoped_refptr<ServiceWorkerRegistration> new_registration =
1477       RunRegisterJob(script_url, options);
1478 
1479   // Ensure that the registration object is not copied.
1480   EXPECT_EQ(old_registration, new_registration);
1481   EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kNone,
1482             new_registration->update_via_cache());
1483 
1484   scoped_refptr<ServiceWorkerRegistration> new_registration_by_scope =
1485       FindRegistrationForScope(options.scope);
1486 
1487   EXPECT_EQ(new_registration_by_scope, old_registration);
1488 }
1489 
TEST_F(ServiceWorkerUpdateJobTest,Update_NoChange)1490 TEST_F(ServiceWorkerUpdateJobTest, Update_NoChange) {
1491   scoped_refptr<ServiceWorkerRegistration> registration =
1492       update_helper_->SetupInitialRegistration(GURL(kNoChangeOrigin));
1493   ASSERT_TRUE(registration.get());
1494   ASSERT_EQ(4u, update_helper_->state_change_log_.size());
1495   EXPECT_EQ(ServiceWorkerVersion::INSTALLING,
1496             update_helper_->state_change_log_[0].status);
1497   EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
1498             update_helper_->state_change_log_[1].status);
1499   EXPECT_EQ(ServiceWorkerVersion::ACTIVATING,
1500             update_helper_->state_change_log_[2].status);
1501   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
1502             update_helper_->state_change_log_[3].status);
1503   update_helper_->state_change_log_.clear();
1504 
1505   // Run the update job.
1506   base::HistogramTester histogram_tester;
1507   registration->AddListener(update_helper_);
1508   scoped_refptr<ServiceWorkerVersion> first_version =
1509       registration->active_version();
1510   first_version->StartUpdate();
1511   base::RunLoop().RunUntilIdle();
1512 
1513   // Verify results.
1514   ASSERT_TRUE(registration->active_version());
1515   EXPECT_EQ(first_version.get(), registration->active_version());
1516   EXPECT_FALSE(registration->installing_version());
1517   EXPECT_FALSE(registration->waiting_version());
1518   EXPECT_TRUE(update_helper_->attribute_change_log_.empty());
1519   EXPECT_FALSE(update_helper_->update_found_);
1520 }
1521 
TEST_F(ServiceWorkerUpdateJobTest,Update_BumpLastUpdateCheckTime)1522 TEST_F(ServiceWorkerUpdateJobTest, Update_BumpLastUpdateCheckTime) {
1523   const base::Time kToday = base::Time::Now();
1524   const base::Time kYesterday =
1525       kToday - base::TimeDelta::FromDays(1) - base::TimeDelta::FromHours(1);
1526   const GURL kNewVersionOrigin("https://newversion/");
1527 
1528   scoped_refptr<ServiceWorkerRegistration> registration =
1529       update_helper_->SetupInitialRegistration(GURL(kNoChangeOrigin));
1530   ASSERT_TRUE(registration.get());
1531 
1532   registration->AddListener(update_helper_);
1533 
1534   // Run an update where the script did not change and the network was not
1535   // accessed. The check time should not be updated.
1536   // Set network not accessed.
1537   update_helper_->fake_network_.SetResponse(
1538       GURL(kNoChangeOrigin).Resolve(kScript), kHeaders, kBody,
1539       /*network_accessed=*/false, net::OK);
1540 
1541   {
1542     base::HistogramTester histogram_tester;
1543     registration->set_last_update_check(kToday);
1544     registration->active_version()->StartUpdate();
1545     base::RunLoop().RunUntilIdle();
1546     EXPECT_EQ(kToday, registration->last_update_check());
1547     EXPECT_FALSE(update_helper_->update_found_);
1548   }
1549 
1550   // Run an update where the script did not change and the network was
1551   // accessed. The check time should be updated.
1552   // Set network accessed.
1553   update_helper_->fake_network_.SetResponse(
1554       GURL(kNoChangeOrigin).Resolve(kScript), kHeaders, kBody,
1555       /*network_accessed=*/true, net::OK);
1556 
1557   {
1558     base::HistogramTester histogram_tester;
1559     registration->set_last_update_check(kYesterday);
1560     registration->active_version()->StartUpdate();
1561     base::RunLoop().RunUntilIdle();
1562     EXPECT_LT(kYesterday, registration->last_update_check());
1563     EXPECT_FALSE(update_helper_->update_found_);
1564     registration->RemoveListener(update_helper_);
1565     registration = update_helper_->SetupInitialRegistration(kNewVersionOrigin);
1566     ASSERT_TRUE(registration.get());
1567   }
1568 
1569   registration->AddListener(update_helper_);
1570 
1571   // Run an update where the script changed. The check time should be updated.
1572   // Change script body.
1573   update_helper_->fake_network_.SetResponse(kNewVersionOrigin.Resolve(kScript),
1574                                             kHeaders, kNewBody,
1575                                             /*network_accessed=*/true, net::OK);
1576   {
1577     base::HistogramTester histogram_tester;
1578     registration->set_last_update_check(kYesterday);
1579     registration->active_version()->StartUpdate();
1580     base::RunLoop().RunUntilIdle();
1581     EXPECT_LT(kYesterday, registration->last_update_check());
1582   }
1583 
1584   // Run an update to a worker that loads successfully but fails to start up
1585   // (script evaluation failure). The check time should be updated.
1586   auto* embedded_worker_instance_client =
1587       update_helper_->AddNewPendingInstanceClient<
1588           UpdateJobTestHelper::ScriptFailureEmbeddedWorkerInstanceClient>(
1589           update_helper_);
1590   update_helper_->AddNewPendingServiceWorker<
1591       UpdateJobTestHelper::ScriptFailureServiceWorker>(
1592       update_helper_, embedded_worker_instance_client);
1593   registration->set_last_update_check(kYesterday);
1594   // Change script body.
1595   update_helper_->fake_network_.SetResponse(kNewVersionOrigin.Resolve(kScript),
1596                                             kHeaders, kBody,
1597                                             /*network_accessed=*/true, net::OK);
1598   {
1599     base::HistogramTester histogram_tester;
1600     registration->active_version()->StartUpdate();
1601     base::RunLoop().RunUntilIdle();
1602     EXPECT_LT(kYesterday, registration->last_update_check());
1603   }
1604 }
1605 
TEST_F(ServiceWorkerUpdateJobTest,Update_NewVersion)1606 TEST_F(ServiceWorkerUpdateJobTest, Update_NewVersion) {
1607   const GURL kNewVersionOrigin("https://newversion/");
1608 
1609   scoped_refptr<ServiceWorkerRegistration> registration =
1610       update_helper_->SetupInitialRegistration(kNewVersionOrigin);
1611   ASSERT_TRUE(registration.get());
1612   update_helper_->state_change_log_.clear();
1613   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
1614   registration->SetTaskRunnerForTest(runner);
1615 
1616   // Run the update job and an update is found.
1617   // Change script body.
1618   update_helper_->fake_network_.SetResponse(kNewVersionOrigin.Resolve(kScript),
1619                                             kHeaders, kNewBody,
1620                                             /*network_accessed=*/true, net::OK);
1621 
1622   base::HistogramTester histogram_tester;
1623   registration->AddListener(update_helper_);
1624   scoped_refptr<ServiceWorkerVersion> first_version =
1625       registration->active_version();
1626   first_version->StartUpdate();
1627   base::RunLoop().RunUntilIdle();
1628 
1629   // The worker is updated after RequestTermination() is called from the
1630   // renderer. Until then, the active version stays active.
1631   EXPECT_EQ(first_version.get(), registration->active_version());
1632   // The new worker is installed but not yet to be activated.
1633   scoped_refptr<ServiceWorkerVersion> new_version =
1634       registration->waiting_version();
1635   EXPECT_EQ(2u, update_helper_->attribute_change_log_.size());
1636   RequestTermination(
1637       &(update_helper_->initial_embedded_worker_instance_client_->host()));
1638 
1639   TestServiceWorkerObserver observer(helper_->context_wrapper());
1640   observer.RunUntilActivated(new_version.get(), runner);
1641 
1642   // Pump the loop again. This ensures |update_helper_| observes all
1643   // the status changes, since RunUntilActivated() only ensured
1644   // ServiceWorkerJobTest did.
1645   base::RunLoop().RunUntilIdle();
1646 
1647   // Verify results.
1648   ASSERT_TRUE(registration->active_version());
1649   EXPECT_NE(first_version.get(), registration->active_version());
1650   EXPECT_FALSE(registration->installing_version());
1651   EXPECT_FALSE(registration->waiting_version());
1652   ASSERT_EQ(3u, update_helper_->attribute_change_log_.size());
1653 
1654   {
1655     const UpdateJobTestHelper::AttributeChangeLogEntry& entry =
1656         update_helper_->attribute_change_log_[0];
1657     EXPECT_TRUE(entry.mask->installing);
1658     EXPECT_FALSE(entry.mask->waiting);
1659     EXPECT_FALSE(entry.mask->active);
1660     EXPECT_NE(entry.info.installing_version.version_id,
1661               blink::mojom::kInvalidServiceWorkerVersionId);
1662     EXPECT_EQ(entry.info.waiting_version.version_id,
1663               blink::mojom::kInvalidServiceWorkerVersionId);
1664     EXPECT_NE(entry.info.active_version.version_id,
1665               blink::mojom::kInvalidServiceWorkerVersionId);
1666   }
1667 
1668   {
1669     const UpdateJobTestHelper::AttributeChangeLogEntry& entry =
1670         update_helper_->attribute_change_log_[1];
1671     EXPECT_TRUE(entry.mask->installing);
1672     EXPECT_TRUE(entry.mask->waiting);
1673     EXPECT_FALSE(entry.mask->active);
1674     EXPECT_EQ(entry.info.installing_version.version_id,
1675               blink::mojom::kInvalidServiceWorkerVersionId);
1676     EXPECT_NE(entry.info.waiting_version.version_id,
1677               blink::mojom::kInvalidServiceWorkerVersionId);
1678     EXPECT_NE(entry.info.active_version.version_id,
1679               blink::mojom::kInvalidServiceWorkerVersionId);
1680   }
1681 
1682   {
1683     const UpdateJobTestHelper::AttributeChangeLogEntry& entry =
1684         update_helper_->attribute_change_log_[2];
1685     EXPECT_FALSE(entry.mask->installing);
1686     EXPECT_TRUE(entry.mask->waiting);
1687     EXPECT_TRUE(entry.mask->active);
1688     EXPECT_EQ(entry.info.installing_version.version_id,
1689               blink::mojom::kInvalidServiceWorkerVersionId);
1690     EXPECT_EQ(entry.info.waiting_version.version_id,
1691               blink::mojom::kInvalidServiceWorkerVersionId);
1692     EXPECT_NE(entry.info.active_version.version_id,
1693               blink::mojom::kInvalidServiceWorkerVersionId);
1694   }
1695 
1696   // expected version state transitions:
1697   // new.installing, new.installed,
1698   // old.redundant,
1699   // new.activating, new.activated
1700   ASSERT_EQ(5u, update_helper_->state_change_log_.size());
1701 
1702   EXPECT_EQ(registration->active_version()->version_id(),
1703             update_helper_->state_change_log_[0].version_id);
1704   EXPECT_EQ(ServiceWorkerVersion::INSTALLING,
1705             update_helper_->state_change_log_[0].status);
1706 
1707   EXPECT_EQ(registration->active_version()->version_id(),
1708             update_helper_->state_change_log_[1].version_id);
1709   EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
1710             update_helper_->state_change_log_[1].status);
1711 
1712   EXPECT_EQ(first_version->version_id(),
1713             update_helper_->state_change_log_[2].version_id);
1714   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT,
1715             update_helper_->state_change_log_[2].status);
1716 
1717   EXPECT_EQ(registration->active_version()->version_id(),
1718             update_helper_->state_change_log_[3].version_id);
1719   EXPECT_EQ(ServiceWorkerVersion::ACTIVATING,
1720             update_helper_->state_change_log_[3].status);
1721 
1722   EXPECT_EQ(registration->active_version()->version_id(),
1723             update_helper_->state_change_log_[4].version_id);
1724   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
1725             update_helper_->state_change_log_[4].status);
1726 
1727   EXPECT_TRUE(update_helper_->update_found_);
1728 }
1729 
1730 // Test that the update job uses the script URL of the newest worker when the
1731 // job starts, rather than when it is scheduled.
TEST_F(ServiceWorkerUpdateJobTest,Update_ScriptUrlChanged)1732 TEST_F(ServiceWorkerUpdateJobTest, Update_ScriptUrlChanged) {
1733   const GURL old_script("https://www.example.com/service_worker.js");
1734   const GURL new_script("https://www.example.com/new_worker.js");
1735 
1736   // Create a registration with an active version.
1737   blink::mojom::ServiceWorkerRegistrationOptions options;
1738   options.scope = GURL("https://www.example.com/one/");
1739   auto* initial_client =
1740       helper_->AddNewPendingInstanceClient<FakeEmbeddedWorkerInstanceClient>(
1741           helper_.get());
1742   // Setup the old script response.
1743   update_helper_->fake_network_.SetResponse(old_script, kHeaders, kBody,
1744                                             /*network_accessed=*/true, net::OK);
1745   scoped_refptr<ServiceWorkerRegistration> registration =
1746       RunRegisterJob(old_script, options);
1747   // Wait until the worker becomes active.
1748   base::RunLoop().RunUntilIdle();
1749   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
1750   registration->SetTaskRunnerForTest(runner);
1751 
1752   // Queue an Update. When this runs, it will use the waiting version's script.
1753   job_coordinator()->Update(registration.get(), false);
1754 
1755   // Add a waiting version with a new script.
1756   scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
1757       registration.get(), new_script, blink::mojom::ScriptType::kClassic,
1758       2L /* dummy version id */,
1759       mojo::PendingRemote<storage::mojom::ServiceWorkerLiveVersionRef>(),
1760       helper_->context()->AsWeakPtr());
1761   registration->SetWaitingVersion(version);
1762 
1763   // Setup the new script response.
1764   update_helper_->fake_network_.SetResponse(new_script, kHeaders, kNewBody,
1765                                             /*network_accessed=*/true, net::OK);
1766 
1767   // Make sure the storage has the data of the current waiting version.
1768   const int64_t resource_id = 2;
1769   mojo::Remote<storage::mojom::ServiceWorkerResourceWriter> writer;
1770   context()->GetStorageControl()->CreateResourceWriter(
1771       resource_id, writer.BindNewPipeAndPassReceiver());
1772   version->script_cache_map()->NotifyStartedCaching(new_script, resource_id);
1773   WriteStringResponse(writer, kBody);
1774   version->script_cache_map()->NotifyFinishedCaching(
1775       new_script, base::size(kBody), net::OK, std::string());
1776 
1777   // Run the update job.
1778   base::RunLoop().RunUntilIdle();
1779 
1780   // The worker is activated after RequestTermination() is called from the
1781   // renderer. Until then, the active version stays active.
1782   // Still waiting, but the waiting version isn't |version| since another
1783   // ServiceWorkerVersion is created during the update job and the job wipes
1784   // out the older waiting version.
1785   ServiceWorkerVersion* waiting_version = registration->waiting_version();
1786   EXPECT_TRUE(registration->active_version());
1787   EXPECT_TRUE(waiting_version);
1788   EXPECT_NE(version.get(), waiting_version);
1789 
1790   RequestTermination(&initial_client->host());
1791   TestServiceWorkerObserver observer(helper_->context_wrapper());
1792   observer.RunUntilActivated(waiting_version, runner);
1793 
1794   // The update job should have created a new version with the new script,
1795   // and promoted it to the active version.
1796   EXPECT_EQ(new_script, registration->active_version()->script_url());
1797   EXPECT_EQ(nullptr, registration->waiting_version());
1798   EXPECT_EQ(nullptr, registration->installing_version());
1799 }
1800 
1801 // Test that update fails if the incumbent worker was evicted
1802 // during the update job (this can happen on disk cache failure).
TEST_F(ServiceWorkerUpdateJobTest,Update_EvictedIncumbent)1803 TEST_F(ServiceWorkerUpdateJobTest, Update_EvictedIncumbent) {
1804   const GURL kNewVersionOrigin("https://newversion/");
1805 
1806   scoped_refptr<ServiceWorkerRegistration> registration =
1807       update_helper_->SetupInitialRegistration(kNewVersionOrigin);
1808   ASSERT_TRUE(registration.get());
1809   update_helper_->state_change_log_.clear();
1810 
1811   registration->AddListener(update_helper_);
1812   scoped_refptr<ServiceWorkerVersion> first_version =
1813       registration->active_version();
1814   auto* instance_client = helper_->AddNewPendingInstanceClient<
1815       DelayedFakeEmbeddedWorkerInstanceClient>(helper_.get());
1816 
1817   // Start the update job and make it block on the worker starting.
1818   // Evict the incumbent during that time.
1819   // Change script body.
1820   update_helper_->fake_network_.SetResponse(kNewVersionOrigin.Resolve(kScript),
1821                                             kHeaders, kNewBody,
1822                                             /*network_accessed=*/true, net::OK);
1823 
1824   first_version->StartUpdate();
1825   instance_client->RunUntilStartWorker();
1826   registration->ForceDelete();
1827 
1828   // Finish the update job.
1829   instance_client->UnblockStartWorker();
1830   base::RunLoop().RunUntilIdle();
1831 
1832   // Verify results.
1833   EXPECT_FALSE(registration->GetNewestVersion());
1834   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, first_version->status());
1835   EXPECT_TRUE(update_helper_->attribute_change_log_.empty());
1836   EXPECT_FALSE(update_helper_->update_found_);
1837   EXPECT_TRUE(update_helper_->registration_failed_);
1838   EXPECT_TRUE(registration->is_uninstalled());
1839 }
1840 
TEST_F(ServiceWorkerUpdateJobTest,Update_UninstallingRegistration)1841 TEST_F(ServiceWorkerUpdateJobTest, Update_UninstallingRegistration) {
1842   const GURL scope("https://www.example.com/one/");
1843 
1844   // Create a registration with a controllee and queue an unregister to force
1845   // the uninstalling state.
1846   scoped_refptr<ServiceWorkerRegistration> registration =
1847       CreateRegistrationWithControllee(
1848           GURL("https://www.example.com/service_worker.js"), scope);
1849 
1850   ServiceWorkerVersion* active_version = registration->active_version();
1851 
1852   base::RunLoop run_loop;
1853   job_coordinator()->Unregister(
1854       scope, /*is_immediate=*/false,
1855       SaveUnregistration(blink::ServiceWorkerStatusCode::kOk,
1856                          run_loop.QuitClosure()));
1857 
1858   // Update should abort after it starts and sees uninstalling.
1859   job_coordinator()->Update(registration.get(), false);
1860 
1861   run_loop.Run();
1862 
1863   // Verify the registration was not modified by the Update.
1864   EXPECT_TRUE(registration->is_uninstalling());
1865   EXPECT_EQ(active_version, registration->active_version());
1866   EXPECT_EQ(nullptr, registration->waiting_version());
1867   EXPECT_EQ(nullptr, registration->installing_version());
1868 }
1869 
TEST_F(ServiceWorkerUpdateJobTest,RegisterMultipleTimesWhileUninstalling)1870 TEST_F(ServiceWorkerUpdateJobTest, RegisterMultipleTimesWhileUninstalling) {
1871   GURL script1("https://www.example.com/service_worker.js?first");
1872   GURL script2("https://www.example.com/service_worker.js?second");
1873   GURL script3("https://www.example.com/service_worker.js?third");
1874   blink::mojom::ServiceWorkerRegistrationOptions options;
1875   options.scope = GURL("https://www.example.com/one/");
1876 
1877   auto* initial_client =
1878       helper_->AddNewPendingInstanceClient<FakeEmbeddedWorkerInstanceClient>(
1879           helper_.get());
1880   scoped_refptr<ServiceWorkerRegistration> registration =
1881       RunRegisterJob(script1, options);
1882   // Wait until the worker becomes actvie.
1883   base::RunLoop().RunUntilIdle();
1884   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
1885   registration->SetTaskRunnerForTest(runner);
1886 
1887   // Add a controllee and queue an unregister to force the uninstalling state.
1888   ServiceWorkerContainerHost* container_host = CreateControllee();
1889   scoped_refptr<ServiceWorkerVersion> first_version =
1890       registration->active_version();
1891   first_version->AddControllee(container_host);
1892   RunUnregisterJob(options.scope);
1893 
1894   EXPECT_EQ(registration, RunRegisterJob(script2, options));
1895   // Wait until the worker becomes installed.
1896   base::RunLoop().RunUntilIdle();
1897 
1898   scoped_refptr<ServiceWorkerVersion> second_version =
1899       registration->waiting_version();
1900   ASSERT_TRUE(second_version);
1901 
1902   RunUnregisterJob(options.scope);
1903 
1904   EXPECT_TRUE(registration->is_uninstalling());
1905 
1906   EXPECT_EQ(registration, RunRegisterJob(script3, options));
1907   TestServiceWorkerObserver observer(helper_->context_wrapper());
1908   observer.RunUntilStatusChange(second_version.get(),
1909                                 ServiceWorkerVersion::REDUNDANT);
1910   scoped_refptr<ServiceWorkerVersion> third_version =
1911       registration->waiting_version();
1912   ASSERT_TRUE(third_version);
1913 
1914   EXPECT_FALSE(registration->is_uninstalling());
1915   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, second_version->status());
1916 
1917   first_version->RemoveControllee(container_host->client_uuid());
1918   RequestTermination(&initial_client->host());
1919 
1920   // Wait for activated.
1921   observer.RunUntilActivated(third_version.get(), runner);
1922 
1923   // Verify the new version is activated.
1924   EXPECT_FALSE(registration->is_uninstalling());
1925   EXPECT_FALSE(registration->is_uninstalled());
1926   EXPECT_EQ(nullptr, registration->installing_version());
1927   EXPECT_EQ(nullptr, registration->waiting_version());
1928   EXPECT_EQ(third_version, registration->active_version());
1929   EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, third_version->status());
1930 }
1931 
1932 // Test that activation doesn't complete if it's triggered by removing a
1933 // controllee and starting the worker failed due to shutdown.
TEST_F(ServiceWorkerUpdateJobTest,ActivateCancelsOnShutdown)1934 TEST_F(ServiceWorkerUpdateJobTest, ActivateCancelsOnShutdown) {
1935   GURL script("https://www.example.com/service_worker.js");
1936   blink::mojom::ServiceWorkerRegistrationOptions options;
1937   options.scope = GURL("https://www.example.com/");
1938 
1939   auto* initial_client =
1940       helper_->AddNewPendingInstanceClient<FakeEmbeddedWorkerInstanceClient>(
1941           helper_.get());
1942   scoped_refptr<ServiceWorkerRegistration> registration =
1943       RunRegisterJob(script, options);
1944   // Wait until the worker becomes active.
1945   base::RunLoop().RunUntilIdle();
1946   auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
1947   registration->SetTaskRunnerForTest(runner);
1948 
1949   // Add a controllee.
1950   ServiceWorkerContainerHost* container_host = CreateControllee();
1951   scoped_refptr<ServiceWorkerVersion> first_version =
1952       registration->active_version();
1953   first_version->AddControllee(container_host);
1954 
1955   // Update. The new version should be waiting.
1956   // Change script body.
1957   update_helper_->fake_network_.SetResponse(script, kHeaders, kNewBody,
1958                                             /*network_accessed=*/true, net::OK);
1959 
1960   registration->AddListener(update_helper_);
1961   first_version->StartUpdate();
1962   base::RunLoop().RunUntilIdle();
1963   scoped_refptr<ServiceWorkerVersion> new_version =
1964       registration->waiting_version();
1965   ASSERT_TRUE(new_version);
1966   EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
1967 
1968   // Stop the worker so that it must start again when activation is attempted.
1969   // (This is not strictly necessary to exercise the codepath, but it makes it
1970   // easy to cause a failure with set_force_start_worker_failure after
1971   // shutdown is simulated. Otherwise our test helper often fails on
1972   // DCHECK(context)).
1973   new_version->StopWorker(base::DoNothing());
1974 
1975   // Remove the controllee. The new version should be activating, and delayed
1976   // until the runner runs again.
1977   first_version->RemoveControllee(container_host->client_uuid());
1978   base::RunLoop().RunUntilIdle();
1979 
1980   // Activating the new version won't happen until
1981   // RequestTermination() is called.
1982   EXPECT_EQ(first_version.get(), registration->active_version());
1983   RequestTermination(&initial_client->host());
1984 
1985   TestServiceWorkerObserver observer(helper_->context_wrapper());
1986   observer.RunUntilStatusChange(new_version.get(),
1987                                 ServiceWorkerVersion::ACTIVATING);
1988   EXPECT_EQ(new_version.get(), registration->active_version());
1989   EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, new_version->status());
1990 
1991   // Shutdown.
1992   update_helper_->context()->wrapper()->Shutdown();
1993   auto* embedded_worker_instance_client =
1994       update_helper_->AddNewPendingInstanceClient<
1995           UpdateJobTestHelper::ScriptFailureEmbeddedWorkerInstanceClient>(
1996           update_helper_);
1997   update_helper_->AddNewPendingServiceWorker<
1998       UpdateJobTestHelper::ScriptFailureServiceWorker>(
1999       update_helper_, embedded_worker_instance_client);
2000 
2001   // Allow the activation to continue. It will fail, and the worker
2002   // should not be promoted to ACTIVATED because failure occur
2003   // during shutdown.
2004   runner->RunPendingTasks();
2005   base::RunLoop().RunUntilIdle();
2006   EXPECT_EQ(new_version.get(), registration->active_version());
2007   EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, new_version->status());
2008   registration->RemoveListener(update_helper_);
2009   // Dispatch Mojo messages for those Mojo interfaces bound on |runner| to
2010   // avoid possible memory leak.
2011   runner->RunUntilIdle();
2012 }
2013 
2014 class ServiceWorkerUpdateJobTestWithCrossOriginIsolation
2015     : public ServiceWorkerUpdateJobTest {
2016  public:
ServiceWorkerUpdateJobTestWithCrossOriginIsolation()2017   ServiceWorkerUpdateJobTestWithCrossOriginIsolation() {
2018     feature_list_.InitAndEnableFeature(
2019         ::network::features::kCrossOriginEmbedderPolicy);
2020   }
2021 
2022  private:
2023   base::test::ScopedFeatureList feature_list_;
2024 };
2025 
2026 // Update job should handle the COEP header appropriately.
TEST_F(ServiceWorkerUpdateJobTestWithCrossOriginIsolation,Update_CrossOriginEmbedderPolicyValue)2027 TEST_F(ServiceWorkerUpdateJobTestWithCrossOriginIsolation,
2028        Update_CrossOriginEmbedderPolicyValue) {
2029   const GURL kNewVersionOrigin("https://newversion/");
2030   const char kHeadersWithRequireCorp[] = R"(HTTP/1.1 200 OK
2031 Content-Type: application/javascript
2032 Cross-Origin-Embedder-Policy: require-corp
2033 
2034 )";
2035   const char kHeadersWithNone[] = R"(HTTP/1.1 200 OK
2036 Content-Type: application/javascript
2037 Cross-Origin-Embedder-Policy: none
2038 
2039 )";
2040 
2041   const base::Time kToday = base::Time::Now();
2042   const base::Time kYesterday =
2043       kToday - base::TimeDelta::FromDays(1) - base::TimeDelta::FromHours(1);
2044 
2045   scoped_refptr<ServiceWorkerRegistration> registration =
2046       update_helper_->SetupInitialRegistration(kNewVersionOrigin);
2047   ASSERT_TRUE(registration.get());
2048   EXPECT_FALSE(registration->active_version()->cross_origin_embedder_policy());
2049 
2050   registration->AddListener(update_helper_);
2051 
2052   // Run an update where the response header is updated but the script did not
2053   // change. No update is found but the last update check time is updated.
2054   update_helper_->fake_network_.SetResponse(kNewVersionOrigin.Resolve(kScript),
2055                                             kHeadersWithRequireCorp, kBody,
2056                                             /*network_accessed=*/true, net::OK);
2057 
2058   {
2059     base::HistogramTester histogram_tester;
2060     registration->set_last_update_check(kYesterday);
2061     registration->active_version()->StartUpdate();
2062     base::RunLoop().RunUntilIdle();
2063     EXPECT_LT(kYesterday, registration->last_update_check());
2064     EXPECT_FALSE(update_helper_->update_found_);
2065   }
2066 
2067   // Run an update where the COEP value and the script changed.
2068   update_helper_->fake_network_.SetResponse(kNewVersionOrigin.Resolve(kScript),
2069                                             kHeadersWithRequireCorp, kNewBody,
2070                                             /*network_accessed=*/true, net::OK);
2071   {
2072     base::HistogramTester histogram_tester;
2073     registration->set_last_update_check(kYesterday);
2074     registration->active_version()->StartUpdate();
2075     base::RunLoop().RunUntilIdle();
2076     EXPECT_LT(kYesterday, registration->last_update_check());
2077     EXPECT_TRUE(update_helper_->update_found_);
2078     ASSERT_NE(nullptr, registration->waiting_version());
2079     EXPECT_EQ(CrossOriginEmbedderPolicyRequireCorp(),
2080               registration->waiting_version()->cross_origin_embedder_policy());
2081   }
2082 
2083   // Run an update again where the COEP value and the body has been updated. The
2084   // COEP value should be updated appropriately.
2085   update_helper_->fake_network_.SetResponse(kNewVersionOrigin.Resolve(kScript),
2086                                             kHeadersWithNone, kBody,
2087                                             /*network_accessed=*/true, net::OK);
2088   {
2089     base::HistogramTester histogram_tester;
2090     registration->set_last_update_check(kYesterday);
2091     registration->active_version()->StartUpdate();
2092     base::RunLoop().RunUntilIdle();
2093     EXPECT_LT(kYesterday, registration->last_update_check());
2094     EXPECT_TRUE(update_helper_->update_found_);
2095     ASSERT_NE(nullptr, registration->waiting_version());
2096     EXPECT_EQ(CrossOriginEmbedderPolicyNone(),
2097               registration->waiting_version()->cross_origin_embedder_policy());
2098   }
2099 }
2100 
2101 class WaitForeverInstallWorker : public FakeServiceWorker {
2102  public:
WaitForeverInstallWorker(EmbeddedWorkerTestHelper * helper)2103   WaitForeverInstallWorker(EmbeddedWorkerTestHelper* helper)
2104       : FakeServiceWorker(helper) {}
2105   ~WaitForeverInstallWorker() override = default;
2106 
DispatchInstallEvent(blink::mojom::ServiceWorker::DispatchInstallEventCallback callback)2107   void DispatchInstallEvent(
2108       blink::mojom::ServiceWorker::DispatchInstallEventCallback callback)
2109       override {
2110     callback_ = std::move(callback);
2111   }
2112 
2113  private:
2114   blink::mojom::ServiceWorker::DispatchInstallEventCallback callback_;
2115 };
2116 
2117 // Test that the job queue doesn't get stuck by bad workers.
TEST_F(ServiceWorkerJobTest,TimeoutBadJobs)2118 TEST_F(ServiceWorkerJobTest, TimeoutBadJobs) {
2119   blink::mojom::ServiceWorkerRegistrationOptions options;
2120   options.scope = GURL("https://www.example.com/");
2121 
2122   // Make a job that gets stuck due to a worker stalled in starting.
2123   base::RunLoop loop1;
2124   scoped_refptr<ServiceWorkerRegistration> registration1;
2125   helper_->AddPendingInstanceClient(
2126       std::make_unique<DelayedFakeEmbeddedWorkerInstanceClient>(helper_.get()));
2127   job_coordinator()->Register(
2128       GURL("https://www.example.com/service_worker1.js"), options,
2129       blink::mojom::FetchClientSettingsObject::New(),
2130       SaveRegistration(blink::ServiceWorkerStatusCode::kErrorTimeout,
2131                        &registration1, loop1.QuitClosure()));
2132 
2133   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
2134 
2135   // Make a job that gets stuck due to a worker that doesn't finish the install
2136   // event. The callback is called with kOk, but the job will be stuck until
2137   // the install event times out.
2138   base::RunLoop loop2;
2139   helper_->AddPendingServiceWorker(
2140       std::make_unique<WaitForeverInstallWorker>(helper_.get()));
2141   scoped_refptr<ServiceWorkerRegistration> registration2;
2142   job_coordinator()->Register(
2143       GURL("https://www.example.com/service_worker2.js"), options,
2144       blink::mojom::FetchClientSettingsObject::New(),
2145       SaveRegistration(blink::ServiceWorkerStatusCode::kOk, &registration2,
2146                        loop2.QuitClosure()));
2147 
2148   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
2149 
2150   // Make a normal job.
2151   base::RunLoop loop3;
2152   scoped_refptr<ServiceWorkerRegistration> registration3;
2153   job_coordinator()->Register(
2154       GURL("https://www.example.com/service_worker3.js"), options,
2155       blink::mojom::FetchClientSettingsObject::New(),
2156       SaveRegistration(blink::ServiceWorkerStatusCode::kOk, &registration3,
2157                        loop3.QuitClosure()));
2158 
2159   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
2160 
2161   // Timeout the first job.
2162   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(2));
2163   loop1.Run();
2164 
2165   // Let the second job run until the install event is dispatched, then
2166   // time out the event.
2167   loop2.Run();
2168   scoped_refptr<ServiceWorkerVersion> version =
2169       registration2->installing_version();
2170   ASSERT_TRUE(version);
2171   EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version->status());
2172   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(5));
2173   EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
2174 
2175   // Let the third job finish successfully. It might have already been
2176   // progressing so we don't know what state its worker is in, but it will
2177   // eventually reach ACTIVATED.
2178   loop3.Run();
2179   version = registration3->GetNewestVersion();
2180   ASSERT_TRUE(version);
2181   TestServiceWorkerObserver observer(helper_->context_wrapper());
2182   observer.RunUntilStatusChange(version.get(), ServiceWorkerVersion::ACTIVATED);
2183 }
2184 
2185 }  // namespace content
2186