OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/service_worker/service_worker_registration.h" | 5 #include "content/browser/service_worker/service_worker_registration.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/files/scoped_temp_dir.h" | 10 #include "base/files/scoped_temp_dir.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
13 #include "base/threading/thread_task_runner_handle.h" | 13 #include "base/threading/thread_task_runner_handle.h" |
| 14 #include "content/browser/service_worker/embedded_worker_status.h" |
14 #include "content/browser/service_worker/embedded_worker_test_helper.h" | 15 #include "content/browser/service_worker/embedded_worker_test_helper.h" |
15 #include "content/browser/service_worker/service_worker_context_core.h" | 16 #include "content/browser/service_worker/service_worker_context_core.h" |
16 #include "content/browser/service_worker/service_worker_registration_handle.h" | 17 #include "content/browser/service_worker/service_worker_registration_handle.h" |
| 18 #include "content/browser/service_worker/service_worker_test_utils.h" |
| 19 #include "content/common/service_worker/service_worker_utils.h" |
17 #include "content/public/test/test_browser_thread_bundle.h" | 20 #include "content/public/test/test_browser_thread_bundle.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
19 #include "url/gurl.h" | 22 #include "url/gurl.h" |
20 | 23 |
21 namespace content { | 24 namespace content { |
22 | 25 |
| 26 namespace { |
| 27 |
| 28 int CreateInflightRequest(ServiceWorkerVersion* version) { |
| 29 version->StartWorker(ServiceWorkerMetrics::EventType::PUSH, |
| 30 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
| 31 base::RunLoop().RunUntilIdle(); |
| 32 return version->StartRequest( |
| 33 ServiceWorkerMetrics::EventType::PUSH, |
| 34 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
| 35 } |
| 36 |
| 37 } // namespace |
| 38 |
23 class ServiceWorkerRegistrationTest : public testing::Test { | 39 class ServiceWorkerRegistrationTest : public testing::Test { |
24 public: | 40 public: |
25 ServiceWorkerRegistrationTest() | 41 ServiceWorkerRegistrationTest() |
26 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} | 42 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} |
27 | 43 |
28 void SetUp() override { | 44 void SetUp() override { |
29 helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath())); | 45 helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath())); |
| 46 |
| 47 helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing)); |
| 48 base::RunLoop().RunUntilIdle(); |
30 } | 49 } |
31 | 50 |
32 void TearDown() override { | 51 void TearDown() override { |
33 helper_.reset(); | 52 helper_.reset(); |
34 base::RunLoop().RunUntilIdle(); | 53 base::RunLoop().RunUntilIdle(); |
35 } | 54 } |
36 | 55 |
37 ServiceWorkerContextCore* context() { return helper_->context(); } | 56 ServiceWorkerContextCore* context() { return helper_->context(); } |
| 57 ServiceWorkerStorage* storage() { return helper_->context()->storage(); } |
38 | 58 |
39 class RegistrationListener : public ServiceWorkerRegistration::Listener { | 59 class RegistrationListener : public ServiceWorkerRegistration::Listener { |
40 public: | 60 public: |
41 RegistrationListener() {} | 61 RegistrationListener() {} |
42 ~RegistrationListener() { | 62 ~RegistrationListener() { |
43 if (observed_registration_.get()) | 63 if (observed_registration_.get()) |
44 observed_registration_->RemoveListener(this); | 64 observed_registration_->RemoveListener(this); |
45 } | 65 } |
46 | 66 |
47 void OnVersionAttributesChanged( | 67 void OnVersionAttributesChanged( |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 new ServiceWorkerRegistration(kScope, kRegistrationId, | 173 new ServiceWorkerRegistration(kScope, kRegistrationId, |
154 context()->AsWeakPtr()); | 174 context()->AsWeakPtr()); |
155 std::unique_ptr<ServiceWorkerRegistrationHandle> handle( | 175 std::unique_ptr<ServiceWorkerRegistrationHandle> handle( |
156 new ServiceWorkerRegistrationHandle( | 176 new ServiceWorkerRegistrationHandle( |
157 context()->AsWeakPtr(), base::WeakPtr<ServiceWorkerProviderHost>(), | 177 context()->AsWeakPtr(), base::WeakPtr<ServiceWorkerProviderHost>(), |
158 registration.get())); | 178 registration.get())); |
159 registration->NotifyRegistrationFailed(); | 179 registration->NotifyRegistrationFailed(); |
160 // Don't crash when handle gets destructed. | 180 // Don't crash when handle gets destructed. |
161 } | 181 } |
162 | 182 |
| 183 // Sets up a registration with a waiting worker, and an active worker |
| 184 // with a controllee and an inflight request. |
| 185 class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest { |
| 186 public: |
| 187 ServiceWorkerActivationTest() : ServiceWorkerRegistrationTest() {} |
| 188 |
| 189 void SetUp() override { |
| 190 ServiceWorkerRegistrationTest::SetUp(); |
| 191 |
| 192 const GURL kScope("https://www.example.not/"); |
| 193 const GURL kScript("https://www.example.not/service_worker.js"); |
| 194 |
| 195 registration_ = new ServiceWorkerRegistration( |
| 196 kScope, storage()->NewRegistrationId(), context()->AsWeakPtr()); |
| 197 |
| 198 // Create an active version. |
| 199 scoped_refptr<ServiceWorkerVersion> version_1 = new ServiceWorkerVersion( |
| 200 registration_.get(), kScript, storage()->NewVersionId(), |
| 201 context()->AsWeakPtr()); |
| 202 registration_->SetActiveVersion(version_1); |
| 203 version_1->SetStatus(ServiceWorkerVersion::ACTIVATED); |
| 204 |
| 205 // Store the registration. |
| 206 std::vector<ServiceWorkerDatabase::ResourceRecord> records; |
| 207 records.push_back(ServiceWorkerDatabase::ResourceRecord( |
| 208 10, version_1->script_url(), 100)); |
| 209 version_1->script_cache_map()->SetResources(records); |
| 210 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE; |
| 211 context()->storage()->StoreRegistration( |
| 212 registration_.get(), version_1.get(), |
| 213 CreateReceiverOnCurrentThread(&status)); |
| 214 base::RunLoop().RunUntilIdle(); |
| 215 ASSERT_EQ(SERVICE_WORKER_OK, status); |
| 216 |
| 217 // Give the active version a controllee. |
| 218 host_.reset(new ServiceWorkerProviderHost( |
| 219 33 /* dummy render process id */, |
| 220 MSG_ROUTING_NONE /* render_frame_id */, 1 /* dummy provider_id */, |
| 221 SERVICE_WORKER_PROVIDER_FOR_WINDOW, |
| 222 ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, |
| 223 context()->AsWeakPtr(), nullptr)); |
| 224 version_1->AddControllee(host_.get()); |
| 225 |
| 226 // Give the active version an in-flight request. |
| 227 inflight_request_id_ = CreateInflightRequest(version_1.get()); |
| 228 |
| 229 // Create a waiting version. |
| 230 scoped_refptr<ServiceWorkerVersion> version_2 = new ServiceWorkerVersion( |
| 231 registration_.get(), kScript, storage()->NewVersionId(), |
| 232 context()->AsWeakPtr()); |
| 233 registration_->SetWaitingVersion(version_2); |
| 234 version_2->SetStatus(ServiceWorkerVersion::INSTALLED); |
| 235 |
| 236 // Set it to activate when ready. The original version should still be |
| 237 // active. |
| 238 registration_->ActivateWaitingVersionWhenReady(); |
| 239 base::RunLoop().RunUntilIdle(); |
| 240 EXPECT_EQ(version_1.get(), registration_->active_version()); |
| 241 } |
| 242 |
| 243 void TearDown() override { |
| 244 registration_->active_version()->RemoveListener(registration_.get()); |
| 245 ServiceWorkerRegistrationTest::TearDown(); |
| 246 } |
| 247 |
| 248 ServiceWorkerRegistration* registration() { return registration_.get(); } |
| 249 ServiceWorkerProviderHost* controllee() { return host_.get(); } |
| 250 int inflight_request_id() const { return inflight_request_id_; } |
| 251 |
| 252 private: |
| 253 scoped_refptr<ServiceWorkerRegistration> registration_; |
| 254 std::unique_ptr<ServiceWorkerProviderHost> host_; |
| 255 int inflight_request_id_ = -1; |
| 256 }; |
| 257 |
| 258 // Test activation triggered by finishing all requests. |
| 259 TEST_F(ServiceWorkerActivationTest, NoInflightRequest) { |
| 260 scoped_refptr<ServiceWorkerRegistration> reg = registration(); |
| 261 scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version(); |
| 262 scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version(); |
| 263 |
| 264 // Remove the controllee. Since there is an in-flight request, |
| 265 // activation should not yet happen. |
| 266 version_1->RemoveControllee(controllee()); |
| 267 base::RunLoop().RunUntilIdle(); |
| 268 EXPECT_EQ(version_1.get(), reg->active_version()); |
| 269 |
| 270 // Finish the request. Activation should happen. |
| 271 version_1->FinishRequest(inflight_request_id(), true /* was_handled */); |
| 272 base::RunLoop().RunUntilIdle(); |
| 273 EXPECT_EQ(version_2.get(), reg->active_version()); |
| 274 } |
| 275 |
| 276 // Test activation triggered by loss of controllee. |
| 277 TEST_F(ServiceWorkerActivationTest, NoControllee) { |
| 278 scoped_refptr<ServiceWorkerRegistration> reg = registration(); |
| 279 scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version(); |
| 280 scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version(); |
| 281 |
| 282 // Finish the request. Since there is a controllee, activation should not yet |
| 283 // happen. |
| 284 version_1->FinishRequest(inflight_request_id(), true /* was_handled */); |
| 285 base::RunLoop().RunUntilIdle(); |
| 286 EXPECT_EQ(version_1.get(), reg->active_version()); |
| 287 |
| 288 // Remove the controllee. Activation should happen. |
| 289 version_1->RemoveControllee(controllee()); |
| 290 base::RunLoop().RunUntilIdle(); |
| 291 EXPECT_EQ(version_2.get(), reg->active_version()); |
| 292 } |
| 293 |
| 294 // Test activation triggered by skipWaiting. |
| 295 TEST_F(ServiceWorkerActivationTest, SkipWaiting) { |
| 296 scoped_refptr<ServiceWorkerRegistration> reg = registration(); |
| 297 scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version(); |
| 298 scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version(); |
| 299 |
| 300 // Finish the in-flight request. Since there is a controllee, |
| 301 // activation should not happen. |
| 302 version_1->FinishRequest(inflight_request_id(), true /* was_handled */); |
| 303 base::RunLoop().RunUntilIdle(); |
| 304 EXPECT_EQ(version_1.get(), reg->active_version()); |
| 305 |
| 306 // Call skipWaiting. Activation should happen. |
| 307 version_2->OnSkipWaiting(77 /* dummy request_id */); |
| 308 base::RunLoop().RunUntilIdle(); |
| 309 EXPECT_EQ(version_2.get(), reg->active_version()); |
| 310 } |
| 311 |
| 312 // Test activation triggered by skipWaiting and finishing requests. |
| 313 TEST_F(ServiceWorkerActivationTest, SkipWaitingWithInflightRequest) { |
| 314 scoped_refptr<ServiceWorkerRegistration> reg = registration(); |
| 315 scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version(); |
| 316 scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version(); |
| 317 |
| 318 // Set skip waiting flag. Since there is still an in-flight request, |
| 319 // activation should not happen. |
| 320 version_2->OnSkipWaiting(77 /* dummy request_id */); |
| 321 base::RunLoop().RunUntilIdle(); |
| 322 EXPECT_EQ(version_1.get(), reg->active_version()); |
| 323 |
| 324 // Finish the request. Activation should happen. |
| 325 version_1->FinishRequest(inflight_request_id(), true /* was_handled */); |
| 326 base::RunLoop().RunUntilIdle(); |
| 327 EXPECT_EQ(version_2.get(), reg->active_version()); |
| 328 } |
| 329 |
163 } // namespace content | 330 } // namespace content |
OLD | NEW |