Home | History | Annotate | Download | only in renderer
      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 
     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 
     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 
     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 
     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 
     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 
     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 
     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 
    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 
    111 void WebSharedWorkerProxy::OnWorkerScriptLoadFailed() {
    112   if (connect_listener_) {
    113     // This can result in this object being freed.
    114     connect_listener_->scriptLoadFailed();
    115   }
    116 }
    117 
    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