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. 4 5 #include "chrome/browser/extensions/api/metrics_private/metrics_private_api.h" 6 7 #include <algorithm> 8 9 #include "base/metrics/field_trial.h" 10 #include "base/metrics/histogram.h" 11 #include "base/metrics/sparse_histogram.h" 12 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" 13 #include "chrome/common/extensions/api/metrics_private.h" 14 #include "components/variations/variations_associated_data.h" 15 #include "content/public/browser/user_metrics.h" 16 #include "extensions/common/extension.h" 17 18 namespace extensions { 19 20 namespace GetIsCrashReportingEnabled = 21 api::metrics_private::GetIsCrashReportingEnabled; 22 namespace GetVariationParams = api::metrics_private::GetVariationParams; 23 namespace GetFieldTrial = api::metrics_private::GetFieldTrial; 24 namespace RecordUserAction = api::metrics_private::RecordUserAction; 25 namespace RecordValue = api::metrics_private::RecordValue; 26 namespace RecordSparseValue = api::metrics_private::RecordSparseValue; 27 namespace RecordPercentage = api::metrics_private::RecordPercentage; 28 namespace RecordCount = api::metrics_private::RecordCount; 29 namespace RecordSmallCount = api::metrics_private::RecordSmallCount; 30 namespace RecordMediumCount = api::metrics_private::RecordMediumCount; 31 namespace RecordTime = api::metrics_private::RecordTime; 32 namespace RecordMediumTime = api::metrics_private::RecordMediumTime; 33 namespace RecordLongTime = api::metrics_private::RecordLongTime; 34 35 namespace { 36 37 const size_t kMaxBuckets = 10000; // We don't ever want more than these many 38 // buckets; there is no real need for them 39 // and would cause crazy memory usage 40 } // namespace 41 42 bool MetricsPrivateGetIsCrashReportingEnabledFunction::RunSync() { 43 SetResult(new base::FundamentalValue( 44 ChromeMetricsServiceAccessor::IsCrashReportingEnabled())); 45 return true; 46 } 47 48 bool MetricsPrivateGetFieldTrialFunction::RunSync() { 49 std::string name; 50 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &name)); 51 52 SetResult(new base::StringValue(base::FieldTrialList::FindFullName(name))); 53 return true; 54 } 55 56 bool MetricsPrivateGetVariationParamsFunction::RunSync() { 57 scoped_ptr<GetVariationParams::Params> params( 58 GetVariationParams::Params::Create(*args_)); 59 EXTENSION_FUNCTION_VALIDATE(params.get()); 60 61 GetVariationParams::Results::Params result; 62 if (variations::GetVariationParams(params->name, 63 &result.additional_properties)) { 64 SetResult(result.ToValue().release()); 65 } 66 return true; 67 } 68 69 bool MetricsPrivateRecordUserActionFunction::RunSync() { 70 scoped_ptr<RecordUserAction::Params> params( 71 RecordUserAction::Params::Create(*args_)); 72 EXTENSION_FUNCTION_VALIDATE(params.get()); 73 74 content::RecordComputedAction(params->name); 75 return true; 76 } 77 78 bool MetricsHistogramHelperFunction::RecordValue( 79 const std::string& name, 80 base::HistogramType type, 81 int min, int max, size_t buckets, 82 int sample) { 83 // Make sure toxic values don't get to internal code. 84 // Fix for maximums 85 min = std::min(min, INT_MAX - 3); 86 max = std::min(max, INT_MAX - 3); 87 buckets = std::min(buckets, kMaxBuckets); 88 // Fix for minimums. 89 min = std::max(min, 1); 90 max = std::max(max, min + 1); 91 buckets = std::max(buckets, static_cast<size_t>(3)); 92 // Trim buckets down to a maximum of the given range + over/underflow buckets 93 if (buckets > static_cast<size_t>(max - min + 2)) 94 buckets = max - min + 2; 95 96 base::HistogramBase* counter; 97 if (type == base::LINEAR_HISTOGRAM) { 98 counter = base::LinearHistogram::FactoryGet( 99 name, min, max, buckets, 100 base::HistogramBase::kUmaTargetedHistogramFlag); 101 } else { 102 counter = base::Histogram::FactoryGet( 103 name, min, max, buckets, 104 base::HistogramBase::kUmaTargetedHistogramFlag); 105 } 106 107 // The histogram can be NULL if it is constructed with bad arguments. Ignore 108 // that data for this API. An error message will be logged. 109 if (counter) 110 counter->Add(sample); 111 return true; 112 } 113 114 bool MetricsPrivateRecordValueFunction::RunSync() { 115 scoped_ptr<RecordValue::Params> params(RecordValue::Params::Create(*args_)); 116 EXTENSION_FUNCTION_VALIDATE(params.get()); 117 118 // Get the histogram parameters from the metric type object. 119 std::string type = api::metrics_private::MetricType::ToString( 120 params->metric.type); 121 122 base::HistogramType histogram_type(type == "histogram-linear" ? 123 base::LINEAR_HISTOGRAM : base::HISTOGRAM); 124 return RecordValue(params->metric.metric_name, histogram_type, 125 params->metric.min, params->metric.max, 126 params->metric.buckets, params->value); 127 } 128 129 bool MetricsPrivateRecordSparseValueFunction::RunSync() { 130 scoped_ptr<RecordSparseValue::Params> params( 131 RecordSparseValue::Params::Create(*args_)); 132 EXTENSION_FUNCTION_VALIDATE(params.get()); 133 // This particular UMA_HISTOGRAM_ macro is okay for 134 // non-runtime-constant strings. 135 UMA_HISTOGRAM_SPARSE_SLOWLY(params->metric_name, params->value); 136 return true; 137 } 138 139 bool MetricsPrivateRecordPercentageFunction::RunSync() { 140 scoped_ptr<RecordPercentage::Params> params( 141 RecordPercentage::Params::Create(*args_)); 142 EXTENSION_FUNCTION_VALIDATE(params.get()); 143 return RecordValue(params->metric_name, base::LINEAR_HISTOGRAM, 144 1, 101, 102, params->value); 145 } 146 147 bool MetricsPrivateRecordCountFunction::RunSync() { 148 scoped_ptr<RecordCount::Params> params(RecordCount::Params::Create(*args_)); 149 EXTENSION_FUNCTION_VALIDATE(params.get()); 150 return RecordValue(params->metric_name, base::HISTOGRAM, 151 1, 1000000, 50, params->value); 152 } 153 154 bool MetricsPrivateRecordSmallCountFunction::RunSync() { 155 scoped_ptr<RecordSmallCount::Params> params( 156 RecordSmallCount::Params::Create(*args_)); 157 EXTENSION_FUNCTION_VALIDATE(params.get()); 158 return RecordValue(params->metric_name, base::HISTOGRAM, 159 1, 100, 50, params->value); 160 } 161 162 bool MetricsPrivateRecordMediumCountFunction::RunSync() { 163 scoped_ptr<RecordMediumCount::Params> params( 164 RecordMediumCount::Params::Create(*args_)); 165 EXTENSION_FUNCTION_VALIDATE(params.get()); 166 return RecordValue(params->metric_name, base::HISTOGRAM, 167 1, 10000, 50, params->value); 168 } 169 170 bool MetricsPrivateRecordTimeFunction::RunSync() { 171 scoped_ptr<RecordTime::Params> params(RecordTime::Params::Create(*args_)); 172 EXTENSION_FUNCTION_VALIDATE(params.get()); 173 static const int kTenSecMs = 10 * 1000; 174 return RecordValue(params->metric_name, base::HISTOGRAM, 175 1, kTenSecMs, 50, params->value); 176 } 177 178 bool MetricsPrivateRecordMediumTimeFunction::RunSync() { 179 scoped_ptr<RecordMediumTime::Params> params( 180 RecordMediumTime::Params::Create(*args_)); 181 EXTENSION_FUNCTION_VALIDATE(params.get()); 182 static const int kThreeMinMs = 3 * 60 * 1000; 183 return RecordValue(params->metric_name, base::HISTOGRAM, 184 1, kThreeMinMs, 50, params->value); 185 } 186 187 bool MetricsPrivateRecordLongTimeFunction::RunSync() { 188 scoped_ptr<RecordLongTime::Params> params( 189 RecordLongTime::Params::Create(*args_)); 190 EXTENSION_FUNCTION_VALIDATE(params.get()); 191 static const int kOneHourMs = 60 * 60 * 1000; 192 return RecordValue(params->metric_name, base::HISTOGRAM, 193 1, kOneHourMs, 50, params->value); 194 } 195 196 } // namespace extensions 197