Cast: Skip receiver log messages with time delta that can't be encoded.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_browsertest.cc
blob84c68fdd95b3cf924cc46c77719dda6311a5f4b6
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 "base/bind.h"
6 #include "base/callback.h"
7 #include "base/command_line.h"
8 #include "base/run_loop.h"
9 #include "content/browser/service_worker/embedded_worker_instance.h"
10 #include "content/browser/service_worker/embedded_worker_registry.h"
11 #include "content/browser/service_worker/service_worker_context_core.h"
12 #include "content/browser/service_worker/service_worker_context_wrapper.h"
13 #include "content/browser/service_worker/service_worker_registration.h"
14 #include "content/browser/service_worker/service_worker_test_utils.h"
15 #include "content/browser/service_worker/service_worker_version.h"
16 #include "content/common/service_worker/service_worker_messages.h"
17 #include "content/public/browser/browser_context.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/render_process_host.h"
20 #include "content/public/browser/storage_partition.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/common/content_switches.h"
23 #include "content/shell/browser/shell.h"
24 #include "content/test/content_browser_test.h"
25 #include "content/test/content_browser_test_utils.h"
26 #include "net/test/embedded_test_server/embedded_test_server.h"
28 namespace content {
30 namespace {
32 void RunAndQuit(const base::Closure& closure,
33 const base::Closure& quit,
34 base::MessageLoopProxy* original_message_loop) {
35 closure.Run();
36 original_message_loop->PostTask(FROM_HERE, quit);
39 void RunOnIOThread(const base::Closure& closure) {
40 base::RunLoop run_loop;
41 BrowserThread::PostTask(
42 BrowserThread::IO, FROM_HERE,
43 base::Bind(&RunAndQuit, closure, run_loop.QuitClosure(),
44 base::MessageLoopProxy::current()));
45 run_loop.Run();
48 void ReceiveFetchResult(BrowserThread::ID run_quit_thread,
49 const base::Closure& quit,
50 ServiceWorkerStatusCode* out_status,
51 ServiceWorkerFetchResponse* out_response,
52 ServiceWorkerStatusCode actual_status,
53 const ServiceWorkerFetchResponse& actual_response) {
54 *out_status = actual_status;
55 *out_response = actual_response;
56 if (!quit.is_null())
57 BrowserThread::PostTask(run_quit_thread, FROM_HERE, quit);
60 ServiceWorkerVersion::FetchCallback CreateFetchResponseReceiver(
61 BrowserThread::ID run_quit_thread,
62 const base::Closure& quit,
63 ServiceWorkerStatusCode* out_status,
64 ServiceWorkerFetchResponse* out_response) {
65 return base::Bind(
66 &ReceiveFetchResult, run_quit_thread, quit, out_status, out_response);
69 } // namespace
71 class ServiceWorkerBrowserTest : public ContentBrowserTest {
72 protected:
73 typedef ServiceWorkerBrowserTest self;
75 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
76 command_line->AppendSwitch(switches::kEnableServiceWorker);
79 virtual void SetUpOnMainThread() OVERRIDE {
80 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
81 StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
82 shell()->web_contents()->GetBrowserContext());
83 wrapper_ = partition->GetServiceWorkerContext();
85 // Navigate to the page to set up a renderer page (where we can embed
86 // a worker).
87 NavigateToURLBlockUntilNavigationsComplete(
88 shell(),
89 embedded_test_server()->GetURL("/service_worker/empty.html"), 1);
91 RunOnIOThread(base::Bind(&self::SetUpOnIOThread, this));
94 virtual void TearDownOnMainThread() OVERRIDE {
95 RunOnIOThread(base::Bind(&self::TearDownOnIOThread, this));
96 wrapper_ = NULL;
99 virtual void SetUpOnIOThread() {}
100 virtual void TearDownOnIOThread() {}
102 ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); }
104 void AssociateRendererProcessToWorker(EmbeddedWorkerInstance* worker) {
105 worker->AddProcessReference(
106 shell()->web_contents()->GetRenderProcessHost()->GetID());
109 private:
110 scoped_refptr<ServiceWorkerContextWrapper> wrapper_;
113 class EmbeddedWorkerBrowserTest : public ServiceWorkerBrowserTest,
114 public EmbeddedWorkerInstance::Observer {
115 public:
116 typedef EmbeddedWorkerBrowserTest self;
118 EmbeddedWorkerBrowserTest()
119 : last_worker_status_(EmbeddedWorkerInstance::STOPPED) {}
120 virtual ~EmbeddedWorkerBrowserTest() {}
122 virtual void TearDownOnIOThread() OVERRIDE {
123 if (worker_) {
124 worker_->RemoveObserver(this);
125 worker_.reset();
129 void StartOnIOThread() {
130 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
131 worker_ = wrapper()->context()->embedded_worker_registry()->CreateWorker();
132 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker_->status());
133 worker_->AddObserver(this);
135 AssociateRendererProcessToWorker(worker_.get());
137 const int64 service_worker_version_id = 33L;
138 const GURL script_url = embedded_test_server()->GetURL(
139 "/service_worker/worker.js");
140 ServiceWorkerStatusCode status = worker_->Start(
141 service_worker_version_id, script_url);
143 last_worker_status_ = worker_->status();
144 EXPECT_EQ(SERVICE_WORKER_OK, status);
145 EXPECT_EQ(EmbeddedWorkerInstance::STARTING, last_worker_status_);
147 if (status != SERVICE_WORKER_OK && !done_closure_.is_null())
148 done_closure_.Run();
151 void StopOnIOThread() {
152 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
153 EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker_->status());
155 ServiceWorkerStatusCode status = worker_->Stop();
157 last_worker_status_ = worker_->status();
158 EXPECT_EQ(SERVICE_WORKER_OK, status);
159 EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, last_worker_status_);
161 if (status != SERVICE_WORKER_OK && !done_closure_.is_null())
162 done_closure_.Run();
165 protected:
166 // EmbeddedWorkerInstance::Observer overrides:
167 virtual void OnStarted() OVERRIDE {
168 ASSERT_TRUE(worker_ != NULL);
169 ASSERT_FALSE(done_closure_.is_null());
170 last_worker_status_ = worker_->status();
171 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_);
173 virtual void OnStopped() OVERRIDE {
174 ASSERT_TRUE(worker_ != NULL);
175 ASSERT_FALSE(done_closure_.is_null());
176 last_worker_status_ = worker_->status();
177 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_);
179 virtual void OnMessageReceived(
180 int request_id, const IPC::Message& message) OVERRIDE {
181 NOTREACHED();
184 scoped_ptr<EmbeddedWorkerInstance> worker_;
185 EmbeddedWorkerInstance::Status last_worker_status_;
187 // Called by EmbeddedWorkerInstance::Observer overrides so that
188 // test code can wait for the worker status notifications.
189 base::Closure done_closure_;
192 class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
193 public:
194 typedef ServiceWorkerVersionBrowserTest self;
196 ServiceWorkerVersionBrowserTest() : next_registration_id_(1) {}
197 virtual ~ServiceWorkerVersionBrowserTest() {}
199 virtual void TearDownOnIOThread() OVERRIDE {
200 if (registration_) {
201 registration_->Shutdown();
202 registration_ = NULL;
204 if (version_) {
205 version_->Shutdown();
206 version_ = NULL;
210 void InstallTestHelper(const std::string& worker_url) {
211 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
212 worker_url));
214 // Dispatch install on a worker.
215 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
216 base::RunLoop install_run_loop;
217 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
218 base::Bind(&self::InstallOnIOThread, this,
219 install_run_loop.QuitClosure(),
220 &status));
221 install_run_loop.Run();
222 ASSERT_EQ(SERVICE_WORKER_OK, status);
224 // Stop the worker.
225 status = SERVICE_WORKER_ERROR_FAILED;
226 base::RunLoop stop_run_loop;
227 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
228 base::Bind(&self::StopOnIOThread, this,
229 stop_run_loop.QuitClosure(),
230 &status));
231 stop_run_loop.Run();
232 ASSERT_EQ(SERVICE_WORKER_OK, status);
235 void SetUpRegistrationOnIOThread(const std::string& worker_url) {
236 const int64 version_id = 1L;
237 registration_ = new ServiceWorkerRegistration(
238 embedded_test_server()->GetURL("/*"),
239 embedded_test_server()->GetURL(worker_url),
240 next_registration_id_++);
241 version_ = new ServiceWorkerVersion(
242 registration_,
243 wrapper()->context()->embedded_worker_registry(),
244 version_id);
245 AssociateRendererProcessToWorker(version_->embedded_worker());
248 void StartOnIOThread(const base::Closure& done,
249 ServiceWorkerStatusCode* result) {
250 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
251 version_->StartWorker(CreateReceiver(BrowserThread::UI, done, result));
254 void InstallOnIOThread(const base::Closure& done,
255 ServiceWorkerStatusCode* result) {
256 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
257 version_->DispatchInstallEvent(
258 -1, CreateReceiver(BrowserThread::UI, done, result));
261 void FetchOnIOThread(const base::Closure& done,
262 ServiceWorkerStatusCode* result,
263 ServiceWorkerFetchResponse* message) {
264 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
265 ServiceWorkerFetchRequest request(
266 embedded_test_server()->GetURL("/service_worker/empty.html"),
267 "GET",
268 std::map<std::string, std::string>());
269 version_->DispatchFetchEvent(
270 request,
271 CreateFetchResponseReceiver(BrowserThread::UI, done, result, message));
275 void StopOnIOThread(const base::Closure& done,
276 ServiceWorkerStatusCode* result) {
277 ASSERT_TRUE(version_);
278 version_->StopWorker(CreateReceiver(BrowserThread::UI, done, result));
281 protected:
282 int64 next_registration_id_;
283 scoped_refptr<ServiceWorkerRegistration> registration_;
284 scoped_refptr<ServiceWorkerVersion> version_;
287 IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest, StartAndStop) {
288 // Start a worker and wait until OnStarted() is called.
289 base::RunLoop start_run_loop;
290 done_closure_ = start_run_loop.QuitClosure();
291 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
292 base::Bind(&self::StartOnIOThread, this));
293 start_run_loop.Run();
295 ASSERT_EQ(EmbeddedWorkerInstance::RUNNING, last_worker_status_);
297 // Stop a worker and wait until OnStopped() is called.
298 base::RunLoop stop_run_loop;
299 done_closure_ = stop_run_loop.QuitClosure();
300 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
301 base::Bind(&self::StopOnIOThread, this));
302 stop_run_loop.Run();
304 ASSERT_EQ(EmbeddedWorkerInstance::STOPPED, last_worker_status_);
307 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
308 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
309 "/service_worker/worker.js"));
311 // Start a worker.
312 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
313 base::RunLoop start_run_loop;
314 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
315 base::Bind(&self::StartOnIOThread, this,
316 start_run_loop.QuitClosure(),
317 &status));
318 start_run_loop.Run();
319 ASSERT_EQ(SERVICE_WORKER_OK, status);
321 // Stop the worker.
322 status = SERVICE_WORKER_ERROR_FAILED;
323 base::RunLoop stop_run_loop;
324 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
325 base::Bind(&self::StopOnIOThread, this,
326 stop_run_loop.QuitClosure(),
327 &status));
328 stop_run_loop.Run();
329 ASSERT_EQ(SERVICE_WORKER_OK, status);
332 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) {
333 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
334 "/service_worker/nonexistent.js"));
336 // Start a worker for nonexistent URL.
337 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
338 base::RunLoop start_run_loop;
339 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
340 base::Bind(&self::StartOnIOThread, this,
341 start_run_loop.QuitClosure(),
342 &status));
343 start_run_loop.Run();
344 ASSERT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
347 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) {
348 InstallTestHelper("/service_worker/worker.js");
351 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
352 InstallWithWaitUntil_Fulfilled) {
353 InstallTestHelper("/service_worker/worker_install_fulfilled.js");
356 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
357 InstallWithWaitUntil_Rejected) {
358 // TODO(kinuko): This should also report back an error, but we
359 // don't have plumbing for it yet.
360 InstallTestHelper("/service_worker/worker_install_rejected.js");
363 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Fetch) {
364 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
365 "/service_worker/worker.js"));
367 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
368 ServiceWorkerFetchResponse response;
369 base::RunLoop fetch_run_loop;
370 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
371 base::Bind(&self::FetchOnIOThread, this,
372 fetch_run_loop.QuitClosure(),
373 &status, &response));
374 fetch_run_loop.Run();
375 ASSERT_EQ(SERVICE_WORKER_OK, status);
376 ASSERT_EQ(200, response.status_code);
377 ASSERT_EQ("OK", response.status_text);
378 ASSERT_EQ("GET", response.method);
379 std::map<std::string, std::string> expected_headers;
380 ASSERT_EQ(expected_headers, response.headers);
383 } // namespace content