blob: 0c587b9186e7dfebb2e85cd5eb8d6baa51c9eeda [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 Polymer element for displaying a summary of network states
* by type: Ethernet, WiFi, Cellular, WiMAX, and VPN.
*/
/** @typedef {chrome.networkingPrivate.DeviceStateProperties} */
var DeviceStateProperties;
/**
* @typedef {{
* Ethernet: (DeviceStateProperties|undefined),
* WiFi: (DeviceStateProperties|undefined),
* Cellular: (DeviceStateProperties|undefined),
* WiMAX: (DeviceStateProperties|undefined),
* VPN: (DeviceStateProperties|undefined)
* }}
*/
var DeviceStateObject;
/**
* @typedef {{
* Ethernet: (Array<CrOnc.NetworkStateProperties>|undefined),
* WiFi: (Array<CrOnc.NetworkStateProperties>|undefined),
* Cellular: (Array<CrOnc.NetworkStateProperties>|undefined),
* WiMAX: (Array<CrOnc.NetworkStateProperties>|undefined),
* VPN: (Array<CrOnc.NetworkStateProperties>|undefined)
* }}
*/
var NetworkStateListObject;
Polymer({
is: 'network-summary',
behaviors: [CrPolicyNetworkBehavior],
properties: {
/**
* Highest priority connected network or null.
* @type {?CrOnc.NetworkStateProperties}
*/
defaultNetwork: {
type: Object,
value: null,
notify: true,
},
/**
* Interface for networkingPrivate calls, passed from internet_page.
* @type {NetworkingPrivate}
*/
networkingPrivate: Object,
/**
* The device state for each network device type. We initialize this to
* include a disabled WiFi type since WiFi is always present. This reduces
* the amount of visual change on first load.
* @private {DeviceStateObject}
*/
deviceStates: {
type: Object,
value: function() {
return {
WiFi: {
Type: chrome.networkingPrivate.NetworkType.WI_FI,
State: chrome.networkingPrivate.DeviceStateType.DISABLED
},
};
},
notify: true,
},
/**
* Array of active network states, one per device type. Initialized to
* include a default WiFi state (see deviceStates comment).
* @private {!Array<!CrOnc.NetworkStateProperties>}
*/
activeNetworkStates_: {
type: Array,
value: function() {
return [{GUID: '', Type: chrome.networkingPrivate.NetworkType.WI_FI}];
},
},
/**
* List of network state data for each network type.
* @private {NetworkStateListObject}
*/
networkStateLists_: {
type: Object,
value: function() {
return {WiFi: []};
},
},
},
/**
* Listener function for chrome.networkingPrivate.onNetworkListChanged event.
* @type {?function(!Array<string>)}
* @private
*/
networkListChangedListener_: null,
/**
* Listener function for chrome.networkingPrivate.onDeviceStateListChanged
* event.
* @type {?function(!Array<string>)}
* @private
*/
deviceStateListChangedListener_: null,
/**
* Listener function for chrome.networkingPrivate.onNetworksChanged event.
* @type {?function(!Array<string>)}
* @private
*/
networksChangedListener_: null,
/**
* Set of GUIDs identifying active networks, one for each type.
* @type {?Set<string>}
* @private
*/
activeNetworkIds_: null,
/** @override */
attached: function() {
this.getNetworkLists_();
this.networkListChangedListener_ = this.networkListChangedListener_ ||
this.onNetworkListChangedEvent_.bind(this);
this.networkingPrivate.onNetworkListChanged.addListener(
this.networkListChangedListener_);
this.deviceStateListChangedListener_ =
this.deviceStateListChangedListener_ ||
this.onDeviceStateListChangedEvent_.bind(this);
this.networkingPrivate.onDeviceStateListChanged.addListener(
this.deviceStateListChangedListener_);
this.networksChangedListener_ = this.networksChangedListener_ ||
this.onNetworksChangedEvent_.bind(this);
this.networkingPrivate.onNetworksChanged.addListener(
this.networksChangedListener_);
},
/** @override */
detached: function() {
this.networkingPrivate.onNetworkListChanged.removeListener(
assert(this.networkListChangedListener_));
this.networkingPrivate.onDeviceStateListChanged.removeListener(
assert(this.deviceStateListChangedListener_));
this.networkingPrivate.onNetworksChanged.removeListener(
assert(this.networksChangedListener_));
},
/**
* networkingPrivate.onNetworkListChanged event callback.
* @private
*/
onNetworkListChangedEvent_: function() {
this.getNetworkLists_();
},
/**
* networkingPrivate.onDeviceStateListChanged event callback.
* @private
*/
onDeviceStateListChangedEvent_: function() {
this.getNetworkLists_();
},
/**
* networkingPrivate.onNetworksChanged event callback.
* @param {!Array<string>} networkIds The list of changed network GUIDs.
* @private
*/
onNetworksChangedEvent_: function(networkIds) {
if (!this.activeNetworkIds_)
return; // Initial list of networks not received yet.
networkIds.forEach(function(id) {
if (this.activeNetworkIds_.has(id)) {
this.networkingPrivate.getState(
id, this.getActiveStateCallback_.bind(this, id));
}
}, this);
},
/**
* networkingPrivate.getState event callback for an active state.
* @param {string} id The id of the requested state.
* @param {!chrome.networkingPrivate.NetworkStateProperties} state
* @private
*/
getActiveStateCallback_: function(id, state) {
if (chrome.runtime.lastError) {
var message = chrome.runtime.lastError.message;
if (message != 'Error.NetworkUnavailable') {
console.error(
'Unexpected networkingPrivate.getState error: ' + message +
' For: ' + id);
}
return;
}
// Async call, ensure id still exists.
if (!this.activeNetworkIds_.has(id))
return;
if (!state) {
this.activeNetworkIds_.delete(id);
return;
}
// Find the active state for the type and update it.
for (var i = 0; i < this.activeNetworkStates_.length; ++i) {
if (this.activeNetworkStates_[i].type == state.type) {
this.activeNetworkStates_[i] = state;
return;
}
}
// Not found
console.error('Active state not found: ' + state.Name);
},
/**
* Requests the list of device states and network states from Chrome.
* Updates deviceStates, activeNetworkStates, and networkStateLists once the
* results are returned from Chrome.
* @private
*/
getNetworkLists_: function() {
// First get the device states.
this.networkingPrivate.getDeviceStates(function(deviceStates) {
// Second get the network states.
this.getNetworkStates_(deviceStates);
}.bind(this));
},
/**
* Requests the list of network states from Chrome. Updates
* activeNetworkStates and networkStateLists once the results are returned
* from Chrome.
* @param {!Array<!DeviceStateProperties>=} opt_deviceStates
* Optional list of state properties for all available devices.
* @private
*/
getNetworkStates_: function(opt_deviceStates) {
var filter = {
networkType: chrome.networkingPrivate.NetworkType.ALL,
visible: true,
configured: false
};
this.networkingPrivate.getNetworks(filter, function(networkStates) {
this.updateNetworkStates_(networkStates, opt_deviceStates);
}.bind(this));
},
/**
* Called after network states are received from getNetworks.
* @param {!Array<!CrOnc.NetworkStateProperties>} networkStates The state
* properties for all visible networks.
* @param {!Array<!DeviceStateProperties>=} opt_deviceStates
* Optional list of state properties for all available devices. If not
* defined the existing list of device states will be used.
* @private
*/
updateNetworkStates_: function(networkStates, opt_deviceStates) {
var newDeviceStates;
if (opt_deviceStates) {
newDeviceStates = /** @type {!DeviceStateObject} */ ({});
for (var i = 0; i < opt_deviceStates.length; ++i) {
var state = opt_deviceStates[i];
newDeviceStates[state.Type] = state;
}
} else {
newDeviceStates = Object.assign({}, this.deviceStates);
}
// Clear any current networks.
var activeNetworkStatesByType =
/** @type {!Map<string, !CrOnc.NetworkStateProperties>} */ (new Map);
// Complete list of states by type.
/** @type {!NetworkStateListObject} */ var newNetworkStateLists = {
Ethernet: [],
Tether: [],
WiFi: [],
Cellular: [],
WiMAX: [],
VPN: [],
};
var firstConnectedNetwork = null;
networkStates.forEach(function(networkState) {
var type = networkState.Type;
if (!activeNetworkStatesByType.has(type)) {
activeNetworkStatesByType.set(type, networkState);
if (!firstConnectedNetwork && networkState.Type != CrOnc.Type.VPN &&
networkState.ConnectionState == CrOnc.ConnectionState.CONNECTED) {
firstConnectedNetwork = networkState;
}
}
newNetworkStateLists[type].push(networkState);
}, this);
this.defaultNetwork = firstConnectedNetwork;
// Create a VPN entry in deviceStates if there are any VPN networks.
if (newNetworkStateLists.VPN && newNetworkStateLists.VPN.length > 0) {
newDeviceStates.VPN = /** @type {DeviceStateProperties} */ ({
Type: CrOnc.Type.VPN,
State: chrome.networkingPrivate.DeviceStateType.ENABLED
});
}
// Push the active networks onto newActiveNetworkStates in order based on
// device priority, creating an empty state for devices with no networks.
var newActiveNetworkStates = [];
this.activeNetworkIds_ = new Set;
var orderedDeviceTypes = [
CrOnc.Type.ETHERNET, CrOnc.Type.WI_FI, CrOnc.Type.CELLULAR,
CrOnc.Type.TETHER, CrOnc.Type.WI_MAX, CrOnc.Type.VPN
];
for (var i = 0; i < orderedDeviceTypes.length; ++i) {
var type = orderedDeviceTypes[i];
var device = newDeviceStates[type];
if (!device)
continue;
var state = activeNetworkStatesByType.get(type) || {GUID: '', Type: type};
if (state.Source === undefined &&
device.State == chrome.networkingPrivate.DeviceStateType.PROHIBITED) {
// Prohibited technologies are enforced by the device policy.
state.Source = CrOnc.Source.DEVICE_POLICY;
}
newActiveNetworkStates.push(state);
this.activeNetworkIds_.add(state.GUID);
}
this.deviceStates = newDeviceStates;
this.networkStateLists_ = newNetworkStateLists;
// Set activeNetworkStates last to rebuild the dom-repeat.
this.activeNetworkStates_ = newActiveNetworkStates;
},
});