service_worker_dispatcher_host_unittest.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
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
3// found in the LICENSE file.
4
5#include "content/browser/service_worker/service_worker_dispatcher_host.h"
6
7#include "base/command_line.h"
8#include "base/files/file_path.h"
9#include "base/run_loop.h"
10#include "content/browser/browser_thread_impl.h"
11#include "content/browser/service_worker/embedded_worker_instance.h"
12#include "content/browser/service_worker/embedded_worker_registry.h"
13#include "content/browser/service_worker/embedded_worker_test_helper.h"
14#include "content/browser/service_worker/service_worker_context_core.h"
15#include "content/browser/service_worker/service_worker_context_wrapper.h"
16#include "content/common/service_worker/embedded_worker_messages.h"
17#include "content/common/service_worker/service_worker_messages.h"
18#include "content/public/common/content_switches.h"
19#include "content/public/test/test_browser_thread_bundle.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22namespace content {
23
24static const int kRenderProcessId = 1;
25
26class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
27 public:
28  TestingServiceWorkerDispatcherHost(
29      int process_id,
30      ServiceWorkerContextWrapper* context_wrapper,
31      EmbeddedWorkerTestHelper* helper)
32      : ServiceWorkerDispatcherHost(process_id, NULL),
33        bad_messages_received_count_(0),
34        helper_(helper) {
35    Init(context_wrapper);
36  }
37
38  virtual bool Send(IPC::Message* message) OVERRIDE {
39    return helper_->Send(message);
40  }
41
42  IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); }
43
44  virtual void BadMessageReceived() OVERRIDE {
45    ++bad_messages_received_count_;
46  }
47
48  int bad_messages_received_count_;
49
50 protected:
51  EmbeddedWorkerTestHelper* helper_;
52  virtual ~TestingServiceWorkerDispatcherHost() {}
53};
54
55class ServiceWorkerDispatcherHostTest : public testing::Test {
56 protected:
57  ServiceWorkerDispatcherHostTest()
58      : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
59
60  virtual void SetUp() {
61    helper_.reset(new EmbeddedWorkerTestHelper(kRenderProcessId));
62    dispatcher_host_ = new TestingServiceWorkerDispatcherHost(
63        kRenderProcessId, context_wrapper(), helper_.get());
64  }
65
66  virtual void TearDown() {
67    helper_.reset();
68  }
69
70  ServiceWorkerContextCore* context() { return helper_->context(); }
71  ServiceWorkerContextWrapper* context_wrapper() {
72    return helper_->context_wrapper();
73  }
74
75  void Register(int64 provider_id,
76                GURL pattern,
77                GURL worker_url,
78                uint32 expected_message) {
79    dispatcher_host_->OnMessageReceived(
80        ServiceWorkerHostMsg_RegisterServiceWorker(
81            -1, -1, provider_id, pattern, worker_url));
82    base::RunLoop().RunUntilIdle();
83    EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
84        expected_message));
85    dispatcher_host_->ipc_sink()->ClearMessages();
86  }
87
88  void Unregister(int64 provider_id, GURL pattern, uint32 expected_message) {
89    dispatcher_host_->OnMessageReceived(
90        ServiceWorkerHostMsg_UnregisterServiceWorker(
91            -1, -1, provider_id, pattern));
92    base::RunLoop().RunUntilIdle();
93    EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
94        expected_message));
95    dispatcher_host_->ipc_sink()->ClearMessages();
96  }
97
98  TestBrowserThreadBundle browser_thread_bundle_;
99  scoped_ptr<EmbeddedWorkerTestHelper> helper_;
100  scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_;
101};
102
103TEST_F(ServiceWorkerDispatcherHostTest, DisabledCausesError) {
104  DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
105              switches::kEnableServiceWorker));
106
107  dispatcher_host_->OnMessageReceived(
108      ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, -1, GURL(), GURL()));
109
110  // TODO(alecflett): Pump the message loop when this becomes async.
111  ASSERT_EQ(1UL, dispatcher_host_->ipc_sink()->message_count());
112  EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
113      ServiceWorkerMsg_ServiceWorkerRegistrationError::ID));
114}
115
116// TODO(falken): Enable this test when we remove the
117// --enable-service-worker-flag (see crbug.com/352581)
118TEST_F(ServiceWorkerDispatcherHostTest, DISABLED_RegisterSameOrigin) {
119  const int64 kProviderId = 99;  // Dummy value
120  scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
121      kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
122  host->SetDocumentUrl(GURL("http://www.example.com/foo"));
123  base::WeakPtr<ServiceWorkerProviderHost> provider_host = host->AsWeakPtr();
124  context()->AddProviderHost(host.Pass());
125
126  Register(kProviderId,
127           GURL("http://www.example.com/*"),
128           GURL("http://foo.example.com/bar"),
129           ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
130  Register(kProviderId,
131           GURL("http://foo.example.com/*"),
132           GURL("http://www.example.com/bar"),
133           ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
134  Register(kProviderId,
135           GURL("http://foo.example.com/*"),
136           GURL("http://foo.example.com/bar"),
137           ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
138  Register(kProviderId,
139           GURL("http://www.example.com/*"),
140           GURL("http://www.example.com/bar"),
141           ServiceWorkerMsg_ServiceWorkerRegistered::ID);
142}
143
144// TODO(falken): Enable this test when we remove the
145// --enable-service-worker-flag (see crbug.com/352581)
146TEST_F(ServiceWorkerDispatcherHostTest, DISABLED_UnregisterSameOrigin) {
147  const int64 kProviderId = 99;  // Dummy value
148  scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
149      kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
150  host->SetDocumentUrl(GURL("http://www.example.com/foo"));
151  base::WeakPtr<ServiceWorkerProviderHost> provider_host = host->AsWeakPtr();
152  context()->AddProviderHost(host.Pass());
153
154  Unregister(kProviderId,
155             GURL("http://foo.example.com/*"),
156             ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
157  Unregister(kProviderId,
158             GURL("http://www.example.com/*"),
159             ServiceWorkerMsg_ServiceWorkerUnregistered::ID);
160}
161
162// Disable this since now we cache command-line switch in
163// ServiceWorkerUtils::IsFeatureEnabled() and this could be flaky depending
164// on testing order. (crbug.com/352581)
165// TODO(kinuko): Just remove DisabledCausesError test above and enable
166// this test when we remove the --enable-service-worker flag.
167TEST_F(ServiceWorkerDispatcherHostTest, DISABLED_Enabled) {
168  DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
169              switches::kEnableServiceWorker));
170  CommandLine::ForCurrentProcess()->AppendSwitch(
171      switches::kEnableServiceWorker);
172
173  dispatcher_host_->OnMessageReceived(
174      ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, -1, GURL(), GURL()));
175  base::RunLoop().RunUntilIdle();
176
177  // TODO(alecflett): Pump the message loop when this becomes async.
178  ASSERT_EQ(2UL, dispatcher_host_->ipc_sink()->message_count());
179  EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
180      EmbeddedWorkerMsg_StartWorker::ID));
181  EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
182      ServiceWorkerMsg_ServiceWorkerRegistered::ID));
183}
184
185TEST_F(ServiceWorkerDispatcherHostTest, EarlyContextDeletion) {
186  DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
187              switches::kEnableServiceWorker));
188  CommandLine::ForCurrentProcess()->AppendSwitch(
189      switches::kEnableServiceWorker);
190
191  helper_->ShutdownContext();
192
193  // Let the shutdown reach the simulated IO thread.
194  base::RunLoop().RunUntilIdle();
195
196  dispatcher_host_->OnMessageReceived(
197      ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, -1, GURL(), GURL()));
198
199  // TODO(alecflett): Pump the message loop when this becomes async.
200  ASSERT_EQ(1UL, dispatcher_host_->ipc_sink()->message_count());
201  EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
202      ServiceWorkerMsg_ServiceWorkerRegistrationError::ID));
203}
204
205TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
206  const int kProviderId = 1001;  // Test with a value != kRenderProcessId.
207
208  dispatcher_host_->OnMessageReceived(
209      ServiceWorkerHostMsg_ProviderCreated(kProviderId));
210  EXPECT_TRUE(context()->GetProviderHost(kRenderProcessId, kProviderId));
211
212  // Two with the same ID should be seen as a bad message.
213  dispatcher_host_->OnMessageReceived(
214      ServiceWorkerHostMsg_ProviderCreated(kProviderId));
215  EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
216
217  dispatcher_host_->OnMessageReceived(
218      ServiceWorkerHostMsg_ProviderDestroyed(kProviderId));
219  EXPECT_FALSE(context()->GetProviderHost(kRenderProcessId, kProviderId));
220
221  // Destroying an ID that does not exist warrants a bad message.
222  dispatcher_host_->OnMessageReceived(
223      ServiceWorkerHostMsg_ProviderDestroyed(kProviderId));
224  EXPECT_EQ(2, dispatcher_host_->bad_messages_received_count_);
225
226  // Deletion of the dispatcher_host should cause providers for that
227  // process to get deleted as well.
228  dispatcher_host_->OnMessageReceived(
229      ServiceWorkerHostMsg_ProviderCreated(kProviderId));
230  EXPECT_TRUE(context()->GetProviderHost(kRenderProcessId, kProviderId));
231  EXPECT_TRUE(dispatcher_host_->HasOneRef());
232  dispatcher_host_ = NULL;
233  EXPECT_FALSE(context()->GetProviderHost(kRenderProcessId, kProviderId));
234}
235
236}  // namespace content
237