Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / renderer / pepper / renderer_ppapi_host_impl.cc
blob61c1ba66f007de890ecff41200df058dc0555d5f
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/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/geometry/point.h"
32 namespace content {
33 // static
34 CONTENT_EXPORT RendererPpapiHost* RendererPpapiHost::GetForPPInstance(
35 PP_Instance instance) {
36 return RendererPpapiHostImpl::GetForPPInstance(instance);
39 // Out-of-process constructor.
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;
55 // In-process constructor.
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;
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();
76 // static
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);
85 // Takes ownership of pointer.
86 module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
88 return result;
91 // static
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);
99 // Takes ownership of pointer.
100 module->SetRendererPpapiHost(scoped_ptr<RendererPpapiHostImpl>(result));
102 return result;
105 // static
106 RendererPpapiHostImpl* RendererPpapiHostImpl::GetForPPInstance(
107 PP_Instance pp_instance) {
108 PepperPluginInstanceImpl* instance =
109 HostGlobals::Get()->GetInstance(pp_instance);
110 if (!instance)
111 return NULL;
113 // All modules created by content will have their embedder state be the
114 // host impl.
115 return instance->module()->renderer_ppapi_host();
118 scoped_ptr<ppapi::thunk::ResourceCreationAPI>
119 RendererPpapiHostImpl::CreateInProcessResourceCreationAPI(
120 PepperPluginInstanceImpl* instance) {
121 return scoped_ptr<ppapi::thunk::ResourceCreationAPI>(
122 new PepperInProcessResourceCreation(this, instance));
125 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetPluginInstanceImpl(
126 PP_Instance instance) const {
127 return GetAndValidateInstance(instance);
130 bool RendererPpapiHostImpl::IsExternalPluginHost() const {
131 return is_external_plugin_host_;
134 ppapi::host::PpapiHost* RendererPpapiHostImpl::GetPpapiHost() {
135 return ppapi_host_.get();
138 RenderFrame* RendererPpapiHostImpl::GetRenderFrameForInstance(
139 PP_Instance instance) const {
140 PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
141 if (!instance_object)
142 return NULL;
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();
149 RenderView* RendererPpapiHostImpl::GetRenderViewForInstance(
150 PP_Instance instance) const {
151 PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
152 if (!instance_object)
153 return NULL;
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();
160 bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
161 return !!GetAndValidateInstance(instance);
164 PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance(
165 PP_Instance instance) const {
166 return GetAndValidateInstance(instance);
169 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();
177 base::ProcessId RendererPpapiHostImpl::GetPluginPID() const {
178 if (dispatcher_)
179 return dispatcher_->channel()->GetPeerPID();
180 return base::kNullProcessId;
183 bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance) const {
184 PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
185 if (!instance_object)
186 return false;
188 if (instance_object->module()->permissions().HasPermission(
189 ppapi::PERMISSION_BYPASS_USER_GESTURE))
190 return true;
191 return instance_object->IsProcessingUserGesture();
194 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();
202 return GetRenderViewForInstance(instance)->GetRoutingID();
205 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;
214 return gfx::Point(pt.x() + plugin_instance->view_data().rect.point.x,
215 pt.y() + plugin_instance->view_data().rect.point.y);
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);
229 return dispatcher_->ShareHandleWithRemote(handle, should_close_source);
232 bool RendererPpapiHostImpl::IsRunningInProcess() const {
233 return is_running_in_process_;
236 std::string RendererPpapiHostImpl::GetPluginName() const {
237 return module_->name();
240 void RendererPpapiHostImpl::SetToExternalPluginHost() {
241 is_external_plugin_host_ = true;
244 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);
261 GURL RendererPpapiHostImpl::GetDocumentURL(PP_Instance pp_instance) const {
262 PepperPluginInstanceImpl* instance = GetAndValidateInstance(pp_instance);
263 if (!instance)
264 return GURL();
265 return instance->document_url();
268 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;
279 } // namespace content