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