summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/notification_type.h4
-rw-r--r--chrome/common/webmessageportchannel_impl.cc204
-rw-r--r--chrome/common/webmessageportchannel_impl.h73
-rw-r--r--chrome/common/worker_messages.h2
-rw-r--r--chrome/common/worker_messages_internal.h58
5 files changed, 338 insertions, 3 deletions
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