Refactor management of overview window copy lifetime into a separate class.
[chromium-blink-merge.git] / content / renderer / websharedworker_proxy.cc
blob190a35c59cfda690deeaf2d68606e708996c2a59
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/websharedworker_proxy.h"
7 #include "content/child/child_thread.h"
8 #include "content/child/webmessageportchannel_impl.h"
9 #include "content/common/view_messages.h"
10 #include "content/common/worker_messages.h"
11 #include "third_party/WebKit/public/platform/WebURL.h"
12 #include "third_party/WebKit/public/web/WebSharedWorkerClient.h"
14 namespace content {
16 WebSharedWorkerProxy::WebSharedWorkerProxy(ChildThread* child_thread,
17 unsigned long long document_id,
18 bool exists,
19 int route_id,
20 int render_view_route_id)
21 : route_id_(exists ? route_id : MSG_ROUTING_NONE),
22 render_view_route_id_(render_view_route_id),
23 child_thread_(child_thread),
24 document_id_(document_id),
25 pending_route_id_(route_id),
26 connect_listener_(NULL) {
27 if (route_id_ != MSG_ROUTING_NONE)
28 child_thread_->AddRoute(route_id_, this);
31 WebSharedWorkerProxy::~WebSharedWorkerProxy() {
32 Disconnect();
34 // Free up any unsent queued messages.
35 for (size_t i = 0; i < queued_messages_.size(); ++i)
36 delete queued_messages_[i];
39 void WebSharedWorkerProxy::Disconnect() {
40 if (route_id_ == MSG_ROUTING_NONE)
41 return;
43 // So the messages from WorkerContext (like WorkerContextDestroyed) do not
44 // come after nobody is listening. Since Worker and WorkerContext can
45 // terminate independently, already sent messages may still be in the pipe.
46 child_thread_->RemoveRoute(route_id_);
48 route_id_ = MSG_ROUTING_NONE;
51 void WebSharedWorkerProxy::CreateWorkerContext(
52 const GURL& script_url,
53 bool is_shared,
54 const string16& name,
55 const string16& user_agent,
56 const string16& source_code,
57 const string16& content_security_policy,
58 WebKit::WebContentSecurityPolicyType policy_type,
59 int pending_route_id,
60 int64 script_resource_appcache_id) {
61 DCHECK(route_id_ == MSG_ROUTING_NONE);
62 ViewHostMsg_CreateWorker_Params params;
63 params.url = script_url;
64 params.name = name;
65 params.document_id = document_id_;
66 params.render_view_route_id = render_view_route_id_;
67 params.route_id = pending_route_id;
68 params.script_resource_appcache_id = script_resource_appcache_id;
69 IPC::Message* create_message = new ViewHostMsg_CreateWorker(
70 params, &route_id_);
71 child_thread_->Send(create_message);
72 if (route_id_ == MSG_ROUTING_NONE)
73 return;
75 child_thread_->AddRoute(route_id_, this);
77 // We make sure that the start message is the first, since postMessage or
78 // connect might have already been called.
79 queued_messages_.insert(queued_messages_.begin(),
80 new WorkerMsg_StartWorkerContext(
81 route_id_, script_url, user_agent, source_code,
82 content_security_policy, policy_type));
85 bool WebSharedWorkerProxy::IsStarted() {
86 // Worker is started if we have a route ID and there are no queued messages
87 // (meaning we've sent the WorkerMsg_StartWorkerContext already).
88 return (route_id_ != MSG_ROUTING_NONE && queued_messages_.empty());
91 bool WebSharedWorkerProxy::Send(IPC::Message* message) {
92 // It's possible that messages will be sent before the worker is created, in
93 // which case route_id_ will be none. Or the worker object can be interacted
94 // with before the browser process told us that it started, in which case we
95 // also want to queue the message.
96 if (!IsStarted()) {
97 queued_messages_.push_back(message);
98 return true;
101 // For now we proxy all messages to the worker process through the browser.
102 // Revisit if we find this slow.
103 // TODO(jabdelmalek): handle sync messages if we need them.
104 IPC::Message* wrapped_msg = new ViewHostMsg_ForwardToWorker(*message);
105 delete message;
106 return child_thread_->Send(wrapped_msg);
109 void WebSharedWorkerProxy::SendQueuedMessages() {
110 DCHECK(queued_messages_.size());
111 std::vector<IPC::Message*> queued_messages = queued_messages_;
112 queued_messages_.clear();
113 for (size_t i = 0; i < queued_messages.size(); ++i) {
114 queued_messages[i]->set_routing_id(route_id_);
115 Send(queued_messages[i]);
119 bool WebSharedWorkerProxy::isStarted() {
120 return IsStarted();
123 void WebSharedWorkerProxy::startWorkerContext(
124 const WebKit::WebURL& script_url,
125 const WebKit::WebString& name,
126 const WebKit::WebString& user_agent,
127 const WebKit::WebString& source_code,
128 const WebKit::WebString& content_security_policy,
129 WebKit::WebContentSecurityPolicyType policy_type,
130 long long script_resource_appcache_id) {
131 DCHECK(!isStarted());
132 CreateWorkerContext(
133 script_url, true, name, user_agent, source_code, content_security_policy,
134 policy_type, pending_route_id_, script_resource_appcache_id);
137 void WebSharedWorkerProxy::terminateWorkerContext() {
138 // This API should only be invoked from worker context.
139 NOTREACHED();
142 void WebSharedWorkerProxy::clientDestroyed() {
143 // This API should only be invoked from worker context.
144 NOTREACHED();
147 void WebSharedWorkerProxy::connect(WebKit::WebMessagePortChannel* channel,
148 ConnectListener* listener) {
149 WebMessagePortChannelImpl* webchannel =
150 static_cast<WebMessagePortChannelImpl*>(channel);
152 int message_port_id = webchannel->message_port_id();
153 DCHECK(message_port_id != MSG_ROUTING_NONE);
154 webchannel->QueueMessages();
156 Send(new WorkerMsg_Connect(route_id_, message_port_id, MSG_ROUTING_NONE));
157 if (HasQueuedMessages()) {
158 connect_listener_ = listener;
159 } else {
160 listener->connected();
161 // The listener may free this object, so do not access the object after
162 // this point.
166 bool WebSharedWorkerProxy::OnMessageReceived(const IPC::Message& message) {
167 bool handled = true;
168 IPC_BEGIN_MESSAGE_MAP(WebSharedWorkerProxy, message)
169 IPC_MESSAGE_HANDLER(ViewMsg_WorkerCreated, OnWorkerCreated)
170 IPC_MESSAGE_UNHANDLED(handled = false)
171 IPC_END_MESSAGE_MAP()
172 return handled;
175 void WebSharedWorkerProxy::OnWorkerCreated() {
176 // The worker is created - now send off the CreateWorkerContext message and
177 // any other queued messages
178 SendQueuedMessages();
180 // Inform any listener that the pending connect event has been sent
181 // (this can result in this object being freed).
182 if (connect_listener_) {
183 connect_listener_->connected();
187 } // namespace content