Add ICU message format support
[chromium-blink-merge.git] / content / browser / renderer_host / pepper / browser_ppapi_host_impl.cc
blobeaa9c51b71f1b8adf228b7e1961f4be4a19cd641
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"
15 namespace content {
17 // static
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(
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(
48 IPC::Sender* sender,
49 const ppapi::PpapiPermissions& permissions,
50 const std::string& plugin_name,
51 const base::FilePath& plugin_path,
52 const base::FilePath& profile_data_directory,
53 bool in_process,
54 bool external_plugin)
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,
74 OnHostDestroyed());
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.
80 ppapi_host_.reset();
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(
98 PP_Instance instance,
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;
105 return false;
108 *render_process_id = data->renderer_data.render_process_id;
109 *render_frame_id = data->renderer_data.render_frame_id;
110 return true;
113 const std::string& BrowserPpapiHostImpl::GetPluginName() {
114 return plugin_name_;
117 const base::FilePath& BrowserPpapiHostImpl::GetPluginPath() {
118 return plugin_path_;
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);
127 if (data == nullptr)
128 return GURL();
129 return data->renderer_data.document_url;
132 GURL BrowserPpapiHostImpl::GetPluginURLForInstance(PP_Instance instance) {
133 auto* data = instance_map_.get(instance);
134 if (data == nullptr)
135 return GURL();
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);
147 if (data == nullptr)
148 return false;
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);
173 if (data)
174 data->observer_list.RemoveObserver(observer);
177 void BrowserPpapiHostImpl::OnThrottleStateChanged(PP_Instance instance,
178 bool is_throttled) {
179 auto* data = instance_map_.get(instance);
180 if (data) {
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);
189 if (data)
190 return data->is_throttled;
192 return false;
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.
204 if (!ppapi_host_)
205 return false;
207 bool handled = true;
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();
215 return handled;
218 void BrowserPpapiHostImpl::HostMessageFilter::OnHostDestroyed() {
219 DCHECK(ppapi_host_);
220 ppapi_host_ = NULL;
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(
232 int hash) const {
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())
254 return;
256 BrowserPpapiHost::OnKeepaliveInstanceData instance_data(instance_map_.size());
258 auto instance = instance_map_.begin();
259 int i = 0;
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;
267 ++instance;
268 ++i;
270 on_keepalive_callback_.Run(instance_data, profile_data_directory_);
273 } // namespace content