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:
IPCWebSocketStreamHandleBridge(blink::WebSocketStreamHandle * handle,WebSocketStreamHandleDelegate * delegate)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 */
FromSocketId(int id)72 IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId(
73 int id) {
74 return all_bridges.Get().Lookup(id);
75 }
76
~IPCWebSocketStreamHandleBridge()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
Connect(const GURL & url)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
Send(const std::vector<char> & data)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
Close()122 void IPCWebSocketStreamHandleBridge::Close() {
123 DVLOG(1) << "Bridge #" << socket_id_ << " Close";
124
125 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
126 }
127
OnConnected(int max_pending_send_allowed)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
OnSentData(int amount_sent)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
OnReceivedData(const std::vector<char> & data)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
OnClosed()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
OnFailed(int error_code,const std::string & error_msg)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
SocketStreamDispatcher()174 SocketStreamDispatcher::SocketStreamDispatcher() {
175 }
176
177 // static
CreateBridge(blink::WebSocketStreamHandle * handle,WebSocketStreamHandleDelegate * delegate)178 WebSocketStreamHandleBridge* SocketStreamDispatcher::CreateBridge(
179 blink::WebSocketStreamHandle* handle,
180 WebSocketStreamHandleDelegate* delegate) {
181 return new IPCWebSocketStreamHandleBridge(handle, delegate);
182 }
183
OnMessageReceived(const IPC::Message & msg)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
OnConnected(int socket_id,int max_pending_send_allowed)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
OnSentData(int socket_id,int amount_sent)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
OnReceivedData(int socket_id,const std::vector<char> & data)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
OnClosed(int socket_id)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
OnFailed(int socket_id,int error_code)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