Skip to content
This repository has been archived by the owner on Feb 29, 2020. It is now read-only.

Commit

Permalink
Bug 1462124 - Switch .addonInfo to an async API in snippets targeting
Browse files Browse the repository at this point in the history
  • Loading branch information
k88hudson committed May 22, 2018
1 parent eb96bc0 commit de57703
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 33 deletions.
44 changes: 24 additions & 20 deletions docs/v2-system-addon/snippets.md
Expand Up @@ -44,6 +44,30 @@ does not hide onboarding notifications on the **current** page, since that would
bookmarks a user has (including default bookmarks). Note that is value is only updated once per day or when a
a user restarts the browser.

`.getAddonsInfo()`:( func) An async function that resolves with an object `{isFullData: (bool), addons: (obj)}`.
Note that at startup, we are sometimes unable to provide full data due to performance constraits (`.isFullData` will be `false`).
E.g.

```js
{
isFullData: true,
addons: {
// This is the ID of the addon
"someaddon@mozilla.org": {
type: "extension",
isSystem: false,
isWebExtension: true,
version: "29.0.0"

// The following properties may not be available when the browser starts up
name: "Firefox Screenshots",
userDisabled: false,
installDate: Date 2018-02-27T19:33:33.440Z,
}
}
}
```

### Expected values in gSnippetsMap

Note that names and functionality of values in v4 snippets have been preserved
Expand Down Expand Up @@ -87,26 +111,6 @@ currently this value is only checked once when the browser is initialized.

`appData.isDevtoolsUser`: (bool) Has the user ever used devtools?

`appData.addonInfo`: (obj) An object containing info about installed addons.
For example:

```js
{
// This is the ID of the addon
"someaddon@mozilla.org": {
type: "extension",
isSystem: false,
isWebExtension: true,
version: "29.0.0"

// The following properties may not be available when the browser starts up
name: "Firefox Screenshots",
userDisabled: false,
installDate: Date 2018-02-27T19:33:33.440Z,
}
}
```

## Events

ActivityStream dispatches custom DOM events on the window to allow snippets
Expand Down
2 changes: 2 additions & 0 deletions system-addon/common/Actions.jsm
Expand Up @@ -25,6 +25,8 @@ this.globalImportContext = globalImportContext;
// }
const actionTypes = {};
for (const type of [
"ADDONS_INFO_REQUEST",
"ADDONS_INFO_RESPONSE",
"ARCHIVE_FROM_POCKET",
"AS_ROUTER_TELEMETRY_USER_EVENT",
"BLOCK_URL",
Expand Down
12 changes: 12 additions & 0 deletions system-addon/content-src/lib/snippets.js
Expand Up @@ -83,6 +83,18 @@ export class SnippetsMap extends Map {
});
}

getAddonsInfo() {
return new Promise(resolve => {
this._dispatch(ac.OnlyToMain({type: at.ADDONS_INFO_REQUEST}));
global.addMessageListener("ActivityStream:MainToContent", function onMessage({data: action}) {
if (action.type === at.ADDONS_INFO_RESPONSE) {
resolve(action.data);
global.removeMessageListener("ActivityStream:MainToContent", onMessage);
}
});
});
}

/**
* connect - Attaches an indexedDB back-end to the Map so that any set values
* are also cached in a store. It also restores any existing values
Expand Down
11 changes: 7 additions & 4 deletions system-addon/lib/SnippetsFeed.jsm
Expand Up @@ -89,7 +89,7 @@ this.SnippetsFeed = class SnippetsFeed {
});
}

async getAddonInfo() {
async getAddonsInfo(target) {
const {addons, fullData} = await AddonManager.getActiveAddons(["extension", "service"]);
const info = {};
for (const addon of addons) {
Expand All @@ -107,7 +107,8 @@ this.SnippetsFeed = class SnippetsFeed {
});
}
}
return info;
const data = {addons: info, isFullData: fullData};
this.store.dispatch(ac.OnlyToOneContent({type: at.ADDONS_INFO_RESPONSE, data}, target));
}

async getTotalBookmarksCount(target) {
Expand Down Expand Up @@ -152,7 +153,6 @@ this.SnippetsFeed = class SnippetsFeed {
selectedSearchEngine: await this.getSelectedSearchEngine(),
defaultBrowser: this.isDefaultBrowser(),
isDevtoolsUser: this.isDevtoolsUser(),
addonInfo: await this.getAddonInfo(),
blockList: await this._getBlockList() || [],
previousSessionEnd: this._previousSessionEnd
};
Expand Down Expand Up @@ -193,7 +193,7 @@ this.SnippetsFeed = class SnippetsFeed {
browser.loadURI(url);
}

onAction(action) {
async onAction(action) {
switch (action.type) {
case at.INIT:
this.init();
Expand All @@ -214,6 +214,9 @@ this.SnippetsFeed = class SnippetsFeed {
case at.TOTAL_BOOKMARKS_REQUEST:
this.getTotalBookmarksCount(action.meta.fromTarget);
break;
case at.ADDONS_INFO_REQUEST:
await this.getAddonsInfo(action.meta.fromTarget);
break;
}
}
};
Expand Down
19 changes: 19 additions & 0 deletions system-addon/test/unit/content-src/lib/snippets.test.js
Expand Up @@ -165,6 +165,25 @@ describe("SnippetsMap", () => {
assert.calledWith(global.removeMessageListener, INCOMING_MESSAGE_NAME, listener);
});
});
describe("#getAddonsInfo", () => {
it("should dispatch a ADDONS_INFO_REQUEST and resolve with the right data", async () => {
const addonsPromise = snippetsMap.getAddonsInfo();

assert.calledOnce(dispatch);
assert.equal(dispatch.firstCall.args[0].type, at.ADDONS_INFO_REQUEST);
assert.calledWith(global.addMessageListener, INCOMING_MESSAGE_NAME);

// Call listener
const [, listener] = global.addMessageListener.firstCall.args;
const addonsInfo = {isFullData: true, addons: {foo: {}}};
listener({data: {type: at.ADDONS_INFO_RESPONSE, data: addonsInfo}});

const result = await addonsPromise;

assert.equal(result, addonsInfo);
assert.calledWith(global.removeMessageListener, INCOMING_MESSAGE_NAME, listener);
});
});
});

describe("SnippetsProvider", () => {
Expand Down
33 changes: 24 additions & 9 deletions system-addon/test/unit/lib/SnippetsFeed.test.js
Expand Up @@ -64,14 +64,6 @@ describe("SnippetsFeed", () => {
sandbox.stub(global.Services.prefs, "getIntPref")
.withArgs("devtools.selfxss.count")
.returns(5);
sandbox.stub(global.AddonManager, "getActiveAddons")
.resolves({
addons: [
Object.assign({id: "foo"}, FAKE_ADDONS.foo),
Object.assign({id: "bar"}, FAKE_ADDONS.bar)
],
fullData: true
});

const getStub = sandbox.stub();
getStub.withArgs("previousSessionEnd").resolves(42);
Expand Down Expand Up @@ -104,7 +96,6 @@ describe("SnippetsFeed", () => {
assert.deepEqual(action.data.selectedSearchEngine, searchData);
assert.propertyVal(action.data, "defaultBrowser", true);
assert.propertyVal(action.data, "isDevtoolsUser", true);
assert.deepEqual(action.data.addonInfo, FAKE_ADDONS);
assert.deepEqual(action.data.blockList, [1]);
assert.propertyVal(action.data, "previousSessionEnd", 42);
});
Expand Down Expand Up @@ -223,6 +214,30 @@ describe("SnippetsFeed", () => {

assert.calledWith(feed.store.dispatch, ac.OnlyToOneContent(action, browser));
});
it("should respond with ADDONS_INFO_RESPONSE when ADDONS_INFO_REQUEST is received", async () => {
sandbox.stub(global.AddonManager, "getActiveAddons")
.resolves({
addons: [
Object.assign({id: "foo"}, FAKE_ADDONS.foo),
Object.assign({id: "bar"}, FAKE_ADDONS.bar)
],
fullData: true
});
const portId = "1234";
const feed = new SnippetsFeed();
feed.store = {dispatch: sandbox.stub()};
const expectedAction = {
type: at.ADDONS_INFO_RESPONSE,
data: {
isFullData: true,
addons: FAKE_ADDONS
}
};

await feed.onAction({type: at.ADDONS_INFO_REQUEST, meta: {fromTarget: portId}});

assert.calledWith(feed.store.dispatch, ac.OnlyToOneContent(expectedAction, portId));
});
it("should return true for isDevtoolsUser is devtools.selfxss.count is 5", async () => {
sandbox.stub(global.Services.prefs, "getIntPref")
.withArgs("devtools.selfxss.count")
Expand Down

0 comments on commit de57703

Please sign in to comment.