Home | History | Annotate | Download | only in pepper
      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/pepper/pepper_message_filter.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/callback.h"
     10 #include "base/compiler_specific.h"
     11 #include "base/files/file_path.h"
     12 #include "base/logging.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "base/threading/sequenced_worker_pool.h"
     16 #include "base/threading/worker_pool.h"
     17 #include "build/build_config.h"
     18 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
     19 #include "content/browser/renderer_host/pepper/pepper_tcp_socket.h"
     20 #include "content/browser/renderer_host/render_process_host_impl.h"
     21 #include "content/browser/renderer_host/render_view_host_impl.h"
     22 #include "content/common/pepper_messages.h"
     23 #include "content/public/browser/browser_context.h"
     24 #include "content/public/browser/browser_thread.h"
     25 #include "content/public/browser/content_browser_client.h"
     26 #include "content/public/browser/resource_context.h"
     27 #include "content/public/common/content_client.h"
     28 #include "net/base/address_family.h"
     29 #include "net/base/address_list.h"
     30 #include "net/base/host_port_pair.h"
     31 #include "net/base/sys_addrinfo.h"
     32 #include "net/cert/cert_verifier.h"
     33 #include "ppapi/c/pp_errors.h"
     34 #include "ppapi/c/private/ppb_net_address_private.h"
     35 #include "ppapi/proxy/ppapi_messages.h"
     36 #include "ppapi/shared_impl/api_id.h"
     37 #include "ppapi/shared_impl/private/net_address_private_impl.h"
     38 #include "ppapi/shared_impl/socket_option_data.h"
     39 
     40 using ppapi::NetAddressPrivateImpl;
     41 
     42 namespace content {
     43 namespace {
     44 
     45 const size_t kMaxSocketsAllowed = 1024;
     46 const uint32 kInvalidSocketID = 0;
     47 
     48 }  // namespace
     49 
     50 PepperMessageFilter::PepperMessageFilter(int process_id,
     51                                          BrowserContext* browser_context)
     52     : plugin_type_(PLUGIN_TYPE_IN_PROCESS),
     53       permissions_(),
     54       process_id_(process_id),
     55       external_plugin_render_view_id_(0),
     56       resource_context_(browser_context->GetResourceContext()),
     57       host_resolver_(NULL),
     58       next_socket_id_(1) {
     59   DCHECK(browser_context);
     60   // Keep BrowserContext data in FILE-thread friendly storage.
     61   browser_path_ = browser_context->GetPath();
     62   incognito_ = browser_context->IsOffTheRecord();
     63   DCHECK(resource_context_);
     64 }
     65 
     66 PepperMessageFilter::PepperMessageFilter(
     67     const ppapi::PpapiPermissions& permissions,
     68     net::HostResolver* host_resolver)
     69     : plugin_type_(PLUGIN_TYPE_OUT_OF_PROCESS),
     70       permissions_(permissions),
     71       process_id_(0),
     72       external_plugin_render_view_id_(0),
     73       resource_context_(NULL),
     74       host_resolver_(host_resolver),
     75       next_socket_id_(1),
     76       incognito_(false) {
     77   DCHECK(host_resolver);
     78 }
     79 
     80 PepperMessageFilter::PepperMessageFilter(
     81     const ppapi::PpapiPermissions& permissions,
     82     net::HostResolver* host_resolver,
     83     int process_id,
     84     int render_view_id)
     85     : plugin_type_(PLUGIN_TYPE_EXTERNAL_PLUGIN),
     86       permissions_(permissions),
     87       process_id_(process_id),
     88       external_plugin_render_view_id_(render_view_id),
     89       resource_context_(NULL),
     90       host_resolver_(host_resolver),
     91       next_socket_id_(1) {
     92   DCHECK(host_resolver);
     93 }
     94 
     95 bool PepperMessageFilter::OnMessageReceived(const IPC::Message& msg,
     96                                             bool* message_was_ok) {
     97   bool handled = true;
     98   IPC_BEGIN_MESSAGE_MAP_EX(PepperMessageFilter, msg, *message_was_ok)
     99     // TCP messages.
    100     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Create, OnTCPCreate)
    101     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_CreatePrivate,
    102                         OnTCPCreatePrivate)
    103     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Connect, OnTCPConnect)
    104     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress,
    105                         OnTCPConnectWithNetAddress)
    106     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_SSLHandshake,
    107                         OnTCPSSLHandshake)
    108     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Read, OnTCPRead)
    109     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Write, OnTCPWrite)
    110     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Disconnect, OnTCPDisconnect)
    111     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_SetOption, OnTCPSetOption)
    112 
    113     // NetworkMonitor messages.
    114     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBNetworkMonitor_Start,
    115                         OnNetworkMonitorStart)
    116     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBNetworkMonitor_Stop,
    117                         OnNetworkMonitorStop)
    118 
    119     // X509 certificate messages.
    120     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBX509Certificate_ParseDER,
    121                         OnX509CertificateParseDER);
    122 
    123   IPC_MESSAGE_UNHANDLED(handled = false)
    124   IPC_END_MESSAGE_MAP_EX()
    125   return handled;
    126 }
    127 
    128 void PepperMessageFilter::OnIPAddressChanged() {
    129   GetAndSendNetworkList();
    130 }
    131 
    132 net::HostResolver* PepperMessageFilter::GetHostResolver() {
    133   return resource_context_ ?
    134       resource_context_->GetHostResolver() : host_resolver_;
    135 }
    136 
    137 net::CertVerifier* PepperMessageFilter::GetCertVerifier() {
    138   if (!cert_verifier_)
    139     cert_verifier_.reset(net::CertVerifier::CreateDefault());
    140 
    141   return cert_verifier_.get();
    142 }
    143 
    144 net::TransportSecurityState* PepperMessageFilter::GetTransportSecurityState() {
    145   if (!transport_security_state_)
    146     transport_security_state_.reset(new net::TransportSecurityState);
    147 
    148   return transport_security_state_.get();
    149 }
    150 
    151 uint32 PepperMessageFilter::AddAcceptedTCPSocket(
    152     int32 routing_id,
    153     uint32 plugin_dispatcher_id,
    154     net::StreamSocket* socket) {
    155   scoped_ptr<net::StreamSocket> s(socket);
    156 
    157   uint32 tcp_socket_id = GenerateSocketID();
    158   if (tcp_socket_id != kInvalidSocketID) {
    159     // Currently all TCP sockets created this way correspond to
    160     // PPB_TCPSocket_Private.
    161     tcp_sockets_[tcp_socket_id] = linked_ptr<PepperTCPSocket>(
    162         new PepperTCPSocket(this,
    163                             routing_id,
    164                             plugin_dispatcher_id,
    165                             tcp_socket_id,
    166                             s.release(),
    167                             true /* private_api */));
    168   }
    169   return tcp_socket_id;
    170 }
    171 
    172 PepperMessageFilter::~PepperMessageFilter() {
    173   if (!network_monitor_ids_.empty())
    174     net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
    175 }
    176 
    177 void PepperMessageFilter::OnTCPCreate(int32 routing_id,
    178                                       uint32 plugin_dispatcher_id,
    179                                       uint32* socket_id) {
    180   CreateTCPSocket(routing_id, plugin_dispatcher_id, false, socket_id);
    181 }
    182 
    183 void PepperMessageFilter::OnTCPCreatePrivate(int32 routing_id,
    184                                              uint32 plugin_dispatcher_id,
    185                                              uint32* socket_id) {
    186   CreateTCPSocket(routing_id, plugin_dispatcher_id, true, socket_id);
    187 }
    188 
    189 void PepperMessageFilter::OnTCPConnect(int32 routing_id,
    190                                        uint32 socket_id,
    191                                        const std::string& host,
    192                                        uint16_t port) {
    193   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    194   TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
    195   if (iter == tcp_sockets_.end()) {
    196     NOTREACHED();
    197     return;
    198   }
    199 
    200   // This is only supported by PPB_TCPSocket_Private.
    201   if (!iter->second->private_api()) {
    202     NOTREACHED();
    203     return;
    204   }
    205 
    206   content::SocketPermissionRequest params(
    207       content::SocketPermissionRequest::TCP_CONNECT, host, port);
    208   BrowserThread::PostTaskAndReplyWithResult(
    209       BrowserThread::UI, FROM_HERE,
    210       base::Bind(&PepperMessageFilter::CanUseSocketAPIs, this,
    211                  routing_id, params, true /* private_api */),
    212       base::Bind(&PepperMessageFilter::DoTCPConnect, this,
    213                  routing_id, socket_id, host, port));
    214 }
    215 
    216 void PepperMessageFilter::DoTCPConnect(int32 routing_id,
    217                                        uint32 socket_id,
    218                                        const std::string& host,
    219                                        uint16_t port,
    220                                        bool allowed) {
    221   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    222   TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
    223   if (iter == tcp_sockets_.end()) {
    224     // Due to current permission check process (IO -> UI -> IO) some
    225     // calls to the TCP socket interface can be intermixed (like
    226     // Connect and Close). So, NOTREACHED() is not appropriate here.
    227     return;
    228   }
    229 
    230   if (routing_id == iter->second->routing_id() && allowed)
    231     iter->second->Connect(host, port);
    232   else
    233     iter->second->SendConnectACKError(PP_ERROR_NOACCESS);
    234 }
    235 
    236 void PepperMessageFilter::OnTCPConnectWithNetAddress(
    237     int32 routing_id,
    238     uint32 socket_id,
    239     const PP_NetAddress_Private& net_addr) {
    240   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    241   TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
    242   if (iter == tcp_sockets_.end()) {
    243     NOTREACHED();
    244     return;
    245   }
    246 
    247   content::SocketPermissionRequest params =
    248       pepper_socket_utils::CreateSocketPermissionRequest(
    249           content::SocketPermissionRequest::TCP_CONNECT, net_addr);
    250   BrowserThread::PostTaskAndReplyWithResult(
    251       BrowserThread::UI, FROM_HERE,
    252       base::Bind(&PepperMessageFilter::CanUseSocketAPIs, this,
    253                  routing_id, params, iter->second->private_api()),
    254       base::Bind(&PepperMessageFilter::DoTCPConnectWithNetAddress, this,
    255                  routing_id, socket_id, net_addr));
    256 }
    257 
    258 void PepperMessageFilter::DoTCPConnectWithNetAddress(
    259     int32 routing_id,
    260     uint32 socket_id,
    261     const PP_NetAddress_Private& net_addr,
    262     bool allowed) {
    263   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    264   TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
    265   if (iter == tcp_sockets_.end()) {
    266     // Due to current permission check process (IO -> UI -> IO) some
    267     // calls to the TCP socket interface can be intermixed (like
    268     // ConnectWithNetAddress and Close). So, NOTREACHED() is not
    269     // appropriate here.
    270     return;
    271   }
    272 
    273   if (routing_id == iter->second->routing_id() && allowed)
    274     iter->second->ConnectWithNetAddress(net_addr);
    275   else
    276     iter->second->SendConnectACKError(PP_ERROR_NOACCESS);
    277 }
    278 
    279 void PepperMessageFilter::OnTCPSSLHandshake(
    280     uint32 socket_id,
    281     const std::string& server_name,
    282     uint16_t server_port,
    283     const std::vector<std::vector<char> >& trusted_certs,
    284     const std::vector<std::vector<char> >& untrusted_certs) {
    285   TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
    286   if (iter == tcp_sockets_.end()) {
    287     NOTREACHED();
    288     return;
    289   }
    290 
    291   // This is only supported by PPB_TCPSocket_Private.
    292   if (!iter->second->private_api()) {
    293     NOTREACHED();
    294     return;
    295   }
    296 
    297   iter->second->SSLHandshake(server_name, server_port, trusted_certs,
    298                              untrusted_certs);
    299 }
    300 
    301 void PepperMessageFilter::OnTCPRead(uint32 socket_id, int32_t bytes_to_read) {
    302   TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
    303   if (iter == tcp_sockets_.end()) {
    304     NOTREACHED();
    305     return;
    306   }
    307 
    308   iter->second->Read(bytes_to_read);
    309 }
    310 
    311 void PepperMessageFilter::OnTCPWrite(uint32 socket_id,
    312                                      const std::string& data) {
    313   TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
    314   if (iter == tcp_sockets_.end()) {
    315     NOTREACHED();
    316     return;
    317   }
    318 
    319   iter->second->Write(data);
    320 }
    321 
    322 void PepperMessageFilter::OnTCPDisconnect(uint32 socket_id) {
    323   TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
    324   if (iter == tcp_sockets_.end()) {
    325     NOTREACHED();
    326     return;
    327   }
    328 
    329   // Destroying the TCPSocket instance will cancel any pending completion
    330   // callback. From this point on, there won't be any messages associated with
    331   // this socket sent to the plugin side.
    332   tcp_sockets_.erase(iter);
    333 }
    334 
    335 void PepperMessageFilter::OnTCPSetOption(uint32 socket_id,
    336                                          PP_TCPSocket_Option name,
    337                                          const ppapi::SocketOptionData& value) {
    338   TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id);
    339   if (iter == tcp_sockets_.end()) {
    340     NOTREACHED();
    341     return;
    342   }
    343 
    344   iter->second->SetOption(name, value);
    345 }
    346 
    347 void PepperMessageFilter::OnNetworkMonitorStart(uint32 plugin_dispatcher_id) {
    348   // Support all in-process plugins, and ones with "private" permissions.
    349   if (plugin_type_ != PLUGIN_TYPE_IN_PROCESS &&
    350       !permissions_.HasPermission(ppapi::PERMISSION_PRIVATE)) {
    351     return;
    352   }
    353 
    354   if (network_monitor_ids_.empty())
    355     net::NetworkChangeNotifier::AddIPAddressObserver(this);
    356 
    357   network_monitor_ids_.insert(plugin_dispatcher_id);
    358   GetAndSendNetworkList();
    359 }
    360 
    361 void PepperMessageFilter::OnNetworkMonitorStop(uint32 plugin_dispatcher_id) {
    362   // Support all in-process plugins, and ones with "private" permissions.
    363   if (plugin_type_ != PLUGIN_TYPE_IN_PROCESS &&
    364       !permissions_.HasPermission(ppapi::PERMISSION_PRIVATE)) {
    365     return;
    366   }
    367 
    368   network_monitor_ids_.erase(plugin_dispatcher_id);
    369   if (network_monitor_ids_.empty())
    370     net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
    371 }
    372 
    373 void PepperMessageFilter::OnX509CertificateParseDER(
    374     const std::vector<char>& der,
    375     bool* succeeded,
    376     ppapi::PPB_X509Certificate_Fields* result) {
    377   if (der.size() == 0)
    378     *succeeded = false;
    379   *succeeded = PepperTCPSocket::GetCertificateFields(&der[0], der.size(),
    380                                                      result);
    381 }
    382 
    383 uint32 PepperMessageFilter::GenerateSocketID() {
    384   // TODO(yzshen): Change to use Pepper resource ID as socket ID.
    385   //
    386   // Generate a socket ID. For each process which sends us socket requests, IDs
    387   // of living sockets must be unique, to each socket type.
    388   //
    389   // However, it is safe to generate IDs based on the internal state of a single
    390   // PepperSocketMessageHandler object, because for each plugin or renderer
    391   // process, there is at most one PepperMessageFilter (in other words, at most
    392   // one PepperSocketMessageHandler) talking to it.
    393   if (tcp_sockets_.size() >= kMaxSocketsAllowed)
    394     return kInvalidSocketID;
    395 
    396   uint32 socket_id = kInvalidSocketID;
    397   do {
    398     // Although it is unlikely, make sure that we won't cause any trouble when
    399     // the counter overflows.
    400     socket_id = next_socket_id_++;
    401   } while (socket_id == kInvalidSocketID ||
    402            tcp_sockets_.find(socket_id) != tcp_sockets_.end());
    403 
    404   return socket_id;
    405 }
    406 
    407 bool PepperMessageFilter::CanUseSocketAPIs(
    408     int32 render_id,
    409     const content::SocketPermissionRequest& params,
    410     bool private_api) {
    411   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    412 
    413   // External plugins always get their own PepperMessageFilter, initialized with
    414   // a render view id. Use this instead of the one that came with the message,
    415   // which is actually an API ID.
    416   bool external_plugin = false;
    417   if (plugin_type_ == PLUGIN_TYPE_EXTERNAL_PLUGIN) {
    418     external_plugin = true;
    419     render_id = external_plugin_render_view_id_;
    420   }
    421 
    422   RenderViewHostImpl* render_view_host =
    423       RenderViewHostImpl::FromID(process_id_, render_id);
    424 
    425   return pepper_socket_utils::CanUseSocketAPIs(external_plugin,
    426                                                private_api,
    427                                                params,
    428                                                render_view_host);
    429 }
    430 
    431 void PepperMessageFilter::GetAndSendNetworkList() {
    432   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    433 
    434   BrowserThread::PostBlockingPoolTask(
    435       FROM_HERE, base::Bind(&PepperMessageFilter::DoGetNetworkList, this));
    436 }
    437 
    438 void PepperMessageFilter::DoGetNetworkList() {
    439   scoped_ptr<net::NetworkInterfaceList> list(new net::NetworkInterfaceList());
    440   net::GetNetworkList(list.get());
    441   BrowserThread::PostTask(
    442       BrowserThread::IO, FROM_HERE,
    443       base::Bind(&PepperMessageFilter::SendNetworkList,
    444                  this, base::Passed(&list)));
    445 }
    446 
    447 void PepperMessageFilter::SendNetworkList(
    448     scoped_ptr<net::NetworkInterfaceList> list) {
    449   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    450 
    451   scoped_ptr< ::ppapi::NetworkList> list_copy(
    452       new ::ppapi::NetworkList(list->size()));
    453   for (size_t i = 0; i < list->size(); ++i) {
    454     const net::NetworkInterface& network = list->at(i);
    455     ::ppapi::NetworkInfo& network_copy = list_copy->at(i);
    456     network_copy.name = network.name;
    457 
    458     network_copy.addresses.resize(1, NetAddressPrivateImpl::kInvalidNetAddress);
    459     bool result = NetAddressPrivateImpl::IPEndPointToNetAddress(
    460         network.address, 0, &(network_copy.addresses[0]));
    461     DCHECK(result);
    462 
    463     // TODO(sergeyu): Currently net::NetworkInterfaceList provides
    464     // only name and one IP address. Add all other fields and copy
    465     // them here.
    466     network_copy.type = PP_NETWORKLIST_UNKNOWN;
    467     network_copy.state = PP_NETWORKLIST_UP;
    468     network_copy.display_name = network.name;
    469     network_copy.mtu = 0;
    470   }
    471   for (NetworkMonitorIdSet::iterator it = network_monitor_ids_.begin();
    472        it != network_monitor_ids_.end(); ++it) {
    473     Send(new PpapiMsg_PPBNetworkMonitor_NetworkList(
    474         ppapi::API_ID_PPB_NETWORKMANAGER_PRIVATE, *it, *list_copy));
    475   }
    476 }
    477 
    478 void PepperMessageFilter::CreateTCPSocket(int32 routing_id,
    479                                           uint32 plugin_dispatcher_id,
    480                                           bool private_api,
    481                                           uint32* socket_id) {
    482   *socket_id = GenerateSocketID();
    483   if (*socket_id == kInvalidSocketID)
    484     return;
    485 
    486   tcp_sockets_[*socket_id] = linked_ptr<PepperTCPSocket>(
    487       new PepperTCPSocket(this, routing_id, plugin_dispatcher_id, *socket_id,
    488                           private_api));
    489 }
    490 
    491 }  // namespace content
    492