1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/service_worker/service_worker_registration.h"
6
7 #include <stdint.h>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback_helpers.h"
13 #include "base/compiler_specific.h"
14 #include "base/files/scoped_temp_dir.h"
15 #include "base/logging.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/optional.h"
18 #include "base/run_loop.h"
19 #include "base/test/bind_test_util.h"
20 #include "base/test/scoped_feature_list.h"
21 #include "base/test/simple_test_tick_clock.h"
22 #include "base/test/test_simple_task_runner.h"
23 #include "base/threading/thread_task_runner_handle.h"
24 #include "base/time/time.h"
25 #include "content/browser/service_worker/embedded_worker_status.h"
26 #include "content/browser/service_worker/embedded_worker_test_helper.h"
27 #include "content/browser/service_worker/fake_embedded_worker_instance_client.h"
28 #include "content/browser/service_worker/fake_service_worker.h"
29 #include "content/browser/service_worker/service_worker_container_host.h"
30 #include "content/browser/service_worker/service_worker_context_core.h"
31 #include "content/browser/service_worker/service_worker_context_core_observer.h"
32 #include "content/browser/service_worker/service_worker_context_wrapper.h"
33 #include "content/browser/service_worker/service_worker_provider_host.h"
34 #include "content/browser/service_worker/service_worker_register_job.h"
35 #include "content/browser/service_worker/service_worker_registration_object_host.h"
36 #include "content/browser/service_worker/service_worker_test_utils.h"
37 #include "content/browser/service_worker/test_service_worker_observer.h"
38 #include "content/browser/storage_partition_impl.h"
39 #include "content/common/service_worker/service_worker_utils.h"
40 #include "content/public/common/content_client.h"
41 #include "content/public/test/browser_task_environment.h"
42 #include "content/public/test/test_browser_context.h"
43 #include "content/public/test/url_loader_interceptor.h"
44 #include "content/test/fake_network.h"
45 #include "content/test/test_content_browser_client.h"
46 #include "mojo/core/embedder/embedder.h"
47 #include "mojo/public/cpp/bindings/associated_receiver.h"
48 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
49 #include "testing/gtest/include/gtest/gtest.h"
50 #include "third_party/blink/public/common/features.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 #include "url/gurl.h"
54 #include "url/origin.h"
55
56 namespace content {
57
58 namespace {
59
60 // From service_worker_registration.cc.
61 constexpr base::TimeDelta kMaxLameDuckTime = base::TimeDelta::FromMinutes(5);
62
CreateInflightRequest(ServiceWorkerVersion * version)63 int CreateInflightRequest(ServiceWorkerVersion* version) {
64 EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, StartServiceWorker(version));
65 return version->StartRequest(ServiceWorkerMetrics::EventType::PUSH,
66 base::DoNothing());
67 }
68
SaveStatusCallback(bool * called,blink::ServiceWorkerStatusCode * out,blink::ServiceWorkerStatusCode status)69 void SaveStatusCallback(bool* called,
70 blink::ServiceWorkerStatusCode* out,
71 blink::ServiceWorkerStatusCode status) {
72 *called = true;
73 *out = status;
74 }
75
76 } // namespace
77
78 class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
79 public:
AllowServiceWorkerOnIO(const GURL & scope,const GURL & site_for_cookies,const base::Optional<url::Origin> & top_frame_origin,const GURL & script_url,content::ResourceContext * context,base::RepeatingCallback<WebContents * ()> wc_getter)80 bool AllowServiceWorkerOnIO(
81 const GURL& scope,
82 const GURL& site_for_cookies,
83 const base::Optional<url::Origin>& top_frame_origin,
84 const GURL& script_url,
85 content::ResourceContext* context,
86 base::RepeatingCallback<WebContents*()> wc_getter) override {
87 return false;
88 }
89
AllowServiceWorkerOnUI(const GURL & scope,const GURL & site_for_cookies,const base::Optional<url::Origin> & top_frame_origin,const GURL & script_url,content::BrowserContext * context,base::RepeatingCallback<WebContents * ()> wc_getter)90 bool AllowServiceWorkerOnUI(
91 const GURL& scope,
92 const GURL& site_for_cookies,
93 const base::Optional<url::Origin>& top_frame_origin,
94 const GURL& script_url,
95 content::BrowserContext* context,
96 base::RepeatingCallback<WebContents*()> wc_getter) override {
97 return false;
98 }
99 };
100
RequestTermination(mojo::AssociatedRemote<blink::mojom::EmbeddedWorkerInstanceHost> * host)101 void RequestTermination(
102 mojo::AssociatedRemote<blink::mojom::EmbeddedWorkerInstanceHost>* host) {
103 // We can't wait for the callback since Stop() arrives first which severs
104 // the connection.
105 (*host)->RequestTermination(base::DoNothing());
106 }
107
108 class MockServiceWorkerRegistrationObject
109 : public blink::mojom::ServiceWorkerRegistrationObject {
110 public:
MockServiceWorkerRegistrationObject(mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerRegistrationObject> receiver)111 explicit MockServiceWorkerRegistrationObject(
112 mojo::PendingAssociatedReceiver<
113 blink::mojom::ServiceWorkerRegistrationObject> receiver)
114 : receiver_(this, std::move(receiver)) {}
115 ~MockServiceWorkerRegistrationObject() override = default;
116
update_found_called_count() const117 int update_found_called_count() const { return update_found_called_count_; }
set_version_attributes_called_count() const118 int set_version_attributes_called_count() const {
119 return set_version_attributes_called_count_;
120 }
set_update_via_cache_called_count() const121 int set_update_via_cache_called_count() const {
122 return set_update_via_cache_called_count_;
123 }
changed_mask() const124 const blink::mojom::ChangedServiceWorkerObjectsMask& changed_mask() const {
125 return *changed_mask_;
126 }
installing() const127 const blink::mojom::ServiceWorkerObjectInfoPtr& installing() const {
128 return installing_;
129 }
waiting() const130 const blink::mojom::ServiceWorkerObjectInfoPtr& waiting() const {
131 return waiting_;
132 }
active() const133 const blink::mojom::ServiceWorkerObjectInfoPtr& active() const {
134 return active_;
135 }
update_via_cache() const136 blink::mojom::ServiceWorkerUpdateViaCache update_via_cache() const {
137 return update_via_cache_;
138 }
139
140 private:
141 // Implements blink::mojom::ServiceWorkerRegistrationObject.
SetServiceWorkerObjects(blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,blink::mojom::ServiceWorkerObjectInfoPtr installing,blink::mojom::ServiceWorkerObjectInfoPtr waiting,blink::mojom::ServiceWorkerObjectInfoPtr active)142 void SetServiceWorkerObjects(
143 blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
144 blink::mojom::ServiceWorkerObjectInfoPtr installing,
145 blink::mojom::ServiceWorkerObjectInfoPtr waiting,
146 blink::mojom::ServiceWorkerObjectInfoPtr active) override {
147 set_version_attributes_called_count_++;
148 changed_mask_ = std::move(changed_mask);
149 installing_ = std::move(installing);
150 waiting_ = std::move(waiting);
151 active_ = std::move(active);
152 }
SetUpdateViaCache(blink::mojom::ServiceWorkerUpdateViaCache update_via_cache)153 void SetUpdateViaCache(
154 blink::mojom::ServiceWorkerUpdateViaCache update_via_cache) override {
155 set_update_via_cache_called_count_++;
156 update_via_cache_ = update_via_cache;
157 }
UpdateFound()158 void UpdateFound() override { update_found_called_count_++; }
159
160 int update_found_called_count_ = 0;
161 int set_version_attributes_called_count_ = 0;
162 int set_update_via_cache_called_count_ = 0;
163 blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask_;
164 blink::mojom::ServiceWorkerObjectInfoPtr installing_;
165 blink::mojom::ServiceWorkerObjectInfoPtr waiting_;
166 blink::mojom::ServiceWorkerObjectInfoPtr active_;
167 blink::mojom::ServiceWorkerUpdateViaCache update_via_cache_ =
168 blink::mojom::ServiceWorkerUpdateViaCache::kImports;
169
170 mojo::AssociatedReceiver<blink::mojom::ServiceWorkerRegistrationObject>
171 receiver_;
172 };
173
174 class ServiceWorkerRegistrationTest : public testing::Test {
175 public:
ServiceWorkerRegistrationTest()176 ServiceWorkerRegistrationTest()
177 : task_environment_(BrowserTaskEnvironment::IO_MAINLOOP) {}
178
SetUp()179 void SetUp() override {
180 helper_ = std::make_unique<EmbeddedWorkerTestHelper>(base::FilePath());
181
182 // Create a StoragePartition with the testing browser context so that the
183 // ServiceWorkerUpdateChecker can find the BrowserContext through it.
184 storage_partition_impl_ = StoragePartitionImpl::Create(
185 helper_->browser_context(), /* in_memory= */ true, base::FilePath(),
186 /* partition_domain= */ "");
187 storage_partition_impl_->Initialize();
188 helper_->context_wrapper()->set_storage_partition(
189 storage_partition_impl_.get());
190
191 context()->storage()->LazyInitializeForTest();
192 }
193
context()194 ServiceWorkerContextCore* context() { return helper_->context(); }
registry()195 ServiceWorkerRegistry* registry() { return helper_->context()->registry(); }
storage()196 ServiceWorkerStorage* storage() { return helper_->context()->storage(); }
197
198 class RegistrationListener : public ServiceWorkerRegistration::Listener {
199 public:
RegistrationListener()200 RegistrationListener() {}
~RegistrationListener()201 ~RegistrationListener() {
202 if (observed_registration_.get())
203 observed_registration_->RemoveListener(this);
204 }
205
OnVersionAttributesChanged(ServiceWorkerRegistration * registration,blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,const ServiceWorkerRegistrationInfo & info)206 void OnVersionAttributesChanged(
207 ServiceWorkerRegistration* registration,
208 blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask,
209 const ServiceWorkerRegistrationInfo& info) override {
210 observed_registration_ = registration;
211 observed_changed_mask_ = std::move(changed_mask);
212 observed_info_ = info;
213 }
214
OnRegistrationFailed(ServiceWorkerRegistration * registration)215 void OnRegistrationFailed(
216 ServiceWorkerRegistration* registration) override {
217 NOTREACHED();
218 }
219
OnUpdateFound(ServiceWorkerRegistration * registration)220 void OnUpdateFound(ServiceWorkerRegistration* registration) override {
221 NOTREACHED();
222 }
223
Reset()224 void Reset() {
225 observed_registration_ = nullptr;
226 observed_changed_mask_ = nullptr;
227 observed_info_ = ServiceWorkerRegistrationInfo();
228 }
229
230 scoped_refptr<ServiceWorkerRegistration> observed_registration_;
231 blink::mojom::ChangedServiceWorkerObjectsMaskPtr observed_changed_mask_;
232 ServiceWorkerRegistrationInfo observed_info_;
233 };
234
235 protected:
236 BrowserTaskEnvironment task_environment_;
237 std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
238 std::unique_ptr<StoragePartitionImpl> storage_partition_impl_;
239 };
240
TEST_F(ServiceWorkerRegistrationTest,SetAndUnsetVersions)241 TEST_F(ServiceWorkerRegistrationTest, SetAndUnsetVersions) {
242 const GURL kScope("http://www.example.not/");
243 const GURL kScript("http://www.example.not/service_worker.js");
244 int64_t kRegistrationId = 1L;
245
246 blink::mojom::ServiceWorkerRegistrationOptions options;
247 options.scope = kScope;
248 scoped_refptr<ServiceWorkerRegistration> registration =
249 base::MakeRefCounted<ServiceWorkerRegistration>(options, kRegistrationId,
250 context()->AsWeakPtr());
251
252 const int64_t version_1_id = 1L;
253 const int64_t version_2_id = 2L;
254 scoped_refptr<ServiceWorkerVersion> version_1 =
255 base::MakeRefCounted<ServiceWorkerVersion>(
256 registration.get(), kScript, blink::mojom::ScriptType::kClassic,
257 version_1_id, context()->AsWeakPtr());
258 scoped_refptr<ServiceWorkerVersion> version_2 =
259 base::MakeRefCounted<ServiceWorkerVersion>(
260 registration.get(), kScript, blink::mojom::ScriptType::kClassic,
261 version_2_id, context()->AsWeakPtr());
262
263 RegistrationListener listener;
264 registration->AddListener(&listener);
265 registration->SetActiveVersion(version_1);
266
267 EXPECT_EQ(version_1.get(), registration->active_version());
268 EXPECT_EQ(registration, listener.observed_registration_);
269 EXPECT_TRUE(listener.observed_changed_mask_->active);
270 EXPECT_EQ(kScope, listener.observed_info_.scope);
271 EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
272 EXPECT_EQ(kScript, listener.observed_info_.active_version.script_url);
273 EXPECT_EQ(listener.observed_info_.installing_version.version_id,
274 blink::mojom::kInvalidServiceWorkerVersionId);
275 EXPECT_EQ(listener.observed_info_.waiting_version.version_id,
276 blink::mojom::kInvalidServiceWorkerVersionId);
277 listener.Reset();
278
279 registration->SetInstallingVersion(version_2);
280
281 EXPECT_EQ(version_2.get(), registration->installing_version());
282 EXPECT_TRUE(listener.observed_changed_mask_->installing);
283 EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
284 EXPECT_EQ(version_2_id,
285 listener.observed_info_.installing_version.version_id);
286 EXPECT_EQ(listener.observed_info_.waiting_version.version_id,
287 blink::mojom::kInvalidServiceWorkerVersionId);
288 listener.Reset();
289
290 registration->SetWaitingVersion(version_2);
291
292 EXPECT_EQ(version_2.get(), registration->waiting_version());
293 EXPECT_FALSE(registration->installing_version());
294 EXPECT_TRUE(listener.observed_changed_mask_->waiting);
295 EXPECT_TRUE(listener.observed_changed_mask_->installing);
296 EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
297 EXPECT_EQ(version_2_id, listener.observed_info_.waiting_version.version_id);
298 EXPECT_EQ(listener.observed_info_.installing_version.version_id,
299 blink::mojom::kInvalidServiceWorkerVersionId);
300 listener.Reset();
301
302 registration->UnsetVersion(version_2.get());
303
304 EXPECT_FALSE(registration->waiting_version());
305 EXPECT_TRUE(listener.observed_changed_mask_->waiting);
306 EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
307 EXPECT_EQ(listener.observed_info_.waiting_version.version_id,
308 blink::mojom::kInvalidServiceWorkerVersionId);
309 EXPECT_EQ(listener.observed_info_.installing_version.version_id,
310 blink::mojom::kInvalidServiceWorkerVersionId);
311 }
312
TEST_F(ServiceWorkerRegistrationTest,FailedRegistrationNoCrash)313 TEST_F(ServiceWorkerRegistrationTest, FailedRegistrationNoCrash) {
314 const GURL kScope("http://www.example.not/");
315 int64_t kRegistrationId = 1L;
316 blink::mojom::ServiceWorkerRegistrationOptions options;
317 options.scope = kScope;
318 auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
319 options, kRegistrationId, context()->AsWeakPtr());
320 // Prepare a ServiceWorkerContainerHost.
321 ServiceWorkerRemoteProviderEndpoint remote_endpoint;
322 base::WeakPtr<ServiceWorkerContainerHost> container_host =
323 CreateContainerHostForWindow(helper_->mock_render_process_id(),
324 true /* is_parent_frame_secure */,
325 context()->AsWeakPtr(), &remote_endpoint);
326 auto registration_object_host =
327 std::make_unique<ServiceWorkerRegistrationObjectHost>(
328 context()->AsWeakPtr(), container_host.get(), registration);
329 // To enable the caller end point
330 // |registration_object_host->remote_registration_| to make calls safely with
331 // no need to pass |object_info_->receiver| through a message pipe endpoint.
332 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr object_info =
333 registration_object_host->CreateObjectInfo();
334 mojo::AssociateWithDisconnectedPipe(object_info->receiver.PassHandle());
335
336 registration->NotifyRegistrationFailed();
337 // Don't crash when |registration_object_host| gets destructed.
338 }
339
TEST_F(ServiceWorkerRegistrationTest,NavigationPreload)340 TEST_F(ServiceWorkerRegistrationTest, NavigationPreload) {
341 const GURL kScope("http://www.example.not/");
342 const GURL kScript("https://www.example.not/service_worker.js");
343 // Setup.
344
345 blink::mojom::ServiceWorkerRegistrationOptions options;
346 options.scope = kScope;
347 scoped_refptr<ServiceWorkerRegistration> registration =
348 CreateNewServiceWorkerRegistration(context()->registry(), options);
349 scoped_refptr<ServiceWorkerVersion> version_1 = CreateNewServiceWorkerVersion(
350 context()->registry(), registration.get(), kScript,
351 blink::mojom::ScriptType::kClassic);
352 version_1->set_fetch_handler_existence(
353 ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
354 registration->SetActiveVersion(version_1);
355 version_1->SetStatus(ServiceWorkerVersion::ACTIVATED);
356 scoped_refptr<ServiceWorkerVersion> version_2 = CreateNewServiceWorkerVersion(
357 context()->registry(), registration.get(), kScript,
358 blink::mojom::ScriptType::kClassic);
359 version_2->set_fetch_handler_existence(
360 ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
361 registration->SetWaitingVersion(version_2);
362 version_2->SetStatus(ServiceWorkerVersion::INSTALLED);
363
364 // Navigation preload is disabled by default.
365 EXPECT_FALSE(version_1->navigation_preload_state().enabled);
366 // Enabling it sets the flag on the active version.
367 registration->EnableNavigationPreload(true);
368 EXPECT_TRUE(version_1->navigation_preload_state().enabled);
369 // A new active version gets the flag.
370 registration->SetActiveVersion(version_2);
371 version_2->SetStatus(ServiceWorkerVersion::ACTIVATING);
372 EXPECT_TRUE(version_2->navigation_preload_state().enabled);
373 // Disabling it unsets the flag on the active version.
374 registration->EnableNavigationPreload(false);
375 EXPECT_FALSE(version_2->navigation_preload_state().enabled);
376 }
377
378 // Sets up a registration with a waiting worker, and an active worker
379 // with a controllee and an inflight request.
380 class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest,
381 public testing::WithParamInterface<bool> {
382 public:
ServiceWorkerActivationTest()383 ServiceWorkerActivationTest() : ServiceWorkerRegistrationTest() {}
384
SetUp()385 void SetUp() override {
386 ServiceWorkerRegistrationTest::SetUp();
387
388 const GURL kUrl("https://www.example.not/");
389 const GURL kScope("https://www.example.not/");
390 const GURL kScript("https://www.example.not/service_worker.js");
391
392 blink::mojom::ServiceWorkerRegistrationOptions options;
393 options.scope = kScope;
394 registration_ =
395 CreateNewServiceWorkerRegistration(context()->registry(), options);
396
397 // Create an active version.
398 scoped_refptr<ServiceWorkerVersion> version_1 =
399 CreateNewServiceWorkerVersion(context()->registry(),
400 registration_.get(), kScript,
401 blink::mojom::ScriptType::kClassic);
402 version_1->set_fetch_handler_existence(
403 ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
404 registration_->SetActiveVersion(version_1);
405 version_1->SetStatus(ServiceWorkerVersion::ACTIVATED);
406
407 // Store the registration.
408 std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> records_1;
409 records_1.push_back(WriteToDiskCacheSync(
410 helper_->context()->storage(), version_1->script_url(),
411 {} /* headers */, "I'm the body", "I'm the meta data"));
412 version_1->script_cache_map()->SetResources(records_1);
413 version_1->SetMainScriptResponse(
414 EmbeddedWorkerTestHelper::CreateMainScriptResponse());
415 base::Optional<blink::ServiceWorkerStatusCode> status;
416 base::RunLoop run_loop;
417 context()->registry()->StoreRegistration(
418 registration_.get(), version_1.get(),
419 ReceiveServiceWorkerStatus(&status, run_loop.QuitClosure()));
420 run_loop.Run();
421 ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
422
423 // Give the active version a controllee.
424 container_host_ = CreateContainerHostForWindow(
425 helper_->mock_render_process_id(), true /* is_parent_frame_secure */,
426 context()->AsWeakPtr(), &remote_endpoint_);
427 DCHECK(remote_endpoint_.client_receiver()->is_valid());
428 DCHECK(remote_endpoint_.host_remote()->is_bound());
429 container_host_->UpdateUrls(kUrl, net::SiteForCookies::FromUrl(kUrl),
430 url::Origin::Create(kUrl));
431 container_host_->SetControllerRegistration(
432 registration_, false /* notify_controllerchange */);
433
434 // Setup the Mojo implementation fakes for the renderer-side service worker.
435 // These will be bound once the service worker starts.
436 version_1_client_ =
437 helper_->AddNewPendingInstanceClient<FakeEmbeddedWorkerInstanceClient>(
438 helper_.get());
439 version_1_service_worker_ =
440 helper_->AddNewPendingServiceWorker<FakeServiceWorker>(helper_.get());
441
442 // Start the active version and give it an in-flight request.
443 inflight_request_id_ = CreateInflightRequest(version_1.get());
444
445 // Create a waiting version.
446 scoped_refptr<ServiceWorkerVersion> version_2 =
447 CreateNewServiceWorkerVersion(context()->registry(),
448 registration_.get(), kScript,
449 blink::mojom::ScriptType::kClassic);
450 std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> records_2;
451 records_2.push_back(WriteToDiskCacheSync(
452 helper_->context()->storage(), version_2->script_url(),
453 {} /* headers */, "I'm the body", "I'm the meta data"));
454 version_2->script_cache_map()->SetResources(records_2);
455 version_2->SetMainScriptResponse(
456 EmbeddedWorkerTestHelper::CreateMainScriptResponse());
457 version_2->set_fetch_handler_existence(
458 ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
459 registration_->SetWaitingVersion(version_2);
460
461 // Setup the Mojo implementation fakes for the renderer-side service worker.
462 // These will be bound once the service worker starts.
463 version_2_client_ =
464 helper_->AddNewPendingInstanceClient<FakeEmbeddedWorkerInstanceClient>(
465 helper_.get());
466 version_2_service_worker_ =
467 helper_->AddNewPendingServiceWorker<FakeServiceWorker>(helper_.get());
468
469 // Start the worker.
470 ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk,
471 StartServiceWorker(version_2.get()));
472 version_2->SetStatus(ServiceWorkerVersion::INSTALLED);
473
474 // Set it to activate when ready. The original version should still be
475 // active.
476 registration_->ActivateWaitingVersionWhenReady();
477 base::RunLoop().RunUntilIdle();
478 EXPECT_EQ(version_1.get(), registration_->active_version());
479
480 if (devtools_should_be_attached()) {
481 // Attach DevTools to the active worker. This shouldn't prevent from
482 // promoting the waiting worker to active.
483 version_1->SetDevToolsAttached(true);
484 }
485 }
486
TearDown()487 void TearDown() override {
488 registration_->active_version()->RemoveObserver(registration_.get());
489 ServiceWorkerRegistrationTest::TearDown();
490 }
491
devtools_should_be_attached() const492 bool devtools_should_be_attached() const { return GetParam(); }
493
registration()494 ServiceWorkerRegistration* registration() { return registration_.get(); }
inflight_request_id() const495 int inflight_request_id() const { return inflight_request_id_; }
496
AddControllee()497 void AddControllee() {
498 container_host_->SetControllerRegistration(
499 registration(), false /* notify_controllerchange */);
500 }
501
RemoveControllee()502 void RemoveControllee() {
503 container_host_->SetControllerRegistration(
504 nullptr, false /* notify_controllerchange */);
505 }
506
IsLameDuckTimerRunning()507 bool IsLameDuckTimerRunning() {
508 return registration_->lame_duck_timer_.IsRunning();
509 }
510
RunLameDuckTimer()511 void RunLameDuckTimer() { registration_->RemoveLameDuckIfNeeded(); }
512
513 // Simulates skipWaiting(). Note that skipWaiting() might not try to activate
514 // the worker "immediately", if it can't yet be activated yet. If activation
515 // is delayed, |out_result| will not be set. If activation is attempted,
516 // |out_result| is generally true but false in case of a fatal/unexpected
517 // error like ServiceWorkerContext shutdown.
SimulateSkipWaiting(ServiceWorkerVersion * version,base::Optional<bool> * out_result)518 void SimulateSkipWaiting(ServiceWorkerVersion* version,
519 base::Optional<bool>* out_result) {
520 SimulateSkipWaitingWithCallback(version, out_result, base::DoNothing());
521 }
522
SimulateSkipWaitingWithCallback(ServiceWorkerVersion * version,base::Optional<bool> * out_result,base::OnceClosure done_callback)523 void SimulateSkipWaitingWithCallback(ServiceWorkerVersion* version,
524 base::Optional<bool>* out_result,
525 base::OnceClosure done_callback) {
526 version->SkipWaiting(base::BindOnce(
527 [](base::OnceClosure done_callback, base::Optional<bool>* out_result,
528 bool success) {
529 *out_result = success;
530 std::move(done_callback).Run();
531 },
532 std::move(done_callback), out_result));
533 base::RunLoop().RunUntilIdle();
534 }
535
version_1_client()536 FakeEmbeddedWorkerInstanceClient* version_1_client() {
537 return version_1_client_;
538 }
version_2_client()539 FakeEmbeddedWorkerInstanceClient* version_2_client() {
540 return version_2_client_;
541 }
version_1_service_worker()542 FakeServiceWorker* version_1_service_worker() {
543 return version_1_service_worker_;
544 }
version_2_service_worker()545 FakeServiceWorker* version_2_service_worker() {
546 return version_2_service_worker_;
547 }
548
549 private:
550 scoped_refptr<ServiceWorkerRegistration> registration_;
551
552 // Mojo implementation fakes for the renderer-side service workers. Their
553 // lifetime is bound to the Mojo connection.
554 FakeEmbeddedWorkerInstanceClient* version_1_client_ = nullptr;
555 FakeServiceWorker* version_1_service_worker_ = nullptr;
556 FakeEmbeddedWorkerInstanceClient* version_2_client_ = nullptr;
557 FakeServiceWorker* version_2_service_worker_ = nullptr;
558
559 base::WeakPtr<ServiceWorkerContainerHost> container_host_;
560 ServiceWorkerRemoteProviderEndpoint remote_endpoint_;
561 int inflight_request_id_ = -1;
562
563 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerActivationTest);
564 };
565
566 // Test activation triggered by finishing all requests.
TEST_P(ServiceWorkerActivationTest,NoInflightRequest)567 TEST_P(ServiceWorkerActivationTest, NoInflightRequest) {
568 scoped_refptr<ServiceWorkerRegistration> reg = registration();
569 scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
570 scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
571 auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
572 reg->SetTaskRunnerForTest(runner);
573
574 // Remove the controllee. Since there is an in-flight request,
575 // activation should not yet happen.
576 RemoveControllee();
577 base::RunLoop().RunUntilIdle();
578 EXPECT_EQ(version_1.get(), reg->active_version());
579 // The idle timer living in the renderer is requested to notify the idle state
580 // to the browser ASAP.
581 EXPECT_EQ(base::TimeDelta::FromSeconds(0),
582 version_1_service_worker()->idle_delay().value());
583
584 // Finish the request. Activation should happen.
585 version_1->FinishRequest(inflight_request_id(), true /* was_handled */);
586 EXPECT_EQ(version_1.get(), reg->active_version());
587 RequestTermination(&version_1_client()->host());
588
589 TestServiceWorkerObserver observer(helper_->context_wrapper());
590 observer.RunUntilActivated(version_2.get(), runner);
591 EXPECT_EQ(version_2.get(), reg->active_version());
592 }
593
594 // Test activation triggered by skipWaiting and finishing requests.
TEST_P(ServiceWorkerActivationTest,SkipWaitingWithInflightRequest)595 TEST_P(ServiceWorkerActivationTest, SkipWaitingWithInflightRequest) {
596 scoped_refptr<ServiceWorkerRegistration> reg = registration();
597 scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
598 scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
599
600 base::Optional<bool> result;
601 base::RunLoop skip_waiting_loop;
602 // Set skip waiting flag. Since there is still an in-flight request,
603 // activation should not happen.
604 SimulateSkipWaitingWithCallback(version_2.get(), &result,
605 skip_waiting_loop.QuitClosure());
606 EXPECT_FALSE(result.has_value());
607 EXPECT_EQ(version_1.get(), reg->active_version());
608 EXPECT_EQ(base::TimeDelta::FromSeconds(0),
609 version_1_service_worker()->idle_delay().value());
610
611 // Finish the request. FinishRequest() doesn't immediately make the worker
612 // reach the "no work" state. It needs to be notfied of the idle state by
613 // RequestTermination().
614 version_1->FinishRequest(inflight_request_id(), true /* was_handled */);
615
616 EXPECT_EQ(version_1.get(), reg->active_version());
617 RequestTermination(&version_1_client()->host());
618
619 // Wait until SkipWaiting resolves.
620 skip_waiting_loop.Run();
621
622 EXPECT_TRUE(result.has_value());
623 EXPECT_TRUE(*result);
624 EXPECT_EQ(version_2.get(), reg->active_version());
625 }
626
627 // Test activation triggered by skipWaiting.
TEST_P(ServiceWorkerActivationTest,SkipWaiting)628 TEST_P(ServiceWorkerActivationTest, SkipWaiting) {
629 scoped_refptr<ServiceWorkerRegistration> reg = registration();
630 scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
631 scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
632
633 // Finish the in-flight request. Since there is a controllee,
634 // activation should not happen.
635 version_1->FinishRequest(inflight_request_id(), true /* was_handled */);
636 base::RunLoop().RunUntilIdle();
637 EXPECT_EQ(version_1.get(), reg->active_version());
638
639 // Call skipWaiting. Activation happens after RequestTermination is triggered.
640 base::Optional<bool> result;
641 base::RunLoop skip_waiting_loop;
642 SimulateSkipWaitingWithCallback(version_2.get(), &result,
643 skip_waiting_loop.QuitClosure());
644
645 EXPECT_EQ(base::TimeDelta::FromSeconds(0),
646 version_1_service_worker()->idle_delay().value());
647 EXPECT_FALSE(result.has_value());
648 EXPECT_EQ(version_1.get(), reg->active_version());
649 RequestTermination(&version_1_client()->host());
650
651 // Wait until SkipWaiting resolves.
652 skip_waiting_loop.Run();
653
654 EXPECT_TRUE(result.has_value());
655 EXPECT_TRUE(*result);
656 EXPECT_EQ(version_2.get(), reg->active_version());
657 }
658
TEST_P(ServiceWorkerActivationTest,TimeSinceSkipWaiting_Installing)659 TEST_P(ServiceWorkerActivationTest, TimeSinceSkipWaiting_Installing) {
660 scoped_refptr<ServiceWorkerRegistration> reg = registration();
661 scoped_refptr<ServiceWorkerVersion> version = reg->waiting_version();
662 base::SimpleTestTickClock clock;
663 clock.SetNowTicks(base::TimeTicks::Now());
664 version->SetTickClockForTesting(&clock);
665
666 // Reset version to the installing phase.
667 reg->UnsetVersion(version.get());
668 version->SetStatus(ServiceWorkerVersion::INSTALLING);
669
670 base::Optional<bool> result;
671 // Call skipWaiting(). The time ticks since skip waiting shouldn't start
672 // since the version is not yet installed.
673 SimulateSkipWaiting(version.get(), &result);
674 EXPECT_TRUE(result.has_value());
675 EXPECT_TRUE(*result);
676 clock.Advance(base::TimeDelta::FromSeconds(11));
677 EXPECT_EQ(base::TimeDelta(), version->TimeSinceSkipWaiting());
678
679 // Install the version. Now the skip waiting time starts ticking.
680 version->SetStatus(ServiceWorkerVersion::INSTALLED);
681 reg->SetWaitingVersion(version);
682 base::RunLoop().RunUntilIdle();
683 clock.Advance(base::TimeDelta::FromSeconds(33));
684 EXPECT_EQ(base::TimeDelta::FromSeconds(33), version->TimeSinceSkipWaiting());
685
686 result.reset();
687 // Call skipWaiting() again. It doesn't reset the time.
688 SimulateSkipWaiting(version.get(), &result);
689 EXPECT_FALSE(result.has_value());
690 EXPECT_EQ(base::TimeDelta::FromSeconds(33), version->TimeSinceSkipWaiting());
691 }
692
693 // Test lame duck timer triggered by skip waiting.
TEST_P(ServiceWorkerActivationTest,LameDuckTime_SkipWaiting)694 TEST_P(ServiceWorkerActivationTest, LameDuckTime_SkipWaiting) {
695 scoped_refptr<ServiceWorkerRegistration> reg = registration();
696 scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
697 scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
698 base::SimpleTestTickClock clock_1;
699 base::SimpleTestTickClock clock_2;
700 clock_1.SetNowTicks(base::TimeTicks::Now());
701 clock_2.SetNowTicks(clock_1.NowTicks());
702 version_1->SetTickClockForTesting(&clock_1);
703 version_2->SetTickClockForTesting(&clock_2);
704
705 base::Optional<bool> result;
706 // Set skip waiting flag. Since there is still an in-flight request,
707 // activation should not happen. But the lame duck timer should start.
708 EXPECT_FALSE(IsLameDuckTimerRunning());
709 SimulateSkipWaiting(version_2.get(), &result);
710 EXPECT_FALSE(result.has_value());
711 EXPECT_EQ(version_1.get(), reg->active_version());
712 EXPECT_TRUE(IsLameDuckTimerRunning());
713
714 // Move forward by lame duck time.
715 clock_2.Advance(kMaxLameDuckTime + base::TimeDelta::FromSeconds(1));
716
717 // Activation should happen by the lame duck timer.
718 RunLameDuckTimer();
719 base::RunLoop().RunUntilIdle();
720 EXPECT_TRUE(result.has_value());
721 EXPECT_TRUE(*result);
722 EXPECT_EQ(version_2.get(), reg->active_version());
723 EXPECT_FALSE(IsLameDuckTimerRunning());
724
725 // Restore the TickClock to the default. This is required because the dtor
726 // of ServiceWorkerVersions can access the TickClock and it should outlive
727 // ServiceWorkerVersion.
728 version_1->SetTickClockForTesting(base::DefaultTickClock::GetInstance());
729 version_2->SetTickClockForTesting(base::DefaultTickClock::GetInstance());
730 }
731
732 // Test lame duck timer triggered by loss of controllee.
TEST_P(ServiceWorkerActivationTest,LameDuckTime_NoControllee)733 TEST_P(ServiceWorkerActivationTest, LameDuckTime_NoControllee) {
734 scoped_refptr<ServiceWorkerRegistration> reg = registration();
735 scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
736 scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
737 base::SimpleTestTickClock clock_1;
738 base::SimpleTestTickClock clock_2;
739 clock_1.SetNowTicks(base::TimeTicks::Now());
740 clock_2.SetNowTicks(clock_1.NowTicks());
741 version_1->SetTickClockForTesting(&clock_1);
742 version_2->SetTickClockForTesting(&clock_2);
743
744 // Remove the controllee. Since there is still an in-flight request,
745 // activation should not happen. But the lame duck timer should start.
746 EXPECT_FALSE(IsLameDuckTimerRunning());
747 RemoveControllee();
748 base::RunLoop().RunUntilIdle();
749 EXPECT_EQ(version_1.get(), reg->active_version());
750 EXPECT_TRUE(IsLameDuckTimerRunning());
751
752 // Move clock forward by a little bit.
753 constexpr base::TimeDelta kLittleBit = base::TimeDelta::FromMinutes(1);
754 clock_1.Advance(kLittleBit);
755
756 // Add a controllee again to reset the lame duck period.
757 AddControllee();
758 base::RunLoop().RunUntilIdle();
759 EXPECT_TRUE(IsLameDuckTimerRunning());
760
761 // Remove the controllee.
762 RemoveControllee();
763 base::RunLoop().RunUntilIdle();
764 EXPECT_TRUE(IsLameDuckTimerRunning());
765
766 // Move clock forward to the next lame duck timer tick.
767 clock_1.Advance(kMaxLameDuckTime - kLittleBit +
768 base::TimeDelta::FromSeconds(1));
769
770 // Run the lame duck timer. Activation should not yet happen
771 // since the lame duck period has not expired.
772 RunLameDuckTimer();
773 base::RunLoop().RunUntilIdle();
774 EXPECT_EQ(version_1.get(), reg->active_version());
775 EXPECT_TRUE(IsLameDuckTimerRunning());
776
777 // Continue on to the next lame duck timer tick.
778 clock_1.Advance(kMaxLameDuckTime + base::TimeDelta::FromSeconds(1));
779
780 // Activation should happen by the lame duck timer.
781 RunLameDuckTimer();
782 base::RunLoop().RunUntilIdle();
783 EXPECT_EQ(version_2.get(), reg->active_version());
784 EXPECT_FALSE(IsLameDuckTimerRunning());
785 }
786
787 INSTANTIATE_TEST_SUITE_P(ServiceWorkerActivationTestWithDevTools,
788 ServiceWorkerActivationTest,
789 testing::Bool());
790
791 // Sets up a registration with a ServiceWorkerRegistrationObjectHost to hold it.
792 class ServiceWorkerRegistrationObjectHostTest
793 : public ServiceWorkerRegistrationTest {
794 protected:
SetUp()795 void SetUp() override {
796 ServiceWorkerRegistrationTest::SetUp();
797 mojo::core::SetDefaultProcessErrorCallback(base::AdaptCallbackForRepeating(
798 base::BindOnce(&ServiceWorkerRegistrationObjectHostTest::OnMojoError,
799 base::Unretained(this))));
800 }
801
TearDown()802 void TearDown() override {
803 mojo::core::SetDefaultProcessErrorCallback(
804 mojo::core::ProcessErrorCallback());
805 ServiceWorkerRegistrationTest::TearDown();
806 }
807
808 // Pass nullptr for |out_error_msg| if it's not needed.
CallUpdate(blink::mojom::ServiceWorkerRegistrationObjectHost * registration_host,std::string * out_error_msg)809 blink::mojom::ServiceWorkerErrorType CallUpdate(
810 blink::mojom::ServiceWorkerRegistrationObjectHost* registration_host,
811 std::string* out_error_msg) {
812 blink::mojom::ServiceWorkerErrorType out_error =
813 blink::mojom::ServiceWorkerErrorType::kUnknown;
814 registration_host->Update(
815 blink::mojom::FetchClientSettingsObject::New(),
816 base::BindLambdaForTesting(
817 [&out_error, &out_error_msg](
818 blink::mojom::ServiceWorkerErrorType error,
819 const base::Optional<std::string>& error_msg) {
820 out_error = error;
821 if (out_error_msg) {
822 *out_error_msg = error_msg ? *error_msg : "";
823 }
824 }));
825 base::RunLoop().RunUntilIdle();
826 return out_error;
827 }
828
CallDelayUpdate(blink::mojom::ServiceWorkerContainerType provider_type,ServiceWorkerRegistration * registration,ServiceWorkerVersion * version)829 blink::ServiceWorkerStatusCode CallDelayUpdate(
830 blink::mojom::ServiceWorkerContainerType provider_type,
831 ServiceWorkerRegistration* registration,
832 ServiceWorkerVersion* version) {
833 base::Optional<blink::ServiceWorkerStatusCode> status;
834 base::RunLoop run_loop;
835 ServiceWorkerRegistrationObjectHost::DelayUpdate(
836 blink::mojom::ServiceWorkerContainerType::kForServiceWorker,
837 registration, version,
838 base::BindOnce(
839 [](base::Optional<blink::ServiceWorkerStatusCode>* out_status,
840 base::OnceClosure callback,
841 blink::ServiceWorkerStatusCode status) {
842 *out_status = status;
843 std::move(callback).Run();
844 },
845 &status, run_loop.QuitClosure()));
846 run_loop.Run();
847 return status.value();
848 }
849
CallUnregister(blink::mojom::ServiceWorkerRegistrationObjectHost * registration_host)850 blink::mojom::ServiceWorkerErrorType CallUnregister(
851 blink::mojom::ServiceWorkerRegistrationObjectHost* registration_host) {
852 blink::mojom::ServiceWorkerErrorType error =
853 blink::mojom::ServiceWorkerErrorType::kUnknown;
854 registration_host->Unregister(base::BindOnce(
855 [](blink::mojom::ServiceWorkerErrorType* out_error,
856 blink::mojom::ServiceWorkerErrorType error,
857 const base::Optional<std::string>& error_msg) {
858 *out_error = error;
859 },
860 &error));
861 base::RunLoop().RunUntilIdle();
862 return error;
863 }
864
FindRegistrationInStorage(int64_t registration_id,const GURL & scope)865 blink::ServiceWorkerStatusCode FindRegistrationInStorage(
866 int64_t registration_id,
867 const GURL& scope) {
868 base::Optional<blink::ServiceWorkerStatusCode> status;
869 registry()->FindRegistrationForId(
870 registration_id, scope,
871 base::AdaptCallbackForRepeating(base::BindOnce(
872 [](base::Optional<blink::ServiceWorkerStatusCode>* out_status,
873 blink::ServiceWorkerStatusCode status,
874 scoped_refptr<ServiceWorkerRegistration> registration) {
875 *out_status = status;
876 },
877 &status)));
878 base::RunLoop().RunUntilIdle();
879 return status.value();
880 }
881
CreateNewRegistration(const GURL & scope)882 scoped_refptr<ServiceWorkerRegistration> CreateNewRegistration(
883 const GURL& scope) {
884 blink::mojom::ServiceWorkerRegistrationOptions options;
885 options.scope = scope;
886 return CreateNewServiceWorkerRegistration(context()->registry(), options);
887 }
888
CreateVersion(ServiceWorkerRegistration * registration,const GURL & script_url)889 scoped_refptr<ServiceWorkerVersion> CreateVersion(
890 ServiceWorkerRegistration* registration,
891 const GURL& script_url) {
892 scoped_refptr<ServiceWorkerVersion> version = CreateNewServiceWorkerVersion(
893 context()->registry(), registration, script_url,
894 blink::mojom::ScriptType::kClassic);
895 std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> records;
896 records.push_back(WriteToDiskCacheSync(storage(), version->script_url(),
897 {} /* headers */, "I'm the body",
898 "I'm the meta data"));
899 version->script_cache_map()->SetResources(records);
900 version->SetMainScriptResponse(
901 EmbeddedWorkerTestHelper::CreateMainScriptResponse());
902 version->set_fetch_handler_existence(
903 ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
904 version->SetStatus(ServiceWorkerVersion::INSTALLING);
905 return version;
906 }
907
SetUpRegistration(const GURL & scope,const GURL & script_url)908 int64_t SetUpRegistration(const GURL& scope, const GURL& script_url) {
909 storage()->LazyInitializeForTest();
910
911 // Prepare ServiceWorkerRegistration and ServiceWorkerVersion.
912 scoped_refptr<ServiceWorkerRegistration> registration =
913 CreateNewRegistration(scope);
914 scoped_refptr<ServiceWorkerVersion> version =
915 CreateVersion(registration.get(), script_url);
916
917 // Make the registration findable via storage functions.
918 bool called = false;
919 blink::ServiceWorkerStatusCode status =
920 blink::ServiceWorkerStatusCode::kErrorFailed;
921 registry()->StoreRegistration(
922 registration.get(), version.get(),
923 base::BindOnce(&SaveStatusCallback, &called, &status));
924 base::RunLoop().RunUntilIdle();
925 EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
926
927 return registration->id();
928 }
929
PrepareContainerHost(const GURL & document_url,base::WeakPtr<ServiceWorkerContainerHost> * out_container_host)930 ServiceWorkerRemoteProviderEndpoint PrepareContainerHost(
931 const GURL& document_url,
932 base::WeakPtr<ServiceWorkerContainerHost>* out_container_host) {
933 ServiceWorkerRemoteProviderEndpoint remote_endpoint;
934 base::WeakPtr<ServiceWorkerContainerHost> container_host =
935 CreateContainerHostForWindow(helper_->mock_render_process_id(),
936 true /* is_parent_frame_secure */,
937 context()->AsWeakPtr(), &remote_endpoint);
938 container_host->UpdateUrls(document_url,
939 net::SiteForCookies::FromUrl(document_url),
940 url::Origin::Create(document_url));
941 if (out_container_host)
942 *out_container_host = container_host;
943 return remote_endpoint;
944 }
945
946 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
GetRegistrationFromRemote(blink::mojom::ServiceWorkerContainerHost * container_host,const GURL & url)947 GetRegistrationFromRemote(
948 blink::mojom::ServiceWorkerContainerHost* container_host,
949 const GURL& url) {
950 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info;
951 container_host->GetRegistration(
952 url, base::BindOnce(
953 [](blink::mojom::ServiceWorkerRegistrationObjectInfoPtr*
954 out_registration_info,
955 blink::mojom::ServiceWorkerErrorType error,
956 const base::Optional<std::string>& error_msg,
957 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
958 registration) {
959 ASSERT_EQ(blink::mojom::ServiceWorkerErrorType::kNone,
960 error);
961 *out_registration_info = std::move(registration);
962 },
963 ®istration_info));
964 base::RunLoop().RunUntilIdle();
965 EXPECT_TRUE(registration_info->host_remote.is_valid());
966 return registration_info;
967 }
968
OnMojoError(const std::string & error)969 void OnMojoError(const std::string& error) { bad_messages_.push_back(error); }
970
971 std::vector<std::string> bad_messages_;
972 };
973
974 class ServiceWorkerRegistrationObjectHostUpdateTest
975 : public ServiceWorkerRegistrationObjectHostTest,
976 public testing::WithParamInterface<bool> {
977 public:
ServiceWorkerRegistrationObjectHostUpdateTest()978 ServiceWorkerRegistrationObjectHostUpdateTest()
979 : interceptor_(base::BindRepeating(&FakeNetwork::HandleRequest,
980 base::Unretained(&fake_network_))) {}
981 private:
982 FakeNetwork fake_network_;
983 URLLoaderInterceptor interceptor_;
984 };
985
986 INSTANTIATE_TEST_SUITE_P(ServiceWorkerRegistrationObjectHostUpdateTestP,
987 ServiceWorkerRegistrationObjectHostUpdateTest,
988 testing::Bool());
989
TEST_F(ServiceWorkerRegistrationObjectHostTest,BreakConnection_Destroy)990 TEST_F(ServiceWorkerRegistrationObjectHostTest, BreakConnection_Destroy) {
991 const GURL kScope("https://www.example.com/");
992 const GURL kScriptUrl("https://www.example.com/sw.js");
993 int64_t registration_id = SetUpRegistration(kScope, kScriptUrl);
994 ServiceWorkerRemoteProviderEndpoint remote_endpoint =
995 PrepareContainerHost(kScope, nullptr /* out_container_host */);
996 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
997 GetRegistrationFromRemote(remote_endpoint.host_remote()->get(), kScope);
998 mojo::AssociatedRemote<blink::mojom::ServiceWorkerRegistrationObjectHost>
999 registration_host;
1000 registration_host.Bind(std::move(info->host_remote));
1001
1002 EXPECT_NE(nullptr, context()->GetLiveRegistration(registration_id));
1003 registration_host.reset();
1004 base::RunLoop().RunUntilIdle();
1005 EXPECT_EQ(nullptr, context()->GetLiveRegistration(registration_id));
1006 }
1007
TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,Update_Success)1008 TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest, Update_Success) {
1009 const GURL kScope("https://www.example.com/");
1010 const GURL kScriptUrl("https://www.example.com/sw.js");
1011 SetUpRegistration(kScope, kScriptUrl);
1012 ServiceWorkerRemoteProviderEndpoint remote_endpoint =
1013 PrepareContainerHost(kScope, nullptr /* out_container_host */);
1014 mojo::AssociatedRemote<blink::mojom::ServiceWorkerRegistrationObjectHost>
1015 registration_host;
1016 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
1017 GetRegistrationFromRemote(remote_endpoint.host_remote()->get(), kScope);
1018 registration_host.Bind(std::move(info->host_remote));
1019 // Ignore the messages to the registration object, otherwise the callbacks
1020 // issued from |registration_host| may wait for receiving the messages to
1021 // |info->receiver|.
1022 info->receiver.reset();
1023
1024 EXPECT_EQ(blink::mojom::ServiceWorkerErrorType::kNone,
1025 CallUpdate(registration_host.get(), /*out_error_msg=*/nullptr));
1026 }
1027
TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,Update_CrossOriginShouldFail)1028 TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,
1029 Update_CrossOriginShouldFail) {
1030 const GURL kScope("https://www.example.com/");
1031 const GURL kScriptUrl("https://www.example.com/sw.js");
1032 SetUpRegistration(kScope, kScriptUrl);
1033 base::WeakPtr<ServiceWorkerContainerHost> container_host;
1034 ServiceWorkerRemoteProviderEndpoint remote_endpoint =
1035 PrepareContainerHost(kScope, &container_host);
1036 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
1037 GetRegistrationFromRemote(remote_endpoint.host_remote()->get(), kScope);
1038 mojo::AssociatedRemote<blink::mojom::ServiceWorkerRegistrationObjectHost>
1039 registration_host;
1040 registration_host.Bind(std::move(info->host_remote));
1041
1042 ASSERT_TRUE(bad_messages_.empty());
1043 GURL url("https://does.not.exist/");
1044 container_host->UpdateUrls(url, net::SiteForCookies::FromUrl(url),
1045 url::Origin::Create(url));
1046 CallUpdate(registration_host.get(), /*out_error_msg=*/nullptr);
1047 EXPECT_EQ(1u, bad_messages_.size());
1048 }
1049
TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,Update_ContentSettingsDisallowsServiceWorker)1050 TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,
1051 Update_ContentSettingsDisallowsServiceWorker) {
1052 const GURL kScope("https://www.example.com/");
1053 const GURL kScriptUrl("https://www.example.com/sw.js");
1054 SetUpRegistration(kScope, kScriptUrl);
1055 ServiceWorkerRemoteProviderEndpoint remote_endpoint =
1056 PrepareContainerHost(kScope, nullptr /* out_container_host */);
1057 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
1058 GetRegistrationFromRemote(remote_endpoint.host_remote()->get(), kScope);
1059 mojo::AssociatedRemote<blink::mojom::ServiceWorkerRegistrationObjectHost>
1060 registration_host;
1061 registration_host.Bind(std::move(info->host_remote));
1062
1063 ServiceWorkerTestContentBrowserClient test_browser_client;
1064 ContentBrowserClient* old_browser_client =
1065 SetBrowserClientForTesting(&test_browser_client);
1066 std::string error_msg;
1067 EXPECT_EQ(blink::mojom::ServiceWorkerErrorType::kDisabled,
1068 CallUpdate(registration_host.get(), &error_msg));
1069 EXPECT_EQ(
1070 error_msg,
1071 "Failed to update a ServiceWorker for scope ('https://www.example.com/') "
1072 "with script ('https://www.example.com/sw.js'): The user denied "
1073 "permission to use Service Worker.");
1074 SetBrowserClientForTesting(old_browser_client);
1075 }
1076
TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,Update_NoDelayFromControllee)1077 TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,
1078 Update_NoDelayFromControllee) {
1079 const GURL kScope("https://www.example.com/");
1080 const GURL kScriptUrl("https://www.example.com/sw.js");
1081 int64_t registration_id = SetUpRegistration(kScope, kScriptUrl);
1082 ServiceWorkerRemoteProviderEndpoint remote_endpoint =
1083 PrepareContainerHost(kScope, nullptr /* out_container_host */);
1084 mojo::AssociatedRemote<blink::mojom::ServiceWorkerRegistrationObjectHost>
1085 registration_host;
1086
1087 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
1088 GetRegistrationFromRemote(remote_endpoint.host_remote()->get(), kScope);
1089 registration_host.Bind(std::move(info->host_remote));
1090 // Ignore the messages to the registration object, otherwise the callbacks
1091 // issued from |registration_host| may wait for receiving the messages to
1092 // |info->receiver|.
1093 info->receiver.reset();
1094
1095 // Get registration and set |self_update_delay| to zero.
1096 ServiceWorkerRegistration* registration =
1097 context()->GetLiveRegistration(registration_id);
1098 ASSERT_TRUE(registration);
1099 registration->set_self_update_delay(base::TimeDelta());
1100 EXPECT_EQ(base::TimeDelta(), registration->self_update_delay());
1101
1102 EXPECT_EQ(blink::mojom::ServiceWorkerErrorType::kNone,
1103 CallUpdate(registration_host.get(), /*out_error_msg=*/nullptr));
1104 EXPECT_EQ(base::TimeDelta(), registration->self_update_delay());
1105 }
1106
TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,Update_DelayFromWorkerWithoutControllee)1107 TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,
1108 Update_DelayFromWorkerWithoutControllee) {
1109 const GURL kScope("https://www.example.com/");
1110 const GURL kScriptUrl("https://www.example.com/sw.js");
1111 scoped_refptr<ServiceWorkerRegistration> registration =
1112 CreateNewRegistration(kScope);
1113 scoped_refptr<ServiceWorkerVersion> version =
1114 CreateVersion(registration.get(), kScriptUrl);
1115
1116 // Initially set |self_update_delay| to zero.
1117 registration->set_self_update_delay(base::TimeDelta());
1118 EXPECT_EQ(base::TimeDelta(), registration->self_update_delay());
1119
1120 EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
1121 CallDelayUpdate(
1122 blink::mojom::ServiceWorkerContainerType::kForServiceWorker,
1123 registration.get(), version.get()));
1124 EXPECT_LT(base::TimeDelta(), registration->self_update_delay());
1125
1126 // TODO(falken): Add a test verifying that a delayed update will be executed
1127 // eventually.
1128
1129 // Set |self_update_delay| to a time so that update() will reject immediately.
1130 registration->set_self_update_delay(base::TimeDelta::FromMinutes(5));
1131 EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout,
1132 CallDelayUpdate(
1133 blink::mojom::ServiceWorkerContainerType::kForServiceWorker,
1134 registration.get(), version.get()));
1135 EXPECT_LE(base::TimeDelta::FromMinutes(5), registration->self_update_delay());
1136 }
1137
TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,Update_NoDelayFromWorkerWithControllee)1138 TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,
1139 Update_NoDelayFromWorkerWithControllee) {
1140 const GURL kScope("https://www.example.com/");
1141 const GURL kScriptUrl("https://www.example.com/sw.js");
1142 scoped_refptr<ServiceWorkerRegistration> registration =
1143 CreateNewRegistration(kScope);
1144
1145 scoped_refptr<ServiceWorkerVersion> version =
1146 CreateVersion(registration.get(), kScriptUrl);
1147 version->SetStatus(ServiceWorkerVersion::ACTIVATED);
1148
1149 ServiceWorkerRemoteProviderEndpoint remote_endpoint;
1150 base::WeakPtr<ServiceWorkerContainerHost> container_host =
1151 CreateContainerHostForWindow(helper_->mock_render_process_id(),
1152 true /* is_parent_frame_secure */,
1153 context()->AsWeakPtr(), &remote_endpoint);
1154 container_host->UpdateUrls(kScope, net::SiteForCookies::FromUrl(kScope),
1155 url::Origin::Create(kScope));
1156 version->AddControllee(container_host.get());
1157
1158 // Initially set |self_update_delay| to zero.
1159 registration->set_self_update_delay(base::TimeDelta());
1160 EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
1161 CallDelayUpdate(
1162 blink::mojom::ServiceWorkerContainerType::kForServiceWorker,
1163 registration.get(), version.get()));
1164 EXPECT_EQ(base::TimeDelta(), registration->self_update_delay());
1165
1166 // Set |self_update_delay| to a time so that update() will reject immediately
1167 // if the worker doesn't have at least one controlee.
1168 registration->set_self_update_delay(base::TimeDelta::FromMinutes(5));
1169 EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
1170 CallDelayUpdate(
1171 blink::mojom::ServiceWorkerContainerType::kForServiceWorker,
1172 registration.get(), version.get()));
1173 EXPECT_EQ(base::TimeDelta::FromMinutes(5), registration->self_update_delay());
1174 }
1175
TEST_F(ServiceWorkerRegistrationObjectHostTest,Unregister_Success)1176 TEST_F(ServiceWorkerRegistrationObjectHostTest, Unregister_Success) {
1177 const GURL kScope("https://www.example.com/");
1178 const GURL kScriptUrl("https://www.example.com/sw.js");
1179 int64_t registration_id = SetUpRegistration(kScope, kScriptUrl);
1180 ServiceWorkerRemoteProviderEndpoint remote_endpoint =
1181 PrepareContainerHost(kScope, nullptr /* out_container_host */);
1182 mojo::AssociatedRemote<blink::mojom::ServiceWorkerRegistrationObjectHost>
1183 registration_host;
1184 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
1185 GetRegistrationFromRemote(remote_endpoint.host_remote()->get(), kScope);
1186 registration_host.Bind(std::move(info->host_remote));
1187 // Ignore the messages to the registration object and corresponding service
1188 // worker objects, otherwise the callbacks issued from |registration_host|
1189 // may wait for receiving the messages to them.
1190 info->receiver.reset();
1191 info->waiting->receiver.reset();
1192
1193 EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
1194 FindRegistrationInStorage(registration_id, kScope));
1195 EXPECT_EQ(blink::mojom::ServiceWorkerErrorType::kNone,
1196 CallUnregister(registration_host.get()));
1197
1198 EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
1199 FindRegistrationInStorage(registration_id, kScope));
1200 EXPECT_EQ(blink::mojom::ServiceWorkerErrorType::kNotFound,
1201 CallUnregister(registration_host.get()));
1202 }
1203
TEST_F(ServiceWorkerRegistrationObjectHostTest,Unregister_CrossOriginShouldFail)1204 TEST_F(ServiceWorkerRegistrationObjectHostTest,
1205 Unregister_CrossOriginShouldFail) {
1206 const GURL kScope("https://www.example.com/");
1207 const GURL kScriptUrl("https://www.example.com/sw.js");
1208 SetUpRegistration(kScope, kScriptUrl);
1209 base::WeakPtr<ServiceWorkerContainerHost> container_host;
1210 ServiceWorkerRemoteProviderEndpoint remote_endpoint =
1211 PrepareContainerHost(kScope, &container_host);
1212 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
1213 GetRegistrationFromRemote(remote_endpoint.host_remote()->get(), kScope);
1214 mojo::AssociatedRemote<blink::mojom::ServiceWorkerRegistrationObjectHost>
1215 registration_host;
1216 registration_host.Bind(std::move(info->host_remote));
1217
1218 ASSERT_TRUE(bad_messages_.empty());
1219 container_host->UpdateUrls(
1220 GURL("https://does.not.exist/"),
1221 net::SiteForCookies::FromUrl(GURL("https://does.not.exist/")),
1222 url::Origin::Create(GURL("https://does.not.exist/")));
1223 CallUnregister(registration_host.get());
1224 EXPECT_EQ(1u, bad_messages_.size());
1225 }
1226
TEST_F(ServiceWorkerRegistrationObjectHostTest,Unregister_ContentSettingsDisallowsServiceWorker)1227 TEST_F(ServiceWorkerRegistrationObjectHostTest,
1228 Unregister_ContentSettingsDisallowsServiceWorker) {
1229 const GURL kScope("https://www.example.com/");
1230 const GURL kScriptUrl("https://www.example.com/sw.js");
1231 SetUpRegistration(kScope, kScriptUrl);
1232 ServiceWorkerRemoteProviderEndpoint remote_endpoint =
1233 PrepareContainerHost(kScope, nullptr /* out_container_host */);
1234 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
1235 GetRegistrationFromRemote(remote_endpoint.host_remote()->get(), kScope);
1236 mojo::AssociatedRemote<blink::mojom::ServiceWorkerRegistrationObjectHost>
1237 registration_host;
1238 registration_host.Bind(std::move(info->host_remote));
1239
1240 ServiceWorkerTestContentBrowserClient test_browser_client;
1241 ContentBrowserClient* old_browser_client =
1242 SetBrowserClientForTesting(&test_browser_client);
1243 EXPECT_EQ(blink::mojom::ServiceWorkerErrorType::kDisabled,
1244 CallUnregister(registration_host.get()));
1245 SetBrowserClientForTesting(old_browser_client);
1246 }
1247
TEST_F(ServiceWorkerRegistrationObjectHostTest,SetVersionAttributes)1248 TEST_F(ServiceWorkerRegistrationObjectHostTest, SetVersionAttributes) {
1249 const GURL kScope("https://www.example.com/");
1250 const GURL kScriptUrl("https://www.example.com/sw.js");
1251 int64_t registration_id = SetUpRegistration(kScope, kScriptUrl);
1252 ServiceWorkerRemoteProviderEndpoint remote_endpoint =
1253 PrepareContainerHost(kScope, nullptr /* out_container_host */);
1254 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
1255 GetRegistrationFromRemote(remote_endpoint.host_remote()->get(), kScope);
1256 EXPECT_EQ(registration_id, info->registration_id);
1257 EXPECT_TRUE(info->receiver.is_valid());
1258 auto mock_registration_object =
1259 std::make_unique<MockServiceWorkerRegistrationObject>(
1260 std::move(info->receiver));
1261
1262 ServiceWorkerRegistration* registration =
1263 context()->GetLiveRegistration(registration_id);
1264 ASSERT_NE(nullptr, registration);
1265 const int64_t version_1_id = 1L;
1266 const int64_t version_2_id = 2L;
1267 scoped_refptr<ServiceWorkerVersion> version_1 =
1268 base::MakeRefCounted<ServiceWorkerVersion>(
1269 registration, kScriptUrl, blink::mojom::ScriptType::kClassic,
1270 version_1_id, context()->AsWeakPtr());
1271 scoped_refptr<ServiceWorkerVersion> version_2 =
1272 base::MakeRefCounted<ServiceWorkerVersion>(
1273 registration, kScriptUrl, blink::mojom::ScriptType::kClassic,
1274 version_2_id, context()->AsWeakPtr());
1275
1276 // Set an active worker.
1277 registration->SetActiveVersion(version_1);
1278 EXPECT_EQ(version_1.get(), registration->active_version());
1279 base::RunLoop().RunUntilIdle();
1280 EXPECT_EQ(1, mock_registration_object->set_version_attributes_called_count());
1281 EXPECT_FALSE(mock_registration_object->changed_mask().installing);
1282 EXPECT_FALSE(mock_registration_object->installing());
1283 EXPECT_FALSE(mock_registration_object->changed_mask().waiting);
1284 EXPECT_FALSE(mock_registration_object->waiting());
1285 EXPECT_TRUE(mock_registration_object->changed_mask().active);
1286 EXPECT_TRUE(mock_registration_object->active());
1287 EXPECT_EQ(version_1_id, mock_registration_object->active()->version_id);
1288 EXPECT_EQ(kScriptUrl, mock_registration_object->active()->url);
1289
1290 // Set an installing worker.
1291 registration->SetInstallingVersion(version_2);
1292 EXPECT_EQ(version_2.get(), registration->installing_version());
1293 base::RunLoop().RunUntilIdle();
1294 EXPECT_EQ(2, mock_registration_object->set_version_attributes_called_count());
1295 EXPECT_TRUE(mock_registration_object->changed_mask().installing);
1296 EXPECT_TRUE(mock_registration_object->installing());
1297 EXPECT_FALSE(mock_registration_object->changed_mask().waiting);
1298 EXPECT_FALSE(mock_registration_object->waiting());
1299 EXPECT_FALSE(mock_registration_object->changed_mask().active);
1300 EXPECT_FALSE(mock_registration_object->active());
1301 EXPECT_EQ(version_2_id, mock_registration_object->installing()->version_id);
1302 EXPECT_EQ(kScriptUrl, mock_registration_object->installing()->url);
1303
1304 // Promote the installing worker to waiting.
1305 registration->SetWaitingVersion(version_2);
1306 EXPECT_EQ(version_2.get(), registration->waiting_version());
1307 EXPECT_FALSE(registration->installing_version());
1308 base::RunLoop().RunUntilIdle();
1309 EXPECT_EQ(3, mock_registration_object->set_version_attributes_called_count());
1310 EXPECT_TRUE(mock_registration_object->changed_mask().installing);
1311 EXPECT_FALSE(mock_registration_object->installing());
1312 EXPECT_TRUE(mock_registration_object->changed_mask().waiting);
1313 EXPECT_TRUE(mock_registration_object->waiting());
1314 EXPECT_FALSE(mock_registration_object->changed_mask().active);
1315 EXPECT_FALSE(mock_registration_object->active());
1316 EXPECT_EQ(version_2_id, mock_registration_object->waiting()->version_id);
1317 EXPECT_EQ(kScriptUrl, mock_registration_object->waiting()->url);
1318
1319 // Remove the waiting worker.
1320 registration->UnsetVersion(version_2.get());
1321 EXPECT_FALSE(registration->waiting_version());
1322 base::RunLoop().RunUntilIdle();
1323 EXPECT_EQ(4, mock_registration_object->set_version_attributes_called_count());
1324 EXPECT_FALSE(mock_registration_object->changed_mask().installing);
1325 EXPECT_FALSE(mock_registration_object->installing());
1326 EXPECT_TRUE(mock_registration_object->changed_mask().waiting);
1327 EXPECT_FALSE(mock_registration_object->waiting());
1328 EXPECT_FALSE(mock_registration_object->changed_mask().active);
1329 EXPECT_FALSE(mock_registration_object->active());
1330 }
1331
TEST_F(ServiceWorkerRegistrationObjectHostTest,SetUpdateViaCache)1332 TEST_F(ServiceWorkerRegistrationObjectHostTest, SetUpdateViaCache) {
1333 const GURL kScope("https://www.example.com/");
1334 const GURL kScriptUrl("https://www.example.com/sw.js");
1335 int64_t registration_id = SetUpRegistration(kScope, kScriptUrl);
1336 ServiceWorkerRemoteProviderEndpoint remote_endpoint =
1337 PrepareContainerHost(kScope, nullptr /* out_container_host */);
1338 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
1339 GetRegistrationFromRemote(remote_endpoint.host_remote()->get(), kScope);
1340 EXPECT_EQ(registration_id, info->registration_id);
1341 EXPECT_TRUE(info->receiver.is_valid());
1342 auto mock_registration_object =
1343 std::make_unique<MockServiceWorkerRegistrationObject>(
1344 std::move(info->receiver));
1345
1346 ServiceWorkerRegistration* registration =
1347 context()->GetLiveRegistration(registration_id);
1348 ASSERT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kImports,
1349 registration->update_via_cache());
1350 ASSERT_EQ(0, mock_registration_object->set_update_via_cache_called_count());
1351 ASSERT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kImports,
1352 mock_registration_object->update_via_cache());
1353
1354 registration->SetUpdateViaCache(
1355 blink::mojom::ServiceWorkerUpdateViaCache::kImports);
1356 base::RunLoop().RunUntilIdle();
1357 EXPECT_EQ(0, mock_registration_object->set_update_via_cache_called_count());
1358 EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kImports,
1359 mock_registration_object->update_via_cache());
1360
1361 registration->SetUpdateViaCache(
1362 blink::mojom::ServiceWorkerUpdateViaCache::kAll);
1363 base::RunLoop().RunUntilIdle();
1364 EXPECT_EQ(1, mock_registration_object->set_update_via_cache_called_count());
1365 EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kAll,
1366 mock_registration_object->update_via_cache());
1367
1368 registration->SetUpdateViaCache(
1369 blink::mojom::ServiceWorkerUpdateViaCache::kNone);
1370 base::RunLoop().RunUntilIdle();
1371 EXPECT_EQ(2, mock_registration_object->set_update_via_cache_called_count());
1372 EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kNone,
1373 mock_registration_object->update_via_cache());
1374
1375 registration->SetUpdateViaCache(
1376 blink::mojom::ServiceWorkerUpdateViaCache::kImports);
1377 base::RunLoop().RunUntilIdle();
1378 EXPECT_EQ(3, mock_registration_object->set_update_via_cache_called_count());
1379 EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kImports,
1380 mock_registration_object->update_via_cache());
1381 }
1382
TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest,UpdateFound)1383 TEST_P(ServiceWorkerRegistrationObjectHostUpdateTest, UpdateFound) {
1384 const GURL kScope("https://www.example.com/");
1385 const GURL kScriptUrl("https://www.example.com/sw.js");
1386 int64_t registration_id = SetUpRegistration(kScope, kScriptUrl);
1387 ServiceWorkerRemoteProviderEndpoint remote_endpoint =
1388 PrepareContainerHost(kScope, nullptr /* out_container_host */);
1389 blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
1390 GetRegistrationFromRemote(remote_endpoint.host_remote()->get(), kScope);
1391 EXPECT_EQ(registration_id, info->registration_id);
1392 EXPECT_TRUE(info->receiver.is_valid());
1393 auto mock_registration_object =
1394 std::make_unique<MockServiceWorkerRegistrationObject>(
1395 std::move(info->receiver));
1396
1397 ServiceWorkerRegistration* registration =
1398 context()->GetLiveRegistration(registration_id);
1399 ASSERT_NE(nullptr, registration);
1400 EXPECT_EQ(0, mock_registration_object->update_found_called_count());
1401 registration->NotifyUpdateFound();
1402 base::RunLoop().RunUntilIdle();
1403 EXPECT_EQ(1, mock_registration_object->update_found_called_count());
1404 }
1405
1406 } // namespace content
1407