mirror of
https://github.com/HeyPuter/firefox.git
synced 2026-11-13 20:14:57 -10:00
Bug 2000982 - add message level config to allow showing message in AI Window. r=pdahiya,omc-reviewers,ngrato,aminomancer
Differential Revision: https://phabricator.services.mozilla.com/D274045
This commit is contained in:
1 parent
c73a503493
commit
108746012f
7 files changed
+116
-16
No files matched your search
@@ -48,6 +48,7 @@ Please note that some targeting attributes require stricter controls on the tele
|
||||
* [hasSelectableProfiles](#hasselectableprofiles)
|
||||
* [homePageSettings](#homepagesettings)
|
||||
* [isBackgroundTaskMode](#isbackgroundtaskmode)
|
||||
* [isAIWindow] (#isaiwindow)
|
||||
* [isChinaRepack](#ischinarepack)
|
||||
* [isDefaultBrowser](#isdefaultbrowser)
|
||||
* [isDefaultBrowserUncached](#isdefaultbrowseruncached)
|
||||
@@ -855,6 +856,36 @@ actually emit from tabs, this is always true. For other triggers, like
|
||||
declare const browserIsSelected: boolean;
|
||||
```
|
||||
|
||||
### `isAIWindow`
|
||||
|
||||
A context property included for all triggers that evaluates to `true` when the
|
||||
message comes from an AI Window, and `false` otherwise.
|
||||
|
||||
#### Definition
|
||||
|
||||
```ts
|
||||
declare const isAIWindow: boolean;
|
||||
```
|
||||
|
||||
#### Examples
|
||||
|
||||
* Target AI Windows only:
|
||||
```javascript
|
||||
isAIWindow
|
||||
```
|
||||
|
||||
* Target Classic Windows only:
|
||||
```javascript
|
||||
!isAIWindow
|
||||
```
|
||||
|
||||
* Target both AI Windows and Classic Windows:
|
||||
```javascript
|
||||
isAIWindow == isAIWindow
|
||||
or equivalently
|
||||
(isAIWindow || !isAIWindow)
|
||||
```
|
||||
|
||||
### `isChinaRepack`
|
||||
|
||||
Does the user use [the partner repack distributed by Mozilla Online](https://github.com/mozilla-partners/mozillaonline),
|
||||
|
||||
@@ -60,6 +60,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
Spotlight: "resource:///modules/asrouter/Spotlight.sys.mjs",
|
||||
ToastNotification: "resource:///modules/asrouter/ToastNotification.sys.mjs",
|
||||
ToolbarBadgeHub: "resource:///modules/asrouter/ToolbarBadgeHub.sys.mjs",
|
||||
AIWindow:
|
||||
"moz-src:///browser/components/aiwindow/ui/modules/AIWindow.sys.mjs",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
@@ -2342,6 +2344,9 @@ export class _ASRouter {
|
||||
trigger.context = {};
|
||||
}
|
||||
if (typeof trigger.context === "object") {
|
||||
trigger.context.isAIWindow = !!lazy.AIWindow?.isAIWindowActive?.(
|
||||
browser.ownerGlobal
|
||||
);
|
||||
trigger.context.browserIsSelected =
|
||||
trigger.context.browserIsSelected ||
|
||||
browser === browser.ownerGlobal.gBrowser?.selectedBrowser;
|
||||
|
||||
@@ -1390,6 +1390,19 @@ const TargetingGetters = {
|
||||
},
|
||||
};
|
||||
|
||||
function addAIWindowTargeting(targeting) {
|
||||
if (!targeting || targeting === "true") {
|
||||
// Default behavior: Classic-only if no targeting is specified
|
||||
return `!isAIWindow`;
|
||||
}
|
||||
|
||||
if (/\bisAIWindow\b/.test(targeting)) {
|
||||
return targeting;
|
||||
}
|
||||
|
||||
return `((${targeting}) && !isAIWindow)`;
|
||||
}
|
||||
|
||||
export const ASRouterTargeting = {
|
||||
Environment: TargetingGetters,
|
||||
|
||||
@@ -1531,14 +1544,13 @@ export const ASRouterTargeting = {
|
||||
Array.from(arguments) // eslint-disable-line prefer-rest-params
|
||||
);
|
||||
|
||||
// If no targeting is specified,
|
||||
if (!message.targeting) {
|
||||
return true;
|
||||
}
|
||||
let { targeting } = message;
|
||||
targeting = addAIWindowTargeting(targeting);
|
||||
|
||||
let result;
|
||||
try {
|
||||
if (shouldCache) {
|
||||
result = this.getCachedEvaluation(message.targeting);
|
||||
result = this.getCachedEvaluation(targeting);
|
||||
if (result) {
|
||||
return result.value;
|
||||
}
|
||||
@@ -1546,9 +1558,9 @@ export const ASRouterTargeting = {
|
||||
// Used to report the source of the targeting error in the case of
|
||||
// undesired events
|
||||
targetingContext.setTelemetrySource(message.id);
|
||||
result = await targetingContext.evalWithDefault(message.targeting);
|
||||
result = await targetingContext.evalWithDefault(targeting);
|
||||
if (shouldCache) {
|
||||
jexlEvaluationCache.set(message.targeting, {
|
||||
jexlEvaluationCache.set(targeting, {
|
||||
timestamp: Date.now(),
|
||||
value: result,
|
||||
});
|
||||
|
||||
@@ -486,6 +486,7 @@ add_task(async function test_trigger() {
|
||||
context: {
|
||||
source: MenuMessage.SOURCES.APP_MENU,
|
||||
browserIsSelected: true,
|
||||
isAIWindow: false,
|
||||
},
|
||||
}),
|
||||
"sendTriggerMessage was called when opening the AppMenu panel."
|
||||
@@ -501,6 +502,7 @@ add_task(async function test_trigger() {
|
||||
context: {
|
||||
source: MenuMessage.SOURCES.PXI_MENU,
|
||||
browserIsSelected: true,
|
||||
isAIWindow: false,
|
||||
},
|
||||
}),
|
||||
"sendTriggerMessage was called when opening the PXI panel."
|
||||
|
||||
@@ -1801,15 +1801,14 @@ describe("ASRouter", () => {
|
||||
id: "firstRun",
|
||||
});
|
||||
|
||||
const [{ trigger }] =
|
||||
ASRouterTargeting.findMatchingMessage.firstCall.args;
|
||||
|
||||
assert.calledOnce(ASRouterTargeting.findMatchingMessage);
|
||||
assert.deepEqual(
|
||||
ASRouterTargeting.findMatchingMessage.firstCall.args[0].trigger,
|
||||
{
|
||||
id: "firstRun",
|
||||
param: undefined,
|
||||
context: { browserIsSelected: true },
|
||||
}
|
||||
);
|
||||
assert.strictEqual(trigger.id, "firstRun");
|
||||
assert.strictEqual(trigger.param, undefined);
|
||||
assert.isObject(trigger.context);
|
||||
assert.strictEqual(trigger.context.browserIsSelected, true);
|
||||
});
|
||||
it("should record telemetry information", async () => {
|
||||
const fakeTimerId = 42;
|
||||
|
||||
@@ -322,7 +322,10 @@ describe("ASRouterTargeting", () => {
|
||||
false
|
||||
);
|
||||
assert.calledOnce(fakeTargetingContext.evalWithDefault);
|
||||
assert.calledWithExactly(fakeTargetingContext.evalWithDefault, "true");
|
||||
assert.include(
|
||||
fakeTargetingContext.evalWithDefault.firstCall.args[0],
|
||||
"!isAIWindow"
|
||||
);
|
||||
assert.calledWithExactly(
|
||||
fakeTargetingContext.setTelemetrySource,
|
||||
"message"
|
||||
@@ -404,6 +407,53 @@ describe("ASRouterTargeting", () => {
|
||||
|
||||
assert.calledTwice(evalStub);
|
||||
});
|
||||
it("defaults to Classic-only targeting when no targeting is specified", async () => {
|
||||
evalStub.resolves(true);
|
||||
const targetingContext = new global.TargetingContext();
|
||||
const message = { id: "test-message" };
|
||||
|
||||
await ASRouterTargeting.checkMessageTargeting(
|
||||
message,
|
||||
targetingContext,
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
assert.calledOnce(fakeTargetingContext.evalWithDefault);
|
||||
assert.calledWith(fakeTargetingContext.evalWithDefault, "!isAIWindow");
|
||||
});
|
||||
it("blocks messages in AI windows by default via !isAIWindow", async () => {
|
||||
evalStub.resolves(true);
|
||||
const targetingContext = new global.TargetingContext();
|
||||
targetingContext.isAIWindow = false;
|
||||
const message = { id: "test-message" };
|
||||
|
||||
await ASRouterTargeting.checkMessageTargeting(
|
||||
message,
|
||||
targetingContext,
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
assert.calledOnce(fakeTargetingContext.evalWithDefault);
|
||||
assert.calledWith(fakeTargetingContext.evalWithDefault, "!isAIWindow");
|
||||
});
|
||||
it("does not modify targeting that explicitly references isAIWindow", async () => {
|
||||
evalStub.resolves(true);
|
||||
const targetingContext = new global.TargetingContext();
|
||||
targetingContext.isAIWindow = true;
|
||||
const message = { id: "test-message", targeting: "isAIWindow" };
|
||||
|
||||
await ASRouterTargeting.checkMessageTargeting(
|
||||
message,
|
||||
targetingContext,
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
assert.calledOnce(fakeTargetingContext.evalWithDefault);
|
||||
assert.calledWith(fakeTargetingContext.evalWithDefault, "isAIWindow");
|
||||
});
|
||||
|
||||
describe("#findMatchingMessage", () => {
|
||||
let matchStub;
|
||||
|
||||
@@ -74,6 +74,7 @@ describe("ASRTargeting docs", () => {
|
||||
"messageImpressions",
|
||||
"screenImpressions",
|
||||
"browserIsSelected",
|
||||
"isAIWindow",
|
||||
];
|
||||
for (const targetingParam of DOCS_TARGETING_HEADINGS.filter(
|
||||
doc => !allow.includes(doc)
|
||||
|
||||
Reference in new issue
Block a user