<!DOCTYPE HTML>
<html i18n-values="dir:textdirection;">
<head>
<meta charset="utf-8">
<title i18n-content="pluginsTitle"></title>
<style>
body {
margin: 10px;
min-width: 47em;
}
a {
color: blue;
font-size: 103%;
}
div#header {
margin-bottom: 1.05em;
/* 67px is the height of the header's background image. */
min-height: 67px;
overflow: hidden;
padding-bottom: 20px;
-webkit-padding-start: 0;
padding-top: 20px;
position: relative;
box-sizing: border-box;
}
#header h1 {
background: url('../../app/theme/extensions_section.png') 0px 20px no-repeat;
display: inline;
margin: 0;
padding-bottom: 43px;
padding-left: 75px;
padding-top: 40px;
}
html[dir=rtl] #header h1 {
background: url('../../app/theme/extensions_section.png') right no-repeat;
padding-right: 95px;
padding-left: 0;
}
h1 {
font-size: 156%;
font-weight: bold;
padding: 0;
margin: 0;
}
div.content {
font-size: 88%;
margin-top: 5px;
}
.section-header {
background: #ebeff9;
border-top: 1px solid #b5c7de;
font-size: 99%;
padding-bottom: 2px;
-webkit-padding-start: 5px;
padding-top: 3px;
width: 100%;
}
.section-header > table tr td:first-child {
width: 100%;
}
.section-header > table {
width: 100%;
}
.section-header-title {
font-weight: bold;
}
.vbox-container {
display: -webkit-box;
-webkit-box-orient: vertical;
}
.wbox {
display: -webkit-box;
-webkit-box-align: stretch;
-webkit-box-flex: 1;
}
#top {
-webkit-padding-end: 5px;
}
.showInTmiMode {
overflow: hidden;
}
body.hideTmiModeInitial .showInTmiMode {
height: 0 !important;
opacity: 0;
}
body.hideTmiMode .showInTmiMode {
height: 0 !important;
opacity: 0;
-webkit-transition: all .1s ease-out;
}
body.showTmiModeInitial .showInTmiMode {
opacity: 1;
}
body.showTmiMode .showInTmiMode {
opacity: 1;
-webkit-transition: all .1s ease-in;
}
.wbox-tmi-mode {
-webkit-box-align: stretch;
-webkit-box-flex: 1;
}
.tmi-mode-image {
margin-top: 2px;
padding-left: 5px;
padding-right: 5px;
}
.tmi-mode-link {
margin-right: 3px;
white-space: nowrap;
}
.tmi-mode-link a {
font-size: 97%;
}
.tmi-mode {
background: #f4f6fc;
border-bottom: 1px solid #edeff5;
font-size: 89%;
padding-bottom: 0.8em;
-webkit-padding-start: 10px;
padding-top: 0.8em;
width: 100%;
}
.plugin-disabled > td {
background-color: #f0f0f0;
color: #a0a0a0;
padding-bottom: 4px;
padding-top: 5px;
}
.plugin-enabled > td {
padding-bottom: 4px;
padding-top: 5px;
}
.plugin-file-disabled {
background-color: #f0f0f0;
color: #a0a0a0;
padding-top: 5px;
padding-bottom: 5px;
}
.plugin-file-enabled {
padding-top: 5px;
padding-bottom: 5px;
}
.plugin {
border-bottom: 1px solid #cdcdcd;
}
.critical {
color: red;
}
/* Indent the text related to each plug-in. */
.plugin-text {
-webkit-padding-start: 5px;
}
.plugin-name {
font-weight: bold;
}
.no-plugins {
margin: 6em 0 0;
text-align: center;
font-size: 1.2em;
}
/* Use tables for layout, so eliminate extra spacing. */
.plugin-details table {
-webkit-border-horizontal-spacing: 0;
-webkit-border-vertical-spacing: 0;
}
.plugin-details {
-webkit-padding-start: 1em;
}
/* Separate the inital line, Description, Location, and MIME Types lines. */
.plugin-details > div {
padding-top: 0.1em
}
/* Align rows of tables along the top. */
.plugin-details tr {
vertical-align: top;
}
/* Separate columns by 1em for the most part. */
.plugin-details td+td {
-webkit-padding-start: 1em;
}
/* Make the MIME Types tables smaller. */
.plugin-details .mime-types {
font-size: 95%;
}
/* Separate the header from the contents in each MIME Types table. */
.plugin-details .mime-types .header td {
padding-bottom: 0.1em;
border-bottom: 1px solid;
}
/* Separate the columns for tables used for horizontal listings only a bit. */
.hlisting td+td {
-webkit-padding-start: 0.4em;
}
/* Match the indentation of .plugin-text. */
.plugin-actions {
-webkit-padding-start: 5px;
margin-top: 0.2em;
margin-bottom: 0.2em;
}
button {
font-size: 104%;
}
</style>
<script>
/**
* This variable structure is here to document the structure that the template
* expects to correctly populate the page.
*/
var pluginDataFormat = {
'plugins': [
{
'name': 'Group Name',
'description': 'description',
'version': 'version',
'update_url': 'http://update/',
'critical': true,
'enabled': true,
'plugin_files': [
{
'path': '/blahblah/blahblah/MyCrappyPlugin.plugin',
'name': 'MyCrappyPlugin',
'version': '1.2.3',
'description': 'My crappy plugin',
'mimeTypes': [
{ 'description': 'Foo Media',
'fileExtensions': [ 'foo' ],
'mimeType': 'application/x-my-foo' },
{ 'description': 'Bar Stuff',
'fileExtensions': [ 'bar','baz' ],
'mimeType': 'application/my-bar' }
],
'enabledMode': 'enabledByUser'
},
{
'path': '/tmp/MyFirst.plugin',
'name': 'MyFirstPlugin',
'version': '3.14r15926',
'description': 'My first plugin',
'mimeTypes': [
{ 'description': 'New Guy Media',
'fileExtensions': [ 'mfp' ],
'mimeType': 'application/x-my-first' }
],
'enabledMode': 'enabledByPolicy'
},
{
'path': '/foobar/baz/YourGreatPlugin.plugin',
'name': 'YourGreatPlugin',
'version': '4.5',
'description': 'Your great plugin',
'mimeTypes': [
{ 'description': 'Baz Stuff',
'fileExtensions': [ 'baz' ],
'mimeType': 'application/x-your-baz' }
],
'enabledMode': 'disabledByUser'
},
{
'path': '/foobiz/bar/HisGreatPlugin.plugin',
'name': 'HisGreatPlugin',
'version': '1.2',
'description': 'His great plugin',
'mimeTypes': [
{ 'description': 'More baz Stuff',
'fileExtensions': [ 'bor' ],
'mimeType': 'application/x-his-bor' }
],
'enabledMode': 'disabledByPolicy'
}
]
}
]
};
/**
* Takes the |pluginsData| input argument which represents data about the
* currently installed/running plugins and populates the html jstemplate with
* that data. It expects an object structure like the above.
* @param {Object} pluginsData Detailed info about installed plugins
*/
function renderTemplate(pluginsData) {
// This is the javascript code that processes the template:
var input = new JsEvalContext(pluginsData);
var output = document.getElementById('pluginTemplate');
jstProcess(input, output);
}
/**
* Asks the C++ PluginsDOMHandler to get details about the installed plugins and
* return detailed data about the configuration. The PluginsDOMHandler should
* reply to returnPluginsData() (below).
*/
function requestPluginsData() {
chrome.send('requestPluginsData', []);
chrome.send('getShowDetails', []);
}
function loadShowDetailsFromPrefs(show_details) {
tmiModeExpanded = show_details;
document.getElementById('collapse').style.display =
show_details ? 'inline' : 'none';
document.getElementById('expand').style.display =
show_details ? 'none' : 'inline';
document.body.className =
show_details ? 'showTmiMode' : 'hideTmiMode';
}
/**
* Asks the C++ PluginsDOMHandler to show the terms of service (about:terms).
*/
function showTermsOfService() {
chrome.send('showTermsOfService', []);
}
/**
* Called by the web_ui_ to re-populate the page with data representing the
* current state of installed plugins.
*/
function returnPluginsData(pluginsData){
var bodyContainer = document.getElementById('body-container');
var body = document.body;
// Set all page content to be visible so we can measure heights.
bodyContainer.style.visibility = 'hidden';
body.className = '';
var slidables = document.getElementsByClassName('showInTmiMode');
for (var i = 0; i < slidables.length; i++)
slidables[i].style.height = 'auto';
renderTemplate(pluginsData);
// Make sure the left column (with "Description:", "Location:", etc.) is the
// same size for all plugins.
var labels = document.getElementsByClassName('plugin-details-label');
var maxLabelWidth = 0;
for (var i = 0; i < labels.length; i++)
labels[i].style.width = 'auto';
for (var i = 0; i < labels.length; i++)
maxLabelWidth = Math.max(maxLabelWidth, labels[i].offsetWidth);
for (var i = 0; i < labels.length; i++)
labels[i].style.width = maxLabelWidth + 'px';
// Explicitly set the height for each element that wants to be "slid" in and
// out when the tmiModeExpanded is toggled.
var slidables = document.getElementsByClassName('showInTmiMode');
for (var i = 0; i < slidables.length; i++)
slidables[i].style.height = slidables[i].offsetHeight + 'px';
// Reset visibility of page based on the current tmi mode.
document.getElementById('collapse').style.display =
tmiModeExpanded ? 'inline' : 'none';
document.getElementById('expand').style.display =
tmiModeExpanded ? 'none' : 'inline';
bodyContainer.style.visibility = 'visible';
body.className = tmiModeExpanded ?
'showTmiModeInitial' : 'hideTmiModeInitial';
}
/**
* Handles a 'enable' or 'disable' button getting clicked.
*/
function handleEnablePlugin(node, enable, isGroup) {
// Tell the C++ PluginsDOMHandler to enable/disable the plugin.
chrome.send('enablePlugin', [String(node.path), String(enable),
String(isGroup)]);
}
// Keeps track of whether details have been made visible (expanded) or not.
var tmiModeExpanded = false;
/*
* Toggles visibility of details.
*/
function toggleTmiMode() {
tmiModeExpanded = !tmiModeExpanded;
document.getElementById('collapse').style.display =
tmiModeExpanded ? 'inline' : 'none';
document.getElementById('expand').style.display =
tmiModeExpanded ? 'none' : 'inline';
document.body.className =
tmiModeExpanded ? 'showTmiMode' : 'hideTmiMode';
chrome.send('saveShowDetailsToPrefs', [String(tmiModeExpanded)]);
}
/**
* Determines whether a plugin's version should be displayed.
*/
function shouldDisplayPluginVersion(plugin) {
return !!plugin.version && plugin.version != '0';
}
/**
* Determines whether a plugin's description should be displayed.
*/
function shouldDisplayPluginDescription(plugin) {
// Only display the description if it's not blank and if it's not just the
// name, version, or combination thereof.
return plugin.description &&
plugin.description != plugin.name &&
plugin.description != plugin.version &&
plugin.description != 'Version ' + plugin.version &&
plugin.description != plugin.name + ' ' + plugin.version;
}
/**
* Determines whether a plugin is enabled or not.
*/
function isPluginEnabled(plugin) {
return plugin.enabledMode == 'enabledByUser' ||
plugin.enabledMode == 'enabledByPolicy';
}
// Unfortunately, we don't have notifications for plugin (list) status changes
// (yet), so in the meanwhile just update regularly.
setInterval(requestPluginsData, 30000);
// Get data and have it displayed upon loading.
document.addEventListener('DOMContentLoaded', requestPluginsData);
</script>
</head>
<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
<div id="body-container" style="visibility:hidden">
<div id="header"><h1 i18n-content="pluginsTitle">TITLE</h1></div>
<div id="pluginTemplate">
<div id="container" class="vbox-container">
<div id="top" class="wbox">
<div class="section-header">
<table cellpadding="0" cellspacing="0"><tr valign="center">
<td>
<span class="section-header-title" i18n-content="pluginsTitle"
>TITLE</span>
<span class="section-header-title"
jsdisplay="plugins.length > 0">(<span
jscontent="plugins.length"></span>)</span>
</td>
<td width="18">
<img id="collapse" class="tmi-mode-image"
style="display:none" onclick="toggleTmiMode();"
src="shared/images/minus.png">
<img id="expand" class="tmi-mode-image"
onclick="toggleTmiMode();" src="shared/images/plus.png">
</td>
<td>
<div class="tmi-mode-link">
<a onclick="toggleTmiMode();" style="cursor: default"
i18n-content="pluginsDetailsModeLink">DETAILS</a>
</div>
</td>
</tr></table>
</div>
</div>
</div>
<div class="content">
<div class="plugin-name no-plugins" jsdisplay="plugins.length === 0">
<div i18n-content="noPlugins">NO_PLUGINS_ARE_INSTALLED</div>
</div>
<div jsdisplay="plugins.length > 0">
<div class="plugin" jsselect="plugins">
<table width="100%" cellpadding="2" cellspacing="0">
<tr jsvalues=
".className:isPluginEnabled($this) ? 'plugin-enabled' : 'plugin-disabled'">
<td valign="top">
<div class="plugin-text">
<div>
<span class="plugin-name" dir="ltr"
jscontent="name">NAME</span>
<span jsdisplay="plugin_files.length > 1"
jscontent="'(' + plugin_files.length +' files)'">(x)</span>
<span jsdisplay="shouldDisplayPluginVersion($this)">
- <span i18n-content="pluginVersion">VERSION</span>
<span jsvalues=".className:critical? 'critical': ''"
dir="ltr" jscontent="version">x.x.x.x</span>
</span>
<a jsdisplay="critical" jsvalues=".href:update_url"
i18n-content="pluginDownload">DOWNLOAD UPDATE</a>
<span jsdisplay="enabledMode == 'disabledByUser'"
i18n-content="pluginDisabled">(DISABLED)</span>
<span jsdisplay="enabledMode == 'disabledByPolicy'"
i18n-content="pluginDisabledByPolicy">(DISABLED_BY_POLICY)</span>
<span jsdisplay="enabledMode == 'enabledByPolicy'"
i18n-content="pluginEnabledByPolicy">(ENABLED_BY_POLICY)</span>
<div jsdisplay="shouldDisplayPluginDescription($this)">
<span dir="ltr" jsvalues=".innerHTML:description">
</div>
</div>
<div jsselect="plugin_files" class="plugin-details">
<div class="showInTmiMode">
<div jsvalues=
".className:isPluginEnabled($this) ? 'plugin-file-enabled' : 'plugin-file-disabled'">
<div><table><tr>
<td class="plugin-details-label"
i18n-content="pluginName">NAME:</td>
<td><span dir="ltr" jscontent="name">NAME</span></td>
</tr></table></div>
<div><table>
<tr jsdisplay="shouldDisplayPluginDescription($this)">
<td class="plugin-details-label"
i18n-content="pluginDescription">DESCRIPTION:</td>
<td>
<span dir="ltr" jsvalues=".innerHTML:description">
</td>
</tr>
</table></div>
<div><table><tr>
<td class="plugin-details-label"
i18n-content="pluginVersion">VERSION:</td>
<td><span dir="ltr" jscontent="version">x.x.x.x</span></td>
</tr></table></div>
<div><table><tr>
<td class="plugin-details-label"
i18n-content="pluginPath">PATH:</td>
<td><span dir="ltr" jscontent="path"></span></td>
</tr></table></div>
<div><table><tr>
<td class="plugin-details-label"> </td>
<td>
<span jsdisplay="enabledMode == 'disabledByUser'"
i18n-content="pluginDisabled">(DISABLED)</span>
<span jsdisplay="enabledMode == 'disabledByPolicy'"
i18n-content="pluginDisabledByPolicy">(DISABLED_BY_POLICY)</span>
<span jsdisplay="enabledMode == 'enabledByPolicy'"
i18n-content="pluginEnabledByPolicy">(ENABLED_BY_POLICY)</span>
<span>
<a
jsvalues=".path:path"
jsdisplay="enabledMode == 'enabledByUser'"
onclick="handleEnablePlugin(this, false, false)"
href="javascript:void(0);"
i18n-content="disable"
>DISABLE</a>
<a
jsvalues=".path:path"
jsdisplay="enabledMode == 'disabledByUser'"
onclick="handleEnablePlugin(this, true, false)"
href="javascript:void(0);"
i18n-content="enable"
>ENABLE</a>
<span
jsdisplay="enabledMode == 'enabledByPolicy'"
i18n-content="pluginCannotBeDisabledDueToPolicy"
>CANNOT_DISABLE</span>
<span
jsdisplay="enabledMode == 'disabledByPolicy'"
i18n-content="pluginCannotBeEnabledDueToPolicy"
>CANNOT_ENABLE</span>
</span>
</td>
</tr></table></div>
<table><tr jsdisplay="mimeTypes.length > 0">
<td class="plugin-details-label"
i18n-content="pluginMimeTypes">MIME_TYPES:</td>
<td><table width="100%" class="mime-types">
<tr class="header">
<td i18n-content="pluginMimeTypesMimeType"
>MIME type</td>
<td i18n-content="pluginMimeTypesDescription"
>DESCRIPTION</td>
<td i18n-content="pluginMimeTypesFileExtensions"
>FILE_EXTENSIONS</td>
</tr>
<tr jsselect="mimeTypes">
<td><span dir="ltr"
jscontent="mimeType"></span></td>
<td><span dir="ltr"
jsvalues=".innerHTML:description"></span></td>
<td><table jsdisplay="fileExtensions.length > 0"
class="hlisting">
<tr><td jsselect="fileExtensions">
<span dir="ltr" jscontent="'.' + $this">
</td></tr>
</table></td>
</tr>
</table></td>
</tr></table>
</div>
</div>
</div>
</div>
<div class="plugin-actions">
<span>
<a
jsvalues=".path:name"
jsdisplay="enabledMode == 'enabledByUser'"
onclick="handleEnablePlugin(this, false, true)"
href="javascript:void(0);"
i18n-content="disable"
>DISABLE</a>
<a
jsvalues=".path:name"
jsdisplay="enabledMode == 'disabledByUser'"
onclick="handleEnablePlugin(this, true, true)"
href="javascript:void(0);"
i18n-content="enable"
>ENABLE</a>
<span
jsdisplay="enabledMode == 'enabledByPolicy'"
i18n-content="pluginCannotBeDisabledDueToPolicy"
>CANNOT_DISABLE</span>
<span
jsdisplay="enabledMode == 'disabledByPolicy'"
i18n-content="pluginCannotBeEnabledDueToPolicy"
>CANNOT_ENABLE</span>
</span>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
</body>
</html>