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/browser/renderer_host/socket_stream_dispatcher_host.h"
9 #include "base/logging.h"
10 #include "content/browser/renderer_host/socket_stream_host.h"
11 #include "content/browser/ssl/ssl_manager.h"
12 #include "content/common/resource_messages.h"
13 #include "content/common/socket_stream.h"
14 #include "content/common/socket_stream_messages.h"
15 #include "content/public/browser/content_browser_client.h"
16 #include "content/public/browser/global_request_id.h"
17 #include "net/base/net_errors.h"
18 #include "net/cookies/canonical_cookie.h"
19 #include "net/url_request/url_request_context_getter.h"
20 #include "net/websockets/websocket_job.h"
21 #include "net/websockets/websocket_throttle.h"
27 const size_t kMaxSocketStreamHosts
= 16 * 1024;
31 SocketStreamDispatcherHost::SocketStreamDispatcherHost(
32 int render_process_id
,
33 const GetRequestContextCallback
& request_context_callback
,
34 ResourceContext
* resource_context
)
35 : BrowserMessageFilter(SocketStreamMsgStart
),
36 render_process_id_(render_process_id
),
37 request_context_callback_(request_context_callback
),
38 resource_context_(resource_context
),
40 weak_ptr_factory_(this) {
41 net::WebSocketJob::EnsureInit();
44 bool SocketStreamDispatcherHost::OnMessageReceived(
45 const IPC::Message
& message
) {
50 IPC_BEGIN_MESSAGE_MAP(SocketStreamDispatcherHost
, message
)
51 IPC_MESSAGE_HANDLER(SocketStreamHostMsg_Connect
, OnConnect
)
52 IPC_MESSAGE_HANDLER(SocketStreamHostMsg_SendData
, OnSendData
)
53 IPC_MESSAGE_HANDLER(SocketStreamHostMsg_Close
, OnCloseReq
)
54 IPC_MESSAGE_UNHANDLED(handled
= false)
59 // SocketStream::Delegate methods implementations.
60 void SocketStreamDispatcherHost::OnConnected(net::SocketStream
* socket
,
61 int max_pending_send_allowed
) {
62 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
63 DVLOG(2) << "SocketStreamDispatcherHost::OnConnected socket_id=" << socket_id
64 << " max_pending_send_allowed=" << max_pending_send_allowed
;
65 if (socket_id
== kNoSocketId
) {
66 DVLOG(1) << "NoSocketId in OnConnected";
69 if (!Send(new SocketStreamMsg_Connected(
70 socket_id
, max_pending_send_allowed
))) {
71 DVLOG(1) << "SocketStreamMsg_Connected failed.";
72 DeleteSocketStreamHost(socket_id
);
76 void SocketStreamDispatcherHost::OnSentData(net::SocketStream
* socket
,
78 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
79 DVLOG(2) << "SocketStreamDispatcherHost::OnSentData socket_id=" << socket_id
80 << " amount_sent=" << amount_sent
;
81 if (socket_id
== kNoSocketId
) {
82 DVLOG(1) << "NoSocketId in OnSentData";
85 if (!Send(new SocketStreamMsg_SentData(socket_id
, amount_sent
))) {
86 DVLOG(1) << "SocketStreamMsg_SentData failed.";
87 DeleteSocketStreamHost(socket_id
);
91 void SocketStreamDispatcherHost::OnReceivedData(
92 net::SocketStream
* socket
, const char* data
, int len
) {
93 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
94 DVLOG(2) << "SocketStreamDispatcherHost::OnReceiveData socket_id="
96 if (socket_id
== kNoSocketId
) {
97 DVLOG(1) << "NoSocketId in OnReceivedData";
100 if (!Send(new SocketStreamMsg_ReceivedData(
101 socket_id
, std::vector
<char>(data
, data
+ len
)))) {
102 DVLOG(1) << "SocketStreamMsg_ReceivedData failed.";
103 DeleteSocketStreamHost(socket_id
);
107 void SocketStreamDispatcherHost::OnClose(net::SocketStream
* socket
) {
108 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
109 DVLOG(2) << "SocketStreamDispatcherHost::OnClosed socket_id=" << socket_id
;
110 if (socket_id
== kNoSocketId
) {
111 DVLOG(1) << "NoSocketId in OnClose";
114 DeleteSocketStreamHost(socket_id
);
117 void SocketStreamDispatcherHost::OnError(const net::SocketStream
* socket
,
119 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
120 DVLOG(2) << "SocketStreamDispatcherHost::OnError socket_id=" << socket_id
;
121 if (socket_id
== content::kNoSocketId
) {
122 DVLOG(1) << "NoSocketId in OnError";
125 // SocketStream::Delegate::OnError() events are handled as WebSocket error
126 // event when user agent was required to fail WebSocket connection or the
127 // WebSocket connection is closed with prejudice.
128 if (!Send(new SocketStreamMsg_Failed(socket_id
, error
))) {
129 DVLOG(1) << "SocketStreamMsg_Failed failed.";
130 DeleteSocketStreamHost(socket_id
);
134 void SocketStreamDispatcherHost::OnSSLCertificateError(
135 net::SocketStream
* socket
, const net::SSLInfo
& ssl_info
, bool fatal
) {
136 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
137 DVLOG(2) << "SocketStreamDispatcherHost::OnSSLCertificateError socket_id="
139 if (socket_id
== kNoSocketId
) {
140 DVLOG(1) << "NoSocketId in OnSSLCertificateError";
143 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
144 DCHECK(socket_stream_host
);
145 GlobalRequestID
request_id(-1, socket_id
);
146 SSLManager::OnSSLCertificateError(
147 weak_ptr_factory_
.GetWeakPtr(), request_id
, RESOURCE_TYPE_SUB_RESOURCE
,
148 socket
->url(), render_process_id_
, socket_stream_host
->render_frame_id(),
152 bool SocketStreamDispatcherHost::CanGetCookies(net::SocketStream
* socket
,
154 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
155 if (socket_id
== kNoSocketId
) {
158 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
159 DCHECK(socket_stream_host
);
160 return GetContentClient()->browser()->AllowGetCookie(
166 socket_stream_host
->render_frame_id());
169 bool SocketStreamDispatcherHost::CanSetCookie(net::SocketStream
* request
,
171 const std::string
& cookie_line
,
172 net::CookieOptions
* options
) {
173 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(request
);
174 if (socket_id
== kNoSocketId
) {
177 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
178 DCHECK(socket_stream_host
);
179 return GetContentClient()->browser()->AllowSetCookie(
185 socket_stream_host
->render_frame_id(),
189 void SocketStreamDispatcherHost::CancelSSLRequest(
190 const GlobalRequestID
& id
,
192 const net::SSLInfo
* ssl_info
) {
193 int socket_id
= id
.request_id
;
194 DVLOG(2) << "SocketStreamDispatcherHost::CancelSSLRequest socket_id="
196 DCHECK_NE(kNoSocketId
, socket_id
);
197 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
198 DCHECK(socket_stream_host
);
200 socket_stream_host
->CancelWithSSLError(*ssl_info
);
202 socket_stream_host
->CancelWithError(error
);
205 void SocketStreamDispatcherHost::ContinueSSLRequest(
206 const GlobalRequestID
& id
) {
207 int socket_id
= id
.request_id
;
208 DVLOG(2) << "SocketStreamDispatcherHost::ContinueSSLRequest socket_id="
210 DCHECK_NE(kNoSocketId
, socket_id
);
211 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
212 DCHECK(socket_stream_host
);
213 socket_stream_host
->ContinueDespiteError();
216 SocketStreamDispatcherHost::~SocketStreamDispatcherHost() {
217 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
221 // Message handlers called by OnMessageReceived.
222 void SocketStreamDispatcherHost::OnConnect(int render_frame_id
,
225 DVLOG(2) << "SocketStreamDispatcherHost::OnConnect"
226 << " render_frame_id=" << render_frame_id
228 << " socket_id=" << socket_id
;
229 DCHECK_NE(kNoSocketId
, socket_id
);
231 if (hosts_
.size() >= kMaxSocketStreamHosts
) {
232 if (!Send(new SocketStreamMsg_Failed(socket_id
,
233 net::ERR_TOO_MANY_SOCKET_STREAMS
))) {
234 DVLOG(1) << "SocketStreamMsg_Failed failed.";
236 if (!Send(new SocketStreamMsg_Closed(socket_id
))) {
237 DVLOG(1) << "SocketStreamMsg_Closed failed.";
242 if (hosts_
.Lookup(socket_id
)) {
243 DVLOG(1) << "socket_id=" << socket_id
<< " already registered.";
247 // Note that the SocketStreamHost is responsible for checking that |url|
249 SocketStreamHost
* socket_stream_host
=
250 new SocketStreamHost(this, render_process_id_
, render_frame_id
,
252 hosts_
.AddWithID(socket_stream_host
, socket_id
);
253 socket_stream_host
->Connect(url
, GetURLRequestContext());
254 DVLOG(2) << "SocketStreamDispatcherHost::OnConnect -> " << socket_id
;
257 void SocketStreamDispatcherHost::OnSendData(
258 int socket_id
, const std::vector
<char>& data
) {
259 DVLOG(2) << "SocketStreamDispatcherHost::OnSendData socket_id=" << socket_id
;
260 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
261 if (!socket_stream_host
) {
262 DVLOG(1) << "socket_id=" << socket_id
<< " already closed.";
265 if (!socket_stream_host
->SendData(data
)) {
266 // Cannot accept more data to send.
267 socket_stream_host
->Close();
271 void SocketStreamDispatcherHost::OnCloseReq(int socket_id
) {
272 DVLOG(2) << "SocketStreamDispatcherHost::OnCloseReq socket_id=" << socket_id
;
273 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
274 if (!socket_stream_host
)
276 socket_stream_host
->Close();
279 void SocketStreamDispatcherHost::DeleteSocketStreamHost(int socket_id
) {
280 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
281 DCHECK(socket_stream_host
);
282 delete socket_stream_host
;
283 hosts_
.Remove(socket_id
);
284 if (!Send(new SocketStreamMsg_Closed(socket_id
))) {
285 DVLOG(1) << "SocketStreamMsg_Closed failed.";
289 net::URLRequestContext
* SocketStreamDispatcherHost::GetURLRequestContext() {
290 return request_context_callback_
.Run(RESOURCE_TYPE_SUB_RESOURCE
);
293 void SocketStreamDispatcherHost::Shutdown() {
294 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
295 // TODO(ukai): Implement IDMap::RemoveAll().
296 for (IDMap
<SocketStreamHost
>::const_iterator
iter(&hosts_
);
299 int socket_id
= iter
.GetCurrentKey();
300 const SocketStreamHost
* socket_stream_host
= iter
.GetCurrentValue();
301 delete socket_stream_host
;
302 hosts_
.Remove(socket_id
);
307 } // namespace content