1 // Copyright (c) 2012 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/worker/websharedworkerclient_proxy.h" 6 7 #include "base/bind.h" 8 #include "base/command_line.h" 9 #include "base/message_loop/message_loop.h" 10 #include "content/child/shared_worker_devtools_agent.h" 11 #include "content/child/webmessageportchannel_impl.h" 12 #include "content/common/worker_messages.h" 13 #include "content/public/common/content_switches.h" 14 #include "content/worker/shared_worker_permission_client_proxy.h" 15 #include "content/worker/websharedworker_stub.h" 16 #include "content/worker/worker_thread.h" 17 #include "content/worker/worker_webapplicationcachehost_impl.h" 18 #include "ipc/ipc_logging.h" 19 #include "third_party/WebKit/public/platform/WebString.h" 20 #include "third_party/WebKit/public/platform/WebURL.h" 21 #include "third_party/WebKit/public/web/WebDocument.h" 22 #include "third_party/WebKit/public/web/WebFrame.h" 23 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" 24 25 using blink::WebApplicationCacheHost; 26 using blink::WebFrame; 27 using blink::WebMessagePortChannel; 28 using blink::WebMessagePortChannelArray; 29 using blink::WebSecurityOrigin; 30 using blink::WebString; 31 using blink::WebWorker; 32 using blink::WebSharedWorkerClient; 33 34 namespace content { 35 36 // How long to wait for worker to finish after it's been told to terminate. 37 #define kMaxTimeForRunawayWorkerSeconds 3 38 39 WebSharedWorkerClientProxy::WebSharedWorkerClientProxy( 40 int route_id, WebSharedWorkerStub* stub) 41 : route_id_(route_id), 42 appcache_host_id_(0), 43 stub_(stub), 44 weak_factory_(this), 45 devtools_agent_(NULL), 46 app_cache_host_(NULL) { 47 } 48 49 WebSharedWorkerClientProxy::~WebSharedWorkerClientProxy() { 50 } 51 52 void WebSharedWorkerClientProxy::workerContextClosed() { 53 Send(new WorkerHostMsg_WorkerContextClosed(route_id_)); 54 } 55 56 void WebSharedWorkerClientProxy::workerContextDestroyed() { 57 Send(new WorkerHostMsg_WorkerContextDestroyed(route_id_)); 58 // Tell the stub that the worker has shutdown - frees this object. 59 if (stub_) 60 stub_->Shutdown(); 61 } 62 63 void WebSharedWorkerClientProxy::workerScriptLoaded() { 64 Send(new WorkerHostMsg_WorkerScriptLoaded(route_id_)); 65 if (stub_) 66 stub_->WorkerScriptLoaded(); 67 } 68 69 void WebSharedWorkerClientProxy::workerScriptLoadFailed() { 70 Send(new WorkerHostMsg_WorkerScriptLoadFailed(route_id_)); 71 if (stub_) 72 stub_->WorkerScriptLoadFailed(); 73 } 74 75 void WebSharedWorkerClientProxy::selectAppCacheID(long long app_cache_id) { 76 if (app_cache_host_) { 77 // app_cache_host_ could become stale as it's owned by blink's 78 // DocumentLoader. This method is assumed to be called while it's valid. 79 app_cache_host_->backend()->SelectCacheForSharedWorker( 80 app_cache_host_->host_id(), 81 app_cache_id); 82 } 83 } 84 85 blink::WebNotificationPresenter* 86 WebSharedWorkerClientProxy::notificationPresenter() { 87 // TODO(johnnyg): Notifications are not yet hooked up to workers. 88 // Coming soon. 89 NOTREACHED(); 90 return NULL; 91 } 92 93 WebApplicationCacheHost* WebSharedWorkerClientProxy::createApplicationCacheHost( 94 blink::WebApplicationCacheHostClient* client) { 95 DCHECK(!app_cache_host_); 96 app_cache_host_ = new WorkerWebApplicationCacheHostImpl(client); 97 // Remember the id of the instance we create so we have access to that 98 // value when creating nested dedicated workers in createWorker. 99 appcache_host_id_ = app_cache_host_->host_id(); 100 return app_cache_host_; 101 } 102 103 blink::WebWorkerPermissionClientProxy* 104 WebSharedWorkerClientProxy::createWorkerPermissionClientProxy( 105 const blink::WebSecurityOrigin& origin) { 106 return new SharedWorkerPermissionClientProxy( 107 GURL(origin.toString()), origin.isUnique(), route_id_, 108 ChildThread::current()->thread_safe_sender()); 109 } 110 111 void WebSharedWorkerClientProxy::dispatchDevToolsMessage( 112 const WebString& message) { 113 if (devtools_agent_) 114 devtools_agent_->SendDevToolsMessage(message); 115 } 116 117 void WebSharedWorkerClientProxy::saveDevToolsAgentState( 118 const blink::WebString& state) { 119 if (devtools_agent_) 120 devtools_agent_->SaveDevToolsAgentState(state); 121 } 122 123 bool WebSharedWorkerClientProxy::Send(IPC::Message* message) { 124 return WorkerThread::current()->Send(message); 125 } 126 127 void WebSharedWorkerClientProxy::EnsureWorkerContextTerminates() { 128 // This shuts down the process cleanly from the perspective of the browser 129 // process, and avoids the crashed worker infobar from appearing to the new 130 // page. It's ok to post several of theese, because the first executed task 131 // will exit the message loop and subsequent ones won't be executed. 132 base::MessageLoop::current()->PostDelayedTask( 133 FROM_HERE, 134 base::Bind(&WebSharedWorkerClientProxy::workerContextDestroyed, 135 weak_factory_.GetWeakPtr()), 136 base::TimeDelta::FromSeconds(kMaxTimeForRunawayWorkerSeconds)); 137 } 138 139 } // namespace content 140