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/common/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.h"
14 #include "content/common/child_thread.h"
15 #include "content/common/socket_stream.h"
16 #include "content/common/socket_stream_handle_data.h"
17 #include "content/common/socket_stream_messages.h"
18 #include "googleurl/src/gurl.h"
19 #include "webkit/glue/websocketstreamhandle_bridge.h"
20 #include "webkit/glue/websocketstreamhandle_delegate.h"
24 // IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle.
25 // It communicates with the main browser process via SocketStreamDispatcher.
26 class IPCWebSocketStreamHandleBridge
27 : public webkit_glue::WebSocketStreamHandleBridge
{
29 IPCWebSocketStreamHandleBridge(
30 ChildThread
* child_thread
,
31 WebKit::WebSocketStreamHandle
* handle
,
32 webkit_glue::WebSocketStreamHandleDelegate
* delegate
)
33 : socket_id_(content::kNoSocketId
),
34 child_thread_(child_thread
),
36 delegate_(delegate
) {}
38 // Returns the handle having given id or NULL if there is no such handle.
39 static IPCWebSocketStreamHandleBridge
* FromSocketId(int id
);
41 // webkit_glue::WebSocketStreamHandleBridge methods.
42 virtual void Connect(const GURL
& url
);
43 virtual bool Send(const std::vector
<char>& data
);
46 // Called by SocketStreamDispatcher.
47 void OnConnected(int max_amount_send_allowed
);
48 void OnSentData(int amount_sent
);
49 void OnReceivedData(const std::vector
<char>& data
);
53 virtual ~IPCWebSocketStreamHandleBridge();
55 void DoConnect(const GURL
& url
);
59 ChildThread
* child_thread_
;
60 WebKit::WebSocketStreamHandle
* handle_
;
61 webkit_glue::WebSocketStreamHandleDelegate
* delegate_
;
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) << "IPCWebSocketStreamHandleBridge destructor socket_id="
80 if (socket_id_
!= content::kNoSocketId
) {
81 child_thread_
->Send(new SocketStreamHostMsg_Close(socket_id_
));
82 socket_id_
= content::kNoSocketId
;
86 void IPCWebSocketStreamHandleBridge::Connect(const GURL
& url
) {
87 DCHECK(child_thread_
);
88 DVLOG(1) << "Connect url=" << url
;
89 child_thread_
->message_loop()->PostTask(
91 base::Bind(&IPCWebSocketStreamHandleBridge::DoConnect
, this, url
));
94 bool IPCWebSocketStreamHandleBridge::Send(
95 const std::vector
<char>& data
) {
96 DVLOG(1) << "Send data.size=" << data
.size();
97 if (child_thread_
->Send(
98 new SocketStreamHostMsg_SendData(socket_id_
, data
))) {
100 delegate_
->WillSendData(handle_
, &data
[0], data
.size());
106 void IPCWebSocketStreamHandleBridge::Close() {
107 DVLOG(1) << "Close socket_id" << socket_id_
;
108 AddRef(); // Released in DoClose().
109 child_thread_
->message_loop()->PostTask(
111 base::Bind(&IPCWebSocketStreamHandleBridge::DoClose
, this));
114 void IPCWebSocketStreamHandleBridge::OnConnected(int max_pending_send_allowed
) {
115 DVLOG(1) << "IPCWebSocketStreamHandleBridge::OnConnected socket_id="
118 delegate_
->DidOpenStream(handle_
, max_pending_send_allowed
);
121 void IPCWebSocketStreamHandleBridge::OnSentData(int amount_sent
) {
123 delegate_
->DidSendData(handle_
, amount_sent
);
126 void IPCWebSocketStreamHandleBridge::OnReceivedData(
127 const std::vector
<char>& data
) {
129 delegate_
->DidReceiveData(handle_
, &data
[0], data
.size());
132 void IPCWebSocketStreamHandleBridge::OnClosed() {
133 DVLOG(1) << "IPCWebSocketStreamHandleBridge::OnClosed";
134 if (socket_id_
!= content::kNoSocketId
) {
135 all_bridges
.Get().Remove(socket_id_
);
136 socket_id_
= content::kNoSocketId
;
139 delegate_
->DidClose(handle_
);
144 void IPCWebSocketStreamHandleBridge::DoConnect(const GURL
& url
) {
145 DCHECK(child_thread_
);
146 DCHECK_EQ(socket_id_
, content::kNoSocketId
);
148 delegate_
->WillOpenStream(handle_
, url
);
150 socket_id_
= all_bridges
.Get().Add(this);
151 DCHECK_NE(socket_id_
, content::kNoSocketId
);
152 int render_view_id
= MSG_ROUTING_NONE
;
153 const SocketStreamHandleData
* data
=
154 SocketStreamHandleData::ForHandle(handle_
);
156 render_view_id
= data
->render_view_id();
157 AddRef(); // Released in OnClosed().
158 if (child_thread_
->Send(
159 new SocketStreamHostMsg_Connect(render_view_id
, url
, socket_id_
))) {
160 DVLOG(1) << "Connect socket_id=" << socket_id_
;
161 // TODO(ukai): timeout to OnConnected.
163 DLOG(ERROR
) << "IPC SocketStream_Connect failed.";
168 void IPCWebSocketStreamHandleBridge::DoClose() {
169 child_thread_
->Send(new SocketStreamHostMsg_Close(socket_id_
));
173 SocketStreamDispatcher::SocketStreamDispatcher() {
177 webkit_glue::WebSocketStreamHandleBridge
*
178 SocketStreamDispatcher::CreateBridge(
179 WebKit::WebSocketStreamHandle
* handle
,
180 webkit_glue::WebSocketStreamHandleDelegate
* delegate
) {
181 return new IPCWebSocketStreamHandleBridge(
182 ChildThread::current(), 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_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 socket_id=" << socket_id
200 << " max_pending_send_allowed=" << max_pending_send_allowed
;
201 IPCWebSocketStreamHandleBridge
* bridge
=
202 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
204 bridge
->OnConnected(max_pending_send_allowed
);
206 DLOG(ERROR
) << "No SocketStreamHandleBridge for socket_id=" << socket_id
;
209 void SocketStreamDispatcher::OnSentData(int socket_id
, int amount_sent
) {
210 IPCWebSocketStreamHandleBridge
* bridge
=
211 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
213 bridge
->OnSentData(amount_sent
);
215 DLOG(ERROR
) << "No SocketStreamHandleBridge for socket_id=" << socket_id
;
218 void SocketStreamDispatcher::OnReceivedData(
219 int socket_id
, const std::vector
<char>& data
) {
220 IPCWebSocketStreamHandleBridge
* bridge
=
221 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
223 bridge
->OnReceivedData(data
);
225 DLOG(ERROR
) << "No SocketStreamHandleBridge for socket_id=" << socket_id
;
228 void SocketStreamDispatcher::OnClosed(int socket_id
) {
229 IPCWebSocketStreamHandleBridge
* bridge
=
230 IPCWebSocketStreamHandleBridge::FromSocketId(socket_id
);
234 DLOG(ERROR
) << "No SocketStreamHandleBridge for socket_id=" << socket_id
;
237 } // namespace content