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 27namespace content { 28 29// IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle. 30// It communicates with the main browser process via SocketStreamDispatcher. 31class 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 68base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky 69 IPCWebSocketStreamHandleBridge::all_bridges = LAZY_INSTANCE_INITIALIZER; 70 71/* static */ 72IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId( 73 int id) { 74 return all_bridges.Get().Lookup(id); 75} 76 77IPCWebSocketStreamHandleBridge::~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 88void 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 111bool 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 122void IPCWebSocketStreamHandleBridge::Close() { 123 DVLOG(1) << "Bridge #" << socket_id_ << " Close"; 124 125 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_)); 126} 127 128void 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 137void 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 145void 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 153void 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 166void 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 174SocketStreamDispatcher::SocketStreamDispatcher() { 175} 176 177// static 178WebSocketStreamHandleBridge* SocketStreamDispatcher::CreateBridge( 179 blink::WebSocketStreamHandle* handle, 180 WebSocketStreamHandleDelegate* delegate) { 181 return new IPCWebSocketStreamHandleBridge(handle, delegate); 182} 183 184bool 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 197void 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 210void 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 222void 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 235void 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 246void 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