diff options
-rw-r--r-- | chrome/browser/extensions/extension_apitest.cc | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_function_dispatcher.cc | 16 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_metrics_apitest.cc | 152 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_metrics_module.cc | 153 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_metrics_module.h | 65 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 1 | ||||
-rwxr-xr-x | chrome/common/extensions/api/extension_api.json | 105 | ||||
-rw-r--r-- | chrome/renderer/resources/renderer_extension_bindings.js | 1 | ||||
-rw-r--r-- | chrome/test/data/extensions/api_test/metrics/manifest.json | 6 | ||||
-rw-r--r-- | chrome/test/data/extensions/api_test/metrics/test.html | 1 | ||||
-rw-r--r-- | chrome/test/data/extensions/api_test/metrics/test.js | 62 | ||||
-rw-r--r-- | chrome/test/test_launcher/out_of_proc_test_runner.cc | 10 | ||||
-rw-r--r-- | chrome_frame/chrome_launcher.cc | 1 |
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, |