diff options
author | atwilson@chromium.org <atwilson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-30 18:11:47 +0000 |
---|---|---|
committer | atwilson@chromium.org <atwilson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-30 18:11:47 +0000 |
commit | ab3505360bf6612d18915a39a0fec74b00642e82 (patch) | |
tree | 7a39d15a688b8e52c839fb9151851b2a37533ed0 /chrome | |
parent | 06b9e3b77773477b5ee889ded41d10741d6b0647 (diff) | |
download | chromium_src-ab3505360bf6612d18915a39a0fec74b00642e82.zip chromium_src-ab3505360bf6612d18915a39a0fec74b00642e82.tar.gz chromium_src-ab3505360bf6612d18915a39a0fec74b00642e82.tar.bz2 |
Initial pass of shared workers renderer-side code
Added initial interface hooks betweek WebKit code and renderer-side worker code.
The proper messages are generated to fire off a shared worker, but they are currently
ignored by the browser process.
BUG=26233
TEST=none (will enable layout tests when basic functionality available)
Review URL: http://codereview.chromium.org/340036
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30599 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/in_process_webkit/browser_webkitclient_impl.cc | 6 | ||||
-rw-r--r-- | chrome/browser/in_process_webkit/browser_webkitclient_impl.h | 1 | ||||
-rw-r--r-- | chrome/browser/worker_host/worker_process_host.cc | 78 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 6 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 18 | ||||
-rw-r--r-- | chrome/common/worker_messages_internal.h | 4 | ||||
-rw-r--r-- | chrome/renderer/renderer_webkitclient_impl.cc | 5 | ||||
-rw-r--r-- | chrome/renderer/renderer_webkitclient_impl.h | 8 | ||||
-rw-r--r-- | chrome/renderer/websharedworker_impl.cc | 58 | ||||
-rw-r--r-- | chrome/renderer/websharedworker_impl.h | 49 | ||||
-rw-r--r-- | chrome/renderer/websharedworkerrepository_impl.cc | 24 | ||||
-rw-r--r-- | chrome/renderer/websharedworkerrepository_impl.h | 22 | ||||
-rw-r--r-- | chrome/renderer/webworker_base.cc | 102 | ||||
-rw-r--r-- | chrome/renderer/webworker_base.h | 64 | ||||
-rw-r--r-- | chrome/renderer/webworker_proxy.cc | 69 | ||||
-rw-r--r-- | chrome/renderer/webworker_proxy.h | 21 | ||||
-rw-r--r-- | chrome/worker/worker_webkitclient_impl.cc | 5 | ||||
-rw-r--r-- | chrome/worker/worker_webkitclient_impl.h | 1 |
18 files changed, 434 insertions, 107 deletions
diff --git a/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc b/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc index 6a13013..ec893fb 100644 --- a/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc +++ b/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc @@ -123,3 +123,9 @@ void BrowserWebKitClientImpl::dispatchStorageEvent( DOMStorageDispatcherHost::DispatchStorageEvent(key, old_value, new_value, origin, is_local_storage); } + +WebKit::WebSharedWorkerRepository* +BrowserWebKitClientImpl::sharedWorkerRepository() { + NOTREACHED(); + return NULL; +} diff --git a/chrome/browser/in_process_webkit/browser_webkitclient_impl.h b/chrome/browser/in_process_webkit/browser_webkitclient_impl.h index 0024bfb..ff79350 100644 --- a/chrome/browser/in_process_webkit/browser_webkitclient_impl.h +++ b/chrome/browser/in_process_webkit/browser_webkitclient_impl.h @@ -36,6 +36,7 @@ class BrowserWebKitClientImpl : public webkit_glue::WebKitClientImpl { virtual void dispatchStorageEvent(const WebKit::WebString& key, const WebKit::WebString& oldValue, const WebKit::WebString& newValue, const WebKit::WebString& origin, bool isLocalStorage); + virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository(); }; #endif // CHROME_BROWSER_IN_PROCESS_WEBKIT_WEBKIT_CLIENT_IMPL_H_ diff --git a/chrome/browser/worker_host/worker_process_host.cc b/chrome/browser/worker_host/worker_process_host.cc index 094a2fd..54446b3 100644 --- a/chrome/browser/worker_host/worker_process_host.cc +++ b/chrome/browser/worker_host/worker_process_host.cc @@ -144,7 +144,7 @@ void WorkerProcessHost::CreateWorker(const WorkerInstance& instance) { UpdateTitle(); instances_.back().sender->Send( - new ViewMsg_DedicatedWorkerCreated(instance.sender_route_id)); + new ViewMsg_WorkerCreated(instance.sender_route_id)); } bool WorkerProcessHost::FilterMessage(const IPC::Message& message, @@ -229,39 +229,59 @@ void WorkerProcessHost::RelayMessage( IPC::Message::Sender* sender, int route_id, CallbackWithReturnValue<int>::Type* next_route_id) { - if (message.type() != WorkerMsg_PostMessage::ID) { - IPC::Message* new_message = new IPC::Message(message); - new_message->set_routing_id(route_id); - sender->Send(new_message); - return; - } - // We want to send the receiver a routing id for the new channel, so - // crack the message first. - string16 msg; - std::vector<int> sent_message_port_ids; - std::vector<int> new_routing_ids; - if (!WorkerMsg_PostMessage::Read( - &message, &msg, &sent_message_port_ids, &new_routing_ids)) { - return; - } - DCHECK(sent_message_port_ids.size() == new_routing_ids.size()); + if (message.type() == WorkerMsg_PostMessage::ID) { + // We want to send the receiver a routing id for the new channel, so + // crack the message first. + string16 msg; + std::vector<int> sent_message_port_ids; + std::vector<int> new_routing_ids; + if (!WorkerMsg_PostMessage::Read( + &message, &msg, &sent_message_port_ids, &new_routing_ids)) { + return; + } + DCHECK(sent_message_port_ids.size() == new_routing_ids.size()); + + for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { + new_routing_ids[i] = next_route_id->Run(); + MessagePortDispatcher::GetInstance()->UpdateMessagePort( + sent_message_port_ids[i], sender, new_routing_ids[i], next_route_id); + } + + sender->Send(new WorkerMsg_PostMessage( + route_id, msg, sent_message_port_ids, new_routing_ids)); - for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { - new_routing_ids[i] = next_route_id->Run(); + // Send any queued messages to the sent message ports. We can only do this + // after sending the above message, since it's the one that sets up the + // message port route which the queued messages are sent to. + for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { + MessagePortDispatcher::GetInstance()-> + SendQueuedMessagesIfPossible(sent_message_port_ids[i]); + } + } else if (message.type() == WorkerMsg_Connect::ID) { + // Crack the SharedWorker Connect message to setup routing for the port. + int sent_message_port_id; + int new_routing_id; + if (!WorkerMsg_Connect::Read( + &message, &sent_message_port_id, &new_routing_id)) { + return; + } + new_routing_id = next_route_id->Run(); MessagePortDispatcher::GetInstance()->UpdateMessagePort( - sent_message_port_ids[i], sender, new_routing_ids[i], next_route_id); - } + sent_message_port_id, sender, new_routing_id, next_route_id); - sender->Send(new WorkerMsg_PostMessage( - route_id, msg, sent_message_port_ids, new_routing_ids)); + // Resend the message with the new routing id. + sender->Send(new WorkerMsg_Connect( + route_id, sent_message_port_id, new_routing_id)); - // Send any queued messages to the sent message ports. We can only do this - // after sending the above message, since it's the one that sets up the - // message port route which the queued messages are sent to. - for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { - MessagePortDispatcher::GetInstance()-> - SendQueuedMessagesIfPossible(sent_message_port_ids[i]); + // Send any queued messages for the sent port. + MessagePortDispatcher::GetInstance()->SendQueuedMessagesIfPossible( + sent_message_port_id); + } else { + IPC::Message* new_message = new IPC::Message(message); + new_message->set_routing_id(route_id); + sender->Send(new_message); + return; } } diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 91fcfab..32ecdb5 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -3306,6 +3306,12 @@ 'renderer/webplugin_delegate_proxy.h', 'renderer/webplugin_delegate_pepper.cc', 'renderer/webplugin_delegate_pepper.h', + 'renderer/websharedworker_impl.cc', + 'renderer/websharedworker_impl.h', + 'renderer/websharedworkerrepository_impl.cc', + 'renderer/websharedworkerrepository_impl.h', + 'renderer/webworker_base.cc', + 'renderer/webworker_base.h', 'renderer/webworker_proxy.cc', 'renderer/webworker_proxy.h', ], diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index cecc9fc6..81f9c1f 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -720,9 +720,9 @@ IPC_BEGIN_MESSAGES(View) IPC_MESSAGE_ROUTED1(ViewMsg_SetActive, bool /* active */) - // Response message to ViewHostMsg_CreateDedicatedWorker. Sent when the - // worker has started. - IPC_MESSAGE_ROUTED0(ViewMsg_DedicatedWorkerCreated) + // Response message to ViewHostMsg_CreateShared/DedicatedWorker. + // Sent when the worker has started. + IPC_MESSAGE_ROUTED0(ViewMsg_WorkerCreated) // Tell the renderer which browser window it's being attached to. IPC_MESSAGE_ROUTED1(ViewMsg_UpdateBrowserWindowId, @@ -1710,6 +1710,16 @@ IPC_BEGIN_MESSAGES(ViewHost) int /* render_view_route_id */, int /* route_id */) + // A renderer sends this to the browser process when it wants to create a + // shared worker. The browser will create the worker process if necessary, + // and will return the route id on success. On error returns + // MSG_ROUTING_NONE. + IPC_SYNC_MESSAGE_CONTROL3_1(ViewHostMsg_CreateSharedWorker, + GURL /* url */, + string16 /* name */, + int /* render_view_route_id */, + int /* route_id */) + // A message sent to the browser on behalf of a renderer which wants to show // a desktop notification. IPC_MESSAGE_ROUTED3(ViewHostMsg_ShowDesktopNotification, @@ -1732,7 +1742,7 @@ IPC_BEGIN_MESSAGES(ViewHost) int /* permission_result */) // Sent if the worker object has sent a ViewHostMsg_CreateDedicatedWorker - // message and not received a ViewMsg_DedicatedWorkerCreated reply, but in the + // message and not received a ViewMsg_WorkerCreated reply, but in the // mean time it's destroyed. This tells the browser to not create the queued // worker. IPC_MESSAGE_CONTROL1(ViewHostMsg_CancelCreateDedicatedWorker, diff --git a/chrome/common/worker_messages_internal.h b/chrome/common/worker_messages_internal.h index 9b1cac2..6ed4d09 100644 --- a/chrome/common/worker_messages_internal.h +++ b/chrome/common/worker_messages_internal.h @@ -94,6 +94,10 @@ IPC_BEGIN_MESSAGES(Worker) std::vector<int> /* sent_message_port_ids */, std::vector<int> /* new_routing_ids */) + IPC_MESSAGE_ROUTED2(WorkerMsg_Connect, + int /* sent_message_port_id */, + int /* routing_id */) + IPC_MESSAGE_ROUTED0(WorkerMsg_WorkerObjectDestroyed) IPC_END_MESSAGES(Worker) diff --git a/chrome/renderer/renderer_webkitclient_impl.cc b/chrome/renderer/renderer_webkitclient_impl.cc index 8203bb5..52d4a24 100644 --- a/chrome/renderer/renderer_webkitclient_impl.cc +++ b/chrome/renderer/renderer_webkitclient_impl.cc @@ -352,6 +352,11 @@ long long RendererWebKitClientImpl::databaseGetFileSize( message_id, 0LL); } +WebKit::WebSharedWorkerRepository* +RendererWebKitClientImpl::sharedWorkerRepository() { + return &shared_worker_repository_; +} + //------------------------------------------------------------------------------ WebKit::WebString RendererWebKitClientImpl::signedPublicKeyAndChallengeString( diff --git a/chrome/renderer/renderer_webkitclient_impl.h b/chrome/renderer/renderer_webkitclient_impl.h index 79e56fc..28056c3 100644 --- a/chrome/renderer/renderer_webkitclient_impl.h +++ b/chrome/renderer/renderer_webkitclient_impl.h @@ -6,6 +6,7 @@ #define CHROME_RENDERER_RENDERER_WEBKIT_CLIENT_IMPL_H_ #include "base/platform_file.h" +#include "chrome/renderer/websharedworkerrepository_impl.h" #include "webkit/glue/simple_webmimeregistry_impl.h" #include "webkit/glue/webclipboard_impl.h" #include "webkit/glue/webkitclient_impl.h" @@ -64,6 +65,8 @@ class RendererWebKitClientImpl : public webkit_glue::WebKitClientImpl { virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost( WebKit::WebApplicationCacheHostClient*); + virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository(); + private: class MimeRegistry : public webkit_glue::SimpleWebMimeRegistryImpl { public: @@ -106,6 +109,11 @@ class RendererWebKitClientImpl : public webkit_glue::WebKitClientImpl { // increments by 1, for every enable decrements by 1. When it reaches 0, // we tell the browser to enable fast termination. int sudden_termination_disables_; + + // Implementation of the WebSharedWorkerRepository APIs (provides an interface + // to WorkerService on the browser thread. + WebSharedWorkerRepositoryImpl shared_worker_repository_; + }; #endif // CHROME_RENDERER_WEBKIT_CLIENT_IMPL_H_ diff --git a/chrome/renderer/websharedworker_impl.cc b/chrome/renderer/websharedworker_impl.cc new file mode 100644 index 0000000..f5e20ce --- /dev/null +++ b/chrome/renderer/websharedworker_impl.cc @@ -0,0 +1,58 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/websharedworker_impl.h" + +#include "chrome/common/render_messages.h" +#include "chrome/common/webmessageportchannel_impl.h" +#include "chrome/common/worker_messages.h" +#include "webkit/api/public/WebURL.h" + +WebSharedWorkerImpl::WebSharedWorkerImpl(const GURL& url, + const string16& name, + ChildThread* child_thread, + int route_id, + int render_view_route_id) + : WebWorkerBase(child_thread, route_id, render_view_route_id), + url_(url), + name_(name) { +} + +bool WebSharedWorkerImpl::isStarted() { + return IsStarted(); +} + +void WebSharedWorkerImpl::startWorkerContext( + const WebKit::WebURL& script_url, + const WebKit::WebString& user_agent, + const WebKit::WebString& source_code) { + DCHECK(url_ == script_url); + IPC::Message* create_message = new ViewHostMsg_CreateSharedWorker( + url_, name_, render_view_route_id_, &route_id_); + CreateWorkerContext(create_message, script_url, user_agent, source_code); +} + +void WebSharedWorkerImpl::connect(WebKit::WebMessagePortChannel* channel) { + WebMessagePortChannelImpl* webchannel = + static_cast<WebMessagePortChannelImpl*>(channel); + + int message_port_id = webchannel->message_port_id(); + DCHECK(message_port_id != MSG_ROUTING_NONE); + webchannel->QueueMessages(); + + Send(new WorkerMsg_Connect(route_id_, message_port_id, MSG_ROUTING_NONE)); +} + +void WebSharedWorkerImpl::OnMessageReceived(const IPC::Message& message) { + IPC_BEGIN_MESSAGE_MAP(WebSharedWorkerImpl, message) + IPC_MESSAGE_HANDLER(ViewMsg_WorkerCreated, OnWorkerCreated) + IPC_END_MESSAGE_MAP() +} + +void WebSharedWorkerImpl::OnWorkerCreated() { + // The worker is created - now send off the CreateWorkerContext message and + // any other queued messages + SendQueuedMessages(); +} + diff --git a/chrome/renderer/websharedworker_impl.h b/chrome/renderer/websharedworker_impl.h new file mode 100644 index 0000000..14d122d89 --- /dev/null +++ b/chrome/renderer/websharedworker_impl.h @@ -0,0 +1,49 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_WEBSHAREDWORKER_IMPL_H_ +#define CHROME_RENDERER_WEBSHAREDWORKER_IMPL_H_ + +#include "base/basictypes.h" +#include "chrome/renderer/webworker_base.h" +#include "googleurl/src/gurl.h" +#include "webkit/api/public/WebSharedWorker.h" + +class ChildThread; + +// Implementation of the WebSharedWorker APIs. This object is intended to only +// live long enough to allow the caller to send a "connect" event to the worker +// thread. Once the connect event has been sent, all future communication will +// happen via the WebMessagePortChannel, and the WebSharedWorker instance will +// be freed. +class WebSharedWorkerImpl : public WebKit::WebSharedWorker, + private WebWorkerBase { + public: + WebSharedWorkerImpl(const GURL& url, + const string16& name, + ChildThread* child_thread, + int route_id, + int render_view_route_id); + + // Implementations of WebSharedWorker APIs + virtual bool isStarted(); + virtual void connect(WebKit::WebMessagePortChannel* channel); + virtual void startWorkerContext(const WebKit::WebURL& script_url, + const WebKit::WebString& user_agent, + const WebKit::WebString& source_code); + + // IPC::Channel::Listener implementation. + void OnMessageReceived(const IPC::Message& message); + + private: + void OnWorkerCreated(); + + // The name and URL that uniquely identify this worker. + GURL url_; + string16 name_; + + DISALLOW_COPY_AND_ASSIGN(WebSharedWorkerImpl); +}; + +#endif // CHROME_RENDERER_WEBSHAREDWORKER_IMPL_H_ diff --git a/chrome/renderer/websharedworkerrepository_impl.cc b/chrome/renderer/websharedworkerrepository_impl.cc new file mode 100644 index 0000000..15aea07 --- /dev/null +++ b/chrome/renderer/websharedworkerrepository_impl.cc @@ -0,0 +1,24 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in the +// LICENSE file. + +#include "chrome/renderer/websharedworkerrepository_impl.h" + +WebKit::WebSharedWorker* WebSharedWorkerRepositoryImpl::lookup( + const WebKit::WebURL& url, + const WebKit::WebString& name, + DocumentID document) { + return NULL; +} + +void WebSharedWorkerRepositoryImpl::documentDetached( + DocumentID document) { + // TODO(atwilson): Update this to call to WorkerService to shutdown any + // associated SharedWorkers. +} + +bool WebSharedWorkerRepositoryImpl::hasSharedWorkers( + DocumentID document) { + // TODO(atwilson): Update this when we track shared worker creation. + return false; +} diff --git a/chrome/renderer/websharedworkerrepository_impl.h b/chrome/renderer/websharedworkerrepository_impl.h new file mode 100644 index 0000000..bf6369c --- /dev/null +++ b/chrome/renderer/websharedworkerrepository_impl.h @@ -0,0 +1,22 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in the +// LICENSE file. + +#ifndef CHROME_RENDERER_WEB_SHARED_WORKER_REPOSITORY_IMPL_H_ +#define CHROME_RENDERER_WEB_SHARED_WORKER_REPOSITORY_IMPL_H_ + +#include "webkit/api/public/WebSharedWorkerRepository.h" + +class WebKit::WebSharedWorker; + +class WebSharedWorkerRepositoryImpl : public WebKit::WebSharedWorkerRepository { + virtual WebKit::WebSharedWorker* lookup(const WebKit::WebURL& url, + const WebKit::WebString& name, + DocumentID document); + + virtual void documentDetached(DocumentID document); + + virtual bool hasSharedWorkers(DocumentID document); +}; + +#endif // CHROME_RENDERER_WEB_SHARED_WORKER_REPOSITORY_IMPL_H_ diff --git a/chrome/renderer/webworker_base.cc b/chrome/renderer/webworker_base.cc new file mode 100644 index 0000000..98365cd --- /dev/null +++ b/chrome/renderer/webworker_base.cc @@ -0,0 +1,102 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/webworker_base.h" + +#include "chrome/common/child_thread.h" +#include "chrome/common/render_messages.h" +#include "chrome/common/webmessageportchannel_impl.h" +#include "chrome/common/worker_messages.h" +#include "webkit/api/public/WebURL.h" +#include "webkit/api/public/WebWorkerClient.h" + +using WebKit::WebMessagePortChannel; +using WebKit::WebMessagePortChannelArray; +using WebKit::WebString; +using WebKit::WebURL; +using WebKit::WebWorkerClient; + +WebWorkerBase::WebWorkerBase( + ChildThread* child_thread, + int route_id, + int render_view_route_id) + : route_id_(route_id), + render_view_route_id_(render_view_route_id), + child_thread_(child_thread) { + if (route_id_ != MSG_ROUTING_NONE) + child_thread_->AddRoute(route_id_, this); +} + +WebWorkerBase::~WebWorkerBase() { + Disconnect(); + + // Free up any unsent queued messages. + for (size_t i = 0; i < queued_messages_.size(); ++i) + delete queued_messages_[i]; +} + +void WebWorkerBase::Disconnect() { + if (route_id_ == MSG_ROUTING_NONE) + return; + + // So the messages from WorkerContext (like WorkerContextDestroyed) do not + // come after nobody is listening. Since Worker and WorkerContext can + // terminate independently, already sent messages may still be in the pipe. + child_thread_->RemoveRoute(route_id_); + + route_id_ = MSG_ROUTING_NONE; +} + +void WebWorkerBase::CreateWorkerContext(IPC::Message* create_message, + const GURL& script_url, + const string16& user_agent, + const string16& source_code) { + DCHECK(route_id_ == MSG_ROUTING_NONE); + // create_message is a sync message that sets route_id_ + child_thread_->Send(create_message); + if (route_id_ == MSG_ROUTING_NONE) + return; + + child_thread_->AddRoute(route_id_, this); + + // We make sure that the start message is the first, since postMessage or + // connect might have already been called. + queued_messages_.insert(queued_messages_.begin(), + new WorkerMsg_StartWorkerContext( + route_id_, script_url, user_agent, source_code)); +} + +bool WebWorkerBase::IsStarted() { + // Worker is started if we have a route ID and there are no queued messages + // (meaning we've sent the WorkerMsg_StartWorkerContext already). + return (route_id_ != MSG_ROUTING_NONE && queued_messages_.empty()); +} + +bool WebWorkerBase::Send(IPC::Message* message) { + // It's possible that messages will be sent before the worker is created, in + // which case route_id_ will be none. Or the worker object can be interacted + // with before the browser process told us that it started, in which case we + // also want to queue the message. + if (!IsStarted()) { + queued_messages_.push_back(message); + return true; + } + + // For now we proxy all messages to the worker process through the browser. + // Revisit if we find this slow. + // TODO(jabdelmalek): handle sync messages if we need them. + IPC::Message* wrapped_msg = new ViewHostMsg_ForwardToWorker(*message); + delete message; + return child_thread_->Send(wrapped_msg); +} + +void WebWorkerBase::SendQueuedMessages() { + DCHECK(queued_messages_.size()); + std::vector<IPC::Message*> queued_messages = queued_messages_; + queued_messages_.clear(); + for (size_t i = 0; i < queued_messages.size(); ++i) { + queued_messages[i]->set_routing_id(route_id_); + Send(queued_messages[i]); + } +} diff --git a/chrome/renderer/webworker_base.h b/chrome/renderer/webworker_base.h new file mode 100644 index 0000000..c7c6c62 --- /dev/null +++ b/chrome/renderer/webworker_base.h @@ -0,0 +1,64 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_WEBWORKER_BASE_H_ +#define CHROME_RENDERER_WEBWORKER_BASE_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "ipc/ipc_channel.h" + +class ChildThread; +class GURL; + +// WebWorkerBase is the common base class used by both WebWorkerProxy and +// WebSharedWorker. It contains logic to support starting up both dedicated +// and shared workers, and handling message queueing while waiting for the +// worker process to start. +class WebWorkerBase : public IPC::Channel::Listener { + public: + WebWorkerBase(ChildThread* child_thread, + int route_id, + int render_view_route_id); + + virtual ~WebWorkerBase(); + + // Creates and initializes a new worker context. + void CreateWorkerContext(IPC::Message* create_message, + const GURL& script_url, + const string16& user_agent, + const string16& source_code); + + // Returns true if the worker is running (can send messages to it). + bool IsStarted(); + + // Disconnects the worker (stops listening for incoming messages). + virtual void Disconnect(); + + // Sends a message to the worker thread (forwarded via the RenderViewHost). + // If WorkerStarted() has not yet been called, message is queued. + bool Send(IPC::Message*); + + // Sends any messages currently in the queue. + void SendQueuedMessages(); + + protected: + // Routing id associated with this worker - used to receive messages from the + // worker, and also to route messages to the worker (WorkerService contains + // a map that maps between these renderer-side route IDs and worker-side + // routing ids). + int route_id_; + + // The routing id for the RenderView that created this worker. + int render_view_route_id_; + + ChildThread* child_thread_; + + private: + // Stores messages that were sent before the StartWorkerContext message. + std::vector<IPC::Message*> queued_messages_; +}; + +#endif // CHROME_RENDERER_WEBWORKER_BASE_H_ diff --git a/chrome/renderer/webworker_proxy.cc b/chrome/renderer/webworker_proxy.cc index 3932d6e..5a24c41 100644 --- a/chrome/renderer/webworker_proxy.cc +++ b/chrome/renderer/webworker_proxy.cc @@ -21,51 +21,29 @@ WebWorkerProxy::WebWorkerProxy( WebWorkerClient* client, ChildThread* child_thread, int render_view_route_id) - : route_id_(MSG_ROUTING_NONE), - child_thread_(child_thread), - render_view_route_id_(render_view_route_id), + : WebWorkerBase(child_thread, MSG_ROUTING_NONE, render_view_route_id), client_(client) { } -WebWorkerProxy::~WebWorkerProxy() { - Disconnect(); - - for (size_t i = 0; i < queued_messages_.size(); ++i) - delete queued_messages_[i]; -} - void WebWorkerProxy::Disconnect() { if (route_id_ == MSG_ROUTING_NONE) return; - // So the messages from WorkerContext (like WorkerContextDestroyed) do not - // come after nobody is listening. Since Worker and WorkerContext can - // terminate independently, already sent messages may still be in the pipe. - child_thread_->RemoveRoute(route_id_); - // Tell the browser to not start our queued worker. - if (!queued_messages_.empty()) + if (!IsStarted()) child_thread_->Send(new ViewHostMsg_CancelCreateDedicatedWorker(route_id_)); - route_id_ = MSG_ROUTING_NONE; + // Call our superclass to shutdown the routing + WebWorkerBase::Disconnect(); } void WebWorkerProxy::startWorkerContext( const WebURL& script_url, const WebString& user_agent, const WebString& source_code) { - child_thread_->Send(new ViewHostMsg_CreateDedicatedWorker( - script_url, render_view_route_id_, &route_id_)); - if (route_id_ == MSG_ROUTING_NONE) - return; - - child_thread_->AddRoute(route_id_, this); - - // We make sure that the start message is the first, since postMessage might - // have already been called. - queued_messages_.insert(queued_messages_.begin(), - new WorkerMsg_StartWorkerContext( - route_id_, script_url, user_agent, source_code)); + IPC::Message* create_message = new ViewHostMsg_CreateDedicatedWorker( + script_url, render_view_route_id_, &route_id_); + CreateWorkerContext(create_message, script_url, user_agent, source_code); } void WebWorkerProxy::terminateWorkerContext() { @@ -100,31 +78,12 @@ void WebWorkerProxy::workerObjectDestroyed() { void WebWorkerProxy::clientDestroyed() { } -bool WebWorkerProxy::Send(IPC::Message* message) { - // It's possible that postMessage is called before the worker is created, in - // which case route_id_ will be none. Or the worker object can be interacted - // with before the browser process told us that it started, in which case we - // also want to queue the message. - if (route_id_ == MSG_ROUTING_NONE || !queued_messages_.empty()) { - queued_messages_.push_back(message); - return true; - } - - // For now we proxy all messages to the worker process through the browser. - // Revisit if we find this slow. - // TODO(jabdelmalek): handle sync messages if we need them. - IPC::Message* wrapped_msg = new ViewHostMsg_ForwardToWorker(*message); - delete message; - return child_thread_->Send(wrapped_msg); -} - void WebWorkerProxy::OnMessageReceived(const IPC::Message& message) { if (!client_) return; IPC_BEGIN_MESSAGE_MAP(WebWorkerProxy, message) - IPC_MESSAGE_HANDLER(ViewMsg_DedicatedWorkerCreated, - OnDedicatedWorkerCreated) + IPC_MESSAGE_HANDLER(ViewMsg_WorkerCreated, OnWorkerCreated) IPC_MESSAGE_HANDLER(WorkerMsg_PostMessage, OnPostMessage) IPC_MESSAGE_FORWARD(WorkerHostMsg_PostExceptionToWorkerObject, client_, @@ -143,14 +102,10 @@ void WebWorkerProxy::OnMessageReceived(const IPC::Message& message) { IPC_END_MESSAGE_MAP() } -void WebWorkerProxy::OnDedicatedWorkerCreated() { - DCHECK(queued_messages_.size()); - std::vector<IPC::Message*> queued_messages = queued_messages_; - queued_messages_.clear(); - for (size_t i = 0; i < queued_messages.size(); ++i) { - queued_messages[i]->set_routing_id(route_id_); - Send(queued_messages[i]); - } +void WebWorkerProxy::OnWorkerCreated() { + // The worker is created - now send off the CreateWorkerContext message and + // any other queued messages + SendQueuedMessages(); } void WebWorkerProxy::OnPostMessage( diff --git a/chrome/renderer/webworker_proxy.h b/chrome/renderer/webworker_proxy.h index 8c53a67..686669a 100644 --- a/chrome/renderer/webworker_proxy.h +++ b/chrome/renderer/webworker_proxy.h @@ -8,6 +8,7 @@ #include <vector> #include "base/basictypes.h" +#include "chrome/renderer/webworker_base.h" #include "ipc/ipc_channel.h" #include "webkit/api/public/WebWorker.h" @@ -21,13 +22,11 @@ struct WorkerHostMsg_PostConsoleMessageToWorkerObject_Params; // dispatched in the worker process by WebWorkerClientProxy. It also receives // IPC messages from WebWorkerClientProxy which it converts to function calls to // WebWorkerClient. -class WebWorkerProxy : public WebKit::WebWorker, - public IPC::Channel::Listener { +class WebWorkerProxy : public WebKit::WebWorker, private WebWorkerBase { public: WebWorkerProxy(WebKit::WebWorkerClient* client, ChildThread* child_thread, int render_view_route_id); - virtual ~WebWorkerProxy(); // WebWorker implementation. virtual void startWorkerContext(const WebKit::WebURL& script_url, @@ -44,32 +43,20 @@ class WebWorkerProxy : public WebKit::WebWorker, void OnMessageReceived(const IPC::Message& message); private: - bool Send(IPC::Message* message); + virtual void Disconnect(); - void OnDedicatedWorkerCreated(); + void OnWorkerCreated(); void OnPostMessage(const string16& message, const std::vector<int>& sent_message_port_ids, const std::vector<int>& new_routing_ids); void OnPostConsoleMessageToWorkerObject( const WorkerHostMsg_PostConsoleMessageToWorkerObject_Params& params); - void Disconnect(); - - // The routing id used to reach WebWorkerClientProxy in the worker process. - int route_id_; - - ChildThread* child_thread_; - - // The routing id for the RenderView that created this worker. - int render_view_route_id_; // Used to communicate to the WebCore::Worker object in response to IPC // messages. WebKit::WebWorkerClient* client_; - // Stores messages that were sent before the StartWorkerContext message. - std::vector<IPC::Message*> queued_messages_; - DISALLOW_COPY_AND_ASSIGN(WebWorkerProxy); }; diff --git a/chrome/worker/worker_webkitclient_impl.cc b/chrome/worker/worker_webkitclient_impl.cc index 2d60954..fdb20f3 100644 --- a/chrome/worker/worker_webkitclient_impl.cc +++ b/chrome/worker/worker_webkitclient_impl.cc @@ -74,3 +74,8 @@ WebKit::WebString WorkerWebKitClientImpl::defaultLocale() { NOTREACHED(); return WebKit::WebString(); } + +WebKit::WebSharedWorkerRepository* +WorkerWebKitClientImpl::sharedWorkerRepository() { + return 0; +} diff --git a/chrome/worker/worker_webkitclient_impl.h b/chrome/worker/worker_webkitclient_impl.h index a9ccb36..c89f0fa 100644 --- a/chrome/worker/worker_webkitclient_impl.h +++ b/chrome/worker/worker_webkitclient_impl.h @@ -26,6 +26,7 @@ class WorkerWebKitClientImpl : public webkit_glue::WebKitClientImpl { virtual void prefetchHostName(const WebKit::WebString&); virtual bool getFileSize(const WebKit::WebString& path, long long& result); virtual WebKit::WebString defaultLocale(); + virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository(); }; #endif // CHROME_WORKER_WORKER_WEBKIT_CLIENT_IMPL_H_ |