/* This Source Code Form is subject to the terms of the Mozilla Public * 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/. */ /* eslint max-len: ["error", 80] */ loadTestSubscript("head_abuse_report.js"); const TESTPAGE = `${SECURE_TESTROOT}webapi_checkavailable.html`; const TELEMETRY_EVENTS_FILTERS = { category: "addonsManager", method: "report", }; const REPORT_PROP_NAMES = [ "addon", "addon_signature", "reason", "message", "report_entry_point", ]; function getObjectProps(obj, propNames) { const res = {}; for (const k of propNames) { res[k] = obj[k]; } return res; } async function assertSubmittedReport(expectedReportProps) { let reportSubmitted; const onReportSubmitted = AbuseReportTestUtils.promiseReportSubmitHandled( ({ data, request, response }) => { reportSubmitted = JSON.parse(data); handleSubmitRequest({ request, response }); } ); let panelEl = await AbuseReportTestUtils.promiseReportDialogRendered(); let promiseWinClosed = waitClosedWindow(); let promisePanelUpdated = AbuseReportTestUtils.promiseReportUpdated( panelEl, "submit" ); panelEl._form.elements.reason.value = expectedReportProps.reason; AbuseReportTestUtils.clickPanelButton(panelEl._btnNext); await promisePanelUpdated; panelEl._form.elements.message.value = expectedReportProps.message; // Reset the timestamp of the last report between tests. AbuseReporter._lastReportTimestamp = null; AbuseReportTestUtils.clickPanelButton(panelEl._btnSubmit); await Promise.all([onReportSubmitted, promiseWinClosed]); ok(!panelEl.ownerGlobal, "Report dialog window is closed"); Assert.deepEqual( getObjectProps(reportSubmitted, REPORT_PROP_NAMES), expectedReportProps, "Got the expected report data submitted" ); } add_setup(async function () { await AbuseReportTestUtils.setup(); await SpecialPowers.pushPrefEnv({ set: [ ["extensions.webapi.testing", true], ["extensions.abuseReport.amWebAPI.enabled", true], ], }); }); add_task(async function test_report_installed_addon_cancelled() { Services.telemetry.clearEvents(); await BrowserTestUtils.withNewTab(TESTPAGE, async browser => { const extension = await installTestExtension(ADDON_ID); let reportEnabled = await SpecialPowers.spawn(browser, [], () => { return content.navigator.mozAddonManager.abuseReportPanelEnabled; }); is(reportEnabled, true, "Expect abuseReportPanelEnabled to be true"); info("Test reportAbuse result on user cancelled report"); let promiseNewWindow = waitForNewWindow(); let promiseWebAPIResult = SpecialPowers.spawn( browser, [ADDON_ID], addonId => content.navigator.mozAddonManager.reportAbuse(addonId) ); let win = await promiseNewWindow; is(win, AbuseReportTestUtils.getReportDialog(), "Got the report dialog"); let panelEl = await AbuseReportTestUtils.promiseReportDialogRendered(); let promiseWinClosed = waitClosedWindow(); AbuseReportTestUtils.clickPanelButton(panelEl._btnCancel); let reportResult = await promiseWebAPIResult; is( reportResult, false, "Expect reportAbuse to resolve to false on user cancelled report" ); await promiseWinClosed; ok(!panelEl.ownerGlobal, "Report dialog window is closed"); await extension.unload(); }); // Expect no telemetry events collected for user cancelled reports. TelemetryTestUtils.assertEvents([], TELEMETRY_EVENTS_FILTERS); }); add_task(async function test_report_installed_addon_submitted() { Services.telemetry.clearEvents(); await BrowserTestUtils.withNewTab(TESTPAGE, async browser => { const extension = await installTestExtension(ADDON_ID); let promiseNewWindow = waitForNewWindow(); let promiseWebAPIResult = SpecialPowers.spawn(browser, [ADDON_ID], id => content.navigator.mozAddonManager.reportAbuse(id) ); let win = await promiseNewWindow; is(win, AbuseReportTestUtils.getReportDialog(), "Got the report dialog"); await assertSubmittedReport({ addon: ADDON_ID, addon_signature: "missing", message: "fake report message", reason: "unwanted", report_entry_point: "amo", }); let reportResult = await promiseWebAPIResult; is( reportResult, true, "Expect reportAbuse to resolve to false on user cancelled report" ); await extension.unload(); }); TelemetryTestUtils.assertEvents( [ { object: "amo", value: ADDON_ID, extra: { addon_type: "extension" }, }, ], TELEMETRY_EVENTS_FILTERS ); }); add_task(async function test_report_unknown_not_installed_addon() { const addonId = "unknown-addon@mochi.test"; Services.telemetry.clearEvents(); await BrowserTestUtils.withNewTab(TESTPAGE, async browser => { let promiseWebAPIResult = SpecialPowers.spawn(browser, [addonId], id => content.navigator.mozAddonManager.reportAbuse(id).catch(err => { return { name: err.name, message: err.message }; }) ); await Assert.deepEqual( await promiseWebAPIResult, { name: "Error", message: "Error creating abuse report" }, "Got the expected rejected error on reporting unknown addon" ); ok(!AbuseReportTestUtils.getReportDialog(), "No report dialog is open"); }); TelemetryTestUtils.assertEvents( [ { object: "amo", value: addonId, extra: { error_type: "ERROR_AMODETAILS_NOTFOUND" }, }, { object: "amo", value: addonId, extra: { error_type: "ERROR_ADDON_NOTFOUND" }, }, ], TELEMETRY_EVENTS_FILTERS ); }); add_task(async function test_report_not_installed_addon() { const addonId = "not-installed-addon@mochi.test"; Services.telemetry.clearEvents(); await BrowserTestUtils.withNewTab(TESTPAGE, async browser => { const fakeAMODetails = { name: "fake name", current_version: { version: "1.0" }, type: "extension", icon_url: "http://test.addons.org/asserts/fake-icon-url.png", homepage: "http://fake.url/homepage", authors: [{ name: "author1", url: "http://fake.url/author1" }], is_recommended: false, }; AbuseReportTestUtils.amoAddonDetailsMap.set(addonId, fakeAMODetails); registerCleanupFunction(() => AbuseReportTestUtils.amoAddonDetailsMap.clear() ); let promiseNewWindow = waitForNewWindow(); let promiseWebAPIResult = SpecialPowers.spawn(browser, [addonId], id => content.navigator.mozAddonManager.reportAbuse(id) ); let win = await promiseNewWindow; is(win, AbuseReportTestUtils.getReportDialog(), "Got the report dialog"); await assertSubmittedReport({ addon: addonId, addon_signature: "unknown", message: "fake report message", reason: "other", report_entry_point: "amo", }); let reportResult = await promiseWebAPIResult; is( reportResult, true, "Expect reportAbuse to resolve to true on submitted report" ); }); TelemetryTestUtils.assertEvents( [ { object: "amo", value: addonId, extra: { addon_type: "extension" }, }, ], TELEMETRY_EVENTS_FILTERS ); }); add_task(async function test_amo_report_on_report_already_inprogress() { const extension = await installTestExtension(ADDON_ID); const reportDialog = await AbuseReporter.openDialog( ADDON_ID, "menu", gBrowser.selectedBrowser ); await AbuseReportTestUtils.promiseReportDialogRendered(); ok(reportDialog.window, "Got an open report dialog"); let promiseWinClosed = waitClosedWindow(); await BrowserTestUtils.withNewTab(TESTPAGE, async browser => { const promiseAMOResult = SpecialPowers.spawn(browser, [ADDON_ID], id => content.navigator.mozAddonManager.reportAbuse(id) ); await promiseWinClosed; ok(reportDialog.window.closed, "previous report dialog should be closed"); is( await reportDialog.promiseAMOResult, undefined, "old report cancelled after AMO called mozAddonManager.reportAbuse" ); const panelEl = await AbuseReportTestUtils.promiseReportDialogRendered(); const { report } = AbuseReportTestUtils.getReportDialogParams(); Assert.deepEqual( { reportEntryPoint: report.reportEntryPoint, addonId: report.addon.id, }, { reportEntryPoint: "amo", addonId: ADDON_ID, }, "Got the expected report from the opened report dialog" ); promiseWinClosed = waitClosedWindow(); AbuseReportTestUtils.clickPanelButton(panelEl._btnCancel); await promiseWinClosed; is( await promiseAMOResult, false, "AMO report request resolved to false on cancel button clicked" ); }); await extension.unload(); }); add_task(async function test_reject_on_unsupported_addon_types() { const addonId = "not-supported-addon-type@mochi.test"; await BrowserTestUtils.withNewTab(TESTPAGE, async browser => { const fakeAMODetails = { name: "fake name", current_version: { version: "1.0" }, type: "fake-unsupported-addon-type", }; AbuseReportTestUtils.amoAddonDetailsMap.set(addonId, fakeAMODetails); registerCleanupFunction(() => AbuseReportTestUtils.amoAddonDetailsMap.clear() ); let webAPIResult = await SpecialPowers.spawn(browser, [addonId], id => content.navigator.mozAddonManager.reportAbuse(id).then( res => ({ gotRejection: false, result: res }), err => ({ gotRejection: true, message: err.message }) ) ); Assert.deepEqual( webAPIResult, { gotRejection: true, message: "Error creating abuse report" }, "Got the expected rejection from mozAddonManager.reportAbuse" ); }); }); add_task(async function test_report_on_disabled_webapi() { await SpecialPowers.pushPrefEnv({ set: [["extensions.abuseReport.amWebAPI.enabled", false]], }); await BrowserTestUtils.withNewTab(TESTPAGE, async browser => { let reportEnabled = await SpecialPowers.spawn(browser, [], () => { return content.navigator.mozAddonManager.abuseReportPanelEnabled; }); is(reportEnabled, false, "Expect abuseReportPanelEnabled to be false"); info("Test reportAbuse result on report webAPI disabled"); let promiseWebAPIResult = SpecialPowers.spawn( browser, ["an-addon@mochi.test"], addonId => content.navigator.mozAddonManager.reportAbuse(addonId).catch(err => { return { name: err.name, message: err.message }; }) ); Assert.deepEqual( await promiseWebAPIResult, { name: "Error", message: "amWebAPI reportAbuse not supported" }, "Got the expected rejected error" ); }); await SpecialPowers.popPrefEnv(); });