Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / renderer_host / socket_stream_dispatcher_host.cc
blobc52023eb407c2e84234dc16b9964f98e83e8d0d4
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"
7 #include <string>
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"
23 namespace content {
25 namespace {
27 const size_t kMaxSocketStreamHosts = 16 * 1024;
29 } // namespace
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),
39 weak_ptr_factory_(this),
40 on_shutdown_(false) {
41 net::WebSocketJob::EnsureInit();
44 bool SocketStreamDispatcherHost::OnMessageReceived(
45 const IPC::Message& message) {
46 if (on_shutdown_)
47 return false;
49 bool handled = true;
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)
55 IPC_END_MESSAGE_MAP()
56 return handled;
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";
67 return;
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,
77 int amount_sent) {
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";
83 return;
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="
95 << socket_id;
96 if (socket_id == kNoSocketId) {
97 DVLOG(1) << "NoSocketId in OnReceivedData";
98 return;
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";
112 return;
114 DeleteSocketStreamHost(socket_id);
117 void SocketStreamDispatcherHost::OnError(const net::SocketStream* socket,
118 int error) {
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";
123 return;
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="
138 << socket_id;
139 if (socket_id == kNoSocketId) {
140 DVLOG(1) << "NoSocketId in OnSSLCertificateError";
141 return;
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(),
149 ssl_info, fatal);
152 bool SocketStreamDispatcherHost::CanGetCookies(net::SocketStream* socket,
153 const GURL& url) {
154 int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
155 if (socket_id == kNoSocketId) {
156 return false;
158 SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
159 DCHECK(socket_stream_host);
160 return GetContentClient()->browser()->AllowGetCookie(
161 url,
162 url,
163 net::CookieList(),
164 resource_context_,
165 render_process_id_,
166 socket_stream_host->render_frame_id());
169 bool SocketStreamDispatcherHost::CanSetCookie(net::SocketStream* request,
170 const GURL& url,
171 const std::string& cookie_line,
172 net::CookieOptions* options) {
173 int socket_id = SocketStreamHost::SocketIdFromSocketStream(request);
174 if (socket_id == kNoSocketId) {
175 return false;
177 SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
178 DCHECK(socket_stream_host);
179 return GetContentClient()->browser()->AllowSetCookie(
180 url,
181 url,
182 cookie_line,
183 resource_context_,
184 render_process_id_,
185 socket_stream_host->render_frame_id(),
186 options);
189 void SocketStreamDispatcherHost::CancelSSLRequest(
190 const GlobalRequestID& id,
191 int error,
192 const net::SSLInfo* ssl_info) {
193 int socket_id = id.request_id;
194 DVLOG(2) << "SocketStreamDispatcherHost::CancelSSLRequest socket_id="
195 << socket_id;
196 DCHECK_NE(kNoSocketId, socket_id);
197 SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
198 DCHECK(socket_stream_host);
199 if (ssl_info)
200 socket_stream_host->CancelWithSSLError(*ssl_info);
201 else
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="
209 << 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);
218 Shutdown();
221 // Message handlers called by OnMessageReceived.
222 void SocketStreamDispatcherHost::OnConnect(int render_frame_id,
223 const GURL& url,
224 int socket_id) {
225 DVLOG(2) << "SocketStreamDispatcherHost::OnConnect"
226 << " render_frame_id=" << render_frame_id
227 << " url=" << url
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.";
239 return;
242 if (hosts_.Lookup(socket_id)) {
243 DVLOG(1) << "socket_id=" << socket_id << " already registered.";
244 return;
247 // Note that the SocketStreamHost is responsible for checking that |url|
248 // is valid.
249 SocketStreamHost* socket_stream_host =
250 new SocketStreamHost(this, render_process_id_, render_frame_id,
251 socket_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.";
263 return;
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)
275 return;
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_);
297 !iter.IsAtEnd();
298 iter.Advance()) {
299 int socket_id = iter.GetCurrentKey();
300 const SocketStreamHost* socket_stream_host = iter.GetCurrentValue();
301 delete socket_stream_host;
302 hosts_.Remove(socket_id);
304 on_shutdown_ = true;
307 } // namespace content