summaryrefslogtreecommitdiffstats
path: root/browser/components/newtab/lib/Spotlight.jsm
blob: b194929c64a62d7f5ede63a4da84ec5e138378af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* 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 = {};

XPCOMUtils.defineLazyModuleGetters(lazy, {
  AboutWelcomeTelemetry:
    "resource://activity-stream/aboutwelcome/lib/AboutWelcomeTelemetry.jsm",
  RemoteImages: "resource://activity-stream/lib/RemoteImages.jsm",
  SpecialMessageActions:
    "resource://messaging-system/lib/SpecialMessageActions.jsm",
});

XPCOMUtils.defineLazyGetter(
  lazy,
  "AWTelemetry",
  () => new lazy.AboutWelcomeTelemetry()
);

const Spotlight = {
  sendUserEventTelemetry(event, message, dispatch) {
    const message_id =
      message.template === "multistage" ? message.content.id : message.id;
    const ping = {
      message_id,
      event,
    };
    dispatch({
      type: "SPOTLIGHT_TELEMETRY",
      data: { action: "spotlight_user_event", ...ping },
    });
  },

  defaultDispatch(message) {
    if (message.type === "SPOTLIGHT_TELEMETRY") {
      const { message_id, event } = message.data;
      lazy.AWTelemetry.sendTelemetry({ message_id, event });
    }
  },

  /**
   * Shows spotlight tab or window modal specific to the given browser
   * @param browser             The browser for spotlight display
   * @param message             Message containing content to show
   * @param dispatchCFRAction   A function to dispatch resulting actions
   * @return                    boolean value capturing if spotlight was displayed
   */
  async showSpotlightDialog(browser, message, dispatch = this.defaultDispatch) {
    const win = browser.ownerGlobal;
    if (win.gDialogBox.isOpen) {
      return false;
    }
    const spotlight_url = "chrome://browser/content/spotlight.html";

    const dispatchCFRAction =
      // This also blocks CFR impressions, which is fine for current use cases.
      message.content?.metrics === "block" ? () => {} : dispatch;
    let params = { primaryBtn: false, secondaryBtn: false };

    // 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, dispatchCFRAction);
    dispatchCFRAction({ type: "IMPRESSION", data: message });

    const unload = await lazy.RemoteImages.patchMessage(message.content.logo);

    if (message.content?.modal === "tab") {
      let { closedPromise } = win.gBrowser.getTabDialogBox(browser).open(
        spotlight_url,
        {
          features: "resizable=no",
          allowDuplicateDialogs: false,
        },
        [message.content, params]
      );
      await closedPromise;
    } else {
      await win.gDialogBox.open(spotlight_url, [message.content, params]);
    }

    if (unload) {
      unload();
    }

    // If dismissed report telemetry and exit
    if (!params.secondaryBtn && !params.primaryBtn) {
      this.sendUserEventTelemetry("DISMISS", message, dispatchCFRAction);
      return true;
    }

    if (params.secondaryBtn) {
      this.sendUserEventTelemetry("DISMISS", message, dispatchCFRAction);
      lazy.SpecialMessageActions.handleAction(
        message.content.body.secondary.action,
        browser
      );
    }

    if (params.primaryBtn) {
      this.sendUserEventTelemetry("CLICK", message, dispatchCFRAction);
      lazy.SpecialMessageActions.handleAction(
        message.content.body.primary.action,
        browser
      );
    }

    return true;
  },
};

const EXPORTED_SYMBOLS = ["Spotlight"];