From a96d0d63314b06e83ff3c2dac4d5bcffb7826271 Mon Sep 17 00:00:00 2001 From: Andrew Swan Date: Mon, 14 May 2018 10:18:32 -0700 Subject: [PATCH] Bug 1429610 Add internal api to look up available language packs r=gandalf,rpl MozReview-Commit-ID: ISIu9mDIvbP --HG-- extra : rebase_source : 800cbd7ddf943f7740d37f47fe6154240da3b831 extra : source : ca539f07691c6e243bcb0f4a3137d0e0940ab2a0 --- browser/app/profile/firefox.js | 1 + mobile/android/app/mobile.js | 1 + .../extensions/internal/AddonRepository.jsm | 38 +++++++- .../test_AddonRepository_langpacks.js | 95 +++++++++++++++++++ .../extensions/test/xpcshell/xpcshell.ini | 1 + 5 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_langpacks.js diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 74c9de5cabd5..747461f68a85 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -45,6 +45,7 @@ pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCAL pref("extensions.webservice.discoverURL", "https://discovery.addons.mozilla.org/%LOCALE%/firefox/discovery/pane/%VERSION%/%OS%/%COMPATIBILITY_MODE%"); pref("extensions.getAddons.link.url", "https://addons.mozilla.org/%LOCALE%/firefox/"); pref("extensions.getAddons.themes.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes/?src=firefox"); +pref("extensions.getAddons.langpacks.url", "https://services.addons.mozilla.org/api/v3/addons/language-tools/?app=firefox&type=language&appversion=%VERSION%"); pref("extensions.update.autoUpdateDefault", true); diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index 328fc752ca17..c12d1bb25377 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -216,6 +216,7 @@ pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCAL pref("extensions.getAddons.browseAddons", "https://addons.mozilla.org/%LOCALE%/android/"); pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/api/v3/addons/search/?guid=%IDS%&lang=%LOCALE%"); pref("extensions.getAddons.compatOverides.url", "https://services.addons.mozilla.org/api/v3/addons/compat-override/?guid=%IDS%&lang=%LOCALE%"); +pref("extensions.getAddons.langpacks.url", "https://services.addons.mozilla.org/api/v3/addons/language-tools/?app=android&type=language&appversion=%VERSION%"); /* preference for the locale picker */ pref("extensions.getLocales.get.url", ""); diff --git a/toolkit/mozapps/extensions/internal/AddonRepository.jsm b/toolkit/mozapps/extensions/internal/AddonRepository.jsm index b159b527d507..3dfa3eda1bf7 100644 --- a/toolkit/mozapps/extensions/internal/AddonRepository.jsm +++ b/toolkit/mozapps/extensions/internal/AddonRepository.jsm @@ -40,6 +40,8 @@ XPCOMUtils.defineLazyGetter(this, "PLATFORM", () => { var EXPORTED_SYMBOLS = [ "AddonRepository" ]; +Cu.importGlobalProperties(["fetch"]); + const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; const PREF_GETADDONS_CACHE_TYPES = "extensions.getAddons.cache.types"; const PREF_GETADDONS_CACHE_ID_ENABLED = "extensions.%ID%.getAddons.cache.enabled"; @@ -48,6 +50,7 @@ const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url"; const PREF_COMPAT_OVERRIDES = "extensions.getAddons.compatOverides.url"; const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL"; const PREF_GETADDONS_DB_SCHEMA = "extensions.getAddons.databaseSchema"; +const PREF_GET_LANGPACKS = "extensions.getAddons.langpacks.url"; const PREF_METADATA_LASTUPDATE = "extensions.getAddons.cache.lastUpdate"; const PREF_METADATA_UPDATETHRESHOLD_SEC = "extensions.getAddons.cache.updateThreshold"; @@ -731,7 +734,7 @@ var AddonRepository = { }, // Create url from preference, returning null if preference does not exist - _formatURLPref(aPreference, aSubstitutions) { + _formatURLPref(aPreference, aSubstitutions = {}) { let url = Services.prefs.getCharPref(aPreference, ""); if (!url) { logger.warn("_formatURLPref: Couldn't get pref: " + aPreference); @@ -772,6 +775,39 @@ var AddonRepository = { flush() { return AddonDatabase.flush(); }, + + async getAvailableLangpacks() { + // This should be the API endpoint documented at: + // http://addons-server.readthedocs.io/en/latest/topics/api/addons.html#language-tools + let url = this._formatURLPref(PREF_GET_LANGPACKS); + + let response = await fetch(url); + if (!response.ok) { + throw new Error("fetching available language packs failed"); + } + + let data = await response.json(); + + let result = []; + for (let entry of data.results) { + if (!entry.current_compatible_version || + !entry.current_compatible_version.files) { + continue; + } + + for (let file of entry.current_compatible_version.files) { + if (file.platform == "all" || file.platform == Services.appinfo.OS.toLowerCase()) { + result.push({ + target_locale: entry.target_locale, + url: file.url, + hash: file.hash, + }); + } + } + } + + return result; + }, }; var AddonDatabase = { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_langpacks.js b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_langpacks.js new file mode 100644 index 000000000000..d985ff528d5e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_langpacks.js @@ -0,0 +1,95 @@ +ChromeUtils.import("resource://gre/modules/addons/AddonRepository.jsm"); + +const PREF_GET_LANGPACKS = "extensions.getAddons.langpacks.url"; + +let server = AddonTestUtils.createHttpServer({hosts: ["example.com"]}); + +add_task(async function setup() { + Services.prefs.setStringPref(PREF_GET_LANGPACKS, "http://example.com/langpacks.json"); + + function setData(data) { + if (typeof data != "string") { + data = JSON.stringify(data); + } + + server.registerPathHandler("/langpacks.json", (request, response) => { + response.setHeader("content-type", "application/json"); + response.write(data); + }); + } + + const EXPECTED = [ + { + target_locale: "kl", + url: "http://example.com/langpack1.xpi", + hash: "sha256:0123456789abcdef", + }, + { + target_locale: "fo", + url: "http://example.com/langpack2.xpi", + hash: "sha256:fedcba9876543210", + }, + ]; + + setData({ + results: [ + // A simple entry + { + target_locale: EXPECTED[0].target_locale, + current_compatible_version: { + files: [ + { + platform: "all", + url: EXPECTED[0].url, + hash: EXPECTED[0].hash, + }, + ], + }, + }, + + // An entry with multiple supported platforms + { + target_locale: EXPECTED[1].target_locale, + current_compatible_version: { + files: [ + { + platform: "somethingelse", + url: "http://example.com/bogus.xpi", + hash: "sha256:abcd", + }, + { + platform: Services.appinfo.OS.toLowerCase(), + url: EXPECTED[1].url, + hash: EXPECTED[1].hash, + }, + ], + }, + }, + + // An entry with no matching platform + { + target_locale: "bla", + current_compatible_version: { + files: [ + { + platform: "unsupportedplatform", + url: "http://example.com/bogus2.xpi", + hash: "sha256:1234", + }, + ], + }, + }, + ] + }); + + let result = await AddonRepository.getAvailableLangpacks(); + equal(result.length, 2, "Got 2 results"); + + deepEqual(result[0], EXPECTED[0], "Got expected result for simple entry"); + deepEqual(result[1], EXPECTED[1], "Got expected result for multi-platform entry"); + + setData("not valid json"); + await Assert.rejects(AddonRepository.getAvailableLangpacks(), + /SyntaxError/, "Got parse error on invalid JSON"); + +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini index 20b11d256e70..3b95d736f20a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini @@ -11,6 +11,7 @@ support-files = [test_AddonRepository_cache.js] # Bug 676992: test consistently hangs on Android skip-if = os == "android" +[test_AddonRepository_langpacks.js] [test_AddonRepository_paging.js] [test_LightweightThemeManager.js] [test_ProductAddonChecker.js]