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.
4
5 #include "content/renderer/websharedworker_proxy.h"
6
7 #include "content/child/webmessageportchannel_impl.h"
8 #include "content/common/message_router.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"
13
14 namespace content {
15
WebSharedWorkerProxy(MessageRouter * router,unsigned long long document_id,int route_id,int render_frame_route_id)16 WebSharedWorkerProxy::WebSharedWorkerProxy(MessageRouter* router,
17 unsigned long long document_id,
18 int route_id,
19 int render_frame_route_id)
20 : route_id_(route_id),
21 render_frame_route_id_(render_frame_route_id),
22 router_(router),
23 document_id_(document_id),
24 pending_route_id_(route_id),
25 connect_listener_(NULL),
26 created_(false) {
27 router_->AddRoute(route_id_, this);
28 }
29
~WebSharedWorkerProxy()30 WebSharedWorkerProxy::~WebSharedWorkerProxy() {
31 Disconnect();
32
33 // Free up any unsent queued messages.
34 for (size_t i = 0; i < queued_messages_.size(); ++i)
35 delete queued_messages_[i];
36 }
37
Disconnect()38 void WebSharedWorkerProxy::Disconnect() {
39 if (route_id_ == MSG_ROUTING_NONE)
40 return;
41
42 // So the messages from WorkerContext (like WorkerContextDestroyed) do not
43 // come after nobody is listening. Since Worker and WorkerContext can
44 // terminate independently, already sent messages may still be in the pipe.
45 router_->RemoveRoute(route_id_);
46
47 route_id_ = MSG_ROUTING_NONE;
48 }
49
Send(IPC::Message * message)50 bool WebSharedWorkerProxy::Send(IPC::Message* message) {
51 // It's possible that messages will be sent before the worker is created, in
52 // which case route_id_ will be none. Or the worker object can be interacted
53 // with before the browser process told us that it started, in which case we
54 // also want to queue the message.
55 if (!created_) {
56 queued_messages_.push_back(message);
57 return true;
58 }
59
60 // For now we proxy all messages to the worker process through the browser.
61 // Revisit if we find this slow.
62 // TODO(jabdelmalek): handle sync messages if we need them.
63 IPC::Message* wrapped_msg = new ViewHostMsg_ForwardToWorker(*message);
64 delete message;
65 return router_->Send(wrapped_msg);
66 }
67
SendQueuedMessages()68 void WebSharedWorkerProxy::SendQueuedMessages() {
69 DCHECK(queued_messages_.size());
70 std::vector<IPC::Message*> queued_messages = queued_messages_;
71 queued_messages_.clear();
72 for (size_t i = 0; i < queued_messages.size(); ++i) {
73 queued_messages[i]->set_routing_id(route_id_);
74 Send(queued_messages[i]);
75 }
76 }
77
connect(blink::WebMessagePortChannel * channel,ConnectListener * listener)78 void WebSharedWorkerProxy::connect(blink::WebMessagePortChannel* channel,
79 ConnectListener* listener) {
80 WebMessagePortChannelImpl* webchannel =
81 static_cast<WebMessagePortChannelImpl*>(channel);
82
83 int message_port_id = webchannel->message_port_id();
84 DCHECK(message_port_id != MSG_ROUTING_NONE);
85 webchannel->QueueMessages();
86
87 Send(new WorkerMsg_Connect(route_id_, message_port_id, MSG_ROUTING_NONE));
88 connect_listener_ = listener;
89 }
90
OnMessageReceived(const IPC::Message & message)91 bool WebSharedWorkerProxy::OnMessageReceived(const IPC::Message& message) {
92 bool handled = true;
93 IPC_BEGIN_MESSAGE_MAP(WebSharedWorkerProxy, message)
94 IPC_MESSAGE_HANDLER(ViewMsg_WorkerCreated, OnWorkerCreated)
95 IPC_MESSAGE_HANDLER(ViewMsg_WorkerScriptLoadFailed,
96 OnWorkerScriptLoadFailed)
97 IPC_MESSAGE_HANDLER(ViewMsg_WorkerConnected,
98 OnWorkerConnected)
99 IPC_MESSAGE_UNHANDLED(handled = false)
100 IPC_END_MESSAGE_MAP()
101 return handled;
102 }
103
OnWorkerCreated()104 void WebSharedWorkerProxy::OnWorkerCreated() {
105 created_ = true;
106 // The worker is created - now send off the WorkerMsg_Connect message and
107 // any other queued messages
108 SendQueuedMessages();
109 }
110
OnWorkerScriptLoadFailed()111 void WebSharedWorkerProxy::OnWorkerScriptLoadFailed() {
112 if (connect_listener_) {
113 // This can result in this object being freed.
114 connect_listener_->scriptLoadFailed();
115 }
116 }
117
OnWorkerConnected()118 void WebSharedWorkerProxy::OnWorkerConnected() {
119 if (connect_listener_) {
120 // This can result in this object being freed.
121 connect_listener_->connected();
122 }
123 }
124
125 } // namespace content
126