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

Unified Diff: content/browser/service_worker/service_worker_dispatcher_host_unittest.cc

Issue 1799413002: ServiceWorker: Release a reference when it fails to dispatch ExtendableMessageEvent (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@move_dispatch_extendable_message_event
Patch Set: fix build failures Created 4 years, 9 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_dispatcher_host_unittest.cc
diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index 9bce9aec5328300bd91f5d067ca8a609fd861709..d8a370af8bf8414b14eba126e477b64f01c59082 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -11,11 +11,13 @@
#include "base/files/file_path.h"
#include "base/run_loop.h"
#include "content/browser/browser_thread_impl.h"
+#include "content/browser/message_port_service.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_registry.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_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_handle.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/common/content_switches.h"
@@ -35,8 +37,17 @@ static void SaveStatusCallback(bool* called,
*out = status;
}
+void SetUpDummyMessagePort(std::vector<TransferredMessagePort>* ports) {
+ int port_id = -1;
+ MessagePortService::GetInstance()->Create(MSG_ROUTING_NONE, nullptr,
+ &port_id);
+ TransferredMessagePort dummy_port;
+ dummy_port.id = port_id;
+ ports->push_back(dummy_port);
}
+} // namespace
+
static const int kRenderFrameId = 1;
class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
@@ -65,25 +76,81 @@ class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
~TestingServiceWorkerDispatcherHost() override {}
};
+class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
+ public:
+ FailToStartWorkerTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
+
+ void OnStartWorker(int embedded_worker_id,
+ int64_t service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download) override {
+ EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
+ registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
+ }
+};
+
class ServiceWorkerDispatcherHostTest : public testing::Test {
protected:
ServiceWorkerDispatcherHostTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
void SetUp() override {
- helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
- dispatcher_host_ = new TestingServiceWorkerDispatcherHost(
- helper_->mock_render_process_id(), context_wrapper(),
- &resource_context_, helper_.get());
+ Initialize(make_scoped_ptr(new EmbeddedWorkerTestHelper(base::FilePath())));
}
- void TearDown() override { helper_.reset(); }
+ void TearDown() override {
+ version_ = nullptr;
+ registration_ = nullptr;
+ helper_.reset();
+ }
ServiceWorkerContextCore* context() { return helper_->context(); }
ServiceWorkerContextWrapper* context_wrapper() {
return helper_->context_wrapper();
}
+ void Initialize(scoped_ptr<EmbeddedWorkerTestHelper> helper) {
+ helper_.reset(helper.release());
+ dispatcher_host_ = new TestingServiceWorkerDispatcherHost(
+ helper_->mock_render_process_id(), context_wrapper(),
+ &resource_context_, helper_.get());
+ }
+
+ void SetUpRegistration(const GURL& scope, const GURL& script_url) {
+ registration_ = new ServiceWorkerRegistration(
+ scope, 1L, helper_->context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(registration_.get(), script_url, 1L,
+ helper_->context()->AsWeakPtr());
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records;
+ records.push_back(
+ ServiceWorkerDatabase::ResourceRecord(10, version_->script_url(), 100));
+ version_->script_cache_map()->SetResources(records);
+
+ // Make the registration findable via storage functions.
+ helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing));
+ base::RunLoop().RunUntilIdle();
+ bool called = false;
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ helper_->context()->storage()->StoreRegistration(
+ registration_.get(), version_.get(),
+ base::Bind(&SaveStatusCallback, &called, &status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ }
+
+ void SendProviderCreated(ServiceWorkerProviderType type,
+ const GURL& pattern) {
+ const int64_t kProviderId = 99;
+ dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated(
+ kProviderId, MSG_ROUTING_NONE, type));
+ helper_->SimulateAddProcessToPattern(pattern,
+ helper_->mock_render_process_id());
+ provider_host_ = context()->GetProviderHost(
+ helper_->mock_render_process_id(), kProviderId);
+ }
+
void SendRegister(int64_t provider_id, GURL pattern, GURL worker_url) {
dispatcher_host_->OnMessageReceived(
ServiceWorkerHostMsg_RegisterServiceWorker(
@@ -146,6 +213,18 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
dispatcher_host_->ipc_sink()->ClearMessages();
}
+ void DispatchExtendableMessageEvent(
+ scoped_refptr<ServiceWorkerVersion> worker,
+ const base::string16& message,
+ const url::Origin& source_origin,
+ const std::vector<TransferredMessagePort>& sent_message_ports,
+ ServiceWorkerProviderHost* sender_provider_host,
+ const ServiceWorkerDispatcherHost::StatusCallback& callback) {
+ dispatcher_host_->DispatchExtendableMessageEvent(
+ std::move(worker), message, source_origin, sent_message_ports,
+ sender_provider_host, callback);
+ }
+
ServiceWorkerProviderHost* CreateServiceWorkerProviderHost(int provider_id) {
return new ServiceWorkerProviderHost(
helper_->mock_render_process_id(), kRenderFrameId, provider_id,
@@ -153,11 +232,13 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
dispatcher_host_.get());
}
-
TestBrowserThreadBundle browser_thread_bundle_;
content::MockResourceContext resource_context_;
scoped_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_;
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ scoped_refptr<ServiceWorkerVersion> version_;
+ ServiceWorkerProviderHost* provider_host_;
};
class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
@@ -526,61 +607,33 @@ TEST_F(ServiceWorkerDispatcherHostTest, GetRegistrations_EarlyContextDeletion) {
}
TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
+ GURL pattern = GURL("http://www.example.com/");
+ GURL script_url = GURL("http://www.example.com/service_worker.js");
int process_id = helper_->mock_render_process_id();
- // Add a provider and worker.
- const int64_t kProviderId = 99; // Dummy value
- dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated(
- kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW));
+ SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_WINDOW, pattern);
+ SetUpRegistration(pattern, script_url);
+ int64_t provider_id = provider_host_->provider_id();
- GURL pattern = GURL("http://www.example.com/");
- scoped_refptr<ServiceWorkerRegistration> registration(
- new ServiceWorkerRegistration(pattern,
- 1L,
- helper_->context()->AsWeakPtr()));
- scoped_refptr<ServiceWorkerVersion> version(
- new ServiceWorkerVersion(registration.get(),
- GURL("http://www.example.com/service_worker.js"),
- 1L,
- helper_->context()->AsWeakPtr()));
- std::vector<ServiceWorkerDatabase::ResourceRecord> records;
- records.push_back(
- ServiceWorkerDatabase::ResourceRecord(10, version->script_url(), 100));
- version->script_cache_map()->SetResources(records);
-
- // Make the registration findable via storage functions.
- helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing));
- base::RunLoop().RunUntilIdle();
+ // Start up the worker.
bool called = false;
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_ABORT;
- helper_->context()->storage()->StoreRegistration(
- registration.get(),
- version.get(),
- base::Bind(&SaveStatusCallback, &called, &status));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(called);
- ASSERT_EQ(SERVICE_WORKER_OK, status);
-
- helper_->SimulateAddProcessToPattern(pattern, process_id);
-
- // Start up the worker.
- status = SERVICE_WORKER_ERROR_ABORT;
- version->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
- base::Bind(&SaveStatusCallback, &called, &status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ base::Bind(&SaveStatusCallback, &called, &status));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId));
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+ EXPECT_TRUE(context()->GetProviderHost(process_id, provider_id));
+ EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
// Simulate the render process crashing.
dispatcher_host_->OnFilterRemoved();
// The dispatcher host should clean up the state from the process.
- EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId));
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+ EXPECT_FALSE(context()->GetProviderHost(process_id, provider_id));
+ EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
// We should be able to hook up a new dispatcher host although the old object
// is not yet destroyed. This is what the browser does when reusing a crashed
@@ -593,8 +646,89 @@ TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
// the old dispatcher cleaned up the old provider host, the new one won't
// complain.
new_dispatcher_host->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated(
- kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW));
+ provider_id, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW));
EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_);
}
+TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent) {
+ GURL pattern = GURL("http://www.example.com/");
+ GURL script_url = GURL("http://www.example.com/service_worker.js");
+
+ SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, pattern);
+ SetUpRegistration(pattern, script_url);
+
+ // Set the running hosted version so that we can retrieve a valid service
+ // worker object information for the source attribute of the message event.
+ provider_host_->running_hosted_version_ = version_;
+
+ // Set aside the initial refcount of the worker handle.
+ provider_host_->GetOrCreateServiceWorkerHandle(version_.get());
+ ServiceWorkerHandle* sender_worker_handle =
+ dispatcher_host_->FindServiceWorkerHandle(provider_host_->provider_id(),
+ version_->version_id());
+ const int ref_count = sender_worker_handle->ref_count();
+
+ // Dispatch ExtendableMessageEvent.
+ std::vector<TransferredMessagePort> ports;
+ SetUpDummyMessagePort(&ports);
+ bool called = false;
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ DispatchExtendableMessageEvent(
+ version_, base::string16(), url::Origin(version_->scope().GetOrigin()),
+ ports, provider_host_, base::Bind(&SaveStatusCallback, &called, &status));
+ for (TransferredMessagePort port : ports)
+ EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
+ EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+
+ // Messages should be held until ports are created at the destination.
+ for (TransferredMessagePort port : ports)
+ EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
+
+ EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count());
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent_Fail) {
+ GURL pattern = GURL("http://www.example.com/");
+ GURL script_url = GURL("http://www.example.com/service_worker.js");
+
+ Initialize(make_scoped_ptr(new FailToStartWorkerTestHelper));
+ SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, pattern);
+ SetUpRegistration(pattern, script_url);
+
+ // Set the running hosted version so that we can retrieve a valid service
+ // worker object information for the source attribute of the message event.
+ provider_host_->running_hosted_version_ = version_;
+
+ // Set aside the initial refcount of the worker handle.
+ provider_host_->GetOrCreateServiceWorkerHandle(version_.get());
+ ServiceWorkerHandle* sender_worker_handle =
+ dispatcher_host_->FindServiceWorkerHandle(provider_host_->provider_id(),
+ version_->version_id());
+ const int ref_count = sender_worker_handle->ref_count();
+
+ // Try to dispatch ExtendableMessageEvent. This should fail to start the
+ // worker and to dispatch the event.
+ std::vector<TransferredMessagePort> ports;
+ SetUpDummyMessagePort(&ports);
+ bool called = false;
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ DispatchExtendableMessageEvent(
+ version_, base::string16(), url::Origin(version_->scope().GetOrigin()),
+ ports, provider_host_, base::Bind(&SaveStatusCallback, &called, &status));
+ for (TransferredMessagePort port : ports)
+ EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
+ EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
+
+ // The error callback should clean up the ports and handle.
+ for (TransferredMessagePort port : ports)
+ EXPECT_FALSE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
+ EXPECT_EQ(ref_count, sender_worker_handle->ref_count());
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698