1 // Copyright 2014 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 "chrome/renderer/pepper/pepper_uma_host.h"
7 #include "base/metrics/histogram.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "chrome/common/chrome_content_client.h"
11 #include "chrome/common/chrome_switches.h"
12 #include "chrome/common/render_messages.h"
13 #include "chrome/renderer/chrome_content_renderer_client.h"
14 #include "content/public/renderer/pepper_plugin_instance.h"
15 #include "content/public/renderer/render_thread.h"
16 #include "content/public/renderer/renderer_ppapi_host.h"
17 #include "ppapi/c/pp_errors.h"
18 #include "ppapi/host/dispatch_host_message.h"
19 #include "ppapi/host/host_message_context.h"
20 #include "ppapi/host/ppapi_host.h"
21 #include "ppapi/proxy/ppapi_messages.h"
23 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
25 #if defined(ENABLE_EXTENSIONS)
26 #include "extensions/common/constants.h"
27 #include "extensions/common/extension.h"
28 #endif // defined(ENABLE_EXTENSIONS)
32 const char* const kPredefinedAllowedUMAOrigins
[] = {
33 "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", // see http://crbug.com/317833
34 "4EB74897CB187C7633357C2FE832E0AD6A44883A", // see http://crbug.com/317833
37 const char* const kWhitelistedHistogramPrefixes
[] = {
38 "22F67DA2061FFC4DC9A4974036348D9C38C22919", // see http://crbug.com/390221
41 const char* const kWhitelistedPluginBaseNames
[] = {
42 #if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
43 kWidevineCdmAdapterFileName
, // see http://crbug.com/368743
44 // and http://crbug.com/410630
46 ChromeContentClient::kPDFPluginPath
,
49 std::string
HashPrefix(const std::string
& histogram
) {
50 const std::string id_hash
=
51 base::SHA1HashString(histogram
.substr(0, histogram
.find('.')));
52 DCHECK_EQ(id_hash
.length(), base::kSHA1Length
);
53 return base::HexEncode(id_hash
.c_str(), id_hash
.length());
58 PepperUMAHost::PepperUMAHost(content::RendererPpapiHost
* host
,
61 : ResourceHost(host
->GetPpapiHost(), instance
, resource
),
62 document_url_(host
->GetDocumentURL(instance
)),
63 is_plugin_in_process_(host
->IsRunningInProcess()) {
64 if (host
->GetPluginInstance(instance
)) {
66 host
->GetPluginInstance(instance
)->GetModulePath().BaseName();
69 for (size_t i
= 0; i
< arraysize(kPredefinedAllowedUMAOrigins
); ++i
)
70 allowed_origins_
.insert(kPredefinedAllowedUMAOrigins
[i
]);
71 for (size_t i
= 0; i
< arraysize(kWhitelistedHistogramPrefixes
); ++i
)
72 allowed_histogram_prefixes_
.insert(kWhitelistedHistogramPrefixes
[i
]);
73 for (size_t i
= 0; i
< arraysize(kWhitelistedPluginBaseNames
); ++i
)
74 allowed_plugin_base_names_
.insert(kWhitelistedPluginBaseNames
[i
]);
77 PepperUMAHost::~PepperUMAHost() {}
79 int32_t PepperUMAHost::OnResourceMessageReceived(
80 const IPC::Message
& msg
,
81 ppapi::host::HostMessageContext
* context
) {
82 PPAPI_BEGIN_MESSAGE_MAP(PepperUMAHost
, msg
)
83 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramCustomTimes
,
84 OnHistogramCustomTimes
)
85 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramCustomCounts
,
86 OnHistogramCustomCounts
)
87 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramEnumeration
,
88 OnHistogramEnumeration
)
89 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
90 PpapiHostMsg_UMA_IsCrashReportingEnabled
, OnIsCrashReportingEnabled
)
91 PPAPI_END_MESSAGE_MAP()
92 return PP_ERROR_FAILED
;
95 bool PepperUMAHost::IsPluginWhitelisted() {
96 #if defined(ENABLE_EXTENSIONS)
97 return ChromeContentRendererClient::IsExtensionOrSharedModuleWhitelisted(
98 document_url_
, allowed_origins_
);
104 bool PepperUMAHost::IsHistogramAllowed(const std::string
& histogram
) {
105 if (is_plugin_in_process_
&& histogram
.find("NaCl.") == 0) {
109 if (IsPluginWhitelisted() &&
110 ContainsKey(allowed_histogram_prefixes_
, HashPrefix(histogram
))) {
114 if (ContainsKey(allowed_plugin_base_names_
,
115 plugin_base_name_
.MaybeAsASCII())) {
119 LOG(ERROR
) << "Host or histogram name is not allowed to use the UMA API.";
123 #define RETURN_IF_BAD_ARGS(_min, _max, _buckets) \
125 if (_min >= _max || _buckets <= 1) \
126 return PP_ERROR_BADARGUMENT; \
129 int32_t PepperUMAHost::OnHistogramCustomTimes(
130 ppapi::host::HostMessageContext
* context
,
131 const std::string
& name
,
135 uint32_t bucket_count
) {
136 if (!IsHistogramAllowed(name
)) {
137 return PP_ERROR_NOACCESS
;
139 RETURN_IF_BAD_ARGS(min
, max
, bucket_count
);
141 base::HistogramBase
* counter
= base::Histogram::FactoryTimeGet(
143 base::TimeDelta::FromMilliseconds(min
),
144 base::TimeDelta::FromMilliseconds(max
),
146 base::HistogramBase::kUmaTargetedHistogramFlag
);
147 // The histogram can be NULL if it is constructed with bad arguments. Ignore
148 // that data for this API. An error message will be logged.
150 counter
->AddTime(base::TimeDelta::FromMilliseconds(sample
));
154 int32_t PepperUMAHost::OnHistogramCustomCounts(
155 ppapi::host::HostMessageContext
* context
,
156 const std::string
& name
,
160 uint32_t bucket_count
) {
161 if (!IsHistogramAllowed(name
)) {
162 return PP_ERROR_NOACCESS
;
164 RETURN_IF_BAD_ARGS(min
, max
, bucket_count
);
166 base::HistogramBase
* counter
= base::Histogram::FactoryGet(
171 base::HistogramBase::kUmaTargetedHistogramFlag
);
172 // The histogram can be NULL if it is constructed with bad arguments. Ignore
173 // that data for this API. An error message will be logged.
175 counter
->Add(sample
);
179 int32_t PepperUMAHost::OnHistogramEnumeration(
180 ppapi::host::HostMessageContext
* context
,
181 const std::string
& name
,
183 int32_t boundary_value
) {
184 if (!IsHistogramAllowed(name
)) {
185 return PP_ERROR_NOACCESS
;
187 RETURN_IF_BAD_ARGS(0, boundary_value
, boundary_value
+ 1);
189 base::HistogramBase
* counter
= base::LinearHistogram::FactoryGet(
194 base::HistogramBase::kUmaTargetedHistogramFlag
);
195 // The histogram can be NULL if it is constructed with bad arguments. Ignore
196 // that data for this API. An error message will be logged.
198 counter
->Add(sample
);
202 int32_t PepperUMAHost::OnIsCrashReportingEnabled(
203 ppapi::host::HostMessageContext
* context
) {
204 if (!IsPluginWhitelisted())
205 return PP_ERROR_NOACCESS
;
206 bool enabled
= false;
207 content::RenderThread::Get()->Send(
208 new ChromeViewHostMsg_IsCrashReportingEnabled(&enabled
));
211 return PP_ERROR_FAILED
;