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
35 "9E527CDA9D7C50844E8A5DB964A54A640AE48F98", // see http://crbug.com/521189
36 "DF52618D0B040D8A054D8348D2E84DDEEE5974E7", // see http://crbug.com/521189
37 "269D721F163E587BC53C6F83553BF9CE2BB143CD", // see http://crbug.com/521189
38 "6B55A5329E3F1F30F6032BDB20B2EB4378DBF767", // see http://crbug.com/521189
39 "C449A798C495E6CF7D6AF10162113D564E67AD12", // see http://crbug.com/521189
40 "01E9FFA9A8F3C18271FE91BEE46207F3B81755CC", // see http://crbug.com/521189
41 "97B23E01B2AA064E8332EE43A7A85C628AADC3F2", // see http://crbug.com/521189
44 const char* const kWhitelistedHistogramPrefixes
[] = {
45 "22F67DA2061FFC4DC9A4974036348D9C38C22919", // see http://crbug.com/390221
46 "3FEA4650221C5E6C39CF5C5C9F464FF74EAB6CE1", // see http://crbug.com/521189
49 const char* const kWhitelistedPluginBaseNames
[] = {
50 #if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
51 kWidevineCdmAdapterFileName
, // see http://crbug.com/368743
52 // and http://crbug.com/410630
54 ChromeContentClient::kPDFPluginPath
,
57 std::string
HashPrefix(const std::string
& histogram
) {
58 const std::string id_hash
=
59 base::SHA1HashString(histogram
.substr(0, histogram
.find('.')));
60 DCHECK_EQ(id_hash
.length(), base::kSHA1Length
);
61 return base::HexEncode(id_hash
.c_str(), id_hash
.length());
66 PepperUMAHost::PepperUMAHost(content::RendererPpapiHost
* host
,
69 : ResourceHost(host
->GetPpapiHost(), instance
, resource
),
70 document_url_(host
->GetDocumentURL(instance
)),
71 is_plugin_in_process_(host
->IsRunningInProcess()) {
72 if (host
->GetPluginInstance(instance
)) {
74 host
->GetPluginInstance(instance
)->GetModulePath().BaseName();
77 for (size_t i
= 0; i
< arraysize(kPredefinedAllowedUMAOrigins
); ++i
)
78 allowed_origins_
.insert(kPredefinedAllowedUMAOrigins
[i
]);
79 for (size_t i
= 0; i
< arraysize(kWhitelistedHistogramPrefixes
); ++i
)
80 allowed_histogram_prefixes_
.insert(kWhitelistedHistogramPrefixes
[i
]);
81 for (size_t i
= 0; i
< arraysize(kWhitelistedPluginBaseNames
); ++i
)
82 allowed_plugin_base_names_
.insert(kWhitelistedPluginBaseNames
[i
]);
85 PepperUMAHost::~PepperUMAHost() {}
87 int32_t PepperUMAHost::OnResourceMessageReceived(
88 const IPC::Message
& msg
,
89 ppapi::host::HostMessageContext
* context
) {
90 PPAPI_BEGIN_MESSAGE_MAP(PepperUMAHost
, msg
)
91 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramCustomTimes
,
92 OnHistogramCustomTimes
)
93 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramCustomCounts
,
94 OnHistogramCustomCounts
)
95 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramEnumeration
,
96 OnHistogramEnumeration
)
97 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
98 PpapiHostMsg_UMA_IsCrashReportingEnabled
, OnIsCrashReportingEnabled
)
99 PPAPI_END_MESSAGE_MAP()
100 return PP_ERROR_FAILED
;
103 bool PepperUMAHost::IsPluginWhitelisted() {
104 #if defined(ENABLE_EXTENSIONS)
105 return ChromeContentRendererClient::IsExtensionOrSharedModuleWhitelisted(
106 document_url_
, allowed_origins_
);
112 bool PepperUMAHost::IsHistogramAllowed(const std::string
& histogram
) {
113 if (is_plugin_in_process_
&& histogram
.find("NaCl.") == 0) {
117 if (IsPluginWhitelisted() &&
118 ContainsKey(allowed_histogram_prefixes_
, HashPrefix(histogram
))) {
122 if (ContainsKey(allowed_plugin_base_names_
,
123 plugin_base_name_
.MaybeAsASCII())) {
127 LOG(ERROR
) << "Host or histogram name is not allowed to use the UMA API.";
131 #define RETURN_IF_BAD_ARGS(_min, _max, _buckets) \
133 if (_min >= _max || _buckets <= 1) \
134 return PP_ERROR_BADARGUMENT; \
137 int32_t PepperUMAHost::OnHistogramCustomTimes(
138 ppapi::host::HostMessageContext
* context
,
139 const std::string
& name
,
143 uint32_t bucket_count
) {
144 if (!IsHistogramAllowed(name
)) {
145 return PP_ERROR_NOACCESS
;
147 RETURN_IF_BAD_ARGS(min
, max
, bucket_count
);
149 base::HistogramBase
* counter
= base::Histogram::FactoryTimeGet(
151 base::TimeDelta::FromMilliseconds(min
),
152 base::TimeDelta::FromMilliseconds(max
),
154 base::HistogramBase::kUmaTargetedHistogramFlag
);
155 // The histogram can be NULL if it is constructed with bad arguments. Ignore
156 // that data for this API. An error message will be logged.
158 counter
->AddTime(base::TimeDelta::FromMilliseconds(sample
));
162 int32_t PepperUMAHost::OnHistogramCustomCounts(
163 ppapi::host::HostMessageContext
* context
,
164 const std::string
& name
,
168 uint32_t bucket_count
) {
169 if (!IsHistogramAllowed(name
)) {
170 return PP_ERROR_NOACCESS
;
172 RETURN_IF_BAD_ARGS(min
, max
, bucket_count
);
174 base::HistogramBase
* counter
= base::Histogram::FactoryGet(
179 base::HistogramBase::kUmaTargetedHistogramFlag
);
180 // The histogram can be NULL if it is constructed with bad arguments. Ignore
181 // that data for this API. An error message will be logged.
183 counter
->Add(sample
);
187 int32_t PepperUMAHost::OnHistogramEnumeration(
188 ppapi::host::HostMessageContext
* context
,
189 const std::string
& name
,
191 int32_t boundary_value
) {
192 if (!IsHistogramAllowed(name
)) {
193 return PP_ERROR_NOACCESS
;
195 RETURN_IF_BAD_ARGS(0, boundary_value
, boundary_value
+ 1);
197 base::HistogramBase
* counter
= base::LinearHistogram::FactoryGet(
202 base::HistogramBase::kUmaTargetedHistogramFlag
);
203 // The histogram can be NULL if it is constructed with bad arguments. Ignore
204 // that data for this API. An error message will be logged.
206 counter
->Add(sample
);
210 int32_t PepperUMAHost::OnIsCrashReportingEnabled(
211 ppapi::host::HostMessageContext
* context
) {
212 if (!IsPluginWhitelisted())
213 return PP_ERROR_NOACCESS
;
214 bool enabled
= false;
215 content::RenderThread::Get()->Send(
216 new ChromeViewHostMsg_IsCrashReportingEnabled(&enabled
));
219 return PP_ERROR_FAILED
;