261 lines
7.9 KiB
JavaScript
261 lines
7.9 KiB
JavaScript
/* 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/. */
|
|
|
|
const lazy = {};
|
|
|
|
ChromeUtils.defineESModuleGetters(lazy, {
|
|
AppMenuNotifications: "resource://gre/modules/AppMenuNotifications.sys.mjs",
|
|
ASRouter: "resource:///modules/asrouter/ASRouter.sys.mjs",
|
|
PanelMultiView: "resource:///modules/PanelMultiView.sys.mjs",
|
|
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
|
|
RemoteL10n: "resource:///modules/asrouter/RemoteL10n.sys.mjs",
|
|
SpecialMessageActions:
|
|
"resource://messaging-system/lib/SpecialMessageActions.sys.mjs",
|
|
UIState: "resource://services-sync/UIState.sys.mjs",
|
|
});
|
|
|
|
export const MenuMessage = {
|
|
SOURCES: Object.freeze({
|
|
APP_MENU: "app_menu",
|
|
PXI_MENU: "pxi_menu",
|
|
}),
|
|
|
|
SHOWING_FXA_MENU_MESSAGE_ATTR: "showing-fxa-menu-message",
|
|
|
|
async showMenuMessage(browser, message, trigger, force) {
|
|
if (!browser) {
|
|
return;
|
|
}
|
|
|
|
let win = browser.ownerGlobal;
|
|
|
|
if (!win || lazy.PrivateBrowsingUtils.isWindowPrivate(win)) {
|
|
return;
|
|
}
|
|
|
|
let source = trigger?.context?.source || message.testingTriggerContext;
|
|
|
|
switch (source) {
|
|
case MenuMessage.SOURCES.APP_MENU: {
|
|
this.showAppMenuMessage(browser, message, force);
|
|
break;
|
|
}
|
|
case MenuMessage.SOURCES.PXI_MENU: {
|
|
this.showPxiMenuMessage(browser, message, force);
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
|
|
async showAppMenuMessage(browser, message, force) {
|
|
const win = browser.ownerGlobal;
|
|
const msgContainer = this.hideAppMenuMessage(browser);
|
|
|
|
// This version of the browser only supports the fxa_cta version
|
|
// of this message in the AppMenu. We also don't draw focus away from any
|
|
// existing AppMenuNotifications.
|
|
if (
|
|
!message ||
|
|
message.content.messageType !== "fxa_cta" ||
|
|
lazy.AppMenuNotifications.activeNotification
|
|
) {
|
|
return;
|
|
}
|
|
|
|
// Since we know this is an fxa_cta message, we know that if we're already
|
|
// signed in, we don't want to show it in the AppMenu.
|
|
if (lazy.UIState.get().status === lazy.UIState.STATUS_SIGNED_IN) {
|
|
return;
|
|
}
|
|
|
|
win.PanelUI.mainView.setAttribute(
|
|
MenuMessage.SHOWING_FXA_MENU_MESSAGE_ATTR,
|
|
message.id
|
|
);
|
|
|
|
let msgElement = await this.constructFxAMessage(
|
|
win,
|
|
message,
|
|
MenuMessage.SOURCES.APP_MENU
|
|
);
|
|
|
|
msgElement.addEventListener("FxAMenuMessage:Close", () => {
|
|
win.PanelUI.mainView.removeAttribute(
|
|
MenuMessage.SHOWING_FXA_MENU_MESSAGE_ATTR
|
|
);
|
|
});
|
|
|
|
msgElement.addEventListener("FxAMenuMessage:SignUp", () => {
|
|
win.PanelUI.hide();
|
|
});
|
|
|
|
msgContainer.appendChild(msgElement);
|
|
|
|
if (force) {
|
|
win.PanelUI.show();
|
|
}
|
|
},
|
|
|
|
hideAppMenuMessage(browser) {
|
|
const win = browser.ownerGlobal;
|
|
const document = browser.ownerDocument;
|
|
const msgContainer = lazy.PanelMultiView.getViewNode(
|
|
document,
|
|
"appMenu-fxa-menu-message"
|
|
);
|
|
msgContainer.innerHTML = "";
|
|
win.PanelUI.mainView.removeAttribute(
|
|
MenuMessage.SHOWING_FXA_MENU_MESSAGE_ATTR
|
|
);
|
|
|
|
return msgContainer;
|
|
},
|
|
|
|
async showPxiMenuMessage(browser, message, force) {
|
|
const win = browser.ownerGlobal;
|
|
const { document } = win;
|
|
const msgContainer = this.hidePxiMenuMessage(browser);
|
|
|
|
// This version of the browser only supports the fxa_cta version
|
|
// of this message in the PXI menu.
|
|
if (!message || message.content.messageType !== "fxa_cta") {
|
|
return;
|
|
}
|
|
|
|
// Since we know this is an fxa_cta message, we know that if we're already
|
|
// signed in, we don't want to show it in the AppMenu.
|
|
if (lazy.UIState.get().status === lazy.UIState.STATUS_SIGNED_IN) {
|
|
return;
|
|
}
|
|
|
|
let fxaPanelView = lazy.PanelMultiView.getViewNode(document, "PanelUI-fxa");
|
|
fxaPanelView.setAttribute(
|
|
MenuMessage.SHOWING_FXA_MENU_MESSAGE_ATTR,
|
|
message.id
|
|
);
|
|
|
|
let msgElement = await this.constructFxAMessage(
|
|
win,
|
|
message,
|
|
MenuMessage.SOURCES.PXI_MENU
|
|
);
|
|
|
|
msgElement.addEventListener("FxAMenuMessage:Close", () => {
|
|
fxaPanelView.removeAttribute(MenuMessage.SHOWING_FXA_MENU_MESSAGE_ATTR);
|
|
});
|
|
|
|
msgElement.addEventListener("FxAMenuMessage:SignUp", () => {
|
|
let panelNode = fxaPanelView.closest("panel");
|
|
|
|
if (panelNode) {
|
|
lazy.PanelMultiView.hidePopup(panelNode);
|
|
}
|
|
});
|
|
|
|
msgContainer.appendChild(msgElement);
|
|
|
|
if (force) {
|
|
await win.gSync.toggleAccountPanel(
|
|
document.getElementById("fxa-toolbar-menu-button"),
|
|
new MouseEvent("mousedown")
|
|
);
|
|
}
|
|
},
|
|
|
|
hidePxiMenuMessage(browser) {
|
|
const document = browser.ownerDocument;
|
|
const msgContainer = lazy.PanelMultiView.getViewNode(
|
|
document,
|
|
"PanelUI-fxa-menu-message"
|
|
);
|
|
msgContainer.innerHTML = "";
|
|
let fxaPanelView = lazy.PanelMultiView.getViewNode(document, "PanelUI-fxa");
|
|
fxaPanelView.removeAttribute(MenuMessage.SHOWING_FXA_MENU_MESSAGE_ATTR);
|
|
return msgContainer;
|
|
},
|
|
|
|
async constructFxAMessage(win, message, source) {
|
|
let { document, gBrowser } = win;
|
|
|
|
win.MozXULElement.insertFTLIfNeeded("browser/newtab/asrouter.ftl");
|
|
|
|
const msgElement = document.createElement("fxa-menu-message");
|
|
msgElement.layout = message.content.layout ?? "column";
|
|
msgElement.imageURL = message.content.imageURL;
|
|
msgElement.buttonText = await lazy.RemoteL10n.formatLocalizableText(
|
|
message.content.primaryActionText
|
|
);
|
|
msgElement.primaryText = await lazy.RemoteL10n.formatLocalizableText(
|
|
message.content.primaryText
|
|
);
|
|
msgElement.secondaryText = await lazy.RemoteL10n.formatLocalizableText(
|
|
message.content.secondaryText
|
|
);
|
|
msgElement.dataset.navigableWithTabOnly = "true";
|
|
if (message.content.imageWidth !== undefined) {
|
|
msgElement.style.setProperty(
|
|
"--image-width",
|
|
`${message.content.imageWidth}px`
|
|
);
|
|
}
|
|
msgElement.style.setProperty(
|
|
"--illustration-margin-block-start-offset",
|
|
`${message.content.imageVerticalTopOffset}px`
|
|
);
|
|
msgElement.style.setProperty(
|
|
"--illustration-margin-block-end-offset",
|
|
`${message.content.imageVerticalBottomOffset}px`
|
|
);
|
|
msgElement.style.setProperty(
|
|
"--container-margin-block-end-offset",
|
|
`${message.content.containerVerticalBottomOffset}px`
|
|
);
|
|
|
|
msgElement.addEventListener("FxAMenuMessage:Close", () => {
|
|
msgElement.remove();
|
|
|
|
this.recordMenuMessageTelemetry("DISMISS", source, message.id);
|
|
|
|
lazy.SpecialMessageActions.handleAction(
|
|
message.content.closeAction,
|
|
gBrowser.selectedBrowser
|
|
);
|
|
});
|
|
|
|
msgElement.addEventListener("FxAMenuMessage:SignUp", () => {
|
|
this.recordMenuMessageTelemetry("CLICK", source, message.id);
|
|
|
|
// Depending on the source that showed the message, we'll want to set
|
|
// a particular entrypoint in the data payload in the event that we're
|
|
// opening up the FxA sign-up page.
|
|
let clonedPrimaryAction = structuredClone(message.content.primaryAction);
|
|
if (source === MenuMessage.SOURCES.APP_MENU) {
|
|
clonedPrimaryAction.data.entrypoint = "fxa_app_menu";
|
|
clonedPrimaryAction.data.extraParams.utm_content += "-app_menu";
|
|
} else if (source === MenuMessage.SOURCES.PXI_MENU) {
|
|
clonedPrimaryAction.data.entrypoint = "fxa_avatar_menu";
|
|
clonedPrimaryAction.data.extraParams.utm_content += "-avatar";
|
|
}
|
|
|
|
lazy.SpecialMessageActions.handleAction(
|
|
clonedPrimaryAction,
|
|
gBrowser.selectedBrowser
|
|
);
|
|
});
|
|
|
|
return msgElement;
|
|
},
|
|
|
|
recordMenuMessageTelemetry(event, source, messageId) {
|
|
let ping = {
|
|
message_id: messageId,
|
|
event,
|
|
source,
|
|
};
|
|
lazy.ASRouter.dispatchCFRAction({
|
|
type: "MENU_MESSAGE_TELEMETRY",
|
|
data: { action: "menu_message_user_event", ...ping },
|
|
});
|
|
},
|
|
};
|