• 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
GetForPPInstance(PP_Instance instance)34 CONTENT_EXPORT RendererPpapiHost* RendererPpapiHost::GetForPPInstance(
35     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       is_external_plugin_host_(false) {
47   // Hook the PpapiHost up to the dispatcher for out-of-process communication.
48   ppapi_host_.reset(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), dispatcher_(NULL), is_external_plugin_host_(false) {
60   // Hook the host up to the in-process router.
61   in_process_router_.reset(new PepperInProcessRouter(this));
62   ppapi_host_.reset(new ppapi::host::PpapiHost(
63       in_process_router_->GetRendererToPluginSender(), permissions));
64   ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>(
65       new ContentRendererPepperHostFactory(this)));
66   is_running_in_process_ = true;
67 }
68 
~RendererPpapiHostImpl()69 RendererPpapiHostImpl::~RendererPpapiHostImpl() {
70   // Delete the host explicitly first. This shutdown will destroy the
71   // resources, which may want to do cleanup in their destructors and expect
72   // their pointers to us to be valid.
73   ppapi_host_.reset();
74 }
75 
76 // static
CreateOnModuleForOutOfProcess(PluginModule * module,ppapi::proxy::HostDispatcher * dispatcher,const ppapi::PpapiPermissions & permissions)77 RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForOutOfProcess(
78     PluginModule* module,
79     ppapi::proxy::HostDispatcher* dispatcher,
80     const ppapi::PpapiPermissions& permissions) {
81   DCHECK(!module->renderer_ppapi_host());
82   RendererPpapiHostImpl* result =
83       new RendererPpapiHostImpl(module, dispatcher, permissions);
84 
85   // Takes ownership of pointer.
86   module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
87 
88   return result;
89 }
90 
91 // static
CreateOnModuleForInProcess(PluginModule * module,const ppapi::PpapiPermissions & permissions)92 RendererPpapiHostImpl* RendererPpapiHostImpl::CreateOnModuleForInProcess(
93     PluginModule* module,
94     const ppapi::PpapiPermissions& permissions) {
95   DCHECK(!module->renderer_ppapi_host());
96   RendererPpapiHostImpl* result =
97       new RendererPpapiHostImpl(module, permissions);
98 
99   // Takes ownership of pointer.
100   module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
101 
102   return result;
103 }
104 
105 // static
GetForPPInstance(PP_Instance pp_instance)106 RendererPpapiHostImpl* RendererPpapiHostImpl::GetForPPInstance(
107     PP_Instance pp_instance) {
108   PepperPluginInstanceImpl* instance =
109       HostGlobals::Get()->GetInstance(pp_instance);
110   if (!instance)
111     return NULL;
112 
113   // All modules created by content will have their embedder state be the
114   // host impl.
115   return instance->module()->renderer_ppapi_host();
116 }
117 
118 scoped_ptr<ppapi::thunk::ResourceCreationAPI>
CreateInProcessResourceCreationAPI(PepperPluginInstanceImpl * instance)119 RendererPpapiHostImpl::CreateInProcessResourceCreationAPI(
120     PepperPluginInstanceImpl* instance) {
121   return scoped_ptr<ppapi::thunk::ResourceCreationAPI>(
122       new PepperInProcessResourceCreation(this, instance));
123 }
124 
GetPluginInstanceImpl(PP_Instance instance) const125 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetPluginInstanceImpl(
126     PP_Instance instance) const {
127   return GetAndValidateInstance(instance);
128 }
129 
IsExternalPluginHost() const130 bool RendererPpapiHostImpl::IsExternalPluginHost() const {
131   return is_external_plugin_host_;
132 }
133 
GetPpapiHost()134 ppapi::host::PpapiHost* RendererPpapiHostImpl::GetPpapiHost() {
135   return ppapi_host_.get();
136 }
137 
GetRenderFrameForInstance(PP_Instance instance) const138 RenderFrame* RendererPpapiHostImpl::GetRenderFrameForInstance(
139     PP_Instance instance) const {
140   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
141   if (!instance_object)
142     return NULL;
143 
144   // Since we're the embedder, we can make assumptions about the helper on
145   // the instance and get back to our RenderFrame.
146   return instance_object->render_frame();
147 }
148 
GetRenderViewForInstance(PP_Instance instance) const149 RenderView* RendererPpapiHostImpl::GetRenderViewForInstance(
150     PP_Instance instance) const {
151   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
152   if (!instance_object)
153     return NULL;
154 
155   // Since we're the embedder, we can make assumptions about the helper on
156   // the instance and get back to our RenderView.
157   return instance_object->render_frame()->render_view();
158 }
159 
IsValidInstance(PP_Instance instance) const160 bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
161   return !!GetAndValidateInstance(instance);
162 }
163 
GetPluginInstance(PP_Instance instance) const164 PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance(
165     PP_Instance instance) const {
166   return GetAndValidateInstance(instance);
167 }
168 
GetContainerForInstance(PP_Instance instance) const169 blink::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance(
170     PP_Instance instance) const {
171   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
172   if (!instance_object)
173     return NULL;
174   return instance_object->container();
175 }
176 
GetPluginPID() const177 base::ProcessId RendererPpapiHostImpl::GetPluginPID() const {
178   if (dispatcher_)
179     return dispatcher_->channel()->GetPeerPID();
180   return base::kNullProcessId;
181 }
182 
HasUserGesture(PP_Instance instance) const183 bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance) const {
184   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
185   if (!instance_object)
186     return false;
187 
188   if (instance_object->module()->permissions().HasPermission(
189           ppapi::PERMISSION_BYPASS_USER_GESTURE))
190     return true;
191   return instance_object->IsProcessingUserGesture();
192 }
193 
GetRoutingIDForWidget(PP_Instance instance) const194 int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance) const {
195   PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
196   if (!plugin_instance)
197     return 0;
198   if (plugin_instance->flash_fullscreen()) {
199     FullscreenContainer* container = plugin_instance->fullscreen_container();
200     return static_cast<RenderWidgetFullscreenPepper*>(container)->routing_id();
201   }
202   return GetRenderViewForInstance(instance)->GetRoutingID();
203 }
204 
PluginPointToRenderFrame(PP_Instance instance,const gfx::Point & pt) const205 gfx::Point RendererPpapiHostImpl::PluginPointToRenderFrame(
206     PP_Instance instance,
207     const gfx::Point& pt) const {
208   PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
209   if (!plugin_instance || plugin_instance->flash_fullscreen()) {
210     // Flash fullscreen is special in that it renders into its own separate,
211     // dedicated window.  So, do not offset the point.
212     return pt;
213   }
214   return gfx::Point(pt.x() + plugin_instance->view_data().rect.point.x,
215                     pt.y() + plugin_instance->view_data().rect.point.y);
216 }
217 
ShareHandleWithRemote(base::PlatformFile handle,bool should_close_source)218 IPC::PlatformFileForTransit RendererPpapiHostImpl::ShareHandleWithRemote(
219     base::PlatformFile handle,
220     bool should_close_source) {
221   if (!dispatcher_) {
222     DCHECK(is_running_in_process_);
223     // Duplicate the file handle for in process mode so this function
224     // has the same semantics for both in process mode and out of
225     // process mode (i.e., the remote side must cloes the handle).
226     return BrokerGetFileHandleForProcess(
227         handle, base::GetCurrentProcId(), should_close_source);
228   }
229   return dispatcher_->ShareHandleWithRemote(handle, should_close_source);
230 }
231 
IsRunningInProcess() const232 bool RendererPpapiHostImpl::IsRunningInProcess() const {
233   return is_running_in_process_;
234 }
235 
GetPluginName() const236 std::string RendererPpapiHostImpl::GetPluginName() const {
237   return module_->name();
238 }
239 
SetToExternalPluginHost()240 void RendererPpapiHostImpl::SetToExternalPluginHost() {
241   is_external_plugin_host_ = true;
242 }
243 
CreateBrowserResourceHosts(PP_Instance instance,const std::vector<IPC::Message> & nested_msgs,const base::Callback<void (const std::vector<int> &)> & callback) const244 void RendererPpapiHostImpl::CreateBrowserResourceHosts(
245     PP_Instance instance,
246     const std::vector<IPC::Message>& nested_msgs,
247     const base::Callback<void(const std::vector<int>&)>& callback) const {
248   RenderFrame* render_frame = GetRenderFrameForInstance(instance);
249   PepperBrowserConnection* browser_connection =
250       PepperBrowserConnection::Get(render_frame);
251   if (!browser_connection) {
252     base::MessageLoop::current()->PostTask(
253         FROM_HERE,
254         base::Bind(callback, std::vector<int>(nested_msgs.size(), 0)));
255   } else {
256     browser_connection->SendBrowserCreate(
257         module_->GetPluginChildId(), instance, nested_msgs, callback);
258   }
259 }
260 
GetDocumentURL(PP_Instance instance) const261 GURL RendererPpapiHostImpl::GetDocumentURL(PP_Instance instance) const {
262   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
263   if (!instance_object)
264     return GURL();
265 
266   return instance_object->container()->element().document().url();
267 }
268 
GetAndValidateInstance(PP_Instance pp_instance) const269 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetAndValidateInstance(
270     PP_Instance pp_instance) const {
271   PepperPluginInstanceImpl* instance =
272       HostGlobals::Get()->GetInstance(pp_instance);
273   if (!instance)
274     return NULL;
275   if (!instance->IsValidInstanceOf(module_))
276     return NULL;
277   return instance;
278 }
279 
280 }  // namespace content
281