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/common/socket_stream.h" 18 #include "content/common/socket_stream_handle_data.h" 19 #include "content/common/socket_stream_messages.h" 20 #include "net/base/net_errors.h" 21 #include "url/gurl.h" 22 #include "webkit/child/websocketstreamhandle_bridge.h" 23 #include "webkit/child/websocketstreamhandle_delegate.h" 24 25 namespace content { 26 27 // IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle. 28 // It communicates with the main browser process via SocketStreamDispatcher. 29 class IPCWebSocketStreamHandleBridge 30 : public webkit_glue::WebSocketStreamHandleBridge { 31 public: 32 IPCWebSocketStreamHandleBridge( 33 blink::WebSocketStreamHandle* handle, 34 webkit_glue::WebSocketStreamHandleDelegate* delegate) 35 : socket_id_(kNoSocketId), 36 handle_(handle), 37 delegate_(delegate) {} 38 39 // Returns the handle having given id or NULL if there is no such handle. 40 static IPCWebSocketStreamHandleBridge* FromSocketId(int id); 41 42 // webkit_glue::WebSocketStreamHandleBridge methods. 43 virtual void Connect(const GURL& url) OVERRIDE; 44 virtual bool Send(const std::vector<char>& data) OVERRIDE; 45 virtual void Close() OVERRIDE; 46 47 // Called by SocketStreamDispatcher. 48 void OnConnected(int max_amount_send_allowed); 49 void OnSentData(int amount_sent); 50 void OnReceivedData(const std::vector<char>& data); 51 void OnClosed(); 52 void OnFailed(int error_code, const char* error_msg); 53 54 private: 55 virtual ~IPCWebSocketStreamHandleBridge(); 56 57 // The ID for this bridge and corresponding SocketStream instance in the 58 // browser process. 59 int socket_id_; 60 61 blink::WebSocketStreamHandle* handle_; 62 webkit_glue::WebSocketStreamHandleDelegate* delegate_; 63 64 // Map from ID to bridge instance. 65 static base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky 66 all_bridges; 67 }; 68 69 // static 70 base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky 71 IPCWebSocketStreamHandleBridge::all_bridges = LAZY_INSTANCE_INITIALIZER; 72 73 /* static */ 74 IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId( 75 int id) { 76 return all_bridges.Get().Lookup(id); 77 } 78 79 IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() { 80 DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_ 81 << ") Destructor"; 82 83 if (socket_id_ == kNoSocketId) 84 return; 85 86 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_)); 87 socket_id_ = kNoSocketId; 88 } 89 90 void IPCWebSocketStreamHandleBridge::Connect(const GURL& url) { 91 DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url << ")"; 92 93 DCHECK_EQ(socket_id_, kNoSocketId); 94 if (delegate_) 95 delegate_->WillOpenStream(handle_, url); 96 97 socket_id_ = all_bridges.Get().Add(this); 98 DCHECK_NE(socket_id_, kNoSocketId); 99 int render_view_id = MSG_ROUTING_NONE; 100 const SocketStreamHandleData* data = 101 SocketStreamHandleData::ForHandle(handle_); 102 if (data) 103 render_view_id = data->render_view_id(); 104 AddRef(); // Released in OnClosed(). 105 ChildThread::current()->Send( 106 new SocketStreamHostMsg_Connect(render_view_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 char* error_msg) { 168 DVLOG(1) << "Bridge #" << socket_id_ << " OnFailed (error_code=" << error_code 169 << ")"; 170 if (delegate_) 171 delegate_->DidFail(handle_, error_code, ASCIIToUTF16(error_msg)); 172 } 173 174 SocketStreamDispatcher::SocketStreamDispatcher() { 175 } 176 177 /* static */ 178 webkit_glue::WebSocketStreamHandleBridge* 179 SocketStreamDispatcher::CreateBridge( 180 blink::WebSocketStreamHandle* handle, 181 webkit_glue::WebSocketStreamHandleDelegate* delegate) { 182 return new IPCWebSocketStreamHandleBridge(handle, delegate); 183 } 184 185 bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message& msg) { 186 bool handled = true; 187 IPC_BEGIN_MESSAGE_MAP(SocketStreamDispatcher, msg) 188 IPC_MESSAGE_HANDLER(SocketStreamMsg_Connected, OnConnected) 189 IPC_MESSAGE_HANDLER(SocketStreamMsg_SentData, OnSentData) 190 IPC_MESSAGE_HANDLER(SocketStreamMsg_ReceivedData, OnReceivedData) 191 IPC_MESSAGE_HANDLER(SocketStreamMsg_Closed, OnClosed) 192 IPC_MESSAGE_HANDLER(SocketStreamMsg_Failed, OnFailed) 193 IPC_MESSAGE_UNHANDLED(handled = false) 194 IPC_END_MESSAGE_MAP() 195 return handled; 196 } 197 198 void SocketStreamDispatcher::OnConnected(int socket_id, 199 int max_pending_send_allowed) { 200 DVLOG(1) << "SocketStreamDispatcher::OnConnected (max_pending_send_allowed=" 201 << max_pending_send_allowed << ") to socket_id=" << socket_id; 202 203 IPCWebSocketStreamHandleBridge* bridge = 204 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id); 205 if (bridge) 206 bridge->OnConnected(max_pending_send_allowed); 207 else 208 DLOG(ERROR) << "No bridge for socket_id=" << socket_id; 209 } 210 211 void SocketStreamDispatcher::OnSentData(int socket_id, int amount_sent) { 212 DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent 213 << " bytes) to socket_id=" << socket_id; 214 215 IPCWebSocketStreamHandleBridge* bridge = 216 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id); 217 if (bridge) 218 bridge->OnSentData(amount_sent); 219 else 220 DLOG(ERROR) << "No bridge for socket_id=" << socket_id; 221 } 222 223 void SocketStreamDispatcher::OnReceivedData( 224 int socket_id, const std::vector<char>& data) { 225 DVLOG(1) << "SocketStreamDispatcher::OnReceivedData (" << data.size() 226 << " bytes) to socket_id=" << socket_id; 227 228 IPCWebSocketStreamHandleBridge* bridge = 229 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id); 230 if (bridge) 231 bridge->OnReceivedData(data); 232 else 233 DLOG(ERROR) << "No bridge for socket_id=" << socket_id; 234 } 235 236 void SocketStreamDispatcher::OnClosed(int socket_id) { 237 DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id; 238 239 IPCWebSocketStreamHandleBridge* bridge = 240 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id); 241 if (bridge) 242 bridge->OnClosed(); 243 else 244 DLOG(ERROR) << "No bridge for socket_id=" << socket_id; 245 } 246 247 void SocketStreamDispatcher::OnFailed(int socket_id, int error_code) { 248 IPCWebSocketStreamHandleBridge* bridge = 249 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id); 250 if (bridge) 251 bridge->OnFailed(error_code, net::ErrorToString(error_code)); 252 else 253 DLOG(ERROR) << "No bridge for socket_id=" << socket_id; 254 } 255 256 } // namespace content 257