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