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/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
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"
18 BrowserPpapiHost
* BrowserPpapiHost::CreateExternalPluginProcess(
20 ppapi::PpapiPermissions permissions
,
21 base::ProcessHandle plugin_child_process
,
22 IPC::ChannelProxy
* channel
,
23 int render_process_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
,
33 false /* in_process */,
34 true /* external_plugin */);
35 browser_ppapi_host
->set_plugin_process(
36 base::Process::DeprecatedGetProcessFromHandle(plugin_child_process
));
38 scoped_refptr
<PepperMessageFilter
> pepper_message_filter(
39 new PepperMessageFilter());
40 channel
->AddFilter(pepper_message_filter
->GetFilter());
41 channel
->AddFilter(browser_ppapi_host
->message_filter().get());
42 channel
->AddFilter((new TraceMessageFilter(render_process_id
))->GetFilter());
44 return browser_ppapi_host
;
47 BrowserPpapiHostImpl::BrowserPpapiHostImpl(
49 const ppapi::PpapiPermissions
& permissions
,
50 const std::string
& plugin_name
,
51 const base::FilePath
& plugin_path
,
52 const base::FilePath
& profile_data_directory
,
55 : ppapi_host_(new ppapi::host::PpapiHost(sender
, permissions
)),
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)));
67 BrowserPpapiHostImpl::~BrowserPpapiHostImpl() {
68 // Notify the filter so it won't foward messages to us.
69 message_filter_
->OnHostDestroyed();
71 // Notify instance observers about our impending destruction.
72 for (auto& instance_data
: instance_map_
) {
73 FOR_EACH_OBSERVER(InstanceObserver
, instance_data
.second
->observer_list
,
77 // Delete the host explicitly first. This shutdown will destroy the
78 // resources, which may want to do cleanup in their destructors and expect
79 // their pointers to us to be valid.
83 ppapi::host::PpapiHost
* BrowserPpapiHostImpl::GetPpapiHost() {
84 return ppapi_host_
.get();
87 const base::Process
& BrowserPpapiHostImpl::GetPluginProcess() const {
88 // Handle should previously have been set before use.
89 DCHECK(in_process_
|| plugin_process_
.IsValid());
90 return plugin_process_
;
93 bool BrowserPpapiHostImpl::IsValidInstance(PP_Instance instance
) const {
94 return instance_map_
.contains(instance
);
97 bool BrowserPpapiHostImpl::GetRenderFrameIDsForInstance(
99 int* render_process_id
,
100 int* render_frame_id
) const {
101 auto* data
= instance_map_
.get(instance
);
102 if (data
== nullptr) {
103 *render_process_id
= 0;
104 *render_frame_id
= 0;
108 *render_process_id
= data
->renderer_data
.render_process_id
;
109 *render_frame_id
= data
->renderer_data
.render_frame_id
;
113 const std::string
& BrowserPpapiHostImpl::GetPluginName() {
117 const base::FilePath
& BrowserPpapiHostImpl::GetPluginPath() {
121 const base::FilePath
& BrowserPpapiHostImpl::GetProfileDataDirectory() {
122 return profile_data_directory_
;
125 GURL
BrowserPpapiHostImpl::GetDocumentURLForInstance(PP_Instance instance
) {
126 auto* data
= instance_map_
.get(instance
);
129 return data
->renderer_data
.document_url
;
132 GURL
BrowserPpapiHostImpl::GetPluginURLForInstance(PP_Instance instance
) {
133 auto* data
= instance_map_
.get(instance
);
136 return data
->renderer_data
.plugin_url
;
139 void BrowserPpapiHostImpl::SetOnKeepaliveCallback(
140 const BrowserPpapiHost::OnKeepaliveCallback
& callback
) {
141 on_keepalive_callback_
= callback
;
144 bool BrowserPpapiHostImpl::IsPotentiallySecurePluginContext(
145 PP_Instance instance
) {
146 auto* data
= instance_map_
.get(instance
);
149 return data
->renderer_data
.is_potentially_secure_plugin_context
;
152 void BrowserPpapiHostImpl::AddInstance(
153 PP_Instance instance
,
154 const PepperRendererInstanceData
& renderer_instance_data
) {
155 DCHECK(!instance_map_
.contains(instance
));
156 instance_map_
.add(instance
,
157 make_scoped_ptr(new InstanceData(renderer_instance_data
)));
160 void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance
) {
161 int erased
= instance_map_
.erase(instance
);
162 DCHECK_EQ(1, erased
);
165 void BrowserPpapiHostImpl::AddInstanceObserver(PP_Instance instance
,
166 InstanceObserver
* observer
) {
167 instance_map_
.get(instance
)->observer_list
.AddObserver(observer
);
170 void BrowserPpapiHostImpl::RemoveInstanceObserver(PP_Instance instance
,
171 InstanceObserver
* observer
) {
172 auto* data
= instance_map_
.get(instance
);
174 data
->observer_list
.RemoveObserver(observer
);
177 void BrowserPpapiHostImpl::OnThrottleStateChanged(PP_Instance instance
,
179 auto* data
= instance_map_
.get(instance
);
181 data
->is_throttled
= is_throttled
;
182 FOR_EACH_OBSERVER(InstanceObserver
, data
->observer_list
,
183 OnThrottleStateChanged(is_throttled
));
187 bool BrowserPpapiHostImpl::IsThrottled(PP_Instance instance
) const {
188 auto* data
= instance_map_
.get(instance
);
190 return data
->is_throttled
;
195 BrowserPpapiHostImpl::HostMessageFilter::HostMessageFilter(
196 ppapi::host::PpapiHost
* ppapi_host
,
197 BrowserPpapiHostImpl
* browser_ppapi_host_impl
)
198 : ppapi_host_(ppapi_host
),
199 browser_ppapi_host_impl_(browser_ppapi_host_impl
) {}
201 bool BrowserPpapiHostImpl::HostMessageFilter::OnMessageReceived(
202 const IPC::Message
& msg
) {
203 // Don't forward messages if our owner object has been destroyed.
208 IPC_BEGIN_MESSAGE_MAP(BrowserPpapiHostImpl::HostMessageFilter
, msg
)
209 // Add necessary message handlers here.
210 IPC_MESSAGE_HANDLER(PpapiHostMsg_Keepalive
, OnKeepalive
)
211 IPC_MESSAGE_HANDLER(PpapiHostMsg_LogInterfaceUsage
,
212 OnHostMsgLogInterfaceUsage
)
213 IPC_MESSAGE_UNHANDLED(handled
= ppapi_host_
->OnMessageReceived(msg
))
214 IPC_END_MESSAGE_MAP();
218 void BrowserPpapiHostImpl::HostMessageFilter::OnHostDestroyed() {
221 browser_ppapi_host_impl_
= NULL
;
224 BrowserPpapiHostImpl::HostMessageFilter::~HostMessageFilter() {}
226 void BrowserPpapiHostImpl::HostMessageFilter::OnKeepalive() {
227 if (browser_ppapi_host_impl_
)
228 browser_ppapi_host_impl_
->OnKeepalive();
231 void BrowserPpapiHostImpl::HostMessageFilter::OnHostMsgLogInterfaceUsage(
233 UMA_HISTOGRAM_SPARSE_SLOWLY("Pepper.InterfaceUsed", hash
);
236 BrowserPpapiHostImpl::InstanceData::InstanceData(
237 const PepperRendererInstanceData
& renderer_data
)
238 : renderer_data(renderer_data
), is_throttled(false) {
241 BrowserPpapiHostImpl::InstanceData::~InstanceData() {
244 void BrowserPpapiHostImpl::OnKeepalive() {
245 // An instance has been active. The on_keepalive_callback_ will be
246 // used to permit the content embedder to handle this, e.g. by tracking
247 // activity and shutting down processes that go idle.
249 // Currently embedders do not need to distinguish between instances having
250 // different idle state, and thus this implementation handles all instances
251 // for this module together.
253 if (on_keepalive_callback_
.is_null())
256 BrowserPpapiHost::OnKeepaliveInstanceData
instance_data(instance_map_
.size());
258 auto instance
= instance_map_
.begin();
260 while (instance
!= instance_map_
.end()) {
261 instance_data
[i
].render_process_id
=
262 instance
->second
->renderer_data
.render_process_id
;
263 instance_data
[i
].render_frame_id
=
264 instance
->second
->renderer_data
.render_frame_id
;
265 instance_data
[i
].document_url
=
266 instance
->second
->renderer_data
.document_url
;
270 on_keepalive_callback_
.Run(instance_data
, profile_data_directory_
);
273 } // namespace content