Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 1 | // 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" |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 8 | #include "base/stl_util.h" |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 9 | #include "base/threading/thread_local.h" |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 10 | #include "content/child/child_thread.h" |
| 11 | #include "content/child/service_worker/service_worker_handle_reference.h" |
| 12 | #include "content/child/service_worker/service_worker_provider_context.h" |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 13 | #include "content/child/service_worker/service_worker_registration_handle_reference.h" |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 14 | #include "content/child/service_worker/web_service_worker_impl.h" |
Torne (Richard Coles) | 5f1c943 | 2014-08-12 13:47:38 +0100 | [diff] [blame] | 15 | #include "content/child/service_worker/web_service_worker_registration_impl.h" |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 16 | #include "content/child/thread_safe_sender.h" |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 17 | #include "content/child/webmessageportchannel_impl.h" |
Torne (Richard Coles) | 5d1f7b1 | 2014-02-21 12:16:55 +0000 | [diff] [blame] | 18 | #include "content/common/service_worker/service_worker_messages.h" |
Torne (Richard Coles) | 6d86b77 | 2014-06-25 10:30:53 +0100 | [diff] [blame] | 19 | #include "content/public/common/url_utils.h" |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 20 | #include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h" |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 21 | #include "third_party/WebKit/public/web/WebSecurityOrigin.h" |
| 22 | |
Torne (Richard Coles) | f2477e0 | 2013-11-28 11:55:43 +0000 | [diff] [blame] | 23 | using blink::WebServiceWorkerError; |
| 24 | using blink::WebServiceWorkerProvider; |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 25 | using base::ThreadLocalPointer; |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 26 | |
| 27 | namespace content { |
| 28 | |
| 29 | namespace { |
| 30 | |
| 31 | base::LazyInstance<ThreadLocalPointer<ServiceWorkerDispatcher> >::Leaky |
| 32 | g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER; |
| 33 | |
| 34 | ServiceWorkerDispatcher* const kHasBeenDeleted = |
| 35 | reinterpret_cast<ServiceWorkerDispatcher*>(0x1); |
| 36 | |
| 37 | int CurrentWorkerId() { |
| 38 | return WorkerTaskRunner::Instance()->CurrentWorkerId(); |
| 39 | } |
| 40 | |
| 41 | } // namespace |
| 42 | |
| 43 | ServiceWorkerDispatcher::ServiceWorkerDispatcher( |
| 44 | ThreadSafeSender* thread_safe_sender) |
| 45 | : thread_safe_sender_(thread_safe_sender) { |
| 46 | g_dispatcher_tls.Pointer()->Set(this); |
| 47 | } |
| 48 | |
| 49 | ServiceWorkerDispatcher::~ServiceWorkerDispatcher() { |
| 50 | g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted); |
| 51 | } |
| 52 | |
| 53 | void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) { |
| 54 | bool handled = true; |
| 55 | IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg) |
Torne (Richard Coles) | f2477e0 | 2013-11-28 11:55:43 +0000 | [diff] [blame] | 56 | IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered) |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 57 | IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered, |
Torne (Richard Coles) | f2477e0 | 2013-11-28 11:55:43 +0000 | [diff] [blame] | 58 | OnUnregistered) |
| 59 | IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError, |
| 60 | OnRegistrationError) |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 61 | IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged, |
| 62 | OnServiceWorkerStateChanged) |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 63 | IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes, |
| 64 | OnSetVersionAttributes) |
Ben Murdoch | 116680a | 2014-07-20 18:25:52 -0700 | [diff] [blame] | 65 | IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker, |
| 66 | OnSetControllerServiceWorker) |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 67 | IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument, |
| 68 | OnPostMessage) |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 69 | IPC_MESSAGE_UNHANDLED(handled = false) |
| 70 | IPC_END_MESSAGE_MAP() |
| 71 | DCHECK(handled) << "Unhandled message:" << msg.type(); |
| 72 | } |
| 73 | |
| 74 | bool ServiceWorkerDispatcher::Send(IPC::Message* msg) { |
| 75 | return thread_safe_sender_->Send(msg); |
| 76 | } |
| 77 | |
| 78 | void ServiceWorkerDispatcher::RegisterServiceWorker( |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 79 | int provider_id, |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 80 | const GURL& pattern, |
| 81 | const GURL& script_url, |
Torne (Richard Coles) | 5f1c943 | 2014-08-12 13:47:38 +0100 | [diff] [blame] | 82 | WebServiceWorkerRegistrationCallbacks* callbacks) { |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 83 | DCHECK(callbacks); |
Torne (Richard Coles) | 6d86b77 | 2014-06-25 10:30:53 +0100 | [diff] [blame] | 84 | |
| 85 | if (pattern.possibly_invalid_spec().size() > GetMaxURLChars() || |
| 86 | script_url.possibly_invalid_spec().size() > GetMaxURLChars()) { |
Torne (Richard Coles) | 5f1c943 | 2014-08-12 13:47:38 +0100 | [diff] [blame] | 87 | scoped_ptr<WebServiceWorkerRegistrationCallbacks> |
Torne (Richard Coles) | 6d86b77 | 2014-06-25 10:30:53 +0100 | [diff] [blame] | 88 | owned_callbacks(callbacks); |
| 89 | scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError( |
| 90 | WebServiceWorkerError::ErrorTypeSecurity, "URL too long")); |
| 91 | callbacks->onError(error.release()); |
| 92 | return; |
| 93 | } |
| 94 | |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 95 | int request_id = pending_callbacks_.Add(callbacks); |
| 96 | thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker( |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 97 | CurrentWorkerId(), request_id, provider_id, pattern, script_url)); |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 98 | } |
| 99 | |
| 100 | void ServiceWorkerDispatcher::UnregisterServiceWorker( |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 101 | int provider_id, |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 102 | const GURL& pattern, |
Torne (Richard Coles) | 5f1c943 | 2014-08-12 13:47:38 +0100 | [diff] [blame] | 103 | WebServiceWorkerRegistrationCallbacks* callbacks) { |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 104 | DCHECK(callbacks); |
Torne (Richard Coles) | 6d86b77 | 2014-06-25 10:30:53 +0100 | [diff] [blame] | 105 | |
| 106 | if (pattern.possibly_invalid_spec().size() > GetMaxURLChars()) { |
Torne (Richard Coles) | 5f1c943 | 2014-08-12 13:47:38 +0100 | [diff] [blame] | 107 | scoped_ptr<WebServiceWorkerRegistrationCallbacks> |
Torne (Richard Coles) | 6d86b77 | 2014-06-25 10:30:53 +0100 | [diff] [blame] | 108 | owned_callbacks(callbacks); |
| 109 | scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError( |
| 110 | WebServiceWorkerError::ErrorTypeSecurity, "URL too long")); |
| 111 | callbacks->onError(error.release()); |
| 112 | return; |
| 113 | } |
| 114 | |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 115 | int request_id = pending_callbacks_.Add(callbacks); |
| 116 | thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker( |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 117 | CurrentWorkerId(), request_id, provider_id, pattern)); |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 118 | } |
| 119 | |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 120 | void ServiceWorkerDispatcher::AddProviderContext( |
| 121 | ServiceWorkerProviderContext* provider_context) { |
| 122 | DCHECK(provider_context); |
| 123 | int provider_id = provider_context->provider_id(); |
| 124 | DCHECK(!ContainsKey(provider_contexts_, provider_id)); |
| 125 | provider_contexts_[provider_id] = provider_context; |
| 126 | } |
| 127 | |
| 128 | void ServiceWorkerDispatcher::RemoveProviderContext( |
| 129 | ServiceWorkerProviderContext* provider_context) { |
| 130 | DCHECK(provider_context); |
| 131 | DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id())); |
| 132 | provider_contexts_.erase(provider_context->provider_id()); |
Ben Murdoch | 116680a | 2014-07-20 18:25:52 -0700 | [diff] [blame] | 133 | worker_to_provider_.erase(provider_context->installing_handle_id()); |
Torne (Richard Coles) | f8ee788 | 2014-06-20 14:52:04 +0100 | [diff] [blame] | 134 | worker_to_provider_.erase(provider_context->waiting_handle_id()); |
Ben Murdoch | 116680a | 2014-07-20 18:25:52 -0700 | [diff] [blame] | 135 | worker_to_provider_.erase(provider_context->active_handle_id()); |
| 136 | worker_to_provider_.erase(provider_context->controller_handle_id()); |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 137 | } |
| 138 | |
Torne (Richard Coles) | a140131 | 2014-03-18 10:20:56 +0000 | [diff] [blame] | 139 | void ServiceWorkerDispatcher::AddScriptClient( |
| 140 | int provider_id, |
| 141 | blink::WebServiceWorkerProviderClient* client) { |
| 142 | DCHECK(client); |
| 143 | DCHECK(!ContainsKey(script_clients_, provider_id)); |
| 144 | script_clients_[provider_id] = client; |
Torne (Richard Coles) | a140131 | 2014-03-18 10:20:56 +0000 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | void ServiceWorkerDispatcher::RemoveScriptClient(int provider_id) { |
| 148 | // This could be possibly called multiple times to ensure termination. |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 149 | if (ContainsKey(script_clients_, provider_id)) |
Torne (Richard Coles) | a140131 | 2014-03-18 10:20:56 +0000 | [diff] [blame] | 150 | script_clients_.erase(provider_id); |
Torne (Richard Coles) | a140131 | 2014-03-18 10:20:56 +0000 | [diff] [blame] | 151 | } |
| 152 | |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 153 | ServiceWorkerDispatcher* |
| 154 | ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance( |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 155 | ThreadSafeSender* thread_safe_sender) { |
| 156 | if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) { |
| 157 | NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher."; |
| 158 | g_dispatcher_tls.Pointer()->Set(NULL); |
| 159 | } |
| 160 | if (g_dispatcher_tls.Pointer()->Get()) |
| 161 | return g_dispatcher_tls.Pointer()->Get(); |
| 162 | |
| 163 | ServiceWorkerDispatcher* dispatcher = |
| 164 | new ServiceWorkerDispatcher(thread_safe_sender); |
| 165 | if (WorkerTaskRunner::Instance()->CurrentWorkerId()) |
Torne (Richard Coles) | a140131 | 2014-03-18 10:20:56 +0000 | [diff] [blame] | 166 | WorkerTaskRunner::Instance()->AddStopObserver(dispatcher); |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 167 | return dispatcher; |
| 168 | } |
| 169 | |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 170 | ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() { |
| 171 | if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) |
| 172 | return NULL; |
| 173 | return g_dispatcher_tls.Pointer()->Get(); |
| 174 | } |
| 175 | |
| 176 | void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() { |
| 177 | delete this; |
| 178 | } |
| 179 | |
Torne (Richard Coles) | 46d4c2b | 2014-06-09 12:00:27 +0100 | [diff] [blame] | 180 | WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker( |
| 181 | const ServiceWorkerObjectInfo& info, |
| 182 | bool adopt_handle) { |
Torne (Richard Coles) | f8ee788 | 2014-06-20 14:52:04 +0100 | [diff] [blame] | 183 | if (info.handle_id == kInvalidServiceWorkerHandleId) |
| 184 | return NULL; |
| 185 | |
Torne (Richard Coles) | 46d4c2b | 2014-06-09 12:00:27 +0100 | [diff] [blame] | 186 | WorkerObjectMap::iterator existing_worker = |
| 187 | service_workers_.find(info.handle_id); |
| 188 | |
| 189 | if (existing_worker != service_workers_.end()) { |
| 190 | if (adopt_handle) { |
| 191 | // We are instructed to adopt a handle but we already have one, so |
| 192 | // adopt and destroy a handle ref. |
| 193 | ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_); |
| 194 | } |
| 195 | return existing_worker->second; |
| 196 | } |
| 197 | |
| 198 | scoped_ptr<ServiceWorkerHandleReference> handle_ref = |
| 199 | adopt_handle |
| 200 | ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_) |
| 201 | : ServiceWorkerHandleReference::Create(info, thread_safe_sender_); |
| 202 | // WebServiceWorkerImpl constructor calls AddServiceWorker. |
| 203 | return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_); |
| 204 | } |
| 205 | |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 206 | WebServiceWorkerRegistrationImpl* |
| 207 | ServiceWorkerDispatcher::GetServiceWorkerRegistration( |
| 208 | int registration_handle_id, |
| 209 | const ServiceWorkerObjectInfo& info, |
| 210 | bool adopt_handle) { |
| 211 | if (registration_handle_id == kInvalidServiceWorkerRegistrationHandleId) |
| 212 | return NULL; |
| 213 | |
| 214 | RegistrationObjectMap::iterator existing_registration = |
| 215 | registrations_.find(registration_handle_id); |
| 216 | |
| 217 | if (existing_registration != registrations_.end()) { |
| 218 | if (adopt_handle) { |
| 219 | // We are instructed to adopt a handle but we already have one, so |
| 220 | // adopt and destroy a handle ref. |
| 221 | ServiceWorkerRegistrationHandleReference::Adopt( |
| 222 | registration_handle_id, info, thread_safe_sender_); |
| 223 | } |
| 224 | return existing_registration->second; |
| 225 | } |
| 226 | |
| 227 | scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref = |
| 228 | adopt_handle |
| 229 | ? ServiceWorkerRegistrationHandleReference::Adopt( |
| 230 | registration_handle_id, info, thread_safe_sender_) |
| 231 | : ServiceWorkerRegistrationHandleReference::Create( |
| 232 | registration_handle_id, info, thread_safe_sender_); |
| 233 | |
| 234 | // WebServiceWorkerRegistrationImpl constructor calls |
| 235 | // AddServiceWorkerRegistration. |
| 236 | return new WebServiceWorkerRegistrationImpl(handle_ref.Pass()); |
| 237 | } |
| 238 | |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 239 | void ServiceWorkerDispatcher::OnRegistered( |
| 240 | int thread_id, |
| 241 | int request_id, |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 242 | int registration_handle_id, |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 243 | const ServiceWorkerObjectInfo& info) { |
Torne (Richard Coles) | 5f1c943 | 2014-08-12 13:47:38 +0100 | [diff] [blame] | 244 | WebServiceWorkerRegistrationCallbacks* callbacks = |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 245 | pending_callbacks_.Lookup(request_id); |
| 246 | DCHECK(callbacks); |
| 247 | if (!callbacks) |
| 248 | return; |
| 249 | |
Torne (Richard Coles) | 5f1c943 | 2014-08-12 13:47:38 +0100 | [diff] [blame] | 250 | #ifdef DISABLE_SERVICE_WORKER_REGISTRATION |
Torne (Richard Coles) | 46d4c2b | 2014-06-09 12:00:27 +0100 | [diff] [blame] | 251 | callbacks->onSuccess(GetServiceWorker(info, true)); |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 252 | // We should adopt and destroy an unused handle ref. |
| 253 | ServiceWorkerRegistrationHandleReference::Adopt( |
| 254 | registration_handle_id, info, thread_safe_sender_); |
Torne (Richard Coles) | 5f1c943 | 2014-08-12 13:47:38 +0100 | [diff] [blame] | 255 | #else |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 256 | callbacks->onSuccess(GetServiceWorkerRegistration( |
| 257 | registration_handle_id, info, true)); |
| 258 | // We should adopt and destroy an unused handle ref. |
| 259 | ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_); |
Torne (Richard Coles) | 5f1c943 | 2014-08-12 13:47:38 +0100 | [diff] [blame] | 260 | #endif |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 261 | pending_callbacks_.Remove(request_id); |
| 262 | } |
| 263 | |
Torne (Richard Coles) | f2477e0 | 2013-11-28 11:55:43 +0000 | [diff] [blame] | 264 | void ServiceWorkerDispatcher::OnUnregistered( |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 265 | int thread_id, |
| 266 | int request_id) { |
Torne (Richard Coles) | 5f1c943 | 2014-08-12 13:47:38 +0100 | [diff] [blame] | 267 | WebServiceWorkerRegistrationCallbacks* callbacks = |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 268 | pending_callbacks_.Lookup(request_id); |
| 269 | DCHECK(callbacks); |
| 270 | if (!callbacks) |
| 271 | return; |
| 272 | |
| 273 | callbacks->onSuccess(NULL); |
| 274 | pending_callbacks_.Remove(request_id); |
| 275 | } |
| 276 | |
Torne (Richard Coles) | f2477e0 | 2013-11-28 11:55:43 +0000 | [diff] [blame] | 277 | void ServiceWorkerDispatcher::OnRegistrationError( |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 278 | int thread_id, |
| 279 | int request_id, |
Torne (Richard Coles) | f2477e0 | 2013-11-28 11:55:43 +0000 | [diff] [blame] | 280 | WebServiceWorkerError::ErrorType error_type, |
Torne (Richard Coles) | a3f6a49 | 2013-12-18 16:25:09 +0000 | [diff] [blame] | 281 | const base::string16& message) { |
Torne (Richard Coles) | 5f1c943 | 2014-08-12 13:47:38 +0100 | [diff] [blame] | 282 | WebServiceWorkerRegistrationCallbacks* callbacks = |
Torne (Richard Coles) | f2477e0 | 2013-11-28 11:55:43 +0000 | [diff] [blame] | 283 | pending_callbacks_.Lookup(request_id); |
| 284 | DCHECK(callbacks); |
| 285 | if (!callbacks) |
| 286 | return; |
| 287 | |
Torne (Richard Coles) | 6d86b77 | 2014-06-25 10:30:53 +0100 | [diff] [blame] | 288 | scoped_ptr<WebServiceWorkerError> error( |
Torne (Richard Coles) | f2477e0 | 2013-11-28 11:55:43 +0000 | [diff] [blame] | 289 | new WebServiceWorkerError(error_type, message)); |
| 290 | callbacks->onError(error.release()); |
| 291 | pending_callbacks_.Remove(request_id); |
| 292 | } |
| 293 | |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 294 | void ServiceWorkerDispatcher::OnServiceWorkerStateChanged( |
Ben Murdoch | 0529e5d | 2014-04-24 10:50:13 +0100 | [diff] [blame] | 295 | int thread_id, |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 296 | int handle_id, |
| 297 | blink::WebServiceWorkerState state) { |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 298 | WorkerObjectMap::iterator worker = service_workers_.find(handle_id); |
| 299 | if (worker != service_workers_.end()) |
| 300 | worker->second->OnStateChanged(state); |
| 301 | |
| 302 | WorkerToProviderMap::iterator provider = worker_to_provider_.find(handle_id); |
| 303 | if (provider != worker_to_provider_.end()) |
| 304 | provider->second->OnServiceWorkerStateChanged(handle_id, state); |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 305 | } |
| 306 | |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 307 | void ServiceWorkerDispatcher::OnSetVersionAttributes( |
Ben Murdoch | 116680a | 2014-07-20 18:25:52 -0700 | [diff] [blame] | 308 | int thread_id, |
| 309 | int provider_id, |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 310 | int registration_handle_id, |
| 311 | int changed_mask, |
| 312 | const ServiceWorkerVersionAttributes& attributes) { |
| 313 | ChangedVersionAttributesMask mask(changed_mask); |
| 314 | if (mask.installing_changed()) { |
| 315 | SetInstallingServiceWorker(provider_id, |
| 316 | registration_handle_id, |
| 317 | attributes.installing); |
| 318 | } |
| 319 | if (mask.waiting_changed()) { |
| 320 | SetWaitingServiceWorker(provider_id, |
| 321 | registration_handle_id, |
| 322 | attributes.waiting); |
| 323 | } |
| 324 | if (mask.active_changed()) { |
| 325 | SetActiveServiceWorker(provider_id, |
| 326 | registration_handle_id, |
| 327 | attributes.active); |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | void ServiceWorkerDispatcher::SetInstallingServiceWorker( |
| 332 | int provider_id, |
| 333 | int registration_handle_id, |
Ben Murdoch | 116680a | 2014-07-20 18:25:52 -0700 | [diff] [blame] | 334 | const ServiceWorkerObjectInfo& info) { |
| 335 | ProviderContextMap::iterator provider = provider_contexts_.find(provider_id); |
| 336 | if (provider != provider_contexts_.end()) { |
| 337 | int existing_installing_id = provider->second->installing_handle_id(); |
| 338 | if (existing_installing_id != info.handle_id && |
| 339 | existing_installing_id != kInvalidServiceWorkerHandleId) { |
| 340 | WorkerToProviderMap::iterator associated_provider = |
| 341 | worker_to_provider_.find(existing_installing_id); |
| 342 | DCHECK(associated_provider != worker_to_provider_.end()); |
| 343 | DCHECK(associated_provider->second->provider_id() == provider_id); |
| 344 | worker_to_provider_.erase(associated_provider); |
| 345 | } |
| 346 | provider->second->OnSetInstallingServiceWorker(provider_id, info); |
| 347 | if (info.handle_id != kInvalidServiceWorkerHandleId) |
| 348 | worker_to_provider_[info.handle_id] = provider->second; |
| 349 | } |
| 350 | |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 351 | #ifdef DISABLE_SERVICE_WORKER_REGISTRATION |
Ben Murdoch | 116680a | 2014-07-20 18:25:52 -0700 | [diff] [blame] | 352 | ScriptClientMap::iterator found = script_clients_.find(provider_id); |
| 353 | if (found != script_clients_.end()) { |
| 354 | // Populate the .installing field with the new worker object. |
| 355 | found->second->setInstalling(GetServiceWorker(info, false)); |
| 356 | } |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 357 | #else |
| 358 | RegistrationObjectMap::iterator found = |
| 359 | registrations_.find(registration_handle_id); |
| 360 | if (found != registrations_.end()) { |
| 361 | found->second->setInstalling(GetServiceWorker(info, false)); |
| 362 | if (info.handle_id != kInvalidServiceWorkerHandleId) |
| 363 | found->second->OnUpdateFound(); |
| 364 | } |
| 365 | #endif |
Ben Murdoch | 116680a | 2014-07-20 18:25:52 -0700 | [diff] [blame] | 366 | } |
| 367 | |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 368 | void ServiceWorkerDispatcher::SetWaitingServiceWorker( |
Torne (Richard Coles) | f8ee788 | 2014-06-20 14:52:04 +0100 | [diff] [blame] | 369 | int provider_id, |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 370 | int registration_handle_id, |
Torne (Richard Coles) | f8ee788 | 2014-06-20 14:52:04 +0100 | [diff] [blame] | 371 | const ServiceWorkerObjectInfo& info) { |
| 372 | ProviderContextMap::iterator provider = provider_contexts_.find(provider_id); |
| 373 | if (provider != provider_contexts_.end()) { |
| 374 | int existing_waiting_id = provider->second->waiting_handle_id(); |
| 375 | if (existing_waiting_id != info.handle_id && |
| 376 | existing_waiting_id != kInvalidServiceWorkerHandleId) { |
| 377 | WorkerToProviderMap::iterator associated_provider = |
| 378 | worker_to_provider_.find(existing_waiting_id); |
| 379 | DCHECK(associated_provider != worker_to_provider_.end()); |
| 380 | DCHECK(associated_provider->second->provider_id() == provider_id); |
| 381 | worker_to_provider_.erase(associated_provider); |
| 382 | } |
| 383 | provider->second->OnSetWaitingServiceWorker(provider_id, info); |
| 384 | if (info.handle_id != kInvalidServiceWorkerHandleId) |
| 385 | worker_to_provider_[info.handle_id] = provider->second; |
| 386 | } |
| 387 | |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 388 | #ifdef DISABLE_SERVICE_WORKER_REGISTRATION |
Torne (Richard Coles) | f8ee788 | 2014-06-20 14:52:04 +0100 | [diff] [blame] | 389 | ScriptClientMap::iterator found = script_clients_.find(provider_id); |
| 390 | if (found != script_clients_.end()) { |
| 391 | // Populate the .waiting field with the new worker object. |
| 392 | found->second->setWaiting(GetServiceWorker(info, false)); |
| 393 | } |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 394 | #else |
| 395 | RegistrationObjectMap::iterator found = |
| 396 | registrations_.find(registration_handle_id); |
| 397 | if (found != registrations_.end()) |
| 398 | found->second->setWaiting(GetServiceWorker(info, false)); |
| 399 | #endif |
Torne (Richard Coles) | f8ee788 | 2014-06-20 14:52:04 +0100 | [diff] [blame] | 400 | } |
| 401 | |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 402 | void ServiceWorkerDispatcher::SetActiveServiceWorker( |
Ben Murdoch | 0529e5d | 2014-04-24 10:50:13 +0100 | [diff] [blame] | 403 | int provider_id, |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 404 | int registration_handle_id, |
Ben Murdoch | 0529e5d | 2014-04-24 10:50:13 +0100 | [diff] [blame] | 405 | const ServiceWorkerObjectInfo& info) { |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 406 | ProviderContextMap::iterator provider = provider_contexts_.find(provider_id); |
| 407 | if (provider != provider_contexts_.end()) { |
Ben Murdoch | 116680a | 2014-07-20 18:25:52 -0700 | [diff] [blame] | 408 | int existing_active_id = provider->second->active_handle_id(); |
| 409 | if (existing_active_id != info.handle_id && |
| 410 | existing_active_id != kInvalidServiceWorkerHandleId) { |
| 411 | WorkerToProviderMap::iterator associated_provider = |
| 412 | worker_to_provider_.find(existing_active_id); |
| 413 | DCHECK(associated_provider != worker_to_provider_.end()); |
| 414 | DCHECK(associated_provider->second->provider_id() == provider_id); |
| 415 | worker_to_provider_.erase(associated_provider); |
| 416 | } |
| 417 | provider->second->OnSetActiveServiceWorker(provider_id, info); |
| 418 | if (info.handle_id != kInvalidServiceWorkerHandleId) |
| 419 | worker_to_provider_[info.handle_id] = provider->second; |
| 420 | } |
| 421 | |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 422 | #ifdef DISABLE_SERVICE_WORKER_REGISTRATION |
Ben Murdoch | 116680a | 2014-07-20 18:25:52 -0700 | [diff] [blame] | 423 | ScriptClientMap::iterator found = script_clients_.find(provider_id); |
| 424 | if (found != script_clients_.end()) { |
| 425 | // Populate the .active field with the new worker object. |
| 426 | found->second->setActive(GetServiceWorker(info, false)); |
| 427 | } |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 428 | #else |
| 429 | RegistrationObjectMap::iterator found = |
| 430 | registrations_.find(registration_handle_id); |
| 431 | if (found != registrations_.end()) |
| 432 | found->second->setActive(GetServiceWorker(info, false)); |
| 433 | #endif |
Ben Murdoch | 116680a | 2014-07-20 18:25:52 -0700 | [diff] [blame] | 434 | } |
| 435 | |
| 436 | void ServiceWorkerDispatcher::OnSetControllerServiceWorker( |
| 437 | int thread_id, |
| 438 | int provider_id, |
| 439 | const ServiceWorkerObjectInfo& info) { |
| 440 | ProviderContextMap::iterator provider = provider_contexts_.find(provider_id); |
| 441 | if (provider != provider_contexts_.end()) { |
| 442 | provider->second->OnSetControllerServiceWorker(provider_id, info); |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 443 | worker_to_provider_[info.handle_id] = provider->second; |
| 444 | } |
| 445 | |
| 446 | ScriptClientMap::iterator found = script_clients_.find(provider_id); |
| 447 | if (found != script_clients_.end()) { |
Torne (Richard Coles) | f8ee788 | 2014-06-20 14:52:04 +0100 | [diff] [blame] | 448 | // Populate the .controller field with the new worker object. |
| 449 | found->second->setController(GetServiceWorker(info, false)); |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 450 | } |
| 451 | } |
| 452 | |
| 453 | void ServiceWorkerDispatcher::OnPostMessage( |
| 454 | int thread_id, |
| 455 | int provider_id, |
| 456 | const base::string16& message, |
| 457 | const std::vector<int>& sent_message_port_ids, |
| 458 | const std::vector<int>& new_routing_ids) { |
| 459 | // Make sure we're on the main document thread. (That must be the only |
| 460 | // thread we get this message) |
| 461 | DCHECK(ChildThread::current()); |
| 462 | |
Ben Murdoch | 0529e5d | 2014-04-24 10:50:13 +0100 | [diff] [blame] | 463 | ScriptClientMap::iterator found = script_clients_.find(provider_id); |
| 464 | if (found == script_clients_.end()) { |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 465 | // For now we do no queueing for messages sent to nonexistent / unattached |
| 466 | // client. |
Ben Murdoch | 0529e5d | 2014-04-24 10:50:13 +0100 | [diff] [blame] | 467 | return; |
| 468 | } |
Torne (Richard Coles) | 010d83a | 2014-05-14 12:12:37 +0100 | [diff] [blame] | 469 | |
| 470 | std::vector<WebMessagePortChannelImpl*> ports; |
| 471 | if (!sent_message_port_ids.empty()) { |
| 472 | ports.resize(sent_message_port_ids.size()); |
| 473 | for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { |
| 474 | ports[i] = new WebMessagePortChannelImpl( |
| 475 | new_routing_ids[i], sent_message_port_ids[i], |
| 476 | base::MessageLoopProxy::current()); |
| 477 | } |
| 478 | } |
| 479 | |
| 480 | found->second->dispatchMessageEvent(message, ports); |
Ben Murdoch | 0529e5d | 2014-04-24 10:50:13 +0100 | [diff] [blame] | 481 | } |
| 482 | |
Ben Murdoch | a02191e | 2014-04-16 11:17:03 +0100 | [diff] [blame] | 483 | void ServiceWorkerDispatcher::AddServiceWorker( |
| 484 | int handle_id, WebServiceWorkerImpl* worker) { |
| 485 | DCHECK(!ContainsKey(service_workers_, handle_id)); |
| 486 | service_workers_[handle_id] = worker; |
| 487 | } |
| 488 | |
| 489 | void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) { |
| 490 | DCHECK(ContainsKey(service_workers_, handle_id)); |
| 491 | service_workers_.erase(handle_id); |
| 492 | } |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 493 | |
Torne (Richard Coles) | 6e8cce6 | 2014-08-19 13:00:08 +0100 | [diff] [blame^] | 494 | void ServiceWorkerDispatcher::AddServiceWorkerRegistration( |
| 495 | int registration_handle_id, |
| 496 | WebServiceWorkerRegistrationImpl* registration) { |
| 497 | DCHECK(!ContainsKey(registrations_, registration_handle_id)); |
| 498 | registrations_[registration_handle_id] = registration; |
| 499 | } |
| 500 | |
| 501 | void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration( |
| 502 | int registration_handle_id) { |
| 503 | DCHECK(ContainsKey(registrations_, registration_handle_id)); |
| 504 | registrations_.erase(registration_handle_id); |
| 505 | } |
| 506 | |
Torne (Richard Coles) | 1e9bf3e | 2013-10-31 11:16:26 +0000 | [diff] [blame] | 507 | } // namespace content |