Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / socket_stream_dispatcher_host.cc
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.
4
5 #include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
6
7 #include <string>
8
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"
22
23 namespace content {
24
25 namespace {
26
27 const size_t kMaxSocketStreamHosts = 16 * 1024;
28
29 }  // namespace
30
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();
42 }
43
44 bool SocketStreamDispatcherHost::OnMessageReceived(
45     const IPC::Message& message) {
46   if (on_shutdown_)
47     return false;
48
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;
57 }
58
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;
68   }
69   if (!Send(new SocketStreamMsg_Connected(
70           socket_id, max_pending_send_allowed))) {
71     DVLOG(1) << "SocketStreamMsg_Connected failed.";
72     DeleteSocketStreamHost(socket_id);
73   }
74 }
75
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;
84   }
85   if (!Send(new SocketStreamMsg_SentData(socket_id, amount_sent))) {
86     DVLOG(1) << "SocketStreamMsg_SentData failed.";
87     DeleteSocketStreamHost(socket_id);
88   }
89 }
90
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;
99   }
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);
104   }
105 }
106
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;
113   }
114   DeleteSocketStreamHost(socket_id);
115 }
116
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;
124   }
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);
131   }
132 }
133
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;
142   }
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);
150 }
151
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;
157   }
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());
167 }
168
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;
176   }
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);
187 }
188
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);
203 }
204
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();
214 }
215
216 SocketStreamDispatcherHost::~SocketStreamDispatcherHost() {
217   DCHECK_CURRENTLY_ON(BrowserThread::IO);
218   Shutdown();
219 }
220
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);
230
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.";
235     }
236     if (!Send(new SocketStreamMsg_Closed(socket_id))) {
237       DVLOG(1) << "SocketStreamMsg_Closed failed.";
238     }
239     return;
240   }
241
242   if (hosts_.Lookup(socket_id)) {
243     DVLOG(1) << "socket_id=" << socket_id << " already registered.";
244     return;
245   }
246
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;
255 }
256
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;
264   }
265   if (!socket_stream_host->SendData(data)) {
266     // Cannot accept more data to send.
267     socket_stream_host->Close();
268   }
269 }
270
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();
277 }
278
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.";
286   }
287 }
288
289 net::URLRequestContext* SocketStreamDispatcherHost::GetURLRequestContext() {
290   return request_context_callback_.Run(RESOURCE_TYPE_SUB_RESOURCE);
291 }
292
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);
303   }
304   on_shutdown_ = true;
305 }
306
307 }  // namespace content