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_switches.h"
11 #include "chrome/common/render_messages.h"
12 #include "chrome/renderer/chrome_content_renderer_client.h"
13 #include "content/public/renderer/pepper_plugin_instance.h"
14 #include "content/public/renderer/render_thread.h"
15 #include "content/public/renderer/renderer_ppapi_host.h"
16 #include "extensions/common/constants.h"
17 #include "extensions/common/extension.h"
18 #include "ppapi/c/pp_errors.h"
19 #include "ppapi/host/dispatch_host_message.h"
20 #include "ppapi/host/host_message_context.h"
21 #include "ppapi/host/ppapi_host.h"
22 #include "ppapi/proxy/ppapi_messages.h"
24 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
28 const char* const kPredefinedAllowedUMAOrigins
[] = {
29 "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", // see http://crbug.com/317833
30 "4EB74897CB187C7633357C2FE832E0AD6A44883A" // see http://crbug.com/317833
33 const char* const kWhitelistedHistogramPrefixes
[] = {
34 "22F67DA2061FFC4DC9A4974036348D9C38C22919" // see http://crbug.com/390221
37 const char* const kWhitelistedPluginBaseNames
[] = {
38 #if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
39 kWidevineCdmAdapterFileName
, // see http://crbug.com/368743
40 // and http://crbug.com/410630
42 "libpdf.so" // see http://crbug.com/405305
45 std::string
HashPrefix(const std::string
& histogram
) {
46 const std::string id_hash
=
47 base::SHA1HashString(histogram
.substr(0, histogram
.find('.')));
48 DCHECK_EQ(id_hash
.length(), base::kSHA1Length
);
49 return base::HexEncode(id_hash
.c_str(), id_hash
.length());
54 PepperUMAHost::PepperUMAHost(content::RendererPpapiHost
* host
,
57 : ResourceHost(host
->GetPpapiHost(), instance
, resource
),
58 document_url_(host
->GetDocumentURL(instance
)),
59 is_plugin_in_process_(host
->IsRunningInProcess()) {
60 if (host
->GetPluginInstance(instance
)) {
62 host
->GetPluginInstance(instance
)->GetModulePath().BaseName();
65 for (size_t i
= 0; i
< arraysize(kPredefinedAllowedUMAOrigins
); ++i
)
66 allowed_origins_
.insert(kPredefinedAllowedUMAOrigins
[i
]);
67 for (size_t i
= 0; i
< arraysize(kWhitelistedHistogramPrefixes
); ++i
)
68 allowed_histogram_prefixes_
.insert(kWhitelistedHistogramPrefixes
[i
]);
69 for (size_t i
= 0; i
< arraysize(kWhitelistedPluginBaseNames
); ++i
)
70 allowed_plugin_base_names_
.insert(kWhitelistedPluginBaseNames
[i
]);
73 PepperUMAHost::~PepperUMAHost() {}
75 int32_t PepperUMAHost::OnResourceMessageReceived(
76 const IPC::Message
& msg
,
77 ppapi::host::HostMessageContext
* context
) {
78 PPAPI_BEGIN_MESSAGE_MAP(PepperUMAHost
, msg
)
79 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramCustomTimes
,
80 OnHistogramCustomTimes
)
81 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramCustomCounts
,
82 OnHistogramCustomCounts
)
83 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramEnumeration
,
84 OnHistogramEnumeration
)
85 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
86 PpapiHostMsg_UMA_IsCrashReportingEnabled
, OnIsCrashReportingEnabled
)
87 PPAPI_END_MESSAGE_MAP()
88 return PP_ERROR_FAILED
;
91 bool PepperUMAHost::IsPluginWhitelisted() {
92 #if defined(ENABLE_EXTENSIONS)
93 return ChromeContentRendererClient::IsExtensionOrSharedModuleWhitelisted(
94 document_url_
, allowed_origins_
);
100 bool PepperUMAHost::IsHistogramAllowed(const std::string
& histogram
) {
101 if (is_plugin_in_process_
&& histogram
.find("NaCl.") == 0) {
105 if (IsPluginWhitelisted() &&
106 allowed_histogram_prefixes_
.find(HashPrefix(histogram
)) !=
107 allowed_histogram_prefixes_
.end()) {
111 if (allowed_plugin_base_names_
.find(plugin_base_name_
.MaybeAsASCII()) !=
112 allowed_plugin_base_names_
.end()) {
116 LOG(ERROR
) << "Host or histogram name is not allowed to use the UMA API.";
120 #define RETURN_IF_BAD_ARGS(_min, _max, _buckets) \
122 if (_min >= _max || _buckets <= 1) \
123 return PP_ERROR_BADARGUMENT; \
126 int32_t PepperUMAHost::OnHistogramCustomTimes(
127 ppapi::host::HostMessageContext
* context
,
128 const std::string
& name
,
132 uint32_t bucket_count
) {
133 if (!IsHistogramAllowed(name
)) {
134 return PP_ERROR_NOACCESS
;
136 RETURN_IF_BAD_ARGS(min
, max
, bucket_count
);
138 base::HistogramBase
* counter
= base::Histogram::FactoryTimeGet(
140 base::TimeDelta::FromMilliseconds(min
),
141 base::TimeDelta::FromMilliseconds(max
),
143 base::HistogramBase::kUmaTargetedHistogramFlag
);
144 // The histogram can be NULL if it is constructed with bad arguments. Ignore
145 // that data for this API. An error message will be logged.
147 counter
->AddTime(base::TimeDelta::FromMilliseconds(sample
));
151 int32_t PepperUMAHost::OnHistogramCustomCounts(
152 ppapi::host::HostMessageContext
* context
,
153 const std::string
& name
,
157 uint32_t bucket_count
) {
158 if (!IsHistogramAllowed(name
)) {
159 return PP_ERROR_NOACCESS
;
161 RETURN_IF_BAD_ARGS(min
, max
, bucket_count
);
163 base::HistogramBase
* counter
= base::Histogram::FactoryGet(
168 base::HistogramBase::kUmaTargetedHistogramFlag
);
169 // The histogram can be NULL if it is constructed with bad arguments. Ignore
170 // that data for this API. An error message will be logged.
172 counter
->Add(sample
);
176 int32_t PepperUMAHost::OnHistogramEnumeration(
177 ppapi::host::HostMessageContext
* context
,
178 const std::string
& name
,
180 int32_t boundary_value
) {
181 if (!IsHistogramAllowed(name
)) {
182 return PP_ERROR_NOACCESS
;
184 RETURN_IF_BAD_ARGS(0, boundary_value
, boundary_value
+ 1);
186 base::HistogramBase
* counter
= base::LinearHistogram::FactoryGet(
191 base::HistogramBase::kUmaTargetedHistogramFlag
);
192 // The histogram can be NULL if it is constructed with bad arguments. Ignore
193 // that data for this API. An error message will be logged.
195 counter
->Add(sample
);
199 int32_t PepperUMAHost::OnIsCrashReportingEnabled(
200 ppapi::host::HostMessageContext
* context
) {
201 if (!IsPluginWhitelisted())
202 return PP_ERROR_NOACCESS
;
203 bool enabled
= false;
204 content::RenderThread::Get()->Send(
205 new ChromeViewHostMsg_IsCrashReportingEnabled(&enabled
));
208 return PP_ERROR_FAILED
;