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/browser_ppapi_host_impl.h"
      6 
      7 #include "base/metrics/sparse_histogram.h"
      8 #include "content/browser/renderer_host/pepper/pepper_message_filter.h"
      9 #include "content/browser/tracing/trace_message_filter.h"
     10 #include "content/common/pepper_renderer_instance_data.h"
     11 #include "content/public/common/process_type.h"
     12 #include "ipc/ipc_message_macros.h"
     13 #include "ppapi/proxy/ppapi_messages.h"
     14 
     15 namespace content {
     16 
     17 // static
     18 BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess(
     19     IPC::Sender* sender,
     20     ppapi::PpapiPermissions permissions,
     21     base::ProcessHandle plugin_child_process,
     22     IPC::ChannelProxy* channel,
     23     int render_process_id,
     24     int render_view_id,
     25     const base::FilePath& profile_directory) {
     26   // The plugin name and path shouldn't be needed for external plugins.
     27   BrowserPpapiHostImpl* browser_ppapi_host =
     28       new BrowserPpapiHostImpl(sender,
     29                                permissions,
     30                                std::string(),
     31                                base::FilePath(),
     32                                profile_directory,
     33                                false /* in_process */,
     34                                true /* external_plugin */);
     35   browser_ppapi_host->set_plugin_process_handle(plugin_child_process);
     36 
     37   scoped_refptr<PepperMessageFilter> pepper_message_filter(
     38       new PepperMessageFilter());
     39   channel->AddFilter(pepper_message_filter->GetFilter());
     40   channel->AddFilter(browser_ppapi_host->message_filter().get());
     41   channel->AddFilter((new TraceMessageFilter())->GetFilter());
     42 
     43   return browser_ppapi_host;
     44 }
     45 
     46 BrowserPpapiHostImpl::BrowserPpapiHostImpl(
     47     IPC::Sender* sender,
     48     const ppapi::PpapiPermissions& permissions,
     49     const std::string& plugin_name,
     50     const base::FilePath& plugin_path,
     51     const base::FilePath& profile_data_directory,
     52     bool in_process,
     53     bool external_plugin)
     54     : ppapi_host_(new ppapi::host::PpapiHost(sender, permissions)),
     55       plugin_process_handle_(base::kNullProcessHandle),
     56       plugin_name_(plugin_name),
     57       plugin_path_(plugin_path),
     58       profile_data_directory_(profile_data_directory),
     59       in_process_(in_process),
     60       external_plugin_(external_plugin),
     61       ssl_context_helper_(new SSLContextHelper()) {
     62   message_filter_ = new HostMessageFilter(ppapi_host_.get(), this);
     63   ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
     64       new ContentBrowserPepperHostFactory(this)));
     65 }
     66 
     67 BrowserPpapiHostImpl::~BrowserPpapiHostImpl() {
     68   // Notify the filter so it won't foward messages to us.
     69   message_filter_->OnHostDestroyed();
     70 
     71   // Delete the host explicitly first. This shutdown will destroy the
     72   // resources, which may want to do cleanup in their destructors and expect
     73   // their pointers to us to be valid.
     74   ppapi_host_.reset();
     75 }
     76 
     77 ppapi::host::PpapiHost* BrowserPpapiHostImpl::GetPpapiHost() {
     78   return ppapi_host_.get();
     79 }
     80 
     81 base::ProcessHandle BrowserPpapiHostImpl::GetPluginProcessHandle() const {
     82   // Handle should previously have been set before use.
     83   DCHECK(in_process_ || plugin_process_handle_ != base::kNullProcessHandle);
     84   return plugin_process_handle_;
     85 }
     86 
     87 bool BrowserPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
     88   return instance_map_.find(instance) != instance_map_.end();
     89 }
     90 
     91 bool BrowserPpapiHostImpl::GetRenderFrameIDsForInstance(
     92     PP_Instance instance,
     93     int* render_process_id,
     94     int* render_frame_id) const {
     95   InstanceMap::const_iterator found = instance_map_.find(instance);
     96   if (found == instance_map_.end()) {
     97     *render_process_id = 0;
     98     *render_frame_id = 0;
     99     return false;
    100   }
    101 
    102   *render_process_id = found->second.render_process_id;
    103   *render_frame_id = found->second.render_frame_id;
    104   return true;
    105 }
    106 
    107 const std::string& BrowserPpapiHostImpl::GetPluginName() {
    108   return plugin_name_;
    109 }
    110 
    111 const base::FilePath& BrowserPpapiHostImpl::GetPluginPath() {
    112   return plugin_path_;
    113 }
    114 
    115 const base::FilePath& BrowserPpapiHostImpl::GetProfileDataDirectory() {
    116   return profile_data_directory_;
    117 }
    118 
    119 GURL BrowserPpapiHostImpl::GetDocumentURLForInstance(PP_Instance instance) {
    120   InstanceMap::const_iterator found = instance_map_.find(instance);
    121   if (found == instance_map_.end())
    122     return GURL();
    123   return found->second.document_url;
    124 }
    125 
    126 GURL BrowserPpapiHostImpl::GetPluginURLForInstance(PP_Instance instance) {
    127   InstanceMap::const_iterator found = instance_map_.find(instance);
    128   if (found == instance_map_.end())
    129     return GURL();
    130   return found->second.plugin_url;
    131 }
    132 
    133 void BrowserPpapiHostImpl::SetOnKeepaliveCallback(
    134     const BrowserPpapiHost::OnKeepaliveCallback& callback) {
    135   on_keepalive_callback_ = callback;
    136 }
    137 
    138 void BrowserPpapiHostImpl::AddInstance(
    139     PP_Instance instance,
    140     const PepperRendererInstanceData& instance_data) {
    141   DCHECK(instance_map_.find(instance) == instance_map_.end());
    142   instance_map_[instance] = instance_data;
    143 }
    144 
    145 void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance) {
    146   InstanceMap::iterator found = instance_map_.find(instance);
    147   if (found == instance_map_.end()) {
    148     NOTREACHED();
    149     return;
    150   }
    151   instance_map_.erase(found);
    152 }
    153 
    154 BrowserPpapiHostImpl::HostMessageFilter::HostMessageFilter(
    155     ppapi::host::PpapiHost* ppapi_host,
    156     BrowserPpapiHostImpl* browser_ppapi_host_impl)
    157     : ppapi_host_(ppapi_host),
    158       browser_ppapi_host_impl_(browser_ppapi_host_impl) {}
    159 
    160 bool BrowserPpapiHostImpl::HostMessageFilter::OnMessageReceived(
    161     const IPC::Message& msg) {
    162   // Don't forward messages if our owner object has been destroyed.
    163   if (!ppapi_host_)
    164     return false;
    165 
    166   bool handled = true;
    167   IPC_BEGIN_MESSAGE_MAP(BrowserPpapiHostImpl::HostMessageFilter, msg)
    168   // Add necessary message handlers here.
    169   IPC_MESSAGE_HANDLER(PpapiHostMsg_Keepalive, OnKeepalive)
    170   IPC_MESSAGE_HANDLER(PpapiHostMsg_LogInterfaceUsage,
    171                       OnHostMsgLogInterfaceUsage)
    172   IPC_MESSAGE_UNHANDLED(handled = ppapi_host_->OnMessageReceived(msg))
    173   IPC_END_MESSAGE_MAP();
    174   return handled;
    175 }
    176 
    177 void BrowserPpapiHostImpl::HostMessageFilter::OnHostDestroyed() {
    178   DCHECK(ppapi_host_);
    179   ppapi_host_ = NULL;
    180   browser_ppapi_host_impl_ = NULL;
    181 }
    182 
    183 BrowserPpapiHostImpl::HostMessageFilter::~HostMessageFilter() {}
    184 
    185 void BrowserPpapiHostImpl::HostMessageFilter::OnKeepalive() {
    186   if (browser_ppapi_host_impl_)
    187     browser_ppapi_host_impl_->OnKeepalive();
    188 }
    189 
    190 void BrowserPpapiHostImpl::HostMessageFilter::OnHostMsgLogInterfaceUsage(
    191     int hash) const {
    192   UMA_HISTOGRAM_SPARSE_SLOWLY("Pepper.InterfaceUsed", hash);
    193 }
    194 
    195 void BrowserPpapiHostImpl::OnKeepalive() {
    196   // An instance has been active. The on_keepalive_callback_ will be
    197   // used to permit the content embedder to handle this, e.g. by tracking
    198   // activity and shutting down processes that go idle.
    199   //
    200   // Currently embedders do not need to distinguish between instances having
    201   // different idle state, and thus this implementation handles all instances
    202   // for this module together.
    203 
    204   if (on_keepalive_callback_.is_null())
    205     return;
    206 
    207   BrowserPpapiHost::OnKeepaliveInstanceData instance_data(instance_map_.size());
    208 
    209   InstanceMap::iterator instance = instance_map_.begin();
    210   int i = 0;
    211   while (instance != instance_map_.end()) {
    212     instance_data[i].render_process_id = instance->second.render_process_id;
    213     instance_data[i].render_frame_id = instance->second.render_frame_id;
    214     instance_data[i].document_url = instance->second.document_url;
    215     ++instance;
    216     ++i;
    217   }
    218   on_keepalive_callback_.Run(instance_data, profile_data_directory_);
    219 }
    220 
    221 }  // namespace content
    222