From 8dd16259287f58f9273002717ec4d27e97127719 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:43:14 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- .../extensions/test/xpcshell/test_AbuseReporter.js | 687 +-------------------- .../test/xpcshell/test_dictionary_webextension.js | 15 +- .../test/xpcshell/test_webextension_install.js | 196 +++++- .../mozapps/extensions/test/xpcshell/xpcshell.toml | 199 +++++- 4 files changed, 392 insertions(+), 705 deletions(-) (limited to 'toolkit/mozapps/extensions/test/xpcshell') diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_AbuseReporter.js b/toolkit/mozapps/extensions/test/xpcshell/test_AbuseReporter.js index c94ef29e31..4fe0821c70 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_AbuseReporter.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_AbuseReporter.js @@ -2,88 +2,21 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -const { AbuseReporter, AbuseReportError } = ChromeUtils.importESModule( +const { AbuseReporter } = ChromeUtils.importESModule( "resource://gre/modules/AbuseReporter.sys.mjs" ); const { ClientID } = ChromeUtils.importESModule( "resource://gre/modules/ClientID.sys.mjs" ); -const { TelemetryController } = ChromeUtils.importESModule( - "resource://gre/modules/TelemetryController.sys.mjs" -); -const { TelemetryTestUtils } = ChromeUtils.importESModule( - "resource://testing-common/TelemetryTestUtils.sys.mjs" -); const APPNAME = "XPCShell"; const APPVERSION = "1"; const ADDON_ID = "test-addon@tests.mozilla.org"; -const ADDON_ID2 = "test-addon2@tests.mozilla.org"; const FAKE_INSTALL_INFO = { source: "fake-Install:Source", method: "fake:install method", }; -const PREF_REQUIRED_LOCALE = "intl.locale.requested"; -const REPORT_OPTIONS = { reportEntryPoint: "menu" }; -const TELEMETRY_EVENTS_FILTERS = { - category: "addonsManager", - method: "report", -}; - -const FAKE_AMO_DETAILS = { - name: { - "en-US": "fake name", - "it-IT": "fake it-IT name", - }, - current_version: { version: "1.0" }, - type: "extension", - is_recommended: true, -}; - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "49"); - -const server = createHttpServer({ hosts: ["test.addons.org"] }); - -// Mock abuse report API endpoint. -let apiRequestHandler; -server.registerPathHandler("/api/report/", (request, response) => { - const stream = request.bodyInputStream; - const buffer = NetUtil.readInputStream(stream, stream.available()); - const data = new TextDecoder().decode(buffer); - apiRequestHandler({ data, request, response }); -}); - -// Mock addon details API endpoint. -const amoAddonDetailsMap = new Map(); -server.registerPrefixHandler("/api/addons/addon/", (request, response) => { - const addonId = request.path.split("/").pop(); - if (!amoAddonDetailsMap.has(addonId)) { - response.setStatusLine(request.httpVersion, 404, "Not Found"); - response.write(JSON.stringify({ detail: "Not found." })); - } else { - response.setStatusLine(request.httpVersion, 200, "Success"); - response.write(JSON.stringify(amoAddonDetailsMap.get(addonId))); - } -}); - -function getProperties(obj, propNames) { - return propNames.reduce((acc, el) => { - acc[el] = obj[el]; - return acc; - }, {}); -} - -function handleSubmitRequest({ request, response }) { - response.setStatusLine(request.httpVersion, 200, "OK"); - response.setHeader("Content-Type", "application/json", false); - response.write("{}"); -} - -function clearAbuseReportState() { - // Clear the timestamp of the last submission. - AbuseReporter._lastReportTimestamp = null; -} async function installTestExtension(overrideOptions = {}) { const extOptions = { @@ -104,34 +37,6 @@ async function installTestExtension(overrideOptions = {}) { return { extension, addon }; } -async function assertRejectsAbuseReportError(promise, errorType, errorInfo) { - let error; - - await Assert.rejects( - promise, - err => { - // Log the actual error to make investigating test failures easier. - Cu.reportError(err); - error = err; - return err instanceof AbuseReportError; - }, - `Got an AbuseReportError` - ); - - equal(error.errorType, errorType, "Got the expected errorType"); - equal(error.errorInfo, errorInfo, "Got the expected errorInfo"); - ok( - error.message.includes(errorType), - "errorType should be included in the error message" - ); - if (errorInfo) { - ok( - error.message.includes(errorInfo), - "errorInfo should be included in the error message" - ); - } -} - async function assertBaseReportData({ reportData, addon }) { // Report properties related to addon metadata. equal(reportData.addon, ADDON_ID, "Got expected 'addon'"); @@ -191,42 +96,10 @@ async function assertBaseReportData({ reportData, addon }) { ); } -add_task(async function test_setup() { - Services.prefs.setCharPref( - "extensions.abuseReport.url", - "http://test.addons.org/api/report/" - ); - - Services.prefs.setCharPref( - "extensions.abuseReport.amoDetailsURL", - "http://test.addons.org/api/addons/addon" - ); +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "49"); +add_setup(async () => { await promiseStartupManager(); - // Telemetry test setup needed to ensure that the builtin events are defined - // and they can be collected and verified. - await TelemetryController.testSetup(); - - // This is actually only needed on Android, because it does not properly support unified telemetry - // and so, if not enabled explicitly here, it would make these tests to fail when running on a - // non-Nightly build. - const oldCanRecordBase = Services.telemetry.canRecordBase; - Services.telemetry.canRecordBase = true; - registerCleanupFunction(() => { - Services.telemetry.canRecordBase = oldCanRecordBase; - }); - - // Register a fake it-IT locale (used to test localized AMO details in some - // of the test case defined in this test file). - L10nRegistry.getInstance().registerSources([ - L10nFileSource.createMock( - "mock", - "app", - ["it-IT", "fr-FR"], - "resource://fake/locales/{locale}", - [] - ), - ]); }); add_task(async function test_addon_report_data() { @@ -260,37 +133,6 @@ add_task(async function test_addon_report_data() { await extension3.unload(); }); -add_task(async function test_report_on_not_installed_addon() { - Services.telemetry.clearEvents(); - - // Make sure that the AMO addons details API endpoint is going to - // return a 404 status for the not installed addon. - amoAddonDetailsMap.delete(ADDON_ID); - - await assertRejectsAbuseReportError( - AbuseReporter.createAbuseReport(ADDON_ID, REPORT_OPTIONS), - "ERROR_ADDON_NOTFOUND" - ); - - TelemetryTestUtils.assertEvents( - [ - { - object: REPORT_OPTIONS.reportEntryPoint, - value: ADDON_ID, - extra: { error_type: "ERROR_AMODETAILS_NOTFOUND" }, - }, - { - object: REPORT_OPTIONS.reportEntryPoint, - value: ADDON_ID, - extra: { error_type: "ERROR_ADDON_NOTFOUND" }, - }, - ], - TELEMETRY_EVENTS_FILTERS - ); - - Services.telemetry.clearEvents(); -}); - // This tests verifies how the addon installTelemetryInfo values are being // normalized into the addon_install_source and addon_install_method // expected by the API endpoint. @@ -379,526 +221,3 @@ add_task(async function test_normalized_addon_install_source_and_method() { await assertAddonInstallMethod(test, expect); } }); - -add_task(async function test_report_create_and_submit() { - Services.telemetry.clearEvents(); - - // Override the test api server request handler, to be able to - // intercept the submittions to the test api server. - let reportSubmitted; - apiRequestHandler = ({ data, request, response }) => { - reportSubmitted = JSON.parse(data); - handleSubmitRequest({ request, response }); - }; - - const { addon, extension } = await installTestExtension(); - - const reportEntryPoint = "menu"; - const report = await AbuseReporter.createAbuseReport(ADDON_ID, { - reportEntryPoint, - }); - - equal(report.addon, addon, "Got the expected addon property"); - equal( - report.reportEntryPoint, - reportEntryPoint, - "Got the expected reportEntryPoint" - ); - - const baseReportData = await AbuseReporter.getReportData(addon); - const reportProperties = { - message: "test message", - reason: "test-reason", - }; - - info("Submitting report"); - report.setMessage(reportProperties.message); - report.setReason(reportProperties.reason); - await report.submit(); - - const expectedEntries = Object.entries({ - report_entry_point: reportEntryPoint, - ...baseReportData, - ...reportProperties, - }); - - for (const [expectedKey, expectedValue] of expectedEntries) { - equal( - reportSubmitted[expectedKey], - expectedValue, - `Got the expected submitted value for "${expectedKey}"` - ); - } - - TelemetryTestUtils.assertEvents( - [ - { - object: reportEntryPoint, - value: ADDON_ID, - extra: { addon_type: "extension" }, - }, - ], - TELEMETRY_EVENTS_FILTERS - ); - - await extension.unload(); -}); - -add_task(async function test_error_recent_submit() { - Services.telemetry.clearEvents(); - clearAbuseReportState(); - - let reportSubmitted; - apiRequestHandler = ({ data, request, response }) => { - reportSubmitted = JSON.parse(data); - handleSubmitRequest({ request, response }); - }; - - const { extension } = await installTestExtension(); - const report = await AbuseReporter.createAbuseReport(ADDON_ID, { - reportEntryPoint: "uninstall", - }); - - const { extension: extension2 } = await installTestExtension({ - manifest: { - browser_specific_settings: { gecko: { id: ADDON_ID2 } }, - name: "Test Extension2", - }, - }); - const report2 = await AbuseReporter.createAbuseReport( - ADDON_ID2, - REPORT_OPTIONS - ); - - // Submit the two reports in fast sequence. - report.setReason("reason1"); - report2.setReason("reason2"); - await report.submit(); - await assertRejectsAbuseReportError(report2.submit(), "ERROR_RECENT_SUBMIT"); - equal( - reportSubmitted.reason, - "reason1", - "Server only received the data from the first submission" - ); - - TelemetryTestUtils.assertEvents( - [ - { - object: "uninstall", - value: ADDON_ID, - extra: { addon_type: "extension" }, - }, - { - object: REPORT_OPTIONS.reportEntryPoint, - value: ADDON_ID2, - extra: { - addon_type: "extension", - error_type: "ERROR_RECENT_SUBMIT", - }, - }, - ], - TELEMETRY_EVENTS_FILTERS - ); - - await extension.unload(); - await extension2.unload(); -}); - -add_task(async function test_submission_server_error() { - const { extension } = await installTestExtension(); - - async function testErrorCode({ - responseStatus, - responseText = "", - expectedErrorType, - expectedErrorInfo, - expectRequest = true, - }) { - info( - `Test expected AbuseReportError on response status "${responseStatus}"` - ); - Services.telemetry.clearEvents(); - clearAbuseReportState(); - - let requestReceived = false; - apiRequestHandler = ({ request, response }) => { - requestReceived = true; - response.setStatusLine(request.httpVersion, responseStatus, "Error"); - response.write(responseText); - }; - - const report = await AbuseReporter.createAbuseReport( - ADDON_ID, - REPORT_OPTIONS - ); - report.setReason("a-reason"); - const promiseSubmit = report.submit(); - if (typeof expectedErrorType === "string") { - // Assert a specific AbuseReportError errorType. - await assertRejectsAbuseReportError( - promiseSubmit, - expectedErrorType, - expectedErrorInfo - ); - } else { - // Assert on a given Error class. - await Assert.rejects(promiseSubmit, expectedErrorType); - } - equal( - requestReceived, - expectRequest, - `${expectRequest ? "" : "Not "}received a request as expected` - ); - - TelemetryTestUtils.assertEvents( - [ - { - object: REPORT_OPTIONS.reportEntryPoint, - value: ADDON_ID, - extra: { - addon_type: "extension", - error_type: - typeof expectedErrorType === "string" - ? expectedErrorType - : "ERROR_UNKNOWN", - }, - }, - ], - TELEMETRY_EVENTS_FILTERS - ); - } - - await testErrorCode({ - responseStatus: 500, - responseText: "A server error", - expectedErrorType: "ERROR_SERVER", - expectedErrorInfo: JSON.stringify({ - status: 500, - responseText: "A server error", - }), - }); - await testErrorCode({ - responseStatus: 404, - responseText: "Not found error", - expectedErrorType: "ERROR_CLIENT", - expectedErrorInfo: JSON.stringify({ - status: 404, - responseText: "Not found error", - }), - }); - // Test response with unexpected status code. - await testErrorCode({ - responseStatus: 604, - responseText: "An unexpected status code", - expectedErrorType: "ERROR_UNKNOWN", - expectedErrorInfo: JSON.stringify({ - status: 604, - responseText: "An unexpected status code", - }), - }); - // Test response status 200 with invalid json data. - await testErrorCode({ - responseStatus: 200, - expectedErrorType: /SyntaxError: JSON.parse/, - }); - - // Test on invalid url. - Services.prefs.setCharPref( - "extensions.abuseReport.url", - "invalid-protocol://abuse-report" - ); - await testErrorCode({ - expectedErrorType: "ERROR_NETWORK", - expectRequest: false, - }); - - await extension.unload(); -}); - -add_task(async function set_test_abusereport_url() { - Services.prefs.setCharPref( - "extensions.abuseReport.url", - "http://test.addons.org/api/report/" - ); -}); - -add_task(async function test_submission_aborting() { - Services.telemetry.clearEvents(); - clearAbuseReportState(); - - const { extension } = await installTestExtension(); - - // override the api request handler with one that is never going to reply. - let receivedRequestsCount = 0; - let resolvePendingResponses; - const waitToReply = new Promise( - resolve => (resolvePendingResponses = resolve) - ); - - const onRequestReceived = new Promise(resolve => { - apiRequestHandler = ({ request, response }) => { - response.processAsync(); - response.setStatusLine(request.httpVersion, 200, "OK"); - receivedRequestsCount++; - resolve(); - - // Keep the request pending until resolvePendingResponses have been - // called. - waitToReply.then(() => { - response.finish(); - }); - }; - }); - - const report = await AbuseReporter.createAbuseReport( - ADDON_ID, - REPORT_OPTIONS - ); - report.setReason("a-reason"); - const promiseResult = report.submit(); - - await onRequestReceived; - - Assert.greater( - receivedRequestsCount, - 0, - "Got the expected number of requests" - ); - Assert.strictEqual( - await Promise.race([promiseResult, Promise.resolve("pending")]), - "pending", - "Submission fetch request should still be pending" - ); - - report.abort(); - - await assertRejectsAbuseReportError(promiseResult, "ERROR_ABORTED_SUBMIT"); - - TelemetryTestUtils.assertEvents( - [ - { - object: REPORT_OPTIONS.reportEntryPoint, - value: ADDON_ID, - extra: { addon_type: "extension", error_type: "ERROR_ABORTED_SUBMIT" }, - }, - ], - TELEMETRY_EVENTS_FILTERS - ); - - await extension.unload(); - - // Unblock pending requests on the server request handler side, so that the - // test file can shutdown (otherwise the test run will be stuck after this - // task completed). - resolvePendingResponses(); -}); - -add_task(async function test_truncated_string_properties() { - const generateString = len => new Array(len).fill("a").join(""); - - const LONG_STRINGS_ADDON_ID = "addon-with-long-strings-props@mochi.test"; - const { extension } = await installTestExtension({ - manifest: { - name: generateString(400), - description: generateString(400), - browser_specific_settings: { gecko: { id: LONG_STRINGS_ADDON_ID } }, - }, - }); - - // Override the test api server request handler, to be able to - // intercept the properties actually submitted. - let reportSubmitted; - apiRequestHandler = ({ data, request, response }) => { - reportSubmitted = JSON.parse(data); - handleSubmitRequest({ request, response }); - }; - - const report = await AbuseReporter.createAbuseReport( - LONG_STRINGS_ADDON_ID, - REPORT_OPTIONS - ); - - report.setMessage("fake-message"); - report.setReason("fake-reason"); - await report.submit(); - - const expected = { - addon_name: generateString(255), - addon_summary: generateString(255), - }; - - Assert.deepEqual( - { - addon_name: reportSubmitted.addon_name, - addon_summary: reportSubmitted.addon_summary, - }, - expected, - "Got the long strings truncated as expected" - ); - - await extension.unload(); -}); - -add_task(async function test_report_recommended() { - const NON_RECOMMENDED_ADDON_ID = "non-recommended-addon@mochi.test"; - const RECOMMENDED_ADDON_ID = "recommended-addon@mochi.test"; - - const now = Date.now(); - const not_before = new Date(now - 3600000).toISOString(); - const not_after = new Date(now + 3600000).toISOString(); - - const { extension: nonRecommended } = await installTestExtension({ - manifest: { - name: "Fake non recommended addon", - browser_specific_settings: { gecko: { id: NON_RECOMMENDED_ADDON_ID } }, - }, - }); - - const { extension: recommended } = await installTestExtension({ - manifest: { - name: "Fake recommended addon", - browser_specific_settings: { gecko: { id: RECOMMENDED_ADDON_ID } }, - }, - files: { - "mozilla-recommendation.json": { - addon_id: RECOMMENDED_ADDON_ID, - states: ["recommended"], - validity: { not_before, not_after }, - }, - }, - }); - - // Override the test api server request handler, to be able to - // intercept the properties actually submitted. - let reportSubmitted; - apiRequestHandler = ({ data, request, response }) => { - reportSubmitted = JSON.parse(data); - handleSubmitRequest({ request, response }); - }; - - async function checkReportedSignature(addonId, expectedAddonSignature) { - clearAbuseReportState(); - const report = await AbuseReporter.createAbuseReport( - addonId, - REPORT_OPTIONS - ); - report.setMessage("fake-message"); - report.setReason("fake-reason"); - await report.submit(); - equal( - reportSubmitted.addon_signature, - expectedAddonSignature, - `Got the expected addon_signature for ${addonId}` - ); - } - - await checkReportedSignature(NON_RECOMMENDED_ADDON_ID, "signed"); - await checkReportedSignature(RECOMMENDED_ADDON_ID, "curated"); - - await nonRecommended.unload(); - await recommended.unload(); -}); - -add_task(async function test_query_amo_details() { - async function assertReportOnAMODetails({ addonId, expectedReport } = {}) { - // Clear last report timestamp and any telemetry event recorded so far. - clearAbuseReportState(); - Services.telemetry.clearEvents(); - - const report = await AbuseReporter.createAbuseReport(addonId, { - reportEntryPoint: "menu", - }); - - let reportSubmitted; - apiRequestHandler = ({ data, request, response }) => { - reportSubmitted = JSON.parse(data); - handleSubmitRequest({ request, response }); - }; - - report.setMessage("fake message"); - report.setReason("reason1"); - await report.submit(); - - Assert.deepEqual( - expectedReport, - getProperties(reportSubmitted, Object.keys(expectedReport)), - "Got the expected report properties" - ); - - // Telemetry recorded for the successfully submitted report. - TelemetryTestUtils.assertEvents( - [ - { - object: "menu", - value: addonId, - extra: { addon_type: FAKE_AMO_DETAILS.type }, - }, - ], - TELEMETRY_EVENTS_FILTERS - ); - - clearAbuseReportState(); - } - - // Add the expected AMO addons details. - const addonId = "not-installed-addon@mochi.test"; - amoAddonDetailsMap.set(addonId, FAKE_AMO_DETAILS); - - // Test on the default en-US locale. - Services.prefs.setCharPref(PREF_REQUIRED_LOCALE, "en-US"); - let locale = Services.locale.appLocaleAsBCP47; - equal(locale, "en-US", "Got the expected app locale set"); - - let expectedReport = { - addon: addonId, - addon_name: FAKE_AMO_DETAILS.name[locale], - addon_version: FAKE_AMO_DETAILS.current_version.version, - addon_install_source: "not_installed", - addon_install_method: null, - addon_signature: "curated", - }; - - await assertReportOnAMODetails({ addonId, expectedReport }); - - // Test with a non-default locale also available in the AMO details. - Services.prefs.setCharPref(PREF_REQUIRED_LOCALE, "it-IT"); - locale = Services.locale.appLocaleAsBCP47; - equal(locale, "it-IT", "Got the expected app locale set"); - - expectedReport = { - ...expectedReport, - addon_name: FAKE_AMO_DETAILS.name[locale], - }; - await assertReportOnAMODetails({ addonId, expectedReport }); - - // Test with a non-default locale not available in the AMO details. - Services.prefs.setCharPref(PREF_REQUIRED_LOCALE, "fr-FR"); - locale = Services.locale.appLocaleAsBCP47; - equal(locale, "fr-FR", "Got the expected app locale set"); - - expectedReport = { - ...expectedReport, - // Fallbacks on en-US for non available locales. - addon_name: FAKE_AMO_DETAILS.name["en-US"], - }; - await assertReportOnAMODetails({ addonId, expectedReport }); - - Services.prefs.clearUserPref(PREF_REQUIRED_LOCALE); - - amoAddonDetailsMap.clear(); -}); - -add_task(async function test_statictheme_normalized_into_type_theme() { - const themeId = "not-installed-statictheme@mochi.test"; - amoAddonDetailsMap.set(themeId, { - ...FAKE_AMO_DETAILS, - type: "statictheme", - }); - - const report = await AbuseReporter.createAbuseReport(themeId, REPORT_OPTIONS); - - equal(report.addon.id, themeId, "Got a report for the expected theme id"); - equal(report.addon.type, "theme", "Got the expected addon type"); - - amoAddonDetailsMap.clear(); -}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_dictionary_webextension.js b/toolkit/mozapps/extensions/test/xpcshell/test_dictionary_webextension.js index 1f52c8a8bc..bcb777e135 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_dictionary_webextension.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_dictionary_webextension.js @@ -10,7 +10,7 @@ XPCOMUtils.defineLazyServiceGetter( "mozISpellCheckingEngine" ); -add_task(async function setup() { +add_setup(async function setup() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "61", "61"); // Initialize the URLPreloader so that we can load the built-in @@ -18,6 +18,12 @@ add_task(async function setup() { AddonTestUtils.initializeURLPreloader(); await promiseStartupManager(); + // Sanity check, builtin dictionaries should be registered. + Assert.deepEqual( + spellCheck.getDictionaryList(), + ["en-US"], + "Expect en-US builtin dictionary to be registered" + ); // Starts collecting the Addon Manager Telemetry events. AddonTestUtils.hookAMTelemetryEvents(); @@ -218,6 +224,13 @@ add_task( const WORD = "Flehgragh"; add_task(async function test_registration() { + // Sanity check, builtin dictionaries should be registered. + Assert.deepEqual( + spellCheck.getDictionaryList(), + ["en-US"], + "Expect en-US builtin dictionary to be registered" + ); + spellCheck.dictionaries = ["en-US"]; ok(!spellCheck.check(WORD), "Word should not pass check before add-on loads"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js index 913c802609..3551b2c8dd 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js @@ -1,5 +1,14 @@ +AddonTestUtils.overrideCertDB(); +AddonTestUtils.usePrivilegedSignatures = id => id.startsWith("privileged-"); + +// Some tests in this test file can't run on android build because +// theme addon type isn't supported. +const skipOnAndroid = () => ({ + skip_if: () => AppConstants.platform === "android", +}); + let profileDir; -add_task(async function setup() { +add_setup(async function setup() { profileDir = gProfD.clone(); profileDir.append("extensions"); @@ -19,7 +28,7 @@ const IMPLICIT_ID_ID = "{46607a7b-1b2a-40ce-9afe-91cda52c46a6}"; // webext-implicit-id.xpi has a minimal manifest with no // applications or browser_specific_settings, so its id comes // from its signature, which should be the ID constant defined below. -add_task(async function test_implicit_id() { +add_task(skipOnAndroid(), async function test_implicit_id() { let addon = await promiseAddonByID(IMPLICIT_ID_ID); equal(addon, null, "Add-on is not installed"); @@ -34,7 +43,7 @@ add_task(async function test_implicit_id() { // We should also be able to install webext-implicit-id.xpi temporarily // and it should look just like the regular install (ie, the ID should // come from the signature) -add_task(async function test_implicit_id_temp() { +add_task(skipOnAndroid(), async function test_implicit_id_temp() { let addon = await promiseAddonByID(IMPLICIT_ID_ID); equal(addon, null, "Add-on is not installed"); @@ -602,6 +611,187 @@ add_task(async function test_permissions_prompt() { await IOUtils.remove(xpi.path); }); +// Check normalized optional origins. +add_task(async function test_normalized_optional_origins() { + const assertAddonWrapperPermissionsProperties = async ( + manifest, + expected + ) => { + let xpi = ExtensionTestCommon.generateXPI({ manifest }); + + let install = await AddonManager.getInstallForFile(xpi); + + let perminfo; + let installPromptCompletedDeferred = Promise.withResolvers(); + let installPromptShownDeferred = Promise.withResolvers(); + install.promptHandler = info => { + perminfo = info; + installPromptShownDeferred.resolve(); + return installPromptCompletedDeferred.promise; + }; + + const promiseInstalled = install.install(); + info("Wait for the install prompt"); + await installPromptShownDeferred.promise; + + equal( + await promiseAddonByID(perminfo.addon.id), + null, + "Extension should not be installed yet" + ); + notEqual(perminfo, undefined, "Permission handler was invoked"); + notEqual(perminfo.addon, null, "Permission info includes the new addon"); + equal( + perminfo.addon.isPrivileged, + expected.isPrivileged, + `Expect the addon to be ${expected.isPrivileged ? "" : "non-"}privileged` + ); + let addon = perminfo.addon; + deepEqual( + addon.userPermissions, + expected.userPermissions, + "userPermissions are correct" + ); + deepEqual( + addon.optionalPermissions, + expected.optionalPermissions, + "optionalPermissions are correct" + ); + info("Assert normalized optional origins on non-installed extension"); + deepEqual( + addon.optionalOriginsNormalized, + expected.optionalOriginsNormalized, + "optionalOriginsNormalized are correct" + ); + + installPromptCompletedDeferred.resolve(); + await promiseInstalled; + addon = await promiseAddonByID(perminfo.addon.id); + notEqual(addon, null, "Extension was installed successfully"); + + info("Assert normalized optional origins again on installed extension"); + deepEqual( + addon.optionalOriginsNormalized, + expected.optionalOriginsNormalized, + "Normalized origin permissions are correct" + ); + + await addon.uninstall(); + await IOUtils.remove(xpi.path); + }; + + info( + "Test normalized optional origins on non-privileged ManifestV2 extension" + ); + const manifestV2 = { + name: "permissions test mv2", + manifest_version: 2, + // Include a permission that would trigger an install time prompt. + permissions: ["tabs"], + // Include optional origins to be normalized. + // NOTE: we expect the normalized origins to be deduplicated. + optional_permissions: [ + "http://*.example.com/", + "http://*.example.com/somepath/", + "*://example.org/*", + "*://example.org/another-path/*", + "file://*/*", + ], + }; + + await assertAddonWrapperPermissionsProperties(manifestV2, { + isPrivileged: false, + userPermissions: { permissions: manifestV2.permissions, origins: [] }, + optionalPermissions: { + permissions: [], + origins: manifestV2.optional_permissions, + }, + optionalOriginsNormalized: [ + "http://*.example.com/*", + "*://example.org/*", + "file://*/*", + ], + }); + + info( + "Test normalized optional origins on non-privileged ManifestV3 extension" + ); + const manifestV3 = { + name: "permissions test mv3", + manifest_version: 3, + // Include a permission that would trigger an install time prompt. + permissions: ["tabs"], + + // Content Scripts match patterns are also expected to be part + // of the optional host permissions (and to be deduplicated). + content_scripts: [ + { + matches: ["*://*/*"], + js: ["script.js"], + }, + { + matches: ["*://example.org/*"], + js: ["script2.js"], + }, + ], + + // Include optional origins to be normalized. + host_permissions: [ + "http://*.example.com/", + "*://example.org/*", + "file://*/*", + ], + }; + + await assertAddonWrapperPermissionsProperties(manifestV3, { + isPrivileged: false, + userPermissions: { permissions: manifestV3.permissions, origins: [] }, + optionalPermissions: { + permissions: [], + origins: [...manifestV3.host_permissions, "*://*/*"], + }, + optionalOriginsNormalized: [ + "http://*.example.com/*", + "*://example.org/*", + "file://*/*", + "*://*/*", + ], + }); + + info("Test normalized optional origins on privileged ManifestV2 extension"); + const manifestV2Privileged = { + name: "permissions test privileged mv2", + manifest_version: 2, + browser_specific_settings: { gecko: { id: "privileged-mv2@ext" } }, + // Include a permission that would trigger an install time prompt. + permissions: ["tabs", "mozillaAddons"], + optional_permissions: [ + "http://*.example.com/", + "*://example.org/*", + "file://*/*", + "resource://gre/", + ], + }; + + await assertAddonWrapperPermissionsProperties(manifestV2Privileged, { + isPrivileged: true, + userPermissions: { + permissions: manifestV2Privileged.permissions, + origins: [], + }, + optionalPermissions: { + permissions: [], + origins: manifestV2Privileged.optional_permissions, + }, + optionalOriginsNormalized: [ + "http://*.example.com/*", + "*://example.org/*", + "file://*/*", + "resource://gre/*", + ], + }); +}); + // Check permissions prompt cancellation add_task(async function test_permissions_prompt_cancel() { const manifest = { diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.toml b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.toml index e8d3807ab9..a342fad700 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.toml +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.toml @@ -1,5 +1,4 @@ [DEFAULT] -skip-if = ["os == 'android'"] tags = "addons" head = "head_addons.js" firefox-appdir = "browser" @@ -11,252 +10,374 @@ support-files = [ "../xpinstall/amosigned-sha1only.xpi", ] +# TODO: Most tests are skipped on Android but we should re-enable them, +# cf. Bug 1872867. + ["test_AMBrowserExtensionsImport.js"] +skip-if = ["os == 'android'"] ["test_AbuseReporter.js"] +skip-if = ["os == 'android'"] ["test_AddonRepository.js"] +skip-if = ["os == 'android'"] ["test_AddonRepository_appIsShuttingDown.js"] +skip-if = ["os == 'android'"] ["test_AddonRepository_cache.js"] +skip-if = ["os == 'android'"] ["test_AddonRepository_cache_locale.js"] +skip-if = ["os == 'android'"] ["test_AddonRepository_langpacks.js"] +skip-if = ["os == 'android'"] ["test_AddonRepository_paging.js"] +skip-if = ["os == 'android'"] ["test_ProductAddonChecker.js"] +skip-if = ["os == 'android'"] ["test_ProductAddonChecker_signatures.js"] head = "head_addons.js head_cert_handling.js" +skip-if = ["os == 'android'"] ["test_QuarantinedDomains_AMRemoteSettings.js"] head = "head_addons.js head_amremotesettings.js ../../../../components/extensions/test/xpcshell/head_telemetry.js" +skip-if = ["os == 'android'"] ["test_QuarantinedDomains_AddonWrapper.js"] +skip-if = ["os == 'android'"] ["test_XPIStates.js"] -skip-if = ["condprof"] # Bug 1769184 - by design for now +skip-if = [ + "condprof", # Bug 1769184 - by design for now + "os == 'android'", +] ["test_XPIcancel.js"] +skip-if = ["os == 'android'"] ["test_addonStartup.js"] +skip-if = ["os == 'android'"] ["test_addon_manager_telemetry_events.js"] +skip-if = ["os == 'android'"] ["test_amo_stats_telemetry.js"] +skip-if = ["os == 'android'"] ["test_aom_startup.js"] +skip-if = ["os == 'android'"] ["test_bad_json.js"] +skip-if = ["os == 'android'"] ["test_badschema.js"] +skip-if = ["os == 'android'"] ["test_builtin_location.js"] +skip-if = ["os == 'android'"] ["test_cacheflush.js"] +skip-if = ["os == 'android'"] ["test_childprocess.js"] head = "" +skip-if = ["os == 'android'"] ["test_colorways_builtin_theme_upgrades.js"] -skip-if = ["appname == 'thunderbird'"] # Bug 1809438 - No colorways in Thunderbird +skip-if = [ + "appname == 'thunderbird'", # Bug 1809438 - No colorways in Thunderbird + "os == 'android'", +] ["test_cookies.js"] +skip-if = ["os == 'android'"] ["test_corrupt.js"] +skip-if = ["os == 'android'"] ["test_crash_annotation_quoting.js"] +skip-if = ["os == 'android'"] ["test_db_path.js"] head = "" +skip-if = ["os == 'android'"] ["test_delay_update_webextension.js"] tags = "webextensions" +skip-if = ["os == 'android'"] ["test_dependencies.js"] +skip-if = ["os == 'android'"] ["test_dictionary_webextension.js"] +skip-if = ["os == 'android'"] ["test_distribution.js"] +skip-if = ["os == 'android'"] ["test_distribution_langpack.js"] +skip-if = ["os == 'android'"] ["test_embedderDisabled.js"] +skip-if = ["os == 'android'"] ["test_error.js"] -skip-if = ["os == 'win'"] # Bug 1508482 +skip-if = [ + "os == 'win'", # Bug 1508482 + "os == 'android'", +] ["test_ext_management.js"] tags = "webextensions" +skip-if = ["os == 'android'"] ["test_general.js"] +skip-if = ["os == 'android'"] ["test_getInstallSourceFromHost.js"] +skip-if = ["os == 'android'"] ["test_gmpProvider.js"] -skip-if = ["appname != 'firefox'"] +skip-if = [ + "appname != 'firefox'", + "os == 'android'", +] ["test_harness.js"] +skip-if = ["os == 'android'"] ["test_hidden.js"] +skip-if = ["os == 'android'"] ["test_install.js"] +skip-if = ["os == 'android'"] ["test_installOrigins.js"] +skip-if = ["os == 'android'"] ["test_install_cancel.js"] +skip-if = ["os == 'android'"] ["test_install_file_change.js"] +skip-if = ["os == 'android'"] ["test_install_icons.js"] +skip-if = ["os == 'android'"] ["test_installtrigger_deprecation.js"] head = "head_addons.js head_amremotesettings.js" +skip-if = ["os == 'android'"] ["test_installtrigger_schemes.js"] +skip-if = ["os == 'android'"] ["test_isDebuggable.js"] +skip-if = ["os == 'android'"] ["test_isReady.js"] +skip-if = ["os == 'android'"] ["test_loadManifest_isPrivileged.js"] +skip-if = ["os == 'android'"] ["test_locale.js"] +skip-if = ["os == 'android'"] ["test_moved_extension_metadata.js"] skip-if = ["true"] # bug 1777900 ["test_no_addons.js"] +skip-if = ["os == 'android'"] ["test_nodisable_hidden.js"] +skip-if = ["os == 'android'"] ["test_onPropertyChanged_appDisabled.js"] head = "head_addons.js head_compat.js" -skip-if = ["tsan"] # Times out, bug 1674773 +skip-if = [ + "tsan", # Times out, bug 1674773 + "os == 'android'", +] ["test_permissions.js"] +skip-if = ["os == 'android'"] ["test_permissions_prefs.js"] +skip-if = ["os == 'android'"] ["test_pref_properties.js"] +skip-if = ["os == 'android'"] ["test_provider_markSafe.js"] +skip-if = ["os == 'android'"] ["test_provider_shutdown.js"] +skip-if = ["os == 'android'"] ["test_provider_unsafe_access_shutdown.js"] +skip-if = ["os == 'android'"] ["test_provider_unsafe_access_startup.js"] +skip-if = ["os == 'android'"] ["test_proxies.js"] -skip-if = ["require_signing"] +skip-if = [ + "require_signing", + "os == 'android'", +] ["test_recommendations.js"] -skip-if = ["require_signing"] +skip-if = [ + "require_signing", + "os == 'android'", +] ["test_registerchrome.js"] +skip-if = ["os == 'android'"] ["test_registry.js"] run-if = ["os == 'win'"] +skip-if = ["os == 'android'"] ["test_reinstall_disabled_addon.js"] +skip-if = ["os == 'android'"] ["test_reload.js"] -skip-if = ["os == 'win'"] # There's a problem removing a temp file without manually clearing the cache on Windows +skip-if = [ + "os == 'win'", # There's a problem removing a temp file without manually clearing the cache on Windows + "os == 'android'", +] tags = "webextensions" ["test_remote_pref_telemetry.js"] +skip-if = ["os == 'android'"] ["test_safemode.js"] +skip-if = ["os == 'android'"] ["test_schema_change.js"] +skip-if = ["os == 'android'"] ["test_seen.js"] +skip-if = ["os == 'android'"] ["test_shutdown.js"] +skip-if = ["os == 'android'"] ["test_shutdown_barriers.js"] +skip-if = ["os == 'android'"] ["test_shutdown_early.js"] -skip-if = ["condprof"] # Bug 1769184 - by design for now +skip-if = [ + "condprof", # Bug 1769184 - by design for now + "os == 'android'", +] ["test_sideload_scopes.js"] head = "head_addons.js head_sideload.js" skip-if = [ "os == 'linux'", # Bug 1613268 "condprof", # Bug 1769184 - by design for now + "os == 'android'", ] ["test_sideloads.js"] +skip-if = ["os == 'android'"] ["test_sideloads_after_rebuild.js"] -skip-if = ["condprof"] # Bug 1769184 - by design for now +skip-if = [ + "condprof", # Bug 1769184 - by design for now + "os == 'android'", +] head = "head_addons.js head_sideload.js" ["test_signed_inject.js"] skip-if = ["true"] # Bug 1394122 ["test_signed_install.js"] +skip-if = ["os == 'android'"] ["test_signed_langpack.js"] +skip-if = ["os == 'android'"] ["test_signed_long.js"] +skip-if = ["os == 'android'"] ["test_signed_updatepref.js"] skip-if = [ "require_signing", "!allow_legacy_extensions", + "os == 'android'", ] ["test_signed_verify.js"] ["test_sitePermsAddonProvider.js"] -skip-if = ["appname == 'thunderbird'"] # Disabled in extensions.manifest +skip-if = [ + "appname == 'thunderbird'", # Disabled in extensions.manifest + "os == 'android'", +] ["test_startup.js"] head = "head_addons.js head_sideload.js" skip-if = [ "os == 'linux'", # Bug 1613268 "condprof", # Bug 1769184 - by design for now + "os == 'android'", ] ["test_startup_enable.js"] +skip-if = ["os == 'android'"] ["test_startup_isPrivileged.js"] +skip-if = ["os == 'android'"] ["test_startup_scan.js"] head = "head_addons.js head_sideload.js" +skip-if = ["os == 'android'"] ["test_strictcompatibility.js"] head = "head_addons.js head_compat.js" +skip-if = ["os == 'android'"] ["test_syncGUID.js"] +skip-if = ["os == 'android'"] ["test_system_allowed.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_delay_update.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_profile_location.js"] +skip-if = ["os == 'android'"] ["test_system_repository.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_reset.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_update_blank.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_update_checkSizeHash.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_update_custom.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_update_empty.js"] head = "head_addons.js head_system_addons.js" @@ -264,104 +385,148 @@ skip-if = ["true"] # Failing intermittently due to a race condition in the test, ["test_system_update_enterprisepolicy.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_update_fail.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_update_installTelemetryInfo.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_update_newset.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_update_overlapping.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_update_uninstall_check.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_update_upgrades.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_system_upgrades.js"] -skip-if = ["condprof"] # Bug 1769184 - by design for now +skip-if = [ + "condprof", # Bug 1769184 - by design for now + "os == 'android'", +] head = "head_addons.js head_system_addons.js" ["test_systemaddomstartupprefs.js"] -skip-if = ["condprof"] # Bug 1769184 - by design for now +skip-if = [ + "condprof", # Bug 1769184 - by design for now + "os == 'android'", +] head = "head_addons.js head_system_addons.js" ["test_temporary.js"] -skip-if = ["os == 'win'"] # Bug 1469904 +skip-if = [ + "os == 'win'", # Bug 1469904 + "os == 'android'", +] tags = "webextensions" ["test_trash_directory.js"] run-if = ["os == 'win'"] +skip-if = ["os == 'android'"] ["test_types.js"] ["test_undouninstall.js"] -skip-if = ["os == 'win'"] # Bug 1358846 +skip-if = [ + "os == 'win'", # Bug 1358846 + "os == 'android'", +] ["test_update.js"] +skip-if = ["os == 'android'"] ["test_updateCancel.js"] +skip-if = ["os == 'android'"] ["test_update_addontype.js"] +skip-if = ["os == 'android'"] ["test_update_compatmode.js"] head = "head_addons.js head_compat.js" +skip-if = ["os == 'android'"] ["test_update_ignorecompat.js"] skip-if = ["true"] # Bug 676922 Bug 1437697 ["test_update_isPrivileged.js"] -skip-if = ["condprof"] # Bug 1769184 - by design for now +skip-if = [ + "condprof", # Bug 1769184 - by design for now + "os == 'android'", +] ["test_update_noSystemAddonUpdate.js"] head = "head_addons.js head_system_addons.js" +skip-if = ["os == 'android'"] ["test_update_strictcompat.js"] head = "head_addons.js head_compat.js" +skip-if = ["os == 'android'"] ["test_update_theme.js"] +skip-if = ["os == 'android'"] ["test_update_webextensions.js"] tags = "webextensions" +skip-if = ["os == 'android'"] ["test_updatecheck.js"] +skip-if = ["os == 'android'"] ["test_updatecheck_errors.js"] +skip-if = ["os == 'android'"] ["test_updatecheck_json.js"] +skip-if = ["os == 'android'"] ["test_updateid.js"] +skip-if = ["os == 'android'"] ["test_updateversion.js"] +skip-if = ["os == 'android'"] ["test_upgrade.js"] head = "head_addons.js head_compat.js" run-sequentially = "Uses global XCurProcD dir." +skip-if = ["os == 'android'"] ["test_upgrade_incompatible.js"] +skip-if = ["os == 'android'"] ["test_webextension.js"] tags = "webextensions" +skip-if = ["os == 'android'"] ["test_webextension_events.js"] tags = "webextensions" +skip-if = ["os == 'android'"] ["test_webextension_icons.js"] tags = "webextensions" +skip-if = ["os == 'android'"] ["test_webextension_install.js"] tags = "webextensions" ["test_webextension_install_syntax_error.js"] tags = "webextensions" +skip-if = ["os == 'android'"] ["test_webextension_langpack.js"] tags = "webextensions" +skip-if = ["os == 'android'"] ["test_webextension_theme.js"] tags = "webextensions" +skip-if = ["os == 'android'"] -- cgit v1.2.3