Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(188)

Side by Side Diff: chrome/browser/resources/options2/chromeos/network_list.js

Issue 10809005: Options: Rename chrome/browser/resources/options2 -> chrome/browser/resources/options. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 cr.define('options.network', function() {
6
7 var ArrayDataModel = cr.ui.ArrayDataModel;
8 var List = cr.ui.List;
9 var ListItem = cr.ui.ListItem;
10 var Menu = cr.ui.Menu;
11 var MenuItem = cr.ui.MenuItem;
12 var ControlledSettingIndicator = options.ControlledSettingIndicator;
13
14 /**
15 * Network settings constants. These enums usually match their C++
16 * counterparts.
17 */
18 function Constants() {}
19
20 // Network types:
21 Constants.TYPE_UNKNOWN = 0;
22 Constants.TYPE_ETHERNET = 1;
23 Constants.TYPE_WIFI = 2;
24 Constants.TYPE_WIMAX = 3;
25 Constants.TYPE_BLUETOOTH = 4;
26 Constants.TYPE_CELLULAR = 5;
27 Constants.TYPE_VPN = 6;
28
29 // Cellular activation states:
30 Constants.ACTIVATION_STATE_UNKNOWN = 0;
31 Constants.ACTIVATION_STATE_ACTIVATED = 1;
32 Constants.ACTIVATION_STATE_ACTIVATING = 2;
33 Constants.ACTIVATION_STATE_NOT_ACTIVATED = 3;
34 Constants.ACTIVATION_STATE_PARTIALLY_ACTIVATED = 4;
35
36 /**
37 * Order in which controls are to appear in the network list sorted by key.
38 */
39 Constants.NETWORK_ORDER = ['ethernet',
40 'wifi',
41 'wimax',
42 'cellular',
43 'vpn',
44 'airplaneMode',
45 'addConnection'];
46
47 /**
48 * Mapping of network category titles to the network type.
49 */
50 var categoryMap = {
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
56 };
57
58 /**
59 * ID of the menu that is currently visible.
60 * @type {?string}
61 * @private
62 */
63 var activeMenu_ = null;
64
65 /**
66 * Indicates if cellular networks are available.
67 * @type {boolean}
68 * @private
69 */
70 var cellularAvailable_ = false;
71
72 /**
73 * Indicates if cellular networks are enabled.
74 * @type {boolean}
75 * @private
76 */
77 var cellularEnabled_ = false;
78
79 /**
80 * Indicates if WiMAX networks are available.
81 * @type {boolean}
82 * @private
83 */
84 var wimaxAvailable_ = false;
85
86 /**
87 * Indicates if WiMAX networks are enabled.
88 * @type {boolean}
89 * @private
90 */
91 var wimaxEnabled_ = false;
92
93 /**
94 * Indicates if mobile data roaming is enabled.
95 * @type {boolean}
96 * @private
97 */
98 var enableDataRoaming_ = false;
99
100 /**
101 * Create an element in the network list for controlling network
102 * connectivity.
103 * @param {Object} data Description of the network list or command.
104 * @constructor
105 */
106 function NetworkListItem(data) {
107 var el = cr.doc.createElement('li');
108 el.data_ = {};
109 for (var key in data)
110 el.data_[key] = data[key];
111 NetworkListItem.decorate(el);
112 return el;
113 }
114
115 /**
116 * Decorate an element as a NetworkListItem.
117 * @param {!Element} el The element to decorate.
118 */
119 NetworkListItem.decorate = function(el) {
120 el.__proto__ = NetworkListItem.prototype;
121 el.decorate();
122 };
123
124 NetworkListItem.prototype = {
125 __proto__: ListItem.prototype,
126
127 /**
128 * Description of the network group or control.
129 * @type {Object.<string,Object>}
130 * @private
131 */
132 data_: null,
133
134 /**
135 * Element for the control's subtitle.
136 * @type {?Element}
137 * @private
138 */
139 subtitle_: null,
140
141 /**
142 * Icon for the network control.
143 * @type {?Element}
144 * @private
145 */
146 icon_: null,
147
148 /**
149 * Indicates if in the process of connecting to a network.
150 * @type {boolean}
151 * @private
152 */
153 connecting_: false,
154
155 /**
156 * Description of the network control.
157 * @type {Object}
158 */
159 get data() {
160 return this.data_;
161 },
162
163 /**
164 * Text label for the subtitle.
165 * @type {string}
166 */
167 set subtitle(text) {
168 if (text)
169 this.subtitle_.textContent = text;
170 this.subtitle_.hidden = !text;
171 },
172
173 /**
174 * URL for the network icon.
175 * @type {string}
176 */
177 set iconURL(iconURL) {
178 this.icon_.style.backgroundImage = url(iconURL);
179 },
180
181 /**
182 * Type of network icon. Each type corresponds to a CSS rule.
183 * @type {string}
184 */
185 set iconType(type) {
186 this.icon_.classList.add('network-' + type);
187 },
188
189 /**
190 * Indicates if the network is in the process of being connected.
191 * @type {boolean}
192 */
193 set connecting(state) {
194 this.connecting_ = state;
195 if (state)
196 this.icon_.classList.add('network-connecting');
197 else
198 this.icon_.classList.remove('network-connecting');
199 },
200
201 /**
202 * Indicates if the network is in the process of being connected.
203 * @type {boolean}
204 */
205 get connecting() {
206 return this.connecting_;
207 },
208
209 /**
210 * Set the direction of the text.
211 * @param {string} direction The direction of the text, e.g. 'ltr'.
212 */
213 setSubtitleDirection: function(direction) {
214 this.subtitle_.dir = direction;
215 },
216
217 /**
218 * Indicate that the selector arrow should be shown.
219 */
220 showSelector: function() {
221 this.subtitle_.classList.add('network-selector');
222 },
223
224 /**
225 * Adds an indicator to show that the network is policy managed.
226 */
227 showManagedNetworkIndicator: function() {
228 this.appendChild(new ManagedNetworkIndicator());
229 },
230
231 /* @inheritDoc */
232 decorate: function() {
233 ListItem.prototype.decorate.call(this);
234 this.className = 'network-group';
235 this.icon_ = this.ownerDocument.createElement('div');
236 this.icon_.className = 'network-icon';
237 this.appendChild(this.icon_);
238 var textContent = this.ownerDocument.createElement('div');
239 textContent.className = 'network-group-labels';
240 this.appendChild(textContent);
241 var categoryLabel = this.ownerDocument.createElement('div');
242 var title = this.data_.key + 'Title';
243 categoryLabel.className = 'network-title';
244 categoryLabel.textContent = loadTimeData.getString(title);
245 textContent.appendChild(categoryLabel);
246 this.subtitle_ = this.ownerDocument.createElement('div');
247 this.subtitle_.className = 'network-subtitle';
248 textContent.appendChild(this.subtitle_);
249 },
250 };
251
252 /**
253 * Creates a control that displays a popup menu when clicked.
254 * @param {Object} data Description of the control.
255 */
256 function NetworkMenuItem(data) {
257 var el = new NetworkListItem(data);
258 el.__proto__ = NetworkMenuItem.prototype;
259 el.decorate();
260 return el;
261 }
262
263 NetworkMenuItem.prototype = {
264 __proto__: NetworkListItem.prototype,
265
266 /**
267 * Popup menu element.
268 * @type {?Element}
269 * @private
270 */
271 menu_: null,
272
273 /* @inheritDoc */
274 decorate: function() {
275 this.subtitle = null;
276 if (this.data.iconType)
277 this.iconType = this.data.iconType;
278 this.addEventListener('click', function() {
279 this.showMenu();
280 });
281 },
282
283 /**
284 * Retrieves the ID for the menu.
285 * @private
286 */
287 getMenuName_: function() {
288 return this.data_.key + '-network-menu';
289 },
290
291 /**
292 * Creates a popup menu for the control.
293 * @return {Element} The newly created menu.
294 */
295 createMenu: function() {
296 if (this.data.menu) {
297 var menu = this.ownerDocument.createElement('div');
298 menu.id = this.getMenuName_();
299 menu.className = 'network-menu';
300 menu.hidden = true;
301 Menu.decorate(menu);
302 for (var i = 0; i < this.data.menu.length; i++) {
303 var entry = this.data.menu[i];
304 var button = this.ownerDocument.createElement('div');
305 button.className = 'network-menu-item';
306 var buttonLabel = this.ownerDocument.createElement('div');
307 buttonLabel.className = 'network-menu-item-label';
308 buttonLabel.textContent = entry.label;
309 button.appendChild(buttonLabel);
310 button.addEventListener('click', entry.command);
311 MenuItem.decorate(button);
312 menu.appendChild(button);
313 }
314 return menu;
315 }
316 return null;
317 },
318
319 canUpdateMenu: function() {
320 return false;
321 },
322
323 /**
324 * Displays a popup menu.
325 */
326 showMenu: function() {
327 var rebuild = false;
328 // Force a rescan if opening the menu for WiFi networks to ensure the
329 // list is up to date. Networks are periodically rescanned, but depending
330 // on timing, there could be an excessive delay before the first rescan
331 // unless forced.
332 var rescan = !activeMenu_ && this.data_.key == 'wifi';
333 if (!this.menu_) {
334 rebuild = true;
335 var existing = $(this.getMenuName_());
336 if (existing) {
337 if (this.updateMenu())
338 return;
339 closeMenu_();
340 }
341 this.menu_ = this.createMenu();
342 this.menu_.addEventListener('mousedown', function(e) {
343 // Prevent blurring of list, which would close the menu.
344 e.preventDefault();
345 }, true);
346 var parent = $('network-menus');
347 if (existing)
348 parent.replaceChild(this.menu_, existing);
349 else
350 parent.appendChild(this.menu_);
351 }
352 var top = this.offsetTop + this.clientHeight;
353 var menuId = this.getMenuName_();
354 if (menuId != activeMenu_ || rebuild) {
355 closeMenu_();
356 activeMenu_ = menuId;
357 this.menu_.style.setProperty('top', top + 'px');
358 this.menu_.hidden = false;
359 }
360 if (rescan)
361 chrome.send('refreshNetworks');
362 },
363 };
364
365 /**
366 * Creates a control for selecting or configuring a network connection based
367 * on the type of connection (e.g. wifi versus vpn).
368 * @param {{key: string,
369 * networkList: Array.<Object>} data Description of the network.
370 * @constructor
371 */
372 function NetworkSelectorItem(data) {
373 var el = new NetworkMenuItem(data);
374 el.__proto__ = NetworkSelectorItem.prototype;
375 el.decorate();
376 return el;
377 }
378
379 NetworkSelectorItem.prototype = {
380 __proto__: NetworkMenuItem.prototype,
381
382 /* @inheritDoc */
383 decorate: function() {
384 // TODO(kevers): Generalize method of setting default label.
385 var policyManaged = false;
386 var defaultMessage = this.data_.key == 'wifi' ?
387 'networkOffline' : 'networkNotConnected';
388 this.subtitle = loadTimeData.getString(defaultMessage);
389 var list = this.data_.networkList;
390 var candidateURL = null;
391 for (var i = 0; i < list.length; i++) {
392 var networkDetails = list[i];
393 if (networkDetails.connecting || networkDetails.connected) {
394 this.subtitle = networkDetails.networkName;
395 this.setSubtitleDirection('ltr');
396 policyManaged = networkDetails.policyManaged;
397 candidateURL = networkDetails.iconURL;
398 // Only break when we see a connecting network as it is possible to
399 // have a connected network and a connecting network at the same
400 // time.
401 if (networkDetails.connecting) {
402 this.connecting = true;
403 candidateURL = null;
404 break;
405 }
406 }
407 }
408 if (candidateURL)
409 this.iconURL = candidateURL;
410 else
411 this.iconType = this.data.key;
412
413 this.showSelector();
414
415 if (policyManaged)
416 this.showManagedNetworkIndicator();
417
418 if (activeMenu_ == this.getMenuName_()) {
419 // Menu is already showing and needs to be updated. Explicitly calling
420 // show menu will force the existing menu to be replaced. The call
421 // is deferred in order to ensure that position of this element has
422 // beem properly updated.
423 var self = this;
424 setTimeout(function() {self.showMenu();}, 0);
425 }
426 },
427
428 /**
429 * Creates a menu for selecting, configuring or disconnecting from a
430 * network.
431 * @return {Element} The newly created menu.
432 */
433 createMenu: function() {
434 var menu = this.ownerDocument.createElement('div');
435 menu.id = this.getMenuName_();
436 menu.className = 'network-menu';
437 menu.hidden = true;
438 Menu.decorate(menu);
439 var addendum = [];
440 if (this.data_.key == 'wifi') {
441 addendum.push({label: loadTimeData.getString('joinOtherNetwork'),
442 command: 'connect',
443 data: {networkType: Constants.TYPE_WIFI,
444 servicePath: '?'}});
445 } else if (this.data_.key == 'cellular') {
446 var label = enableDataRoaming_ ? 'disableDataRoaming' :
447 'enableDataRoaming';
448 var disabled = !UIAccountTweaks.currentUserIsOwner();
449 var entry = {label: loadTimeData.getString(label),
450 data: {}};
451 if (disabled) {
452 entry.command = null;
453 entry.tooltip =
454 loadTimeData.getString('dataRoamingDisableToggleTooltip');
455 } else {
456 entry.command = function() {
457 options.Preferences.setBooleanPref(
458 'cros.signed.data_roaming_enabled',
459 !enableDataRoaming_);
460 // Force revalidation of the menu the next time it is displayed.
461 this.menu_ = null;
462 };
463 }
464 addendum.push(entry);
465 }
466 var list = this.data.rememberedNetworks;
467 if (list && list.length > 0) {
468 var callback = function(list) {
469 $('remembered-network-list').clear();
470 var dialog = options.PreferredNetworks.getInstance();
471 OptionsPage.showPageByName('preferredNetworksPage', false);
472 dialog.update(list);
473 };
474 addendum.push({label: loadTimeData.getString('preferredNetworks'),
475 command: callback,
476 data: list});
477 }
478
479 var networkGroup = this.ownerDocument.createElement('div');
480 networkGroup.className = 'network-menu-group';
481 list = this.data.networkList;
482 var empty = !list || list.length == 0;
483 if (list) {
484 for (var i = 0; i < list.length; i++) {
485 var data = list[i];
486 this.createNetworkOptionsCallback_(networkGroup, data);
487 if (data.connected) {
488 if (data.networkType == Constants.TYPE_VPN) {
489 // Add separator
490 addendum.push({});
491 var i18nKey = 'disconnectNetwork';
492 addendum.push({label: loadTimeData.getString(i18nKey),
493 command: 'disconnect',
494 data: data});
495 }
496 }
497 }
498 }
499 if (this.data_.key == 'wifi' || this.data_.key == 'wimax' ||
500 this.data_.key == 'cellular') {
501 addendum.push({});
502 if (this.data_.key == 'wifi') {
503 addendum.push({label: loadTimeData.getString('turnOffWifi'),
504 command: function() {
505 chrome.send('disableWifi');
506 },
507 data: {}});
508 } else if (this.data_.key == 'wimax') {
509 // TODO(zelidrag): Add proper strings for wimax.
510 addendum.push({label: loadTimeData.getString('turnOffCellular'),
511 command: function() {
512 chrome.send('disableWimax');
513 },
514 data: {}});
515 } else if (this.data_.key == 'cellular') {
516 addendum.push({label: loadTimeData.getString('turnOffCellular'),
517 command: function() {
518 chrome.send('disableCellular');
519 },
520 data: {}});
521 }
522 }
523 if (!empty)
524 menu.appendChild(networkGroup);
525 if (addendum.length > 0) {
526 var separator = false;
527 if (!empty) {
528 menu.appendChild(MenuItem.createSeparator());
529 separator = true;
530 }
531 for (var i = 0; i < addendum.length; i++) {
532 var value = addendum[i];
533 if (value.data) {
534 var item = this.createCallback_(menu, value.data, value.label,
535 value.command);
536 if (value.tooltip)
537 item.title = value.tooltip;
538 separator = false;
539 } else if (!separator) {
540 menu.appendChild(MenuItem.createSeparator());
541 separator = true;
542 }
543 }
544 }
545 return menu;
546 },
547
548 /**
549 * Determines if a menu can be updated on the fly. Menus that cannot be
550 * updated are fully regenerated using createMenu. The advantage of
551 * updating a menu is that it can preserve ordering of networks avoiding
552 * entries from jumping around after an update.
553 */
554 canUpdateMenu: function() {
555 return this.data_.key == 'wifi' && activeMenu_ == this.getMenuName_();
556 },
557
558 /**
559 * Updates an existing menu. Updated menus preserve ordering of prior
560 * entries. During the update process, the ordering may differ from the
561 * preferred ordering as determined by the network library. If the
562 * ordering becomes potentially out of sync, then the updated menu is
563 * marked for disposal on close. Reopening the menu will force a
564 * regeneration, which will in turn fix the ordering.
565 * @return {boolean} True if successfully updated.
566 */
567 updateMenu: function() {
568 if (!this.canUpdateMenu())
569 return false;
570 var oldMenu = $(this.getMenuName_());
571 var group = oldMenu.getElementsByClassName('network-menu-group')[0];
572 if (!group)
573 return false;
574 var newMenu = this.createMenu();
575 var discardOnClose = false;
576 var oldNetworkButtons = this.extractNetworkConnectButtons_(oldMenu);
577 var newNetworkButtons = this.extractNetworkConnectButtons_(newMenu);
578 for (var key in oldNetworkButtons) {
579 if (newNetworkButtons[key]) {
580 group.replaceChild(newNetworkButtons[key].button,
581 oldNetworkButtons[key].button);
582 if (newNetworkButtons[key].index != oldNetworkButtons[key].index)
583 discardOnClose = true;
584 newNetworkButtons[key] = null;
585 } else {
586 // Leave item in list to prevent network items from jumping due to
587 // deletions.
588 oldNetworkButtons[key].disabled = true;
589 discardOnClose = true;
590 }
591 }
592 for (var key in newNetworkButtons) {
593 var entry = newNetworkButtons[key];
594 if (entry) {
595 group.appendChild(entry.button);
596 discardOnClose = true;
597 }
598 }
599 oldMenu.data = {discardOnClose: discardOnClose};
600 return true;
601 },
602
603 /**
604 * Extracts a mapping of network names to menu element and position.
605 * @param {!Element} menu The menu to process.
606 * @return {Object.<string, Element>} Network mapping.
607 * @private
608 */
609 extractNetworkConnectButtons_: function(menu) {
610 var group = menu.getElementsByClassName('network-menu-group')[0];
611 var networkButtons = {};
612 if (!group)
613 return networkButtons;
614 var buttons = group.getElementsByClassName('network-menu-item');
615 for (var i = 0; i < buttons.length; i++) {
616 var label = buttons[i].data.label;
617 networkButtons[label] = {index: i, button: buttons[i]};
618 }
619 return networkButtons;
620 },
621
622 /**
623 * Adds a command to a menu for modifying network settings.
624 * @param {!Element} menu Parent menu.
625 * @param {Object} data Description of the network.
626 * @param {string} label Display name for the menu item.
627 * @param {string|function} command Callback function or name
628 * of the command for |networkCommand|.
629 * @return {!Element} The created menu item.
630 * @private
631 */
632 createCallback_: function(menu, data, label, command) {
633 var button = this.ownerDocument.createElement('div');
634 button.className = 'network-menu-item';
635 var buttonLabel = this.ownerDocument.createElement('span');
636 buttonLabel.className = 'network-menu-item-label';
637 buttonLabel.textContent = label;
638 button.appendChild(buttonLabel);
639 var callback = null;
640 if (typeof command == 'string') {
641 var type = String(data.networkType);
642 var path = data.servicePath;
643 callback = function() {
644 chrome.send('networkCommand',
645 [type, path, command]);
646 closeMenu_();
647 };
648 } else if (command != null) {
649 callback = function() {
650 command(data);
651 closeMenu_();
652 };
653 }
654 if (callback != null)
655 button.addEventListener('click', callback);
656 else
657 buttonLabel.classList.add('network-disabled-control');
658
659 button.data = {label: label};
660 MenuItem.decorate(button);
661 menu.appendChild(button);
662 return button;
663 },
664
665 /**
666 * Adds a menu item for showing network details.
667 * @param {!Element} parent The parent element.
668 * @param {Object} data Description of the network.
669 * @private
670 */
671 createNetworkOptionsCallback_: function(parent, data) {
672 var menuItem = this.createCallback_(parent,
673 data,
674 data.networkName,
675 'options');
676 menuItem.style.backgroundImage = url(data.iconURL);
677 if (data.policyManaged)
678 menuItem.appendChild(new ManagedNetworkIndicator());
679 if (data.connected || data.connecting) {
680 var label = menuItem.getElementsByClassName(
681 'network-menu-item-label')[0];
682 label.classList.add('active-network');
683 }
684 }
685 };
686
687 /**
688 * Creates a button-like control for configurating internet connectivity.
689 * @param {{key: string,
690 * subtitle: string,
691 * command: function} data Description of the network control.
692 * @constructor
693 */
694 function NetworkButtonItem(data) {
695 var el = new NetworkListItem(data);
696 el.__proto__ = NetworkButtonItem.prototype;
697 el.decorate();
698 return el;
699 }
700
701 NetworkButtonItem.prototype = {
702 __proto__: NetworkListItem.prototype,
703
704 /** @inheritDoc */
705 decorate: function() {
706 if (this.data.subtitle)
707 this.subtitle = this.data.subtitle;
708 else
709 this.subtitle = null;
710 if (this.data.command)
711 this.addEventListener('click', this.data.command);
712 if (this.data.iconURL)
713 this.iconURL = this.data.iconURL;
714 else if (this.data.iconType)
715 this.iconType = this.data.iconType;
716 },
717 };
718
719 /**
720 * A list of controls for manipulating network connectivity.
721 * @constructor
722 */
723 var NetworkList = cr.ui.define('list');
724
725 NetworkList.prototype = {
726 __proto__: List.prototype,
727
728 /** @inheritDoc */
729 decorate: function() {
730 List.prototype.decorate.call(this);
731 this.startBatchUpdates();
732 this.autoExpands = true;
733 this.addEventListener('blur', this.onBlur_);
734 this.dataModel = new ArrayDataModel([]);
735
736 // Wi-Fi control is always visible.
737 this.update({key: 'wifi', networkList: []});
738
739 if (airplaneModeAvailable_()) {
740 this.update({key: 'airplaneMode',
741 subtitle: loadTimeData.getString('airplaneModeLabel'),
742 command: function() {
743 chrome.send('toggleAirplaneMode');
744 }});
745 }
746
747 // Add connection control.
748 var addConnection = function(type) {
749 var callback = function() {
750 chrome.send('networkCommand',
751 [String(type), '?', 'connect']);
752 }
753 return callback;
754 }
755 this.update({key: 'addConnection',
756 iconType: 'add-connection',
757 menu: [{label: loadTimeData.getString('addConnectionWifi'),
758 command: addConnection(Constants.TYPE_WIFI)},
759 {label: loadTimeData.getString('addConnectionVPN'),
760 command: addConnection(Constants.TYPE_VPN)}]
761 });
762
763 var prefs = options.Preferences.getInstance();
764 prefs.addEventListener('cros.signed.data_roaming_enabled',
765 function(event) {
766 enableDataRoaming_ = event.value.value;
767 });
768 this.endBatchUpdates();
769 },
770
771 /**
772 * When the list loses focus, unselect all items in the list and close the
773 * active menu.
774 * @private
775 */
776 onBlur_: function() {
777 this.selectionModel.unselectAll();
778 closeMenu_();
779 },
780
781 /**
782 * Finds the index of a network item within the data model based on
783 * category.
784 * @param {string} key Unique key for the item in the list.
785 * @return {number} The index of the network item, or |undefined| if it is
786 * not found.
787 */
788 indexOf: function(key) {
789 var size = this.dataModel.length;
790 for (var i = 0; i < size; i++) {
791 var entry = this.dataModel.item(i);
792 if (entry.key == key)
793 return i;
794 }
795 },
796
797 /**
798 * Updates a network control.
799 * @param {Object.<string,string>} data Description of the entry.
800 */
801 update: function(data) {
802 this.startBatchUpdates();
803 var index = this.indexOf(data.key);
804 if (index == undefined) {
805 // Find reference position for adding the element. We cannot hide
806 // individual list elements, thus we need to conditionally add or
807 // remove elements and cannot rely on any element having a fixed index.
808 for (var i = 0; i < Constants.NETWORK_ORDER.length; i++) {
809 if (data.key == Constants.NETWORK_ORDER[i]) {
810 data.sortIndex = i;
811 break;
812 }
813 }
814 var referenceIndex = -1;
815 for (var i = 0; i < this.dataModel.length; i++) {
816 var entry = this.dataModel.item(i);
817 if (entry.sortIndex < data.sortIndex)
818 referenceIndex = i;
819 else
820 break;
821 }
822 if (referenceIndex == -1) {
823 // Prepend to the start of the list.
824 this.dataModel.splice(0, 0, data);
825 } else if (referenceIndex == this.dataModel.length) {
826 // Append to the end of the list.
827 this.dataModel.push(data);
828 } else {
829 // Insert after the reference element.
830 this.dataModel.splice(referenceIndex + 1, 0, data);
831 }
832 } else {
833 var entry = this.dataModel.item(index);
834 data.sortIndex = entry.sortIndex;
835 this.dataModel.splice(index, 1, data);
836 }
837 this.endBatchUpdates();
838 },
839
840 /** @inheritDoc */
841 createItem: function(entry) {
842 if (entry.networkList)
843 return new NetworkSelectorItem(entry);
844 if (entry.command)
845 return new NetworkButtonItem(entry);
846 if (entry.menu)
847 return new NetworkMenuItem(entry);
848 },
849
850 /**
851 * Deletes an element from the list.
852 * @param {string} key Unique identifier for the element.
853 */
854 deleteItem: function(key) {
855 var index = this.indexOf(key);
856 if (index != undefined)
857 this.dataModel.splice(index, 1);
858 },
859
860 /**
861 * Updates the state of a toggle button.
862 * @param {string} key Unique identifier for the element.
863 * @param {boolean} active Whether the control is active.
864 */
865 updateToggleControl: function(key, active) {
866 var index = this.indexOf(key);
867 if (index != undefined) {
868 var entry = this.dataModel.item(index);
869 entry.iconType = active ? 'control-active' :
870 'control-inactive';
871 this.update(entry);
872 }
873 }
874 };
875
876 /**
877 * Chrome callback for updating network controls.
878 * @param {Object} data Description of available network devices and their
879 * corresponding state.
880 */
881 NetworkList.refreshNetworkData = function(data) {
882 var networkList = $('network-list');
883 networkList.startBatchUpdates();
884 cellularAvailable_ = data.cellularAvailable;
885 cellularEnabled_ = data.cellularEnabled;
886 wimaxAvailable_ = data.wimaxAvailable;
887 wimaxEnabled_ = data.wimaxEnabled;
888
889 if (data.accessLocked) {
890 $('network-locked-message').hidden = false;
891 networkList.disabled = true;
892 $('use-shared-proxies').disabled = true;
893 } else {
894 $('network-locked-message').hidden = true;
895 networkList.disabled = false;
896 $('use-shared-proxies').disabled = false;
897 }
898
899 // Only show Ethernet control if connected.
900 var ethernetConnection = getConnection_(data.wiredList);
901 if (ethernetConnection) {
902 var type = String(Constants.TYPE_ETHERNET);
903 var path = ethernetConnection.servicePath;
904 var ethernetOptions = function() {
905 chrome.send('networkCommand',
906 [type, path, 'options']);
907 };
908 networkList.update({key: 'ethernet',
909 subtitle: loadTimeData.getString('networkConnected'),
910 iconURL: ethernetConnection.iconURL,
911 command: ethernetOptions});
912 } else {
913 networkList.deleteItem('ethernet');
914 }
915
916 if (data.wifiEnabled) {
917 loadData_('wifi', data.wirelessList, data.rememberedList);
918 } else {
919 var enableWifi = function() {
920 chrome.send('enableWifi');
921 };
922 networkList.update({key: 'wifi',
923 subtitle: loadTimeData.getString('networkDisabled'),
924 iconType: 'wifi',
925 command: enableWifi});
926 }
927
928 // Only show cellular control if available and not in airplane mode.
929 if (data.cellularAvailable && !data.airplaneMode) {
930 if (data.cellularEnabled) {
931 loadData_('cellular', data.wirelessList, data.rememberedList);
932 } else {
933 var subtitle = loadTimeData.getString('networkDisabled');
934 var enableCellular = function() {
935 chrome.send('enableCellular');
936 };
937 networkList.update({key: 'cellular',
938 subtitle: subtitle,
939 iconType: 'cellular',
940 command: enableCellular});
941 }
942 } else {
943 networkList.deleteItem('cellular');
944 }
945
946 // Only show cellular control if available and not in airplane mode.
947 if (data.wimaxAvailable && !data.airplaneMode) {
948 if (data.wimaxEnabled) {
949 loadData_('wimax', data.wirelessList, data.rememberedList);
950 } else {
951 var subtitle = loadTimeData.getString('networkDisabled');
952 var enableWimax = function() {
953 chrome.send('enableWimax');
954 };
955 networkList.update({key: 'wimax',
956 subtitle: subtitle,
957 iconType: 'cellular',
958 command: enableWimax});
959 }
960 } else {
961 networkList.deleteItem('wimax');
962 }
963
964 // Only show VPN control if there is an available network and an internet
965 // connection.
966 if (data.vpnList.length > 0 && (ethernetConnection ||
967 isConnected_(data.wirelessList)))
968 loadData_('vpn', data.vpnList, data.rememberedList);
969 else
970 networkList.deleteItem('vpn');
971 networkList.updateToggleControl('airplaneMode', data.airplaneMode);
972 networkList.endBatchUpdates();
973 };
974
975 /**
976 * Element for indicating a policy managed network.
977 * @constructor
978 */
979 function ManagedNetworkIndicator() {
980 var el = cr.doc.createElement('div');
981 el.__proto__ = ManagedNetworkIndicator.prototype;
982 el.decorate();
983 return el;
984 }
985
986 ManagedNetworkIndicator.prototype = {
987 __proto__: ControlledSettingIndicator.prototype,
988
989 /** @inheritDoc */
990 decorate: function() {
991 ControlledSettingIndicator.prototype.decorate.call(this);
992 this.controlledBy = 'policy';
993 var policyLabel = loadTimeData.getString('managedNetwork');
994 this.setAttribute('textPolicy', policyLabel);
995 this.className = 'controlled-setting-indicator';
996 // The default popup clips to the bounds of the list of networks in the
997 // drop-down because it has enforced size constraints with auto-
998 // scrolling. Use a tooltip in place of the bubble popup until the
999 // clipping issues are resolved.
1000 this.setAttribute('title', policyLabel);
1001 this.addEventListener('click', function(e) {
1002 e.preventDefault();
1003 e.stopPropagation();
1004 });
1005 }
1006 };
1007
1008 /**
1009 * Updates the list of available networks and their status, filtered by
1010 * network type.
1011 * @param {string} category The type of network.
1012 * @param {Array} available The list of available networks and their status.
1013 * @param {Array} remembered The list of remmebered networks.
1014 */
1015 function loadData_(category, available, remembered) {
1016 var data = {key: category};
1017 var type = categoryMap[category];
1018 var availableNetworks = [];
1019 for (var i = 0; i < available.length; i++) {
1020 if (available[i].networkType == type)
1021 availableNetworks.push(available[i]);
1022 }
1023 data.networkList = availableNetworks;
1024 if (remembered) {
1025 var rememberedNetworks = [];
1026 for (var i = 0; i < remembered.length; i++) {
1027 if (remembered[i].networkType == type)
1028 rememberedNetworks.push(remembered[i]);
1029 }
1030 data.rememberedNetworks = rememberedNetworks;
1031 }
1032 $('network-list').update(data);
1033 }
1034
1035 /**
1036 * Hides the currently visible menu.
1037 * @private
1038 */
1039 function closeMenu_() {
1040 if (activeMenu_) {
1041 var menu = $(activeMenu_);
1042 menu.hidden = true;
1043 if (menu.data && menu.data.discardOnClose)
1044 menu.parentNode.removeChild(menu);
1045 activeMenu_ = null;
1046 }
1047 }
1048
1049 /**
1050 * Determines if the user is connected to or in the process of connecting to
1051 * a wireless network.
1052 * @param {Array.<Object>} networkList List of networks.
1053 * @return {boolean} True if connected or connecting to a network.
1054 * @private
1055 */
1056 function isConnected_(networkList) {
1057 return getConnection_(networkList) != null;
1058 }
1059
1060 /**
1061 * Fetches the active connection.
1062 * @param {Array.<Object>} networkList List of networks.
1063 * @return {boolean} True if connected or connecting to a network.
1064 * @private
1065 */
1066 function getConnection_(networkList) {
1067 if (!networkList)
1068 return null;
1069 for (var i = 0; i < networkList.length; i++) {
1070 var entry = networkList[i];
1071 if (entry.connected || entry.connecting)
1072 return entry;
1073 }
1074 return null;
1075 }
1076
1077 /**
1078 * Queries if airplane mode is available.
1079 * @return {boolean} Indicates if airplane mode is available.
1080 * @private
1081 */
1082 function airplaneModeAvailable_() {
1083 // TODO(kevers): Use library callback to determine if airplane mode is
1084 // available once back-end suport is in place.
1085 return false;
1086 }
1087
1088 /**
1089 * Whether the Network list is disabled. Only used for display purpose.
1090 * @type {boolean}
1091 */
1092 cr.defineProperty(NetworkList, 'disabled', cr.PropertyKind.BOOL_ATTR);
1093
1094 // Export
1095 return {
1096 NetworkList: NetworkList
1097 };
1098 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698