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"
7 #include "base/files/file_path.h"
8 #include "base/logging.h"
9 #include "base/process_util.h"
10 #include "content/common/sandbox_util.h"
11 #include "content/renderer/pepper/pepper_graphics_2d_host.h"
12 #include "content/renderer/pepper/pepper_in_process_resource_creation.h"
13 #include "content/renderer/pepper/pepper_in_process_router.h"
14 #include "content/renderer/pepper/pepper_plugin_delegate_impl.h"
15 #include "content/renderer/render_view_impl.h"
16 #include "content/renderer/render_widget_fullscreen_pepper.h"
17 #include "ppapi/host/ppapi_host.h"
18 #include "ppapi/proxy/host_dispatcher.h"
19 #include "third_party/WebKit/Source/Platform/chromium/public/WebRect.h"
20 #include "ui/gfx/point.h"
21 #include "webkit/plugins/ppapi/fullscreen_container.h"
22 #include "webkit/plugins/ppapi/host_globals.h"
23 #include "webkit/plugins/ppapi/plugin_delegate.h"
24 #include "webkit/plugins/ppapi/plugin_module.h"
25 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
27 using webkit::ppapi::HostGlobals
;
28 using webkit::ppapi::PluginInstance
;
29 using webkit::ppapi::PluginModule
;
34 CONTENT_EXPORT RendererPpapiHost
*
35 RendererPpapiHost::CreateExternalPluginModule(
36 scoped_refptr
<PluginModule
> plugin_module
,
37 PluginInstance
* plugin_instance
,
38 const base::FilePath
& file_path
,
39 ppapi::PpapiPermissions permissions
,
40 const IPC::ChannelHandle
& channel_handle
,
41 base::ProcessId plugin_pid
,
42 int plugin_child_id
) {
43 RendererPpapiHost
* renderer_ppapi_host
= NULL
;
44 // Since we're the embedder, we can make assumptions about the delegate on
46 PepperPluginDelegateImpl
* pepper_plugin_delegate
=
47 static_cast<PepperPluginDelegateImpl
*>(plugin_instance
->delegate());
48 if (pepper_plugin_delegate
) {
49 renderer_ppapi_host
= pepper_plugin_delegate
->CreateExternalPluginModule(
57 return renderer_ppapi_host
;
61 CONTENT_EXPORT RendererPpapiHost
*
62 RendererPpapiHost::GetForPPInstance(PP_Instance instance
) {
63 return RendererPpapiHostImpl::GetForPPInstance(instance
);
66 // Out-of-process constructor.
67 RendererPpapiHostImpl::RendererPpapiHostImpl(
69 ppapi::proxy::HostDispatcher
* dispatcher
,
70 const ppapi::PpapiPermissions
& permissions
)
72 dispatcher_(dispatcher
) {
73 // Hook the PpapiHost up to the dispatcher for out-of-process communication.
75 new ppapi::host::PpapiHost(dispatcher
, permissions
));
76 ppapi_host_
->AddHostFactoryFilter(scoped_ptr
<ppapi::host::HostFactory
>(
77 new ContentRendererPepperHostFactory(this)));
78 dispatcher
->AddFilter(ppapi_host_
.get());
79 is_running_in_process_
= false;
82 // In-process constructor.
83 RendererPpapiHostImpl::RendererPpapiHostImpl(
85 const ppapi::PpapiPermissions
& permissions
)
88 // Hook the host up to the in-process router.
89 in_process_router_
.reset(new PepperInProcessRouter(this));
90 ppapi_host_
.reset(new ppapi::host::PpapiHost(
91 in_process_router_
->GetRendererToPluginSender(), permissions
));
92 ppapi_host_
->AddHostFactoryFilter(scoped_ptr
<ppapi::host::HostFactory
>(
93 new ContentRendererPepperHostFactory(this)));
94 is_running_in_process_
= true;
97 RendererPpapiHostImpl::~RendererPpapiHostImpl() {
98 // Delete the host explicitly first. This shutdown will destroy the
99 // resources, which may want to do cleanup in their destructors and expect
100 // their pointers to us to be valid.
105 RendererPpapiHostImpl
* RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
106 PluginModule
* module
,
107 ppapi::proxy::HostDispatcher
* dispatcher
,
108 const ppapi::PpapiPermissions
& permissions
) {
109 DCHECK(!module
->GetEmbedderState());
110 RendererPpapiHostImpl
* result
= new RendererPpapiHostImpl(
111 module
, dispatcher
, permissions
);
113 // Takes ownership of pointer.
114 module
->SetEmbedderState(
115 scoped_ptr
<PluginModule::EmbedderState
>(result
));
121 RendererPpapiHostImpl
* RendererPpapiHostImpl::CreateOnModuleForInProcess(
122 PluginModule
* module
,
123 const ppapi::PpapiPermissions
& permissions
) {
124 DCHECK(!module
->GetEmbedderState());
125 RendererPpapiHostImpl
* result
= new RendererPpapiHostImpl(
126 module
, permissions
);
128 // Takes ownership of pointer.
129 module
->SetEmbedderState(
130 scoped_ptr
<PluginModule::EmbedderState
>(result
));
136 RendererPpapiHostImpl
* RendererPpapiHostImpl::GetForPPInstance(
137 PP_Instance pp_instance
) {
138 PluginInstance
* instance
= HostGlobals::Get()->GetInstance(pp_instance
);
142 // All modules created by content will have their embedder state be the
144 return static_cast<RendererPpapiHostImpl
*>(
145 instance
->module()->GetEmbedderState());
148 scoped_ptr
< ::ppapi::thunk::ResourceCreationAPI
>
149 RendererPpapiHostImpl::CreateInProcessResourceCreationAPI(
150 PluginInstance
* instance
) {
151 return scoped_ptr
< ::ppapi::thunk::ResourceCreationAPI
>(
152 new PepperInProcessResourceCreation(this, instance
));
155 ppapi::host::PpapiHost
* RendererPpapiHostImpl::GetPpapiHost() {
156 return ppapi_host_
.get();
159 RenderView
* RendererPpapiHostImpl::GetRenderViewForInstance(
160 PP_Instance instance
) const {
161 PluginInstance
* instance_object
= GetAndValidateInstance(instance
);
162 if (!instance_object
)
165 // Since we're the embedder, we can make assumptions about the delegate on
166 // the instance and get back to our RenderView.
167 return static_cast<PepperPluginDelegateImpl
*>(
168 instance_object
->delegate())->render_view();
171 webkit::ppapi::PluginDelegate::PlatformGraphics2D
*
172 RendererPpapiHostImpl::GetPlatformGraphics2D(
173 PP_Resource resource
) {
174 ppapi::host::ResourceHost
* resource_host
=
175 GetPpapiHost()->GetResourceHost(resource
);
176 if (!resource_host
|| !resource_host
->IsGraphics2DHost()) {
177 DLOG(ERROR
) << "Resource is not Graphics2D";
180 return static_cast<PepperGraphics2DHost
*>(resource_host
);
183 bool RendererPpapiHostImpl::IsValidInstance(
184 PP_Instance instance
) const {
185 return !!GetAndValidateInstance(instance
);
188 webkit::ppapi::PluginInstance
* RendererPpapiHostImpl::GetPluginInstance(
189 PP_Instance instance
) const {
190 return GetAndValidateInstance(instance
);
193 WebKit::WebPluginContainer
* RendererPpapiHostImpl::GetContainerForInstance(
194 PP_Instance instance
) const {
195 PluginInstance
* instance_object
= GetAndValidateInstance(instance
);
196 if (!instance_object
)
198 return instance_object
->container();
201 bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance
) const {
202 PluginInstance
* instance_object
= GetAndValidateInstance(instance
);
203 if (!instance_object
)
206 if (instance_object
->module()->permissions().HasPermission(
207 ppapi::PERMISSION_BYPASS_USER_GESTURE
))
209 return instance_object
->IsProcessingUserGesture();
212 int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance
) const {
213 webkit::ppapi::PluginInstance
* plugin_instance
=
214 GetAndValidateInstance(instance
);
215 if (!plugin_instance
)
217 if (plugin_instance
->flash_fullscreen()) {
218 webkit::ppapi::FullscreenContainer
* container
=
219 plugin_instance
->fullscreen_container();
220 return static_cast<RenderWidgetFullscreenPepper
*>(container
)->routing_id();
222 return GetRenderViewForInstance(instance
)->GetRoutingID();
225 gfx::Point
RendererPpapiHostImpl::PluginPointToRenderView(
226 PP_Instance instance
,
227 const gfx::Point
& pt
) const {
228 webkit::ppapi::PluginInstance
* plugin_instance
=
229 GetAndValidateInstance(instance
);
230 if (!plugin_instance
)
233 RenderViewImpl
* render_view
= static_cast<RenderViewImpl
*>(
234 GetRenderViewForInstance(instance
));
235 if (plugin_instance
->view_data().is_fullscreen
||
236 plugin_instance
->flash_fullscreen()) {
237 WebKit::WebRect window_rect
= render_view
->windowRect();
238 WebKit::WebRect screen_rect
= render_view
->screenInfo().rect
;
239 return gfx::Point(pt
.x() - window_rect
.x
+ screen_rect
.x
,
240 pt
.y() - window_rect
.y
+ screen_rect
.y
);
242 return gfx::Point(pt
.x() + plugin_instance
->view_data().rect
.point
.x
,
243 pt
.y() + plugin_instance
->view_data().rect
.point
.y
);
246 IPC::PlatformFileForTransit
RendererPpapiHostImpl::ShareHandleWithRemote(
247 base::PlatformFile handle
,
248 bool should_close_source
) {
250 DCHECK(is_running_in_process_
);
251 // Duplicate the file handle for in process mode so this function
252 // has the same semantics for both in process mode and out of
253 // process mode (i.e., the remote side must cloes the handle).
254 return BrokerGetFileHandleForProcess(handle
,
255 base::GetCurrentProcId(),
256 should_close_source
);
258 return dispatcher_
->ShareHandleWithRemote(handle
, should_close_source
);
261 bool RendererPpapiHostImpl::IsRunningInProcess() const {
262 return is_running_in_process_
;
265 PluginInstance
* RendererPpapiHostImpl::GetAndValidateInstance(
266 PP_Instance pp_instance
) const {
267 PluginInstance
* instance
= HostGlobals::Get()->GetInstance(pp_instance
);
270 if (!instance
->IsValidInstanceOf(module_
))
275 } // namespace content