From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../doctor/test/browser/browser_decoderDoctor.js | 356 +++++++++++++++++++++ 1 file changed, 356 insertions(+) create mode 100644 dom/media/doctor/test/browser/browser_decoderDoctor.js (limited to 'dom/media/doctor/test/browser/browser_decoderDoctor.js') diff --git a/dom/media/doctor/test/browser/browser_decoderDoctor.js b/dom/media/doctor/test/browser/browser_decoderDoctor.js new file mode 100644 index 0000000000..c502131fec --- /dev/null +++ b/dom/media/doctor/test/browser/browser_decoderDoctor.js @@ -0,0 +1,356 @@ +"use strict"; + +// 'data' contains the notification data object: +// - data.type must be provided. +// - data.isSolved and data.decoderDoctorReportId will be added if not provided +// (false and "testReportId" resp.) +// - Other fields (e.g.: data.formats) may be provided as needed. +// 'notificationMessage': Expected message in the notification bar. +// Falsy if nothing is expected after the notification is sent, in which case +// we won't have further checks, so the following parameters are not needed. +// 'label': Expected button label. Falsy if no button is expected, in which case +// we won't have further checks, so the following parameters are not needed. +// 'accessKey': Expected access key for the button. +// 'tabChecker': function(openedTab) called with the opened tab that resulted +// from clicking the button. +async function test_decoder_doctor_notification( + data, + notificationMessage, + label, + accessKey, + isLink, + tabChecker +) { + const TEST_URL = "https://example.org"; + // A helper closure to test notifications in same or different origins. + // 'test_cross_origin' is used to determine if the observers used in the test + // are notified in the same frame (when false) or in a cross origin iframe + // (when true). + async function create_tab_and_test(test_cross_origin) { + await BrowserTestUtils.withNewTab( + { gBrowser, url: TEST_URL }, + async function (browser) { + let awaitNotificationBar; + if (notificationMessage) { + awaitNotificationBar = BrowserTestUtils.waitForNotificationBar( + gBrowser, + browser, + "decoder-doctor-notification" + ); + } + + await SpecialPowers.spawn( + browser, + [data, test_cross_origin], + /* eslint-disable-next-line no-shadow */ + async function (data, test_cross_origin) { + if (!test_cross_origin) { + // Notify in the same origin. + Services.obs.notifyObservers( + content.window, + "decoder-doctor-notification", + JSON.stringify(data) + ); + return; + // Done notifying in the same origin. + } + + // Notify in a different origin. + const CROSS_ORIGIN_URL = "https://example.com"; + let frame = content.document.createElement("iframe"); + frame.src = CROSS_ORIGIN_URL; + await new Promise(resolve => { + frame.addEventListener("load", () => { + resolve(); + }); + content.document.body.appendChild(frame); + }); + + await content.SpecialPowers.spawn( + frame, + [data], + async function ( + /* eslint-disable-next-line no-shadow */ + data + ) { + Services.obs.notifyObservers( + content.window, + "decoder-doctor-notification", + JSON.stringify(data) + ); + } + ); + // Done notifying in a different origin. + } + ); + + if (!notificationMessage) { + ok( + true, + "Tested notifying observers with a nonsensical message, no effects expected" + ); + return; + } + + let notification; + try { + notification = await awaitNotificationBar; + } catch (ex) { + ok(false, ex); + return; + } + ok(notification, "Got decoder-doctor-notification notification"); + if (label?.l10nId) { + // Without the following statement, the + // test_cannot_initialize_pulseaudio + // will permanently fail on Linux. + if (label.l10nId === "moz-support-link-text") { + MozXULElement.insertFTLIfNeeded( + "browser/components/mozSupportLink.ftl" + ); + } + label = await document.l10n.formatValue(label.l10nId); + } + if (isLink) { + let link = notification.messageText.querySelector("a"); + if (link) { + // Seems to be a Windows specific quirk, but without this + // mutation observer the notification.messageText.textContent + // will not be updated. This will cause consistent failures + // on Windows. + await BrowserTestUtils.waitForMutationCondition( + link, + { childList: true }, + () => link.textContent.trim() + ); + } + } + is( + notification.messageText.textContent, + notificationMessage + (isLink && label ? ` ${label}` : ""), + "notification message should match expectation" + ); + + let button = notification.buttonContainer.querySelector("button"); + let link = notification.messageText.querySelector("a"); + if (!label) { + ok(!button, "There should not be a button"); + ok(!link, "There should not be a link"); + return; + } + + if (isLink) { + ok(!button, "There should not be a button"); + is(link.innerText, label, `notification link should be '${label}'`); + ok( + !link.hasAttribute("accesskey"), + "notification link should not have accesskey" + ); + } else { + ok(!link, "There should not be a link"); + is( + button.getAttribute("label"), + label, + `notification button should be '${label}'` + ); + is( + button.getAttribute("accesskey"), + accessKey, + "notification button should have accesskey" + ); + } + + if (!tabChecker) { + ok(false, "Test implementation error: Missing tabChecker"); + return; + } + let awaitNewTab = BrowserTestUtils.waitForNewTab(gBrowser); + if (button) { + button.click(); + } else { + link.click(); + } + let openedTab = await awaitNewTab; + tabChecker(openedTab); + BrowserTestUtils.removeTab(openedTab); + } + ); + } + + if (typeof data.type === "undefined") { + ok(false, "Test implementation error: data.type must be provided"); + return; + } + data.isSolved = data.isSolved || false; + if (typeof data.decoderDoctorReportId === "undefined") { + data.decoderDoctorReportId = "testReportId"; + } + + // Test same origin. + await create_tab_and_test(false); + // Test cross origin. + await create_tab_and_test(true); +} + +function tab_checker_for_sumo(expectedPath) { + return function (openedTab) { + let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL"); + let url = baseURL + expectedPath; + is( + openedTab.linkedBrowser.currentURI.spec, + url, + `Expected '${url}' in new tab` + ); + }; +} + +function tab_checker_for_webcompat(expectedParams) { + return function (openedTab) { + let urlString = openedTab.linkedBrowser.currentURI.spec; + let endpoint = Services.prefs.getStringPref( + "media.decoder-doctor.new-issue-endpoint", + "" + ); + ok( + urlString.startsWith(endpoint), + `Expected URL starting with '${endpoint}', got '${urlString}'` + ); + let params = new URL(urlString).searchParams; + for (let k in expectedParams) { + if (!params.has(k)) { + ok(false, `Expected ${k} in webcompat URL`); + } else { + is( + params.get(k), + expectedParams[k], + `Expected ${k}='${expectedParams[k]}' in webcompat URL` + ); + } + } + }; +} + +add_task(async function test_platform_decoder_not_found() { + let message = ""; + let decoderDoctorReportId = ""; + let isLinux = AppConstants.platform == "linux"; + if (isLinux) { + message = gNavigatorBundle.getString("decoder.noCodecsLinux.message"); + decoderDoctorReportId = "MediaPlatformDecoderNotFound"; + } else if (AppConstants.platform == "win") { + message = gNavigatorBundle.getString("decoder.noHWAcceleration.message"); + decoderDoctorReportId = "MediaWMFNeeded"; + } + + await test_decoder_doctor_notification( + { + type: "platform-decoder-not-found", + decoderDoctorReportId, + formats: "testFormat", + }, + message, + isLinux ? "" : { l10nId: "moz-support-link-text" }, + isLinux ? "" : gNavigatorBundle.getString("decoder.noCodecs.accesskey"), + true, + tab_checker_for_sumo("fix-video-audio-problems-firefox-windows") + ); +}); + +add_task(async function test_cannot_initialize_pulseaudio() { + let message = ""; + // This is only sent on Linux. + if (AppConstants.platform == "linux") { + message = gNavigatorBundle.getString("decoder.noPulseAudio.message"); + } + + await test_decoder_doctor_notification( + { type: "cannot-initialize-pulseaudio", formats: "testFormat" }, + message, + { l10nId: "moz-support-link-text" }, + gNavigatorBundle.getString("decoder.noCodecs.accesskey"), + true, + tab_checker_for_sumo("fix-common-audio-and-video-issues") + ); +}); + +add_task(async function test_unsupported_libavcodec() { + let message = ""; + // This is only sent on Linux. + if (AppConstants.platform == "linux") { + message = gNavigatorBundle.getString( + "decoder.unsupportedLibavcodec.message" + ); + } + + await test_decoder_doctor_notification( + { type: "unsupported-libavcodec", formats: "testFormat" }, + message + ); +}); + +add_task(async function test_decode_error() { + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "media.decoder-doctor.new-issue-endpoint", + "http://example.com/webcompat", + ], + ["browser.fixup.fallback-to-https", false], + ], + }); + let message = gNavigatorBundle.getString("decoder.decodeError.message"); + await test_decoder_doctor_notification( + { + type: "decode-error", + decodeIssue: "DecodeIssue", + docURL: "DocURL", + resourceURL: "ResURL", + }, + message, + gNavigatorBundle.getString("decoder.decodeError.button"), + gNavigatorBundle.getString("decoder.decodeError.accesskey"), + false, + tab_checker_for_webcompat({ + url: "DocURL", + label: "type-media", + problem_type: "video_bug", + details: JSON.stringify({ + "Technical Information:": "DecodeIssue", + "Resource:": "ResURL", + }), + }) + ); +}); + +add_task(async function test_decode_warning() { + await SpecialPowers.pushPrefEnv({ + set: [ + [ + "media.decoder-doctor.new-issue-endpoint", + "http://example.com/webcompat", + ], + ], + }); + let message = gNavigatorBundle.getString("decoder.decodeWarning.message"); + await test_decoder_doctor_notification( + { + type: "decode-warning", + decodeIssue: "DecodeIssue", + docURL: "DocURL", + resourceURL: "ResURL", + }, + message, + gNavigatorBundle.getString("decoder.decodeError.button"), + gNavigatorBundle.getString("decoder.decodeError.accesskey"), + false, + tab_checker_for_webcompat({ + url: "DocURL", + label: "type-media", + problem_type: "video_bug", + details: JSON.stringify({ + "Technical Information:": "DecodeIssue", + "Resource:": "ResURL", + }), + }) + ); +}); -- cgit v1.2.3