зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1494275 - Support dynamic install urls for CFR r=ursula
Differential Revision: https://phabricator.services.mozilla.com/D6974 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
acee6df4f4
Коммит
109f2177c9
|
@ -100,6 +100,12 @@
|
|||
"addon": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"allOf": [
|
||||
{"$ref": "#/definitions/plainText"},
|
||||
{"description": "Unique addon ID"}
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"allOf": [
|
||||
{"$ref": "#/definitions/plainText"},
|
||||
|
@ -212,10 +218,9 @@
|
|||
"data": {
|
||||
"properties": {
|
||||
"url": {
|
||||
"allOf": [
|
||||
{"$ref": "#/definitions/linkUrl"},
|
||||
{"description": "URL used in combination with the primary action dispatched."}
|
||||
]
|
||||
"type": "null",
|
||||
"$comment": "This is dynamically generated from the addon.id. See CFRPageActions.jsm",
|
||||
"description": "URL used in combination with the primary action dispatched."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
* 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 BASE_ADDONS_DOWNLOAD_URL = "https://addons.mozilla.org/firefox/downloads/file";
|
||||
const AMAZON_ASSISTANT_PARAMS = {
|
||||
existing_addons: ["abb@amazon.com", "{75c7fe97-5a90-4b54-9052-3534235eaf41}", "{ef34596e-1e43-4e84-b2ff-1e58e287e08d}", "{ea280feb-155a-492e-8016-ac96dd995f2c}", "izer@camelcamelcamel.com", "amptra@keepa.com", "pricealarm@icopron.ch", "{774f76c7-6807-481e-bf64-f9b7d5cda602}"],
|
||||
open_urls: ["smile.amazon.com", "www.audible.com", "www.amazon.com", "amazon.com", "audible.com"],
|
||||
|
@ -58,6 +57,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: AMAZON_ASSISTANT_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "337359",
|
||||
title: "Amazon Assistant",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_amazon_assistant.png",
|
||||
rating: 3.3,
|
||||
|
@ -71,7 +71,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/950930/amazon_assistant_for_firefox-10.1805.2.1019-an+fx.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
@ -99,6 +99,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: AMAZON_ASSISTANT_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "337359",
|
||||
title: "Amazon Assistant",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_amazon_assistant.png",
|
||||
rating: 3.3,
|
||||
|
@ -112,7 +113,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/950930/amazon_assistant_for_firefox-10.1805.2.1019-an+fx.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
@ -140,6 +141,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: FACEBOOK_CONTAINER_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "954390",
|
||||
title: "Facebook Container",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_fb_container.png",
|
||||
rating: 4.6,
|
||||
|
@ -153,7 +155,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/918624/facebook_container-1.3.1-an+fx-linux.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
@ -181,6 +183,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: FACEBOOK_CONTAINER_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "954390",
|
||||
title: "Facebook Container",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_fb_container.png",
|
||||
rating: 4.6,
|
||||
|
@ -194,7 +197,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/918624/facebook_container-1.3.1-an+fx-linux.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
@ -222,6 +225,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: GOOGLE_TRANSLATE_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "445852",
|
||||
title: "To Google Translate",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_google_translate.png",
|
||||
rating: 4.1,
|
||||
|
@ -235,7 +239,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/1008798/al_traductor_de_google-3.3-an+fx.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
@ -263,6 +267,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: GOOGLE_TRANSLATE_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "445852",
|
||||
title: "To Google Translate",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_google_translate.png",
|
||||
rating: 4.1,
|
||||
|
@ -276,7 +281,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/1008798/al_traductor_de_google-3.3-an+fx.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
@ -304,6 +309,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: YOUTUBE_ENHANCE_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "700308",
|
||||
title: "Enhancer for YouTube\u2122",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_enhancer_youtube.png",
|
||||
rating: 4.8,
|
||||
|
@ -317,7 +323,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/1028400/enhancer_for_youtubetm-2.0.73-an+fx-linux.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
@ -345,6 +351,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: YOUTUBE_ENHANCE_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "700308",
|
||||
title: "Enhancer for YouTube\u2122",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_enhancer_youtube.png",
|
||||
rating: 4.8,
|
||||
|
@ -358,7 +365,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/1028400/enhancer_for_youtubetm-2.0.73-an+fx-linux.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
@ -386,6 +393,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: WIKIPEDIA_CONTEXT_MENU_SEARCH_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "659026",
|
||||
title: "Wikipedia Context Menu Search",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_wiki_search.png",
|
||||
rating: 4.9,
|
||||
|
@ -399,7 +407,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/890224/wikipedia_context_menu_search-1.8-an+fx.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
@ -427,6 +435,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: WIKIPEDIA_CONTEXT_MENU_SEARCH_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "659026",
|
||||
title: "Wikipedia Context Menu Search",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_wiki_search.png",
|
||||
rating: 4.9,
|
||||
|
@ -440,7 +449,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/890224/wikipedia_context_menu_search-1.8-an+fx.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
@ -468,6 +477,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: REDDIT_ENHANCEMENT_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "387429",
|
||||
title: "Reddit Enhancement Suite",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_reddit_enhancement.png",
|
||||
rating: 4.6,
|
||||
|
@ -481,7 +491,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/991623/reddit_enhancement_suite-5.12.5-an+fx.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
@ -509,6 +519,7 @@ const CFR_MESSAGES = [
|
|||
sumo_path: REDDIT_ENHANCEMENT_PARAMS.sumo_path,
|
||||
},
|
||||
addon: {
|
||||
id: "387429",
|
||||
title: "Reddit Enhancement Suite",
|
||||
icon: "resource://activity-stream/data/content/assets/cfr_reddit_enhancement.png",
|
||||
rating: 4.6,
|
||||
|
@ -522,7 +533,7 @@ const CFR_MESSAGES = [
|
|||
label: {string_id: "cfr-doorhanger-extension-ok-button"},
|
||||
action: {
|
||||
type: "INSTALL_ADDON_FROM_URL",
|
||||
data: {url: `${BASE_ADDONS_DOWNLOAD_URL}/991623/reddit_enhancement_suite-5.12.5-an+fx.xpi`},
|
||||
data: {url: null},
|
||||
},
|
||||
},
|
||||
secondary: {
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Localization.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
const POPUP_NOTIFICATION_ID = "contextual-feature-recommendation";
|
||||
const SUMO_BASE_URL = Services.urlFormatter.formatURLPref("app.support.baseURL");
|
||||
const ADDONS_API_URL = "https://services.addons.mozilla.org/api/v3/addons/addon";
|
||||
|
||||
const DELAY_BEFORE_EXPAND_MS = 1000;
|
||||
|
||||
|
@ -396,16 +399,70 @@ const CFRPageActions = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch the URL to the latest add-on xpi so the recommendation can download it.
|
||||
* @param addon The add-on provided by the CFRMessageProvider
|
||||
* @return A string for the URL that was fetched
|
||||
*/
|
||||
async _fetchLatestAddonVersion({id}) {
|
||||
let url = null;
|
||||
try {
|
||||
const response = await fetch(`${ADDONS_API_URL}/${id}`);
|
||||
if (response.status !== 204 && response.ok) {
|
||||
const json = await response.json();
|
||||
url = json.current_version.files[0].url;
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError("Failed to get the latest add-on version for this recommendation");
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
async _maybeAddAddonInstallURL(recommendation) {
|
||||
const {content, template} = recommendation;
|
||||
// If this is CFR is not for an add-on, return the original recommendation
|
||||
if (template !== "cfr_doorhanger") {
|
||||
return recommendation;
|
||||
}
|
||||
|
||||
const url = await this._fetchLatestAddonVersion(content.addon);
|
||||
// If we failed to get a url to the latest xpi, return false so we know not to show
|
||||
// a recommendation
|
||||
if (!url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the action's data with the url to the latest xpi, leave the rest
|
||||
// of the recommendation properties intact
|
||||
return {
|
||||
...recommendation,
|
||||
content: {
|
||||
...content,
|
||||
buttons: {
|
||||
...content.buttons,
|
||||
primary: {
|
||||
...content.buttons.primary,
|
||||
action: {...content.buttons.primary.action, data: {url}},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Force a recommendation to be shown. Should only happen via the Admin page.
|
||||
* @param browser The browser for the recommendation
|
||||
* @param recommendation The recommendation to show
|
||||
* @param originalRecommendation The recommendation to show
|
||||
* @param dispatchToASRouter A function to dispatch resulting actions to
|
||||
* @return Did adding the recommendation succeed?
|
||||
*/
|
||||
async forceRecommendation(browser, recommendation, dispatchToASRouter) {
|
||||
async forceRecommendation(browser, originalRecommendation, dispatchToASRouter) {
|
||||
// If we are forcing via the Admin page, the browser comes in a different format
|
||||
const win = browser.browser.ownerGlobal;
|
||||
const recommendation = await this._maybeAddAddonInstallURL(originalRecommendation);
|
||||
if (!recommendation) {
|
||||
return false;
|
||||
}
|
||||
const {id, content} = recommendation;
|
||||
RecommendationMap.set(browser.browser, {id, content});
|
||||
if (!PageActionMap.has(win)) {
|
||||
|
@ -419,11 +476,11 @@ const CFRPageActions = {
|
|||
* Add a recommendation specific to the given browser and host.
|
||||
* @param browser The browser for the recommendation
|
||||
* @param host The host for the recommendation
|
||||
* @param recommendation The recommendation to show
|
||||
* @param originalRecommendation The recommendation to show
|
||||
* @param dispatchToASRouter A function to dispatch resulting actions to
|
||||
* @return Did adding the recommendation succeed?
|
||||
*/
|
||||
async addRecommendation(browser, host, recommendation, dispatchToASRouter) {
|
||||
async addRecommendation(browser, host, originalRecommendation, dispatchToASRouter) {
|
||||
const win = browser.ownerGlobal;
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(win)) {
|
||||
return false;
|
||||
|
@ -431,6 +488,10 @@ const CFRPageActions = {
|
|||
if (browser !== win.gBrowser.selectedBrowser || !isHostMatch(browser, host)) {
|
||||
return false;
|
||||
}
|
||||
const recommendation = await this._maybeAddAddonInstallURL(originalRecommendation);
|
||||
if (!recommendation) {
|
||||
return false;
|
||||
}
|
||||
const {id, content} = recommendation;
|
||||
RecommendationMap.set(browser, {id, host, content});
|
||||
if (!PageActionMap.has(win)) {
|
||||
|
|
|
@ -640,6 +640,23 @@ describe("CFRPageActions", () => {
|
|||
assert.equal(dispatchStub, pageAction._dispatchToASRouter);
|
||||
assert.calledOnce(PageAction.prototype.show);
|
||||
});
|
||||
it("should add the right url if we fetched and addon install URL", async () => {
|
||||
sinon.stub(CFRPageActions, "_fetchLatestAddonVersion").returns(Promise.resolve("latest-addon.xpi"));
|
||||
fakeRecommendation.template = "cfr_doorhanger";
|
||||
await CFRPageActions.addRecommendation(fakeBrowser, fakeHost, fakeRecommendation, dispatchStub);
|
||||
const recommendation = CFRPageActions.RecommendationMap.get(fakeBrowser);
|
||||
assert.equal(recommendation.content.buttons.primary.action.data.url, "latest-addon.xpi");
|
||||
|
||||
// sanity check - just go through some of the rest of the attributes to make sure they were untouched
|
||||
assert.equal(recommendation.id, fakeRecommendation.id);
|
||||
assert.equal(recommendation.content.heading_text, fakeRecommendation.content.heading_text);
|
||||
assert.equal(recommendation.content.addon, fakeRecommendation.content.addon);
|
||||
assert.equal(recommendation.content.text, fakeRecommendation.content.text);
|
||||
assert.equal(recommendation.content.buttons.secondary, fakeRecommendation.content.buttons.secondary);
|
||||
assert.equal(recommendation.content.buttons.primary.action.id, fakeRecommendation.content.buttons.primary.action.id);
|
||||
|
||||
delete fakeRecommendation.template;
|
||||
});
|
||||
});
|
||||
|
||||
describe("clearRecommendations", () => {
|
||||
|
|
|
@ -10,6 +10,7 @@ const DEFAULT_CONTENT = {
|
|||
"sumo_path": "extensionrecommendations",
|
||||
},
|
||||
"addon": {
|
||||
"id": "1234",
|
||||
"title": "Addon name",
|
||||
"icon": "https://mozilla.org/icon",
|
||||
"author": "Author name",
|
||||
|
@ -24,7 +25,7 @@ const DEFAULT_CONTENT = {
|
|||
},
|
||||
"action": {
|
||||
"type": "INSTALL_ADDON_FROM_URL",
|
||||
"data": {"url": "https://example.com"},
|
||||
"data": {"url": null},
|
||||
},
|
||||
},
|
||||
"secondary": {
|
||||
|
@ -46,6 +47,7 @@ const L10N_CONTENT = {
|
|||
"sumo_path": "extensionrecommendations",
|
||||
},
|
||||
"addon": {
|
||||
"id": "1234",
|
||||
"title": "Addon name",
|
||||
"icon": "https://mozilla.org/icon",
|
||||
"author": "Author name",
|
||||
|
@ -57,7 +59,7 @@ const L10N_CONTENT = {
|
|||
"label": {"string_id": "btn_ok_id"},
|
||||
"action": {
|
||||
"type": "INSTALL_ADDON_FROM_URL",
|
||||
"data": {"url": "https://example.com"},
|
||||
"data": {"url": null},
|
||||
},
|
||||
},
|
||||
"secondary": {
|
||||
|
|
Загрузка…
Ссылка в новой задаче