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.
5 #include "content/child/socket_stream_dispatcher.h"
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"
29 // IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle.
30 // It communicates with the main browser process via SocketStreamDispatcher.
31 class IPCWebSocketStreamHandleBridge
: public WebSocketStreamHandleBridge
{
33 IPCWebSocketStreamHandleBridge(blink::WebSocketStreamHandle
* handle
,
34 WebSocketStreamHandleDelegate
* delegate
)
35 : socket_id_(kNoSocketId
), handle_(handle
), delegate_(delegate
) {}
37 // Returns the handle having given id or NULL if there is no such handle.
38 static IPCWebSocketStreamHandleBridge
* FromSocketId(int id
);
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
;
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
);
50 void OnFailed(int error_code
, const std::string
& error_msg
);
53 virtual ~IPCWebSocketStreamHandleBridge();
55 // The ID for this bridge and corresponding SocketStream instance in the
59 blink::WebSocketStreamHandle
* handle_
;
60 WebSocketStreamHandleDelegate
* delegate_
;
62 // Map from ID to bridge instance.
63 static base::LazyInstance
<IDMap
<IPCWebSocketStreamHandleBridge
> >::Leaky
68 base::LazyInstance
<IDMap
<IPCWebSocketStreamHandleBridge
> >::Leaky
69 IPCWebSocketStreamHandleBridge::all_bridges
= LAZY_INSTANCE_INITIALIZER
;
72 IPCWebSocketStreamHandleBridge
* IPCWebSocketStreamHandleBridge::FromSocketId(
74 return all_bridges
.Get().Lookup(id
);
77 IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() {
78 DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_
81 if (socket_id_
== kNoSocketId
)
84 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_
));
85 socket_id_
= kNoSocketId
;
88 void IPCWebSocketStreamHandleBridge::Connect(const GURL
& url
) {
89 DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url
<< ")";
91 DCHECK_EQ(socket_id_
, kNoSocketId
);
93 delegate_
->WillOpenStream(handle_
, url
);
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_
));
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.
111 bool IPCWebSocketStreamHandleBridge::Send(const std::vector
<char>& data
) {
112 DVLOG(1) << "Bridge #" << socket_id_
<< " Send (" << data
.size()
115 ChildThread::current()->Send(
116 new SocketStreamHostMsg_SendData(socket_id_
, data
));
118 delegate_
->WillSendData(handle_
, &data
[0], data
.size());
122 void IPCWebSocketStreamHandleBridge::Close() {
123 DVLOG(1) << "Bridge #" << socket_id_
<< " Close";
125 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_
));
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
<< ")";
134 delegate_
->DidOpenStream(handle_
, max_pending_send_allowed
);
137 void IPCWebSocketStreamHandleBridge::OnSentData(int amount_sent
) {
138 DVLOG(1) << "Bridge #" << socket_id_
<< " OnSentData (" << amount_sent
142 delegate_
->DidSendData(handle_
, amount_sent
);
145 void IPCWebSocketStreamHandleBridge::OnReceivedData(
146 const std::vector
<char>& data
) {
147 DVLOG(1) << "Bridge #" << socket_id_
<< " OnReceiveData (" << data
.size()
150 delegate_
->DidReceiveData(handle_
, &data
[0], data
.size());
153 void IPCWebSocketStreamHandleBridge::OnClosed() {
154 DVLOG(1) << "Bridge #" << socket_id_
<< " OnClosed";
156 if (socket_id_
!= kNoSocketId
) {
157 all_bridges
.Get().Remove(socket_id_
);
158 socket_id_
= kNoSocketId
;
161 delegate_
->DidClose(handle_
);
166 void IPCWebSocketStreamHandleBridge::OnFailed(int error_code
,
167 const std::string
& error_msg
) {
168 DVLOG(1) << "Bridge #" << socket_id_
<< " OnFailed (error_code=" << error_code
171 delegate_
->DidFail(handle_
, error_code
, base::ASCIIToUTF16(error_msg
));
174 SocketStreamDispatcher::SocketStreamDispatcher() {
178 WebSocketStreamHandleBridge
* SocketStreamDispatcher::CreateBridge(
179 blink::WebSocketStreamHandle
* handle
,
180 WebSocketStreamHandleDelegate
* delegate
) {
181 return new IPCWebSocketStreamHandleBridge(handle
, delegate
);
184 bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
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()
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
;
202 IPCWebSocketStreamHandleBridge
* bridge
=
203 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
205 bridge
->OnConnected(max_pending_send_allowed
);
207 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
210 void SocketStreamDispatcher::OnSentData(int socket_id
, int amount_sent
) {
211 DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent
212 << " bytes) to socket_id=" << socket_id
;
214 IPCWebSocketStreamHandleBridge
* bridge
=
215 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
217 bridge
->OnSentData(amount_sent
);
219 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
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
;
227 IPCWebSocketStreamHandleBridge
* bridge
=
228 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
230 bridge
->OnReceivedData(data
);
232 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
235 void SocketStreamDispatcher::OnClosed(int socket_id
) {
236 DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id
;
238 IPCWebSocketStreamHandleBridge
* bridge
=
239 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
243 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
246 void SocketStreamDispatcher::OnFailed(int socket_id
, int error_code
) {
247 IPCWebSocketStreamHandleBridge
* bridge
=
248 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
250 bridge
->OnFailed(error_code
, net::ErrorToString(error_code
));
252 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
255 } // namespace content