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.
5 cr.define('options.network', function() {
7 var ArrayDataModel = cr.ui.ArrayDataModel;
9 var ListItem = cr.ui.ListItem;
10 var ListSingleSelectionModel = cr.ui.ListSingleSelectionModel;
11 var Menu = cr.ui.Menu;
12 var MenuItem = cr.ui.MenuItem;
13 var ControlledSettingIndicator = options.ControlledSettingIndicator;
16 * Network settings constants. These enums usually match their C++
19 function Constants() {}
22 Constants.TYPE_UNKNOWN = 'UNKNOWN';
23 Constants.TYPE_ETHERNET = 'ethernet';
24 Constants.TYPE_WIFI = 'wifi';
25 Constants.TYPE_WIMAX = 'wimax';
26 Constants.TYPE_BLUETOOTH = 'bluetooth';
27 Constants.TYPE_CELLULAR = 'cellular';
28 Constants.TYPE_VPN = 'vpn';
30 // Cellular activation states:
31 Constants.ACTIVATION_STATE_UNKNOWN = 0;
32 Constants.ACTIVATION_STATE_ACTIVATED = 1;
33 Constants.ACTIVATION_STATE_ACTIVATING = 2;
34 Constants.ACTIVATION_STATE_NOT_ACTIVATED = 3;
35 Constants.ACTIVATION_STATE_PARTIALLY_ACTIVATED = 4;
38 * Order in which controls are to appear in the network list sorted by key.
40 Constants.NETWORK_ORDER = ['ethernet',
48 * Mapping of network category titles to the network type.
51 'cellular': Constants.TYPE_CELLULAR,
52 'ethernet': Constants.TYPE_ETHERNET,
53 'wimax': Constants.TYPE_WIMAX,
54 'wifi': Constants.TYPE_WIFI,
55 'vpn': Constants.TYPE_VPN
59 * ID of the menu that is currently visible.
63 var activeMenu_ = null;
66 * Indicates if cellular networks are available.
70 var cellularAvailable_ = false;
73 * Indicates if cellular networks are enabled.
77 var cellularEnabled_ = false;
80 * Indicates if cellular device supports network scanning.
84 var cellularSupportsScan_ = false;
87 * Indicates if WiMAX networks are available.
91 var wimaxAvailable_ = false;
94 * Indicates if WiMAX networks are enabled.
98 var wimaxEnabled_ = false;
101 * Indicates if mobile data roaming is enabled.
105 var enableDataRoaming_ = false;
108 * Icon to use when not connected to a particular type of network.
109 * @type {!Object.<string, string>} Mapping of network type to icon data url.
112 var defaultIcons_ = {};
115 * Contains the current logged in user type, which is one of 'none',
116 * 'regular', 'owner', 'guest', 'retail-mode', 'public-account',
117 * 'locally-managed', and 'kiosk-app', or empty string if the data has not
122 var loggedInUserType_ = '';
125 * Create an element in the network list for controlling network
127 * @param {Object} data Description of the network list or command.
130 function NetworkListItem(data) {
131 var el = cr.doc.createElement('li');
133 for (var key in data)
134 el.data_[key] = data[key];
135 NetworkListItem.decorate(el);
140 * Decorate an element as a NetworkListItem.
141 * @param {!Element} el The element to decorate.
143 NetworkListItem.decorate = function(el) {
144 el.__proto__ = NetworkListItem.prototype;
148 NetworkListItem.prototype = {
149 __proto__: ListItem.prototype,
152 * Description of the network group or control.
153 * @type {Object.<string,Object>}
159 * Element for the control's subtitle.
166 * Icon for the network control.
173 * Indicates if in the process of connecting to a network.
180 * Description of the network control.
188 * Text label for the subtitle.
193 this.subtitle_.textContent = text;
194 this.subtitle_.hidden = !text;
198 * URL for the network icon.
201 set iconURL(iconURL) {
202 this.icon_.style.backgroundImage = url(iconURL);
206 * Type of network icon. Each type corresponds to a CSS rule.
210 if (defaultIcons_[type])
211 this.iconURL = defaultIcons_[type];
213 this.icon_.classList.add('network-' + type);
217 * Indicates if the network is in the process of being connected.
220 set connecting(state) {
221 this.connecting_ = state;
223 this.icon_.classList.add('network-connecting');
225 this.icon_.classList.remove('network-connecting');
229 * Indicates if the network is in the process of being connected.
233 return this.connecting_;
237 * Set the direction of the text.
238 * @param {string} direction The direction of the text, e.g. 'ltr'.
240 setSubtitleDirection: function(direction) {
241 this.subtitle_.dir = direction;
245 * Indicate that the selector arrow should be shown.
247 showSelector: function() {
248 this.subtitle_.classList.add('network-selector');
252 * Adds an indicator to show that the network is policy managed.
254 showManagedNetworkIndicator: function() {
255 this.appendChild(new ManagedNetworkIndicator());
259 decorate: function() {
260 ListItem.prototype.decorate.call(this);
261 this.className = 'network-group';
262 this.icon_ = this.ownerDocument.createElement('div');
263 this.icon_.className = 'network-icon';
264 this.appendChild(this.icon_);
265 var textContent = this.ownerDocument.createElement('div');
266 textContent.className = 'network-group-labels';
267 this.appendChild(textContent);
268 var categoryLabel = this.ownerDocument.createElement('div');
269 var title = this.data_.key + 'Title';
270 categoryLabel.className = 'network-title';
271 categoryLabel.textContent = loadTimeData.getString(title);
272 textContent.appendChild(categoryLabel);
273 this.subtitle_ = this.ownerDocument.createElement('div');
274 this.subtitle_.className = 'network-subtitle';
275 textContent.appendChild(this.subtitle_);
280 * Creates a control that displays a popup menu when clicked.
281 * @param {Object} data Description of the control.
283 function NetworkMenuItem(data) {
284 var el = new NetworkListItem(data);
285 el.__proto__ = NetworkMenuItem.prototype;
290 NetworkMenuItem.prototype = {
291 __proto__: NetworkListItem.prototype,
294 * Popup menu element.
301 decorate: function() {
302 this.subtitle = null;
303 if (this.data.iconType)
304 this.iconType = this.data.iconType;
305 this.addEventListener('click', function() {
311 * Retrieves the ID for the menu.
313 getMenuName: function() {
314 return this.data_.key + '-network-menu';
318 * Creates a popup menu for the control.
319 * @return {Element} The newly created menu.
321 createMenu: function() {
322 if (this.data.menu) {
323 var menu = this.ownerDocument.createElement('div');
324 menu.id = this.getMenuName();
325 menu.className = 'network-menu';
328 for (var i = 0; i < this.data.menu.length; i++) {
329 var entry = this.data.menu[i];
330 createCallback_(menu, null, entry.label, entry.command);
337 canUpdateMenu: function() {
342 * Displays a popup menu.
344 showMenu: function() {
346 // Force a rescan if opening the menu for WiFi networks to ensure the
347 // list is up to date. Networks are periodically rescanned, but depending
348 // on timing, there could be an excessive delay before the first rescan
350 var rescan = !activeMenu_ && this.data_.key == 'wifi';
353 var existing = $(this.getMenuName());
355 if (this.updateMenu())
359 this.menu_ = this.createMenu();
360 this.menu_.addEventListener('mousedown', function(e) {
361 // Prevent blurring of list, which would close the menu.
364 var parent = $('network-menus');
366 parent.replaceChild(this.menu_, existing);
368 parent.appendChild(this.menu_);
370 var top = this.offsetTop + this.clientHeight;
371 var menuId = this.getMenuName();
372 if (menuId != activeMenu_ || rebuild) {
374 activeMenu_ = menuId;
375 this.menu_.style.setProperty('top', top + 'px');
376 this.menu_.hidden = false;
379 chrome.send('refreshNetworks');
384 * Creates a control for selecting or configuring a network connection based
385 * on the type of connection (e.g. wifi versus vpn).
386 * @param {{key: string,
387 * networkList: Array.<Object>} data Description of the network.
390 function NetworkSelectorItem(data) {
391 var el = new NetworkMenuItem(data);
392 el.__proto__ = NetworkSelectorItem.prototype;
397 NetworkSelectorItem.prototype = {
398 __proto__: NetworkMenuItem.prototype,
401 decorate: function() {
402 // TODO(kevers): Generalize method of setting default label.
403 var policyManaged = false;
404 var defaultMessage = this.data_.key == 'wifi' ?
405 'networkOffline' : 'networkNotConnected';
406 this.subtitle = loadTimeData.getString(defaultMessage);
407 var list = this.data_.networkList;
408 var candidateURL = null;
409 for (var i = 0; i < list.length; i++) {
410 var networkDetails = list[i];
411 if (networkDetails.connecting || networkDetails.connected) {
412 this.subtitle = networkDetails.networkName;
413 this.setSubtitleDirection('ltr');
414 policyManaged = networkDetails.policyManaged;
415 candidateURL = networkDetails.iconURL;
416 // Only break when we see a connecting network as it is possible to
417 // have a connected network and a connecting network at the same
419 if (networkDetails.connecting) {
420 this.connecting = true;
427 this.iconURL = candidateURL;
429 this.iconType = this.data.key;
434 this.showManagedNetworkIndicator();
436 if (activeMenu_ == this.getMenuName()) {
437 // Menu is already showing and needs to be updated. Explicitly calling
438 // show menu will force the existing menu to be replaced. The call
439 // is deferred in order to ensure that position of this element has
440 // beem properly updated.
442 setTimeout(function() {self.showMenu();}, 0);
447 * Creates a menu for selecting, configuring or disconnecting from a
449 * @return {Element} The newly created menu.
451 createMenu: function() {
452 var menu = this.ownerDocument.createElement('div');
453 menu.id = this.getMenuName();
454 menu.className = 'network-menu';
458 if (this.data_.key == 'wifi') {
459 addendum.push({label: loadTimeData.getString('joinOtherNetwork'),
461 data: {networkType: Constants.TYPE_WIFI,
463 } else if (this.data_.key == 'cellular') {
464 if (cellularEnabled_ && cellularSupportsScan_) {
466 label: loadTimeData.getString('otherCellularNetworks'),
467 command: createAddConnectionCallback_(Constants.TYPE_CELLULAR),
468 addClass: ['other-cellulars'],
471 addendum.push(entry);
474 var label = enableDataRoaming_ ? 'disableDataRoaming' :
476 var disabled = loggedInUserType_ != 'owner';
477 var entry = {label: loadTimeData.getString(label),
480 entry.command = null;
482 loadTimeData.getString('dataRoamingDisableToggleTooltip');
485 entry.command = function() {
486 options.Preferences.setBooleanPref(
487 'cros.signed.data_roaming_enabled',
488 !enableDataRoaming_, true);
489 // Force revalidation of the menu the next time it is displayed.
493 addendum.push(entry);
495 var list = this.data.rememberedNetworks;
496 if (list && list.length > 0) {
497 var callback = function(list) {
498 $('remembered-network-list').clear();
499 var dialog = options.PreferredNetworks.getInstance();
500 OptionsPage.showPageByName('preferredNetworksPage', false);
502 chrome.send('coreOptionsUserMetricsAction',
503 ['Options_NetworkShowPreferred']);
505 addendum.push({label: loadTimeData.getString('preferredNetworks'),
510 var networkGroup = this.ownerDocument.createElement('div');
511 networkGroup.className = 'network-menu-group';
512 list = this.data.networkList;
513 var empty = !list || list.length == 0;
515 for (var i = 0; i < list.length; i++) {
517 this.createNetworkOptionsCallback_(networkGroup, data);
518 if (data.connected) {
519 if (data.networkType == Constants.TYPE_VPN) {
522 var i18nKey = 'disconnectNetwork';
523 addendum.push({label: loadTimeData.getString(i18nKey),
524 command: 'disconnect',
530 if (this.data_.key == 'wifi' || this.data_.key == 'wimax' ||
531 this.data_.key == 'cellular') {
533 if (this.data_.key == 'wifi') {
534 addendum.push({label: loadTimeData.getString('turnOffWifi'),
535 command: function() {
536 chrome.send('disableWifi');
539 } else if (this.data_.key == 'wimax') {
540 addendum.push({label: loadTimeData.getString('turnOffWimax'),
541 command: function() {
542 chrome.send('disableWimax');
545 } else if (this.data_.key == 'cellular') {
546 addendum.push({label: loadTimeData.getString('turnOffCellular'),
547 command: function() {
548 chrome.send('disableCellular');
554 menu.appendChild(networkGroup);
555 if (addendum.length > 0) {
556 var separator = false;
558 menu.appendChild(MenuItem.createSeparator());
561 for (var i = 0; i < addendum.length; i++) {
562 var value = addendum[i];
564 var item = createCallback_(menu, value.data, value.label,
567 item.title = value.tooltip;
569 item.classList.add(value.addClass);
571 } else if (!separator) {
572 menu.appendChild(MenuItem.createSeparator());
581 * Determines if a menu can be updated on the fly. Menus that cannot be
582 * updated are fully regenerated using createMenu. The advantage of
583 * updating a menu is that it can preserve ordering of networks avoiding
584 * entries from jumping around after an update.
586 canUpdateMenu: function() {
587 return this.data_.key == 'wifi' && activeMenu_ == this.getMenuName();
591 * Updates an existing menu. Updated menus preserve ordering of prior
592 * entries. During the update process, the ordering may differ from the
593 * preferred ordering as determined by the network library. If the
594 * ordering becomes potentially out of sync, then the updated menu is
595 * marked for disposal on close. Reopening the menu will force a
596 * regeneration, which will in turn fix the ordering.
597 * @return {boolean} True if successfully updated.
599 updateMenu: function() {
600 if (!this.canUpdateMenu())
602 var oldMenu = $(this.getMenuName());
603 var group = oldMenu.getElementsByClassName('network-menu-group')[0];
606 var newMenu = this.createMenu();
607 var discardOnClose = false;
608 var oldNetworkButtons = this.extractNetworkConnectButtons_(oldMenu);
609 var newNetworkButtons = this.extractNetworkConnectButtons_(newMenu);
610 for (var key in oldNetworkButtons) {
611 if (newNetworkButtons[key]) {
612 group.replaceChild(newNetworkButtons[key].button,
613 oldNetworkButtons[key].button);
614 if (newNetworkButtons[key].index != oldNetworkButtons[key].index)
615 discardOnClose = true;
616 newNetworkButtons[key] = null;
618 // Leave item in list to prevent network items from jumping due to
620 oldNetworkButtons[key].disabled = true;
621 discardOnClose = true;
624 for (var key in newNetworkButtons) {
625 var entry = newNetworkButtons[key];
627 group.appendChild(entry.button);
628 discardOnClose = true;
631 oldMenu.data = {discardOnClose: discardOnClose};
636 * Extracts a mapping of network names to menu element and position.
637 * @param {!Element} menu The menu to process.
638 * @return {Object.<string, Element>} Network mapping.
641 extractNetworkConnectButtons_: function(menu) {
642 var group = menu.getElementsByClassName('network-menu-group')[0];
643 var networkButtons = {};
645 return networkButtons;
646 var buttons = group.getElementsByClassName('network-menu-item');
647 for (var i = 0; i < buttons.length; i++) {
648 var label = buttons[i].data.label;
649 networkButtons[label] = {index: i, button: buttons[i]};
651 return networkButtons;
655 * Adds a menu item for showing network details.
656 * @param {!Element} parent The parent element.
657 * @param {Object} data Description of the network.
660 createNetworkOptionsCallback_: function(parent, data) {
661 var menuItem = createCallback_(parent,
666 if (data.policyManaged)
667 menuItem.appendChild(new ManagedNetworkIndicator());
668 if (data.connected || data.connecting) {
669 var label = menuItem.getElementsByClassName(
670 'network-menu-item-label')[0];
671 label.classList.add('active-network');
677 * Creates a button-like control for configurating internet connectivity.
678 * @param {{key: string,
680 * command: function} data Description of the network control.
683 function NetworkButtonItem(data) {
684 var el = new NetworkListItem(data);
685 el.__proto__ = NetworkButtonItem.prototype;
690 NetworkButtonItem.prototype = {
691 __proto__: NetworkListItem.prototype,
694 decorate: function() {
695 if (this.data.subtitle)
696 this.subtitle = this.data.subtitle;
698 this.subtitle = null;
699 if (this.data.command)
700 this.addEventListener('click', this.data.command);
701 if (this.data.iconURL)
702 this.iconURL = this.data.iconURL;
703 else if (this.data.iconType)
704 this.iconType = this.data.iconType;
705 if (this.data.policyManaged)
706 this.showManagedNetworkIndicator();
711 * Adds a command to a menu for modifying network settings.
712 * @param {!Element} menu Parent menu.
713 * @param {!Object} data Description of the network.
714 * @param {!string} label Display name for the menu item.
715 * @param {?(string|function)} command Callback function or name
716 * of the command for |networkCommand|.
717 * @param {?string=} opt_iconURL Optional URL to an icon for the menu item.
718 * @return {!Element} The created menu item.
721 function createCallback_(menu, data, label, command, opt_iconURL) {
722 var button = menu.ownerDocument.createElement('div');
723 button.className = 'network-menu-item';
725 var buttonIcon = menu.ownerDocument.createElement('div');
726 buttonIcon.className = 'network-menu-item-icon';
727 button.appendChild(buttonIcon);
729 buttonIcon.style.backgroundImage = url(opt_iconURL);
731 var buttonLabel = menu.ownerDocument.createElement('span');
732 buttonLabel.className = 'network-menu-item-label';
733 buttonLabel.textContent = label;
734 button.appendChild(buttonLabel);
736 if (typeof command == 'string') {
737 var type = data.networkType;
738 var path = data.servicePath;
739 callback = function() {
740 chrome.send('networkCommand',
741 [type, path, command]);
744 } else if (command != null) {
746 callback = function() {
751 callback = function() {
757 if (callback != null)
758 button.addEventListener('click', callback);
760 buttonLabel.classList.add('network-disabled-control');
762 button.data = {label: label};
763 MenuItem.decorate(button);
764 menu.appendChild(button);
769 * A list of controls for manipulating network connectivity.
772 var NetworkList = cr.ui.define('list');
774 NetworkList.prototype = {
775 __proto__: List.prototype,
778 decorate: function() {
779 List.prototype.decorate.call(this);
780 this.startBatchUpdates();
781 this.autoExpands = true;
782 this.dataModel = new ArrayDataModel([]);
783 this.selectionModel = new ListSingleSelectionModel();
784 this.addEventListener('blur', this.onBlur_.bind(this));
785 this.selectionModel.addEventListener('change',
786 this.onSelectionChange_.bind(this));
788 // Wi-Fi control is always visible.
789 this.update({key: 'wifi', networkList: []});
792 label: loadTimeData.getString('addConnectionWifi'),
793 command: createAddConnectionCallback_(Constants.TYPE_WIFI)
796 label: loadTimeData.getString('addConnectionVPN'),
797 command: createAddConnectionCallback_(Constants.TYPE_VPN)
799 this.update({key: 'addConnection',
800 iconType: 'add-connection',
801 menu: [entryAddWifi, entryAddVPN]
804 var prefs = options.Preferences.getInstance();
805 prefs.addEventListener('cros.signed.data_roaming_enabled',
807 enableDataRoaming_ = event.value.value;
809 this.endBatchUpdates();
813 * When the list loses focus, unselect all items in the list and close the
817 onBlur_: function() {
818 this.selectionModel.unselectAll();
823 * Close bubble and menu when a different list item is selected.
824 * @param {Event} event Event detailing the selection change.
827 onSelectionChange_: function(event) {
828 OptionsPage.hideBubble();
829 // A list item may temporarily become unselected while it is constructing
830 // its menu. The menu should therefore only be closed if a different item
831 // is selected, not when the menu's owner item is deselected.
833 for (var i = 0; i < event.changes.length; ++i) {
834 if (event.changes[i].selected) {
835 var item = this.dataModel.item(event.changes[i].index);
836 if (!item.getMenuName || item.getMenuName() != activeMenu_) {
846 * Finds the index of a network item within the data model based on
848 * @param {string} key Unique key for the item in the list.
849 * @return {number} The index of the network item, or |undefined| if it is
852 indexOf: function(key) {
853 var size = this.dataModel.length;
854 for (var i = 0; i < size; i++) {
855 var entry = this.dataModel.item(i);
856 if (entry.key == key)
862 * Updates a network control.
863 * @param {Object.<string,string>} data Description of the entry.
865 update: function(data) {
866 this.startBatchUpdates();
867 var index = this.indexOf(data.key);
868 if (index == undefined) {
869 // Find reference position for adding the element. We cannot hide
870 // individual list elements, thus we need to conditionally add or
871 // remove elements and cannot rely on any element having a fixed index.
872 for (var i = 0; i < Constants.NETWORK_ORDER.length; i++) {
873 if (data.key == Constants.NETWORK_ORDER[i]) {
878 var referenceIndex = -1;
879 for (var i = 0; i < this.dataModel.length; i++) {
880 var entry = this.dataModel.item(i);
881 if (entry.sortIndex < data.sortIndex)
886 if (referenceIndex == -1) {
887 // Prepend to the start of the list.
888 this.dataModel.splice(0, 0, data);
889 } else if (referenceIndex == this.dataModel.length) {
890 // Append to the end of the list.
891 this.dataModel.push(data);
893 // Insert after the reference element.
894 this.dataModel.splice(referenceIndex + 1, 0, data);
897 var entry = this.dataModel.item(index);
898 data.sortIndex = entry.sortIndex;
899 this.dataModel.splice(index, 1, data);
901 this.endBatchUpdates();
905 createItem: function(entry) {
906 if (entry.networkList)
907 return new NetworkSelectorItem(entry);
909 return new NetworkButtonItem(entry);
911 return new NetworkMenuItem(entry);
915 * Deletes an element from the list.
916 * @param {string} key Unique identifier for the element.
918 deleteItem: function(key) {
919 var index = this.indexOf(key);
920 if (index != undefined)
921 this.dataModel.splice(index, 1);
925 * Updates the state of a toggle button.
926 * @param {string} key Unique identifier for the element.
927 * @param {boolean} active Whether the control is active.
929 updateToggleControl: function(key, active) {
930 var index = this.indexOf(key);
931 if (index != undefined) {
932 var entry = this.dataModel.item(index);
933 entry.iconType = active ? 'control-active' :
941 * Sets the default icon to use for each network type if disconnected.
942 * @param {!Object.<string, string>} data Mapping of network type to icon
945 NetworkList.setDefaultNetworkIcons = function(data) {
946 defaultIcons_ = Object.create(data);
950 * Sets the current logged in user type.
951 * @param {string} userType Current logged in user type.
953 NetworkList.updateLoggedInUserType = function(userType) {
954 loggedInUserType_ = String(userType);
958 * Chrome callback for updating network controls.
959 * @param {Object} data Description of available network devices and their
960 * corresponding state.
962 NetworkList.refreshNetworkData = function(data) {
963 var networkList = $('network-list');
964 networkList.startBatchUpdates();
965 cellularAvailable_ = data.cellularAvailable;
966 cellularEnabled_ = data.cellularEnabled;
967 cellularSupportsScan_ = data.cellularSupportsScan;
968 wimaxAvailable_ = data.wimaxAvailable;
969 wimaxEnabled_ = data.wimaxEnabled;
971 // Only show Ethernet control if connected.
972 var ethernetConnection = getConnection_(data.wiredList);
973 if (ethernetConnection) {
974 var type = String(Constants.TYPE_ETHERNET);
975 var path = ethernetConnection.servicePath;
976 var ethernetOptions = function() {
977 chrome.send('networkCommand',
978 [type, path, 'options']);
980 networkList.update({key: 'ethernet',
981 subtitle: loadTimeData.getString('networkConnected'),
982 iconURL: ethernetConnection.iconURL,
983 command: ethernetOptions,
984 policyManaged: ethernetConnection.policyManaged});
986 networkList.deleteItem('ethernet');
989 if (data.wifiEnabled)
990 loadData_('wifi', data.wirelessList, data.rememberedList);
992 addEnableNetworkButton_('wifi', 'enableWifi', 'wifi');
994 // Only show cellular control if available.
995 if (data.cellularAvailable) {
996 if (data.cellularEnabled)
997 loadData_('cellular', data.wirelessList, data.rememberedList);
999 addEnableNetworkButton_('cellular', 'enableCellular', 'cellular');
1001 networkList.deleteItem('cellular');
1004 // Only show cellular control if available.
1005 if (data.wimaxAvailable) {
1006 if (data.wimaxEnabled)
1007 loadData_('wimax', data.wirelessList, data.rememberedList);
1009 addEnableNetworkButton_('wimax', 'enableWimax', 'cellular');
1011 networkList.deleteItem('wimax');
1014 // Only show VPN control if there is at least one VPN configured.
1015 if (data.vpnList.length > 0)
1016 loadData_('vpn', data.vpnList, data.rememberedList);
1018 networkList.deleteItem('vpn');
1019 networkList.endBatchUpdates();
1023 * Replaces a network menu with a button for reenabling the type of network.
1024 * @param {string} name The type of network (wifi, cellular or wimax).
1025 * @param {string} command The command for reenabling the network.
1026 * @param {string} type of icon (wifi or cellular).
1029 function addEnableNetworkButton_(name, command, icon) {
1030 var subtitle = loadTimeData.getString('networkDisabled');
1031 var enableNetwork = function() {
1032 chrome.send(command);
1034 var networkList = $('network-list');
1035 networkList.update({key: name,
1038 command: enableNetwork});
1042 * Element for indicating a policy managed network.
1045 function ManagedNetworkIndicator() {
1046 var el = cr.doc.createElement('span');
1047 el.__proto__ = ManagedNetworkIndicator.prototype;
1052 ManagedNetworkIndicator.prototype = {
1053 __proto__: ControlledSettingIndicator.prototype,
1056 decorate: function() {
1057 ControlledSettingIndicator.prototype.decorate.call(this);
1058 this.controlledBy = 'policy';
1059 var policyLabel = loadTimeData.getString('managedNetwork');
1060 this.setAttribute('textPolicy', policyLabel);
1061 this.removeAttribute('tabindex');
1065 handleEvent: function(event) {
1066 // Prevent focus blurring as that would close any currently open menu.
1067 if (event.type == 'mousedown')
1069 ControlledSettingIndicator.prototype.handleEvent.call(this, event);
1073 * Handle mouse events received by the bubble, preventing focus blurring as
1074 * that would close any currently open menu and preventing propagation to
1075 * any elements located behind the bubble.
1076 * @param {Event} Mouse event.
1078 stopEvent: function(event) {
1079 event.preventDefault();
1080 event.stopPropagation();
1084 toggleBubble_: function() {
1085 if (activeMenu_ && !$(activeMenu_).contains(this))
1087 ControlledSettingIndicator.prototype.toggleBubble_.call(this);
1088 if (this.showingBubble) {
1089 var bubble = OptionsPage.getVisibleBubble();
1090 bubble.addEventListener('mousedown', this.stopEvent);
1091 bubble.addEventListener('click', this.stopEvent);
1097 * Updates the list of available networks and their status, filtered by
1099 * @param {string} category The type of network.
1100 * @param {Array} available The list of available networks and their status.
1101 * @param {Array} remembered The list of remmebered networks.
1103 function loadData_(category, available, remembered) {
1104 var data = {key: category};
1105 var type = categoryMap[category];
1106 var availableNetworks = [];
1107 for (var i = 0; i < available.length; i++) {
1108 if (available[i].networkType == type)
1109 availableNetworks.push(available[i]);
1111 data.networkList = availableNetworks;
1113 var rememberedNetworks = [];
1114 for (var i = 0; i < remembered.length; i++) {
1115 if (remembered[i].networkType == type)
1116 rememberedNetworks.push(remembered[i]);
1118 data.rememberedNetworks = rememberedNetworks;
1120 $('network-list').update(data);
1124 * Hides the currently visible menu.
1127 function closeMenu_() {
1129 var menu = $(activeMenu_);
1131 if (menu.data && menu.data.discardOnClose)
1132 menu.parentNode.removeChild(menu);
1138 * Fetches the active connection.
1139 * @param {Array.<Object>} networkList List of networks.
1140 * @return {boolean} True if connected or connecting to a network.
1143 function getConnection_(networkList) {
1146 for (var i = 0; i < networkList.length; i++) {
1147 var entry = networkList[i];
1148 if (entry.connected || entry.connecting)
1155 * Create a callback function that adds a new connection of the given type.
1156 * @param {!number} type A network type Constants.TYPE_*.
1157 * @return {function()} The created callback.
1160 function createAddConnectionCallback_(type) {
1162 chrome.send('networkCommand', [String(type), '', 'add']);
1167 * Whether the Network list is disabled. Only used for display purpose.
1170 cr.defineProperty(NetworkList, 'disabled', cr.PropertyKind.BOOL_ATTR);
1174 NetworkList: NetworkList