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_frame_id_(0) {
     53   ++g_num_instances;
     54   DCHECK(factory_);
     55   DCHECK(ppapi_host_);
     56   if (!host->GetRenderFrameIDsForInstance(
     57           instance, &render_process_id_, &render_frame_id_)) {
     58     NOTREACHED();
     59   }
     60 }
     61 
     62 PepperTCPServerSocketMessageFilter::~PepperTCPServerSocketMessageFilter() {
     63   --g_num_instances;
     64 }
     65 
     66 // static
     67 size_t PepperTCPServerSocketMessageFilter::GetNumInstances() {
     68   return g_num_instances;
     69 }
     70 
     71 scoped_refptr<base::TaskRunner>
     72 PepperTCPServerSocketMessageFilter::OverrideTaskRunnerForMessage(
     73     const IPC::Message& message) {
     74   switch (message.type()) {
     75     case PpapiHostMsg_TCPServerSocket_Listen::ID:
     76       return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
     77     case PpapiHostMsg_TCPServerSocket_Accept::ID:
     78     case PpapiHostMsg_TCPServerSocket_StopListening::ID:
     79       return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
     80   }
     81   return NULL;
     82 }
     83 
     84 int32_t PepperTCPServerSocketMessageFilter::OnResourceMessageReceived(
     85     const IPC::Message& msg,
     86     ppapi::host::HostMessageContext* context) {
     87   PPAPI_BEGIN_MESSAGE_MAP(PepperTCPServerSocketMessageFilter, msg)
     88     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPServerSocket_Listen,
     89                                       OnMsgListen)
     90     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TCPServerSocket_Accept,
     91                                         OnMsgAccept)
     92     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
     93         PpapiHostMsg_TCPServerSocket_StopListening, OnMsgStopListening)
     94   PPAPI_END_MESSAGE_MAP()
     95   return PP_ERROR_FAILED;
     96 }
     97 
     98 int32_t PepperTCPServerSocketMessageFilter::OnMsgListen(
     99     const ppapi::host::HostMessageContext* context,
    100     const PP_NetAddress_Private& addr,
    101     int32_t backlog) {
    102   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    103   DCHECK(context);
    104 
    105   SocketPermissionRequest request =
    106       pepper_socket_utils::CreateSocketPermissionRequest(
    107           content::SocketPermissionRequest::TCP_LISTEN, addr);
    108   if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
    109                                              private_api_,
    110                                              &request,
    111                                              render_process_id_,
    112                                              render_frame_id_)) {
    113     return PP_ERROR_NOACCESS;
    114   }
    115 
    116   BrowserThread::PostTask(
    117       BrowserThread::IO,
    118       FROM_HERE,
    119       base::Bind(&PepperTCPServerSocketMessageFilter::DoListen,
    120                  this,
    121                  context->MakeReplyMessageContext(),
    122                  addr,
    123                  backlog));
    124   return PP_OK_COMPLETIONPENDING;
    125 }
    126 
    127 int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
    128     const ppapi::host::HostMessageContext* context) {
    129   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    130   DCHECK(context);
    131 
    132   if (state_ != STATE_LISTENING)
    133     return PP_ERROR_FAILED;
    134 
    135   state_ = STATE_ACCEPT_IN_PROGRESS;
    136   ppapi::host::ReplyMessageContext reply_context(
    137       context->MakeReplyMessageContext());
    138   int net_result = socket_->Accept(
    139       &accepted_socket_,
    140       &accepted_address_,
    141       base::Bind(&PepperTCPServerSocketMessageFilter::OnAcceptCompleted,
    142                  base::Unretained(this),
    143                  reply_context));
    144   if (net_result != net::ERR_IO_PENDING)
    145     OnAcceptCompleted(reply_context, net_result);
    146   return PP_OK_COMPLETIONPENDING;
    147 }
    148 
    149 int32_t PepperTCPServerSocketMessageFilter::OnMsgStopListening(
    150     const ppapi::host::HostMessageContext* context) {
    151   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    152   DCHECK(context);
    153 
    154   state_ = STATE_CLOSED;
    155   socket_.reset();
    156   return PP_OK;
    157 }
    158 
    159 void PepperTCPServerSocketMessageFilter::DoListen(
    160     const ppapi::host::ReplyMessageContext& context,
    161     const PP_NetAddress_Private& addr,
    162     int32_t backlog) {
    163   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    164 
    165   net::IPAddressNumber address;
    166   int port;
    167   if (state_ != STATE_BEFORE_LISTENING ||
    168       !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
    169     SendListenError(context, PP_ERROR_FAILED);
    170     state_ = STATE_CLOSED;
    171     return;
    172   }
    173 
    174   state_ = STATE_LISTEN_IN_PROGRESS;
    175 
    176   socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
    177   int net_result = net::OK;
    178   do {
    179     net::IPEndPoint ip_end_point(address, port);
    180     net_result = socket_->Open(ip_end_point.GetFamily());
    181     if (net_result != net::OK)
    182       break;
    183     net_result = socket_->SetDefaultOptionsForServer();
    184     if (net_result != net::OK)
    185       break;
    186     net_result = socket_->Bind(ip_end_point);
    187     if (net_result != net::OK)
    188       break;
    189     net_result = socket_->Listen(backlog);
    190   } while (false);
    191 
    192   if (net_result != net::ERR_IO_PENDING)
    193     OnListenCompleted(context, net_result);
    194 }
    195 
    196 void PepperTCPServerSocketMessageFilter::OnListenCompleted(
    197     const ppapi::host::ReplyMessageContext& context,
    198     int net_result) {
    199   if (state_ != STATE_LISTEN_IN_PROGRESS) {
    200     SendListenError(context, PP_ERROR_FAILED);
    201     state_ = STATE_CLOSED;
    202     return;
    203   }
    204   if (net_result != net::OK) {
    205     SendListenError(context, NetErrorToPepperError(net_result));
    206     state_ = STATE_BEFORE_LISTENING;
    207     return;
    208   }
    209 
    210   DCHECK(socket_.get());
    211 
    212   net::IPEndPoint end_point;
    213   PP_NetAddress_Private addr;
    214 
    215   int32_t pp_result =
    216       NetErrorToPepperError(socket_->GetLocalAddress(&end_point));
    217   if (pp_result != PP_OK) {
    218     SendListenError(context, pp_result);
    219     state_ = STATE_BEFORE_LISTENING;
    220     return;
    221   }
    222   if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
    223           end_point.address(), end_point.port(), &addr)) {
    224     SendListenError(context, PP_ERROR_FAILED);
    225     state_ = STATE_BEFORE_LISTENING;
    226     return;
    227   }
    228 
    229   SendListenReply(context, PP_OK, addr);
    230   state_ = STATE_LISTENING;
    231 }
    232 
    233 void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
    234     const ppapi::host::ReplyMessageContext& context,
    235     int net_result) {
    236   if (state_ != STATE_ACCEPT_IN_PROGRESS) {
    237     SendAcceptError(context, PP_ERROR_FAILED);
    238     state_ = STATE_CLOSED;
    239     return;
    240   }
    241 
    242   state_ = STATE_LISTENING;
    243 
    244   if (net_result != net::OK) {
    245     SendAcceptError(context, NetErrorToPepperError(net_result));
    246     return;
    247   }
    248 
    249   DCHECK(accepted_socket_.get());
    250 
    251   net::IPEndPoint ip_end_point_local;
    252   PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
    253   PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
    254 
    255   int32_t pp_result = NetErrorToPepperError(
    256       accepted_socket_->GetLocalAddress(&ip_end_point_local));
    257   if (pp_result != PP_OK) {
    258     SendAcceptError(context, pp_result);
    259     return;
    260   }
    261   if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
    262           ip_end_point_local.address(),
    263           ip_end_point_local.port(),
    264           &local_addr) ||
    265       !NetAddressPrivateImpl::IPEndPointToNetAddress(
    266           accepted_address_.address(),
    267           accepted_address_.port(),
    268           &remote_addr)) {
    269     SendAcceptError(context, PP_ERROR_FAILED);
    270     return;
    271   }
    272 
    273   scoped_ptr<ppapi::host::ResourceHost> host =
    274       factory_->CreateAcceptedTCPSocket(instance_,
    275                                         ppapi::TCP_SOCKET_VERSION_PRIVATE,
    276                                         accepted_socket_.Pass());
    277   if (!host) {
    278     SendAcceptError(context, PP_ERROR_NOSPACE);
    279     return;
    280   }
    281   int pending_resource_id = ppapi_host_->AddPendingResourceHost(host.Pass());
    282   if (pending_resource_id) {
    283     SendAcceptReply(
    284         context, PP_OK, pending_resource_id, local_addr, remote_addr);
    285   } else {
    286     SendAcceptError(context, PP_ERROR_NOSPACE);
    287   }
    288 }
    289 
    290 void PepperTCPServerSocketMessageFilter::SendListenReply(
    291     const ppapi::host::ReplyMessageContext& context,
    292     int32_t pp_result,
    293     const PP_NetAddress_Private& local_addr) {
    294   ppapi::host::ReplyMessageContext reply_context(context);
    295   reply_context.params.set_result(pp_result);
    296   SendReply(reply_context,
    297             PpapiPluginMsg_TCPServerSocket_ListenReply(local_addr));
    298 }
    299 
    300 void PepperTCPServerSocketMessageFilter::SendListenError(
    301     const ppapi::host::ReplyMessageContext& context,
    302     int32_t pp_result) {
    303   SendListenReply(
    304       context, pp_result, NetAddressPrivateImpl::kInvalidNetAddress);
    305 }
    306 
    307 void PepperTCPServerSocketMessageFilter::SendAcceptReply(
    308     const ppapi::host::ReplyMessageContext& context,
    309     int32_t pp_result,
    310     int pending_resource_id,
    311     const PP_NetAddress_Private& local_addr,
    312     const PP_NetAddress_Private& remote_addr) {
    313   ppapi::host::ReplyMessageContext reply_context(context);
    314   reply_context.params.set_result(pp_result);
    315   SendReply(reply_context,
    316             PpapiPluginMsg_TCPServerSocket_AcceptReply(
    317                 pending_resource_id, local_addr, remote_addr));
    318 }
    319 
    320 void PepperTCPServerSocketMessageFilter::SendAcceptError(
    321     const ppapi::host::ReplyMessageContext& context,
    322     int32_t pp_result) {
    323   SendAcceptReply(context,
    324                   pp_result,
    325                   0,
    326                   NetAddressPrivateImpl::kInvalidNetAddress,
    327                   NetAddressPrivateImpl::kInvalidNetAddress);
    328 }
    329 
    330 }  // namespace content
    331