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_dispatcher_host.h" | 5 #include "content/browser/service_worker/service_worker_dispatcher_host.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
13 #include "content/browser/browser_thread_impl.h" | 13 #include "content/browser/browser_thread_impl.h" |
14 #include "content/browser/message_port_service.h" | |
14 #include "content/browser/service_worker/embedded_worker_instance.h" | 15 #include "content/browser/service_worker/embedded_worker_instance.h" |
15 #include "content/browser/service_worker/embedded_worker_registry.h" | 16 #include "content/browser/service_worker/embedded_worker_registry.h" |
16 #include "content/browser/service_worker/embedded_worker_test_helper.h" | 17 #include "content/browser/service_worker/embedded_worker_test_helper.h" |
17 #include "content/browser/service_worker/service_worker_context_core.h" | 18 #include "content/browser/service_worker/service_worker_context_core.h" |
18 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 19 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
20 #include "content/browser/service_worker/service_worker_handle.h" | |
19 #include "content/common/service_worker/embedded_worker_messages.h" | 21 #include "content/common/service_worker/embedded_worker_messages.h" |
20 #include "content/common/service_worker/service_worker_messages.h" | 22 #include "content/common/service_worker/service_worker_messages.h" |
21 #include "content/public/common/content_switches.h" | 23 #include "content/public/common/content_switches.h" |
22 #include "content/public/test/mock_resource_context.h" | 24 #include "content/public/test/mock_resource_context.h" |
23 #include "content/public/test/test_browser_thread_bundle.h" | 25 #include "content/public/test/test_browser_thread_bundle.h" |
24 #include "content/test/test_content_browser_client.h" | 26 #include "content/test/test_content_browser_client.h" |
25 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
26 | 28 |
27 namespace content { | 29 namespace content { |
28 | 30 |
29 namespace { | 31 namespace { |
30 | 32 |
31 static void SaveStatusCallback(bool* called, | 33 static void SaveStatusCallback(bool* called, |
32 ServiceWorkerStatusCode* out, | 34 ServiceWorkerStatusCode* out, |
33 ServiceWorkerStatusCode status) { | 35 ServiceWorkerStatusCode status) { |
34 *called = true; | 36 *called = true; |
35 *out = status; | 37 *out = status; |
36 } | 38 } |
37 | 39 |
40 void SetUpDummyMessagePort(std::vector<TransferredMessagePort>* ports) { | |
41 int port_id = -1; | |
42 MessagePortService::GetInstance()->Create(MSG_ROUTING_NONE, nullptr, | |
43 &port_id); | |
44 TransferredMessagePort dummy_port; | |
45 dummy_port.id = port_id; | |
46 ports->push_back(dummy_port); | |
38 } | 47 } |
39 | 48 |
49 } // namespace | |
50 | |
40 static const int kRenderFrameId = 1; | 51 static const int kRenderFrameId = 1; |
41 | 52 |
42 class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost { | 53 class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost { |
43 public: | 54 public: |
44 TestingServiceWorkerDispatcherHost( | 55 TestingServiceWorkerDispatcherHost( |
45 int process_id, | 56 int process_id, |
46 ServiceWorkerContextWrapper* context_wrapper, | 57 ServiceWorkerContextWrapper* context_wrapper, |
47 ResourceContext* resource_context, | 58 ResourceContext* resource_context, |
48 EmbeddedWorkerTestHelper* helper) | 59 EmbeddedWorkerTestHelper* helper) |
49 : ServiceWorkerDispatcherHost(process_id, NULL, resource_context), | 60 : ServiceWorkerDispatcherHost(process_id, NULL, resource_context), |
50 bad_messages_received_count_(0), | 61 bad_messages_received_count_(0), |
51 helper_(helper) { | 62 helper_(helper) { |
52 Init(context_wrapper); | 63 Init(context_wrapper); |
53 } | 64 } |
54 | 65 |
55 bool Send(IPC::Message* message) override { return helper_->Send(message); } | 66 bool Send(IPC::Message* message) override { return helper_->Send(message); } |
56 | 67 |
57 IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); } | 68 IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); } |
58 | 69 |
59 void ShutdownForBadMessage() override { ++bad_messages_received_count_; } | 70 void ShutdownForBadMessage() override { ++bad_messages_received_count_; } |
60 | 71 |
61 int bad_messages_received_count_; | 72 int bad_messages_received_count_; |
62 | 73 |
63 protected: | 74 protected: |
64 EmbeddedWorkerTestHelper* helper_; | 75 EmbeddedWorkerTestHelper* helper_; |
65 ~TestingServiceWorkerDispatcherHost() override {} | 76 ~TestingServiceWorkerDispatcherHost() override {} |
66 }; | 77 }; |
67 | 78 |
79 class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper { | |
80 public: | |
81 FailToStartWorkerTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {} | |
82 | |
83 void OnStartWorker(int embedded_worker_id, | |
84 int64_t service_worker_version_id, | |
85 const GURL& scope, | |
86 const GURL& script_url, | |
87 bool pause_after_download) override { | |
88 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id); | |
89 registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id); | |
90 } | |
91 }; | |
92 | |
68 class ServiceWorkerDispatcherHostTest : public testing::Test { | 93 class ServiceWorkerDispatcherHostTest : public testing::Test { |
69 protected: | 94 protected: |
70 ServiceWorkerDispatcherHostTest() | 95 ServiceWorkerDispatcherHostTest() |
71 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} | 96 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} |
72 | 97 |
73 void SetUp() override { | 98 void SetUp() override { |
74 helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath())); | 99 Initialize(make_scoped_ptr(new EmbeddedWorkerTestHelper(base::FilePath()))); |
75 dispatcher_host_ = new TestingServiceWorkerDispatcherHost( | |
76 helper_->mock_render_process_id(), context_wrapper(), | |
77 &resource_context_, helper_.get()); | |
78 } | 100 } |
79 | 101 |
80 void TearDown() override { helper_.reset(); } | 102 void TearDown() override { helper_.reset(); } |
81 | 103 |
82 ServiceWorkerContextCore* context() { return helper_->context(); } | 104 ServiceWorkerContextCore* context() { return helper_->context(); } |
83 ServiceWorkerContextWrapper* context_wrapper() { | 105 ServiceWorkerContextWrapper* context_wrapper() { |
84 return helper_->context_wrapper(); | 106 return helper_->context_wrapper(); |
85 } | 107 } |
86 | 108 |
109 void Initialize(scoped_ptr<EmbeddedWorkerTestHelper> helper) { | |
110 helper_.reset(helper.release()); | |
111 dispatcher_host_ = new TestingServiceWorkerDispatcherHost( | |
112 helper_->mock_render_process_id(), context_wrapper(), | |
113 &resource_context_, helper_.get()); | |
114 } | |
115 | |
87 void SendRegister(int64_t provider_id, GURL pattern, GURL worker_url) { | 116 void SendRegister(int64_t provider_id, GURL pattern, GURL worker_url) { |
88 dispatcher_host_->OnMessageReceived( | 117 dispatcher_host_->OnMessageReceived( |
89 ServiceWorkerHostMsg_RegisterServiceWorker( | 118 ServiceWorkerHostMsg_RegisterServiceWorker( |
90 -1, -1, provider_id, pattern, worker_url)); | 119 -1, -1, provider_id, pattern, worker_url)); |
91 base::RunLoop().RunUntilIdle(); | 120 base::RunLoop().RunUntilIdle(); |
92 } | 121 } |
93 | 122 |
94 void Register(int64_t provider_id, | 123 void Register(int64_t provider_id, |
95 GURL pattern, | 124 GURL pattern, |
96 GURL worker_url, | 125 GURL worker_url, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 base::RunLoop().RunUntilIdle(); | 168 base::RunLoop().RunUntilIdle(); |
140 } | 169 } |
141 | 170 |
142 void GetRegistrations(int64_t provider_id, uint32_t expected_message) { | 171 void GetRegistrations(int64_t provider_id, uint32_t expected_message) { |
143 SendGetRegistrations(provider_id); | 172 SendGetRegistrations(provider_id); |
144 EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching( | 173 EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching( |
145 expected_message)); | 174 expected_message)); |
146 dispatcher_host_->ipc_sink()->ClearMessages(); | 175 dispatcher_host_->ipc_sink()->ClearMessages(); |
147 } | 176 } |
148 | 177 |
178 void DispatchExtendableMessageEvent( | |
179 scoped_refptr<ServiceWorkerVersion> worker, | |
180 const base::string16& message, | |
181 const url::Origin& source_origin, | |
182 const std::vector<TransferredMessagePort>& sent_message_ports, | |
183 ServiceWorkerProviderHost* sender_provider_host, | |
184 const ServiceWorkerDispatcherHost::StatusCallback& callback) { | |
185 dispatcher_host_->DispatchExtendableMessageEvent( | |
186 std::move(worker), message, source_origin, sent_message_ports, | |
187 sender_provider_host, callback); | |
188 } | |
189 | |
149 ServiceWorkerProviderHost* CreateServiceWorkerProviderHost(int provider_id) { | 190 ServiceWorkerProviderHost* CreateServiceWorkerProviderHost(int provider_id) { |
150 return new ServiceWorkerProviderHost( | 191 return new ServiceWorkerProviderHost( |
151 helper_->mock_render_process_id(), kRenderFrameId, provider_id, | 192 helper_->mock_render_process_id(), kRenderFrameId, provider_id, |
152 SERVICE_WORKER_PROVIDER_FOR_WINDOW, context()->AsWeakPtr(), | 193 SERVICE_WORKER_PROVIDER_FOR_WINDOW, context()->AsWeakPtr(), |
153 dispatcher_host_.get()); | 194 dispatcher_host_.get()); |
154 } | 195 } |
155 | 196 |
156 | |
157 TestBrowserThreadBundle browser_thread_bundle_; | 197 TestBrowserThreadBundle browser_thread_bundle_; |
158 content::MockResourceContext resource_context_; | 198 content::MockResourceContext resource_context_; |
159 scoped_ptr<EmbeddedWorkerTestHelper> helper_; | 199 scoped_ptr<EmbeddedWorkerTestHelper> helper_; |
160 scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_; | 200 scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_; |
161 }; | 201 }; |
162 | 202 |
163 class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient { | 203 class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient { |
164 public: | 204 public: |
165 ServiceWorkerTestContentBrowserClient() {} | 205 ServiceWorkerTestContentBrowserClient() {} |
166 bool AllowServiceWorker(const GURL& scope, | 206 bool AllowServiceWorker(const GURL& scope, |
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
589 process_id, context_wrapper(), &resource_context_, helper_.get())); | 629 process_id, context_wrapper(), &resource_context_, helper_.get())); |
590 | 630 |
591 // To show the new dispatcher can operate, simulate provider creation. Since | 631 // To show the new dispatcher can operate, simulate provider creation. Since |
592 // the old dispatcher cleaned up the old provider host, the new one won't | 632 // the old dispatcher cleaned up the old provider host, the new one won't |
593 // complain. | 633 // complain. |
594 new_dispatcher_host->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( | 634 new_dispatcher_host->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( |
595 kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW)); | 635 kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW)); |
596 EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_); | 636 EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_); |
597 } | 637 } |
598 | 638 |
639 TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent) { | |
640 GURL pattern = GURL("http://www.example.com/"); | |
641 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
| |
642 int process_id = helper_->mock_render_process_id(); | |
643 | |
644 // Add a provider for a service worker to send a message. | |
645 const int64_t kProviderId = 99; | |
646 dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( | |
647 kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER)); | |
648 helper_->SimulateAddProcessToPattern(pattern, process_id); | |
649 ServiceWorkerProviderHost* sender_provider_host = | |
650 context()->GetProviderHost(process_id, kProviderId); | |
651 | |
652 // Set up a registration and service worker to receive a message. | |
653 scoped_refptr<ServiceWorkerRegistration> registration( | |
654 new ServiceWorkerRegistration(pattern, 1L, | |
655 helper_->context()->AsWeakPtr())); | |
656 scoped_refptr<ServiceWorkerVersion> version(new ServiceWorkerVersion( | |
657 registration.get(), scope, 1L, helper_->context()->AsWeakPtr())); | |
658 std::vector<ServiceWorkerDatabase::ResourceRecord> records; | |
659 records.push_back( | |
660 ServiceWorkerDatabase::ResourceRecord(10, version->script_url(), 100)); | |
661 version->script_cache_map()->SetResources(records); | |
662 | |
663 // Make the registration findable via storage functions. | |
664 helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing)); | |
665 base::RunLoop().RunUntilIdle(); | |
666 bool called = false; | |
667 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE; | |
668 helper_->context()->storage()->StoreRegistration( | |
669 registration.get(), version.get(), | |
670 base::Bind(&SaveStatusCallback, &called, &status)); | |
671 base::RunLoop().RunUntilIdle(); | |
672 EXPECT_TRUE(called); | |
673 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.
| |
674 | |
675 // Set the running hosted version so that we can retrieve a valid service | |
676 // worker object information for the source attribute of the message event. | |
677 sender_provider_host->running_hosted_version_ = version; | |
678 | |
679 // Set aside the initial refcount of the worker handle. | |
680 sender_provider_host->GetOrCreateServiceWorkerHandle(version.get()); | |
681 ServiceWorkerHandle* sender_worker_handle = | |
682 dispatcher_host_->FindServiceWorkerHandle( | |
683 sender_provider_host->provider_id(), version->version_id()); | |
684 const int ref_count = sender_worker_handle->ref_count(); | |
685 | |
686 // Dispatch ExtendableMessageEvent. | |
687 std::vector<TransferredMessagePort> ports; | |
688 SetUpDummyMessagePort(&ports); | |
689 called = false; | |
690 status = SERVICE_WORKER_ERROR_MAX_VALUE; | |
691 DispatchExtendableMessageEvent( | |
692 version, base::string16(), url::Origin(version->scope().GetOrigin()), | |
693 ports, sender_provider_host, | |
694 base::Bind(&SaveStatusCallback, &called, &status)); | |
695 for (TransferredMessagePort port : ports) | |
696 EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id)); | |
697 EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count()); | |
698 base::RunLoop().RunUntilIdle(); | |
699 EXPECT_TRUE(called); | |
700 EXPECT_EQ(SERVICE_WORKER_OK, status); | |
701 | |
702 // Messages should be held until ports are created at the destination. | |
703 for (TransferredMessagePort port : ports) | |
704 EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id)); | |
705 | |
706 EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count()); | |
707 } | |
708 | |
709 TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent_Fail) { | |
710 Initialize(make_scoped_ptr(new FailToStartWorkerTestHelper)); | |
711 | |
712 GURL pattern = GURL("http://www.example.com/"); | |
713 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.
| |
714 int process_id = helper_->mock_render_process_id(); | |
715 | |
716 // Add a provider for a service worker to send a message. | |
717 const int64_t kProviderId = 99; | |
718 dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( | |
719 kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER)); | |
720 helper_->SimulateAddProcessToPattern(pattern, process_id); | |
721 ServiceWorkerProviderHost* sender_provider_host = | |
722 context()->GetProviderHost(process_id, kProviderId); | |
723 | |
724 // Set up a registration and service worker to receive a message. | |
725 scoped_refptr<ServiceWorkerRegistration> registration( | |
726 new ServiceWorkerRegistration(pattern, 1L, | |
727 helper_->context()->AsWeakPtr())); | |
728 scoped_refptr<ServiceWorkerVersion> version(new ServiceWorkerVersion( | |
729 registration.get(), scope, 1L, helper_->context()->AsWeakPtr())); | |
730 std::vector<ServiceWorkerDatabase::ResourceRecord> records; | |
731 records.push_back( | |
732 ServiceWorkerDatabase::ResourceRecord(10, version->script_url(), 100)); | |
733 version->script_cache_map()->SetResources(records); | |
734 | |
735 // Make the registration findable via storage functions. | |
736 helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing)); | |
737 base::RunLoop().RunUntilIdle(); | |
738 bool called = false; | |
739 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE; | |
740 helper_->context()->storage()->StoreRegistration( | |
741 registration.get(), version.get(), | |
742 base::Bind(&SaveStatusCallback, &called, &status)); | |
743 base::RunLoop().RunUntilIdle(); | |
744 EXPECT_TRUE(called); | |
745 ASSERT_EQ(SERVICE_WORKER_OK, status); | |
746 | |
747 // Set the running hosted version so that we can retrieve a valid service | |
748 // worker object information for the source attribute of the message event. | |
749 sender_provider_host->running_hosted_version_ = version; | |
750 | |
751 // Set aside the initial refcount of the worker handle. | |
752 sender_provider_host->GetOrCreateServiceWorkerHandle(version.get()); | |
753 ServiceWorkerHandle* sender_worker_handle = | |
754 dispatcher_host_->FindServiceWorkerHandle( | |
755 sender_provider_host->provider_id(), version->version_id()); | |
756 const int ref_count = sender_worker_handle->ref_count(); | |
757 | |
758 // Try to dispatch ExtendableMessageEvent. This should fail to start the | |
759 // worker and to dispatch the event. | |
760 std::vector<TransferredMessagePort> ports; | |
761 SetUpDummyMessagePort(&ports); | |
762 called = false; | |
763 status = SERVICE_WORKER_ERROR_MAX_VALUE; | |
764 DispatchExtendableMessageEvent( | |
765 version, base::string16(), url::Origin(version->scope().GetOrigin()), | |
766 ports, sender_provider_host, | |
767 base::Bind(&SaveStatusCallback, &called, &status)); | |
768 for (TransferredMessagePort port : ports) | |
769 EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id)); | |
770 EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count()); | |
771 base::RunLoop().RunUntilIdle(); | |
772 EXPECT_TRUE(called); | |
773 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status); | |
774 | |
775 // The error callback should clean up the ports and handle. | |
776 for (TransferredMessagePort port : ports) | |
777 EXPECT_FALSE(MessagePortService::GetInstance()->AreMessagesHeld(port.id)); | |
778 EXPECT_EQ(ref_count, sender_worker_handle->ref_count()); | |
779 } | |
780 | |
599 } // namespace content | 781 } // namespace content |
OLD | NEW |