1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 * ConnectionState: string,
9 * policyManaged: boolean,
12 * @see chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
16 cr.define('options.network', function() {
17 var ArrayDataModel = cr.ui.ArrayDataModel;
18 var List = cr.ui.List;
19 var ListItem = cr.ui.ListItem;
20 var ListSingleSelectionModel = cr.ui.ListSingleSelectionModel;
21 var Menu = cr.ui.Menu;
22 var MenuItem = cr.ui.MenuItem;
23 var ControlledSettingIndicator = options.ControlledSettingIndicator;
26 * Network settings constants. These enums usually match their C++
29 function Constants() {}
31 // Cellular activation states:
32 Constants.ACTIVATION_STATE_UNKNOWN = 0;
33 Constants.ACTIVATION_STATE_ACTIVATED = 1;
34 Constants.ACTIVATION_STATE_ACTIVATING = 2;
35 Constants.ACTIVATION_STATE_NOT_ACTIVATED = 3;
36 Constants.ACTIVATION_STATE_PARTIALLY_ACTIVATED = 4;
39 * Order in which controls are to appear in the network list sorted by key.
41 Constants.NETWORK_ORDER = ['Ethernet',
49 * ID of the menu that is currently visible.
53 var activeMenu_ = null;
56 * Indicates if cellular networks are available.
60 var cellularAvailable_ = false;
63 * Indicates if cellular networks are enabled.
67 var cellularEnabled_ = false;
70 * Indicates if cellular device supports network scanning.
74 var cellularSupportsScan_ = false;
77 * Indicates the current SIM lock type of the cellular device.
81 var cellularSimLockType_ = '';
84 * Indicates whether the SIM card is absent on the cellular device.
88 var cellularSimAbsent_ = false;
91 * Indicates if WiMAX networks are available.
95 var wimaxAvailable_ = false;
98 * Indicates if WiMAX networks are enabled.
102 var wimaxEnabled_ = false;
105 * Indicates if mobile data roaming is enabled.
109 var enableDataRoaming_ = false;
112 * Icon to use when not connected to a particular type of network.
113 * @type {!Object.<string, string>} Mapping of network type to icon data url.
116 var defaultIcons_ = {};
119 * Returns the display name for 'network'.
120 * @param {Object} data The network data dictionary.
122 function getNetworkName(data) {
123 if (data.Type == 'Ethernet')
124 return loadTimeData.getString('ethernetName');
129 * Create an element in the network list for controlling network
131 * @param {Object} data Description of the network list or command.
133 * @extends {cr.ui.ListItem}
135 function NetworkListItem(data) {
136 var el = cr.doc.createElement('li');
138 for (var key in data)
139 el.data_[key] = data[key];
140 NetworkListItem.decorate(el);
145 * @param {string} action An action to send to coreOptionsUserMetricsAction.
147 function sendChromeMetricsAction(action) {
148 chrome.send('coreOptionsUserMetricsAction', [action]);
152 * @param {string} servicePath The network service path.
154 function showDetails(servicePath) {
155 // TODO(stevenjb): chrome.networkingPrivate.getManagedProperties
156 // (Note: we will need to provide DetailsInternetPage.initializeDetailsPage
158 chrome.send('getManagedProperties', [servicePath]);
162 * Decorate an element as a NetworkListItem.
163 * @param {!Element} el The element to decorate.
165 NetworkListItem.decorate = function(el) {
166 el.__proto__ = NetworkListItem.prototype;
170 NetworkListItem.prototype = {
171 __proto__: ListItem.prototype,
174 * Description of the network group or control.
175 * @type {Object.<string,Object>}
181 * Element for the control's subtitle.
188 * Icon for the network control.
195 * Indicates if in the process of connecting to a network.
202 * Description of the network control.
210 * Text label for the subtitle.
215 this.subtitle_.textContent = text;
216 this.subtitle_.hidden = !text;
220 * URL for the network icon.
223 set iconURL(iconURL) {
224 this.icon_.style.backgroundImage = url(iconURL);
228 * Type of network icon. Each type corresponds to a CSS rule.
232 if (defaultIcons_[type])
233 this.iconURL = defaultIcons_[type];
235 this.icon_.classList.add('network-' + type.toLowerCase());
239 * Indicates if the network is in the process of being connected.
242 set connecting(state) {
243 this.connecting_ = state;
245 this.icon_.classList.add('network-connecting');
247 this.icon_.classList.remove('network-connecting');
251 * Indicates if the network is in the process of being connected.
255 return this.connecting_;
259 * Set the direction of the text.
260 * @param {string} direction The direction of the text, e.g. 'ltr'.
262 setSubtitleDirection: function(direction) {
263 this.subtitle_.dir = direction;
267 * Indicate that the selector arrow should be shown.
269 showSelector: function() {
270 this.subtitle_.classList.add('network-selector');
274 * Adds an indicator to show that the network is policy managed.
276 showManagedNetworkIndicator: function() {
277 this.appendChild(new ManagedNetworkIndicator());
281 decorate: function() {
282 ListItem.prototype.decorate.call(this);
283 this.className = 'network-group';
284 this.icon_ = this.ownerDocument.createElement('div');
285 this.icon_.className = 'network-icon';
286 this.appendChild(this.icon_);
287 var textContent = this.ownerDocument.createElement('div');
288 textContent.className = 'network-group-labels';
289 this.appendChild(textContent);
290 var categoryLabel = this.ownerDocument.createElement('div');
292 if (this.data_.key == 'addConnection')
293 title = 'addConnectionTitle';
295 title = this.data_.key.toLowerCase() + 'Title';
296 categoryLabel.className = 'network-title';
297 categoryLabel.textContent = loadTimeData.getString(title);
298 textContent.appendChild(categoryLabel);
299 this.subtitle_ = this.ownerDocument.createElement('div');
300 this.subtitle_.className = 'network-subtitle';
301 textContent.appendChild(this.subtitle_);
306 * Creates a control that displays a popup menu when clicked.
307 * @param {Object} data Description of the control.
309 * @extends {NetworkListItem}
311 function NetworkMenuItem(data) {
312 var el = new NetworkListItem(data);
313 el.__proto__ = NetworkMenuItem.prototype;
318 NetworkMenuItem.prototype = {
319 __proto__: NetworkListItem.prototype,
322 * Popup menu element.
329 decorate: function() {
330 this.subtitle = null;
331 if (this.data.iconType)
332 this.iconType = this.data.iconType;
333 this.addEventListener('click', function() {
339 * Retrieves the ID for the menu.
341 getMenuName: function() {
342 return this.data_.key.toLowerCase() + '-network-menu';
346 * Creates a popup menu for the control.
347 * @return {Element} The newly created menu.
349 createMenu: function() {
350 if (this.data.menu) {
351 var menu = this.ownerDocument.createElement('div');
352 menu.id = this.getMenuName();
353 menu.className = 'network-menu';
356 for (var i = 0; i < this.data.menu.length; i++) {
357 var entry = this.data.menu[i];
358 createCallback_(menu, null, entry.label, entry.command);
365 canUpdateMenu: function() {
370 * Displays a popup menu.
372 showMenu: function() {
374 // Force a rescan if opening the menu for WiFi networks to ensure the
375 // list is up to date. Networks are periodically rescanned, but depending
376 // on timing, there could be an excessive delay before the first rescan
378 var rescan = !activeMenu_ && this.data_.key == 'WiFi';
381 var existing = $(this.getMenuName());
383 if (this.updateMenu())
387 this.menu_ = this.createMenu();
388 this.menu_.addEventListener('mousedown', function(e) {
389 // Prevent blurring of list, which would close the menu.
392 var parent = $('network-menus');
394 parent.replaceChild(this.menu_, existing);
396 parent.appendChild(this.menu_);
398 var top = this.offsetTop + this.clientHeight;
399 var menuId = this.getMenuName();
400 if (menuId != activeMenu_ || rebuild) {
402 activeMenu_ = menuId;
403 this.menu_.style.setProperty('top', top + 'px');
404 this.menu_.hidden = false;
407 // TODO(stevenjb): chrome.networkingPrivate.requestNetworkScan
408 chrome.send('requestNetworkScan');
414 * Creates a control for selecting or configuring a network connection based
415 * on the type of connection (e.g. wifi versus vpn).
416 * @param {{key: string, networkList: Array.<NetworkInfo>}} data Description
419 * @extends {NetworkMenuItem}
421 function NetworkSelectorItem(data) {
422 var el = new NetworkMenuItem(data);
423 el.__proto__ = NetworkSelectorItem.prototype;
428 NetworkSelectorItem.prototype = {
429 __proto__: NetworkMenuItem.prototype,
432 decorate: function() {
433 // TODO(kevers): Generalize method of setting default label.
434 var policyManaged = false;
435 this.subtitle = loadTimeData.getString('OncConnectionStateNotConnected');
436 var list = this.data_.networkList;
437 var candidateURL = null;
438 for (var i = 0; i < list.length; i++) {
439 var networkDetails = list[i];
440 if (networkDetails.ConnectionState == 'Connecting' ||
441 networkDetails.ConnectionState == 'Connected') {
442 this.subtitle = getNetworkName(networkDetails);
443 this.setSubtitleDirection('ltr');
444 policyManaged = networkDetails.policyManaged;
445 candidateURL = networkDetails.iconURL;
446 // Only break when we see a connecting network as it is possible to
447 // have a connected network and a connecting network at the same
449 if (networkDetails.ConnectionState == 'Connecting') {
450 this.connecting = true;
457 this.iconURL = candidateURL;
459 this.iconType = this.data.key;
464 this.showManagedNetworkIndicator();
466 if (activeMenu_ == this.getMenuName()) {
467 // Menu is already showing and needs to be updated. Explicitly calling
468 // show menu will force the existing menu to be replaced. The call
469 // is deferred in order to ensure that position of this element has
470 // beem properly updated.
472 setTimeout(function() {self.showMenu();}, 0);
477 * Creates a menu for selecting, configuring or disconnecting from a
479 * @return {!Element} The newly created menu.
481 createMenu: function() {
482 var menu = this.ownerDocument.createElement('div');
483 menu.id = this.getMenuName();
484 menu.className = 'network-menu';
488 if (this.data_.key == 'WiFi') {
490 label: loadTimeData.getString('joinOtherNetwork'),
491 command: createAddConnectionCallback_('WiFi'),
494 } else if (this.data_.key == 'Cellular') {
495 if (cellularEnabled_ && cellularSupportsScan_) {
497 label: loadTimeData.getString('otherCellularNetworks'),
498 command: createAddConnectionCallback_('Cellular'),
499 addClass: ['other-cellulars'],
504 var label = enableDataRoaming_ ? 'disableDataRoaming' :
506 var disabled = !loadTimeData.getValue('loggedInAsOwner');
507 var entry = {label: loadTimeData.getString(label),
510 entry.command = null;
512 loadTimeData.getString('dataRoamingDisableToggleTooltip');
515 entry.command = function() {
516 options.Preferences.setBooleanPref(
517 'cros.signed.data_roaming_enabled',
518 !enableDataRoaming_, true);
519 // Force revalidation of the menu the next time it is displayed.
523 addendum.push(entry);
524 } else if (this.data_.key == 'VPN') {
526 label: loadTimeData.getString('joinOtherNetwork'),
527 command: createAddConnectionCallback_('VPN'),
532 var list = this.data.rememberedNetworks;
533 if (list && list.length > 0) {
534 var callback = function(list) {
535 $('remembered-network-list').clear();
536 var dialog = options.PreferredNetworks.getInstance();
537 PageManager.showPageByName('preferredNetworksPage', false);
539 sendChromeMetricsAction('Options_NetworkShowPreferred');
541 addendum.push({label: loadTimeData.getString('preferredNetworks'),
546 var networkGroup = this.ownerDocument.createElement('div');
547 networkGroup.className = 'network-menu-group';
548 list = this.data.networkList;
549 var empty = !list || list.length == 0;
551 var connectedVpnServicePath = '';
552 for (var i = 0; i < list.length; i++) {
554 this.createNetworkOptionsCallback_(networkGroup, data);
555 // For VPN only, append a 'Disconnect' item to the dropdown menu.
556 if (!connectedVpnServicePath && data.Type == 'VPN' &&
557 (data.ConnectionState == 'Connected' ||
558 data.ConnectionState == 'Connecting')) {
559 connectedVpnServicePath = data.servicePath;
562 if (connectedVpnServicePath) {
563 var disconnectCallback = function() {
564 sendChromeMetricsAction('Options_NetworkDisconnectVPN');
565 // TODO(stevenjb): chrome.networkingPrivate.startDisconnect
566 chrome.send('startDisconnect', [connectedVpnServicePath]);
570 addendum.push({label: loadTimeData.getString('disconnectNetwork'),
571 command: disconnectCallback,
575 if (this.data_.key == 'WiFi' || this.data_.key == 'WiMAX' ||
576 this.data_.key == 'Cellular') {
578 if (this.data_.key == 'WiFi') {
580 label: loadTimeData.getString('turnOffWifi'),
581 command: function() {
582 sendChromeMetricsAction('Options_NetworkWifiToggle');
583 // TODO(stevenjb): chrome.networkingPrivate.disableNetworkType
584 chrome.send('disableNetworkType', ['WiFi']);
587 } else if (this.data_.key == 'WiMAX') {
589 label: loadTimeData.getString('turnOffWimax'),
590 command: function() {
591 // TODO(stevenjb): chrome.networkingPrivate.disableNetworkType
592 chrome.send('disableNetworkType', ['WiMAX']);
595 } else if (this.data_.key == 'Cellular') {
597 label: loadTimeData.getString('turnOffCellular'),
598 command: function() {
599 // TODO(stevenjb): chrome.networkingPrivate.disableNetworkType
600 chrome.send('disableNetworkType', ['Cellular']);
606 menu.appendChild(networkGroup);
607 if (addendum.length > 0) {
608 var separator = false;
610 menu.appendChild(MenuItem.createSeparator());
613 for (var i = 0; i < addendum.length; i++) {
614 var value = addendum[i];
616 var item = createCallback_(menu, value.data, value.label,
619 item.title = value.tooltip;
621 item.classList.add(value.addClass);
623 } else if (!separator) {
624 menu.appendChild(MenuItem.createSeparator());
633 * Determines if a menu can be updated on the fly. Menus that cannot be
634 * updated are fully regenerated using createMenu. The advantage of
635 * updating a menu is that it can preserve ordering of networks avoiding
636 * entries from jumping around after an update.
638 canUpdateMenu: function() {
639 return this.data_.key == 'WiFi' && activeMenu_ == this.getMenuName();
643 * Updates an existing menu. Updated menus preserve ordering of prior
644 * entries. During the update process, the ordering may differ from the
645 * preferred ordering as determined by the network library. If the
646 * ordering becomes potentially out of sync, then the updated menu is
647 * marked for disposal on close. Reopening the menu will force a
648 * regeneration, which will in turn fix the ordering.
649 * @return {boolean} True if successfully updated.
651 updateMenu: function() {
652 if (!this.canUpdateMenu())
654 var oldMenu = $(this.getMenuName());
655 var group = oldMenu.getElementsByClassName('network-menu-group')[0];
658 var newMenu = this.createMenu();
659 var discardOnClose = false;
660 var oldNetworkButtons = this.extractNetworkConnectButtons_(oldMenu);
661 var newNetworkButtons = this.extractNetworkConnectButtons_(newMenu);
662 for (var key in oldNetworkButtons) {
663 if (newNetworkButtons[key]) {
664 group.replaceChild(newNetworkButtons[key].button,
665 oldNetworkButtons[key].button);
666 if (newNetworkButtons[key].index != oldNetworkButtons[key].index)
667 discardOnClose = true;
668 newNetworkButtons[key] = null;
670 // Leave item in list to prevent network items from jumping due to
672 oldNetworkButtons[key].disabled = true;
673 discardOnClose = true;
676 for (var key in newNetworkButtons) {
677 var entry = newNetworkButtons[key];
679 group.appendChild(entry.button);
680 discardOnClose = true;
683 oldMenu.data = {discardOnClose: discardOnClose};
688 * Extracts a mapping of network names to menu element and position.
689 * @param {!Element} menu The menu to process.
690 * @return {Object.<string, ?{index: number, button: Element}>}
694 extractNetworkConnectButtons_: function(menu) {
695 var group = menu.getElementsByClassName('network-menu-group')[0];
696 var networkButtons = {};
698 return networkButtons;
699 var buttons = group.getElementsByClassName('network-menu-item');
700 for (var i = 0; i < buttons.length; i++) {
701 var label = buttons[i].data.label;
702 networkButtons[label] = {index: i, button: buttons[i]};
704 return networkButtons;
708 * Adds a menu item for showing network details.
709 * @param {!Element} parent The parent element.
710 * @param {Object} data Description of the network.
713 createNetworkOptionsCallback_: function(parent, data) {
714 var servicePath = data.servicePath;
715 var menuItem = createCallback_(parent,
717 getNetworkName(data),
718 showDetails.bind(null, servicePath),
720 if (data.policyManaged)
721 menuItem.appendChild(new ManagedNetworkIndicator());
722 if (data.ConnectionState == 'Connected' ||
723 data.ConnectionState == 'Connecting') {
724 var label = menuItem.getElementsByClassName(
725 'network-menu-item-label')[0];
726 label.classList.add('active-network');
732 * Creates a button-like control for configurating internet connectivity.
733 * @param {{key: string, subtitle: string, command: Function}} data
734 * Description of the network control.
736 * @extends {NetworkListItem}
738 function NetworkButtonItem(data) {
739 var el = new NetworkListItem(data);
740 el.__proto__ = NetworkButtonItem.prototype;
745 NetworkButtonItem.prototype = {
746 __proto__: NetworkListItem.prototype,
749 decorate: function() {
750 if (this.data.subtitle)
751 this.subtitle = this.data.subtitle;
753 this.subtitle = null;
754 if (this.data.command)
755 this.addEventListener('click', this.data.command);
756 if (this.data.iconURL)
757 this.iconURL = this.data.iconURL;
758 else if (this.data.iconType)
759 this.iconType = this.data.iconType;
760 if (this.data.policyManaged)
761 this.showManagedNetworkIndicator();
766 * Adds a command to a menu for modifying network settings.
767 * @param {!Element} menu Parent menu.
768 * @param {Object} data Description of the network.
769 * @param {!string} label Display name for the menu item.
770 * @param {!Function} command Callback function.
771 * @param {string=} opt_iconURL Optional URL to an icon for the menu item.
772 * @return {!Element} The created menu item.
775 function createCallback_(menu, data, label, command, opt_iconURL) {
776 var button = menu.ownerDocument.createElement('div');
777 button.className = 'network-menu-item';
779 var buttonIcon = menu.ownerDocument.createElement('div');
780 buttonIcon.className = 'network-menu-item-icon';
781 button.appendChild(buttonIcon);
783 buttonIcon.style.backgroundImage = url(opt_iconURL);
785 var buttonLabel = menu.ownerDocument.createElement('span');
786 buttonLabel.className = 'network-menu-item-label';
787 buttonLabel.textContent = label;
788 button.appendChild(buttonLabel);
790 if (command != null) {
792 callback = function() {
793 (/** @type {Function} */(command))(data);
797 callback = function() {
798 (/** @type {Function} */(command))();
803 if (callback != null)
804 button.addEventListener('click', callback);
806 buttonLabel.classList.add('network-disabled-control');
808 button.data = {label: label};
809 MenuItem.decorate(button);
810 menu.appendChild(button);
815 * A list of controls for manipulating network connectivity.
817 * @extends {cr.ui.List}
819 var NetworkList = cr.ui.define('list');
821 NetworkList.prototype = {
822 __proto__: List.prototype,
825 decorate: function() {
826 List.prototype.decorate.call(this);
827 this.startBatchUpdates();
828 this.autoExpands = true;
829 this.dataModel = new ArrayDataModel([]);
830 this.selectionModel = new ListSingleSelectionModel();
831 this.addEventListener('blur', this.onBlur_.bind(this));
832 this.selectionModel.addEventListener('change',
833 this.onSelectionChange_.bind(this));
835 // Wi-Fi control is always visible.
836 this.update({key: 'WiFi', networkList: []});
839 label: loadTimeData.getString('addConnectionWifi'),
840 command: createAddConnectionCallback_('WiFi')
843 label: loadTimeData.getString('addConnectionVPN'),
844 command: createAddConnectionCallback_('VPN')
846 this.update({key: 'addConnection',
847 iconType: 'add-connection',
848 menu: [entryAddWifi, entryAddVPN]
851 var prefs = options.Preferences.getInstance();
852 prefs.addEventListener('cros.signed.data_roaming_enabled',
854 enableDataRoaming_ = event.value.value;
856 this.endBatchUpdates();
860 * When the list loses focus, unselect all items in the list and close the
864 onBlur_: function() {
865 this.selectionModel.unselectAll();
870 * Close bubble and menu when a different list item is selected.
871 * @param {Event} event Event detailing the selection change.
874 onSelectionChange_: function(event) {
875 PageManager.hideBubble();
876 // A list item may temporarily become unselected while it is constructing
877 // its menu. The menu should therefore only be closed if a different item
878 // is selected, not when the menu's owner item is deselected.
880 for (var i = 0; i < event.changes.length; ++i) {
881 if (event.changes[i].selected) {
882 var item = this.dataModel.item(event.changes[i].index);
883 if (!item.getMenuName || item.getMenuName() != activeMenu_) {
893 * Finds the index of a network item within the data model based on
895 * @param {string} key Unique key for the item in the list.
896 * @return {(number|undefined)} The index of the network item, or
897 * |undefined| if it is not found.
899 indexOf: function(key) {
900 var size = this.dataModel.length;
901 for (var i = 0; i < size; i++) {
902 var entry = this.dataModel.item(i);
903 if (entry.key == key)
910 * Updates a network control.
911 * @param {Object.<string,string>} data Description of the entry.
913 update: function(data) {
914 this.startBatchUpdates();
915 var index = this.indexOf(data.key);
916 if (index == undefined) {
917 // Find reference position for adding the element. We cannot hide
918 // individual list elements, thus we need to conditionally add or
919 // remove elements and cannot rely on any element having a fixed index.
920 for (var i = 0; i < Constants.NETWORK_ORDER.length; i++) {
921 if (data.key == Constants.NETWORK_ORDER[i]) {
926 var referenceIndex = -1;
927 for (var i = 0; i < this.dataModel.length; i++) {
928 var entry = this.dataModel.item(i);
929 if (entry.sortIndex < data.sortIndex)
934 if (referenceIndex == -1) {
935 // Prepend to the start of the list.
936 this.dataModel.splice(0, 0, data);
937 } else if (referenceIndex == this.dataModel.length) {
938 // Append to the end of the list.
939 this.dataModel.push(data);
941 // Insert after the reference element.
942 this.dataModel.splice(referenceIndex + 1, 0, data);
945 var entry = this.dataModel.item(index);
946 data.sortIndex = entry.sortIndex;
947 this.dataModel.splice(index, 1, data);
949 this.endBatchUpdates();
954 * @param {Object} entry
956 createItem: function(entry) {
957 if (entry.networkList)
958 return new NetworkSelectorItem(
959 /** @type {{key: string, networkList: Array.<NetworkInfo>}} */(
962 return new NetworkButtonItem(
963 /** @type {{key: string, subtitle: string, command: Function}} */(
966 return new NetworkMenuItem(entry);
971 * Deletes an element from the list.
972 * @param {string} key Unique identifier for the element.
974 deleteItem: function(key) {
975 var index = this.indexOf(key);
976 if (index != undefined)
977 this.dataModel.splice(index, 1);
981 * Updates the state of a toggle button.
982 * @param {string} key Unique identifier for the element.
983 * @param {boolean} active Whether the control is active.
985 updateToggleControl: function(key, active) {
986 var index = this.indexOf(key);
987 if (index != undefined) {
988 var entry = this.dataModel.item(index);
989 entry.iconType = active ? 'control-active' :
997 * Sets the default icon to use for each network type if disconnected.
998 * @param {!Object.<string, string>} data Mapping of network type to icon
1001 NetworkList.setDefaultNetworkIcons = function(data) {
1002 defaultIcons_ = Object.create(data);
1006 * Chrome callback for updating network controls.
1007 * @param {{cellularAvailable: boolean,
1008 * cellularEnabled: boolean,
1009 * cellularSimAbsent: boolean,
1010 * cellularSimLockType: string,
1011 * cellularSupportsScan: boolean,
1012 * rememberedList: Array.<NetworkInfo>,
1013 * vpnList: Array.<NetworkInfo>,
1014 * wifiAvailable: boolean,
1015 * wifiEnabled: boolean,
1016 * wimaxAvailable: boolean,
1017 * wimaxEnabled: boolean,
1018 * wiredList: Array.<NetworkInfo>,
1019 * wirelessList: Array.<NetworkInfo>}} data Description of available
1020 * network devices and their corresponding state.
1022 NetworkList.refreshNetworkData = function(data) {
1023 var networkList = $('network-list');
1024 networkList.startBatchUpdates();
1025 cellularAvailable_ = data.cellularAvailable;
1026 cellularEnabled_ = data.cellularEnabled;
1027 cellularSupportsScan_ = data.cellularSupportsScan;
1028 cellularSimAbsent_ = data.cellularSimAbsent;
1029 cellularSimLockType_ = data.cellularSimLockType;
1030 wimaxAvailable_ = data.wimaxAvailable;
1031 wimaxEnabled_ = data.wimaxEnabled;
1033 // Only show Ethernet control if connected.
1034 var ethernetConnection = getConnection_(data.wiredList);
1035 if (ethernetConnection) {
1036 var type = String('Ethernet');
1037 var path = ethernetConnection.servicePath;
1038 var ethernetOptions = function() {
1043 subtitle: loadTimeData.getString('OncConnectionStateConnected'),
1044 iconURL: ethernetConnection.iconURL,
1045 command: ethernetOptions,
1046 policyManaged: ethernetConnection.policyManaged }
1049 networkList.deleteItem('Ethernet');
1052 if (data.wifiEnabled)
1053 loadData_('WiFi', data.wirelessList, data.rememberedList);
1055 addEnableNetworkButton_('WiFi');
1057 // Only show cellular control if available.
1058 if (data.cellularAvailable) {
1059 if (data.cellularEnabled)
1060 loadData_('Cellular', data.wirelessList, data.rememberedList);
1062 addEnableNetworkButton_('Cellular');
1064 networkList.deleteItem('Cellular');
1067 // Only show wimax control if available. Uses cellular icons.
1068 if (data.wimaxAvailable) {
1069 if (data.wimaxEnabled)
1070 loadData_('WiMAX', data.wirelessList, data.rememberedList);
1072 addEnableNetworkButton_('WiMAX');
1074 networkList.deleteItem('WiMAX');
1077 // Only show VPN control if there is at least one VPN configured.
1078 if (data.vpnList.length > 0)
1079 loadData_('VPN', data.vpnList, data.rememberedList);
1081 networkList.deleteItem('VPN');
1082 networkList.endBatchUpdates();
1086 * Replaces a network menu with a button for enabling the network type.
1087 * @param {string} type The type of network (WiFi, Cellular or Wimax).
1090 function addEnableNetworkButton_(type) {
1091 var subtitle = loadTimeData.getString('networkDisabled');
1092 var icon = (type == 'WiMAX') ? 'Cellular' : type;
1093 var enableNetwork = function() {
1095 sendChromeMetricsAction('Options_NetworkWifiToggle');
1096 if (type == 'Cellular') {
1097 if (cellularSimLockType_) {
1098 chrome.send('simOperation', ['unlock']);
1100 } else if (cellularEnabled_ && cellularSimAbsent_) {
1101 chrome.send('simOperation', ['configure']);
1105 // TODO(stevenjb): chrome.networkingPrivate.enableNetworkType
1106 chrome.send('enableNetworkType', [type]);
1108 $('network-list').update({key: type,
1111 command: enableNetwork});
1115 * Element for indicating a policy managed network.
1117 * @extends {options.ControlledSettingIndicator}
1119 function ManagedNetworkIndicator() {
1120 var el = cr.doc.createElement('span');
1121 el.__proto__ = ManagedNetworkIndicator.prototype;
1126 ManagedNetworkIndicator.prototype = {
1127 __proto__: ControlledSettingIndicator.prototype,
1130 decorate: function() {
1131 ControlledSettingIndicator.prototype.decorate.call(this);
1132 this.controlledBy = 'policy';
1133 var policyLabel = loadTimeData.getString('managedNetwork');
1134 this.setAttribute('textPolicy', policyLabel);
1135 this.removeAttribute('tabindex');
1139 handleEvent: function(event) {
1140 // Prevent focus blurring as that would close any currently open menu.
1141 if (event.type == 'mousedown')
1143 ControlledSettingIndicator.prototype.handleEvent.call(this, event);
1147 * Handle mouse events received by the bubble, preventing focus blurring as
1148 * that would close any currently open menu and preventing propagation to
1149 * any elements located behind the bubble.
1150 * @param {Event} event Mouse event.
1152 stopEvent: function(event) {
1153 event.preventDefault();
1154 event.stopPropagation();
1158 toggleBubble: function() {
1159 if (activeMenu_ && !$(activeMenu_).contains(this))
1161 ControlledSettingIndicator.prototype.toggleBubble.call(this);
1162 if (this.showingBubble) {
1163 var bubble = PageManager.getVisibleBubble();
1164 bubble.addEventListener('mousedown', this.stopEvent);
1165 bubble.addEventListener('click', this.stopEvent);
1171 * Updates the list of available networks and their status, filtered by
1173 * @param {string} type The type of network.
1174 * @param {Array} available The list of available networks and their status.
1175 * @param {Array} remembered The list of remmebered networks.
1177 function loadData_(type, available, remembered) {
1178 var data = {key: type};
1179 var availableNetworks = [];
1180 for (var i = 0; i < available.length; i++) {
1181 if (available[i].Type == type)
1182 availableNetworks.push(available[i]);
1184 data.networkList = availableNetworks;
1186 var rememberedNetworks = [];
1187 for (var i = 0; i < remembered.length; i++) {
1188 if (remembered[i].Type == type)
1189 rememberedNetworks.push(remembered[i]);
1191 data.rememberedNetworks = rememberedNetworks;
1193 $('network-list').update(data);
1197 * Hides the currently visible menu.
1200 function closeMenu_() {
1202 var menu = $(activeMenu_);
1204 if (menu.data && menu.data.discardOnClose)
1205 menu.parentNode.removeChild(menu);
1211 * Fetches the active connection.
1212 * @param {Array.<Object>} networkList List of networks.
1216 function getConnection_(networkList) {
1219 for (var i = 0; i < networkList.length; i++) {
1220 var entry = networkList[i];
1221 if (entry.ConnectionState == 'Connected' ||
1222 entry.ConnectionState == 'Connecting')
1229 * Create a callback function that adds a new connection of the given type.
1230 * @param {string} type An ONC network type
1231 * @return {function()} The created callback.
1234 function createAddConnectionCallback_(type) {
1237 sendChromeMetricsAction('Options_NetworkJoinOtherWifi');
1238 else if (type == 'VPN')
1239 sendChromeMetricsAction('Options_NetworkJoinOtherVPN');
1240 chrome.send('addConnection', [type]);
1245 * Whether the Network list is disabled. Only used for display purpose.
1247 cr.defineProperty(NetworkList, 'disabled', cr.PropertyKind.BOOL_ATTR);
1251 NetworkList: NetworkList