// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. cr.define('options', function() { var OptionsPage = options.OptionsPage; var ArrayDataModel = cr.ui.ArrayDataModel; var RepeatingButton = cr.ui.RepeatingButton; // // BrowserOptions class // Encapsulated handling of browser options page. // function BrowserOptions() { OptionsPage.call(this, 'settings', templateData.settingsTitle, 'settings'); } cr.addSingletonGetter(BrowserOptions); BrowserOptions.prototype = { __proto__: options.OptionsPage.prototype, // State variables. syncSetupCompleted: false, showHomeButton_: false, homePageIsNtp_: false, /** * An autocomplete list that can be attached to the home page URL text field * during editing. * @type {HTMLElement} * @private */ autocompleteList_: null, /** * The cached value of the instant.confirm_dialog_shown preference. * @type {bool} * @private */ instantConfirmDialogShown_: false, /** * @inheritDoc */ initializePage: function() { OptionsPage.prototype.initializePage.call(this); var self = this; window.addEventListener('message', this.handleWindowMessage_.bind(this)); $('advanced-settings-expander').onclick = this.toggleAdvancedSettings_.bind(this); // Sync (Sign in) section. this.updateSyncState_(templateData.syncData); $('sync-action-link').onclick = function(event) { SyncSetupOverlay.showErrorUI(); }; $('start-stop-sync').onclick = function(event) { if (self.syncSetupCompleted) SyncSetupOverlay.showStopSyncingUI(); else SyncSetupOverlay.showSetupUI(); }; $('customize-sync').onclick = function(event) { SyncSetupOverlay.showSetupUI(); }; // Internet connection section (ChromeOS only). if (cr.isChromeOS) { $('internet-options-button').onclick = function(event) { OptionsPage.navigateToPage('internet'); chrome.send('coreOptionsUserMetricsAction', ['Options_InternetOptions']); }; } // On Startup section. var startupSetPagesLink = $('startup-set-pages'); const showPagesValue = Number($('startup-show-pages').value); Preferences.getInstance().addEventListener('session.restore_on_startup', function(event) { startupSetPagesLink.disabled = event.value['disabled'] && event.value['value'] != showPagesValue; }); startupSetPagesLink.onclick = function() { OptionsPage.navigateToPage('startup'); }; this.sessionRestoreEnabled_ = templateData.enable_restore_session_state; if (this.sessionRestoreEnabled_) { $('old-startup-last-text').hidden = true; $('new-startup-last-text').hidden = false; } // Appearance section. $('home-page-select').addEventListener( 'change', this.onHomePageSelectChange_.bind(this)); ['browser.show_home_button', 'homepage', 'homepage_is_newtabpage'].forEach(function(pref) { Preferences.getInstance().addEventListener( pref, self.onHomePagePrefChanged_.bind(self)); }); $('themes-gallery').onclick = function(event) { window.open(localStrings.getString('themesGalleryURL')); }; $('themes-reset').onclick = function(event) { chrome.send('themesReset'); }; // Device section (ChromeOS only). if (cr.isChromeOS) { $('keyboard-settings-button').onclick = function(evt) { OptionsPage.navigateToPage('keyboard-overlay'); }; $('pointer-settings-button').onclick = function(evt) { OptionsPage.navigateToPage('pointer-overlay'); }; this.initBrightnessButton_('brightness-decrease-button', 'decreaseScreenBrightness'); this.initBrightnessButton_('brightness-increase-button', 'increaseScreenBrightness'); } // Search section. $('manage-default-search-engines').onclick = function(event) { OptionsPage.navigateToPage('searchEngines'); chrome.send('coreOptionsUserMetricsAction', ['Options_ManageSearchEngines']); }; $('default-search-engine').addEventListener('change', this.setDefaultSearchEngine_); $('instant-enabled-control').customChangeHandler = function(event) { if (this.checked) { if (self.instantConfirmDialogShown_) chrome.send('enableInstant'); else OptionsPage.navigateToPage('instantConfirm'); } else { chrome.send('disableInstant'); } return true; }; $('instant-field-trial-control').onchange = function(evt) { this.checked = true; chrome.send('disableInstant'); }; Preferences.getInstance().addEventListener('instant.confirm_dialog_shown', this.onInstantConfirmDialogShownChanged_.bind(this)); Preferences.getInstance().addEventListener('instant.enabled', this.onInstantEnabledChanged_.bind(this)); Preferences.getInstance().addEventListener( 'session.restore_on_startup', this.onSessionRestoreSelectedChanged_.bind(this)); Preferences.getInstance().addEventListener( 'restore_session_state.dialog_shown', this.onSessionRestoreDialogShownChanged_.bind(this)); // Text fields may change widths when the window changes size, so make // sure the suggestion list stays in sync. window.addEventListener('resize', function() { self.autocompleteList_.syncWidthToInput(); }); var suggestionList = new cr.ui.AutocompleteList(); suggestionList.autoExpands = true; suggestionList.suggestionUpdateRequestCallback = this.requestAutocompleteSuggestions_.bind(this); $('main-content').appendChild(suggestionList); this.autocompleteList_ = suggestionList; // Users section. var profilesList = $('profiles-list'); options.browser_options.ProfileList.decorate(profilesList); profilesList.autoExpands = true; profilesList.addEventListener('change', this.setProfileViewButtonsStatus_); $('profiles-create').onclick = function(event) { chrome.send('createProfile'); }; $('profiles-manage').onclick = function(event) { var selectedProfile = self.getSelectedProfileItem_(); if (selectedProfile) ManageProfileOverlay.showManageDialog(selectedProfile); }; $('profiles-delete').onclick = function(event) { var selectedProfile = self.getSelectedProfileItem_(); if (selectedProfile) ManageProfileOverlay.showDeleteDialog(selectedProfile); }; if (cr.isChromeOS) { // Username (canonical email) of the currently logged in user or // |kGuestUser| if a guest session is active. this.username_ = localStrings.getString('username'); this.updateAccountPicture_(); if (cr.commandLine && cr.commandLine.options['--bwsi']) { // Disable the screen lock checkbox in guest mode. $('enable-screen-lock').disabled = true; // Hide the startup section in Guest mode. $('startup-section').hidden = true; } else { $('account-picture-wrapper').onclick = function(event) { OptionsPage.navigateToPage('changePicture'); }; } $('manage-accounts-button').onclick = function(event) { OptionsPage.navigateToPage('accounts'); chrome.send('coreOptionsUserMetricsAction', ['Options_ManageAccounts']); }; } else { $('import-data').onclick = function(event) { // Make sure that any previous import success message is hidden, and // we're showing the UI to import further data. $('import-data-configure').hidden = false; $('import-data-success').hidden = true; OptionsPage.navigateToPage('importData'); chrome.send('coreOptionsUserMetricsAction', ['Import_ShowDlg']); }; if ($('themes-GTK-button')) { $('themes-GTK-button').onclick = function(event) { chrome.send('themesSetGTK'); }; } } // Default browser section. if (!cr.isChromeOS) { $('set-as-default-browser').onclick = function(event) { chrome.send('becomeDefaultBrowser'); }; $('auto-launch').onclick = this.handleAutoLaunchChanged_; } // Date and time section (CrOS only). if (cr.isChromeOS && AccountsOptions.loggedInAsGuest()) { // Disable time-related settings if we're not logged in as a real user. $('timezone-select').disabled = true; $('use-24hour-clock').disabled = true; } // Privacy section. $('privacyContentSettingsButton').onclick = function(event) { OptionsPage.navigateToPage('content'); OptionsPage.showTab($('cookies-nav-tab')); chrome.send('coreOptionsUserMetricsAction', ['Options_ContentSettings']); }; $('privacyClearDataButton').onclick = function(event) { OptionsPage.navigateToPage('clearBrowserData'); chrome.send('coreOptionsUserMetricsAction', ['Options_ClearData']); }; // 'metricsReportingEnabled' element is only present on Chrome branded // builds. if ($('metricsReportingEnabled')) { $('metricsReportingEnabled').onclick = function(event) { chrome.send('metricsReportingCheckboxAction', [String(event.target.checked)]); }; } // Bluetooth (CrOS only). if (cr.isChromeOS) { options.system.bluetooth.BluetoothDeviceList.decorate( $('bluetooth-paired-devices-list')); $('bluetooth-add-device').onclick = this.handleAddBluetoothDevice_.bind(this); $('enable-bluetooth').onchange = function(event) { var state = $('enable-bluetooth').checked; chrome.send('bluetoothEnableChange', [Boolean(state)]); }; $('bluetooth-reconnect-device').onclick = function(event) { var device = $('bluetooth-paired-devices-list').selectedItem; var address = device.address; chrome.send('updateBluetoothDevice', [address, 'connect']); OptionsPage.closeOverlay(); }; $('bluetooth-reconnect-device').onmousedown = function(event) { // Prevent 'blur' event, which would reset the list selection, // thereby disabling the apply button. event.preventDefault(); }; $('bluetooth-paired-devices-list').addEventListener('change', function() { var item = $('bluetooth-paired-devices-list').selectedItem; var disabled = !item || !item.paired || item.connected; $('bluetooth-reconnect-device').disabled = disabled; }); } // Passwords and Forms section. $('autofill-settings').onclick = function(event) { OptionsPage.navigateToPage('autofill'); chrome.send('coreOptionsUserMetricsAction', ['Options_ShowAutofillSettings']); }; $('manage-passwords').onclick = function(event) { OptionsPage.navigateToPage('passwords'); OptionsPage.showTab($('passwords-nav-tab')); chrome.send('coreOptionsUserMetricsAction', ['Options_ShowPasswordManager']); }; if (this.guestModeActive_()) { // Disable and turn off Autofill in guest mode. var autofillEnabled = $('autofill-enabled'); autofillEnabled.disabled = true; autofillEnabled.checked = false; cr.dispatchSimpleEvent(autofillEnabled, 'change'); $('autofill-settings').disabled = true; // Disable and turn off Password Manager in guest mode. var passwordManagerEnabled = $('password-manager-enabled'); passwordManagerEnabled.disabled = true; passwordManagerEnabled.checked = false; cr.dispatchSimpleEvent(passwordManagerEnabled, 'change'); $('manage-passwords').disabled = true; // Hide the entire section on ChromeOS if (cr.isChromeOS) $('passwords-and-autofill-section').hidden = true; } $('mac-passwords-warning').hidden = !(localStrings.getString('macPasswordsWarning')); // Network section. if (!cr.isChromeOS) { $('proxiesConfigureButton').onclick = function(event) { chrome.send('showNetworkProxySettings'); }; } // Web Content section. $('fontSettingsCustomizeFontsButton').onclick = function(event) { OptionsPage.navigateToPage('fonts'); chrome.send('coreOptionsUserMetricsAction', ['Options_FontSettings']); }; $('defaultFontSize').onchange = function(event) { var value = event.target.options[event.target.selectedIndex].value; Preferences.setIntegerPref( 'webkit.webprefs.global.default_fixed_font_size', value - OptionsPage.SIZE_DIFFERENCE_FIXED_STANDARD, ''); chrome.send('defaultFontSizeAction', [String(value)]); }; $('defaultZoomFactor').onchange = function(event) { chrome.send('defaultZoomFactorAction', [String(event.target.options[event.target.selectedIndex].value)]); }; // Languages section. $('language-button').onclick = function(event) { OptionsPage.navigateToPage('languages'); chrome.send('coreOptionsUserMetricsAction', ['Options_LanuageAndSpellCheckSettings']); }; // Downloads section. if (!cr.isChromeOS) { $('downloadLocationChangeButton').onclick = function(event) { chrome.send('selectDownloadLocation'); }; // This text field is always disabled. Setting ".disabled = true" isn't // enough, since a policy can disable it but shouldn't re-enable when // it is removed. $('downloadLocationPath').setDisabled('readonly', true); $('autoOpenFileTypesResetToDefault').onclick = function(event) { chrome.send('autoOpenFileTypesAction'); }; } // HTTPS/SSL section. if (cr.isWindows || cr.isMac) { $('certificatesManageButton').onclick = function(event) { chrome.send('showManageSSLCertificates'); }; } else { $('certificatesManageButton').onclick = function(event) { OptionsPage.navigateToPage('certificates'); chrome.send('coreOptionsUserMetricsAction', ['Options_ManageSSLCertificates']); }; } $('sslCheckRevocation').onclick = function(event) { chrome.send('checkRevocationCheckboxAction', [String($('sslCheckRevocation').checked)]); }; // Cloud Print section. // 'cloudPrintProxyEnabled' is true for Chrome branded builds on // certain platforms, or could be enabled by a lab. if (!cr.isChromeOS) { $('cloudPrintConnectorSetupButton').onclick = function(event) { if ($('cloudPrintManageButton').style.display == 'none') { // Disable the button, set it's text to the intermediate state. $('cloudPrintConnectorSetupButton').textContent = localStrings.getString('cloudPrintConnectorEnablingButton'); $('cloudPrintConnectorSetupButton').disabled = true; chrome.send('showCloudPrintSetupDialog'); } else { chrome.send('disableCloudPrintConnector'); } }; } $('cloudPrintManageButton').onclick = function(event) { chrome.send('showCloudPrintManagePage'); }; // Accessibility section (CrOS only). if (cr.isChromeOS) { $('accessibility-spoken-feedback-check').onchange = function(event) { chrome.send('spokenFeedbackChange', [$('accessibility-spoken-feedback-check').checked]); }; } // Background mode section. if ($('backgroundModeCheckbox')) { $('backgroundModeCheckbox').onclick = function(event) { chrome.send('backgroundModeAction', [String($('backgroundModeCheckbox').checked)]); }; } }, /** * @inheritDoc */ didShowPage: function() { $('search-field').focus(); }, /** * Handler for messages sent from the main uber page. * @param {Event} e The 'message' event from the uber page. * @private */ handleWindowMessage_: function(e) { if (e.data.method == 'frameSelected') $('search-field').focus(); }, /** * Toggle the visibility state of the Advanced section. * @private */ toggleAdvancedSettings_: function() { if ($('advanced-settings').style.height == '') this.showAdvancedSettings_(); else this.hideAdvancedSettings_(); }, /** * Show advanced settings. * @private */ showAdvancedSettings_: function() { $('advanced-settings').style.height = $('advanced-settings-container').offsetHeight + 20 + 'px'; $('advanced-settings-expander').textContent = localStrings.getString('hideAdvancedSettings'); }, /** * Hide advanced settings. * @private */ hideAdvancedSettings_: function() { $('advanced-settings').style.height = ''; $('advanced-settings-expander').textContent = localStrings.getString('showAdvancedSettings'); }, /** * Initializes a button for controlling screen brightness. * @param {string} id Button ID. * @param {string} callback Name of the callback function. */ initBrightnessButton_: function(id, callback) { var button = $(id); cr.ui.decorate(button, RepeatingButton); button.repeatInterval = 300; button.addEventListener(RepeatingButton.Event.BUTTON_HELD, function(e) { chrome.send(callback); }); }, /** * Updates the sync section with the given state. * @param {Object} syncData A bunch of data records that describe the status * of the sync system. * @private */ updateSyncState_: function(syncData) { if (!syncData.syncSystemEnabled) { $('sync-section').hidden = true; return; } $('sync-section').hidden = false; this.syncSetupCompleted = syncData.setupCompleted; $('customize-sync').hidden = !syncData.setupCompleted; var startStopButton = $('start-stop-sync'); startStopButton.disabled = syncData.managed || syncData.setupInProgress; startStopButton.hidden = syncData.setupCompleted && cr.isChromeOs; startStopButton.textContent = syncData.setupCompleted ? localStrings.getString('syncButtonTextStop') : syncData.setupInProgress ? localStrings.getString('syncButtonTextInProgress') : localStrings.getString('syncButtonTextStart'); // TODO(estade): can this just be textContent? $('sync-status-text').innerHTML = syncData.statusText; var statusSet = syncData.statusText.length != 0; $('sync-overview').hidden = statusSet; $('sync-status').hidden = !statusSet; $('sync-action-link').textContent = syncData.actionLinkText; $('sync-action-link').hidden = syncData.actionLinkText.length == 0; $('sync-action-link').disabled = syncData.managed; if (syncData.syncHasError) $('sync-status').classList.add('sync-error'); else $('sync-status').classList.remove('sync-error'); $('customize-sync').disabled = syncData.hasUnrecoverableError; $('enable-auto-login-checkbox').hidden = !syncData.autoLoginVisible; }, /** * Display or hide the profiles section of the page. This is used for * multi-profile settings. * @param {boolean} visible True to show the section. * @private */ setProfilesSectionVisible_: function(visible) { $('profiles-section').hidden = !visible; }, /** * Get the start/stop sync button DOM element. Used for testing. * @return {DOMElement} The start/stop sync button. * @private */ getStartStopSyncButton_: function() { return $('start-stop-sync'); }, /** * Returns the