• 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/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
6 
7 #include "base/metrics/sparse_histogram.h"
8 #include "content/browser/renderer_host/pepper/pepper_message_filter.h"
9 #include "content/browser/tracing/trace_message_filter.h"
10 #include "content/common/pepper_renderer_instance_data.h"
11 #include "content/public/common/process_type.h"
12 #include "ipc/ipc_message_macros.h"
13 #include "ppapi/proxy/ppapi_messages.h"
14 
15 namespace content {
16 
17 // static
CreateExternalPluginProcess(IPC::Sender * sender,ppapi::PpapiPermissions permissions,base::ProcessHandle plugin_child_process,IPC::ChannelProxy * channel,int render_process_id,int render_view_id,const base::FilePath & profile_directory)18 BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess(
19     IPC::Sender* sender,
20     ppapi::PpapiPermissions permissions,
21     base::ProcessHandle plugin_child_process,
22     IPC::ChannelProxy* channel,
23     int render_process_id,
24     int render_view_id,
25     const base::FilePath& profile_directory) {
26   // The plugin name and path shouldn't be needed for external plugins.
27   BrowserPpapiHostImpl* browser_ppapi_host =
28       new BrowserPpapiHostImpl(sender,
29                                permissions,
30                                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 
BrowserPpapiHostImpl(IPC::Sender * sender,const ppapi::PpapiPermissions & permissions,const std::string & plugin_name,const base::FilePath & plugin_path,const base::FilePath & profile_data_directory,bool in_process,bool external_plugin)46 BrowserPpapiHostImpl::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 
~BrowserPpapiHostImpl()67 BrowserPpapiHostImpl::~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 
GetPpapiHost()77 ppapi::host::PpapiHost* BrowserPpapiHostImpl::GetPpapiHost() {
78   return ppapi_host_.get();
79 }
80 
GetPluginProcessHandle() const81 base::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 
IsValidInstance(PP_Instance instance) const87 bool BrowserPpapiHostImpl::IsValidInstance(PP_Instance instance) const {
88   return instance_map_.find(instance) != instance_map_.end();
89 }
90 
GetRenderFrameIDsForInstance(PP_Instance instance,int * render_process_id,int * render_frame_id) const91 bool 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 
GetPluginName()107 const std::string& BrowserPpapiHostImpl::GetPluginName() {
108   return plugin_name_;
109 }
110 
GetPluginPath()111 const base::FilePath& BrowserPpapiHostImpl::GetPluginPath() {
112   return plugin_path_;
113 }
114 
GetProfileDataDirectory()115 const base::FilePath& BrowserPpapiHostImpl::GetProfileDataDirectory() {
116   return profile_data_directory_;
117 }
118 
GetDocumentURLForInstance(PP_Instance instance)119 GURL 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 
GetPluginURLForInstance(PP_Instance instance)126 GURL 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 
SetOnKeepaliveCallback(const BrowserPpapiHost::OnKeepaliveCallback & callback)133 void BrowserPpapiHostImpl::SetOnKeepaliveCallback(
134     const BrowserPpapiHost::OnKeepaliveCallback& callback) {
135   on_keepalive_callback_ = callback;
136 }
137 
AddInstance(PP_Instance instance,const PepperRendererInstanceData & instance_data)138 void 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 
DeleteInstance(PP_Instance instance)145 void 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 
HostMessageFilter(ppapi::host::PpapiHost * ppapi_host,BrowserPpapiHostImpl * browser_ppapi_host_impl)154 BrowserPpapiHostImpl::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 
OnMessageReceived(const IPC::Message & msg)160 bool 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 
OnHostDestroyed()177 void BrowserPpapiHostImpl::HostMessageFilter::OnHostDestroyed() {
178   DCHECK(ppapi_host_);
179   ppapi_host_ = NULL;
180   browser_ppapi_host_impl_ = NULL;
181 }
182 
~HostMessageFilter()183 BrowserPpapiHostImpl::HostMessageFilter::~HostMessageFilter() {}
184 
OnKeepalive()185 void BrowserPpapiHostImpl::HostMessageFilter::OnKeepalive() {
186   if (browser_ppapi_host_impl_)
187     browser_ppapi_host_impl_->OnKeepalive();
188 }
189 
OnHostMsgLogInterfaceUsage(int hash) const190 void BrowserPpapiHostImpl::HostMessageFilter::OnHostMsgLogInterfaceUsage(
191     int hash) const {
192   UMA_HISTOGRAM_SPARSE_SLOWLY("Pepper.InterfaceUsed", hash);
193 }
194 
OnKeepalive()195 void 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