Backed out 2 changesets, 09209cd02343:8f2aaabd3130 (bug 1498967) for MozMill failures. a=backout
Backed out changeset 8f2aaabd3130 (bug 1498967) Backed out changeset 09209cd02343 (bug 1498967)
This commit is contained in:
Родитель
ed8a923565
Коммит
a0bf018511
|
@ -3,13 +3,12 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Helper functions for use by extensions that should ease them plug
|
||||
* Helper functions for use by entensions that should ease them plug
|
||||
* into the application.
|
||||
*/
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["ExtensionSupport"];
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
// ChromeUtils.import("resource://gre/modules/Deprecated.jsm") - needed for warning.
|
||||
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
@ -18,56 +17,10 @@ var { fixIterator } = ChromeUtils.import("resource:///modules/iteratorUtils.jsm"
|
|||
ChromeUtils.import("resource:///modules/IOUtils.js");
|
||||
|
||||
var extensionHooks = new Map();
|
||||
var legacyExtensions = new Map();
|
||||
var openWindowList;
|
||||
|
||||
var ExtensionSupport = {
|
||||
/**
|
||||
* A Map-like object which tracks legacy extension status. The "has" method
|
||||
* returns only active extensions for compatibility with existing code.
|
||||
*/
|
||||
loadedLegacyExtensions: {
|
||||
set(id, state) {
|
||||
legacyExtensions.set(id, state);
|
||||
},
|
||||
get(id) {
|
||||
return legacyExtensions.get(id);
|
||||
},
|
||||
has(id) {
|
||||
if (!legacyExtensions.has(id))
|
||||
return false;
|
||||
|
||||
let state = legacyExtensions.get(id);
|
||||
return !["install", "enable"].includes(state.pendingOperation);
|
||||
},
|
||||
hasAnyState(id) {
|
||||
return legacyExtensions.has(id);
|
||||
},
|
||||
_maybeDelete(id, newPendingOperation) {
|
||||
if (!legacyExtensions.has(id))
|
||||
return;
|
||||
|
||||
let state = legacyExtensions.get(id);
|
||||
if (state.pendingOperation == "enable" && newPendingOperation == "disable") {
|
||||
legacyExtensions.delete(id);
|
||||
this.notifyObservers(state);
|
||||
} else if (state.pendingOperation == "install" && newPendingOperation == "uninstall") {
|
||||
legacyExtensions.delete(id);
|
||||
this.notifyObservers(state);
|
||||
}
|
||||
},
|
||||
notifyObservers(state) {
|
||||
let wrappedState = { wrappedJSObject: state };
|
||||
Services.obs.notifyObservers(wrappedState, "legacy-addon-status-changed");
|
||||
},
|
||||
// AddonListener
|
||||
onDisabled(ev) {
|
||||
this._maybeDelete(ev.id, "disable");
|
||||
},
|
||||
onUninstalled(ev) {
|
||||
this._maybeDelete(ev.id, "uninstall");
|
||||
},
|
||||
},
|
||||
loadedLegacyExtensions: new Set(),
|
||||
|
||||
loadAddonPrefs(addonFile) {
|
||||
function setPref(preferDefault, name, value) {
|
||||
|
@ -354,5 +307,3 @@ var ExtensionSupport = {
|
|||
return extensionHooks.size;
|
||||
},
|
||||
};
|
||||
|
||||
AddonManager.addAddonListener(ExtensionSupport.loadedLegacyExtensions);
|
||||
|
|
|
@ -126,127 +126,55 @@ gDetailView._oldDetailUpdateState = gDetailView.updateState;
|
|||
gDetailView.updateState = function() {
|
||||
this._oldDetailUpdateState();
|
||||
|
||||
let pending = this._addon.pendingOperations;
|
||||
|
||||
let warningContainer = document.getElementById("warning-container");
|
||||
let warning = document.getElementById("detail-warning");
|
||||
let warningLink = document.getElementById("detail-warning-link");
|
||||
let restartButton = document.getElementById("restart-btn");
|
||||
let undoButton = document.getElementById("undo-btn");
|
||||
|
||||
if (ExtensionSupport.loadedLegacyExtensions.has(this._addon.id)) {
|
||||
this.node.setAttribute("active", "true");
|
||||
this.node.removeAttribute("pending");
|
||||
}
|
||||
|
||||
if (ExtensionSupport.loadedLegacyExtensions.hasAnyState(this._addon.id, true)) {
|
||||
let { stringName, undoCommand, version } = getTrueState(this._addon, "gDetailView._addon");
|
||||
if (ExtensionSupport.loadedLegacyExtensions.has(this._addon.id) &&
|
||||
(this._addon.userDisabled || pending & AddonManager.PENDING_UNINSTALL)) {
|
||||
this.node.setAttribute("notification", "warning");
|
||||
|
||||
if (stringName) {
|
||||
this.node.setAttribute("notification", "warning");
|
||||
this.node.removeAttribute("pending");
|
||||
let stringName = this._addon.userDisabled ? "warnLegacyDisable" : "warnLegacyUninstall";
|
||||
warning.textContent = gStrings.mailExt.formatStringFromName(
|
||||
stringName, [this._addon.name, gStrings.brandShortName], 2
|
||||
);
|
||||
|
||||
let warningContainer = document.getElementById("warning-container");
|
||||
let warning = document.getElementById("detail-warning");
|
||||
document.getElementById("detail-warning-link").hidden = true;
|
||||
warning.textContent = gStrings.mailExt.formatStringFromName(
|
||||
stringName, [this._addon.name, gStrings.brandShortName], 2
|
||||
);
|
||||
warningLink.hidden = true;
|
||||
|
||||
if (version) {
|
||||
document.getElementById("detail-version").value = version;
|
||||
}
|
||||
|
||||
if (!restartButton) {
|
||||
restartButton = document.createElement("button");
|
||||
restartButton.id = "restart-btn";
|
||||
restartButton.className = "button-link restart-btn";
|
||||
restartButton.setAttribute(
|
||||
"label", gStrings.mailExt.GetStringFromName("warnLegacyRestartButton")
|
||||
);
|
||||
restartButton.setAttribute("oncommand", "BrowserUtils.restartApplication()");
|
||||
warningContainer.insertBefore(restartButton, warningContainer.lastElementChild);
|
||||
}
|
||||
restartButton.hidden = false;
|
||||
if (undoCommand) {
|
||||
if (!undoButton) {
|
||||
undoButton = document.createElement("button");
|
||||
undoButton.className = "button-link undo-btn";
|
||||
undoButton.setAttribute(
|
||||
"label", gStrings.mailExt.GetStringFromName("warnLegacyUndoButton")
|
||||
);
|
||||
// We shouldn't really attach non-anonymous content to anonymous content, but we can.
|
||||
warningContainer.insertBefore(undoButton, warningContainer.lastElementChild);
|
||||
}
|
||||
undoButton.setAttribute("oncommand", undoCommand);
|
||||
undoButton.hidden = false;
|
||||
} else if (undoButton) {
|
||||
undoButton.hidden = true;
|
||||
}
|
||||
return;
|
||||
if (!restartButton) {
|
||||
restartButton = document.createElement("button");
|
||||
restartButton.id = "restart-btn";
|
||||
restartButton.className = "button-link restart-btn";
|
||||
restartButton.setAttribute("label", gStrings.mailExt.GetStringFromName("warnLegacyRestartButton"));
|
||||
restartButton.setAttribute("oncommand", "BrowserUtils.restartApplication()");
|
||||
warningContainer.insertBefore(restartButton, warningContainer.lastElementChild);
|
||||
}
|
||||
}
|
||||
restartButton.hidden = false;
|
||||
|
||||
if (restartButton) {
|
||||
if (!undoButton) {
|
||||
undoButton = document.createElement("button");
|
||||
undoButton.id = "undo-btn";
|
||||
undoButton.className = "button-link undo-btn";
|
||||
undoButton.setAttribute("label", gStrings.mailExt.GetStringFromName("warnLegacyUndoButton"));
|
||||
warningContainer.insertBefore(undoButton, warningContainer.lastElementChild);
|
||||
}
|
||||
if (this._addon.userDisabled) {
|
||||
undoButton.setAttribute("oncommand", "gDetailView._addon.enable()");
|
||||
} else {
|
||||
undoButton.setAttribute("oncommand", "gDetailView._addon.cancelUninstall()");
|
||||
}
|
||||
undoButton.hidden = false;
|
||||
} else if (restartButton) { // If one exists, so does the other.
|
||||
restartButton.hidden = true;
|
||||
}
|
||||
if (undoButton) {
|
||||
undoButton.hidden = true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the UI when things change.
|
||||
*/
|
||||
function statusChangedObserver(subject, topic, data) {
|
||||
let { id } = subject.wrappedJSObject;
|
||||
|
||||
if (gViewController.currentViewObj == gListView) {
|
||||
let listItem = gListView.getListItemForID(id);
|
||||
if (listItem) {
|
||||
setTimeout(() => listItem._updateState());
|
||||
}
|
||||
} else if (gViewController.currentViewObj == gDetailView) {
|
||||
setTimeout(() => gDetailView.updateState());
|
||||
}
|
||||
}
|
||||
Services.obs.addObserver(statusChangedObserver, "legacy-addon-status-changed");
|
||||
window.addEventListener("unload", () => {
|
||||
Services.obs.removeObserver(statusChangedObserver, "legacy-addon-status-changed");
|
||||
});
|
||||
|
||||
/**
|
||||
* The true status of legacy extensions, which AddonManager doesn't know
|
||||
* about because it thinks all extensions are restartless.
|
||||
*
|
||||
* @return An object of three properties:
|
||||
* stringName: a string to display to the user, from extensionsOverlay.properties.
|
||||
* undoCommand: code to run, should the user want to return to the previous state.
|
||||
* version: the current version of the extension.
|
||||
*/
|
||||
function getTrueState(addon, addonRef) {
|
||||
let state = ExtensionSupport.loadedLegacyExtensions.get(addon.id);
|
||||
let returnObject = {};
|
||||
|
||||
if (addon.pendingOperations & AddonManager.PENDING_UNINSTALL &&
|
||||
ExtensionSupport.loadedLegacyExtensions.has(addon.id)) {
|
||||
returnObject.stringName = "warnLegacyUninstall";
|
||||
returnObject.undoCommand = `${addonRef}.cancelUninstall()`;
|
||||
|
||||
} else if (state.pendingOperation == "install") {
|
||||
returnObject.stringName = "warnLegacyInstall";
|
||||
returnObject.undoCommand = `${addonRef}.uninstall()`;
|
||||
|
||||
} else if (addon.userDisabled) {
|
||||
returnObject.stringName = "warnLegacyDisable";
|
||||
returnObject.undoCommand = `${addonRef}.enable()`;
|
||||
|
||||
} else if (state.pendingOperation == "enable") {
|
||||
returnObject.stringName = "warnLegacyEnable";
|
||||
returnObject.undoCommand = `${addonRef}.disable()`;
|
||||
|
||||
} else if (state.pendingOperation == "upgrade") {
|
||||
returnObject.stringName = "warnLegacyUpgrade";
|
||||
returnObject.version = state.version;
|
||||
|
||||
} else if (state.pendingOperation == "downgrade") {
|
||||
returnObject.stringName = "warnLegacyDowngrade";
|
||||
returnObject.version = state.version;
|
||||
}
|
||||
|
||||
return returnObject;
|
||||
}
|
||||
|
|
|
@ -23,56 +23,42 @@
|
|||
<method name="_updateState">
|
||||
<body><![CDATA[
|
||||
this.__proto__.__proto__._updateState.call(this);
|
||||
let pending = this.mAddon.pendingOperations;
|
||||
let undoButton = this._warningContainer.querySelector("button.undo-btn");
|
||||
|
||||
if (ExtensionSupport.loadedLegacyExtensions.has(this.mAddon.id)) {
|
||||
this.setAttribute("active", "true");
|
||||
this.removeAttribute("pending");
|
||||
}
|
||||
|
||||
if (ExtensionSupport.loadedLegacyExtensions.hasAnyState(this.mAddon.id, true)) {
|
||||
let {
|
||||
stringName,
|
||||
undoCommand,
|
||||
} = getTrueState(this.mAddon, "document.getBindingParent(this).mAddon");
|
||||
if (
|
||||
ExtensionSupport.loadedLegacyExtensions.has(this.mAddon.id) &&
|
||||
(this.mAddon.userDisabled || pending & AddonManager.PENDING_UNINSTALL)
|
||||
) {
|
||||
this.setAttribute("notification", "warning");
|
||||
let stringName = this.mAddon.userDisabled ? "warnLegacyDisable" : "warnLegacyUninstall";
|
||||
this._warning.textContent = gStrings.mailExt.formatStringFromName(stringName, [this.mAddon.name, gStrings.brandShortName], 2);
|
||||
|
||||
if (stringName) {
|
||||
this.setAttribute("notification", "warning");
|
||||
this.removeAttribute("pending");
|
||||
this._warningLink.hidden = true;
|
||||
|
||||
this._warningLink.hidden = true;
|
||||
this._warning.textContent = gStrings.mailExt.formatStringFromName(
|
||||
stringName, [this.mAddon.name, gStrings.brandShortName], 2
|
||||
);
|
||||
this._warningBtn.label = gStrings.mailExt.GetStringFromName("warnLegacyRestartButton");
|
||||
this._warningBtn.setAttribute("oncommand", "BrowserUtils.restartApplication()");
|
||||
this._warningBtn.hidden = false;
|
||||
|
||||
this._warningBtn.label = gStrings.mailExt.GetStringFromName(
|
||||
"warnLegacyRestartButton"
|
||||
);
|
||||
this._warningBtn.setAttribute("oncommand", "BrowserUtils.restartApplication()");
|
||||
this._warningBtn.hidden = false;
|
||||
|
||||
if (undoCommand) {
|
||||
if (!undoButton) {
|
||||
undoButton = document.createElement("button");
|
||||
undoButton.className = "button-link undo-btn";
|
||||
undoButton.setAttribute(
|
||||
"label", gStrings.mailExt.GetStringFromName("warnLegacyUndoButton")
|
||||
);
|
||||
// We shouldn't really attach non-anonymous content to anonymous content,
|
||||
// but we can.
|
||||
this._warningContainer.insertBefore(
|
||||
undoButton, this._warningContainer.lastElementChild
|
||||
);
|
||||
}
|
||||
undoButton.setAttribute("oncommand", undoCommand);
|
||||
undoButton.hidden = false;
|
||||
} else if (undoButton) {
|
||||
undoButton.hidden = true;
|
||||
}
|
||||
return;
|
||||
if (!undoButton) {
|
||||
undoButton = document.createElement("button");
|
||||
undoButton.className = "button-link undo-btn";
|
||||
undoButton.setAttribute("label", gStrings.mailExt.GetStringFromName("warnLegacyUndoButton"));
|
||||
// We shouldn't really attach non-anonymous content to anonymous content, but we can.
|
||||
this._warningContainer.insertBefore(undoButton, this._warningContainer.lastElementChild);
|
||||
}
|
||||
}
|
||||
|
||||
if (undoButton) {
|
||||
if (this.mAddon.userDisabled) {
|
||||
undoButton.setAttribute("oncommand", "document.getBindingParent(this).mAddon.enable()");
|
||||
} else {
|
||||
undoButton.setAttribute("oncommand", "document.getBindingParent(this).mAddon.cancelUninstall()");
|
||||
}
|
||||
undoButton.hidden = false;
|
||||
} else if (undoButton) {
|
||||
undoButton.hidden = true;
|
||||
}
|
||||
]]></body>
|
||||
|
|
|
@ -333,9 +333,7 @@
|
|||
</popupnotification>
|
||||
|
||||
<popupnotification id="addon-installed-notification" hidden="true">
|
||||
<popupnotificationcontent class="addon-installed-notification-content" orient="vertical">
|
||||
<description id="addon-installed-restart-text" class="addon-installed-restart-text"/>
|
||||
</popupnotificationcontent>
|
||||
<popupnotificationcontent class="addon-installed-notification-content" orient="vertical"/>
|
||||
</popupnotification>
|
||||
|
||||
#include editContactPanel.inc
|
||||
|
|
|
@ -265,8 +265,7 @@ var gXPInstallObserver = {
|
|||
return promise;
|
||||
},
|
||||
|
||||
async showInstallNotification(browser, addon) {
|
||||
let document = browser.ownerDocument;
|
||||
showInstallNotification(browser, addon) {
|
||||
let window = browser.ownerGlobal;
|
||||
|
||||
let brandBundle = window.document.getElementById("bundle_brand");
|
||||
|
@ -274,56 +273,33 @@ var gXPInstallObserver = {
|
|||
|
||||
let message = addonsBundle.getFormattedString("addonPostInstall.message1",
|
||||
["<>", appName]);
|
||||
|
||||
let restartRequired = false;
|
||||
let icon = DEFAULT_EXTENSION_ICON;
|
||||
if (addon.isWebExtension) {
|
||||
let uri = addon.getResourceURI().spec;
|
||||
let data = new ExtensionData(Services.io.newURI(`jar:${uri}!/`));
|
||||
await data.loadManifest();
|
||||
restartRequired = data.manifest.legacy;
|
||||
icon = AddonManager.getPreferredIconURL(addon, 32, window) || icon;
|
||||
}
|
||||
|
||||
let action;
|
||||
let secondaryActions = null;
|
||||
let textEl = document.getElementById("addon-installed-restart-text");
|
||||
if (restartRequired) {
|
||||
action = {
|
||||
label: addonsBundle.getString("addonPostInstall.restart.label"),
|
||||
accessKey: addonsBundle.getString("addonPostInstall.restart.key"),
|
||||
callback: () => {
|
||||
ChromeUtils.import("resource://gre/modules/BrowserUtils.jsm");
|
||||
BrowserUtils.restartApplication();
|
||||
},
|
||||
};
|
||||
secondaryActions = [{
|
||||
label: addonsBundle.getString("addonPostInstall.noRestart.label"),
|
||||
accessKey: addonsBundle.getString("addonPostInstall.noRestart.key"),
|
||||
callback: () => {},
|
||||
}];
|
||||
textEl.textContent = addonsBundle.getFormattedString(
|
||||
"addonPostInstall.restartRequired.message", [appName]
|
||||
);
|
||||
textEl.hidden = false;
|
||||
} else {
|
||||
action = {
|
||||
return new Promise(resolve => {
|
||||
let action = {
|
||||
label: addonsBundle.getString("addonPostInstall.okay.label"),
|
||||
accessKey: addonsBundle.getString("addonPostInstall.okay.key"),
|
||||
callback: () => {},
|
||||
callback: resolve,
|
||||
};
|
||||
textEl.hidden = true;
|
||||
}
|
||||
|
||||
let options = {
|
||||
hideClose: true,
|
||||
timeout: Date.now() + 30000,
|
||||
popupIconURL: icon,
|
||||
name: addon.name,
|
||||
};
|
||||
let icon = DEFAULT_EXTENSION_ICON;
|
||||
if (addon.isWebExtension) {
|
||||
icon = AddonManager.getPreferredIconURL(addon, 32, window) || icon;
|
||||
}
|
||||
|
||||
showNotification(browser, "addon-installed", message, "addons-notification-icon",
|
||||
action, secondaryActions, options);
|
||||
let options = {
|
||||
hideClose: true,
|
||||
timeout: Date.now() + 30000,
|
||||
popupIconURL: icon,
|
||||
eventCallback(topic) {
|
||||
if (topic == "dismissed") {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
name: addon.name,
|
||||
};
|
||||
|
||||
showNotification(browser, "addon-installed", message, "addons-notification-icon",
|
||||
action, null, options);
|
||||
});
|
||||
},
|
||||
|
||||
/* eslint-disable complexity */
|
||||
|
@ -546,7 +522,7 @@ var gXPInstallObserver = {
|
|||
break;
|
||||
}
|
||||
case "webextension-permission-prompt": {
|
||||
let { info } = subject.wrappedJSObject;
|
||||
let {info} = subject.wrappedJSObject;
|
||||
|
||||
// Dismiss the progress notification. Note that this is bad if
|
||||
// there are multiple simultaneous installs happening, see
|
||||
|
@ -582,7 +558,7 @@ var gXPInstallObserver = {
|
|||
break;
|
||||
}
|
||||
case "webextension-update-permissions": {
|
||||
let { info } = subject.wrappedJSObject;
|
||||
let {info} = subject.wrappedJSObject;
|
||||
info.type = "update";
|
||||
let strings = this._buildStrings(info);
|
||||
|
||||
|
@ -601,15 +577,19 @@ var gXPInstallObserver = {
|
|||
break;
|
||||
}
|
||||
case "webextension-install-notify": {
|
||||
let { addon } = subject.wrappedJSObject;
|
||||
this.showInstallNotification(browser, addon);
|
||||
let {addon, callback} = subject.wrappedJSObject;
|
||||
this.showInstallNotification(browser, addon).then(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "webextension-optional-permission-prompt": {
|
||||
let { name, icon, permissions, resolve } = subject.wrappedJSObject;
|
||||
let {name, icon, permissions, resolve} = subject.wrappedJSObject;
|
||||
let strings = this._buildStrings({
|
||||
type: "optional",
|
||||
addon: { name },
|
||||
addon: {name},
|
||||
permissions,
|
||||
});
|
||||
|
||||
|
@ -630,7 +610,7 @@ var gXPInstallObserver = {
|
|||
// This bundle isn't the same as addonsBundle.
|
||||
let bundle = Services.strings.createBundle(ADDONS_PROPERTIES);
|
||||
let appName = brandBundle.getString("brandShortName");
|
||||
let info2 = Object.assign({ appName }, info);
|
||||
let info2 = Object.assign({appName}, info);
|
||||
|
||||
let strings = ExtensionData.formatPermissionStrings(info2, bundle);
|
||||
strings.addonName = info.addon.name;
|
||||
|
|
|
@ -20,32 +20,12 @@ this.legacy = class extends ExtensionAPI {
|
|||
async register() {
|
||||
this.extension.legacyLoaded = true;
|
||||
|
||||
let state = {
|
||||
id: this.extension.id,
|
||||
pendingOperation: null,
|
||||
version: this.extension.version,
|
||||
};
|
||||
if (ExtensionSupport.loadedLegacyExtensions.has(this.extension.id)) {
|
||||
state = ExtensionSupport.loadedLegacyExtensions.get(this.extension.id);
|
||||
let versionComparison = Services.vc.compare(this.extension.version, state.version);
|
||||
if (versionComparison > 0) {
|
||||
state.pendingOperation = "upgrade";
|
||||
ExtensionSupport.loadedLegacyExtensions.notifyObservers(state);
|
||||
} else if (versionComparison < 0) {
|
||||
state.pendingOperation = "downgrade";
|
||||
ExtensionSupport.loadedLegacyExtensions.notifyObservers(state);
|
||||
}
|
||||
console.log(`Legacy WebExtension ${this.extension.id} has already been loaded in this run, refusing to do so again. Please restart.`);
|
||||
console.log(`Legacy WebExtension ${this.extension.id} has already been loaded in this run, refusing to do so again. Please restart`);
|
||||
return;
|
||||
}
|
||||
ExtensionSupport.loadedLegacyExtensions.add(this.extension.id);
|
||||
|
||||
ExtensionSupport.loadedLegacyExtensions.set(this.extension.id, state);
|
||||
if (["ADDON_INSTALL", "ADDON_ENABLE"].includes(this.extension.startupReason)) {
|
||||
state.pendingOperation = this.extension.startupReason.substring(6).toLowerCase();
|
||||
console.log(`Legacy WebExtension ${this.extension.id} loading for other reason than startup (${this.extension.startupReason}), refusing to load immediately.`);
|
||||
ExtensionSupport.loadedLegacyExtensions.notifyObservers(state);
|
||||
return;
|
||||
}
|
||||
|
||||
let extensionRoot;
|
||||
if (this.extension.rootURI instanceof Ci.nsIJARURI) {
|
||||
|
|
|
@ -19,14 +19,6 @@ addonPostInstall.message1=%1$S has been added to %2$S.
|
|||
addonPostInstall.okay.label=OK
|
||||
addonPostInstall.okay.key=O
|
||||
|
||||
# LOCALIZATION NOTE (addonPostInstall.restartRequired.message)
|
||||
# %S is the application name
|
||||
addonPostInstall.restartRequired.message=%S must be restarted to complete the installation.
|
||||
addonPostInstall.restart.label=Restart now
|
||||
addonPostInstall.restart.key=R
|
||||
addonPostInstall.noRestart.label=Not now
|
||||
addonPostInstall.noRestart.key=N
|
||||
|
||||
# LOCALIZATION NOTE (addonDownloadingAndVerifying):
|
||||
# Semicolon-separated list of plural forms. See:
|
||||
# http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
|
|
|
@ -10,13 +10,9 @@ cmdForwardTooltip=Go forward one page
|
|||
legacyInfo=Legacy extensions must be updated to be compatible with #1 #2.
|
||||
legacyLearnMore=Learn more…
|
||||
|
||||
# LOCALIZATION NOTE (warnLegacyUpgrade, warnLegacyDowngrade, warnLegacyEnable, warnLegacyDisable, warnLegacyInstall, warnLegacyUninstall)
|
||||
# %1$S is the add-on name, %2$S is brand name
|
||||
warnLegacyUpgrade=%1$S will be upgraded after you restart %2$S.
|
||||
warnLegacyDowngrade=%1$S will be downgraded after you restart %2$S.
|
||||
warnLegacyEnable=%1$S will be enabled after you restart %2$S.
|
||||
#LOCALIZATION NOTE (notification.disable) %1$S is the add-on name, %2$S is brand name
|
||||
warnLegacyDisable=%1$S will be disabled after you restart %2$S.
|
||||
warnLegacyInstall=%1$S will be installed after you restart %2$S.
|
||||
#LOCALIZATION NOTE (notification.uninstall) %1$S is the add-on name, %2$S is brand name
|
||||
warnLegacyUninstall=%1$S will be uninstalled after you restart %2$S.
|
||||
warnLegacyRestartButton=Restart
|
||||
warnLegacyUndoButton=Undo
|
||||
|
|
Загрузка…
Ссылка в новой задаче