blob: dd78352cb0dc1f0be8fe8058ccf6230b8bf70770 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/process/process_handle.h"
#include "content/common/sandbox_util.h"
#include "content/renderer/pepper/fullscreen_container.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_browser_connection.h"
#include "content/renderer/pepper/pepper_graphics_2d_host.h"
#include "content/renderer/pepper/pepper_in_process_resource_creation.h"
#include "content/renderer/pepper/pepper_in_process_router.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/render_widget_fullscreen_pepper.h"
#include "ipc/ipc_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/host_dispatcher.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "ui/gfx/point.h"
namespace content {
// static
CONTENT_EXPORT RendererPpapiHost*
RendererPpapiHost::GetForPPInstance(PP_Instance instance) {
return RendererPpapiHostImpl::GetForPPInstance(instance);
}
// Out-of-process constructor.
RendererPpapiHostImpl::RendererPpapiHostImpl(
PluginModule* module,
ppapi::proxy::HostDispatcher* dispatcher,
const ppapi::PpapiPermissions& permissions)
: module_(module),
dispatcher_(dispatcher) {
// Hook the PpapiHost up to the dispatcher for out-of-process communication.
ppapi_host_.reset(
new ppapi::host::PpapiHost(dispatcher, permissions));
ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
new ContentRendererPepperHostFactory(this)));
dispatcher->AddFilter(ppapi_host_.get());
is_running_in_process_ = false;
}
// In-process constructor.
RendererPpapiHostImpl::RendererPpapiHostImpl(
PluginModule* module,
const ppapi::PpapiPermissions& permissions)
: module_(module),
dispatcher_(NULL) {
// Hook the host up to the in-process router.
in_process_router_.reset(new PepperInProcessRouter(this));
ppapi_host_.reset(new ppapi::host::PpapiHost(
in_process_router_->GetRendererToPluginSender(), permissions));
ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
new ContentRendererPepperHostFactory(this)));
is_running_in_process_ = true;
}
RendererPpapiHostImpl::~RendererPpapiHostImpl() {
// Delete the host explicitly first. This shutdown will destroy the
// resources, which may want to do cleanup in their destructors and expect
// their pointers to us to be valid.
ppapi_host_.reset();
}
// static
RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
PluginModule* module,
ppapi::proxy::HostDispatcher* dispatcher,
const ppapi::PpapiPermissions& permissions) {
DCHECK(!module->renderer_ppapi_host());
RendererPpapiHostImpl* result = new RendererPpapiHostImpl(
module, dispatcher, permissions);
// Takes ownership of pointer.
module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
return result;
}
// static
RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForInProcess(
PluginModule* module,
const ppapi::PpapiPermissions& permissions) {
DCHECK(!module->renderer_ppapi_host());
RendererPpapiHostImpl* result = new RendererPpapiHostImpl(
module, permissions);
// Takes ownership of pointer.
module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
return result;
}
// static
RendererPpapiHostImpl* RendererPpapiHostImpl::GetForPPInstance(
PP_Instance pp_instance) {
PepperPluginInstanceImpl* instance =
HostGlobals::Get()->GetInstance(pp_instance);
if (!instance)
return NULL;
// All modules created by content will have their embedder state be the
// host impl.
return instance->module()->renderer_ppapi_host();
}
scoped_ptr<ppapi::thunk::ResourceCreationAPI>
RendererPpapiHostImpl::CreateInProcessResourceCreationAPI(
PepperPluginInstanceImpl* instance) {
return scoped_ptr<ppapi::thunk::ResourceCreationAPI>(
new PepperInProcessResourceCreation(this, instance));
}
PepperPluginInstanceImpl* RendererPpapiHostImpl::GetPluginInstanceImpl(
PP_Instance instance) const {
return GetAndValidateInstance(instance);
}
ppapi::host::PpapiHost* RendererPpapiHostImpl::GetPpapiHost() {
return ppapi_host_.get();
}
RenderView* RendererPpapiHostImpl::GetRenderViewForInstance(
PP_Instance instance) const {
PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
if (!instance_object)
return NULL;
// Since we're the embedder, we can make assumptions about the helper on
// the instance and get back to our RenderView.
return instance_object->render_view();
}
bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
return !!GetAndValidateInstance(instance);
}
PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance(
PP_Instance instance) const {
return GetAndValidateInstance(instance);
}
WebKit::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance(
PP_Instance instance) const {
PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
if (!instance_object)
return NULL;
return instance_object->container();
}
base::ProcessId RendererPpapiHostImpl::GetPluginPID() const {
if (dispatcher_)
return dispatcher_->channel()->peer_pid();
return base::kNullProcessId;
}
bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance) const {
PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
if (!instance_object)
return false;
if (instance_object->module()->permissions().HasPermission(
ppapi::PERMISSION_BYPASS_USER_GESTURE))
return true;
return instance_object->IsProcessingUserGesture();
}
int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance) const {
PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
if (!plugin_instance)
return 0;
if (plugin_instance->flash_fullscreen()) {
FullscreenContainer* container = plugin_instance->fullscreen_container();
return static_cast<RenderWidgetFullscreenPepper*>(container)->routing_id();
}
return GetRenderViewForInstance(instance)->GetRoutingID();
}
gfx::Point RendererPpapiHostImpl::PluginPointToRenderView(
PP_Instance instance,
const gfx::Point& pt) const {
PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
if (!plugin_instance)
return pt;
RenderViewImpl* render_view = static_cast<RenderViewImpl*>(
GetRenderViewForInstance(instance));
if (plugin_instance->view_data().is_fullscreen ||
plugin_instance->flash_fullscreen()) {
WebKit::WebRect window_rect = render_view->windowRect();
WebKit::WebRect screen_rect = render_view->screenInfo().rect;
return gfx::Point(pt.x() - window_rect.x + screen_rect.x,
pt.y() - window_rect.y + screen_rect.y);
}
return gfx::Point(pt.x() + plugin_instance->view_data().rect.point.x,
pt.y() + plugin_instance->view_data().rect.point.y);
}
IPC::PlatformFileForTransit RendererPpapiHostImpl::ShareHandleWithRemote(
base::PlatformFile handle,
bool should_close_source) {
if (!dispatcher_) {
DCHECK(is_running_in_process_);
// Duplicate the file handle for in process mode so this function
// has the same semantics for both in process mode and out of
// process mode (i.e., the remote side must cloes the handle).
return BrokerGetFileHandleForProcess(handle,
base::GetCurrentProcId(),
should_close_source);
}
return dispatcher_->ShareHandleWithRemote(handle, should_close_source);
}
bool RendererPpapiHostImpl::IsRunningInProcess() const {
return is_running_in_process_;
}
void RendererPpapiHostImpl::CreateBrowserResourceHost(
PP_Instance instance,
const IPC::Message& nested_msg,
const base::Callback<void(int)>& callback) const {
RenderView* render_view = GetRenderViewForInstance(instance);
PepperBrowserConnection* browser_connection =
PepperBrowserConnection::Get(render_view);
if (!browser_connection) {
callback.Run(0);
} else {
browser_connection->SendBrowserCreate(module_->GetPluginChildId(),
instance,
nested_msg,
callback);
}
}
PepperPluginInstanceImpl* RendererPpapiHostImpl::GetAndValidateInstance(
PP_Instance pp_instance) const {
PepperPluginInstanceImpl* instance =
HostGlobals::Get()->GetInstance(pp_instance);
if (!instance)
return NULL;
if (!instance->IsValidInstanceOf(module_))
return NULL;
return instance;
}
} // namespace content