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