blob: e37ad1ad976255edabafed5fc6b5f45d6eec160f [file] [log] [blame]
// Copyright 2015 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
* 'settings-internet-detail' is the settings subpage containing details
* for a network.
*/
(function() {
'use strict';
/** @const */ var CARRIER_VERIZON = 'Verizon Wireless';
Polymer({
is: 'settings-internet-detail-page',
behaviors:
[CrPolicyNetworkBehavior, settings.RouteObserverBehavior, I18nBehavior],
properties: {
/** The network GUID to display details for. */
guid: String,
/**
* The current properties for the network matching |guid|.
* @type {!CrOnc.NetworkProperties|undefined}
*/
networkProperties: {
type: Object,
observer: 'networkPropertiesChanged_',
},
/** Preferences state. */
prefs: {
type: Object,
notify: true,
},
/**
* Highest priority connected network or null.
* @type {?CrOnc.NetworkStateProperties}
*/
defaultNetwork: {
type: Object,
value: null,
},
/**
* Interface for networkingPrivate calls, passed from internet_page.
* @type {NetworkingPrivate}
*/
networkingPrivate: Object,
/**
* The network AutoConnect state.
* @private
*/
autoConnect_: {
type: Boolean,
value: false,
observer: 'autoConnectChanged_',
},
/**
* The network preferred state.
* @private
*/
preferNetwork_: {
type: Boolean,
value: false,
observer: 'preferNetworkChanged_',
},
/**
* The network IP Address.
* @private
*/
IPAddress_: {
type: String,
value: '',
},
/** @private */
advancedExpanded_: Boolean,
/**
* Object providing network type values for data binding.
* @const
* @private
*/
NetworkType_: {
type: Object,
value: {
CELLULAR: CrOnc.Type.CELLULAR,
ETHERNET: CrOnc.Type.ETHERNET,
VPN: CrOnc.Type.VPN,
WIFI: CrOnc.Type.WI_FI,
WIMAX: CrOnc.Type.WI_MAX,
},
readOnly: true
},
},
/**
* Listener function for chrome.networkingPrivate.onNetworksChanged event.
* @type {?function(!Array<string>)}
* @private
*/
networksChangedListener_: null,
/**
* settings.RouteObserverBehavior
* @param {!settings.Route} route
* @protected
*/
currentRouteChanged: function(route) {
if (route != settings.Route.NETWORK_DETAIL) {
if (this.networksChangedListener_) {
this.networkingPrivate.onNetworksChanged.removeListener(
this.networksChangedListener_);
this.networksChangedListener_ = null;
}
return;
}
if (!this.networksChangedListener_) {
this.networksChangedListener_ = this.onNetworksChangedEvent_.bind(this);
this.networkingPrivate.onNetworksChanged.addListener(
this.networksChangedListener_);
}
let queryParams = settings.getQueryParameters();
this.guid = queryParams.get('guid') || '';
if (!this.guid) {
console.error('No guid specified for page:' + route);
this.close_();
}
this.getNetworkDetails_();
},
/** @private */
close_: function() {
// Delay navigating until the next render frame to allow other subpages to
// load first.
setTimeout(function() {
settings.navigateTo(settings.Route.INTERNET);
});
},
/** @private */
networkPropertiesChanged_: function() {
if (!this.networkProperties)
return;
// Update autoConnect if it has changed. Default value is false.
var autoConnect = CrOnc.getAutoConnect(this.networkProperties);
if (autoConnect != this.autoConnect_)
this.autoConnect_ = autoConnect;
// Update preferNetwork if it has changed. Default value is false.
var priority = /** @type {number} */ (
CrOnc.getActiveValue(this.networkProperties.Priority) || 0);
var preferNetwork = priority > 0;
if (preferNetwork != this.preferNetwork_)
this.preferNetwork_ = preferNetwork;
// Set the IPAddress property to the IPV4 Address.
var ipv4 =
CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV4);
this.IPAddress_ = (ipv4 && ipv4.IPAddress) || '';
// Update the detail page title.
this.parentNode.pageTitle =
CrOnc.getNetworkName(this.networkProperties, this);
},
/** @private */
autoConnectChanged_: function() {
if (!this.networkProperties || !this.guid)
return;
var onc = this.getEmptyNetworkProperties_();
CrOnc.setTypeProperty(onc, 'AutoConnect', this.autoConnect_);
this.setNetworkProperties_(onc);
},
/** @private */
preferNetworkChanged_: function() {
if (!this.networkProperties || !this.guid)
return;
var onc = this.getEmptyNetworkProperties_();
onc.Priority = this.preferNetwork_ ? 1 : 0;
this.setNetworkProperties_(onc);
},
/**
* networkingPrivate.onNetworksChanged event callback.
* @param {!Array<string>} networkIds The list of changed network GUIDs.
* @private
*/
onNetworksChangedEvent_: function(networkIds) {
if (networkIds.indexOf(this.guid) != -1)
this.getNetworkDetails_();
},
/**
* Calls networkingPrivate.getProperties for this.guid.
* @private
*/
getNetworkDetails_: function() {
assert(!!this.guid);
this.networkingPrivate.getManagedProperties(
this.guid, this.getPropertiesCallback_.bind(this));
},
/**
* networkingPrivate.getProperties callback.
* @param {CrOnc.NetworkProperties} properties The network properties.
* @private
*/
getPropertiesCallback_: function(properties) {
this.networkProperties = properties;
if (!properties) {
// If |properties| becomes null (i.e. the network is no longer visible),
// close the page.
console.error('Network no longer exists: ' + this.guid);
this.close_();
}
},
/**
* @param {!chrome.networkingPrivate.NetworkConfigProperties} onc The ONC
* network properties.
* @private
*/
setNetworkProperties_: function(onc) {
assert(!!this.guid);
this.networkingPrivate.setProperties(this.guid, onc, function() {
if (chrome.runtime.lastError) {
// An error typically indicates invalid input; request the properties
// to update any invalid fields.
this.getNetworkDetails_();
}
}.bind(this));
},
/**
* @return {!chrome.networkingPrivate.NetworkConfigProperties} An ONC
* dictionary with just the Type property set. Used for passing properties
* to setNetworkProperties_.
* @private
*/
getEmptyNetworkProperties_: function() {
return {Type: this.networkProperties.Type};
},
/**
* @return {string} The text to display for the network connection state.
* @private
*/
getStateText_: function() {
return this.i18n('Onc' + this.networkProperties.ConnectionState);
},
/**
* @return {boolean} True if the network is connected.
* @private
*/
isConnectedState_: function() {
return this.networkProperties.ConnectionState ==
CrOnc.ConnectionState.CONNECTED;
},
/**
* @return {boolean}
* @private
*/
isRemembered_: function() {
var source = this.networkProperties.Source;
return !!source && source != CrOnc.Source.NONE;
},
/**
* @return {boolean}
* @private
*/
isRememberedOrConnected_: function() {
return this.isRemembered_() || this.isConnectedState_();
},
/**
* @return {boolean}
* @private
*/
showConnect_: function() {
return this.networkProperties.Type != CrOnc.Type.ETHERNET &&
this.networkProperties.ConnectionState ==
CrOnc.ConnectionState.NOT_CONNECTED;
},
/**
* @return {boolean}
* @private
*/
showDisconnect_: function() {
return this.networkProperties.Type != CrOnc.Type.ETHERNET &&
this.networkProperties.ConnectionState !=
CrOnc.ConnectionState.NOT_CONNECTED;
},
/**
* @return {boolean}
* @private
*/
showForget_: function() {
var type = this.networkProperties.Type;
if (type != CrOnc.Type.WI_FI && type != CrOnc.Type.VPN)
return false;
return this.isRemembered_();
},
/**
* @return {boolean}
* @private
*/
showActivate_: function() {
if (this.networkProperties.Type != CrOnc.Type.CELLULAR)
return false;
var activation = this.networkProperties.Cellular.ActivationState;
return activation == CrOnc.ActivationState.NOT_ACTIVATED ||
activation == CrOnc.ActivationState.PARTIALLY_ACTIVATED;
},
/**
* @return {boolean}
* @private
*/
showConfigure_: function() {
var type = this.networkProperties.Type;
if (type == CrOnc.Type.CELLULAR || type == CrOnc.Type.WI_MAX)
return false;
if (type == CrOnc.Type.WI_FI &&
this.networkProperties.ConnectionState !=
CrOnc.ConnectionState.NOT_CONNECTED) {
return false;
}
return this.isRemembered_();
},
/**
* @return {boolean}
* @private
*/
showViewAccount_: function() {
// Show either the 'Activate' or the 'View Account' button.
if (this.showActivate_())
return false;
if (this.networkProperties.Type != CrOnc.Type.CELLULAR ||
!this.networkProperties.Cellular) {
return false;
}
// Only show if online payment URL is provided or the carrier is Verizon.
var carrier = CrOnc.getActiveValue(this.networkProperties.Cellular.Carrier);
if (carrier != CARRIER_VERIZON) {
var paymentPortal = this.networkProperties.Cellular.PaymentPortal;
if (!paymentPortal || !paymentPortal.Url)
return false;
}
// Only show for connected networks or LTE networks with a valid MDN.
if (!this.isConnectedState_()) {
var technology = this.networkProperties.Cellular.NetworkTechnology;
if (technology != CrOnc.NetworkTechnology.LTE &&
technology != CrOnc.NetworkTechnology.LTE_ADVANCED) {
return false;
}
if (!this.networkProperties.Cellular.MDN)
return false;
}
return true;
},
/**
* @return {boolean} Whether or not to enable the network connect button.
* @private
*/
enableConnect_: function() {
if (!this.showConnect_())
return false;
if (this.networkProperties.Type == CrOnc.Type.CELLULAR &&
CrOnc.isSimLocked(this.networkProperties)) {
return false;
}
if (this.networkProperties.Type == CrOnc.Type.VPN && !this.defaultNetwork)
return false;
return true;
},
/** @private */
onConnectTap_: function() {
this.networkingPrivate.startConnect(this.guid);
},
/** @private */
onDisconnectTap_: function() {
this.networkingPrivate.startDisconnect(this.guid);
},
/** @private */
onForgetTap_: function() {
this.networkingPrivate.forgetNetwork(this.guid);
// A forgotten WiFi network can still be configured, but not other types.
if (this.networkProperties.Type != CrOnc.Type.WI_FI)
this.close_();
},
/** @private */
onActivateTap_: function() {
this.networkingPrivate.startActivate(this.guid);
},
/** @private */
onConfigureTap_: function() {
chrome.send('configureNetwork', [this.guid]);
},
/** @private */
onViewAccountTap_: function() {
// startActivate() will show the account page for activated networks.
this.networkingPrivate.startActivate(this.guid);
},
/**
* @param {Event} event
* @private
*/
toggleAdvancedExpanded_: function(event) {
if (event.target.id == 'expandButton')
return; // Already handled.
this.advancedExpanded_ = !this.advancedExpanded_;
},
/**
* Event triggered for elements associated with network properties.
* @param {!{detail: !{field: string, value: (string|!Object)}}} event
* @private
*/
onNetworkPropertyChange_: function(event) {
if (!this.networkProperties)
return;
var field = event.detail.field;
var value = event.detail.value;
var onc = this.getEmptyNetworkProperties_();
if (field == 'APN') {
CrOnc.setTypeProperty(onc, 'APN', value);
} else if (field == 'SIMLockStatus') {
CrOnc.setTypeProperty(onc, 'SIMLockStatus', value);
} else {
console.error('Unexpected property change event: ' + field);
return;
}
this.setNetworkProperties_(onc);
},
/**
* Event triggered when the IP Config or NameServers element changes.
* @param {!{detail: !{field: string,
* value: (string|!CrOnc.IPConfigProperties|
* !Array<string>)}}} event
* The network-ip-config or network-nameservers change event.
* @private
*/
onIPConfigChange_: function(event) {
if (!this.networkProperties)
return;
var field = event.detail.field;
var value = event.detail.value;
// Get an empty ONC dictionary and set just the IP Config properties that
// need to change.
var onc = this.getEmptyNetworkProperties_();
var ipConfigType =
/** @type {chrome.networkingPrivate.IPConfigType|undefined} */ (
CrOnc.getActiveValue(this.networkProperties.IPAddressConfigType));
if (field == 'IPAddressConfigType') {
var newIpConfigType =
/** @type {chrome.networkingPrivate.IPConfigType} */ (value);
if (newIpConfigType == ipConfigType)
return;
onc.IPAddressConfigType = newIpConfigType;
} else if (field == 'NameServersConfigType') {
var nsConfigType =
/** @type {chrome.networkingPrivate.IPConfigType|undefined} */ (
CrOnc.getActiveValue(
this.networkProperties.NameServersConfigType));
var newNsConfigType =
/** @type {chrome.networkingPrivate.IPConfigType} */ (value);
if (newNsConfigType == nsConfigType)
return;
onc.NameServersConfigType = newNsConfigType;
} else if (field == 'StaticIPConfig') {
if (ipConfigType == CrOnc.IPConfigType.STATIC) {
let staticIpConfig = this.networkProperties.StaticIPConfig;
let ipConfigValue = /** @type {!Object} */ (value);
if (staticIpConfig &&
this.allPropertiesMatch_(staticIpConfig, ipConfigValue)) {
return;
}
}
onc.IPAddressConfigType = CrOnc.IPConfigType.STATIC;
if (!onc.StaticIPConfig) {
onc.StaticIPConfig =
/** @type {!chrome.networkingPrivate.IPConfigProperties} */ ({});
}
for (let key in value)
onc.StaticIPConfig[key] = value[key];
} else if (field == 'NameServers') {
// If a StaticIPConfig property is specified and its NameServers value
// matches the new value, no need to set anything.
let nameServers = /** @type {!Array<string>} */ (value);
if (onc.NameServersConfigType == CrOnc.IPConfigType.STATIC &&
onc.StaticIPConfig && onc.StaticIPConfig.NameServers == nameServers) {
return;
}
onc.NameServersConfigType = CrOnc.IPConfigType.STATIC;
if (!onc.StaticIPConfig) {
onc.StaticIPConfig =
/** @type {!chrome.networkingPrivate.IPConfigProperties} */ ({});
}
onc.StaticIPConfig.NameServers = nameServers;
} else {
console.error('Unexpected change field: ' + field);
return;
}
// setValidStaticIPConfig will fill in any other properties from
// networkProperties. This is necessary since we update IP Address and
// NameServers independently.
CrOnc.setValidStaticIPConfig(onc, this.networkProperties);
this.setNetworkProperties_(onc);
},
/**
* Event triggered when the Proxy configuration element changes.
* @param {!{detail: {field: string, value: !CrOnc.ProxySettings}}} event
* The network-proxy change event.
* @private
*/
onProxyChange_: function(event) {
if (!this.networkProperties)
return;
var field = event.detail.field;
var value = event.detail.value;
if (field != 'ProxySettings')
return;
var onc = this.getEmptyNetworkProperties_();
CrOnc.setProperty(onc, 'ProxySettings', /** @type {!Object} */ (value));
this.setNetworkProperties_(onc);
},
/**
* @return {boolean} True if the shared message should be shown.
* @private
*/
showShared_: function() {
return this.networkProperties.Source == 'Device' ||
this.networkProperties.Source == 'DevicePolicy';
},
/**
* @return {boolean} True if the AutoConnect checkbox should be shown.
* @private
*/
showAutoConnect_: function() {
return this.networkProperties.Type != CrOnc.Type.ETHERNET &&
this.isRemembered_();
},
/**
* @return {!CrOnc.ManagedProperty|undefined} Managed AutoConnect property.
* @private
*/
getManagedAutoConnect_: function() {
return CrOnc.getManagedAutoConnect(this.networkProperties);
},
/**
* @return {boolean} True if the prefer network checkbox should be shown.
* @private
*/
showPreferNetwork_: function() {
// TODO(stevenjb): Resolve whether or not we want to allow "preferred" for
// networkProperties.Type == CrOnc.Type.ETHERNET.
return this.isRemembered_();
},
/**
* @param {!Array<string>} fields
* @return {boolean}
* @private
*/
hasVisibleFields_: function(fields) {
for (let key of fields) {
let value = this.get(key, this.networkProperties);
if (value !== undefined && value !== '')
return true;
}
return false;
},
/**
* @return {boolean}
* @private
*/
hasInfoFields_: function() {
return this.hasVisibleFields_(this.getInfoFields_());
},
/**
* @return {!Array<string>} The fields to display in the info section.
* @private
*/
getInfoFields_: function() {
/** @type {!Array<string>} */ var fields = [];
if (this.networkProperties.Type == CrOnc.Type.CELLULAR) {
fields.push(
'Cellular.ActivationState', 'Cellular.RoamingState',
'RestrictedConnectivity', 'Cellular.ServingOperator.Name');
}
if (this.networkProperties.Type == CrOnc.Type.VPN) {
let vpnType = CrOnc.getActiveValue(this.networkProperties.VPN.Type);
if (vpnType == 'ThirdPartyVPN') {
fields.push('VPN.ThirdPartyVPN.ProviderName');
} else {
fields.push('VPN.Host', 'VPN.Type');
if (vpnType == 'OpenVPN')
fields.push('VPN.OpenVPN.Username');
else if (vpnType == 'L2TP-IPsec')
fields.push('VPN.L2TP.Username');
}
}
if (this.networkProperties.Type == CrOnc.Type.WI_FI)
fields.push('RestrictedConnectivity');
if (this.networkProperties.Type == CrOnc.Type.WI_MAX) {
fields.push('RestrictedConnectivity', 'WiMAX.EAP.Identity');
}
return fields;
},
/**
* @return {!Array<string>} The fields to display in the Advanced section.
* @private
*/
getAdvancedFields_: function() {
/** @type {!Array<string>} */ var fields = [];
fields.push('MacAddress');
if (this.networkProperties.Type == CrOnc.Type.CELLULAR) {
fields.push(
'Cellular.Carrier', 'Cellular.Family', 'Cellular.NetworkTechnology',
'Cellular.ServingOperator.Code');
}
if (this.networkProperties.Type == CrOnc.Type.WI_FI) {
fields.push(
'WiFi.SSID', 'WiFi.BSSID', 'WiFi.Security', 'WiFi.SignalStrength',
'WiFi.Frequency');
}
if (this.networkProperties.Type == CrOnc.Type.WI_MAX)
fields.push('WiFi.SignalStrength');
return fields;
},
/**
* @return {!Array<string>} The fields to display in the device section.
* @private
*/
getDeviceFields_: function() {
/** @type {!Array<string>} */ var fields = [];
if (this.networkProperties.Type == CrOnc.Type.CELLULAR) {
fields.push(
'Cellular.HomeProvider.Name', 'Cellular.HomeProvider.Country',
'Cellular.HomeProvider.Code', 'Cellular.Manufacturer',
'Cellular.ModelID', 'Cellular.FirmwareRevision',
'Cellular.HardwareRevision', 'Cellular.ESN', 'Cellular.ICCID',
'Cellular.IMEI', 'Cellular.IMSI', 'Cellular.MDN', 'Cellular.MEID',
'Cellular.MIN', 'Cellular.PRLVersion');
}
return fields;
},
/**
* @return {boolean}
* @private
*/
showAdvanced_: function() {
return this.hasAdvancedFields_() || this.hasDeviceFields_() ||
this.isRememberedOrConnected_();
},
/**
* @return {boolean}
* @private
*/
hasAdvancedFields_: function() {
return this.hasVisibleFields_(this.getAdvancedFields_());
},
/**
* @return {boolean}
* @private
*/
hasDeviceFields_: function() {
return this.hasVisibleFields_(this.getDeviceFields_());
},
/**
* @return {boolean}
* @private
*/
hasAdvancedOrDeviceFields_: function() {
return this.hasAdvancedFields_() || this.hasDeviceFields_();
},
/**
* @return {boolean} True if the network section should be shown.
* @private
*/
hasNetworkSection_: function() {
if (this.networkProperties.Type == CrOnc.Type.VPN)
return false;
if (this.networkProperties.Type == CrOnc.Type.CELLULAR)
return true;
return this.isRememberedOrConnected_();
},
/**
* @param {string} type The network type.
* @return {boolean} True if the network type matches 'type'.
* @private
*/
isType_: function(type) {
return this.networkProperties.Type == type;
},
/**
* @return {boolean} True if the Cellular SIM section should be shown.
* @private
*/
showCellularSim_: function() {
if (this.networkProperties.Type != 'Cellular' ||
!this.networkProperties.Cellular) {
return false;
}
return this.networkProperties.Cellular.Family == 'GSM';
},
/**
* @param {!Object} curValue
* @param {!Object} newValue
* @return {boolean} True if all properties set in |newValue| are equal to
* the corresponding properties in |curValue|. Note: Not all properties
* of |curValue| need to be specified in |newValue| for this to return
* true.
* @private
*/
allPropertiesMatch_: function(curValue, newValue) {
for (let key in newValue) {
if (newValue[key] != curValue[key])
return false;
}
return true;
}
});
})();