<?xml version="1.0"?> <!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <!DOCTYPE page [ <!ENTITY % extensionsDTD SYSTEM "chrome://mozapps/locale/extensions/extensions.dtd"> %extensionsDTD; <!ENTITY % aboutDTD SYSTEM "chrome://mozapps/locale/extensions/about.dtd"> %aboutDTD; ]> <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 Components.Exception("Invalid value", Components.results.NS_ERROR_ILLEGAL_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:spacer flex="1"/> <xul:label anonid="status" class="status"/> <xul:spacer flex="1"/> <xul:button anonid="cancel-btn" class="cancel" tooltiptext="&progress.cancel.tooltip;" oncommand="document.getBindingParent(this).cancel();"/> </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="_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> <method name="cancel"> <body><![CDATA[ this.mInstall.cancel(); ]]></body> </method> </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> <!-- Translators list - Names of a translators of Language Pack. --> <binding id="translators-list"> <content> <xul:label anonid="label" value="&translators.label;" class="sectionTitle"/> <xul:vbox flex="1" anonid="translatorsBox" class="boxIndent"/> </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="_translatorsBox"> document.getAnonymousElementByAttribute(this, "anonid", "translatorsBox"); </field> <method name="setTranslators"> <parameter name="aTranslators"/> <parameter name="aType"/> <body><![CDATA[ if (aType != "locale" || !aTranslators || aTranslators.length == 0) { this.collapsed = true; return; } this.collapsed = false; while (this._translatorsBox.firstChild) { this._translatorsBox.removeChild(this._translatorsBox.firstChild); } for (let currentItem of aTranslators) { var label = document.createElement("label"); label.textContent = currentItem; label.setAttribute("class", "contributor"); this._translatorsBox.appendChild(label); } ]]></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._progress.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="typeHasFlag"> <parameter name="aFlag"/> <body><![CDATA[ let flag = AddonManager["TYPE_" + aFlag]; let type = AddonManager.addonTypes[this.mAddon.type]; return !!(type.flags & flag); ]]></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" 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" 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" 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 class="content-container"> <xul:vbox class="icon-container"> <xul:image anonid="icon" class="icon"/> </xul:vbox> <xul:vbox class="content-inner-container" flex="1"> <xul:hbox class="basicinfo-container"> <xul:hbox class="name-container"> <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="nativeIndicator nativeAddon" value="●" tooltiptext="&addon.nativeAddon;"/> <xul:label class="nativeIndicator compatAddon" value="●" tooltiptext="&addon.compatAddon;"/> <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="date-updated" class="date-updated" unknown="&addon.unknownDate;"/> </xul:hbox> <xul:hbox class="experiment-container"> <svg width="6" height="6" viewBox="0 0 6 6" version="1.1" xmlns="http://www.w3.org/2000/svg" class="experiment-bullet-container"> <circle cx="3" cy="3" r="3" class="experiment-bullet"/> </svg> <xul:label anonid="experiment-state" class="experiment-state"/> <xul:label anonid="experiment-time" class="experiment-time"/> </xul:hbox> <xul:hbox class="advancedinfo-container" flex="1"> <xul:vbox class="description-outer-container" flex="1"> <xul:hbox class="description-container"> <xul:label anonid="description" class="description" crop="end" flex="1"/> <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 class="relnotes-toggle-container"> <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 class="status-control-wrapper"> <xul:hbox class="status-container"> <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"> <xul:checkbox anonid="include-update" class="include-update" label="&addon.includeUpdate.label;" checked="true" oncommand="document.getBindingParent(this).onIncludeUpdateChanged();"/> <xul:hbox class="update-info-container"> <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"> <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();"/> <!-- label="&cmd.debugAddon.label;" --> <xul:button anonid="debug-btn" class="addon-control debug" label="&cmd.debugAddon.label;" oncommand="document.getBindingParent(this).debug();"/> <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:menulist anonid="state-menulist" class="addon-control state" tooltiptext="&cmd.stateMenu.tooltip;"> <xul:menupopup> <xul:menuitem anonid="ask-to-activate-menuitem" class="addon-control" label="&cmd.askToActivate.label;" tooltiptext="&cmd.askToActivate.tooltip;" oncommand="document.getBindingParent(this).userDisabled = AddonManager.STATE_ASK_TO_ACTIVATE;"/> <xul:menuitem anonid="always-activate-menuitem" class="addon-control" label="&cmd.alwaysActivate.label;" tooltiptext="&cmd.alwaysActivate.tooltip;" oncommand="document.getBindingParent(this).userDisabled = false;"/> <xul:menuitem anonid="never-activate-menuitem" class="addon-control" label="&cmd.neverActivate.label;" tooltiptext="&cmd.neverActivate.tooltip;" oncommand="document.getBindingParent(this).userDisabled = true;"/> </xul:menupopup> </xul:menulist> </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="_version"> document.getAnonymousElementByAttribute(this, "anonid", "version"); </field> <field name="_experimentState"> document.getAnonymousElementByAttribute(this, "anonid", "experiment-state"); </field> <field name="_experimentTime"> document.getAnonymousElementByAttribute(this, "anonid", "experiment-time"); </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="_stateMenulist"> document.getAnonymousElementByAttribute(this, "anonid", "state-menulist"); </field> <field name="_askToActivateMenuitem"> document.getAnonymousElementByAttribute(this, "anonid", "ask-to-activate-menuitem"); </field> <field name="_alwaysActivateMenuitem"> document.getAnonymousElementByAttribute(this, "anonid", "always-activate-menuitem"); </field> <field name="_neverActivateMenuitem"> document.getAnonymousElementByAttribute(this, "anonid", "never-activate-menuitem"); </field> <field name="_preferencesBtn"> document.getAnonymousElementByAttribute(this, "anonid", "preferences-btn"); </field> <field name="_enableBtn"> document.getAnonymousElementByAttribute(this, "anonid", "enable-btn"); </field> <field name="_debugBtn"> document.getAnonymousElementByAttribute(this, "anonid", "debug-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 = ""; if (shouldShowVersionNumber(this.mAddon)) this._version.value = this.mAddon.version; else this._version.hidden = true; 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 install of aInstallsList) { 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[ if (this.parentNode.selectedItem == this) gViewController.updateCommands(); var pending = this.mAddon.pendingOperations; if (pending != AddonManager.PENDING_NONE) { this.removeAttribute("notification"); var pending = null; const PENDING_OPERATIONS = ["enable", "disable", "install", "uninstall", "upgrade"]; for (let op of PENDING_OPERATIONS) { if (this.isPending(op)) pending = op; } 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 = this.mAddon.blocklistURL; this._errorLink.hidden = false; } else if ((!isUpgrade && !this.mAddon.isCompatible) && (AddonManager.checkCompatibility || (this.mAddon.blocklistState != Ci.nsIBlocklistService.STATE_SOFTBLOCKED))) { 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 = this.mAddon.blocklistURL; 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 if (!isUpgrade && this.mAddon.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE) { this.setAttribute("notification", "error"); this._error.textContent = gStrings.ext.formatStringFromName( "notification.vulnerableUpdatable", [this.mAddon.name], 1 ); this._errorLink.value = gStrings.ext.GetStringFromName("notification.vulnerableUpdatable.link"); this._errorLink.href = this.mAddon.blocklistURL; this._errorLink.hidden = false; } else if (!isUpgrade && this.mAddon.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE) { this.setAttribute("notification", "error"); this._error.textContent = gStrings.ext.formatStringFromName( "notification.vulnerableNoUpdate", [this.mAddon.name], 1 ); this._errorLink.value = gStrings.ext.GetStringFromName("notification.vulnerableNoUpdate.link"); this._errorLink.href = this.mAddon.blocklistURL; this._errorLink.hidden = false; } else if (this.mAddon.isGMPlugin && !this.mAddon.isInstalled && this.mAddon.isActive) { this.setAttribute("notification", "warning"); this._warning.textContent = gStrings.ext.formatStringFromName("notification.gmpPending", [this.mAddon.name], 1); } else { this.removeAttribute("notification"); if (this.mAddon.type == "extension") this.setAttribute("native", this.mAddon.native); } } this._preferencesBtn.hidden = (!this.mAddon.optionsURL) || this.mAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_INFO; if (this.typeHasFlag("SUPPORTS_ASK_TO_ACTIVATE")) { this._enableBtn.disabled = true; this._disableBtn.disabled = true; this._askToActivateMenuitem.disabled = !this.hasPermission("ask_to_activate"); this._alwaysActivateMenuitem.disabled = !this.hasPermission("enable"); this._neverActivateMenuitem.disabled = !this.hasPermission("disable"); if (!this.mAddon.isActive) { this._stateMenulist.selectedItem = this._neverActivateMenuitem; } else if (this.mAddon.userDisabled == AddonManager.STATE_ASK_TO_ACTIVATE) { this._stateMenulist.selectedItem = this._askToActivateMenuitem; } else { this._stateMenulist.selectedItem = this._alwaysActivateMenuitem; } let hasActivatePermission = ["ask_to_activate", "enable", "disable"].some(perm => this.hasPermission(perm)); this._stateMenulist.disabled = !hasActivatePermission; this._stateMenulist.hidden = false; this._stateMenulist.classList.add('no-auto-hide'); } else { this._stateMenulist.hidden = true; 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"); let debuggable = this.mAddon.isDebuggable && Services.prefs.getBoolPref('devtools.chrome.enabled') && Services.prefs.getBoolPref('devtools.debugger.remote-enabled'); this._debugBtn.disabled = this._debugBtn.hidden = !debuggable if (this.mAddon.type == "experiment") { this.removeAttribute("notification"); let prefix = "experiment."; let active = this.mAddon.isActive; if (!showProgress) { let stateKey = prefix + "state." + (active ? "active" : "complete"); this._experimentState.value = gStrings.ext.GetStringFromName(stateKey); let now = Date.now(); let end = this.endDate; let days = Math.abs(end - now) / (24 * 60 * 60 * 1000); let timeKey = prefix + "time."; let timeMessage; if (days < 1) { timeKey += (active ? "endsToday" : "endedToday"); timeMessage = gStrings.ext.GetStringFromName(timeKey); } else { timeKey += (active ? "daysRemaining" : "daysPassed"); days = Math.round(days); let timeString = gStrings.ext.GetStringFromName(timeKey); timeMessage = PluralForm.get(days, timeString) .replace("#1", days); } this._experimentTime.value = timeMessage; } } ]]></body> </method> <method name="_updateUpgradeInfo"> <body><![CDATA[ // Only update the version string if we're displaying the upgrade info if (this.hasAttribute("upgrade") && shouldShowVersionNumber(this.mAddon)) 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; var ct = req.getResponseHeader("content-type"); if ((!ct || ct.indexOf("text/html") < 0) && 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 and the type doesn't // support undoing of restartless uninstalls, then we fake it by // just disabling it it, and doing the real uninstall later. if (!this.opRequiresRestart("uninstall") && !this.typeHasFlag("SUPPORTS_UNDO_RESTARTLESS_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(true); } ]]></body> </method> <method name="debug"> <body><![CDATA[ gViewController.doCommand("cmd_debugItem", this.mAddon); ]]></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="onPropertyChanged"> <parameter name="aProperties"/> <body><![CDATA[ if (aProperties.indexOf("appDisabled") != -1 || aProperties.indexOf("userDisabled") != -1) 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"> <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.opRequiresRestart("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" 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 class="content-container"> <xul:vbox class="icon-outer-container"> <xul:vbox class="icon-container"> <xul:image anonid="icon" class="icon"/> </xul:vbox> </xul:vbox> <xul:vbox class="fade name-outer-container" flex="1"> <xul:hbox class="name-container"> <xul:label anonid="name" class="name" crop="end"/> <xul:label anonid="version" class="version" hidden="true"/> </xul:hbox> </xul:vbox> <xul:vbox class="install-status-container"> <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>