Bug 1685525 - Update or add a trigger capable of targeting newtab/homepage for messages r=k88hudson

Differential Revision: https://phabricator.services.mozilla.com/D101936
This commit is contained in:
Andrei Oprea 2021-02-01 19:36:47 +00:00
parent 8bee559e1a
commit 96e52c74a2
24 changed files with 540 additions and 42 deletions

View File

@ -15,6 +15,7 @@ const { XPCOMUtils } = ChromeUtils.import(
XPCOMUtils.defineLazyModuleGetters(this, {
Services: "resource://gre/modules/Services.jsm",
ASRouter: "resource://activity-stream/lib/ASRouter.jsm",
});
XPCOMUtils.defineLazyPreferenceGetter(
@ -35,6 +36,14 @@ class AboutNewTabParent extends JSWindowActorParent {
async receiveMessage(message) {
switch (message.name) {
case "DefaultBrowserNotification":
ASRouter.waitForInitialized.then(() =>
ASRouter.sendTriggerMessage({
browser: this.browsingContext.top.embedderElement,
// triggerId and triggerContext
id: "defaultBrowserCheck",
context: { source: "newtab" },
})
);
await DefaultBrowserNotification.maybeShow(
this.browsingContext.top.embedderElement,
this.browsingContext.topChromeWindow?.getShellService()

View File

@ -1394,7 +1394,7 @@ pref("browser.newtabpage.activity-stream.asrouter.providers.message-groups", "{\
// this page over http opens us up to a man-in-the-middle attack that we'd rather not face. If you are a downstream
// repackager of this code using an alternate snippet url, please keep your users safe
pref("browser.newtabpage.activity-stream.asrouter.providers.snippets", "{\"id\":\"snippets\",\"enabled\":true,\"type\":\"remote\",\"url\":\"https://snippets.cdn.mozilla.net/%STARTPAGE_VERSION%/%NAME%/%VERSION%/%APPBUILDID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/\",\"updateCycleInMs\":14400000}");
pref("browser.newtabpage.activity-stream.asrouter.providers.messaging-experiments", "{\"id\":\"messaging-experiments\",\"enabled\":true,\"type\":\"remote-experiments\",\"messageGroups\":[\"cfr\",\"whats-new-panel\",\"moments-page\",\"snippets\",\"cfr-fxa\",\"aboutwelcome\"],\"updateCycleInMs\":3600000}");
pref("browser.newtabpage.activity-stream.asrouter.providers.messaging-experiments", "{\"id\":\"messaging-experiments\",\"enabled\":true,\"type\":\"remote-experiments\",\"messageGroups\":[\"cfr\",\"whats-new-panel\",\"moments-page\",\"snippets\",\"cfr-fxa\",\"aboutwelcome\",\"infobar\"],\"updateCycleInMs\":3600000}");
// ASRouter user prefs
pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons", true);

View File

@ -25,6 +25,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
ASRouterDefaultConfig:
"resource://activity-stream/lib/ASRouterDefaultConfig.jsm",
ASRouterNewTabHook: "resource://activity-stream/lib/ASRouterNewTabHook.jsm",
ASRouter: "resource://activity-stream/lib/ASRouter.jsm",
AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm",
Blocklist: "resource://gre/modules/Blocklist.jsm",
BookmarkHTMLUtils: "resource://gre/modules/BookmarkHTMLUtils.jsm",
@ -43,6 +44,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
"resource:///modules/DownloadsViewableInternally.jsm",
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
ExtensionsUI: "resource:///modules/ExtensionsUI.jsm",
ExperimentAPI: "resource://messaging-system/experiments/ExperimentAPI.jsm",
FeatureGate: "resource://featuregates/FeatureGate.jsm",
FirefoxMonitor: "resource:///modules/FirefoxMonitor.jsm",
FxAccounts: "resource://gre/modules/FxAccounts.jsm",
@ -3852,21 +3854,44 @@ BrowserGlue.prototype = {
},
_maybeShowDefaultBrowserPrompt() {
DefaultBrowserCheck.willCheckDefaultBrowser(/* isStartupCheck */ true).then(
async willPrompt => {
let { DefaultBrowserNotification } = ChromeUtils.import(
"resource:///actors/AboutNewTabParent.jsm",
{}
);
if (willPrompt) {
// Prevent the related notification from appearing and
// show the modal prompt.
DefaultBrowserNotification.notifyModalDisplayed();
let win = BrowserWindowTracker.getTopWindow();
DefaultBrowserCheck.prompt(win);
}
Promise.all([
DefaultBrowserCheck.willCheckDefaultBrowser(/* isStartupCheck */ true),
ExperimentAPI.ready,
]).then(async ([willPrompt]) => {
let { DefaultBrowserNotification } = ChromeUtils.import(
"resource:///actors/AboutNewTabParent.jsm",
{}
);
let isFeatureEnabled = false;
try {
isFeatureEnabled = ExperimentAPI.getExperiment({
featureId: "infobar",
sendExposurePing: false,
})?.branch.feature.enabled;
} catch (e) {}
if (willPrompt) {
// Prevent the related notification from appearing and
// show the modal prompt.
DefaultBrowserNotification.notifyModalDisplayed();
}
);
// If no experiment go ahead with default experience
if (willPrompt && !isFeatureEnabled) {
let win = BrowserWindowTracker.getTopWindow();
DefaultBrowserCheck.prompt(win);
}
// If in experiment notify ASRouter to dispatch message
if (isFeatureEnabled) {
ASRouter.waitForInitialized.then(() =>
ASRouter.sendTriggerMessage({
browser: BrowserWindowTracker.getTopWindow()?.gBrowser
.selectedBrowser,
// triggerId and triggerContext
id: "defaultBrowserCheck",
context: { willShowDefaultPrompt: willPrompt },
})
);
}
});
},
/**

View File

@ -14,6 +14,7 @@ const MESSAGE_TYPE_LIST = [
"TOOLBAR_BADGE_TELEMETRY",
"TOOLBAR_PANEL_TELEMETRY",
"MOMENTS_PAGE_TELEMETRY",
"INFOBAR_TELEMETRY",
"AS_ROUTER_TELEMETRY_USER_EVENT",
// Admin types

View File

@ -48,7 +48,8 @@ Please note that some targeting attributes require stricter controls on the tele
* [profileRestartCount](#profilerestartcount)
* [homePageSettings](#homepagesettings)
* [newtabSettings](#newtabsettings)
* [isFissionExperimentEnabled](#isFissionExperimentEnabled)
* [isFissionExperimentEnabled](#isfissionexperimentenabled)
* [activeNotifications](#activenotifications)
## Detailed usage
@ -820,3 +821,8 @@ Object {
### `isFissionExperimentEnabled`
A boolean. `true` if we're running Fission experiment, `false` otherwise.
### `activeNotifications`
True when an infobar style message is displayed or when the awesomebar is
expanded to show a message (for example onboarding tips).

View File

@ -0,0 +1,96 @@
{
"title": "InfoBar",
"description": "A template with an image, test and buttons.",
"version": "1.0.0",
"type": "object",
"definitions": {
"plainText": {
"description": "Plain text (no HTML allowed)",
"type": "string"
},
"linkUrl": {
"description": "Target for links or buttons",
"type": "string",
"format": "uri"
}
},
"properties": {
"type": {
"type": "string",
"description": "Should the message be global (persisted across tabs) or local (disappear when switching to a different tab).",
"enum": ["global", "tab"]
},
"text": {
"description": "The text show in the notification box.",
"oneOf": [
{
"type": "string",
"description": "Message shown in the location bar notification."
},
{
"type": "object",
"properties": {
"string_id": {
"type": "string",
"description": "Id of localized string for the location bar notification."
}
},
"required": ["string_id"]
}
]
},
"buttons": {
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"description": "The text label of the button.",
"oneOf": [
{
"type": "string",
"description": "Message content for the button."
},
{
"type": "object",
"properties": {
"string_id": {
"type": "string",
"description": "Id of localized string for the button."
}
},
"required": ["string_id"]
}
]
},
"primary": {
"type": "boolean",
"description": "Is this the primary button?"
},
"accessKey": {
"type": "string",
"description": "Keyboard shortcut letter."
},
"action": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Action dispatched by the button."
},
"data": {
"type": "object"
}
},
"required": ["type"],
"additionalProperties": false
}
},
"required": ["label", "action", "accessKey"],
"additionalProperties": false
}
}
},
"additionalProperties": false,
"required": ["text", "buttons"]
}

View File

@ -966,6 +966,30 @@ as other CFR messages.
}
```
## InfoBar pings
This reports when the user interacts with the browser infobar (messaging area
located at the top of the content area). Similar policy applied as for the
What's New panel client_id is reported in all the channels.
```
{
"experiments" : {
"exp1" : {
"branch" : "treatment-a"
}
},
"addon_version" : "20210115035053",
"release_channel" : "release",
"locale" : "en-US",
"event" : ["IMPRESSION", "CLICK_PRIMARY_BUTTON", "CLICK_SECONDARY_BUTTON", "DISMISSED"],
"client_id" : "c4beb4bf-4feb-9c4e-9587-9323b28c2e50",
"version" : "86",
"message_id" : "INFOBAR_ACTION_86",
"browser_session_id" : "93714e76-9919-ca49-b697-5e7c09a1394f"
}
```
## Messaging-experiments pings
As the new experiment platform, the Messaging experiment manager is now managing & operating all the experiments of Firefox Messaging System, including the first-run experience (about:welcome), CFR, Whats-new-panel, Moments Page, and Snippets.

View File

@ -18,6 +18,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
ToolbarBadgeHub: "resource://activity-stream/lib/ToolbarBadgeHub.jsm",
ToolbarPanelHub: "resource://activity-stream/lib/ToolbarPanelHub.jsm",
MomentsPageHub: "resource://activity-stream/lib/MomentsPageHub.jsm",
InfoBar: "resource://activity-stream/lib/InfoBar.jsm",
ASRouterTargeting: "resource://activity-stream/lib/ASRouterTargeting.jsm",
ASRouterPreferences: "resource://activity-stream/lib/ASRouterPreferences.jsm",
TARGETING_PREFERENCES:
@ -1056,14 +1057,14 @@ class _ASRouter {
return targetingParameters;
}
_handleTargetingError(type, error, message) {
_handleTargetingError(error, message) {
Cu.reportError(error);
this.dispatchCFRAction(
ac.ASRouterUserEvent({
message_id: message.id,
action: "asrouter_undesired_event",
event: "TARGETING_EXPRESSION_ERROR",
event_context: type,
event_context: {},
})
);
}
@ -1226,6 +1227,9 @@ class _ASRouter {
case "update_action":
MomentsPageHub.executeAction(message);
break;
case "infobar":
InfoBar.showInfoBarMessage(browser, message, this.dispatchCFRAction);
break;
}
return { message };

View File

@ -30,6 +30,7 @@ class ASRouterParentProcessMessageHandler {
handleCFRAction({ type, data }, browser) {
switch (type) {
case msg.INFOBAR_TELEMETRY:
case msg.TOOLBAR_BADGE_TELEMETRY:
case msg.TOOLBAR_PANEL_TELEMETRY:
case msg.MOMENTS_PAGE_TELEMETRY:

View File

@ -27,6 +27,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
TelemetrySession: "resource://gre/modules/TelemetrySession.jsm",
HomePage: "resource:///modules/HomePage.jsm",
AboutNewTab: "resource:///modules/AboutNewTab.jsm",
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
});
XPCOMUtils.defineLazyPreferenceGetter(
@ -636,6 +637,19 @@ const TargetingGetters = {
Ci.nsIXULRuntime.eExperimentStatusTreatment
);
},
get activeNotifications() {
let window = BrowserWindowTracker.getTopWindow();
if (
window.gURLBar.view.isOpen ||
window.gHighPriorityNotificationBox.currentNotification ||
window.gBrowser.getNotificationBox().currentNotification
) {
return true;
}
return false;
},
};
this.ASRouterTargeting = {

View File

@ -1044,6 +1044,26 @@ const CFR_MESSAGES = [
params: ["google.com", "www.google.com"],
},
},
{
id: "INFOBAR_ACTION_86",
targeting: "false",
template: "infobar",
content: {
type: "global",
text: { string_id: "default-browser-notification-message" },
buttons: [
{
label: { string_id: "default-browser-notification-button" },
primary: true,
accessKey: "O",
action: {
type: "SET_DEFAULT_BROWSER",
},
},
],
},
trigger: { id: "defaultBrowserCheck" },
},
];
const CFRMessageProvider = {

View File

@ -0,0 +1,158 @@
/* 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.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
XPCOMUtils.defineLazyModuleGetters(this, {
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
RemoteL10n: "resource://activity-stream/lib/RemoteL10n.jsm",
Services: "resource://gre/modules/Services.jsm",
});
class InfoBarNotification {
constructor(message, dispatch) {
this._dispatch = dispatch;
this.dispatchUserAction = this.dispatchUserAction.bind(this);
this.buttonCallback = this.buttonCallback.bind(this);
this.infobarCallback = this.infobarCallback.bind(this);
this.message = message;
this.notification = null;
}
/**
* Show the infobar notification and send an impression ping
*
* @param {object} browser Browser reference for the currently selected tab
*/
showNotification(browser) {
let { content } = this.message;
let { gBrowser } = browser.ownerGlobal;
let doc = gBrowser.ownerDocument;
let notificationContainer;
if (content.type === "global") {
notificationContainer = browser.ownerGlobal.gHighPriorityNotificationBox;
} else {
notificationContainer = gBrowser.getNotificationBox(browser);
}
this.notification = notificationContainer.appendNotification(
this.formatMessageConfig(doc, content.text),
this.message.id,
content.icon || "chrome://branding/content/icon64.png",
notificationContainer.PRIORITY_INFO_MEDIUM,
content.buttons.map(b => this.formatButtonConfig(b)),
this.infobarCallback
);
this.addImpression();
}
formatMessageConfig(doc, content) {
let docFragment = doc.createDocumentFragment();
// notificationbox will only `appendChild` for documentFragments
docFragment.appendChild(RemoteL10n.createElement(doc, "span", { content }));
return docFragment;
}
formatButtonConfig(button) {
let btnConfig = { callback: this.buttonCallback, ...button };
// notificationbox will set correct data-l10n-id attributes if passed in
// using the l10n-id key. Otherwise the `button.label` text is used.
if (button.label.string_id) {
btnConfig["l10n-id"] = button.label.string_id;
}
return btnConfig;
}
addImpression() {
// Record an impression in ASRouter for frequency capping
this._dispatch({ type: "IMPRESSION", data: this.message });
// Send a user impression telemetry ping
this.sendUserEventTelemetry("IMPRESSION");
}
/**
* Called when one of the infobar buttons is clicked
*/
buttonCallback(notificationBox, btnDescription, target) {
this.dispatchUserAction(
btnDescription.action,
target.ownerGlobal.gBrowser.selectedBrowser
);
let isPrimary = target.classList.contains("primary");
let eventName = isPrimary
? "CLICK_PRIMARY_BUTTON"
: "CLICK_SECONDARY_BUTTON";
this.sendUserEventTelemetry(eventName);
}
dispatchUserAction(action, selectedBrowser) {
this._dispatch({ type: "USER_ACTION", data: action }, selectedBrowser);
}
/**
* Called when interacting with the toolbar (but not through the buttons)
*/
infobarCallback(eventType) {
if (eventType === "removed" || eventType === "disconnected") {
this.notification = null;
} else {
this.sendUserEventTelemetry(eventType.toUpperCase());
}
}
sendUserEventTelemetry(event) {
const ping = {
message_id: this.message.id,
event,
};
this._dispatch({
type: "INFOBAR_TELEMETRY",
data: { action: "infobar_user_event", ...ping },
});
}
}
const InfoBar = {
maybeLoadCustomElement(win) {
if (!win.customElements.get("remote-text")) {
Services.scriptloader.loadSubScript(
"resource://activity-stream/data/custom-elements/paragraph.js",
win
);
}
},
maybeInsertFTL(win) {
win.MozXULElement.insertFTLIfNeeded("browser/newtab/asrouter.ftl");
win.MozXULElement.insertFTLIfNeeded(
"browser/defaultBrowserNotification.ftl"
);
},
showInfoBarMessage(browser, message, dispatch) {
const win = browser.ownerGlobal;
if (PrivateBrowsingUtils.isWindowPrivate(win)) {
return null;
}
this.maybeLoadCustomElement(win);
this.maybeInsertFTL(win);
let notification = new InfoBarNotification(message, dispatch);
notification.showNotification(browser);
return notification;
},
};
this.InfoBar = InfoBar;
const EXPORTED_SYMBOLS = ["InfoBar"];

View File

@ -218,6 +218,7 @@ class _RemoteL10n {
"browser/branding/brandings.ftl",
"browser/branding/sync-brand.ftl",
"branding/brand.ftl",
"browser/defaultBrowserNotification.ftl",
],
false,
Services.prefs.getBoolPref(USE_REMOTE_L10N_PREF, true)

View File

@ -604,6 +604,9 @@ this.TelemetryFeed = class TelemetryFeed {
case "whats-new-panel_user_event":
event = await this.applyWhatsNewPolicy(event);
break;
case "infobar_user_event":
event = await this.applyInfoBarPolicy(event);
break;
case "moments_user_event":
event = await this.applyMomentsPolicy(event);
break;
@ -652,6 +655,13 @@ this.TelemetryFeed = class TelemetryFeed {
return { ping, pingType: "whats-new-panel" };
}
async applyInfoBarPolicy(ping) {
ping.client_id = await this.telemetryClientId;
ping.browser_session_id = browserSessionId;
delete ping.action;
return { ping, pingType: "infobar" };
}
/**
* Per Bug 1484035, Moments metrics comply with following policies:
* 1). In release, it collects impression_id, and treats bucket_id as message_id
@ -945,6 +955,8 @@ this.TelemetryFeed = class TelemetryFeed {
// Intentional fall-through
case msg.DOORHANGER_TELEMETRY:
// Intentional fall-through
case msg.INFOBAR_TELEMETRY:
// Intentional fall-through
case at.AS_ROUTER_TELEMETRY_USER_EVENT:
this.handleASRouterUserEvent(action);
break;

View File

@ -43,6 +43,7 @@ skip-if = (os == "linux") # Test setup only implemented for OSX and Windows
[browser_topsites_contextMenu_options.js]
[browser_topsites_section.js]
[browser_asrouter_cfr.js]
[browser_asrouter_infobar.js]
[browser_asrouter_bookmarkpanel.js]
[browser_asrouter_toolbarbadge.js]
[browser_asrouter_whatsnewpanel.js]

View File

@ -0,0 +1,85 @@
const { InfoBar } = ChromeUtils.import(
"resource://activity-stream/lib/InfoBar.jsm"
);
const { CFRMessageProvider } = ChromeUtils.import(
"resource://activity-stream/lib/CFRMessageProvider.jsm"
);
const { ASRouter } = ChromeUtils.import(
"resource://activity-stream/lib/ASRouter.jsm"
);
const { BrowserWindowTracker } = ChromeUtils.import(
"resource:///modules/BrowserWindowTracker.jsm"
);
add_task(async function show_and_send_telemetry() {
let message = (await CFRMessageProvider.getMessages()).find(
m => m.id === "INFOBAR_ACTION_86"
);
Assert.ok(message.id, "Found the message");
let dispatchStub = sinon.stub();
let infobar = InfoBar.showInfoBarMessage(
BrowserWindowTracker.getTopWindow().gBrowser.selectedBrowser,
message,
dispatchStub
);
Assert.equal(dispatchStub.callCount, 2, "Called twice with IMPRESSION");
// This is the call to increment impressions for frequency capping
Assert.equal(dispatchStub.firstCall.args[0].type, "IMPRESSION");
Assert.equal(dispatchStub.firstCall.args[0].data.id, message.id);
// This is the telemetry ping
Assert.equal(dispatchStub.secondCall.args[0].data.event, "IMPRESSION");
Assert.equal(dispatchStub.secondCall.args[0].data.message_id, message.id);
let primaryBtn = infobar.notification.querySelector(
".notification-button.primary"
);
Assert.ok(primaryBtn, "Has a primary button");
primaryBtn.click();
Assert.equal(dispatchStub.callCount, 4, "Called again with CLICK + removed");
Assert.equal(dispatchStub.thirdCall.args[0].type, "USER_ACTION");
Assert.equal(
dispatchStub.lastCall.args[0].data.event,
"CLICK_PRIMARY_BUTTON"
);
});
add_task(async function react_to_trigger() {
let message = {
...(await CFRMessageProvider.getMessages()).find(
m => m.id === "INFOBAR_ACTION_86"
),
};
message.targeting = "true";
message.content.type = "tab";
message.groups = [];
message.provider = ASRouter.state.providers[0].id;
message.content.message = "Infobar Mochitest";
await ASRouter.setState({ messages: [message] });
let notificationStack = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
Assert.ok(
!notificationStack.currentNotification,
"No notification to start with"
);
await ASRouter.sendTriggerMessage({
browser: BrowserWindowTracker.getTopWindow().gBrowser.selectedBrowser,
id: "defaultBrowserCheck",
});
await BrowserTestUtils.waitForCondition(
() => notificationStack.currentNotification,
"Wait for notification to show"
);
Assert.equal(
notificationStack.currentNotification.getAttribute("value"),
message.id,
"Notification id should match"
);
});

View File

@ -912,7 +912,7 @@ add_task(async function checkPatternMatches() {
add_task(async function checkPatternsValid() {
const messages = (await CFRMessageProvider.getMessages()).filter(
m => m.trigger.patterns
m => m.trigger?.patterns
);
for (const message of messages) {

View File

@ -14,8 +14,8 @@ describe("CFRMessageProvider", () => {
beforeEach(async () => {
messages = await CFRMessageProvider.getMessages();
});
it("should have a total of 13 messages", () => {
assert.lengthOf(messages, 13);
it("should have a total of 14 messages", () => {
assert.lengthOf(messages, 14);
});
it("should have one message each for the three regular addons", () => {
for (const id of REGULAR_IDS) {
@ -29,21 +29,6 @@ describe("CFRMessageProvider", () => {
assert.notInclude(cohort3.targeting, `providerCohorts.cfr`);
}
});
it("should always have xpinstallEnabled as targeting if it is an addon", () => {
for (const message of messages) {
// Ensure that the CFR messages that are recommending an addon have this targeting.
// In the future when we can do targeting based on category, this test will change.
// See bug 1494778 and 1497653
if (!message.content.layout) {
assert.include(message.targeting, `(xpinstallEnabled == true)`);
}
}
});
it("should restrict all messages to `en` locale for now (PIN TAB is handled separately)", () => {
for (const message of messages.filter(m => !m.content.layout)) {
assert.include(message.targeting, `localeLanguageCode == "en"`);
}
});
it("should restrict locale for PIN_TAB message", () => {
const pinTabMessage = messages.find(m => m.id === "PIN_TAB");

View File

@ -64,6 +64,7 @@ describe("RemoteL10n", () => {
"browser/branding/brandings.ftl",
"browser/branding/sync-brand.ftl",
"branding/brand.ftl",
"browser/defaultBrowserNotification.ftl",
]);
assert.isFalse(args[1]);
assert.isFunction(args[2].generateBundles);
@ -82,6 +83,7 @@ describe("RemoteL10n", () => {
"browser/branding/brandings.ftl",
"browser/branding/sync-brand.ftl",
"branding/brand.ftl",
"browser/defaultBrowserNotification.ftl",
]);
assert.isFalse(args[1]);
assert.isEmpty(args[2]);

View File

@ -1,11 +1,13 @@
import { CFRMessageProvider } from "lib/CFRMessageProvider.jsm";
import CFRDoorhangerSchema from "content-src/asrouter/templates/CFR/templates/ExtensionDoorhanger.schema.json";
import CFRChicletSchema from "content-src/asrouter/templates/CFR/templates/CFRUrlbarChiclet.schema.json";
import InfoBarSchema from "content-src/asrouter/templates/CFR/templates/InfoBar.schema.json";
const SCHEMAS = {
cfr_urlbar_chiclet: CFRChicletSchema,
cfr_doorhanger: CFRDoorhangerSchema,
milestone_message: CFRDoorhangerSchema,
infobar: InfoBarSchema,
};
const DEFAULT_CONTENT = {

View File

@ -766,6 +766,14 @@ describe("TelemetryFeed", () => {
assert.equal(pingType, "whats-new-panel");
});
});
describe("#applyInfoBarPolicy", () => {
it("should set client_id and set pingType", async () => {
const { ping, pingType } = await instance.applyInfoBarPolicy({});
assert.propertyVal(ping, "client_id", FAKE_TELEMETRY_ID);
assert.equal(pingType, "infobar");
});
});
describe("#applyMomentsPolicy", () => {
it("should use client_id and message_id in prerelease", async () => {
globals.set("UpdateUtils", {

View File

@ -14,11 +14,17 @@ add_task(async function test_all_test_messages() {
for (let message of messagesWithButtons) {
info(`Testing ${message.id}`);
let { primary, secondary } = message.content.buttons;
await SMATestUtils.validateAction(primary.action);
for (let secondaryBtn of secondary) {
if (secondaryBtn.action) {
await SMATestUtils.validateAction(secondaryBtn.action);
if (message.template === "infobar") {
for (let button of message.content.buttons) {
await SMATestUtils.validateAction(button.action);
}
} else {
let { primary, secondary } = message.content.buttons;
await SMATestUtils.validateAction(primary.action);
for (let secondaryBtn of secondary) {
if (secondaryBtn.action) {
await SMATestUtils.validateAction(secondaryBtn.action);
}
}
}
}

View File

@ -158,8 +158,35 @@
],
"additionalProperties": false,
"description": "Happens every time Firefox blocks the loading of a page script/asset/resource that matches the one of the tracking behaviours specifid through params. See https://searchfox.org/mozilla-central/rev/8ccea36c4fb09412609fb738c722830d7098602b/uriloader/base/nsIWebProgressListener.idl#336"
},
{
"type": "object",
"properties": {
"id": {
"type": "string",
"enum": ["defaultBrowserCheck"]
},
"context": {
"type": "object",
"properties": {
"source": {
"type": "string",
"enum": ["newtab"],
"description": "When the source of the trigger is home/newtab"
},
"willShowDefaultPrompt": {
"type": "boolean",
"description": "When the source of the trigger is startup"
}
},
"additionalProperties": false
}
},
"additionalProperties": false,
"required": ["id"],
"description": "Happens when starting the browser or navigating to about:home/newtab"
}
]
}
}
}
}

View File

@ -108,3 +108,14 @@ ANDing the various STATE_BLOCKED_* flags.
let event: ContentBlockingEventFlag;
let pageLoad = number;
```
### `defaultBrowserCheck`
Happens at startup, when opening a newtab and when navigating to about:home.
At startup it provides the result of running `DefaultBrowserCheck.willCheckDefaultBrowser` to follow existing behaviour if needed.
On the newtab/homepage it reports the `source` as `newtab`.
```typescript
let source = "newtab" | undefined;
let willShowDefaultPrompt = boolean;
```