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.
5 #include "content/renderer/pepper/renderer_ppapi_host_impl.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"
34 CONTENT_EXPORT RendererPpapiHost* RendererPpapiHost::GetForPPInstance(
35 PP_Instance instance) {
36 return RendererPpapiHostImpl::GetForPPInstance(instance);
39 // Out-of-process constructor.
40 RendererPpapiHostImpl::RendererPpapiHostImpl(
42 ppapi::proxy::HostDispatcher* dispatcher,
43 const ppapi::PpapiPermissions& permissions)
44 : module_(module), dispatcher_(dispatcher) {
45 // Hook the PpapiHost up to the dispatcher for out-of-process communication.
46 ppapi_host_.reset(new ppapi::host::PpapiHost(dispatcher, permissions));
47 ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
48 new ContentRendererPepperHostFactory(this)));
49 dispatcher->AddFilter(ppapi_host_.get());
50 is_running_in_process_ = false;
53 // In-process constructor.
54 RendererPpapiHostImpl::RendererPpapiHostImpl(
56 const ppapi::PpapiPermissions& permissions)
57 : module_(module), dispatcher_(NULL) {
58 // Hook the host up to the in-process router.
59 in_process_router_.reset(new PepperInProcessRouter(this));
60 ppapi_host_.reset(new ppapi::host::PpapiHost(
61 in_process_router_->GetRendererToPluginSender(), permissions));
62 ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
63 new ContentRendererPepperHostFactory(this)));
64 is_running_in_process_ = true;
67 RendererPpapiHostImpl::~RendererPpapiHostImpl() {
68 // Delete the host explicitly first. This shutdown will destroy the
69 // resources, which may want to do cleanup in their destructors and expect
70 // their pointers to us to be valid.
75 RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
77 ppapi::proxy::HostDispatcher* dispatcher,
78 const ppapi::PpapiPermissions& permissions) {
79 DCHECK(!module->renderer_ppapi_host());
80 RendererPpapiHostImpl* result =
81 new RendererPpapiHostImpl(module, dispatcher, permissions);
83 // Takes ownership of pointer.
84 module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
90 RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForInProcess(
92 const ppapi::PpapiPermissions& permissions) {
93 DCHECK(!module->renderer_ppapi_host());
94 RendererPpapiHostImpl* result =
95 new RendererPpapiHostImpl(module, permissions);
97 // Takes ownership of pointer.
98 module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
104 RendererPpapiHostImpl* RendererPpapiHostImpl::GetForPPInstance(
105 PP_Instance pp_instance) {
106 PepperPluginInstanceImpl* instance =
107 HostGlobals::Get()->GetInstance(pp_instance);
111 // All modules created by content will have their embedder state be the
113 return instance->module()->renderer_ppapi_host();
116 scoped_ptr<ppapi::thunk::ResourceCreationAPI>
117 RendererPpapiHostImpl::CreateInProcessResourceCreationAPI(
118 PepperPluginInstanceImpl* instance) {
119 return scoped_ptr<ppapi::thunk::ResourceCreationAPI>(
120 new PepperInProcessResourceCreation(this, instance));
123 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetPluginInstanceImpl(
124 PP_Instance instance) const {
125 return GetAndValidateInstance(instance);
128 ppapi::host::PpapiHost* RendererPpapiHostImpl::GetPpapiHost() {
129 return ppapi_host_.get();
132 RenderFrame* RendererPpapiHostImpl::GetRenderFrameForInstance(
133 PP_Instance instance) const {
134 PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
135 if (!instance_object)
138 // Since we're the embedder, we can make assumptions about the helper on
139 // the instance and get back to our RenderFrame.
140 return instance_object->render_frame();
143 RenderView* RendererPpapiHostImpl::GetRenderViewForInstance(
144 PP_Instance instance) const {
145 PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
146 if (!instance_object)
149 // Since we're the embedder, we can make assumptions about the helper on
150 // the instance and get back to our RenderView.
151 return instance_object->render_frame()->render_view();
154 bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
155 return !!GetAndValidateInstance(instance);
158 PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance(
159 PP_Instance instance) const {
160 return GetAndValidateInstance(instance);
163 blink::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance(
164 PP_Instance instance) const {
165 PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
166 if (!instance_object)
168 return instance_object->container();
171 base::ProcessId RendererPpapiHostImpl::GetPluginPID() const {
173 return dispatcher_->channel()->peer_pid();
174 return base::kNullProcessId;
177 bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance) const {
178 PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
179 if (!instance_object)
182 if (instance_object->module()->permissions().HasPermission(
183 ppapi::PERMISSION_BYPASS_USER_GESTURE))
185 return instance_object->IsProcessingUserGesture();
188 int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance) const {
189 PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
190 if (!plugin_instance)
192 if (plugin_instance->flash_fullscreen()) {
193 FullscreenContainer* container = plugin_instance->fullscreen_container();
194 return static_cast<RenderWidgetFullscreenPepper*>(container)->routing_id();
196 return GetRenderViewForInstance(instance)->GetRoutingID();
199 gfx::Point RendererPpapiHostImpl::PluginPointToRenderFrame(
200 PP_Instance instance,
201 const gfx::Point& pt) const {
202 PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
203 if (!plugin_instance || plugin_instance->flash_fullscreen()) {
204 // Flash fullscreen is special in that it renders into its own separate,
205 // dedicated window. So, do not offset the point.
208 return gfx::Point(pt.x() + plugin_instance->view_data().rect.point.x,
209 pt.y() + plugin_instance->view_data().rect.point.y);
212 IPC::PlatformFileForTransit RendererPpapiHostImpl::ShareHandleWithRemote(
213 base::PlatformFile handle,
214 bool should_close_source) {
216 DCHECK(is_running_in_process_);
217 // Duplicate the file handle for in process mode so this function
218 // has the same semantics for both in process mode and out of
219 // process mode (i.e., the remote side must cloes the handle).
220 return BrokerGetFileHandleForProcess(
221 handle, base::GetCurrentProcId(), should_close_source);
223 return dispatcher_->ShareHandleWithRemote(handle, should_close_source);
226 bool RendererPpapiHostImpl::IsRunningInProcess() const {
227 return is_running_in_process_;
230 void RendererPpapiHostImpl::CreateBrowserResourceHosts(
231 PP_Instance instance,
232 const std::vector<IPC::Message>& nested_msgs,
233 const base::Callback<void(const std::vector<int>&)>& callback) const {
234 RenderFrame* render_frame = GetRenderFrameForInstance(instance);
235 PepperBrowserConnection* browser_connection =
236 PepperBrowserConnection::Get(render_frame);
237 if (!browser_connection) {
238 base::MessageLoop::current()->PostTask(
240 base::Bind(callback, std::vector<int>(nested_msgs.size(), 0)));
242 browser_connection->SendBrowserCreate(
243 module_->GetPluginChildId(), instance, nested_msgs, callback);
247 GURL RendererPpapiHostImpl::GetDocumentURL(PP_Instance instance) const {
248 PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
249 if (!instance_object)
252 return instance_object->container()->element().document().url();
255 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetAndValidateInstance(
256 PP_Instance pp_instance) const {
257 PepperPluginInstanceImpl* instance =
258 HostGlobals::Get()->GetInstance(pp_instance);
261 if (!instance->IsValidInstanceOf(module_))
266 } // namespace content