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