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/renderer/pepper/renderer_ppapi_host_impl.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/files/file_path.h"
      9 #include "base/logging.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/process/process_handle.h"
     12 #include "content/common/sandbox_util.h"
     13 #include "content/renderer/pepper/fullscreen_container.h"
     14 #include "content/renderer/pepper/host_globals.h"
     15 #include "content/renderer/pepper/pepper_browser_connection.h"
     16 #include "content/renderer/pepper/pepper_graphics_2d_host.h"
     17 #include "content/renderer/pepper/pepper_in_process_resource_creation.h"
     18 #include "content/renderer/pepper/pepper_in_process_router.h"
     19 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
     20 #include "content/renderer/pepper/plugin_module.h"
     21 #include "content/renderer/render_view_impl.h"
     22 #include "content/renderer/render_widget_fullscreen_pepper.h"
     23 #include "ipc/ipc_message.h"
     24 #include "ppapi/host/ppapi_host.h"
     25 #include "ppapi/proxy/host_dispatcher.h"
     26 #include "third_party/WebKit/public/platform/WebRect.h"
     27 #include "third_party/WebKit/public/web/WebDocument.h"
     28 #include "third_party/WebKit/public/web/WebElement.h"
     29 #include "third_party/WebKit/public/web/WebPluginContainer.h"
     30 #include "ui/gfx/point.h"
     31 
     32 namespace content {
     33 // static
     34 CONTENT_EXPORT RendererPpapiHost* RendererPpapiHost::GetForPPInstance(
     35     PP_Instance instance) {
     36   return RendererPpapiHostImpl::GetForPPInstance(instance);
     37 }
     38 
     39 // Out-of-process constructor.
     40 RendererPpapiHostImpl::RendererPpapiHostImpl(
     41     PluginModule* module,
     42     ppapi::proxy::HostDispatcher* dispatcher,
     43     const ppapi::PpapiPermissions& permissions)
     44     : module_(module),
     45       dispatcher_(dispatcher),
     46       is_external_plugin_host_(false) {
     47   // Hook the PpapiHost up to the dispatcher for out-of-process communication.
     48   ppapi_host_.reset(new ppapi::host::PpapiHost(dispatcher, permissions));
     49   ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
     50       new ContentRendererPepperHostFactory(this)));
     51   dispatcher->AddFilter(ppapi_host_.get());
     52   is_running_in_process_ = false;
     53 }
     54 
     55 // In-process constructor.
     56 RendererPpapiHostImpl::RendererPpapiHostImpl(
     57     PluginModule* module,
     58     const ppapi::PpapiPermissions& permissions)
     59     : module_(module), dispatcher_(NULL), is_external_plugin_host_(false) {
     60   // Hook the host up to the in-process router.
     61   in_process_router_.reset(new PepperInProcessRouter(this));
     62   ppapi_host_.reset(new ppapi::host::PpapiHost(
     63       in_process_router_->GetRendererToPluginSender(), permissions));
     64   ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
     65       new ContentRendererPepperHostFactory(this)));
     66   is_running_in_process_ = true;
     67 }
     68 
     69 RendererPpapiHostImpl::~RendererPpapiHostImpl() {
     70   // Delete the host explicitly first. This shutdown will destroy the
     71   // resources, which may want to do cleanup in their destructors and expect
     72   // their pointers to us to be valid.
     73   ppapi_host_.reset();
     74 }
     75 
     76 // static
     77 RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
     78     PluginModule* module,
     79     ppapi::proxy::HostDispatcher* dispatcher,
     80     const ppapi::PpapiPermissions& permissions) {
     81   DCHECK(!module->renderer_ppapi_host());
     82   RendererPpapiHostImpl* result =
     83       new RendererPpapiHostImpl(module, dispatcher, permissions);
     84 
     85   // Takes ownership of pointer.
     86   module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
     87 
     88   return result;
     89 }
     90 
     91 // static
     92 RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForInProcess(
     93     PluginModule* module,
     94     const ppapi::PpapiPermissions& permissions) {
     95   DCHECK(!module->renderer_ppapi_host());
     96   RendererPpapiHostImpl* result =
     97       new RendererPpapiHostImpl(module, permissions);
     98 
     99   // Takes ownership of pointer.
    100   module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
    101 
    102   return result;
    103 }
    104 
    105 // static
    106 RendererPpapiHostImpl* RendererPpapiHostImpl::GetForPPInstance(
    107     PP_Instance pp_instance) {
    108   PepperPluginInstanceImpl* instance =
    109       HostGlobals::Get()->GetInstance(pp_instance);
    110   if (!instance)
    111     return NULL;
    112 
    113   // All modules created by content will have their embedder state be the
    114   // host impl.
    115   return instance->module()->renderer_ppapi_host();
    116 }
    117 
    118 scoped_ptr<ppapi::thunk::ResourceCreationAPI>
    119 RendererPpapiHostImpl::CreateInProcessResourceCreationAPI(
    120     PepperPluginInstanceImpl* instance) {
    121   return scoped_ptr<ppapi::thunk::ResourceCreationAPI>(
    122       new PepperInProcessResourceCreation(this, instance));
    123 }
    124 
    125 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetPluginInstanceImpl(
    126     PP_Instance instance) const {
    127   return GetAndValidateInstance(instance);
    128 }
    129 
    130 bool RendererPpapiHostImpl::IsExternalPluginHost() const {
    131   return is_external_plugin_host_;
    132 }
    133 
    134 ppapi::host::PpapiHost* RendererPpapiHostImpl::GetPpapiHost() {
    135   return ppapi_host_.get();
    136 }
    137 
    138 RenderFrame* RendererPpapiHostImpl::GetRenderFrameForInstance(
    139     PP_Instance instance) const {
    140   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
    141   if (!instance_object)
    142     return NULL;
    143 
    144   // Since we're the embedder, we can make assumptions about the helper on
    145   // the instance and get back to our RenderFrame.
    146   return instance_object->render_frame();
    147 }
    148 
    149 RenderView* RendererPpapiHostImpl::GetRenderViewForInstance(
    150     PP_Instance instance) const {
    151   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
    152   if (!instance_object)
    153     return NULL;
    154 
    155   // Since we're the embedder, we can make assumptions about the helper on
    156   // the instance and get back to our RenderView.
    157   return instance_object->render_frame()->render_view();
    158 }
    159 
    160 bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
    161   return !!GetAndValidateInstance(instance);
    162 }
    163 
    164 PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance(
    165     PP_Instance instance) const {
    166   return GetAndValidateInstance(instance);
    167 }
    168 
    169 blink::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance(
    170     PP_Instance instance) const {
    171   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
    172   if (!instance_object)
    173     return NULL;
    174   return instance_object->container();
    175 }
    176 
    177 base::ProcessId RendererPpapiHostImpl::GetPluginPID() const {
    178   if (dispatcher_)
    179     return dispatcher_->channel()->GetPeerPID();
    180   return base::kNullProcessId;
    181 }
    182 
    183 bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance) const {
    184   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
    185   if (!instance_object)
    186     return false;
    187 
    188   if (instance_object->module()->permissions().HasPermission(
    189           ppapi::PERMISSION_BYPASS_USER_GESTURE))
    190     return true;
    191   return instance_object->IsProcessingUserGesture();
    192 }
    193 
    194 int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance) const {
    195   PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
    196   if (!plugin_instance)
    197     return 0;
    198   if (plugin_instance->flash_fullscreen()) {
    199     FullscreenContainer* container = plugin_instance->fullscreen_container();
    200     return static_cast<RenderWidgetFullscreenPepper*>(container)->routing_id();
    201   }
    202   return GetRenderViewForInstance(instance)->GetRoutingID();
    203 }
    204 
    205 gfx::Point RendererPpapiHostImpl::PluginPointToRenderFrame(
    206     PP_Instance instance,
    207     const gfx::Point& pt) const {
    208   PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
    209   if (!plugin_instance || plugin_instance->flash_fullscreen()) {
    210     // Flash fullscreen is special in that it renders into its own separate,
    211     // dedicated window.  So, do not offset the point.
    212     return pt;
    213   }
    214   return gfx::Point(pt.x() + plugin_instance->view_data().rect.point.x,
    215                     pt.y() + plugin_instance->view_data().rect.point.y);
    216 }
    217 
    218 IPC::PlatformFileForTransit RendererPpapiHostImpl::ShareHandleWithRemote(
    219     base::PlatformFile handle,
    220     bool should_close_source) {
    221   if (!dispatcher_) {
    222     DCHECK(is_running_in_process_);
    223     // Duplicate the file handle for in process mode so this function
    224     // has the same semantics for both in process mode and out of
    225     // process mode (i.e., the remote side must cloes the handle).
    226     return BrokerGetFileHandleForProcess(
    227         handle, base::GetCurrentProcId(), should_close_source);
    228   }
    229   return dispatcher_->ShareHandleWithRemote(handle, should_close_source);
    230 }
    231 
    232 bool RendererPpapiHostImpl::IsRunningInProcess() const {
    233   return is_running_in_process_;
    234 }
    235 
    236 std::string RendererPpapiHostImpl::GetPluginName() const {
    237   return module_->name();
    238 }
    239 
    240 void RendererPpapiHostImpl::SetToExternalPluginHost() {
    241   is_external_plugin_host_ = true;
    242 }
    243 
    244 void RendererPpapiHostImpl::CreateBrowserResourceHosts(
    245     PP_Instance instance,
    246     const std::vector<IPC::Message>& nested_msgs,
    247     const base::Callback<void(const std::vector<int>&)>& callback) const {
    248   RenderFrame* render_frame = GetRenderFrameForInstance(instance);
    249   PepperBrowserConnection* browser_connection =
    250       PepperBrowserConnection::Get(render_frame);
    251   if (!browser_connection) {
    252     base::MessageLoop::current()->PostTask(
    253         FROM_HERE,
    254         base::Bind(callback, std::vector<int>(nested_msgs.size(), 0)));
    255   } else {
    256     browser_connection->SendBrowserCreate(
    257         module_->GetPluginChildId(), instance, nested_msgs, callback);
    258   }
    259 }
    260 
    261 GURL RendererPpapiHostImpl::GetDocumentURL(PP_Instance instance) const {
    262   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
    263   if (!instance_object)
    264     return GURL();
    265 
    266   return instance_object->container()->element().document().url();
    267 }
    268 
    269 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetAndValidateInstance(
    270     PP_Instance pp_instance) const {
    271   PepperPluginInstanceImpl* instance =
    272       HostGlobals::Get()->GetInstance(pp_instance);
    273   if (!instance)
    274     return NULL;
    275   if (!instance->IsValidInstanceOf(module_))
    276     return NULL;
    277   return instance;
    278 }
    279 
    280 }  // namespace content
    281