Home | History | Annotate | Download | only in resources
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 /**
      6  * This variable structure is here to document the structure that the template
      7  * expects to correctly populate the page.
      8  */
      9 
     10 /**
     11  * Takes the |experimentsData| input argument which represents data about all
     12  * the current experiments and populates the html jstemplate with that data.
     13  * with that data. It expects an object structure like the above.
     14  * @param {Object} experimentsData Information about all experiments.
     15  *     See returnFlagsExperiments() for the structure of this object.
     16  */
     17 function renderTemplate(experimentsData) {
     18   // This is the javascript code that processes the template:
     19   jstProcess(new JsEvalContext(experimentsData),
     20              $('flagsExperimentTemplate'));
     21 
     22   // Add handlers to dynamically created HTML elements.
     23   var elements = document.getElementsByClassName('experiment-select');
     24   for (var i = 0; i < elements.length; ++i) {
     25     elements[i].onchange = function() {
     26       handleSelectChoiceExperiment(this, this.selectedIndex);
     27       return false;
     28     };
     29   }
     30 
     31   elements = document.getElementsByClassName('experiment-disable-link');
     32   for (var i = 0; i < elements.length; ++i) {
     33     elements[i].onclick = function() {
     34       handleEnableExperiment(this, false);
     35       return false;
     36     };
     37   }
     38 
     39   elements = document.getElementsByClassName('experiment-enable-link');
     40   for (var i = 0; i < elements.length; ++i) {
     41     elements[i].onclick = function() {
     42       handleEnableExperiment(this, true);
     43       return false;
     44     };
     45   }
     46 
     47   elements = document.getElementsByClassName('experiment-restart-button');
     48   for (var i = 0; i < elements.length; ++i) {
     49     elements[i].onclick = restartBrowser;
     50   }
     51 
     52   $('experiment-reset-all').onclick = resetAllFlags;
     53 
     54   highlightReferencedFlag();
     55 }
     56 
     57 /**
     58  * Highlight an element associated with the page's location's hash. We need to
     59  * fake fragment navigation with '.scrollIntoView()', since the fragment IDs
     60  * don't actually exist until after the template code runs; normal navigation
     61  * therefore doesn't work.
     62  */
     63 function highlightReferencedFlag() {
     64   if (window.location.hash) {
     65     var el = document.querySelector(window.location.hash);
     66     if (el && !el.classList.contains('referenced')) {
     67       // Unhighlight whatever's highlighted.
     68       if (document.querySelector('.referenced'))
     69         document.querySelector('.referenced').classList.remove('referenced');
     70       // Highlight the referenced element.
     71       el.classList.add('referenced');
     72       el.scrollIntoView();
     73     }
     74   }
     75 }
     76 
     77 /**
     78  * Asks the C++ FlagsDOMHandler to get details about the available experiments
     79  * and return detailed data about the configuration. The FlagsDOMHandler
     80  * should reply to returnFlagsExperiments() (below).
     81  */
     82 function requestFlagsExperimentsData() {
     83   chrome.send('requestFlagsExperiments');
     84 }
     85 
     86 /**
     87  * Asks the C++ FlagsDOMHandler to restart the browser (restoring tabs).
     88  */
     89 function restartBrowser() {
     90   chrome.send('restartBrowser');
     91 }
     92 
     93 /**
     94  * Reset all flags to their default values and refresh the UI.
     95  */
     96 function resetAllFlags() {
     97   // Asks the C++ FlagsDOMHandler to reset all flags to default values.
     98   chrome.send('resetAllFlags');
     99   requestFlagsExperimentsData();
    100 }
    101 
    102 /**
    103  * Called by the WebUI to re-populate the page with data representing the
    104  * current state of all experiments.
    105  * @param {Object} experimentsData Information about all experiments.
    106  *     in the following format:
    107  *   {
    108  *     supportedExperiments: [
    109  *       {
    110  *         internal_name: 'Experiment ID string',
    111  *         name: 'Experiment Name',
    112  *         description: 'description',
    113  *         // enabled is only set if the experiment is single valued.
    114  *         enabled: true,
    115  *         // choices is only set if the experiment has multiple values.
    116  *         choices: [
    117  *           {
    118  *             internal_name: 'Experiment ID string',
    119  *             description: 'description',
    120  *             selected: true
    121  *           }
    122  *         ],
    123  *         supported_platforms: [
    124  *           'Mac',
    125  *           'Linux'
    126  *         ],
    127  *       }
    128  *     ],
    129  *     unsupportedExperiments: [
    130  *       // Mirrors the format of |supportedExperiments| above.
    131  *     ],
    132  *     needsRestart: false,
    133  *     showBetaChannelPromotion: false,
    134  *     showDevChannelPromotion: false
    135  *   }
    136  */
    137 function returnFlagsExperiments(experimentsData) {
    138   var bodyContainer = $('body-container');
    139   renderTemplate(experimentsData);
    140 
    141   if (experimentsData.showBetaChannelPromotion)
    142     $('channel-promo-beta').hidden = false;
    143   else if (experimentsData.showDevChannelPromotion)
    144     $('channel-promo-dev').hidden = false;
    145 
    146   bodyContainer.style.visibility = 'visible';
    147 }
    148 
    149 /**
    150  * Handles a 'enable' or 'disable' button getting clicked.
    151  * @param {HTMLElement} node The node for the experiment being changed.
    152  * @param {boolean} enable Whether to enable or disable the experiment.
    153  */
    154 function handleEnableExperiment(node, enable) {
    155   // Tell the C++ FlagsDOMHandler to enable/disable the experiment.
    156   chrome.send('enableFlagsExperiment', [String(node.internal_name),
    157                                         String(enable)]);
    158   requestFlagsExperimentsData();
    159 }
    160 
    161 /**
    162  * Invoked when the selection of a multi-value choice is changed to the
    163  * specified index.
    164  * @param {HTMLElement} node The node for the experiment being changed.
    165  * @param {number} index The index of the option that was selected.
    166  */
    167 function handleSelectChoiceExperiment(node, index) {
    168   // Tell the C++ FlagsDOMHandler to enable the selected choice.
    169   chrome.send('enableFlagsExperiment',
    170               [String(node.internal_name) + '@' + index, 'true']);
    171   requestFlagsExperimentsData();
    172 }
    173 
    174 // Get data and have it displayed upon loading.
    175 document.addEventListener('DOMContentLoaded', requestFlagsExperimentsData);
    176 
    177 // Update the highlighted flag when the hash changes.
    178 window.addEventListener('hashchange', highlightReferencedFlag);
    179