Commit 6b1ff066 authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS MultiDevice] Update Instant Tethering item (multi-device subpage).

Before this CL, the multi-device settings displayed Instant Tethering
settings using exactly the same mechanism used by the network settings.
However, this is undesirable because (1) it does not display the
"prohibited" icon when a device administrator prohibits the feature and
(2) it does not display the correct text as a label for the item.

This CL changes the settings subpage to use the same infrastructure as
the rest of the features. As a result, this also requires that
TetherService be updated; previously, TetherService was responsible for
changing the "enabled" user pref itself, but now it needs to support that
mode as well as responding to changes of the "enabled" pref.

Bug: 896324, 884830
Change-Id: I083a8e8e07725130058db35ee540dd6ad733d421
Reviewed-on: https://chromium-review.googlesource.com/c/1297594Reviewed-by: default avatarTommy Li <tommycli@chromium.org>
Reviewed-by: default avatarJeremy Klein <jlklein@chromium.org>
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#602199}
parent 538e9529
...@@ -174,10 +174,14 @@ TetherService::TetherService( ...@@ -174,10 +174,14 @@ TetherService::TetherService(
} }
} }
registrar_.Init(profile_->GetPrefs()); if (!base::FeatureList::IsEnabled(
registrar_.Add(chromeos::multidevice_setup::kInstantTetheringAllowedPrefName, chromeos::features::kEnableUnifiedMultiDeviceSetup)) {
base::BindRepeating(&TetherService::OnPrefsChanged, registrar_.Init(profile_->GetPrefs());
weak_ptr_factory_.GetWeakPtr())); registrar_.Add(
chromeos::multidevice_setup::kInstantTetheringAllowedPrefName,
base::BindRepeating(&TetherService::OnPrefsChanged,
weak_ptr_factory_.GetWeakPtr()));
}
UMA_HISTOGRAM_BOOLEAN("InstantTethering.UserPreference.OnStartup", UMA_HISTOGRAM_BOOLEAN("InstantTethering.UserPreference.OnStartup",
IsEnabledByPreference()); IsEnabledByPreference());
...@@ -309,9 +313,14 @@ void TetherService::Shutdown() { ...@@ -309,9 +313,14 @@ void TetherService::Shutdown() {
multidevice_setup_client_->RemoveObserver(this); multidevice_setup_client_->RemoveObserver(this);
} }
} }
if (adapter_) if (adapter_)
adapter_->RemoveObserver(this); adapter_->RemoveObserver(this);
registrar_.RemoveAll();
if (!base::FeatureList::IsEnabled(
chromeos::features::kEnableUnifiedMultiDeviceSetup)) {
registrar_.RemoveAll();
}
// Shut down the feature. Note that this does not change Tether's technology // Shut down the feature. Note that this does not change Tether's technology
// state in NetworkStateHandler because doing so could cause visual jank just // state in NetworkStateHandler because doing so could cause visual jank just
...@@ -408,13 +417,12 @@ void TetherService::UpdateEnabledState() { ...@@ -408,13 +417,12 @@ void TetherService::UpdateEnabledState() {
profile_->GetPrefs()->SetBoolean( profile_->GetPrefs()->SetBoolean(
chromeos::multidevice_setup::kInstantTetheringEnabledPrefName, chromeos::multidevice_setup::kInstantTetheringEnabledPrefName,
is_enabled); is_enabled);
LogUserPreferenceChanged(is_enabled);
UpdateTetherTechnologyState();
} }
} else {
UMA_HISTOGRAM_BOOLEAN("InstantTethering.UserPreference.OnToggle", UpdateTetherTechnologyState();
is_enabled);
PA_LOG(INFO) << "Tether user preference changed. New value: " << is_enabled;
} }
UpdateTetherTechnologyState();
} }
void TetherService::OnShutdownComplete() { void TetherService::OnShutdownComplete() {
...@@ -446,6 +454,23 @@ void TetherService::OnReady() { ...@@ -446,6 +454,23 @@ void TetherService::OnReady() {
void TetherService::OnFeatureStatesChanged( void TetherService::OnFeatureStatesChanged(
const chromeos::multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& const chromeos::multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
feature_states_map) { feature_states_map) {
const chromeos::multidevice_setup::mojom::FeatureState new_state =
feature_states_map
.find(chromeos::multidevice_setup::mojom::Feature::kInstantTethering)
->second;
// If the feature changed from enabled to disabled or vice-versa, log the
// associated metric.
if (new_state ==
chromeos::multidevice_setup::mojom::FeatureState::kEnabledByUser &&
previous_feature_state_ == TetherFeatureState::USER_PREFERENCE_DISABLED) {
LogUserPreferenceChanged(true /* is_now_enabled */);
} else if (new_state == chromeos::multidevice_setup::mojom::FeatureState::
kDisabledByUser &&
previous_feature_state_ == TetherFeatureState::ENABLED) {
LogUserPreferenceChanged(false /* is_now_enabled */);
}
if (adapter_) if (adapter_)
UpdateTetherTechnologyState(); UpdateTetherTechnologyState();
else else
...@@ -792,6 +817,13 @@ bool TetherService::HandleFeatureStateMetricIfUninitialized() { ...@@ -792,6 +817,13 @@ bool TetherService::HandleFeatureStateMetricIfUninitialized() {
return true; return true;
} }
void TetherService::LogUserPreferenceChanged(bool is_now_enabled) {
UMA_HISTOGRAM_BOOLEAN("InstantTethering.UserPreference.OnToggle",
is_now_enabled);
PA_LOG(INFO) << "Tether user preference changed. New value: "
<< is_now_enabled;
}
void TetherService::SetTestDoubles( void TetherService::SetTestDoubles(
std::unique_ptr<chromeos::tether::NotificationPresenter> std::unique_ptr<chromeos::tether::NotificationPresenter>
notification_presenter, notification_presenter,
......
...@@ -182,7 +182,10 @@ class TetherService ...@@ -182,7 +182,10 @@ class TetherService
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestCellularIsAvailable); FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestCellularIsAvailable);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestDisabled); FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestDisabled);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestEnabled); FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestEnabled);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestEnabled_MultiDeviceFlags); FRIEND_TEST_ALL_PREFIXES(TetherServiceTest,
TestUserPrefChangesViaFeatureStateChange);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest,
TestUserPrefChangesViaTechnologyStateChange);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestBluetoothNotification); FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestBluetoothNotification);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestBluetoothNotPresent); FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestBluetoothNotPresent);
FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestMetricsFalsePositives); FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestMetricsFalsePositives);
...@@ -260,6 +263,8 @@ class TetherService ...@@ -260,6 +263,8 @@ class TetherService
// are ephemeral. Returns whether a false positive case was handled. // are ephemeral. Returns whether a false positive case was handled.
bool HandleFeatureStateMetricIfUninitialized(); bool HandleFeatureStateMetricIfUninitialized();
void LogUserPreferenceChanged(bool is_now_enabled);
void SetTestDoubles(std::unique_ptr<chromeos::tether::NotificationPresenter> void SetTestDoubles(std::unique_ptr<chromeos::tether::NotificationPresenter>
notification_presenter, notification_presenter,
std::unique_ptr<base::OneShotTimer> timer); std::unique_ptr<base::OneShotTimer> timer);
......
...@@ -1327,7 +1327,69 @@ TEST_F(TetherServiceTest, TestEnabled) { ...@@ -1327,7 +1327,69 @@ TEST_F(TetherServiceTest, TestEnabled) {
chromeos::tether::TetherComponent::ShutdownReason::PREF_DISABLED); chromeos::tether::TetherComponent::ShutdownReason::PREF_DISABLED);
} }
TEST_F(TetherServiceTest, TestEnabled_MultiDeviceFlags) { TEST_F(TetherServiceTest, TestUserPrefChangesViaFeatureStateChange) {
// Start with the feature disabled.
initial_feature_state_ =
chromeos::multidevice_setup::mojom::FeatureState::kDisabledByUser;
profile_->GetPrefs()->SetBoolean(
chromeos::multidevice_setup::kInstantTetheringEnabledPrefName, false);
CreateTetherService(true /* enable_multidevice_apis */);
// Enable the feature.
profile_->GetPrefs()->SetBoolean(
chromeos::multidevice_setup::kInstantTetheringEnabledPrefName, true);
fake_multidevice_setup_client_->SetFeatureState(
chromeos::multidevice_setup::mojom::Feature::kInstantTethering,
chromeos::multidevice_setup::mojom::FeatureState::kEnabledByUser);
EXPECT_EQ(chromeos::NetworkStateHandler::TechnologyState::TECHNOLOGY_ENABLED,
network_state_handler()->GetTechnologyState(
chromeos::NetworkTypePattern::Tether()));
VerifyTetherActiveStatus(true /* expected_active */);
VerifyTetherFeatureStateRecorded(TetherService::TetherFeatureState::ENABLED,
1 /* expected_count */);
histogram_tester_.ExpectBucketCount(
"InstantTethering.UserPreference.OnToggle", true,
1u /* expected_count */);
// Disable the feature.
profile_->GetPrefs()->SetBoolean(
chromeos::multidevice_setup::kInstantTetheringEnabledPrefName, false);
fake_multidevice_setup_client_->SetFeatureState(
chromeos::multidevice_setup::mojom::Feature::kInstantTethering,
chromeos::multidevice_setup::mojom::FeatureState::kDisabledByUser);
EXPECT_EQ(
chromeos::NetworkStateHandler::TechnologyState::TECHNOLOGY_AVAILABLE,
network_state_handler()->GetTechnologyState(
chromeos::NetworkTypePattern::Tether()));
VerifyTetherActiveStatus(false /* expected_active */);
VerifyTetherFeatureStateRecorded(
TetherService::TetherFeatureState::USER_PREFERENCE_DISABLED,
2 /* expected_count */);
histogram_tester_.ExpectBucketCount(
"InstantTethering.UserPreference.OnToggle", false,
1u /* expected_count */);
// Enable the feature.
profile_->GetPrefs()->SetBoolean(
chromeos::multidevice_setup::kInstantTetheringEnabledPrefName, true);
fake_multidevice_setup_client_->SetFeatureState(
chromeos::multidevice_setup::mojom::Feature::kInstantTethering,
chromeos::multidevice_setup::mojom::FeatureState::kEnabledByUser);
EXPECT_EQ(chromeos::NetworkStateHandler::TechnologyState::TECHNOLOGY_ENABLED,
network_state_handler()->GetTechnologyState(
chromeos::NetworkTypePattern::Tether()));
VerifyTetherActiveStatus(true /* expected_active */);
VerifyTetherFeatureStateRecorded(TetherService::TetherFeatureState::ENABLED,
2 /* expected_count */);
histogram_tester_.ExpectBucketCount(
"InstantTethering.UserPreference.OnToggle", true,
2u /* expected_count */);
VerifyLastShutdownReason(
chromeos::tether::TetherComponent::ShutdownReason::PREF_DISABLED);
}
TEST_F(TetherServiceTest, TestUserPrefChangesViaTechnologyStateChange) {
CreateTetherService(true /* enable_multidevice_apis */); CreateTetherService(true /* enable_multidevice_apis */);
EXPECT_EQ(chromeos::NetworkStateHandler::TechnologyState::TECHNOLOGY_ENABLED, EXPECT_EQ(chromeos::NetworkStateHandler::TechnologyState::TECHNOLOGY_ENABLED,
......
...@@ -98,6 +98,8 @@ js_library("multidevice_subpage") { ...@@ -98,6 +98,8 @@ js_library("multidevice_subpage") {
js_library("multidevice_tether_item") { js_library("multidevice_tether_item") {
deps = [ deps = [
":multidevice_feature_behavior",
"..:route",
"//ui/webui/resources/cr_elements/chromeos/network:cr_onc_types", "//ui/webui/resources/cr_elements/chromeos/network:cr_onc_types",
] ]
externs_list = [ "$externs_path/networking_private.js" ] externs_list = [ "$externs_path/networking_private.js" ]
......
...@@ -134,6 +134,8 @@ const MultiDeviceFeatureBehaviorImpl = { ...@@ -134,6 +134,8 @@ const MultiDeviceFeatureBehaviorImpl = {
switch (feature) { switch (feature) {
case settings.MultiDeviceFeature.SMART_LOCK: case settings.MultiDeviceFeature.SMART_LOCK:
return this.i18nAdvanced('multideviceSmartLockItemSummary'); return this.i18nAdvanced('multideviceSmartLockItemSummary');
case settings.MultiDeviceFeature.INSTANT_TETHERING:
return this.i18nAdvanced('multideviceInstantTetheringItemSummary');
case settings.MultiDeviceFeature.MESSAGES: case settings.MultiDeviceFeature.MESSAGES:
return this.i18nAdvanced('multideviceAndroidMessagesItemSummary'); return this.i18nAdvanced('multideviceAndroidMessagesItemSummary');
default: default:
......
...@@ -33,8 +33,10 @@ ...@@ -33,8 +33,10 @@
class="settings-box two-line" class="settings-box two-line"
on-click="handleItemClick_" on-click="handleItemClick_"
actionable$="[[hasSubpageClickHandler_( actionable$="[[hasSubpageClickHandler_(
subpageRoute, pageContentData, feature)]]"> feature, pageContentData, subpageRoute)]]">
<iron-icon icon="[[getIconName(feature)]]"></iron-icon> <slot name="icon">
<iron-icon icon="[[getIconName(feature)]]"></iron-icon>
</slot>
<div id="item-text-container" class="middle"> <div id="item-text-container" class="middle">
<div id="featureName">[[getFeatureName(feature)]]</div> <div id="featureName">[[getFeatureName(feature)]]</div>
<div class="secondary" <div class="secondary"
...@@ -44,7 +46,7 @@ ...@@ -44,7 +46,7 @@
</div> </div>
<template is="dom-if" <template is="dom-if"
if="[[hasSubpageClickHandler_( if="[[hasSubpageClickHandler_(
subpageRoute, pageContentData, feature)]]" feature, pageContentData, subpageRoute)]]"
restamp> restamp>
<paper-icon-button-light class="subpage-arrow"> <paper-icon-button-light class="subpage-arrow">
<button aria-labelledby="featureName" <button aria-labelledby="featureName"
......
...@@ -28,6 +28,13 @@ Polymer({ ...@@ -28,6 +28,13 @@ Polymer({
* @type {settings.Route|undefined} * @type {settings.Route|undefined}
*/ */
subpageRoute: Object, subpageRoute: Object,
/**
* URLSearchParams for subpage route. No param is provided if it is
* undefined.
* @type {URLSearchParams|undefined}
*/
subpageRouteUrlSearchParams: Object,
}, },
/** /**
...@@ -49,6 +56,6 @@ Polymer({ ...@@ -49,6 +56,6 @@ Polymer({
return; return;
} }
settings.navigateTo(this.subpageRoute); settings.navigateTo(this.subpageRoute, this.subpageRouteUrlSearchParams);
}, },
}); });
...@@ -73,7 +73,8 @@ ...@@ -73,7 +73,8 @@
if="[[isFeatureSupported( if="[[isFeatureSupported(
MultiDeviceFeature.INSTANT_TETHERING, pageContentData)]]" MultiDeviceFeature.INSTANT_TETHERING, pageContentData)]]"
restamp> restamp>
<settings-multidevice-tether-item id="instantTetheringItem"> <settings-multidevice-tether-item id="instantTetheringItem"
page-content-data="[[pageContentData]]">
</settings-multidevice-tether-item> </settings-multidevice-tether-item>
</template> </template>
<template is="dom-if" <template is="dom-if"
......
...@@ -18,7 +18,10 @@ Polymer({ ...@@ -18,7 +18,10 @@ Polymer({
], ],
properties: { properties: {
/** @type {?SettingsRoutes} */ /**
* Alias for allowing Polymer bindings to settings.routes.
* @type {?SettingsRoutes}
*/
routes: { routes: {
type: Object, type: Object,
value: settings.routes, value: settings.routes,
...@@ -61,16 +64,6 @@ Polymer({ ...@@ -61,16 +64,6 @@ Polymer({
this.browserProxy_.setUpAndroidSms(); this.browserProxy_.setUpAndroidSms();
}, },
listeners: {
'show-networks': 'onShowNetworks_',
},
onShowNetworks_: function() {
settings.navigateTo(
settings.routes.INTERNET_NETWORKS,
new URLSearchParams('type=' + CrOnc.Type.TETHER));
},
/** /**
* @return {boolean} * @return {boolean}
* @private * @private
......
<link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html"> <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.html"> <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html">
<link rel="import" href="../i18n_setup.html"> <link rel="import" href="../i18n_setup.html">
<link rel="import" href="../internet_page/network_summary_item.html"> <link rel="import" href="../route.html">
<link rel="import" href="../settings_shared_css.html"> <link rel="import" href="../settings_shared_css.html">
<link rel="import" href="../settings_vars_css.html"> <link rel="import" href="../settings_vars_css.html">
<link rel="import" href="multidevice_feature_behavior.html">
<link rel="import" href="multidevice_feature_item.html">
<dom-module id="settings-multidevice-tether-item"> <dom-module id="settings-multidevice-tether-item">
<style include="settings-shared"> <style include="settings-shared">
network-summary-item {
--network-summary-item-outer-box: {
padding: var(--feature-item-row-padding);
};
--network-summary-item-title: {
color: var(--cr-primary-text-color);
font-weight: 400;
};
}
</style> </style>
<template> <template>
<network-summary-item id="networkSummaryItem" <settings-multidevice-feature-item page-content-data="[[pageContentData]]"
active-network-state="[[activeNetworkState_]]" feature="[[MultiDeviceFeature.INSTANT_TETHERING]]"
device-state="[[deviceState_]]" subpage-route="[[routes.INTERNET_NETWORKS]]"
network-state-list="[[getNetworkStateList_(activeNetworkState_)]]" subpage-route-url-search-params=
networking-private="[[networkingPrivate]]" "[[getTetherNetworkUrlSearchParams_()]]">
tether-device-state="[[deviceState_]]" <cr-network-icon slot="icon"
network-title-text="$i18n{multideviceInstantTetheringItemTitle}"> network-state="[[activeNetworkState_]]"
</network-summary-item> device-state="[[deviceState_]]">
</cr-network-icon>
</settings-multidevice-feature-item>
</template> </template>
<script src="multidevice_tether_item.js"></script> <script src="multidevice_tether_item.js"></script>
</dom-module> </dom-module>
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
Polymer({ Polymer({
is: 'settings-multidevice-tether-item', is: 'settings-multidevice-tether-item',
behaviors: [MultiDeviceFeatureBehavior],
properties: { properties: {
/** /**
* Interface for networkingPrivate calls. * Interface for networkingPrivate calls.
...@@ -37,10 +39,18 @@ Polymer({ ...@@ -37,10 +39,18 @@ Polymer({
* @private {?CrOnc.NetworkStateProperties|undefined} * @private {?CrOnc.NetworkStateProperties|undefined}
*/ */
activeNetworkState_: Object, activeNetworkState_: Object,
/**
* Alias for allowing Polymer bindings to settings.routes.
* @type {?SettingsRoutes}
*/
routes: {
type: Object,
value: settings.routes,
},
}, },
listeners: { listeners: {
'device-enabled-toggled': 'onDeviceEnabledToggled_',
'network-list-changed': 'updateTetherNetworkState_', 'network-list-changed': 'updateTetherNetworkState_',
// network-changed is fired by the settings-multidevice-subpage element's // network-changed is fired by the settings-multidevice-subpage element's
// CrNetworkListenerBehavior. // CrNetworkListenerBehavior.
...@@ -104,18 +114,6 @@ Polymer({ ...@@ -104,18 +114,6 @@ Polymer({
}); });
}, },
/**
* Event triggered by a device state enabled toggle.
* @param {!{detail: {enabled: boolean, type: CrOnc.Type}}} event
* @private
*/
onDeviceEnabledToggled_: function(event) {
if (event.detail.enabled)
this.networkingPrivate_.enableNetworkType(CrOnc.Type.TETHER);
else
this.networkingPrivate_.disableNetworkType(CrOnc.Type.TETHER);
},
/** /**
* Retrieves device states (CrOnc.DeviceStateProperties) and sets * Retrieves device states (CrOnc.DeviceStateProperties) and sets
* this.deviceState_ to the retrieved Instant Tethering state (or undefined if * this.deviceState_ to the retrieved Instant Tethering state (or undefined if
...@@ -160,4 +158,12 @@ Polymer({ ...@@ -160,4 +158,12 @@ Polymer({
getNetworkStateList_: function() { getNetworkStateList_: function() {
return this.activeNetworkState_.GUID ? [this.activeNetworkState_] : []; return this.activeNetworkState_.GUID ? [this.activeNetworkState_] : [];
}, },
/**
* @return {!URLSearchParams}
* @private
*/
getTetherNetworkUrlSearchParams_: function() {
return new URLSearchParams('type=' + CrOnc.Type.TETHER);
},
}); });
...@@ -2722,6 +2722,8 @@ void AddMultideviceStrings(content::WebUIDataSource* html_source) { ...@@ -2722,6 +2722,8 @@ void AddMultideviceStrings(content::WebUIDataSource* html_source) {
{"multideviceSmartLockItemTitle", IDS_SETTINGS_EASY_UNLOCK_SECTION_TITLE}, {"multideviceSmartLockItemTitle", IDS_SETTINGS_EASY_UNLOCK_SECTION_TITLE},
{"multideviceInstantTetheringItemTitle", {"multideviceInstantTetheringItemTitle",
IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING}, IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING},
{"multideviceInstantTetheringItemSummary",
IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING_SUMMARY},
{"multideviceAndroidMessagesItemTitle", {"multideviceAndroidMessagesItemTitle",
IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES}, IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES},
{"multideviceForgetDevice", IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE}, {"multideviceForgetDevice", IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE},
......
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