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 * Decorate an element as a NetworkListItem.
153 * @param {!Element} el The element to decorate.
155 NetworkListItem.decorate = function(el) {
156 el.__proto__ = NetworkListItem.prototype;
160 NetworkListItem.prototype = {
161 __proto__: ListItem.prototype,
164 * Description of the network group or control.
165 * @type {Object.<string,Object>}
171 * Element for the control's subtitle.
178 * Icon for the network control.
185 * Indicates if in the process of connecting to a network.
192 * Description of the network control.
200 * Text label for the subtitle.
205 this.subtitle_.textContent = text;
206 this.subtitle_.hidden = !text;
210 * URL for the network icon.
213 set iconURL(iconURL) {
214 this.icon_.style.backgroundImage = url(iconURL);
218 * Type of network icon. Each type corresponds to a CSS rule.
222 if (defaultIcons_[type])
223 this.iconURL = defaultIcons_[type];
225 this.icon_.classList.add('network-' + type.toLowerCase());
229 * Indicates if the network is in the process of being connected.
232 set connecting(state) {
233 this.connecting_ = state;
235 this.icon_.classList.add('network-connecting');
237 this.icon_.classList.remove('network-connecting');
241 * Indicates if the network is in the process of being connected.
245 return this.connecting_;
249 * Set the direction of the text.
250 * @param {string} direction The direction of the text, e.g. 'ltr'.
252 setSubtitleDirection: function(direction) {
253 this.subtitle_.dir = direction;
257 * Indicate that the selector arrow should be shown.
259 showSelector: function() {
260 this.subtitle_.classList.add('network-selector');
264 * Adds an indicator to show that the network is policy managed.
266 showManagedNetworkIndicator: function() {
267 this.appendChild(new ManagedNetworkIndicator());
271 decorate: function() {
272 ListItem.prototype.decorate.call(this);
273 this.className = 'network-group';
274 this.icon_ = this.ownerDocument.createElement('div');
275 this.icon_.className = 'network-icon';
276 this.appendChild(this.icon_);
277 var textContent = this.ownerDocument.createElement('div');
278 textContent.className = 'network-group-labels';
279 this.appendChild(textContent);
280 var categoryLabel = this.ownerDocument.createElement('div');
282 if (this.data_.key == 'addConnection')
283 title = 'addConnectionTitle';
285 title = this.data_.key.toLowerCase() + 'Title';
286 categoryLabel.className = 'network-title';
287 categoryLabel.textContent = loadTimeData.getString(title);
288 textContent.appendChild(categoryLabel);
289 this.subtitle_ = this.ownerDocument.createElement('div');
290 this.subtitle_.className = 'network-subtitle';
291 textContent.appendChild(this.subtitle_);
296 * Creates a control that displays a popup menu when clicked.
297 * @param {Object} data Description of the control.
299 * @extends {NetworkListItem}
301 function NetworkMenuItem(data) {
302 var el = new NetworkListItem(data);
303 el.__proto__ = NetworkMenuItem.prototype;
308 NetworkMenuItem.prototype = {
309 __proto__: NetworkListItem.prototype,
312 * Popup menu element.
319 decorate: function() {
320 this.subtitle = null;
321 if (this.data.iconType)
322 this.iconType = this.data.iconType;
323 this.addEventListener('click', function() {
329 * Retrieves the ID for the menu.
331 getMenuName: function() {
332 return this.data_.key.toLowerCase() + '-network-menu';
336 * Creates a popup menu for the control.
337 * @return {Element} The newly created menu.
339 createMenu: function() {
340 if (this.data.menu) {
341 var menu = this.ownerDocument.createElement('div');
342 menu.id = this.getMenuName();
343 menu.className = 'network-menu';
346 for (var i = 0; i < this.data.menu.length; i++) {
347 var entry = this.data.menu[i];
348 createCallback_(menu, null, entry.label, entry.command);
355 canUpdateMenu: function() {
360 * Displays a popup menu.
362 showMenu: function() {
364 // Force a rescan if opening the menu for WiFi networks to ensure the
365 // list is up to date. Networks are periodically rescanned, but depending
366 // on timing, there could be an excessive delay before the first rescan
368 var rescan = !activeMenu_ && this.data_.key == 'WiFi';
371 var existing = $(this.getMenuName());
373 if (this.updateMenu())
377 this.menu_ = this.createMenu();
378 this.menu_.addEventListener('mousedown', function(e) {
379 // Prevent blurring of list, which would close the menu.
382 var parent = $('network-menus');
384 parent.replaceChild(this.menu_, existing);
386 parent.appendChild(this.menu_);
388 var top = this.offsetTop + this.clientHeight;
389 var menuId = this.getMenuName();
390 if (menuId != activeMenu_ || rebuild) {
392 activeMenu_ = menuId;
393 this.menu_.style.setProperty('top', top + 'px');
394 this.menu_.hidden = false;
397 // TODO(stevenjb): chrome.networkingPrivate.requestNetworkScan
398 chrome.send('requestNetworkScan');
404 * Creates a control for selecting or configuring a network connection based
405 * on the type of connection (e.g. wifi versus vpn).
406 * @param {{key: string, networkList: Array.<NetworkInfo>}} data Description
409 * @extends {NetworkMenuItem}
411 function NetworkSelectorItem(data) {
412 var el = new NetworkMenuItem(data);
413 el.__proto__ = NetworkSelectorItem.prototype;
418 NetworkSelectorItem.prototype = {
419 __proto__: NetworkMenuItem.prototype,
422 decorate: function() {
423 // TODO(kevers): Generalize method of setting default label.
424 var policyManaged = false;
425 this.subtitle = loadTimeData.getString('OncConnectionStateNotConnected');
426 var list = this.data_.networkList;
427 var candidateURL = null;
428 for (var i = 0; i < list.length; i++) {
429 var networkDetails = list[i];
430 if (networkDetails.ConnectionState == 'Connecting' ||
431 networkDetails.ConnectionState == 'Connected') {
432 this.subtitle = getNetworkName(networkDetails);
433 this.setSubtitleDirection('ltr');
434 policyManaged = networkDetails.policyManaged;
435 candidateURL = networkDetails.iconURL;
436 // Only break when we see a connecting network as it is possible to
437 // have a connected network and a connecting network at the same
439 if (networkDetails.ConnectionState == 'Connecting') {
440 this.connecting = true;
447 this.iconURL = candidateURL;
449 this.iconType = this.data.key;
454 this.showManagedNetworkIndicator();
456 if (activeMenu_ == this.getMenuName()) {
457 // Menu is already showing and needs to be updated. Explicitly calling
458 // show menu will force the existing menu to be replaced. The call
459 // is deferred in order to ensure that position of this element has
460 // beem properly updated.
462 setTimeout(function() {self.showMenu();}, 0);
467 * Creates a menu for selecting, configuring or disconnecting from a
469 * @return {!Element} The newly created menu.
471 createMenu: function() {
472 var menu = this.ownerDocument.createElement('div');
473 menu.id = this.getMenuName();
474 menu.className = 'network-menu';
478 if (this.data_.key == 'WiFi') {
480 label: loadTimeData.getString('joinOtherNetwork'),
481 command: createAddConnectionCallback_('WiFi'),
484 } else if (this.data_.key == 'Cellular') {
485 if (cellularEnabled_ && cellularSupportsScan_) {
487 label: loadTimeData.getString('otherCellularNetworks'),
488 command: createAddConnectionCallback_('Cellular'),
489 addClass: ['other-cellulars'],
494 var label = enableDataRoaming_ ? 'disableDataRoaming' :
496 var disabled = !loadTimeData.getValue('loggedInAsOwner');
497 var entry = {label: loadTimeData.getString(label),
500 entry.command = null;
502 loadTimeData.getString('dataRoamingDisableToggleTooltip');
505 entry.command = function() {
506 options.Preferences.setBooleanPref(
507 'cros.signed.data_roaming_enabled',
508 !enableDataRoaming_, true);
509 // Force revalidation of the menu the next time it is displayed.
513 addendum.push(entry);
514 } else if (this.data_.key == 'VPN') {
516 label: loadTimeData.getString('joinOtherNetwork'),
517 command: createAddConnectionCallback_('VPN'),
522 var list = this.data.rememberedNetworks;
523 if (list && list.length > 0) {
524 var callback = function(list) {
525 $('remembered-network-list').clear();
526 var dialog = options.PreferredNetworks.getInstance();
527 PageManager.showPageByName('preferredNetworksPage', false);
529 sendChromeMetricsAction('Options_NetworkShowPreferred');
531 addendum.push({label: loadTimeData.getString('preferredNetworks'),
536 var networkGroup = this.ownerDocument.createElement('div');
537 networkGroup.className = 'network-menu-group';
538 list = this.data.networkList;
539 var empty = !list || list.length == 0;
541 var connectedVpnServicePath = '';
542 for (var i = 0; i < list.length; i++) {
544 this.createNetworkOptionsCallback_(networkGroup, data);
545 // For VPN only, append a 'Disconnect' item to the dropdown menu.
546 if (!connectedVpnServicePath && data.Type == 'VPN' &&
547 (data.ConnectionState == 'Connected' ||
548 data.ConnectionState == 'Connecting')) {
549 connectedVpnServicePath = data.servicePath;
552 if (connectedVpnServicePath) {
553 var disconnectCallback = function() {
554 sendChromeMetricsAction('Options_NetworkDisconnectVPN');
555 // TODO(stevenjb): chrome.networkingPrivate.startDisconnect
556 chrome.send('startDisconnect', [connectedVpnServicePath]);
560 addendum.push({label: loadTimeData.getString('disconnectNetwork'),
561 command: disconnectCallback,
565 if (this.data_.key == 'WiFi' || this.data_.key == 'WiMAX' ||
566 this.data_.key == 'Cellular') {
568 if (this.data_.key == 'WiFi') {
570 label: loadTimeData.getString('turnOffWifi'),
571 command: function() {
572 sendChromeMetricsAction('Options_NetworkWifiToggle');
573 // TODO(stevenjb): chrome.networkingPrivate.disableNetworkType
574 chrome.send('disableNetworkType', ['WiFi']);
577 } else if (this.data_.key == 'WiMAX') {
579 label: loadTimeData.getString('turnOffWimax'),
580 command: function() {
581 // TODO(stevenjb): chrome.networkingPrivate.disableNetworkType
582 chrome.send('disableNetworkType', ['WiMAX']);
585 } else if (this.data_.key == 'Cellular') {
587 label: loadTimeData.getString('turnOffCellular'),
588 command: function() {
589 // TODO(stevenjb): chrome.networkingPrivate.disableNetworkType
590 chrome.send('disableNetworkType', ['Cellular']);
596 menu.appendChild(networkGroup);
597 if (addendum.length > 0) {
598 var separator = false;
600 menu.appendChild(MenuItem.createSeparator());
603 for (var i = 0; i < addendum.length; i++) {
604 var value = addendum[i];
606 var item = createCallback_(menu, value.data, value.label,
609 item.title = value.tooltip;
611 item.classList.add(value.addClass);
613 } else if (!separator) {
614 menu.appendChild(MenuItem.createSeparator());
623 * Determines if a menu can be updated on the fly. Menus that cannot be
624 * updated are fully regenerated using createMenu. The advantage of
625 * updating a menu is that it can preserve ordering of networks avoiding
626 * entries from jumping around after an update.
628 canUpdateMenu: function() {
629 return this.data_.key == 'WiFi' && activeMenu_ == this.getMenuName();
633 * Updates an existing menu. Updated menus preserve ordering of prior
634 * entries. During the update process, the ordering may differ from the
635 * preferred ordering as determined by the network library. If the
636 * ordering becomes potentially out of sync, then the updated menu is
637 * marked for disposal on close. Reopening the menu will force a
638 * regeneration, which will in turn fix the ordering.
639 * @return {boolean} True if successfully updated.
641 updateMenu: function() {
642 if (!this.canUpdateMenu())
644 var oldMenu = $(this.getMenuName());
645 var group = oldMenu.getElementsByClassName('network-menu-group')[0];
648 var newMenu = this.createMenu();
649 var discardOnClose = false;
650 var oldNetworkButtons = this.extractNetworkConnectButtons_(oldMenu);
651 var newNetworkButtons = this.extractNetworkConnectButtons_(newMenu);
652 for (var key in oldNetworkButtons) {
653 if (newNetworkButtons[key]) {
654 group.replaceChild(newNetworkButtons[key].button,
655 oldNetworkButtons[key].button);
656 if (newNetworkButtons[key].index != oldNetworkButtons[key].index)
657 discardOnClose = true;
658 newNetworkButtons[key] = null;
660 // Leave item in list to prevent network items from jumping due to
662 oldNetworkButtons[key].disabled = true;
663 discardOnClose = true;
666 for (var key in newNetworkButtons) {
667 var entry = newNetworkButtons[key];
669 group.appendChild(entry.button);
670 discardOnClose = true;
673 oldMenu.data = {discardOnClose: discardOnClose};
678 * Extracts a mapping of network names to menu element and position.
679 * @param {!Element} menu The menu to process.
680 * @return {Object.<string, ?{index: number, button: Element}>}
684 extractNetworkConnectButtons_: function(menu) {
685 var group = menu.getElementsByClassName('network-menu-group')[0];
686 var networkButtons = {};
688 return networkButtons;
689 var buttons = group.getElementsByClassName('network-menu-item');
690 for (var i = 0; i < buttons.length; i++) {
691 var label = buttons[i].data.label;
692 networkButtons[label] = {index: i, button: buttons[i]};
694 return networkButtons;
698 * Adds a menu item for showing network details.
699 * @param {!Element} parent The parent element.
700 * @param {Object} data Description of the network.
703 createNetworkOptionsCallback_: function(parent, data) {
704 var menuItem = createCallback_(parent,
706 getNetworkName(data),
709 if (data.policyManaged)
710 menuItem.appendChild(new ManagedNetworkIndicator());
711 if (data.ConnectionState == 'Connected' ||
712 data.ConnectionState == 'Connecting') {
713 var label = menuItem.getElementsByClassName(
714 'network-menu-item-label')[0];
715 label.classList.add('active-network');
721 * Creates a button-like control for configurating internet connectivity.
722 * @param {{key: string, subtitle: string, command: Function}} data
723 * Description of the network control.
725 * @extends {NetworkListItem}
727 function NetworkButtonItem(data) {
728 var el = new NetworkListItem(data);
729 el.__proto__ = NetworkButtonItem.prototype;
734 NetworkButtonItem.prototype = {
735 __proto__: NetworkListItem.prototype,
738 decorate: function() {
739 if (this.data.subtitle)
740 this.subtitle = this.data.subtitle;
742 this.subtitle = null;
743 if (this.data.command)
744 this.addEventListener('click', this.data.command);
745 if (this.data.iconURL)
746 this.iconURL = this.data.iconURL;
747 else if (this.data.iconType)
748 this.iconType = this.data.iconType;
749 if (this.data.policyManaged)
750 this.showManagedNetworkIndicator();
755 * Adds a command to a menu for modifying network settings.
756 * @param {!Element} menu Parent menu.
757 * @param {Object} data Description of the network.
758 * @param {!string} label Display name for the menu item.
759 * @param {?(string|!Function)} command Callback function or name
760 * of the command for |networkCommand|.
761 * @param {string=} opt_iconURL Optional URL to an icon for the menu item.
762 * @return {!Element} The created menu item.
765 function createCallback_(menu, data, label, command, opt_iconURL) {
766 var button = menu.ownerDocument.createElement('div');
767 button.className = 'network-menu-item';
769 var buttonIcon = menu.ownerDocument.createElement('div');
770 buttonIcon.className = 'network-menu-item-icon';
771 button.appendChild(buttonIcon);
773 buttonIcon.style.backgroundImage = url(opt_iconURL);
775 var buttonLabel = menu.ownerDocument.createElement('span');
776 buttonLabel.className = 'network-menu-item-label';
777 buttonLabel.textContent = label;
778 button.appendChild(buttonLabel);
780 if (typeof command == 'string') {
781 var type = data.Type;
782 var path = data.servicePath;
783 callback = function() {
784 chrome.send('networkCommand', [type, path, command]);
787 } else if (command != null) {
789 callback = function() {
790 (/** @type {Function} */(command))(data);
794 callback = function() {
795 (/** @type {Function} */(command))();
800 if (callback != null)
801 button.addEventListener('click', callback);
803 buttonLabel.classList.add('network-disabled-control');
805 button.data = {label: label};
806 MenuItem.decorate(button);
807 menu.appendChild(button);
812 * A list of controls for manipulating network connectivity.
814 * @extends {cr.ui.List}
816 var NetworkList = cr.ui.define('list');
818 NetworkList.prototype = {
819 __proto__: List.prototype,
822 decorate: function() {
823 List.prototype.decorate.call(this);
824 this.startBatchUpdates();
825 this.autoExpands = true;
826 this.dataModel = new ArrayDataModel([]);
827 this.selectionModel = new ListSingleSelectionModel();
828 this.addEventListener('blur', this.onBlur_.bind(this));
829 this.selectionModel.addEventListener('change',
830 this.onSelectionChange_.bind(this));
832 // Wi-Fi control is always visible.
833 this.update({key: 'WiFi', networkList: []});
836 label: loadTimeData.getString('addConnectionWifi'),
837 command: createAddConnectionCallback_('WiFi')
840 label: loadTimeData.getString('addConnectionVPN'),
841 command: createAddConnectionCallback_('VPN')
843 this.update({key: 'addConnection',
844 iconType: 'add-connection',
845 menu: [entryAddWifi, entryAddVPN]
848 var prefs = options.Preferences.getInstance();
849 prefs.addEventListener('cros.signed.data_roaming_enabled',
851 enableDataRoaming_ = event.value.value;
853 this.endBatchUpdates();
857 * When the list loses focus, unselect all items in the list and close the
861 onBlur_: function() {
862 this.selectionModel.unselectAll();
867 * Close bubble and menu when a different list item is selected.
868 * @param {Event} event Event detailing the selection change.
871 onSelectionChange_: function(event) {
872 PageManager.hideBubble();
873 // A list item may temporarily become unselected while it is constructing
874 // its menu. The menu should therefore only be closed if a different item
875 // is selected, not when the menu's owner item is deselected.
877 for (var i = 0; i < event.changes.length; ++i) {
878 if (event.changes[i].selected) {
879 var item = this.dataModel.item(event.changes[i].index);
880 if (!item.getMenuName || item.getMenuName() != activeMenu_) {
890 * Finds the index of a network item within the data model based on
892 * @param {string} key Unique key for the item in the list.
893 * @return {(number|undefined)} The index of the network item, or
894 * |undefined| if it is not found.
896 indexOf: function(key) {
897 var size = this.dataModel.length;
898 for (var i = 0; i < size; i++) {
899 var entry = this.dataModel.item(i);
900 if (entry.key == key)
907 * Updates a network control.
908 * @param {Object.<string,string>} data Description of the entry.
910 update: function(data) {
911 this.startBatchUpdates();
912 var index = this.indexOf(data.key);
913 if (index == undefined) {
914 // Find reference position for adding the element. We cannot hide
915 // individual list elements, thus we need to conditionally add or
916 // remove elements and cannot rely on any element having a fixed index.
917 for (var i = 0; i < Constants.NETWORK_ORDER.length; i++) {
918 if (data.key == Constants.NETWORK_ORDER[i]) {
923 var referenceIndex = -1;
924 for (var i = 0; i < this.dataModel.length; i++) {
925 var entry = this.dataModel.item(i);
926 if (entry.sortIndex < data.sortIndex)
931 if (referenceIndex == -1) {
932 // Prepend to the start of the list.
933 this.dataModel.splice(0, 0, data);
934 } else if (referenceIndex == this.dataModel.length) {
935 // Append to the end of the list.
936 this.dataModel.push(data);
938 // Insert after the reference element.
939 this.dataModel.splice(referenceIndex + 1, 0, data);
942 var entry = this.dataModel.item(index);
943 data.sortIndex = entry.sortIndex;
944 this.dataModel.splice(index, 1, data);
946 this.endBatchUpdates();
951 * @param {Object} entry
953 createItem: function(entry) {
954 if (entry.networkList)
955 return new NetworkSelectorItem(
956 /** @type {{key: string, networkList: Array.<NetworkInfo>}} */(
959 return new NetworkButtonItem(
960 /** @type {{key: string, subtitle: string, command: Function}} */(
963 return new NetworkMenuItem(entry);
968 * Deletes an element from the list.
969 * @param {string} key Unique identifier for the element.
971 deleteItem: function(key) {
972 var index = this.indexOf(key);
973 if (index != undefined)
974 this.dataModel.splice(index, 1);
978 * Updates the state of a toggle button.
979 * @param {string} key Unique identifier for the element.
980 * @param {boolean} active Whether the control is active.
982 updateToggleControl: function(key, active) {
983 var index = this.indexOf(key);
984 if (index != undefined) {
985 var entry = this.dataModel.item(index);
986 entry.iconType = active ? 'control-active' :
994 * Sets the default icon to use for each network type if disconnected.
995 * @param {!Object.<string, string>} data Mapping of network type to icon
998 NetworkList.setDefaultNetworkIcons = function(data) {
999 defaultIcons_ = Object.create(data);
1003 * Chrome callback for updating network controls.
1004 * @param {{wiredList: Array.<NetworkInfo>, wirelessList: Array.<NetworkInfo>,
1005 * vpnList: Array.<NetworkInfo>, rememberedList: Array.<NetworkInfo>,
1006 * wifiAvailable: boolean, wifiEnabled: boolean, wimaxAvailable: boolean,
1007 * wimaxEnabled: boolean, cellularAvailable: boolean,
1008 * cellularEnabled: boolean, cellularSupportsScan: boolean}} data
1009 * Description of available network devices and their corresponding state.
1011 NetworkList.refreshNetworkData = function(data) {
1012 var networkList = $('network-list');
1013 networkList.startBatchUpdates();
1014 cellularAvailable_ = data.cellularAvailable;
1015 cellularEnabled_ = data.cellularEnabled;
1016 cellularSupportsScan_ = data.cellularSupportsScan;
1017 cellularSimAbsent_ = data.cellularSimAbsent;
1018 cellularSimLockType_ = data.cellularSimLockType;
1019 wimaxAvailable_ = data.wimaxAvailable;
1020 wimaxEnabled_ = data.wimaxEnabled;
1022 // Only show Ethernet control if connected.
1023 var ethernetConnection = getConnection_(data.wiredList);
1024 if (ethernetConnection) {
1025 var type = String('Ethernet');
1026 var path = ethernetConnection.servicePath;
1027 var ethernetOptions = function() {
1028 chrome.send('networkCommand', [type, path, 'showDetails']);
1032 subtitle: loadTimeData.getString('OncConnectionStateConnected'),
1033 iconURL: ethernetConnection.iconURL,
1034 command: ethernetOptions,
1035 policyManaged: ethernetConnection.policyManaged }
1038 networkList.deleteItem('Ethernet');
1041 if (data.wifiEnabled)
1042 loadData_('WiFi', data.wirelessList, data.rememberedList);
1044 addEnableNetworkButton_('WiFi');
1046 // Only show cellular control if available.
1047 if (data.cellularAvailable) {
1048 if (data.cellularEnabled)
1049 loadData_('Cellular', data.wirelessList, data.rememberedList);
1051 addEnableNetworkButton_('Cellular');
1053 networkList.deleteItem('Cellular');
1056 // Only show wimax control if available. Uses cellular icons.
1057 if (data.wimaxAvailable) {
1058 if (data.wimaxEnabled)
1059 loadData_('WiMAX', data.wirelessList, data.rememberedList);
1061 addEnableNetworkButton_('WiMAX');
1063 networkList.deleteItem('WiMAX');
1066 // Only show VPN control if there is at least one VPN configured.
1067 if (data.vpnList.length > 0)
1068 loadData_('VPN', data.vpnList, data.rememberedList);
1070 networkList.deleteItem('VPN');
1071 networkList.endBatchUpdates();
1075 * Replaces a network menu with a button for enabling the network type.
1076 * @param {string} type The type of network (WiFi, Cellular or Wimax).
1079 function addEnableNetworkButton_(type) {
1080 var subtitle = loadTimeData.getString('networkDisabled');
1081 var icon = (type == 'WiMAX') ? 'Cellular' : type;
1082 var enableNetwork = function() {
1084 sendChromeMetricsAction('Options_NetworkWifiToggle');
1085 if (type == 'Cellular') {
1086 if (cellularSimLockType_) {
1087 chrome.send('simOperation', ['unlock']);
1089 } else if (cellularEnabled_ && cellularSimAbsent_) {
1090 chrome.send('simOperation', ['configure']);
1094 // TODO(stevenjb): chrome.networkingPrivate.enableNetworkType
1095 chrome.send('enableNetworkType', [type]);
1097 $('network-list').update({key: type,
1100 command: enableNetwork});
1104 * Element for indicating a policy managed network.
1106 * @extends {options.ControlledSettingIndicator}
1108 function ManagedNetworkIndicator() {
1109 var el = cr.doc.createElement('span');
1110 el.__proto__ = ManagedNetworkIndicator.prototype;
1115 ManagedNetworkIndicator.prototype = {
1116 __proto__: ControlledSettingIndicator.prototype,
1119 decorate: function() {
1120 ControlledSettingIndicator.prototype.decorate.call(this);
1121 this.controlledBy = 'policy';
1122 var policyLabel = loadTimeData.getString('managedNetwork');
1123 this.setAttribute('textPolicy', policyLabel);
1124 this.removeAttribute('tabindex');
1128 handleEvent: function(event) {
1129 // Prevent focus blurring as that would close any currently open menu.
1130 if (event.type == 'mousedown')
1132 ControlledSettingIndicator.prototype.handleEvent.call(this, event);
1136 * Handle mouse events received by the bubble, preventing focus blurring as
1137 * that would close any currently open menu and preventing propagation to
1138 * any elements located behind the bubble.
1139 * @param {Event} event Mouse event.
1141 stopEvent: function(event) {
1142 event.preventDefault();
1143 event.stopPropagation();
1147 toggleBubble: function() {
1148 if (activeMenu_ && !$(activeMenu_).contains(this))
1150 ControlledSettingIndicator.prototype.toggleBubble.call(this);
1151 if (this.showingBubble) {
1152 var bubble = PageManager.getVisibleBubble();
1153 bubble.addEventListener('mousedown', this.stopEvent);
1154 bubble.addEventListener('click', this.stopEvent);
1160 * Updates the list of available networks and their status, filtered by
1162 * @param {string} type The type of network.
1163 * @param {Array} available The list of available networks and their status.
1164 * @param {Array} remembered The list of remmebered networks.
1166 function loadData_(type, available, remembered) {
1167 var data = {key: type};
1168 var availableNetworks = [];
1169 for (var i = 0; i < available.length; i++) {
1170 if (available[i].Type == type)
1171 availableNetworks.push(available[i]);
1173 data.networkList = availableNetworks;
1175 var rememberedNetworks = [];
1176 for (var i = 0; i < remembered.length; i++) {
1177 if (remembered[i].Type == type)
1178 rememberedNetworks.push(remembered[i]);
1180 data.rememberedNetworks = rememberedNetworks;
1182 $('network-list').update(data);
1186 * Hides the currently visible menu.
1189 function closeMenu_() {
1191 var menu = $(activeMenu_);
1193 if (menu.data && menu.data.discardOnClose)
1194 menu.parentNode.removeChild(menu);
1200 * Fetches the active connection.
1201 * @param {Array.<Object>} networkList List of networks.
1205 function getConnection_(networkList) {
1208 for (var i = 0; i < networkList.length; i++) {
1209 var entry = networkList[i];
1210 if (entry.ConnectionState == 'Connected' ||
1211 entry.ConnectionState == 'Connecting')
1218 * Create a callback function that adds a new connection of the given type.
1219 * @param {string} type An ONC network type
1220 * @return {function()} The created callback.
1223 function createAddConnectionCallback_(type) {
1226 sendChromeMetricsAction('Options_NetworkJoinOtherWifi');
1227 else if (type == 'VPN')
1228 sendChromeMetricsAction('Options_NetworkJoinOtherVPN');
1229 chrome.send('networkCommand', [type, '', 'add']);
1234 * Whether the Network list is disabled. Only used for display purpose.
1236 cr.defineProperty(NetworkList, 'disabled', cr.PropertyKind.BOOL_ATTR);
1240 NetworkList: NetworkList