diff --git a/browser/base/content/spotlight.js b/browser/base/content/spotlight.js index e513081b5e1e8..79dfa7b7189e9 100644 --- a/browser/base/content/spotlight.js +++ b/browser/base/content/spotlight.js @@ -148,6 +148,8 @@ function renderMultistage(ready) { document.body.classList.add("onboardingContainer"); document.body.id = "root"; + // This value is reported as the "page" in telemetry + document.body.dataset.page = "spotlight"; // Prevent applying the default modal shadow and margins because the content // handles styling, including its own modal shadowing. diff --git a/browser/base/content/tabbrowser.js b/browser/base/content/tabbrowser.js index d4ca2e36d7e0a..9fe6e7e21bcec 100644 --- a/browser/base/content/tabbrowser.js +++ b/browser/base/content/tabbrowser.js @@ -339,7 +339,7 @@ this._featureCallout = new FeatureCallout({ win: window, prefName: "browser.pdfjs.feature-tour", - source: location.spec, + page: "chrome", }); }, _setupInitialBrowserAndTab() { diff --git a/browser/components/firefoxview/firefoxview.mjs b/browser/components/firefoxview/firefoxview.mjs index 3500e2db59014..3c71256d8c972 100644 --- a/browser/components/firefoxview/firefoxview.mjs +++ b/browser/components/firefoxview/firefoxview.mjs @@ -36,6 +36,7 @@ const launchFeatureTour = () => { let callout = new FeatureCallout({ win: window, prefName: "browser.firefox-view.feature-tour", + page: "about:firefoxview", }); callout.showFeatureCallout(); }; diff --git a/browser/components/firefoxview/tests/browser/browser_feature_callout.js b/browser/components/firefoxview/tests/browser/browser_feature_callout.js index e90b7ab7ac3a4..a2da8305f8cbe 100644 --- a/browser/components/firefoxview/tests/browser/browser_feature_callout.js +++ b/browser/components/firefoxview/tests/browser/browser_feature_callout.js @@ -166,7 +166,7 @@ add_task(async function feature_callout_closes_on_dismiss() { event: "CLICK_BUTTON", event_context: { source: "dismiss_button", - page: document.location.href, + page: "about:firefoxview", }, message_id: sinon.match("FEATURE_CALLOUT_2"), }); @@ -174,7 +174,7 @@ add_task(async function feature_callout_closes_on_dismiss() { event: "DISMISS", event_context: { source: "dismiss_button", - page: document.location.href, + page: "about:firefoxview", }, message_id: sinon.match("FEATURE_CALLOUT_2"), }); @@ -418,7 +418,7 @@ add_task(async function feature_callout_dismiss_on_page_click() { action: "DISMISS", reason: "CLICK", source: sinon.match(testClickSelector), - page: document.location.href, + page: "about:firefoxview", }, message_id: screenId, }); @@ -428,7 +428,7 @@ add_task(async function feature_callout_dismiss_on_page_click() { source: sinon .match("PAGE_EVENT:") .and(sinon.match(testClickSelector)), - page: document.location.href, + page: "about:firefoxview", }, message_id: screenId, }); diff --git a/browser/components/firefoxview/tests/browser/head.js b/browser/components/firefoxview/tests/browser/head.js index c8e44f23dbb28..0d8270285e361 100644 --- a/browser/components/firefoxview/tests/browser/head.js +++ b/browser/components/firefoxview/tests/browser/head.js @@ -491,7 +491,7 @@ const getCalloutMessageById = id => { const createSandboxWithCalloutTriggerStub = testMessage => { const firefoxViewMatch = sinon.match({ id: "featureCalloutCheck", - context: { source: "firefoxview" }, + context: { source: "about:firefoxview" }, }); const sandbox = sinon.createSandbox(); const sendTriggerStub = sandbox.stub(ASRouter, "sendTriggerMessage"); diff --git a/browser/components/newtab/aboutwelcome/content/aboutwelcome.bundle.js b/browser/components/newtab/aboutwelcome/content/aboutwelcome.bundle.js index 36aa2615f139f..c4c92b3aefa03 100644 --- a/browser/components/newtab/aboutwelcome/content/aboutwelcome.bundle.js +++ b/browser/components/newtab/aboutwelcome/content/aboutwelcome.bundle.js @@ -31,10 +31,10 @@ __webpack_require__.r(__webpack_exports__); /* 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/. */ -// If we're in a subdialog, then this is a spotlight modal. -// Otherwise, this is about:welcome or a Feature Callout -// in another "about" page and we should return the current page. -const page = document.querySelector(":root[dialogroot=true]") ? "spotlight" : document.location.href; +// If the container has a "page" data attribute, then this is +// a Spotlight modal or Feature Callout. Otherwise, this is +// about:welcome and we should return the current page. +const page = document.querySelector("#root.onboardingContainer[data-page]") ? document.querySelector("#root[data-page]").dataset.page : document.location.href; const AboutWelcomeUtils = { handleUserAction(action) { window.AWSendToParent("SPECIAL_ACTION", action); diff --git a/browser/components/newtab/content-src/lib/aboutwelcome-utils.js b/browser/components/newtab/content-src/lib/aboutwelcome-utils.js index 1a2842e7139fb..4d94dbb29d69d 100644 --- a/browser/components/newtab/content-src/lib/aboutwelcome-utils.js +++ b/browser/components/newtab/content-src/lib/aboutwelcome-utils.js @@ -2,11 +2,11 @@ * 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/. */ -// If we're in a subdialog, then this is a spotlight modal. -// Otherwise, this is about:welcome or a Feature Callout -// in another "about" page and we should return the current page. -const page = document.querySelector(":root[dialogroot=true]") - ? "spotlight" +// If the container has a "page" data attribute, then this is +// a Spotlight modal or Feature Callout. Otherwise, this is +// about:welcome and we should return the current page. +const page = document.querySelector("#root.onboardingContainer[data-page]") + ? document.querySelector("#root[data-page]").dataset.page : document.location.href; export const AboutWelcomeUtils = { diff --git a/browser/components/newtab/lib/FeatureCalloutMessages.jsm b/browser/components/newtab/lib/FeatureCalloutMessages.jsm index b1b6a22ac9d04..c84e93f9ca70c 100644 --- a/browser/components/newtab/lib/FeatureCalloutMessages.jsm +++ b/browser/components/newtab/lib/FeatureCalloutMessages.jsm @@ -10,7 +10,6 @@ const FIREFOX_VIEW_PREF = "browser.firefox-view.feature-tour"; const PDFJS_PREF = "browser.pdfjs.feature-tour"; // Empty screens are included as placeholders to ensure step // indicator shows the correct number of total steps in the tour -const PDF_SOURCE = `(source || "") | regExpMatch('(? 0`; const EMPTY_SCREEN = { content: {} }; const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000; @@ -139,7 +138,7 @@ const MESSAGES = () => { // Add the highest possible cap to ensure impressions are recorded while allowing the Spotlight to sync across windows/tabs with Firefox View open lifetime: 100, }, - targeting: `!inMr2022Holdback && source == "firefoxview" && + targeting: `!inMr2022Holdback && source == "about:firefoxview" && !'browser.newtabpage.activity-stream.asrouter.providers.cfr'|preferenceIsUserSet && 'browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features'|preferenceValue && ${matchCurrentScreenTargeting( @@ -212,7 +211,7 @@ const MESSAGES = () => { ], }, priority: 3, - targeting: `!inMr2022Holdback && source == "firefoxview" && ${matchCurrentScreenTargeting( + targeting: `!inMr2022Holdback && source == "about:firefoxview" && ${matchCurrentScreenTargeting( FIREFOX_VIEW_PREF, "FEATURE_CALLOUT_1" )}`, @@ -278,7 +277,7 @@ const MESSAGES = () => { ], }, priority: 3, - targeting: `!inMr2022Holdback && source == "firefoxview" && ${matchCurrentScreenTargeting( + targeting: `!inMr2022Holdback && source == "about:firefoxview" && ${matchCurrentScreenTargeting( FIREFOX_VIEW_PREF, "FEATURE_CALLOUT_2" )}`, @@ -337,7 +336,7 @@ const MESSAGES = () => { ], }, priority: 2, - targeting: `!inMr2022Holdback && source == "firefoxview" && "browser.firefox-view.view-count" | preferenceValue > 2 + targeting: `!inMr2022Holdback && source == "about:firefoxview" && "browser.firefox-view.view-count" | preferenceValue > 2 && (("identity.fxaccounts.enabled" | preferenceValue == false) || !(("services.sync.engine.tabs" | preferenceValue == true) && ("services.sync.username" | preferenceValue))) && (!messageImpressions.FIREFOX_VIEW_SPOTLIGHT[messageImpressions.FIREFOX_VIEW_SPOTLIGHT | length - 1] || messageImpressions.FIREFOX_VIEW_SPOTLIGHT[messageImpressions.FIREFOX_VIEW_SPOTLIGHT | length - 1] < currentDate|date - ${ONE_DAY_IN_MS})`, frequency: { lifetime: 1, @@ -407,7 +406,7 @@ const MESSAGES = () => { ], }, priority: 1, - targeting: `${PDF_SOURCE} && ${matchCurrentScreenTargeting( + targeting: `source == "chrome" && ${matchCurrentScreenTargeting( PDFJS_PREF, "FEATURE_CALLOUT_1_A" )}`, @@ -477,7 +476,7 @@ const MESSAGES = () => { ], }, priority: 1, - targeting: `${PDF_SOURCE} && ${matchCurrentScreenTargeting( + targeting: `source == "chrome" && ${matchCurrentScreenTargeting( PDFJS_PREF, "FEATURE_CALLOUT_2_A" )}`, @@ -546,7 +545,7 @@ const MESSAGES = () => { ], }, priority: 1, - targeting: `${PDF_SOURCE} && ${matchCurrentScreenTargeting( + targeting: `source == "chrome" && ${matchCurrentScreenTargeting( PDFJS_PREF, "FEATURE_CALLOUT_1_B" )}`, @@ -616,7 +615,7 @@ const MESSAGES = () => { ], }, priority: 1, - targeting: `${PDF_SOURCE} && ${matchCurrentScreenTargeting( + targeting: `source == "chrome" && ${matchCurrentScreenTargeting( PDFJS_PREF, "FEATURE_CALLOUT_2_B" )}`, diff --git a/browser/components/newtab/test/browser/browser_feature_callout_in_chrome.js b/browser/components/newtab/test/browser/browser_feature_callout_in_chrome.js index f14d7697afccd..370f04254b494 100644 --- a/browser/components/newtab/test/browser/browser_feature_callout_in_chrome.js +++ b/browser/components/newtab/test/browser/browser_feature_callout_in_chrome.js @@ -35,9 +35,7 @@ async function openURLInNewTab(window, url) { } const pdfMatch = sinon.match(val => { - return ( - val?.id === "featureCalloutCheck" && val?.context?.source === PDF_TEST_URL - ); + return val?.id === "featureCalloutCheck" && val?.context?.source === "chrome"; }); const validateCalloutCustomPosition = (element, positionOverride, doc) => { diff --git a/browser/modules/FeatureCallout.sys.mjs b/browser/modules/FeatureCallout.sys.mjs index 582854896fef0..6c26f754ae76f 100644 --- a/browser/modules/FeatureCallout.sys.mjs +++ b/browser/modules/FeatureCallout.sys.mjs @@ -14,13 +14,13 @@ const CONTAINER_ID = "root"; * the parent page pointing to the element they describe. * @param {Window} Window in which messages will be rendered * @param {String} Name of the pref used to track progress through a given feature tour - * @param {String} Optional string to pass as the source when checking for messages to show, - * defaults to this.doc.location.pathname.toLowerCase(). + * @param {String} Optional string to pass as the page when checking for messages to show, + * in the case of the browser chrome the string "chrome" is used. * @param {Browser} browser */ export class FeatureCallout { - constructor({ win, prefName, source, browser }) { + constructor({ win, prefName, page, browser }) { this.win = win || window; this.doc = win.document; this.browser = browser || this.win.docShell.chromeEventHandler; @@ -32,7 +32,7 @@ export class FeatureCallout { this.ready = false; this.listenersRegistered = false; this.AWSetup = false; - this.source = source || this.doc.location.pathname.toLowerCase(); + this.page = page; this.focusHandler = this._focusHandler.bind(this); XPCOMUtils.defineLazyPreferenceGetter( @@ -70,12 +70,10 @@ export class FeatureCallout { return this.win.pageEventManager; }); - const inChrome = - this.win.location.toString() === "chrome://browser/content/browser.xhtml"; // When the window is focused, ensure tour is synced with tours in // any other instances of the parent page. This does not apply when // the Callout is shown in the browser chrome. - if (!inChrome) { + if (this.page !== "chrome") { this.win.addEventListener( "visibilitychange", this._handlePrefChange.bind(this) @@ -197,6 +195,8 @@ export class FeatureCallout { "hidden" ); container.id = CONTAINER_ID; + // This value is reported as the "page" in about:welcome telemetry + container.dataset.page = this.page; container.setAttribute( "aria-describedby", `#${CONTAINER_ID} .welcome-text` @@ -687,7 +687,7 @@ export class FeatureCallout { browser: this.browser, // triggerId and triggerContext id: "featureCalloutCheck", - context: { source: this.source }, + context: { source: this.page }, }); this.loadingConfig = false; @@ -789,7 +789,7 @@ export class FeatureCallout { * @param {Event} event Triggering event */ _handlePageEventAction(action, event) { - const page = this.doc.location.href; + const page = this.page; const message_id = this.config?.id.toUpperCase(); const source = this._getUniqueElementIdentifier(event.target); this.win.AWSendEventTelemetry?.({