• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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"
31 
32 namespace content {
33 // static
34 CONTENT_EXPORT RendererPpapiHost*
GetForPPInstance(PP_Instance instance)35 RendererPpapiHost::GetForPPInstance(PP_Instance instance) {
36   return RendererPpapiHostImpl::GetForPPInstance(instance);
37 }
38 
39 // Out-of-process constructor.
RendererPpapiHostImpl(PluginModule * module,ppapi::proxy::HostDispatcher * dispatcher,const ppapi::PpapiPermissions & permissions)40 RendererPpapiHostImpl::RendererPpapiHostImpl(
41     PluginModule* module,
42     ppapi::proxy::HostDispatcher* dispatcher,
43     const ppapi::PpapiPermissions& permissions)
44     : module_(module),
45       dispatcher_(dispatcher) {
46   // Hook the PpapiHost up to the dispatcher for out-of-process communication.
47   ppapi_host_.reset(
48       new ppapi::host::PpapiHost(dispatcher, permissions));
49   ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
50       new ContentRendererPepperHostFactory(this)));
51   dispatcher->AddFilter(ppapi_host_.get());
52   is_running_in_process_ = false;
53 }
54 
55 // In-process constructor.
RendererPpapiHostImpl(PluginModule * module,const ppapi::PpapiPermissions & permissions)56 RendererPpapiHostImpl::RendererPpapiHostImpl(
57     PluginModule* module,
58     const ppapi::PpapiPermissions& permissions)
59     : module_(module),
60       dispatcher_(NULL) {
61   // Hook the host up to the in-process router.
62   in_process_router_.reset(new PepperInProcessRouter(this));
63   ppapi_host_.reset(new ppapi::host::PpapiHost(
64       in_process_router_->GetRendererToPluginSender(), permissions));
65   ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
66       new ContentRendererPepperHostFactory(this)));
67   is_running_in_process_ = true;
68 }
69 
~RendererPpapiHostImpl()70 RendererPpapiHostImpl::~RendererPpapiHostImpl() {
71   // Delete the host explicitly first. This shutdown will destroy the
72   // resources, which may want to do cleanup in their destructors and expect
73   // their pointers to us to be valid.
74   ppapi_host_.reset();
75 }
76 
77 // static
CreateOnModuleForOutOfProcess(PluginModule * module,ppapi::proxy::HostDispatcher * dispatcher,const ppapi::PpapiPermissions & permissions)78 RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
79     PluginModule* module,
80     ppapi::proxy::HostDispatcher* dispatcher,
81     const ppapi::PpapiPermissions& permissions) {
82   DCHECK(!module->renderer_ppapi_host());
83   RendererPpapiHostImpl* result = new RendererPpapiHostImpl(
84       module, dispatcher, permissions);
85 
86   // Takes ownership of pointer.
87   module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
88 
89   return result;
90 }
91 
92 // static
CreateOnModuleForInProcess(PluginModule * module,const ppapi::PpapiPermissions & permissions)93 RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForInProcess(
94     PluginModule* module,
95     const ppapi::PpapiPermissions& permissions) {
96   DCHECK(!module->renderer_ppapi_host());
97   RendererPpapiHostImpl* result = new RendererPpapiHostImpl(
98       module, permissions);
99 
100   // Takes ownership of pointer.
101   module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
102 
103   return result;
104 }
105 
106 // static
GetForPPInstance(PP_Instance pp_instance)107 RendererPpapiHostImpl* RendererPpapiHostImpl::GetForPPInstance(
108     PP_Instance pp_instance) {
109   PepperPluginInstanceImpl* instance =
110       HostGlobals::Get()->GetInstance(pp_instance);
111   if (!instance)
112     return NULL;
113 
114   // All modules created by content will have their embedder state be the
115   // host impl.
116   return instance->module()->renderer_ppapi_host();
117 }
118 
119 scoped_ptr<ppapi::thunk::ResourceCreationAPI>
CreateInProcessResourceCreationAPI(PepperPluginInstanceImpl * instance)120 RendererPpapiHostImpl::CreateInProcessResourceCreationAPI(
121     PepperPluginInstanceImpl* instance) {
122   return scoped_ptr<ppapi::thunk::ResourceCreationAPI>(
123       new PepperInProcessResourceCreation(this, instance));
124 }
125 
GetPluginInstanceImpl(PP_Instance instance) const126 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetPluginInstanceImpl(
127     PP_Instance instance) const {
128   return GetAndValidateInstance(instance);
129 }
130 
GetPpapiHost()131 ppapi::host::PpapiHost* RendererPpapiHostImpl::GetPpapiHost() {
132   return ppapi_host_.get();
133 }
134 
GetRenderFrameForInstance(PP_Instance instance) const135 RenderFrame* RendererPpapiHostImpl::GetRenderFrameForInstance(
136     PP_Instance instance) const  {
137   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
138   if (!instance_object)
139     return NULL;
140 
141   // Since we're the embedder, we can make assumptions about the helper on
142   // the instance and get back to our RenderFrame.
143   return instance_object->render_frame();
144 }
145 
GetRenderViewForInstance(PP_Instance instance) const146 RenderView* RendererPpapiHostImpl::GetRenderViewForInstance(
147     PP_Instance instance) const {
148   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
149   if (!instance_object)
150     return NULL;
151 
152   // Since we're the embedder, we can make assumptions about the helper on
153   // the instance and get back to our RenderView.
154   return instance_object->render_frame()->render_view();
155 }
156 
IsValidInstance(PP_Instance instance) const157 bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
158   return !!GetAndValidateInstance(instance);
159 }
160 
GetPluginInstance(PP_Instance instance) const161 PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance(
162     PP_Instance instance) const {
163   return GetAndValidateInstance(instance);
164 }
165 
GetContainerForInstance(PP_Instance instance) const166 blink::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance(
167       PP_Instance instance) const {
168   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
169   if (!instance_object)
170     return NULL;
171   return instance_object->container();
172 }
173 
GetPluginPID() const174 base::ProcessId RendererPpapiHostImpl::GetPluginPID() const {
175   if (dispatcher_)
176     return dispatcher_->channel()->peer_pid();
177   return base::kNullProcessId;
178 }
179 
HasUserGesture(PP_Instance instance) const180 bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance) const {
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->IsProcessingUserGesture();
189 }
190 
GetRoutingIDForWidget(PP_Instance instance) const191 int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance) const {
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) const202 gfx::Point RendererPpapiHostImpl::PluginPointToRenderFrame(
203     PP_Instance instance,
204     const gfx::Point& pt) const {
205   PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
206   if (!plugin_instance)
207     return pt;
208 
209   RenderFrameImpl* render_frame = static_cast<RenderFrameImpl*>(
210       GetRenderFrameForInstance(instance));
211   if (plugin_instance->view_data().is_fullscreen ||
212       plugin_instance->flash_fullscreen()) {
213     blink::WebRect window_rect = render_frame->GetRenderWidget()->windowRect();
214     blink::WebRect screen_rect =
215         render_frame->GetRenderWidget()->screenInfo().rect;
216     return gfx::Point(pt.x() - window_rect.x + screen_rect.x,
217                       pt.y() - window_rect.y + screen_rect.y);
218   }
219   return gfx::Point(pt.x() + plugin_instance->view_data().rect.point.x,
220                     pt.y() + plugin_instance->view_data().rect.point.y);
221 }
222 
ShareHandleWithRemote(base::PlatformFile handle,bool should_close_source)223 IPC::PlatformFileForTransit RendererPpapiHostImpl::ShareHandleWithRemote(
224     base::PlatformFile handle,
225     bool should_close_source) {
226   if (!dispatcher_) {
227     DCHECK(is_running_in_process_);
228     // Duplicate the file handle for in process mode so this function
229     // has the same semantics for both in process mode and out of
230     // process mode (i.e., the remote side must cloes the handle).
231     return BrokerGetFileHandleForProcess(handle,
232                                          base::GetCurrentProcId(),
233                                          should_close_source);
234   }
235   return dispatcher_->ShareHandleWithRemote(handle, should_close_source);
236 }
237 
IsRunningInProcess() const238 bool RendererPpapiHostImpl::IsRunningInProcess() const {
239   return is_running_in_process_;
240 }
241 
CreateBrowserResourceHosts(PP_Instance instance,const std::vector<IPC::Message> & nested_msgs,const base::Callback<void (const std::vector<int> &)> & callback) const242 void RendererPpapiHostImpl::CreateBrowserResourceHosts(
243     PP_Instance instance,
244     const std::vector<IPC::Message>& nested_msgs,
245     const base::Callback<void(const std::vector<int>&)>& callback) const {
246   RenderFrame* render_frame = GetRenderFrameForInstance(instance);
247   PepperBrowserConnection* browser_connection =
248       PepperBrowserConnection::Get(render_frame);
249   if (!browser_connection) {
250     base::MessageLoop::current()->PostTask(FROM_HERE,
251         base::Bind(callback, std::vector<int>(nested_msgs.size(), 0)));
252   } else {
253     browser_connection->SendBrowserCreate(module_->GetPluginChildId(),
254                                           instance,
255                                           nested_msgs,
256                                           callback);
257   }
258 }
259 
GetDocumentURL(PP_Instance instance) const260 GURL RendererPpapiHostImpl::GetDocumentURL(PP_Instance instance) const {
261   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
262   if (!instance_object)
263     return GURL();
264 
265   return instance_object->container()->element().document().url();
266 }
267 
GetAndValidateInstance(PP_Instance pp_instance) const268 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetAndValidateInstance(
269     PP_Instance pp_instance) const {
270   PepperPluginInstanceImpl* instance =
271       HostGlobals::Get()->GetInstance(pp_instance);
272   if (!instance)
273     return NULL;
274   if (!instance->IsValidInstanceOf(module_))
275     return NULL;
276   return instance;
277 }
278 
279 }  // namespace content
280