blob: f36dd88535e6a5ab978e2025610c0d6b4d9676b1 [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 This file has two parts:
*
* 1. Typedefs for network properties. Note: These 'types' define a subset of
* ONC properties in the ONC data dictionary. The first letter is capitalized to
* match the ONC spec and avoid an extra layer of translation.
* See components/onc/docs/onc_spec.html for the complete spec.
* TODO(stevenjb): Replace with chrome.networkingPrivate.NetworkStateProperties
* once that is fully defined.
*
* 2. Helper functions to facilitate extracting and setting ONC properties.
*/
var CrOnc = {};
/** @typedef {chrome.networkingPrivate.NetworkStateProperties} */
CrOnc.NetworkStateProperties;
/** @typedef {chrome.networkingPrivate.ManagedProperties} */
CrOnc.NetworkProperties;
/** @typedef {string|number|boolean|Object|Array<Object>} */
CrOnc.NetworkPropertyType;
/**
* Generic managed property type. This should match any of the basic managed
* types in chrome.networkingPrivate, e.g. networkingPrivate.ManagedBoolean.
* @typedef {{
* Active: (!CrOnc.NetworkPropertyType|undefined),
* Effective: (string|undefined),
* UserPolicy: (!CrOnc.NetworkPropertyType|undefined),
* DevicePolicy: (!CrOnc.NetworkPropertyType|undefined),
* UserSetting: (!CrOnc.NetworkPropertyType|undefined),
* SharedSetting: (!CrOnc.NetworkPropertyType|undefined),
* UserEditable: (boolean|undefined),
* DeviceEditable: (boolean|undefined)
* }}
*/
CrOnc.ManagedProperty;
/** @typedef {chrome.networkingPrivate.SIMLockStatus} */
CrOnc.SIMLockStatus;
/** @typedef {chrome.networkingPrivate.APNProperties} */
CrOnc.APNProperties;
/** @typedef {chrome.networkingPrivate.CellularSimState} */
CrOnc.CellularSimState;
/** @typedef {chrome.networkingPrivate.IPConfigProperties} */
CrOnc.IPConfigProperties;
/** @typedef {chrome.networkingPrivate.ManualProxySettings} */
CrOnc.ManualProxySettings;
/** @typedef {chrome.networkingPrivate.ProxyLocation} */
CrOnc.ProxyLocation;
/** @typedef {chrome.networkingPrivate.ProxySettings} */
CrOnc.ProxySettings;
// Modified version of IPConfigProperties to store RoutingPrefix as a
// human-readable string instead of as a number.
/**
* @typedef {{
* Gateway: (string|undefined),
* IPAddress: (string|undefined),
* NameServers: (!Array<string>|undefined),
* RoutingPrefix: (string|undefined),
* Type: (string|undefined),
* WebProxyAutoDiscoveryUrl: (string|undefined)
* }}
*/
CrOnc.IPConfigUIProperties;
/** @typedef {chrome.networkingPrivate.PaymentPortal} */
CrOnc.PaymentPortal;
CrOnc.ActivationState = chrome.networkingPrivate.ActivationStateType;
CrOnc.ConnectionState = chrome.networkingPrivate.ConnectionStateType;
CrOnc.IPConfigType = chrome.networkingPrivate.IPConfigType;
CrOnc.ProxySettingsType = chrome.networkingPrivate.ProxySettingsType;
CrOnc.Type = chrome.networkingPrivate.NetworkType;
/** @enum {string} */
CrOnc.IPType = {
IPV4: 'IPv4',
IPV6: 'IPv6',
};
/** @enum {string} */
CrOnc.LockType = {
NONE: '',
PIN: 'sim-pin',
PUK: 'sim-puk',
};
/** @enum {string} */
CrOnc.NetworkTechnology = {
CDMA1XRTT: 'CDMA1XRTT',
EDGE: 'EDGE',
EVDO: 'EVDO',
GPRS: 'GPRS',
GSM: 'GSM',
HSPA: 'HSPA',
HSPA_PLUS: 'HSPAPlus',
LTE: 'LTE',
LTE_ADVANCED: 'LTEAdvanced',
UMTS: 'UMTS',
UNKNOWN: 'Unknown',
};
/** @enum {string} */
CrOnc.RoamingState = {
HOME: 'Home',
REQUIRED: 'Required',
ROAMING: 'Roaming',
UNKNOWN: 'Unknown',
};
/** @enum {string} */
CrOnc.Security = {
NONE: 'None',
WEP_8021X: 'WEP-8021X',
WEP_PSK: 'WEP-PSK',
WPA_EAP: 'WPA-EAP',
WPA_PSK: 'WPA-PSK',
};
/** @enum {string} */
CrOnc.Source = {
NONE: 'None',
DEVICE: 'Device',
DEVICE_POLICY: 'DevicePolicy',
USER: 'User',
USER_POLICY: 'UserPolicy',
};
/**
* Helper function to retrieve the active ONC property value from a managed
* dictionary.
* @param {!CrOnc.ManagedProperty|undefined} property The managed dictionary
* for the property if it exists or undefined.
* @return {!CrOnc.NetworkPropertyType|undefined} The active property value
* if it exists, otherwise undefined.
*/
CrOnc.getActiveValue = function(property) {
if (property == undefined)
return undefined;
if (typeof property != 'object') {
console.error('getActiveValue called on non object: ' +
JSON.stringify(property));
return undefined;
}
// Return the Active value if it exists.
if ('Active' in property)
return property['Active'];
// If no Active value is defined, return the effective value.
if ('Effective' in property) {
var effective = property.Effective;
if (effective in property)
return property[effective];
}
console.error('getActiveValue called on invalid ONC object: ' +
JSON.stringify(property));
return undefined;
};
/**
* Converts a managed ONC dictionary into an unmanaged dictionary (i.e. a
* dictionary of active values).
* NOTE: This is not intended to be used with dictionaries that contain
* nested dictionaries. This will fail and return undefined in that case.
* @param {!Object|undefined} properties A managed ONC dictionary
* @return {!Object|undefined} An unmanaged version of |properties|.
*/
CrOnc.getSimpleActiveProperties = function(properties) {
'use strict';
if (!properties)
return undefined;
var result = {};
var keys = Object.keys(properties);
for (let k of keys) {
var prop = CrOnc.getActiveValue(properties[k]);
if (prop == undefined) {
console.error('getSimpleActiveProperties called on invalid ONC object: ' +
JSON.stringify(properties));
return undefined;
}
result[k] = prop;
}
return result;
};
/**
* Returns an IPConfigProperties object for |type|. For IPV4, these will be the
* static properties if IPAddressConfigType is Static and StaticIPConfig is set.
* @param {!CrOnc.NetworkProperties|undefined} properties The ONC properties.
* @param {!CrOnc.IPType} type The IP Config type.
* @return {CrOnc.IPConfigProperties|undefined} The IP Config object, or
* undefined if no properties for |type| are available.
*/
CrOnc.getIPConfigForType = function(properties, type) {
'use strict';
/** @type {!CrOnc.IPConfigProperties|undefined} */ var ipConfig = undefined;
var ipConfigs = properties.IPConfigs;
if (ipConfigs) {
for (let i = 0; i < ipConfigs.length; ++i) {
ipConfig = ipConfigs[i];
if (ipConfig.Type == type)
break;
}
}
if (type != CrOnc.IPType.IPV4)
return ipConfig;
var staticIpConfig =
/** @type {!CrOnc.IPConfigProperties|undefined} */(
CrOnc.getSimpleActiveProperties(properties.StaticIPConfig));
if (!staticIpConfig)
return ipConfig;
// If there is no entry in IPConfigs for |type|, return the static config.
if (!ipConfig)
return staticIpConfig;
// Otherwise, merge the appropriate static values into the result.
if (staticIpConfig.IPAddress &&
CrOnc.getActiveValue(properties.IPAddressConfigType) == 'Static') {
ipConfig.Gateway = staticIpConfig.Gateway;
ipConfig.IPAddress = staticIpConfig.IPAddress;
ipConfig.RoutingPrefix = staticIpConfig.RoutingPrefix;
ipConfig.Type = staticIpConfig.Type;
}
if (staticIpConfig.NameServers &&
CrOnc.getActiveValue(properties.NameServersConfigType) == 'Static') {
ipConfig.NameServers = staticIpConfig.NameServers;
}
return ipConfig;
};
/**
* Gets the SignalStrength value from |properties| based on properties.Type.
* @param {!CrOnc.NetworkProperties|!CrOnc.NetworkStateProperties|undefined}
* properties The ONC network properties or state properties.
* @return {number} The signal strength value if it exists or 0.
*/
CrOnc.getSignalStrength = function(properties) {
var type = properties.Type;
if (type == CrOnc.Type.CELLULAR && properties.Cellular)
return properties.Cellular.SignalStrength || 0;
if (type == CrOnc.Type.WI_FI && properties.WiFi)
return properties.WiFi.SignalStrength || 0;
if (type == CrOnc.Type.WI_MAX && properties.WiMAX)
return properties.WiMAX.SignalStrength || 0;
return 0;
}
/**
* Gets the Managed AutoConnect dictionary from |properties| based on
* properties.Type.
* @param {!CrOnc.NetworkProperties|undefined}
* properties The ONC network properties or state properties.
* @return {!chrome.networkingPrivate.ManagedBoolean|undefined} The AutoConnect
* managed dictionary or undefined.
*/
CrOnc.getManagedAutoConnect = function(properties) {
var type = properties.Type;
if (type == CrOnc.Type.CELLULAR && properties.Cellular)
return properties.Cellular.AutoConnect;
if (type == CrOnc.Type.VPN && properties.VPN)
return properties.VPN.AutoConnect;
if (type == CrOnc.Type.WI_FI && properties.WiFi)
return properties.WiFi.AutoConnect;
if (type == CrOnc.Type.WI_MAX && properties.WiMAX)
return properties.WiMAX.AutoConnect;
return undefined;
}
/**
* Gets the AutoConnect value from |properties| based on properties.Type.
* @param {!CrOnc.NetworkProperties|undefined}
* properties The ONC network properties or state properties.
* @return {boolean} The AutoConnect value if it exists or false.
*/
CrOnc.getAutoConnect = function(properties) {
var autoconnect = CrOnc.getManagedAutoConnect(properties);
return !!CrOnc.getActiveValue(autoconnect);
}
/**
* @param {!CrOnc.NetworkProperties|!CrOnc.NetworkStateProperties|undefined}
* properties The ONC network properties or state properties.
* @return {boolean} True if |properties| is a Cellular network with a
* locked SIM.
*/
CrOnc.isSimLocked = function(properties) {
if (!properties.Cellular)
return false;
var simLockStatus = properties.Cellular.SIMLockStatus;
if (simLockStatus == undefined)
return false;
return simLockStatus.LockType == CrOnc.LockType.PIN ||
simLockStatus.LockType == CrOnc.LockType.PUK;
};
/**
* Modifies |config| to include the correct set of properties for configuring
* a network IP Address and NameServer configuration for |state|. Existing
* properties in |config| will be preserved unless invalid.
* @param {!chrome.networkingPrivate.NetworkConfigProperties} config A partial
* ONC configuration.
* @param {CrOnc.NetworkProperties|undefined} properties The ONC properties.
*/
CrOnc.setValidStaticIPConfig = function(config, properties) {
if (!config.IPAddressConfigType) {
var ipConfigType = /** @type {chrome.networkingPrivate.IPConfigType} */(
CrOnc.getActiveValue(properties.IPAddressConfigType));
config.IPAddressConfigType = ipConfigType || CrOnc.IPConfigType.DHCP;
}
if (!config.NameServersConfigType) {
var nsConfigType = /** @type {chrome.networkingPrivate.IPConfigType} */(
CrOnc.getActiveValue(properties.NameServersConfigType));
config.NameServersConfigType = nsConfigType || CrOnc.IPConfigType.DHCP;
}
if (config.IPAddressConfigType != CrOnc.IPConfigType.STATIC &&
config.NameServersConfigType != CrOnc.IPConfigType.STATIC) {
if (config.hasOwnProperty('StaticIPConfig'))
delete config.StaticIPConfig;
return;
}
if (!config.hasOwnProperty('StaticIPConfig')) {
config.StaticIPConfig =
/** @type {chrome.networkingPrivate.IPConfigProperties} */({});
}
var staticIP = config.StaticIPConfig;
var stateIPConfig = CrOnc.getIPConfigForType(properties, CrOnc.IPType.IPV4);
if (config.IPAddressConfigType == 'Static') {
staticIP.Gateway = staticIP.Gateway || stateIPConfig.Gateway || '';
staticIP.IPAddress = staticIP.IPAddress || stateIPConfig.IPAddress || '';
staticIP.RoutingPrefix =
staticIP.RoutingPrefix || stateIPConfig.RoutingPrefix || 0;
staticIP.Type = staticIP.Type || stateIPConfig.Type || CrOnc.IPType.IPV4;
}
if (config.NameServersConfigType == 'Static') {
staticIP.NameServers =
staticIP.NameServers || stateIPConfig.NameServers || [];
}
};
/**
* Sets the value of a property in an ONC dictionary.
* @param {!chrome.networkingPrivate.NetworkConfigProperties} properties
* The ONC property dictionary to modify.
* @param {string} key The property key which may be nested, e.g. 'Foo.Bar'.
* @param {!CrOnc.NetworkPropertyType} value The property value to set.
*/
CrOnc.setProperty = function(properties, key, value) {
while (true) {
var index = key.indexOf('.');
if (index < 0)
break;
var keyComponent = key.substr(0, index);
if (!properties.hasOwnProperty(keyComponent))
properties[keyComponent] = {};
properties = properties[keyComponent];
key = key.substr(index + 1);
}
properties[key] = value;
};
/**
* Calls setProperty with '{state.Type}.key', e.g. WiFi.AutoConnect.
* @param {!chrome.networkingPrivate.NetworkConfigProperties} properties The
* ONC properties to set. properties.Type must be set already.
* @param {string} key The type property key, e.g. 'AutoConnect'.
* @param {!CrOnc.NetworkPropertyType} value The property value to set.
*/
CrOnc.setTypeProperty = function(properties, key, value) {
if (properties.Type == undefined) {
console.error('Type not defined in properties: ' +
JSON.stringify(properties));
return;
}
var typeKey = properties.Type + '.' + key;
CrOnc.setProperty(properties, typeKey, value);
};
/**
* Returns the routing prefix as a string for a given prefix length.
* @param {number} prefixLength The ONC routing prefix length.
* @return {string} The corresponding netmask.
*/
CrOnc.getRoutingPrefixAsNetmask = function(prefixLength) {
'use strict';
// Return the empty string for invalid inputs.
if (prefixLength < 0 || prefixLength > 32)
return '';
var netmask = '';
for (let i = 0; i < 4; ++i) {
let remainder = 8;
if (prefixLength >= 8) {
prefixLength -= 8;
} else {
remainder = prefixLength;
prefixLength = 0;
}
if (i > 0)
netmask += '.';
let value = 0;
if (remainder != 0)
value = ((2 << (remainder - 1)) - 1) << (8 - remainder);
netmask += value.toString();
}
return netmask;
};
/**
* Returns the routing prefix length as a number from the netmask string.
* @param {string} netmask The netmask string, e.g. 255.255.255.0.
* @return {number} The corresponding netmask or -1 if invalid.
*/
CrOnc.getRoutingPrefixAsLength = function(netmask) {
'use strict';
var prefixLength = 0;
var tokens = netmask.split('.');
if (tokens.length != 4)
return -1;
for (let i = 0; i < tokens.length; ++i) {
let token = tokens[i];
// If we already found the last mask and the current one is not
// '0' then the netmask is invalid. For example, 255.224.255.0
if (prefixLength / 8 != i) {
if (token != '0')
return -1;
} else if (token == '255') {
prefixLength += 8;
} else if (token == '254') {
prefixLength += 7;
} else if (token == '252') {
prefixLength += 6;
} else if (token == '248') {
prefixLength += 5;
} else if (token == '240') {
prefixLength += 4;
} else if (token == '224') {
prefixLength += 3;
} else if (token == '192') {
prefixLength += 2;
} else if (token == '128') {
prefixLength += 1;
} else if (token == '0') {
prefixLength += 0;
} else {
// mask is not a valid number.
return -1;
}
}
return prefixLength;
};