--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -3240,16 +3240,22 @@ var gDetailView = {
let stack = document.getElementById(containerId);
if (stack) {
// Remove the existent options container (if any).
stack.remove();
}
+ // If the addon gets disabled before we get here (which probably
+ // happens more in tests that in regular usage) then just bail out.
+ if (!this._addon) {
+ return;
+ }
+
stack = document.createElement("stack");
stack.setAttribute("id", containerId);
let browser = document.createElement("browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
browser.setAttribute("id", "addon-options");
browser.setAttribute("class", "inline-options-browser");
@@ -3326,17 +3332,17 @@ var gDetailView = {
};
if (optionsBrowserStyle) {
browserOptions.stylesheets = extensionStylesheets;
}
mm.sendAsyncMessage("Extension:InitBrowser", browserOptions);
- browser.loadURI(optionsURL);
+ browser.loadURIWithFlags(optionsURL, {flags: Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY});
});
},
getSelectedAddon() {
return this._addon;
},
onEnabling() {
--- a/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js
@@ -2,16 +2,26 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var gManagerWindow;
var gDocument;
var gCategoryUtilities;
var gProvider;
+let epScope = {};
+Components.utils.import("resource://gre/modules/ExtensionParent.jsm", epScope);
+let {ExtensionParent} = epScope;
+
+function promiseOptionsPageLoaded() {
+ return new Promise(resolve => {
+ ExtensionParent.apiManager.once("extension-browser-inserted", resolve);
+ });
+}
+
add_task(async function setup() {
requestLongerTimeout(2);
gProvider = new MockProvider();
gProvider.createAddons([{
id: "addon1@tests.mozilla.org",
name: "Test addon 1",
@@ -27,16 +37,23 @@ add_task(async function setup() {
name: "Test addon 3",
type: "extension",
operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE
}, {
id: "addon4@tests.mozilla.org",
name: "Test addon 4",
type: "extension",
operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE
+ }, {
+ id: "addon5@tests.mozilla.org",
+ name: "Test addon with inline options",
+ type: "extension",
+ operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE,
+ optionsType: AddonManager.OPTIONS_TYPE_INLINE_BROWSER,
+ optionsURL: "about:blank",
}]);
gManagerWindow = await open_manager(null);
gDocument = gManagerWindow.document;
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
});
function get_item_in_list(aId, aList) {
@@ -404,11 +421,74 @@ add_task(async function() {
is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension");
item = get_item_in_list(ID, list);
is(item, null, "Should not have found the add-on in the list");
item = get_item_in_list(ID2, list);
is(item, null, "Should not have found the second add-on in the list");
});
+// Tests that uninstalling an extension with inline options from the
+// details view works.
+add_task(async function() {
+ var ID = "addon5@tests.mozilla.org";
+ var list = gDocument.getElementById("addon-list");
+
+ // Select the extensions category
+ await gCategoryUtilities.openType("extension");
+ is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension");
+
+ let addon = await AddonManager.getAddonByID(ID);
+ ok(addon.isActive, "Add-on should be active");
+ ok(!(addon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall");
+ ok(!(addon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall");
+
+ var item = get_item_in_list(ID, list);
+ isnot(item, null, "Should have found the add-on in the list");
+
+ EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
+ EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
+ await Promise.all([
+ promiseViewLoaded(gManagerWindow),
+ promiseOptionsPageLoaded(),
+ ]);
+
+ is(get_current_view(gManagerWindow).id, "detail-view", "Should be in the detail view");
+
+ var button = gDocument.getElementById("detail-uninstall-btn");
+ isnot(button, null, "Should have a remove button");
+ ok(!button.disabled, "Button should not be disabled");
+
+ EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow);
+
+ await promiseViewLoaded(gManagerWindow);
+ is(gCategoryUtilities.selectedCategory, "extension", "View should have changed to extension");
+
+ item = get_item_in_list(ID, list);
+ isnot(item, null, "Should have found the add-on in the list");
+ is(item.getAttribute("pending"), "uninstall", "Add-on should be uninstalling");
+
+ ok(!!(addon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall");
+ ok(!addon.isActive, "Add-on should be inactive");
+
+ // Force XBL to apply
+ item.clientTop;
+
+ button = gDocument.getAnonymousElementByAttribute(item, "anonid", "restart-btn");
+ isnot(button, null, "Should have a restart button");
+ ok(button.hidden, "Restart button should be hidden");
+ button = gDocument.getAnonymousElementByAttribute(item, "anonid", "undo-btn");
+ isnot(button, null, "Should have an undo button");
+
+ EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow);
+
+ // Force XBL to apply
+ item.clientTop;
+
+ ok(addon.isActive, "Add-on should be active");
+ button = gDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn");
+ isnot(button, null, "Should have a remove button");
+ ok(!button.disabled, "Button should not be disabled");
+});
+
add_task(function finish() {
return close_manager(gManagerWindow);
});