ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / content / renderer / service_worker / embedded_worker_context_client.cc
blobb84340b5bcb8f166fcea25cad1f18bdecbfcd139
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.
5 #include "content/renderer/service_worker/embedded_worker_context_client.h"
7 #include <map>
8 #include <string>
10 #include "base/lazy_instance.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/pickle.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/threading/thread_local.h"
17 #include "base/trace_event/trace_event.h"
18 #include "content/child/request_extra_data.h"
19 #include "content/child/service_worker/service_worker_dispatcher.h"
20 #include "content/child/service_worker/service_worker_network_provider.h"
21 #include "content/child/service_worker/service_worker_provider_context.h"
22 #include "content/child/service_worker/service_worker_registration_handle_reference.h"
23 #include "content/child/service_worker/web_service_worker_impl.h"
24 #include "content/child/service_worker/web_service_worker_provider_impl.h"
25 #include "content/child/service_worker/web_service_worker_registration_impl.h"
26 #include "content/child/thread_safe_sender.h"
27 #include "content/child/worker_task_runner.h"
28 #include "content/common/devtools_messages.h"
29 #include "content/common/service_worker/embedded_worker_messages.h"
30 #include "content/common/service_worker/service_worker_types.h"
31 #include "content/public/renderer/document_state.h"
32 #include "content/renderer/devtools/devtools_agent.h"
33 #include "content/renderer/render_thread_impl.h"
34 #include "content/renderer/service_worker/embedded_worker_dispatcher.h"
35 #include "content/renderer/service_worker/service_worker_script_context.h"
36 #include "content/renderer/service_worker/service_worker_type_util.h"
37 #include "ipc/ipc_message_macros.h"
38 #include "third_party/WebKit/public/platform/WebServiceWorkerResponse.h"
39 #include "third_party/WebKit/public/platform/WebString.h"
40 #include "third_party/WebKit/public/web/WebDataSource.h"
41 #include "third_party/WebKit/public/web/WebServiceWorkerNetworkProvider.h"
43 namespace content {
45 namespace {
47 // For now client must be a per-thread instance.
48 // TODO(kinuko): This needs to be refactored when we start using thread pool
49 // or having multiple clients per one thread.
50 base::LazyInstance<base::ThreadLocalPointer<EmbeddedWorkerContextClient> >::
51 Leaky g_worker_client_tls = LAZY_INSTANCE_INITIALIZER;
53 void CallWorkerContextDestroyedOnMainThread(int embedded_worker_id) {
54 if (!RenderThreadImpl::current() ||
55 !RenderThreadImpl::current()->embedded_worker_dispatcher())
56 return;
57 RenderThreadImpl::current()->embedded_worker_dispatcher()->
58 WorkerContextDestroyed(embedded_worker_id);
61 // We store an instance of this class in the "extra data" of the WebDataSource
62 // and attach a ServiceWorkerNetworkProvider to it as base::UserData.
63 // (see createServiceWorkerNetworkProvider).
64 class DataSourceExtraData
65 : public blink::WebDataSource::ExtraData,
66 public base::SupportsUserData {
67 public:
68 DataSourceExtraData() {}
69 virtual ~DataSourceExtraData() {}
72 // Called on the main thread only and blink owns it.
73 class WebServiceWorkerNetworkProviderImpl
74 : public blink::WebServiceWorkerNetworkProvider {
75 public:
76 // Blink calls this method for each request starting with the main script,
77 // we tag them with the provider id.
78 virtual void willSendRequest(
79 blink::WebDataSource* data_source,
80 blink::WebURLRequest& request) {
81 ServiceWorkerNetworkProvider* provider =
82 ServiceWorkerNetworkProvider::FromDocumentState(
83 static_cast<DataSourceExtraData*>(data_source->extraData()));
84 scoped_ptr<RequestExtraData> extra_data(new RequestExtraData);
85 extra_data->set_service_worker_provider_id(provider->provider_id());
86 request.setExtraData(extra_data.release());
90 } // namespace
92 EmbeddedWorkerContextClient*
93 EmbeddedWorkerContextClient::ThreadSpecificInstance() {
94 return g_worker_client_tls.Pointer()->Get();
97 EmbeddedWorkerContextClient::EmbeddedWorkerContextClient(
98 int embedded_worker_id,
99 int64 service_worker_version_id,
100 const GURL& service_worker_scope,
101 const GURL& script_url,
102 int worker_devtools_agent_route_id)
103 : embedded_worker_id_(embedded_worker_id),
104 service_worker_version_id_(service_worker_version_id),
105 service_worker_scope_(service_worker_scope),
106 script_url_(script_url),
107 worker_devtools_agent_route_id_(worker_devtools_agent_route_id),
108 sender_(ChildThreadImpl::current()->thread_safe_sender()),
109 main_thread_task_runner_(RenderThreadImpl::current()->GetTaskRunner()),
110 weak_factory_(this) {
111 TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
112 "EmbeddedWorkerContextClient::StartingWorkerContext",
113 this);
114 TRACE_EVENT_ASYNC_STEP_INTO0(
115 "ServiceWorker",
116 "EmbeddedWorkerContextClient::StartingWorkerContext",
117 this,
118 "PrepareWorker");
121 EmbeddedWorkerContextClient::~EmbeddedWorkerContextClient() {
124 bool EmbeddedWorkerContextClient::OnMessageReceived(
125 const IPC::Message& msg) {
126 bool handled = true;
127 IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerContextClient, msg)
128 IPC_MESSAGE_HANDLER(EmbeddedWorkerContextMsg_MessageToWorker,
129 OnMessageToWorker)
130 IPC_MESSAGE_UNHANDLED(handled = false)
131 IPC_END_MESSAGE_MAP()
132 return handled;
135 void EmbeddedWorkerContextClient::Send(IPC::Message* message) {
136 sender_->Send(message);
139 blink::WebURL EmbeddedWorkerContextClient::scope() const {
140 return service_worker_scope_;
143 blink::WebServiceWorkerCacheStorage*
144 EmbeddedWorkerContextClient::cacheStorage() {
145 return script_context_->cache_storage();
148 void EmbeddedWorkerContextClient::didPauseAfterDownload() {
149 Send(new EmbeddedWorkerHostMsg_DidPauseAfterDownload(embedded_worker_id_));
152 void EmbeddedWorkerContextClient::getClients(
153 blink::WebServiceWorkerClientsCallbacks* callbacks) {
154 DCHECK(script_context_);
155 script_context_->GetClientDocuments(callbacks);
158 void EmbeddedWorkerContextClient::openWindow(
159 const blink::WebURL& url,
160 blink::WebServiceWorkerClientCallbacks* callbacks) {
161 DCHECK(script_context_);
162 script_context_->OpenWindow(url, callbacks);
165 void EmbeddedWorkerContextClient::setCachedMetadata(const blink::WebURL& url,
166 const char* data,
167 size_t size) {
168 DCHECK(script_context_);
169 script_context_->SetCachedMetadata(url, data, size);
172 void EmbeddedWorkerContextClient::clearCachedMetadata(
173 const blink::WebURL& url) {
174 DCHECK(script_context_);
175 script_context_->ClearCachedMetadata(url);
178 void EmbeddedWorkerContextClient::workerReadyForInspection() {
179 Send(new EmbeddedWorkerHostMsg_WorkerReadyForInspection(embedded_worker_id_));
182 void EmbeddedWorkerContextClient::workerContextFailedToStart() {
183 DCHECK(main_thread_task_runner_->RunsTasksOnCurrentThread());
184 DCHECK(!script_context_);
186 Send(new EmbeddedWorkerHostMsg_WorkerScriptLoadFailed(embedded_worker_id_));
188 RenderThreadImpl::current()->embedded_worker_dispatcher()->
189 WorkerContextDestroyed(embedded_worker_id_);
192 void EmbeddedWorkerContextClient::workerContextStarted(
193 blink::WebServiceWorkerContextProxy* proxy) {
194 DCHECK(!worker_task_runner_.get());
195 DCHECK_NE(0, WorkerTaskRunner::Instance()->CurrentWorkerId());
196 worker_task_runner_ = base::ThreadTaskRunnerHandle::Get();
197 // g_worker_client_tls.Pointer()->Get() could return NULL if this context
198 // gets deleted before workerContextStarted() is called.
199 DCHECK(g_worker_client_tls.Pointer()->Get() == NULL);
200 DCHECK(!script_context_);
201 g_worker_client_tls.Pointer()->Set(this);
202 script_context_.reset(new ServiceWorkerScriptContext(this, proxy));
204 SetRegistrationInServiceWorkerGlobalScope();
206 Send(new EmbeddedWorkerHostMsg_WorkerScriptLoaded(
207 embedded_worker_id_,
208 WorkerTaskRunner::Instance()->CurrentWorkerId(),
209 provider_context_->provider_id()));
211 // Schedule a task to send back WorkerStarted asynchronously,
212 // so that at the time we send it we can be sure that the worker
213 // script has been evaluated and worker run loop has been started.
214 worker_task_runner_->PostTask(
215 FROM_HERE,
216 base::Bind(&EmbeddedWorkerContextClient::SendWorkerStarted,
217 weak_factory_.GetWeakPtr()));
218 TRACE_EVENT_ASYNC_STEP_INTO0(
219 "ServiceWorker",
220 "EmbeddedWorkerContextClient::StartingWorkerContext",
221 this,
222 "ExecuteScript");
225 void EmbeddedWorkerContextClient::didEvaluateWorkerScript(bool success) {
226 Send(new EmbeddedWorkerHostMsg_WorkerScriptEvaluated(
227 embedded_worker_id_, success));
230 void EmbeddedWorkerContextClient::willDestroyWorkerContext() {
231 // At this point OnWorkerRunLoopStopped is already called, so
232 // worker_task_runner_->RunsTasksOnCurrentThread() returns false
233 // (while we're still on the worker thread).
234 script_context_.reset();
236 // This also lets the message filter stop dispatching messages to
237 // this client.
238 g_worker_client_tls.Pointer()->Set(NULL);
241 void EmbeddedWorkerContextClient::workerContextDestroyed() {
242 DCHECK(g_worker_client_tls.Pointer()->Get() == NULL);
244 // Now we should be able to free the WebEmbeddedWorker container on the
245 // main thread.
246 main_thread_task_runner_->PostTask(
247 FROM_HERE,
248 base::Bind(&CallWorkerContextDestroyedOnMainThread,
249 embedded_worker_id_));
252 void EmbeddedWorkerContextClient::reportException(
253 const blink::WebString& error_message,
254 int line_number,
255 int column_number,
256 const blink::WebString& source_url) {
257 Send(new EmbeddedWorkerHostMsg_ReportException(
258 embedded_worker_id_, error_message, line_number,
259 column_number, GURL(source_url)));
262 void EmbeddedWorkerContextClient::reportConsoleMessage(
263 int source,
264 int level,
265 const blink::WebString& message,
266 int line_number,
267 const blink::WebString& source_url) {
268 EmbeddedWorkerHostMsg_ReportConsoleMessage_Params params;
269 params.source_identifier = source;
270 params.message_level = level;
271 params.message = message;
272 params.line_number = line_number;
273 params.source_url = GURL(source_url);
275 Send(new EmbeddedWorkerHostMsg_ReportConsoleMessage(
276 embedded_worker_id_, params));
279 void EmbeddedWorkerContextClient::sendDevToolsMessage(
280 int call_id,
281 const blink::WebString& message,
282 const blink::WebString& state_cookie) {
283 DevToolsAgent::SendChunkedProtocolMessage(
284 sender_.get(), worker_devtools_agent_route_id_,
285 call_id, message.utf8(), state_cookie.utf8());
288 void EmbeddedWorkerContextClient::didHandleActivateEvent(
289 int request_id,
290 blink::WebServiceWorkerEventResult result) {
291 DCHECK(script_context_);
292 script_context_->DidHandleActivateEvent(request_id, result);
295 void EmbeddedWorkerContextClient::didHandleInstallEvent(
296 int request_id,
297 blink::WebServiceWorkerEventResult result) {
298 DCHECK(script_context_);
299 script_context_->DidHandleInstallEvent(request_id, result);
302 void EmbeddedWorkerContextClient::didHandleFetchEvent(int request_id) {
303 DCHECK(script_context_);
304 script_context_->DidHandleFetchEvent(
305 request_id,
306 SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
307 ServiceWorkerResponse());
310 void EmbeddedWorkerContextClient::didHandleFetchEvent(
311 int request_id,
312 const blink::WebServiceWorkerResponse& web_response) {
313 DCHECK(script_context_);
314 ServiceWorkerHeaderMap headers;
315 GetServiceWorkerHeaderMapFromWebResponse(web_response, &headers);
316 ServiceWorkerResponse response(web_response.url(),
317 web_response.status(),
318 web_response.statusText().utf8(),
319 web_response.responseType(),
320 headers,
321 web_response.blobUUID().utf8(),
322 web_response.blobSize(),
323 web_response.streamURL());
324 script_context_->DidHandleFetchEvent(
325 request_id, SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, response);
328 void EmbeddedWorkerContextClient::didHandleNotificationClickEvent(
329 int request_id,
330 blink::WebServiceWorkerEventResult result) {
331 DCHECK(script_context_);
332 script_context_->DidHandleNotificationClickEvent(request_id, result);
335 void EmbeddedWorkerContextClient::didHandlePushEvent(
336 int request_id,
337 blink::WebServiceWorkerEventResult result) {
338 DCHECK(script_context_);
339 script_context_->DidHandlePushEvent(request_id, result);
342 void EmbeddedWorkerContextClient::didHandleSyncEvent(int request_id) {
343 DCHECK(script_context_);
344 script_context_->DidHandleSyncEvent(request_id);
347 void EmbeddedWorkerContextClient::didHandleCrossOriginConnectEvent(
348 int request_id,
349 bool accept_connection) {
350 DCHECK(script_context_);
351 script_context_->DidHandleCrossOriginConnectEvent(request_id,
352 accept_connection);
355 blink::WebServiceWorkerNetworkProvider*
356 EmbeddedWorkerContextClient::createServiceWorkerNetworkProvider(
357 blink::WebDataSource* data_source) {
358 DCHECK(main_thread_task_runner_->RunsTasksOnCurrentThread());
360 // Create a content::ServiceWorkerNetworkProvider for this data source so
361 // we can observe its requests.
362 scoped_ptr<ServiceWorkerNetworkProvider> provider(
363 new ServiceWorkerNetworkProvider(
364 MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER));
365 provider_context_ = provider->context();
367 // Tell the network provider about which version to load.
368 provider->SetServiceWorkerVersionId(service_worker_version_id_);
370 // The provider is kept around for the lifetime of the DataSource
371 // and ownership is transferred to the DataSource.
372 DataSourceExtraData* extra_data = new DataSourceExtraData();
373 data_source->setExtraData(extra_data);
374 ServiceWorkerNetworkProvider::AttachToDocumentState(
375 extra_data, provider.Pass());
377 // Blink is responsible for deleting the returned object.
378 return new WebServiceWorkerNetworkProviderImpl();
381 blink::WebServiceWorkerProvider*
382 EmbeddedWorkerContextClient::createServiceWorkerProvider() {
383 DCHECK(main_thread_task_runner_->RunsTasksOnCurrentThread());
384 DCHECK(provider_context_);
386 // Blink is responsible for deleting the returned object.
387 return new WebServiceWorkerProviderImpl(
388 thread_safe_sender(), provider_context_.get());
391 void EmbeddedWorkerContextClient::postMessageToClient(
392 int client_id,
393 const blink::WebString& message,
394 blink::WebMessagePortChannelArray* channels) {
395 DCHECK(script_context_);
396 script_context_->PostMessageToDocument(client_id, message,
397 make_scoped_ptr(channels));
400 void EmbeddedWorkerContextClient::postMessageToCrossOriginClient(
401 const blink::WebCrossOriginServiceWorkerClient& client,
402 const blink::WebString& message,
403 blink::WebMessagePortChannelArray* channels) {
404 DCHECK(script_context_);
405 script_context_->PostCrossOriginMessageToClient(client, message,
406 make_scoped_ptr(channels));
409 void EmbeddedWorkerContextClient::focus(
410 int client_id, blink::WebServiceWorkerClientCallbacks* callback) {
411 DCHECK(script_context_);
412 script_context_->FocusClient(client_id, callback);
415 void EmbeddedWorkerContextClient::skipWaiting(
416 blink::WebServiceWorkerSkipWaitingCallbacks* callbacks) {
417 DCHECK(script_context_);
418 script_context_->SkipWaiting(callbacks);
421 void EmbeddedWorkerContextClient::claim(
422 blink::WebServiceWorkerClientsClaimCallbacks* callbacks) {
423 DCHECK(script_context_);
424 script_context_->ClaimClients(callbacks);
427 void EmbeddedWorkerContextClient::OnMessageToWorker(
428 int thread_id,
429 int embedded_worker_id,
430 const IPC::Message& message) {
431 if (!script_context_)
432 return;
433 DCHECK_EQ(embedded_worker_id_, embedded_worker_id);
434 script_context_->OnMessageReceived(message);
437 void EmbeddedWorkerContextClient::SendWorkerStarted() {
438 DCHECK(worker_task_runner_->RunsTasksOnCurrentThread());
439 TRACE_EVENT_ASYNC_END0("ServiceWorker",
440 "EmbeddedWorkerContextClient::StartingWorkerContext",
441 this);
442 Send(new EmbeddedWorkerHostMsg_WorkerStarted(embedded_worker_id_));
445 void EmbeddedWorkerContextClient::SetRegistrationInServiceWorkerGlobalScope() {
446 DCHECK(worker_task_runner_->RunsTasksOnCurrentThread());
447 DCHECK(provider_context_);
448 DCHECK(script_context_);
450 ServiceWorkerRegistrationObjectInfo info;
451 ServiceWorkerVersionAttributes attrs;
452 bool found =
453 provider_context_->GetRegistrationInfoAndVersionAttributes(&info, &attrs);
454 if (!found)
455 return; // Cannot be associated with a registration in some tests.
457 ServiceWorkerDispatcher* dispatcher =
458 ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
459 thread_safe_sender());
461 // Register a registration and its version attributes with the dispatcher
462 // living on the worker thread.
463 scoped_ptr<WebServiceWorkerRegistrationImpl> registration(
464 dispatcher->CreateServiceWorkerRegistration(info, false));
465 registration->SetInstalling(
466 dispatcher->GetServiceWorker(attrs.installing, false));
467 registration->SetWaiting(
468 dispatcher->GetServiceWorker(attrs.waiting, false));
469 registration->SetActive(
470 dispatcher->GetServiceWorker(attrs.active, false));
472 script_context_->SetRegistrationInServiceWorkerGlobalScope(
473 registration.Pass());
476 } // namespace content