Home | History | Annotate | Download | only in child
      1 // Copyright (c) 2012 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/child/socket_stream_dispatcher.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/id_map.h"
     11 #include "base/lazy_instance.h"
     12 #include "base/memory/ref_counted.h"
     13 #include "base/message_loop/message_loop.h"
     14 #include "base/strings/string16.h"
     15 #include "base/strings/utf_string_conversions.h"
     16 #include "content/child/child_thread.h"
     17 #include "content/child/web_socket_stream_handle_bridge.h"
     18 #include "content/child/web_socket_stream_handle_delegate.h"
     19 #include "content/child/web_socket_stream_handle_impl.h"
     20 #include "content/common/socket_stream.h"
     21 #include "content/common/socket_stream_handle_data.h"
     22 #include "content/common/socket_stream_messages.h"
     23 #include "net/base/net_errors.h"
     24 #include "url/gurl.h"
     25 
     26 namespace content {
     27 
     28 // IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle.
     29 // It communicates with the main browser process via SocketStreamDispatcher.
     30 class IPCWebSocketStreamHandleBridge : public WebSocketStreamHandleBridge {
     31  public:
     32   IPCWebSocketStreamHandleBridge(blink::WebSocketStreamHandle* handle,
     33                                  WebSocketStreamHandleDelegate* delegate)
     34       : socket_id_(kNoSocketId), handle_(handle), delegate_(delegate) {}
     35 
     36   // Returns the handle having given id or NULL if there is no such handle.
     37   static IPCWebSocketStreamHandleBridge* FromSocketId(int id);
     38 
     39   // WebSocketStreamHandleBridge methods.
     40   virtual void Connect(const GURL& url) OVERRIDE;
     41   virtual bool Send(const std::vector<char>& data) OVERRIDE;
     42   virtual void Close() OVERRIDE;
     43 
     44   // Called by SocketStreamDispatcher.
     45   void OnConnected(int max_amount_send_allowed);
     46   void OnSentData(int amount_sent);
     47   void OnReceivedData(const std::vector<char>& data);
     48   void OnClosed();
     49   void OnFailed(int error_code, const char* error_msg);
     50 
     51  private:
     52   virtual ~IPCWebSocketStreamHandleBridge();
     53 
     54   // The ID for this bridge and corresponding SocketStream instance in the
     55   // browser process.
     56   int socket_id_;
     57 
     58   blink::WebSocketStreamHandle* handle_;
     59   WebSocketStreamHandleDelegate* delegate_;
     60 
     61   // Map from ID to bridge instance.
     62   static base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
     63       all_bridges;
     64 };
     65 
     66 // static
     67 base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
     68     IPCWebSocketStreamHandleBridge::all_bridges = LAZY_INSTANCE_INITIALIZER;
     69 
     70 /* static */
     71 IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId(
     72     int id) {
     73   return all_bridges.Get().Lookup(id);
     74 }
     75 
     76 IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() {
     77   DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_
     78            << ") Destructor";
     79 
     80   if (socket_id_ == kNoSocketId)
     81     return;
     82 
     83   ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
     84   socket_id_ = kNoSocketId;
     85 }
     86 
     87 void IPCWebSocketStreamHandleBridge::Connect(const GURL& url) {
     88   DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url << ")";
     89 
     90   DCHECK_EQ(socket_id_, kNoSocketId);
     91   if (delegate_)
     92     delegate_->WillOpenStream(handle_, url);
     93 
     94   socket_id_ = all_bridges.Get().Add(this);
     95   DCHECK_NE(socket_id_, kNoSocketId);
     96   int render_frame_id = MSG_ROUTING_NONE;
     97   WebSocketStreamHandleImpl* impl =
     98       static_cast<WebSocketStreamHandleImpl*>(handle_);
     99   const SocketStreamHandleData* data =
    100       static_cast<SocketStreamHandleData*>(impl->GetUserData(handle_));
    101   if (data)
    102     render_frame_id = data->render_frame_id();
    103   AddRef();  // Released in OnClosed().
    104   ChildThread::current()->Send(
    105       new SocketStreamHostMsg_Connect(render_frame_id, url, socket_id_));
    106   DVLOG(1) << "Bridge #" << socket_id_ << " sent IPC Connect";
    107   // TODO(ukai): timeout to OnConnected.
    108 }
    109 
    110 bool IPCWebSocketStreamHandleBridge::Send(const std::vector<char>& data) {
    111   DVLOG(1) << "Bridge #" << socket_id_ << " Send (" << data.size()
    112            << " bytes)";
    113 
    114   ChildThread::current()->Send(
    115       new SocketStreamHostMsg_SendData(socket_id_, data));
    116   if (delegate_)
    117     delegate_->WillSendData(handle_, &data[0], data.size());
    118   return true;
    119 }
    120 
    121 void IPCWebSocketStreamHandleBridge::Close() {
    122   DVLOG(1) << "Bridge #" << socket_id_ << " Close";
    123 
    124   ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
    125 }
    126 
    127 void IPCWebSocketStreamHandleBridge::OnConnected(int max_pending_send_allowed) {
    128   DVLOG(1) << "Bridge #" << socket_id_
    129            << " OnConnected (max_pending_send_allowed="
    130            << max_pending_send_allowed << ")";
    131 
    132   if (delegate_)
    133     delegate_->DidOpenStream(handle_, max_pending_send_allowed);
    134 }
    135 
    136 void IPCWebSocketStreamHandleBridge::OnSentData(int amount_sent) {
    137   DVLOG(1) << "Bridge #" << socket_id_ << " OnSentData (" << amount_sent
    138            << " bytes)";
    139 
    140   if (delegate_)
    141     delegate_->DidSendData(handle_, amount_sent);
    142 }
    143 
    144 void IPCWebSocketStreamHandleBridge::OnReceivedData(
    145     const std::vector<char>& data) {
    146   DVLOG(1) << "Bridge #" << socket_id_ << " OnReceiveData (" << data.size()
    147            << " bytes)";
    148   if (delegate_)
    149     delegate_->DidReceiveData(handle_, &data[0], data.size());
    150 }
    151 
    152 void IPCWebSocketStreamHandleBridge::OnClosed() {
    153   DVLOG(1) << "Bridge #" << socket_id_ << " OnClosed";
    154 
    155   if (socket_id_ != kNoSocketId) {
    156     all_bridges.Get().Remove(socket_id_);
    157     socket_id_ = kNoSocketId;
    158   }
    159   if (delegate_)
    160     delegate_->DidClose(handle_);
    161   delegate_ = NULL;
    162   Release();
    163 }
    164 
    165 void IPCWebSocketStreamHandleBridge::OnFailed(int error_code,
    166                                               const char* error_msg) {
    167   DVLOG(1) << "Bridge #" << socket_id_ << " OnFailed (error_code=" << error_code
    168            << ")";
    169   if (delegate_)
    170     delegate_->DidFail(handle_, error_code, base::ASCIIToUTF16(error_msg));
    171 }
    172 
    173 SocketStreamDispatcher::SocketStreamDispatcher() {
    174 }
    175 
    176 // static
    177 WebSocketStreamHandleBridge* SocketStreamDispatcher::CreateBridge(
    178     blink::WebSocketStreamHandle* handle,
    179     WebSocketStreamHandleDelegate* delegate) {
    180   return new IPCWebSocketStreamHandleBridge(handle, delegate);
    181 }
    182 
    183 bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message& msg) {
    184   bool handled = true;
    185   IPC_BEGIN_MESSAGE_MAP(SocketStreamDispatcher, msg)
    186     IPC_MESSAGE_HANDLER(SocketStreamMsg_Connected, OnConnected)
    187     IPC_MESSAGE_HANDLER(SocketStreamMsg_SentData, OnSentData)
    188     IPC_MESSAGE_HANDLER(SocketStreamMsg_ReceivedData, OnReceivedData)
    189     IPC_MESSAGE_HANDLER(SocketStreamMsg_Closed, OnClosed)
    190     IPC_MESSAGE_HANDLER(SocketStreamMsg_Failed, OnFailed)
    191     IPC_MESSAGE_UNHANDLED(handled = false)
    192   IPC_END_MESSAGE_MAP()
    193   return handled;
    194 }
    195 
    196 void SocketStreamDispatcher::OnConnected(int socket_id,
    197                                          int max_pending_send_allowed) {
    198   DVLOG(1) << "SocketStreamDispatcher::OnConnected (max_pending_send_allowed="
    199            << max_pending_send_allowed << ") to socket_id=" << socket_id;
    200 
    201   IPCWebSocketStreamHandleBridge* bridge =
    202       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
    203   if (bridge)
    204     bridge->OnConnected(max_pending_send_allowed);
    205   else
    206     DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
    207 }
    208 
    209 void SocketStreamDispatcher::OnSentData(int socket_id, int amount_sent) {
    210   DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent
    211            << " bytes) to socket_id=" << socket_id;
    212 
    213   IPCWebSocketStreamHandleBridge* bridge =
    214       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
    215   if (bridge)
    216     bridge->OnSentData(amount_sent);
    217   else
    218     DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
    219 }
    220 
    221 void SocketStreamDispatcher::OnReceivedData(
    222     int socket_id, const std::vector<char>& data) {
    223   DVLOG(1) << "SocketStreamDispatcher::OnReceivedData (" << data.size()
    224            << " bytes) to socket_id=" << socket_id;
    225 
    226   IPCWebSocketStreamHandleBridge* bridge =
    227       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
    228   if (bridge)
    229     bridge->OnReceivedData(data);
    230   else
    231     DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
    232 }
    233 
    234 void SocketStreamDispatcher::OnClosed(int socket_id) {
    235   DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id;
    236 
    237   IPCWebSocketStreamHandleBridge* bridge =
    238       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
    239   if (bridge)
    240     bridge->OnClosed();
    241   else
    242     DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
    243 }
    244 
    245 void SocketStreamDispatcher::OnFailed(int socket_id, int error_code) {
    246   IPCWebSocketStreamHandleBridge* bridge =
    247       IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
    248   if (bridge)
    249     bridge->OnFailed(error_code, net::ErrorToString(error_code));
    250   else
    251     DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
    252 }
    253 
    254 }  // namespace content
    255