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 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 146 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 157 bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const { 158 return !!GetAndValidateInstance(instance); 159 } 160 161 PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance( 162 PP_Instance instance) const { 163 return GetAndValidateInstance(instance); 164 } 165 166 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 174 base::ProcessId RendererPpapiHostImpl::GetPluginPID() const { 175 if (dispatcher_) 176 return dispatcher_->channel()->peer_pid(); 177 return base::kNullProcessId; 178 } 179 180 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 191 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 202 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 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 238 bool RendererPpapiHostImpl::IsRunningInProcess() const { 239 return is_running_in_process_; 240 } 241 242 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 260 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 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; 277 } 278 279 } // namespace content 280