Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / renderer_host / socket_stream_dispatcher_host.cc
blob30f3d35a1f96587cb90e6a63bc110c7af32fa39f
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/cookies/canonical_cookie.h"
18 #include "net/url_request/url_request_context_getter.h"
19 #include "net/websockets/websocket_job.h"
20 #include "net/websockets/websocket_throttle.h"
22 namespace content {
24 SocketStreamDispatcherHost::SocketStreamDispatcherHost(
25 int render_process_id,
26 ResourceMessageFilter::URLRequestContextSelector* selector,
27 ResourceContext* resource_context)
28 : render_process_id_(render_process_id),
29 url_request_context_selector_(selector),
30 resource_context_(resource_context),
31 weak_ptr_factory_(this),
32 on_shutdown_(false) {
33 DCHECK(selector);
34 net::WebSocketJob::EnsureInit();
37 bool SocketStreamDispatcherHost::OnMessageReceived(const IPC::Message& message,
38 bool* message_was_ok) {
39 if (on_shutdown_)
40 return false;
42 bool handled = true;
43 IPC_BEGIN_MESSAGE_MAP_EX(SocketStreamDispatcherHost, message, *message_was_ok)
44 IPC_MESSAGE_HANDLER(SocketStreamHostMsg_Connect, OnConnect)
45 IPC_MESSAGE_HANDLER(SocketStreamHostMsg_SendData, OnSendData)
46 IPC_MESSAGE_HANDLER(SocketStreamHostMsg_Close, OnCloseReq)
47 IPC_MESSAGE_UNHANDLED(handled = false)
48 IPC_END_MESSAGE_MAP_EX()
49 return handled;
52 // SocketStream::Delegate methods implementations.
53 void SocketStreamDispatcherHost::OnConnected(net::SocketStream* socket,
54 int max_pending_send_allowed) {
55 int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
56 DVLOG(2) << "SocketStreamDispatcherHost::OnConnected socket_id=" << socket_id
57 << " max_pending_send_allowed=" << max_pending_send_allowed;
58 if (socket_id == kNoSocketId) {
59 DVLOG(1) << "NoSocketId in OnConnected";
60 return;
62 if (!Send(new SocketStreamMsg_Connected(
63 socket_id, max_pending_send_allowed))) {
64 DVLOG(1) << "SocketStreamMsg_Connected failed.";
65 DeleteSocketStreamHost(socket_id);
69 void SocketStreamDispatcherHost::OnSentData(net::SocketStream* socket,
70 int amount_sent) {
71 int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
72 DVLOG(2) << "SocketStreamDispatcherHost::OnSentData socket_id=" << socket_id
73 << " amount_sent=" << amount_sent;
74 if (socket_id == kNoSocketId) {
75 DVLOG(1) << "NoSocketId in OnSentData";
76 return;
78 if (!Send(new SocketStreamMsg_SentData(socket_id, amount_sent))) {
79 DVLOG(1) << "SocketStreamMsg_SentData failed.";
80 DeleteSocketStreamHost(socket_id);
84 void SocketStreamDispatcherHost::OnReceivedData(
85 net::SocketStream* socket, const char* data, int len) {
86 int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
87 DVLOG(2) << "SocketStreamDispatcherHost::OnReceiveData socket_id="
88 << socket_id;
89 if (socket_id == kNoSocketId) {
90 DVLOG(1) << "NoSocketId in OnReceivedData";
91 return;
93 if (!Send(new SocketStreamMsg_ReceivedData(
94 socket_id, std::vector<char>(data, data + len)))) {
95 DVLOG(1) << "SocketStreamMsg_ReceivedData failed.";
96 DeleteSocketStreamHost(socket_id);
100 void SocketStreamDispatcherHost::OnClose(net::SocketStream* socket) {
101 int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
102 DVLOG(2) << "SocketStreamDispatcherHost::OnClosed socket_id=" << socket_id;
103 if (socket_id == kNoSocketId) {
104 DVLOG(1) << "NoSocketId in OnClose";
105 return;
107 DeleteSocketStreamHost(socket_id);
110 void SocketStreamDispatcherHost::OnError(const net::SocketStream* socket,
111 int error) {
112 int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
113 DVLOG(2) << "SocketStreamDispatcherHost::OnError socket_id=" << socket_id;
114 if (socket_id == content::kNoSocketId) {
115 DVLOG(1) << "NoSocketId in OnError";
116 return;
118 // SocketStream::Delegate::OnError() events are handled as WebSocket error
119 // event when user agent was required to fail WebSocket connection or the
120 // WebSocket connection is closed with prejudice.
121 if (!Send(new SocketStreamMsg_Failed(socket_id, error))) {
122 DVLOG(1) << "SocketStreamMsg_Failed failed.";
123 DeleteSocketStreamHost(socket_id);
127 void SocketStreamDispatcherHost::OnSSLCertificateError(
128 net::SocketStream* socket, const net::SSLInfo& ssl_info, bool fatal) {
129 int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
130 DVLOG(2) << "SocketStreamDispatcherHost::OnSSLCertificateError socket_id="
131 << socket_id;
132 if (socket_id == kNoSocketId) {
133 DVLOG(1) << "NoSocketId in OnSSLCertificateError";
134 return;
136 SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
137 DCHECK(socket_stream_host);
138 GlobalRequestID request_id(-1, socket_id);
139 SSLManager::OnSSLCertificateError(
140 weak_ptr_factory_.GetWeakPtr(), request_id, ResourceType::SUB_RESOURCE,
141 socket->url(), render_process_id_, socket_stream_host->render_view_id(),
142 ssl_info, fatal);
145 bool SocketStreamDispatcherHost::CanGetCookies(net::SocketStream* socket,
146 const GURL& url) {
147 return GetContentClient()->browser()->AllowGetCookie(
148 url, url, net::CookieList(), resource_context_, 0, MSG_ROUTING_NONE);
151 bool SocketStreamDispatcherHost::CanSetCookie(net::SocketStream* request,
152 const GURL& url,
153 const std::string& cookie_line,
154 net::CookieOptions* options) {
155 return GetContentClient()->browser()->AllowSetCookie(
156 url, url, cookie_line, resource_context_, 0, MSG_ROUTING_NONE, options);
159 void SocketStreamDispatcherHost::CancelSSLRequest(
160 const GlobalRequestID& id,
161 int error,
162 const net::SSLInfo* ssl_info) {
163 int socket_id = id.request_id;
164 DVLOG(2) << "SocketStreamDispatcherHost::CancelSSLRequest socket_id="
165 << socket_id;
166 DCHECK_NE(kNoSocketId, socket_id);
167 SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
168 DCHECK(socket_stream_host);
169 if (ssl_info)
170 socket_stream_host->CancelWithSSLError(*ssl_info);
171 else
172 socket_stream_host->CancelWithError(error);
175 void SocketStreamDispatcherHost::ContinueSSLRequest(
176 const GlobalRequestID& id) {
177 int socket_id = id.request_id;
178 DVLOG(2) << "SocketStreamDispatcherHost::ContinueSSLRequest socket_id="
179 << socket_id;
180 DCHECK_NE(kNoSocketId, socket_id);
181 SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
182 DCHECK(socket_stream_host);
183 socket_stream_host->ContinueDespiteError();
186 SocketStreamDispatcherHost::~SocketStreamDispatcherHost() {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
188 Shutdown();
191 // Message handlers called by OnMessageReceived.
192 void SocketStreamDispatcherHost::OnConnect(int render_view_id,
193 const GURL& url,
194 int socket_id) {
195 DVLOG(2) << "SocketStreamDispatcherHost::OnConnect"
196 << " render_view_id=" << render_view_id
197 << " url=" << url
198 << " socket_id=" << socket_id;
199 DCHECK_NE(kNoSocketId, socket_id);
200 if (hosts_.Lookup(socket_id)) {
201 DVLOG(1) << "socket_id=" << socket_id << " already registered.";
202 return;
205 // Note that the SocketStreamHost is responsible for checking that |url|
206 // is valid.
207 SocketStreamHost* socket_stream_host =
208 new SocketStreamHost(this, render_view_id, socket_id);
209 hosts_.AddWithID(socket_stream_host, socket_id);
210 socket_stream_host->Connect(url, GetURLRequestContext());
211 DVLOG(2) << "SocketStreamDispatcherHost::OnConnect -> " << socket_id;
214 void SocketStreamDispatcherHost::OnSendData(
215 int socket_id, const std::vector<char>& data) {
216 DVLOG(2) << "SocketStreamDispatcherHost::OnSendData socket_id=" << socket_id;
217 SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
218 if (!socket_stream_host) {
219 DVLOG(1) << "socket_id=" << socket_id << " already closed.";
220 return;
222 if (!socket_stream_host->SendData(data)) {
223 // Cannot accept more data to send.
224 socket_stream_host->Close();
228 void SocketStreamDispatcherHost::OnCloseReq(int socket_id) {
229 DVLOG(2) << "SocketStreamDispatcherHost::OnCloseReq socket_id=" << socket_id;
230 SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
231 if (!socket_stream_host)
232 return;
233 socket_stream_host->Close();
236 void SocketStreamDispatcherHost::DeleteSocketStreamHost(int socket_id) {
237 SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
238 DCHECK(socket_stream_host);
239 delete socket_stream_host;
240 hosts_.Remove(socket_id);
241 if (!Send(new SocketStreamMsg_Closed(socket_id))) {
242 DVLOG(1) << "SocketStreamMsg_Closed failed.";
246 net::URLRequestContext* SocketStreamDispatcherHost::GetURLRequestContext() {
247 return url_request_context_selector_->GetRequestContext(
248 ResourceType::SUB_RESOURCE);
251 void SocketStreamDispatcherHost::Shutdown() {
252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
253 // TODO(ukai): Implement IDMap::RemoveAll().
254 for (IDMap<SocketStreamHost>::const_iterator iter(&hosts_);
255 !iter.IsAtEnd();
256 iter.Advance()) {
257 int socket_id = iter.GetCurrentKey();
258 const SocketStreamHost* socket_stream_host = iter.GetCurrentValue();
259 delete socket_stream_host;
260 hosts_.Remove(socket_id);
262 on_shutdown_ = true;
265 } // namespace content