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 84e1b6e0a35c49efd0b425b388fa04730bcfd8b6..f0cb6740a467cfcc8faf2e83e81c5454f2494f98 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,16 +76,27 @@ 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(); } |
@@ -84,6 +106,13 @@ class ServiceWorkerDispatcherHostTest : public testing::Test { |
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 SendRegister(int64_t provider_id, GURL pattern, GURL worker_url) { |
dispatcher_host_->OnMessageReceived( |
ServiceWorkerHostMsg_RegisterServiceWorker( |
@@ -146,6 +175,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,7 +194,6 @@ class ServiceWorkerDispatcherHostTest : public testing::Test { |
dispatcher_host_.get()); |
} |
- |
TestBrowserThreadBundle browser_thread_bundle_; |
content::MockResourceContext resource_context_; |
scoped_ptr<EmbeddedWorkerTestHelper> helper_; |
@@ -596,4 +636,146 @@ TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) { |
EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_); |
} |
+TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent) { |
+ GURL pattern = GURL("http://www.example.com/"); |
+ GURL scope = GURL("http://www.example.com/service_worker.js"); |
falken
2016/03/17 06:44:36
script_url
nhiroki
2016/03/17 07:58:17
Good eye. I wrote this line while I was thinking a
|
+ int process_id = helper_->mock_render_process_id(); |
+ |
+ // Add a provider for a service worker to send a message. |
+ const int64_t kProviderId = 99; |
+ dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( |
+ kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER)); |
+ helper_->SimulateAddProcessToPattern(pattern, process_id); |
+ ServiceWorkerProviderHost* sender_provider_host = |
+ context()->GetProviderHost(process_id, kProviderId); |
+ |
+ // Set up a registration and service worker to receive a message. |
+ scoped_refptr<ServiceWorkerRegistration> registration( |
+ new ServiceWorkerRegistration(pattern, 1L, |
+ helper_->context()->AsWeakPtr())); |
+ scoped_refptr<ServiceWorkerVersion> version(new ServiceWorkerVersion( |
+ registration.get(), scope, 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); |
+ ASSERT_EQ(SERVICE_WORKER_OK, status); |
falken
2016/03/17 06:44:36
Maybe it's time to refactor lines 640-673 and the
nhiroki
2016/03/17 07:58:17
Done.
|
+ |
+ // Set the running hosted version so that we can retrieve a valid service |
+ // worker object information for the source attribute of the message event. |
+ sender_provider_host->running_hosted_version_ = version; |
+ |
+ // Set aside the initial refcount of the worker handle. |
+ sender_provider_host->GetOrCreateServiceWorkerHandle(version.get()); |
+ ServiceWorkerHandle* sender_worker_handle = |
+ dispatcher_host_->FindServiceWorkerHandle( |
+ sender_provider_host->provider_id(), version->version_id()); |
+ const int ref_count = sender_worker_handle->ref_count(); |
+ |
+ // Dispatch ExtendableMessageEvent. |
+ std::vector<TransferredMessagePort> ports; |
+ SetUpDummyMessagePort(&ports); |
+ called = false; |
+ status = SERVICE_WORKER_ERROR_MAX_VALUE; |
+ DispatchExtendableMessageEvent( |
+ version, base::string16(), url::Origin(version->scope().GetOrigin()), |
+ ports, sender_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) { |
+ Initialize(make_scoped_ptr(new FailToStartWorkerTestHelper)); |
+ |
+ GURL pattern = GURL("http://www.example.com/"); |
+ GURL scope = GURL("http://www.example.com/service_worker.js"); |
falken
2016/03/17 06:44:36
script_url
nhiroki
2016/03/17 07:58:17
Done.
|
+ int process_id = helper_->mock_render_process_id(); |
+ |
+ // Add a provider for a service worker to send a message. |
+ const int64_t kProviderId = 99; |
+ dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( |
+ kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER)); |
+ helper_->SimulateAddProcessToPattern(pattern, process_id); |
+ ServiceWorkerProviderHost* sender_provider_host = |
+ context()->GetProviderHost(process_id, kProviderId); |
+ |
+ // Set up a registration and service worker to receive a message. |
+ scoped_refptr<ServiceWorkerRegistration> registration( |
+ new ServiceWorkerRegistration(pattern, 1L, |
+ helper_->context()->AsWeakPtr())); |
+ scoped_refptr<ServiceWorkerVersion> version(new ServiceWorkerVersion( |
+ registration.get(), scope, 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); |
+ ASSERT_EQ(SERVICE_WORKER_OK, status); |
+ |
+ // Set the running hosted version so that we can retrieve a valid service |
+ // worker object information for the source attribute of the message event. |
+ sender_provider_host->running_hosted_version_ = version; |
+ |
+ // Set aside the initial refcount of the worker handle. |
+ sender_provider_host->GetOrCreateServiceWorkerHandle(version.get()); |
+ ServiceWorkerHandle* sender_worker_handle = |
+ dispatcher_host_->FindServiceWorkerHandle( |
+ sender_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); |
+ called = false; |
+ status = SERVICE_WORKER_ERROR_MAX_VALUE; |
+ DispatchExtendableMessageEvent( |
+ version, base::string16(), url::Origin(version->scope().GetOrigin()), |
+ ports, sender_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 |