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/fileapi/file_system_dispatcher.h" 11#include "content/child/fileapi/webfilesystem_callback_adapters.h" 12#include "content/child/quota_dispatcher.h" 13#include "content/child/webmessageportchannel_impl.h" 14#include "content/common/worker_messages.h" 15#include "content/public/common/content_switches.h" 16#include "content/worker/shared_worker_devtools_agent.h" 17#include "content/worker/websharedworker_stub.h" 18#include "content/worker/worker_thread.h" 19#include "content/worker/worker_webapplicationcachehost_impl.h" 20#include "ipc/ipc_logging.h" 21#include "third_party/WebKit/public/platform/WebString.h" 22#include "third_party/WebKit/public/platform/WebURL.h" 23#include "third_party/WebKit/public/web/WebDocument.h" 24#include "third_party/WebKit/public/web/WebFileSystemCallbacks.h" 25#include "third_party/WebKit/public/web/WebFrame.h" 26#include "third_party/WebKit/public/web/WebSecurityOrigin.h" 27 28using WebKit::WebApplicationCacheHost; 29using WebKit::WebFrame; 30using WebKit::WebMessagePortChannel; 31using WebKit::WebMessagePortChannelArray; 32using WebKit::WebSecurityOrigin; 33using WebKit::WebString; 34using WebKit::WebWorker; 35using WebKit::WebSharedWorkerClient; 36 37namespace content { 38 39// How long to wait for worker to finish after it's been told to terminate. 40#define kMaxTimeForRunawayWorkerSeconds 3 41 42WebSharedWorkerClientProxy::WebSharedWorkerClientProxy( 43 int route_id, WebSharedWorkerStub* stub) 44 : route_id_(route_id), 45 appcache_host_id_(0), 46 stub_(stub), 47 weak_factory_(this), 48 devtools_agent_(NULL) { 49} 50 51WebSharedWorkerClientProxy::~WebSharedWorkerClientProxy() { 52} 53 54void WebSharedWorkerClientProxy::postMessageToWorkerObject( 55 const WebString& message, 56 const WebMessagePortChannelArray& channels) { 57 std::vector<int> message_port_ids(channels.size()); 58 std::vector<int> routing_ids(channels.size()); 59 for (size_t i = 0; i < channels.size(); ++i) { 60 WebMessagePortChannelImpl* webchannel = 61 static_cast<WebMessagePortChannelImpl*>(channels[i]); 62 message_port_ids[i] = webchannel->message_port_id(); 63 webchannel->QueueMessages(); 64 DCHECK(message_port_ids[i] != MSG_ROUTING_NONE); 65 routing_ids[i] = MSG_ROUTING_NONE; 66 } 67 68 Send(new WorkerMsg_PostMessage( 69 route_id_, message, message_port_ids, routing_ids)); 70} 71 72void WebSharedWorkerClientProxy::postExceptionToWorkerObject( 73 const WebString& error_message, 74 int line_number, 75 const WebString& source_url) { 76 Send(new WorkerHostMsg_PostExceptionToWorkerObject( 77 route_id_, error_message, line_number, source_url)); 78} 79 80void WebSharedWorkerClientProxy::postConsoleMessageToWorkerObject( 81 int source, 82 int type, 83 int level, 84 const WebString& message, 85 int line_number, 86 const WebString& source_url) { 87 WorkerHostMsg_PostConsoleMessageToWorkerObject_Params params; 88 params.source_identifier = source; 89 params.message_type = type; 90 params.message_level = level; 91 params.message = message; 92 params.line_number = line_number; 93 params.source_url = source_url; 94 Send(new WorkerHostMsg_PostConsoleMessageToWorkerObject(route_id_, params)); 95} 96 97void WebSharedWorkerClientProxy::confirmMessageFromWorkerObject( 98 bool has_pending_activity) { 99 Send(new WorkerHostMsg_ConfirmMessageFromWorkerObject( 100 route_id_, has_pending_activity)); 101} 102 103void WebSharedWorkerClientProxy::reportPendingActivity( 104 bool has_pending_activity) { 105 Send(new WorkerHostMsg_ReportPendingActivity( 106 route_id_, has_pending_activity)); 107} 108 109void WebSharedWorkerClientProxy::workerContextClosed() { 110 Send(new WorkerHostMsg_WorkerContextClosed(route_id_)); 111} 112 113void WebSharedWorkerClientProxy::workerContextDestroyed() { 114 Send(new WorkerHostMsg_WorkerContextDestroyed(route_id_)); 115 // Tell the stub that the worker has shutdown - frees this object. 116 if (stub_) 117 stub_->Shutdown(); 118} 119 120WebKit::WebNotificationPresenter* 121WebSharedWorkerClientProxy::notificationPresenter() { 122 // TODO(johnnyg): Notifications are not yet hooked up to workers. 123 // Coming soon. 124 NOTREACHED(); 125 return NULL; 126} 127 128WebApplicationCacheHost* WebSharedWorkerClientProxy::createApplicationCacheHost( 129 WebKit::WebApplicationCacheHostClient* client) { 130 WorkerWebApplicationCacheHostImpl* host = 131 new WorkerWebApplicationCacheHostImpl(stub_->appcache_init_info(), 132 client); 133 // Remember the id of the instance we create so we have access to that 134 // value when creating nested dedicated workers in createWorker. 135 appcache_host_id_ = host->host_id(); 136 return host; 137} 138 139// TODO(abarth): Security checks should use WebDocument or WebSecurityOrigin, 140// not WebFrame as the context object because WebFrames can contain different 141// WebDocuments at different times. 142bool WebSharedWorkerClientProxy::allowDatabase(WebFrame* frame, 143 const WebString& name, 144 const WebString& display_name, 145 unsigned long estimated_size) { 146 WebSecurityOrigin origin = frame->document().securityOrigin(); 147 if (origin.isUnique()) 148 return false; 149 150 bool result = false; 151 Send(new WorkerProcessHostMsg_AllowDatabase( 152 route_id_, GURL(origin.toString().utf8()), name, display_name, 153 estimated_size, &result)); 154 return result; 155} 156 157bool WebSharedWorkerClientProxy::allowFileSystem() { 158 bool result = false; 159 Send(new WorkerProcessHostMsg_AllowFileSystem( 160 route_id_, stub_->url().GetOrigin(), &result)); 161 return result; 162} 163 164void WebSharedWorkerClientProxy::openFileSystem( 165 WebKit::WebFileSystemType type, 166 long long size, 167 bool create, 168 WebKit::WebFileSystemCallbacks* callbacks) { 169 ChildThread::current()->file_system_dispatcher()->OpenFileSystem( 170 stub_->url().GetOrigin(), static_cast<fileapi::FileSystemType>(type), 171 size, create, 172 base::Bind(&OpenFileSystemCallbackAdapter, callbacks), 173 base::Bind(&FileStatusCallbackAdapter, callbacks)); 174} 175 176bool WebSharedWorkerClientProxy::allowIndexedDB(const WebKit::WebString& name) { 177 bool result = false; 178 Send(new WorkerProcessHostMsg_AllowIndexedDB( 179 route_id_, stub_->url().GetOrigin(), name, &result)); 180 return result; 181} 182 183void WebSharedWorkerClientProxy::queryUsageAndQuota( 184 WebKit::WebStorageQuotaType type, 185 WebKit::WebStorageQuotaCallbacks* callbacks) { 186 ChildThread::current()->quota_dispatcher()->QueryStorageUsageAndQuota( 187 stub_->url().GetOrigin(), static_cast<quota::StorageType>(type), 188 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks)); 189} 190 191void WebSharedWorkerClientProxy::dispatchDevToolsMessage( 192 const WebString& message) { 193 if (devtools_agent_) 194 devtools_agent_->SendDevToolsMessage(message); 195} 196 197void WebSharedWorkerClientProxy::saveDevToolsAgentState( 198 const WebKit::WebString& state) { 199 if (devtools_agent_) 200 devtools_agent_->SaveDevToolsAgentState(state); 201} 202 203bool WebSharedWorkerClientProxy::Send(IPC::Message* message) { 204 return WorkerThread::current()->Send(message); 205} 206 207void WebSharedWorkerClientProxy::EnsureWorkerContextTerminates() { 208 // This shuts down the process cleanly from the perspective of the browser 209 // process, and avoids the crashed worker infobar from appearing to the new 210 // page. It's ok to post several of theese, because the first executed task 211 // will exit the message loop and subsequent ones won't be executed. 212 base::MessageLoop::current()->PostDelayedTask( 213 FROM_HERE, 214 base::Bind(&WebSharedWorkerClientProxy::workerContextDestroyed, 215 weak_factory_.GetWeakPtr()), 216 base::TimeDelta::FromSeconds(kMaxTimeForRunawayWorkerSeconds)); 217} 218 219} // namespace content 220