15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/sparse_histogram.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/pepper/pepper_message_filter.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/tracing/trace_message_filter.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/pepper_renderer_instance_data.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/process_type.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message_macros.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess( 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::Sender* sender, 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ppapi::PpapiPermissions permissions, 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ProcessHandle plugin_child_process, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::ChannelProxy* channel, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_process_id, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_view_id, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::FilePath& profile_directory) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The plugin name and path shouldn't be needed for external plugins. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserPpapiHostImpl* browser_ppapi_host = 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new BrowserPpapiHostImpl(sender, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) permissions, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(), 31 base::FilePath(), 32 profile_directory, 33 false /* in_process */, 34 true /* external_plugin */); 35 browser_ppapi_host->set_plugin_process_handle(plugin_child_process); 36 37 scoped_refptr<PepperMessageFilter> pepper_message_filter( 38 new PepperMessageFilter()); 39 channel->AddFilter(pepper_message_filter->GetFilter()); 40 channel->AddFilter(browser_ppapi_host->message_filter().get()); 41 channel->AddFilter((new TraceMessageFilter())->GetFilter()); 42 43 return browser_ppapi_host; 44} 45 46BrowserPpapiHostImpl::BrowserPpapiHostImpl( 47 IPC::Sender* sender, 48 const ppapi::PpapiPermissions& permissions, 49 const std::string& plugin_name, 50 const base::FilePath& plugin_path, 51 const base::FilePath& profile_data_directory, 52 bool in_process, 53 bool external_plugin) 54 : ppapi_host_(new ppapi::host::PpapiHost(sender, permissions)), 55 plugin_process_handle_(base::kNullProcessHandle), 56 plugin_name_(plugin_name), 57 plugin_path_(plugin_path), 58 profile_data_directory_(profile_data_directory), 59 in_process_(in_process), 60 external_plugin_(external_plugin), 61 ssl_context_helper_(new SSLContextHelper()) { 62 message_filter_ = new HostMessageFilter(ppapi_host_.get(), this); 63 ppapi_host_->AddHostFactoryFilter(scoped_ptr<ppapi::host::HostFactory>( 64 new ContentBrowserPepperHostFactory(this))); 65} 66 67BrowserPpapiHostImpl::~BrowserPpapiHostImpl() { 68 // Notify the filter so it won't foward messages to us. 69 message_filter_->OnHostDestroyed(); 70 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 77ppapi::host::PpapiHost* BrowserPpapiHostImpl::GetPpapiHost() { 78 return ppapi_host_.get(); 79} 80 81base::ProcessHandle BrowserPpapiHostImpl::GetPluginProcessHandle() const { 82 // Handle should previously have been set before use. 83 DCHECK(in_process_ || plugin_process_handle_ != base::kNullProcessHandle); 84 return plugin_process_handle_; 85} 86 87bool BrowserPpapiHostImpl::IsValidInstance(PP_Instance instance) const { 88 return instance_map_.find(instance) != instance_map_.end(); 89} 90 91bool BrowserPpapiHostImpl::GetRenderFrameIDsForInstance( 92 PP_Instance instance, 93 int* render_process_id, 94 int* render_frame_id) const { 95 InstanceMap::const_iterator found = instance_map_.find(instance); 96 if (found == instance_map_.end()) { 97 *render_process_id = 0; 98 *render_frame_id = 0; 99 return false; 100 } 101 102 *render_process_id = found->second.render_process_id; 103 *render_frame_id = found->second.render_frame_id; 104 return true; 105} 106 107const std::string& BrowserPpapiHostImpl::GetPluginName() { 108 return plugin_name_; 109} 110 111const base::FilePath& BrowserPpapiHostImpl::GetPluginPath() { 112 return plugin_path_; 113} 114 115const base::FilePath& BrowserPpapiHostImpl::GetProfileDataDirectory() { 116 return profile_data_directory_; 117} 118 119GURL BrowserPpapiHostImpl::GetDocumentURLForInstance(PP_Instance instance) { 120 InstanceMap::const_iterator found = instance_map_.find(instance); 121 if (found == instance_map_.end()) 122 return GURL(); 123 return found->second.document_url; 124} 125 126GURL BrowserPpapiHostImpl::GetPluginURLForInstance(PP_Instance instance) { 127 InstanceMap::const_iterator found = instance_map_.find(instance); 128 if (found == instance_map_.end()) 129 return GURL(); 130 return found->second.plugin_url; 131} 132 133void BrowserPpapiHostImpl::SetOnKeepaliveCallback( 134 const BrowserPpapiHost::OnKeepaliveCallback& callback) { 135 on_keepalive_callback_ = callback; 136} 137 138void BrowserPpapiHostImpl::AddInstance( 139 PP_Instance instance, 140 const PepperRendererInstanceData& instance_data) { 141 DCHECK(instance_map_.find(instance) == instance_map_.end()); 142 instance_map_[instance] = instance_data; 143} 144 145void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance) { 146 InstanceMap::iterator found = instance_map_.find(instance); 147 if (found == instance_map_.end()) { 148 NOTREACHED(); 149 return; 150 } 151 instance_map_.erase(found); 152} 153 154BrowserPpapiHostImpl::HostMessageFilter::HostMessageFilter( 155 ppapi::host::PpapiHost* ppapi_host, 156 BrowserPpapiHostImpl* browser_ppapi_host_impl) 157 : ppapi_host_(ppapi_host), 158 browser_ppapi_host_impl_(browser_ppapi_host_impl) {} 159 160bool BrowserPpapiHostImpl::HostMessageFilter::OnMessageReceived( 161 const IPC::Message& msg) { 162 // Don't forward messages if our owner object has been destroyed. 163 if (!ppapi_host_) 164 return false; 165 166 bool handled = true; 167 IPC_BEGIN_MESSAGE_MAP(BrowserPpapiHostImpl::HostMessageFilter, msg) 168 // Add necessary message handlers here. 169 IPC_MESSAGE_HANDLER(PpapiHostMsg_Keepalive, OnKeepalive) 170 IPC_MESSAGE_HANDLER(PpapiHostMsg_LogInterfaceUsage, 171 OnHostMsgLogInterfaceUsage) 172 IPC_MESSAGE_UNHANDLED(handled = ppapi_host_->OnMessageReceived(msg)) 173 IPC_END_MESSAGE_MAP(); 174 return handled; 175} 176 177void BrowserPpapiHostImpl::HostMessageFilter::OnHostDestroyed() { 178 DCHECK(ppapi_host_); 179 ppapi_host_ = NULL; 180 browser_ppapi_host_impl_ = NULL; 181} 182 183BrowserPpapiHostImpl::HostMessageFilter::~HostMessageFilter() {} 184 185void BrowserPpapiHostImpl::HostMessageFilter::OnKeepalive() { 186 if (browser_ppapi_host_impl_) 187 browser_ppapi_host_impl_->OnKeepalive(); 188} 189 190void BrowserPpapiHostImpl::HostMessageFilter::OnHostMsgLogInterfaceUsage( 191 int hash) const { 192 UMA_HISTOGRAM_SPARSE_SLOWLY("Pepper.InterfaceUsed", hash); 193} 194 195void BrowserPpapiHostImpl::OnKeepalive() { 196 // An instance has been active. The on_keepalive_callback_ will be 197 // used to permit the content embedder to handle this, e.g. by tracking 198 // activity and shutting down processes that go idle. 199 // 200 // Currently embedders do not need to distinguish between instances having 201 // different idle state, and thus this implementation handles all instances 202 // for this module together. 203 204 if (on_keepalive_callback_.is_null()) 205 return; 206 207 BrowserPpapiHost::OnKeepaliveInstanceData instance_data(instance_map_.size()); 208 209 InstanceMap::iterator instance = instance_map_.begin(); 210 int i = 0; 211 while (instance != instance_map_.end()) { 212 instance_data[i].render_process_id = instance->second.render_process_id; 213 instance_data[i].render_frame_id = instance->second.render_frame_id; 214 instance_data[i].document_url = instance->second.document_url; 215 ++instance; 216 ++i; 217 } 218 on_keepalive_callback_.Run(instance_data, profile_data_directory_); 219} 220 221} // namespace content 222