Skip to content

Commit

Permalink
[CrOS settings] Add subscription removal dialog
Browse files Browse the repository at this point in the history
Creates a dialog to inform the user that the removal of a Wi-Fi network
connected using Passpoint will also remove the subscription.

Bug: b:266150498
Change-Id: I5b3a2800212567705022f1b6f51873a7be41dbf9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4295374
Reviewed-by: Kyle Horimoto <khorimoto@chromium.org>
Reviewed-by: Xiaohui Chen <xiaohuic@chromium.org>
Commit-Queue: Damien Dejean <damiendejean@google.com>
Cr-Commit-Position: refs/heads/main@{#1115594}
  • Loading branch information
Damien Dejean authored and Chromium LUCI CQ committed Mar 10, 2023
1 parent 249a246 commit 08b9549
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 4 deletions.
6 changes: 6 additions & 0 deletions chrome/app/os_settings_strings.grdp
Original file line number Diff line number Diff line change
Expand Up @@ -3402,6 +3402,12 @@ Press an assigned switch or key to remove assignment.
<message name="IDS_SETTINGS_INTERNET_NETWORK_SECTION_NETWORK_ACCESSIBILITY_LABEL" desc="Label for the button that toggles showing the network address configuration settings. Only visible by screen reader software.">
Show network address settings
</message>
<message name="IDS_SETTINGS_INTERNET_NETWORK_SECTION_PASSPOINT_REMOVAL_TITLE" desc="Settings > Internet > Network details: Title of the Passpoint network removal dialog.">
Forget this subscription?
</message>
<message name="IDS_SETTINGS_INTERNET_NETWORK_SECTION_PASSPOINT_REMOVAL_DESCRIPTION" desc="Settings > Internet > Network details: Description of the Passpoint network removal dialog.">
By forgetting this network you will also remove the Passpoint subscription and its associated networks. <ph name="LINK_BEGIN">&lt;a&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
</message>
<message name="IDS_SETTINGS_INTERNET_NETWORK_SECTION_PROXY" desc="Settings > Internet > Network details: Proxy section label.">
Proxy
</message>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
95f5b4043a4c282b03f15f8b08ccfd8339fb911f
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
95f5b4043a4c282b03f15f8b08ccfd8339fb911f
Original file line number Diff line number Diff line change
Expand Up @@ -513,3 +513,28 @@
out-of-range="[[outOfRange_]]">
</tether-connection-dialog>
</template>
<template is="dom-if" if="[[isPasspointWifi_(managedProperties_)]]" restamp>
<!-- Passpoint subscription removal confirmation dialog -->
<cr-dialog id="passpointRemovalDialog" close-text="$i18n{close}">
<div slot="title">
$i18nPolymer{networkSectionPasspointRemovalTitle}
</div>
<div slot="body">
<localized-link
localized-string=
"$i18nPolymer{networkSectionPasspointRemovalDescription}"
link-url="$i18nRaw{wifiPasspointLearnMoreUrl}">
</localized-link>
</div>
<div slot="button-container">
<cr-button id="passpointRemovalCancelButton" class="cancel-button"
on-click="onPasspointRemovalDialogCancel_">
$i18n{cancel}
</cr-button>
<cr-button id="passpointRemovalConfirmButton" class="action-button"
on-click="onPasspointRemovalDialogConfirm_">
$i18n{confirm}
</cr-button>
</div>
</cr-dialog>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import {CrToggleElement} from 'chrome://resources/cr_elements/cr_toggle/cr_toggl
import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js';
import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {ActivationStateType, ApnProperties, ConfigProperties, CrosNetworkConfigRemote, GlobalPolicy, HiddenSsidMode, IPConfigProperties, ManagedProperties, NetworkStateProperties, ProxySettings, SecurityType, VpnType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js';
import {ActivationStateType, ApnProperties, ConfigProperties, CrosNetworkConfigRemote, GlobalPolicy, HiddenSsidMode, IPConfigProperties, ManagedProperties, MatchType, NetworkStateProperties, ProxySettings, SecurityType, VpnType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js';
import {ConnectionStateType, DeviceStateType, IPConfigType, NetworkType, OncSource, PolicySource, PortalState} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js';
import {afterNextRender, flush, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

Expand Down Expand Up @@ -298,6 +298,14 @@ class SettingsInternetDetailPageElement extends
},
},

isPasspointEnabled_: {
type: Boolean,
value() {
return loadTimeData.valueExists('isPasspointEnabled') &&
loadTimeData.getBoolean('isPasspointEnabled');
},
},

advancedExpanded_: Boolean,

networkExpanded_: Boolean,
Expand Down Expand Up @@ -371,6 +379,7 @@ class SettingsInternetDetailPageElement extends
private hiddenPref_: chrome.settingsPrivate.PrefObject<boolean>;
private ipAddress_: string;
private isApnRevampEnabled_: boolean;
private isPasspointEnabled_: boolean;
private isSecondaryUser_: boolean;
private isTrafficCountersEnabled_: boolean;
private isWifiSyncEnabled_: boolean;
Expand Down Expand Up @@ -1467,6 +1476,11 @@ class SettingsInternetDetailPageElement extends
'#tetherDialog'));
}

private getPasspointRemovalDialog_(): HTMLDialogElement {
return castExists(this.shadowRoot!.querySelector<HTMLDialogElement>(
'#passpointRemovalDialog'));
}

private handleConnectTap_(): void {
assertExists(this.managedProperties_);
if (this.managedProperties_.type === NetworkType.kTether &&
Expand Down Expand Up @@ -1557,6 +1571,16 @@ class SettingsInternetDetailPageElement extends
}

private async onForgetTap_(): Promise<void> {
if (this.isPasspointWifi_(this.managedProperties_)) {
// Ask user confirmation before removing a Passpoint Wi-Fi and the
// associated subscription.
this.getPasspointRemovalDialog_().showModal();
return;
}
return this.forgetNetwork_();
}

private async forgetNetwork_(): Promise<void> {
if (this.managedProperties_!.type === NetworkType.kWiFi) {
recordSettingChange(Setting.kForgetWifiNetwork);
} else {
Expand Down Expand Up @@ -2098,6 +2122,27 @@ class SettingsInternetDetailPageElement extends
return this.isRememberedOrConnected_(managedProperties);
}

private isPasspointWifi_(managedProperties: ManagedProperties|
undefined): boolean {
if (!this.isPasspointEnabled_) {
return false;
}
return !!managedProperties &&
managedProperties.type === NetworkType.kWiFi &&
managedProperties.typeProperties.wifi!.passpointId !== '' &&
managedProperties.typeProperties.wifi!.passpointMatchType !==
MatchType.kNoMatch;
}

private onPasspointRemovalDialogCancel_(): void {
this.getPasspointRemovalDialog_().close();
}

private onPasspointRemovalDialogConfirm_(): void {
this.getPasspointRemovalDialog_().close();
this.forgetNetwork_();
}

private showCellularChooseNetwork_(managedProperties: ManagedProperties):
boolean {
return !!managedProperties &&
Expand Down
9 changes: 9 additions & 0 deletions chrome/browser/ui/webui/settings/ash/internet_section.cc
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,10 @@ void InternetSection::AddLoadTimeData(content::WebUIDataSource* html_source) {
{"networkSectionNetwork", IDS_SETTINGS_INTERNET_NETWORK_SECTION_NETWORK},
{"networkSectionNetworkExpandA11yLabel",
IDS_SETTINGS_INTERNET_NETWORK_SECTION_NETWORK_ACCESSIBILITY_LABEL},
{"networkSectionPasspointRemovalTitle",
IDS_SETTINGS_INTERNET_NETWORK_SECTION_PASSPOINT_REMOVAL_TITLE},
{"networkSectionPasspointRemovalDescription",
IDS_SETTINGS_INTERNET_NETWORK_SECTION_PASSPOINT_REMOVAL_DESCRIPTION},
{"networkSectionProxy", IDS_SETTINGS_INTERNET_NETWORK_SECTION_PROXY},
{"networkSectionProxyExpandA11yLabel",
IDS_SETTINGS_INTERNET_NETWORK_SECTION_PROXY_ACCESSIBILITY_LABEL},
Expand Down Expand Up @@ -1006,13 +1010,18 @@ void InternetSection::AddLoadTimeData(content::WebUIDataSource* html_source) {
base::FeatureList::IsEnabled(::features::kShowHiddenNetworkToggle));
html_source->AddBoolean("isHotspotEnabled",
ash::features::IsHotspotEnabled());
html_source->AddBoolean("isPasspointEnabled",
ash::features::IsPasspointARCSupportEnabled());

html_source->AddString("networkGoogleNameserversLearnMoreUrl",
chrome::kGoogleNameserversLearnMoreURL);

html_source->AddString("wifiHiddenNetworkLearnMoreUrl",
chrome::kWifiHiddenNetworkURL);

html_source->AddString("wifiPasspointLearnMoreUrl",
chrome::kWifiPasspointURL);

html_source->AddString(
"networkNotSynced",
l10n_util::GetStringFUTF16(
Expand Down
3 changes: 3 additions & 0 deletions chrome/common/url_constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,9 @@ const char kWifiSyncLearnMoreURL[] =
const char kWifiHiddenNetworkURL[] =
"https://support.google.com/chromebook?p=hidden_networks";

const char kWifiPasspointURL[] =
"https://support.google.com/chromebook?p=wifi_passpoint";

const char kNearbyShareLearnMoreURL[] =
"https://support.google.com/chromebook?p=nearby_share";

Expand Down
3 changes: 3 additions & 0 deletions chrome/common/url_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,9 @@ extern const char kWifiSyncLearnMoreURL[];
// The URL for the help center article about hidden Wi-Fi networks.
extern const char kWifiHiddenNetworkURL[];

// The URL for the help center article about Passpoint.
extern const char kWifiPasspointURL[];

// The URL for contacts management in Nearby Share feature.
extern const char kNearbyShareManageContactsURL[];

Expand Down
15 changes: 13 additions & 2 deletions chrome/test/data/webui/chromeos/fake_network_config_mojom.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ export class FakeNetworkConfig {
'getManagedProperties', 'setNetworkTypeEnabledState', 'requestNetworkScan',
'getGlobalPolicy', 'getVpnProviders', 'getNetworkCertificates',
'setProperties', 'setCellularSimState', 'startConnect', 'startDisconnect',
'configureNetwork', 'getAlwaysOnVpn', 'getSupportedVpnTypes',
'requestTrafficCounters', 'resetTrafficCounters',
'configureNetwork', 'forgetNetwork', 'getAlwaysOnVpn',
'getSupportedVpnTypes', 'requestTrafficCounters', 'resetTrafficCounters',
'setTrafficCountersAutoReset', 'removeCustomApn', 'createCustomApn',
'modifyCustomApn']
.forEach((methodName) => {
Expand Down Expand Up @@ -340,6 +340,17 @@ export class FakeNetworkConfig {
});
}

/**
* @param {!string} guid
* @return {!Promise<{success: !boolean}>}
*/
forgetNetwork(guid) {
return new Promise(resolve => {
this.methodCalled('forgetNetwork');
resolve({success: true});
});
}

/**
* @param {string} guid
* @param {ConfigProperties} properties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {InternetPageBrowserProxyImpl, Router, routes} from 'chrome://os-settings
import {MojoInterfaceProviderImpl} from 'chrome://resources/ash/common/network/mojo_interface_provider.js';
import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js';
import {getDeepActiveElement} from 'chrome://resources/ash/common/util.js';
import {ActivationStateType, CrosNetworkConfigRemote, InhibitReason, ManagedProperties, VpnType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js';
import {ActivationStateType, CrosNetworkConfigRemote, InhibitReason, ManagedProperties, MatchType, VpnType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js';
import {ConnectionStateType, DeviceStateType, NetworkType, OncSource, PolicySource, PortalState} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {FakeNetworkConfig} from 'chrome://webui-test/chromeos/fake_network_config_mojom.js';
Expand Down Expand Up @@ -96,6 +96,12 @@ suite('InternetDetailPage', function() {
return button;
}

function getDialog(dialogId) {
const dialog = internetDetailPage.shadowRoot.querySelector(`#${dialogId}`);
assertTrue(!!dialog);
return dialog;
}

function getManagedProperties(type, name, opt_source) {
const result =
OncMojo.getDefaultManagedProperties(type, name + '_guid', name);
Expand Down Expand Up @@ -161,6 +167,7 @@ suite('InternetDetailPage', function() {
internetKnownNetworksPageTitle: 'internetKnownNetworksPageTitle',
showMeteredToggle: true,
isApnRevampEnabled: false,
isPasspointEnabled: true,
});

PolymerTest.clearBody();
Expand Down Expand Up @@ -585,6 +592,79 @@ suite('InternetDetailPage', function() {
assertFalse(!!internetDetailPage.shadowRoot.querySelector(
'network-proxy-section'));
});

test('WiFi Passpoint removal shows a dialog', async () => {
loadTimeData.overrideValues({isPasspointEnabled: true});
init();
mojoApi_.resetForTest();
mojoApi_.setNetworkTypeEnabledState(NetworkType.kWiFi, true);
const wifiNetwork =
getManagedProperties(NetworkType.kWiFi, 'wifi_passpoint');
wifiNetwork.source = OncSource.kUser;
wifiNetwork.connectable = true;
wifiNetwork.typeProperties.wifi.passpointId = 'a_passpoint_id';
wifiNetwork.typeProperties.wifi.passpointMatchType = MatchType.kHome;
mojoApi_.setManagedPropertiesForTest(wifiNetwork);

internetDetailPage.init('wifi_passpoint_guid', 'WiFi', 'wifi_passpoint');
await flushAsync();

const forgetButton = getButton('forgetButton');
assertFalse(forgetButton.hidden);
assertFalse(forgetButton.disabled);

// Click the button and check the dialog is displayed.
forgetButton.click();
await flushAsync();
const dialog = getDialog('passpointRemovalDialog');
assertTrue(dialog.open);

// Check "Cancel" dismiss the dialog.
const cancelButton = getButton('passpointRemovalCancelButton');
assertTrue(!!cancelButton);
cancelButton.click();
await flushAsync();
assertFalse(dialog.open);

// Check "Confirm" triggers network removal
forgetButton.click();
await flushAsync();
const confirmButton = getButton('passpointRemovalConfirmButton');
confirmButton.click();
await flushAsync();
assertFalse(dialog.open);
await mojoApi_.whenCalled('forgetNetwork');
});

[true, false].forEach(isPasspointEnabled => {
test(
'WiFi network removal without Passpoint does not show a dialog',
async () => {
loadTimeData.overrideValues({
isPasspointEnabled: isPasspointEnabled,
});
init();
mojoApi_.resetForTest();
mojoApi_.setNetworkTypeEnabledState(NetworkType.kWiFi, true);
const wifiNetwork = getManagedProperties(NetworkType.kWiFi, 'wifi');
wifiNetwork.source = OncSource.kUser;
wifiNetwork.connectable = true;
mojoApi_.setManagedPropertiesForTest(wifiNetwork);

internetDetailPage.init('wifi_guid', 'WiFi', 'wifi');
await flushAsync();

const forgetButton = getButton('forgetButton');
assertFalse(forgetButton.hidden);
assertFalse(forgetButton.disabled);

// Click the button and check the dialog is displayed.
forgetButton.click();
await flushAsync();
assertFalse(!!internetDetailPage.shadowRoot.querySelector(
'#passpointRemovalDialog'));
});
});
});

suite('DetailsPageVPN', function() {
Expand Down

0 comments on commit 08b9549

Please sign in to comment.