Commit e0588bf3 authored by Alexander Hendrich's avatar Alexander Hendrich Committed by Commit Bot

Blacklist WiFi SSIDs through ONC policy [UI]

This CL implements the UI changes for blacklisted WiFi networks.

DesignDoc: http://go/cros-blacklist-ssids

Bug: 837205
Cq-Include-Trybots: luci.chromium.try:closure_compilation
Change-Id: I2e830c5d25a756b7e20fcc9b75f79e8d24f7c6f3
Reviewed-on: https://chromium-review.googlesource.com/1101204
Commit-Queue: Alexander Hendrich <hendrich@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569193}
parent 9fdacf3b
......@@ -1101,7 +1101,7 @@ This file contains the strings for ash.
<message name="IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED" desc="Description in status area or network list when no network is connected.">
No network
</message>
<message name="IDS_ASH_STATUS_TRAY_NETWORK_PROHIBITED" desc="Tooltip in network list when no network is prohibited by policy.">
<message name="IDS_ASH_STATUS_TRAY_NETWORK_PROHIBITED" desc="Tooltip in network list when the network is prohibited by policy.">
This network is disabled by your administrator.
</message>
<message name="IDS_ASH_STATUS_TRAY_NETWORK_SIGNAL_WEAK" desc="Accessibility text for the network status tray when the connected network has a weak signal.">
......
......@@ -80,28 +80,6 @@ const int64_t kBluetoothTimeoutDelaySeconds = 2;
const int kMobileNetworkBatteryIconSize = 14;
const int kPowerStatusPaddingRight = 10;
bool IsProhibitedByPolicy(const chromeos::NetworkState* network) {
if (!NetworkTypePattern::WiFi().MatchesType(network->type()))
return false;
if (!Shell::Get()->session_controller()->IsActiveUserSessionStarted())
return false;
ManagedNetworkConfigurationHandler* managed_configuration_handler =
NetworkHandler::Get()->managed_network_configuration_handler();
const base::DictionaryValue* global_network_config =
managed_configuration_handler->GetGlobalConfigFromPolicy(
std::string() /* no username hash, device policy */);
bool policy_prohibites_unmanaged = false;
if (global_network_config) {
global_network_config->GetBooleanWithoutPathExpansion(
::onc::global_network_config::kAllowOnlyPolicyNetworksToConnect,
&policy_prohibites_unmanaged);
}
if (!policy_prohibites_unmanaged)
return false;
return !managed_configuration_handler->FindPolicyByGuidAndProfile(
network->guid(), network->profile_path(), nullptr /* onc_source */);
}
bool IsCellularSimLocked() {
const chromeos::DeviceState* cellular_device =
NetworkHandler::Get()->network_state_handler()->GetDeviceStateByType(
......@@ -582,7 +560,13 @@ void NetworkListView::UpdateNetworkIcons() {
handler->GetNetworkStateFromGuid(info->guid);
if (!network)
continue;
bool prohibited_by_policy = IsProhibitedByPolicy(network);
bool prohibited_by_policy =
Shell::Get()->session_controller()->IsActiveUserSessionStarted() &&
NetworkHandler::Get()
->managed_network_configuration_handler()
->IsNetworkBlockedByPolicy(network->type(), network->guid(),
network->profile_path(),
network->GetHexSsid());
info->label = network_icon::GetLabelForNetwork(
network, network_icon::ICON_TYPE_MENU_LIST);
info->image =
......@@ -777,16 +761,17 @@ void NetworkListView::UpdateViewForNetwork(HoverHighlightView* view,
// Add an additional icon to the right of the label for networks
// that require it (e.g. Tether, controlled by extension).
views::View* power_icon = CreatePowerStatusView(info);
if (power_icon) {
view->AddRightView(
power_icon, views::CreateEmptyBorder(
gfx::Insets(0 /* top */, 0 /* left */, 0 /* bottom */,
kPowerStatusPaddingRight)));
views::View* icon = CreatePowerStatusView(info);
if (icon) {
view->AddRightView(icon, views::CreateEmptyBorder(gfx::Insets(
0 /* top */, 0 /* left */, 0 /* bottom */,
kPowerStatusPaddingRight)));
} else {
views::View* controlled_icon = CreateControlledByExtensionView(info);
if (controlled_icon)
view->AddRightView(controlled_icon);
icon = CreatePolicyView(info);
if (!icon)
icon = CreateControlledByExtensionView(info);
if (icon)
view->AddRightView(icon);
}
needs_relayout_ = true;
......@@ -818,6 +803,27 @@ views::View* NetworkListView::CreatePowerStatusView(const NetworkInfo& info) {
return icon;
}
views::View* NetworkListView::CreatePolicyView(const NetworkInfo& info) {
// Check if the network is managed by policy.
const chromeos::NetworkState* network =
NetworkHandler::Get()->network_state_handler()->GetNetworkStateFromGuid(
info.guid);
if (!network)
return nullptr;
const base::DictionaryValue* policy =
NetworkHandler::Get()
->managed_network_configuration_handler()
->FindPolicyByGuidAndProfile(network->guid(), network->profile_path(),
nullptr /* onc_source */);
if (!policy)
return nullptr;
views::ImageView* controlled_icon = TrayPopupUtils::CreateMainImageView();
controlled_icon->SetImage(
gfx::CreateVectorIcon(kSystemMenuBusinessIcon, kMenuIconColor));
return controlled_icon;
}
views::View* NetworkListView::CreateControlledByExtensionView(
const NetworkInfo& info) {
NetworkingConfigDelegate* networking_config_delegate =
......
......@@ -76,11 +76,16 @@ class NetworkListView : public NetworkStateListDetailedView,
// Updates |view| with the information in |info|.
void UpdateViewForNetwork(HoverHighlightView* view, const NetworkInfo& info);
// Creates the a battery icon next to the name of Tether networks indicating
// Creates a battery icon next to the name of Tether networks indicating
// the battery percentage of the mobile device that is being used as a
// hotspot.
views::View* CreatePowerStatusView(const NetworkInfo& info);
// Creates a policy icon next to the name of managed networks indicating
// that the network is managed by policy. Returns |nullptr| if the network is
// not managed by policy.
views::View* CreatePolicyView(const NetworkInfo& info);
// Creates the view of an extra icon appearing next to the network name
// indicating that the network is controlled by an extension. If no extension
// is registered for this network, returns |nullptr|.
......
......@@ -95,11 +95,11 @@
<paper-button on-click="onConfigureTap_"
hidden$="[[!showConfigure_(networkProperties, globalPolicy)]]">
$i18n{networkButtonConfigure}
</paper-button>
</paper-button>
<paper-button class="action-button" on-click="onConnectTap_"
hidden$="[[!showConnect_(networkProperties, globalPolicy)]]"
disabled="[[!enableConnect_(networkProperties, defaultNetwork,
globalPolicy, networkPropertiesReceived_, outOfRange_)]]">
networkPropertiesReceived_, outOfRange_, globalPolicy)]]">
$i18n{networkButtonConnect}
</paper-button>
<paper-button class="action-button" on-click="onDisconnectTap_"
......@@ -110,12 +110,12 @@
<!-- Disabled by policy / Shared messages. -->
<div class="settings-box continuation"
hidden$="[[!connectNotAllowed_(networkProperties, globalPolicy)]]">
hidden$="[[!isBlockedByPolicy_(networkProperties, globalPolicy)]]">
<iron-icon class="policy" icon="cr20:domain"></iron-icon>
<div>$i18n{networkConnectNotAllowed}</div>
</div>
<div class="settings-box continuation"
hidden$="[[!showShared_(networkProperties)]]">
hidden$="[[!showShared_(networkProperties, globalPolicy)]]">
$i18n{networkShared}
</div>
......@@ -131,7 +131,8 @@
<template is="dom-if" if="[[!isSecondaryUser_]]">
<!-- Prefer this network. -->
<template is="dom-if" if="[[showPreferNetwork_(networkProperties)]]">
<template is="dom-if"
if="[[showPreferNetwork_(networkProperties, globalPolicy)]]">
<div class="settings-box">
<div id="preferNetworkToggleLabel"class="start">
$i18n{networkPrefer}
......@@ -146,7 +147,8 @@
</div>
</template>
<!-- Autoconnect. -->
<template is="dom-if" if="[[showAutoConnect_(networkProperties)]]">
<template is="dom-if"
if="[[showAutoConnect_(networkProperties, globalPolicy)]]">
<div class="settings-box">
<div id="autoConnectToggleLabel" class="start">
$i18n{networkAutoConnect}
......@@ -155,8 +157,7 @@
property="[[getManagedAutoConnect_(networkProperties)]]">
</cr-policy-network-indicator>
<cr-toggle checked="{{autoConnect_}}"
disabled="[[!enableAutoConnect_(networkProperties,
globalPolicy)]]"
disabled="[[!enableAutoConnect_(networkProperties)]]"
aria-labelledby="autoConnectToggleLabel">
</cr-toggle>
</div>
......@@ -226,7 +227,8 @@
</iron-collapse>
</template>
<template is="dom-if" if="[[hasNetworkSection_(networkProperties)]]">
<template is="dom-if"
if="[[hasNetworkSection_(networkProperties, globalPolicy)]]">
<!-- Network toggle -->
<div class="settings-box" actionable on-click="toggleNetworkExpanded_">
<div class="start">$i18n{networkSectionNetwork}</div>
......@@ -268,7 +270,8 @@
</iron-collapse>
</template>
<template is="dom-if" if="[[hasProxySection_(networkProperties)]]">
<template is="dom-if"
if="[[hasProxySection_(networkProperties, globalPolicy)]]">
<!-- Proxy toggle -->
<div class="settings-box" actionable on-click="toggleProxyExpanded_">
<div class="start">$i18n{networkSectionProxy}</div>
......
......@@ -85,7 +85,10 @@ Polymer({
},
/** @type {!chrome.networkingPrivate.GlobalPolicy|undefined} */
globalPolicy: Object,
globalPolicy: {
type: Object,
value: null,
},
/**
* Interface for networkingPrivate calls, passed from internet_page.
......@@ -468,10 +471,17 @@ Polymer({
* @return {boolean}
* @private
*/
connectNotAllowed_: function(networkProperties, globalPolicy) {
return networkProperties.Type == CrOnc.Type.WI_FI &&
!!globalPolicy.AllowOnlyPolicyNetworksToConnect &&
!this.isPolicySource(networkProperties.Source);
isBlockedByPolicy_: function(networkProperties, globalPolicy) {
if (networkProperties.Type != CrOnc.Type.WI_FI ||
this.isPolicySource(networkProperties.Source)) {
return false;
}
return !!globalPolicy &&
(!!globalPolicy.AllowOnlyPolicyNetworksToConnect ||
(!!networkProperties.WiFi && !!networkProperties.WiFi.HexSSID &&
!!globalPolicy.BlacklistedHexSSIDs &&
globalPolicy.BlacklistedHexSSIDs.includes(
CrOnc.getStateOrActiveString(networkProperties.WiFi.HexSSID))));
},
/**
......@@ -481,7 +491,7 @@ Polymer({
* @private
*/
showConnect_: function(networkProperties, globalPolicy) {
if (this.connectNotAllowed_(networkProperties, globalPolicy))
if (this.isBlockedByPolicy_(networkProperties, globalPolicy))
return false;
// TODO(lgcheng@) support connect Arc VPN from UI once Android support API
// to initiate a VPN session.
......@@ -545,7 +555,7 @@ Polymer({
showConfigure_: function(networkProperties, globalPolicy) {
if (this.isSecondaryUser_)
return false;
if (this.connectNotAllowed_(networkProperties, globalPolicy))
if (this.isBlockedByPolicy_(networkProperties, globalPolicy))
return false;
const type = networkProperties.Type;
if (type == CrOnc.Type.CELLULAR || type == CrOnc.Type.TETHER)
......@@ -608,15 +618,15 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {?CrOnc.NetworkStateProperties} defaultNetwork
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
* @param {boolean} networkPropertiesReceived
* @param {boolean} outOfRange
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
* @return {boolean} Whether or not to enable the network connect button.
* @private
*/
enableConnect_: function(
networkProperties, defaultNetwork, globalPolicy,
networkPropertiesReceived, outOfRange) {
networkProperties, defaultNetwork, networkPropertiesReceived, outOfRange,
globalPolicy) {
if (!this.showConnect_(networkProperties, globalPolicy))
return false;
if (!networkPropertiesReceived || outOfRange)
......@@ -869,23 +879,27 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
* @return {boolean} True if the shared message should be shown.
* @private
*/
showShared_: function(networkProperties) {
return networkProperties.Source == 'Device' ||
networkProperties.Source == 'DevicePolicy';
showShared_: function(networkProperties, globalPolicy) {
return (networkProperties.Source == 'Device' ||
networkProperties.Source == 'DevicePolicy') &&
!this.isBlockedByPolicy_(networkProperties, globalPolicy);
},
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
* @return {boolean} True if the AutoConnect checkbox should be shown.
* @private
*/
showAutoConnect_: function(networkProperties) {
showAutoConnect_: function(networkProperties, globalPolicy) {
return networkProperties.Type != CrOnc.Type.ETHERNET &&
this.isRemembered_(networkProperties) &&
!this.isArcVpn_(networkProperties);
!this.isArcVpn_(networkProperties) &&
!this.isBlockedByPolicy_(networkProperties, globalPolicy);
},
/**
......@@ -895,7 +909,7 @@ Polymer({
* @private
*/
enableAutoConnect_: function(networkProperties, globalPolicy) {
if (networkProperties.Type == CrOnc.Type.WI_FI &&
if (networkProperties.Type == CrOnc.Type.WI_FI && !!globalPolicy &&
!!globalPolicy.AllowOnlyPolicyNetworksToAutoconnect &&
!this.isPolicySource(networkProperties.Source)) {
return false;
......@@ -915,14 +929,16 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
* @return {boolean} True if the prefer network checkbox should be shown.
* @private
*/
showPreferNetwork_: function(networkProperties) {
showPreferNetwork_: function(networkProperties, globalPolicy) {
// TODO(stevenjb): Resolve whether or not we want to allow "preferred" for
// networkProperties.Type == CrOnc.Type.ETHERNET.
return this.isRemembered_(networkProperties) &&
!this.isArcVpn_(networkProperties);
!this.isArcVpn_(networkProperties) &&
!this.isBlockedByPolicy_(networkProperties, globalPolicy);
},
/**
......@@ -1092,15 +1108,18 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
* @return {boolean}
* @private
*/
hasNetworkSection_: function(networkProperties) {
hasNetworkSection_: function(networkProperties, globalPolicy) {
if (networkProperties.Type == CrOnc.Type.TETHER) {
// These settings apply to the underlying WiFi network, not the Tether
// network.
return false;
}
if (this.isBlockedByPolicy_(networkProperties, globalPolicy))
return false;
if (networkProperties.Type == CrOnc.Type.CELLULAR)
return true;
return this.isRememberedOrConnected_(networkProperties);
......@@ -1108,15 +1127,18 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
* @return {boolean}
* @private
*/
hasProxySection_: function(networkProperties) {
hasProxySection_: function(networkProperties, globalPolicy) {
if (networkProperties.Type == CrOnc.Type.TETHER) {
// Proxy settings apply to the underlying WiFi network, not the Tether
// network.
return false;
}
if (this.isBlockedByPolicy_(networkProperties, globalPolicy))
return false;
return this.isRememberedOrConnected_(networkProperties);
},
......
......@@ -509,7 +509,7 @@ Polymer({
assert(this.defaultNetwork !== undefined);
const state = e.detail;
e.target.blur();
if (this.canConnect_(state, this.globalPolicy, this.defaultNetwork)) {
if (this.canConnect_(state, this.defaultNetwork, this.globalPolicy)) {
this.fire('network-connect', {networkProperties: state});
return;
}
......@@ -517,20 +517,33 @@ Polymer({
},
/**
* Determines whether or not a network state can be connected to.
* @param {!CrOnc.NetworkStateProperties} state The network state.
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
* @private
*/
isBlockedByPolicy_: function(state, globalPolicy) {
if (state.Type != CrOnc.Type.WI_FI || this.isPolicySource(state.Source)) {
return false;
}
return !!globalPolicy &&
(!!globalPolicy.AllowOnlyPolicyNetworksToConnect ||
(!!state.WiFi && !!state.WiFi.HexSSID &&
!!globalPolicy.BlacklistedHexSSIDs &&
globalPolicy.BlacklistedHexSSIDs.includes(state.WiFi.HexSSID)));
},
/**
* Determines whether or not a network state can be connected to.
* @param {!CrOnc.NetworkStateProperties} state The network state.
* @param {?CrOnc.NetworkStateProperties} defaultNetwork
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
* @private
*/
canConnect_: function(state, globalPolicy, defaultNetwork) {
canConnect_: function(state, defaultNetwork, globalPolicy) {
if (state.ConnectionState != CrOnc.ConnectionState.NOT_CONNECTED)
return false;
if (state.Type == CrOnc.Type.WI_FI && globalPolicy &&
globalPolicy.AllowOnlyPolicyNetworksToConnect &&
!this.isPolicySource(state.Source)) {
if (this.isBlockedByPolicy_(state, globalPolicy))
return false;
}
if (state.Type == CrOnc.Type.VPN &&
(!defaultNetwork ||
defaultNetwork.ConnectionState != CrOnc.ConnectionState.CONNECTED)) {
......
......@@ -240,7 +240,7 @@ namespace networking.onc {
// If set, the value against which to match the certificate subject's
// organizational units. At least one organizational unit should match the
// value.
DOMString? OrganizationalUnit;
DOMString? OrganizationalUnit;
};
dictionary CertificatePattern {
......@@ -417,7 +417,7 @@ namespace networking.onc {
[noinline_doc] dictionary CellularProperties {
// Whether the cellular network should be connected automatically (when
// in range).
// in range).
boolean? AutoConnect;
// The cellular network activation type.
DOMString? ActivationType;
......@@ -533,7 +533,7 @@ namespace networking.onc {
};
dictionary EthernetProperties {
// Whether the Ethernet network should be connected automatically.
// Whether the Ethernet network should be connected automatically.
boolean? AutoConnect;
// The authentication used by the Ethernet network. Possible values are
// <code>None</code> and <code>8021X</code>.
......@@ -874,6 +874,11 @@ namespace networking.onc {
// If true, only policy networks may be connected to and no new networks may
// be added or configured. Defaults to false.
boolean? AllowOnlyPolicyNetworksToConnect;
// List of blacklisted networks. Connections to blacklisted networks are
// prohibited. Networks can be whitelisted again by specifying an explicit
// network configuration. Defaults to an empty list.
DOMString[]? BlacklistedHexSSIDs;
};
callback VoidCallback = void();
......
......@@ -864,6 +864,11 @@ namespace networkingPrivate {
// If true, only policy networks may be connected to and no new networks may
// be added or configured. Defaults to false.
boolean? AllowOnlyPolicyNetworksToConnect;
// List of blacklisted networks. Connections to blacklisted networks are
// prohibited. Networks can be whitelisted again by specifying an explicit
// network configuration. Defaults to an empty list.
DOMString[]? BlacklistedHexSSIDs;
};
dictionary Certificate {
......
......@@ -988,7 +988,8 @@ chrome.networkingPrivate.NetworkFilter;
/**
* @typedef {{
* AllowOnlyPolicyNetworksToAutoconnect: (boolean|undefined),
* AllowOnlyPolicyNetworksToConnect: (boolean|undefined)
* AllowOnlyPolicyNetworksToConnect: (boolean|undefined),
* BlacklistedHexSSIDs: (!Array<string>|undefined)
* }}
*/
chrome.networkingPrivate.GlobalPolicy;
......
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