зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1525179 - Use aboutaddons.html at the root of about:addons. r=robwu
- Moved aboutaddons.html at the root of the about:addons page - renamed aboutaddons.js `initialize` global function to `initializeView` (and renamed `show` and `hide` global functions accordingly) - Simplify initial load logic a bit more: - remove gCategories - moved responsability of the CategoriesBox initialization to the `initializationView` function - replaced initialization logic based on `gPendingInitializations` and `notifyInitialized` with a `promiseInitialized` global resolved when `initializeView` method has been called and its return value resolved - Fix test helpers and test failures - InlineOptionsBrowser: take into account that browser-custom-element does opt-in the delayedConnectedCallback behavior and browser.loadURI may throw if called while the document is still loading. Differential Revision: https://phabricator.services.mozilla.com/D96472
This commit is contained in:
Родитель
bedfe8bf76
Коммит
e1d14d5183
|
@ -39,11 +39,9 @@ function promiseEvent(eventEmitter, event) {
|
|||
}
|
||||
|
||||
function getAddonElement(managerWindow, addonId) {
|
||||
const { contentDocument: doc } = managerWindow.document.getElementById(
|
||||
"html-view-browser"
|
||||
);
|
||||
return BrowserTestUtils.waitForCondition(
|
||||
() => doc.querySelector(`addon-card[addon-id="${addonId}"]`),
|
||||
() =>
|
||||
managerWindow.document.querySelector(`addon-card[addon-id="${addonId}"]`),
|
||||
`Found entry for sideload extension addon "${addonId}" in HTML about:addons`
|
||||
);
|
||||
}
|
||||
|
@ -59,7 +57,7 @@ function assertSideloadedAddonElementState(addonElement, checked) {
|
|||
is(enableBtn.type, "checkbox", "It's a checkbox");
|
||||
}
|
||||
|
||||
function clickEnableExtension(managerWindow, addonElement) {
|
||||
function clickEnableExtension(addonElement) {
|
||||
addonElement.querySelector('[action="toggle-disabled"]').click();
|
||||
}
|
||||
|
||||
|
@ -218,7 +216,7 @@ add_task(async function test_sideloading() {
|
|||
);
|
||||
}
|
||||
|
||||
// XUL or HTML about:addons addon entry element.
|
||||
// about:addons addon entry element.
|
||||
const addonElement = await getAddonElement(win, ID2);
|
||||
|
||||
assertSideloadedAddonElementState(addonElement, false);
|
||||
|
@ -227,7 +225,7 @@ add_task(async function test_sideloading() {
|
|||
|
||||
// When clicking enable we should see the permissions notification
|
||||
popupPromise = promisePopupNotificationShown("addon-webext-permissions");
|
||||
clickEnableExtension(win, addonElement);
|
||||
clickEnableExtension(addonElement);
|
||||
panel = await popupPromise;
|
||||
checkNotification(panel, DEFAULT_ICON_URL, [
|
||||
["webextPerms.hostDescription.allUrls"],
|
||||
|
|
|
@ -14,13 +14,11 @@ async function installFile(filename) {
|
|||
MockFilePicker.setFiles([file]);
|
||||
MockFilePicker.afterOpenCallback = MockFilePicker.cleanup;
|
||||
|
||||
let managerWin = await BrowserOpenAddonsMgr("addons://list/extension");
|
||||
let { document } = await BrowserOpenAddonsMgr("addons://list/extension");
|
||||
|
||||
// Do the install...
|
||||
await BrowserTestUtils.waitForEvent(managerWin.document, "ViewChanged");
|
||||
let installButton = managerWin
|
||||
.getHtmlBrowser()
|
||||
.contentDocument.querySelector('[action="install-from-file"]');
|
||||
await BrowserTestUtils.waitForEvent(document, "ViewChanged");
|
||||
let installButton = document.querySelector('[action="install-from-file"]');
|
||||
installButton.click();
|
||||
}
|
||||
|
||||
|
|
|
@ -179,10 +179,7 @@ async function waitForUpdate(addon) {
|
|||
* Trigger an action from the page options menu.
|
||||
*/
|
||||
function triggerPageOptionsAction(win, action) {
|
||||
win
|
||||
.getHtmlBrowser()
|
||||
.contentDocument.querySelector(`#page-options [action="${action}"]`)
|
||||
.click();
|
||||
win.document.querySelector(`#page-options [action="${action}"]`).click();
|
||||
}
|
||||
|
||||
function isDefaultIcon(icon) {
|
||||
|
@ -484,16 +481,13 @@ async function interactiveUpdateTest(autoUpdate, checkFn) {
|
|||
if (manualUpdatePromise) {
|
||||
await manualUpdatePromise;
|
||||
|
||||
let doc = win.getHtmlBrowser().contentDocument;
|
||||
let doc = win.document;
|
||||
if (win.gViewController.currentViewId !== "addons://updates/available") {
|
||||
let showUpdatesBtn = doc.querySelector("addon-updates-message").button;
|
||||
await TestUtils.waitForCondition(() => {
|
||||
return !showUpdatesBtn.hidden;
|
||||
}, "Wait for show updates button");
|
||||
let viewChanged = BrowserTestUtils.waitForEvent(
|
||||
win.document,
|
||||
"ViewChanged"
|
||||
);
|
||||
let viewChanged = BrowserTestUtils.waitForEvent(doc, "ViewChanged");
|
||||
showUpdatesBtn.click();
|
||||
await viewChanged;
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ add_task(async function() {
|
|||
),
|
||||
]);
|
||||
|
||||
let addonsPage = gBrowser.selectedBrowser.contentWindow.document.getElementById(
|
||||
"addons-page"
|
||||
let addonsPage = gBrowser.selectedBrowser.contentWindow.document.querySelector(
|
||||
"title[data-l10n-id='addons-page-title']"
|
||||
);
|
||||
ok(addonsPage, "Add-ons page was opened");
|
||||
});
|
||||
|
|
|
@ -7,10 +7,8 @@ const BASE_URL =
|
|||
"http://mochi.test:8888/browser/browser/components/enterprisepolicies/tests/browser";
|
||||
|
||||
async function isExtensionLocked(win, addonID) {
|
||||
let addonCard = await BrowserTestUtils.waitForCondition(async () => {
|
||||
let doc = win.getHtmlBrowser().contentDocument;
|
||||
await win.htmlBrowserLoaded;
|
||||
return doc.querySelector(`addon-card[addon-id="${addonID}"]`);
|
||||
let addonCard = await BrowserTestUtils.waitForCondition(() => {
|
||||
return win.document.querySelector(`addon-card[addon-id="${addonID}"]`);
|
||||
}, `Get addon-card for "${addonID}"`);
|
||||
let disableBtn = addonCard.querySelector('[action="toggle-disabled"]');
|
||||
let removeBtn = addonCard.querySelector('panel-item[action="remove"]');
|
||||
|
|
|
@ -645,8 +645,13 @@ add_task(async function browseraction_contextmenu_report_extension() {
|
|||
"Got about:addons tab selected"
|
||||
);
|
||||
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
|
||||
// Do not wait for the about:addons tab to be loaded if its
|
||||
// document is already readyState==complete.
|
||||
// This prevents intermittent timeout failures while running
|
||||
// this test in optimized builds.
|
||||
if (browser.contentDocument?.readyState != "complete") {
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
}
|
||||
await testReportDialog();
|
||||
|
||||
// Close the new about:addons tab when running in customize mode,
|
||||
|
|
|
@ -138,12 +138,8 @@ let img =
|
|||
var imageBuffer = imageBufferFromDataURI(img);
|
||||
|
||||
function getInlineOptionsBrowser(aboutAddonsBrowser) {
|
||||
let { contentWindow } = aboutAddonsBrowser;
|
||||
let htmlBrowser = contentWindow.document.getElementById("html-view-browser");
|
||||
return (
|
||||
htmlBrowser.contentDocument.getElementById("addon-inline-options") ||
|
||||
contentWindow.document.getElementById("addon-options")
|
||||
);
|
||||
let { contentDocument } = aboutAddonsBrowser;
|
||||
return contentDocument.getElementById("addon-inline-options");
|
||||
}
|
||||
|
||||
function getListStyleImage(button) {
|
||||
|
|
|
@ -64,7 +64,7 @@ class CrashChannel final : public nsBaseChannel {
|
|||
*/
|
||||
static const RedirEntry kRedirMap[] = {
|
||||
{"about", "chrome://global/content/aboutAbout.html", 0},
|
||||
{"addons", "chrome://mozapps/content/extensions/extensions.xhtml",
|
||||
{"addons", "chrome://mozapps/content/extensions/aboutaddons.html",
|
||||
nsIAboutModule::ALLOW_SCRIPT},
|
||||
{"buildconfig", "chrome://global/content/buildconfig.html",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT},
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
<link rel="stylesheet" href="chrome://mozapps/content/extensions/aboutaddons.css">
|
||||
<link rel="stylesheet" href="chrome://mozapps/content/extensions/shortcuts.css">
|
||||
|
||||
<link rel="shortcut icon" href="chrome://mozapps/skin/extensions/extension.svg">
|
||||
|
||||
<link rel="localization" href="branding/brand.ftl">
|
||||
<link rel="localization" href="toolkit/about/aboutAddons.ftl">
|
||||
<link rel="localization" href="toolkit/about/abuseReports.ftl">
|
||||
|
@ -29,6 +31,7 @@
|
|||
<script defer src="chrome://mozapps/content/extensions/shortcuts.js"></script>
|
||||
<script defer src="chrome://mozapps/content/extensions/drag-drop-addon-installer.js"></script>
|
||||
<script defer src="chrome://mozapps/content/extensions/aboutaddons.js"></script>
|
||||
<script defer src="chrome://mozapps/content/extensions/view-controller.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<drag-drop-addon-installer></drag-drop-addon-installer>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
/* eslint max-len: ["error", 80] */
|
||||
/* exported hide, initialize, show */
|
||||
/* exported hideView, initializeView, showView */
|
||||
/* import-globals-from aboutaddonsCommon.js */
|
||||
/* import-globals-from abuse-reports.js */
|
||||
/* global MozXULElement, MessageBarStackElement, windowRoot */
|
||||
|
@ -1388,8 +1388,7 @@ class AddonPageHeader extends HTMLElement {
|
|||
this.heading.hidden = viewType === "detail";
|
||||
this.backButton.hidden = viewType !== "detail" && viewType !== "shortcuts";
|
||||
|
||||
let { contentWindow } = getBrowserElement();
|
||||
this.backButton.disabled = !contentWindow.history.state?.previousView;
|
||||
this.backButton.disabled = !history.state?.previousView;
|
||||
|
||||
if (viewType !== "detail") {
|
||||
document.l10n.setAttributes(this.heading, `${viewType}-heading`);
|
||||
|
@ -1763,12 +1762,6 @@ class CategoriesBox extends customElements.get("button-group") {
|
|||
this.promiseRendered = new Promise(resolve => {
|
||||
this._resolveRendered = resolve;
|
||||
});
|
||||
// This will resolve when the final category states have been set by
|
||||
// checking the AddonManager state and showing/hiding categories. The page
|
||||
// won't be "initialized" until this resolves.
|
||||
this.promiseInitialized = new Promise(resolve => {
|
||||
this._resolveInitialized = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
|
@ -1811,7 +1804,6 @@ class CategoriesBox extends customElements.get("button-group") {
|
|||
|
||||
this._resolveRendered();
|
||||
await hiddenUpdated;
|
||||
this._resolveInitialized();
|
||||
}
|
||||
|
||||
get initialViewId() {
|
||||
|
@ -2436,11 +2428,27 @@ class InlineOptionsBrowser extends HTMLElement {
|
|||
|
||||
mm.sendAsyncMessage("Extension:InitBrowser", browserOptions);
|
||||
|
||||
// prettier-ignore
|
||||
browser.loadURI(optionsURL, {
|
||||
triggeringPrincipal:
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
if (browser.isConnectedAndReady) {
|
||||
this.loadURI(optionsURL);
|
||||
} else {
|
||||
// browser custom element does opt-in the delayConnectedCallback
|
||||
// behavior (see connectedCallback in the custom element definition
|
||||
// from browser-custom-element.js) and so calling browser.loadURI
|
||||
// would fail if the about:addons document is not yet fully loaded.
|
||||
promiseEvent("DOMContentLoaded", document).then(() => {
|
||||
this.loadURI(optionsURL);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadURI(uri) {
|
||||
if (!this.browser || !this.browser.isConnectedAndReady) {
|
||||
throw new Error("Fail to loadURI");
|
||||
}
|
||||
|
||||
this.browser.loadURI(uri, {
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -4721,9 +4729,9 @@ var ScrollOffsets = {
|
|||
};
|
||||
|
||||
/**
|
||||
* Called from extensions.js once, when about:addons is loading.
|
||||
* Called automatically when about:addons is loading by view-controller.js.
|
||||
*/
|
||||
function initialize(opts) {
|
||||
async function initializeView(opts) {
|
||||
mainEl = document.getElementById("main");
|
||||
addonPageHeader = document.getElementById("page-header");
|
||||
categoriesBox = document.querySelector("categories-box");
|
||||
|
@ -4731,9 +4739,6 @@ function initialize(opts) {
|
|||
loadViewFn = opts.loadViewFn;
|
||||
replaceWithDefaultViewFn = opts.replaceWithDefaultViewFn;
|
||||
|
||||
if (opts.shouldLoadInitialView) {
|
||||
opts.loadInitialViewFn(categoriesBox.initialViewId);
|
||||
}
|
||||
categoriesBox.initialize();
|
||||
|
||||
AddonManagerListenerHandler.startup();
|
||||
|
@ -4755,7 +4760,7 @@ function initialize(opts) {
|
|||
* resolve once the view has been updated to conform with other about:addons
|
||||
* views.
|
||||
*/
|
||||
async function show(type, param, { historyEntryId }) {
|
||||
async function showView(type, param, { historyEntryId }) {
|
||||
let container = document.createElement("div");
|
||||
container.setAttribute("current-view", type);
|
||||
addonPageHeader.setViewInfo({ type, param });
|
||||
|
@ -4804,7 +4809,10 @@ async function show(type, param, { historyEntryId }) {
|
|||
});
|
||||
}
|
||||
|
||||
function hide() {
|
||||
async function hideView() {
|
||||
if (!mainEl) {
|
||||
return;
|
||||
}
|
||||
ScrollOffsets.save();
|
||||
ScrollOffsets.setView(null);
|
||||
mainEl.textContent = "";
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
<?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/. -->
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xhtml="http://www.w3.org/1999/xhtml"
|
||||
csp="default-src chrome:; frame-src chrome:; object-src 'none'"
|
||||
id="addons-page" data-l10n-id="addons-window"
|
||||
role="application" windowtype="Addons:Manager">
|
||||
|
||||
<xhtml:link rel="shortcut icon"
|
||||
href="chrome://mozapps/skin/extensions/extension.svg"/>
|
||||
<linkset>
|
||||
<xhtml:link rel="localization" href="branding/brand.ftl"/>
|
||||
<xhtml:link rel="localization" href="toolkit/about/aboutAddons.ftl"/>
|
||||
</linkset>
|
||||
|
||||
<script src="chrome://mozapps/content/extensions/aboutaddonsCommon.js"/>
|
||||
<script src="chrome://mozapps/content/extensions/extensions.js"/>
|
||||
|
||||
<browser id="html-view-browser" type="content" flex="1" disablehistory="true"/>
|
||||
</window>
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
/* import-globals-from ../../../content/customElements.js */
|
||||
/* import-globals-from aboutaddonsCommon.js */
|
||||
/* import-globals-from aboutaddons.js */
|
||||
/* exported loadView */
|
||||
|
||||
const { AddonManager } = ChromeUtils.import(
|
||||
|
@ -18,50 +19,32 @@ ChromeUtils.defineModuleGetter(
|
|||
"resource://gre/modules/AddonManager.jsm"
|
||||
);
|
||||
|
||||
document.addEventListener("load", initialize, true);
|
||||
window.addEventListener("unload", shutdown);
|
||||
|
||||
var gPendingInitializations = 1;
|
||||
Object.defineProperty(this, "gIsInitializing", {
|
||||
get: () => gPendingInitializations > 0,
|
||||
window.promiseInitialized = new Promise(resolve => {
|
||||
window.addEventListener("load", () => initialize(resolve), { once: true });
|
||||
});
|
||||
|
||||
function initialize(event) {
|
||||
document.removeEventListener("load", initialize, true);
|
||||
|
||||
// Support focusing the search bar from the XUL document.
|
||||
document.addEventListener("keypress", e => {
|
||||
getHtmlBrowser()
|
||||
.contentDocument.querySelector("search-addons")
|
||||
.handleEvent(e);
|
||||
});
|
||||
|
||||
gViewController.initialize();
|
||||
async function initialize(resolvePromiseInitialized) {
|
||||
Services.obs.addObserver(sendEMPong, "EM-ping");
|
||||
Services.obs.notifyObservers(window, "EM-loaded");
|
||||
|
||||
await gViewController.initialize().then(resolvePromiseInitialized);
|
||||
|
||||
// If the initial view has already been selected (by a call to loadView from
|
||||
// the above notifications) then bail out now
|
||||
if (gViewController.initialViewSelected) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is a history state to restore then use that
|
||||
if (history.state) {
|
||||
// If there is a history state to restore then use that
|
||||
gViewController.updateState(history.state);
|
||||
}
|
||||
}
|
||||
|
||||
function notifyInitialized() {
|
||||
if (!gIsInitializing) {
|
||||
return;
|
||||
}
|
||||
|
||||
gPendingInitializations--;
|
||||
if (!gIsInitializing) {
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("Initialized", true, true);
|
||||
document.dispatchEvent(event);
|
||||
} else if (!gViewController.currentViewId) {
|
||||
// Fallback to the last category or first valid category view otherwise.
|
||||
gViewController.loadInitialView(
|
||||
document.querySelector("categories-box").initialViewId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,7 +80,11 @@ async function recordViewTelemetry(param) {
|
|||
}
|
||||
|
||||
// Used by external callers to load a specific view into the manager
|
||||
function loadView(aViewId) {
|
||||
async function loadView(aViewId) {
|
||||
// Make sure to wait about:addons initialization before loading
|
||||
// a view triggered by external callers.
|
||||
await window.promiseInitialized;
|
||||
|
||||
if (!gViewController.initialViewSelected) {
|
||||
// The caller opened the window and immediately loaded the view so it
|
||||
// should be the initial history entry
|
||||
|
@ -109,8 +96,14 @@ function loadView(aViewId) {
|
|||
}
|
||||
|
||||
var gViewController = {
|
||||
defaultViewId: "addons://discover/",
|
||||
currentViewId: "",
|
||||
get defaultViewId() {
|
||||
if (!isDiscoverEnabled()) {
|
||||
return "addons://list/extension";
|
||||
}
|
||||
return "addons://discover/";
|
||||
},
|
||||
initialViewSelected: false,
|
||||
isLoading: true,
|
||||
// All historyEntryId values must be unique within one session, because the
|
||||
// IDs are used to map history entries to page state. It is not possible to
|
||||
|
@ -118,14 +111,17 @@ var gViewController = {
|
|||
// was loaded, so start counting from a random value to avoid collisions.
|
||||
// This is used for scroll offsets in aboutaddons.js
|
||||
nextHistoryEntryId: Math.floor(Math.random() * 2 ** 32),
|
||||
initialViewSelected: false,
|
||||
|
||||
initialize() {
|
||||
if (!isDiscoverEnabled()) {
|
||||
this.defaultViewId = "addons://list/extension";
|
||||
}
|
||||
|
||||
gCategories.initialize();
|
||||
async initialize() {
|
||||
await initializeView({
|
||||
loadViewFn: async view => {
|
||||
let viewId = view.startsWith("addons://") ? view : `addons://${view}`;
|
||||
await this.loadView(viewId);
|
||||
},
|
||||
replaceWithDefaultViewFn: async () => {
|
||||
await this.replaceView(this.defaultViewId);
|
||||
},
|
||||
});
|
||||
|
||||
window.addEventListener("popstate", e => {
|
||||
this.updateState(e.state);
|
||||
|
@ -173,15 +169,13 @@ var gViewController = {
|
|||
},
|
||||
|
||||
loadInitialView(aViewId) {
|
||||
var state = {
|
||||
let state = {
|
||||
view: aViewId,
|
||||
previousView: null,
|
||||
historyEntryId: ++this.nextHistoryEntryId,
|
||||
};
|
||||
history.replaceState(state, "");
|
||||
|
||||
this.loadViewInternal(aViewId, null, state);
|
||||
notifyInitialized();
|
||||
},
|
||||
|
||||
loadViewInternal(aViewId, aPreviousView, aState) {
|
||||
|
@ -193,9 +187,7 @@ var gViewController = {
|
|||
}
|
||||
|
||||
if (aViewId != aPreviousView) {
|
||||
promiseHtmlBrowserLoaded()
|
||||
.then(browser => browser.contentWindow.hide())
|
||||
.catch(err => Cu.reportError(err));
|
||||
hideView().catch(err => Cu.reportError(err));
|
||||
}
|
||||
|
||||
this.currentViewId = aViewId;
|
||||
|
@ -203,98 +195,19 @@ var gViewController = {
|
|||
|
||||
recordViewTelemetry(view.param);
|
||||
|
||||
let promiseLoad;
|
||||
if (aViewId != aPreviousView) {
|
||||
promiseHtmlBrowserLoaded()
|
||||
.then(browser =>
|
||||
browser.contentWindow.show(view.type, view.param, aState)
|
||||
)
|
||||
.then(() => {
|
||||
this.isLoading = false;
|
||||
promiseLoad = showView(view.type, view.param, aState).then(() => {
|
||||
this.isLoading = false;
|
||||
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("ViewChanged", true, true);
|
||||
document.dispatchEvent(event);
|
||||
});
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("ViewChanged", true, true);
|
||||
document.dispatchEvent(event);
|
||||
});
|
||||
}
|
||||
|
||||
this.initialViewSelected = true;
|
||||
|
||||
return promiseLoad;
|
||||
},
|
||||
};
|
||||
|
||||
var gCategories = {
|
||||
initialize() {
|
||||
gPendingInitializations++;
|
||||
promiseHtmlBrowserLoaded().then(async browser => {
|
||||
await browser.contentWindow.customElements.whenDefined("categories-box");
|
||||
let categoriesBox = browser.contentDocument.getElementById("categories");
|
||||
await categoriesBox.promiseInitialized;
|
||||
notifyInitialized();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const htmlViewOpts = {
|
||||
loadViewFn(view) {
|
||||
let viewId = view.startsWith("addons://") ? view : `addons://${view}`;
|
||||
gViewController.loadView(viewId);
|
||||
},
|
||||
loadInitialViewFn(viewId) {
|
||||
gViewController.loadInitialView(viewId);
|
||||
},
|
||||
replaceWithDefaultViewFn() {
|
||||
gViewController.replaceView(gViewController.defaultViewId);
|
||||
},
|
||||
get shouldLoadInitialView() {
|
||||
// Let the HTML document load the view if `loadView` hasn't been called
|
||||
// externally and we don't have history to refresh from.
|
||||
return !gViewController.currentViewId && !window.history.state;
|
||||
},
|
||||
};
|
||||
|
||||
// View wrappers for the HTML version of about:addons. These delegate to an
|
||||
// HTML browser that renders the actual views.
|
||||
let htmlBrowser;
|
||||
let _htmlBrowserLoaded;
|
||||
function getHtmlBrowser() {
|
||||
if (!htmlBrowser) {
|
||||
gPendingInitializations++;
|
||||
htmlBrowser = document.getElementById("html-view-browser");
|
||||
htmlBrowser.loadURI(
|
||||
"chrome://mozapps/content/extensions/aboutaddons.html",
|
||||
{
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
}
|
||||
);
|
||||
_htmlBrowserLoaded = new Promise(resolve =>
|
||||
htmlBrowser.addEventListener("load", function loadListener() {
|
||||
if (htmlBrowser.contentWindow.location.href != "about:blank") {
|
||||
htmlBrowser.removeEventListener("load", loadListener);
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
).then(() => {
|
||||
htmlBrowser.contentWindow.initialize(htmlViewOpts);
|
||||
notifyInitialized();
|
||||
});
|
||||
}
|
||||
return htmlBrowser;
|
||||
}
|
||||
|
||||
async function promiseHtmlBrowserLoaded() {
|
||||
// Call getHtmlBrowser() first to ensure _htmlBrowserLoaded has been defined.
|
||||
let browser = getHtmlBrowser();
|
||||
await _htmlBrowserLoaded;
|
||||
return browser;
|
||||
}
|
||||
|
||||
// Helper method exported into the about:addons global, used to open the
|
||||
// abuse report panel from outside of the about:addons page
|
||||
// (e.g. triggered from the browserAction context menu).
|
||||
window.openAbuseReport = ({ addonId, reportEntryPoint }) => {
|
||||
promiseHtmlBrowserLoaded().then(browser => {
|
||||
browser.contentWindow.openAbuseReport({
|
||||
addonId,
|
||||
reportEntryPoint,
|
||||
});
|
||||
});
|
||||
};
|
|
@ -5,10 +5,6 @@
|
|||
toolkit.jar:
|
||||
% content mozapps %content/mozapps/
|
||||
#ifndef MOZ_FENNEC
|
||||
content/mozapps/extensions/extensions.xhtml (content/extensions.xhtml)
|
||||
content/mozapps/extensions/extensions.js (content/extensions.js)
|
||||
content/mozapps/extensions/blocklist.xhtml (content/blocklist.xhtml)
|
||||
content/mozapps/extensions/blocklist.js (content/blocklist.js)
|
||||
content/mozapps/extensions/OpenH264-license.txt (content/OpenH264-license.txt)
|
||||
content/mozapps/extensions/aboutaddons.html (content/aboutaddons.html)
|
||||
content/mozapps/extensions/aboutaddons.js (content/aboutaddons.js)
|
||||
|
@ -18,6 +14,8 @@ toolkit.jar:
|
|||
content/mozapps/extensions/abuse-report-frame.html (content/abuse-report-frame.html)
|
||||
content/mozapps/extensions/abuse-report-panel.css (content/abuse-report-panel.css)
|
||||
content/mozapps/extensions/abuse-report-panel.js (content/abuse-report-panel.js)
|
||||
content/mozapps/extensions/blocklist.xhtml (content/blocklist.xhtml)
|
||||
content/mozapps/extensions/blocklist.js (content/blocklist.js)
|
||||
content/mozapps/extensions/default-theme.svg (content/default-theme.svg)
|
||||
content/mozapps/extensions/drag-drop-addon-installer.js (content/drag-drop-addon-installer.js)
|
||||
content/mozapps/extensions/firefox-compact-dark.svg (content/firefox-compact-dark.svg)
|
||||
|
@ -31,6 +29,7 @@ toolkit.jar:
|
|||
content/mozapps/extensions/rating-star.css (content/rating-star.css)
|
||||
content/mozapps/extensions/shortcuts.css (content/shortcuts.css)
|
||||
content/mozapps/extensions/shortcuts.js (content/shortcuts.js)
|
||||
content/mozapps/extensions/view-controller.js (content/view-controller.js)
|
||||
|
||||
% resource default-theme %content/mozapps/extensions/default-theme/
|
||||
content/mozapps/extensions/default-theme/icon.svg (default-theme/icon.svg)
|
||||
|
|
|
@ -69,7 +69,6 @@ function check_state(canGoBack, canGoForward) {
|
|||
}
|
||||
|
||||
function is_in_list(aManager, view, canGoBack, canGoForward) {
|
||||
var doc = aManager.document;
|
||||
var categoryUtils = new CategoryUtilities(aManager);
|
||||
|
||||
is(
|
||||
|
@ -78,17 +77,15 @@ function is_in_list(aManager, view, canGoBack, canGoForward) {
|
|||
"Should be on the right category"
|
||||
);
|
||||
|
||||
doc = aManager.getHtmlBrowser().contentDocument;
|
||||
ok(
|
||||
doc.querySelector("addon-list"),
|
||||
"Got a list-view in the HTML about:addons browser"
|
||||
aManager.document.querySelector("addon-list"),
|
||||
"Got a list-view in about:addons"
|
||||
);
|
||||
|
||||
check_state(canGoBack, canGoForward);
|
||||
}
|
||||
|
||||
function is_in_detail(aManager, view, canGoBack, canGoForward) {
|
||||
var doc = aManager.document;
|
||||
var categoryUtils = new CategoryUtilities(aManager);
|
||||
|
||||
is(
|
||||
|
@ -97,20 +94,18 @@ function is_in_detail(aManager, view, canGoBack, canGoForward) {
|
|||
"Should be on the right category"
|
||||
);
|
||||
|
||||
doc = aManager.getHtmlBrowser().contentDocument;
|
||||
is(
|
||||
doc.querySelectorAll("addon-card").length,
|
||||
aManager.document.querySelectorAll("addon-card").length,
|
||||
1,
|
||||
"Got a detail-view in the HTML about:addons browser"
|
||||
"Got a detail-view in about:addons"
|
||||
);
|
||||
|
||||
check_state(canGoBack, canGoForward);
|
||||
}
|
||||
|
||||
function is_in_discovery(aManager, canGoBack, canGoForward) {
|
||||
const doc = aManager.getHtmlBrowser().contentDocument;
|
||||
ok(
|
||||
doc.querySelector("discovery-pane"),
|
||||
aManager.document.querySelector("discovery-pane"),
|
||||
"Got a discovery panel in the HTML about:addons browser"
|
||||
);
|
||||
|
||||
|
@ -190,7 +185,9 @@ add_task(async function test_navigate_between_webpage_and_aboutaddons() {
|
|||
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, "about:addons");
|
||||
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
|
||||
let manager = await wait_for_manager_load(gBrowser.contentWindow);
|
||||
let manager = await wait_for_manager_load(
|
||||
gBrowser.selectedBrowser.contentWindow
|
||||
);
|
||||
|
||||
info("Part 3");
|
||||
is_in_list(manager, "addons://list/extension", true, false);
|
||||
|
@ -501,8 +498,7 @@ add_task(async function test_history_on_detailview_extension_removed() {
|
|||
info("Part 2");
|
||||
is_in_detail(aManager, "addons://list/extension", true, false);
|
||||
|
||||
const doc = aManager.getHtmlBrowser().contentDocument;
|
||||
const addonCard = doc.querySelector(
|
||||
const addonCard = aManager.document.querySelector(
|
||||
'addon-card[addon-id="test1@tests.mozilla.org"]'
|
||||
);
|
||||
const promptService = mockPromptService();
|
||||
|
@ -604,7 +600,6 @@ add_task(async function test_initialSelectedView_on_aboutaddons_reload() {
|
|||
managerWindow.gViewController.initialViewSelected,
|
||||
"initialViewSelected is true as expected on first about:addons load"
|
||||
);
|
||||
is(managerWindow.gPendingInitializations, 0, "No pending initializations");
|
||||
|
||||
await close_manager(managerWindow);
|
||||
});
|
||||
|
|
|
@ -543,13 +543,10 @@ add_task(async function test_abusereport_from_aboutaddons_menu() {
|
|||
const extension = await installTestExtension(EXT_ID);
|
||||
|
||||
await openAboutAddons();
|
||||
await gManagerWindow.promiseHtmlBrowserLoaded();
|
||||
|
||||
AbuseReportTestUtils.assertReportPanelHidden();
|
||||
|
||||
const { contentDocument: doc } = gManagerWindow.getHtmlBrowser();
|
||||
|
||||
const addonCard = doc.querySelector(
|
||||
const addonCard = gManagerWindow.document.querySelector(
|
||||
`addon-list addon-card[addon-id="${extension.id}"]`
|
||||
);
|
||||
ok(addonCard, "Got the addon-card for the test extension");
|
||||
|
@ -580,13 +577,10 @@ add_task(async function test_abusereport_from_aboutaddons_remove() {
|
|||
const extension = await installTestExtension(EXT_ID, "theme");
|
||||
|
||||
await openAboutAddons("theme");
|
||||
await gManagerWindow.promiseHtmlBrowserLoaded();
|
||||
|
||||
AbuseReportTestUtils.assertReportPanelHidden();
|
||||
|
||||
const { contentDocument: doc } = gManagerWindow.getHtmlBrowser();
|
||||
|
||||
const addonCard = doc.querySelector(
|
||||
const addonCard = gManagerWindow.document.querySelector(
|
||||
`addon-list addon-card[addon-id="${extension.id}"]`
|
||||
);
|
||||
ok(addonCard, "Got the addon-card for the test theme extension");
|
||||
|
@ -691,6 +685,7 @@ add_task(async function test_abusereport_from_browserAction_remove() {
|
|||
menu.hidePopup();
|
||||
|
||||
let panelEl = await onceReportOpened;
|
||||
|
||||
await AbuseReportTestUtils.closeReportPanel(panelEl);
|
||||
|
||||
let onceExtStarted = AddonTestUtils.promiseWebExtensionStartup(EXT_ID);
|
||||
|
@ -862,11 +857,8 @@ add_task(async function test_abusereport_open_author_url() {
|
|||
add_task(async function test_no_report_checkbox_for_unsupported_addon_types() {
|
||||
async function test_report_checkbox_hidden(addon) {
|
||||
await openAboutAddons(addon.type);
|
||||
await gManagerWindow.promiseHtmlBrowserLoaded();
|
||||
|
||||
const { contentDocument: doc } = gManagerWindow.getHtmlBrowser();
|
||||
|
||||
const addonCard = doc.querySelector(
|
||||
const addonCard = gManagerWindow.document.querySelector(
|
||||
`addon-list addon-card[addon-id="${addon.id}"]`
|
||||
);
|
||||
ok(addonCard, "Got the addon-card for the test extension");
|
||||
|
|
|
@ -412,7 +412,7 @@ add_task(async function testPermissionsViewStates() {
|
|||
|
||||
function wait_for_addon_item_updated(addonId) {
|
||||
return BrowserTestUtils.waitForEvent(
|
||||
get_addon_element(view.managerWindow, addonId),
|
||||
get_addon_element(view, addonId),
|
||||
"update"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -123,11 +123,8 @@ async function hasPrivateAllowed(id) {
|
|||
}
|
||||
|
||||
async function assertBackButtonIsDisabled(win) {
|
||||
await win.htmlBrowserLoaded;
|
||||
|
||||
let backButton = await BrowserTestUtils.waitForCondition(async () => {
|
||||
let doc = win.getHtmlBrowser().contentDocument;
|
||||
let backButton = doc.querySelector(".back-button");
|
||||
let backButton = win.document.querySelector(".back-button");
|
||||
|
||||
// Wait until the button is visible in the page.
|
||||
return backButton && !backButton.hidden ? backButton : false;
|
||||
|
|
|
@ -158,8 +158,8 @@ async function switchToNonDiscoView(win) {
|
|||
// Listeners registered while the discopane was the active view continue to be
|
||||
// active when the view switches to the extensions list, because both views
|
||||
// share the same document.
|
||||
win.managerWindow.gViewController.loadView("addons://list/extension");
|
||||
await wait_for_view_load(win.managerWindow);
|
||||
win.gViewController.loadView("addons://list/extension");
|
||||
await wait_for_view_load(win);
|
||||
ok(
|
||||
win.document.querySelector("addon-list"),
|
||||
"Should be at the extension list view"
|
||||
|
@ -174,8 +174,8 @@ async function switchToDiscoView(win) {
|
|||
null,
|
||||
"Cannot switch to discopane when the discopane is already shown"
|
||||
);
|
||||
win.managerWindow.gViewController.loadView("addons://discover/");
|
||||
await wait_for_view_load(win.managerWindow);
|
||||
win.gViewController.loadView("addons://discover/");
|
||||
await wait_for_view_load(win);
|
||||
await promiseDiscopaneUpdate(win);
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ add_task(async function testRecentUpdatesList() {
|
|||
// Load extension view first so we can mock the startOfDay property.
|
||||
let win = await loadInitialView("extension");
|
||||
let doc = win.document;
|
||||
let categoryUtils = new CategoryUtilities(win.managerWindow);
|
||||
let categoryUtils = new CategoryUtilities(win);
|
||||
const RECENT_URL = "addons://updates/recent";
|
||||
let recentCat = categoryUtils.get("recent-updates");
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ add_task(async function setup() {
|
|||
|
||||
async function switchToView(win, type, param = "") {
|
||||
let loaded = waitForViewLoad(win);
|
||||
win.managerWindow.gViewController.loadView(`addons://${type}/${param}`);
|
||||
win.gViewController.loadView(`addons://${type}/${param}`);
|
||||
await loaded;
|
||||
await waitForStableLayout(win);
|
||||
}
|
||||
|
@ -71,10 +71,10 @@ async function switchToView(win, type, param = "") {
|
|||
// delta = +1 = go forwards.
|
||||
async function historyGo(win, delta, expectedViewType) {
|
||||
let loaded = waitForViewLoad(win);
|
||||
win.managerWindow.history.go(delta);
|
||||
win.history.go(delta);
|
||||
await loaded;
|
||||
is(
|
||||
win.managerWindow.gViewController.currentViewId,
|
||||
win.gViewController.currentViewId,
|
||||
expectedViewType,
|
||||
"Expected view after history navigation"
|
||||
);
|
||||
|
|
|
@ -606,7 +606,7 @@ add_task(async function testAvailableUpdates() {
|
|||
let win = await loadInitialView("extension");
|
||||
let doc = win.document;
|
||||
let updatesMessage = doc.getElementById("updates-message");
|
||||
let categoryUtils = new CategoryUtilities(win.managerWindow);
|
||||
let categoryUtils = new CategoryUtilities(win);
|
||||
|
||||
let availableCat = categoryUtils.get("available-updates");
|
||||
|
||||
|
@ -727,7 +727,7 @@ add_task(async function testUpdatesShownOnLoad() {
|
|||
await findUpdatesForAddonId(id);
|
||||
|
||||
let win = await loadInitialView("extension");
|
||||
let categoryUtils = new CategoryUtilities(win.managerWindow);
|
||||
let categoryUtils = new CategoryUtilities(win);
|
||||
let updatesButton = categoryUtils.get("available-updates");
|
||||
|
||||
ok(!updatesButton.hidden, "The updates button is shown");
|
||||
|
@ -752,7 +752,7 @@ add_task(async function testUpdatesShownOnLoad() {
|
|||
info("Check that the updates section is hidden when re-opened");
|
||||
await closeView(win);
|
||||
win = await loadInitialView("extension");
|
||||
categoryUtils = new CategoryUtilities(win.managerWindow);
|
||||
categoryUtils = new CategoryUtilities(win);
|
||||
updatesButton = categoryUtils.get("available-updates");
|
||||
|
||||
ok(updatesButton.hidden, "Available updates is hidden");
|
||||
|
|
|
@ -131,8 +131,7 @@ async function init(startPage) {
|
|||
|
||||
await gCategoryUtilities.openType(startPage);
|
||||
|
||||
return gManagerWindow.document.getElementById("html-view-browser")
|
||||
.contentDocument;
|
||||
return gManagerWindow.document;
|
||||
}
|
||||
|
||||
/* Test functions start here. */
|
||||
|
|
|
@ -18,7 +18,7 @@ async function loadShortcutsView() {
|
|||
// Load the theme view initially so we can verify that the category is switched
|
||||
// to "extension" when the shortcuts view is loaded.
|
||||
let win = await loadInitialView("theme");
|
||||
let categoryUtils = new CategoryUtilities(win.managerWindow);
|
||||
let categoryUtils = new CategoryUtilities(win);
|
||||
|
||||
is(
|
||||
categoryUtils.getSelectedViewId(),
|
||||
|
@ -86,11 +86,24 @@ add_task(async function testUpdatingCommands() {
|
|||
);
|
||||
}
|
||||
|
||||
// Load the about:addons shortcut view before verify that emitting
|
||||
// the key events does trigger the expected extension commands.
|
||||
// There is apparently a race (more likely to be triggered on an
|
||||
// optimized build) between:
|
||||
// - the new opened browser window to be ready to listen for the
|
||||
// keyboard events that are expected to triggered one of the key
|
||||
// in the extension keyset
|
||||
// - and the test calling EventUtils.syntesizeKey to test that
|
||||
// the expected extension command listener is notified.
|
||||
//
|
||||
// Loading the shortcut view before calling checkShortcut seems to be
|
||||
// enough to consistently avoid that race condition.
|
||||
let win = await loadShortcutsView();
|
||||
|
||||
// Check that the original shortcuts work.
|
||||
await checkShortcut("commandOne", "7", { shiftKey: true, altKey: true });
|
||||
await checkShortcut("commandTwo", "4", { altKey: true });
|
||||
|
||||
let win = await loadShortcutsView();
|
||||
let doc = win.document;
|
||||
|
||||
let card = doc.querySelector(`.card[addon-id="${extension.id}"]`);
|
||||
|
|
|
@ -5,8 +5,7 @@ async function loadShortcutsView() {
|
|||
let managerWin = await open_manager(null);
|
||||
managerWin.gViewController.loadView("addons://shortcuts/shortcuts");
|
||||
await wait_for_view_load(managerWin);
|
||||
return managerWin.document.getElementById("html-view-browser")
|
||||
.contentDocument;
|
||||
return managerWin.document;
|
||||
}
|
||||
|
||||
async function closeShortcutsView(doc) {
|
||||
|
|
|
@ -4,8 +4,7 @@ async function loadShortcutsView() {
|
|||
let managerWin = await open_manager(null);
|
||||
managerWin.gViewController.loadView("addons://shortcuts/shortcuts");
|
||||
await wait_for_view_load(managerWin);
|
||||
return managerWin.document.getElementById("html-view-browser")
|
||||
.contentDocument;
|
||||
return managerWin.document;
|
||||
}
|
||||
|
||||
async function closeShortcutsView(doc) {
|
||||
|
|
|
@ -40,7 +40,7 @@ function assertEnabledSideloadedExtensionElement(managerWindow, addonElement) {
|
|||
ok(!toggleDisabled.checked, "toggle-disable isn't checked");
|
||||
}
|
||||
|
||||
function clickEnableExtension(managerWindow, addonElement) {
|
||||
function clickEnableExtension(addonElement) {
|
||||
addonElement.querySelector('[action="toggle-disabled"]').click();
|
||||
}
|
||||
|
||||
|
@ -80,11 +80,11 @@ add_task(async function test_theme_enable() {
|
|||
// enable fresh installed theme
|
||||
let manager = await open_manager("addons://list/theme");
|
||||
let customTheme = get_addon_element(manager, CUSTOM_THEME_ID);
|
||||
clickEnableExtension(manager, customTheme);
|
||||
clickEnableExtension(customTheme);
|
||||
|
||||
// enable default theme again
|
||||
let defaultTheme = get_addon_element(manager, DEFAULT_THEME_ID);
|
||||
clickEnableExtension(manager, defaultTheme);
|
||||
clickEnableExtension(defaultTheme);
|
||||
|
||||
let addon = await AddonManager.getAddonByID(CUSTOM_THEME_ID);
|
||||
await close_manager(manager);
|
||||
|
@ -128,7 +128,7 @@ add_task(async function test_sideloaded_extension_permissions_prompt() {
|
|||
assertDisabledSideloadedExtensionElement(manager, addon);
|
||||
|
||||
let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
|
||||
clickEnableExtension(manager, addon);
|
||||
clickEnableExtension(addon);
|
||||
let panel = await popupPromise;
|
||||
|
||||
ok(PopupNotifications.isPanelOpen, "Permission popup should be visible");
|
||||
|
@ -151,7 +151,7 @@ add_task(async function test_sideloaded_extension_permissions_prompt() {
|
|||
assertEnabledSideloadedExtensionElement(manager, addon);
|
||||
|
||||
popupPromise = promisePopupNotificationShown("addon-webext-permissions");
|
||||
clickEnableExtension(manager, addon);
|
||||
clickEnableExtension(addon);
|
||||
panel = await popupPromise;
|
||||
|
||||
ok(PopupNotifications.isPanelOpen, "Permission popup should be visible");
|
||||
|
|
|
@ -15,8 +15,7 @@ const testIdSuffix = "@tests.mozilla.org";
|
|||
let gManagerWindow, xpi1, xpi2;
|
||||
|
||||
function htmlDoc() {
|
||||
return gManagerWindow.document.getElementById("html-view-browser")
|
||||
.contentDocument;
|
||||
return gManagerWindow.document;
|
||||
}
|
||||
|
||||
function get_list_item_count() {
|
||||
|
|
|
@ -25,18 +25,13 @@ function testKeys(win, searchBox) {
|
|||
searchBox.blur();
|
||||
}
|
||||
|
||||
// Get a stack frame with the expected browser type.
|
||||
const testHtmlKeys = (...args) => testKeys(...args);
|
||||
const testXulKeys = (...args) => testKeys(...args);
|
||||
|
||||
add_task(async function testSearchBarKeyboardAccess() {
|
||||
let win = await loadInitialView("extension");
|
||||
|
||||
let doc = win.document;
|
||||
let searchBox = doc.querySelector("search-addons").input;
|
||||
|
||||
testHtmlKeys(win, searchBox);
|
||||
testXulKeys(win.managerWindow, searchBox);
|
||||
testKeys(win, searchBox);
|
||||
|
||||
await closeView(win);
|
||||
});
|
||||
|
|
|
@ -54,8 +54,7 @@ add_task(async function testClickingSidebarEntriesChangesView() {
|
|||
|
||||
add_task(async function testClickingSidebarPaddingNoChange() {
|
||||
let win = await loadInitialView("theme");
|
||||
let { managerWindow } = win;
|
||||
let categoryUtils = new CategoryUtilities(managerWindow);
|
||||
let categoryUtils = new CategoryUtilities(win);
|
||||
let themeCategory = categoryUtils.get("theme");
|
||||
|
||||
let loadDetailView = async () => {
|
||||
|
@ -64,7 +63,7 @@ add_task(async function testClickingSidebarPaddingNoChange() {
|
|||
await loaded;
|
||||
|
||||
is(
|
||||
managerWindow.gViewController.currentViewId,
|
||||
win.gViewController.currentViewId,
|
||||
`addons://detail/${THEME_ID}`,
|
||||
"The detail view loaded"
|
||||
);
|
||||
|
@ -76,7 +75,7 @@ add_task(async function testClickingSidebarPaddingNoChange() {
|
|||
EventUtils.synthesizeMouseAtCenter(themeCategory, {}, win);
|
||||
await loaded;
|
||||
is(
|
||||
managerWindow.gViewController.currentViewId,
|
||||
win.gViewController.currentViewId,
|
||||
`addons://list/theme`,
|
||||
"The detail view loaded"
|
||||
);
|
||||
|
@ -84,7 +83,7 @@ add_task(async function testClickingSidebarPaddingNoChange() {
|
|||
// Confirm that clicking on the padding beside it does nothing.
|
||||
await loadDetailView();
|
||||
EventUtils.synthesizeMouse(themeCategory, -5, -5, {}, win);
|
||||
ok(!managerWindow.gViewController.isLoading, "No view is loading");
|
||||
ok(!win.gViewController.isLoading, "No view is loading");
|
||||
|
||||
await closeView(win);
|
||||
});
|
||||
|
@ -108,8 +107,6 @@ add_task(async function testKeyboardUsage() {
|
|||
|
||||
ok(!isFocusInCategories(), "Focus is not in the category list");
|
||||
|
||||
// Tab into the HTML browser.
|
||||
await sendTabKey();
|
||||
// Tab to the first focusable element.
|
||||
await sendTabKey();
|
||||
|
||||
|
@ -148,7 +145,7 @@ add_task(async function testKeyboardUsage() {
|
|||
|
||||
await sendKey("VK_DOWN");
|
||||
is(win.document.activeElement, pluginCategory, "Plugins is still focused");
|
||||
ok(!win.managerWindow.gViewController.isLoading, "No view is loading");
|
||||
ok(!win.gViewController.isLoading, "No view is loading");
|
||||
|
||||
loaded = waitForViewLoad(win);
|
||||
await sendKey("VK_UP");
|
||||
|
|
|
@ -193,7 +193,7 @@ add_task(async function testLocalesHiddenIfPreviousViewAndNoLocales() {
|
|||
});
|
||||
let win = await viewLoaded;
|
||||
|
||||
let categoryUtils = new CategoryUtilities(win.managerWindow);
|
||||
let categoryUtils = new CategoryUtilities(win);
|
||||
|
||||
await TestUtils.waitForCondition(
|
||||
() => categoryUtils.selectedCategory != "locale"
|
||||
|
@ -206,7 +206,7 @@ add_task(async function testLocalesHiddenIfPreviousViewAndNoLocales() {
|
|||
|
||||
is(
|
||||
categoryUtils.getSelectedViewId(),
|
||||
win.managerWindow.gViewController.defaultViewId,
|
||||
win.gViewController.defaultViewId,
|
||||
"default view is selected"
|
||||
);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
add_task(async function testCategoryRestore() {
|
||||
let win = await loadInitialView("extension");
|
||||
let utils = new CategoryUtilities(win.managerWindow);
|
||||
let utils = new CategoryUtilities(win);
|
||||
|
||||
// Open the plugins category
|
||||
await utils.openType("plugin");
|
||||
|
@ -14,7 +14,7 @@ add_task(async function testCategoryRestore() {
|
|||
// Re-open the manager
|
||||
await closeView(win);
|
||||
win = await loadInitialView();
|
||||
utils = new CategoryUtilities(win.managerWindow);
|
||||
utils = new CategoryUtilities(win);
|
||||
|
||||
is(
|
||||
utils.selectedCategory,
|
||||
|
@ -28,7 +28,7 @@ add_task(async function testCategoryRestore() {
|
|||
// Re-open the manager
|
||||
await closeView(win);
|
||||
win = await loadInitialView();
|
||||
utils = new CategoryUtilities(win.managerWindow);
|
||||
utils = new CategoryUtilities(win);
|
||||
|
||||
is(
|
||||
utils.selectedCategory,
|
||||
|
@ -42,15 +42,15 @@ add_task(async function testCategoryRestore() {
|
|||
add_task(async function testInvalidAddonType() {
|
||||
let win = await loadInitialView("invalid");
|
||||
|
||||
let categoryUtils = new CategoryUtilities(win.managerWindow);
|
||||
let categoryUtils = new CategoryUtilities(win);
|
||||
is(
|
||||
categoryUtils.getSelectedViewId(),
|
||||
win.managerWindow.gViewController.defaultViewId,
|
||||
win.gViewController.defaultViewId,
|
||||
"default view is selected"
|
||||
);
|
||||
is(
|
||||
win.managerWindow.gViewController.currentViewId,
|
||||
win.managerWindow.gViewController.defaultViewId,
|
||||
win.gViewController.currentViewId,
|
||||
win.gViewController.defaultViewId,
|
||||
"default view is shown"
|
||||
);
|
||||
|
||||
|
@ -60,15 +60,15 @@ add_task(async function testInvalidAddonType() {
|
|||
add_task(async function testInvalidViewId() {
|
||||
let win = await loadInitialView("addons://invalid/view");
|
||||
|
||||
let categoryUtils = new CategoryUtilities(win.managerWindow);
|
||||
let categoryUtils = new CategoryUtilities(win);
|
||||
is(
|
||||
categoryUtils.getSelectedViewId(),
|
||||
win.managerWindow.gViewController.defaultViewId,
|
||||
win.gViewController.defaultViewId,
|
||||
"default view is selected"
|
||||
);
|
||||
is(
|
||||
win.managerWindow.gViewController.currentViewId,
|
||||
win.managerWindow.gViewController.defaultViewId,
|
||||
win.gViewController.currentViewId,
|
||||
win.gViewController.defaultViewId,
|
||||
"default view is shown"
|
||||
);
|
||||
|
||||
|
|
|
@ -19,9 +19,7 @@ AddonTestUtils.initMochitest(this);
|
|||
function get_test_items() {
|
||||
var items = {};
|
||||
|
||||
for (let item of gManagerWindow
|
||||
.getHtmlBrowser()
|
||||
.contentDocument.querySelectorAll("addon-card")) {
|
||||
for (let item of gManagerWindow.document.querySelectorAll("addon-card")) {
|
||||
items[item.getAttribute("addon-id")] = item;
|
||||
}
|
||||
|
||||
|
@ -29,9 +27,7 @@ function get_test_items() {
|
|||
}
|
||||
|
||||
function getHtmlElem(selector) {
|
||||
return gManagerWindow
|
||||
.getHtmlBrowser()
|
||||
.contentDocument.querySelector(selector);
|
||||
return gManagerWindow.document.querySelector(selector);
|
||||
}
|
||||
|
||||
function getPrivateBrowsingBadge(card) {
|
||||
|
|
|
@ -295,21 +295,28 @@ function check_all_in_list(aManager, aIds, aIgnoreExtras) {
|
|||
}
|
||||
}
|
||||
|
||||
// XXX(rpl): merge both get_addon_element and getAddonCard into a single helper function
|
||||
function get_addon_element(aManager, aId) {
|
||||
const win = aManager.getHtmlBrowser().contentWindow;
|
||||
return getAddonCard(win, aId);
|
||||
return getAddonCard(aManager, aId);
|
||||
}
|
||||
|
||||
function getAddonCard(win, id) {
|
||||
return win.document.querySelector(`addon-card[addon-id="${id}"]`);
|
||||
}
|
||||
|
||||
function wait_for_view_load(
|
||||
async function wait_for_view_load(
|
||||
aManagerWindow,
|
||||
aCallback,
|
||||
aForceWait,
|
||||
aLongerTimeout
|
||||
) {
|
||||
// Wait one tick to make sure that the microtask related to an
|
||||
// async loadView call originated from outsite about:addons
|
||||
// is already executing (otherwise isLoading would be still false
|
||||
// and we wouldn't be waiting for that load before resolving
|
||||
// the promise returned by this test helper function).
|
||||
await Promise.resolve();
|
||||
|
||||
let p = new Promise(resolve => {
|
||||
requestLongerTimeout(aLongerTimeout ? aLongerTimeout : 2);
|
||||
|
||||
|
@ -331,23 +338,11 @@ function wait_for_view_load(
|
|||
}
|
||||
|
||||
function wait_for_manager_load(aManagerWindow, aCallback) {
|
||||
let p = new Promise(resolve => {
|
||||
if (!aManagerWindow.gIsInitializing) {
|
||||
resolve(aManagerWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
info("Waiting for initialization");
|
||||
aManagerWindow.document.addEventListener(
|
||||
"Initialized",
|
||||
function() {
|
||||
resolve(aManagerWindow);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
});
|
||||
|
||||
return log_callback(p, aCallback);
|
||||
info("Waiting for initialization");
|
||||
return log_callback(
|
||||
aManagerWindow.promiseInitialized.then(() => aManagerWindow),
|
||||
aCallback
|
||||
);
|
||||
}
|
||||
|
||||
function open_manager(
|
||||
|
@ -537,22 +532,14 @@ async function install_addon(path, cb, pathPrefix = TESTROOT) {
|
|||
}
|
||||
|
||||
function CategoryUtilities(aManagerWindow) {
|
||||
this.window = aManagerWindow.getHtmlBrowser().contentWindow;
|
||||
this.managerWindow = aManagerWindow;
|
||||
|
||||
this.window = aManagerWindow;
|
||||
this.window.addEventListener("unload", () => (this.window = null), {
|
||||
once: true,
|
||||
});
|
||||
this.managerWindow.addEventListener(
|
||||
"unload",
|
||||
() => (this.managerWindow = null),
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
|
||||
CategoryUtilities.prototype = {
|
||||
window: null,
|
||||
managerWindow: null,
|
||||
|
||||
get _categoriesBox() {
|
||||
return this.window.document.querySelector("categories-box");
|
||||
|
@ -571,7 +558,7 @@ CategoryUtilities.prototype = {
|
|||
"Should not get selected category when manager window is not loaded"
|
||||
);
|
||||
let viewId = this.getSelectedViewId();
|
||||
let view = this.managerWindow.gViewController.parseViewId(viewId);
|
||||
let view = this.window.gViewController.parseViewId(viewId);
|
||||
return view.type == "list" ? view.param : view.type;
|
||||
},
|
||||
|
||||
|
@ -628,7 +615,7 @@ CategoryUtilities.prototype = {
|
|||
EventUtils.synthesizeMouseAtCenter(categoryButton, {}, this.window);
|
||||
|
||||
// Use wait_for_view_load until all open_manager calls are gone.
|
||||
return wait_for_view_load(this.managerWindow);
|
||||
return wait_for_view_load(this.window);
|
||||
},
|
||||
|
||||
openType(categoryType) {
|
||||
|
@ -1631,27 +1618,18 @@ async function loadInitialView(type, opts) {
|
|||
let loadCallbackDone = Promise.resolve();
|
||||
|
||||
if (opts && opts.loadCallback) {
|
||||
// Make sure the HTML browser is loaded and pass its window to the callback
|
||||
// function instead of the XUL window.
|
||||
loadCallback = managerWindow => {
|
||||
loadCallbackDone = managerWindow
|
||||
.promiseHtmlBrowserLoaded()
|
||||
.then(async browser => {
|
||||
let win = browser.contentWindow;
|
||||
win.managerWindow = managerWindow;
|
||||
// Wait for the test code to finish running before proceeding.
|
||||
await opts.loadCallback(win);
|
||||
});
|
||||
loadCallback = win => {
|
||||
loadCallbackDone = (async () => {
|
||||
// Wait for the test code to finish running before proceeding.
|
||||
await opts.loadCallback(win);
|
||||
})();
|
||||
};
|
||||
}
|
||||
let managerWindow = await open_manager(null, null, loadCallback);
|
||||
|
||||
let browser = managerWindow.document.getElementById("html-view-browser");
|
||||
let win = browser.contentWindow;
|
||||
let win = await open_manager(null, null, loadCallback);
|
||||
if (!opts || !opts.withAnimations) {
|
||||
win.document.body.setAttribute("skip-animations", "");
|
||||
}
|
||||
win.managerWindow = managerWindow;
|
||||
|
||||
// Let any load callback code to run before the rest of the test continues.
|
||||
await loadCallbackDone;
|
||||
|
@ -1660,19 +1638,19 @@ async function loadInitialView(type, opts) {
|
|||
}
|
||||
|
||||
function waitForViewLoad(win) {
|
||||
return wait_for_view_load(win.managerWindow, undefined, true);
|
||||
return wait_for_view_load(win, undefined, true);
|
||||
}
|
||||
|
||||
function closeView(win) {
|
||||
return close_manager(win.managerWindow);
|
||||
return close_manager(win);
|
||||
}
|
||||
|
||||
function switchView(win, type) {
|
||||
return new CategoryUtilities(win.managerWindow).openType(type);
|
||||
return new CategoryUtilities(win).openType(type);
|
||||
}
|
||||
|
||||
function isCategoryVisible(win, type) {
|
||||
return new CategoryUtilities(win.managerWindow).isTypeVisible(type);
|
||||
return new CategoryUtilities(win).isTypeVisible(type);
|
||||
}
|
||||
|
||||
function mockPromptService() {
|
||||
|
|
|
@ -43,21 +43,17 @@ const EXT_SYSTEM_ADDON_ID = "test-system-addon@mochi.test";
|
|||
const EXT_UNSUPPORTED_TYPE_ADDON_ID = "report-unsupported-type@mochi.test";
|
||||
const THEME_NO_UNINSTALL_ID = "theme-without-perm-can-uninstall@mochi.test";
|
||||
|
||||
let gHtmlAboutAddonsWindow;
|
||||
let gManagerWindow;
|
||||
|
||||
AddonTestUtils.initMochitest(this);
|
||||
|
||||
async function openAboutAddons(type = "extension") {
|
||||
const win = await loadInitialView(type);
|
||||
gHtmlAboutAddonsWindow = win;
|
||||
gManagerWindow = win.managerWindow;
|
||||
gManagerWindow = await loadInitialView(type);
|
||||
}
|
||||
|
||||
async function closeAboutAddons() {
|
||||
if (gHtmlAboutAddonsWindow) {
|
||||
await closeView(gHtmlAboutAddonsWindow);
|
||||
gHtmlAboutAddonsWindow = null;
|
||||
if (gManagerWindow) {
|
||||
await closeView(gManagerWindow);
|
||||
gManagerWindow = null;
|
||||
}
|
||||
}
|
||||
|
@ -314,14 +310,14 @@ const AbuseReportTestUtils = {
|
|||
}
|
||||
}
|
||||
function cleanup() {
|
||||
if (gHtmlAboutAddonsWindow) {
|
||||
gHtmlAboutAddonsWindow.document.removeEventListener(
|
||||
if (gManagerWindow) {
|
||||
gManagerWindow.document.removeEventListener(
|
||||
"abuse-report:new-message-bar",
|
||||
listener
|
||||
);
|
||||
}
|
||||
}
|
||||
gHtmlAboutAddonsWindow.document.addEventListener(
|
||||
gManagerWindow.document.addEventListener(
|
||||
"abuse-report:new-message-bar",
|
||||
listener
|
||||
);
|
||||
|
@ -331,10 +327,7 @@ const AbuseReportTestUtils = {
|
|||
// Assert that the report action is hidden on the addon card
|
||||
// for the given about:addons windows and extension id.
|
||||
async assertReportActionHidden(gManagerWindow, extId) {
|
||||
await gManagerWindow.promiseHtmlBrowserLoaded();
|
||||
const { contentDocument: doc } = gManagerWindow.getHtmlBrowser();
|
||||
|
||||
let addonCard = doc.querySelector(
|
||||
let addonCard = gManagerWindow.document.querySelector(
|
||||
`addon-list addon-card[addon-id="${extId}"]`
|
||||
);
|
||||
ok(addonCard, `Got the addon-card for the ${extId} test extension`);
|
||||
|
@ -364,7 +357,7 @@ const AbuseReportTestUtils = {
|
|||
},
|
||||
|
||||
triggerNewReport(addonId, reportEntryPoint) {
|
||||
gHtmlAboutAddonsWindow.openAbuseReport({ addonId, reportEntryPoint });
|
||||
gManagerWindow.openAbuseReport({ addonId, reportEntryPoint });
|
||||
},
|
||||
|
||||
triggerSubmit(reason, message) {
|
||||
|
@ -379,7 +372,7 @@ const AbuseReportTestUtils = {
|
|||
async openReport(addonId, reportEntryPoint = REPORT_ENTRY_POINT) {
|
||||
// Close the current about:addons window if it has been leaved open from
|
||||
// a previous test case failure.
|
||||
if (gHtmlAboutAddonsWindow) {
|
||||
if (gManagerWindow) {
|
||||
await closeAboutAddons();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ const RELATIVE_DIR = "toolkit/mozapps/extensions/test/xpinstall/";
|
|||
const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
|
||||
const TESTROOT2 = "http://example.org/browser/" + RELATIVE_DIR;
|
||||
const PROMPT_URL = "chrome://global/content/commonDialog.xhtml";
|
||||
const ADDONS_URL = "chrome://mozapps/content/extensions/extensions.xhtml";
|
||||
const ADDONS_URL = "chrome://mozapps/content/extensions/aboutaddons.html";
|
||||
const PREF_LOGGING_ENABLED = "extensions.logging.enabled";
|
||||
const PREF_INSTALL_REQUIREBUILTINCERTS =
|
||||
"extensions.install.requireBuiltInCerts";
|
||||
|
|
Загрузка…
Ссылка в новой задаче