gecko/toolkit/mozapps/extensions/content/extensions.xml

1913 lines
70 KiB
XML

<?xml version="1.0"?>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is the Extension Manager UI.
-
- The Initial Developer of the Original Code is
- the Mozilla Foundation.
- Portions created by the Initial Developer are Copyright (C) 2010
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Blair McBride <bmcbride@mozilla.com>
- David Dahl <ddahl@mozilla.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the LGPL or the GPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the MPL, the GPL or the LGPL.
-
- ***** END LICENSE BLOCK ***** -->
<!DOCTYPE page [
<!ENTITY % extensionsDTD SYSTEM "chrome://mozapps/locale/extensions/extensions.dtd">
%extensionsDTD;
]>
<bindings id="addonBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<!-- Rating - displays current/average rating, allows setting user rating -->
<binding id="rating">
<content>
<xul:image class="star"
onmouseover="document.getBindingParent(this)._hover(1);"
onclick="document.getBindingParent(this).userRating = 1;"/>
<xul:image class="star"
onmouseover="document.getBindingParent(this)._hover(2);"
onclick="document.getBindingParent(this).userRating = 2;"/>
<xul:image class="star"
onmouseover="document.getBindingParent(this)._hover(3);"
onclick="document.getBindingParent(this).userRating = 3;"/>
<xul:image class="star"
onmouseover="document.getBindingParent(this)._hover(4);"
onclick="document.getBindingParent(this).userRating = 4;"/>
<xul:image class="star"
onmouseover="document.getBindingParent(this)._hover(5);"
onclick="document.getBindingParent(this).userRating = 5;"/>
</content>
<implementation>
<constructor><![CDATA[
this._updateStars();
]]></constructor>
<property name="stars" readonly="true">
<getter><![CDATA[
return document.getAnonymousNodes(this);
]]></getter>
</property>
<property name="averageRating">
<getter><![CDATA[
if (this.hasAttribute("averagerating"))
return this.getAttribute("averagerating");
return -1;
]]></getter>
<setter><![CDATA[
this.setAttribute("averagerating", val);
if (this.showRating == "average")
this._updateStars();
]]></setter>
</property>
<property name="userRating">
<getter><![CDATA[
if (this.hasAttribute("userrating"))
return this.getAttribute("userrating");
return -1;
]]></getter>
<setter><![CDATA[
if (this.showRating != "user")
return;
this.setAttribute("userrating", val);
if (this.showRating == "user")
this._updateStars();
]]></setter>
</property>
<property name="showRating">
<getter><![CDATA[
if (this.hasAttribute("showrating"))
return this.getAttribute("showrating");
return "average";
]]></getter>
<setter><![CDATA[
if (val != "average" || val != "user")
throw new Error("Invalid value");
this.setAttribute("showrating", val);
this._updateStars();
]]></setter>
</property>
<method name="_updateStars">
<body><![CDATA[
var stars = this.stars;
var rating = this[this.showRating + "Rating"];
// average ratings can be non-whole numbers, round them so they
// match to their closest star
rating = Math.round(rating);
for (let i = 0; i < stars.length; i++)
stars[i].setAttribute("on", rating > i);
]]></body>
</method>
<method name="_hover">
<parameter name="aScore"/>
<body><![CDATA[
if (this.showRating != "user")
return;
var stars = this.stars;
for (let i = 0; i < stars.length; i++)
stars[i].setAttribute("on", i <= (aScore -1));
]]></body>
</method>
</implementation>
<handlers>
<handler event="mouseout">
this._updateStars();
</handler>
</handlers>
</binding>
<!-- Download progress - shows graphical progress of download and any
related status message. -->
<binding id="download-progress">
<content>
<xul:stack flex="1">
<xul:hbox flex="1">
<xul:hbox class="start-cap"/>
<xul:progressmeter anonid="progress" class="progress" flex="1"
min="0" max="100"/>
<xul:hbox class="end-cap"/>
</xul:hbox>
<xul:hbox class="status-container">
<xul:button anonid="pause-btn" class="pause"
tooltiptext="&progress.pause.tooltip;"/>
<xul:spacer flex="1"/>
<xul:label anonid="status" class="status"/>
<xul:spacer flex="1"/>
<xul:button anonid="cancel-btn" class="cancel"
tooltiptext="&progress.cancel.tooltip;"/>
</xul:hbox>
</xul:stack>
</content>
<implementation>
<constructor><![CDATA[
var progress = 0;
if (this.hasAttribute("progress"))
progress = parseInt(this.getAttribute("progress"));
this.progress = progress;
]]></constructor>
<field name="_progress">
document.getAnonymousElementByAttribute(this, "anonid", "progress");
</field>
<field name="_pause">
document.getAnonymousElementByAttribute(this, "anonid", "pause-btn");
</field>
<field name="_cancel">
document.getAnonymousElementByAttribute(this, "anonid", "cancel-btn");
</field>
<field name="_status">
document.getAnonymousElementByAttribute(this, "anonid", "status");
</field>
<property name="progress">
<getter><![CDATA[
return this._progress.value;
]]></getter>
<setter><![CDATA[
this._progress.value = val;
if (val == this._progress.max)
this.setAttribute("complete", true);
else
this.removeAttribute("complete");
]]></setter>
</property>
<property name="maxProgress">
<getter><![CDATA[
return this._progress.max;
]]></getter>
<setter><![CDATA[
if (val == -1) {
this._progress.mode = "undetermined";
} else {
this._progress.mode = "determined";
this._progress.max = val;
}
this.setAttribute("mode", this._progress.mode);
]]></setter>
</property>
<property name="status">
<getter><![CDATA[
return this._status.value;
]]></getter>
<setter><![CDATA[
this._status.value = val;
]]></setter>
</property>
</implementation>
</binding>
<!-- Sorters - displays and controls the sort state of a list. -->
<binding id="sorters">
<content orient="horizontal">
<xul:button anonid="name-btn" class="sorter"
label="&sort.name.label;" tooltiptext="&sort.name.tooltip;"
oncommand="this.parentNode._handleChange('name');"/>
<xul:button anonid="date-btn" class="sorter"
label="&sort.dateUpdated.label;"
tooltiptext="&sort.dateUpdated.tooltip;"
oncommand="this.parentNode._handleChange('updateDate');"/>
<xul:button anonid="price-btn" class="sorter" hidden="true"
label="&sort.price.label;"
tooltiptext="&sort.price.tooltip;"
oncommand="this.parentNode._handleChange('purchaseAmount');"/>
<xul:button anonid="relevance-btn" class="sorter" hidden="true"
label="&sort.relevance.label;"
tooltiptext="&sort.relevance.tooltip;"
oncommand="this.parentNode._handleChange('relevancescore');"/>
</content>
<implementation>
<constructor><![CDATA[
if (!this.hasAttribute("sortby"))
this.setAttribute("sortby", "name");
if (this.getAttribute("showrelevance") == "true")
this._btnRelevance.hidden = false;
if (this.getAttribute("showprice") == "true")
this._btnPrice.hidden = false;
this._refreshState();
]]></constructor>
<field name="handler">null</field>
<field name="_btnName">
document.getAnonymousElementByAttribute(this, "anonid", "name-btn");
</field>
<field name="_btnDate">
document.getAnonymousElementByAttribute(this, "anonid", "date-btn");
</field>
<field name="_btnPrice">
document.getAnonymousElementByAttribute(this, "anonid", "price-btn");
</field>
<field name="_btnRelevance">
document.getAnonymousElementByAttribute(this, "anonid", "relevance-btn");
</field>
<property name="sortBy">
<getter><![CDATA[
return this.getAttribute("sortby");
]]></getter>
<setter><![CDATA[
if (val != this.sortBy) {
this.setAttribute("sortBy", val);
this._refreshState();
}
]]></setter>
</property>
<property name="ascending">
<getter><![CDATA[
return (this.getAttribute("ascending") == "true");
]]></getter>
<setter><![CDATA[
val = !!val;
if (val != this.ascending) {
this.setAttribute("ascending", val);
this._refreshState();
}
]]></setter>
</property>
<property name="showrelevance">
<getter><![CDATA[
return (this.getAttribute("showrelevance") == "true");
]]></getter>
<setter><![CDATA[
val = !!val;
this.setAttribute("showrelevance", val);
this._btnRelevance.hidden = !val;
]]></setter>
</property>
<property name="showprice">
<getter><![CDATA[
return (this.getAttribute("showprice") == "true");
]]></getter>
<setter><![CDATA[
val = !!val;
this.setAttribute("showprice", val);
this._btnPrice.hidden = !val;
]]></setter>
</property>
<method name="setSort">
<parameter name="aSort"/>
<parameter name="aAscending"/>
<body><![CDATA[
var sortChanged = false;
if (aSort != this.sortBy) {
this.setAttribute("sortby", aSort);
sortChanged = true;
}
aAscending = !!aAscending;
if (this.ascending != aAscending) {
this.setAttribute("ascending", aAscending);
sortChanged = true;
}
if (sortChanged)
this._refreshState();
]]></body>
</method>
<method name="_handleChange">
<parameter name="aSort"/>
<body><![CDATA[
const ASCENDING_SORT_FIELDS = ["name", "purchaseAmount"];
// Toggle ascending if sort by is not changing, otherwise
// name sorting defaults to ascending, others to descending
if (aSort == this.sortBy)
this.ascending = !this.ascending;
else
this.setSort(aSort, ASCENDING_SORT_FIELDS.indexOf(aSort) >= 0);
]]></body>
</method>
<method name="_refreshState">
<body><![CDATA[
var sortBy = this.sortBy;
var checkState = this.ascending ? 2 : 1;
if (sortBy == "name") {
this._btnName.checkState = checkState;
this._btnName.checked = true;
} else {
this._btnName.checkState = 0;
this._btnName.checked = false;
}
if (sortBy == "updateDate") {
this._btnDate.checkState = checkState;
this._btnDate.checked = true;
} else {
this._btnDate.checkState = 0;
this._btnDate.checked = false;
}
if (sortBy == "purchaseAmount") {
this._btnPrice.checkState = checkState;
this._btnPrice.checked = true;
} else {
this._btnPrice.checkState = 0;
this._btnPrice.checked = false;
}
if (sortBy == "relevancescore") {
this._btnRelevance.checkState = checkState;
this._btnRelevance.checked = true;
} else {
this._btnRelevance.checkState = 0;
this._btnRelevance.checked = false;
}
if (this.handler && "onSortChanged" in this.handler)
this.handler.onSortChanged(sortBy, this.ascending);
]]></body>
</method>
</implementation>
</binding>
<!-- Categories list - displays the list of categories on the left pane. -->
<binding id="categories-list"
extends="chrome://global/content/bindings/richlistbox.xml#richlistbox">
<implementation>
<!-- This needs to be overridden to allow the fancy animation while not
allowing that item to be selected when hiding. -->
<method name="_canUserSelect">
<parameter name="aItem"/>
<body>
<![CDATA[
if (aItem.hasAttribute("disabled") &&
aItem.getAttribute("disabled") == "true")
return false;
var style = document.defaultView.getComputedStyle(aItem, "");
return style.display != "none" && style.visibility == "visible";
]]>
</body>
</method>
</implementation>
</binding>
<!-- Category item - an item in the category list. -->
<binding id="category"
extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<content align="center">
<xul:image anonid="icon" class="category-icon"/>
<xul:label anonid="name" class="category-name" flex="1" xbl:inherits="value=name"/>
<xul:label anonid="badge" class="category-badge" xbl:inherits="value=count"/>
</content>
<implementation>
<constructor><![CDATA[
if (!this.hasAttribute("count"))
this.setAttribute("count", 0);
]]></constructor>
<property name="badgeCount">
<getter><![CDATA[
return this.getAttribute("count");
]]></getter>
<setter><![CDATA[
if (this.getAttribute("count") == val)
return;
this.setAttribute("count", val);
var event = document.createEvent("Events");
event.initEvent("CategoryBadgeUpdated", true, true);
this.dispatchEvent(event);
]]></setter>
</property>
</implementation>
</binding>
<!-- Creator link - Name of a user/developer, providing a link if relevant. -->
<binding id="creator-link">
<content>
<xul:label anonid="label" value="&addon.createdBy.label;"/>
<xul:label anonid="creator-link" class="creator-link text-link"/>
<xul:label anonid="creator-name" class="creator-name"/>
</content>
<implementation>
<constructor><![CDATA[
if (this.hasAttribute("nameonly") &&
this.getAttribute("nameonly") == "true") {
this._label.hidden = true;
}
]]></constructor>
<field name="_label">
document.getAnonymousElementByAttribute(this, "anonid", "label");
</field>
<field name="_creatorLink">
document.getAnonymousElementByAttribute(this, "anonid", "creator-link");
</field>
<field name="_creatorName">
document.getAnonymousElementByAttribute(this, "anonid", "creator-name");
</field>
<method name="setCreator">
<parameter name="aCreator"/>
<parameter name="aHomepageURL"/>
<body><![CDATA[
if (!aCreator) {
this.collapsed = true;
return;
}
this.collapsed = false;
var url = aCreator.url || aHomepageURL;
var showLink = !!url;
if (showLink) {
this._creatorLink.value = aCreator.name;
this._creatorLink.href = url;
} else {
this._creatorName.value = aCreator.name;
}
this._creatorLink.hidden = !showLink;
this._creatorName.hidden = showLink;
]]></body>
</method>
</implementation>
</binding>
<!-- Install status - Displays the status of an install/upgrade. -->
<binding id="install-status">
<content>
<xul:label anonid="message"/>
<xul:progressmeter anonid="progress" class="download-progress"/>
<xul:button anonid="purchase-remote-btn" hidden="true"
class="addon-control"
oncommand="document.getBindingParent(this).purchaseRemote();"/>
<xul:button anonid="install-remote-btn" hidden="true"
class="addon-control install" label="&addon.install.label;"
tooltiptext="&addon.install.tooltip;"
oncommand="document.getBindingParent(this).installRemote();"/>
</content>
<implementation>
<constructor><![CDATA[
if (this.mInstall)
this.initWithInstall(this.mInstall);
else if (this.mControl.mAddon.install)
this.initWithInstall(this.mControl.mAddon.install);
else
this.refreshState();
]]></constructor>
<destructor><![CDATA[
if (this.mInstall)
this.mInstall.removeListener(this);
]]></destructor>
<field name="_message">
document.getAnonymousElementByAttribute(this, "anonid", "message");
</field>
<field name="_progress">
document.getAnonymousElementByAttribute(this, "anonid", "progress");
</field>
<field name="_purchaseRemote">
document.getAnonymousElementByAttribute(this, "anonid",
"purchase-remote-btn");
</field>
<field name="_installRemote">
document.getAnonymousElementByAttribute(this, "anonid",
"install-remote-btn");
</field>
<field name="_restartNeeded">
document.getAnonymousElementByAttribute(this, "anonid",
"restart-needed");
</field>
<field name="_undo">
document.getAnonymousElementByAttribute(this, "anonid",
"undo-btn");
</field>
<method name="initWithInstall">
<parameter name="aInstall"/>
<body><![CDATA[
if (this.mInstall) {
this.mInstall.removeListener(this);
this.mInstall = null;
}
this.mInstall = aInstall;
this.refreshState();
this.mInstall.addListener(this);
]]></body>
</method>
<method name="refreshState">
<body><![CDATA[
var showInstallRemote = false;
var showPurchase = false;
if (this.mInstall) {
switch (this.mInstall.state) {
case AddonManager.STATE_AVAILABLE:
if (this.mControl.getAttribute("remote") != "true")
break;
this._progress.hidden = true;
showInstallRemote = true;
break;
case AddonManager.STATE_DOWNLOADING:
this.showMessage("installDownloading");
break;
case AddonManager.STATE_CHECKING:
this.showMessage("installVerifying");
break;
case AddonManager.STATE_DOWNLOADED:
this.showMessage("installDownloaded");
break;
case AddonManager.STATE_DOWNLOAD_FAILED:
// XXXunf expose what error occured (bug 553487)
this.showMessage("installDownloadFailed", true);
break;
case AddonManager.STATE_INSTALLING:
this.showMessage("installInstalling");
break;
case AddonManager.STATE_INSTALL_FAILED:
// XXXunf expose what error occured (bug 553487)
this.showMessage("installFailed", true);
break;
case AddonManager.STATE_CANCELLED:
this.showMessage("installCancelled", true);
break;
}
} else if (this.mControl.mAddon.purchaseURL) {
this._progress.hidden = true;
showPurchase = true;
this._purchaseRemote.label =
gStrings.ext.formatStringFromName("addon.purchase.label",
[this.mControl.mAddon.purchaseDisplayAmount], 1);
this._purchaseRemote.tooltiptext =
gStrings.ext.GetStringFromName("addon.purchase.tooltip");
}
this._purchaseRemote.hidden = !showPurchase;
this._installRemote.hidden = !showInstallRemote;
if ("refreshInfo" in this.mControl)
this.mControl.refreshInfo();
]]></body>
</method>
<method name="showMessage">
<parameter name="aMsgId"/>
<parameter name="aHideProgress"/>
<body><![CDATA[
this._message.setAttribute("hidden", !aHideProgress);
this._progress.setAttribute("hidden", !!aHideProgress);
var msg = gStrings.ext.GetStringFromName(aMsgId);
if (aHideProgress)
this._message.value = msg;
else
this._progress.status = msg;
]]></body>
</method>
<method name="purchaseRemote">
<body><![CDATA[
openURL(this.mControl.mAddon.purchaseURL);
]]></body>
</method>
<method name="installRemote">
<body><![CDATA[
if (this.mControl.getAttribute("remote") != "true")
return;
if (this.mControl.mAddon.eula) {
var data = {
addon: this.mControl.mAddon,
accepted: false
};
window.openDialog("chrome://mozapps/content/extensions/eula.xul", "_blank",
"chrome,dialog,modal,centerscreen,resizable=no", data);
if (!data.accepted)
return;
}
delete this.mControl.mAddon;
this.mControl.mInstall = this.mInstall;
this.mControl.setAttribute("status", "installing");
this.mInstall.install();
]]></body>
</method>
<method name="undoAction">
<body><![CDATA[
if (!this.mAddon)
return;
var pending = this.mAddon.pendingOperations;
if (pending & AddonManager.PENDING_ENABLE)
this.mAddon.userDisabled = true;
else if (pending & AddonManager.PENDING_DISABLE)
this.mAddon.userDisabled = false;
this.refreshState();
]]></body>
</method>
<method name="onDownloadStarted">
<body><![CDATA[
this.refreshState();
]]></body>
</method>
<method name="onDownloadEnded">
<body><![CDATA[
this.refreshState();
]]></body>
</method>
<method name="onDownloadFailed">
<body><![CDATA[
this.refreshState();
]]></body>
</method>
<method name="onDownloadProgress">
<body><![CDATA[
this._progress.maxProgress = this.mInstall.maxProgress;
this._progress.progress = this.mInstall.progress;
]]></body>
</method>
<method name="onInstallStarted">
<body><![CDATA[
this._progress.progress = 0;
this.refreshState();
]]></body>
</method>
<method name="onInstallEnded">
<body><![CDATA[
this.refreshState();
if ("onInstallCompleted" in this.mControl)
this.mControl.onInstallCompleted();
]]></body>
</method>
<method name="onInstallFailed">
<body><![CDATA[
this.refreshState();
]]></body>
</method>
</implementation>
</binding>
<!-- Addon - base - parent binding of any item representing an addon. -->
<binding id="addon-base"
extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<implementation>
<method name="hasPermission">
<parameter name="aPerm"/>
<body><![CDATA[
var perm = AddonManager["PERM_CAN_" + aPerm.toUpperCase()];
return !!(this.mAddon.permissions & perm);
]]></body>
</method>
<method name="opRequiresRestart">
<parameter name="aOperation"/>
<body><![CDATA[
var operation = AddonManager["OP_NEEDS_RESTART_" + aOperation.toUpperCase()];
return !!(this.mAddon.operationsRequiringRestart & operation);
]]></body>
</method>
<method name="isPending">
<parameter name="aAction"/>
<body><![CDATA[
var action = AddonManager["PENDING_" + aAction.toUpperCase()];
return !!(this.mAddon.pendingOperations & action);
]]></body>
</method>
<method name="onUninstalled">
<body><![CDATA[
this.parentNode.removeChild(this);
]]></body>
</method>
</implementation>
</binding>
<!-- Addon - generic - A normal addon item, or an update to one -->
<binding id="addon-generic"
extends="chrome://mozapps/content/extensions/extensions.xml#addon-base">
<content>
<xul:hbox anonid="warning-container" align="center"
class="warning">
<xul:image class="warning-icon"/>
<xul:label anonid="warning" flex="1"/>
<xul:label anonid="warning-link" class="text-link"/>
<xul:button anonid="warning-btn" class="button-link"/>
<xul:spacer flex="5000"/> <!-- Necessary to allow the message to wrap -->
</xul:hbox>
<xul:hbox anonid="error-container" align="center"
class="error">
<xul:image class="error-icon"/>
<xul:label anonid="error" flex="1"/>
<xul:label anonid="error-link" class="text-link"/>
<xul:spacer flex="5000"/> <!-- Necessary to allow the message to wrap -->
</xul:hbox>
<xul:hbox anonid="pending-container" align="center"
class="pending">
<xul:image class="pending-icon"/>
<xul:label anonid="pending" flex="1"/>
<xul:button anonid="restart-btn" class="button-link"
label="&addon.restartNow.label;"
oncommand="document.getBindingParent(this).restart();"/>
<xul:button anonid="undo-btn" class="button-link"
label="&addon.undoAction.label;"
tooltipText="&addon.undoAction.tooltip;"
oncommand="document.getBindingParent(this).undo();"/>
<xul:spacer flex="5000"/> <!-- Necessary to allow the message to wrap -->
</xul:hbox>
<xul:hbox>
<xul:vbox align="center" pack="start" class="icon-container">
<xul:image anonid="icon" class="icon"/>
</xul:vbox>
<xul:vbox flex="1">
<xul:hbox align="start">
<xul:vbox flex="1">
<xul:hbox class="name-container" align="end">
<xul:label anonid="name" class="name" crop="end" flex="1"
xbl:inherits="value=name,tooltiptext=name"/>
<xul:label anonid="version" class="version"/>
<xul:label class="disabled-postfix" value="&addon.disabled.postfix;"/>
<xul:label class="update-postfix" value="&addon.update.postfix;"/>
<xul:spacer flex="5000"/> <!-- Necessary to make the name crop -->
</xul:hbox>
<xul:label anonid="creator" class="creator"/>
</xul:vbox>
<xul:label anonid="date-updated" class="date-updated"
unknown="&addon.unknownDate;"/>
</xul:hbox>
<xul:hbox flex="1" align="end">
<xul:vbox flex="1">
<xul:hbox align="center" class="description-container">
<xul:label flex="1" anonid="description" class="description" crop="end"/>
<xul:button anonid="details-btn" class="details button-link"
label="&addon.details.label;"
tooltiptext="&addon.details.tooltip;"
oncommand="document.getBindingParent(this).showInDetailView();"/>
<xul:spacer flex="5000"/> <!-- Necessary to make the description crop -->
</xul:hbox>
<xul:vbox anonid="relnotes-container" class="relnotes-container">
<xul:label class="relnotes-header" value="&addon.releaseNotes.label;"/>
<xul:label anonid="relnotes-loading" value="&addon.loadingReleaseNotes.label;"/>
<xul:label anonid="relnotes-error" hidden="true"
value="&addon.errorLoadingReleaseNotes.label;"/>
<xul:vbox anonid="relnotes" class="relnotes"/>
</xul:vbox>
<xul:hbox pack="start">
<xul:button anonid="relnotes-toggle-btn" class="relnotes-toggle"
hidden="true" label="&cmd.showReleaseNotes.label;"
tooltiptext="&cmd.showReleaseNotes.tooltip;"
showlabel="&cmd.showReleaseNotes.label;"
showtooltip="&cmd.showReleaseNotes.tooltip;"
hidelabel="&cmd.hideReleaseNotes.label;"
hidetooltip="&cmd.hideReleaseNotes.tooltip;"
oncommand="document.getBindingParent(this).toggleReleaseNotes();"/>
</xul:hbox>
</xul:vbox>
<xul:vbox>
<xul:hbox class="status-container" pack="end">
<xul:hbox anonid="checking-update" hidden="true">
<xul:image class="spinner"/>
<xul:label value="&addon.checkingForUpdates.label;"/>
</xul:hbox>
<xul:vbox anonid="update-available" class="update-available"
hidden="true" align="end">
<xul:checkbox anonid="include-update" class="include-update"
label="&addon.includeUpdate.label;" checked="true"
oncommand="document.getBindingParent(this).onIncludeUpdateChanged();"/>
<xul:hbox align="center">
<xul:label class="update-available-notice"
value="&addon.updateAvailable.label;"/>
<xul:button anonid="update-btn" class="addon-control update"
label="&addon.updateNow.label;"
tooltiptext="&addon.updateNow.tooltip;"
oncommand="document.getBindingParent(this).upgrade();"/>
</xul:hbox>
</xul:vbox>
<xul:hbox anonid="install-status" class="install-status"
hidden="true"/>
</xul:hbox>
<xul:hbox anonid="control-container" class="control-container"
pack="end">
<xul:button anonid="preferences-btn"
class="addon-control preferences"
#ifdef XP_WIN
label="&cmd.showPreferencesWin.label;"
tooltiptext="&cmd.showPreferencesWin.tooltip;"
#else
label="&cmd.showPreferencesUnix.label;"
tooltiptext="&cmd.showPreferencesUnix.tooltip;"
#endif
oncommand="document.getBindingParent(this).showPreferences();"/>
<xul:button anonid="enable-btn" class="addon-control enable"
label="&cmd.enableAddon.label;"
oncommand="document.getBindingParent(this).userDisabled = false;"/>
<xul:button anonid="disable-btn" class="addon-control disable"
label="&cmd.disableAddon.label;"
oncommand="document.getBindingParent(this).userDisabled = true;"/>
<xul:button anonid="remove-btn" class="addon-control remove"
label="&cmd.uninstallAddon.label;"
oncommand="document.getBindingParent(this).uninstall();"/>
</xul:hbox>
</xul:vbox>
</xul:hbox>
</xul:vbox>
</xul:hbox>
</content>
<implementation>
<constructor><![CDATA[
this._installStatus.mControl = this;
this.setAttribute("contextmenu", "addonitem-popup");
this._showStatus("none");
this._initWithAddon(this.mAddon);
gEventManager.registerAddonListener(this, this.mAddon.id);
]]></constructor>
<destructor><![CDATA[
gEventManager.unregisterAddonListener(this, this.mAddon.id);
]]></destructor>
<field name="_warningContainer">
document.getAnonymousElementByAttribute(this, "anonid",
"warning-container");
</field>
<field name="_warning">
document.getAnonymousElementByAttribute(this, "anonid",
"warning");
</field>
<field name="_warningLink">
document.getAnonymousElementByAttribute(this, "anonid",
"warning-link");
</field>
<field name="_warningBtn">
document.getAnonymousElementByAttribute(this, "anonid",
"warning-btn");
</field>
<field name="_errorContainer">
document.getAnonymousElementByAttribute(this, "anonid",
"error-container");
</field>
<field name="_error">
document.getAnonymousElementByAttribute(this, "anonid",
"error");
</field>
<field name="_errorLink">
document.getAnonymousElementByAttribute(this, "anonid",
"error-link");
</field>
<field name="_pendingContainer">
document.getAnonymousElementByAttribute(this, "anonid",
"pending-container");
</field>
<field name="_pending">
document.getAnonymousElementByAttribute(this, "anonid",
"pending");
</field>
<field name="_infoContainer">
document.getAnonymousElementByAttribute(this, "anonid",
"info-container");
</field>
<field name="_info">
document.getAnonymousElementByAttribute(this, "anonid",
"info");
</field>
<field name="_creator">
document.getAnonymousElementByAttribute(this, "anonid",
"creator");
</field>
<field name="_version">
document.getAnonymousElementByAttribute(this, "anonid", "version");
</field>
<field name="_icon">
document.getAnonymousElementByAttribute(this, "anonid", "icon");
</field>
<field name="_dateUpdated">
document.getAnonymousElementByAttribute(this, "anonid",
"date-updated");
</field>
<field name="_description">
document.getAnonymousElementByAttribute(this, "anonid",
"description");
</field>
<field name="_preferencesBtn">
document.getAnonymousElementByAttribute(this, "anonid",
"preferences-btn");
</field>
<field name="_enableBtn">
document.getAnonymousElementByAttribute(this, "anonid",
"enable-btn");
</field>
<field name="_disableBtn">
document.getAnonymousElementByAttribute(this, "anonid",
"disable-btn");
</field>
<field name="_removeBtn">
document.getAnonymousElementByAttribute(this, "anonid",
"remove-btn");
</field>
<field name="_updateBtn">
document.getAnonymousElementByAttribute(this, "anonid",
"update-btn");
</field>
<field name="_controlContainer">
document.getAnonymousElementByAttribute(this, "anonid",
"control-container");
</field>
<field name="_installStatus">
document.getAnonymousElementByAttribute(this, "anonid",
"install-status");
</field>
<field name="_checkingUpdate">
document.getAnonymousElementByAttribute(this, "anonid",
"checking-update");
</field>
<field name="_updateAvailable">
document.getAnonymousElementByAttribute(this, "anonid",
"update-available");
</field>
<field name="_includeUpdate">
document.getAnonymousElementByAttribute(this, "anonid",
"include-update");
</field>
<field name="_relNotesLoaded">false</field>
<field name="_relNotesToggle">
document.getAnonymousElementByAttribute(this, "anonid",
"relnotes-toggle-btn");
</field>
<field name="_relNotesLoading">
document.getAnonymousElementByAttribute(this, "anonid",
"relnotes-loading");
</field>
<field name="_relNotesError">
document.getAnonymousElementByAttribute(this, "anonid",
"relnotes-error");
</field>
<field name="_relNotesContainer">
document.getAnonymousElementByAttribute(this, "anonid",
"relnotes-container");
</field>
<field name="_relNotes">
document.getAnonymousElementByAttribute(this, "anonid",
"relnotes");
</field>
<property name="userDisabled">
<getter><![CDATA[
return this.mAddon.userDisabled;
]]></getter>
<setter><![CDATA[
this.mAddon.userDisabled = val;
]]></setter>
</property>
<property name="includeUpdate">
<getter><![CDATA[
return this._includeUpdate.checked && !!this.mManualUpdate;
]]></getter>
<setter><![CDATA[
//XXXunf Eventually, we'll want to persist this for individual
// updates - see bug 594619.
this._includeUpdate.checked = !!val;
]]></setter>
</property>
<method name="_initWithAddon">
<parameter name="aAddon"/>
<body><![CDATA[
this.mAddon = aAddon;
this._installStatus.mAddon = this.mAddon;
this._updateDates();
this._updateState();
this.setAttribute("name", aAddon.name);
var iconURL = this.mAddon.iconURL;
if (iconURL)
this._icon.src = iconURL;
else
this._icon.src = null;
if (this.mAddon.version)
this._version.value = this.mAddon.version;
else
this._version.hidden = true;
this._creator.setCreator(this.mAddon.creator);
if (this.mAddon.description)
this._description.value = this.mAddon.description;
else
this._description.hidden = true;
if (!("applyBackgroundUpdates" in this.mAddon) ||
(this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DISABLE ||
(this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DEFAULT &&
!AddonManager.autoUpdateDefault))) {
var self = this;
AddonManager.getAllInstalls(function(aInstallsList) {
// This can return after the binding has been destroyed,
// so try to detect that and return early
if (!("onNewInstall" in self))
return;
for (let i = 0; i < aInstallsList.length; i++) {
let install = aInstallsList[i];
if (install.existingAddon &&
install.existingAddon.id == self.mAddon.id &&
install.state == AddonManager.STATE_AVAILABLE) {
self.onNewInstall(install);
self.onIncludeUpdateChanged();
}
}
});
}
]]></body>
</method>
<method name="_showStatus">
<parameter name="aType"/>
<body><![CDATA[
this._controlContainer.hidden = aType != "none" &&
!(aType == "update-available" && !this.hasAttribute("upgrade"));
this._installStatus.hidden = aType != "progress";
if (aType == "progress")
this._installStatus.refreshState();
this._checkingUpdate.hidden = aType != "checking-update";
this._updateAvailable.hidden = aType != "update-available";
this._relNotesToggle.hidden = !(this.mManualUpdate ?
this.mManualUpdate.releaseNotesURI :
this.mAddon.releaseNotesURI);
]]></body>
</method>
<method name="_updateDates">
<body><![CDATA[
function formatDate(aDate) {
return Cc["@mozilla.org/intl/scriptabledateformat;1"]
.getService(Ci.nsIScriptableDateFormat)
.FormatDate("",
Ci.nsIScriptableDateFormat.dateFormatLong,
aDate.getFullYear(),
aDate.getMonth() + 1,
aDate.getDate()
);
}
if (this.mAddon.updateDate)
this._dateUpdated.value = formatDate(this.mAddon.updateDate);
else
this._dateUpdated.value = this._dateUpdated.getAttribute("unknown");
]]></body>
</method>
<method name="_updateState">
<body><![CDATA[
var pending = this.mAddon.pendingOperations;
if (pending != AddonManager.PENDING_NONE) {
this.removeAttribute("notification");
var pending = null;
["enable", "disable", "install", "uninstall", "upgrade"].forEach(function(aOp) {
if (this.isPending(aOp))
pending = aOp;
}, this);
this.setAttribute("pending", pending);
this._pending.textContent = gStrings.ext.formatStringFromName(
"notification." + pending,
[this.mAddon.name, gStrings.brandShortName], 2
);
} else {
this.removeAttribute("pending");
var isUpgrade = this.hasAttribute("upgrade");
var install = this._installStatus.mInstall;
if (install && install.state == AddonManager.STATE_DOWNLOAD_FAILED) {
this.setAttribute("notification", "warning");
this._warning.textContent = gStrings.ext.formatStringFromName(
"notification.downloadError",
[this.mAddon.name], 1
);
this._warningBtn.label = gStrings.ext.GetStringFromName("notification.downloadError.retry");
this._warningBtn.tooltipText = gStrings.ext.GetStringFromName("notification.downloadError.retry.tooltip");
this._warningBtn.setAttribute("oncommand", "document.getBindingParent(this).retryInstall();");
this._warningBtn.hidden = false;
this._warningLink.hidden = true;
} else if (install && install.state == AddonManager.STATE_INSTALL_FAILED) {
this.setAttribute("notification", "warning");
this._warning.textContent = gStrings.ext.formatStringFromName(
"notification.installError",
[this.mAddon.name], 1
);
this._warningBtn.label = gStrings.ext.GetStringFromName("notification.installError.retry");
this._warningBtn.tooltipText = gStrings.ext.GetStringFromName("notification.downloadError.retry.tooltip");
this._warningBtn.setAttribute("oncommand", "document.getBindingParent(this).retryInstall();");
this._warningBtn.hidden = false;
this._warningLink.hidden = true;
} else if (!isUpgrade && this.mAddon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED) {
this.setAttribute("notification", "error");
this._error.textContent = gStrings.ext.formatStringFromName(
"notification.blocked",
[this.mAddon.name], 1
);
this._errorLink.value = gStrings.ext.GetStringFromName("notification.blocked.link");
this._errorLink.href = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL");
this._errorLink.hidden = false;
} else if (!isUpgrade && !this.mAddon.isCompatible) {
this.setAttribute("notification", "warning");
this._warning.textContent = gStrings.ext.formatStringFromName(
"notification.incompatible",
[this.mAddon.name, gStrings.brandShortName, gStrings.appVersion], 3
);
this._warningLink.hidden = true;
this._warningBtn.hidden = true;
} else if (!isUpgrade && this.mAddon.blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED) {
this.setAttribute("notification", "warning");
this._warning.textContent = gStrings.ext.formatStringFromName(
"notification.softblocked",
[this.mAddon.name], 1
);
this._warningLink.value = gStrings.ext.GetStringFromName("notification.softblocked.link");
this._warningLink.href = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL");
this._warningLink.hidden = false;
this._warningBtn.hidden = true;
} else if (!isUpgrade && this.mAddon.blocklistState == Ci.nsIBlocklistService.STATE_OUTDATED) {
this.setAttribute("notification", "warning");
this._warning.textContent = gStrings.ext.formatStringFromName(
"notification.outdated",
[this.mAddon.name], 1
);
this._warningLink.value = gStrings.ext.GetStringFromName("notification.outdated.link");
this._warningLink.href = Services.urlFormatter.formatURLPref("plugins.update.url");
this._warningLink.hidden = false;
this._warningBtn.hidden = true;
} else {
this.removeAttribute("notification");
}
}
this._preferencesBtn.hidden = !this.mAddon.optionsURL;
if (this.hasPermission("enable")) {
this._enableBtn.hidden = false;
let tooltip = gViewController.commands["cmd_enableItem"]
.getTooltip(this.mAddon);
this._enableBtn.setAttribute("tooltiptext", tooltip);
} else {
this._enableBtn.hidden = true;
}
if (this.hasPermission("disable")) {
this._disableBtn.hidden = false;
let tooltip = gViewController.commands["cmd_disableItem"]
.getTooltip(this.mAddon);
this._disableBtn.setAttribute("tooltiptext", tooltip);
} else {
this._disableBtn.hidden = true;
}
if (this.hasPermission("uninstall")) {
this._removeBtn.hidden = false;
let tooltip = gViewController.commands["cmd_uninstallItem"]
.getTooltip(this.mAddon);
this._removeBtn.setAttribute("tooltiptext", tooltip);
} else {
this._removeBtn.hidden = true;
}
this.setAttribute("active", this.mAddon.isActive);
var showProgress = this.mAddon.purchaseURL || (this.mAddon.install &&
this.mAddon.install.state != AddonManager.STATE_INSTALLED);
this._showStatus(showProgress ? "progress" : "none");
]]></body>
</method>
<method name="_updateUpgradeInfo">
<body><![CDATA[
// Only update the version string if we're displaying the upgrade info
if (this.hasAttribute("upgrade"))
this._version.value = this.mManualUpdate.version;
]]></body>
</method>
<method name="_fetchReleaseNotes">
<parameter name="aURI"/>
<body><![CDATA[
var self = this;
if (!aURI || this._relNotesLoaded) {
sendToggleEvent();
return;
}
var relNotesData = null, transformData = null;
this._relNotesLoaded = true;
this._relNotesLoading.hidden = false;
this._relNotesError.hidden = true;
function sendToggleEvent() {
var event = document.createEvent("Events");
event.initEvent("RelNotesToggle", true, true);
self.dispatchEvent(event);
}
function showRelNotes() {
if (!relNotesData || !transformData)
return;
self._relNotesLoading.hidden = true;
var processor = Components.classes["@mozilla.org/document-transformer;1?type=xslt"]
.createInstance(Components.interfaces.nsIXSLTProcessor);
processor.flags |= Components.interfaces.nsIXSLTProcessorPrivate.DISABLE_ALL_LOADS;
processor.importStylesheet(transformData);
var fragment = processor.transformToFragment(relNotesData, document);
self._relNotes.appendChild(fragment);
if (self.hasAttribute("show-relnotes")) {
var container = self._relNotesContainer;
container.style.height = container.scrollHeight + "px";
}
sendToggleEvent();
}
function handleError() {
dataReq.abort();
styleReq.abort();
self._relNotesLoading.hidden = true;
self._relNotesError.hidden = false;
self._relNotesLoaded = false; // allow loading to be re-tried
sendToggleEvent();
}
function handleResponse(aEvent) {
var req = aEvent.target;
if (req.responseXML &&
req.responseXML.documentElement.namespaceURI != XMLURI_PARSE_ERROR) {
if (req == dataReq)
relNotesData = req.responseXML;
else
transformData = req.responseXML;
showRelNotes();
} else {
handleError();
}
}
var dataReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
dataReq.open("GET", aURI.spec, true);
dataReq.addEventListener("load", handleResponse, false);
dataReq.addEventListener("error", handleError, false);
dataReq.send(null);
var styleReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
styleReq.open("GET", UPDATES_RELEASENOTES_TRANSFORMFILE, true);
styleReq.addEventListener("load", handleResponse, false);
styleReq.addEventListener("error", handleError, false);
styleReq.send(null);
]]></body>
</method>
<method name="toggleReleaseNotes">
<body><![CDATA[
if (this.hasAttribute("show-relnotes")) {
this._relNotesContainer.style.height = "0px";
this.removeAttribute("show-relnotes");
this._relNotesToggle.setAttribute(
"label",
this._relNotesToggle.getAttribute("showlabel")
);
this._relNotesToggle.setAttribute(
"tooltiptext",
this._relNotesToggle.getAttribute("showtooltip")
);
var event = document.createEvent("Events");
event.initEvent("RelNotesToggle", true, true);
this.dispatchEvent(event);
} else {
this._relNotesContainer.style.height = this._relNotesContainer.scrollHeight +
"px";
this.setAttribute("show-relnotes", true);
this._relNotesToggle.setAttribute(
"label",
this._relNotesToggle.getAttribute("hidelabel")
);
this._relNotesToggle.setAttribute(
"tooltiptext",
this._relNotesToggle.getAttribute("hidetooltip")
);
var uri = this.mManualUpdate ?
this.mManualUpdate.releaseNotesURI :
this.mAddon.releaseNotesURI;
this._fetchReleaseNotes(uri);
}
]]></body>
</method>
<method name="restart">
<body><![CDATA[
gViewController.commands["cmd_restartApp"].doCommand();
]]></body>
</method>
<method name="undo">
<body><![CDATA[
gViewController.commands["cmd_cancelOperation"].doCommand(this.mAddon);
]]></body>
</method>
<method name="uninstall">
<body><![CDATA[
// If uninstalling does not require a restart then just disable it
// and show the undo UI.
if (!this.opRequiresRestart("uninstall")) {
this.setAttribute("wasDisabled", this.mAddon.userDisabled);
// We must set userDisabled to true first, this will call
// _updateState which will clear any pending attribute set.
this.mAddon.userDisabled = true;
// This won't update any other add-on manager views (bug 582002)
this.setAttribute("pending", "uninstall");
} else {
this.mAddon.uninstall();
}
]]></body>
</method>
<method name="showPreferences">
<body><![CDATA[
gViewController.doCommand("cmd_showItemPreferences", this.mAddon);
]]></body>
</method>
<method name="upgrade">
<body><![CDATA[
var install = this.mManualUpdate;
delete this.mManualUpdate;
install.install();
]]></body>
</method>
<method name="retryInstall">
<body><![CDATA[
var install = this._installStatus.mInstall;
if (!install)
return;
if (install.state != AddonManager.STATE_DOWNLOAD_FAILED &&
install.state != AddonManager.STATE_INSTALL_FAILED)
return;
install.install();
]]></body>
</method>
<method name="showInDetailView">
<body><![CDATA[
gViewController.loadView("addons://detail/" +
encodeURIComponent(this.mAddon.id));
]]></body>
</method>
<method name="onIncludeUpdateChanged">
<body><![CDATA[
var event = document.createEvent("Events");
event.initEvent("IncludeUpdateChanged", true, true);
this.dispatchEvent(event);
]]></body>
</method>
<method name="onEnabling">
<body><![CDATA[
this._updateState();
]]></body>
</method>
<method name="onEnabled">
<body><![CDATA[
this._updateState();
]]></body>
</method>
<method name="onDisabling">
<body><![CDATA[
this._updateState();
]]></body>
</method>
<method name="onDisabled">
<body><![CDATA[
this._updateState();
]]></body>
</method>
<method name="onUninstalling">
<parameter name="aRestartRequired"/>
<body><![CDATA[
this._updateState();
]]></body>
</method>
<method name="onOperationCancelled">
<body><![CDATA[
this._updateState();
]]></body>
</method>
<method name="onNoUpdateAvailable">
<body><![CDATA[
this._showStatus("none");
]]></body>
</method>
<method name="onCheckingUpdate">
<body><![CDATA[
this._showStatus("checking-update");
]]></body>
</method>
<method name="onCompatibilityUpdateAvailable">
<body><![CDATA[
this._updateState();
]]></body>
</method>
<method name="onExternalInstall">
<parameter name="aAddon"/>
<parameter name="aExistingAddon"/>
<parameter name="aNeedsRestart"/>
<body><![CDATA[
if (aExistingAddon.id != this.mAddon.id)
return;
// If the install completed without needing a restart then switch to
// using the new Addon
if (!aNeedsRestart)
this._initWithAddon(aAddon);
else
this._updateState();
]]></body>
</method>
<method name="onNewInstall">
<parameter name="aInstall"/>
<body><![CDATA[
if (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_ENABLE)
return;
if (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DEFAULT &&
AddonManager.autoUpdateDefault)
return;
this.mManualUpdate = aInstall;
this._showStatus("update-available");
this._updateUpgradeInfo();
]]></body>
</method>
<method name="onDownloadStarted">
<parameter name="aInstall"/>
<body><![CDATA[
this._updateState();
this._showStatus("progress");
this._installStatus.initWithInstall(aInstall);
]]></body>
</method>
<method name="onInstallStarted">
<parameter name="aInstall"/>
<body><![CDATA[
this._updateState();
this._showStatus("progress");
this._installStatus.initWithInstall(aInstall);
]]></body>
</method>
<method name="onInstallEnded">
<parameter name="aInstall"/>
<parameter name="aAddon"/>
<body><![CDATA[
// If the install completed without needing a restart then switch to
// using the new Addon
if (!(aAddon.pendingOperations & AddonManager.PENDING_INSTALL))
this._initWithAddon(aAddon);
else
this._updateState();
]]></body>
</method>
<method name="onDownloadFailed">
<body><![CDATA[
this._updateState();
]]></body>
</method>
<method name="onInstallFailed">
<body><![CDATA[
this._updateState();
]]></body>
</method>
<method name="onInstallCancelled">
<body><![CDATA[
this._updateState();
]]></body>
</method>
</implementation>
<handlers>
<handler event="click" button="0"><![CDATA[
switch (event.detail) {
case 1:
// Prevent double-click where the UI changes on the first click
this._lastClickTarget = event.originalTarget;
break;
case 2:
if (event.originalTarget.localName != 'button' &&
!event.originalTarget.classList.contains('text-link') &&
event.originalTarget == this._lastClickTarget) {
this.showInDetailView();
}
break;
}
]]></handler>
</handlers>
</binding>
<!-- Addon - uninstalled - An uninstalled addon that can be re-installed. -->
<binding id="addon-uninstalled"
extends="chrome://mozapps/content/extensions/extensions.xml#addon-base">
<content>
<xul:hbox class="pending" align="center">
<xul:image class="pending-icon"/>
<xul:label anonid="notice" flex="1"/>
<xul:button anonid="restart-btn" class="button-link"
label="&addon.restartNow.label;"
command="cmd_restartApp"/>
<xul:button anonid="undo-btn" class="button-link"
label="&addon.undoRemove.label;"
tooltiptext="&addon.undoRemove.tooltip;"
oncommand="document.getBindingParent(this).cancelUninstall();"/>
<xul:spacer flex="5000"/> <!-- Necessary to allow the message to wrap -->
</xul:hbox>
</content>
<implementation>
<constructor><![CDATA[
this._notice.textContent = gStrings.ext.formatStringFromName("uninstallNotice",
[this.mAddon.name],
1);
if (!this.isPending("uninstall"))
this._restartBtn.setAttribute("hidden", true);
gEventManager.registerAddonListener(this, this.mAddon.id);
]]></constructor>
<destructor><![CDATA[
gEventManager.unregisterAddonListener(this, this.mAddon.id);
]]></destructor>
<field name="_notice" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "notice");
</field>
<field name="_restartBtn" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "restart-btn");
</field>
<method name="cancelUninstall">
<body><![CDATA[
// This assumes that disabling does not require a restart when
// uninstalling doesn't. Things will still work if not, the add-on
// will just still be active until finally getting uninstalled.
if (this.isPending("uninstall"))
this.mAddon.cancelUninstall();
else if (this.getAttribute("wasDisabled") != "true")
this.mAddon.userDisabled = false;
this.removeAttribute("pending");
]]></body>
</method>
<method name="onOperationCancelled">
<body><![CDATA[
if (!this.isPending("uninstall"))
this.removeAttribute("pending");
]]></body>
</method>
<method name="onExternalInstall">
<parameter name="aAddon"/>
<parameter name="aExistingAddon"/>
<parameter name="aNeedsRestart"/>
<body><![CDATA[
if (aExistingAddon.id != this.mAddon.id)
return;
// Make sure any newly installed add-on has the correct disabled state
if (this.hasAttribute("wasDisabled"))
aAddon.userDisabled = this.getAttribute("wasDisabled") == "true";
// If the install completed without needing a restart then switch to
// using the new Addon
if (!aNeedsRestart)
this.mAddon = aAddon;
this.removeAttribute("pending");
]]></body>
</method>
<method name="onInstallStarted">
<parameter name="aInstall"/>
<body><![CDATA[
// Make sure any newly installed add-on has the correct disabled state
if (this.hasAttribute("wasDisabled"))
aInstall.addon.userDisabled = this.getAttribute("wasDisabled") == "true";
]]></body>
</method>
<method name="onInstallEnded">
<parameter name="aInstall"/>
<parameter name="aAddon"/>
<body><![CDATA[
// If the install completed without needing a restart then switch to
// using the new Addon
if (!(aAddon.pendingOperations & AddonManager.PENDING_INSTALL))
this.mAddon = aAddon;
this.removeAttribute("pending");
]]></body>
</method>
</implementation>
</binding>
<!-- Addon - installing - an addon item that is currently being installed -->
<binding id="addon-installing"
extends="chrome://mozapps/content/extensions/extensions.xml#addon-base">
<content>
<xul:hbox anonid="warning-container" align="center"
class="warning">
<xul:image class="warning-icon"/>
<xul:label anonid="warning" flex="1"/>
<xul:button anonid="warning-link" class="button-link"
oncommand="document.getBindingParent(this).retryInstall();"/>
<xul:spacer flex="5000"/> <!-- Necessary to allow the message to wrap -->
</xul:hbox>
<xul:hbox align="stretch">
<xul:vbox pack="start">
<xul:vbox align="center" pack="center" class="icon-container">
<xul:image anonid="icon" class="icon"/>
</xul:vbox>
</xul:vbox>
<xul:vbox flex="1" class="fade" align="stretch" pack="center">
<xul:hbox class="name-container" align="end">
<xul:label anonid="name" class="name"/>
<xul:label anonid="version" class="version" hidden="true"/>
</xul:hbox>
</xul:vbox>
<xul:vbox align="end" pack="end">
<xul:hbox anonid="install-status" class="install-status"/>
</xul:vbox>
</xul:hbox>
</content>
<implementation>
<constructor><![CDATA[
this._installStatus.mControl = this;
this._installStatus.mInstall = this.mInstall;
this.refreshInfo();
]]></constructor>
<field name="_icon">
document.getAnonymousElementByAttribute(this, "anonid", "icon");
</field>
<field name="_name">
document.getAnonymousElementByAttribute(this, "anonid", "name");
</field>
<field name="_version">
document.getAnonymousElementByAttribute(this, "anonid", "version");
</field>
<field name="_warning">
document.getAnonymousElementByAttribute(this, "anonid", "warning");
</field>
<field name="_warningLink">
document.getAnonymousElementByAttribute(this, "anonid", "warning-link");
</field>
<field name="_installStatus">
document.getAnonymousElementByAttribute(this, "anonid",
"install-status");
</field>
<method name="onInstallCompleted">
<body><![CDATA[
this.mAddon = this.mInstall.addon;
this.setAttribute("name", this.mAddon.name);
this.setAttribute("value", this.mAddon.id);
this.setAttribute("status", "installed");
]]></body>
</method>
<method name="refreshInfo">
<body><![CDATA[
this.mAddon = this.mAddon || this.mInstall.addon;
if (this.mAddon) {
this._icon.src = this.mAddon.iconURL ||
(this.mInstall ? this.mInstall.iconURL : "");
this._name.value = this.mAddon.name;
if (this.mAddon.version) {
this._version.value = this.mAddon.version;
this._version.hidden = false;
} else {
this._version.hidden = true;
}
} else {
this._icon.src = this.mInstall.iconURL;
// AddonInstall.name isn't always available - fallback to filename
if (this.mInstall.name) {
this._name.value = this.mInstall.name;
} else if (this.mInstall.sourceURI) {
var url = Components.classes["@mozilla.org/network/standard-url;1"]
.createInstance(Components.interfaces.nsIStandardURL);
url.init(url.URLTYPE_STANDARD, 80, this.mInstall.sourceURI.spec,
null, null);
url.QueryInterface(Components.interfaces.nsIURL);
this._name.value = url.fileName;
}
if (this.mInstall.version) {
this._version.value = this.mInstall.version;
this._version.hidden = false;
} else {
this._version.hidden = true;
}
}
if (this.mInstall.state == AddonManager.STATE_DOWNLOAD_FAILED) {
this.setAttribute("notification", "warning");
this._warning.textContent = gStrings.ext.formatStringFromName(
"notification.downloadError",
[this._name.value], 1
);
this._warningLink.label = gStrings.ext.GetStringFromName("notification.downloadError.retry");
this._warningLink.tooltipText = gStrings.ext.GetStringFromName("notification.downloadError.retry.tooltip");
} else if (this.mInstall.state == AddonManager.STATE_INSTALL_FAILED) {
this.setAttribute("notification", "warning");
this._warning.textContent = gStrings.ext.formatStringFromName(
"notification.installError",
[this._name.value], 1
);
this._warningLink.label = gStrings.ext.GetStringFromName("notification.installError.retry");
this._warningLink.tooltipText = gStrings.ext.GetStringFromName("notification.downloadError.retry.tooltip");
} else {
this.removeAttribute("notification");
}
]]></body>
</method>
<method name="retryInstall">
<body><![CDATA[
this.mInstall.install();
]]></body>
</method>
</implementation>
</binding>
<binding id="detail-row">
<content>
<xul:label class="detail-row-label" xbl:inherits="value=label"/>
<xul:label class="detail-row-value" xbl:inherits="value"/>
</content>
<implementation>
<property name="value">
<getter><![CDATA[
return this.getAttribute("value");
]]></getter>
<setter><![CDATA[
if (!val)
this.removeAttribute("value");
else
this.setAttribute("value", val);
]]></setter>
</property>
</implementation>
</binding>
</bindings>