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*
     35 RendererPpapiHost::GetForPPInstance(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   // Hook the PpapiHost up to the dispatcher for out-of-process communication.
     47   ppapi_host_.reset(
     48       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),
     60       dispatcher_(NULL) {
     61   // Hook the host up to the in-process router.
     62   in_process_router_.reset(new PepperInProcessRouter(this));
     63   ppapi_host_.reset(new ppapi::host::PpapiHost(
     64       in_process_router_->GetRendererToPluginSender(), permissions));
     65   ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
     66       new ContentRendererPepperHostFactory(this)));
     67   is_running_in_process_ = true;
     68 }
     69 
     70 RendererPpapiHostImpl::~RendererPpapiHostImpl() {
     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 // static
     78 RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
     79     PluginModule* module,
     80     ppapi::proxy::HostDispatcher* dispatcher,
     81     const ppapi::PpapiPermissions& permissions) {
     82   DCHECK(!module->renderer_ppapi_host());
     83   RendererPpapiHostImpl* result = new RendererPpapiHostImpl(
     84       module, dispatcher, permissions);
     85 
     86   // Takes ownership of pointer.
     87   module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
     88 
     89   return result;
     90 }
     91 
     92 // static
     93 RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForInProcess(
     94     PluginModule* module,
     95     const ppapi::PpapiPermissions& permissions) {
     96   DCHECK(!module->renderer_ppapi_host());
     97   RendererPpapiHostImpl* result = new RendererPpapiHostImpl(
     98       module, permissions);
     99 
    100   // Takes ownership of pointer.
    101   module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
    102 
    103   return result;
    104 }
    105 
    106 // static
    107 RendererPpapiHostImpl* RendererPpapiHostImpl::GetForPPInstance(
    108     PP_Instance pp_instance) {
    109   PepperPluginInstanceImpl* instance =
    110       HostGlobals::Get()->GetInstance(pp_instance);
    111   if (!instance)
    112     return NULL;
    113 
    114   // All modules created by content will have their embedder state be the
    115   // host impl.
    116   return instance->module()->renderer_ppapi_host();
    117 }
    118 
    119 scoped_ptr<ppapi::thunk::ResourceCreationAPI>
    120 RendererPpapiHostImpl::CreateInProcessResourceCreationAPI(
    121     PepperPluginInstanceImpl* instance) {
    122   return scoped_ptr<ppapi::thunk::ResourceCreationAPI>(
    123       new PepperInProcessResourceCreation(this, instance));
    124 }
    125 
    126 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetPluginInstanceImpl(
    127     PP_Instance instance) const {
    128   return GetAndValidateInstance(instance);
    129 }
    130 
    131 ppapi::host::PpapiHost* RendererPpapiHostImpl::GetPpapiHost() {
    132   return ppapi_host_.get();
    133 }
    134 
    135 RenderFrame* RendererPpapiHostImpl::GetRenderFrameForInstance(
    136     PP_Instance instance) const  {
    137   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
    138   if (!instance_object)
    139     return NULL;
    140 
    141   // Since we're the embedder, we can make assumptions about the helper on
    142   // the instance and get back to our RenderFrame.
    143   return instance_object->render_frame();
    144 }
    145 
    146 RenderView* RendererPpapiHostImpl::GetRenderViewForInstance(
    147     PP_Instance instance) const {
    148   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
    149   if (!instance_object)
    150     return NULL;
    151 
    152   // Since we're the embedder, we can make assumptions about the helper on
    153   // the instance and get back to our RenderView.
    154   return instance_object->render_frame()->render_view();
    155 }
    156 
    157 bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
    158   return !!GetAndValidateInstance(instance);
    159 }
    160 
    161 PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance(
    162     PP_Instance instance) const {
    163   return GetAndValidateInstance(instance);
    164 }
    165 
    166 blink::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance(
    167       PP_Instance instance) const {
    168   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
    169   if (!instance_object)
    170     return NULL;
    171   return instance_object->container();
    172 }
    173 
    174 base::ProcessId RendererPpapiHostImpl::GetPluginPID() const {
    175   if (dispatcher_)
    176     return dispatcher_->channel()->peer_pid();
    177   return base::kNullProcessId;
    178 }
    179 
    180 bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance) const {
    181   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
    182   if (!instance_object)
    183     return false;
    184 
    185   if (instance_object->module()->permissions().HasPermission(
    186           ppapi::PERMISSION_BYPASS_USER_GESTURE))
    187     return true;
    188   return instance_object->IsProcessingUserGesture();
    189 }
    190 
    191 int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance) const {
    192   PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
    193   if (!plugin_instance)
    194     return 0;
    195   if (plugin_instance->flash_fullscreen()) {
    196     FullscreenContainer* container = plugin_instance->fullscreen_container();
    197     return static_cast<RenderWidgetFullscreenPepper*>(container)->routing_id();
    198   }
    199   return GetRenderViewForInstance(instance)->GetRoutingID();
    200 }
    201 
    202 gfx::Point RendererPpapiHostImpl::PluginPointToRenderFrame(
    203     PP_Instance instance,
    204     const gfx::Point& pt) const {
    205   PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
    206   if (!plugin_instance)
    207     return pt;
    208 
    209   RenderFrameImpl* render_frame = static_cast<RenderFrameImpl*>(
    210       GetRenderFrameForInstance(instance));
    211   if (plugin_instance->view_data().is_fullscreen ||
    212       plugin_instance->flash_fullscreen()) {
    213     blink::WebRect window_rect = render_frame->GetRenderWidget()->windowRect();
    214     blink::WebRect screen_rect =
    215         render_frame->GetRenderWidget()->screenInfo().rect;
    216     return gfx::Point(pt.x() - window_rect.x + screen_rect.x,
    217                       pt.y() - window_rect.y + screen_rect.y);
    218   }
    219   return gfx::Point(pt.x() + plugin_instance->view_data().rect.point.x,
    220                     pt.y() + plugin_instance->view_data().rect.point.y);
    221 }
    222 
    223 IPC::PlatformFileForTransit RendererPpapiHostImpl::ShareHandleWithRemote(
    224     base::PlatformFile handle,
    225     bool should_close_source) {
    226   if (!dispatcher_) {
    227     DCHECK(is_running_in_process_);
    228     // Duplicate the file handle for in process mode so this function
    229     // has the same semantics for both in process mode and out of
    230     // process mode (i.e., the remote side must cloes the handle).
    231     return BrokerGetFileHandleForProcess(handle,
    232                                          base::GetCurrentProcId(),
    233                                          should_close_source);
    234   }
    235   return dispatcher_->ShareHandleWithRemote(handle, should_close_source);
    236 }
    237 
    238 bool RendererPpapiHostImpl::IsRunningInProcess() const {
    239   return is_running_in_process_;
    240 }
    241 
    242 void RendererPpapiHostImpl::CreateBrowserResourceHosts(
    243     PP_Instance instance,
    244     const std::vector<IPC::Message>& nested_msgs,
    245     const base::Callback<void(const std::vector<int>&)>& callback) const {
    246   RenderFrame* render_frame = GetRenderFrameForInstance(instance);
    247   PepperBrowserConnection* browser_connection =
    248       PepperBrowserConnection::Get(render_frame);
    249   if (!browser_connection) {
    250     base::MessageLoop::current()->PostTask(FROM_HERE,
    251         base::Bind(callback, std::vector<int>(nested_msgs.size(), 0)));
    252   } else {
    253     browser_connection->SendBrowserCreate(module_->GetPluginChildId(),
    254                                           instance,
    255                                           nested_msgs,
    256                                           callback);
    257   }
    258 }
    259 
    260 GURL RendererPpapiHostImpl::GetDocumentURL(PP_Instance instance) const {
    261   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
    262   if (!instance_object)
    263     return GURL();
    264 
    265   return instance_object->container()->element().document().url();
    266 }
    267 
    268 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetAndValidateInstance(
    269     PP_Instance pp_instance) const {
    270   PepperPluginInstanceImpl* instance =
    271       HostGlobals::Get()->GetInstance(pp_instance);
    272   if (!instance)
    273     return NULL;
    274   if (!instance->IsValidInstanceOf(module_))
    275     return NULL;
    276   return instance;
    277 }
    278 
    279 }  // namespace content
    280