Commit ef1b8e1c authored by Daniel Classon's avatar Daniel Classon Committed by Commit Bot

[OsSettingsMetrics] Add metric handling for pref based setting

Adds a new helper function that converts a (pref, prefValue) pair to
a (setting, settingChangeValue) pair that can be used to log metrics.
Uses this helper function to automatically capture setting changes
for all pref based settings. As a first example, implements metrics
for the kKeyboardFunctionKeys on the Device page.

Bug:  1133553

Change-Id: Ia1f0118e27bb7e0f610bfe1d75ba0ef324260f7d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2459846
Commit-Queue: Daniel Classon <dclasson@google.com>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#816692}
parent e4c0cb8c
...@@ -196,6 +196,7 @@ group("closure_compile") { ...@@ -196,6 +196,7 @@ group("closure_compile") {
":os_page_visibility", ":os_page_visibility",
":os_route", ":os_route",
":os_settings_routes", ":os_settings_routes",
":pref_to_setting_metric_converter",
":route_origin_behavior", ":route_origin_behavior",
":search_handler", ":search_handler",
"ambient_mode_page:closure_compile", "ambient_mode_page:closure_compile",
...@@ -267,6 +268,10 @@ js_library("os_settings_routes") { ...@@ -267,6 +268,10 @@ js_library("os_settings_routes") {
] ]
} }
js_library("pref_to_setting_metric_converter") {
deps = [ "//chrome/browser/ui/webui/settings/chromeos/constants:mojom_js_library_for_compile" ]
}
js_library("route_origin_behavior") { js_library("route_origin_behavior") {
deps = [ deps = [
":os_route", ":os_route",
...@@ -343,6 +348,7 @@ js_type_check("closure_compile_local_module") { ...@@ -343,6 +348,7 @@ js_type_check("closure_compile_local_module") {
# ":os_settings.m", # ":os_settings.m",
# ":os_settings_icons_css.m", # ":os_settings_icons_css.m",
":os_settings_routes.m", ":os_settings_routes.m",
":pref_to_setting_metric_converter.m",
":route_origin_behavior.m", ":route_origin_behavior.m",
#":search_handler.m", #":search_handler.m",
...@@ -411,6 +417,12 @@ js_library("os_settings_routes.m") { ...@@ -411,6 +417,12 @@ js_library("os_settings_routes.m") {
extra_deps = [ ":modulize" ] extra_deps = [ ":modulize" ]
} }
js_library("pref_to_setting_metric_converter.m") {
sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/pref_to_setting_metric_converter.m.js" ]
deps = [ "//chrome/browser/ui/webui/settings/chromeos/constants:mojom_js_library_for_compile" ]
extra_deps = [ ":modulize" ]
}
js_library("route_origin_behavior.m") { js_library("route_origin_behavior.m") {
sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/route_origin_behavior.m.js" ] sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/route_origin_behavior.m.js" ]
deps = [ deps = [
...@@ -497,13 +509,14 @@ polymer_modulizer("os_settings_icons_css") { ...@@ -497,13 +509,14 @@ polymer_modulizer("os_settings_icons_css") {
js_modulizer("modulize") { js_modulizer("modulize") {
input_files = [ input_files = [
"deep_linking_behavior.js",
"metrics_recorder.js", "metrics_recorder.js",
"os_settings_routes.js", "os_settings_routes.js",
"route_origin_behavior.js", "route_origin_behavior.js",
"search_handler.js", "search_handler.js",
"os_route.js", "os_route.js",
"os_page_visibility.js", "os_page_visibility.js",
"deep_linking_behavior.js", "pref_to_setting_metric_converter.js",
] ]
namespace_rewrites = os_settings_namespace_rewrites namespace_rewrites = os_settings_namespace_rewrites
} }
...@@ -623,6 +623,11 @@ ...@@ -623,6 +623,11 @@
file="page_visibility.js" file="page_visibility.js"
preprocess="true" preprocess="true"
compress="false" type="BINDATA" /> compress="false" type="BINDATA" />
<include name="IDR_OS_SETTINGS_PREF_TO_SETTING_METRIC_CONVERTER_M_JS"
file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/pref_to_setting_metric_converter.m.js"
use_base_dir="false"
compress="false"
type="BINDATA" />
<include name="IDR_OS_SETTINGS_MULTIDEVICE_PAGE_M_JS" <include name="IDR_OS_SETTINGS_MULTIDEVICE_PAGE_M_JS"
file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.m.js" file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.m.js"
use_base_dir="false" use_base_dir="false"
......
...@@ -13,6 +13,7 @@ js_library("os_settings_ui") { ...@@ -13,6 +13,7 @@ js_library("os_settings_ui") {
"..:metrics_recorder", "..:metrics_recorder",
"..:os_page_visibility", "..:os_page_visibility",
"..:os_route", "..:os_route",
"..:pref_to_setting_metric_converter",
"../..:global_scroll_target_behavior", "../..:global_scroll_target_behavior",
"../..:router", "../..:router",
"../../prefs", "../../prefs",
......
...@@ -16,10 +16,13 @@ ...@@ -16,10 +16,13 @@
<link rel="import" href="../../i18n_setup.html"> <link rel="import" href="../../i18n_setup.html">
<link rel="import" href="../../settings_shared_css.html"> <link rel="import" href="../../settings_shared_css.html">
<link rel="import" href="../os_page_visibility.html"> <link rel="import" href="../os_page_visibility.html">
<link rel="import" href="../pref_to_setting_metric_converter.html">
<link rel="import" href="../../prefs/prefs.html"> <link rel="import" href="../../prefs/prefs.html">
<link rel="import" href="../os_route.html"> <link rel="import" href="../os_route.html">
<link rel="import" href="../../router.html"> <link rel="import" href="../../router.html">
<link rel="import" href="../../settings_vars_css.html"> <link rel="import" href="../../settings_vars_css.html">
<script src="chrome://os-settings/constants/setting.mojom-lite.js"></script>
<script src="chrome://os-settings/search/user_action_recorder.mojom-lite.js"></script>
<dom-module id="os-settings-ui"> <dom-module id="os-settings-ui">
<template> <template>
......
...@@ -125,9 +125,16 @@ cr.define('settings', function() { ...@@ -125,9 +125,16 @@ cr.define('settings', function() {
*/ */
activeRoute_: null, activeRoute_: null,
/**
* Converts prefs to settings metrics to help record pref changes.
* @private {PrefToSettingMetricConverter}
*/
prefToSettingMetricConverter_: null,
/** @override */ /** @override */
created() { created() {
settings.Router.getInstance().initializeRouteFromUrl(); settings.Router.getInstance().initializeRouteFromUrl();
this.prefToSettingMetricConverter_ = new PrefToSettingMetricConverter();
}, },
/** /**
...@@ -350,10 +357,26 @@ cr.define('settings', function() { ...@@ -350,10 +357,26 @@ cr.define('settings', function() {
}, },
/** /**
* @param {!CustomEvent<!{prefKey: string, prefValue: *}>} e
* @private * @private
*/ */
onSettingChange_() { onSettingChange_(e) {
settings.recordSettingChange(); const {prefKey, prefValue} = e.detail;
const settingMetric =
this.prefToSettingMetricConverter_.convertPrefToSettingMetric(
prefKey, prefValue);
// New metrics for this setting pref have not yet been implemented.
if (!settingMetric) {
settings.recordSettingChange();
return;
}
const setting = /** @type {!chromeos.settings.mojom.Setting} */ (
settingMetric.setting);
const value = /** @type {!chromeos.settings.mojom.SettingChangeValue} */ (
settingMetric.value);
settings.recordSettingChange(setting, value);
}, },
/** /**
......
<script src="chrome://os-settings/constants/setting.mojom-lite.js"></script>
<script src="chrome://os-settings/search/user_action_recorder.mojom-lite.js"></script>
<script src="pref_to_setting_metric_converter.js"></script>
\ No newline at end of file
/* Copyright 2020 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. */
/**
* @fileoverview Helper class for converting a given settings pref to a pair of
* setting ID and setting change value. Used to record metrics about changes
* to pref-based settings.
*/
// clang-format off
// #import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'
// #import '../constants/setting.mojom-lite.js';
// #import '../search/user_action_recorder.mojom-lite.js';
// clang-format on
/* export */ class PrefToSettingMetricConverter {
/**
* @param {string} prefKey
* @param {*} prefValue
* @return {?{setting: !chromeos.settings.mojom.Setting, value:
* !chromeos.settings.mojom.SettingChangeValue}}
*/
convertPrefToSettingMetric(prefKey, prefValue) {
switch (prefKey) {
// device_page/keyboard.js
case 'settings.language.send_function_keys':
return {
setting: chromeos.settings.mojom.Setting.kKeyboardFunctionKeys,
value: {boolValue: /** @type {boolean} */ (prefValue)}
};
// pref to setting metric not implemented.
default:
return null;
}
}
}
...@@ -985,6 +985,12 @@ ...@@ -985,6 +985,12 @@
<structure name="IDR_OS_SETTINGS_OS_PAGE_VISIBILITY_JS" <structure name="IDR_OS_SETTINGS_OS_PAGE_VISIBILITY_JS"
file="chromeos/os_page_visibility.js" file="chromeos/os_page_visibility.js"
compress="false" type="chrome_html" /> compress="false" type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PREF_TO_SETTING_METRIC_CONVERTER_HTML"
file="chromeos/pref_to_setting_metric_converter.html"
compress="false" type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PREF_TO_SETTING_METRIC_CONVERTER_JS"
file="chromeos/pref_to_setting_metric_converter.js"
compress="false" type="chrome_html" />
<!-- TODO(jamescook): Remove after sync settings is forked. --> <!-- TODO(jamescook): Remove after sync settings is forked. -->
<structure name="IDR_OS_SETTINGS_PERSONALIZATION_OPTIONS_HTML" <structure name="IDR_OS_SETTINGS_PERSONALIZATION_OPTIONS_HTML"
file="privacy_page/personalization_options.html" file="privacy_page/personalization_options.html"
......
...@@ -213,7 +213,9 @@ Polymer({ ...@@ -213,7 +213,9 @@ Polymer({
// settingsPrivate.setPref and potentially trigger an IPC loop.) // settingsPrivate.setPref and potentially trigger an IPC loop.)
if (!deepEqual(prefStoreValue, prefObj.value)) { if (!deepEqual(prefStoreValue, prefObj.value)) {
// <if expr="chromeos"> // <if expr="chromeos">
this.fire('user-action-setting-change'); this.fire(
'user-action-setting-change',
{prefKey: key, prefValue: prefObj.value});
// </if> // </if>
this.settingsApi_.setPref( this.settingsApi_.setPref(
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "ash/public/cpp/stylus_utils.h" #include "ash/public/cpp/stylus_utils.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
...@@ -842,8 +843,15 @@ std::string DeviceSection::GetSectionPath() const { ...@@ -842,8 +843,15 @@ std::string DeviceSection::GetSectionPath() const {
bool DeviceSection::LogMetric(mojom::Setting setting, bool DeviceSection::LogMetric(mojom::Setting setting,
base::Value& value) const { base::Value& value) const {
// Unimplemented. switch (setting) {
return false; case mojom::Setting::kKeyboardFunctionKeys:
base::UmaHistogramBoolean("ChromeOS.Settings.Device.KeyboardFunctionKeys",
value.GetBool());
return true;
default:
return false;
}
} }
void DeviceSection::RegisterHierarchy(HierarchyGenerator* generator) const { void DeviceSection::RegisterHierarchy(HierarchyGenerator* generator) const {
......
...@@ -42,6 +42,8 @@ class SettingsUserActionTracker : public mojom::UserActionRecorder { ...@@ -42,6 +42,8 @@ class SettingsUserActionTracker : public mojom::UserActionRecorder {
TestRecordSettingChangedBool); TestRecordSettingChangedBool);
FRIEND_TEST_ALL_PREFIXES(SettingsUserActionTrackerTest, FRIEND_TEST_ALL_PREFIXES(SettingsUserActionTrackerTest,
TestRecordSettingChangedInt); TestRecordSettingChangedInt);
FRIEND_TEST_ALL_PREFIXES(SettingsUserActionTrackerTest,
TestRecordSettingChangedBoolPref);
// mojom::UserActionRecorder: // mojom::UserActionRecorder:
void RecordPageFocus() override; void RecordPageFocus() override;
......
...@@ -33,6 +33,8 @@ class SettingsUserActionTrackerTest : public testing::Test { ...@@ -33,6 +33,8 @@ class SettingsUserActionTrackerTest : public testing::Test {
void SetUp() override { void SetUp() override {
fake_hierarchy_.AddSettingMetadata(mojom::Section::kBluetooth, fake_hierarchy_.AddSettingMetadata(mojom::Section::kBluetooth,
mojom::Setting::kBluetoothOnOff); mojom::Setting::kBluetoothOnOff);
fake_hierarchy_.AddSettingMetadata(mojom::Section::kDevice,
mojom::Setting::kKeyboardFunctionKeys);
fake_hierarchy_.AddSettingMetadata(mojom::Section::kPeople, fake_hierarchy_.AddSettingMetadata(mojom::Section::kPeople,
mojom::Setting::kAddAccount); mojom::Setting::kAddAccount);
} }
...@@ -86,5 +88,29 @@ TEST_F(SettingsUserActionTrackerTest, TestRecordSettingChangedInt) { ...@@ -86,5 +88,29 @@ TEST_F(SettingsUserActionTrackerTest, TestRecordSettingChangedInt) {
mojom::Setting::kAddAccount); mojom::Setting::kAddAccount);
} }
TEST_F(SettingsUserActionTrackerTest, TestRecordSettingChangedBoolPref) {
// Record that the keyboard function keys setting was toggled off. This
// setting is controlled by a pref and uses the pref-to-setting-metric
// converter flow.
tracker_.RecordSettingChangeWithDetails(
mojom::Setting::kKeyboardFunctionKeys,
mojom::SettingChangeValue::NewBoolValue(false));
// The umbrella metric for which setting was changed should be updated. Note
// that kKeyboardFunctionKeys has enum value of 411.
histogram_tester_.ExpectTotalCount("ChromeOS.Settings.SettingChanged",
/*count=*/1);
histogram_tester_.ExpectBucketCount("ChromeOS.Settings.SettingChanged",
/*sample=*/411,
/*count=*/1);
// The LogMetric fn in the Device section should have been called.
const FakeOsSettingsSection* device_section =
static_cast<const FakeOsSettingsSection*>(
fake_sections_.GetSection(mojom::Section::kDevice));
EXPECT_TRUE(device_section->logged_metrics().back() ==
mojom::Setting::kKeyboardFunctionKeys);
}
} // namespace settings. } // namespace settings.
} // namespace chromeos. } // namespace chromeos.
...@@ -548,6 +548,17 @@ incoming reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -548,6 +548,17 @@ incoming reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary> </summary>
</histogram> </histogram>
<histogram name="ChromeOS.Settings.Device.KeyboardFunctionKeys"
enum="BooleanToggled" expires_after="2021-09-30">
<owner>khorimoto@chromium.org</owner>
<owner>hsuregan@chromium.org</owner>
<owner>cros-customization@google.com</owner>
<summary>
Records when a user changes the kKeyboardFunctionKeys setting on the Device
page.
</summary>
</histogram>
<histogram name="ChromeOS.Settings.Languages.Browser.Interaction" <histogram name="ChromeOS.Settings.Languages.Browser.Interaction"
enum="SettingsLanguagesPageBrowserInteraction" expires_after="2021-03-31"> enum="SettingsLanguagesPageBrowserInteraction" expires_after="2021-03-31">
<owner>myy@chromium.org</owner> <owner>myy@chromium.org</owner>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment