summaryrefslogtreecommitdiffstats
path: root/browser/components/newtab/lib/ToastNotification.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/newtab/lib/ToastNotification.jsm')
-rw-r--r--browser/components/newtab/lib/ToastNotification.jsm118
1 files changed, 118 insertions, 0 deletions
diff --git a/browser/components/newtab/lib/ToastNotification.jsm b/browser/components/newtab/lib/ToastNotification.jsm
new file mode 100644
index 0000000000..0b2d756415
--- /dev/null
+++ b/browser/components/newtab/lib/ToastNotification.jsm
@@ -0,0 +1,118 @@
+/* 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/. */
+"use strict";
+
+const { XPCOMUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/XPCOMUtils.sys.mjs"
+);
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ ExperimentAPI: "resource://nimbus/ExperimentAPI.sys.mjs",
+ RemoteL10n: "resource://activity-stream/lib/RemoteL10n.sys.mjs",
+});
+
+XPCOMUtils.defineLazyServiceGetters(lazy, {
+ AlertsService: ["@mozilla.org/alerts-service;1", "nsIAlertsService"],
+});
+
+const ToastNotification = {
+ // Allow testing to stub the alerts service.
+ get AlertsService() {
+ return lazy.AlertsService;
+ },
+
+ sendUserEventTelemetry(event, message, dispatch) {
+ const ping = {
+ message_id: message.id,
+ event,
+ };
+ dispatch({
+ type: "TOAST_NOTIFICATION_TELEMETRY",
+ data: { action: "toast_notification_user_event", ...ping },
+ });
+ },
+
+ /**
+ * Show a toast notification.
+ * @param message Message containing content to show.
+ * @param dispatch A function to dispatch resulting actions.
+ * @return boolean value capturing if toast notification was displayed.
+ */
+ async showToastNotification(message, dispatch) {
+ let { content } = message;
+ let title = await lazy.RemoteL10n.formatLocalizableText(content.title);
+ let body = await lazy.RemoteL10n.formatLocalizableText(content.body);
+
+ // The only link between background task message experiment and user
+ // re-engagement via the notification is the associated "tag". Said tag is
+ // usually controlled by the message content, but for message experiments,
+ // we want to avoid a missing tag and to ensure a deterministic tag for
+ // easier analysis, including across branches.
+ let { tag } = content;
+
+ let experimentMetadata =
+ lazy.ExperimentAPI.getExperimentMetaData({
+ featureId: "backgroundTaskMessage",
+ }) || {};
+
+ if (
+ experimentMetadata?.active &&
+ experimentMetadata?.slug &&
+ experimentMetadata?.branch?.slug
+ ) {
+ // Like `my-experiment:my-branch`.
+ tag = `${experimentMetadata?.slug}:${experimentMetadata?.branch?.slug}`;
+ }
+
+ // There are two events named `IMPRESSION` the first one refers to telemetry
+ // while the other refers to ASRouter impressions used for the frequency cap
+ this.sendUserEventTelemetry("IMPRESSION", message, dispatch);
+ dispatch({ type: "IMPRESSION", data: message });
+
+ let alert = Cc["@mozilla.org/alert-notification;1"].createInstance(
+ Ci.nsIAlertNotification
+ );
+ let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
+ alert.init(
+ tag,
+ content.image_url
+ ? Services.urlFormatter.formatURL(content.image_url)
+ : content.image_url,
+ title,
+ body,
+ true /* aTextClickable */,
+ content.data,
+ null /* aDir */,
+ null /* aLang */,
+ null /* aData */,
+ systemPrincipal,
+ null /* aInPrivateBrowsing */,
+ content.requireInteraction
+ );
+
+ if (content.actions) {
+ let actions = Cu.cloneInto(content.actions, {});
+ for (let action of actions) {
+ if (action.title) {
+ action.title = await lazy.RemoteL10n.formatLocalizableText(
+ action.title
+ );
+ }
+ }
+ alert.actions = actions;
+ }
+
+ if (content.launch_url) {
+ alert.launchURL = Services.urlFormatter.formatURL(content.launch_url);
+ }
+
+ this.AlertsService.showAlert(alert);
+
+ return true;
+ },
+};
+
+const EXPORTED_SYMBOLS = ["ToastNotification"];