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/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"
28 // IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle.
29 // It communicates with the main browser process via SocketStreamDispatcher.
30 class IPCWebSocketStreamHandleBridge
: public WebSocketStreamHandleBridge
{
32 IPCWebSocketStreamHandleBridge(blink::WebSocketStreamHandle
* handle
,
33 WebSocketStreamHandleDelegate
* delegate
)
34 : socket_id_(kNoSocketId
), handle_(handle
), delegate_(delegate
) {}
36 // Returns the handle having given id or NULL if there is no such handle.
37 static IPCWebSocketStreamHandleBridge
* FromSocketId(int id
);
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
;
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
);
49 void OnFailed(int error_code
, const char* error_msg
);
52 virtual ~IPCWebSocketStreamHandleBridge();
54 // The ID for this bridge and corresponding SocketStream instance in the
58 blink::WebSocketStreamHandle
* handle_
;
59 WebSocketStreamHandleDelegate
* delegate_
;
61 // Map from ID to bridge instance.
62 static base::LazyInstance
<IDMap
<IPCWebSocketStreamHandleBridge
> >::Leaky
67 base::LazyInstance
<IDMap
<IPCWebSocketStreamHandleBridge
> >::Leaky
68 IPCWebSocketStreamHandleBridge::all_bridges
= LAZY_INSTANCE_INITIALIZER
;
71 IPCWebSocketStreamHandleBridge
* IPCWebSocketStreamHandleBridge::FromSocketId(
73 return all_bridges
.Get().Lookup(id
);
76 IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() {
77 DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_
80 if (socket_id_
== kNoSocketId
)
83 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_
));
84 socket_id_
= kNoSocketId
;
87 void IPCWebSocketStreamHandleBridge::Connect(const GURL
& url
) {
88 DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url
<< ")";
90 DCHECK_EQ(socket_id_
, kNoSocketId
);
92 delegate_
->WillOpenStream(handle_
, url
);
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_
));
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.
110 bool IPCWebSocketStreamHandleBridge::Send(const std::vector
<char>& data
) {
111 DVLOG(1) << "Bridge #" << socket_id_
<< " Send (" << data
.size()
114 ChildThread::current()->Send(
115 new SocketStreamHostMsg_SendData(socket_id_
, data
));
117 delegate_
->WillSendData(handle_
, &data
[0], data
.size());
121 void IPCWebSocketStreamHandleBridge::Close() {
122 DVLOG(1) << "Bridge #" << socket_id_
<< " Close";
124 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_
));
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
<< ")";
133 delegate_
->DidOpenStream(handle_
, max_pending_send_allowed
);
136 void IPCWebSocketStreamHandleBridge::OnSentData(int amount_sent
) {
137 DVLOG(1) << "Bridge #" << socket_id_
<< " OnSentData (" << amount_sent
141 delegate_
->DidSendData(handle_
, amount_sent
);
144 void IPCWebSocketStreamHandleBridge::OnReceivedData(
145 const std::vector
<char>& data
) {
146 DVLOG(1) << "Bridge #" << socket_id_
<< " OnReceiveData (" << data
.size()
149 delegate_
->DidReceiveData(handle_
, &data
[0], data
.size());
152 void IPCWebSocketStreamHandleBridge::OnClosed() {
153 DVLOG(1) << "Bridge #" << socket_id_
<< " OnClosed";
155 if (socket_id_
!= kNoSocketId
) {
156 all_bridges
.Get().Remove(socket_id_
);
157 socket_id_
= kNoSocketId
;
160 delegate_
->DidClose(handle_
);
165 void IPCWebSocketStreamHandleBridge::OnFailed(int error_code
,
166 const char* error_msg
) {
167 DVLOG(1) << "Bridge #" << socket_id_
<< " OnFailed (error_code=" << error_code
170 delegate_
->DidFail(handle_
, error_code
, base::ASCIIToUTF16(error_msg
));
173 SocketStreamDispatcher::SocketStreamDispatcher() {
177 WebSocketStreamHandleBridge
* SocketStreamDispatcher::CreateBridge(
178 blink::WebSocketStreamHandle
* handle
,
179 WebSocketStreamHandleDelegate
* delegate
) {
180 return new IPCWebSocketStreamHandleBridge(handle
, delegate
);
183 bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
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()
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
;
201 IPCWebSocketStreamHandleBridge
* bridge
=
202 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
204 bridge
->OnConnected(max_pending_send_allowed
);
206 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
209 void SocketStreamDispatcher::OnSentData(int socket_id
, int amount_sent
) {
210 DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent
211 << " bytes) to socket_id=" << socket_id
;
213 IPCWebSocketStreamHandleBridge
* bridge
=
214 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
216 bridge
->OnSentData(amount_sent
);
218 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
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
;
226 IPCWebSocketStreamHandleBridge
* bridge
=
227 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
229 bridge
->OnReceivedData(data
);
231 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
234 void SocketStreamDispatcher::OnClosed(int socket_id
) {
235 DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id
;
237 IPCWebSocketStreamHandleBridge
* bridge
=
238 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
242 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
245 void SocketStreamDispatcher::OnFailed(int socket_id
, int error_code
) {
246 IPCWebSocketStreamHandleBridge
* bridge
=
247 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
249 bridge
->OnFailed(error_code
, net::ErrorToString(error_code
));
251 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
254 } // namespace content