Bug 1691578 - part6 : add test cases to test reporting decode error. r=bryce,webidl,emilio

Differential Revision: https://phabricator.services.mozilla.com/D104570
This commit is contained in:
alwu 2021-02-25 18:07:06 +00:00
Родитель edf054e11a
Коммит 5c51ce0bba
4 изменённых файлов: 131 добавлений и 20 удалений

Просмотреть файл

@ -9,6 +9,9 @@
#endif
#include "mozilla/dom/HTMLMediaElement.h"
#include <unordered_map>
#include "AudioDeviceInfo.h"
#include "AudioStreamTrack.h"
#include "AutoplayPolicy.h"
@ -2087,6 +2090,44 @@ void HTMLMediaElement::SetFormatDiagnosticsReportForMimeType(
__func__);
}
void HTMLMediaElement::SetDecodeError(const nsAString& aError,
ErrorResult& aRv) {
// The reason we use this map-ish structure is because we can't use
// `CR.NS_ERROR.*` directly in test. In order to use them in test, we have to
// add them into `xpc.msg`. As we won't use `CR.NS_ERROR.*` in the production
// code, adding them to `xpc.msg` seems an overdesign and adding maintenance
// effort (exposing them in CR also needs to add a description, which is
// useless because we won't show them to users)
static struct {
const char* mName;
nsresult mResult;
} kSupportedErrorList[] = {
{"NS_ERROR_DOM_MEDIA_ABORT_ERR", NS_ERROR_DOM_MEDIA_ABORT_ERR},
{"NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR",
NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR},
{"NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR",
NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR},
{"NS_ERROR_DOM_MEDIA_DECODE_ERR", NS_ERROR_DOM_MEDIA_DECODE_ERR},
{"NS_ERROR_DOM_MEDIA_FATAL_ERR", NS_ERROR_DOM_MEDIA_FATAL_ERR},
{"NS_ERROR_DOM_MEDIA_METADATA_ERR", NS_ERROR_DOM_MEDIA_METADATA_ERR},
{"NS_ERROR_DOM_MEDIA_OVERFLOW_ERR", NS_ERROR_DOM_MEDIA_OVERFLOW_ERR},
{"NS_ERROR_DOM_MEDIA_MEDIASINK_ERR", NS_ERROR_DOM_MEDIA_MEDIASINK_ERR},
{"NS_ERROR_DOM_MEDIA_DEMUXER_ERR", NS_ERROR_DOM_MEDIA_DEMUXER_ERR},
{"NS_ERROR_DOM_MEDIA_CDM_ERR", NS_ERROR_DOM_MEDIA_CDM_ERR},
{"NS_ERROR_DOM_MEDIA_CUBEB_INITIALIZATION_ERR",
NS_ERROR_DOM_MEDIA_CUBEB_INITIALIZATION_ERR}
};
for (auto& error : kSupportedErrorList) {
if (strcmp(error.mName, NS_ConvertUTF16toUTF8(aError).get()) == 0) {
DecoderDoctorDiagnostics diagnostics;
diagnostics.StoreDecodeError(OwnerDoc(), error.mResult, u""_ns, __func__);
return;
}
}
aRv.Throw(NS_ERROR_FAILURE);
return;
}
already_AddRefed<layers::Image> HTMLMediaElement::GetCurrentImage() {
MarkAsTainted();

Просмотреть файл

@ -658,6 +658,7 @@ class HTMLMediaElement : public nsGenericHTMLElement,
// Test methods for decoder doctor.
void SetFormatDiagnosticsReportForMimeType(const nsAString& aMimeType,
DecoderDoctorReportType aType);
void SetDecodeError(const nsAString& aError, ErrorResult& aRv);
// Synchronously, return the next video frame and mark the element unable to
// participate in decode suspending.

Просмотреть файл

@ -5,13 +5,14 @@
* Error should be reported after calling `DecoderDoctorDiagnostics::StoreXXX`
* methods.
* - StoreFormatDiagnostics() [for checking if type is supported]
* - StoreDecodeError() [when decode error occurs]
*/
// Only types being listed here would be allowed to display on a
// notification banner. Otherwise, the error would only be showed on the
// web console.
var gAllowedNotificationTypes =
"MediaWMFNeeded,MediaFFMpegNotFound,MediaUnsupportedLibavcodec,";
"MediaWMFNeeded,MediaFFMpegNotFound,MediaUnsupportedLibavcodec,MediaDecodeError";
// Used to check if the mime type in the notification is equal to what we set
// before. This mime type doesn't reflect the real world siutation, i.e. not
@ -81,6 +82,54 @@ add_task(async function testNoDecoder() {
BrowserTestUtils.removeTab(tab);
});
const gErrorList = [
"NS_ERROR_DOM_MEDIA_ABORT_ERR",
"NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR",
"NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR",
"NS_ERROR_DOM_MEDIA_DECODE_ERR",
"NS_ERROR_DOM_MEDIA_FATAL_ERR",
"NS_ERROR_DOM_MEDIA_METADATA_ERR",
"NS_ERROR_DOM_MEDIA_OVERFLOW_ERR",
"NS_ERROR_DOM_MEDIA_MEDIASINK_ERR",
"NS_ERROR_DOM_MEDIA_DEMUXER_ERR",
"NS_ERROR_DOM_MEDIA_CDM_ERR",
"NS_ERROR_DOM_MEDIA_CUBEB_INITIALIZATION_ERR",
];
add_task(async function testDecodeError() {
const type = "decode-error";
const decoderDoctorReportId = "mediadecodeerror";
for (let error of gErrorList) {
const tab = await createTab("about:blank");
info(`first to try if the error is not allowed to be reported`);
// No error is allowed to be reported in the notification banner.
await SpecialPowers.pushPrefEnv({
set: [["media.decoder-doctor.decode-errors-allowed", ""]],
});
await setDecodeError(tab, {
type,
decoderDoctorReportId,
error,
shouldReportNotification: false,
});
// If the notification type is `MediaDecodeError` and the error type is
// listed in the pref, then the error would be reported to the
// notification banner.
info(`Then to try if the error is allowed to be reported`);
await SpecialPowers.pushPrefEnv({
set: [["media.decoder-doctor.decode-errors-allowed", error]],
});
await setDecodeError(tab, {
type,
decoderDoctorReportId,
error,
shouldReportNotification: true,
});
BrowserTestUtils.removeTab(tab);
}
});
/**
* Following are helper functions
*/
@ -126,6 +175,27 @@ async function createTab(url) {
});
},
};
content._waitForReport = (params, shouldReportNotification) => {
const reportToConsolePromise = new Promise(r => {
content.document.addEventListener(
"mozreportmediaerror",
_ => {
r();
},
{ once: true }
);
});
const reportToNotificationBannerPromise = shouldReportNotification
? content._obs.waitFor(params)
: Promise.resolve();
info(
`waitForConsole=true, waitForNotificationBanner=${shouldReportNotification}`
);
return Promise.all([
reportToConsolePromise,
reportToNotificationBannerPromise,
]);
};
});
return tab;
}
@ -143,26 +213,22 @@ async function setFormatDiagnosticsReportForMimeType(tab, params) {
params.formats,
params.decoderDoctorReportId
);
const reportToConsolePromise = new Promise(r => {
content.document.addEventListener(
"mozreportmediaerror",
_ => {
r();
},
{ once: true }
);
});
const reportToNotificationBannerPromise = shouldReportNotification
? content._obs.waitFor(params)
: Promise.resolve();
info(
`waitForConsole=true, waitForNotificationBanner=${shouldReportNotification}`
);
await Promise.all([
reportToConsolePromise,
reportToNotificationBannerPromise,
]);
await content._waitForReport(params, shouldReportNotification);
}
);
ok(true, `finished check for ${params.decoderDoctorReportId}`);
}
async function setDecodeError(tab, params) {
info(`start check for ${params.error}`);
await SpecialPowers.spawn(
tab.linkedBrowser,
[params],
async (params, shouldReportNotification) => {
const video = content.document.createElement("video");
SpecialPowers.wrap(video).setDecodeError(params.error);
await content._waitForReport(params, params.shouldReportNotification);
}
);
ok(true, `finished check for ${params.error}`);
}

Просмотреть файл

@ -240,6 +240,9 @@ partial interface HTMLMediaElement {
// These APIs are used for decoder doctor tests.
[ChromeOnly]
void setFormatDiagnosticsReportForMimeType(DOMString mimeType, DecoderDoctorReportType error);
[Throws, ChromeOnly]
void setDecodeError(DOMString error);
};
/* Audio Output Devices API */