Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1020)

Side by Side Diff: content/browser/service_worker/service_worker_registration_unittest.cc

Issue 2119143002: service worker: Wait for inflight requests before activating (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 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() { return request_id_; }
251
252 private:
253 scoped_refptr<ServiceWorkerRegistration> registration_;
254 std::unique_ptr<ServiceWorkerProviderHost> host_;
255 int request_id_;
256 };
257
258 // Test activation triggered by loss of controllee.
259 TEST_F(ServiceWorkerActivationTest, NoControllee) {
nhiroki 2016/07/08 05:04:42 It would be better to swap line 258-259 with line
falken 2016/07/08 07:06:45 Good eye, done.
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 finishing all requests.
277 TEST_F(ServiceWorkerActivationTest, NoInflightRequest) {
nhiroki 2016/07/08 05:04:42 ditto.
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698