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
, permissions
, std::string(),
29 base::FilePath(), profile_directory
,
30 false /* in_process */,
31 true /* external_plugin */);
32 browser_ppapi_host
->set_plugin_process_handle(plugin_child_process
);
34 scoped_refptr
<PepperMessageFilter
> pepper_message_filter(
35 new PepperMessageFilter());
36 channel
->AddFilter(pepper_message_filter
->GetFilter());
37 channel
->AddFilter(browser_ppapi_host
->message_filter());
38 channel
->AddFilter((new TraceMessageFilter())->GetFilter());
40 return browser_ppapi_host
;
43 BrowserPpapiHostImpl::BrowserPpapiHostImpl(
45 const ppapi::PpapiPermissions
& permissions
,
46 const std::string
& plugin_name
,
47 const base::FilePath
& plugin_path
,
48 const base::FilePath
& profile_data_directory
,
51 : ppapi_host_(new ppapi::host::PpapiHost(sender
, permissions
)),
52 plugin_process_handle_(base::kNullProcessHandle
),
53 plugin_name_(plugin_name
),
54 plugin_path_(plugin_path
),
55 profile_data_directory_(profile_data_directory
),
56 in_process_(in_process
),
57 external_plugin_(external_plugin
),
58 ssl_context_helper_(new SSLContextHelper()) {
59 message_filter_
= new HostMessageFilter(ppapi_host_
.get(), this);
60 ppapi_host_
->AddHostFactoryFilter(scoped_ptr
<ppapi::host::HostFactory
>(
61 new ContentBrowserPepperHostFactory(this)));
64 BrowserPpapiHostImpl::~BrowserPpapiHostImpl() {
65 // Notify the filter so it won't foward messages to us.
66 message_filter_
->OnHostDestroyed();
68 // Delete the host explicitly first. This shutdown will destroy the
69 // resources, which may want to do cleanup in their destructors and expect
70 // their pointers to us to be valid.
74 ppapi::host::PpapiHost
* BrowserPpapiHostImpl::GetPpapiHost() {
75 return ppapi_host_
.get();
78 base::ProcessHandle
BrowserPpapiHostImpl::GetPluginProcessHandle() const {
79 // Handle should previously have been set before use.
80 DCHECK(in_process_
|| plugin_process_handle_
!= base::kNullProcessHandle
);
81 return plugin_process_handle_
;
84 bool BrowserPpapiHostImpl::IsValidInstance(PP_Instance instance
) const {
85 return instance_map_
.find(instance
) != instance_map_
.end();
88 bool BrowserPpapiHostImpl::GetRenderFrameIDsForInstance(
90 int* render_process_id
,
91 int* render_frame_id
) const {
92 InstanceMap::const_iterator found
= instance_map_
.find(instance
);
93 if (found
== instance_map_
.end()) {
94 *render_process_id
= 0;
99 *render_process_id
= found
->second
.render_process_id
;
100 *render_frame_id
= found
->second
.render_frame_id
;
104 const std::string
& BrowserPpapiHostImpl::GetPluginName() {
108 const base::FilePath
& BrowserPpapiHostImpl::GetPluginPath() {
112 const base::FilePath
& BrowserPpapiHostImpl::GetProfileDataDirectory() {
113 return profile_data_directory_
;
116 GURL
BrowserPpapiHostImpl::GetDocumentURLForInstance(PP_Instance instance
) {
117 InstanceMap::const_iterator found
= instance_map_
.find(instance
);
118 if (found
== instance_map_
.end())
120 return found
->second
.document_url
;
123 GURL
BrowserPpapiHostImpl::GetPluginURLForInstance(PP_Instance instance
) {
124 InstanceMap::const_iterator found
= instance_map_
.find(instance
);
125 if (found
== instance_map_
.end())
127 return found
->second
.plugin_url
;
130 void BrowserPpapiHostImpl::SetOnKeepaliveCallback(
131 const BrowserPpapiHost::OnKeepaliveCallback
& callback
) {
132 on_keepalive_callback_
= callback
;
135 void BrowserPpapiHostImpl::AddInstance(
136 PP_Instance instance
,
137 const PepperRendererInstanceData
& instance_data
) {
138 DCHECK(instance_map_
.find(instance
) == instance_map_
.end());
139 instance_map_
[instance
] = instance_data
;
142 void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance
) {
143 InstanceMap::iterator found
= instance_map_
.find(instance
);
144 if (found
== instance_map_
.end()) {
148 instance_map_
.erase(found
);
151 BrowserPpapiHostImpl::HostMessageFilter::HostMessageFilter(
152 ppapi::host::PpapiHost
* ppapi_host
,
153 BrowserPpapiHostImpl
* browser_ppapi_host_impl
)
154 : ppapi_host_(ppapi_host
),
155 browser_ppapi_host_impl_(browser_ppapi_host_impl
) {
158 bool BrowserPpapiHostImpl::HostMessageFilter::OnMessageReceived(
159 const IPC::Message
& msg
) {
160 // Don't forward messages if our owner object has been destroyed.
165 IPC_BEGIN_MESSAGE_MAP(BrowserPpapiHostImpl::HostMessageFilter
, msg
)
166 // Add necessary message handlers here.
167 IPC_MESSAGE_HANDLER(PpapiHostMsg_Keepalive
, OnKeepalive
)
168 IPC_MESSAGE_HANDLER(PpapiHostMsg_LogInterfaceUsage
,
169 OnHostMsgLogInterfaceUsage
)
170 IPC_MESSAGE_UNHANDLED(handled
= ppapi_host_
->OnMessageReceived(msg
))
171 IPC_END_MESSAGE_MAP();
175 void BrowserPpapiHostImpl::HostMessageFilter::OnHostDestroyed() {
178 browser_ppapi_host_impl_
= NULL
;
181 BrowserPpapiHostImpl::HostMessageFilter::~HostMessageFilter() {
184 void BrowserPpapiHostImpl::HostMessageFilter::OnKeepalive() {
185 if (browser_ppapi_host_impl_
)
186 browser_ppapi_host_impl_
->OnKeepalive();
189 void BrowserPpapiHostImpl::HostMessageFilter::OnHostMsgLogInterfaceUsage(
191 UMA_HISTOGRAM_SPARSE_SLOWLY("Pepper.InterfaceUsed", hash
);
194 void BrowserPpapiHostImpl::OnKeepalive() {
195 // An instance has been active. The on_keepalive_callback_ will be
196 // used to permit the content embedder to handle this, e.g. by tracking
197 // activity and shutting down processes that go idle.
199 // Currently embedders do not need to distinguish between instances having
200 // different idle state, and thus this implementation handles all instances
201 // for this module together.
203 if (on_keepalive_callback_
.is_null())
206 BrowserPpapiHost::OnKeepaliveInstanceData
207 instance_data(instance_map_
.size());
209 InstanceMap::iterator instance
= instance_map_
.begin();
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
;
218 on_keepalive_callback_
.Run(instance_data
, profile_data_directory_
);
221 } // namespace content