Bug 1525178 - Part 2: Refactor AddonCardListenerHandler r=rpl

Differential Revision: https://phabricator.services.mozilla.com/D60423

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Mark Striemer 2020-03-30 19:44:54 +00:00
parent 541c10fc2d
commit 1a49c36c2c

View File

@ -130,72 +130,91 @@ function shouldSkipAnimations() {
);
}
const AddonCardListenerHandler = {
ADDON_EVENTS: new Set([
"onDisabled",
"onEnabled",
"onInstalled",
"onPropertyChanged",
"onUninstalling",
]),
MANAGER_EVENTS: new Set(["onUpdateModeChanged"]),
INSTALL_EVENTS: new Set(["onNewInstall", "onInstallEnded"]),
delegateAddonEvent(name, args) {
this.delegateEvent(name, args[0], args);
},
delegateInstallEvent(name, args) {
let addon = args[0].addon || args[0].existingAddon;
if (!addon) {
return;
}
this.delegateEvent(name, addon, args);
},
delegateEvent(name, addon, args) {
let elements;
if (this.MANAGER_EVENTS.has(name)) {
elements = document.querySelectorAll("addon-card, addon-page-options");
} else {
let cardSelector = `addon-card[addon-id="${addon.id}"]`;
elements = document.querySelectorAll(
`${cardSelector}, ${cardSelector} addon-details`
);
}
for (let el of elements) {
try {
if (name in el) {
el[name](...args);
}
} catch (e) {
Cu.reportError(e);
function callListeners(name, args, listeners) {
for (let listener of listeners) {
try {
if (name in listener) {
listener[name](...args);
}
} catch (e) {
Cu.reportError(e);
}
}
}
const AddonManagerListenerHandler = {
listeners: new Set(),
addListener(listener) {
this.listeners.add(listener);
},
removeListener(listener) {
this.listeners.delete(listener);
},
delegateEvent(name, args) {
callListeners(name, args, this.listeners);
},
startup() {
for (let name of this.ADDON_EVENTS) {
this[name] = (...args) => this.delegateAddonEvent(name, args);
}
for (let name of this.INSTALL_EVENTS) {
this[name] = (...args) => this.delegateInstallEvent(name, args);
}
for (let name of this.MANAGER_EVENTS) {
this[name] = (...args) => this.delegateEvent(name, null, args);
}
AddonManager.addAddonListener(this);
AddonManager.addInstallListener(this);
AddonManager.addManagerListener(this);
this._listener = new Proxy(
{},
{
has: () => true,
get: (_, name) => (...args) => this.delegateEvent(name, args),
}
);
AddonManager.addAddonListener(this._listener);
AddonManager.addInstallListener(this._listener);
AddonManager.addManagerListener(this._listener);
},
shutdown() {
AddonManager.removeAddonListener(this);
AddonManager.removeInstallListener(this);
AddonManager.removeManagerListener(this);
AddonManager.removeAddonListener(this._listener);
AddonManager.removeInstallListener(this._listener);
AddonManager.removeManagerListener(this._listener);
},
};
/**
* This object wires the AddonManager event listeners into addon-card and
* addon-details elements rather than needing to add/remove listeners all the
* time as the view changes.
*/
const AddonCardListenerHandler = new Proxy(
{},
{
has: () => true,
get(_, name) {
return (...args) => {
let elements = [];
let addon;
// We expect args[0] to be of type:
// - AddonInstall, on AddonManager install events
// - AddonWrapper, on AddonManager addon events
// - undefined, on AddonManager manage events
if (args[0]) {
addon = args[0].addon || args[0].existingAddon || args[0];
}
if (addon && addon.id) {
let cardSelector = `addon-card[addon-id="${addon.id}"]`;
elements = document.querySelectorAll(
`${cardSelector}, ${cardSelector} addon-details`
);
} else {
elements = document.querySelectorAll("addon-card");
}
callListeners(name, args, elements);
};
},
}
);
AddonManagerListenerHandler.addListener(AddonCardListenerHandler);
function isAbuseReportSupported(addon) {
return (
ABUSE_REPORT_ENABLED &&
@ -1184,12 +1203,12 @@ class GlobalWarnings extends MessageBarStackElement {
connectedCallback() {
this.refresh();
this.addEventListener("click", this);
AddonManager.addManagerListener(this);
AddonManagerListenerHandler.addListener(this);
}
disconnectedCallback() {
this.removeEventListener("click", this);
AddonManager.removeManagerListener(this);
AddonManagerListenerHandler.removeListener(this);
}
refresh() {
@ -1253,6 +1272,10 @@ class GlobalWarnings extends MessageBarStackElement {
}
}
/**
* AddonManager listener events.
*/
onCompatibilityModeChanged() {
this.refresh();
}
@ -1407,11 +1430,13 @@ class AddonPageOptions extends HTMLElement {
}
this.addEventListener("click", this);
this.panel.addEventListener("showing", this);
AddonManagerListenerHandler.addListener(this);
}
disconnectedCallback() {
this.removeEventListener("click", this);
this.panel.removeEventListener("showing", this);
AddonManagerListenerHandler.removeListener(this);
}
toggle(...args) {
@ -1481,14 +1506,6 @@ class AddonPageOptions extends HTMLElement {
}
}
onUpdateModeChanged() {
let updatesEnabled = this.automaticUpdatesEnabled();
this.toggleUpdatesEl.checked = updatesEnabled;
let resetType = updatesEnabled ? "automatic" : "manual";
let resetStringId = `addon-updates-reset-updates-to-${resetType}`;
document.l10n.setAttributes(this.resetUpdatesEl, resetStringId);
}
async checkForUpdates(e) {
this.recordActionEvent({ action: "checkForUpdates" });
let message = document.getElementById("updates-message");
@ -1583,6 +1600,18 @@ class AddonPageOptions extends HTMLElement {
},
});
}
/**
* AddonManager listener events.
*/
onUpdateModeChanged() {
let updatesEnabled = this.automaticUpdatesEnabled();
this.toggleUpdatesEl.checked = updatesEnabled;
let resetType = updatesEnabled ? "automatic" : "manual";
let resetStringId = `addon-updates-reset-updates-to-${resetType}`;
document.l10n.setAttributes(this.resetUpdatesEl, resetStringId);
}
}
customElements.define("addon-page-options", AddonPageOptions);
@ -2630,51 +2659,6 @@ class AddonCard extends HTMLElement {
this.panel.removeEventListener("hidden", this);
}
onNewInstall(install) {
this.updateInstall = install;
this.sendEvent("update-found");
}
onInstallEnded(install) {
this.setAddon(install.addon);
}
onDisabled(addon) {
if (!this.reloading) {
this.update();
}
}
onEnabled(addon) {
this.reloading = false;
this.update();
}
onInstalled(addon) {
// When a temporary addon is reloaded, onInstalled is triggered instead of
// onEnabled.
this.reloading = false;
this.update();
}
onUninstalling() {
// Dispatch a remove event, the DetailView is listening for this to get us
// back to the list view when the current add-on is removed.
this.sendEvent("remove");
}
onUpdateModeChanged() {
this.update();
}
onPropertyChanged(addon, changed) {
if (this.details && changed.includes("applyBackgroundUpdates")) {
this.details.update();
} else if (addon.type == "plugin" && changed.includes("userDisabled")) {
this.update();
}
}
/**
* Update the card's contents based on the previously set add-on. This should
* be called if there has been a change to the add-on.
@ -2893,6 +2877,55 @@ class AddonCard extends HTMLElement {
value,
});
}
/**
* AddonManager listener events.
*/
onNewInstall(install) {
this.updateInstall = install;
this.sendEvent("update-found");
}
onInstallEnded(install) {
this.setAddon(install.addon);
}
onDisabled(addon) {
if (!this.reloading) {
this.update();
}
}
onEnabled(addon) {
this.reloading = false;
this.update();
}
onInstalled(addon) {
// When a temporary addon is reloaded, onInstalled is triggered instead of
// onEnabled.
this.reloading = false;
this.update();
}
onUninstalling() {
// Dispatch a remove event, the DetailView is listening for this to get us
// back to the list view when the current add-on is removed.
this.sendEvent("remove");
}
onUpdateModeChanged() {
this.update();
}
onPropertyChanged(addon, changed) {
if (this.details && changed.includes("applyBackgroundUpdates")) {
this.details.update();
} else if (addon.type == "plugin" && changed.includes("userDisabled")) {
this.update();
}
}
}
customElements.define("addon-card", AddonCard);
@ -3527,13 +3560,24 @@ class AddonList extends HTMLElement {
}
registerListener() {
AddonManager.addAddonListener(this);
AddonManagerListenerHandler.addListener(this);
}
removeListener() {
AddonManager.removeAddonListener(this);
AddonManagerListenerHandler.removeListener(this);
}
handleEvent(e) {
if (!this.isUserFocused || (e.type == "mouseleave" && !this.hasMenuOpen)) {
this._removeUserFocusListeners();
this.update();
}
}
/**
* AddonManager listener events.
*/
onOperationCancelled(addon) {
if (
this.pendingUninstallAddons.has(addon) &&
@ -3576,13 +3620,6 @@ class AddonList extends HTMLElement {
this.removePendingUninstallBar(addon);
this.removeAddon(addon);
}
handleEvent(e) {
if (!this.isUserFocused || (e.type == "mouseleave" && !this.hasMenuOpen)) {
this._removeUserFocusListeners();
this.update();
}
}
}
customElements.define("addon-list", AddonList);
@ -3592,11 +3629,11 @@ class RecommendedAddonList extends HTMLElement {
this.loadCardsIfNeeded();
this.updateCardsWithAddonManager();
}
AddonManager.addAddonListener(this);
AddonManagerListenerHandler.addListener(this);
}
disconnectedCallback() {
AddonManager.removeAddonListener(this);
AddonManagerListenerHandler.removeListener(this);
}
get type() {
@ -3632,20 +3669,6 @@ class RecommendedAddonList extends HTMLElement {
this.toggleAttribute("hide-installed", val);
}
onInstalled(addon) {
let card = this.getCardById(addon.id);
if (card) {
this.setAddonForCard(card, addon);
}
}
onUninstalled(addon) {
let card = this.getCardById(addon.id);
if (card) {
this.setAddonForCard(card, null);
}
}
getCardById(addonId) {
for (let card of this.children) {
if (card.addonId === addonId) {
@ -3717,6 +3740,24 @@ class RecommendedAddonList extends HTMLElement {
this.append(frag);
await this.updateCardsWithAddonManager();
}
/**
* AddonManager listener events.
*/
onInstalled(addon) {
let card = this.getCardById(addon.id);
if (card) {
this.setAddonForCard(card, addon);
}
}
onUninstalled(addon) {
let card = this.getCardById(addon.id);
if (card) {
this.setAddonForCard(card, null);
}
}
}
customElements.define("recommended-addon-list", RecommendedAddonList);
@ -4092,14 +4133,14 @@ function initialize(opts) {
loadViewFn = opts.loadViewFn;
replaceWithDefaultViewFn = opts.replaceWithDefaultViewFn;
setCategoryFn = opts.setCategoryFn;
AddonCardListenerHandler.startup();
AddonManagerListenerHandler.startup();
window.addEventListener(
"unload",
() => {
// Clear out the document so the disconnectedCallback will trigger
// properly and all of the custom elements can cleanup.
document.body.textContent = "";
AddonCardListenerHandler.shutdown();
AddonManagerListenerHandler.shutdown();
},
{ once: true }
);