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  * Takes the |pluginsData| input argument which represents data about the
      7  * currently installed/running plugins and populates the html jstemplate with
      8  * that data. It expects an object structure like the above.
      9  * @param {Object} pluginsData Detailed info about installed plugins. Same
     10  *     expected format as returnPluginsData().
     11  */
     12 function renderTemplate(pluginsData) {
     13   // This is the javascript code that processes the template:
     14   var input = new JsEvalContext(pluginsData);
     15   var output = $('pluginTemplate');
     16   jstProcess(input, output);
     17 }
     18 
     19 /**
     20  * Asks the C++ PluginsDOMHandler to get details about the installed plugins and
     21  * return detailed data about the configuration. The PluginsDOMHandler should
     22  * reply to returnPluginsData() (below).
     23  */
     24 function requestPluginsData() {
     25   chrome.send('requestPluginsData');
     26   chrome.send('getShowDetails');
     27 }
     28 
     29 function loadShowDetailsFromPrefs(show_details) {
     30   tmiModeExpanded = show_details;
     31   $('collapse').style.display =
     32       show_details ? 'inline' : 'none';
     33   $('expand').style.display =
     34       show_details ? 'none' : 'inline';
     35 
     36   document.body.className = show_details ? 'show-in-tmi-mode' : 'hide-tmi-mode';
     37 }
     38 
     39 /**
     40  * Called by the web_ui_ to re-populate the page with data representing the
     41  * current state of installed plugins.
     42  * @param {Object} pluginsData Detailed info about installed plugins. The
     43  *     template expects each plugin's format to match the following structure to
     44  *     correctly populate the page:
     45  *   {
     46  *     plugins: [
     47  *       {
     48  *         name: 'Group Name',
     49  *         description: 'description',
     50  *         version: 'version',
     51  *         update_url: 'http://update/',
     52  *         critical: true,
     53  *         enabled: true,
     54  *         identifier: 'plugin-name',
     55  *         plugin_files: [
     56  *           {
     57  *             path: '/blahblah/blahblah/MyCrappyPlugin.plugin',
     58  *             name: 'MyCrappyPlugin',
     59  *             version: '1.2.3',
     60  *             description: 'My crappy plugin',
     61  *             mimeTypes: [
     62  *               { description: 'Foo Media',
     63  *                 fileExtensions: ['foo'],
     64  *                 mimeType: 'application/x-my-foo' },
     65  *               { description: 'Bar Stuff',
     66  *                 fileExtensions: ['bar', 'baz'],
     67  *                 mimeType: 'application/my-bar' }
     68  *             ],
     69  *             enabledMode: 'enabledByUser'
     70  *           },
     71  *           {
     72  *             path: '/tmp/MyFirst.plugin',
     73  *             name: 'MyFirstPlugin',
     74  *             version: '3.14r15926',
     75  *             description: 'My first plugin',
     76  *             mimeTypes: [
     77  *               { description: 'New Guy Media',
     78  *                 fileExtensions: ['mfp'],
     79  *                 mimeType: 'application/x-my-first' }
     80  *             ],
     81  *             enabledMode: 'enabledByPolicy'
     82  *           },
     83  *           {
     84  *             path: '/foobar/baz/YourGreatPlugin.plugin',
     85  *             name: 'YourGreatPlugin',
     86  *             version: '4.5',
     87  *             description: 'Your great plugin',
     88  *             mimeTypes: [
     89  *               { description: 'Baz Stuff',
     90  *                 fileExtensions: ['baz'],
     91  *                 mimeType: 'application/x-your-baz' }
     92  *             ],
     93  *             enabledMode: 'disabledByUser'
     94  *           },
     95  *           {
     96  *             path: '/foobiz/bar/HisGreatPlugin.plugin',
     97  *             name: 'HisGreatPlugin',
     98  *             version: '1.2',
     99  *             description: 'His great plugin',
    100  *             mimeTypes: [
    101  *               { description: 'More baz Stuff',
    102  *                 fileExtensions: ['bor'],
    103  *                 mimeType: 'application/x-his-bor' }
    104  *             ],
    105  *             enabledMode: 'disabledByPolicy'
    106  *           }
    107  *         ]
    108  *       }
    109  *     ]
    110  *   }
    111  */
    112 function returnPluginsData(pluginsData) {
    113   var bodyContainer = $('body-container');
    114   var body = document.body;
    115 
    116   // Set all page content to be visible so we can measure heights.
    117   bodyContainer.style.visibility = 'hidden';
    118   body.className = '';
    119   var slidables = document.getElementsByClassName('show-in-tmi-mode');
    120   for (var i = 0; i < slidables.length; i++)
    121     slidables[i].style.height = 'auto';
    122 
    123   renderTemplate(pluginsData);
    124 
    125   // Add handlers to dynamically created HTML elements.
    126   var links = document.getElementsByClassName('disable-plugin-link');
    127   for (var i = 0; i < links.length; i++) {
    128     links[i].onclick = function() {
    129       handleEnablePlugin(this, false, false);
    130       return false;
    131     };
    132   }
    133   links = document.getElementsByClassName('enable-plugin-link');
    134   for (var i = 0; i < links.length; i++) {
    135     links[i].onclick = function() {
    136       handleEnablePlugin(this, true, false);
    137       return false;
    138     };
    139   }
    140   links = document.getElementsByClassName('disable-group-link');
    141   for (var i = 0; i < links.length; i++) {
    142     links[i].onclick = function() {
    143       handleEnablePlugin(this, false, true);
    144       return false;
    145     };
    146   }
    147   links = document.getElementsByClassName('enable-group-link');
    148   for (var i = 0; i < links.length; i++) {
    149     links[i].onclick = function() {
    150       handleEnablePlugin(this, true, true);
    151       return false;
    152     };
    153   }
    154   var checkboxes = document.getElementsByClassName('always-allow');
    155   for (var i = 0; i < checkboxes.length; i++) {
    156     checkboxes[i].onclick = function() {
    157       handleSetPluginAlwaysAllowed(this);
    158     };
    159   }
    160 
    161   if (cr.isChromeOS) {
    162     // Disable some controls for Guest in ChromeOS.
    163     uiAccountTweaks.UIAccountTweaks.applyGuestSessionVisibility(document);
    164     // Disable some controls for Public session in ChromeOS.
    165     uiAccountTweaks.UIAccountTweaks.applyPublicSessionVisibility(document);
    166   }
    167 
    168   // Make sure the left column (with "Description:", "Location:", etc.) is the
    169   // same size for all plugins.
    170   var labels = document.getElementsByClassName('plugin-details-label');
    171   var maxLabelWidth = 0;
    172   for (var i = 0; i < labels.length; i++)
    173     labels[i].style.width = 'auto';
    174   for (var i = 0; i < labels.length; i++)
    175     maxLabelWidth = Math.max(maxLabelWidth, labels[i].offsetWidth);
    176   for (var i = 0; i < labels.length; i++)
    177     labels[i].style.width = maxLabelWidth + 'px';
    178 
    179   // Explicitly set the height for each element that wants to be "slid" in and
    180   // out when the tmiModeExpanded is toggled.
    181   var slidables = document.getElementsByClassName('show-in-tmi-mode');
    182   for (var i = 0; i < slidables.length; i++)
    183     slidables[i].style.height = slidables[i].offsetHeight + 'px';
    184 
    185   // Reset visibility of page based on the current tmi mode.
    186   $('collapse').style.display =
    187      tmiModeExpanded ? 'inline' : 'none';
    188   $('expand').style.display =
    189      tmiModeExpanded ? 'none' : 'inline';
    190   bodyContainer.style.visibility = 'visible';
    191   body.className = tmiModeExpanded ?
    192      'show-tmi-mode-initial' : 'hide-tmi-mode-initial';
    193 }
    194 
    195 /**
    196  * Handles a 'enable' or 'disable' button getting clicked.
    197  * @param {HTMLElement} node The HTML element for the plugin being changed.
    198  * @param {boolean} enable Whether to enable or disable the plugin.
    199  * @param {boolean} isGroup True if we're enabling/disabling a plugin group,
    200  *     rather than a single plugin.
    201  */
    202 function handleEnablePlugin(node, enable, isGroup) {
    203   // Tell the C++ PluginsDOMHandler to enable/disable the plugin.
    204   chrome.send('enablePlugin', [String(node.path), String(enable),
    205               String(isGroup)]);
    206 }
    207 
    208 // Keeps track of whether details have been made visible (expanded) or not.
    209 var tmiModeExpanded = false;
    210 
    211 /*
    212  * Toggles visibility of details.
    213  */
    214 function toggleTmiMode() {
    215   tmiModeExpanded = !tmiModeExpanded;
    216 
    217   $('collapse').style.display =
    218       tmiModeExpanded ? 'inline' : 'none';
    219   $('expand').style.display =
    220       tmiModeExpanded ? 'none' : 'inline';
    221 
    222   document.body.className =
    223       tmiModeExpanded ? 'show-tmi-mode' : 'hide-tmi-mode';
    224 
    225   chrome.send('saveShowDetailsToPrefs', [String(tmiModeExpanded)]);
    226 }
    227 
    228 function handleSetPluginAlwaysAllowed(el) {
    229   chrome.send('setPluginAlwaysAllowed', [el.identifier, el.checked]);
    230 }
    231 
    232 /**
    233  * @param {Object} plugin An object containing the information about a plugin.
    234  *     See returnPluginsData() for the format of this object.
    235  * @return {boolean} Whether the plugin's version should be displayed.
    236  */
    237 function shouldDisplayPluginVersion(plugin) {
    238   return !!plugin.version && plugin.version != '0';
    239 }
    240 
    241 /**
    242  * @param {Object} plugin An object containing the information about a plugin.
    243  *     See returnPluginsData() for the format of this object.
    244  * @return {boolean} Whether the plugin's description should be displayed.
    245  */
    246 function shouldDisplayPluginDescription(plugin) {
    247   // Only display the description if it's not blank and if it's not just the
    248   // name, version, or combination thereof.
    249   return plugin.description &&
    250          plugin.description != plugin.name &&
    251          plugin.description != plugin.version &&
    252          plugin.description != 'Version ' + plugin.version &&
    253          plugin.description != plugin.name + ' ' + plugin.version;
    254 }
    255 
    256 /**
    257  * @param {Object} plugin An object containing the information about a plugin.
    258  *     See returnPluginsData() for the format of this object.
    259  * @return {boolean} Whether the plugin is enabled.
    260  */
    261 function isPluginEnabled(plugin) {
    262   return plugin.enabledMode == 'enabledByUser' ||
    263          plugin.enabledMode == 'enabledByPolicy';
    264 }
    265 
    266 // Unfortunately, we don't have notifications for plugin (list) status changes
    267 // (yet), so in the meanwhile just update regularly.
    268 setInterval(requestPluginsData, 30000);
    269 
    270 // Get data and have it displayed upon loading.
    271 document.addEventListener('DOMContentLoaded', requestPluginsData);
    272 
    273 // Add handlers to static HTML elements.
    274 $('collapse').onclick = toggleTmiMode;
    275 $('expand').onclick = toggleTmiMode;
    276 $('details-link').onclick = toggleTmiMode;
    277