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 */ 12function 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 */ 24function requestPluginsData() { 25 chrome.send('requestPluginsData'); 26 chrome.send('getShowDetails'); 27} 28 29function 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 */ 112function 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 */ 202function 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. 209var tmiModeExpanded = false; 210 211/* 212 * Toggles visibility of details. 213 */ 214function 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 228function 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 */ 237function 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 */ 246function 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 */ 261function 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. 268setInterval(requestPluginsData, 30000); 269 270// Get data and have it displayed upon loading. 271document.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