No dual_mode on Win10+ shortcuts.
[chromium-blink-merge.git] / chrome / browser / resources / options / chromeos / internet_detail.js
bloba21fd1bc45cccbdfa265d215f5dbf1688191425e
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';
21 /** @const */ var CarrierSprint = 'Sprint';
22 /** @const */ var CarrierVerizon = 'Verizon Wireless';
24 /**
25 * Helper function to set hidden attribute for elements matching a selector.
26 * @param {string} selector CSS selector for extracting a list of elements.
27 * @param {boolean} hidden New hidden value.
29 function updateHidden(selector, hidden) {
30 var elements = cr.doc.querySelectorAll(selector);
31 for (var i = 0, el; el = elements[i]; i++) {
32 el.hidden = hidden;
36 /**
37 * Helper function to update the properties of the data object from the
38 * properties in the update object.
39 * @param {Object} data Object to update.
40 * @param {Object} update Object containing the updated properties.
42 function updateDataObject(data, update) {
43 for (var prop in update) {
44 if (prop in data)
45 data[prop] = update[prop];
49 /**
50 * Monitor pref change of given element.
51 * @param {Element} el Target element.
53 function observePrefsUI(el) {
54 Preferences.getInstance().addEventListener(el.pref, handlePrefUpdate);
57 /**
58 * UI pref change handler.
59 * @param {Event} e The update event.
61 function handlePrefUpdate(e) {
62 DetailsInternetPage.getInstance().updateControls();
65 /**
66 * Simple helper method for converting a field to a string. It is used to
67 * easily assign an empty string from fields that may be unknown or undefined.
68 * @param {Object} value that should be converted to a string.
69 * @return {string} the result.
71 function stringFromValue(value) {
72 return value ? String(value) : '';
75 /**
76 * @param {string} action An action to send to coreOptionsUserMetricsAction.
78 function sendChromeMetricsAction(action) {
79 chrome.send('coreOptionsUserMetricsAction', [action]);
82 /**
83 * Send metrics to Chrome when the detailed page is opened.
84 * @param {string} type The ONC type of the network being shown.
85 * @param {string} state The ONC network state.
87 function sendShowDetailsMetrics(type, state) {
88 if (type == 'WiFi') {
89 sendChromeMetricsAction('Options_NetworkShowDetailsWifi');
90 if (state != 'NotConnected')
91 sendChromeMetricsAction('Options_NetworkShowDetailsWifiConnected');
92 } else if (type == 'Cellular') {
93 sendChromeMetricsAction('Options_NetworkShowDetailsCellular');
94 if (state != 'NotConnected')
95 sendChromeMetricsAction('Options_NetworkShowDetailsCellularConnected');
96 } else if (type == 'VPN') {
97 sendChromeMetricsAction('Options_NetworkShowDetailsVPN');
98 if (state != 'NotConnected')
99 sendChromeMetricsAction('Options_NetworkShowDetailsVPNConnected');
104 * Returns the netmask as a string for a given prefix length.
105 * @param {number} prefixLength The ONC routing prefix length.
106 * @return {string} The corresponding netmask.
108 function prefixLengthToNetmask(prefixLength) {
109 // Return the empty string for invalid inputs.
110 if (prefixLength < 0 || prefixLength > 32)
111 return '';
112 var netmask = '';
113 for (var i = 0; i < 4; ++i) {
114 var remainder = 8;
115 if (prefixLength >= 8) {
116 prefixLength -= 8;
117 } else {
118 remainder = prefixLength;
119 prefixLength = 0;
121 if (i > 0)
122 netmask += '.';
123 var value = 0;
124 if (remainder != 0)
125 value = ((2 << (remainder - 1)) - 1) << (8 - remainder);
126 netmask += value.toString();
128 return netmask;
132 * Returns the prefix length from the netmask string.
133 * @param {string} netmask The netmask string, e.g. 255.255.255.0.
134 * @return {number} The corresponding netmask or -1 if invalid.
136 function netmaskToPrefixLength(netmask) {
137 var prefixLength = 0;
138 var tokens = netmask.split('.');
139 if (tokens.length != 4)
140 return -1;
141 for (var i = 0; i < tokens.length; ++i) {
142 var token = tokens[i];
143 // If we already found the last mask and the current one is not
144 // '0' then the netmask is invalid. For example, 255.224.255.0
145 if (prefixLength / 8 != i) {
146 if (token != '0')
147 return -1;
148 } else if (token == '255') {
149 prefixLength += 8;
150 } else if (token == '254') {
151 prefixLength += 7;
152 } else if (token == '252') {
153 prefixLength += 6;
154 } else if (token == '248') {
155 prefixLength += 5;
156 } else if (token == '240') {
157 prefixLength += 4;
158 } else if (token == '224') {
159 prefixLength += 3;
160 } else if (token == '192') {
161 prefixLength += 2;
162 } else if (token == '128') {
163 prefixLength += 1;
164 } else if (token == '0') {
165 prefixLength += 0;
166 } else {
167 // mask is not a valid number.
168 return -1;
171 return prefixLength;
174 // Returns true if we should show the 'View Account' button for |onc|.
175 // TODO(stevenjb): We should query the Mobile Config API for whether or not to
176 // show the 'View Account' button once it is integrated with Settings.
177 function shouldShowViewAccountButton(onc) {
178 var activationState = onc.getActiveValue('Cellular.ActivationState');
179 if (activationState != 'Activating' && activationState != 'Activated')
180 return false;
182 // If no online payment URL was provided by Shill, only show 'View Account'
183 // for Verizon Wireless.
184 if (!onc.getActiveValue('Cellular.PaymentPortal.Url') &&
185 onc.getActiveValue('Cellular.Carrier') != CarrierVerizon) {
186 return false;
189 // 'View Account' should only be shown for connected networks, or
190 // disconnected LTE networks with a valid MDN.
191 var connectionState = onc.getActiveValue('ConnectionState');
192 if (connectionState != 'Connected') {
193 var technology = onc.getActiveValue('Cellular.NetworkTechnology');
194 if (technology != 'LTE' && technology != 'LTEAdvanced')
195 return false;
196 if (!onc.getActiveValue('Cellular.MDN'))
197 return false;
200 return true;
203 /////////////////////////////////////////////////////////////////////////////
204 // DetailsInternetPage class:
207 * Encapsulated handling of ChromeOS internet details overlay page.
208 * @constructor
209 * @extends {cr.ui.pageManager.Page}
211 function DetailsInternetPage() {
212 // If non-negative, indicates a custom entry in select-apn.
213 this.userApnIndex_ = -1;
215 // The custom APN properties associated with entry |userApnIndex_|.
216 this.userApn_ = {};
218 // The currently selected APN entry in $('select-apn') (which may or may not
219 // == userApnIndex_).
220 this.selectedApnIndex_ = -1;
222 // We show the Proxy configuration tab for remembered networks and when
223 // configuring a proxy from the login screen.
224 this.showProxy_ = false;
226 Page.call(this, 'detailsInternetPage', '', 'details-internet-page');
229 cr.addSingletonGetter(DetailsInternetPage);
231 DetailsInternetPage.prototype = {
232 __proto__: Page.prototype,
234 /** @override */
235 initializePage: function() {
236 Page.prototype.initializePage.call(this);
237 this.initializePageContents_();
239 chrome.networkingPrivate.onNetworksChanged.addListener(
240 this.onNetworksChanged_.bind(this));
242 this.showNetworkDetails_();
246 * Automatically shows the network details dialog if network information
247 * is included in the URL.
249 showNetworkDetails_: function() {
250 var guid = parseQueryParams(window.location).guid;
251 if (!guid || !guid.length)
252 return;
253 chrome.send('loadVPNProviders');
254 chrome.networkingPrivate.getManagedProperties(
255 guid, DetailsInternetPage.initializeDetailsPage);
259 * networkingPrivate callback when networks change.
260 * @param {Array<string>} changes List of GUIDs whose properties have
261 * changed.
262 * @private
264 onNetworksChanged_: function(changes) {
265 if (!this.onc_)
266 return;
267 var guid = this.onc_.guid();
268 if (changes.indexOf(guid) != -1) {
269 chrome.networkingPrivate.getManagedProperties(
270 guid, DetailsInternetPage.updateConnectionData);
275 * Initializes the contents of the page.
277 initializePageContents_: function() {
278 $('details-internet-dismiss').addEventListener('click', function(event) {
279 DetailsInternetPage.setDetails();
282 $('details-internet-login').addEventListener('click', function(event) {
283 DetailsInternetPage.setDetails();
284 DetailsInternetPage.loginFromDetails();
287 $('details-internet-disconnect').addEventListener('click',
288 function(event) {
289 DetailsInternetPage.setDetails();
290 DetailsInternetPage.disconnectNetwork();
293 $('details-internet-configure').addEventListener('click',
294 function(event) {
295 DetailsInternetPage.setDetails();
296 DetailsInternetPage.configureNetwork();
299 $('activate-details').addEventListener('click', function(event) {
300 DetailsInternetPage.activateFromDetails();
303 $('view-account-details').addEventListener('click', function(event) {
304 chrome.send('showMorePlanInfo',
305 [DetailsInternetPage.getInstance().onc_.guid()]);
306 PageManager.closeOverlay();
309 $('cellular-apn-use-default').addEventListener('click', function(event) {
310 DetailsInternetPage.getInstance().setDefaultApn_();
313 $('cellular-apn-set').addEventListener('click', function(event) {
314 DetailsInternetPage.getInstance().setApn_($('cellular-apn').value);
317 $('cellular-apn-cancel').addEventListener('click', function(event) {
318 DetailsInternetPage.getInstance().cancelApn_();
321 $('select-apn').addEventListener('change', function(event) {
322 DetailsInternetPage.getInstance().selectApn_();
325 $('sim-card-lock-enabled').addEventListener('click', function(event) {
326 var newValue = $('sim-card-lock-enabled').checked;
327 // Leave value as is because user needs to enter PIN code first.
328 // When PIN will be entered and value changed,
329 // we'll update UI to reflect that change.
330 $('sim-card-lock-enabled').checked = !newValue;
331 var operation = newValue ? 'setLocked' : 'setUnlocked';
332 chrome.send('simOperation', [operation]);
334 $('change-pin').addEventListener('click', function(event) {
335 chrome.send('simOperation', ['changePin']);
338 // Proxy
339 ['proxy-host-single-port',
340 'secure-proxy-port',
341 'socks-port',
342 'ftp-proxy-port',
343 'proxy-host-port'
344 ].forEach(function(id) {
345 options.PrefPortNumber.decorate($(id));
348 options.proxyexceptions.ProxyExceptions.decorate($('ignored-host-list'));
349 $('remove-host').addEventListener('click',
350 this.handleRemoveProxyExceptions_);
351 $('add-host').addEventListener('click', this.handleAddProxyException_);
352 $('direct-proxy').addEventListener('click', this.disableManualProxy_);
353 $('manual-proxy').addEventListener('click', this.enableManualProxy_);
354 $('auto-proxy').addEventListener('click', this.disableManualProxy_);
355 $('proxy-all-protocols').addEventListener('click',
356 this.toggleSingleProxy_);
357 $('proxy-use-pac-url').addEventListener('change',
358 this.handleAutoConfigProxy_);
360 observePrefsUI($('direct-proxy'));
361 observePrefsUI($('manual-proxy'));
362 observePrefsUI($('auto-proxy'));
363 observePrefsUI($('proxy-all-protocols'));
364 observePrefsUI($('proxy-use-pac-url'));
366 $('ip-automatic-configuration-checkbox').addEventListener('click',
367 this.handleIpAutoConfig_);
368 $('automatic-dns-radio').addEventListener('click',
369 this.handleNameServerTypeChange_);
370 $('google-dns-radio').addEventListener('click',
371 this.handleNameServerTypeChange_);
372 $('user-dns-radio').addEventListener('click',
373 this.handleNameServerTypeChange_);
375 // We only load this string if we have the string data available
376 // because the proxy settings page on the login screen re-uses the
377 // proxy sub-page from the internet options, and it doesn't ever
378 // show the DNS settings, so we don't need this string there.
379 // The string isn't available because
380 // chrome://settings-frame/strings.js (where the string is
381 // stored) is not accessible from the login screen.
382 // TODO(pneubeck): Remove this once i18n of the proxy dialog on the login
383 // page is fixed. http://crbug.com/242865
384 if (loadTimeData.data_) {
385 $('google-dns-label').innerHTML =
386 loadTimeData.getString('googleNameServers');
391 * Handler for "add" event fired from userNameEdit.
392 * @param {Event} e Add event fired from userNameEdit.
393 * @private
395 handleAddProxyException_: function(e) {
396 var exception = $('new-host').value;
397 $('new-host').value = '';
399 exception = exception.trim();
400 if (exception)
401 $('ignored-host-list').addException(exception);
405 * Handler for when the remove button is clicked
406 * @param {Event} e The click event.
407 * @private
409 handleRemoveProxyExceptions_: function(e) {
410 var selectedItems = $('ignored-host-list').selectedItems;
411 for (var x = 0; x < selectedItems.length; x++) {
412 $('ignored-host-list').removeException(selectedItems[x]);
417 * Handler for when the IP automatic configuration checkbox is clicked.
418 * @param {Event} e The click event.
419 * @private
421 handleIpAutoConfig_: function(e) {
422 var checked = $('ip-automatic-configuration-checkbox').checked;
423 var fields = [$('ip-address'), $('ip-netmask'), $('ip-gateway')];
424 for (var i = 0; i < fields.length; ++i) {
425 fields[i].editable = !checked;
426 if (checked) {
427 var model = fields[i].model;
428 model.value = model.automatic;
429 fields[i].model = model;
432 if (!checked)
433 $('ip-address').focus();
437 * Handler for when the name server selection changes.
438 * @param {Event} event The click event.
439 * @private
441 handleNameServerTypeChange_: function(event) {
442 var type = event.target.value;
443 DetailsInternetPage.updateNameServerDisplay(type);
447 * Gets the IPConfig ONC Object.
448 * @param {string} nameServerType The selected name server type:
449 * 'automatic', 'google', or 'user'.
450 * @return {Object} The IPConfig ONC object.
451 * @private
453 getIpConfig_: function(nameServerType) {
454 var ipConfig = {};
455 // If 'ip-address' is empty, automatic configuration will be used.
456 if (!$('ip-automatic-configuration-checkbox').checked &&
457 $('ip-address').model.value) {
458 ipConfig['IPAddress'] = $('ip-address').model.value;
459 var netmask = $('ip-netmask').model.value;
460 var routingPrefix = 0;
461 if (netmask) {
462 routingPrefix = netmaskToPrefixLength(netmask);
463 if (routingPrefix == -1) {
464 console.error('Invalid netmask: ' + netmask);
465 routingPrefix = 0;
468 ipConfig['RoutingPrefix'] = routingPrefix;
469 ipConfig['Gateway'] = $('ip-gateway').model.value || '';
472 // Note: If no nameserver fields are set, automatic configuration will be
473 // used. TODO(stevenjb): Validate input fields.
474 if (nameServerType != 'automatic') {
475 var userNameServers = [];
476 if (nameServerType == 'google') {
477 userNameServers = GoogleNameServers.slice();
478 } else if (nameServerType == 'user') {
479 for (var i = 1; i <= 4; ++i) {
480 var nameServerField = $('ipconfig-dns' + i);
481 // Skip empty values.
482 if (nameServerField && nameServerField.model &&
483 nameServerField.model.value) {
484 userNameServers.push(nameServerField.model.value);
488 if (userNameServers.length)
489 ipConfig['NameServers'] = userNameServers.sort();
491 return ipConfig;
495 * Creates an indicator event for controlled properties using
496 * the same dictionary format as CoreOptionsHandler::CreateValueForPref.
497 * @param {string} name The name for the Event.
498 * @param {{value: *, controlledBy: *, recommendedValue: *}} propData
499 * Property dictionary.
500 * @private
502 createControlledEvent_: function(name, propData) {
503 assert('value' in propData && 'controlledBy' in propData &&
504 'recommendedValue' in propData);
505 var event = new Event(name);
506 event.value = {
507 value: propData.value,
508 controlledBy: propData.controlledBy,
509 recommendedValue: propData.recommendedValue
511 return event;
515 * Creates an indicator event for controlled properties using
516 * the ONC getManagedProperties dictionary format.
517 * @param {string} name The name for the Event.
518 * @param {Object} propData ONC managed network property dictionary.
519 * @private
521 createManagedEvent_: function(name, propData) {
522 var event = new Event(name);
523 event.value = {};
525 // Set the current value and recommended value.
526 var activeValue = propData['Active'];
527 var effective = propData['Effective'];
528 if (activeValue == undefined)
529 activeValue = propData[effective];
530 event.value.value = activeValue;
532 // If a property is editable then it is not enforced, and 'controlledBy'
533 // is set to 'recommended' unless effective == {User|Shared}Setting, in
534 // which case the value was modified from the recommended value.
535 // Otherwise if 'Effective' is set to 'UserPolicy' or 'DevicePolicy' then
536 // the set value is mandated by the policy.
537 if (propData['UserEditable']) {
538 if (effective == 'UserPolicy')
539 event.value.controlledBy = 'recommended';
540 event.value.recommendedValue = propData['UserPolicy'];
541 } else if (propData['DeviceEditable']) {
542 if (effective == 'DevicePolicy')
543 event.value.controlledBy = 'recommended';
544 event.value.recommendedValue = propData['DevicePolicy'];
545 } else if (effective == 'UserPolicy' || effective == 'DevicePolicy') {
546 event.value.controlledBy = 'policy';
549 return event;
553 * Update details page controls.
555 updateControls: function() {
556 // Note: onc may be undefined when called from a pref update before
557 // initialized in initializeDetailsPage.
558 var onc = this.onc_;
560 // Always show the ipconfig section. TODO(stevenjb): Improve the display
561 // for unconnected networks. Currently the IP address fields may be
562 // blank if the network is not connected.
563 $('ipconfig-section').hidden = false;
564 $('ipconfig-dns-section').hidden = false;
566 // Network type related.
567 updateHidden('#details-internet-page .cellular-details',
568 this.type_ != 'Cellular');
569 updateHidden('#details-internet-page .wifi-details',
570 this.type_ != 'WiFi');
571 updateHidden('#details-internet-page .wimax-details',
572 this.type_ != 'WiMAX');
573 updateHidden('#details-internet-page .vpn-details', this.type_ != 'VPN');
574 updateHidden('#details-internet-page .proxy-details', !this.showProxy_);
576 // Cellular
577 if (onc && this.type_ == 'Cellular') {
578 // Hide gsm/cdma specific elements.
579 if (onc.getActiveValue('Cellular.Family') == 'GSM')
580 updateHidden('#details-internet-page .cdma-only', true);
581 else
582 updateHidden('#details-internet-page .gsm-only', true);
585 // Wifi
587 // Hide network tab for VPN.
588 updateHidden('#details-internet-page .network-details',
589 this.type_ == 'VPN');
591 // Password and shared.
592 var source = onc ? onc.getSource() : 'None';
593 var shared = (source == 'Device' || source == 'DevicePolicy');
594 var security = onc ? onc.getWiFiSecurity() : 'None';
595 updateHidden('#details-internet-page #password-details',
596 this.type_ != 'WiFi' || security == 'None');
597 updateHidden('#details-internet-page #wifi-shared-network', !shared);
598 updateHidden('#details-internet-page #prefer-network', source == 'None');
600 // WiMAX.
601 updateHidden('#details-internet-page #wimax-shared-network', !shared);
603 // Proxy
604 this.updateProxyBannerVisibility_();
605 this.toggleSingleProxy_();
606 if ($('manual-proxy').checked)
607 this.enableManualProxy_();
608 else
609 this.disableManualProxy_();
613 * Updates info banner visibility state. This function shows the banner
614 * if proxy is managed or shared-proxies is off for shared network.
615 * @private
617 updateProxyBannerVisibility_: function() {
618 var bannerDiv = $('network-proxy-info-banner');
619 if (!loadTimeData.data_) {
620 // TODO(pneubeck): This temporarily prevents an exception below until
621 // i18n of the proxy dialog on the login page is
622 // fixed. http://crbug.com/242865
623 bannerDiv.hidden = true;
624 return;
627 // Show banner and determine its message if necessary.
628 var controlledBy = $('direct-proxy').controlledBy;
629 if (!controlledBy || controlledBy == '') {
630 bannerDiv.hidden = true;
631 } else {
632 bannerDiv.hidden = false;
633 // The possible banner texts are loaded in proxy_handler.cc.
634 var bannerText = 'proxyBanner' + controlledBy.charAt(0).toUpperCase() +
635 controlledBy.slice(1);
636 $('banner-text').textContent = loadTimeData.getString(bannerText);
641 * Handler for when the user clicks on the checkbox to allow a
642 * single proxy usage.
643 * @private
645 toggleSingleProxy_: function() {
646 if ($('proxy-all-protocols').checked) {
647 $('multi-proxy').hidden = true;
648 $('single-proxy').hidden = false;
649 } else {
650 $('multi-proxy').hidden = false;
651 $('single-proxy').hidden = true;
656 * Handler for when the user clicks on the checkbox to enter
657 * auto configuration URL.
658 * @private
660 handleAutoConfigProxy_: function() {
661 $('proxy-pac-url').disabled = !$('proxy-use-pac-url').checked;
665 * Handler for selecting a radio button that will disable the manual
666 * controls.
667 * @private
669 disableManualProxy_: function() {
670 $('ignored-host-list').disabled = true;
671 $('new-host').disabled = true;
672 $('remove-host').disabled = true;
673 $('add-host').disabled = true;
674 $('proxy-all-protocols').disabled = true;
675 $('proxy-host-name').disabled = true;
676 $('proxy-host-port').disabled = true;
677 $('proxy-host-single-name').disabled = true;
678 $('proxy-host-single-port').disabled = true;
679 $('secure-proxy-host-name').disabled = true;
680 $('secure-proxy-port').disabled = true;
681 $('ftp-proxy').disabled = true;
682 $('ftp-proxy-port').disabled = true;
683 $('socks-host').disabled = true;
684 $('socks-port').disabled = true;
685 $('proxy-use-pac-url').disabled = $('auto-proxy').disabled ||
686 !$('auto-proxy').checked;
687 $('proxy-pac-url').disabled = $('proxy-use-pac-url').disabled ||
688 !$('proxy-use-pac-url').checked;
689 $('auto-proxy-parms').hidden = !$('auto-proxy').checked;
690 $('manual-proxy-parms').hidden = !$('manual-proxy').checked;
691 sendChromeMetricsAction('Options_NetworkManualProxy_Disable');
695 * Handler for selecting a radio button that will enable the manual
696 * controls.
697 * @private
699 enableManualProxy_: function() {
700 $('ignored-host-list').redraw();
701 var allDisabled = $('manual-proxy').disabled;
702 $('ignored-host-list').disabled = allDisabled;
703 $('new-host').disabled = allDisabled;
704 $('remove-host').disabled = allDisabled;
705 $('add-host').disabled = allDisabled;
706 $('proxy-all-protocols').disabled = allDisabled;
707 $('proxy-host-name').disabled = allDisabled;
708 $('proxy-host-port').disabled = allDisabled;
709 $('proxy-host-single-name').disabled = allDisabled;
710 $('proxy-host-single-port').disabled = allDisabled;
711 $('secure-proxy-host-name').disabled = allDisabled;
712 $('secure-proxy-port').disabled = allDisabled;
713 $('ftp-proxy').disabled = allDisabled;
714 $('ftp-proxy-port').disabled = allDisabled;
715 $('socks-host').disabled = allDisabled;
716 $('socks-port').disabled = allDisabled;
717 $('proxy-use-pac-url').disabled = true;
718 $('proxy-pac-url').disabled = true;
719 $('auto-proxy-parms').hidden = !$('auto-proxy').checked;
720 $('manual-proxy-parms').hidden = !$('manual-proxy').checked;
721 sendChromeMetricsAction('Options_NetworkManualProxy_Enable');
725 * Helper method called from initializeDetailsPage and updateConnectionData.
726 * Updates visibility/enabled of the login/disconnect/configure buttons.
727 * @private
729 updateConnectionButtonVisibilty_: function() {
730 var onc = this.onc_;
731 if (this.type_ == 'Ethernet') {
732 // Ethernet can never be connected or disconnected and can always be
733 // configured (e.g. to set security).
734 $('details-internet-login').hidden = true;
735 $('details-internet-disconnect').hidden = true;
736 $('details-internet-configure').hidden = false;
737 return;
740 var connectable = onc.getActiveValue('Connectable');
741 var connectState = onc.getActiveValue('ConnectionState');
742 if (connectState == 'NotConnected') {
743 $('details-internet-disconnect').hidden = true;
744 $('details-internet-login').hidden = false;
745 // Connecting to an unconfigured network might trigger certificate
746 // installation UI. Until that gets handled here, always enable the
747 // Connect button for built-in networks.
748 var enabled = (this.type_ != 'VPN') ||
749 (onc.getActiveValue('VPN.Type') != 'ThirdPartyVPN') ||
750 connectable;
751 $('details-internet-login').disabled = !enabled;
752 } else {
753 $('details-internet-login').hidden = true;
754 $('details-internet-disconnect').hidden = false;
757 var showConfigure = false;
758 if (this.type_ == 'VPN') {
759 showConfigure = true;
760 } else if (this.type_ == 'WiMAX' && connectState == 'NotConnected') {
761 showConfigure = true;
762 } else if (this.type_ == 'WiFi') {
763 showConfigure = (connectState == 'NotConnected' &&
764 (!connectable || onc.getWiFiSecurity() != 'None'));
766 $('details-internet-configure').hidden = !showConfigure;
770 * Helper method called from initializeDetailsPage and updateConnectionData.
771 * Updates the connection state property and account / sim card links.
772 * @private
774 updateDetails_: function() {
775 var onc = this.onc_;
777 var connectionStateString = onc.getTranslatedValue('ConnectionState');
778 $('connection-state').textContent = connectionStateString;
780 var type = this.type_;
781 var showViewAccount = false;
782 var showActivate = false;
783 if (type == 'WiFi') {
784 $('wifi-connection-state').textContent = connectionStateString;
785 } else if (type == 'WiMAX') {
786 $('wimax-connection-state').textContent = connectionStateString;
787 } else if (type == 'Cellular') {
788 $('activation-state').textContent =
789 onc.getTranslatedValue('Cellular.ActivationState');
790 if (onc.getActiveValue('Cellular.Family') == 'GSM') {
791 var lockEnabled =
792 onc.getActiveValue('Cellular.SIMLockStatus.LockEnabled');
793 $('sim-card-lock-enabled').checked = lockEnabled;
794 $('change-pin').hidden = !lockEnabled;
796 showViewAccount = shouldShowViewAccountButton(onc);
797 var activationState = onc.getActiveValue('Cellular.ActivationState');
798 showActivate = (activationState == 'NotActivated' ||
799 activationState == 'PartiallyActivated');
802 $('view-account-details').hidden = !showViewAccount;
803 $('activate-details').hidden = !showActivate;
804 // If activation is not complete, hide the login button.
805 if (showActivate)
806 $('details-internet-login').hidden = true;
810 * Helper method called from initializeDetailsPage and updateConnectionData.
811 * Updates the fields in the header section of the details frame.
812 * @private
814 populateHeader_: function() {
815 var onc = this.onc_;
817 $('network-details-title').textContent =
818 this.networkTitle_ || onc.getTranslatedValue('Name');
820 var connectionStateString = onc.getTranslatedValue('ConnectionState');
821 $('network-details-subtitle-status').textContent = connectionStateString;
823 var typeKey;
824 var type = this.type_;
825 if (type == 'Ethernet')
826 typeKey = 'ethernetTitle';
827 else if (type == 'WiFi')
828 typeKey = 'wifiTitle';
829 else if (type == 'WiMAX')
830 typeKey = 'wimaxTitle';
831 else if (type == 'Cellular')
832 typeKey = 'cellularTitle';
833 else if (type == 'VPN')
834 typeKey = 'vpnTitle';
835 else
836 typeKey = null;
837 var typeLabel = $('network-details-subtitle-type');
838 var typeSeparator = $('network-details-subtitle-separator');
839 if (typeKey) {
840 typeLabel.textContent = loadTimeData.getString(typeKey);
841 typeLabel.hidden = false;
842 typeSeparator.hidden = false;
843 } else {
844 typeLabel.hidden = true;
845 typeSeparator.hidden = true;
850 * Helper method to insert a 'user' option into the Apn list.
851 * @param {Object} userOption The 'user' apn dictionary
852 * @private
854 insertApnUserOption_: function(userOption) {
855 // Add the 'user' option before the last option ('other')
856 var apnSelector = $('select-apn');
857 assert(apnSelector.length > 0);
858 var otherOption = apnSelector[apnSelector.length - 1];
859 apnSelector.add(userOption, otherOption);
860 this.userApnIndex_ = apnSelector.length - 2;
861 this.selectedApnIndex_ = this.userApnIndex_;
865 * Helper method called from initializeApnList to populate the Apn list.
866 * @param {Array} apnList List of available APNs.
867 * @private
869 populateApnList_: function(apnList) {
870 var onc = this.onc_;
871 var apnSelector = $('select-apn');
872 assert(apnSelector.length == 1);
873 var otherOption = apnSelector[0];
874 var activeApn = onc.getActiveValue('Cellular.APN.AccessPointName');
875 var lastGoodApn =
876 onc.getActiveValue('Cellular.LastGoodAPN.AccessPointName');
877 for (var i = 0; i < apnList.length; i++) {
878 var apnDict = apnList[i];
879 var localizedName = apnDict['LocalizedName'];
880 var name = localizedName ? localizedName : apnDict['Name'];
881 var accessPointName = apnDict['AccessPointName'];
882 var option = document.createElement('option');
883 option.textContent =
884 name ? (name + ' (' + accessPointName + ')') : accessPointName;
885 option.value = i;
886 // Insert new option before 'other' option.
887 apnSelector.add(option, otherOption);
888 if (this.selectedApnIndex_ != -1)
889 continue;
890 // If this matches the active Apn name, or LastGoodApn name (or there
891 // is no last good APN), set it as the selected Apn.
892 if ((activeApn == accessPointName) ||
893 (!activeApn && (!lastGoodApn || lastGoodApn == accessPointName))) {
894 this.selectedApnIndex_ = i;
897 if (this.selectedApnIndex_ == -1 && activeApn) {
898 this.userApn_ = activeApn;
899 // Create a 'user' entry for any active apn not in the list.
900 var userOption = document.createElement('option');
901 userOption.textContent = activeApn;
902 userOption.value = -1;
903 this.insertApnUserOption_(userOption);
908 * Helper method called from initializeDetailsPage to initialize the Apn
909 * list.
910 * @private
912 initializeApnList_: function() {
913 this.selectedApnIndex_ = -1;
914 this.userApnIndex_ = -1;
916 var onc = this.onc_;
917 var apnSelector = $('select-apn');
919 // Clear APN lists, keep only last element, 'other'.
920 while (apnSelector.length != 1)
921 apnSelector.remove(0);
923 var apnList = onc.getActiveValue('Cellular.APNList');
924 if (apnList) {
925 // Populate the list with the existing APNs.
926 this.populateApnList_(apnList);
927 } else {
928 // Create a single 'default' entry.
929 var otherOption = apnSelector[0];
930 var defaultOption = document.createElement('option');
931 defaultOption.textContent =
932 loadTimeData.getString('cellularApnUseDefault');
933 defaultOption.value = -1;
934 // Add 'default' entry before 'other' option
935 apnSelector.add(defaultOption, otherOption);
936 assert(apnSelector.length == 2); // 'default', 'other'
937 this.selectedApnIndex_ = 0; // Select 'default'
939 assert(this.selectedApnIndex_ >= 0);
940 apnSelector.selectedIndex = this.selectedApnIndex_;
941 updateHidden('.apn-list-view', false);
942 updateHidden('.apn-details-view', true);
946 * Helper function for setting APN properties.
947 * @param {Object} apnValue Dictionary of APN properties.
948 * @private
950 setActiveApn_: function(apnValue) {
951 var activeApn = {};
952 var apnName = apnValue['AccessPointName'];
953 if (apnName) {
954 activeApn['AccessPointName'] = apnName;
955 activeApn['Username'] = stringFromValue(apnValue['Username']);
956 activeApn['Password'] = stringFromValue(apnValue['Password']);
958 // Set the cached ONC data.
959 this.onc_.setProperty('Cellular.APN', activeApn);
960 // Set an ONC object with just the APN values.
961 var oncData = new OncData({});
962 oncData.setProperty('Cellular.APN', activeApn);
963 chrome.networkingPrivate.setProperties(this.onc_.guid(),
964 oncData.getData());
968 * Event Listener for the cellular-apn-use-default button.
969 * @private
971 setDefaultApn_: function() {
972 var apnSelector = $('select-apn');
974 // Remove the 'user' entry if it exists.
975 if (this.userApnIndex_ != -1) {
976 assert(this.userApnIndex_ < apnSelector.length - 1);
977 apnSelector.remove(this.userApnIndex_);
978 this.userApnIndex_ = -1;
981 var apnList = this.onc_.getActiveValue('Cellular.APNList');
982 var iApn = (apnList != undefined && apnList.length > 0) ? 0 : -1;
983 apnSelector.selectedIndex = iApn;
984 this.selectedApnIndex_ = iApn;
986 // Clear any user APN entry to inform Chrome to use the default APN.
987 this.setActiveApn_({});
989 updateHidden('.apn-list-view', false);
990 updateHidden('.apn-details-view', true);
994 * Event Listener for the cellular-apn-set button.
995 * @private
997 setApn_: function(apnValue) {
998 if (apnValue == '')
999 return;
1001 var apnSelector = $('select-apn');
1003 var activeApn = {};
1004 activeApn['AccessPointName'] = stringFromValue(apnValue);
1005 activeApn['Username'] = stringFromValue($('cellular-apn-username').value);
1006 activeApn['Password'] = stringFromValue($('cellular-apn-password').value);
1007 this.setActiveApn_(activeApn);
1008 // Set the user selected APN.
1009 this.userApn_ = activeApn;
1011 // Remove any existing 'user' entry.
1012 if (this.userApnIndex_ != -1) {
1013 assert(this.userApnIndex_ < apnSelector.length - 1);
1014 apnSelector.remove(this.userApnIndex_);
1015 this.userApnIndex_ = -1;
1018 // Create a new 'user' entry with the new active apn.
1019 var option = document.createElement('option');
1020 option.textContent = activeApn['AccessPointName'];
1021 option.value = -1;
1022 option.selected = true;
1023 this.insertApnUserOption_(option);
1025 updateHidden('.apn-list-view', false);
1026 updateHidden('.apn-details-view', true);
1030 * Event Listener for the cellular-apn-cancel button.
1031 * @private
1033 cancelApn_: function() { this.initializeApnList_(); },
1036 * Event Listener for the select-apn button.
1037 * @private
1039 selectApn_: function() {
1040 var onc = this.onc_;
1041 var apnSelector = $('select-apn');
1042 if (apnSelector[apnSelector.selectedIndex].value != -1) {
1043 var apnList = onc.getActiveValue('Cellular.APNList');
1044 var apnIndex = apnSelector.selectedIndex;
1045 assert(apnIndex < apnList.length);
1046 this.selectedApnIndex_ = apnIndex;
1047 this.setActiveApn_(apnList[apnIndex]);
1048 } else if (apnSelector.selectedIndex == this.userApnIndex_) {
1049 this.selectedApnIndex_ = apnSelector.selectedIndex;
1050 this.setActiveApn_(this.userApn_);
1051 } else { // 'Other'
1052 var apnDict;
1053 if (this.userApn_['AccessPointName']) {
1054 // Fill in the details fields with the existing 'user' config.
1055 apnDict = this.userApn_;
1056 } else {
1057 // No 'user' config, use the current values.
1058 apnDict = {};
1059 apnDict['AccessPointName'] =
1060 onc.getActiveValue('Cellular.APN.AccessPointName');
1061 apnDict['Username'] = onc.getActiveValue('Cellular.APN.Username');
1062 apnDict['Password'] = onc.getActiveValue('Cellular.APN.Password');
1064 $('cellular-apn').value = stringFromValue(apnDict['AccessPointName']);
1065 $('cellular-apn-username').value = stringFromValue(apnDict['Username']);
1066 $('cellular-apn-password').value = stringFromValue(apnDict['Password']);
1067 updateHidden('.apn-list-view', true);
1068 updateHidden('.apn-details-view', false);
1074 * Enables or Disables all buttons that provide operations on the cellular
1075 * network.
1077 DetailsInternetPage.changeCellularButtonsState = function(disable) {
1078 var buttonsToDisableList =
1079 new Array('details-internet-login',
1080 'details-internet-disconnect',
1081 'details-internet-configure',
1082 'activate-details',
1083 'view-account-details');
1085 for (var i = 0; i < buttonsToDisableList.length; ++i) {
1086 var button = $(buttonsToDisableList[i]);
1087 button.disabled = disable;
1092 * Shows a spinner while the carrier is changed.
1094 DetailsInternetPage.showCarrierChangeSpinner = function(visible) {
1095 if (!DetailsInternetPage.getInstance().visible)
1096 return;
1097 $('switch-carrier-spinner').hidden = !visible;
1098 // Disable any buttons that allow us to operate on cellular networks.
1099 DetailsInternetPage.changeCellularButtonsState(visible);
1103 * Changes the network carrier.
1105 DetailsInternetPage.handleCarrierChanged = function() {
1106 var carrierSelector = $('select-carrier');
1107 var carrier = carrierSelector[carrierSelector.selectedIndex].textContent;
1108 DetailsInternetPage.showCarrierChangeSpinner(true);
1109 var guid = DetailsInternetPage.getInstance().onc_.guid();
1110 var oncData = new OncData({});
1111 oncData.setProperty('Cellular.Carrier', carrier);
1112 chrome.networkingPrivate.setProperties(guid, oncData.getData(), function() {
1113 // Start activation or show the activation UI after changing carriers.
1114 DetailsInternetPage.activateCellular(guid);
1119 * If the network is not already activated, starts the activation process or
1120 * shows the activation UI. Otherwise does nothing.
1122 DetailsInternetPage.activateCellular = function(guid) {
1123 chrome.networkingPrivate.getProperties(guid, function(properties) {
1124 var oncData = new OncData(properties);
1125 if (oncData.getActiveValue('Cellular.ActivationState') == 'Activated') {
1126 DetailsInternetPage.showCarrierChangeSpinner(false);
1127 return;
1129 var carrier = oncData.getActiveValue('Cellular.Carrier');
1130 if (carrier == CarrierSprint) {
1131 // Sprint is directly ativated, call startActivate().
1132 chrome.networkingPrivate.startActivate(guid, '', function() {
1133 DetailsInternetPage.showCarrierChangeSpinner(false);
1135 } else {
1136 DetailsInternetPage.showCarrierChangeSpinner(false);
1137 chrome.send('showMorePlanInfo', [guid]);
1143 * Performs minimal initialization of the InternetDetails dialog in
1144 * preparation for showing proxy-settings.
1146 DetailsInternetPage.initializeProxySettings = function() {
1147 DetailsInternetPage.getInstance().initializePageContents_();
1151 * Displays the InternetDetails dialog with only the proxy settings visible.
1153 DetailsInternetPage.showProxySettings = function() {
1154 var detailsPage = DetailsInternetPage.getInstance();
1155 $('network-details-header').hidden = true;
1156 $('activate-details').hidden = true;
1157 $('view-account-details').hidden = true;
1158 $('web-proxy-auto-discovery').hidden = true;
1159 detailsPage.showProxy_ = true;
1160 updateHidden('#internet-tab', true);
1161 updateHidden('#details-tab-strip', true);
1162 updateHidden('#details-internet-page .action-area', true);
1163 detailsPage.updateControls();
1164 detailsPage.visible = true;
1165 sendChromeMetricsAction('Options_NetworkShowProxyTab');
1169 * Initializes even handling for keyboard driven flow.
1171 DetailsInternetPage.initializeKeyboardFlow = function() {
1172 keyboard.initializeKeyboardFlow();
1175 DetailsInternetPage.updateProxySettings = function(type) {
1176 var proxyHost = null,
1177 proxyPort = null;
1179 if (type == 'cros.session.proxy.singlehttp') {
1180 proxyHost = 'proxy-host-single-name';
1181 proxyPort = 'proxy-host-single-port';
1182 } else if (type == 'cros.session.proxy.httpurl') {
1183 proxyHost = 'proxy-host-name';
1184 proxyPort = 'proxy-host-port';
1185 } else if (type == 'cros.session.proxy.httpsurl') {
1186 proxyHost = 'secure-proxy-host-name';
1187 proxyPort = 'secure-proxy-port';
1188 } else if (type == 'cros.session.proxy.ftpurl') {
1189 proxyHost = 'ftp-proxy';
1190 proxyPort = 'ftp-proxy-port';
1191 } else if (type == 'cros.session.proxy.socks') {
1192 proxyHost = 'socks-host';
1193 proxyPort = 'socks-port';
1194 } else {
1195 return;
1198 var hostValue = $(proxyHost).value;
1199 if (hostValue.indexOf(':') !== -1) {
1200 if (hostValue.match(/:/g).length == 1) {
1201 hostValue = hostValue.split(':');
1202 $(proxyHost).value = hostValue[0];
1203 $(proxyPort).value = hostValue[1];
1208 DetailsInternetPage.loginFromDetails = function() {
1209 DetailsInternetPage.configureOrConnect();
1210 PageManager.closeOverlay();
1214 * This function identifies unconfigured networks and networks that are
1215 * likely to fail (e.g. due to a bad passphrase on a previous connect
1216 * attempt). For such networks a configure dialog will be opened. Otherwise
1217 * a connection will be attempted.
1219 DetailsInternetPage.configureOrConnect = function() {
1220 var detailsPage = DetailsInternetPage.getInstance();
1221 if (detailsPage.type_ == 'WiFi')
1222 sendChromeMetricsAction('Options_NetworkConnectToWifi');
1223 else if (detailsPage.type_ == 'VPN')
1224 sendChromeMetricsAction('Options_NetworkConnectToVPN');
1226 var onc = detailsPage.onc_;
1227 var guid = onc.guid();
1228 var type = onc.getActiveValue('Type');
1230 // Built-in VPNs do not correctly set 'Connectable', so we always show the
1231 // configuration UI.
1232 if (type == 'VPN') {
1233 if (onc.getActiveValue('VPN.Type') != 'ThirdPartyVPN') {
1234 chrome.send('configureNetwork', [guid]);
1235 return;
1239 // If 'Connectable' is false for WiFi or WiMAX, Shill requires
1240 // additional configuration to connect, so show the configuration UI.
1241 if ((type == 'WiFi' || type == 'WiMAX') &&
1242 !onc.getActiveValue('Connectable')) {
1243 chrome.send('configureNetwork', [guid]);
1244 return;
1247 // Secure WiFi networks with ErrorState set most likely require
1248 // configuration (e.g. a correct passphrase) before connecting.
1249 if (type == 'WiFi' && onc.getWiFiSecurity() != 'None') {
1250 var errorState = onc.getActiveValue('ErrorState');
1251 if (errorState && errorState != 'Unknown') {
1252 chrome.send('configureNetwork', [guid]);
1253 return;
1257 // Cellular networks need to be activated before they can be connected to.
1258 if (type == 'Cellular') {
1259 var activationState = onc.getActiveValue('Cellular.ActivationState');
1260 if (activationState != 'Activated' && activationState != 'Unknown') {
1261 DetailsInternetPage.activateCellular(guid);
1262 return;
1266 chrome.networkingPrivate.startConnect(guid);
1269 DetailsInternetPage.disconnectNetwork = function() {
1270 var detailsPage = DetailsInternetPage.getInstance();
1271 if (detailsPage.type_ == 'WiFi')
1272 sendChromeMetricsAction('Options_NetworkDisconnectWifi');
1273 else if (detailsPage.type_ == 'VPN')
1274 sendChromeMetricsAction('Options_NetworkDisconnectVPN');
1275 chrome.networkingPrivate.startDisconnect(detailsPage.onc_.guid());
1276 PageManager.closeOverlay();
1279 DetailsInternetPage.configureNetwork = function() {
1280 var detailsPage = DetailsInternetPage.getInstance();
1281 // This is an explicit request to show the configure dialog; do not show
1282 // the enrollment dialog for networks missing a certificate.
1283 var forceShow = true;
1284 chrome.send('configureNetwork', [detailsPage.onc_.guid(), forceShow]);
1285 PageManager.closeOverlay();
1288 DetailsInternetPage.activateFromDetails = function() {
1289 var detailsPage = DetailsInternetPage.getInstance();
1290 if (detailsPage.type_ == 'Cellular')
1291 DetailsInternetPage.activateCellular(detailsPage.onc_.guid());
1292 PageManager.closeOverlay();
1296 * Event handler called when the details page is closed. Sends changed
1297 * properties to Chrome and closes the overlay.
1299 DetailsInternetPage.setDetails = function() {
1300 var detailsPage = DetailsInternetPage.getInstance();
1301 var type = detailsPage.type_;
1302 var oncData = new OncData({});
1303 var autoConnectCheckboxId = '';
1304 if (type == 'WiFi') {
1305 var preferredCheckbox =
1306 assertInstanceof($('prefer-network-wifi'), HTMLInputElement);
1307 if (!preferredCheckbox.hidden && !preferredCheckbox.disabled) {
1308 var kPreferredPriority = 1;
1309 var priority = preferredCheckbox.checked ? kPreferredPriority : 0;
1310 oncData.setProperty('Priority', priority);
1311 sendChromeMetricsAction('Options_NetworkSetPrefer');
1313 autoConnectCheckboxId = 'auto-connect-network-wifi';
1314 } else if (type == 'WiMAX') {
1315 autoConnectCheckboxId = 'auto-connect-network-wimax';
1316 } else if (type == 'Cellular') {
1317 autoConnectCheckboxId = 'auto-connect-network-cellular';
1318 } else if (type == 'VPN') {
1319 var providerType = detailsPage.onc_.getActiveValue('VPN.Type');
1320 if (providerType != 'ThirdPartyVPN') {
1321 oncData.setProperty('VPN.Type', providerType);
1322 oncData.setProperty('VPN.Host', $('inet-server-hostname').value);
1323 autoConnectCheckboxId = 'auto-connect-network-vpn';
1326 if (autoConnectCheckboxId != '') {
1327 var autoConnectCheckbox =
1328 assertInstanceof($(autoConnectCheckboxId), HTMLInputElement);
1329 if (!autoConnectCheckbox.hidden && !autoConnectCheckbox.disabled) {
1330 var autoConnectKey = type + '.AutoConnect';
1331 oncData.setProperty(autoConnectKey, !!autoConnectCheckbox.checked);
1332 sendChromeMetricsAction('Options_NetworkAutoConnect');
1336 var nameServerTypes = ['automatic', 'google', 'user'];
1337 var nameServerType = 'automatic';
1338 for (var i = 0; i < nameServerTypes.length; ++i) {
1339 if ($(nameServerTypes[i] + '-dns-radio').checked) {
1340 nameServerType = nameServerTypes[i];
1341 break;
1344 var ipConfig = detailsPage.getIpConfig_(nameServerType);
1345 var ipAddressType = ('IPAddress' in ipConfig) ? 'Static' : 'DHCP';
1346 var nameServersType = ('NameServers' in ipConfig) ? 'Static' : 'DHCP';
1347 oncData.setProperty('IPAddressConfigType', ipAddressType);
1348 oncData.setProperty('NameServersConfigType', nameServersType);
1349 oncData.setProperty('StaticIPConfig', ipConfig);
1351 var data = oncData.getData();
1352 if (Object.keys(data).length > 0) {
1353 // TODO(stevenjb): Only set changed properties.
1354 chrome.networkingPrivate.setProperties(detailsPage.onc_.guid(), data);
1357 PageManager.closeOverlay();
1361 * Event handler called when the name server type changes.
1362 * @param {string} type The selected name sever type, 'automatic', 'google',
1363 * or 'user'.
1365 DetailsInternetPage.updateNameServerDisplay = function(type) {
1366 var editable = type == 'user';
1367 var fields = [$('ipconfig-dns1'), $('ipconfig-dns2'),
1368 $('ipconfig-dns3'), $('ipconfig-dns4')];
1369 for (var i = 0; i < fields.length; ++i) {
1370 fields[i].editable = editable;
1372 if (editable)
1373 $('ipconfig-dns1').focus();
1375 var automaticDns = $('automatic-dns-display');
1376 var googleDns = $('google-dns-display');
1377 var userDns = $('user-dns-settings');
1378 switch (type) {
1379 case 'automatic':
1380 automaticDns.setAttribute('selected', '');
1381 googleDns.removeAttribute('selected');
1382 userDns.removeAttribute('selected');
1383 break;
1384 case 'google':
1385 automaticDns.removeAttribute('selected');
1386 googleDns.setAttribute('selected', '');
1387 userDns.removeAttribute('selected');
1388 break;
1389 case 'user':
1390 automaticDns.removeAttribute('selected');
1391 googleDns.removeAttribute('selected');
1392 userDns.setAttribute('selected', '');
1393 break;
1398 * Method called from Chrome when the ONC properties for the displayed
1399 * network may have changed.
1400 * @param {Object} oncData The updated ONC dictionary for the network.
1402 DetailsInternetPage.updateConnectionData = function(oncData) {
1403 var detailsPage = DetailsInternetPage.getInstance();
1404 if (!detailsPage.visible)
1405 return;
1407 if (oncData.GUID != detailsPage.onc_.guid())
1408 return;
1410 // Update our cached data object.
1411 detailsPage.onc_ = new OncData(oncData);
1413 detailsPage.populateHeader_();
1414 detailsPage.updateConnectionButtonVisibilty_();
1415 detailsPage.updateDetails_();
1419 * Initializes the details page with the provided ONC data.
1420 * @param {Object} oncData Dictionary of ONC properties.
1422 DetailsInternetPage.initializeDetailsPage = function(oncData) {
1423 var onc = new OncData(oncData);
1425 var detailsPage = DetailsInternetPage.getInstance();
1426 detailsPage.onc_ = onc;
1427 var type = onc.getActiveValue('Type');
1428 detailsPage.type_ = type;
1430 sendShowDetailsMetrics(type, onc.getActiveValue('ConnectionState'));
1432 if (type == 'VPN') {
1433 // Cache the dialog title, which will contain the provider name in the
1434 // case of a third-party VPN provider. This caching is important as the
1435 // provider may go away while the details dialog is being shown, causing
1436 // subsequent updates to be unable to determine the correct title.
1437 detailsPage.networkTitle_ = options.VPNProviders.formatNetworkName(onc);
1438 } else {
1439 delete detailsPage.networkTitle_;
1442 detailsPage.populateHeader_();
1443 detailsPage.updateConnectionButtonVisibilty_();
1444 detailsPage.updateDetails_();
1446 // TODO(stevenjb): Some of the setup below should be moved to
1447 // updateDetails_() so that updates are reflected in the UI.
1449 // Only show proxy for remembered networks.
1450 var remembered = onc.getSource() != 'None';
1451 if (remembered) {
1452 detailsPage.showProxy_ = true;
1453 // Inform Chrome which network to use for proxy configuration.
1454 chrome.send('selectNetwork', [detailsPage.onc_.guid()]);
1455 } else {
1456 detailsPage.showProxy_ = false;
1459 $('web-proxy-auto-discovery').hidden = true;
1461 var restricted = onc.getActiveValue('RestrictedConnectivity');
1462 var restrictedString = loadTimeData.getString(
1463 restricted ? 'restrictedYes' : 'restrictedNo');
1465 // These objects contain an 'automatic' property that is displayed when
1466 // ip-automatic-configuration-checkbox is checked, and a 'value' property
1467 // that is displayed when unchecked and used to set the associated ONC
1468 // property for StaticIPConfig on commit.
1469 var inetAddress = {};
1470 var inetNetmask = {};
1471 var inetGateway = {};
1473 var inetNameServersString;
1475 var ipconfigList = onc.getActiveValue('IPConfigs');
1476 if (Array.isArray(ipconfigList)) {
1477 for (var i = 0; i < ipconfigList.length; ++i) {
1478 var ipconfig = ipconfigList[i];
1479 var ipType = ipconfig['Type'];
1480 if (ipType != 'IPv4') {
1481 // TODO(stevenjb): Handle IPv6 properties.
1482 continue;
1484 var address = ipconfig['IPAddress'];
1485 inetAddress.automatic = address;
1486 inetAddress.value = address;
1487 var netmask = prefixLengthToNetmask(ipconfig['RoutingPrefix']);
1488 inetNetmask.automatic = netmask;
1489 inetNetmask.value = netmask;
1490 var gateway = ipconfig['Gateway'];
1491 inetGateway.automatic = gateway;
1492 inetGateway.value = gateway;
1493 if ('WebProxyAutoDiscoveryUrl' in ipconfig) {
1494 $('web-proxy-auto-discovery').hidden = false;
1495 $('web-proxy-auto-discovery-url').value =
1496 ipconfig['WebProxyAutoDiscoveryUrl'];
1498 if ('NameServers' in ipconfig) {
1499 var inetNameServers = ipconfig['NameServers'];
1500 inetNameServers = inetNameServers.sort();
1501 inetNameServersString = inetNameServers.join(',');
1503 break; // Use the first IPv4 entry.
1507 // Override the 'automatic' properties with the saved DHCP values if the
1508 // saved value is set, and set any unset 'value' properties.
1509 var savedNameServersString;
1510 var savedIpAddress = onc.getActiveValue('SavedIPConfig.IPAddress');
1511 if (savedIpAddress != undefined) {
1512 inetAddress.automatic = savedIpAddress;
1513 if (!inetAddress.value)
1514 inetAddress.value = savedIpAddress;
1516 var savedPrefix = onc.getActiveValue('SavedIPConfig.RoutingPrefix');
1517 if (savedPrefix != undefined) {
1518 assert(typeof savedPrefix == 'number');
1519 var savedNetmask = prefixLengthToNetmask(
1520 /** @type {number} */(savedPrefix));
1521 inetNetmask.automatic = savedNetmask;
1522 if (!inetNetmask.value)
1523 inetNetmask.value = savedNetmask;
1525 var savedGateway = onc.getActiveValue('SavedIPConfig.Gateway');
1526 if (savedGateway != undefined) {
1527 inetGateway.automatic = savedGateway;
1528 if (!inetGateway.value)
1529 inetGateway.value = savedGateway;
1532 var savedNameServers = onc.getActiveValue('SavedIPConfig.NameServers');
1533 if (savedNameServers) {
1534 savedNameServers = savedNameServers.sort();
1535 savedNameServersString = savedNameServers.join(',');
1538 var ipAutoConfig = 'automatic';
1539 if (onc.getActiveValue('IPAddressConfigType') == 'Static') {
1540 ipAutoConfig = 'user';
1541 var staticIpAddress = onc.getActiveValue('StaticIPConfig.IPAddress');
1542 inetAddress.user = staticIpAddress;
1543 inetAddress.value = staticIpAddress;
1545 var staticPrefix = onc.getActiveValue('StaticIPConfig.RoutingPrefix');
1546 if (typeof staticPrefix != 'number')
1547 staticPrefix = 0;
1548 var staticNetmask = prefixLengthToNetmask(
1549 /** @type {number} */ (staticPrefix));
1550 inetNetmask.user = staticNetmask;
1551 inetNetmask.value = staticNetmask;
1553 var staticGateway = onc.getActiveValue('StaticIPConfig.Gateway');
1554 inetGateway.user = staticGateway;
1555 inetGateway.value = staticGateway;
1558 var staticNameServersString;
1559 if (onc.getActiveValue('NameServersConfigType') == 'Static') {
1560 var staticNameServers = onc.getActiveValue('StaticIPConfig.NameServers');
1561 staticNameServers = staticNameServers.sort();
1562 staticNameServersString = staticNameServers.join(',');
1565 $('ip-automatic-configuration-checkbox').checked =
1566 ipAutoConfig == 'automatic';
1568 inetAddress.autoConfig = ipAutoConfig;
1569 inetNetmask.autoConfig = ipAutoConfig;
1570 inetGateway.autoConfig = ipAutoConfig;
1572 var configureAddressField = function(field, model) {
1573 IPAddressField.decorate(field);
1574 field.model = model;
1575 field.editable = model.autoConfig == 'user';
1577 configureAddressField($('ip-address'), inetAddress);
1578 configureAddressField($('ip-netmask'), inetNetmask);
1579 configureAddressField($('ip-gateway'), inetGateway);
1581 // Set Nameserver fields. Nameservers are 'automatic' by default. If a
1582 // static namerserver is set, use that unless it does not match a non
1583 // empty 'NameServers' value (indicating that the custom nameservers are
1584 // invalid or not being applied for some reason). TODO(stevenjb): Only
1585 // set these properites if they change so that invalid custom values do
1586 // not get lost.
1587 var nameServerType = 'automatic';
1588 if (staticNameServersString &&
1589 (!inetNameServersString ||
1590 staticNameServersString == inetNameServersString)) {
1591 if (staticNameServersString == GoogleNameServers.join(','))
1592 nameServerType = 'google';
1593 else
1594 nameServerType = 'user';
1596 if (nameServerType == 'automatic')
1597 $('automatic-dns-display').textContent = inetNameServersString;
1598 else
1599 $('automatic-dns-display').textContent = savedNameServersString;
1600 $('google-dns-display').textContent = GoogleNameServers.join(',');
1602 var nameServersUser = [];
1603 if (staticNameServers) {
1604 nameServersUser = staticNameServers;
1605 } else if (savedNameServers) {
1606 // Pre-populate with values provided by DHCP server.
1607 nameServersUser = savedNameServers;
1610 var nameServerModels = [];
1611 for (var i = 0; i < 4; ++i)
1612 nameServerModels.push({value: nameServersUser[i] || ''});
1614 $(nameServerType + '-dns-radio').checked = true;
1615 configureAddressField($('ipconfig-dns1'), nameServerModels[0]);
1616 configureAddressField($('ipconfig-dns2'), nameServerModels[1]);
1617 configureAddressField($('ipconfig-dns3'), nameServerModels[2]);
1618 configureAddressField($('ipconfig-dns4'), nameServerModels[3]);
1620 DetailsInternetPage.updateNameServerDisplay(nameServerType);
1622 var macAddress = onc.getActiveValue('MacAddress');
1623 if (macAddress) {
1624 $('hardware-address').textContent = macAddress;
1625 $('hardware-address-row').style.display = 'table-row';
1626 } else {
1627 // This is most likely a device without a hardware address.
1628 $('hardware-address-row').style.display = 'none';
1631 var setOrHideParent = function(field, property) {
1632 if (property != undefined) {
1633 $(field).textContent = property;
1634 $(field).parentElement.hidden = false;
1635 } else {
1636 $(field).parentElement.hidden = true;
1640 var networkName = onc.getTranslatedValue('Name');
1642 // Signal strength as percentage (for WiFi and WiMAX).
1643 var signalStrength;
1644 if (type == 'WiFi' || type == 'WiMAX')
1645 signalStrength = onc.getActiveValue(type + '.SignalStrength');
1646 if (!signalStrength)
1647 signalStrength = 0;
1648 var strengthFormat = loadTimeData.getString('inetSignalStrengthFormat');
1649 var strengthString = strengthFormat.replace('$1', signalStrength);
1651 if (type == 'WiFi') {
1652 OptionsPage.showTab($('wifi-network-nav-tab'));
1653 $('wifi-restricted-connectivity').textContent = restrictedString;
1654 var ssid = onc.getActiveValue('WiFi.SSID');
1655 $('wifi-ssid').textContent = ssid ? ssid : networkName;
1656 setOrHideParent('wifi-bssid', onc.getActiveValue('WiFi.BSSID'));
1657 var security = onc.getWiFiSecurity();
1658 if (security == 'None')
1659 security = undefined;
1660 setOrHideParent('wifi-security', security);
1661 // Frequency is in MHz.
1662 var frequency = onc.getActiveValue('WiFi.Frequency');
1663 if (!frequency)
1664 frequency = 0;
1665 var frequencyFormat = loadTimeData.getString('inetFrequencyFormat');
1666 frequencyFormat = frequencyFormat.replace('$1', frequency);
1667 $('wifi-frequency').textContent = frequencyFormat;
1668 $('wifi-signal-strength').textContent = strengthString;
1669 setOrHideParent('wifi-hardware-address',
1670 onc.getActiveValue('MacAddress'));
1671 var priority = onc.getActiveValue('Priority');
1672 $('prefer-network-wifi').checked = priority > 0;
1673 $('prefer-network-wifi').disabled = !remembered;
1674 $('auto-connect-network-wifi').checked =
1675 onc.getActiveValue('WiFi.AutoConnect');
1676 $('auto-connect-network-wifi').disabled = !remembered;
1677 } else if (type == 'WiMAX') {
1678 OptionsPage.showTab($('wimax-network-nav-tab'));
1679 $('wimax-restricted-connectivity').textContent = restrictedString;
1681 $('auto-connect-network-wimax').checked =
1682 onc.getActiveValue('WiMAX.AutoConnect');
1683 $('auto-connect-network-wimax').disabled = !remembered;
1684 var identity = onc.getActiveValue('WiMAX.EAP.Identity');
1685 setOrHideParent('wimax-eap-identity', identity);
1686 $('wimax-signal-strength').textContent = strengthString;
1687 } else if (type == 'Cellular') {
1688 OptionsPage.showTab($('cellular-conn-nav-tab'));
1690 var isGsm = onc.getActiveValue('Cellular.Family') == 'GSM';
1692 var currentCarrierIndex = -1;
1693 if (loadTimeData.getValue('showCarrierSelect')) {
1694 var currentCarrier =
1695 isGsm ? CarrierGenericUMTS : onc.getActiveValue('Cellular.Carrier');
1696 var supportedCarriers =
1697 onc.getActiveValue('Cellular.SupportedCarriers');
1698 for (var c1 = 0; c1 < supportedCarriers.length; ++c1) {
1699 if (supportedCarriers[c1] == currentCarrier) {
1700 currentCarrierIndex = c1;
1701 break;
1704 if (currentCarrierIndex != -1) {
1705 var carrierSelector = $('select-carrier');
1706 carrierSelector.onchange = DetailsInternetPage.handleCarrierChanged;
1707 carrierSelector.options.length = 0;
1708 for (var c2 = 0; c2 < supportedCarriers.length; ++c2) {
1709 var option = document.createElement('option');
1710 option.textContent = supportedCarriers[c2];
1711 carrierSelector.add(option);
1713 carrierSelector.selectedIndex = currentCarrierIndex;
1716 if (currentCarrierIndex == -1)
1717 $('service-name').textContent = networkName;
1719 // TODO(stevenjb): Ideally many of these should be localized.
1720 $('network-technology').textContent =
1721 onc.getActiveValue('Cellular.NetworkTechnology');
1722 $('roaming-state').textContent =
1723 onc.getTranslatedValue('Cellular.RoamingState');
1724 $('cellular-restricted-connectivity').textContent = restrictedString;
1725 $('error-state').textContent = onc.getActiveValue('ErrorState');
1726 $('manufacturer').textContent =
1727 onc.getActiveValue('Cellular.Manufacturer');
1728 $('model-id').textContent = onc.getActiveValue('Cellular.ModelID');
1729 $('firmware-revision').textContent =
1730 onc.getActiveValue('Cellular.FirmwareRevision');
1731 $('hardware-revision').textContent =
1732 onc.getActiveValue('Cellular.HardwareRevision');
1733 $('mdn').textContent = onc.getActiveValue('Cellular.MDN');
1735 // Show ServingOperator properties only if available.
1736 var servingOperatorName =
1737 onc.getActiveValue('Cellular.ServingOperator.Name');
1738 var servingOperatorCode =
1739 onc.getActiveValue('Cellular.ServingOperator.Code');
1740 if (servingOperatorName != undefined &&
1741 servingOperatorCode != undefined) {
1742 $('operator-name').textContent = servingOperatorName;
1743 $('operator-code').textContent = servingOperatorCode;
1744 } else {
1745 $('operator-name').parentElement.hidden = true;
1746 $('operator-code').parentElement.hidden = true;
1748 // Make sure that GSM/CDMA specific properties that shouldn't be hidden
1749 // are visible.
1750 updateHidden('#details-internet-page .gsm-only', false);
1751 updateHidden('#details-internet-page .cdma-only', false);
1753 // Show IMEI/ESN/MEID/MIN/PRL only if they are available.
1754 setOrHideParent('esn', onc.getActiveValue('Cellular.ESN'));
1755 setOrHideParent('imei', onc.getActiveValue('Cellular.IMEI'));
1756 setOrHideParent('meid', onc.getActiveValue('Cellular.MEID'));
1757 setOrHideParent('min', onc.getActiveValue('Cellular.MIN'));
1758 setOrHideParent('prl-version', onc.getActiveValue('Cellular.PRLVersion'));
1760 if (isGsm) {
1761 $('iccid').textContent = onc.getActiveValue('Cellular.ICCID');
1762 $('imsi').textContent = onc.getActiveValue('Cellular.IMSI');
1763 detailsPage.initializeApnList_();
1765 $('auto-connect-network-cellular').checked =
1766 onc.getActiveValue('Cellular.AutoConnect');
1767 $('auto-connect-network-cellular').disabled = false;
1768 } else if (type == 'VPN') {
1769 OptionsPage.showTab($('vpn-nav-tab'));
1770 var providerType = onc.getActiveValue('VPN.Type');
1771 var isThirdPartyVPN = providerType == 'ThirdPartyVPN';
1772 $('vpn-tab').classList.toggle('third-party-vpn-provider',
1773 isThirdPartyVPN);
1775 $('inet-service-name').textContent = networkName;
1776 $('inet-provider-type').textContent =
1777 onc.getTranslatedValue('VPN.Type');
1779 if (isThirdPartyVPN) {
1780 $('inet-provider-name').textContent = '';
1781 var extensionID = onc.getActiveValue('VPN.ThirdPartyVPN.ExtensionID');
1782 var providers = options.VPNProviders.getProviders();
1783 for (var i = 0; i < providers.length; ++i) {
1784 if (extensionID == providers[i].extensionID) {
1785 $('inet-provider-name').textContent = providers[i].name;
1786 break;
1789 } else {
1790 var usernameKey;
1791 if (providerType == 'OpenVPN')
1792 usernameKey = 'VPN.OpenVPN.Username';
1793 else if (providerType == 'L2TP-IPsec')
1794 usernameKey = 'VPN.L2TP.Username';
1796 if (usernameKey) {
1797 $('inet-username').parentElement.hidden = false;
1798 $('inet-username').textContent = onc.getActiveValue(usernameKey);
1799 } else {
1800 $('inet-username').parentElement.hidden = true;
1802 var inetServerHostname = $('inet-server-hostname');
1803 inetServerHostname.value = onc.getActiveValue('VPN.Host');
1804 inetServerHostname.resetHandler = function() {
1805 PageManager.hideBubble();
1806 var recommended = onc.getRecommendedValue('VPN.Host');
1807 if (recommended != undefined)
1808 inetServerHostname.value = recommended;
1810 $('auto-connect-network-vpn').checked =
1811 onc.getActiveValue('VPN.AutoConnect');
1812 $('auto-connect-network-vpn').disabled = false;
1814 } else {
1815 OptionsPage.showTab($('internet-nav-tab'));
1818 // Update controlled option indicators.
1819 var indicators = cr.doc.querySelectorAll(
1820 '#details-internet-page .controlled-setting-indicator');
1821 for (var i = 0; i < indicators.length; i++) {
1822 var managed = indicators[i].hasAttribute('managed');
1823 // TODO(stevenjb): Eliminate support for 'data' once 39 is stable.
1824 var attributeName = managed ? 'managed' : 'data';
1825 var propName = indicators[i].getAttribute(attributeName);
1826 if (!propName)
1827 continue;
1828 var propValue = managed ?
1829 onc.getManagedProperty(propName) :
1830 onc.getActiveValue(propName);
1831 // If the property is unset or unmanaged (i.e. not an Object) skip it.
1832 if (propValue == undefined || (typeof propValue != 'object'))
1833 continue;
1834 var event;
1835 if (managed)
1836 event = detailsPage.createManagedEvent_(propName, propValue);
1837 else
1838 event = detailsPage.createControlledEvent_(propName,
1839 /** @type {{value: *, controlledBy: *, recommendedValue: *}} */(
1840 propValue));
1841 indicators[i].handlePrefChange(event);
1842 var forElement = $(indicators[i].getAttribute('internet-detail-for'));
1843 if (forElement) {
1844 if (event.value.controlledBy == 'policy')
1845 forElement.disabled = true;
1846 if (forElement.resetHandler)
1847 indicators[i].resetHandler = forElement.resetHandler;
1851 detailsPage.updateControls();
1853 // Don't show page name in address bar and in history to prevent people
1854 // navigate here by hand and solve issue with page session restore.
1855 PageManager.showPageByName('detailsInternetPage', false);
1858 return {
1859 DetailsInternetPage: DetailsInternetPage