blob: 28c4928070bfdbd30a79d56399090c3bae7f3243 [file] [log] [blame]
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +00001// 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/child/service_worker/service_worker_dispatcher.h"
6
7#include "base/lazy_instance.h"
8#include "base/threading/thread_local.h"
9#include "content/child/service_worker/web_service_worker_impl.h"
10#include "content/child/thread_safe_sender.h"
11#include "content/common/service_worker_messages.h"
12#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
13
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000014using blink::WebServiceWorkerError;
15using blink::WebServiceWorkerProvider;
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000016using base::ThreadLocalPointer;
17using webkit_glue::WorkerTaskRunner;
18
19namespace content {
20
21namespace {
22
23base::LazyInstance<ThreadLocalPointer<ServiceWorkerDispatcher> >::Leaky
24 g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
25
26ServiceWorkerDispatcher* const kHasBeenDeleted =
27 reinterpret_cast<ServiceWorkerDispatcher*>(0x1);
28
29int CurrentWorkerId() {
30 return WorkerTaskRunner::Instance()->CurrentWorkerId();
31}
32
33} // namespace
34
35ServiceWorkerDispatcher::ServiceWorkerDispatcher(
36 ThreadSafeSender* thread_safe_sender)
37 : thread_safe_sender_(thread_safe_sender) {
38 g_dispatcher_tls.Pointer()->Set(this);
39}
40
41ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
42 g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
43}
44
45void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
46 bool handled = true;
47 IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg)
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000048 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered)
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000049 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered,
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000050 OnUnregistered)
51 IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
52 OnRegistrationError)
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000053 IPC_MESSAGE_UNHANDLED(handled = false)
54 IPC_END_MESSAGE_MAP()
55 DCHECK(handled) << "Unhandled message:" << msg.type();
56}
57
58bool ServiceWorkerDispatcher::Send(IPC::Message* msg) {
59 return thread_safe_sender_->Send(msg);
60}
61
62void ServiceWorkerDispatcher::RegisterServiceWorker(
63 const GURL& pattern,
64 const GURL& script_url,
65 WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks) {
66 DCHECK(callbacks);
67 int request_id = pending_callbacks_.Add(callbacks);
68 thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
69 CurrentWorkerId(), request_id, pattern, script_url));
70}
71
72void ServiceWorkerDispatcher::UnregisterServiceWorker(
73 const GURL& pattern,
74 WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks) {
75 DCHECK(callbacks);
76 int request_id = pending_callbacks_.Add(callbacks);
77 thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
78 CurrentWorkerId(), request_id, pattern));
79}
80
81ServiceWorkerDispatcher* ServiceWorkerDispatcher::ThreadSpecificInstance(
82 ThreadSafeSender* thread_safe_sender) {
83 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
84 NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
85 g_dispatcher_tls.Pointer()->Set(NULL);
86 }
87 if (g_dispatcher_tls.Pointer()->Get())
88 return g_dispatcher_tls.Pointer()->Get();
89
90 ServiceWorkerDispatcher* dispatcher =
91 new ServiceWorkerDispatcher(thread_safe_sender);
92 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
93 webkit_glue::WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
94 return dispatcher;
95}
96
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000097void ServiceWorkerDispatcher::OnRegistered(
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000098 int32 thread_id,
99 int32 request_id,
100 int64 service_worker_id) {
101 WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
102 pending_callbacks_.Lookup(request_id);
103 DCHECK(callbacks);
104 if (!callbacks)
105 return;
106
107 // the browser has to generate the service_worker_id so the same
108 // worker can be called from different renderer contexts. However,
109 // the impl object doesn't have to be the same instance across calls
110 // unless we require the DOM objects to be identical when there's a
111 // duplicate registration. So for now we mint a new object each
112 // time.
113 scoped_ptr<WebServiceWorkerImpl> worker(
114 new WebServiceWorkerImpl(service_worker_id));
115 callbacks->onSuccess(worker.release());
116 pending_callbacks_.Remove(request_id);
117}
118
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000119void ServiceWorkerDispatcher::OnUnregistered(
120 int32 thread_id,
121 int32 request_id) {
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000122 WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
123 pending_callbacks_.Lookup(request_id);
124 DCHECK(callbacks);
125 if (!callbacks)
126 return;
127
128 callbacks->onSuccess(NULL);
129 pending_callbacks_.Remove(request_id);
130}
131
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000132void ServiceWorkerDispatcher::OnRegistrationError(
133 int32 thread_id,
134 int32 request_id,
135 WebServiceWorkerError::ErrorType error_type,
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000136 const base::string16& message) {
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000137 WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
138 pending_callbacks_.Lookup(request_id);
139 DCHECK(callbacks);
140 if (!callbacks)
141 return;
142
143 scoped_ptr<WebServiceWorkerError> error(
144 new WebServiceWorkerError(error_type, message));
145 callbacks->onError(error.release());
146 pending_callbacks_.Remove(request_id);
147}
148
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000149void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() { delete this; }
150
151} // namespace content