• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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