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_UNHANDLED(handled
= false)
93 // IPC::TestSink only records messages that are not handled by filters,
94 // so we just forward all messages to the separate sink.
95 sink_
.OnMessageReceived(message
);
100 ServiceWorkerContextCore
* EmbeddedWorkerTestHelper::context() {
101 return wrapper_
->context();
104 void EmbeddedWorkerTestHelper::ShutdownContext() {
105 wrapper_
->Shutdown();
109 void EmbeddedWorkerTestHelper::OnStartWorker(int embedded_worker_id
,
110 int64 service_worker_version_id
,
112 const GURL
& script_url
) {
113 embedded_worker_id_service_worker_version_id_map_
[embedded_worker_id
] =
114 service_worker_version_id
;
115 SimulateWorkerReadyForInspection(embedded_worker_id
);
116 SimulateWorkerScriptCached(embedded_worker_id
);
117 SimulateWorkerScriptLoaded(next_thread_id_
++, embedded_worker_id
);
118 SimulateWorkerScriptEvaluated(embedded_worker_id
);
119 SimulateWorkerStarted(embedded_worker_id
);
122 void EmbeddedWorkerTestHelper::OnStopWorker(int embedded_worker_id
) {
123 // By default just notify the sender that the worker is stopped.
124 SimulateWorkerStopped(embedded_worker_id
);
127 bool EmbeddedWorkerTestHelper::OnMessageToWorker(
129 int embedded_worker_id
,
130 const IPC::Message
& message
) {
132 current_embedded_worker_id_
= embedded_worker_id
;
133 IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerTestHelper
, message
)
134 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent
, OnActivateEventStub
)
135 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent
, OnInstallEventStub
)
136 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent
, OnFetchEventStub
)
137 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent
, OnPushEventStub
)
138 IPC_MESSAGE_UNHANDLED(handled
= false)
139 IPC_END_MESSAGE_MAP()
140 // Record all messages directed to inner script context.
141 inner_sink_
.OnMessageReceived(message
);
145 void EmbeddedWorkerTestHelper::OnActivateEvent(int embedded_worker_id
,
148 new ServiceWorkerHostMsg_ActivateEventFinished(
149 embedded_worker_id
, request_id
,
150 blink::WebServiceWorkerEventResultCompleted
));
153 void EmbeddedWorkerTestHelper::OnInstallEvent(int embedded_worker_id
,
155 // The installing worker may have been doomed and terminated.
156 if (!registry()->GetWorker(embedded_worker_id
))
159 new ServiceWorkerHostMsg_InstallEventFinished(
160 embedded_worker_id
, request_id
,
161 blink::WebServiceWorkerEventResultCompleted
));
164 void EmbeddedWorkerTestHelper::OnFetchEvent(
165 int embedded_worker_id
,
167 const ServiceWorkerFetchRequest
& request
) {
168 SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
169 embedded_worker_id
, request_id
,
170 SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
,
171 ServiceWorkerResponse(GURL(), 200, "OK",
172 blink::WebServiceWorkerResponseTypeDefault
,
173 ServiceWorkerHeaderMap(), std::string(), 0, GURL(),
174 blink::WebServiceWorkerResponseErrorUnknown
)));
177 void EmbeddedWorkerTestHelper::OnPushEvent(int embedded_worker_id
,
179 const std::string
& data
) {
180 SimulateSend(new ServiceWorkerHostMsg_PushEventFinished(
181 embedded_worker_id
, request_id
,
182 blink::WebServiceWorkerEventResultCompleted
));
185 void EmbeddedWorkerTestHelper::SimulateWorkerReadyForInspection(
186 int embedded_worker_id
) {
187 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
188 ASSERT_TRUE(worker
!= NULL
);
189 registry()->OnWorkerReadyForInspection(worker
->process_id(),
193 void EmbeddedWorkerTestHelper::SimulateWorkerScriptCached(
194 int embedded_worker_id
) {
196 embedded_worker_id_service_worker_version_id_map_
[embedded_worker_id
];
197 ServiceWorkerVersion
* version
= context()->GetLiveVersion(version_id
);
198 if (!version
|| version
->script_cache_map()->size())
200 std::vector
<ServiceWorkerDatabase::ResourceRecord
> records
;
201 // Add a dummy ResourceRecord for the main script to the script cache map of
202 // the ServiceWorkerVersion. We use embedded_worker_id for resource_id to
203 // avoid ID collision.
204 records
.push_back(ServiceWorkerDatabase::ResourceRecord(
205 embedded_worker_id
, version
->script_url(), 100));
206 version
->script_cache_map()->SetResources(records
);
209 void EmbeddedWorkerTestHelper::SimulateWorkerScriptLoaded(
210 int thread_id
, int embedded_worker_id
) {
211 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
212 ASSERT_TRUE(worker
!= NULL
);
213 registry()->OnWorkerScriptLoaded(
214 worker
->process_id(), thread_id
, embedded_worker_id
);
217 void EmbeddedWorkerTestHelper::SimulateWorkerScriptEvaluated(
218 int embedded_worker_id
) {
219 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
220 ASSERT_TRUE(worker
!= NULL
);
221 registry()->OnWorkerScriptEvaluated(
222 worker
->process_id(), embedded_worker_id
, true /* success */);
225 void EmbeddedWorkerTestHelper::SimulateWorkerStarted(
226 int embedded_worker_id
) {
227 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
228 ASSERT_TRUE(worker
!= NULL
);
229 registry()->OnWorkerStarted(
230 worker
->process_id(),
234 void EmbeddedWorkerTestHelper::SimulateWorkerStopped(
235 int embedded_worker_id
) {
236 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
238 registry()->OnWorkerStopped(worker
->process_id(), embedded_worker_id
);
241 void EmbeddedWorkerTestHelper::SimulateSend(
242 IPC::Message
* message
) {
243 registry()->OnMessageReceived(*message
, mock_render_process_id_
);
247 void EmbeddedWorkerTestHelper::OnStartWorkerStub(
248 const EmbeddedWorkerMsg_StartWorker_Params
& params
) {
249 EmbeddedWorkerInstance
* worker
=
250 registry()->GetWorker(params
.embedded_worker_id
);
251 ASSERT_TRUE(worker
!= NULL
);
252 EXPECT_EQ(EmbeddedWorkerInstance::STARTING
, worker
->status());
253 base::ThreadTaskRunnerHandle::Get()->PostTask(
255 base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker
,
256 weak_factory_
.GetWeakPtr(), params
.embedded_worker_id
,
257 params
.service_worker_version_id
, params
.scope
,
261 void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id
) {
262 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
263 ASSERT_TRUE(worker
!= NULL
);
264 base::ThreadTaskRunnerHandle::Get()->PostTask(
266 base::Bind(&EmbeddedWorkerTestHelper::OnStopWorker
,
267 weak_factory_
.GetWeakPtr(),
268 embedded_worker_id
));
271 void EmbeddedWorkerTestHelper::OnMessageToWorkerStub(
273 int embedded_worker_id
,
274 const IPC::Message
& message
) {
275 EmbeddedWorkerInstance
* worker
= registry()->GetWorker(embedded_worker_id
);
276 ASSERT_TRUE(worker
!= NULL
);
277 EXPECT_EQ(worker
->thread_id(), thread_id
);
278 base::ThreadTaskRunnerHandle::Get()->PostTask(
281 base::IgnoreResult(&EmbeddedWorkerTestHelper::OnMessageToWorker
),
282 weak_factory_
.GetWeakPtr(),
288 void EmbeddedWorkerTestHelper::OnActivateEventStub(int request_id
) {
289 base::ThreadTaskRunnerHandle::Get()->PostTask(
291 base::Bind(&EmbeddedWorkerTestHelper::OnActivateEvent
,
292 weak_factory_
.GetWeakPtr(),
293 current_embedded_worker_id_
,
297 void EmbeddedWorkerTestHelper::OnInstallEventStub(int request_id
) {
298 base::ThreadTaskRunnerHandle::Get()->PostTask(
300 base::Bind(&EmbeddedWorkerTestHelper::OnInstallEvent
,
301 weak_factory_
.GetWeakPtr(),
302 current_embedded_worker_id_
,
306 void EmbeddedWorkerTestHelper::OnFetchEventStub(
308 const ServiceWorkerFetchRequest
& request
) {
309 base::ThreadTaskRunnerHandle::Get()->PostTask(
311 base::Bind(&EmbeddedWorkerTestHelper::OnFetchEvent
,
312 weak_factory_
.GetWeakPtr(),
313 current_embedded_worker_id_
,
318 void EmbeddedWorkerTestHelper::OnPushEventStub(int request_id
,
319 const std::string
& data
) {
320 base::ThreadTaskRunnerHandle::Get()->PostTask(
321 FROM_HERE
, base::Bind(&EmbeddedWorkerTestHelper::OnPushEvent
,
322 weak_factory_
.GetWeakPtr(),
323 current_embedded_worker_id_
, request_id
, data
));
326 EmbeddedWorkerRegistry
* EmbeddedWorkerTestHelper::registry() {
328 return context()->embedded_worker_registry();
331 MessagePortMessageFilter
*
332 EmbeddedWorkerTestHelper::NewMessagePortMessageFilter() {
333 scoped_refptr
<MessagePortMessageFilter
> filter(
334 new MockMessagePortMessageFilter
);
335 message_port_message_filters_
.push_back(filter
);
339 } // namespace content