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/common/socket_stream.h"
18 #include "content/common/socket_stream_handle_data.h"
19 #include "content/common/socket_stream_messages.h"
20 #include "net/base/net_errors.h"
22 #include "webkit/child/websocketstreamhandle_bridge.h"
23 #include "webkit/child/websocketstreamhandle_delegate.h"
27 // IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle.
28 // It communicates with the main browser process via SocketStreamDispatcher.
29 class IPCWebSocketStreamHandleBridge
30 : public webkit_glue::WebSocketStreamHandleBridge
{
32 IPCWebSocketStreamHandleBridge(
33 WebKit::WebSocketStreamHandle
* handle
,
34 webkit_glue::WebSocketStreamHandleDelegate
* delegate
)
35 : socket_id_(kNoSocketId
),
37 delegate_(delegate
) {}
39 // Returns the handle having given id or NULL if there is no such handle.
40 static IPCWebSocketStreamHandleBridge
* FromSocketId(int id
);
42 // webkit_glue::WebSocketStreamHandleBridge methods.
43 virtual void Connect(const GURL
& url
) OVERRIDE
;
44 virtual bool Send(const std::vector
<char>& data
) OVERRIDE
;
45 virtual void Close() OVERRIDE
;
47 // Called by SocketStreamDispatcher.
48 void OnConnected(int max_amount_send_allowed
);
49 void OnSentData(int amount_sent
);
50 void OnReceivedData(const std::vector
<char>& data
);
52 void OnFailed(int error_code
, const char* error_msg
);
55 virtual ~IPCWebSocketStreamHandleBridge();
57 // The ID for this bridge and corresponding SocketStream instance in the
61 WebKit::WebSocketStreamHandle
* handle_
;
62 webkit_glue::WebSocketStreamHandleDelegate
* delegate_
;
64 // Map from ID to bridge instance.
65 static base::LazyInstance
<IDMap
<IPCWebSocketStreamHandleBridge
> >::Leaky
70 base::LazyInstance
<IDMap
<IPCWebSocketStreamHandleBridge
> >::Leaky
71 IPCWebSocketStreamHandleBridge::all_bridges
= LAZY_INSTANCE_INITIALIZER
;
74 IPCWebSocketStreamHandleBridge
* IPCWebSocketStreamHandleBridge::FromSocketId(
76 return all_bridges
.Get().Lookup(id
);
79 IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() {
80 DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_
83 if (socket_id_
== kNoSocketId
)
86 ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_
));
87 socket_id_
= kNoSocketId
;
90 void IPCWebSocketStreamHandleBridge::Connect(const GURL
& url
) {
91 DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url
<< ")";
93 DCHECK_EQ(socket_id_
, kNoSocketId
);
95 delegate_
->WillOpenStream(handle_
, url
);
97 socket_id_
= all_bridges
.Get().Add(this);
98 DCHECK_NE(socket_id_
, kNoSocketId
);
99 int render_view_id
= MSG_ROUTING_NONE
;
100 const SocketStreamHandleData
* data
=
101 SocketStreamHandleData::ForHandle(handle_
);
103 render_view_id
= data
->render_view_id();
104 AddRef(); // Released in OnClosed().
105 ChildThread::current()->Send(
106 new SocketStreamHostMsg_Connect(render_view_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 char* error_msg
) {
168 DVLOG(1) << "Bridge #" << socket_id_
<< " OnFailed (error_code=" << error_code
171 delegate_
->DidFail(handle_
, error_code
, ASCIIToUTF16(error_msg
));
174 SocketStreamDispatcher::SocketStreamDispatcher() {
178 webkit_glue::WebSocketStreamHandleBridge
*
179 SocketStreamDispatcher::CreateBridge(
180 WebKit::WebSocketStreamHandle
* handle
,
181 webkit_glue::WebSocketStreamHandleDelegate
* delegate
) {
182 return new IPCWebSocketStreamHandleBridge(handle
, delegate
);
185 bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
187 IPC_BEGIN_MESSAGE_MAP(SocketStreamDispatcher
, msg
)
188 IPC_MESSAGE_HANDLER(SocketStreamMsg_Connected
, OnConnected
)
189 IPC_MESSAGE_HANDLER(SocketStreamMsg_SentData
, OnSentData
)
190 IPC_MESSAGE_HANDLER(SocketStreamMsg_ReceivedData
, OnReceivedData
)
191 IPC_MESSAGE_HANDLER(SocketStreamMsg_Closed
, OnClosed
)
192 IPC_MESSAGE_HANDLER(SocketStreamMsg_Failed
, OnFailed
)
193 IPC_MESSAGE_UNHANDLED(handled
= false)
194 IPC_END_MESSAGE_MAP()
198 void SocketStreamDispatcher::OnConnected(int socket_id
,
199 int max_pending_send_allowed
) {
200 DVLOG(1) << "SocketStreamDispatcher::OnConnected (max_pending_send_allowed="
201 << max_pending_send_allowed
<< ") to socket_id=" << socket_id
;
203 IPCWebSocketStreamHandleBridge
* bridge
=
204 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
206 bridge
->OnConnected(max_pending_send_allowed
);
208 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
211 void SocketStreamDispatcher::OnSentData(int socket_id
, int amount_sent
) {
212 DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent
213 << " bytes) to socket_id=" << socket_id
;
215 IPCWebSocketStreamHandleBridge
* bridge
=
216 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
218 bridge
->OnSentData(amount_sent
);
220 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
223 void SocketStreamDispatcher::OnReceivedData(
224 int socket_id
, const std::vector
<char>& data
) {
225 DVLOG(1) << "SocketStreamDispatcher::OnReceivedData (" << data
.size()
226 << " bytes) to socket_id=" << socket_id
;
228 IPCWebSocketStreamHandleBridge
* bridge
=
229 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
231 bridge
->OnReceivedData(data
);
233 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
236 void SocketStreamDispatcher::OnClosed(int socket_id
) {
237 DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id
;
239 IPCWebSocketStreamHandleBridge
* bridge
=
240 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
244 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
247 void SocketStreamDispatcher::OnFailed(int socket_id
, int error_code
) {
248 IPCWebSocketStreamHandleBridge
* bridge
=
249 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
251 bridge
->OnFailed(error_code
, net::ErrorToString(error_code
));
253 DLOG(ERROR
) << "No bridge for socket_id=" << socket_id
;
256 } // namespace content