Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / resources / options / chromeos / internet_detail.js
blob340fbb26c2c0e20952916aec8cc73a4ed7b6c140
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 // require: onc_data.js
7 // NOTE(stevenjb): This code is in the process of being converted to be
8 // compatible with the networkingPrivate extension API:
9 // * The network property dictionaries are being converted to use ONC values.
10 // * chrome.send calls will be replaced with chrome.networkingPrivate calls.
11 // See crbug.com/279351 for more info.
13 cr.define('options.internet', function() {
14 var OncData = cr.onc.OncData;
15 var Page = cr.ui.pageManager.Page;
16 var PageManager = cr.ui.pageManager.PageManager;
17 /** @const */ var IPAddressField = options.internet.IPAddressField;
19 /** @const */ var GoogleNameServers = ['8.8.4.4', '8.8.8.8'];
20 /** @const */ var CarrierGenericUMTS = 'Generic UMTS';
22 /**
23 * Helper function to set hidden attribute for elements matching a selector.
24 * @param {string} selector CSS selector for extracting a list of elements.
25 * @param {boolean} hidden New hidden value.
27 function updateHidden(selector, hidden) {
28 var elements = cr.doc.querySelectorAll(selector);
29 for (var i = 0, el; el = elements[i]; i++) {
30 el.hidden = hidden;
34 /**
35 * Helper function to update the properties of the data object from the
36 * properties in the update object.
37 * @param {Object} data Object to update.
38 * @param {Object} update Object containing the updated properties.
40 function updateDataObject(data, update) {
41 for (var prop in update) {
42 if (prop in data)
43 data[prop] = update[prop];
47 /**
48 * Monitor pref change of given element.
49 * @param {Element} el Target element.
51 function observePrefsUI(el) {
52 Preferences.getInstance().addEventListener(el.pref, handlePrefUpdate);
55 /**
56 * UI pref change handler.
57 * @param {Event} e The update event.
59 function handlePrefUpdate(e) {
60 DetailsInternetPage.getInstance().updateControls();
63 /**
64 * Simple helper method for converting a field to a string. It is used to
65 * easily assign an empty string from fields that may be unknown or undefined.
66 * @param {Object} value that should be converted to a string.
67 * @return {string} the result.
69 function stringFromValue(value) {
70 return value ? String(value) : '';
73 /**
74 * @param {string} action An action to send to coreOptionsUserMetricsAction.
76 function sendChromeMetricsAction(action) {
77 chrome.send('coreOptionsUserMetricsAction', [action]);
80 /**
81 * Send metrics to Chrome when the detailed page is opened.
82 * @param {string} type The ONC type of the network being shown.
83 * @param {string} state The ONC network state.
85 function sendShowDetailsMetrics(type, state) {
86 if (type == 'WiFi') {
87 sendChromeMetricsAction('Options_NetworkShowDetailsWifi');
88 if (state != 'NotConnected')
89 sendChromeMetricsAction('Options_NetworkShowDetailsWifiConnected');
90 } else if (type == 'Cellular') {
91 sendChromeMetricsAction('Options_NetworkShowDetailsCellular');
92 if (state != 'NotConnected')
93 sendChromeMetricsAction('Options_NetworkShowDetailsCellularConnected');
94 } else if (type == 'VPN') {
95 sendChromeMetricsAction('Options_NetworkShowDetailsVPN');
96 if (state != 'NotConnected')
97 sendChromeMetricsAction('Options_NetworkShowDetailsVPNConnected');
102 * Returns the netmask as a string for a given prefix length.
103 * @param {number} prefixLength The ONC routing prefix length.
104 * @return {string} The corresponding netmask.
106 function prefixLengthToNetmask(prefixLength) {
107 // Return the empty string for invalid inputs.
108 if (prefixLength < 0 || prefixLength > 32)
109 return '';
110 var netmask = '';
111 for (var i = 0; i < 4; ++i) {
112 var remainder = 8;
113 if (prefixLength >= 8) {
114 prefixLength -= 8;
115 } else {
116 remainder = prefixLength;
117 prefixLength = 0;
119 if (i > 0)
120 netmask += '.';
121 var value = 0;
122 if (remainder != 0)
123 value = ((2 << (remainder - 1)) - 1) << (8 - remainder);
124 netmask += value.toString();
126 return netmask;
130 * Returns the prefix length from the netmask string.
131 * @param {string} netmask The netmask string, e.g. 255.255.255.0.
132 * @return {number} The corresponding netmask or -1 if invalid.
134 function netmaskToPrefixLength(netmask) {
135 var prefixLength = 0;
136 var tokens = netmask.split('.');
137 if (tokens.length != 4)
138 return -1;
139 for (var i = 0; i < tokens.length; ++i) {
140 var token = tokens[i];
141 // If we already found the last mask and the current one is not
142 // '0' then the netmask is invalid. For example, 255.224.255.0
143 if (prefixLength / 8 != i) {
144 if (token != '0')
145 return -1;
146 } else if (token == '255') {
147 prefixLength += 8;
148 } else if (token == '254') {
149 prefixLength += 7;
150 } else if (token == '252') {
151 prefixLength += 6;
152 } else if (token == '248') {
153 prefixLength += 5;
154 } else if (token == '240') {
155 prefixLength += 4;
156 } else if (token == '224') {
157 prefixLength += 3;
158 } else if (token == '192') {
159 prefixLength += 2;
160 } else if (token == '128') {
161 prefixLength += 1;
162 } else if (token == '0') {
163 prefixLength += 0;
164 } else {
165 // mask is not a valid number.
166 return -1;
169 return prefixLength;
172 /////////////////////////////////////////////////////////////////////////////
173 // DetailsInternetPage class:
176 * Encapsulated handling of ChromeOS internet details overlay page.
177 * @constructor
178 * @extends {cr.ui.pageManager.Page}
180 function DetailsInternetPage() {
181 // If non-negative, indicates a custom entry in select-apn.
182 this.userApnIndex_ = -1;
184 // The custom APN properties associated with entry |userApnIndex_|.
185 this.userApn_ = {};
187 // The currently selected APN entry in $('select-apn') (which may or may not
188 // == userApnIndex_).
189 this.selectedApnIndex_ = -1;
191 // We show the Proxy configuration tab for remembered networks and when
192 // configuring a proxy from the login screen.
193 this.showProxy_ = false;
195 Page.call(this, 'detailsInternetPage', '', 'details-internet-page');
198 cr.addSingletonGetter(DetailsInternetPage);
200 DetailsInternetPage.prototype = {
201 __proto__: Page.prototype,
203 /** @override */
204 initializePage: function() {
205 Page.prototype.initializePage.call(this);
206 this.initializePageContents_();
207 this.showNetworkDetails_();
211 * Auto-activates the network details dialog if network information
212 * is included in the URL.
214 showNetworkDetails_: function() {
215 var guid = parseQueryParams(window.location).guid;
216 if (!guid || !guid.length)
217 return;
218 chrome.send('loadVPNProviders');
219 chrome.networkingPrivate.getManagedProperties(
220 guid, DetailsInternetPage.initializeDetailsPage);
224 * Initializes the contents of the page.
226 initializePageContents_: function() {
227 $('details-internet-dismiss').addEventListener('click', function(event) {
228 DetailsInternetPage.setDetails();
231 $('details-internet-login').addEventListener('click', function(event) {
232 DetailsInternetPage.setDetails();
233 DetailsInternetPage.loginFromDetails();
236 $('details-internet-disconnect').addEventListener('click',
237 function(event) {
238 DetailsInternetPage.setDetails();
239 DetailsInternetPage.disconnectNetwork();
242 $('details-internet-configure').addEventListener('click',
243 function(event) {
244 DetailsInternetPage.setDetails();
245 DetailsInternetPage.configureNetwork();
248 $('activate-details').addEventListener('click', function(event) {
249 DetailsInternetPage.activateFromDetails();
252 $('view-account-details').addEventListener('click', function(event) {
253 chrome.send('showMorePlanInfo',
254 [DetailsInternetPage.getInstance().onc_.guid()]);
255 PageManager.closeOverlay();
258 $('cellular-apn-use-default').addEventListener('click', function(event) {
259 DetailsInternetPage.getInstance().setDefaultApn_();
262 $('cellular-apn-set').addEventListener('click', function(event) {
263 DetailsInternetPage.getInstance().setApn_($('cellular-apn').value);
266 $('cellular-apn-cancel').addEventListener('click', function(event) {
267 DetailsInternetPage.getInstance().cancelApn_();
270 $('select-apn').addEventListener('change', function(event) {
271 DetailsInternetPage.getInstance().selectApn_();
274 $('sim-card-lock-enabled').addEventListener('click', function(event) {
275 var newValue = $('sim-card-lock-enabled').checked;
276 // Leave value as is because user needs to enter PIN code first.
277 // When PIN will be entered and value changed,
278 // we'll update UI to reflect that change.
279 $('sim-card-lock-enabled').checked = !newValue;
280 var operation = newValue ? 'setLocked' : 'setUnlocked';
281 chrome.send('simOperation', [operation]);
283 $('change-pin').addEventListener('click', function(event) {
284 chrome.send('simOperation', ['changePin']);
287 // Proxy
288 ['proxy-host-single-port',
289 'secure-proxy-port',
290 'socks-port',
291 'ftp-proxy-port',
292 'proxy-host-port'
293 ].forEach(function(id) {
294 options.PrefPortNumber.decorate($(id));
297 options.proxyexceptions.ProxyExceptions.decorate($('ignored-host-list'));
298 $('remove-host').addEventListener('click',
299 this.handleRemoveProxyExceptions_);
300 $('add-host').addEventListener('click', this.handleAddProxyException_);
301 $('direct-proxy').addEventListener('click', this.disableManualProxy_);
302 $('manual-proxy').addEventListener('click', this.enableManualProxy_);
303 $('auto-proxy').addEventListener('click', this.disableManualProxy_);
304 $('proxy-all-protocols').addEventListener('click',
305 this.toggleSingleProxy_);
306 $('proxy-use-pac-url').addEventListener('change',
307 this.handleAutoConfigProxy_);
309 observePrefsUI($('direct-proxy'));
310 observePrefsUI($('manual-proxy'));
311 observePrefsUI($('auto-proxy'));
312 observePrefsUI($('proxy-all-protocols'));
313 observePrefsUI($('proxy-use-pac-url'));
315 $('ip-automatic-configuration-checkbox').addEventListener('click',
316 this.handleIpAutoConfig_);
317 $('automatic-dns-radio').addEventListener('click',
318 this.handleNameServerTypeChange_);
319 $('google-dns-radio').addEventListener('click',
320 this.handleNameServerTypeChange_);
321 $('user-dns-radio').addEventListener('click',
322 this.handleNameServerTypeChange_);
324 // We only load this string if we have the string data available
325 // because the proxy settings page on the login screen re-uses the
326 // proxy sub-page from the internet options, and it doesn't ever
327 // show the DNS settings, so we don't need this string there.
328 // The string isn't available because
329 // chrome://settings-frame/strings.js (where the string is
330 // stored) is not accessible from the login screen.
331 // TODO(pneubeck): Remove this once i18n of the proxy dialog on the login
332 // page is fixed. http://crbug.com/242865
333 if (loadTimeData.data_) {
334 $('google-dns-label').innerHTML =
335 loadTimeData.getString('googleNameServers');
340 * Handler for "add" event fired from userNameEdit.
341 * @param {Event} e Add event fired from userNameEdit.
342 * @private
344 handleAddProxyException_: function(e) {
345 var exception = $('new-host').value;
346 $('new-host').value = '';
348 exception = exception.trim();
349 if (exception)
350 $('ignored-host-list').addException(exception);
354 * Handler for when the remove button is clicked
355 * @param {Event} e The click event.
356 * @private
358 handleRemoveProxyExceptions_: function(e) {
359 var selectedItems = $('ignored-host-list').selectedItems;
360 for (var x = 0; x < selectedItems.length; x++) {
361 $('ignored-host-list').removeException(selectedItems[x]);
366 * Handler for when the IP automatic configuration checkbox is clicked.
367 * @param {Event} e The click event.
368 * @private
370 handleIpAutoConfig_: function(e) {
371 var checked = $('ip-automatic-configuration-checkbox').checked;
372 var fields = [$('ip-address'), $('ip-netmask'), $('ip-gateway')];
373 for (var i = 0; i < fields.length; ++i) {
374 fields[i].editable = !checked;
375 if (checked) {
376 var model = fields[i].model;
377 model.value = model.automatic;
378 fields[i].model = model;
381 if (!checked)
382 $('ip-address').focus();
386 * Handler for when the name server selection changes.
387 * @param {Event} event The click event.
388 * @private
390 handleNameServerTypeChange_: function(event) {
391 var type = event.target.value;
392 DetailsInternetPage.updateNameServerDisplay(type);
396 * Gets the IPConfig ONC Object.
397 * @param {string} nameServerType The selected name server type:
398 * 'automatic', 'google', or 'user'.
399 * @return {Object} The IPConfig ONC object.
400 * @private
402 getIpConfig_: function(nameServerType) {
403 var ipConfig = {};
404 // If 'ip-address' is empty, automatic configuration will be used.
405 if (!$('ip-automatic-configuration-checkbox').checked &&
406 $('ip-address').model.value) {
407 ipConfig['IPAddress'] = $('ip-address').model.value;
408 var netmask = $('ip-netmask').model.value;
409 var routingPrefix = 0;
410 if (netmask) {
411 routingPrefix = netmaskToPrefixLength(netmask);
412 if (routingPrefix == -1) {
413 console.error('Invalid netmask: ' + netmask);
414 routingPrefix = 0;
417 ipConfig['RoutingPrefix'] = routingPrefix;
418 ipConfig['Gateway'] = $('ip-gateway').model.value || '';
421 // Note: If no nameserver fields are set, automatic configuration will be
422 // used. TODO(stevenjb): Validate input fields.
423 if (nameServerType != 'automatic') {
424 var userNameServers = [];
425 if (nameServerType == 'google') {
426 userNameServers = GoogleNameServers.slice();
427 } else if (nameServerType == 'user') {
428 for (var i = 1; i <= 4; ++i) {
429 var nameServerField = $('ipconfig-dns' + i);
430 // Skip empty values.
431 if (nameServerField && nameServerField.model &&
432 nameServerField.model.value) {
433 userNameServers.push(nameServerField.model.value);
437 if (userNameServers.length)
438 ipConfig['NameServers'] = userNameServers.sort();
440 return ipConfig;
444 * Creates an indicator event for controlled properties using
445 * the same dictionary format as CoreOptionsHandler::CreateValueForPref.
446 * @param {string} name The name for the Event.
447 * @param {{value: *, controlledBy: *, recommendedValue: *}} propData
448 * Property dictionary.
449 * @private
451 createControlledEvent_: function(name, propData) {
452 assert('value' in propData && 'controlledBy' in propData &&
453 'recommendedValue' in propData);
454 var event = new Event(name);
455 event.value = {
456 value: propData.value,
457 controlledBy: propData.controlledBy,
458 recommendedValue: propData.recommendedValue
460 return event;
464 * Creates an indicator event for controlled properties using
465 * the ONC getManagedProperties dictionary format.
466 * @param {string} name The name for the Event.
467 * @param {Object} propData ONC managed network property dictionary.
468 * @private
470 createManagedEvent_: function(name, propData) {
471 var event = new Event(name);
472 event.value = {};
474 // Set the current value and recommended value.
475 var activeValue = propData['Active'];
476 var effective = propData['Effective'];
477 if (activeValue == undefined)
478 activeValue = propData[effective];
479 event.value.value = activeValue;
481 // If a property is editable then it is not enforced, and 'controlledBy'
482 // is set to 'recommended' unless effective == {User|Shared}Setting, in
483 // which case the value was modified from the recommended value.
484 // Otherwise if 'Effective' is set to 'UserPolicy' or 'DevicePolicy' then
485 // the set value is mandated by the policy.
486 if (propData['UserEditable']) {
487 if (effective == 'UserPolicy')
488 event.value.controlledBy = 'recommended';
489 event.value.recommendedValue = propData['UserPolicy'];
490 } else if (propData['DeviceEditable']) {
491 if (effective == 'DevicePolicy')
492 event.value.controlledBy = 'recommended';
493 event.value.recommendedValue = propData['DevicePolicy'];
494 } else if (effective == 'UserPolicy' || effective == 'DevicePolicy') {
495 event.value.controlledBy = 'policy';
498 return event;
502 * Update details page controls.
504 updateControls: function() {
505 // Note: onc may be undefined when called from a pref update before
506 // initialized in initializeDetailsPage.
507 var onc = this.onc_;
509 // Always show the ipconfig section. TODO(stevenjb): Improve the display
510 // for unconnected networks. Currently the IP address fields may be
511 // blank if the network is not connected.
512 $('ipconfig-section').hidden = false;
513 $('ipconfig-dns-section').hidden = false;
515 // Network type related.
516 updateHidden('#details-internet-page .cellular-details',
517 this.type_ != 'Cellular');
518 updateHidden('#details-internet-page .wifi-details',
519 this.type_ != 'WiFi');
520 updateHidden('#details-internet-page .wimax-details',
521 this.type_ != 'WiMAX');
522 updateHidden('#details-internet-page .vpn-details', this.type_ != 'VPN');
523 updateHidden('#details-internet-page .proxy-details', !this.showProxy_);
525 // Cellular
526 if (onc && this.type_ == 'Cellular') {
527 // Hide gsm/cdma specific elements.
528 if (onc.getActiveValue('Cellular.Family') == 'GSM')
529 updateHidden('#details-internet-page .cdma-only', true);
530 else
531 updateHidden('#details-internet-page .gsm-only', true);
534 // Wifi
536 // Hide network tab for VPN.
537 updateHidden('#details-internet-page .network-details',
538 this.type_ == 'VPN');
540 // Password and shared.
541 var source = onc ? onc.getSource() : 'None';
542 var shared = (source == 'Device' || source == 'DevicePolicy');
543 var security = onc ? onc.getWiFiSecurity() : 'None';
544 updateHidden('#details-internet-page #password-details',
545 this.type_ != 'WiFi' || security == 'None');
546 updateHidden('#details-internet-page #wifi-shared-network', !shared);
547 updateHidden('#details-internet-page #prefer-network', source == 'None');
549 // WiMAX.
550 updateHidden('#details-internet-page #wimax-shared-network', !shared);
552 // Proxy
553 this.updateProxyBannerVisibility_();
554 this.toggleSingleProxy_();
555 if ($('manual-proxy').checked)
556 this.enableManualProxy_();
557 else
558 this.disableManualProxy_();
562 * Updates info banner visibility state. This function shows the banner
563 * if proxy is managed or shared-proxies is off for shared network.
564 * @private
566 updateProxyBannerVisibility_: function() {
567 var bannerDiv = $('network-proxy-info-banner');
568 if (!loadTimeData.data_) {
569 // TODO(pneubeck): This temporarily prevents an exception below until
570 // i18n of the proxy dialog on the login page is
571 // fixed. http://crbug.com/242865
572 bannerDiv.hidden = true;
573 return;
576 // Show banner and determine its message if necessary.
577 var controlledBy = $('direct-proxy').controlledBy;
578 if (!controlledBy || controlledBy == '') {
579 bannerDiv.hidden = true;
580 } else {
581 bannerDiv.hidden = false;
582 // The possible banner texts are loaded in proxy_handler.cc.
583 var bannerText = 'proxyBanner' + controlledBy.charAt(0).toUpperCase() +
584 controlledBy.slice(1);
585 $('banner-text').textContent = loadTimeData.getString(bannerText);
590 * Handler for when the user clicks on the checkbox to allow a
591 * single proxy usage.
592 * @private
594 toggleSingleProxy_: function() {
595 if ($('proxy-all-protocols').checked) {
596 $('multi-proxy').hidden = true;
597 $('single-proxy').hidden = false;
598 } else {
599 $('multi-proxy').hidden = false;
600 $('single-proxy').hidden = true;
605 * Handler for when the user clicks on the checkbox to enter
606 * auto configuration URL.
607 * @private
609 handleAutoConfigProxy_: function() {
610 $('proxy-pac-url').disabled = !$('proxy-use-pac-url').checked;
614 * Handler for selecting a radio button that will disable the manual
615 * controls.
616 * @private
618 disableManualProxy_: function() {
619 $('ignored-host-list').disabled = true;
620 $('new-host').disabled = true;
621 $('remove-host').disabled = true;
622 $('add-host').disabled = true;
623 $('proxy-all-protocols').disabled = true;
624 $('proxy-host-name').disabled = true;
625 $('proxy-host-port').disabled = true;
626 $('proxy-host-single-name').disabled = true;
627 $('proxy-host-single-port').disabled = true;
628 $('secure-proxy-host-name').disabled = true;
629 $('secure-proxy-port').disabled = true;
630 $('ftp-proxy').disabled = true;
631 $('ftp-proxy-port').disabled = true;
632 $('socks-host').disabled = true;
633 $('socks-port').disabled = true;
634 $('proxy-use-pac-url').disabled = $('auto-proxy').disabled ||
635 !$('auto-proxy').checked;
636 $('proxy-pac-url').disabled = $('proxy-use-pac-url').disabled ||
637 !$('proxy-use-pac-url').checked;
638 $('auto-proxy-parms').hidden = !$('auto-proxy').checked;
639 $('manual-proxy-parms').hidden = !$('manual-proxy').checked;
640 sendChromeMetricsAction('Options_NetworkManualProxy_Disable');
644 * Handler for selecting a radio button that will enable the manual
645 * controls.
646 * @private
648 enableManualProxy_: function() {
649 $('ignored-host-list').redraw();
650 var allDisabled = $('manual-proxy').disabled;
651 $('ignored-host-list').disabled = allDisabled;
652 $('new-host').disabled = allDisabled;
653 $('remove-host').disabled = allDisabled;
654 $('add-host').disabled = allDisabled;
655 $('proxy-all-protocols').disabled = allDisabled;
656 $('proxy-host-name').disabled = allDisabled;
657 $('proxy-host-port').disabled = allDisabled;
658 $('proxy-host-single-name').disabled = allDisabled;
659 $('proxy-host-single-port').disabled = allDisabled;
660 $('secure-proxy-host-name').disabled = allDisabled;
661 $('secure-proxy-port').disabled = allDisabled;
662 $('ftp-proxy').disabled = allDisabled;
663 $('ftp-proxy-port').disabled = allDisabled;
664 $('socks-host').disabled = allDisabled;
665 $('socks-port').disabled = allDisabled;
666 $('proxy-use-pac-url').disabled = true;
667 $('proxy-pac-url').disabled = true;
668 $('auto-proxy-parms').hidden = !$('auto-proxy').checked;
669 $('manual-proxy-parms').hidden = !$('manual-proxy').checked;
670 sendChromeMetricsAction('Options_NetworkManualProxy_Enable');
674 * Helper method called from initializeDetailsPage and updateConnectionData.
675 * Updates visibility/enabled of the login/disconnect/configure buttons.
676 * @private
678 updateConnectionButtonVisibilty_: function() {
679 var onc = this.onc_;
680 if (this.type_ == 'Ethernet') {
681 // Ethernet can never be connected or disconnected and can always be
682 // configured (e.g. to set security).
683 $('details-internet-login').hidden = true;
684 $('details-internet-disconnect').hidden = true;
685 $('details-internet-configure').hidden = false;
686 return;
689 var connectState = onc.getActiveValue('ConnectionState');
690 if (connectState == 'NotConnected') {
691 $('details-internet-login').hidden = false;
692 // Connecting to an unconfigured network might trigger certificate
693 // installation UI. Until that gets handled here, always enable the
694 // Connect button.
695 $('details-internet-login').disabled = false;
696 $('details-internet-disconnect').hidden = true;
697 } else {
698 $('details-internet-login').hidden = true;
699 $('details-internet-disconnect').hidden = false;
702 var connectable = onc.getActiveValue('Connectable');
703 if (connectState != 'Connected' &&
704 (!connectable || onc.getWiFiSecurity() != 'None' ||
705 (this.type_ == 'WiMAX' || this.type_ == 'VPN'))) {
706 $('details-internet-configure').hidden = false;
707 } else {
708 $('details-internet-configure').hidden = true;
713 * Helper method called from initializeDetailsPage and updateConnectionData.
714 * Updates the connection state property and account / sim card links.
715 * @private
717 updateDetails_: function() {
718 var onc = this.onc_;
720 var connectionStateString = onc.getTranslatedValue('ConnectionState');
721 $('connection-state').textContent = connectionStateString;
723 var type = this.type_;
724 var showViewAccount = false;
725 var showActivate = false;
726 if (type == 'WiFi') {
727 $('wifi-connection-state').textContent = connectionStateString;
728 } else if (type == 'WiMAX') {
729 $('wimax-connection-state').textContent = connectionStateString;
730 } else if (type == 'Cellular') {
731 $('activation-state').textContent =
732 onc.getTranslatedValue('Cellular.ActivationState');
733 if (onc.getActiveValue('Cellular.Family') == 'GSM') {
734 var lockEnabled =
735 onc.getActiveValue('Cellular.SIMLockStatus.LockEnabled');
736 $('sim-card-lock-enabled').checked = lockEnabled;
737 $('change-pin').hidden = !lockEnabled;
739 showViewAccount = onc.getActiveValue('showViewAccountButton');
740 var activationState = onc.getActiveValue('Cellular.ActivationState');
741 showActivate = activationState == 'NotActivated' ||
742 activationState == 'PartiallyActivated';
745 $('view-account-details').hidden = !showViewAccount;
746 $('activate-details').hidden = !showActivate;
747 // If activation is not complete, hide the login button.
748 if (showActivate)
749 $('details-internet-login').hidden = true;
753 * Helper method called from initializeDetailsPage and updateConnectionData.
754 * Updates the fields in the header section of the details frame.
755 * @private
757 populateHeader_: function() {
758 var onc = this.onc_;
760 $('network-details-title').textContent =
761 this.networkTitle_ || onc.getTranslatedValue('Name');
763 var connectionState = onc.getActiveValue('ConnectionState');
764 var connectionStateString = onc.getTranslatedValue('ConnectionState');
765 $('network-details-subtitle-status').textContent = connectionStateString;
767 var typeKey;
768 var type = this.type_;
769 if (type == 'Ethernet')
770 typeKey = 'ethernetTitle';
771 else if (type == 'WiFi')
772 typeKey = 'wifiTitle';
773 else if (type == 'WiMAX')
774 typeKey = 'wimaxTitle';
775 else if (type == 'Cellular')
776 typeKey = 'cellularTitle';
777 else if (type == 'VPN')
778 typeKey = 'vpnTitle';
779 else
780 typeKey = null;
781 var typeLabel = $('network-details-subtitle-type');
782 var typeSeparator = $('network-details-subtitle-separator');
783 if (typeKey) {
784 typeLabel.textContent = loadTimeData.getString(typeKey);
785 typeLabel.hidden = false;
786 typeSeparator.hidden = false;
787 } else {
788 typeLabel.hidden = true;
789 typeSeparator.hidden = true;
794 * Helper method to insert a 'user' option into the Apn list.
795 * @param {Object} userOption The 'user' apn dictionary
796 * @private
798 insertApnUserOption_: function(userOption) {
799 // Add the 'user' option before the last option ('other')
800 var apnSelector = $('select-apn');
801 assert(apnSelector.length > 0);
802 var otherOption = apnSelector[apnSelector.length - 1];
803 apnSelector.add(userOption, otherOption);
804 this.userApnIndex_ = apnSelector.length - 2;
805 this.selectedApnIndex_ = this.userApnIndex_;
809 * Helper method called from initializeApnList to populate the Apn list.
810 * @param {Array} apnList List of available APNs.
811 * @private
813 populateApnList_: function(apnList) {
814 var onc = this.onc_;
815 var apnSelector = $('select-apn');
816 assert(apnSelector.length == 1);
817 var otherOption = apnSelector[0];
818 var activeApn = onc.getActiveValue('Cellular.APN.AccessPointName');
819 var activeUsername = onc.getActiveValue('Cellular.APN.Username');
820 var activePassword = onc.getActiveValue('Cellular.APN.Password');
821 var lastGoodApn =
822 onc.getActiveValue('Cellular.LastGoodAPN.AccessPointName');
823 var lastGoodUsername =
824 onc.getActiveValue('Cellular.LastGoodAPN.Username');
825 var lastGoodPassword =
826 onc.getActiveValue('Cellular.LastGoodAPN.Password');
827 for (var i = 0; i < apnList.length; i++) {
828 var apnDict = apnList[i];
829 var option = document.createElement('option');
830 var localizedName = apnDict['LocalizedName'];
831 var name = localizedName ? localizedName : apnDict['Name'];
832 var accessPointName = apnDict['AccessPointName'];
833 option.textContent =
834 name ? (name + ' (' + accessPointName + ')') : accessPointName;
835 option.value = i;
836 // Insert new option before 'other' option.
837 apnSelector.add(option, otherOption);
838 if (this.selectedApnIndex_ != -1)
839 continue;
840 // If this matches the active Apn name, or LastGoodApn name (or there
841 // is no last good APN), set it as the selected Apn.
842 if ((activeApn == accessPointName) ||
843 (!activeApn && (!lastGoodApn || lastGoodApn == accessPointName))) {
844 this.selectedApnIndex_ = i;
847 if (this.selectedApnIndex_ == -1 && activeApn) {
848 this.userApn_ = activeApn;
849 // Create a 'user' entry for any active apn not in the list.
850 var userOption = document.createElement('option');
851 userOption.textContent = activeApn;
852 userOption.value = -1;
853 this.insertApnUserOption_(userOption);
858 * Helper method called from initializeDetailsPage to initialize the Apn
859 * list.
860 * @private
862 initializeApnList_: function() {
863 this.selectedApnIndex_ = -1;
864 this.userApnIndex_ = -1;
866 var onc = this.onc_;
867 var apnSelector = $('select-apn');
869 // Clear APN lists, keep only last element, 'other'.
870 while (apnSelector.length != 1)
871 apnSelector.remove(0);
873 var apnList = onc.getActiveValue('Cellular.APNList');
874 if (apnList) {
875 // Populate the list with the existing APNs.
876 this.populateApnList_(apnList);
877 } else {
878 // Create a single 'default' entry.
879 var otherOption = apnSelector[0];
880 var defaultOption = document.createElement('option');
881 defaultOption.textContent =
882 loadTimeData.getString('cellularApnUseDefault');
883 defaultOption.value = -1;
884 // Add 'default' entry before 'other' option
885 apnSelector.add(defaultOption, otherOption);
886 assert(apnSelector.length == 2); // 'default', 'other'
887 this.selectedApnIndex_ = 0; // Select 'default'
889 assert(this.selectedApnIndex_ >= 0);
890 apnSelector.selectedIndex = this.selectedApnIndex_;
891 updateHidden('.apn-list-view', false);
892 updateHidden('.apn-details-view', true);
896 * Helper function for setting APN properties.
897 * @param {Object} apnValue Dictionary of APN properties.
898 * @private
900 setActiveApn_: function(apnValue) {
901 var activeApn = {};
902 var apnName = apnValue['AccessPointName'];
903 if (apnName) {
904 activeApn['AccessPointName'] = apnName;
905 activeApn['Username'] = stringFromValue(apnValue['Username']);
906 activeApn['Password'] = stringFromValue(apnValue['Password']);
908 // Set the cached ONC data.
909 this.onc_.setProperty('Cellular.APN', activeApn);
910 // Set an ONC object with just the APN values.
911 var oncData = new OncData({});
912 oncData.setProperty('Cellular.APN', activeApn);
913 chrome.networkingPrivate.setProperties(this.onc_.guid(),
914 oncData.getData());
918 * Event Listener for the cellular-apn-use-default button.
919 * @private
921 setDefaultApn_: function() {
922 var apnSelector = $('select-apn');
924 // Remove the 'user' entry if it exists.
925 if (this.userApnIndex_ != -1) {
926 assert(this.userApnIndex_ < apnSelector.length - 1);
927 apnSelector.remove(this.userApnIndex_);
928 this.userApnIndex_ = -1;
931 var apnList = this.onc_.getActiveValue('Cellular.APNList');
932 var iApn = (apnList != undefined && apnList.length > 0) ? 0 : -1;
933 apnSelector.selectedIndex = iApn;
934 this.selectedApnIndex_ = iApn;
936 // Clear any user APN entry to inform Chrome to use the default APN.
937 this.setActiveApn_({});
939 updateHidden('.apn-list-view', false);
940 updateHidden('.apn-details-view', true);
944 * Event Listener for the cellular-apn-set button.
945 * @private
947 setApn_: function(apnValue) {
948 if (apnValue == '')
949 return;
951 var apnSelector = $('select-apn');
953 var activeApn = {};
954 activeApn['AccessPointName'] = stringFromValue(apnValue);
955 activeApn['Username'] = stringFromValue($('cellular-apn-username').value);
956 activeApn['Password'] = stringFromValue($('cellular-apn-password').value);
957 this.setActiveApn_(activeApn);
958 // Set the user selected APN.
959 this.userApn_ = activeApn;
961 // Remove any existing 'user' entry.
962 if (this.userApnIndex_ != -1) {
963 assert(this.userApnIndex_ < apnSelector.length - 1);
964 apnSelector.remove(this.userApnIndex_);
965 this.userApnIndex_ = -1;
968 // Create a new 'user' entry with the new active apn.
969 var option = document.createElement('option');
970 option.textContent = activeApn['AccessPointName'];
971 option.value = -1;
972 option.selected = true;
973 this.insertApnUserOption_(option);
975 updateHidden('.apn-list-view', false);
976 updateHidden('.apn-details-view', true);
980 * Event Listener for the cellular-apn-cancel button.
981 * @private
983 cancelApn_: function() {
984 this.initializeApnList_();
988 * Event Listener for the select-apn button.
989 * @private
991 selectApn_: function() {
992 var onc = this.onc_;
993 var apnSelector = $('select-apn');
994 if (apnSelector[apnSelector.selectedIndex].value != -1) {
995 var apnList = onc.getActiveValue('Cellular.APNList');
996 var apnIndex = apnSelector.selectedIndex;
997 assert(apnIndex < apnList.length);
998 this.selectedApnIndex_ = apnIndex;
999 this.setActiveApn_(apnList[apnIndex]);
1000 } else if (apnSelector.selectedIndex == this.userApnIndex_) {
1001 this.selectedApnIndex_ = apnSelector.selectedIndex;
1002 this.setActiveApn_(this.userApn_);
1003 } else { // 'Other'
1004 var apnDict;
1005 if (this.userApn_['AccessPointName']) {
1006 // Fill in the details fields with the existing 'user' config.
1007 apnDict = this.userApn_;
1008 } else {
1009 // No 'user' config, use the current values.
1010 apnDict = {};
1011 apnDict['AccessPointName'] =
1012 onc.getActiveValue('Cellular.APN.AccessPointName');
1013 apnDict['Username'] = onc.getActiveValue('Cellular.APN.Username');
1014 apnDict['Password'] = onc.getActiveValue('Cellular.APN.Password');
1016 $('cellular-apn').value = stringFromValue(apnDict['AccessPointName']);
1017 $('cellular-apn-username').value = stringFromValue(apnDict['Username']);
1018 $('cellular-apn-password').value = stringFromValue(apnDict['Password']);
1019 updateHidden('.apn-list-view', true);
1020 updateHidden('.apn-details-view', false);
1026 * Enables or Disables all buttons that provide operations on the cellular
1027 * network.
1029 DetailsInternetPage.changeCellularButtonsState = function(disable) {
1030 var buttonsToDisableList =
1031 new Array('details-internet-login',
1032 'details-internet-disconnect',
1033 'details-internet-configure',
1034 'activate-details',
1035 'view-account-details');
1037 for (var i = 0; i < buttonsToDisableList.length; ++i) {
1038 var button = $(buttonsToDisableList[i]);
1039 button.disabled = disable;
1044 * Shows a spinner while the carrier is changed.
1046 DetailsInternetPage.showCarrierChangeSpinner = function(visible) {
1047 $('switch-carrier-spinner').hidden = !visible;
1048 // Disable any buttons that allow us to operate on cellular networks.
1049 DetailsInternetPage.changeCellularButtonsState(visible);
1053 * Changes the network carrier.
1055 DetailsInternetPage.handleCarrierChanged = function() {
1056 var carrierSelector = $('select-carrier');
1057 var carrier = carrierSelector[carrierSelector.selectedIndex].textContent;
1058 DetailsInternetPage.showCarrierChangeSpinner(true);
1059 chrome.send('setCarrier', [carrier]);
1063 * Performs minimal initialization of the InternetDetails dialog in
1064 * preparation for showing proxy-settings.
1066 DetailsInternetPage.initializeProxySettings = function() {
1067 DetailsInternetPage.getInstance().initializePageContents_();
1071 * Displays the InternetDetails dialog with only the proxy settings visible.
1073 DetailsInternetPage.showProxySettings = function() {
1074 var detailsPage = DetailsInternetPage.getInstance();
1075 $('network-details-header').hidden = true;
1076 $('activate-details').hidden = true;
1077 $('view-account-details').hidden = true;
1078 $('web-proxy-auto-discovery').hidden = true;
1079 detailsPage.showProxy_ = true;
1080 updateHidden('#internet-tab', true);
1081 updateHidden('#details-tab-strip', true);
1082 updateHidden('#details-internet-page .action-area', true);
1083 detailsPage.updateControls();
1084 detailsPage.visible = true;
1085 sendChromeMetricsAction('Options_NetworkShowProxyTab');
1089 * Initializes even handling for keyboard driven flow.
1091 DetailsInternetPage.initializeKeyboardFlow = function() {
1092 keyboard.initializeKeyboardFlow();
1095 DetailsInternetPage.updateProxySettings = function(type) {
1096 var proxyHost = null,
1097 proxyPort = null;
1099 if (type == 'cros.session.proxy.singlehttp') {
1100 proxyHost = 'proxy-host-single-name';
1101 proxyPort = 'proxy-host-single-port';
1102 } else if (type == 'cros.session.proxy.httpurl') {
1103 proxyHost = 'proxy-host-name';
1104 proxyPort = 'proxy-host-port';
1105 } else if (type == 'cros.session.proxy.httpsurl') {
1106 proxyHost = 'secure-proxy-host-name';
1107 proxyPort = 'secure-proxy-port';
1108 } else if (type == 'cros.session.proxy.ftpurl') {
1109 proxyHost = 'ftp-proxy';
1110 proxyPort = 'ftp-proxy-port';
1111 } else if (type == 'cros.session.proxy.socks') {
1112 proxyHost = 'socks-host';
1113 proxyPort = 'socks-port';
1114 } else {
1115 return;
1118 var hostValue = $(proxyHost).value;
1119 if (hostValue.indexOf(':') !== -1) {
1120 if (hostValue.match(/:/g).length == 1) {
1121 hostValue = hostValue.split(':');
1122 $(proxyHost).value = hostValue[0];
1123 $(proxyPort).value = hostValue[1];
1128 DetailsInternetPage.updateCarrier = function() {
1129 DetailsInternetPage.showCarrierChangeSpinner(false);
1132 DetailsInternetPage.loginFromDetails = function() {
1133 var detailsPage = DetailsInternetPage.getInstance();
1134 if (detailsPage.type_ == 'WiFi')
1135 sendChromeMetricsAction('Options_NetworkConnectToWifi');
1136 else if (detailsPage.type_ == 'VPN')
1137 sendChromeMetricsAction('Options_NetworkConnectToVPN');
1138 // TODO(stevenjb): chrome.networkingPrivate.startConnect
1139 chrome.send('startConnect', [detailsPage.onc_.guid()]);
1140 PageManager.closeOverlay();
1143 DetailsInternetPage.disconnectNetwork = function() {
1144 var detailsPage = DetailsInternetPage.getInstance();
1145 if (detailsPage.type_ == 'WiFi')
1146 sendChromeMetricsAction('Options_NetworkDisconnectWifi');
1147 else if (detailsPage.type_ == 'VPN')
1148 sendChromeMetricsAction('Options_NetworkDisconnectVPN');
1149 chrome.networkingPrivate.startDisconnect(detailsPage.onc_.guid());
1150 PageManager.closeOverlay();
1153 DetailsInternetPage.configureNetwork = function() {
1154 var detailsPage = DetailsInternetPage.getInstance();
1155 chrome.send('configureNetwork', [detailsPage.onc_.guid()]);
1156 PageManager.closeOverlay();
1159 DetailsInternetPage.activateFromDetails = function() {
1160 var detailsPage = DetailsInternetPage.getInstance();
1161 if (detailsPage.type_ == 'Cellular') {
1162 chrome.send('activateNetwork', [detailsPage.onc_.guid()]);
1164 PageManager.closeOverlay();
1168 * Event handler called when the details page is closed. Sends changed
1169 * properties to Chrome and closes the overlay.
1171 DetailsInternetPage.setDetails = function() {
1172 var detailsPage = DetailsInternetPage.getInstance();
1173 var type = detailsPage.type_;
1174 var oncData = new OncData({});
1175 var autoConnectCheckboxId = '';
1176 if (type == 'WiFi') {
1177 var preferredCheckbox =
1178 assertInstanceof($('prefer-network-wifi'), HTMLInputElement);
1179 if (!preferredCheckbox.hidden && !preferredCheckbox.disabled) {
1180 var kPreferredPriority = 1;
1181 var priority = preferredCheckbox.checked ? kPreferredPriority : 0;
1182 oncData.setProperty('Priority', priority);
1183 sendChromeMetricsAction('Options_NetworkSetPrefer');
1185 autoConnectCheckboxId = 'auto-connect-network-wifi';
1186 } else if (type == 'WiMAX') {
1187 autoConnectCheckboxId = 'auto-connect-network-wimax';
1188 } else if (type == 'Cellular') {
1189 autoConnectCheckboxId = 'auto-connect-network-cellular';
1190 } else if (type == 'VPN') {
1191 var providerType = detailsPage.onc_.getActiveValue('VPN.Type');
1192 if (providerType != 'ThirdPartyVPN') {
1193 oncData.setProperty('VPN.Type', providerType);
1194 oncData.setProperty('VPN.Host', $('inet-server-hostname').value);
1195 autoConnectCheckboxId = 'auto-connect-network-vpn';
1198 if (autoConnectCheckboxId != '') {
1199 var autoConnectCheckbox =
1200 assertInstanceof($(autoConnectCheckboxId), HTMLInputElement);
1201 if (!autoConnectCheckbox.hidden && !autoConnectCheckbox.disabled) {
1202 var autoConnectKey = type + '.AutoConnect';
1203 oncData.setProperty(autoConnectKey, !!autoConnectCheckbox.checked);
1204 sendChromeMetricsAction('Options_NetworkAutoConnect');
1208 var nameServerTypes = ['automatic', 'google', 'user'];
1209 var nameServerType = 'automatic';
1210 for (var i = 0; i < nameServerTypes.length; ++i) {
1211 if ($(nameServerTypes[i] + '-dns-radio').checked) {
1212 nameServerType = nameServerTypes[i];
1213 break;
1216 var ipConfig = detailsPage.getIpConfig_(nameServerType);
1217 var ipAddressType = ('IPAddress' in ipConfig) ? 'Static' : 'DHCP';
1218 var nameServersType = ('NameServers' in ipConfig) ? 'Static' : 'DHCP';
1219 oncData.setProperty('IPAddressConfigType', ipAddressType);
1220 oncData.setProperty('NameServersConfigType', nameServersType);
1221 oncData.setProperty('StaticIPConfig', ipConfig);
1223 var data = oncData.getData();
1224 if (Object.keys(data).length > 0) {
1225 // TODO(stevenjb): Only set changed properties.
1226 chrome.networkingPrivate.setProperties(detailsPage.onc_.guid(), data);
1229 PageManager.closeOverlay();
1233 * Event handler called when the name server type changes.
1234 * @param {string} type The selected name sever type, 'automatic', 'google',
1235 * or 'user'.
1237 DetailsInternetPage.updateNameServerDisplay = function(type) {
1238 var editable = type == 'user';
1239 var fields = [$('ipconfig-dns1'), $('ipconfig-dns2'),
1240 $('ipconfig-dns3'), $('ipconfig-dns4')];
1241 for (var i = 0; i < fields.length; ++i) {
1242 fields[i].editable = editable;
1244 if (editable)
1245 $('ipconfig-dns1').focus();
1247 var automaticDns = $('automatic-dns-display');
1248 var googleDns = $('google-dns-display');
1249 var userDns = $('user-dns-settings');
1250 switch (type) {
1251 case 'automatic':
1252 automaticDns.setAttribute('selected', '');
1253 googleDns.removeAttribute('selected');
1254 userDns.removeAttribute('selected');
1255 break;
1256 case 'google':
1257 automaticDns.removeAttribute('selected');
1258 googleDns.setAttribute('selected', '');
1259 userDns.removeAttribute('selected');
1260 break;
1261 case 'user':
1262 automaticDns.removeAttribute('selected');
1263 googleDns.removeAttribute('selected');
1264 userDns.setAttribute('selected', '');
1265 break;
1270 * Method called from Chrome when the ONC properties for the displayed
1271 * network may have changed.
1272 * @param {Object} oncData The updated ONC dictionary for the network.
1274 DetailsInternetPage.updateConnectionData = function(oncData) {
1275 var detailsPage = DetailsInternetPage.getInstance();
1276 if (!detailsPage.visible)
1277 return;
1279 if (oncData.GUID != detailsPage.onc_.guid())
1280 return;
1282 // Update our cached data object.
1283 detailsPage.onc_ = new OncData(oncData);
1285 detailsPage.populateHeader_();
1286 detailsPage.updateConnectionButtonVisibilty_();
1287 detailsPage.updateDetails_();
1291 * Initializes the details page with the provided ONC data.
1292 * @param {Object} oncData Dictionary of ONC properties.
1294 DetailsInternetPage.initializeDetailsPage = function(oncData) {
1295 var onc = new OncData(oncData);
1297 var detailsPage = DetailsInternetPage.getInstance();
1298 detailsPage.onc_ = onc;
1299 var type = onc.getActiveValue('Type');
1300 detailsPage.type_ = type;
1302 sendShowDetailsMetrics(type, onc.getActiveValue('ConnectionState'));
1304 if (type == 'VPN') {
1305 // Cache the dialog title, which will contain the provider name in the
1306 // case of a third-party VPN provider. This caching is important as the
1307 // provider may go away while the details dialog is being shown, causing
1308 // subsequent updates to be unable to determine the correct title.
1309 detailsPage.networkTitle_ = options.VPNProviders.formatNetworkName(onc);
1310 } else {
1311 delete detailsPage.networkTitle_;
1314 detailsPage.populateHeader_();
1315 detailsPage.updateConnectionButtonVisibilty_();
1316 detailsPage.updateDetails_();
1318 // Inform chrome which network to pass events for in InternetOptionsHandler.
1319 chrome.send('setNetworkGuid', [detailsPage.onc_.guid()]);
1321 // TODO(stevenjb): Some of the setup below should be moved to
1322 // updateDetails_() so that updates are reflected in the UI.
1324 // Only show proxy for remembered networks.
1325 var remembered = onc.getSource() != 'None';
1326 if (remembered) {
1327 detailsPage.showProxy_ = true;
1328 // Inform Chrome which network to use for proxy configuration.
1329 chrome.send('selectNetwork', [detailsPage.onc_.guid()]);
1330 } else {
1331 detailsPage.showProxy_ = false;
1334 $('web-proxy-auto-discovery').hidden = true;
1336 var restricted = onc.getActiveValue('RestrictedConnectivity');
1337 var restrictedString = loadTimeData.getString(
1338 restricted ? 'restrictedYes' : 'restrictedNo');
1340 // These objects contain an 'automatic' property that is displayed when
1341 // ip-automatic-configuration-checkbox is checked, and a 'value' property
1342 // that is displayed when unchecked and used to set the associated ONC
1343 // property for StaticIPConfig on commit.
1344 var inetAddress = {};
1345 var inetNetmask = {};
1346 var inetGateway = {};
1348 var inetNameServersString;
1350 var ipconfigList = onc.getActiveValue('IPConfigs');
1351 if (Array.isArray(ipconfigList)) {
1352 for (var i = 0; i < ipconfigList.length; ++i) {
1353 var ipconfig = ipconfigList[i];
1354 var ipType = ipconfig['Type'];
1355 if (ipType != 'IPv4') {
1356 // TODO(stevenjb): Handle IPv6 properties.
1357 continue;
1359 var address = ipconfig['IPAddress'];
1360 inetAddress.automatic = address;
1361 inetAddress.value = address;
1362 var netmask = prefixLengthToNetmask(ipconfig['RoutingPrefix']);
1363 inetNetmask.automatic = netmask;
1364 inetNetmask.value = netmask;
1365 var gateway = ipconfig['Gateway'];
1366 inetGateway.automatic = gateway;
1367 inetGateway.value = gateway;
1368 if ('WebProxyAutoDiscoveryUrl' in ipconfig) {
1369 $('web-proxy-auto-discovery').hidden = false;
1370 $('web-proxy-auto-discovery-url').value =
1371 ipconfig['WebProxyAutoDiscoveryUrl'];
1373 if ('NameServers' in ipconfig) {
1374 var inetNameServers = ipconfig['NameServers'];
1375 inetNameServers = inetNameServers.sort();
1376 inetNameServersString = inetNameServers.join(',');
1378 break; // Use the first IPv4 entry.
1382 // Override the 'automatic' properties with the saved DHCP values if the
1383 // saved value is set, and set any unset 'value' properties.
1384 var savedNameServersString;
1385 var savedIpAddress = onc.getActiveValue('SavedIPConfig.IPAddress');
1386 if (savedIpAddress != undefined) {
1387 inetAddress.automatic = savedIpAddress;
1388 if (!inetAddress.value)
1389 inetAddress.value = savedIpAddress;
1391 var savedPrefix = onc.getActiveValue('SavedIPConfig.RoutingPrefix');
1392 if (savedPrefix != undefined) {
1393 assert(typeof savedPrefix == 'number');
1394 var savedNetmask = prefixLengthToNetmask(
1395 /** @type {number} */(savedPrefix));
1396 inetNetmask.automatic = savedNetmask;
1397 if (!inetNetmask.value)
1398 inetNetmask.value = savedNetmask;
1400 var savedGateway = onc.getActiveValue('SavedIPConfig.Gateway');
1401 if (savedGateway != undefined) {
1402 inetGateway.automatic = savedGateway;
1403 if (!inetGateway.value)
1404 inetGateway.value = savedGateway;
1407 var savedNameServers = onc.getActiveValue('SavedIPConfig.NameServers');
1408 if (savedNameServers) {
1409 savedNameServers = savedNameServers.sort();
1410 savedNameServersString = savedNameServers.join(',');
1413 var ipAutoConfig = 'automatic';
1414 if (onc.getActiveValue('IPAddressConfigType') == 'Static') {
1415 ipAutoConfig = 'user';
1416 var staticIpAddress = onc.getActiveValue('StaticIPConfig.IPAddress');
1417 inetAddress.user = staticIpAddress;
1418 inetAddress.value = staticIpAddress;
1420 var staticPrefix = onc.getActiveValue('StaticIPConfig.RoutingPrefix');
1421 if (typeof staticPrefix != 'number')
1422 staticPrefix = 0;
1423 var staticNetmask = prefixLengthToNetmask(
1424 /** @type {number} */ (staticPrefix));
1425 inetNetmask.user = staticNetmask;
1426 inetNetmask.value = staticNetmask;
1428 var staticGateway = onc.getActiveValue('StaticIPConfig.Gateway');
1429 inetGateway.user = staticGateway;
1430 inetGateway.value = staticGateway;
1433 var staticNameServersString;
1434 if (onc.getActiveValue('NameServersConfigType') == 'Static') {
1435 var staticNameServers = onc.getActiveValue('StaticIPConfig.NameServers');
1436 staticNameServers = staticNameServers.sort();
1437 staticNameServersString = staticNameServers.join(',');
1440 $('ip-automatic-configuration-checkbox').checked =
1441 ipAutoConfig == 'automatic';
1443 inetAddress.autoConfig = ipAutoConfig;
1444 inetNetmask.autoConfig = ipAutoConfig;
1445 inetGateway.autoConfig = ipAutoConfig;
1447 var configureAddressField = function(field, model) {
1448 IPAddressField.decorate(field);
1449 field.model = model;
1450 field.editable = model.autoConfig == 'user';
1452 configureAddressField($('ip-address'), inetAddress);
1453 configureAddressField($('ip-netmask'), inetNetmask);
1454 configureAddressField($('ip-gateway'), inetGateway);
1456 // Set Nameserver fields. Nameservers are 'automatic' by default. If a
1457 // static namerserver is set, use that unless it does not match a non
1458 // empty 'NameServers' value (indicating that the custom nameservers are
1459 // invalid or not being applied for some reason). TODO(stevenjb): Only
1460 // set these properites if they change so that invalid custom values do
1461 // not get lost.
1462 var nameServerType = 'automatic';
1463 if (staticNameServersString &&
1464 (!inetNameServersString ||
1465 staticNameServersString == inetNameServersString)) {
1466 if (staticNameServersString == GoogleNameServers.join(','))
1467 nameServerType = 'google';
1468 else
1469 nameServerType = 'user';
1471 if (nameServerType == 'automatic')
1472 $('automatic-dns-display').textContent = inetNameServersString;
1473 else
1474 $('automatic-dns-display').textContent = savedNameServersString;
1475 $('google-dns-display').textContent = GoogleNameServers.join(',');
1477 var nameServersUser = [];
1478 if (staticNameServers) {
1479 nameServersUser = staticNameServers;
1480 } else if (savedNameServers) {
1481 // Pre-populate with values provided by DHCP server.
1482 nameServersUser = savedNameServers;
1485 var nameServerModels = [];
1486 for (var i = 0; i < 4; ++i)
1487 nameServerModels.push({value: nameServersUser[i] || ''});
1489 $(nameServerType + '-dns-radio').checked = true;
1490 configureAddressField($('ipconfig-dns1'), nameServerModels[0]);
1491 configureAddressField($('ipconfig-dns2'), nameServerModels[1]);
1492 configureAddressField($('ipconfig-dns3'), nameServerModels[2]);
1493 configureAddressField($('ipconfig-dns4'), nameServerModels[3]);
1495 DetailsInternetPage.updateNameServerDisplay(nameServerType);
1497 var macAddress = onc.getActiveValue('MacAddress');
1498 if (macAddress) {
1499 $('hardware-address').textContent = macAddress;
1500 $('hardware-address-row').style.display = 'table-row';
1501 } else {
1502 // This is most likely a device without a hardware address.
1503 $('hardware-address-row').style.display = 'none';
1506 var setOrHideParent = function(field, property) {
1507 if (property != undefined) {
1508 $(field).textContent = property;
1509 $(field).parentElement.hidden = false;
1510 } else {
1511 $(field).parentElement.hidden = true;
1515 var networkName = onc.getTranslatedValue('Name');
1517 // Signal strength as percentage (for WiFi and WiMAX).
1518 var signalStrength;
1519 if (type == 'WiFi' || type == 'WiMAX')
1520 signalStrength = onc.getActiveValue(type + '.SignalStrength');
1521 if (!signalStrength)
1522 signalStrength = 0;
1523 var strengthFormat = loadTimeData.getString('inetSignalStrengthFormat');
1524 var strengthString = strengthFormat.replace('$1', signalStrength);
1526 if (type == 'WiFi') {
1527 OptionsPage.showTab($('wifi-network-nav-tab'));
1528 $('wifi-restricted-connectivity').textContent = restrictedString;
1529 var ssid = onc.getActiveValue('WiFi.SSID');
1530 $('wifi-ssid').textContent = ssid ? ssid : networkName;
1531 setOrHideParent('wifi-bssid', onc.getActiveValue('WiFi.BSSID'));
1532 var security = onc.getWiFiSecurity();
1533 if (security == 'None')
1534 security = undefined;
1535 setOrHideParent('wifi-security', security);
1536 // Frequency is in MHz.
1537 var frequency = onc.getActiveValue('WiFi.Frequency');
1538 if (!frequency)
1539 frequency = 0;
1540 var frequencyFormat = loadTimeData.getString('inetFrequencyFormat');
1541 frequencyFormat = frequencyFormat.replace('$1', frequency);
1542 $('wifi-frequency').textContent = frequencyFormat;
1543 $('wifi-signal-strength').textContent = strengthString;
1544 setOrHideParent('wifi-hardware-address',
1545 onc.getActiveValue('MacAddress'));
1546 var priority = onc.getActiveValue('Priority');
1547 $('prefer-network-wifi').checked = priority > 0;
1548 $('prefer-network-wifi').disabled = !remembered;
1549 $('auto-connect-network-wifi').checked =
1550 onc.getActiveValue('WiFi.AutoConnect');
1551 $('auto-connect-network-wifi').disabled = !remembered;
1552 } else if (type == 'WiMAX') {
1553 OptionsPage.showTab($('wimax-network-nav-tab'));
1554 $('wimax-restricted-connectivity').textContent = restrictedString;
1556 $('auto-connect-network-wimax').checked =
1557 onc.getActiveValue('WiMAX.AutoConnect');
1558 $('auto-connect-network-wimax').disabled = !remembered;
1559 var identity = onc.getActiveValue('WiMAX.EAP.Identity');
1560 setOrHideParent('wimax-eap-identity', identity);
1561 $('wimax-signal-strength').textContent = strengthString;
1562 } else if (type == 'Cellular') {
1563 OptionsPage.showTab($('cellular-conn-nav-tab'));
1565 var isGsm = onc.getActiveValue('Cellular.Family') == 'GSM';
1567 var currentCarrierIndex = -1;
1568 if (loadTimeData.getValue('showCarrierSelect')) {
1569 var currentCarrier =
1570 isGsm ? CarrierGenericUMTS : onc.getActiveValue('Cellular.Carrier');
1571 var supportedCarriers =
1572 onc.getActiveValue('Cellular.SupportedCarriers');
1573 for (var c1 = 0; c1 < supportedCarriers.length; ++c1) {
1574 if (supportedCarriers[c1] == currentCarrier) {
1575 currentCarrierIndex = c1;
1576 break;
1579 if (currentCarrierIndex != -1) {
1580 var carrierSelector = $('select-carrier');
1581 carrierSelector.onchange = DetailsInternetPage.handleCarrierChanged;
1582 carrierSelector.options.length = 0;
1583 for (var c2 = 0; c2 < supportedCarriers.length; ++c2) {
1584 var option = document.createElement('option');
1585 option.textContent = supportedCarriers[c2];
1586 carrierSelector.add(option);
1588 carrierSelector.selectedIndex = currentCarrierIndex;
1591 if (currentCarrierIndex == -1)
1592 $('service-name').textContent = networkName;
1594 // TODO(stevenjb): Ideally many of these should be localized.
1595 $('network-technology').textContent =
1596 onc.getActiveValue('Cellular.NetworkTechnology');
1597 $('roaming-state').textContent =
1598 onc.getTranslatedValue('Cellular.RoamingState');
1599 $('cellular-restricted-connectivity').textContent = restrictedString;
1600 $('error-state').textContent = onc.getActiveValue('ErrorState');
1601 $('manufacturer').textContent =
1602 onc.getActiveValue('Cellular.Manufacturer');
1603 $('model-id').textContent = onc.getActiveValue('Cellular.ModelID');
1604 $('firmware-revision').textContent =
1605 onc.getActiveValue('Cellular.FirmwareRevision');
1606 $('hardware-revision').textContent =
1607 onc.getActiveValue('Cellular.HardwareRevision');
1608 $('mdn').textContent = onc.getActiveValue('Cellular.MDN');
1610 // Show ServingOperator properties only if available.
1611 var servingOperatorName =
1612 onc.getActiveValue('Cellular.ServingOperator.Name');
1613 var servingOperatorCode =
1614 onc.getActiveValue('Cellular.ServingOperator.Code');
1615 if (servingOperatorName != undefined &&
1616 servingOperatorCode != undefined) {
1617 $('operator-name').textContent = servingOperatorName;
1618 $('operator-code').textContent = servingOperatorCode;
1619 } else {
1620 $('operator-name').parentElement.hidden = true;
1621 $('operator-code').parentElement.hidden = true;
1623 // Make sure that GSM/CDMA specific properties that shouldn't be hidden
1624 // are visible.
1625 updateHidden('#details-internet-page .gsm-only', false);
1626 updateHidden('#details-internet-page .cdma-only', false);
1628 // Show IMEI/ESN/MEID/MIN/PRL only if they are available.
1629 setOrHideParent('esn', onc.getActiveValue('Cellular.ESN'));
1630 setOrHideParent('imei', onc.getActiveValue('Cellular.IMEI'));
1631 setOrHideParent('meid', onc.getActiveValue('Cellular.MEID'));
1632 setOrHideParent('min', onc.getActiveValue('Cellular.MIN'));
1633 setOrHideParent('prl-version', onc.getActiveValue('Cellular.PRLVersion'));
1635 if (isGsm) {
1636 $('iccid').textContent = onc.getActiveValue('Cellular.ICCID');
1637 $('imsi').textContent = onc.getActiveValue('Cellular.IMSI');
1638 detailsPage.initializeApnList_();
1640 $('auto-connect-network-cellular').checked =
1641 onc.getActiveValue('Cellular.AutoConnect');
1642 $('auto-connect-network-cellular').disabled = false;
1643 } else if (type == 'VPN') {
1644 OptionsPage.showTab($('vpn-nav-tab'));
1645 var providerType = onc.getActiveValue('VPN.Type');
1646 var isThirdPartyVPN = providerType == 'ThirdPartyVPN';
1647 $('vpn-tab').classList.toggle('third-party-vpn-provider',
1648 isThirdPartyVPN);
1650 $('inet-service-name').textContent = networkName;
1651 $('inet-provider-type').textContent =
1652 onc.getTranslatedValue('VPN.Type');
1654 if (isThirdPartyVPN) {
1655 $('inet-provider-name').textContent = '';
1656 var extensionID = onc.getActiveValue('VPN.ThirdPartyVPN.ExtensionID');
1657 var providers = options.VPNProviders.getProviders();
1658 for (var i = 0; i < providers.length; ++i) {
1659 if (extensionID == providers[i].extensionID) {
1660 $('inet-provider-name').textContent = providers[i].name;
1661 break;
1664 } else {
1665 var usernameKey;
1666 if (providerType == 'OpenVPN')
1667 usernameKey = 'VPN.OpenVPN.Username';
1668 else if (providerType == 'L2TP-IPsec')
1669 usernameKey = 'VPN.L2TP.Username';
1671 if (usernameKey) {
1672 $('inet-username').parentElement.hidden = false;
1673 $('inet-username').textContent = onc.getActiveValue(usernameKey);
1674 } else {
1675 $('inet-username').parentElement.hidden = true;
1677 var inetServerHostname = $('inet-server-hostname');
1678 inetServerHostname.value = onc.getActiveValue('VPN.Host');
1679 inetServerHostname.resetHandler = function() {
1680 PageManager.hideBubble();
1681 var recommended = onc.getRecommendedValue('VPN.Host');
1682 if (recommended != undefined)
1683 inetServerHostname.value = recommended;
1685 $('auto-connect-network-vpn').checked =
1686 onc.getActiveValue('VPN.AutoConnect');
1687 $('auto-connect-network-vpn').disabled = false;
1689 } else {
1690 OptionsPage.showTab($('internet-nav-tab'));
1693 // Update controlled option indicators.
1694 var indicators = cr.doc.querySelectorAll(
1695 '#details-internet-page .controlled-setting-indicator');
1696 for (var i = 0; i < indicators.length; i++) {
1697 var managed = indicators[i].hasAttribute('managed');
1698 // TODO(stevenjb): Eliminate support for 'data' once 39 is stable.
1699 var attributeName = managed ? 'managed' : 'data';
1700 var propName = indicators[i].getAttribute(attributeName);
1701 if (!propName)
1702 continue;
1703 var propValue = managed ?
1704 onc.getManagedProperty(propName) :
1705 onc.getActiveValue(propName);
1706 // If the property is unset or unmanaged (i.e. not an Object) skip it.
1707 if (propValue == undefined || (typeof propValue != 'object'))
1708 continue;
1709 var event;
1710 if (managed)
1711 event = detailsPage.createManagedEvent_(propName, propValue);
1712 else
1713 event = detailsPage.createControlledEvent_(propName,
1714 /** @type {{value: *, controlledBy: *, recommendedValue: *}} */(
1715 propValue));
1716 indicators[i].handlePrefChange(event);
1717 var forElement = $(indicators[i].getAttribute('internet-detail-for'));
1718 if (forElement) {
1719 if (event.value.controlledBy == 'policy')
1720 forElement.disabled = true;
1721 if (forElement.resetHandler)
1722 indicators[i].resetHandler = forElement.resetHandler;
1726 detailsPage.updateControls();
1728 // Don't show page name in address bar and in history to prevent people
1729 // navigate here by hand and solve issue with page session restore.
1730 PageManager.showPageByName('detailsInternetPage', false);
1733 return {
1734 DetailsInternetPage: DetailsInternetPage