This repository has been archived by the owner on Feb 29, 2020. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 1433216 - Add AS Router targeting
- Loading branch information
Showing
7 changed files
with
149 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
ChromeUtils.import("resource://gre/modules/components-utils/FilterExpressions.jsm"); | ||
ChromeUtils.import("resource://gre/modules/Services.jsm"); | ||
ChromeUtils.defineModuleGetter(this, "ProfileAge", | ||
"resource://gre/modules/ProfileAge.jsm"); | ||
ChromeUtils.import("resource://gre/modules/Console.jsm"); | ||
|
||
const FXA_USERNAME_PREF = "services.sync.username"; | ||
|
||
/** | ||
* removeRandomItemFromArray - Removes a random item from the array and returns it. | ||
* | ||
* @param {Array} arr An array of items | ||
* @returns one of the items in the array | ||
*/ | ||
function removeRandomItemFromArray(arr) { | ||
return arr.splice(Math.floor(Math.random() * arr.length), 1)[0]; | ||
} | ||
|
||
const TargetingGetters = { | ||
get profileAgeCreated() { | ||
return new ProfileAge(null, null).created; | ||
}, | ||
get profileAgeReset() { | ||
return new ProfileAge(null, null).reset; | ||
}, | ||
get hasFxAccount() { | ||
return Services.prefs.prefHasUserValue(FXA_USERNAME_PREF); | ||
} | ||
}; | ||
|
||
this.ASRouterTargeting = { | ||
Environment: TargetingGetters, | ||
|
||
isMatch(filterExpression, context = this.Environment) { | ||
return FilterExpressions.eval(filterExpression, context); | ||
}, | ||
|
||
/** | ||
* findMatchingMessage - Given an array of messages, returns one message | ||
* whos targeting expression evaluates to true | ||
* | ||
* @param {Array} messages An array of AS router messages | ||
* @param {obj|null} context A FilterExpression context. Defaults to TargetingGetters above. | ||
* @returns {obj} an AS router message | ||
*/ | ||
async findMatchingMessage(messages, context) { | ||
const arrayOfItems = [...messages]; | ||
let match; | ||
let candidate; | ||
while (!match && arrayOfItems.length) { | ||
candidate = removeRandomItemFromArray(arrayOfItems); | ||
if (candidate && (!candidate.targeting || await this.isMatch(candidate.targeting, context))) { | ||
match = candidate; | ||
} | ||
} | ||
return match; | ||
} | ||
}; | ||
|
||
this.EXPORTED_SYMBOLS = ["ASRouterTargeting", "removeRandomItemFromArray"]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
system-addon/test/functional/mochitest/browser_asrouter_targeting.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
ChromeUtils.defineModuleGetter(this, "ASRouterTargeting", | ||
"resource://activity-stream/lib/ASRouterTargeting.jsm"); | ||
ChromeUtils.defineModuleGetter(this, "ProfileAge", | ||
"resource://gre/modules/ProfileAge.jsm"); | ||
|
||
// ASRouterTargeting.isMatch | ||
add_task(async function should_do_correct_targeting() { | ||
is(await ASRouterTargeting.isMatch("FOO", {FOO: true}), true, "should return true for a matching value"); | ||
is(await ASRouterTargeting.isMatch("!FOO", {FOO: true}), false, "should return false for a non-matching value"); | ||
}); | ||
|
||
add_task(async function should_handle_async_getters() { | ||
const context = {get FOO() { return Promise.resolve(true); }}; | ||
is(await ASRouterTargeting.isMatch("FOO", context), true, "should return true for a matching async value"); | ||
}); | ||
|
||
// ASRouterTargeting.findMatchingMessage | ||
add_task(async function find_matching_message() { | ||
const messages = [ | ||
{id: "foo", targeting: "FOO"}, | ||
{id: "bar", targeting: "!FOO"} | ||
]; | ||
const context = {FOO: true}; | ||
|
||
const match = await ASRouterTargeting.findMatchingMessage(messages, context); | ||
|
||
is(match, messages[0], "should match and return the correct message"); | ||
}); | ||
|
||
add_task(async function return_nothing_for_no_matching_message() { | ||
const messages = [{id: "bar", targeting: "!FOO"}]; | ||
const context = {FOO: true}; | ||
|
||
const match = await ASRouterTargeting.findMatchingMessage(messages, context); | ||
|
||
is(match, undefined, "should return nothing since no matching message exists"); | ||
}); | ||
|
||
// ASRouterTargeting.Environment | ||
add_task(async function checkProfileAgeCreated() { | ||
let profileAccessor = new ProfileAge(); | ||
is(await ASRouterTargeting.Environment.profileAgeCreated, await profileAccessor.created, | ||
"should return correct profile age creation date"); | ||
|
||
const message = {id: "foo", targeting: `profileAgeCreated > ${await profileAccessor.created - 100}`}; | ||
is(await ASRouterTargeting.findMatchingMessage([message]), message, | ||
"should select correct item by profile age created"); | ||
}); | ||
|
||
add_task(async function checkProfileAgeReset() { | ||
let profileAccessor = new ProfileAge(); | ||
is(await ASRouterTargeting.Environment.profileAgeReset, await profileAccessor.reset, | ||
"should return correct profile age reset"); | ||
|
||
const message = {id: "foo", targeting: `profileAgeReset == ${await profileAccessor.reset}`}; | ||
is(await ASRouterTargeting.findMatchingMessage([message]), message, | ||
"should select correct item by profile age reset"); | ||
}); | ||
|
||
add_task(async function checkhasFxAccount() { | ||
await pushPrefs(["services.sync.username", "someone@foo.com"]); | ||
is(await ASRouterTargeting.Environment.hasFxAccount, true, | ||
"should return true if a fx account is set"); | ||
|
||
const message = {id: "foo", targeting: "hasFxAccount"}; | ||
is(await ASRouterTargeting.findMatchingMessage([message]), message, | ||
"should select correct item by hasFxAccount"); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters