| OLD | NEW |
| (Empty) |
| 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 void Connect(const GURL& url) override; | |
| 42 bool Send(const std::vector<char>& data) override; | |
| 43 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 ~IPCWebSocketStreamHandleBridge() override; | |
| 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 | |
| OLD | NEW |