Home | History | Annotate | Download | only in pepper
      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
    329