- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / pepper / pepper_tcp_server_socket_message_filter.cc
1 // Copyright 2013 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/pepper/pepper_tcp_server_socket_message_filter.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/logging.h"
10 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
11 #include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
12 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/common/socket_permission_request.h"
15 #include "net/base/ip_endpoint.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/net_util.h"
18 #include "ppapi/c/pp_errors.h"
19 #include "ppapi/c/private/ppb_net_address_private.h"
20 #include "ppapi/host/dispatch_host_message.h"
21 #include "ppapi/host/error_conversion.h"
22 #include "ppapi/host/ppapi_host.h"
23 #include "ppapi/host/resource_host.h"
24 #include "ppapi/proxy/ppapi_messages.h"
25 #include "ppapi/shared_impl/api_id.h"
26 #include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
27 #include "ppapi/shared_impl/private/net_address_private_impl.h"
28
29 using ppapi::NetAddressPrivateImpl;
30 using ppapi::host::NetErrorToPepperError;
31
32 namespace {
33
34 size_t g_num_instances = 0;
35
36 }  // namespace
37
38 namespace content {
39
40 PepperTCPServerSocketMessageFilter::PepperTCPServerSocketMessageFilter(
41     ContentBrowserPepperHostFactory* factory,
42     BrowserPpapiHostImpl* host,
43     PP_Instance instance,
44     bool private_api)
45     : ppapi_host_(host->GetPpapiHost()),
46       factory_(factory),
47       instance_(instance),
48       state_(STATE_BEFORE_LISTENING),
49       external_plugin_(host->external_plugin()),
50       private_api_(private_api),
51       render_process_id_(0),
52       render_view_id_(0) {
53   ++g_num_instances;
54   DCHECK(factory_);
55   DCHECK(ppapi_host_);
56   if (!host->GetRenderViewIDsForInstance(instance,
57                                          &render_process_id_,
58                                          &render_view_id_)) {
59     NOTREACHED();
60   }
61 }
62
63 PepperTCPServerSocketMessageFilter::~PepperTCPServerSocketMessageFilter() {
64   --g_num_instances;
65 }
66
67 // static
68 size_t PepperTCPServerSocketMessageFilter::GetNumInstances() {
69   return g_num_instances;
70 }
71
72 scoped_refptr<base::TaskRunner>
73 PepperTCPServerSocketMessageFilter::OverrideTaskRunnerForMessage(
74     const IPC::Message& message) {
75   switch (message.type()) {
76     case PpapiHostMsg_TCPServerSocket_Listen::ID:
77       return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
78     case PpapiHostMsg_TCPServerSocket_Accept::ID:
79     case PpapiHostMsg_TCPServerSocket_StopListening::ID:
80       return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
81   }
82   return NULL;
83 }
84
85 int32_t PepperTCPServerSocketMessageFilter::OnResourceMessageReceived(
86     const IPC::Message& msg,
87     ppapi::host::HostMessageContext* context) {
88   IPC_BEGIN_MESSAGE_MAP(PepperTCPServerSocketMessageFilter, msg)
89     PPAPI_DISPATCH_HOST_RESOURCE_CALL(
90         PpapiHostMsg_TCPServerSocket_Listen, OnMsgListen)
91     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
92         PpapiHostMsg_TCPServerSocket_Accept, OnMsgAccept)
93     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
94         PpapiHostMsg_TCPServerSocket_StopListening, OnMsgStopListening)
95   IPC_END_MESSAGE_MAP()
96   return PP_ERROR_FAILED;
97 }
98
99 int32_t PepperTCPServerSocketMessageFilter::OnMsgListen(
100     const ppapi::host::HostMessageContext* context,
101     const PP_NetAddress_Private& addr,
102     int32_t backlog) {
103   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
104   DCHECK(context);
105
106   SocketPermissionRequest request =
107       pepper_socket_utils::CreateSocketPermissionRequest(
108           content::SocketPermissionRequest::TCP_LISTEN, addr);
109   if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
110                                              private_api_,
111                                              &request,
112                                              render_process_id_,
113                                              render_view_id_)) {
114     return PP_ERROR_NOACCESS;
115   }
116
117   BrowserThread::PostTask(
118       BrowserThread::IO, FROM_HERE,
119       base::Bind(&PepperTCPServerSocketMessageFilter::DoListen, this,
120                  context->MakeReplyMessageContext(), addr, backlog));
121   return PP_OK_COMPLETIONPENDING;
122 }
123
124 int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
125     const ppapi::host::HostMessageContext* context) {
126   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
127   DCHECK(context);
128
129   if (state_ != STATE_LISTENING)
130     return PP_ERROR_FAILED;
131
132   state_ = STATE_ACCEPT_IN_PROGRESS;
133   ppapi::host::ReplyMessageContext reply_context(
134       context->MakeReplyMessageContext());
135   int net_result = socket_->Accept(
136       &accepted_socket_,
137       &accepted_address_,
138       base::Bind(&PepperTCPServerSocketMessageFilter::OnAcceptCompleted,
139                  base::Unretained(this), reply_context));
140   if (net_result != net::ERR_IO_PENDING)
141     OnAcceptCompleted(reply_context, net_result);
142   return PP_OK_COMPLETIONPENDING;
143 }
144
145 int32_t PepperTCPServerSocketMessageFilter::OnMsgStopListening(
146     const ppapi::host::HostMessageContext* context) {
147   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
148   DCHECK(context);
149
150   state_ = STATE_CLOSED;
151   socket_.reset();
152   return PP_OK;
153 }
154
155 void PepperTCPServerSocketMessageFilter::DoListen(
156     const ppapi::host::ReplyMessageContext& context,
157     const PP_NetAddress_Private& addr,
158     int32_t backlog) {
159   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
160
161   net::IPAddressNumber address;
162   int port;
163   if (state_ != STATE_BEFORE_LISTENING ||
164       !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
165     SendListenError(context, PP_ERROR_FAILED);
166     state_ = STATE_CLOSED;
167     return;
168   }
169
170   state_ = STATE_LISTEN_IN_PROGRESS;
171
172   socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
173   int net_result = net::OK;
174   do {
175     net::IPEndPoint ip_end_point(address, port);
176     net_result = socket_->Open(ip_end_point.GetFamily());
177     if (net_result != net::OK)
178       break;
179     net_result = socket_->SetDefaultOptionsForServer();
180     if (net_result != net::OK)
181       break;
182     net_result = socket_->Bind(ip_end_point);
183     if (net_result != net::OK)
184       break;
185     net_result = socket_->Listen(backlog);
186   } while (false);
187
188   if (net_result != net::ERR_IO_PENDING)
189     OnListenCompleted(context, net_result);
190 }
191
192 void PepperTCPServerSocketMessageFilter::OnListenCompleted(
193     const ppapi::host::ReplyMessageContext& context,
194     int net_result) {
195   if (state_ != STATE_LISTEN_IN_PROGRESS) {
196     SendListenError(context, PP_ERROR_FAILED);
197     state_ = STATE_CLOSED;
198     return;
199   }
200   if (net_result != net::OK) {
201     SendListenError(context, NetErrorToPepperError(net_result));
202     state_ = STATE_BEFORE_LISTENING;
203     return;
204   }
205
206   DCHECK(socket_.get());
207
208   net::IPEndPoint end_point;
209   PP_NetAddress_Private addr;
210
211   int32_t pp_result =
212       NetErrorToPepperError(socket_->GetLocalAddress(&end_point));
213   if (pp_result != PP_OK) {
214     SendListenError(context, pp_result);
215     state_ = STATE_BEFORE_LISTENING;
216     return;
217   }
218   if (!NetAddressPrivateImpl::IPEndPointToNetAddress(end_point.address(),
219                                                      end_point.port(),
220                                                      &addr)) {
221     SendListenError(context, PP_ERROR_FAILED);
222     state_ = STATE_BEFORE_LISTENING;
223     return;
224   }
225
226   SendListenReply(context, PP_OK, addr);
227   state_ = STATE_LISTENING;
228 }
229
230 void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
231     const ppapi::host::ReplyMessageContext& context,
232     int net_result) {
233   if (state_ != STATE_ACCEPT_IN_PROGRESS) {
234     SendAcceptError(context, PP_ERROR_FAILED);
235     state_ = STATE_CLOSED;
236     return;
237   }
238
239   state_ = STATE_LISTENING;
240
241   if (net_result != net::OK) {
242     SendAcceptError(context, NetErrorToPepperError(net_result));
243     return;
244   }
245
246   DCHECK(accepted_socket_.get());
247
248   net::IPEndPoint ip_end_point_local;
249   PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
250   PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
251
252   int32_t pp_result =
253       NetErrorToPepperError(accepted_socket_->GetLocalAddress(
254           &ip_end_point_local));
255   if (pp_result != PP_OK) {
256     SendAcceptError(context, pp_result);
257     return;
258   }
259   if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
260           ip_end_point_local.address(),
261           ip_end_point_local.port(),
262           &local_addr) ||
263       !NetAddressPrivateImpl::IPEndPointToNetAddress(
264           accepted_address_.address(),
265           accepted_address_.port(),
266           &remote_addr)) {
267     SendAcceptError(context, PP_ERROR_FAILED);
268     return;
269   }
270
271   scoped_ptr<ppapi::host::ResourceHost> host =
272       factory_->CreateAcceptedTCPSocket(
273           instance_, ppapi::TCP_SOCKET_VERSION_PRIVATE,
274           accepted_socket_.Pass());
275   if (!host) {
276     SendAcceptError(context, PP_ERROR_NOSPACE);
277     return;
278   }
279   int pending_resource_id = ppapi_host_->AddPendingResourceHost(host.Pass());
280   if (pending_resource_id) {
281     SendAcceptReply(context, PP_OK, pending_resource_id,
282                     local_addr,
283                     remote_addr);
284   } else {
285     SendAcceptError(context, PP_ERROR_NOSPACE);
286   }
287 }
288
289 void PepperTCPServerSocketMessageFilter::SendListenReply(
290     const ppapi::host::ReplyMessageContext& context,
291     int32_t pp_result,
292     const PP_NetAddress_Private& local_addr) {
293   ppapi::host::ReplyMessageContext reply_context(context);
294   reply_context.params.set_result(pp_result);
295   SendReply(reply_context,
296             PpapiPluginMsg_TCPServerSocket_ListenReply(local_addr));
297 }
298
299 void PepperTCPServerSocketMessageFilter::SendListenError(
300     const ppapi::host::ReplyMessageContext& context,
301     int32_t pp_result) {
302   SendListenReply(context, pp_result,
303                   NetAddressPrivateImpl::kInvalidNetAddress);
304 }
305
306 void PepperTCPServerSocketMessageFilter::SendAcceptReply(
307     const ppapi::host::ReplyMessageContext& context,
308     int32_t pp_result,
309     int pending_resource_id,
310     const PP_NetAddress_Private& local_addr,
311     const PP_NetAddress_Private& remote_addr) {
312   ppapi::host::ReplyMessageContext reply_context(context);
313   reply_context.params.set_result(pp_result);
314   SendReply(reply_context, PpapiPluginMsg_TCPServerSocket_AcceptReply(
315       pending_resource_id, local_addr, remote_addr));
316 }
317
318 void PepperTCPServerSocketMessageFilter::SendAcceptError(
319     const ppapi::host::ReplyMessageContext& context,
320     int32_t pp_result) {
321   SendAcceptReply(context,
322                   pp_result,
323                   0,
324                   NetAddressPrivateImpl::kInvalidNetAddress,
325                   NetAddressPrivateImpl::kInvalidNetAddress);
326 }
327
328 }  // namespace content