Skip to content
Snippets Groups Projects
Commit ab350536 authored by atwilson@chromium.org's avatar atwilson@chromium.org
Browse files

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
parent 06b9e3b7
No related branches found
No related tags found
No related merge requests found
Showing
with 499 additions and 107 deletions
...@@ -123,3 +123,9 @@ void BrowserWebKitClientImpl::dispatchStorageEvent( ...@@ -123,3 +123,9 @@ void BrowserWebKitClientImpl::dispatchStorageEvent(
DOMStorageDispatcherHost::DispatchStorageEvent(key, old_value, new_value, DOMStorageDispatcherHost::DispatchStorageEvent(key, old_value, new_value,
origin, is_local_storage); origin, is_local_storage);
} }
WebKit::WebSharedWorkerRepository*
BrowserWebKitClientImpl::sharedWorkerRepository() {
NOTREACHED();
return NULL;
}
...@@ -36,6 +36,7 @@ class BrowserWebKitClientImpl : public webkit_glue::WebKitClientImpl { ...@@ -36,6 +36,7 @@ class BrowserWebKitClientImpl : public webkit_glue::WebKitClientImpl {
virtual void dispatchStorageEvent(const WebKit::WebString& key, virtual void dispatchStorageEvent(const WebKit::WebString& key,
const WebKit::WebString& oldValue, const WebKit::WebString& newValue, const WebKit::WebString& oldValue, const WebKit::WebString& newValue,
const WebKit::WebString& origin, bool isLocalStorage); const WebKit::WebString& origin, bool isLocalStorage);
virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository();
}; };
#endif // CHROME_BROWSER_IN_PROCESS_WEBKIT_WEBKIT_CLIENT_IMPL_H_ #endif // CHROME_BROWSER_IN_PROCESS_WEBKIT_WEBKIT_CLIENT_IMPL_H_
...@@ -144,7 +144,7 @@ void WorkerProcessHost::CreateWorker(const WorkerInstance& instance) { ...@@ -144,7 +144,7 @@ void WorkerProcessHost::CreateWorker(const WorkerInstance& instance) {
UpdateTitle(); UpdateTitle();
instances_.back().sender->Send( 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, bool WorkerProcessHost::FilterMessage(const IPC::Message& message,
...@@ -229,39 +229,59 @@ void WorkerProcessHost::RelayMessage( ...@@ -229,39 +229,59 @@ void WorkerProcessHost::RelayMessage(
IPC::Message::Sender* sender, IPC::Message::Sender* sender,
int route_id, int route_id,
CallbackWithReturnValue<int>::Type* next_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 if (message.type() == WorkerMsg_PostMessage::ID) {
// crack the message first. // We want to send the receiver a routing id for the new channel, so
string16 msg; // crack the message first.
std::vector<int> sent_message_port_ids; string16 msg;
std::vector<int> new_routing_ids; std::vector<int> sent_message_port_ids;
if (!WorkerMsg_PostMessage::Read( std::vector<int> new_routing_ids;
&message, &msg, &sent_message_port_ids, &new_routing_ids)) { if (!WorkerMsg_PostMessage::Read(
return; &message, &msg, &sent_message_port_ids, &new_routing_ids)) {
} return;
DCHECK(sent_message_port_ids.size() == new_routing_ids.size()); }
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) { // Send any queued messages to the sent message ports. We can only do this
new_routing_ids[i] = next_route_id->Run(); // 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( 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( // Resend the message with the new routing id.
route_id, msg, sent_message_port_ids, new_routing_ids)); 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 // Send any queued messages for the sent port.
// after sending the above message, since it's the one that sets up the MessagePortDispatcher::GetInstance()->SendQueuedMessagesIfPossible(
// message port route which the queued messages are sent to. sent_message_port_id);
for (size_t i = 0; i < sent_message_port_ids.size(); ++i) { } else {
MessagePortDispatcher::GetInstance()-> IPC::Message* new_message = new IPC::Message(message);
SendQueuedMessagesIfPossible(sent_message_port_ids[i]); new_message->set_routing_id(route_id);
sender->Send(new_message);
return;
} }
} }
......
...@@ -3306,6 +3306,12 @@ ...@@ -3306,6 +3306,12 @@
'renderer/webplugin_delegate_proxy.h', 'renderer/webplugin_delegate_proxy.h',
'renderer/webplugin_delegate_pepper.cc', 'renderer/webplugin_delegate_pepper.cc',
'renderer/webplugin_delegate_pepper.h', '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.cc',
'renderer/webworker_proxy.h', 'renderer/webworker_proxy.h',
], ],
......
...@@ -720,9 +720,9 @@ IPC_BEGIN_MESSAGES(View) ...@@ -720,9 +720,9 @@ IPC_BEGIN_MESSAGES(View)
IPC_MESSAGE_ROUTED1(ViewMsg_SetActive, IPC_MESSAGE_ROUTED1(ViewMsg_SetActive,
bool /* active */) bool /* active */)
// Response message to ViewHostMsg_CreateDedicatedWorker. Sent when the // Response message to ViewHostMsg_CreateShared/DedicatedWorker.
// worker has started. // Sent when the worker has started.
IPC_MESSAGE_ROUTED0(ViewMsg_DedicatedWorkerCreated) IPC_MESSAGE_ROUTED0(ViewMsg_WorkerCreated)
// Tell the renderer which browser window it's being attached to. // Tell the renderer which browser window it's being attached to.
IPC_MESSAGE_ROUTED1(ViewMsg_UpdateBrowserWindowId, IPC_MESSAGE_ROUTED1(ViewMsg_UpdateBrowserWindowId,
...@@ -1710,6 +1710,16 @@ IPC_BEGIN_MESSAGES(ViewHost) ...@@ -1710,6 +1710,16 @@ IPC_BEGIN_MESSAGES(ViewHost)
int /* render_view_route_id */, int /* render_view_route_id */,
int /* 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 message sent to the browser on behalf of a renderer which wants to show
// a desktop notification. // a desktop notification.
IPC_MESSAGE_ROUTED3(ViewHostMsg_ShowDesktopNotification, IPC_MESSAGE_ROUTED3(ViewHostMsg_ShowDesktopNotification,
...@@ -1732,7 +1742,7 @@ IPC_BEGIN_MESSAGES(ViewHost) ...@@ -1732,7 +1742,7 @@ IPC_BEGIN_MESSAGES(ViewHost)
int /* permission_result */) int /* permission_result */)
// Sent if the worker object has sent a ViewHostMsg_CreateDedicatedWorker // 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 // mean time it's destroyed. This tells the browser to not create the queued
// worker. // worker.
IPC_MESSAGE_CONTROL1(ViewHostMsg_CancelCreateDedicatedWorker, IPC_MESSAGE_CONTROL1(ViewHostMsg_CancelCreateDedicatedWorker,
......
...@@ -94,6 +94,10 @@ IPC_BEGIN_MESSAGES(Worker) ...@@ -94,6 +94,10 @@ IPC_BEGIN_MESSAGES(Worker)
std::vector<int> /* sent_message_port_ids */, std::vector<int> /* sent_message_port_ids */,
std::vector<int> /* new_routing_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_MESSAGE_ROUTED0(WorkerMsg_WorkerObjectDestroyed)
IPC_END_MESSAGES(Worker) IPC_END_MESSAGES(Worker)
......
...@@ -352,6 +352,11 @@ long long RendererWebKitClientImpl::databaseGetFileSize( ...@@ -352,6 +352,11 @@ long long RendererWebKitClientImpl::databaseGetFileSize(
message_id, 0LL); message_id, 0LL);
} }
WebKit::WebSharedWorkerRepository*
RendererWebKitClientImpl::sharedWorkerRepository() {
return &shared_worker_repository_;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
WebKit::WebString RendererWebKitClientImpl::signedPublicKeyAndChallengeString( WebKit::WebString RendererWebKitClientImpl::signedPublicKeyAndChallengeString(
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define CHROME_RENDERER_RENDERER_WEBKIT_CLIENT_IMPL_H_ #define CHROME_RENDERER_RENDERER_WEBKIT_CLIENT_IMPL_H_
#include "base/platform_file.h" #include "base/platform_file.h"
#include "chrome/renderer/websharedworkerrepository_impl.h"
#include "webkit/glue/simple_webmimeregistry_impl.h" #include "webkit/glue/simple_webmimeregistry_impl.h"
#include "webkit/glue/webclipboard_impl.h" #include "webkit/glue/webclipboard_impl.h"
#include "webkit/glue/webkitclient_impl.h" #include "webkit/glue/webkitclient_impl.h"
...@@ -64,6 +65,8 @@ class RendererWebKitClientImpl : public webkit_glue::WebKitClientImpl { ...@@ -64,6 +65,8 @@ class RendererWebKitClientImpl : public webkit_glue::WebKitClientImpl {
virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost( virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost(
WebKit::WebApplicationCacheHostClient*); WebKit::WebApplicationCacheHostClient*);
virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository();
private: private:
class MimeRegistry : public webkit_glue::SimpleWebMimeRegistryImpl { class MimeRegistry : public webkit_glue::SimpleWebMimeRegistryImpl {
public: public:
...@@ -106,6 +109,11 @@ class RendererWebKitClientImpl : public webkit_glue::WebKitClientImpl { ...@@ -106,6 +109,11 @@ class RendererWebKitClientImpl : public webkit_glue::WebKitClientImpl {
// increments by 1, for every enable decrements by 1. When it reaches 0, // increments by 1, for every enable decrements by 1. When it reaches 0,
// we tell the browser to enable fast termination. // we tell the browser to enable fast termination.
int sudden_termination_disables_; 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_ #endif // CHROME_RENDERER_WEBKIT_CLIENT_IMPL_H_
// 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();
}
// 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_
// 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;
}
// 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_
// 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]);
}
}
// 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_
...@@ -21,51 +21,29 @@ WebWorkerProxy::WebWorkerProxy( ...@@ -21,51 +21,29 @@ WebWorkerProxy::WebWorkerProxy(
WebWorkerClient* client, WebWorkerClient* client,
ChildThread* child_thread, ChildThread* child_thread,
int render_view_route_id) int render_view_route_id)
: route_id_(MSG_ROUTING_NONE), : WebWorkerBase(child_thread, MSG_ROUTING_NONE, render_view_route_id),
child_thread_(child_thread),
render_view_route_id_(render_view_route_id),
client_(client) { client_(client) {
} }
WebWorkerProxy::~WebWorkerProxy() {
Disconnect();
for (size_t i = 0; i < queued_messages_.size(); ++i)
delete queued_messages_[i];
}
void WebWorkerProxy::Disconnect() { void WebWorkerProxy::Disconnect() {
if (route_id_ == MSG_ROUTING_NONE) if (route_id_ == MSG_ROUTING_NONE)
return; 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. // Tell the browser to not start our queued worker.
if (!queued_messages_.empty()) if (!IsStarted())
child_thread_->Send(new ViewHostMsg_CancelCreateDedicatedWorker(route_id_)); 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( void WebWorkerProxy::startWorkerContext(
const WebURL& script_url, const WebURL& script_url,
const WebString& user_agent, const WebString& user_agent,
const WebString& source_code) { const WebString& source_code) {
child_thread_->Send(new ViewHostMsg_CreateDedicatedWorker( IPC::Message* create_message = new ViewHostMsg_CreateDedicatedWorker(
script_url, render_view_route_id_, &route_id_)); script_url, render_view_route_id_, &route_id_);
if (route_id_ == MSG_ROUTING_NONE) CreateWorkerContext(create_message, script_url, user_agent, source_code);
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));
} }
void WebWorkerProxy::terminateWorkerContext() { void WebWorkerProxy::terminateWorkerContext() {
...@@ -100,31 +78,12 @@ void WebWorkerProxy::workerObjectDestroyed() { ...@@ -100,31 +78,12 @@ void WebWorkerProxy::workerObjectDestroyed() {
void WebWorkerProxy::clientDestroyed() { 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) { void WebWorkerProxy::OnMessageReceived(const IPC::Message& message) {
if (!client_) if (!client_)
return; return;
IPC_BEGIN_MESSAGE_MAP(WebWorkerProxy, message) IPC_BEGIN_MESSAGE_MAP(WebWorkerProxy, message)
IPC_MESSAGE_HANDLER(ViewMsg_DedicatedWorkerCreated, IPC_MESSAGE_HANDLER(ViewMsg_WorkerCreated, OnWorkerCreated)
OnDedicatedWorkerCreated)
IPC_MESSAGE_HANDLER(WorkerMsg_PostMessage, OnPostMessage) IPC_MESSAGE_HANDLER(WorkerMsg_PostMessage, OnPostMessage)
IPC_MESSAGE_FORWARD(WorkerHostMsg_PostExceptionToWorkerObject, IPC_MESSAGE_FORWARD(WorkerHostMsg_PostExceptionToWorkerObject,
client_, client_,
...@@ -143,14 +102,10 @@ void WebWorkerProxy::OnMessageReceived(const IPC::Message& message) { ...@@ -143,14 +102,10 @@ void WebWorkerProxy::OnMessageReceived(const IPC::Message& message) {
IPC_END_MESSAGE_MAP() IPC_END_MESSAGE_MAP()
} }
void WebWorkerProxy::OnDedicatedWorkerCreated() { void WebWorkerProxy::OnWorkerCreated() {
DCHECK(queued_messages_.size()); // The worker is created - now send off the CreateWorkerContext message and
std::vector<IPC::Message*> queued_messages = queued_messages_; // any other queued messages
queued_messages_.clear(); SendQueuedMessages();
for (size_t i = 0; i < queued_messages.size(); ++i) {
queued_messages[i]->set_routing_id(route_id_);
Send(queued_messages[i]);
}
} }
void WebWorkerProxy::OnPostMessage( void WebWorkerProxy::OnPostMessage(
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <vector> #include <vector>
#include "base/basictypes.h" #include "base/basictypes.h"
#include "chrome/renderer/webworker_base.h"
#include "ipc/ipc_channel.h" #include "ipc/ipc_channel.h"
#include "webkit/api/public/WebWorker.h" #include "webkit/api/public/WebWorker.h"
...@@ -21,13 +22,11 @@ struct WorkerHostMsg_PostConsoleMessageToWorkerObject_Params; ...@@ -21,13 +22,11 @@ struct WorkerHostMsg_PostConsoleMessageToWorkerObject_Params;
// dispatched in the worker process by WebWorkerClientProxy. It also receives // dispatched in the worker process by WebWorkerClientProxy. It also receives
// IPC messages from WebWorkerClientProxy which it converts to function calls to // IPC messages from WebWorkerClientProxy which it converts to function calls to
// WebWorkerClient. // WebWorkerClient.
class WebWorkerProxy : public WebKit::WebWorker, class WebWorkerProxy : public WebKit::WebWorker, private WebWorkerBase {
public IPC::Channel::Listener {
public: public:
WebWorkerProxy(WebKit::WebWorkerClient* client, WebWorkerProxy(WebKit::WebWorkerClient* client,
ChildThread* child_thread, ChildThread* child_thread,
int render_view_route_id); int render_view_route_id);
virtual ~WebWorkerProxy();
// WebWorker implementation. // WebWorker implementation.
virtual void startWorkerContext(const WebKit::WebURL& script_url, virtual void startWorkerContext(const WebKit::WebURL& script_url,
...@@ -44,32 +43,20 @@ class WebWorkerProxy : public WebKit::WebWorker, ...@@ -44,32 +43,20 @@ class WebWorkerProxy : public WebKit::WebWorker,
void OnMessageReceived(const IPC::Message& message); void OnMessageReceived(const IPC::Message& message);
private: private:
bool Send(IPC::Message* message); virtual void Disconnect();
void OnDedicatedWorkerCreated(); void OnWorkerCreated();
void OnPostMessage(const string16& message, void OnPostMessage(const string16& message,
const std::vector<int>& sent_message_port_ids, const std::vector<int>& sent_message_port_ids,
const std::vector<int>& new_routing_ids); const std::vector<int>& new_routing_ids);
void OnPostConsoleMessageToWorkerObject( void OnPostConsoleMessageToWorkerObject(
const WorkerHostMsg_PostConsoleMessageToWorkerObject_Params& params); 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 // Used to communicate to the WebCore::Worker object in response to IPC
// messages. // messages.
WebKit::WebWorkerClient* client_; WebKit::WebWorkerClient* client_;
// Stores messages that were sent before the StartWorkerContext message.
std::vector<IPC::Message*> queued_messages_;
DISALLOW_COPY_AND_ASSIGN(WebWorkerProxy); DISALLOW_COPY_AND_ASSIGN(WebWorkerProxy);
}; };
......
...@@ -74,3 +74,8 @@ WebKit::WebString WorkerWebKitClientImpl::defaultLocale() { ...@@ -74,3 +74,8 @@ WebKit::WebString WorkerWebKitClientImpl::defaultLocale() {
NOTREACHED(); NOTREACHED();
return WebKit::WebString(); return WebKit::WebString();
} }
WebKit::WebSharedWorkerRepository*
WorkerWebKitClientImpl::sharedWorkerRepository() {
return 0;
}
...@@ -26,6 +26,7 @@ class WorkerWebKitClientImpl : public webkit_glue::WebKitClientImpl { ...@@ -26,6 +26,7 @@ class WorkerWebKitClientImpl : public webkit_glue::WebKitClientImpl {
virtual void prefetchHostName(const WebKit::WebString&); virtual void prefetchHostName(const WebKit::WebString&);
virtual bool getFileSize(const WebKit::WebString& path, long long& result); virtual bool getFileSize(const WebKit::WebString& path, long long& result);
virtual WebKit::WebString defaultLocale(); virtual WebKit::WebString defaultLocale();
virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository();
}; };
#endif // CHROME_WORKER_WORKER_WEBKIT_CLIENT_IMPL_H_ #endif // CHROME_WORKER_WORKER_WEBKIT_CLIENT_IMPL_H_
...@@ -51,6 +51,7 @@ namespace WebKit { ...@@ -51,6 +51,7 @@ namespace WebKit {
class WebMimeRegistry; class WebMimeRegistry;
class WebPluginListBuilder; class WebPluginListBuilder;
class WebSandboxSupport; class WebSandboxSupport;
class WebSharedWorkerRepository;
class WebSocketStreamHandle; class WebSocketStreamHandle;
class WebStorageNamespace; class WebStorageNamespace;
class WebString; class WebString;
...@@ -224,6 +225,8 @@ namespace WebKit { ...@@ -224,6 +225,8 @@ namespace WebKit {
// sandbox isn't active). // sandbox isn't active).
virtual bool sandboxEnabled() = 0; virtual bool sandboxEnabled() = 0;
// Shared Workers ------------------------------------------------------
virtual WebSharedWorkerRepository* sharedWorkerRepository() = 0;
// Sudden Termination -------------------------------------------------- // Sudden Termination --------------------------------------------------
......
/*
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WebSharedWorker_h
#define WebSharedWorker_h
#include "WebCommon.h"
#include "WebVector.h"
namespace WebKit {
class ScriptExecutionContext;
class WebString;
class WebMessagePortChannel;
class WebURL;
// This is the interface to a SharedWorker thread.
// Since SharedWorkers communicate entirely through MessagePorts this interface only contains APIs for starting up a SharedWorker.
class WebSharedWorker {
public:
virtual ~WebSharedWorker() {};
// Returns false if the thread hasn't been started yet (script loading has not taken place).
// TODO(atwilson): Remove this when we move the initial script loading into the worker process.
virtual bool isStarted() = 0;
virtual void startWorkerContext(const WebURL& scriptURL,
const WebString& userAgent,
const WebString& sourceCode) = 0;
// Sends a connect event to the SharedWorker thread.
virtual void connect(WebMessagePortChannel*) = 0;
};
} // namespace WebKit
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment