summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrogerta@chromium.org <rogerta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-26 18:08:43 +0000
committerrogerta@chromium.org <rogerta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-26 18:08:43 +0000
commit438772df5a7055847d061d49a8c18e6fc77daedb (patch)
treec748b7ff544f07d888a6978cac99c7c1b5d261b6
parent46ef2ce78952914d3723b07aae28b024a1e8a6ad (diff)
downloadchromium_src-438772df5a7055847d061d49a8c18e6fc77daedb.zip
chromium_src-438772df5a7055847d061d49a8c18e6fc77daedb.tar.gz
chromium_src-438772df5a7055847d061d49a8c18e6fc77daedb.tar.bz2
Add a metrics extensions API.
See http://docs.google.com/View?id=dd4ngnpz_0dpsb8n96 for API proposal. BUG=0 TEST=See unit tests as part of this CL Review URL: http://codereview.chromium.org/657037 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40130 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_apitest.cc4
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc16
-rw-r--r--chrome/browser/extensions/extension_metrics_apitest.cc152
-rw-r--r--chrome/browser/extensions/extension_metrics_module.cc153
-rw-r--r--chrome/browser/extensions/extension_metrics_module.h65
-rwxr-xr-xchrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/chrome_switches.cc3
-rw-r--r--chrome/common/chrome_switches.h1
-rwxr-xr-xchrome/common/extensions/api/extension_api.json105
-rw-r--r--chrome/renderer/resources/renderer_extension_bindings.js1
-rw-r--r--chrome/test/data/extensions/api_test/metrics/manifest.json6
-rw-r--r--chrome/test/data/extensions/api_test/metrics/test.html1
-rw-r--r--chrome/test/data/extensions/api_test/metrics/test.js62
-rw-r--r--chrome/test/test_launcher/out_of_proc_test_runner.cc10
-rw-r--r--chrome_frame/chrome_launcher.cc1
16 files changed, 581 insertions, 2 deletions
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc
index 25eff22..e5a0768 100644
--- a/chrome/browser/extensions/extension_apitest.cc
+++ b/chrome/browser/extensions/extension_apitest.cc
@@ -7,6 +7,7 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/profile.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/test/ui_test_utils.h"
@@ -103,4 +104,7 @@ Extension* ExtensionApiTest::GetSingleLoadedExtension() {
void ExtensionApiTest::SetUpCommandLine(CommandLine* command_line) {
ExtensionBrowserTest::SetUpCommandLine(command_line);
test_data_dir_ = test_data_dir_.AppendASCII("api_test");
+
+ // Needed for metrics extension API tests.
+ command_line->AppendSwitch(switches::kEnableMetricsExtensionApi);
}
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index 35b73a5..8f868eb 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/extensions/extension_history_api.h"
#include "chrome/browser/extensions/extension_i18n_api.h"
#include "chrome/browser/extensions/extension_message_service.h"
+#include "chrome/browser/extensions/extension_metrics_module.h"
#include "chrome/browser/extensions/extension_page_actions_module.h"
#include "chrome/browser/extensions/extension_page_actions_module_constants.h"
#include "chrome/browser/extensions/extension_popup_api.h"
@@ -34,6 +35,7 @@
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/result_codes.h"
#include "chrome/common/url_constants.h"
@@ -169,6 +171,20 @@ void FactoryRegistry::ResetFunctions() {
// Processes.
RegisterFunction<GetProcessForTabFunction>();
+ // Metrics.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableMetricsExtensionApi)) {
+ RegisterFunction<MetricsRecordUserActionFunction>();
+ RegisterFunction<MetricsRecordValueFunction>();
+ RegisterFunction<MetricsRecordPercentageFunction>();
+ RegisterFunction<MetricsRecordCountFunction>();
+ RegisterFunction<MetricsRecordSmallCountFunction>();
+ RegisterFunction<MetricsRecordMediumCountFunction>();
+ RegisterFunction<MetricsRecordTimeFunction>();
+ RegisterFunction<MetricsRecordMediumTimeFunction>();
+ RegisterFunction<MetricsRecordLongTimeFunction>();
+ }
+
// Test.
RegisterFunction<ExtensionTestPassFunction>();
RegisterFunction<ExtensionTestFailFunction>();
diff --git a/chrome/browser/extensions/extension_metrics_apitest.cc b/chrome/browser/extensions/extension_metrics_apitest.cc
new file mode 100644
index 0000000..39d342a
--- /dev/null
+++ b/chrome/browser/extensions/extension_metrics_apitest.cc
@@ -0,0 +1,152 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <map>
+
+#include "base/histogram.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/notification_registrar.h"
+
+namespace {
+
+// The tests that are run by this extension are expected to record the following
+// user actions, with the specified counts. If the tests in test.js are
+// modified, this array may need to be updated.
+struct RecordedUserAction {
+ const char* name; // base name of metric without extension id.
+ int count; // number of times the metric was recorded.
+} g_user_actions[] = {
+ {"test.ua.1", 1},
+ {"test.ua.2", 2},
+};
+
+// The tests that are run by this extension are expected to record the following
+// histograms. If the tests in test.js are modified, this array may need to be
+// updated.
+struct RecordedHistogram {
+ const char* name; // base name of metric without extension id.
+ Histogram::ClassType type;
+ int min;
+ int max;
+ size_t buckets;
+} g_histograms[] = {
+ {"test.h.1", Histogram::HISTOGRAM, 1, 100, 50}, // custom
+ {"test.h.2", Histogram::LINEAR_HISTOGRAM, 1, 200, 50}, // custom
+ {"test.h.3", Histogram::LINEAR_HISTOGRAM, 1, 101, 102}, // percentage
+ {"test.time", Histogram::HISTOGRAM, 1, 10000, 50},
+ {"test.medium.time", Histogram::HISTOGRAM, 1, 180000, 50},
+ {"test.long.time", Histogram::HISTOGRAM, 1, 3600000, 50},
+ {"test.count", Histogram::HISTOGRAM, 1, 1000000, 50},
+ {"test.medium.count", Histogram::HISTOGRAM, 1, 10000, 50},
+ {"test.small.count", Histogram::HISTOGRAM, 1, 100, 50},
+};
+
+// Build the full name of a metrics for the given extension. Each metric
+// is made up of the unique name within the extension followed by the
+// extension's id.
+std::string BuildFullName(const std::string& name, const Extension* extension) {
+ std::string full_name(name);
+ full_name += extension->id();
+ return full_name;
+}
+
+// This class observes and collects user action notifications that are sent
+// by the tests, so that they can be examined afterwards for correctness.
+class UserActionObserver : public NotificationObserver {
+ public:
+ UserActionObserver();
+
+ void ValidateUserActions(const Extension* extension,
+ const RecordedUserAction* recorded,
+ int count);
+
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ private:
+ typedef std::map<std::string, int> UserActionCountMap;
+
+ int num_metrics() const {
+ return count_map_.size();
+ }
+
+ int GetMetricCount(const std::string& name) const {
+ UserActionCountMap::const_iterator i = count_map_.find(name);
+ return i == count_map_.end() ? -1 : i->second;
+ }
+
+ NotificationRegistrar registrar_;
+ UserActionCountMap count_map_;
+};
+
+UserActionObserver::UserActionObserver() {
+ registrar_.Add(this, NotificationType::USER_ACTION,
+ NotificationService::AllSources());
+}
+
+void UserActionObserver::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ const char* name = *Details<const char*>(details).ptr();
+ ++(count_map_[name]);
+}
+
+void UserActionObserver::ValidateUserActions(const Extension* extension,
+ const RecordedUserAction* recorded,
+ int count) {
+ EXPECT_EQ(count, num_metrics());
+
+ for (int i = 0; i < count; ++i) {
+ const RecordedUserAction& ua = recorded[i];
+ EXPECT_EQ(ua.count, GetMetricCount(BuildFullName(ua.name, extension)));
+ }
+}
+
+void ValidateHistograms(const Extension* extension,
+ const RecordedHistogram* recorded,
+ int count) {
+ StatisticsRecorder::Histograms histograms;
+ StatisticsRecorder::GetHistograms(&histograms);
+
+ // Code other than the tests tun here will record some histogram values, but
+ // we will ignore those. This function validates that all the histogram we
+ // expect to see are present in the list, and that their basic info is
+ // correct.
+ for (int i = 0; i < count; ++i) {
+ const RecordedHistogram& r = recorded[i];
+ std::string name(BuildFullName(r.name, extension));
+
+ size_t j = 0;
+ for (j = 0; j < histograms.size(); ++j) {
+ scoped_refptr<Histogram> histogram(histograms[j]);
+
+ if (name == histogram->histogram_name()) {
+ EXPECT_EQ(r.type, histogram->histogram_type());
+ EXPECT_EQ(r.min, histogram->declared_min());
+ EXPECT_EQ(r.max, histogram->declared_max());
+ EXPECT_EQ(r.buckets, histogram->bucket_count());
+ break;
+ }
+ }
+ EXPECT_LT(j, histograms.size());
+ }
+}
+
+} // anonymous namespace
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Metrics) {
+ UserActionObserver observer;
+
+ ASSERT_TRUE(RunExtensionTest("metrics")) << message_;
+ Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(extension);
+
+ observer.ValidateUserActions(extension,
+ g_user_actions,
+ arraysize(g_user_actions));
+ ValidateHistograms(extension, g_histograms, arraysize(g_histograms));
+}
diff --git a/chrome/browser/extensions/extension_metrics_module.cc b/chrome/browser/extensions/extension_metrics_module.cc
new file mode 100644
index 0000000..30db486
--- /dev/null
+++ b/chrome/browser/extensions/extension_metrics_module.cc
@@ -0,0 +1,153 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_metrics_module.h"
+
+#include "base/histogram.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/browser/metrics/user_metrics.h"
+
+namespace {
+
+// Build the full name of a metrics for the given extension. Each metric
+// is made up of the unique name within the extension followed by the
+// extension's id. This keeps the metrics from one extension unique from
+// other extensions, as well as those metrics from chrome itself.
+std::string BuildMetricName(const std::string& name,
+ const Extension* extension) {
+ std::string full_name(name);
+ full_name += extension->id();
+ return full_name;
+}
+
+} // anonymous namespace
+
+// These extension function classes are enabled only if the
+// enable-metrics-extension-api command line switch is used. Refer to
+// extension_function_dispatcher.cc to see how they are enabled.
+
+bool MetricsRecordUserActionFunction::RunImpl() {
+ std::string name;
+ EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_STRING));
+ EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&name));
+
+ name = BuildMetricName(name, GetExtension());
+ UserMetrics::RecordComputedAction(name, profile());
+ return true;
+}
+
+bool MetricsHistogramHelperFunction::GetNameAndSample(std::string* name,
+ int* sample) {
+ EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
+ const ListValue* args = args_as_list();
+
+ EXTENSION_FUNCTION_VALIDATE(args->GetString(0, name));
+ EXTENSION_FUNCTION_VALIDATE(args->GetInteger(1, sample));
+ return true;
+}
+
+bool MetricsHistogramHelperFunction::RecordValue(const std::string& name,
+ Histogram::ClassType type,
+ int min,
+ int max,
+ size_t buckets,
+ int sample) {
+ std::string full_name = BuildMetricName(name, GetExtension());
+ scoped_refptr<Histogram> counter;
+ if (type == Histogram::LINEAR_HISTOGRAM) {
+ counter = LinearHistogram::FactoryGet(full_name,
+ min,
+ max,
+ buckets,
+ Histogram::kUmaTargetedHistogramFlag);
+ } else {
+ counter = Histogram::FactoryGet(full_name,
+ min,
+ max,
+ buckets,
+ Histogram::kUmaTargetedHistogramFlag);
+ }
+
+ counter->Add(sample);
+ return true;
+}
+
+bool MetricsRecordValueFunction::RunImpl() {
+ EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
+ const ListValue* args = args_as_list();
+
+ int sample;
+ EXTENSION_FUNCTION_VALIDATE(args->GetInteger(1, &sample));
+
+ // Get the histogram parameters from the metric type object.
+ DictionaryValue* metric_type;
+ EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(0, &metric_type));
+
+ std::string name;
+ std::string type;
+ int min;
+ int max;
+ int buckets;
+ EXTENSION_FUNCTION_VALIDATE(metric_type->GetString(L"metricName", &name));
+ EXTENSION_FUNCTION_VALIDATE(metric_type->GetString(L"type", &type));
+ EXTENSION_FUNCTION_VALIDATE(metric_type->GetInteger(L"min", &min));
+ EXTENSION_FUNCTION_VALIDATE(metric_type->GetInteger(L"max", &max));
+ EXTENSION_FUNCTION_VALIDATE(metric_type->GetInteger(L"buckets", &buckets));
+
+ Histogram::ClassType histogram_type(type == "histogram-linear" ?
+ Histogram::LINEAR_HISTOGRAM : Histogram::HISTOGRAM);
+ return RecordValue(name, histogram_type, min, max, buckets, sample);
+}
+
+bool MetricsRecordPercentageFunction::RunImpl() {
+ std::string name;
+ int sample;
+ EXTENSION_FUNCTION_VALIDATE(GetNameAndSample(&name, &sample));
+ return RecordValue(name, Histogram::LINEAR_HISTOGRAM, 1, 101, 102, sample);
+}
+
+bool MetricsRecordCountFunction::RunImpl() {
+ std::string name;
+ int sample;
+ EXTENSION_FUNCTION_VALIDATE(GetNameAndSample(&name, &sample));
+ return RecordValue(name, Histogram::HISTOGRAM, 1, 1000000, 50, sample);
+}
+
+bool MetricsRecordSmallCountFunction::RunImpl() {
+ std::string name;
+ int sample;
+ EXTENSION_FUNCTION_VALIDATE(GetNameAndSample(&name, &sample));
+ return RecordValue(name, Histogram::HISTOGRAM, 1, 100, 50, sample);
+}
+
+bool MetricsRecordMediumCountFunction::RunImpl() {
+ std::string name;
+ int sample;
+ EXTENSION_FUNCTION_VALIDATE(GetNameAndSample(&name, &sample));
+ return RecordValue(name, Histogram::HISTOGRAM, 1, 10000, 50, sample);
+}
+
+bool MetricsRecordTimeFunction::RunImpl() {
+ std::string name;
+ int sample;
+ EXTENSION_FUNCTION_VALIDATE(GetNameAndSample(&name, &sample));
+ static const int kTenSecMs = 10 * 1000;
+ return RecordValue(name, Histogram::HISTOGRAM, 1, kTenSecMs, 50, sample);
+}
+
+bool MetricsRecordMediumTimeFunction::RunImpl() {
+ std::string name;
+ int sample;
+ EXTENSION_FUNCTION_VALIDATE(GetNameAndSample(&name, &sample));
+ static const int kThreeMinMs = 3 * 60 * 1000;
+ return RecordValue(name, Histogram::HISTOGRAM, 1, kThreeMinMs, 50, sample);
+}
+
+bool MetricsRecordLongTimeFunction::RunImpl() {
+ std::string name;
+ int sample;
+ EXTENSION_FUNCTION_VALIDATE(GetNameAndSample(&name, &sample));
+ static const int kOneHourMs = 60 * 60 * 1000;
+ return RecordValue(name, Histogram::HISTOGRAM, 1, kOneHourMs, 50, sample);
+}
diff --git a/chrome/browser/extensions/extension_metrics_module.h b/chrome/browser/extensions/extension_metrics_module.h
new file mode 100644
index 0000000..c2ffdd2
--- /dev/null
+++ b/chrome/browser/extensions/extension_metrics_module.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_METRICS_MODULE_H__
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_METRICS_MODULE_H__
+
+#include <string>
+
+#include "base/histogram.h"
+#include "chrome/browser/extensions/extension_function.h"
+
+class MetricsRecordUserActionFunction : public SyncExtensionFunction {
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME("metrics.recordUserAction")
+};
+
+class MetricsHistogramHelperFunction : public SyncExtensionFunction {
+ protected:
+ bool GetNameAndSample(std::string* name, int* sample);
+ virtual bool RecordValue(const std::string& name, Histogram::ClassType type,
+ int min, int max, size_t buckets, int sample);
+};
+
+class MetricsRecordValueFunction : public MetricsHistogramHelperFunction {
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME("metrics.recordValue")
+};
+
+class MetricsRecordPercentageFunction : public MetricsHistogramHelperFunction {
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME("metrics.recordPercentage")
+};
+
+class MetricsRecordCountFunction : public MetricsHistogramHelperFunction {
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME("metrics.recordCount")
+};
+
+class MetricsRecordSmallCountFunction : public MetricsHistogramHelperFunction {
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME("metrics.recordSmallCount")
+};
+
+class MetricsRecordMediumCountFunction : public MetricsHistogramHelperFunction {
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME("metrics.recordMediumCount")
+};
+
+class MetricsRecordTimeFunction : public MetricsHistogramHelperFunction {
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME("metrics.recordTime")
+};
+
+class MetricsRecordMediumTimeFunction : public MetricsHistogramHelperFunction {
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME("metrics.recordMediumTime")
+};
+
+class MetricsRecordLongTimeFunction : public MetricsHistogramHelperFunction {
+ virtual bool RunImpl();
+ DECLARE_EXTENSION_FUNCTION_NAME("metrics.recordLongTime")
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_METRICS_MODULE_H__
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index b90d4ca..0616843 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -880,6 +880,8 @@
'browser/extensions/extension_install_ui.h',
'browser/extensions/extension_message_service.cc',
'browser/extensions/extension_message_service.h',
+ 'browser/extensions/extension_metrics_module.cc',
+ 'browser/extensions/extension_metrics_module.h',
'browser/extensions/extension_page_actions_module.cc',
'browser/extensions/extension_page_actions_module.h',
'browser/extensions/extension_page_actions_module_constants.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 9a506e0..6685622 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1160,6 +1160,7 @@
'browser/extensions/extension_javascript_url_apitest.cc',
'browser/extensions/extension_management_tests.cc',
'browser/extensions/extension_messages_apitest.cc',
+ 'browser/extensions/extension_metrics_apitest.cc',
'browser/extensions/extension_override_apitest.cc',
'browser/extensions/extension_processes_apitest.cc',
'browser/extensions/extension_startup_unittest.cc',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 7d16f0e..29e22c4 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -207,6 +207,9 @@ const char kEnableBenchmarking[] = "enable-benchmarking";
const char kEnableExperimentalExtensionApis[] =
"enable-experimental-extension-apis";
+// Enable metrics extension API.
+const char kEnableMetricsExtensionApi[] = "enable-metrics-extension-api";
+
// Enable experimental WebGL support.
const char kEnableExperimentalWebGL[] = "enable-webgl";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 89aa2b0..5ab8178 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -74,6 +74,7 @@ extern const char kDomAutomationController[];
extern const char kDumpHistogramsOnExit[];
extern const char kEnableBenchmarking[];
extern const char kEnableExperimentalExtensionApis[];
+extern const char kEnableMetricsExtensionApi[];
extern const char kEnableExperimentalWebGL[];
extern const char kEnableExtensionApps[];
extern const char kEnableExtensionTimelineApi[];
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 58894e4..cf28b4f 100755
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -2256,6 +2256,111 @@
"events": []
},
{
+ "namespace": "metrics",
+ "types": [
+ {
+ "id": "MetricType",
+ "type": "object",
+ "description": "Describes the type of metric that is to be collected.",
+ "properties": {
+ "metricName": {"type": "string", "description": "A unique name within the extension for the metric."},
+ "type": {
+ "type": "string",
+ "enum": ["histogram-log", "histogram-linear"],
+ "description": "The type of metric, such as 'histogram-log' or 'histogram-linear'."
+ },
+ "min": {"type": "integer", "description": "The minimum sample value to be recoded. Must be greater than zero."},
+ "max": {"type": "integer", "description": "The maximum sample value to be recoded."},
+ "buckets": {"type": "integer", "description": "The number of buckets to use when separating the recorded values."}
+ }
+ }
+ ],
+ "functions": [
+ {
+ "name": "recordUserAction",
+ "type": "function",
+ "description": "Records an action performed by the user.",
+ "parameters": [
+ {"name": "name", "type": "string"}
+ ]
+ },
+ {
+ "name": "recordPercentage",
+ "type": "function",
+ "description": "Record a percentage value from 1 to 100.",
+ "parameters": [
+ {"name": "metricName", "type": "string"},
+ {"name": "value", "type": "integer"}
+ ]
+ },
+ {
+ "name": "recordCount",
+ "type": "function",
+ "description": "Record a value than can range from 1 to 1,000,000.",
+ "parameters": [
+ {"name": "metricName", "type": "string"},
+ {"name": "value", "type": "integer"}
+ ]
+ },
+ {
+ "name": "recordSmallCount",
+ "type": "function",
+ "description": "Record a value than can range from 1 to 100.",
+ "parameters": [
+ {"name": "metricName", "type": "string"},
+ {"name": "value", "type": "integer"}
+ ]
+ },
+ {
+ "name": "recordMediumCount",
+ "type": "function",
+ "description": "Record a value than can range from 1 to 10,000.",
+ "parameters": [
+ {"name": "metricName", "type": "string"},
+ {"name": "value", "type": "integer"}
+ ]
+ },
+ {
+ "name": "recordTime",
+ "type": "function",
+ "description": "Record an elapsed time of no more than 10 seconds. The sample value is specified in milliseconds.",
+ "parameters": [
+ {"name": "metricName", "type": "string"},
+ {"name": "value", "type": "integer"}
+ ]
+ },
+ {
+ "name": "recordMediumTime",
+ "type": "function",
+ "description": "Record an elapsed time of no more than 3 minutes. The sample value is specified in milliseconds.",
+ "parameters": [
+ {"name": "metricName", "type": "string"},
+ {"name": "value", "type": "integer"}
+ ]
+ },
+ {
+ "name": "recordLongTime",
+ "type": "function",
+ "description": "Record an elapsed time of no more than 1 hour. The sample value is specified in milliseconds.",
+ "parameters": [
+ {"name": "metricName", "type": "string"},
+ {"name": "value", "type": "integer"}
+ ]
+ },
+ {
+ "name": "recordValue",
+ "type": "function",
+ "unprivileged": true,
+ "description": "Adds a value to the given metric.",
+ "parameters": [
+ {"name": "metric", "$ref": "MetricType"},
+ {"name": "value", "type": "integer"}
+ ]
+ }
+ ],
+ "events": []
+ },
+ {
"namespace": "test",
"nodoc": true,
"types": [],
diff --git a/chrome/renderer/resources/renderer_extension_bindings.js b/chrome/renderer/resources/renderer_extension_bindings.js
index c063a32..1c69ffa 100644
--- a/chrome/renderer/resources/renderer_extension_bindings.js
+++ b/chrome/renderer/resources/renderer_extension_bindings.js
@@ -250,6 +250,7 @@ var chrome = chrome || {};
"experimental.history",
"experimental.popup",
"experimental.processes",
+ "metrics",
"pageAction",
"pageActions",
"tabs",
diff --git a/chrome/test/data/extensions/api_test/metrics/manifest.json b/chrome/test/data/extensions/api_test/metrics/manifest.json
new file mode 100644
index 0000000..1c45fbd
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/metrics/manifest.json
@@ -0,0 +1,6 @@
+{
+ "name": "chrome.metrics",
+ "version": "0.1",
+ "description": "end-to-end browser test for chrome.metrics API",
+ "background_page": "test.html"
+}
diff --git a/chrome/test/data/extensions/api_test/metrics/test.html b/chrome/test/data/extensions/api_test/metrics/test.html
new file mode 100644
index 0000000..46f4d74
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/metrics/test.html
@@ -0,0 +1 @@
+<script src="test.js"></script>
diff --git a/chrome/test/data/extensions/api_test/metrics/test.js b/chrome/test/data/extensions/api_test/metrics/test.js
new file mode 100644
index 0000000..2de7ba4
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/metrics/test.js
@@ -0,0 +1,62 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// metrics api test
+// browser_tests.exe --gtest_filter=ExtensionApiTest.Metrics
+
+// Any changes to the logging done in these functions should be matched
+// with the checks done in IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Metrics).
+// See extension_metrics_apitest.cc.
+chrome.test.runTests([
+ function recordUserAction() {
+ // Log a metric once.
+ chrome.metrics.recordUserAction('test.ua.1');
+
+ // Log a metric more than once.
+ chrome.metrics.recordUserAction('test.ua.2');
+ chrome.metrics.recordUserAction('test.ua.2');
+
+ chrome.test.succeed();
+ },
+
+ function recordValue() {
+ chrome.metrics.recordValue({
+ 'metricName': 'test.h.1',
+ 'type': 'histogram-log',
+ 'min': 1,
+ 'max': 100,
+ 'buckets': 50
+ }, 42);
+
+ chrome.metrics.recordValue({
+ 'metricName': 'test.h.2',
+ 'type': 'histogram-linear',
+ 'min': 1,
+ 'max': 200,
+ 'buckets': 50
+ }, 42);
+
+ chrome.metrics.recordPercentage('test.h.3', 42);
+ chrome.metrics.recordPercentage('test.h.3', 42);
+
+ chrome.test.succeed();
+ },
+
+ function recordTimes() {
+ chrome.metrics.recordTime('test.time', 42);
+ chrome.metrics.recordMediumTime('test.medium.time', 42 * 1000);
+ chrome.metrics.recordLongTime('test.long.time', 42 * 1000 * 60);
+
+ chrome.test.succeed();
+ },
+
+ function recordCounts() {
+ chrome.metrics.recordCount('test.count', 420000);
+ chrome.metrics.recordMediumCount('test.medium.count', 4200);
+ chrome.metrics.recordSmallCount('test.small.count', 42);
+
+ chrome.test.succeed();
+ }
+]);
+
diff --git a/chrome/test/test_launcher/out_of_proc_test_runner.cc b/chrome/test/test_launcher/out_of_proc_test_runner.cc
index 32fb66c..98bdeca 100644
--- a/chrome/test/test_launcher/out_of_proc_test_runner.cc
+++ b/chrome/test/test_launcher/out_of_proc_test_runner.cc
@@ -84,7 +84,7 @@ class OutOfProcTestRunnerFactory : public tests::TestRunnerFactory {
void PrintUsage() {
fprintf(stdout, "Runs tests using the gtest framework, each test being run in"
" its own process.\nAny gtest flags can be specified.\n"
- " --single-process\n Runs the tests and the launcher in the same "
+ " --single_process\n Runs the tests and the launcher in the same "
"process. Useful for debugging a\n specific test in a debugger\n "
"--help\n Shows this message.\n --gtest_help\n Shows the gtest "
"help message\n");
@@ -101,6 +101,12 @@ int main(int argc, char** argv) {
return 0;
}
+ if (command_line->HasSwitch(kSingleProcessFlag)) {
+ fprintf(stdout,
+ "\n Did you mean --%s instead? (note underscore)\n\n",
+ kSingleProcessAltFlag);
+ }
+
if (command_line->HasSwitch(kChildProcessFlag) ||
command_line->HasSwitch(kSingleProcessFlag) ||
command_line->HasSwitch(kSingleProcessAltFlag) ||
@@ -112,7 +118,7 @@ int main(int argc, char** argv) {
fprintf(stdout,
"Starting tests...\nIMPORTANT DEBUGGING NOTE: each test is run inside"
" its own process.\nFor debugging a test inside a debugger, use the "
- "--single-process and\n--gtest_filter=<your_test_name> flags.\n");
+ "--single_process and\n--gtest_filter=<your_test_name> flags.\n");
OutOfProcTestRunnerFactory test_runner_factory;
return tests::RunTests(test_runner_factory) ? 0 : 1;
}
diff --git a/chrome_frame/chrome_launcher.cc b/chrome_frame/chrome_launcher.cc
index ef20826..c5c43ef 100644
--- a/chrome_frame/chrome_launcher.cc
+++ b/chrome_frame/chrome_launcher.cc
@@ -25,6 +25,7 @@ const char* kAllowedSwitches[] = {
switches::kDisableMetrics,
switches::kEnableRendererAccessibility,
switches::kEnableExperimentalExtensionApis,
+ switches::kEnableMetricsExtensionApi,
switches::kNoErrorDialogs,
switches::kNoFirstRun,
switches::kUserDataDir,