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

Unified 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: reg 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/service_worker/service_worker_registration_unittest.cc
diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc
index 417896b6f419498e17dcd2a351ea72130f6e9fef..654a434ca4585ef84956dec0aeeb7d498b09a1c6 100644
--- a/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -11,15 +11,31 @@
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_registration_handle.h"
+#include "content/browser/service_worker/service_worker_test_utils.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content {
+namespace {
+
+int CreateInflightRequest(ServiceWorkerVersion* version) {
+ version->StartWorker(ServiceWorkerMetrics::EventType::PUSH,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ base::RunLoop().RunUntilIdle();
+ return version->StartRequest(
+ ServiceWorkerMetrics::EventType::PUSH,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+}
+
+} // namespace
+
class ServiceWorkerRegistrationTest : public testing::Test {
public:
ServiceWorkerRegistrationTest()
@@ -27,6 +43,9 @@ class ServiceWorkerRegistrationTest : public testing::Test {
void SetUp() override {
helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
+
+ helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing));
+ base::RunLoop().RunUntilIdle();
}
void TearDown() override {
@@ -35,6 +54,7 @@ class ServiceWorkerRegistrationTest : public testing::Test {
}
ServiceWorkerContextCore* context() { return helper_->context(); }
+ ServiceWorkerStorage* storage() { return helper_->context()->storage(); }
class RegistrationListener : public ServiceWorkerRegistration::Listener {
public:
@@ -160,4 +180,151 @@ TEST_F(ServiceWorkerRegistrationTest, FailedRegistrationNoCrash) {
// Don't crash when handle gets destructed.
}
+// Sets up a registration with a waiting worker, and an active worker
+// with a controllee and an inflight request.
+class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest {
+ public:
+ ServiceWorkerActivationTest() : ServiceWorkerRegistrationTest() {}
+
+ void SetUp() override {
+ ServiceWorkerRegistrationTest::SetUp();
+
+ const GURL kScope("https://www.example.not/");
+ const GURL kScript("https://www.example.not/service_worker.js");
+
+ registration_ = new ServiceWorkerRegistration(
+ kScope, storage()->NewRegistrationId(), context()->AsWeakPtr());
+
+ // Create an active version.
+ scoped_refptr<ServiceWorkerVersion> version_1 = new ServiceWorkerVersion(
+ registration_.get(), kScript, storage()->NewVersionId(),
+ context()->AsWeakPtr());
+ registration_->SetActiveVersion(version_1);
+ version_1->SetStatus(ServiceWorkerVersion::ACTIVATED);
+
+ // Store the registration.
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records;
+ records.push_back(ServiceWorkerDatabase::ResourceRecord(
+ 10, version_1->script_url(), 100));
+ version_1->script_cache_map()->SetResources(records);
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ context()->storage()->StoreRegistration(
+ registration_.get(), version_1.get(),
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(SERVICE_WORKER_OK, status);
+
+ // Give the active version a controllee.
+ host_.reset(new ServiceWorkerProviderHost(
+ 33 /* dummy render process id */,
+ MSG_ROUTING_NONE /* render_frame_id */, 1 /* dummy provider_id */,
+ SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+ ServiceWorkerProviderHost::FrameSecurityLevel::SECURE,
+ context()->AsWeakPtr(), nullptr));
+ version_1->AddControllee(host_.get());
+
+ // Give the active version an in-flight request.
+ inflight_request_id_ = CreateInflightRequest(version_1.get());
+
+ // Create a waiting version.
+ scoped_refptr<ServiceWorkerVersion> version_2 = new ServiceWorkerVersion(
+ registration_.get(), kScript, storage()->NewVersionId(),
+ context()->AsWeakPtr());
+ registration_->SetWaitingVersion(version_2);
+ version_2->SetStatus(ServiceWorkerVersion::INSTALLED);
+
+ // Set it to activate when ready. The original version should still be
+ // active.
+ registration_->ActivateWaitingVersionWhenReady();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_1.get(), registration_->active_version());
+ }
+
+ void TearDown() override {
+ registration_->active_version()->RemoveListener(registration_.get());
+ ServiceWorkerRegistrationTest::TearDown();
+ }
+
+ ServiceWorkerRegistration* registration() { return registration_.get(); }
+ ServiceWorkerProviderHost* controllee() { return host_.get(); }
+ int inflight_request_id() const { return inflight_request_id_; }
+
+ private:
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ std::unique_ptr<ServiceWorkerProviderHost> host_;
+ int inflight_request_id_ = -1;
+};
+
+// Test activation triggered by finishing all requests.
+TEST_F(ServiceWorkerActivationTest, NoInflightRequest) {
+ scoped_refptr<ServiceWorkerRegistration> reg = registration();
+ scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
+ scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
+
+ // Remove the controllee. Since there is an in-flight request,
+ // activation should not yet happen.
+ version_1->RemoveControllee(controllee());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_1.get(), reg->active_version());
+
+ // Finish the request. Activation should happen.
+ version_1->FinishRequest(inflight_request_id(), true /* was_handled */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_2.get(), reg->active_version());
+}
+
+// Test activation triggered by loss of controllee.
+TEST_F(ServiceWorkerActivationTest, NoControllee) {
+ scoped_refptr<ServiceWorkerRegistration> reg = registration();
+ scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
+ scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
+
+ // Finish the request. Since there is a controllee, activation should not yet
+ // happen.
+ version_1->FinishRequest(inflight_request_id(), true /* was_handled */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_1.get(), reg->active_version());
+
+ // Remove the controllee. Activation should happen.
+ version_1->RemoveControllee(controllee());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_2.get(), reg->active_version());
+}
+
+// Test activation triggered by skipWaiting.
+TEST_F(ServiceWorkerActivationTest, SkipWaiting) {
+ scoped_refptr<ServiceWorkerRegistration> reg = registration();
+ scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
+ scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
+
+ // Finish the in-flight request. Since there is a controllee,
+ // activation should not happen.
+ version_1->FinishRequest(inflight_request_id(), true /* was_handled */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_1.get(), reg->active_version());
+
+ // Call skipWaiting. Activation should happen.
+ version_2->OnSkipWaiting(77 /* dummy request_id */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_2.get(), reg->active_version());
+}
+
+// Test activation triggered by skipWaiting and finishing requests.
+TEST_F(ServiceWorkerActivationTest, SkipWaitingWithInflightRequest) {
+ scoped_refptr<ServiceWorkerRegistration> reg = registration();
+ scoped_refptr<ServiceWorkerVersion> version_1 = reg->active_version();
+ scoped_refptr<ServiceWorkerVersion> version_2 = reg->waiting_version();
+
+ // Set skip waiting flag. Since there is still an in-flight request,
+ // activation should not happen.
+ version_2->OnSkipWaiting(77 /* dummy request_id */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_1.get(), reg->active_version());
+
+ // Finish the request. Activation should happen.
+ version_1->FinishRequest(inflight_request_id(), true /* was_handled */);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(version_2.get(), reg->active_version());
+}
+
} // namespace content
« no previous file with comments | « content/browser/service_worker/service_worker_registration.cc ('k') | content/browser/service_worker/service_worker_storage.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698