1<!DOCTYPE HTML> 2<html i18n-values="dir:textdirection;"> 3<head> 4<meta charset="utf-8"> 5<title i18n-content="pluginsTitle"></title> 6<style> 7body { 8 margin: 10px; 9 min-width: 47em; 10} 11 12a { 13 color: blue; 14 font-size: 103%; 15} 16 17div#header { 18 margin-bottom: 1.05em; 19 /* 67px is the height of the header's background image. */ 20 min-height: 67px; 21 overflow: hidden; 22 padding-bottom: 20px; 23 -webkit-padding-start: 0; 24 padding-top: 20px; 25 position: relative; 26 box-sizing: border-box; 27} 28 29#header h1 { 30 background: url('../../app/theme/extensions_section.png') 0px 20px no-repeat; 31 display: inline; 32 margin: 0; 33 padding-bottom: 43px; 34 padding-left: 75px; 35 padding-top: 40px; 36} 37 38html[dir=rtl] #header h1 { 39 background: url('../../app/theme/extensions_section.png') right no-repeat; 40 padding-right: 95px; 41 padding-left: 0; 42} 43 44h1 { 45 font-size: 156%; 46 font-weight: bold; 47 padding: 0; 48 margin: 0; 49} 50 51div.content { 52 font-size: 88%; 53 margin-top: 5px; 54} 55 56.section-header { 57 background: #ebeff9; 58 border-top: 1px solid #b5c7de; 59 font-size: 99%; 60 padding-bottom: 2px; 61 -webkit-padding-start: 5px; 62 padding-top: 3px; 63 width: 100%; 64} 65 66.section-header > table tr td:first-child { 67 width: 100%; 68} 69 70.section-header > table { 71 width: 100%; 72} 73 74.section-header-title { 75 font-weight: bold; 76} 77 78.vbox-container { 79 display: -webkit-box; 80 -webkit-box-orient: vertical; 81} 82 83.wbox { 84 display: -webkit-box; 85 -webkit-box-align: stretch; 86 -webkit-box-flex: 1; 87} 88 89#top { 90 -webkit-padding-end: 5px; 91} 92 93.showInTmiMode { 94 overflow: hidden; 95} 96 97body.hideTmiModeInitial .showInTmiMode { 98 height: 0 !important; 99 opacity: 0; 100} 101 102body.hideTmiMode .showInTmiMode { 103 height: 0 !important; 104 opacity: 0; 105 -webkit-transition: all .1s ease-out; 106} 107 108body.showTmiModeInitial .showInTmiMode { 109 opacity: 1; 110} 111 112body.showTmiMode .showInTmiMode { 113 opacity: 1; 114 -webkit-transition: all .1s ease-in; 115} 116 117.wbox-tmi-mode { 118 -webkit-box-align: stretch; 119 -webkit-box-flex: 1; 120} 121 122.tmi-mode-image { 123 margin-top: 2px; 124 padding-left: 5px; 125 padding-right: 5px; 126} 127 128.tmi-mode-link { 129 margin-right: 3px; 130 white-space: nowrap; 131} 132 133.tmi-mode-link a { 134 font-size: 97%; 135} 136 137.tmi-mode { 138 background: #f4f6fc; 139 border-bottom: 1px solid #edeff5; 140 font-size: 89%; 141 padding-bottom: 0.8em; 142 -webkit-padding-start: 10px; 143 padding-top: 0.8em; 144 width: 100%; 145} 146 147.plugin-disabled > td { 148 background-color: #f0f0f0; 149 color: #a0a0a0; 150 padding-bottom: 4px; 151 padding-top: 5px; 152} 153 154.plugin-enabled > td { 155 padding-bottom: 4px; 156 padding-top: 5px; 157} 158 159.plugin-file-disabled { 160 background-color: #f0f0f0; 161 color: #a0a0a0; 162 padding-top: 5px; 163 padding-bottom: 5px; 164} 165 166.plugin-file-enabled { 167 padding-top: 5px; 168 padding-bottom: 5px; 169} 170 171.plugin { 172 border-bottom: 1px solid #cdcdcd; 173} 174 175.critical { 176 color: red; 177} 178 179/* Indent the text related to each plug-in. */ 180.plugin-text { 181 -webkit-padding-start: 5px; 182} 183 184.plugin-name { 185 font-weight: bold; 186} 187 188.no-plugins { 189 margin: 6em 0 0; 190 text-align: center; 191 font-size: 1.2em; 192} 193 194/* Use tables for layout, so eliminate extra spacing. */ 195.plugin-details table { 196 -webkit-border-horizontal-spacing: 0; 197 -webkit-border-vertical-spacing: 0; 198} 199 200.plugin-details { 201 -webkit-padding-start: 1em; 202} 203 204/* Separate the inital line, Description, Location, and MIME Types lines. */ 205.plugin-details > div { 206 padding-top: 0.1em 207} 208 209/* Align rows of tables along the top. */ 210.plugin-details tr { 211 vertical-align: top; 212} 213 214/* Separate columns by 1em for the most part. */ 215.plugin-details td+td { 216 -webkit-padding-start: 1em; 217} 218 219/* Make the MIME Types tables smaller. */ 220.plugin-details .mime-types { 221 font-size: 95%; 222} 223 224/* Separate the header from the contents in each MIME Types table. */ 225.plugin-details .mime-types .header td { 226 padding-bottom: 0.1em; 227 border-bottom: 1px solid; 228} 229 230/* Separate the columns for tables used for horizontal listings only a bit. */ 231.hlisting td+td { 232 -webkit-padding-start: 0.4em; 233} 234 235/* Match the indentation of .plugin-text. */ 236.plugin-actions { 237 -webkit-padding-start: 5px; 238 margin-top: 0.2em; 239 margin-bottom: 0.2em; 240} 241 242button { 243 font-size: 104%; 244} 245 246</style> 247<script> 248 249/** 250 * This variable structure is here to document the structure that the template 251 * expects to correctly populate the page. 252 */ 253var pluginDataFormat = { 254 'plugins': [ 255 { 256 'name': 'Group Name', 257 'description': 'description', 258 'version': 'version', 259 'update_url': 'http://update/', 260 'critical': true, 261 'enabled': true, 262 'plugin_files': [ 263 { 264 'path': '/blahblah/blahblah/MyCrappyPlugin.plugin', 265 'name': 'MyCrappyPlugin', 266 'version': '1.2.3', 267 'description': 'My crappy plugin', 268 'mimeTypes': [ 269 { 'description': 'Foo Media', 270 'fileExtensions': [ 'foo' ], 271 'mimeType': 'application/x-my-foo' }, 272 { 'description': 'Bar Stuff', 273 'fileExtensions': [ 'bar','baz' ], 274 'mimeType': 'application/my-bar' } 275 ], 276 'enabledMode': 'enabledByUser' 277 }, 278 { 279 'path': '/tmp/MyFirst.plugin', 280 'name': 'MyFirstPlugin', 281 'version': '3.14r15926', 282 'description': 'My first plugin', 283 'mimeTypes': [ 284 { 'description': 'New Guy Media', 285 'fileExtensions': [ 'mfp' ], 286 'mimeType': 'application/x-my-first' } 287 ], 288 'enabledMode': 'enabledByPolicy' 289 }, 290 { 291 'path': '/foobar/baz/YourGreatPlugin.plugin', 292 'name': 'YourGreatPlugin', 293 'version': '4.5', 294 'description': 'Your great plugin', 295 'mimeTypes': [ 296 { 'description': 'Baz Stuff', 297 'fileExtensions': [ 'baz' ], 298 'mimeType': 'application/x-your-baz' } 299 ], 300 'enabledMode': 'disabledByUser' 301 }, 302 { 303 'path': '/foobiz/bar/HisGreatPlugin.plugin', 304 'name': 'HisGreatPlugin', 305 'version': '1.2', 306 'description': 'His great plugin', 307 'mimeTypes': [ 308 { 'description': 'More baz Stuff', 309 'fileExtensions': [ 'bor' ], 310 'mimeType': 'application/x-his-bor' } 311 ], 312 'enabledMode': 'disabledByPolicy' 313 } 314 ] 315 } 316 ] 317}; 318 319/** 320 * Takes the |pluginsData| input argument which represents data about the 321 * currently installed/running plugins and populates the html jstemplate with 322 * that data. It expects an object structure like the above. 323 * @param {Object} pluginsData Detailed info about installed plugins 324 */ 325function renderTemplate(pluginsData) { 326 // This is the javascript code that processes the template: 327 var input = new JsEvalContext(pluginsData); 328 var output = document.getElementById('pluginTemplate'); 329 jstProcess(input, output); 330} 331 332/** 333 * Asks the C++ PluginsDOMHandler to get details about the installed plugins and 334 * return detailed data about the configuration. The PluginsDOMHandler should 335 * reply to returnPluginsData() (below). 336 */ 337function requestPluginsData() { 338 chrome.send('requestPluginsData', []); 339 chrome.send('getShowDetails', []); 340} 341 342function loadShowDetailsFromPrefs(show_details) { 343 tmiModeExpanded = show_details; 344 document.getElementById('collapse').style.display = 345 show_details ? 'inline' : 'none'; 346 document.getElementById('expand').style.display = 347 show_details ? 'none' : 'inline'; 348 349 document.body.className = 350 show_details ? 'showTmiMode' : 'hideTmiMode'; 351} 352 353/** 354 * Asks the C++ PluginsDOMHandler to show the terms of service (about:terms). 355 */ 356function showTermsOfService() { 357 chrome.send('showTermsOfService', []); 358} 359 360/** 361 * Called by the web_ui_ to re-populate the page with data representing the 362 * current state of installed plugins. 363 */ 364function returnPluginsData(pluginsData){ 365 var bodyContainer = document.getElementById('body-container'); 366 var body = document.body; 367 368 // Set all page content to be visible so we can measure heights. 369 bodyContainer.style.visibility = 'hidden'; 370 body.className = ''; 371 var slidables = document.getElementsByClassName('showInTmiMode'); 372 for (var i = 0; i < slidables.length; i++) 373 slidables[i].style.height = 'auto'; 374 375 renderTemplate(pluginsData); 376 377 // Make sure the left column (with "Description:", "Location:", etc.) is the 378 // same size for all plugins. 379 var labels = document.getElementsByClassName('plugin-details-label'); 380 var maxLabelWidth = 0; 381 for (var i = 0; i < labels.length; i++) 382 labels[i].style.width = 'auto'; 383 for (var i = 0; i < labels.length; i++) 384 maxLabelWidth = Math.max(maxLabelWidth, labels[i].offsetWidth); 385 for (var i = 0; i < labels.length; i++) 386 labels[i].style.width = maxLabelWidth + 'px'; 387 388 // Explicitly set the height for each element that wants to be "slid" in and 389 // out when the tmiModeExpanded is toggled. 390 var slidables = document.getElementsByClassName('showInTmiMode'); 391 for (var i = 0; i < slidables.length; i++) 392 slidables[i].style.height = slidables[i].offsetHeight + 'px'; 393 394 // Reset visibility of page based on the current tmi mode. 395 document.getElementById('collapse').style.display = 396 tmiModeExpanded ? 'inline' : 'none'; 397 document.getElementById('expand').style.display = 398 tmiModeExpanded ? 'none' : 'inline'; 399 bodyContainer.style.visibility = 'visible'; 400 body.className = tmiModeExpanded ? 401 'showTmiModeInitial' : 'hideTmiModeInitial'; 402} 403 404/** 405 * Handles a 'enable' or 'disable' button getting clicked. 406 */ 407function handleEnablePlugin(node, enable, isGroup) { 408 // Tell the C++ PluginsDOMHandler to enable/disable the plugin. 409 chrome.send('enablePlugin', [String(node.path), String(enable), 410 String(isGroup)]); 411} 412 413// Keeps track of whether details have been made visible (expanded) or not. 414var tmiModeExpanded = false; 415 416/* 417 * Toggles visibility of details. 418 */ 419function toggleTmiMode() { 420 tmiModeExpanded = !tmiModeExpanded; 421 422 document.getElementById('collapse').style.display = 423 tmiModeExpanded ? 'inline' : 'none'; 424 document.getElementById('expand').style.display = 425 tmiModeExpanded ? 'none' : 'inline'; 426 427 document.body.className = 428 tmiModeExpanded ? 'showTmiMode' : 'hideTmiMode'; 429 430 chrome.send('saveShowDetailsToPrefs', [String(tmiModeExpanded)]); 431} 432 433/** 434 * Determines whether a plugin's version should be displayed. 435 */ 436function shouldDisplayPluginVersion(plugin) { 437 return !!plugin.version && plugin.version != '0'; 438} 439 440/** 441 * Determines whether a plugin's description should be displayed. 442 */ 443function shouldDisplayPluginDescription(plugin) { 444 // Only display the description if it's not blank and if it's not just the 445 // name, version, or combination thereof. 446 return plugin.description && 447 plugin.description != plugin.name && 448 plugin.description != plugin.version && 449 plugin.description != 'Version ' + plugin.version && 450 plugin.description != plugin.name + ' ' + plugin.version; 451} 452 453/** 454 * Determines whether a plugin is enabled or not. 455 */ 456function isPluginEnabled(plugin) { 457 return plugin.enabledMode == 'enabledByUser' || 458 plugin.enabledMode == 'enabledByPolicy'; 459} 460 461// Unfortunately, we don't have notifications for plugin (list) status changes 462// (yet), so in the meanwhile just update regularly. 463setInterval(requestPluginsData, 30000); 464 465// Get data and have it displayed upon loading. 466document.addEventListener('DOMContentLoaded', requestPluginsData); 467 468</script> 469</head> 470<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize"> 471<div id="body-container" style="visibility:hidden"> 472 473 <div id="header"><h1 i18n-content="pluginsTitle">TITLE</h1></div> 474 475 <div id="pluginTemplate"> 476 477 <div id="container" class="vbox-container"> 478 <div id="top" class="wbox"> 479 480 <div class="section-header"> 481 <table cellpadding="0" cellspacing="0"><tr valign="center"> 482 <td> 483 <span class="section-header-title" i18n-content="pluginsTitle" 484 >TITLE</span> 485 <span class="section-header-title" 486 jsdisplay="plugins.length > 0">(<span 487 jscontent="plugins.length"></span>)</span> 488 </td> 489 <td width="18"> 490 <img id="collapse" class="tmi-mode-image" 491 style="display:none" onclick="toggleTmiMode();" 492 src="shared/images/minus.png"> 493 <img id="expand" class="tmi-mode-image" 494 onclick="toggleTmiMode();" src="shared/images/plus.png"> 495 </td> 496 <td> 497 <div class="tmi-mode-link"> 498 <a onclick="toggleTmiMode();" style="cursor: default" 499 i18n-content="pluginsDetailsModeLink">DETAILS</a> 500 </div> 501 </td> 502 </tr></table> 503 </div> 504 505 </div> 506 </div> 507 508 <div class="content"> 509 <div class="plugin-name no-plugins" jsdisplay="plugins.length === 0"> 510 <div i18n-content="noPlugins">NO_PLUGINS_ARE_INSTALLED</div> 511 </div> 512 513 <div jsdisplay="plugins.length > 0"> 514 <div class="plugin" jsselect="plugins"> 515 <table width="100%" cellpadding="2" cellspacing="0"> 516 <tr jsvalues= 517 ".className:isPluginEnabled($this) ? 'plugin-enabled' : 'plugin-disabled'"> 518 <td valign="top"> 519 <div class="plugin-text"> 520 <div> 521 <span class="plugin-name" dir="ltr" 522 jscontent="name">NAME</span> 523 <span jsdisplay="plugin_files.length > 1" 524 jscontent="'(' + plugin_files.length +' files)'">(x)</span> 525 <span jsdisplay="shouldDisplayPluginVersion($this)"> 526 - <span i18n-content="pluginVersion">VERSION</span> 527 <span jsvalues=".className:critical? 'critical': ''" 528 dir="ltr" jscontent="version">x.x.x.x</span> 529 </span> 530 <a jsdisplay="critical" jsvalues=".href:update_url" 531 i18n-content="pluginDownload">DOWNLOAD UPDATE</a> 532 <span jsdisplay="enabledMode == 'disabledByUser'" 533 i18n-content="pluginDisabled">(DISABLED)</span> 534 <span jsdisplay="enabledMode == 'disabledByPolicy'" 535 i18n-content="pluginDisabledByPolicy">(DISABLED_BY_POLICY)</span> 536 <span jsdisplay="enabledMode == 'enabledByPolicy'" 537 i18n-content="pluginEnabledByPolicy">(ENABLED_BY_POLICY)</span> 538 <div jsdisplay="shouldDisplayPluginDescription($this)"> 539 <span dir="ltr" jsvalues=".innerHTML:description"> 540 </div> 541 </div> 542 <div jsselect="plugin_files" class="plugin-details"> 543 <div class="showInTmiMode"> 544 <div jsvalues= 545 ".className:isPluginEnabled($this) ? 'plugin-file-enabled' : 'plugin-file-disabled'"> 546 <div><table><tr> 547 <td class="plugin-details-label" 548 i18n-content="pluginName">NAME:</td> 549 <td><span dir="ltr" jscontent="name">NAME</span></td> 550 </tr></table></div> 551 <div><table> 552 <tr jsdisplay="shouldDisplayPluginDescription($this)"> 553 <td class="plugin-details-label" 554 i18n-content="pluginDescription">DESCRIPTION:</td> 555 <td> 556 <span dir="ltr" jsvalues=".innerHTML:description"> 557 </td> 558 </tr> 559 </table></div> 560 <div><table><tr> 561 <td class="plugin-details-label" 562 i18n-content="pluginVersion">VERSION:</td> 563 <td><span dir="ltr" jscontent="version">x.x.x.x</span></td> 564 </tr></table></div> 565 <div><table><tr> 566 <td class="plugin-details-label" 567 i18n-content="pluginPath">PATH:</td> 568 <td><span dir="ltr" jscontent="path"></span></td> 569 </tr></table></div> 570 <div><table><tr> 571 <td class="plugin-details-label"> </td> 572 <td> 573 <span jsdisplay="enabledMode == 'disabledByUser'" 574 i18n-content="pluginDisabled">(DISABLED)</span> 575 <span jsdisplay="enabledMode == 'disabledByPolicy'" 576 i18n-content="pluginDisabledByPolicy">(DISABLED_BY_POLICY)</span> 577 <span jsdisplay="enabledMode == 'enabledByPolicy'" 578 i18n-content="pluginEnabledByPolicy">(ENABLED_BY_POLICY)</span> 579 <span> 580 <a 581 jsvalues=".path:path" 582 jsdisplay="enabledMode == 'enabledByUser'" 583 onclick="handleEnablePlugin(this, false, false)" 584 href="javascript:void(0);" 585 i18n-content="disable" 586 >DISABLE</a> 587 <a 588 jsvalues=".path:path" 589 jsdisplay="enabledMode == 'disabledByUser'" 590 onclick="handleEnablePlugin(this, true, false)" 591 href="javascript:void(0);" 592 i18n-content="enable" 593 >ENABLE</a> 594 <span 595 jsdisplay="enabledMode == 'enabledByPolicy'" 596 i18n-content="pluginCannotBeDisabledDueToPolicy" 597 >CANNOT_DISABLE</span> 598 <span 599 jsdisplay="enabledMode == 'disabledByPolicy'" 600 i18n-content="pluginCannotBeEnabledDueToPolicy" 601 >CANNOT_ENABLE</span> 602 </span> 603 </td> 604 </tr></table></div> 605 <table><tr jsdisplay="mimeTypes.length > 0"> 606 <td class="plugin-details-label" 607 i18n-content="pluginMimeTypes">MIME_TYPES:</td> 608 <td><table width="100%" class="mime-types"> 609 <tr class="header"> 610 <td i18n-content="pluginMimeTypesMimeType" 611 >MIME type</td> 612 <td i18n-content="pluginMimeTypesDescription" 613 >DESCRIPTION</td> 614 <td i18n-content="pluginMimeTypesFileExtensions" 615 >FILE_EXTENSIONS</td> 616 </tr> 617 <tr jsselect="mimeTypes"> 618 <td><span dir="ltr" 619 jscontent="mimeType"></span></td> 620 <td><span dir="ltr" 621 jsvalues=".innerHTML:description"></span></td> 622 <td><table jsdisplay="fileExtensions.length > 0" 623 class="hlisting"> 624 <tr><td jsselect="fileExtensions"> 625 <span dir="ltr" jscontent="'.' + $this"> 626 </td></tr> 627 </table></td> 628 </tr> 629 </table></td> 630 </tr></table> 631 </div> 632 </div> 633 </div> 634 </div> 635 <div class="plugin-actions"> 636 <span> 637 <a 638 jsvalues=".path:name" 639 jsdisplay="enabledMode == 'enabledByUser'" 640 onclick="handleEnablePlugin(this, false, true)" 641 href="javascript:void(0);" 642 i18n-content="disable" 643 >DISABLE</a> 644 <a 645 jsvalues=".path:name" 646 jsdisplay="enabledMode == 'disabledByUser'" 647 onclick="handleEnablePlugin(this, true, true)" 648 href="javascript:void(0);" 649 i18n-content="enable" 650 >ENABLE</a> 651 <span 652 jsdisplay="enabledMode == 'enabledByPolicy'" 653 i18n-content="pluginCannotBeDisabledDueToPolicy" 654 >CANNOT_DISABLE</span> 655 <span 656 jsdisplay="enabledMode == 'disabledByPolicy'" 657 i18n-content="pluginCannotBeEnabledDueToPolicy" 658 >CANNOT_ENABLE</span> 659 </span> 660 </div> 661 </td> 662 </tr> 663 </table> 664 </div> 665 </div> 666 </div> 667 </div> 668</div> 669</body> 670</html> 671