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 : render_process_id_(render_process_id
),
36 request_context_callback_(request_context_callback
),
37 resource_context_(resource_context
),
38 weak_ptr_factory_(this),
40 net::WebSocketJob::EnsureInit();
43 bool SocketStreamDispatcherHost::OnMessageReceived(const IPC::Message
& message
,
44 bool* message_was_ok
) {
49 IPC_BEGIN_MESSAGE_MAP_EX(SocketStreamDispatcherHost
, message
, *message_was_ok
)
50 IPC_MESSAGE_HANDLER(SocketStreamHostMsg_Connect
, OnConnect
)
51 IPC_MESSAGE_HANDLER(SocketStreamHostMsg_SendData
, OnSendData
)
52 IPC_MESSAGE_HANDLER(SocketStreamHostMsg_Close
, OnCloseReq
)
53 IPC_MESSAGE_UNHANDLED(handled
= false)
54 IPC_END_MESSAGE_MAP_EX()
58 // SocketStream::Delegate methods implementations.
59 void SocketStreamDispatcherHost::OnConnected(net::SocketStream
* socket
,
60 int max_pending_send_allowed
) {
61 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
62 DVLOG(2) << "SocketStreamDispatcherHost::OnConnected socket_id=" << socket_id
63 << " max_pending_send_allowed=" << max_pending_send_allowed
;
64 if (socket_id
== kNoSocketId
) {
65 DVLOG(1) << "NoSocketId in OnConnected";
68 if (!Send(new SocketStreamMsg_Connected(
69 socket_id
, max_pending_send_allowed
))) {
70 DVLOG(1) << "SocketStreamMsg_Connected failed.";
71 DeleteSocketStreamHost(socket_id
);
75 void SocketStreamDispatcherHost::OnSentData(net::SocketStream
* socket
,
77 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
78 DVLOG(2) << "SocketStreamDispatcherHost::OnSentData socket_id=" << socket_id
79 << " amount_sent=" << amount_sent
;
80 if (socket_id
== kNoSocketId
) {
81 DVLOG(1) << "NoSocketId in OnSentData";
84 if (!Send(new SocketStreamMsg_SentData(socket_id
, amount_sent
))) {
85 DVLOG(1) << "SocketStreamMsg_SentData failed.";
86 DeleteSocketStreamHost(socket_id
);
90 void SocketStreamDispatcherHost::OnReceivedData(
91 net::SocketStream
* socket
, const char* data
, int len
) {
92 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
93 DVLOG(2) << "SocketStreamDispatcherHost::OnReceiveData socket_id="
95 if (socket_id
== kNoSocketId
) {
96 DVLOG(1) << "NoSocketId in OnReceivedData";
99 if (!Send(new SocketStreamMsg_ReceivedData(
100 socket_id
, std::vector
<char>(data
, data
+ len
)))) {
101 DVLOG(1) << "SocketStreamMsg_ReceivedData failed.";
102 DeleteSocketStreamHost(socket_id
);
106 void SocketStreamDispatcherHost::OnClose(net::SocketStream
* socket
) {
107 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
108 DVLOG(2) << "SocketStreamDispatcherHost::OnClosed socket_id=" << socket_id
;
109 if (socket_id
== kNoSocketId
) {
110 DVLOG(1) << "NoSocketId in OnClose";
113 DeleteSocketStreamHost(socket_id
);
116 void SocketStreamDispatcherHost::OnError(const net::SocketStream
* socket
,
118 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
119 DVLOG(2) << "SocketStreamDispatcherHost::OnError socket_id=" << socket_id
;
120 if (socket_id
== content::kNoSocketId
) {
121 DVLOG(1) << "NoSocketId in OnError";
124 // SocketStream::Delegate::OnError() events are handled as WebSocket error
125 // event when user agent was required to fail WebSocket connection or the
126 // WebSocket connection is closed with prejudice.
127 if (!Send(new SocketStreamMsg_Failed(socket_id
, error
))) {
128 DVLOG(1) << "SocketStreamMsg_Failed failed.";
129 DeleteSocketStreamHost(socket_id
);
133 void SocketStreamDispatcherHost::OnSSLCertificateError(
134 net::SocketStream
* socket
, const net::SSLInfo
& ssl_info
, bool fatal
) {
135 int socket_id
= SocketStreamHost::SocketIdFromSocketStream(socket
);
136 DVLOG(2) << "SocketStreamDispatcherHost::OnSSLCertificateError socket_id="
138 if (socket_id
== kNoSocketId
) {
139 DVLOG(1) << "NoSocketId in OnSSLCertificateError";
142 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
143 DCHECK(socket_stream_host
);
144 GlobalRequestID
request_id(-1, socket_id
);
145 SSLManager::OnSSLCertificateError(
146 weak_ptr_factory_
.GetWeakPtr(), request_id
, ResourceType::SUB_RESOURCE
,
147 socket
->url(), render_process_id_
, socket_stream_host
->render_frame_id(),
151 bool SocketStreamDispatcherHost::CanGetCookies(net::SocketStream
* socket
,
153 return GetContentClient()->browser()->AllowGetCookie(
154 url
, url
, net::CookieList(), resource_context_
, 0, MSG_ROUTING_NONE
);
157 bool SocketStreamDispatcherHost::CanSetCookie(net::SocketStream
* request
,
159 const std::string
& cookie_line
,
160 net::CookieOptions
* options
) {
161 return GetContentClient()->browser()->AllowSetCookie(
162 url
, url
, cookie_line
, resource_context_
, 0, MSG_ROUTING_NONE
, options
);
165 void SocketStreamDispatcherHost::CancelSSLRequest(
166 const GlobalRequestID
& id
,
168 const net::SSLInfo
* ssl_info
) {
169 int socket_id
= id
.request_id
;
170 DVLOG(2) << "SocketStreamDispatcherHost::CancelSSLRequest socket_id="
172 DCHECK_NE(kNoSocketId
, socket_id
);
173 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
174 DCHECK(socket_stream_host
);
176 socket_stream_host
->CancelWithSSLError(*ssl_info
);
178 socket_stream_host
->CancelWithError(error
);
181 void SocketStreamDispatcherHost::ContinueSSLRequest(
182 const GlobalRequestID
& id
) {
183 int socket_id
= id
.request_id
;
184 DVLOG(2) << "SocketStreamDispatcherHost::ContinueSSLRequest socket_id="
186 DCHECK_NE(kNoSocketId
, socket_id
);
187 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
188 DCHECK(socket_stream_host
);
189 socket_stream_host
->ContinueDespiteError();
192 SocketStreamDispatcherHost::~SocketStreamDispatcherHost() {
193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
197 // Message handlers called by OnMessageReceived.
198 void SocketStreamDispatcherHost::OnConnect(int render_frame_id
,
201 DVLOG(2) << "SocketStreamDispatcherHost::OnConnect"
202 << " render_frame_id=" << render_frame_id
204 << " socket_id=" << socket_id
;
205 DCHECK_NE(kNoSocketId
, socket_id
);
207 if (hosts_
.size() >= kMaxSocketStreamHosts
) {
208 if (!Send(new SocketStreamMsg_Failed(socket_id
,
209 net::ERR_TOO_MANY_SOCKET_STREAMS
))) {
210 DVLOG(1) << "SocketStreamMsg_Failed failed.";
212 if (!Send(new SocketStreamMsg_Closed(socket_id
))) {
213 DVLOG(1) << "SocketStreamMsg_Closed failed.";
218 if (hosts_
.Lookup(socket_id
)) {
219 DVLOG(1) << "socket_id=" << socket_id
<< " already registered.";
223 // Note that the SocketStreamHost is responsible for checking that |url|
225 SocketStreamHost
* socket_stream_host
=
226 new SocketStreamHost(this, render_frame_id
, socket_id
);
227 hosts_
.AddWithID(socket_stream_host
, socket_id
);
228 socket_stream_host
->Connect(url
, GetURLRequestContext());
229 DVLOG(2) << "SocketStreamDispatcherHost::OnConnect -> " << socket_id
;
232 void SocketStreamDispatcherHost::OnSendData(
233 int socket_id
, const std::vector
<char>& data
) {
234 DVLOG(2) << "SocketStreamDispatcherHost::OnSendData socket_id=" << socket_id
;
235 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
236 if (!socket_stream_host
) {
237 DVLOG(1) << "socket_id=" << socket_id
<< " already closed.";
240 if (!socket_stream_host
->SendData(data
)) {
241 // Cannot accept more data to send.
242 socket_stream_host
->Close();
246 void SocketStreamDispatcherHost::OnCloseReq(int socket_id
) {
247 DVLOG(2) << "SocketStreamDispatcherHost::OnCloseReq socket_id=" << socket_id
;
248 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
249 if (!socket_stream_host
)
251 socket_stream_host
->Close();
254 void SocketStreamDispatcherHost::DeleteSocketStreamHost(int socket_id
) {
255 SocketStreamHost
* socket_stream_host
= hosts_
.Lookup(socket_id
);
256 DCHECK(socket_stream_host
);
257 delete socket_stream_host
;
258 hosts_
.Remove(socket_id
);
259 if (!Send(new SocketStreamMsg_Closed(socket_id
))) {
260 DVLOG(1) << "SocketStreamMsg_Closed failed.";
264 net::URLRequestContext
* SocketStreamDispatcherHost::GetURLRequestContext() {
265 return request_context_callback_
.Run(ResourceType::SUB_RESOURCE
);
268 void SocketStreamDispatcherHost::Shutdown() {
269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
270 // TODO(ukai): Implement IDMap::RemoveAll().
271 for (IDMap
<SocketStreamHost
>::const_iterator
iter(&hosts_
);
274 int socket_id
= iter
.GetCurrentKey();
275 const SocketStreamHost
* socket_stream_host
= iter
.GetCurrentValue();
276 delete socket_stream_host
;
277 hosts_
.Remove(socket_id
);
282 } // namespace content