/* 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"); add_setup(async function () { await AbuseReportTestUtils.setup(); }); /** * Base tests on abuse report panel webcomponents. */ // This test case verified that the abuse report panels contains a radio // button for all the expected "abuse report reasons", they are grouped // together under the same form field named "reason". add_task(async function test_abusereport_issuelist() { const extension = await installTestExtension(); const abuseReportEl = await AbuseReportTestUtils.openReport(extension.id); const reasonsPanel = abuseReportEl._reasonsPanel; const radioButtons = reasonsPanel.querySelectorAll("[type=radio]"); const selectedRadios = reasonsPanel.querySelectorAll("[type=radio]:checked"); is(selectedRadios.length, 1, "Expect only one radio button selected"); is( selectedRadios[0], radioButtons[0], "Expect the first radio button to be selected" ); is( abuseReportEl.reason, radioButtons[0].value, `The reason property has the expected value: ${radioButtons[0].value}` ); const reasons = Array.from(radioButtons).map(el => el.value); Assert.deepEqual( reasons.sort(), AbuseReportTestUtils.getReasons(abuseReportEl).sort(), `Got a radio button for the expected reasons` ); for (const radio of radioButtons) { const reasonInfo = AbuseReportTestUtils.getReasonInfo( abuseReportEl, radio.value ); const expectExampleHidden = reasonInfo && reasonInfo.isExampleHidden("extension"); is( radio.parentNode.querySelector(".reason-example").hidden, expectExampleHidden, `Got expected visibility on the example for reason "${radio.value}"` ); } info("Change the selected reason to " + radioButtons[3].value); radioButtons[3].checked = true; is( abuseReportEl.reason, radioButtons[3].value, "The reason property has the expected value" ); await extension.unload(); await closeAboutAddons(); }); // This test case verifies that the abuse report panel: // - switches from its "reasons list" mode to its "submit report" mode when the // "next" button is clicked // - goes back to the "reasons list" mode when the "go back" button is clicked // - the abuse report panel is closed when the "close" icon is clicked add_task(async function test_abusereport_submitpanel() { const extension = await installTestExtension(); const abuseReportEl = await AbuseReportTestUtils.openReport(extension.id); ok( !abuseReportEl._reasonsPanel.hidden, "The list of abuse reasons is the currently visible" ); ok( abuseReportEl._submitPanel.hidden, "The submit panel is the currently hidden" ); let onceUpdated = AbuseReportTestUtils.promiseReportUpdated( abuseReportEl, "submit" ); await AbuseReportTestUtils.clickPanelButton(abuseReportEl._btnNext); await onceUpdated; onceUpdated = AbuseReportTestUtils.promiseReportUpdated( abuseReportEl, "reasons" ); await AbuseReportTestUtils.clickPanelButton(abuseReportEl._btnGoBack); await onceUpdated; const onceReportClosed = AbuseReportTestUtils.promiseReportClosed(abuseReportEl); await AbuseReportTestUtils.clickPanelButton(abuseReportEl._btnCancel); await onceReportClosed; await extension.unload(); await closeAboutAddons(); }); // This test case verifies that the abuse report panel sends the expected data // in the "abuse-report:submit" event detail. add_task(async function test_abusereport_submit() { // Reset the timestamp of the last report between tests. AbuseReporter._lastReportTimestamp = null; const extension = await installTestExtension(); const abuseReportEl = await AbuseReportTestUtils.openReport(extension.id); ok( !abuseReportEl._reasonsPanel.hidden, "The list of abuse reasons is the currently visible" ); let onceUpdated = AbuseReportTestUtils.promiseReportUpdated( abuseReportEl, "submit" ); await AbuseReportTestUtils.clickPanelButton(abuseReportEl._btnNext); await onceUpdated; is(abuseReportEl.message, "", "The abuse report message is initially empty"); info("Test typing a message in the abuse report submit panel textarea"); const typedMessage = "Description of the extension abuse report"; EventUtils.synthesizeComposition( { data: typedMessage, type: "compositioncommit", }, abuseReportEl.ownerGlobal ); is( abuseReportEl.message, typedMessage, "Got the expected typed message in the abuse report" ); const expectedDetail = { addonId: extension.id, }; const expectedReason = abuseReportEl.reason; const expectedMessage = abuseReportEl.message; function handleSubmitRequest({ request, response }) { response.setStatusLine(request.httpVersion, 200, "OK"); response.setHeader("Content-Type", "application/json", false); response.write("{}"); } let reportSubmitted; const onReportSubmitted = AbuseReportTestUtils.promiseReportSubmitHandled( ({ data, request, response }) => { reportSubmitted = JSON.parse(data); handleSubmitRequest({ request, response }); } ); const onceReportClosed = AbuseReportTestUtils.promiseReportClosed(abuseReportEl); const onMessageBarsCreated = AbuseReportTestUtils.promiseMessageBars(2); const onceSubmitEvent = BrowserTestUtils.waitForEvent( abuseReportEl, "abuse-report:submit" ); await AbuseReportTestUtils.clickPanelButton(abuseReportEl._btnSubmit); const submitEvent = await onceSubmitEvent; const actualDetail = { addonId: submitEvent.detail.addonId, }; Assert.deepEqual( actualDetail, expectedDetail, "Got the expected detail in the abuse-report:submit event" ); ok( submitEvent.detail.report, "Got a report object in the abuse-report:submit event detail" ); // Verify that, when the "abuse-report:submit" has been sent, // the abuse report panel has been hidden, the report has been // submitted and the expected message bar is created in the // HTML about:addons page. info("Wait the report to be submitted to the api server"); await onReportSubmitted; info("Wait the report panel to be closed"); await onceReportClosed; is( reportSubmitted.addon, ADDON_ID, "Got the expected addon in the submitted report" ); is( reportSubmitted.reason, expectedReason, "Got the expected reason in the submitted report" ); is( reportSubmitted.message, expectedMessage, "Got the expected message in the submitted report" ); is( reportSubmitted.report_entry_point, REPORT_ENTRY_POINT, "Got the expected report_entry_point in the submitted report" ); info("Waiting the expected message bars to be created"); const barDetails = await onMessageBarsCreated; is(barDetails.length, 2, "Expect two message bars to have been created"); is( barDetails[0].definitionId, "submitting", "Got a submitting message bar as expected" ); is( barDetails[1].definitionId, "submitted", "Got a submitted message bar as expected" ); await extension.unload(); await closeAboutAddons(); }); // This helper does verify that the abuse report panel contains the expected // suggestions when the selected reason requires it (and urls are being set // on the links elements included in the suggestions when expected). async function test_abusereport_suggestions(addonId) { const addon = await AddonManager.getAddonByID(addonId); const abuseReportEl = await AbuseReportTestUtils.openReport(addonId); const { _btnNext, _btnGoBack, _reasonsPanel, _submitPanel, _submitPanel: { _suggestions }, } = abuseReportEl; for (const reason of AbuseReportTestUtils.getReasons(abuseReportEl)) { const reasonInfo = AbuseReportTestUtils.getReasonInfo( abuseReportEl, reason ); // TODO(Bug 1789718): Remove after the deprecated XPIProvider-based // implementation is also removed. const addonType = addon.type === "sitepermission-deprecated" ? "sitepermission" : addon.type; if (reasonInfo.isReasonHidden(addonType)) { continue; } info(`Test suggestions for abuse reason "${reason}"`); // Select a reason with suggestions. let radioEl = abuseReportEl.querySelector(`#abuse-reason-${reason}`); ok(radioEl, `Found radio button for "${reason}"`); radioEl.checked = true; // Make sure the element localization is completed before // checking the content isn't empty. await document.l10n.translateFragment(radioEl); // Verify each radio button has a non-empty localized string. const localizedRadioContent = Array.from( radioEl.closest("label").querySelectorAll("[data-l10n-id]") ).filter(el => !el.hidden); for (let el of localizedRadioContent) { isnot( el.textContent, "", `Fluent string id '${el.getAttribute("data-l10n-id")}' missing` ); } // Switch to the submit form with the current reason radio selected. let oncePanelUpdated = AbuseReportTestUtils.promiseReportUpdated( abuseReportEl, "submit" ); await AbuseReportTestUtils.clickPanelButton(_btnNext); await oncePanelUpdated; const localizedSuggestionsContent = Array.from( _suggestions.querySelectorAll("[data-l10n-id]") ).filter(el => !el.hidden); is( !_suggestions.hidden, !!reasonInfo.hasSuggestions, `Suggestions block has the expected visibility for "${reason}"` ); if (reasonInfo.hasSuggestions) { ok( !!localizedSuggestionsContent.length, `Category suggestions should not be empty for "${reason}"` ); } else { ok( localizedSuggestionsContent.length === 0, `Category suggestions should be empty for "${reason}"` ); } const extSupportLink = _suggestions.querySelector( ".extension-support-link" ); if (extSupportLink) { is( extSupportLink.getAttribute("href"), BASE_TEST_MANIFEST.homepage_url, "Got the expected extension-support-url" ); } const learnMoreLinks = []; for (const linkClass of _suggestions.LEARNMORE_LINKS) { learnMoreLinks.push(..._suggestions.querySelectorAll(linkClass)); } if (learnMoreLinks.length) { ok( learnMoreLinks.every(el => el.getAttribute("target") === "_blank"), "All the learn more links have target _blank" ); ok( learnMoreLinks.every(el => el.hasAttribute("href")), "All the learn more links have a url set" ); } oncePanelUpdated = AbuseReportTestUtils.promiseReportUpdated( abuseReportEl, "reasons" ); await AbuseReportTestUtils.clickPanelButton(_btnGoBack); await oncePanelUpdated; ok(!_reasonsPanel.hidden, "Reasons panel should be visible"); ok(_submitPanel.hidden, "Submit panel should be hidden"); } await closeAboutAddons(); } add_task(async function test_abusereport_suggestions_extension() { const EXT_ID = "test-extension-suggestions@mochi.test"; const extension = await installTestExtension(EXT_ID); await test_abusereport_suggestions(EXT_ID); await extension.unload(); }); add_task(async function test_abusereport_suggestions_theme() { const THEME_ID = "theme@mochi.test"; const theme = await installTestExtension(THEME_ID, "theme"); await test_abusereport_suggestions(THEME_ID); await theme.unload(); }); // TODO(Bug 1789718): adapt to SitePermAddonProvider implementation. add_task(async function test_abusereport_suggestions_sitepermission() { const SITEPERM_ADDON_ID = "webmidi@mochi.test"; const sitePermAddon = await installTestExtension( SITEPERM_ADDON_ID, "sitepermission-deprecated" ); await test_abusereport_suggestions(SITEPERM_ADDON_ID); await sitePermAddon.unload(); }); // This test case verifies the message bars created on other // scenarios (e.g. report creation and submissions errors). // // TODO(Bug 1789718): adapt to SitePermAddonProvider implementation. add_task(async function test_abusereport_messagebars() { const EXT_ID = "test-extension-report@mochi.test"; const EXT_ID2 = "test-extension-report-2@mochi.test"; const THEME_ID = "test-theme-report@mochi.test"; const SITEPERM_ADDON_ID = "webmidi-report@mochi.test"; const extension = await installTestExtension(EXT_ID); const extension2 = await installTestExtension(EXT_ID2); const theme = await installTestExtension(THEME_ID, "theme"); const sitePermAddon = await installTestExtension( SITEPERM_ADDON_ID, "sitepermission-deprecated" ); async function assertMessageBars( expectedMessageBarIds, testSetup, testMessageBarDetails ) { await openAboutAddons(); const expectedLength = expectedMessageBarIds.length; const onMessageBarsCreated = AbuseReportTestUtils.promiseMessageBars(expectedLength); // Reset the timestamp of the last report between tests. AbuseReporter._lastReportTimestamp = null; await testSetup(); info(`Waiting for ${expectedLength} message-bars to be created`); const barDetails = await onMessageBarsCreated; Assert.deepEqual( barDetails.map(d => d.definitionId), expectedMessageBarIds, "Got the expected message bars" ); if (testMessageBarDetails) { await testMessageBarDetails(barDetails); } await closeAboutAddons(); } function setTestRequestHandler(responseStatus, responseData) { AbuseReportTestUtils.promiseReportSubmitHandled(({ request, response }) => { response.setStatusLine(request.httpVersion, responseStatus, "Error"); response.write(responseData); }); } await assertMessageBars(["ERROR_ADDON_NOTFOUND"], async () => { info("Test message bars on addon not found"); AbuseReportTestUtils.triggerNewReport( "non-existend-addon-id@mochi.test", REPORT_ENTRY_POINT ); }); await assertMessageBars(["submitting", "ERROR_RECENT_SUBMIT"], async () => { info("Test message bars on recent submission"); const promiseRendered = AbuseReportTestUtils.promiseReportRendered(); AbuseReportTestUtils.triggerNewReport(EXT_ID, REPORT_ENTRY_POINT); await promiseRendered; AbuseReporter.updateLastReportTimestamp(); AbuseReportTestUtils.triggerSubmit("fake-reason", "fake-message"); }); await assertMessageBars(["submitting", "ERROR_ABORTED_SUBMIT"], async () => { info("Test message bars on aborted submission"); AbuseReportTestUtils.triggerNewReport(EXT_ID, REPORT_ENTRY_POINT); await AbuseReportTestUtils.promiseReportRendered(); const { _report } = AbuseReportTestUtils.getReportPanel(); _report.abort(); AbuseReportTestUtils.triggerSubmit("fake-reason", "fake-message"); }); await assertMessageBars(["submitting", "ERROR_SERVER"], async () => { info("Test message bars on server error"); setTestRequestHandler(500); AbuseReportTestUtils.triggerNewReport(EXT_ID, REPORT_ENTRY_POINT); await AbuseReportTestUtils.promiseReportRendered(); AbuseReportTestUtils.triggerSubmit("fake-reason", "fake-message"); }); await assertMessageBars(["submitting", "ERROR_CLIENT"], async () => { info("Test message bars on client error"); setTestRequestHandler(400); AbuseReportTestUtils.triggerNewReport(EXT_ID, REPORT_ENTRY_POINT); await AbuseReportTestUtils.promiseReportRendered(); AbuseReportTestUtils.triggerSubmit("fake-reason", "fake-message"); }); await assertMessageBars(["submitting", "ERROR_UNKNOWN"], async () => { info("Test message bars on unexpected status code"); setTestRequestHandler(604); AbuseReportTestUtils.triggerNewReport(EXT_ID, REPORT_ENTRY_POINT); await AbuseReportTestUtils.promiseReportRendered(); AbuseReportTestUtils.triggerSubmit("fake-reason", "fake-message"); }); await assertMessageBars(["submitting", "ERROR_UNKNOWN"], async () => { info("Test message bars on invalid json in the response data"); setTestRequestHandler(200, ""); AbuseReportTestUtils.triggerNewReport(EXT_ID, REPORT_ENTRY_POINT); await AbuseReportTestUtils.promiseReportRendered(); AbuseReportTestUtils.triggerSubmit("fake-reason", "fake-message"); }); // Verify message bar on add-on without perm_can_uninstall. await assertMessageBars( ["submitting", "submitted-no-remove-action"], async () => { info("Test message bars on report submitted on an addon without remove"); setTestRequestHandler(200, "{}"); AbuseReportTestUtils.triggerNewReport(THEME_NO_UNINSTALL_ID, "menu"); await AbuseReportTestUtils.promiseReportRendered(); AbuseReportTestUtils.triggerSubmit("fake-reason", "fake-message"); } ); // Verify the 3 expected entry points: // menu, toolbar_context_menu and uninstall // (See https://addons-server.readthedocs.io/en/latest/topics/api/abuse.html). await assertMessageBars(["submitting", "submitted"], async () => { info("Test message bars on report opened from addon options menu"); setTestRequestHandler(200, "{}"); AbuseReportTestUtils.triggerNewReport(EXT_ID, "menu"); await AbuseReportTestUtils.promiseReportRendered(); AbuseReportTestUtils.triggerSubmit("fake-reason", "fake-message"); }); for (const extId of [EXT_ID, THEME_ID]) { await assertMessageBars( ["submitting", "submitted"], async () => { info(`Test message bars on ${extId} reported from toolbar contextmenu`); setTestRequestHandler(200, "{}"); AbuseReportTestUtils.triggerNewReport(extId, "toolbar_context_menu"); await AbuseReportTestUtils.promiseReportRendered(); AbuseReportTestUtils.triggerSubmit("fake-reason", "fake-message"); }, ([submittingDetails, submittedDetails]) => { const buttonsL10nId = Array.from( submittedDetails.messagebar.querySelectorAll("button") ).map(el => el.getAttribute("data-l10n-id")); if (extId === THEME_ID) { ok( buttonsL10nId.every(id => id.endsWith("-theme")), "submitted bar actions should use the Fluent id for themes" ); } else { ok( buttonsL10nId.every(id => id.endsWith("-extension")), "submitted bar actions should use the Fluent id for extensions" ); } } ); } for (const extId of [EXT_ID2, THEME_ID, SITEPERM_ADDON_ID]) { const testFn = async () => { info(`Test message bars on ${extId} reported opened from addon removal`); setTestRequestHandler(200, "{}"); AbuseReportTestUtils.triggerNewReport(extId, "uninstall"); await AbuseReportTestUtils.promiseReportRendered(); const addon = await AddonManager.getAddonByID(extId); // Ensure that the test extension is pending uninstall as it would be // when a user trigger this scenario on an actual addon uninstall. await addon.uninstall(true); AbuseReportTestUtils.triggerSubmit("fake-reason", "fake-message"); }; const assertMessageBarDetails = async ([ submittingDetails, submittedDetails, ]) => AbuseReportTestUtils.assertFluentStrings(submittedDetails.messagebar); await assertMessageBars( ["submitting", "submitted-and-removed"], testFn, assertMessageBarDetails ); } // Verify message bar on sitepermission add-on type. await assertMessageBars( ["submitting", "submitted"], async () => { info( "Test message bars for report submitted on an sitepermission addon type" ); setTestRequestHandler(200, "{}"); AbuseReportTestUtils.triggerNewReport(SITEPERM_ADDON_ID, "menu"); await AbuseReportTestUtils.promiseReportRendered(); AbuseReportTestUtils.triggerSubmit("fake-reason", "fake-message"); }, ([submittingDetails, submittedDetails]) => AbuseReportTestUtils.assertFluentStrings(submittedDetails.messagebar) ); await extension.unload(); await extension2.unload(); await theme.unload(); await sitePermAddon.unload(); }); add_task(async function test_abusereport_from_aboutaddons_menu() { const EXT_ID = "test-report-from-aboutaddons-menu@mochi.test"; const extension = await installTestExtension(EXT_ID); await openAboutAddons(); AbuseReportTestUtils.assertReportPanelHidden(); const addonCard = gManagerWindow.document.querySelector( `addon-list addon-card[addon-id="${extension.id}"]` ); ok(addonCard, "Got the addon-card for the test extension"); const reportButton = addonCard.querySelector("[action=report]"); ok(reportButton, "Got the report action for the test extension"); info("Click the report action and wait for the 'abuse-report:new' event"); let onceReportOpened = AbuseReportTestUtils.promiseReportOpened({ addonId: extension.id, reportEntryPoint: "menu", }); reportButton.click(); const panelEl = await onceReportOpened; await AbuseReportTestUtils.closeReportPanel(panelEl); await closeAboutAddons(); await extension.unload(); }); add_task(async function test_abusereport_from_aboutaddons_remove() { const EXT_ID = "test-report-from-aboutaddons-remove@mochi.test"; // Test on a theme addon to cover the report checkbox included in the // uninstall dialog also on a theme. const extension = await installTestExtension(EXT_ID, "theme"); await openAboutAddons("theme"); AbuseReportTestUtils.assertReportPanelHidden(); const addonCard = gManagerWindow.document.querySelector( `addon-list addon-card[addon-id="${extension.id}"]` ); ok(addonCard, "Got the addon-card for the test theme extension"); const removeButton = addonCard.querySelector("[action=remove]"); ok(removeButton, "Got the remove action for the test theme extension"); // Prepare the mocked prompt service. const promptService = mockPromptService(); promptService.confirmEx = createPromptConfirmEx({ remove: true, report: true, }); info("Click the report action and wait for the 'abuse-report:new' event"); const onceReportOpened = AbuseReportTestUtils.promiseReportOpened({ addonId: extension.id, reportEntryPoint: "uninstall", }); removeButton.click(); const panelEl = await onceReportOpened; await AbuseReportTestUtils.closeReportPanel(panelEl); await closeAboutAddons(); await extension.unload(); }); add_task(async function test_abusereport_from_browserAction_remove() { const EXT_ID = "test-report-from-browseraction-remove@mochi.test"; const xpiFile = AddonTestUtils.createTempWebExtensionFile({ manifest: { ...BASE_TEST_MANIFEST, browser_action: { default_area: "navbar", }, browser_specific_settings: { gecko: { id: EXT_ID } }, }, }); const addon = await AddonManager.installTemporaryAddon(xpiFile); const buttonId = `${makeWidgetId(EXT_ID)}-browser-action`; async function promiseAnimationFrame() { await new Promise(resolve => window.requestAnimationFrame(resolve)); let { tm } = Services; return new Promise(resolve => tm.dispatchToMainThread(resolve)); } async function reportFromContextMenuRemove() { const menu = document.getElementById("toolbar-context-menu"); const node = document.getElementById(CSS.escape(buttonId)); const shown = BrowserTestUtils.waitForEvent( menu, "popupshown", "Wair for contextmenu popup" ); // Wait for an animation frame as we do for the other mochitest-browser // tests related to the browserActions. await promiseAnimationFrame(); EventUtils.synthesizeMouseAtCenter(node, { type: "contextmenu" }); await shown; info(`Clicking on "Remove Extension" context menu item`); let removeExtension = menu.querySelector( ".customize-context-removeExtension" ); removeExtension.click(); return menu; } // Prepare the mocked prompt service. const promptService = mockPromptService(); promptService.confirmEx = createPromptConfirmEx({ remove: true, report: true, }); await BrowserTestUtils.withNewTab("about:blank", async function () { info(`Open browserAction context menu in toolbar context menu`); let promiseMenu = reportFromContextMenuRemove(); // Wait about:addons to be loaded. let browser = gBrowser.selectedBrowser; await BrowserTestUtils.browserLoaded(browser); let onceReportOpened = AbuseReportTestUtils.promiseReportOpened({ addonId: EXT_ID, reportEntryPoint: "uninstall", managerWindow: browser.contentWindow, }); is( browser.currentURI.spec, "about:addons", "about:addons tab currently selected" ); let menu = await promiseMenu; menu.hidePopup(); let panelEl = await onceReportOpened; await AbuseReportTestUtils.closeReportPanel(panelEl); let onceExtStarted = AddonTestUtils.promiseWebExtensionStartup(EXT_ID); addon.cancelUninstall(); await onceExtStarted; // Reload the tab to verify Bug 1559124 didn't regressed. browser.contentWindow.location.reload(); await BrowserTestUtils.browserLoaded(browser); is( browser.currentURI.spec, "about:addons", "about:addons tab currently selected" ); onceReportOpened = AbuseReportTestUtils.promiseReportOpened({ addonId: EXT_ID, reportEntryPoint: "uninstall", managerWindow: browser.contentWindow, }); menu = await reportFromContextMenuRemove(); info("Wait for the report panel"); panelEl = await onceReportOpened; info("Wait for the report panel to be closed"); await AbuseReportTestUtils.closeReportPanel(panelEl); menu.hidePopup(); onceExtStarted = AddonTestUtils.promiseWebExtensionStartup(EXT_ID); addon.cancelUninstall(); await onceExtStarted; }); await addon.uninstall(); }); /* * Test report action hidden on non-supported extension types. */ add_task(async function test_report_action_hidden_on_builtin_addons() { await openAboutAddons("theme"); await AbuseReportTestUtils.assertReportActionHidden( gManagerWindow, DEFAULT_BUILTIN_THEME_ID ); await closeAboutAddons(); }); add_task(async function test_report_action_hidden_on_system_addons() { await openAboutAddons("extension"); await AbuseReportTestUtils.assertReportActionHidden( gManagerWindow, EXT_SYSTEM_ADDON_ID ); await closeAboutAddons(); }); add_task(async function test_report_action_hidden_on_dictionary_addons() { await openAboutAddons("dictionary"); await AbuseReportTestUtils.assertReportActionHidden( gManagerWindow, EXT_DICTIONARY_ADDON_ID ); await closeAboutAddons(); }); add_task(async function test_report_action_hidden_on_langpack_addons() { await openAboutAddons("locale"); await AbuseReportTestUtils.assertReportActionHidden( gManagerWindow, EXT_LANGPACK_ADDON_ID ); await closeAboutAddons(); }); // This test verifies that triggering a report that would be immediately // cancelled (e.g. because abuse reports for that extension type are not // supported) the abuse report is being hidden as expected. add_task(async function test_report_hidden_on_report_unsupported_addontype() { await openAboutAddons(); let onceCreateReportFailed = AbuseReportTestUtils.promiseMessageBars(1); AbuseReportTestUtils.triggerNewReport(EXT_UNSUPPORTED_TYPE_ADDON_ID, "menu"); await onceCreateReportFailed; ok(!AbuseReporter.getOpenDialog(), "report dialog should not be open"); await closeAboutAddons(); }); /* * Test regression fixes. */ add_task(async function test_no_broken_suggestion_on_missing_supportURL() { const EXT_ID = "test-no-author@mochi.test"; const extension = await installTestExtension(EXT_ID, "extension", { homepage_url: undefined, }); const abuseReportEl = await AbuseReportTestUtils.openReport(EXT_ID); info("Select broken as the abuse reason"); abuseReportEl.querySelector("#abuse-reason-broken").checked = true; let oncePanelUpdated = AbuseReportTestUtils.promiseReportUpdated( abuseReportEl, "submit" ); await AbuseReportTestUtils.clickPanelButton(abuseReportEl._btnNext); await oncePanelUpdated; const suggestionEl = abuseReportEl.querySelector( "abuse-report-reason-suggestions" ); is(suggestionEl.reason, "broken", "Got the expected suggestion element"); ok(suggestionEl.hidden, "suggestion element should be empty"); await closeAboutAddons(); await extension.unload(); }); // This test verify that the abuse report panel is opening the // author link using a null triggeringPrincipal. add_task(async function test_abusereport_open_author_url() { const abuseReportEl = await AbuseReportTestUtils.openReport( EXT_WITH_PRIVILEGED_URL_ID ); const authorLink = abuseReportEl._linkAddonAuthor; ok(authorLink, "Got the author link element"); is( authorLink.href, "about:config", "Got a privileged url in the link element" ); SimpleTest.waitForExplicitFinish(); let waitForConsole = new Promise(resolve => { SimpleTest.monitorConsole(resolve, [ { message: // eslint-disable-next-line max-len /Security Error: Content at moz-nullprincipal:{.*} may not load or link to about:config/, }, ]); }); let tabSwitched = BrowserTestUtils.waitForEvent(gBrowser, "TabSwitchDone"); authorLink.click(); await tabSwitched; is( gBrowser.selectedBrowser.currentURI.spec, "about:blank", "Got about:blank loaded in the new tab" ); SimpleTest.endMonitorConsole(); await waitForConsole; BrowserTestUtils.removeTab(gBrowser.selectedTab); await closeAboutAddons(); }); add_task(async function test_no_report_checkbox_for_unsupported_addon_types() { async function test_report_checkbox_hidden(addon) { await openAboutAddons(addon.type); const addonCard = gManagerWindow.document.querySelector( `addon-list addon-card[addon-id="${addon.id}"]` ); ok(addonCard, "Got the addon-card for the test extension"); const removeButton = addonCard.querySelector("[action=remove]"); ok(removeButton, "Got the remove action for the test extension"); // Prepare the mocked prompt service. const promptService = mockPromptService(); promptService.confirmEx = createPromptConfirmEx({ remove: true, report: false, expectCheckboxHidden: true, }); info("Click the report action and wait for the addon to be removed"); const promiseCardRemoved = BrowserTestUtils.waitForEvent( addonCard.closest("addon-list"), "remove" ); removeButton.click(); await promiseCardRemoved; await closeAboutAddons(); } const reportNotSupportedAddons = [ { id: "fake-langpack-to-remove@mochi.test", name: "This is a fake langpack", version: "1.1", type: "locale", }, { id: "fake-dictionary-to-remove@mochi.test", name: "This is a fake dictionary", version: "1.1", type: "dictionary", }, ]; AbuseReportTestUtils.createMockAddons(reportNotSupportedAddons); for (const { id } of reportNotSupportedAddons) { const addon = await AddonManager.getAddonByID(id); await test_report_checkbox_hidden(addon); } }); add_task(async function test_author_hidden_when_missing() { const EXT_ID = "test-no-author@mochi.test"; const extension = await installTestExtension(EXT_ID, "extension", { author: undefined, }); const abuseReportEl = await AbuseReportTestUtils.openReport(EXT_ID); const addon = await AddonManager.getAddonByID(EXT_ID); ok(!addon.creator, "addon.creator should not be undefined"); ok( abuseReportEl._addonAuthorContainer.hidden, "author container should be hidden" ); await closeAboutAddons(); await extension.unload(); }); // Verify addon.siteOrigin is used as a fallback when homepage_url/developer.url // or support url are missing. // // TODO(Bug 1789718): adapt to SitePermAddonProvider implementation. add_task(async function test_siteperm_siteorigin_fallback() { const SITEPERM_ADDON_ID = "webmidi-site-origin@mochi.test"; const sitePermAddon = await installTestExtension( SITEPERM_ADDON_ID, "sitepermission-deprecated", { homepage_url: undefined, } ); const abuseReportEl = await AbuseReportTestUtils.openReport( SITEPERM_ADDON_ID ); const addon = await AddonManager.getAddonByID(SITEPERM_ADDON_ID); ok(addon.siteOrigin, "addon.siteOrigin should not be undefined"); ok(!addon.supportURL, "addon.supportURL should not be set"); ok(!addon.homepageURL, "addon.homepageURL should not be set"); is( abuseReportEl.supportURL, addon.siteOrigin, "Got the expected support_url" ); await closeAboutAddons(); await sitePermAddon.unload(); });