1 // Copyright 2014 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.
5 #include "content/browser/service_worker/embedded_worker_test_helper.h"
10 #include "base/atomic_sequence_num.h"
11 #include "base/bind.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "content/browser/message_port_message_filter.h"
15 #include "content/browser/service_worker/embedded_worker_instance.h"
16 #include "content/browser/service_worker/embedded_worker_registry.h"
17 #include "content/browser/service_worker/service_worker_context_core.h"
18 #include "content/browser/service_worker/service_worker_context_wrapper.h"
19 #include "content/common/service_worker/embedded_worker_messages.h"
20 #include "content/common/service_worker/service_worker_messages.h"
21 #include "testing/gtest/include/gtest/gtest.h"
25 class MockMessagePortMessageFilter
: public MessagePortMessageFilter
{
27 MockMessagePortMessageFilter()
28 : MessagePortMessageFilter(
29 base::Bind(&base::AtomicSequenceNumber::GetNext
,
30 base::Unretained(&next_routing_id_
))) {}
32 bool Send(IPC::Message
* message
) override
{
33 message_queue_
.push_back(message
);
38 ~MockMessagePortMessageFilter() override
{}
39 base::AtomicSequenceNumber next_routing_id_
;
40 ScopedVector
<IPC::Message
> message_queue_
;
43 EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
44 const base::FilePath
& user_data_directory
,
45 int mock_render_process_id
)
46 : wrapper_(new ServiceWorkerContextWrapper(NULL
)),
48 mock_render_process_id_(mock_render_process_id
),
50 scoped_ptr
<MockServiceWorkerDatabaseTaskManager
> database_task_manager(
51 new MockServiceWorkerDatabaseTaskManager(
52 base::ThreadTaskRunnerHandle::Get()));
53 wrapper_
->InitInternal(user_data_directory
,
54 database_task_manager
.Pass(),
55 base::ThreadTaskRunnerHandle::Get(),
58 wrapper_
->process_manager()->SetProcessIdForTest(mock_render_process_id
);
59 registry()->AddChildProcessSender(mock_render_process_id
, this,
60 NewMessagePortMessageFilter());
63 EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() {
68 void EmbeddedWorkerTestHelper::SimulateAddProcessToPattern(
71 registry()->AddChildProcessSender(process_id
, this,
72 NewMessagePortMessageFilter());
73 wrapper_
->process_manager()->AddProcessReferenceToPattern(
77 bool EmbeddedWorkerTestHelper::Send(IPC::Message
* message
) {
78 OnMessageReceived(*message
);
83 bool EmbeddedWorkerTestHelper::OnMessageReceived(const IPC::Message
& message
) {
85 IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerTestHelper
, message
)
86 IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StartWorker
, OnStartWorkerStub
)
87 IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StopWorker
, OnStopWorkerStub
)
88 IPC_MESSAGE_HANDLER(EmbeddedWorkerContextMsg_MessageToWorker
,
89 OnMessageToWorkerStub
)
90 IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_ResumeAfterDownload
,
91 OnResumeAfterDownloadStub
)
92 IPC_MESSAGE_UNHANDLED(handled
= false)
95 // IPC::TestSink only records messages that are not handled by filters,
96 // so we just forward all messages to the separate sink.
97 sink_
.OnMessageReceived(message
);
102 ServiceWorkerContextCore
* EmbeddedWorkerTestHelper::context() {
103 return wrapper_
->context();
106 void EmbeddedWorkerTestHelper::ShutdownContext() {
107 wrapper_
->Shutdown();
111 void EmbeddedWorkerTestHelper::OnStartWorker(
112 int embedded_worker_id
,
113 int64 service_worker_version_id
,
115 const GURL
& script_url
,
116 bool pause_after_download
) {
117 embedded_worker_id_service_worker_version_id_map_
[embedded_worker_id
] =
118 service_worker_version_id
;
119 if (pause_after_download
) {
120 SimulatePausedAfterDownload(embedded_worker_id
);
123 SimulateWorkerReadyForInspection(embedded_worker_id
);
124 SimulateWorkerScriptCached(embedded_worker_id
);
125 SimulateWorkerScriptLoaded(next_thread_id_
++, embedded_worker_id
);
126 SimulateWorkerScriptEvaluated(embedded_worker_id
);
127 SimulateWorkerStarted(embedded_worker_id
);
130 void EmbeddedWorkerTestHelper::OnResumeAfterDownload(int embedded_worker_id
) {
131 SimulateWorkerReadyForInspection(embedded_worker_id
);
132 SimulateWorkerScriptCached(embedded_worker_id
);
133 SimulateWorkerScriptLoaded(next_thread_id_
++, embedded_worker_id
);
134 SimulateWorkerScriptEvaluated(embedded_worker_id
);
135 SimulateWorkerStarted(embedded_worker_id
);
138 void EmbeddedWorkerTestHelper::OnStopWorker(int embedded_worker_id
) {
139 // By default just notify the sender that the worker is stopped.
140 SimulateWorkerStopped(embedded_worker_id
);
143 bool EmbeddedWorkerTestHelper::OnMessageToWorker(
145 int embedded_worker_id
,
146 const IPC::Message
& message
) {
148 current_embedded_worker_id_
= embedded_worker_id
;
149 IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerTestHelper
, message
)
150 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent
, OnActivateEventStub
)
151 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent
, OnInstallEventStub
)
152 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent
, OnFetchEventStub
)
153 IPC_MESSAGE_UNHANDLED(handled
= false)
154 IPC_END_MESSAGE_MAP()
155 // Record all messages directed to inner script context.
156 inner_sink_
.OnMessageReceived(message
);
160 void EmbeddedWorkerTestHelper::OnActivateEvent(int embedded_worker_id
,
163 new ServiceWorkerHostMsg_ActivateEventFinished(
164 embedded_worker_id
, request_id
,
165 blink::WebServiceWorkerEventResultCompleted
));
168 void EmbeddedWorkerTestHelper::OnInstallEvent(int embedded_worker_id
,
170 // The installing worker may have been doomed and terminated.
171 if (!registry()->GetWorker(embedded_worker_id
))
174 new ServiceWorkerHostMsg_InstallEventFinished(
175 embedded_worker_id
, request_id
,
176 blink::WebServiceWorkerEventResultCompleted
));
179 void EmbeddedWorkerTestHelper::OnFetchEvent(
180 int embedded_worker_id
,
182 const ServiceWorkerFetchRequest
& request
) {
183 SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
186 SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
,
187 ServiceWorkerResponse(GURL(),
190 blink::WebServiceWorkerResponseTypeDefault
,
191 ServiceWorkerHeaderMap(),
197 void EmbeddedWorkerTestHelper::SimulatePausedAfterDownload(
198 int embedded_worker_id
) {
199 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
200 ASSERT_TRUE(worker
!= NULL
);
201 registry()->OnPausedAfterDownload(worker
->process_id(), embedded_worker_id
);
204 void EmbeddedWorkerTestHelper::SimulateWorkerReadyForInspection(
205 int embedded_worker_id
) {
206 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
207 ASSERT_TRUE(worker
!= NULL
);
208 registry()->OnWorkerReadyForInspection(worker
->process_id(),
212 void EmbeddedWorkerTestHelper::SimulateWorkerScriptCached(
213 int embedded_worker_id
) {
215 embedded_worker_id_service_worker_version_id_map_
[embedded_worker_id
];
216 ServiceWorkerVersion
* version
= context()->GetLiveVersion(version_id
);
217 if (!version
|| version
->script_cache_map()->size())
219 std::vector
<ServiceWorkerDatabase::ResourceRecord
> records
;
220 // Add a dummy ResourceRecord for the main script to the script cache map of
221 // the ServiceWorkerVersion. We use embedded_worker_id for resource_id to
222 // avoid ID collision.
223 records
.push_back(ServiceWorkerDatabase::ResourceRecord(
224 embedded_worker_id
, version
->script_url(), 100));
225 version
->script_cache_map()->SetResources(records
);
228 void EmbeddedWorkerTestHelper::SimulateWorkerScriptLoaded(
229 int thread_id
, int embedded_worker_id
) {
230 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
231 ASSERT_TRUE(worker
!= NULL
);
232 registry()->OnWorkerScriptLoaded(
233 worker
->process_id(), thread_id
, embedded_worker_id
);
236 void EmbeddedWorkerTestHelper::SimulateWorkerScriptEvaluated(
237 int embedded_worker_id
) {
238 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
239 ASSERT_TRUE(worker
!= NULL
);
240 registry()->OnWorkerScriptEvaluated(
241 worker
->process_id(), embedded_worker_id
, true /* success */);
244 void EmbeddedWorkerTestHelper::SimulateWorkerStarted(
245 int embedded_worker_id
) {
246 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
247 ASSERT_TRUE(worker
!= NULL
);
248 registry()->OnWorkerStarted(
249 worker
->process_id(),
253 void EmbeddedWorkerTestHelper::SimulateWorkerStopped(
254 int embedded_worker_id
) {
255 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
257 registry()->OnWorkerStopped(worker
->process_id(), embedded_worker_id
);
260 void EmbeddedWorkerTestHelper::SimulateSend(
261 IPC::Message
* message
) {
262 registry()->OnMessageReceived(*message
, mock_render_process_id_
);
266 void EmbeddedWorkerTestHelper::OnStartWorkerStub(
267 const EmbeddedWorkerMsg_StartWorker_Params
& params
) {
268 EmbeddedWorkerInstance
* worker
=
269 registry()->GetWorker(params
.embedded_worker_id
);
270 ASSERT_TRUE(worker
!= NULL
);
271 EXPECT_EQ(EmbeddedWorkerInstance::STARTING
, worker
->status());
272 base::ThreadTaskRunnerHandle::Get()->PostTask(
274 base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker
,
275 weak_factory_
.GetWeakPtr(),
276 params
.embedded_worker_id
,
277 params
.service_worker_version_id
,
280 params
.pause_after_download
));
283 void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub(
284 int embedded_worker_id
) {
285 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
286 ASSERT_TRUE(worker
!= NULL
);
287 base::ThreadTaskRunnerHandle::Get()->PostTask(
289 base::Bind(&EmbeddedWorkerTestHelper::OnResumeAfterDownload
,
290 weak_factory_
.GetWeakPtr(),
291 embedded_worker_id
));
294 void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id
) {
295 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
296 ASSERT_TRUE(worker
!= NULL
);
297 base::ThreadTaskRunnerHandle::Get()->PostTask(
299 base::Bind(&EmbeddedWorkerTestHelper::OnStopWorker
,
300 weak_factory_
.GetWeakPtr(),
301 embedded_worker_id
));
304 void EmbeddedWorkerTestHelper::OnMessageToWorkerStub(
306 int embedded_worker_id
,
307 const IPC::Message
& message
) {
308 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
309 ASSERT_TRUE(worker
!= NULL
);
310 EXPECT_EQ(worker
->thread_id(), thread_id
);
311 base::ThreadTaskRunnerHandle::Get()->PostTask(
314 base::IgnoreResult(&EmbeddedWorkerTestHelper::OnMessageToWorker
),
315 weak_factory_
.GetWeakPtr(),
321 void EmbeddedWorkerTestHelper::OnActivateEventStub(int request_id
) {
322 base::ThreadTaskRunnerHandle::Get()->PostTask(
324 base::Bind(&EmbeddedWorkerTestHelper::OnActivateEvent
,
325 weak_factory_
.GetWeakPtr(),
326 current_embedded_worker_id_
,
330 void EmbeddedWorkerTestHelper::OnInstallEventStub(int request_id
) {
331 base::ThreadTaskRunnerHandle::Get()->PostTask(
333 base::Bind(&EmbeddedWorkerTestHelper::OnInstallEvent
,
334 weak_factory_
.GetWeakPtr(),
335 current_embedded_worker_id_
,
339 void EmbeddedWorkerTestHelper::OnFetchEventStub(
341 const ServiceWorkerFetchRequest
& request
) {
342 base::ThreadTaskRunnerHandle::Get()->PostTask(
344 base::Bind(&EmbeddedWorkerTestHelper::OnFetchEvent
,
345 weak_factory_
.GetWeakPtr(),
346 current_embedded_worker_id_
,
351 EmbeddedWorkerRegistry
* EmbeddedWorkerTestHelper::registry() {
353 return context()->embedded_worker_registry();
356 MessagePortMessageFilter
*
357 EmbeddedWorkerTestHelper::NewMessagePortMessageFilter() {
358 scoped_refptr
<MessagePortMessageFilter
> filter(
359 new MockMessagePortMessageFilter
);
360 message_port_message_filters_
.push_back(filter
);
364 } // namespace content