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.
4
5#include "content/browser/service_worker/embedded_worker_test_helper.h"
6
7#include <map>
8#include <string>
9
10#include "base/bind.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/service_worker_context_core.h"
14#include "content/browser/service_worker/service_worker_context_wrapper.h"
15#include "content/common/service_worker/embedded_worker_messages.h"
16#include "content/common/service_worker/service_worker_messages.h"
17#include "testing/gtest/include/gtest/gtest.h"
18
19namespace content {
20
21EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(int mock_render_process_id)
22    : wrapper_(new ServiceWorkerContextWrapper(NULL)),
23      next_thread_id_(0),
24      mock_render_process_id_(mock_render_process_id),
25      weak_factory_(this) {
26  wrapper_->InitInternal(base::FilePath(),
27                         base::MessageLoopProxy::current(),
28                         base::MessageLoopProxy::current(),
29                         base::MessageLoopProxy::current(),
30                         NULL);
31  wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id);
32  registry()->AddChildProcessSender(mock_render_process_id, this);
33}
34
35EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() {
36  if (wrapper_.get())
37    wrapper_->Shutdown();
38}
39
40void EmbeddedWorkerTestHelper::SimulateAddProcessToPattern(
41    const GURL& pattern,
42    int process_id) {
43  registry()->AddChildProcessSender(process_id, this);
44  wrapper_->process_manager()->AddProcessReferenceToPattern(
45      pattern, process_id);
46}
47
48bool EmbeddedWorkerTestHelper::Send(IPC::Message* message) {
49  OnMessageReceived(*message);
50  delete message;
51  return true;
52}
53
54bool EmbeddedWorkerTestHelper::OnMessageReceived(const IPC::Message& message) {
55  bool handled = true;
56  IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerTestHelper, message)
57    IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StartWorker, OnStartWorkerStub)
58    IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StopWorker, OnStopWorkerStub)
59    IPC_MESSAGE_HANDLER(EmbeddedWorkerContextMsg_MessageToWorker,
60                        OnMessageToWorkerStub)
61    IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_ResumeAfterDownload,
62                        OnResumeAfterDownloadStub)
63    IPC_MESSAGE_UNHANDLED(handled = false)
64  IPC_END_MESSAGE_MAP()
65
66  // IPC::TestSink only records messages that are not handled by filters,
67  // so we just forward all messages to the separate sink.
68  sink_.OnMessageReceived(message);
69
70  return handled;
71}
72
73ServiceWorkerContextCore* EmbeddedWorkerTestHelper::context() {
74  return wrapper_->context();
75}
76
77void EmbeddedWorkerTestHelper::ShutdownContext() {
78  wrapper_->Shutdown();
79  wrapper_ = NULL;
80}
81
82void EmbeddedWorkerTestHelper::OnStartWorker(
83    int embedded_worker_id,
84    int64 service_worker_version_id,
85    const GURL& scope,
86    const GURL& script_url,
87    bool pause_after_download) {
88  if (pause_after_download) {
89    SimulatePausedAfterDownload(embedded_worker_id);
90    return;
91  }
92  SimulateWorkerReadyForInspection(embedded_worker_id);
93  SimulateWorkerScriptLoaded(next_thread_id_++, embedded_worker_id);
94  SimulateWorkerStarted(embedded_worker_id);
95}
96
97void EmbeddedWorkerTestHelper::OnResumeAfterDownload(int embedded_worker_id) {
98  SimulateWorkerReadyForInspection(embedded_worker_id);
99  SimulateWorkerScriptLoaded(next_thread_id_++, embedded_worker_id);
100  SimulateWorkerStarted(embedded_worker_id);
101}
102
103void EmbeddedWorkerTestHelper::OnStopWorker(int embedded_worker_id) {
104  // By default just notify the sender that the worker is stopped.
105  SimulateWorkerStopped(embedded_worker_id);
106}
107
108bool EmbeddedWorkerTestHelper::OnMessageToWorker(
109    int thread_id,
110    int embedded_worker_id,
111    const IPC::Message& message) {
112  bool handled = true;
113  current_embedded_worker_id_ = embedded_worker_id;
114  IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerTestHelper, message)
115    IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent, OnActivateEventStub)
116    IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent, OnInstallEventStub)
117    IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent, OnFetchEventStub)
118    IPC_MESSAGE_UNHANDLED(handled = false)
119  IPC_END_MESSAGE_MAP()
120  // Record all messages directed to inner script context.
121  inner_sink_.OnMessageReceived(message);
122  return handled;
123}
124
125void EmbeddedWorkerTestHelper::OnActivateEvent(int embedded_worker_id,
126                                               int request_id) {
127  SimulateSend(
128      new ServiceWorkerHostMsg_ActivateEventFinished(
129          embedded_worker_id, request_id,
130          blink::WebServiceWorkerEventResultCompleted));
131}
132
133void EmbeddedWorkerTestHelper::OnInstallEvent(int embedded_worker_id,
134                                              int request_id,
135                                              int active_version_id) {
136  SimulateSend(
137      new ServiceWorkerHostMsg_InstallEventFinished(
138          embedded_worker_id, request_id,
139          blink::WebServiceWorkerEventResultCompleted));
140}
141
142void EmbeddedWorkerTestHelper::OnFetchEvent(
143    int embedded_worker_id,
144    int request_id,
145    const ServiceWorkerFetchRequest& request) {
146  SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
147      embedded_worker_id,
148      request_id,
149      SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
150      ServiceWorkerResponse(
151          GURL(""), 200, "OK", ServiceWorkerHeaderMap(), std::string())));
152}
153
154void EmbeddedWorkerTestHelper::SimulatePausedAfterDownload(
155      int embedded_worker_id) {
156  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
157  ASSERT_TRUE(worker != NULL);
158  registry()->OnPausedAfterDownload(worker->process_id(), embedded_worker_id);
159}
160
161void EmbeddedWorkerTestHelper::SimulateWorkerReadyForInspection(
162    int embedded_worker_id) {
163  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
164  ASSERT_TRUE(worker != NULL);
165  registry()->OnWorkerReadyForInspection(worker->process_id(),
166                                         embedded_worker_id);
167}
168
169void EmbeddedWorkerTestHelper::SimulateWorkerScriptLoaded(
170    int thread_id, int embedded_worker_id) {
171  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
172  ASSERT_TRUE(worker != NULL);
173  registry()->OnWorkerScriptLoaded(
174      worker->process_id(), thread_id, embedded_worker_id);
175}
176
177void EmbeddedWorkerTestHelper::SimulateWorkerStarted(
178    int embedded_worker_id) {
179  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
180  ASSERT_TRUE(worker != NULL);
181  registry()->OnWorkerStarted(
182      worker->process_id(),
183      embedded_worker_id);
184}
185
186void EmbeddedWorkerTestHelper::SimulateWorkerStopped(
187    int embedded_worker_id) {
188  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
189  if (worker != NULL)
190    registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
191}
192
193void EmbeddedWorkerTestHelper::SimulateSend(
194    IPC::Message* message) {
195  registry()->OnMessageReceived(*message);
196  delete message;
197}
198
199void EmbeddedWorkerTestHelper::OnStartWorkerStub(
200    const EmbeddedWorkerMsg_StartWorker_Params& params) {
201  EmbeddedWorkerInstance* worker =
202      registry()->GetWorker(params.embedded_worker_id);
203  ASSERT_TRUE(worker != NULL);
204  EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
205  base::MessageLoopProxy::current()->PostTask(
206      FROM_HERE,
207      base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker,
208                  weak_factory_.GetWeakPtr(),
209                  params.embedded_worker_id,
210                  params.service_worker_version_id,
211                  params.scope,
212                  params.script_url,
213                  params.pause_after_download));
214}
215
216void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub(
217      int embedded_worker_id) {
218  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
219  ASSERT_TRUE(worker != NULL);
220  base::MessageLoopProxy::current()->PostTask(
221      FROM_HERE,
222      base::Bind(&EmbeddedWorkerTestHelper::OnResumeAfterDownload,
223                 weak_factory_.GetWeakPtr(),
224                 embedded_worker_id));
225}
226
227void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id) {
228  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
229  ASSERT_TRUE(worker != NULL);
230  base::MessageLoopProxy::current()->PostTask(
231      FROM_HERE,
232      base::Bind(&EmbeddedWorkerTestHelper::OnStopWorker,
233                 weak_factory_.GetWeakPtr(),
234                 embedded_worker_id));
235}
236
237void EmbeddedWorkerTestHelper::OnMessageToWorkerStub(
238    int thread_id,
239    int embedded_worker_id,
240    const IPC::Message& message) {
241  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
242  ASSERT_TRUE(worker != NULL);
243  EXPECT_EQ(worker->thread_id(), thread_id);
244  base::MessageLoopProxy::current()->PostTask(
245      FROM_HERE,
246      base::Bind(
247          base::IgnoreResult(&EmbeddedWorkerTestHelper::OnMessageToWorker),
248          weak_factory_.GetWeakPtr(),
249          thread_id,
250          embedded_worker_id,
251          message));
252}
253
254void EmbeddedWorkerTestHelper::OnActivateEventStub(int request_id) {
255  base::MessageLoopProxy::current()->PostTask(
256      FROM_HERE,
257      base::Bind(&EmbeddedWorkerTestHelper::OnActivateEvent,
258                 weak_factory_.GetWeakPtr(),
259                 current_embedded_worker_id_,
260                 request_id));
261}
262
263void EmbeddedWorkerTestHelper::OnInstallEventStub(int request_id,
264                                                  int active_version_id) {
265  base::MessageLoopProxy::current()->PostTask(
266      FROM_HERE,
267      base::Bind(&EmbeddedWorkerTestHelper::OnInstallEvent,
268                 weak_factory_.GetWeakPtr(),
269                 current_embedded_worker_id_,
270                 request_id,
271                 active_version_id));
272}
273
274void EmbeddedWorkerTestHelper::OnFetchEventStub(
275    int request_id,
276    const ServiceWorkerFetchRequest& request) {
277  base::MessageLoopProxy::current()->PostTask(
278      FROM_HERE,
279      base::Bind(&EmbeddedWorkerTestHelper::OnFetchEvent,
280                 weak_factory_.GetWeakPtr(),
281                 current_embedded_worker_id_,
282                 request_id,
283                 request));
284}
285
286EmbeddedWorkerRegistry* EmbeddedWorkerTestHelper::registry() {
287  DCHECK(context());
288  return context()->embedded_worker_registry();
289}
290
291}  // namespace content
292