diff options
33 files changed, 1310 insertions, 60 deletions
@@ -59,6 +59,8 @@ deps = { # TODO(jianli): Remove this once we do not need to run worker's layout tests # in ui test. + "src/chrome/test/data/workers/LayoutTests/fast/events": + Var("webkit_trunk") + "/LayoutTests/fast/events@" + Var("webkit_revision"), "src/chrome/test/data/workers/LayoutTests/fast/workers": Var("webkit_trunk") + "/LayoutTests/fast/workers@" + Var("webkit_revision"), "src/chrome/test/data/workers/LayoutTests/http/tests/resources": diff --git a/base/ref_counted.h b/base/ref_counted.h index 013bd66..79f9f55 100644 --- a/base/ref_counted.h +++ b/base/ref_counted.h @@ -200,6 +200,17 @@ class scoped_refptr { operator T*() const { return ptr_; } T* operator->() const { return ptr_; } + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + T* release() { + T* retVal = ptr_; + ptr_ = NULL; + return retVal; + } + scoped_refptr<T>& operator=(T* p) { // AddRef first so that self assignment should work if (p) diff --git a/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc b/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc index 96119b4..e1052db 100644 --- a/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc +++ b/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc @@ -36,6 +36,12 @@ bool BrowserWebKitClientImpl::isLinkVisited(unsigned long long link_hash) { return false; } +WebKit::WebMessagePortChannel* +BrowserWebKitClientImpl::createMessagePortChannel() { + NOTREACHED(); + return NULL; +} + void BrowserWebKitClientImpl::setCookies(const WebKit::WebURL& url, const WebKit::WebURL& policy_url, const WebKit::WebString& value) { diff --git a/chrome/browser/in_process_webkit/browser_webkitclient_impl.h b/chrome/browser/in_process_webkit/browser_webkitclient_impl.h index 68b4243..61dffa6 100644 --- a/chrome/browser/in_process_webkit/browser_webkitclient_impl.h +++ b/chrome/browser/in_process_webkit/browser_webkitclient_impl.h @@ -16,6 +16,7 @@ class BrowserWebKitClientImpl : public webkit_glue::WebKitClientImpl { virtual unsigned long long visitedLinkHash(const char* canonicalURL, size_t length); virtual bool isLinkVisited(unsigned long long linkHash); + virtual WebKit::WebMessagePortChannel* createMessagePortChannel(); virtual void setCookies(const WebKit::WebURL& url, const WebKit::WebURL& policy_url, const WebKit::WebString& value); diff --git a/chrome/browser/renderer_host/render_sandbox_host_linux.cc b/chrome/browser/renderer_host/render_sandbox_host_linux.cc index 6b274f1..7611df0 100644 --- a/chrome/browser/renderer_host/render_sandbox_host_linux.cc +++ b/chrome/browser/renderer_host/render_sandbox_host_linux.cc @@ -124,6 +124,10 @@ class SandboxIPCProcess : public WebKitClient { virtual unsigned long long visitedLinkHash(const char*, size_t) { return 0; } virtual bool isLinkVisited(unsigned long long) { return false; } + virtual WebKit::WebMessagePortChannel* createMessagePortChannel() { + return NULL; + } + virtual void setCookies(const WebURL&, const WebURL&, const WebString&) { } virtual WebString cookies(const WebURL&, const WebURL&) { return WebString(); } diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index be61cf3..c726591 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -26,6 +26,7 @@ #include "chrome/browser/renderer_host/file_system_accessor.h" #include "chrome/browser/renderer_host/render_widget_helper.h" #include "chrome/browser/spellchecker.h" +#include "chrome/browser/worker_host/message_port_dispatcher.h" #include "chrome/browser/worker_host/worker_service.h" #include "chrome/common/app_cache/app_cache_dispatcher_host.h" #include "chrome/common/chrome_plugin_lib.h" @@ -37,6 +38,7 @@ #include "chrome/common/pref_service.h" #include "chrome/common/render_messages.h" #include "chrome/common/url_constants.h" +#include "chrome/common/worker_messages.h" #include "net/base/mime_util.h" #include "net/base/load_flags.h" #include "net/http/http_cache.h" @@ -158,7 +160,9 @@ ResourceMessageFilter::ResourceMessageFilter( resource_dispatcher_host->webkit_thread()))), ALLOW_THIS_IN_INITIALIZER_LIST(db_dispatcher_host_( new DatabaseDispatcherHost(profile->GetPath(), this))), - off_the_record_(profile->IsOffTheRecord()) { + off_the_record_(profile->IsOffTheRecord()), + next_route_id_(NewCallbackWithReturnValue( + render_widget_helper, &RenderWidgetHelper::GetNextRoutingID)) { DCHECK(request_context_.get()); DCHECK(request_context_->cookie_store()); DCHECK(media_request_context_.get()); @@ -244,22 +248,21 @@ void ResourceMessageFilter::OnChannelClosing() { } // Called on the IPC thread: -bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { +bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) { + MessagePortDispatcher* mp_dispatcher = MessagePortDispatcher::GetInstance(); bool msg_is_ok = true; - bool handled = resource_dispatcher_host_->OnMessageReceived( - message, this, &msg_is_ok) || - app_cache_dispatcher_host_->OnMessageReceived( - message, &msg_is_ok) || - dom_storage_dispatcher_host_->OnMessageReceived( - message, &msg_is_ok) || - audio_renderer_host_->OnMessageReceived( - message, &msg_is_ok) || - db_dispatcher_host_->OnMessageReceived(message, &msg_is_ok); + bool handled = + resource_dispatcher_host_->OnMessageReceived(msg, this, &msg_is_ok) || + app_cache_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) || + dom_storage_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) || + audio_renderer_host_->OnMessageReceived(msg, &msg_is_ok) || + db_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) || + mp_dispatcher->OnMessageReceived(msg, this, next_route_id_, &msg_is_ok); if (!handled) { DCHECK(msg_is_ok); // It should have been marked handled if it wasn't OK. handled = true; - IPC_BEGIN_MESSAGE_MAP_EX(ResourceMessageFilter, message, msg_is_ok) + IPC_BEGIN_MESSAGE_MAP_EX(ResourceMessageFilter, msg, msg_is_ok) // On Linux we need to dispatch these messages to the UI2 thread // because we cannot make X calls from the IO thread. Mac // doesn't have windowed plug-ins so we handle the messages in @@ -288,7 +291,7 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewHostMsg_GetPluginPath, OnGetPluginPath) IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl) IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_ContextMenu, - OnReceiveContextMenuMsg(message)) + OnReceiveContextMenuMsg(msg)) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin, OnOpenChannelToPlugin) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateDedicatedWorker, @@ -304,12 +307,11 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewHostMsg_RendererHistograms, OnRendererHistograms) IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_PaintRect, - render_widget_helper_->DidReceivePaintMsg(message)) + render_widget_helper_->DidReceivePaintMsg(msg)) IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsAsync, OnClipboardWriteObjects) IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsSync, OnClipboardWriteObjects) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardIsFormatAvailable, OnClipboardIsFormatAvailable) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadText, @@ -318,7 +320,6 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { OnClipboardReadAsciiText) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ClipboardReadHTML, OnClipboardReadHTML) - IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromExtension, OnGetMimeTypeFromExtension) IPC_MESSAGE_HANDLER(ViewHostMsg_GetMimeTypeFromFile, @@ -344,14 +345,11 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { #endif IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToExtension, OnOpenChannelToExtension) - IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToTab, - OnOpenChannelToTab) + IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToTab, OnOpenChannelToTab) IPC_MESSAGE_HANDLER(ViewHostMsg_CloseIdleConnections, OnCloseIdleConnections) - IPC_MESSAGE_HANDLER(ViewHostMsg_SetCacheMode, - OnSetCacheMode) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetFileSize, - OnGetFileSize) + IPC_MESSAGE_HANDLER(ViewHostMsg_SetCacheMode, OnSetCacheMode) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetFileSize, OnGetFileSize) IPC_MESSAGE_UNHANDLED( handled = false) @@ -359,8 +357,7 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { } if (!msg_is_ok) { - BrowserRenderProcessHost::BadMessageTerminateProcess(message.type(), - handle()); + BrowserRenderProcessHost::BadMessageTerminateProcess(msg.type(), handle()); } return handled; diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index ee92565..cf84dfc 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -15,6 +15,7 @@ #include "base/ref_counted.h" #include "base/shared_memory.h" #include "base/string16.h" +#include "base/task.h" #include "build/build_config.h" #include "chrome/browser/net/resolve_proxy_msg_helper.h" #include "chrome/browser/renderer_host/render_widget_helper.h" @@ -317,6 +318,9 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, // Whether this process is used for off the record tabs. bool off_the_record_; + // A callback to create a routing id for the associated renderer process. + CallbackWithReturnValue<int>::Type* next_route_id_; + DISALLOW_COPY_AND_ASSIGN(ResourceMessageFilter); }; diff --git a/chrome/browser/worker_host/message_port_dispatcher.cc b/chrome/browser/worker_host/message_port_dispatcher.cc new file mode 100644 index 0000000..9804e86 --- /dev/null +++ b/chrome/browser/worker_host/message_port_dispatcher.cc @@ -0,0 +1,225 @@ +// 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/browser/worker_host/message_port_dispatcher.h" + +#include "base/singleton.h" +#include "chrome/browser/renderer_host/resource_message_filter.h" +#include "chrome/browser/worker_host/worker_process_host.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/worker_messages.h" + + +MessagePortDispatcher* MessagePortDispatcher::GetInstance() { + return Singleton<MessagePortDispatcher>::get(); +} + +MessagePortDispatcher::MessagePortDispatcher() + : next_message_port_id_(0), + sender_(NULL), + next_routing_id_(NULL) { + // Receive a notification if a message filter or WorkerProcessHost is deleted. + registrar_.Add(this, NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, + NotificationService::AllSources()); + + registrar_.Add(this, NotificationType::WORKER_PROCESS_HOST_SHUTDOWN, + NotificationService::AllSources()); +} + +MessagePortDispatcher::~MessagePortDispatcher() { +} + +bool MessagePortDispatcher::OnMessageReceived( + const IPC::Message& message, + IPC::Message::Sender* sender, + CallbackWithReturnValue<int>::Type* next_routing_id, + bool* message_was_ok) { + sender_ = sender; + next_routing_id_ = next_routing_id; + + bool handled = true; + *message_was_ok = true; + + IPC_BEGIN_MESSAGE_MAP_EX(MessagePortDispatcher, message, *message_was_ok) + IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_CreateMessagePort, OnCreate) + IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_DestroyMessagePort, OnDestroy) + IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_Entangle, OnEntangle) + IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_PostMessage, OnPostMessage) + IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_QueueMessages, OnQueueMessages) + IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_SendQueuedMessages, + OnSendQueuedMessages) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP_EX() + + sender_ = NULL; + next_routing_id_ = NULL; + + return handled; +} + +bool MessagePortDispatcher::Send(IPC::Message* message) { + return sender_->Send(message); +} + +void MessagePortDispatcher::OnCreate(int *route_id, + int* message_port_id) { + *message_port_id = ++next_message_port_id_; + *route_id = next_routing_id_->Run(); + + MessagePort port; + port.sender = sender_; + port.route_id = *route_id; + port.next_routing_id = next_routing_id_; + port.message_port_id = *message_port_id; + port.entangled_message_port_id = MSG_ROUTING_NONE; + port.queue_messages = false; + message_ports_[*message_port_id] = port; +} + +void MessagePortDispatcher::OnDestroy(int message_port_id) { + if (!message_ports_.count(message_port_id)) { + NOTREACHED(); + return; + } + + DCHECK(message_ports_[message_port_id].queued_messages.empty()); + delete message_ports_[message_port_id].next_routing_id; + message_ports_.erase(message_port_id); +} + +void MessagePortDispatcher::OnEntangle(int local_message_port_id, + int remote_message_port_id) { + if (!message_ports_.count(local_message_port_id) || + !message_ports_.count(remote_message_port_id)) { + NOTREACHED(); + return; + } + + DCHECK(message_ports_[remote_message_port_id].entangled_message_port_id == + MSG_ROUTING_NONE); + message_ports_[remote_message_port_id].entangled_message_port_id = + local_message_port_id; +} + +void MessagePortDispatcher::OnPostMessage(int sender_message_port_id, + const string16& message, + int sent_message_port_id) { + if (!message_ports_.count(sender_message_port_id)) { + NOTREACHED(); + return; + } + + int entangled_message_port_id = + message_ports_[sender_message_port_id].entangled_message_port_id; + if (entangled_message_port_id == MSG_ROUTING_NONE) + return; // Process could have crashed. + + if (!message_ports_.count(entangled_message_port_id)) { + NOTREACHED(); + return; + } + + PostMessageTo(entangled_message_port_id, message, sent_message_port_id); +} + +void MessagePortDispatcher::PostMessageTo(int message_port_id, + const string16& message, + int sent_message_port_id) { + if (!message_ports_.count(message_port_id) || + (sent_message_port_id != MSG_ROUTING_NONE && + !message_ports_.count(sent_message_port_id))) { + NOTREACHED(); + return; + } + + MessagePort& entangled_port = message_ports_[message_port_id]; + + MessagePort* sent_port = NULL; + if (sent_message_port_id != MSG_ROUTING_NONE) { + sent_port = &message_ports_[sent_message_port_id]; + sent_port->queue_messages = true; + } + + if (entangled_port.queue_messages) { + entangled_port.queued_messages.push_back( + std::make_pair(message, sent_message_port_id)); + } else { + // If a message port was sent around, the new location will need a routing + // id. Instead of having the created port send us a sync message to get it, + // send along with the message. + int new_routing_id = MSG_ROUTING_NONE; + if (sent_message_port_id != MSG_ROUTING_NONE) { + new_routing_id = entangled_port.next_routing_id->Run(); + sent_port->sender = entangled_port.sender; + + // Update the entry for the sent port as it can be in a different process. + sent_port->route_id = new_routing_id; + } + + // Now send the message to the entangled port. + IPC::Message* ipc_msg = new WorkerProcessMsg_Message( + entangled_port.route_id, message, sent_message_port_id, + new_routing_id); + entangled_port.sender->Send(ipc_msg); + } +} + +void MessagePortDispatcher::OnQueueMessages(int message_port_id) { + if (!message_ports_.count(message_port_id)) { + NOTREACHED(); + return; + } + + MessagePort& port = message_ports_[message_port_id]; + port.queue_messages = true; + port.sender->Send(new WorkerProcessMsg_MessagesQueued(port.route_id)); +} + +void MessagePortDispatcher::OnSendQueuedMessages( + int message_port_id, + const QueuedMessages& queued_messages) { + if (!message_ports_.count(message_port_id)) { + NOTREACHED(); + return; + } + + // Send the queued messages to the port again. This time they'll reach the + // new location. + MessagePort& port = message_ports_[message_port_id]; + port.queue_messages = false; + port.queued_messages.insert(port.queued_messages.begin(), + queued_messages.begin(), + queued_messages.end()); + for (QueuedMessages::iterator iter = port.queued_messages.begin(); + iter != port.queued_messages.end(); ++iter) { + PostMessageTo(message_port_id, iter->first, iter->second); + } + port.queued_messages.clear(); +} + +void MessagePortDispatcher::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + IPC::Message::Sender* sender = NULL; + if (type.value == NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN) { + sender = Source<ResourceMessageFilter>(source).ptr(); + } else if (type.value == NotificationType::WORKER_PROCESS_HOST_SHUTDOWN) { + sender = Source<WorkerProcessHost>(source).ptr(); + } else { + NOTREACHED(); + } + + // Check if the (possibly) crashed process had any message ports. + for (MessagePorts::iterator iter = message_ports_.begin(); + iter != message_ports_.end();) { + MessagePorts::iterator cur_item = iter++; + if (cur_item->second.sender == sender) { + if (cur_item->second.entangled_message_port_id != MSG_ROUTING_NONE) { + message_ports_[cur_item->second.entangled_message_port_id]. + entangled_message_port_id = MSG_ROUTING_NONE; + } + message_ports_.erase(cur_item); + } + } +} diff --git a/chrome/browser/worker_host/message_port_dispatcher.h b/chrome/browser/worker_host/message_port_dispatcher.h new file mode 100644 index 0000000..d443b07 --- /dev/null +++ b/chrome/browser/worker_host/message_port_dispatcher.h @@ -0,0 +1,90 @@ +// 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_BROWSER_WORKER_HOST_MESSAGE_PORT_DISPATCHER_H_ +#define CHROME_BROWSER_WORKER_HOST_MESSAGE_PORT_DISPATCHER_H_ + +#include <map> +#include <utility> +#include <vector> + +#include "base/basictypes.h" +#include "base/singleton.h" +#include "base/string16.h" +#include "base/task.h" +#include "chrome/common/notification_registrar.h" +#include "ipc/ipc_message.h" + +class MessagePortDispatcher : public NotificationObserver { + public: + typedef std::vector<std::pair<string16, int> > QueuedMessages; + + // Returns the MessagePortDispatcher singleton. + static MessagePortDispatcher* GetInstance(); + + bool OnMessageReceived(const IPC::Message& message, + IPC::Message::Sender* sender, + CallbackWithReturnValue<int>::Type* next_routing_id, + bool* message_was_ok); + + bool Send(IPC::Message* message); + + private: + friend struct DefaultSingletonTraits<MessagePortDispatcher>; + + MessagePortDispatcher(); + ~MessagePortDispatcher(); + + // Message handlers. + void OnCreate(int* route_id, int* message_port_id); + void OnDestroy(int message_port_id); + void OnEntangle(int local_message_port_id, int remote_message_port_id); + void OnPostMessage(int sender_message_port_id, + const string16& message, + int sent_message_port_id); + void OnQueueMessages(int message_port_id); + void OnSendQueuedMessages(int message_port_id, + const QueuedMessages& queued_messages); + + void PostMessageTo(int message_port_id, + const string16& message, + int sent_message_port_id); + + // NotificationObserver interface. + void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + struct MessagePort { + // sender and route_id are what we need to send messages to the port. + IPC::Message::Sender* sender; + int route_id; + // A function pointer to generate a new route id for the sender above. + // Owned by "sender" above, so don't delete. + CallbackWithReturnValue<int>::Type* next_routing_id; + // A globally unique id for this message port. + int message_port_id; + // The globally unique id of the entangled message port. + int entangled_message_port_id; + // If true, all messages to this message port are queued and not delivered. + bool queue_messages; + QueuedMessages queued_messages; + }; + + typedef std::map<int, MessagePort> MessagePorts; + MessagePorts message_ports_; + + // We need globally unique identifiers for each message port. + int next_message_port_id_; + + // Valid only during IPC message dispatching. + IPC::Message::Sender* sender_; + CallbackWithReturnValue<int>::Type* next_routing_id_; + + NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(MessagePortDispatcher); +}; + +#endif // CHROME_BROWSER_WORKER_HOST_MESSAGE_PORT_DISPATCHER_H_ diff --git a/chrome/browser/worker_host/worker_process_host.cc b/chrome/browser/worker_host/worker_process_host.cc index bcb3da2..ed3fd9f 100644 --- a/chrome/browser/worker_host/worker_process_host.cc +++ b/chrome/browser/worker_host/worker_process_host.cc @@ -18,11 +18,14 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/child_process_security_policy.h" #include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/worker_host/message_port_dispatcher.h" #include "chrome/browser/worker_host/worker_service.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/debug_flags.h" +#include "chrome/common/notification_service.h" #include "chrome/common/process_watcher.h" #include "chrome/common/render_messages.h" +#include "chrome/common/result_codes.h" #include "chrome/common/worker_messages.h" #include "ipc/ipc_descriptors.h" #include "ipc/ipc_switches.h" @@ -59,11 +62,16 @@ class WorkerCrashTask : public Task { WorkerProcessHost::WorkerProcessHost( ResourceDispatcherHost* resource_dispatcher_host_) : ChildProcessHost(WORKER_PROCESS, resource_dispatcher_host_) { + next_route_id_ = NewCallbackWithReturnValue( + WorkerService::GetInstance(), &WorkerService::next_worker_route_id); } WorkerProcessHost::~WorkerProcessHost() { - WorkerService::GetInstance()->OnSenderShutdown(this); - WorkerService::GetInstance()->OnWorkerProcessDestroyed(this); + // Let interested observers know we are being deleted. + NotificationService::current()->Notify( + NotificationType::WORKER_PROCESS_HOST_SHUTDOWN, + Source<WorkerProcessHost>(this), + NotificationService::NoDetails()); // If we crashed, tell the RenderViewHost. MessageLoop* ui_loop = WorkerService::GetInstance()->ui_loop(); @@ -157,16 +165,28 @@ URLRequestContext* WorkerProcessHost::GetRequestContext( } void WorkerProcessHost::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(WorkerProcessHost, message) - IPC_MESSAGE_HANDLER(ViewHostMsg_CreateDedicatedWorker, - OnCreateDedicatedWorker) - IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker, - OnCancelCreateDedicatedWorker) - IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, - OnForwardToWorker) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP_EX() + bool msg_is_ok = true; + bool handled = MessagePortDispatcher::GetInstance()->OnMessageReceived( + message, this, next_route_id_, &msg_is_ok); + + if (!handled) { + handled = true; + IPC_BEGIN_MESSAGE_MAP_EX(WorkerProcessHost, message, msg_is_ok) + IPC_MESSAGE_HANDLER(ViewHostMsg_CreateDedicatedWorker, + OnCreateDedicatedWorker) + IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker, + OnCancelCreateDedicatedWorker) + IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, + OnForwardToWorker) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP_EX() + } + + if (!msg_is_ok) { + NOTREACHED(); + base::KillProcess(handle(), ResultCodes::KILLED_BAD_MESSAGE, false); + } + if (handled) return; diff --git a/chrome/browser/worker_host/worker_process_host.h b/chrome/browser/worker_host/worker_process_host.h index 00a6642..44bc676 100644 --- a/chrome/browser/worker_host/worker_process_host.h +++ b/chrome/browser/worker_host/worker_process_host.h @@ -8,6 +8,7 @@ #include <list> #include "base/basictypes.h" +#include "base/task.h" #include "chrome/common/child_process_host.h" #include "googleurl/src/gurl.h" #include "ipc/ipc_channel.h" @@ -69,6 +70,9 @@ class WorkerProcessHost : public ChildProcessHost { Instances instances_; + // A callback to create a routing id for the associated worker process. + CallbackWithReturnValue<int>::Type* next_route_id_; + DISALLOW_COPY_AND_ASSIGN(WorkerProcessHost); }; diff --git a/chrome/browser/worker_host/worker_service.cc b/chrome/browser/worker_host/worker_service.cc index e67ae80..df8ba51 100644 --- a/chrome/browser/worker_host/worker_service.cc +++ b/chrome/browser/worker_host/worker_service.cc @@ -10,9 +10,9 @@ #include "base/thread.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/plugin_service.h" -#include "chrome/browser/worker_host/worker_process_host.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/resource_message_filter.h" +#include "chrome/browser/worker_host/worker_process_host.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" #include "chrome/common/worker_messages.h" @@ -30,9 +30,12 @@ WorkerService::WorkerService() : next_worker_route_id_(0), resource_dispatcher_host_(NULL), ui_loop_(NULL) { - // Receive a notification if the message filter is deleted. + // Receive a notification if a message filter or WorkerProcessHost is deleted. registrar_.Add(this, NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, NotificationService::AllSources()); + + registrar_.Add(this, NotificationType::WORKER_PROCESS_HOST_SHUTDOWN, + NotificationService::AllSources()); } void WorkerService::Initialize(ResourceDispatcherHost* rdh, @@ -210,12 +213,19 @@ bool WorkerService::CanCreateWorkerProcess( void WorkerService::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { - DCHECK(type.value == NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN); - ResourceMessageFilter* filter = Source<ResourceMessageFilter>(source).ptr(); - OnSenderShutdown(filter); + if (type.value == NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN) { + ResourceMessageFilter* sender = Source<ResourceMessageFilter>(source).ptr(); + SenderShutdown(sender); + } else if (type.value == NotificationType::WORKER_PROCESS_HOST_SHUTDOWN) { + WorkerProcessHost* sender = Source<WorkerProcessHost>(source).ptr(); + SenderShutdown(sender); + WorkerProcessDestroyed(sender); + } else { + NOTREACHED(); + } } -void WorkerService::OnSenderShutdown(IPC::Message::Sender* sender) { +void WorkerService::SenderShutdown(IPC::Message::Sender* sender) { for (ChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); !iter.Done(); ++iter) { WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); @@ -233,7 +243,7 @@ void WorkerService::OnSenderShutdown(IPC::Message::Sender* sender) { } } -void WorkerService::OnWorkerProcessDestroyed(WorkerProcessHost* process) { +void WorkerService::WorkerProcessDestroyed(WorkerProcessHost* process) { if (queued_workers_.empty()) return; diff --git a/chrome/browser/worker_host/worker_service.h b/chrome/browser/worker_host/worker_service.h index 45e8248..704a7da 100644 --- a/chrome/browser/worker_host/worker_service.h +++ b/chrome/browser/worker_host/worker_service.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_WORKER_HOST__WORKER_SERVICE_H_ -#define CHROME_BROWSER_WORKER_HOST__WORKER_SERVICE_H_ +#ifndef CHROME_BROWSER_WORKER_HOST_WORKER_SERVICE_H_ +#define CHROME_BROWSER_WORKER_HOST_WORKER_SERVICE_H_ #include <list> @@ -42,17 +42,6 @@ class WorkerService : public NotificationObserver { // forwarded to the worker process. void ForwardMessage(const IPC::Message& message, int sender_pid); - // NotificationObserver interface. - void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // Notifies us that a process that's talking to a worker has shut down. - void OnSenderShutdown(IPC::Message::Sender* sender); - - // Notifies us that a worker process has closed. - void OnWorkerProcessDestroyed(WorkerProcessHost* process); - MessageLoop* ui_loop() { return ui_loop_; } int next_worker_route_id() { return ++next_worker_route_id_; } @@ -86,6 +75,17 @@ class WorkerService : public NotificationObserver { // we're using a strategy of one process per core. bool CanCreateWorkerProcess(const WorkerProcessHost::WorkerInstance& instance); + // NotificationObserver interface. + void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Notifies us that a process that's talking to a worker has shut down. + void SenderShutdown(IPC::Message::Sender* sender); + + // Notifies us that a worker process has closed. + void WorkerProcessDestroyed(WorkerProcessHost* process); + NotificationRegistrar registrar_; int next_worker_route_id_; ResourceDispatcherHost* resource_dispatcher_host_; @@ -96,4 +96,4 @@ class WorkerService : public NotificationObserver { DISALLOW_COPY_AND_ASSIGN(WorkerService); }; -#endif // CHROME_BROWSER_WORKER_HOST__WORKER_SERVICE_H_ +#endif // CHROME_BROWSER_WORKER_HOST_WORKER_SERVICE_H_ diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index de83502..4edef2fb 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -486,6 +486,8 @@ 'common/visitedlink_common.cc', 'common/visitedlink_common.h', 'common/webkit_param_traits.h', + 'common/webmessageportchannel_impl.cc', + 'common/webmessageportchannel_impl.h', 'common/win_safe_util.cc', 'common/win_safe_util.h', 'common/worker_messages.h', @@ -1901,6 +1903,8 @@ 'browser/window_sizer_mac.mm', 'browser/window_sizer_linux.cc', 'browser/window_sizer_win.cc', + 'browser/worker_host/message_port_dispatcher.cc', + 'browser/worker_host/message_port_dispatcher.h', 'browser/worker_host/worker_process_host.cc', 'browser/worker_host/worker_process_host.h', 'browser/worker_host/worker_service.cc', diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index ad99d89..7a95f9a 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -169,6 +169,10 @@ class NotificationType { // twice). RESOURCE_MESSAGE_FILTER_SHUTDOWN, + // Lets interested observers know when a WorkerProcessHost is being deleted + // and can no longer be used. + WORKER_PROCESS_HOST_SHUTDOWN, + // Views ------------------------------------------------------------------- // Notification that a view was removed from a view hierarchy. The source diff --git a/chrome/common/webmessageportchannel_impl.cc b/chrome/common/webmessageportchannel_impl.cc new file mode 100644 index 0000000..a165db8 --- /dev/null +++ b/chrome/common/webmessageportchannel_impl.cc @@ -0,0 +1,204 @@ +// 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/common/webmessageportchannel_impl.h" + +#include "chrome/common/child_process.h" +#include "chrome/common/child_thread.h" +#include "chrome/common/worker_messages.h" +#include "webkit/api/public/WebString.h" +#include "webkit/api/public/WebMessagePortChannelClient.h" + +using WebKit::WebMessagePortChannel; +using WebKit::WebMessagePortChannelClient; +using WebKit::WebString; + +WebMessagePortChannelImpl::WebMessagePortChannelImpl() + : client_(NULL), + route_id_(MSG_ROUTING_NONE), + message_port_id_(MSG_ROUTING_NONE) { + AddRef(); + Init(); +} + +WebMessagePortChannelImpl::WebMessagePortChannelImpl( + int route_id, + int message_port_id) + : client_(NULL), + route_id_(route_id), + message_port_id_(message_port_id) { + AddRef(); + Init(); +} + +WebMessagePortChannelImpl::~WebMessagePortChannelImpl() { + if (message_port_id_ != MSG_ROUTING_NONE) + Send(new WorkerProcessHostMsg_DestroyMessagePort(message_port_id_)); + + if (route_id_ != MSG_ROUTING_NONE) + ChildThread::current()->RemoveRoute(route_id_); +} + +void WebMessagePortChannelImpl::setClient(WebMessagePortChannelClient* client) { + // Must lock here since client_ is called on the main thread. + AutoLock auto_lock(lock_); + client_ = client; +} + +void WebMessagePortChannelImpl::destroy() { + setClient(NULL); + Release(); +} + +void WebMessagePortChannelImpl::entangle(WebMessagePortChannel* channel) { + // The message port ids might not be set up yet, if this channel wasn't + // created on the main thread. So need to wait until we're on the main thread + // before getting the other message port id. + scoped_refptr<WebMessagePortChannelImpl> webchannel = + static_cast<WebMessagePortChannelImpl*>(channel); + Entangle(webchannel); +} + +void WebMessagePortChannelImpl::postMessage( + const WebString& message, + WebMessagePortChannel* channel) { + if (MessageLoop::current() != ChildThread::current()->message_loop()) { + ChildThread::current()->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &WebMessagePortChannelImpl::postMessage, + message, channel)); + return; + } + + WebMessagePortChannelImpl* webchannel = + static_cast<WebMessagePortChannelImpl*>(channel); + + int message_port_id = MSG_ROUTING_NONE; + if (webchannel) { + message_port_id = webchannel->message_port_id(); + webchannel->QueueMessages(); + DCHECK(message_port_id != MSG_ROUTING_NONE); + } + + IPC::Message* msg = new WorkerProcessHostMsg_PostMessage( + message_port_id_, message, message_port_id); + + Send(msg); +} + +bool WebMessagePortChannelImpl::tryGetMessage( + WebString* message, + WebMessagePortChannel** channel) { + AutoLock auto_lock(lock_); + if (message_queue_.empty()) + return false; + + *message = message_queue_.front().message; + *channel = message_queue_.front().port.release(); + message_queue_.pop(); + return true; +} + +void WebMessagePortChannelImpl::Init() { + if (MessageLoop::current() != ChildThread::current()->message_loop()) { + ChildThread::current()->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &WebMessagePortChannelImpl::Init)); + return; + } + + if (route_id_ == MSG_ROUTING_NONE) { + DCHECK(message_port_id_ == MSG_ROUTING_NONE); + Send(new WorkerProcessHostMsg_CreateMessagePort( + &route_id_, &message_port_id_)); + } + + ChildThread::current()->AddRoute(route_id_, this); +} + +void WebMessagePortChannelImpl::Entangle( + scoped_refptr<WebMessagePortChannelImpl> channel) { + if (MessageLoop::current() != ChildThread::current()->message_loop()) { + ChildThread::current()->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &WebMessagePortChannelImpl::Entangle, channel)); + return; + } + + Send(new WorkerProcessHostMsg_Entangle( + message_port_id_, channel->message_port_id())); +} + +void WebMessagePortChannelImpl::QueueMessages() { + // This message port is being sent elsewhere (perhaps to another process). + // The new endpoint needs to recieve the queued messages, including ones that + // could still be in-flight. So we tell the browser to queue messages, and it + // sends us an ack, whose receipt we know means that no more messages are + // in-flight. We then send the queued messages to the browser, which prepends + // them to the ones it queued and it sends them to the new endpoint. + Send(new WorkerProcessHostMsg_QueueMessages(message_port_id_)); + + // The process could potentially go away while we're still waiting for + // in-flight messages. Ensure it stays alive. + ChildProcess::current()->AddRefProcess(); +} + +void WebMessagePortChannelImpl::Send(IPC::Message* message) { + if (MessageLoop::current() != ChildThread::current()->message_loop()) { + DCHECK(!message->is_sync()); + ChildThread::current()->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &WebMessagePortChannelImpl::Send, message)); + return; + } + + ChildThread::current()->Send(message); +} + +void WebMessagePortChannelImpl::OnMessageReceived(const IPC::Message& message) { + IPC_BEGIN_MESSAGE_MAP(WebMessagePortChannelImpl, message) + IPC_MESSAGE_HANDLER(WorkerProcessMsg_Message, OnMessage) + IPC_MESSAGE_HANDLER(WorkerProcessMsg_MessagesQueued, OnMessagedQueued) + IPC_END_MESSAGE_MAP() +} + +void WebMessagePortChannelImpl::OnMessage(const string16& message, + int sent_message_port_id, + int new_routing_id) { + AutoLock auto_lock(lock_); + Message msg; + msg.message = message; + msg.port = NULL; + if (sent_message_port_id != MSG_ROUTING_NONE) { + msg.port = new WebMessagePortChannelImpl( + new_routing_id, sent_message_port_id); + } + + bool was_empty = message_queue_.empty(); + message_queue_.push(msg); + if (client_ && was_empty) + client_->messageAvailable(); +} + +void WebMessagePortChannelImpl::OnMessagedQueued() { + std::vector<std::pair<string16, int> > queued_messages; + + { + AutoLock auto_lock(lock_); + queued_messages.reserve(message_queue_.size()); + while (!message_queue_.empty()) { + string16 message = message_queue_.front().message; + int port = MSG_ROUTING_NONE; + if (message_queue_.front().port) + port = message_queue_.front().port->message_port_id(); + + queued_messages.push_back(std::make_pair(message, port)); + message_queue_.pop(); + } + } + + Send(new WorkerProcessHostMsg_SendQueuedMessages( + message_port_id_, queued_messages)); + + message_port_id_ = MSG_ROUTING_NONE; + + Release(); + ChildProcess::current()->ReleaseProcess(); +} diff --git a/chrome/common/webmessageportchannel_impl.h b/chrome/common/webmessageportchannel_impl.h new file mode 100644 index 0000000..ee26e66 --- /dev/null +++ b/chrome/common/webmessageportchannel_impl.h @@ -0,0 +1,73 @@ +// 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_COMMON_WEBMESSAGEPORTCHANNEL_IMPL_H_ +#define CHROME_COMMON_WEBMESSAGEPORTCHANNEL_IMPL_H_ + +#include <queue> + +#include "base/basictypes.h" +#include "base/lock.h" +#include "base/string16.h" +#include "base/ref_counted.h" +#include "ipc/ipc_channel.h" +#include "webkit/api/public/WebMessagePortChannel.h" + +// This is thread safe. +class WebMessagePortChannelImpl + : public WebKit::WebMessagePortChannel, + public IPC::Channel::Listener, + public base::RefCountedThreadSafe<WebMessagePortChannelImpl> { + public: + WebMessagePortChannelImpl(); + WebMessagePortChannelImpl(int route_id, int message_port_id); + + // Queues received and incoming messages until there are no more in-flight + // messages, then sends all of them to the browser process. + void QueueMessages(); + int message_port_id() const { return message_port_id_; } + + private: + friend class base::RefCountedThreadSafe<WebMessagePortChannelImpl>; + ~WebMessagePortChannelImpl(); + + // WebMessagePortChannel implementation. + virtual void setClient(WebKit::WebMessagePortChannelClient* client); + virtual void destroy(); + virtual void entangle(WebKit::WebMessagePortChannel* channel); + virtual void postMessage(const WebKit::WebString& message, + WebKit::WebMessagePortChannel* channel); + virtual bool tryGetMessage(WebKit::WebString* message, + WebKit::WebMessagePortChannel** channel); + + void Init(); + void Entangle(scoped_refptr<WebMessagePortChannelImpl> channel); + void Send(IPC::Message* message); + + // IPC::Channel::Listener implementation. + virtual void OnMessageReceived(const IPC::Message& message); + + void OnMessage(const string16& message, + int sent_message_port_id, + int new_routing_id); + void OnMessagedQueued(); + + struct Message { + string16 message; + scoped_refptr<WebMessagePortChannelImpl> port; + }; + + typedef std::queue<Message> MessageQueue; + MessageQueue message_queue_; + + WebKit::WebMessagePortChannelClient* client_; + Lock lock_; // Locks access to above. + + int route_id_; // The routing id for this object. + int message_port_id_; // A globally unique identifier for this message port. + + DISALLOW_COPY_AND_ASSIGN(WebMessagePortChannelImpl); +}; + +#endif // CHROME_COMMON_WEBMESSAGEPORTCHANNEL_IMPL_H_ diff --git a/chrome/common/worker_messages.h b/chrome/common/worker_messages.h index 80004e5..b929d2c 100644 --- a/chrome/common/worker_messages.h +++ b/chrome/common/worker_messages.h @@ -14,6 +14,8 @@ #include "chrome/common/common_param_traits.h" #include "ipc/ipc_message_utils.h" +typedef std::pair<string16, int> QueuedMessage; + // Parameters structure for WorkerHostMsg_PostConsoleMessageToWorkerObject, // which has too many data parameters to be reasonably put in a predefined // IPC message. The data members directly correspond to parameters of diff --git a/chrome/common/worker_messages_internal.h b/chrome/common/worker_messages_internal.h index 9059719..eb536e8 100644 --- a/chrome/common/worker_messages_internal.h +++ b/chrome/common/worker_messages_internal.h @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> #include "base/string16.h" #include "googleurl/src/gurl.h" #include "ipc/ipc_message_macros.h" @@ -14,6 +15,18 @@ IPC_BEGIN_MESSAGES(WorkerProcess) IPC_MESSAGE_CONTROL2(WorkerProcessMsg_CreateWorker, GURL /* url */, int /* route_id */) + + // Note: these Message Port related messages can also be sent to the + // renderer process. Putting them here since we don't have a shared place + // like common_messages_internal.h + IPC_MESSAGE_ROUTED3(WorkerProcessMsg_Message, + string16 /* message */, + int /* sent_message_port_id */, + int /* new_routing_id */) + + // Tells the Message Port Channel object that there are no more in-flight + // messages arriving. + IPC_MESSAGE_ROUTED0(WorkerProcessMsg_MessagesQueued) IPC_END_MESSAGES(WorkerProcess) @@ -21,9 +34,48 @@ IPC_END_MESSAGES(WorkerProcess) // WorkerProcessHost messages // These are messages sent from the worker process to the browser process. -// No messages being sent in this direction for now. -//IPC_BEGIN_MESSAGES(WorkerProcessHost) -//IPC_END_MESSAGES(WorkerProcessHost) +IPC_BEGIN_MESSAGES(WorkerProcessHost) + // Note: these Message Port related messages can also be sent out from the + // renderer process. Putting them here since we don't have a shared place + // like common_messages_internal.h + + // Creates a new Message Port Channel object. The first paramaeter is the + // message port channel's routing id in this process. The second parameter + // is the process-wide-unique identifier for that port. + IPC_SYNC_MESSAGE_CONTROL0_2(WorkerProcessHostMsg_CreateMessagePort, + int /* route_id */, + int /* message_port_id */) + + // Sent when a Message Port Channel object is destroyed. + IPC_MESSAGE_CONTROL1(WorkerProcessHostMsg_DestroyMessagePort, + int /* message_port_id */) + + // Sends a message to a message port. Optionally sends a message port as + // as well if sent_message_port_id != MSG_ROUTING_NONE. + IPC_MESSAGE_CONTROL3(WorkerProcessHostMsg_PostMessage, + int /* sender_message_port_id */, + string16 /* message */, + int /* sent_message_port_id */) + + // Causes messages sent to the remote port to be delivered to this local port. + IPC_MESSAGE_CONTROL2(WorkerProcessHostMsg_Entangle, + int /* local_message_port_id */, + int /* remote_message_port_id */) + + // Causes the browser to queue messages sent to this port until the the port + // has made sure that all in-flight messages were routed to the new + // destination. + IPC_MESSAGE_CONTROL1(WorkerProcessHostMsg_QueueMessages, + int /* message_port_id */) + + // Sends the browser all the queued messages that arrived at this message port + // after it was sent in a postMessage call. + // NOTE: MSVS can't compile the macro if std::vector<std::pair<string16, int> > + // is used, so we typedef it in worker_messages.h. + IPC_MESSAGE_CONTROL2(WorkerProcessHostMsg_SendQueuedMessages, + int /* message_port_id */, + std::vector<QueuedMessage> /* queued_messages */) +IPC_END_MESSAGES(WorkerProcessHost) //----------------------------------------------------------------------------- // Worker messages diff --git a/chrome/renderer/renderer_webkitclient_impl.cc b/chrome/renderer/renderer_webkitclient_impl.cc index c086d0d..e19487b 100644 --- a/chrome/renderer/renderer_webkitclient_impl.cc +++ b/chrome/renderer/renderer_webkitclient_impl.cc @@ -10,6 +10,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/db_message_filter.h" #include "chrome/common/render_messages.h" +#include "chrome/common/webmessageportchannel_impl.h" #include "chrome/plugin/npobject_util.h" #include "chrome/renderer/net/render_dns_master.h" #include "chrome/renderer/render_thread.h" @@ -70,6 +71,11 @@ bool RendererWebKitClientImpl::isLinkVisited(unsigned long long link_hash) { return RenderThread::current()->visited_link_slave()->IsVisited(link_hash); } +WebKit::WebMessagePortChannel* +RendererWebKitClientImpl::createMessagePortChannel() { + return new WebMessagePortChannelImpl(); +} + void RendererWebKitClientImpl::setCookies(const WebURL& url, const WebURL& first_party_for_cookies, const WebString& value) { diff --git a/chrome/renderer/renderer_webkitclient_impl.h b/chrome/renderer/renderer_webkitclient_impl.h index 1f1880d..3d5828c 100644 --- a/chrome/renderer/renderer_webkitclient_impl.h +++ b/chrome/renderer/renderer_webkitclient_impl.h @@ -29,6 +29,7 @@ class RendererWebKitClientImpl : public webkit_glue::WebKitClientImpl { virtual unsigned long long visitedLinkHash( const char* canonicalURL, size_t length); virtual bool isLinkVisited(unsigned long long linkHash); + virtual WebKit::WebMessagePortChannel* createMessagePortChannel(); virtual void setCookies(const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies, const WebKit::WebString&); diff --git a/chrome/worker/worker_uitest.cc b/chrome/worker/worker_uitest.cc index e493203..62c618c 100644 --- a/chrome/worker/worker_uitest.cc +++ b/chrome/worker/worker_uitest.cc @@ -374,6 +374,35 @@ TEST_F(WorkerTest, WorkerXhrHttpLayoutTests) { StopHttpServer(); } +TEST_F(WorkerTest, MessagePorts) { + static const char* kLayoutTestFiles[] = { + "message-channel-gc.html", + "message-channel-gc-2.html", + "message-channel-gc-3.html", + "message-channel-gc-4.html", + "message-port.html", + "message-port-clone.html", + "message-port-constructor-for-deleted-document.html", + "message-port-deleted-document.html", + "message-port-deleted-frame.html", + "message-port-inactive-document.html", + "message-port-no-wrapper.html", + // Only works with run-webkit-tests --leaks. + //"message-channel-listener-circular-ownership.html", + }; + + FilePath fast_test_dir; + fast_test_dir = fast_test_dir.AppendASCII("LayoutTests"); + fast_test_dir = fast_test_dir.AppendASCII("fast"); + + FilePath worker_test_dir; + worker_test_dir = worker_test_dir.AppendASCII("events"); + InitializeForLayoutTest(fast_test_dir, worker_test_dir, false); + + for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i) + RunLayoutTest(kLayoutTestFiles[i], false); +} + TEST_F(WorkerTest, LimitPerPage) { int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate; GURL url = GetTestUrl(L"workers", L"many_workers.html"); diff --git a/chrome/worker/worker_webkitclient_impl.cc b/chrome/worker/worker_webkitclient_impl.cc index 21ca49a..4923542 100644 --- a/chrome/worker/worker_webkitclient_impl.cc +++ b/chrome/worker/worker_webkitclient_impl.cc @@ -5,6 +5,7 @@ #include "chrome/worker/worker_webkitclient_impl.h" #include "base/logging.h" +#include "chrome/common/webmessageportchannel_impl.h" #include "chrome/worker/worker_thread.h" #include "webkit/api/public/WebString.h" #include "webkit/api/public/WebURL.h" @@ -36,6 +37,11 @@ bool WorkerWebKitClientImpl::isLinkVisited(unsigned long long link_hash) { return false; } +WebKit::WebMessagePortChannel* +WorkerWebKitClientImpl::createMessagePortChannel() { + return new WebMessagePortChannelImpl(); +} + void WorkerWebKitClientImpl::setCookies(const WebKit::WebURL& url, const WebKit::WebURL& policy_url, const WebKit::WebString& value) { diff --git a/chrome/worker/worker_webkitclient_impl.h b/chrome/worker/worker_webkitclient_impl.h index ecd3220..69a28e4 100644 --- a/chrome/worker/worker_webkitclient_impl.h +++ b/chrome/worker/worker_webkitclient_impl.h @@ -16,6 +16,7 @@ class WorkerWebKitClientImpl : public webkit_glue::WebKitClientImpl { virtual unsigned long long visitedLinkHash(const char* canonicalURL, size_t length); virtual bool isLinkVisited(unsigned long long linkHash); + virtual WebKit::WebMessagePortChannel* createMessagePortChannel(); virtual void setCookies(const WebKit::WebURL& url, const WebKit::WebURL& policy_url, const WebKit::WebString& value); diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h index 2b2ff91..f337814 100644 --- a/ipc/ipc_message_utils.h +++ b/ipc/ipc_message_utils.h @@ -517,6 +517,25 @@ struct ParamTraits<std::wstring> { } }; +template <class A, class B> +struct ParamTraits<std::pair<A, B> > { + typedef std::pair<A, B> param_type; + static void Write(Message* m, const param_type& p) { + WriteParam(m, p.first); + WriteParam(m, p.second); + } + static bool Read(const Message* m, void** iter, param_type* r) { + return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second); + } + static void Log(const param_type& p, std::wstring* l) { + l->append(L"("); + LogParam(p.first, l); + l->append(L", "); + LogParam(p.second, l); + l->append(L")"); + } +}; + // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't // need this trait. #if !defined(WCHAR_T_IS_UTF16) diff --git a/webkit/api/public/WebKitClient.h b/webkit/api/public/WebKitClient.h index a63ae3d..026caf5 100644 --- a/webkit/api/public/WebKitClient.h +++ b/webkit/api/public/WebKitClient.h @@ -41,6 +41,7 @@ namespace WebKit { class WebClipboard; class WebData; + class WebMessagePortChannel; class WebMimeRegistry; class WebPluginListBuilder; class WebSandboxSupport; @@ -95,6 +96,13 @@ namespace WebKit { virtual bool isLinkVisited(unsigned long long linkHash) = 0; + // Message Ports ------------------------------------------------------- + + // Creates a Message Port Channel. This can be called on any thread. + // The returned object should only be used on the thread it was created on. + virtual WebMessagePortChannel* createMessagePortChannel() = 0; + + // Network ------------------------------------------------------------- virtual void setCookies( diff --git a/webkit/api/public/WebMessagePortChannel.h b/webkit/api/public/WebMessagePortChannel.h new file mode 100644 index 0000000..9ad521c --- /dev/null +++ b/webkit/api/public/WebMessagePortChannel.h @@ -0,0 +1,58 @@ +/* + * 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 WebMessagePortChannel_h +#define WebMessagePortChannel_h + +#include "WebCommon.h" + +namespace WebKit { + class WebMessagePortChannelClient; + class WebString; + + // Provides an interface to a Message Port Channel implementation. The object owns itself and + // is signalled that its not needed anymore with the destroy() call. + class WebMessagePortChannel { + public: + virtual void setClient(WebMessagePortChannelClient*) = 0; + virtual void destroy() = 0; + // WebKit versions of WebCore::MessagePortChannel. + virtual void entangle(WebMessagePortChannel*) = 0; + // If sending a message port, callee receives ownership of the object. + virtual void postMessage(const WebString&, WebMessagePortChannel*) = 0; + virtual bool tryGetMessage(WebString*, WebMessagePortChannel**) = 0; + + protected: + virtual ~WebMessagePortChannel() { } + }; + +} // namespace WebKit + +#endif diff --git a/webkit/api/public/WebMessagePortChannelClient.h b/webkit/api/public/WebMessagePortChannelClient.h new file mode 100644 index 0000000..af20d9a --- /dev/null +++ b/webkit/api/public/WebMessagePortChannelClient.h @@ -0,0 +1,50 @@ +/* + * 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 WebMessagePortChannelClient_h +#define WebMessagePortChannelClient_h + +namespace WebKit { + + // Provides an interface for users of WebMessagePortChannel to be notified + // when messages are available. + class WebMessagePortChannelClient { + public: + // Alerts that new messages have arrived, which are retrieved by calling + // WebMessagePortChannel::tryGetMessage. Note that this may be called + // on any thread. + virtual void messageAvailable() = 0; + protected: + virtual ~WebMessagePortChannelClient() { } + }; + +} // namespace WebKit + +#endif diff --git a/webkit/api/src/PlatformMessagePortChannel.cpp b/webkit/api/src/PlatformMessagePortChannel.cpp new file mode 100644 index 0000000..72a626a --- /dev/null +++ b/webkit/api/src/PlatformMessagePortChannel.cpp @@ -0,0 +1,248 @@ +/* + * 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. + */ + +#include "config.h" +#include "PlatformMessagePortChannel.h" + +#include "WebKit.h" +#include "WebKitClient.h" +#include "WebMessagePortChannel.h" +#include "WebString.h" + +#include "MessagePort.h" +#include "ScriptExecutionContext.h" + +using namespace WebKit; + +namespace WebCore { + +PassOwnPtr<MessagePortChannel> MessagePortChannel::create(PassRefPtr<PlatformMessagePortChannel> channel) +{ + return new MessagePortChannel(channel); +} + +void MessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2) +{ + PlatformMessagePortChannel::createChannel(port1, port2); +} + +MessagePortChannel::MessagePortChannel(PassRefPtr<PlatformMessagePortChannel> channel) + : m_channel(channel) +{ +} + +MessagePortChannel::~MessagePortChannel() +{ + // Make sure we close our platform channel when the base is freed, to keep the channel objects from leaking. + m_channel->close(); +} + +bool MessagePortChannel::entangleIfOpen(MessagePort* port) +{ + return m_channel->entangleIfOpen(port); +} + +void MessagePortChannel::disentangle() +{ + m_channel->disentangle(); +} + +void MessagePortChannel::postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData> message) +{ + m_channel->postMessageToRemote(message); +} + +bool MessagePortChannel::tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>& result) +{ + return m_channel->tryGetMessageFromRemote(result); +} + +void MessagePortChannel::close() +{ + m_channel->close(); +} + +bool MessagePortChannel::isConnectedTo(MessagePort* port) +{ + return m_channel->isConnectedTo(port); +} + +bool MessagePortChannel::hasPendingActivity() +{ + return m_channel->hasPendingActivity(); +} + +MessagePort* MessagePortChannel::locallyEntangledPort(const ScriptExecutionContext* context) +{ + // This is just an optimization, so return NULL always. + return NULL; +} + + +PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create() +{ + return adoptRef(new PlatformMessagePortChannel()); +} + +PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create( + WebMessagePortChannel* channel) +{ + return adoptRef(new PlatformMessagePortChannel(channel)); +} + + +PlatformMessagePortChannel::PlatformMessagePortChannel() + : m_localPort(0) +{ + m_webChannel = webKitClient()->createMessagePortChannel(); + m_webChannel->setClient(this); +} + +PlatformMessagePortChannel::PlatformMessagePortChannel(WebMessagePortChannel* channel) + : m_localPort(0) + , m_webChannel(channel) +{ +} + +PlatformMessagePortChannel::~PlatformMessagePortChannel() +{ + if (m_webChannel) + m_webChannel->destroy(); +} + +void PlatformMessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2) +{ + // Create proxies for each endpoint. + RefPtr<PlatformMessagePortChannel> channel1 = PlatformMessagePortChannel::create(); + RefPtr<PlatformMessagePortChannel> channel2 = PlatformMessagePortChannel::create(); + + // Entangle the two endpoints. + channel1->setEntangledChannel(channel2); + channel2->setEntangledChannel(channel1); + + // Now entangle the proxies with the appropriate local ports. + port1->entangle(MessagePortChannel::create(channel2)); + port2->entangle(MessagePortChannel::create(channel1)); +} + +void PlatformMessagePortChannel::messageAvailable() +{ + MutexLocker lock(m_mutex); + if (m_localPort) + m_localPort->messageAvailable(); +} + +bool PlatformMessagePortChannel::entangleIfOpen(MessagePort* port) +{ + MutexLocker lock(m_mutex); + m_localPort = port; + return true; +} + +void PlatformMessagePortChannel::disentangle() +{ + MutexLocker lock(m_mutex); + m_localPort = 0; +} + +void PlatformMessagePortChannel::postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData> message) +{ + if (!m_localPort) + return; + + WebString messageString = message->message(); + OwnPtr<WebCore::MessagePortChannel> channel = message->channel(); + WebMessagePortChannel* webChannel = NULL; + if (channel.get()) { + WebCore::PlatformMessagePortChannel* platformChannel = channel->channel(); + webChannel = platformChannel->webChannelRelease(); + webChannel->setClient(0); + } + m_webChannel->postMessage(messageString, webChannel); +} + +bool PlatformMessagePortChannel::tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>& result) +{ + if (!m_webChannel) + return false; + + WebString message; + WebMessagePortChannel* webChannel = NULL; + bool rv = m_webChannel->tryGetMessage(&message, &webChannel); + if (rv) { + OwnPtr<MessagePortChannel> channel; + if (webChannel) { + RefPtr<PlatformMessagePortChannel> platformChannel = create(webChannel); + webChannel->setClient(platformChannel.get()); + channel = MessagePortChannel::create(platformChannel); + } + result = MessagePortChannel::EventData::create(message, channel.release()); + } + + return rv; +} + +void PlatformMessagePortChannel::close() +{ + MutexLocker lock(m_mutex); + // Disentangle ourselves from the other end. We still maintain a reference to m_webChannel, + // since previously-existing messages should still be delivered. + m_localPort = 0; + m_entangledChannel = 0; +} + +bool PlatformMessagePortChannel::isConnectedTo(MessagePort* port) +{ + MutexLocker lock(m_mutex); + return m_entangledChannel && m_entangledChannel->m_localPort == port; +} + +bool PlatformMessagePortChannel::hasPendingActivity() +{ + MutexLocker lock(m_mutex); + return m_localPort; +} + +void PlatformMessagePortChannel::setEntangledChannel(PassRefPtr<PlatformMessagePortChannel> remote) +{ + m_webChannel->entangle(remote->m_webChannel); + + MutexLocker lock(m_mutex); + m_entangledChannel = remote; +} + +WebMessagePortChannel* PlatformMessagePortChannel::webChannelRelease() +{ + WebMessagePortChannel* rv = m_webChannel; + m_webChannel = 0; + return rv; +} + +} // namespace WebCore diff --git a/webkit/api/src/PlatformMessagePortChannel.h b/webkit/api/src/PlatformMessagePortChannel.h new file mode 100644 index 0000000..08c6a5c --- /dev/null +++ b/webkit/api/src/PlatformMessagePortChannel.h @@ -0,0 +1,93 @@ +/* + * 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 PlatformMessagePortChannel_h +#define PlatformMessagePortChannel_h + +#include "WebMessagePortChannelClient.h" + +#include "MessagePortChannel.h" + +#include <wtf/PassRefPtr.h> +#include <wtf/Threading.h> + +namespace WebKit { +class WebMessagePortChannel; +} + +namespace WebCore { + class MessagePort; + + // PlatformMessagePortChannel is a platform-dependent interface to the remote side of a message channel. + class PlatformMessagePortChannel : public ThreadSafeShared<PlatformMessagePortChannel>, + public WebKit::WebMessagePortChannelClient { + public: + static void createChannel(PassRefPtr<MessagePort>, PassRefPtr<MessagePort>); + static PassRefPtr<PlatformMessagePortChannel> create(); + static PassRefPtr<PlatformMessagePortChannel> create(WebKit::WebMessagePortChannel*); + + // APIs delegated from MessagePortChannel.h + bool entangleIfOpen(MessagePort*); + void disentangle(); + void postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData>); + bool tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>&); + void close(); + bool isConnectedTo(MessagePort* port); + bool hasPendingActivity(); + + // Releases ownership of the contained web channel. + WebKit::WebMessagePortChannel* webChannelRelease(); + + ~PlatformMessagePortChannel(); + + private: + PlatformMessagePortChannel(); + PlatformMessagePortChannel(WebKit::WebMessagePortChannel*); + + void setEntangledChannel(PassRefPtr<PlatformMessagePortChannel>); + + // WebKit::WebMessagePortChannelClient implementation + virtual void messageAvailable(); + + // Mutex used to ensure exclusive access to the object internals. + Mutex m_mutex; + + // Pointer to our entangled pair - cleared when close() is called. + RefPtr<PlatformMessagePortChannel> m_entangledChannel; + + // The port we are connected to - this is the port that is notified when new messages arrive. + MessagePort* m_localPort; + + WebKit::WebMessagePortChannel* m_webChannel; + }; + +} // namespace WebCore + +#endif // PlatformMessagePortChannel_h diff --git a/webkit/tools/test_shell/test_shell_webkit_init.h b/webkit/tools/test_shell/test_shell_webkit_init.h index 0c64142..dbb8e81 100644 --- a/webkit/tools/test_shell/test_shell_webkit_init.h +++ b/webkit/tools/test_shell/test_shell_webkit_init.h @@ -89,6 +89,10 @@ class TestShellWebKitInit : public webkit_glue::WebKitClientImpl { return false; } + virtual WebKit::WebMessagePortChannel* createMessagePortChannel() { + return NULL; + } + virtual void setCookies(const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies, const WebKit::WebString& value) { diff --git a/webkit/tools/test_shell/test_worker/test_worker_main.cc b/webkit/tools/test_shell/test_worker/test_worker_main.cc index 30b52da..2739640 100644 --- a/webkit/tools/test_shell/test_worker/test_worker_main.cc +++ b/webkit/tools/test_shell/test_worker/test_worker_main.cc @@ -59,6 +59,10 @@ class WorkerWebKitClientImpl : public webkit_glue::WebKitClientImpl { return false; } + virtual WebKit::WebMessagePortChannel* createMessagePortChannel() { + return NULL; + } + virtual void setCookies(const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies, const WebKit::WebString& value) { diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp index 85505ae..17531ce 100644 --- a/webkit/webkit.gyp +++ b/webkit/webkit.gyp @@ -706,6 +706,10 @@ '../third_party/WebKit/WebCore/platform/graphics/RenderLayerBacking.cpp', '../third_party/WebKit/WebCore/platform/graphics/RenderLayerCompositor.cpp', + # We use a multi-process version from the WebKit API. + '../third_party/WebKit/WebCore/dom/default/PlatformMessagePortChannel.cpp', + '../third_party/WebKit/WebCore/dom/default/PlatformMessagePortChannel.h', + ], 'direct_dependent_settings': { 'include_dirs': [ @@ -997,6 +1001,8 @@ 'api/public/WebLocalizedString.h', 'api/public/WebMediaPlayer.h', 'api/public/WebMediaPlayerClient.h', + 'api/public/WebMessagePortChannel.h', + 'api/public/WebMessagePortChannelClient.h', 'api/public/WebMimeRegistry.h', 'api/public/WebNavigationType.h', 'api/public/WebNode.h', @@ -1022,6 +1028,8 @@ 'api/public/WebVector.h', 'api/public/WebWidget.h', 'api/public/WebWidgetClient.h', + 'api/public/WebWorker.h', + 'api/public/WebWorkerClient.h', 'api/public/win/WebInputEventFactory.h', 'api/public/win/WebSandboxSupport.h', 'api/public/win/WebScreenInfoFactory.h', @@ -1038,6 +1046,8 @@ 'api/src/mac/WebScreenInfoFactory.mm', 'api/src/LocalizedStrings.cpp', 'api/src/MediaPlayerPrivateChromium.cpp', + 'api/src/PlatformMessagePortChannel.cpp', + 'api/src/PlatformMessagePortChannel.h', 'api/src/ResourceHandle.cpp', 'api/src/StorageAreaProxy.cpp', 'api/src/StorageAreaProxy.h', |