Home | History | Annotate | Download | only in options
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 cr.define('options', function() {
      6   const OptionsPage = options.OptionsPage;
      7   const ArrayDataModel = cr.ui.ArrayDataModel;
      8 
      9   //
     10   // BrowserOptions class
     11   // Encapsulated handling of browser options page.
     12   //
     13   function BrowserOptions() {
     14     OptionsPage.call(this, 'browser',
     15                      templateData.browserPageTabTitle,
     16                      'browserPage');
     17   }
     18 
     19   cr.addSingletonGetter(BrowserOptions);
     20 
     21   BrowserOptions.prototype = {
     22     // Inherit BrowserOptions from OptionsPage.
     23     __proto__: options.OptionsPage.prototype,
     24 
     25     startup_pages_pref_: {
     26       'name': 'session.urls_to_restore_on_startup',
     27       'managed': false
     28     },
     29 
     30     homepage_pref_: {
     31       'name': 'homepage',
     32       'value': '',
     33       'managed': false
     34     },
     35 
     36     homepage_is_newtabpage_pref_: {
     37       'name': 'homepage_is_newtabpage',
     38       'value': true,
     39       'managed': false
     40     },
     41 
     42     /**
     43      * At autocomplete list that can be attached to a text field during editing.
     44      * @type {HTMLElement}
     45      * @private
     46      */
     47     autocompleteList_: null,
     48 
     49     // The cached value of the instant.confirm_dialog_shown preference.
     50     instantConfirmDialogShown_: false,
     51 
     52     /**
     53      * Initialize BrowserOptions page.
     54      */
     55     initializePage: function() {
     56       // Call base class implementation to start preference initialization.
     57       OptionsPage.prototype.initializePage.call(this);
     58 
     59       // Wire up controls.
     60       $('startupUseCurrentButton').onclick = function(event) {
     61         chrome.send('setStartupPagesToCurrentPages');
     62       };
     63       $('toolbarShowBookmarksBar').onchange = function() {
     64         chrome.send('toggleShowBookmarksBar');
     65       };
     66       $('defaultSearchManageEnginesButton').onclick = function(event) {
     67         OptionsPage.navigateToPage('searchEngines');
     68         chrome.send('coreOptionsUserMetricsAction',
     69             ['Options_ManageSearchEngines']);
     70       };
     71       $('defaultSearchEngine').onchange = this.setDefaultSearchEngine_;
     72 
     73       var self = this;
     74       $('instantEnableCheckbox').onclick = function(event) {
     75         if (this.checked && !self.instantConfirmDialogShown_) {
     76           // Leave disabled for now. The PrefCheckbox handler already set it to
     77           // true so undo that.
     78           Preferences.setBooleanPref(this.pref, false, this.metric);
     79           OptionsPage.navigateToPage('instantConfirm');
     80         }
     81       };
     82 
     83       Preferences.getInstance().addEventListener('instant.confirm_dialog_shown',
     84           this.onInstantConfirmDialogShownChanged_.bind(this));
     85 
     86       var homepageField = $('homepageURL');
     87       $('homepageUseNTPButton').onchange =
     88           this.handleHomepageUseNTPButtonChange_.bind(this);
     89       $('homepageUseURLButton').onchange =
     90           this.handleHomepageUseURLButtonChange_.bind(this);
     91       var homepageChangeHandler = this.handleHomepageURLChange_.bind(this);
     92       homepageField.addEventListener('change', homepageChangeHandler);
     93       homepageField.addEventListener('input', homepageChangeHandler);
     94       homepageField.addEventListener('focus', function(event) {
     95         self.autocompleteList_.attachToInput(homepageField);
     96       });
     97       homepageField.addEventListener('blur', function(event) {
     98         self.autocompleteList_.detach();
     99       });
    100       homepageField.addEventListener('keydown', function(event) {
    101         // Remove focus when the user hits enter since people expect feedback
    102         // indicating that they are done editing.
    103         if (event.keyIdentifier == 'Enter')
    104           homepageField.blur();
    105       });
    106 
    107       // Ensure that changes are committed when closing the page.
    108       window.addEventListener('unload', function() {
    109         if (document.activeElement == homepageField)
    110           homepageField.blur();
    111       });
    112 
    113       if (!cr.isChromeOS) {
    114         $('defaultBrowserUseAsDefaultButton').onclick = function(event) {
    115           chrome.send('becomeDefaultBrowser');
    116         };
    117       }
    118 
    119       var startupPagesList = $('startupPagesList');
    120       options.browser_options.StartupPageList.decorate(startupPagesList);
    121       startupPagesList.autoExpands = true;
    122 
    123       // Check if we are in the guest mode.
    124       if (cr.commandLine.options['--bwsi']) {
    125         // Hide the startup section.
    126         $('startupSection').classList.add('hidden');
    127       } else {
    128         // Initialize control enabled states.
    129         Preferences.getInstance().addEventListener('session.restore_on_startup',
    130             this.updateCustomStartupPageControlStates_.bind(this));
    131         Preferences.getInstance().addEventListener(
    132             this.startup_pages_pref_.name,
    133             this.handleStartupPageListChange_.bind(this));
    134         Preferences.getInstance().addEventListener(
    135             this.homepage_pref_.name,
    136             this.handleHomepageChange_.bind(this));
    137         Preferences.getInstance().addEventListener(
    138             this.homepage_is_newtabpage_pref_.name,
    139             this.handleHomepageIsNewTabPageChange_.bind(this));
    140 
    141         this.updateCustomStartupPageControlStates_();
    142       }
    143 
    144       var suggestionList = new options.AutocompleteList();
    145       suggestionList.autoExpands = true;
    146       suggestionList.suggestionUpdateRequestCallback =
    147           this.requestAutocompleteSuggestions_.bind(this);
    148       $('main-content').appendChild(suggestionList);
    149       this.autocompleteList_ = suggestionList;
    150       startupPagesList.autocompleteList = suggestionList;
    151     },
    152 
    153     /**
    154      * Called when the value of the instant.confirm_dialog_shown preference
    155      * changes. Cache this value.
    156      * @param {Event} event Change event.
    157      * @private
    158      */
    159     onInstantConfirmDialogShownChanged_: function(event) {
    160       this.instantConfirmDialogShown_ = event.value['value'];
    161     },
    162 
    163     /**
    164      * Update the Default Browsers section based on the current state.
    165      * @param {string} statusString Description of the current default state.
    166      * @param {boolean} isDefault Whether or not the browser is currently
    167      *     default.
    168      * @param {boolean} canBeDefault Whether or not the browser can be default.
    169      * @private
    170      */
    171     updateDefaultBrowserState_: function(statusString, isDefault,
    172                                          canBeDefault) {
    173       var label = $('defaultBrowserState');
    174       label.textContent = statusString;
    175 
    176       $('defaultBrowserUseAsDefaultButton').disabled = !canBeDefault ||
    177                                                        isDefault;
    178     },
    179 
    180     /**
    181      * Clears the search engine popup.
    182      * @private
    183      */
    184     clearSearchEngines_: function() {
    185       $('defaultSearchEngine').textContent = '';
    186     },
    187 
    188     /**
    189      * Updates the search engine popup with the given entries.
    190      * @param {Array} engines List of available search engines.
    191      * @param {number} defaultValue The value of the current default engine.
    192      */
    193     updateSearchEngines_: function(engines, defaultValue) {
    194       this.clearSearchEngines_();
    195       engineSelect = $('defaultSearchEngine');
    196       engineCount = engines.length;
    197       var defaultIndex = -1;
    198       for (var i = 0; i < engineCount; i++) {
    199         var engine = engines[i];
    200         var option = new Option(engine['name'], engine['index']);
    201         if (defaultValue == option.value)
    202           defaultIndex = i;
    203         engineSelect.appendChild(option);
    204       }
    205       if (defaultIndex >= 0)
    206         engineSelect.selectedIndex = defaultIndex;
    207     },
    208 
    209     /**
    210      * Returns true if the custom startup page control block should
    211      * be enabled.
    212      * @returns {boolean} Whether the startup page controls should be
    213      *     enabled.
    214      */
    215     shouldEnableCustomStartupPageControls: function(pages) {
    216       return $('startupShowPagesButton').checked &&
    217           !this.startup_pages_pref_.managed;
    218     },
    219 
    220     /**
    221      * Updates the startup pages list with the given entries.
    222      * @param {Array} pages List of startup pages.
    223      * @private
    224      */
    225     updateStartupPages_: function(pages) {
    226       var model = new ArrayDataModel(pages);
    227       // Add a "new page" row.
    228       model.push({
    229         'modelIndex': '-1'
    230       });
    231       $('startupPagesList').dataModel = model;
    232     },
    233 
    234     /**
    235      * Handles change events of the radio button 'homepageUseURLButton'.
    236      * @param {event} change event.
    237      * @private
    238      */
    239     handleHomepageUseURLButtonChange_: function(event) {
    240       Preferences.setBooleanPref(this.homepage_is_newtabpage_pref_.name, false);
    241     },
    242 
    243     /**
    244      * Handles change events of the radio button 'homepageUseNTPButton'.
    245      * @param {event} change event.
    246      * @private
    247      */
    248     handleHomepageUseNTPButtonChange_: function(event) {
    249       Preferences.setBooleanPref(this.homepage_is_newtabpage_pref_.name, true);
    250     },
    251 
    252     /**
    253      * Handles input and change events of the text field 'homepageURL'.
    254      * @param {event} input/change event.
    255      * @private
    256      */
    257     handleHomepageURLChange_: function(event) {
    258       var homepageField = $('homepageURL');
    259       var doFixup = event.type == 'change' ? '1' : '0';
    260       chrome.send('setHomePage', [homepageField.value, doFixup]);
    261     },
    262 
    263     /**
    264      * Handle change events of the preference 'homepage'.
    265      * @param {event} preference changed event.
    266      * @private
    267      */
    268     handleHomepageChange_: function(event) {
    269       this.homepage_pref_.value = event.value['value'];
    270       this.homepage_pref_.managed = event.value['managed'];
    271       if (this.isHomepageURLNewTabPageURL_() && !this.homepage_pref_.managed &&
    272           !this.homepage_is_newtabpage_pref_.managed) {
    273         var useNewTabPage = this.isHomepageIsNewTabPageChoiceSelected_();
    274         Preferences.setStringPref(this.homepage_pref_.name, '')
    275         Preferences.setBooleanPref(this.homepage_is_newtabpage_pref_.name,
    276                                    useNewTabPage)
    277       }
    278       this.updateHomepageControlStates_();
    279     },
    280 
    281     /**
    282      * Handle change events of the preference homepage_is_newtabpage.
    283      * @param {event} preference changed event.
    284      * @private
    285      */
    286     handleHomepageIsNewTabPageChange_: function(event) {
    287       this.homepage_is_newtabpage_pref_.value = event.value['value'];
    288       this.homepage_is_newtabpage_pref_.managed = event.value['managed'];
    289       this.updateHomepageControlStates_();
    290     },
    291 
    292     /**
    293      * Update homepage preference UI controls.  Here's a table describing the
    294      * desired characteristics of the homepage choice radio value, its enabled
    295      * state and the URL field enabled state. They depend on the values of the
    296      * managed bits for homepage (m_hp) and homepageIsNewTabPage (m_ntp)
    297      * preferences, as well as the value of the homepageIsNewTabPage preference
    298      * (ntp) and whether the homepage preference is equal to the new tab page
    299      * URL (hpisntp).
    300      *
    301      * m_hp m_ntp ntp hpisntp| choice value| choice enabled| URL field enabled
    302      * ------------------------------------------------------------------------
    303      * 0    0     0   0      | homepage    | 1             | 1
    304      * 0    0     0   1      | new tab page| 1             | 0
    305      * 0    0     1   0      | new tab page| 1             | 0
    306      * 0    0     1   1      | new tab page| 1             | 0
    307      * 0    1     0   0      | homepage    | 0             | 1
    308      * 0    1     0   1      | homepage    | 0             | 1
    309      * 0    1     1   0      | new tab page| 0             | 0
    310      * 0    1     1   1      | new tab page| 0             | 0
    311      * 1    0     0   0      | homepage    | 1             | 0
    312      * 1    0     0   1      | new tab page| 0             | 0
    313      * 1    0     1   0      | new tab page| 1             | 0
    314      * 1    0     1   1      | new tab page| 0             | 0
    315      * 1    1     0   0      | homepage    | 0             | 0
    316      * 1    1     0   1      | new tab page| 0             | 0
    317      * 1    1     1   0      | new tab page| 0             | 0
    318      * 1    1     1   1      | new tab page| 0             | 0
    319      *
    320      * thus, we have:
    321      *
    322      *    choice value is new tab page === ntp || (hpisntp && (m_hp || !m_ntp))
    323      *    choice enabled === !m_ntp && !(m_hp && hpisntp)
    324      *    URL field enabled === !ntp && !mhp && !(hpisntp && !m_ntp)
    325      *
    326      * which also make sense if you think about them.
    327      * @private
    328      */
    329     updateHomepageControlStates_: function() {
    330       var homepageField = $('homepageURL');
    331       homepageField.disabled = !this.isHomepageURLFieldEnabled_();
    332       if (homepageField.value != this.homepage_pref_.value)
    333         homepageField.value = this.homepage_pref_.value;
    334       homepageField.style.backgroundImage = url('chrome://favicon/' +
    335                                                 this.homepage_pref_.value);
    336       var disableChoice = !this.isHomepageChoiceEnabled_();
    337       $('homepageUseURLButton').disabled = disableChoice;
    338       $('homepageUseNTPButton').disabled = disableChoice;
    339       var useNewTabPage = this.isHomepageIsNewTabPageChoiceSelected_();
    340       $('homepageUseNTPButton').checked = useNewTabPage;
    341       $('homepageUseURLButton').checked = !useNewTabPage;
    342     },
    343 
    344     /**
    345      * Tests whether the value of the 'homepage' preference equls the new tab
    346      * page url (chrome://newtab).
    347      * @returns {boolean} True if the 'homepage' value equals the new tab page
    348      *     url.
    349      * @private
    350      */
    351     isHomepageURLNewTabPageURL_ : function() {
    352       return (this.homepage_pref_.value.toLowerCase() == 'chrome://newtab');
    353     },
    354 
    355     /**
    356      * Tests whether the Homepage choice "Use New Tab Page" is selected.
    357      * @returns {boolean} True if "Use New Tab Page" is selected.
    358      * @private
    359      */
    360     isHomepageIsNewTabPageChoiceSelected_: function() {
    361       return (this.homepage_is_newtabpage_pref_.value ||
    362               (this.isHomepageURLNewTabPageURL_() &&
    363                (this.homepage_pref_.managed ||
    364                 !this.homepage_is_newtabpage_pref_.managed)));
    365     },
    366 
    367     /**
    368      * Tests whether the home page choice controls are enabled.
    369      * @returns {boolean} True if the home page choice controls are enabled.
    370      * @private
    371      */
    372     isHomepageChoiceEnabled_: function() {
    373       return (!this.homepage_is_newtabpage_pref_.managed &&
    374               !(this.homepage_pref_.managed &&
    375                 this.isHomepageURLNewTabPageURL_()));
    376     },
    377 
    378     /**
    379      * Checks whether the home page field should be enabled.
    380      * @returns {boolean} True if the home page field should be enabled.
    381      * @private
    382      */
    383     isHomepageURLFieldEnabled_: function() {
    384       return (!this.homepage_is_newtabpage_pref_.value &&
    385               !this.homepage_pref_.managed &&
    386               !(this.isHomepageURLNewTabPageURL_() &&
    387                 !this.homepage_is_newtabpage_pref_.managed));
    388     },
    389 
    390     /**
    391      * Sets the enabled state of the custom startup page list controls
    392      * based on the current startup radio button selection.
    393      * @private
    394      */
    395     updateCustomStartupPageControlStates_: function() {
    396       var disable = !this.shouldEnableCustomStartupPageControls();
    397       $('startupPagesList').disabled = disable;
    398       $('startupUseCurrentButton').disabled = disable;
    399     },
    400 
    401     /**
    402      * Handle change events of the preference
    403      * 'session.urls_to_restore_on_startup'.
    404      * @param {event} preference changed event.
    405      * @private
    406      */
    407     handleStartupPageListChange_: function(event) {
    408       this.startup_pages_pref_.managed = event.value['managed'];
    409       this.updateCustomStartupPageControlStates_();
    410     },
    411 
    412     /**
    413      * Set the default search engine based on the popup selection.
    414      */
    415     setDefaultSearchEngine_: function() {
    416       var engineSelect = $('defaultSearchEngine');
    417       var selectedIndex = engineSelect.selectedIndex;
    418       if (selectedIndex >= 0) {
    419         var selection = engineSelect.options[selectedIndex];
    420         chrome.send('setDefaultSearchEngine', [String(selection.value)]);
    421       }
    422     },
    423 
    424     /**
    425      * Sends an asynchronous request for new autocompletion suggestions for the
    426      * the given query. When new suggestions are available, the C++ handler will
    427      * call updateAutocompleteSuggestions_.
    428      * @param {string} query List of autocomplete suggestions.
    429      * @private
    430      */
    431     requestAutocompleteSuggestions_: function(query) {
    432       chrome.send('requestAutocompleteSuggestions', [query]);
    433     },
    434 
    435     /**
    436      * Updates the autocomplete suggestion list with the given entries.
    437      * @param {Array} pages List of autocomplete suggestions.
    438      * @private
    439      */
    440     updateAutocompleteSuggestions_: function(suggestions) {
    441       var list = this.autocompleteList_;
    442       // If the trigger for this update was a value being selected from the
    443       // current list, do nothing.
    444       if (list.targetInput && list.selectedItem &&
    445           list.selectedItem['url'] == list.targetInput.value)
    446         return;
    447       list.suggestions = suggestions;
    448     },
    449   };
    450 
    451   BrowserOptions.updateDefaultBrowserState = function(statusString, isDefault,
    452                                                       canBeDefault) {
    453     if (!cr.isChromeOS) {
    454       BrowserOptions.getInstance().updateDefaultBrowserState_(statusString,
    455                                                               isDefault,
    456                                                               canBeDefault);
    457     }
    458   };
    459 
    460   BrowserOptions.updateSearchEngines = function(engines, defaultValue) {
    461     BrowserOptions.getInstance().updateSearchEngines_(engines, defaultValue);
    462   };
    463 
    464   BrowserOptions.updateStartupPages = function(pages) {
    465     BrowserOptions.getInstance().updateStartupPages_(pages);
    466   };
    467 
    468   BrowserOptions.updateAutocompleteSuggestions = function(suggestions) {
    469     BrowserOptions.getInstance().updateAutocompleteSuggestions_(suggestions);
    470   };
    471 
    472   // Export
    473   return {
    474     BrowserOptions: BrowserOptions
    475   };
    476 
    477 });
    478