Index: content/renderer/websharedworker_proxy.cc |
diff --git a/content/renderer/websharedworker_proxy.cc b/content/renderer/websharedworker_proxy.cc |
index 203ec6bb39b9260c5b1297f6ec4548b5fdce6f39..6a94adf84a776264aa3efa3b0a654ad03dba8dbe 100644 |
--- a/content/renderer/websharedworker_proxy.cc |
+++ b/content/renderer/websharedworker_proxy.cc |
@@ -3,24 +3,110 @@ |
// found in the LICENSE file. |
#include "content/renderer/websharedworker_proxy.h" |
- |
+#include "content/common/child_thread.h" |
#include "content/common/view_messages.h" |
#include "content/common/webmessageportchannel_impl.h" |
#include "content/common/worker_messages.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebWorkerClient.h" |
WebSharedWorkerProxy::WebSharedWorkerProxy(ChildThread* child_thread, |
unsigned long long document_id, |
bool exists, |
int route_id, |
int render_view_route_id) |
- : WebWorkerBase(child_thread, |
- document_id, |
- exists ? route_id : MSG_ROUTING_NONE, |
- render_view_route_id, |
- 0), |
+ : route_id_(exists ? route_id : MSG_ROUTING_NONE), |
+ render_view_route_id_(render_view_route_id), |
+ child_thread_(child_thread), |
+ document_id_(document_id), |
pending_route_id_(route_id), |
connect_listener_(NULL) { |
+ if (route_id_ != MSG_ROUTING_NONE) |
+ child_thread_->AddRoute(route_id_, this); |
+} |
+ |
+WebSharedWorkerProxy::~WebSharedWorkerProxy() { |
+ Disconnect(); |
+ |
+ // Free up any unsent queued messages. |
+ for (size_t i = 0; i < queued_messages_.size(); ++i) |
+ delete queued_messages_[i]; |
+} |
+ |
+void WebSharedWorkerProxy::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 WebSharedWorkerProxy::CreateWorkerContext(const GURL& script_url, |
+ bool is_shared, |
+ const string16& name, |
+ const string16& user_agent, |
+ const string16& source_code, |
+ int pending_route_id, |
+ int64 script_resource_appcache_id) { |
+ DCHECK(route_id_ == MSG_ROUTING_NONE); |
+ ViewHostMsg_CreateWorker_Params params; |
+ params.url = script_url; |
+ params.name = name; |
+ params.document_id = document_id_; |
+ params.render_view_route_id = render_view_route_id_; |
+ params.route_id = pending_route_id; |
+ params.script_resource_appcache_id = script_resource_appcache_id; |
+ IPC::Message* create_message = new ViewHostMsg_CreateWorker( |
+ params, &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 WebSharedWorkerProxy::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 WebSharedWorkerProxy::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 WebSharedWorkerProxy::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]); |
+ } |
} |
bool WebSharedWorkerProxy::isStarted() { |
@@ -34,8 +120,8 @@ void WebSharedWorkerProxy::startWorkerContext( |
const WebKit::WebString& source_code, |
long long script_resource_appcache_id) { |
DCHECK(!isStarted()); |
- CreateSharedWorkerContext(script_url, name, user_agent, source_code, |
- pending_route_id_, script_resource_appcache_id); |
+ CreateWorkerContext(script_url, true, name, user_agent, source_code, |
+ pending_route_id_, script_resource_appcache_id); |
} |
void WebSharedWorkerProxy::terminateWorkerContext() { |