- add sources.
[platform/framework/web/crosswalk.git] / src / content / renderer / pepper / renderer_ppapi_host_impl.cc
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*
35 RendererPpapiHost::GetForPPInstance(PP_Instance instance) {
36   return RendererPpapiHostImpl::GetForPPInstance(instance);
37 }
38
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   // 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.
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
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
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
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
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>
120 RendererPpapiHostImpl::CreateInProcessResourceCreationAPI(
121     PepperPluginInstanceImpl* instance) {
122   return scoped_ptr<ppapi::thunk::ResourceCreationAPI>(
123       new PepperInProcessResourceCreation(this, instance));
124 }
125
126 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetPluginInstanceImpl(
127     PP_Instance instance) const {
128   return GetAndValidateInstance(instance);
129 }
130
131 ppapi::host::PpapiHost* RendererPpapiHostImpl::GetPpapiHost() {
132   return ppapi_host_.get();
133 }
134
135 RenderView* RendererPpapiHostImpl::GetRenderViewForInstance(
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 RenderView.
143   return instance_object->render_view();
144 }
145
146 bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
147   return !!GetAndValidateInstance(instance);
148 }
149
150 PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance(
151     PP_Instance instance) const {
152   return GetAndValidateInstance(instance);
153 }
154
155 WebKit::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance(
156       PP_Instance instance) const {
157   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
158   if (!instance_object)
159     return NULL;
160   return instance_object->container();
161 }
162
163 base::ProcessId RendererPpapiHostImpl::GetPluginPID() const {
164   if (dispatcher_)
165     return dispatcher_->channel()->peer_pid();
166   return base::kNullProcessId;
167 }
168
169 bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance) const {
170   PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance);
171   if (!instance_object)
172     return false;
173
174   if (instance_object->module()->permissions().HasPermission(
175           ppapi::PERMISSION_BYPASS_USER_GESTURE))
176     return true;
177   return instance_object->IsProcessingUserGesture();
178 }
179
180 int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance) const {
181   PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
182   if (!plugin_instance)
183     return 0;
184   if (plugin_instance->flash_fullscreen()) {
185     FullscreenContainer* container = plugin_instance->fullscreen_container();
186     return static_cast<RenderWidgetFullscreenPepper*>(container)->routing_id();
187   }
188   return GetRenderViewForInstance(instance)->GetRoutingID();
189 }
190
191 gfx::Point RendererPpapiHostImpl::PluginPointToRenderView(
192     PP_Instance instance,
193     const gfx::Point& pt) const {
194   PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance);
195   if (!plugin_instance)
196     return pt;
197
198   RenderViewImpl* render_view = static_cast<RenderViewImpl*>(
199       GetRenderViewForInstance(instance));
200   if (plugin_instance->view_data().is_fullscreen ||
201       plugin_instance->flash_fullscreen()) {
202     WebKit::WebRect window_rect = render_view->windowRect();
203     WebKit::WebRect screen_rect = render_view->screenInfo().rect;
204     return gfx::Point(pt.x() - window_rect.x + screen_rect.x,
205                       pt.y() - window_rect.y + screen_rect.y);
206   }
207   return gfx::Point(pt.x() + plugin_instance->view_data().rect.point.x,
208                     pt.y() + plugin_instance->view_data().rect.point.y);
209 }
210
211 IPC::PlatformFileForTransit RendererPpapiHostImpl::ShareHandleWithRemote(
212     base::PlatformFile handle,
213     bool should_close_source) {
214   if (!dispatcher_) {
215     DCHECK(is_running_in_process_);
216     // Duplicate the file handle for in process mode so this function
217     // has the same semantics for both in process mode and out of
218     // process mode (i.e., the remote side must cloes the handle).
219     return BrokerGetFileHandleForProcess(handle,
220                                          base::GetCurrentProcId(),
221                                          should_close_source);
222   }
223   return dispatcher_->ShareHandleWithRemote(handle, should_close_source);
224 }
225
226 bool RendererPpapiHostImpl::IsRunningInProcess() const {
227   return is_running_in_process_;
228 }
229
230 void RendererPpapiHostImpl::CreateBrowserResourceHosts(
231     PP_Instance instance,
232     const std::vector<IPC::Message>& nested_msgs,
233     const base::Callback<void(const std::vector<int>&)>& callback) const {
234   RenderView* render_view = GetRenderViewForInstance(instance);
235   PepperBrowserConnection* browser_connection =
236       PepperBrowserConnection::Get(render_view);
237   if (!browser_connection) {
238     base::MessageLoop::current()->PostTask(FROM_HERE,
239         base::Bind(callback, std::vector<int>(nested_msgs.size(), 0)));
240   } else {
241     browser_connection->SendBrowserCreate(module_->GetPluginChildId(),
242                                           instance,
243                                           nested_msgs,
244                                           callback);
245   }
246 }
247
248 PepperPluginInstanceImpl* RendererPpapiHostImpl::GetAndValidateInstance(
249     PP_Instance pp_instance) const {
250   PepperPluginInstanceImpl* instance =
251       HostGlobals::Get()->GetInstance(pp_instance);
252   if (!instance)
253     return NULL;
254   if (!instance->IsValidInstanceOf(module_))
255     return NULL;
256   return instance;
257 }
258
259 }  // namespace content