Merge autoland to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2017-01-18 09:24:55 -05:00
commit 4eacb032f5
1052 changed files with 122344 additions and 133713 deletions

View File

@ -146,12 +146,12 @@ static int do_main(int argc, char* argv[])
Output("Couldn't read application.ini");
return 255;
}
int result = XRE_main(argc, argv, appData, 0);
int result = XRE_main(argc, argv, appData);
XRE_FreeAppData(appData);
return result;
}
return XRE_main(argc, argv, &sAppData, 0);
return XRE_main(argc, argv, &sAppData);
}
int main(int argc, char* argv[])
@ -192,9 +192,6 @@ int main(int argc, char* argv[])
DllBlocklist_Initialize();
#endif
// We do this because of data in bug 771745
XPCOMGlueEnablePreload();
rv = XPCOMGlueStartup(exePath);
if (NS_FAILED(rv)) {
Output("Couldn't load XPCOM.\n");

View File

@ -161,40 +161,7 @@ static bool IsArg(const char* arg, const char* s)
return false;
}
XRE_GetFileFromPathType XRE_GetFileFromPath;
XRE_ParseAppDataType XRE_ParseAppData;
XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
XRE_mainType XRE_main;
XRE_StopLateWriteChecksType XRE_StopLateWriteChecks;
XRE_XPCShellMainType XRE_XPCShellMain;
XRE_GetProcessTypeType XRE_GetProcessType;
XRE_SetProcessTypeType XRE_SetProcessType;
XRE_InitChildProcessType XRE_InitChildProcess;
XRE_EnableSameExecutableForContentProcType XRE_EnableSameExecutableForContentProc;
#ifdef LIBFUZZER
XRE_LibFuzzerSetMainType XRE_LibFuzzerSetMain;
XRE_LibFuzzerGetFuncsType XRE_LibFuzzerGetFuncs;
#endif
static const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
{ "XRE_ParseAppData", (NSFuncPtr*) &XRE_ParseAppData },
{ "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
{ "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
{ "XRE_main", (NSFuncPtr*) &XRE_main },
{ "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks },
{ "XRE_XPCShellMain", (NSFuncPtr*) &XRE_XPCShellMain },
{ "XRE_GetProcessType", (NSFuncPtr*) &XRE_GetProcessType },
{ "XRE_SetProcessType", (NSFuncPtr*) &XRE_SetProcessType },
{ "XRE_InitChildProcess", (NSFuncPtr*) &XRE_InitChildProcess },
{ "XRE_EnableSameExecutableForContentProc", (NSFuncPtr*) &XRE_EnableSameExecutableForContentProc },
#ifdef LIBFUZZER
{ "XRE_LibFuzzerSetMain", (NSFuncPtr*) &XRE_LibFuzzerSetMain },
{ "XRE_LibFuzzerGetFuncs", (NSFuncPtr*) &XRE_LibFuzzerGetFuncs },
#endif
{ nullptr, nullptr }
};
Bootstrap::UniquePtr gBootstrap;
#ifdef LIBFUZZER
int libfuzzer_main(int argc, char **argv);
@ -203,37 +170,22 @@ int libfuzzer_main(int argc, char **argv);
void libFuzzerGetFuncs(const char* moduleName, LibFuzzerInitFunc* initFunc,
LibFuzzerTestingFunc* testingFunc) {
return XRE_LibFuzzerGetFuncs(moduleName, initFunc, testingFunc);
return gBootstrap->XRE_LibFuzzerGetFuncs(moduleName, initFunc, testingFunc);
}
#endif
static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory)
static int do_main(int argc, char* argv[], char* envp[])
{
nsCOMPtr<nsIFile> appini;
nsresult rv;
uint32_t mainFlags = 0;
// Allow firefox.exe to launch XULRunner apps via -app <application.ini>
// Note that -app must be the *first* argument.
const char *appDataFile = getenv("XUL_APP_FILE");
if (appDataFile && *appDataFile) {
rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
if (NS_FAILED(rv)) {
Output("Invalid path found: '%s'", appDataFile);
return 255;
}
}
else if (argc > 1 && IsArg(argv[1], "app")) {
if ((!appDataFile || !*appDataFile) &&
(argc > 1 && IsArg(argv[1], "app"))) {
if (argc == 2) {
Output("Incorrect number of arguments passed to -app");
return 255;
}
rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
if (NS_FAILED(rv)) {
Output("application.ini path not recognized: '%s'", argv[2]);
return 255;
}
appDataFile = argv[2];
char appEnv[MAXPATHLEN];
SprintfLiteral(appEnv, "XUL_APP_FILE=%s", argv[2]);
@ -255,50 +207,20 @@ static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory)
sandboxing::GetInitializedBrokerServices();
#endif
return XRE_XPCShellMain(--argc, argv, envp, &shellData);
return gBootstrap->XRE_XPCShellMain(--argc, argv, envp, &shellData);
}
XREAppData appData;
appData.xreDirectory = xreDirectory;
BootstrapConfig config;
if (appini) {
rv = XRE_ParseAppData(appini, appData);
if (NS_FAILED(rv)) {
Output("Couldn't read application.ini");
return 255;
}
appini->GetParent(getter_AddRefs(appData.directory));
if (appDataFile && *appDataFile) {
config.appData = nullptr;
config.appDataPath = appDataFile;
} else {
// no -app flag so we use the compiled-in app data
appData = sAppData;
nsCOMPtr<nsIFile> exeFile;
rv = mozilla::BinaryPath::GetFile(argv[0], getter_AddRefs(exeFile));
if (NS_FAILED(rv)) {
Output("Couldn't find the application directory.\n");
return 255;
}
nsCOMPtr<nsIFile> greDir;
exeFile->GetParent(getter_AddRefs(greDir));
#ifdef XP_MACOSX
greDir->SetNativeLeafName(NS_LITERAL_CSTRING(kOSXResourcesFolder));
#endif
nsCOMPtr<nsIFile> appSubdir;
greDir->Clone(getter_AddRefs(appSubdir));
appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder));
appData.directory = appSubdir;
config.appData = &sAppData;
config.appDataPath = kDesktopFolder;
}
#if defined(HAS_DLL_BLOCKLIST)
// The dll blocklist operates in the exe vs. xullib. Pass a flag to
// xullib so automated tests can check the result once the browser
// is up and running.
appData.flags |=
DllBlocklist_CheckStatus() ? NS_XRE_DLL_BLOCKLIST_ENABLED : 0;
#endif
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
sandbox::BrokerServices* brokerServices =
sandboxing::GetInitializedBrokerServices();
@ -308,15 +230,15 @@ static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory)
return 255;
}
#endif
appData.sandboxBrokerServices = brokerServices;
config.sandboxBrokerServices = brokerServices;
#endif
#ifdef LIBFUZZER
if (getenv("LIBFUZZER"))
XRE_LibFuzzerSetMain(argc, argv, libfuzzer_main);
gBootstrap->XRE_LibFuzzerSetMain(argc, argv, libfuzzer_main);
#endif
return XRE_main(argc, argv, appData, mainFlags);
return gBootstrap->XRE_main(argc, argv, config);
}
static bool
@ -333,7 +255,7 @@ FileExists(const char *path)
}
static nsresult
InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory)
InitXPCOMGlue(const char *argv0)
{
char exePath[MAXPATHLEN];
@ -355,41 +277,16 @@ InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory)
return NS_ERROR_FAILURE;
}
// We do this because of data in bug 771745
XPCOMGlueEnablePreload();
rv = XPCOMGlueStartup(exePath);
if (NS_FAILED(rv)) {
gBootstrap = mozilla::GetBootstrap(exePath);
if (!gBootstrap) {
Output("Couldn't load XPCOM.\n");
return rv;
}
rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
if (NS_FAILED(rv)) {
Output("Couldn't load XRE functions.\n");
return rv;
return NS_ERROR_FAILURE;
}
// This will set this thread as the main thread.
NS_LogInit();
gBootstrap->NS_LogInit();
if (xreDirectory) {
// chop XPCOM_DLL off exePath
*lastSlash = '\0';
#ifdef XP_MACOSX
lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
strcpy(lastSlash + 1, kOSXResourcesFolder);
#endif
#ifdef XP_WIN
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
xreDirectory);
#else
rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
xreDirectory);
#endif
}
return rv;
return NS_OK;
}
int main(int argc, char* argv[], char* envp[])
@ -421,38 +318,35 @@ int main(int argc, char* argv[], char* envp[])
}
#endif
nsresult rv = InitXPCOMGlue(argv[0], nullptr);
nsresult rv = InitXPCOMGlue(argv[0]);
if (NS_FAILED(rv)) {
return 255;
}
int result = content_process_main(argc, argv);
int result = content_process_main(gBootstrap.get(), argc, argv);
// InitXPCOMGlue calls NS_LogInit, so we need to balance it here.
NS_LogTerm();
gBootstrap->NS_LogTerm();
return result;
}
#endif
nsCOMPtr<nsIFile> xreDirectory;
nsresult rv = InitXPCOMGlue(argv[0], getter_AddRefs(xreDirectory));
nsresult rv = InitXPCOMGlue(argv[0]);
if (NS_FAILED(rv)) {
return 255;
}
XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
gBootstrap->XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
XRE_EnableSameExecutableForContentProc();
gBootstrap->XRE_EnableSameExecutableForContentProc();
#endif
int result = do_main(argc, argv, envp, xreDirectory);
int result = do_main(argc, argv, envp);
xreDirectory = nullptr;
NS_LogTerm();
gBootstrap->NS_LogTerm();
#ifdef XP_MACOSX
// Allow writes again. While we would like to catch writes from static
@ -460,8 +354,10 @@ int main(int argc, char* argv[], char* envp[])
// at least one such write that we don't control (see bug 826029). For
// now we enable writes again and early exits will have to use exit instead
// of _exit.
XRE_StopLateWriteChecks();
gBootstrap->XRE_StopLateWriteChecks();
#endif
gBootstrap.reset();
return result;
}

View File

@ -176,7 +176,7 @@ pref("lightweightThemes.update.enabled", true);
pref("lightweightThemes.getMoreURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes");
pref("lightweightThemes.recommendedThemes", "[{\"id\":\"recommended-1\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/a-web-browser-renaissance/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.header.jpg\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.footer.jpg\",\"textcolor\":\"#000000\",\"accentcolor\":\"#f2d9b1\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.preview.jpg\",\"author\":\"Sean.Martell\",\"version\":\"0\"},{\"id\":\"recommended-2\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/space-fantasy/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.header.jpg\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.footer.jpg\",\"textcolor\":\"#ffffff\",\"accentcolor\":\"#d9d9d9\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.preview.jpg\",\"author\":\"fx5800p\",\"version\":\"1.0\"},{\"id\":\"recommended-3\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/linen-light/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.header.png\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.footer.png\",\"accentcolor\":\"#ada8a8\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.icon.png\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.preview.png\",\"author\":\"DVemer\",\"version\":\"1.0\"},{\"id\":\"recommended-4\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/pastel-gradient/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.header.png\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.footer.png\",\"textcolor\":\"#000000\",\"accentcolor\":\"#000000\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.icon.png\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.preview.png\",\"author\":\"darrinhenein\",\"version\":\"1.0\"},{\"id\":\"recommended-5\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/carbon-light/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.header.png\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.footer.png\",\"textcolor\":\"#3b3b3b\",\"accentcolor\":\"#2e2e2e\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.preview.jpg\",\"author\":\"Jaxivo\",\"version\":\"1.0\"}]");
#if defined(MOZ_ADOBE_EME) || defined(MOZ_WIDEVINE_EME)
#if defined(MOZ_WIDEVINE_EME)
pref("browser.eme.ui.enabled", true);
#else
pref("browser.eme.ui.enabled", false);
@ -1356,16 +1356,6 @@ pref("media.eme.enabled", true);
#endif
pref("media.eme.apiVisible", true);
// Decode using Gecko Media Plugins in <video>, if a system decoder is not
// availble and the preferred GMP is available.
pref("media.gmp.decoder.enabled", false);
// If decoding-via-GMP is turned on for <video>, use Adobe's GMP for decoding,
// if it's available. Note: We won't fallback to another GMP if Adobe's is not
// installed.
pref("media.gmp.decoder.aac", 2);
pref("media.gmp.decoder.h264", 2);
// Whether we should run a test-pattern through EME GMPs before assuming they'll
// decode H.264.
pref("media.gmp.trial-create.enabled", true);
@ -1378,15 +1368,6 @@ pref("media.gmp.trial-create.enabled", true);
// to enable the CDM if its disabled; it's as if the keysystem is completely
// unsupported.
#ifdef MOZ_ADOBE_EME
pref("media.gmp-eme-adobe.visible", true);
// When Adobe EME is enabled in the build system, we don't actually enable
// the plugin by default, so that it doesn't download and install by default.
// When Adobe EME is first used, Firefox will prompt the user to enable it,
// and then download the CDM.
pref("media.gmp-eme-adobe.enabled", false);
#endif
#ifdef MOZ_WIDEVINE_EME
pref("media.gmp-widevinecdm.visible", true);
pref("media.gmp-widevinecdm.enabled", true);

View File

@ -83,6 +83,28 @@ var gFxAccounts = {
return Services.prefs.getBoolPref("services.sync.sendTabToDevice.enabled");
},
isSendableURI(aURISpec) {
if (!aURISpec) {
return false;
}
// Disallow sending tabs with more than 65535 characters.
if (aURISpec.length > 65535) {
return false;
}
try {
// Filter out un-sendable URIs -- things like local files, object urls, etc.
const unsendableRegexp = new RegExp(
Services.prefs.getCharPref("services.sync.engine.tabs.filteredUrls"), "i");
return !unsendableRegexp.test(aURISpec);
} catch (e) {
// The preference has been removed, or is an invalid regexp, so we log an
// error and treat it as a valid URI -- and the more problematic case is
// the length, which we've already addressed.
Cu.reportError(`Failed to build url filter regexp for send tab: ${e}`);
return true;
}
},
get remoteClients() {
return Weave.Service.clientsEngine.remoteClients
.sort((a, b) => a.name.localeCompare(b.name));
@ -410,14 +432,16 @@ var gFxAccounts = {
devicesPopup.appendChild(fragment);
},
updateTabContextMenu(aPopupMenu) {
updateTabContextMenu(aPopupMenu, aTargetTab) {
if (!this.sendTabToDeviceEnabled) {
return;
}
const remoteClientPresent = this.remoteClients.length > 0;
const targetURI = aTargetTab.linkedBrowser.currentURI.spec;
const showSendTab = this.remoteClients.length > 0 && this.isSendableURI(targetURI);
["context_sendTabToDevice", "context_sendTabToDevice_separator"]
.forEach(id => { document.getElementById(id).hidden = !remoteClientPresent });
.forEach(id => { document.getElementById(id).hidden = !showSendTab });
},
initPageContextMenu(contextMenu) {
@ -427,13 +451,20 @@ var gFxAccounts = {
const remoteClientPresent = this.remoteClients.length > 0;
// showSendLink and showSendPage are mutually exclusive
const showSendLink = remoteClientPresent
&& (contextMenu.onSaveableLink || contextMenu.onPlainTextLink);
let showSendLink = remoteClientPresent
&& (contextMenu.onSaveableLink || contextMenu.onPlainTextLink);
const showSendPage = !showSendLink && remoteClientPresent
&& !(contextMenu.isContentSelected ||
contextMenu.onImage || contextMenu.onCanvas ||
contextMenu.onVideo || contextMenu.onAudio ||
contextMenu.onLink || contextMenu.onTextInput);
contextMenu.onLink || contextMenu.onTextInput)
&& this.isSendableURI(contextMenu.browser.currentURI.spec);
if (showSendLink) {
// This isn't part of the condition above since we don't want to try and
// send the page if a link is clicked on or selected but is not sendable.
showSendLink = this.isSendableURI(contextMenu.linkURL);
}
["context-sendpagetodevice", "context-sep-sendpagetodevice"]
.forEach(id => contextMenu.showItem(id, showSendPage));

View File

@ -16,16 +16,11 @@ var gEMEHandler = {
},
ensureEMEEnabled(browser, keySystem) {
Services.prefs.setBoolPref("media.eme.enabled", true);
if (keySystem) {
if (keySystem.startsWith("com.adobe") &&
Services.prefs.getPrefType("media.gmp-eme-adobe.enabled") &&
!Services.prefs.getBoolPref("media.gmp-eme-adobe.enabled")) {
Services.prefs.setBoolPref("media.gmp-eme-adobe.enabled", true);
} else if (keySystem == "com.widevine.alpha" &&
Services.prefs.getPrefType("media.gmp-widevinecdm.enabled") &&
!Services.prefs.getBoolPref("media.gmp-widevinecdm.enabled")) {
Services.prefs.setBoolPref("media.gmp-widevinecdm.enabled", true);
}
if (keySystem &&
keySystem == "com.widevine.alpha" &&
Services.prefs.getPrefType("media.gmp-widevinecdm.enabled") &&
!Services.prefs.getBoolPref("media.gmp-widevinecdm.enabled")) {
Services.prefs.setBoolPref("media.gmp-widevinecdm.enabled", true);
}
browser.reload();
},
@ -33,10 +28,6 @@ var gEMEHandler = {
if (!keySystem) {
return false;
}
if (keySystem.startsWith("com.adobe") &&
Services.prefs.getPrefType("media.gmp-eme-adobe.visible")) {
return Services.prefs.getBoolPref("media.gmp-eme-adobe.visible");
}
if (keySystem == "com.widevine.alpha" &&
Services.prefs.getPrefType("media.gmp-widevinecdm.visible")) {
return Services.prefs.getBoolPref("media.gmp-widevinecdm.visible");

View File

@ -7872,7 +7872,7 @@ var TabContextMenu = {
this.contextTab.addEventListener("TabAttrModified", this);
aPopupMenu.addEventListener("popuphiding", this);
gFxAccounts.updateTabContextMenu(aPopupMenu);
gFxAccounts.updateTabContextMenu(aPopupMenu, this.contextTab);
},
handleEvent(aEvent) {
switch (aEvent.type) {

View File

@ -177,6 +177,7 @@
<menulist popuponly="true" id="ContentSelectDropdown" hidden="true">
<menupopup rolluponmousewheel="true"
activateontab="true" position="after_start"
level="parent"
#ifdef XP_WIN
consumeoutsideclicks="false" ignorekeys="shortcuts"
#endif

View File

@ -580,6 +580,15 @@
return true;
},
_isForInitialAboutBlank(aWebProgress, aLocation) {
if (!this.mBlank || !aWebProgress.isTopLevel) {
return false;
}
let location = aLocation ? aLocation.spec : "";
return location == "about:blank";
},
onProgressChange(aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress) {
@ -609,8 +618,6 @@
if (!aRequest)
return;
var oldBlank = this.mBlank;
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
const nsIChannel = Components.interfaces.nsIChannel;
let location, originalLocation;
@ -620,6 +627,18 @@
originalLocation = aRequest.originalURI;
} catch (ex) {}
let ignoreBlank = this._isForInitialAboutBlank(aWebProgress, location);
// If we were ignoring some messages about the initial about:blank, and we
// got the STATE_STOP for it, we'll want to pay attention to those messages
// from here forward. Similarly, if we conclude that this state change
// is one that we shouldn't be ignoring, then stop ignoring.
if ((ignoreBlank &&
aStateFlags & nsIWebProgressListener.STATE_STOP &&
aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) ||
!ignoreBlank && this.mBlank) {
this.mBlank = false;
}
if (aStateFlags & nsIWebProgressListener.STATE_START) {
this.mRequestCount++;
} else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
@ -706,9 +725,6 @@
this.mTabBrowser.useDefaultIcon(this.mTab);
}
if (this.mBlank)
this.mBlank = false;
// For keyword URIs clear the user typed value since they will be changed into real URIs
if (location.scheme == "keyword")
this.mBrowser.userTypedValue = null;
@ -720,7 +736,7 @@
this.mTabBrowser.mIsBusy = false;
}
if (oldBlank) {
if (ignoreBlank) {
this._callProgressListeners("onUpdateCurrentBrowser",
[aStateFlags, aStatus, "", 0],
true, false);
@ -1772,7 +1788,7 @@
// Create a new tab progress listener for the new browser we just injected,
// since tab progress listeners have logic for handling the initial about:blank
// load
listener = this.mTabProgressListener(tab, aBrowser, false, false);
listener = this.mTabProgressListener(tab, aBrowser, true, false);
this._tabListeners.set(tab, listener);
filter.addProgressListener(listener, Ci.nsIWebProgress.NOTIFY_ALL);

View File

@ -41,6 +41,21 @@ const PAGECONTENT_SMALL =
" <option value='Six'>Six</option>" +
"</select></body></html>";
const PAGECONTENT_GROUPS =
"<html>" +
"<body><select id='one'>" +
" <optgroup label='Group 1'>" +
" <option value='G1 O1'>G1 O1</option>" +
" <option value='G1 O2'>G1 O2</option>" +
" <option value='G1 O3'>G1 O3</option>" +
" </optgroup>" +
" <optgroup label='Group 2'>" +
" <option value='G2 O1'>G2 O4</option>" +
" <option value='G2 O2'>G2 O5</option>" +
" <option value='Hidden' style='display: none;'>Hidden</option>" +
" </optgroup>" +
"</select></body></html>";
const PAGECONTENT_SOMEHIDDEN =
"<html><head><style>.hidden { display: none; }</style></head>" +
"<body><select id='one'>" +
@ -446,13 +461,19 @@ function* performLargePopupTests(win) {
if (positions.length > 0) {
let cs = win.getComputedStyle(selectPopup);
let bpBottom = parseFloat(cs.paddingBottom) + parseFloat(cs.borderBottomWidth);
let selectedOption = 60;
if (Services.prefs.getBoolPref("dom.forms.selectSearch")) {
// Use option 61 instead of 60, as the 60th option element is actually the
// 61st child, since the first child is now the search input field.
selectedOption = 61;
}
// Some of the styles applied to the menuitems are percentages, meaning
// that the final layout calculations returned by getBoundingClientRect()
// might return floating point values. We don't care about sub-pixel
// accuracy, and only care about the final pixel value, so we add a
// fuzz-factor of 1.
SimpleTest.isfuzzy(selectPopup.childNodes[60].getBoundingClientRect().bottom,
SimpleTest.isfuzzy(selectPopup.childNodes[selectedOption].getBoundingClientRect().bottom,
selectPopup.getBoundingClientRect().bottom - bpBottom,
1, "Popup scroll at correct position " + bpBottom);
}
@ -474,6 +495,78 @@ function* performLargePopupTests(win) {
}
}
function* performSelectSearchTests(win) {
let browser = win.gBrowser.selectedBrowser;
yield ContentTask.spawn(browser, null, function*() {
let doc = content.document;
let select = doc.getElementById("one");
for (var i = 0; i < 40; i++) {
select.add(new content.Option("Test" + i));
}
select.options[1].selected = true;
select.focus();
});
let selectPopup = win.document.getElementById("ContentSelectDropdown").menupopup;
yield openSelectPopup(selectPopup, false, "select", win);
let searchElement = selectPopup.querySelector("textbox");
searchElement.focus();
EventUtils.synthesizeKey("O", {}, win);
is(selectPopup.childNodes[2].hidden, false, "First option should be visible");
is(selectPopup.childNodes[3].hidden, false, "Second option should be visible");
EventUtils.synthesizeKey("3", {}, win);
is(selectPopup.childNodes[2].hidden, true, "First option should be hidden");
is(selectPopup.childNodes[3].hidden, true, "Second option should be hidden");
is(selectPopup.childNodes[4].hidden, false, "Third option should be visible");
EventUtils.synthesizeKey("Z", {}, win);
is(selectPopup.childNodes[4].hidden, true, "Third option should be hidden");
is(selectPopup.childNodes[1].hidden, true, "First group header should be hidden");
EventUtils.synthesizeKey("VK_BACK_SPACE", {}, win);
is(selectPopup.childNodes[4].hidden, false, "Third option should be visible");
EventUtils.synthesizeKey("VK_BACK_SPACE", {}, win);
is(selectPopup.childNodes[5].hidden, false, "Second group header should be visible");
EventUtils.synthesizeKey("VK_BACK_SPACE", {}, win);
EventUtils.synthesizeKey("O", {}, win);
EventUtils.synthesizeKey("5", {}, win);
is(selectPopup.childNodes[5].hidden, false, "Second group header should be visible");
is(selectPopup.childNodes[1].hidden, true, "First group header should be hidden");
EventUtils.synthesizeKey("VK_BACK_SPACE", {}, win);
is(selectPopup.childNodes[1].hidden, false, "First group header should be shown");
EventUtils.synthesizeKey("VK_BACK_SPACE", {}, win);
is(selectPopup.childNodes[8].hidden, true, "Option hidden by content should remain hidden");
yield hideSelectPopup(selectPopup, "escape", win);
}
// This test checks the functionality of search in select elements with groups
// and a large number of options.
add_task(function* test_select_search() {
yield SpecialPowers.pushPrefEnv({
set: [
["dom.forms.selectSearch", true],
],
});
const pageUrl = "data:text/html," + escape(PAGECONTENT_GROUPS);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
yield performSelectSearchTests(window);
yield BrowserTestUtils.removeTab(tab);
yield SpecialPowers.popPrefEnv();
});
// This test checks select elements with a large number of options to ensure that
// the popup appears within the browser area.
add_task(function* test_large_popup() {

View File

@ -18,6 +18,8 @@ add_task(function* test() {
if (gFxAccounts.sendTabToDeviceEnabled) {
const origIsSendableURI = gFxAccounts.isSendableURI;
gFxAccounts.isSendableURI = () => true;
// Check the send tab to device menu item
const oldGetter = setupRemoteClientsFixture(remoteClientsFixture);
yield updateTabContextMenu(origTab, function* () {
@ -28,7 +30,11 @@ add_task(function* test() {
is(targets[0].getAttribute("label"), "Foo", "Foo target is present");
is(targets[1].getAttribute("label"), "Bar", "Bar target is present");
is(targets[3].getAttribute("label"), "All Devices", "All Devices target is present");
gFxAccounts.isSendableURI = () => false;
updateTabContextMenu(origTab);
is(document.getElementById("context_sendTabToDevice").hidden, true, "Send tab to device is hidden");
restoreRemoteClients(oldGetter);
gFxAccounts.isSendableURI = origIsSendableURI;
}
// Hide the original tab.

View File

@ -128,10 +128,8 @@
</tabpanel>
<tabpanel id="cookies-tabpanel"
class="tabpanel-content">
<vbox flex="1">
<html:div xmlns="http://www.w3.org/1999/xhtml"
id="react-cookies-tabpanel-hook"/>
</vbox>
<html:div xmlns="http://www.w3.org/1999/xhtml"
id="react-cookies-tabpanel-hook"/>
</tabpanel>
<tabpanel id="params-tabpanel"
class="tabpanel-content">

View File

@ -53,11 +53,13 @@ function CookiesPanel({
}
return (
PropertiesView({
object,
filterPlaceHolder: COOKIES_FILTER_TEXT,
sectionNames: SECTION_NAMES,
})
div({ className: "panel-container" },
PropertiesView({
object,
filterPlaceHolder: COOKIES_FILTER_TEXT,
sectionNames: SECTION_NAMES,
})
)
);
}

View File

@ -202,7 +202,7 @@ const HeadersPanel = createClass({
}
return (
div({},
div({ className: "panel-container" },
div({ className: "summary" },
summaryUrl,
summaryMethod,

View File

@ -92,11 +92,13 @@ function ParamsPanel({
}
return (
PropertiesView({
object,
filterPlaceHolder: PARAMS_FILTER_TEXT,
sectionNames: SECTION_NAMES,
})
div({ className: "panel-container" },
PropertiesView({
object,
filterPlaceHolder: PARAMS_FILTER_TEXT,
sectionNames: SECTION_NAMES,
})
)
);
}

View File

@ -83,7 +83,7 @@ const PropertiesView = createClass({
// Display source editor when specifying to EDITOR_CONFIG_ID along with config
if (level === 1 && name === EDITOR_CONFIG_ID) {
return (
tr({},
tr({ className: "editor-row-container" },
td({ colSpan: 2 },
Editor(value)
)

View File

@ -121,7 +121,7 @@ const ResponsePanel = createClass({
let { width, height } = this.state.imageDimensions;
return (
div({ className: "response-image-box devtools-monospace" },
div({ className: "panel-container response-image-box devtools-monospace" },
img({
className: "response-image",
src: formDataURI(mimeType, encoding, response),
@ -167,7 +167,7 @@ const ResponsePanel = createClass({
}
return (
div({},
div({ className: "panel-container" },
error && div({ className: "response-error-header", title: error },
error
),

View File

@ -10,6 +10,9 @@
add_task(function* () {
let { L10N } = require("devtools/client/netmonitor/l10n");
// Set a higher panel height in order to get full CodeMirror content
Services.prefs.setIntPref("devtools.toolbox.footer.height", 400);
let { tab, monitor } = yield initNetMonitor(POST_DATA_URL);
info("Starting test... ");

View File

@ -25,7 +25,7 @@
"background-clip", "background-color", "background-image",
"background-origin", "background-position", "background-position-x",
"background-position-y", "background-repeat", "background-size"]],
[[21, 9], ["-moz-calc", "auto", "calc", "inherit", "initial","unset"]],
[[21, 9], ["auto", "calc", "inherit", "initial","unset"]],
[[25, 26], [".devtools-toolbarbutton > tab",
".devtools-toolbarbutton > hbox",
".devtools-toolbarbutton > .toolbarbutton-menubutton-button"]],

View File

@ -1077,8 +1077,9 @@
}
}
/* Overwrite tree-view cell colon and use l10n string instead */
.treeTable .treeLabelCell::after {
/* Overwrite tree-view cell colon `:` for security panel and tree section */
#security-tabpanel .treeTable .treeLabelCell::after,
.treeTable .tree-section .treeLabelCell::after {
content: "";
}
@ -1100,18 +1101,17 @@
box-shadow: var(--theme-focus-box-shadow-textbox);
}
.properties-view {
/* FIXME: Minus 24px * 2 for toolbox height + panel height
* Give a fixed panel container height in order to force tree view scrollable */
.panel-container {
/* FIXME: To avoid the issue which panel exceeds visible range,
* we set view heigh - 24px * 2 for toolbox height + tabs height */
height: calc(100vh - 48px);
display: flex;
flex-direction: column;
}
#headers-tabpanel .properties-view {
/* FIXME: Minus 24px * 2 + 87.5 for toolbox height + panel height + headers summary
* Give a fixed panel container height in order to force tree view scrollable */
height: calc(100vh - 135.5px);
.panel-container,
.properties-view {
display: flex;
flex-direction: column;
flex-grow: 1;
}
.properties-view .searchbox-section {
@ -1142,6 +1142,36 @@
left: 0;
}
/* Apply flex to table tbody in order to fill available vertical space */
.tree-container .treeTable tbody {
display: flex;
flex-direction: column;
/* Apply flex to table will create an anonymous table element outside of tbody
* See also http://stackoverflow.com/a/30851678
* Therefore, we set height with this magic number in order to remove the
* redundant scrollbar when source editor appears.
*/
height: calc(100% - 3px);
}
.tree-container .treeTable tr {
display: block;
}
/* Make right td fill available horizontal space */
.tree-container .treeTable td:last-child {
width: 100%;
}
/* If there is a source editor shows up in the last row of TreeView,
* it should occupy the available vertical space.
*/
.tree-container .treeTable .editor-row-container,
.tree-container .treeTable tr:last-child td[colspan="2"] {
display: block;
height: 100%;
}
.properties-view .devtools-searchbox,
.tree-container .treeTable .tree-section {
width: 100%;
@ -1278,7 +1308,12 @@
#react-preview-tabpanel-hook,
#react-response-tabpanel-hook,
#react-security-tabpanel-hook,
#react-timings-tabpanel-hook,
#react-timings-tabpanel-hook {
display: flex;
-moz-box-flex: 1;
-moz-box-orient: vertical;
}
#network-statistics-charts,
#primed-cache-chart,
#empty-cache-chart {
@ -1286,19 +1321,6 @@
-moz-box-flex: 1;
}
/* For vbox */
#react-cookies-tabpanel-hook,
#react-headers-tabpanel-hook,
#react-params-tabpanel-hook,
#react-preview-tabpanel-hook,
#react-response-tabpanel-hook,
#react-security-tabpanel-hook,
#react-timings-tabpanel-hook,
#primed-cache-chart,
#empty-cache-chart {
-moz-box-orient: vertical;
}
#primed-cache-chart,
#empty-cache-chart {
-moz-box-pack: center;

View File

@ -82,7 +82,7 @@ window.onload = function() {
"A CSS variable with spaces fails");
is(toSortedString(cssProperties.getValues('margin')),
toSortedString(["-moz-calc","auto","calc","inherit","initial","unset"]),
toSortedString(["auto","calc","inherit","initial","unset"]),
"Can get values for the CSS margin.");
is(cssProperties.getValues('foobar').length, 0,
"Unknown values return an empty array.");

View File

@ -375,7 +375,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -453,7 +452,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -539,7 +537,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -617,7 +614,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -784,7 +780,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -805,7 +800,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -883,7 +877,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -902,7 +895,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -921,7 +913,6 @@ exports.CSS_PROPERTIES = {
7
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -1033,7 +1024,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -1051,7 +1041,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -1163,7 +1152,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -1180,7 +1168,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -1241,7 +1228,6 @@ exports.CSS_PROPERTIES = {
7
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -2052,7 +2038,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -2074,7 +2059,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -2499,7 +2483,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"hsl",
@ -2545,7 +2528,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -3118,7 +3100,6 @@ exports.CSS_PROPERTIES = {
"-moz-available",
"-moz-block-height",
"-moz-box",
"-moz-calc",
"-moz-center",
"-moz-crisp-edges",
"-moz-deck",
@ -4015,7 +3996,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -4054,7 +4034,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"-moz-element",
"-moz-image-rect",
"-moz-linear-gradient",
@ -4104,7 +4083,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -4182,7 +4160,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -4205,7 +4182,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -4283,7 +4259,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -4306,7 +4281,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -4414,7 +4388,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -4596,7 +4569,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -4674,7 +4646,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -4697,7 +4668,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -4775,7 +4745,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -4798,7 +4767,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -4876,7 +4844,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -4917,7 +4884,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -4995,7 +4961,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -5057,7 +5022,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -5165,7 +5129,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -5187,7 +5150,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -5207,7 +5169,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -5459,7 +5420,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -5480,7 +5440,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"calc",
"currentColor",
"dashed",
@ -5558,7 +5517,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -5577,7 +5535,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -5596,7 +5553,6 @@ exports.CSS_PROPERTIES = {
7
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -5832,7 +5788,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -5854,7 +5809,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -6025,7 +5979,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-block-height",
"-moz-calc",
"all-petite-caps",
"all-small-caps",
"auto",
@ -6124,7 +6077,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -6342,7 +6294,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -6447,7 +6398,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -6479,7 +6429,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -6525,7 +6474,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -6616,7 +6564,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -6700,7 +6647,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -6813,7 +6759,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -6830,7 +6775,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -6871,7 +6815,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-block-height",
"-moz-calc",
"calc",
"inherit",
"initial",
@ -6954,7 +6897,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -6972,7 +6914,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -6990,7 +6931,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7008,7 +6948,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7026,7 +6965,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7044,7 +6982,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7062,7 +6999,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7080,7 +7016,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7098,7 +7033,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7429,7 +7363,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -7448,7 +7381,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -7470,7 +7402,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -7492,7 +7423,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -7513,7 +7443,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7532,7 +7461,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -7554,7 +7482,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -7576,7 +7503,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -7657,7 +7583,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7675,7 +7600,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7693,7 +7617,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7711,7 +7634,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -7760,7 +7682,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"COLOR",
"-moz-calc",
"auto",
"calc",
"currentColor",
@ -7816,7 +7737,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -7854,7 +7774,6 @@ exports.CSS_PROPERTIES = {
6
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -7943,7 +7862,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -7960,7 +7878,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -7977,7 +7894,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -7994,7 +7910,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -8011,7 +7926,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -8028,7 +7942,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -8045,7 +7958,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -8062,7 +7974,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -8079,7 +7990,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -8334,7 +8244,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -8896,7 +8805,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",
@ -8989,7 +8897,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"auto",
"calc",
"inherit",
@ -9209,7 +9116,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"-moz-middle-with-baseline",
"baseline",
"bottom",
@ -9269,7 +9175,6 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-available",
"-moz-calc",
"-moz-fit-content",
"-moz-max-content",
"-moz-min-content",
@ -9317,7 +9222,6 @@ exports.CSS_PROPERTIES = {
8
],
"values": [
"-moz-calc",
"calc",
"inherit",
"initial",

View File

@ -1284,8 +1284,6 @@ nsIDocument::nsIDocument()
mUpgradeInsecurePreloads(false),
mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
mNodeInfoManager(nullptr),
mCompatMode(eCompatibility_FullStandards),
mVisibilityState(dom::VisibilityState::Hidden),
mIsInitialDocumentInWindow(false),
mMayStartLayout(true),
mVisible(true),
@ -1300,6 +1298,8 @@ nsIDocument::nsIDocument()
mFontFaceSetDirty(true),
mGetUserFontSetCalled(false),
mPostedFlushUserFontSet(false),
mCompatMode(eCompatibility_FullStandards),
mVisibilityState(dom::VisibilityState::Hidden),
mBidiOptions(IBMBIDI_DEFAULT_BIDI_OPTIONS),
mPartID(0),
mDidFireDOMContentLoaded(true),

View File

@ -2937,6 +2937,8 @@ nsFrameLoader::TryRemoteBrowser()
if (!mRemoteBrowser) {
return false;
}
// Now that mRemoteBrowser is set, we can initialize the RenderFrameParent
mRemoteBrowser->InitRenderFrame();
MaybeUpdatePrimaryTabParent(eTabParentChanged);

View File

@ -3032,24 +3032,12 @@ protected:
// container for per-context fonts (downloadable, SVG, etc.)
RefPtr<mozilla::dom::FontFaceSet> mFontFaceSet;
// Compatibility mode
nsCompatibility mCompatMode;
// Our readyState
ReadyState mReadyState;
// Whether this document has (or will have, once we have a pres shell) a
// Gecko- or Servo-backed style system.
mozilla::StyleBackendType mStyleBackendType;
#ifdef MOZILLA_INTERNAL_API
// Our visibility state
mozilla::dom::VisibilityState mVisibilityState;
static_assert(sizeof(mozilla::dom::VisibilityState) == sizeof(uint8_t),
"Error size of mVisibilityState and mDummy");
#else
uint8_t mDummy;
#endif
// XXXheycam rust-bindgen currently doesn't generate correctly aligned fields
// to represent the following bitfields if they are preceded by something
// non-pointer aligned, so if adding non-pointer sized fields, please do so
// somewhere other than right here.
//
// https://github.com/servo/rust-bindgen/issues/111
// True if BIDI is enabled.
bool mBidiEnabled : 1;
@ -3199,6 +3187,25 @@ protected:
// True is document has ever been in a foreground window.
bool mEverInForeground : 1;
// Compatibility mode
nsCompatibility mCompatMode;
// Our readyState
ReadyState mReadyState;
// Whether this document has (or will have, once we have a pres shell) a
// Gecko- or Servo-backed style system.
mozilla::StyleBackendType mStyleBackendType;
#ifdef MOZILLA_INTERNAL_API
// Our visibility state
mozilla::dom::VisibilityState mVisibilityState;
static_assert(sizeof(mozilla::dom::VisibilityState) == sizeof(uint8_t),
"Error size of mVisibilityState and mDummy");
#else
uint8_t mDummy;
#endif
enum Type {
eUnknown, // should never be used
eHTML,

View File

@ -6066,16 +6066,6 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendE
if (mMediaKeys) {
nsAutoString keySystem;
mMediaKeys->GetKeySystem(keySystem);
// If we're using Primetime we need to shutdown the key system and
// decoder to preserve secure stop like behavior, other CDMs don't
// implement this so we don't need to worry with them on a suspend.
if (IsPrimetimeKeySystem(keySystem)) {
mMediaKeys->Shutdown();
mMediaKeys = nullptr;
if (mDecoder) {
ShutdownDecoder();
}
}
}
if (mDecoder) {
mDecoder->Pause();

View File

@ -631,12 +631,13 @@ child:
*/
async Show(ScreenIntSize size,
ShowInfo info,
TextureFactoryIdentifier textureFactoryIdentifier,
uint64_t layersId,
nullable PRenderFrame renderFrame,
bool parentIsActive,
nsSizeMode sizeMode);
async InitRendering(TextureFactoryIdentifier textureFactoryIdentifier,
uint64_t layersId,
nullable PRenderFrame renderFrame);
async LoadURL(nsCString uri, ShowInfo info);
async UpdateDimensions(CSSRect rect, CSSSize size,

View File

@ -427,10 +427,10 @@ TabChild::TabChild(nsIContentChild* aManager,
bool
TabChild::AsyncPanZoomEnabled() const
{
// If we have received the CompositorOptions we can answer definitively. If
// not, return a best guess based on gfxPlaform values.
return mCompositorOptions ? mCompositorOptions->UseAPZ()
: gfxPlatform::AsyncPanZoomEnabled();
// By the time anybody calls this, we must have had InitRenderingState called
// already, and so mCompositorOptions should be populated.
MOZ_RELEASE_ASSERT(mCompositorOptions);
return mCompositorOptions->UseAPZ();
}
NS_IMETHODIMP
@ -1167,8 +1167,8 @@ TabChild::DoFakeShow(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
const uint64_t& aLayersId,
PRenderFrameChild* aRenderFrame, const ShowInfo& aShowInfo)
{
RecvShow(ScreenIntSize(0, 0), aShowInfo, aTextureFactoryIdentifier,
aLayersId, aRenderFrame, mParentIsActive, nsSizeMode_Normal);
InitRenderingState(aTextureFactoryIdentifier, aLayersId, aRenderFrame);
RecvShow(ScreenIntSize(0, 0), aShowInfo, mParentIsActive, nsSizeMode_Normal);
mDidFakeShow = true;
}
@ -1224,39 +1224,41 @@ TabChild::ApplyShowInfo(const ShowInfo& aInfo)
mozilla::ipc::IPCResult
TabChild::RecvShow(const ScreenIntSize& aSize,
const ShowInfo& aInfo,
const TextureFactoryIdentifier& aTextureFactoryIdentifier,
const uint64_t& aLayersId,
PRenderFrameChild* aRenderFrame,
const bool& aParentIsActive,
const nsSizeMode& aSizeMode)
{
MOZ_ASSERT((!mDidFakeShow && aRenderFrame) || (mDidFakeShow && !aRenderFrame));
mPuppetWidget->SetSizeMode(aSizeMode);
if (mDidFakeShow) {
ApplyShowInfo(aInfo);
RecvParentActivated(aParentIsActive);
return IPC_OK();
}
bool res = true;
mPuppetWidget->SetSizeMode(aSizeMode);
if (!mDidFakeShow) {
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
if (!baseWindow) {
NS_ERROR("WebNavigation() doesn't QI to nsIBaseWindow");
return IPC_FAIL_NO_REASON(this);
}
InitRenderingState(aTextureFactoryIdentifier, aLayersId, aRenderFrame);
baseWindow->SetVisibility(true);
res = InitTabChildGlobal();
}
bool res = InitTabChildGlobal();
ApplyShowInfo(aInfo);
RecvParentActivated(aParentIsActive);
ApplyShowInfo(aInfo);
RecvParentActivated(aParentIsActive);
if (!res) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
if (!res) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult
TabChild::RecvInitRendering(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
const uint64_t& aLayersId,
PRenderFrameChild* aRenderFrame)
{
MOZ_ASSERT((!mDidFakeShow && aRenderFrame) || (mDidFakeShow && !aRenderFrame));
InitRenderingState(aTextureFactoryIdentifier, aLayersId, aRenderFrame);
return IPC_OK();
}
mozilla::ipc::IPCResult

View File

@ -338,12 +338,14 @@ public:
virtual mozilla::ipc::IPCResult
RecvShow(const ScreenIntSize& aSize,
const ShowInfo& aInfo,
const TextureFactoryIdentifier& aTextureFactoryIdentifier,
const uint64_t& aLayersId,
PRenderFrameChild* aRenderFrame,
const bool& aParentIsActive,
const nsSizeMode& aSizeMode) override;
virtual mozilla::ipc::IPCResult
RecvInitRendering(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
const uint64_t& aLayersId,
PRenderFrameChild* aRenderFrame) override;
virtual mozilla::ipc::IPCResult
RecvUpdateDimensions(const CSSRect& aRect,
const CSSSize& aSize,

View File

@ -620,6 +620,34 @@ TabParent::LoadURL(nsIURI* aURI)
Unused << SendLoadURL(spec, GetShowInfo());
}
void
TabParent::InitRenderFrame()
{
if (IsInitedByParent()) {
// If TabParent is initialized by parent side then the RenderFrame must also
// be created here. If TabParent is initialized by child side,
// child side will create RenderFrame.
MOZ_ASSERT(!GetRenderFrame());
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
MOZ_ASSERT(frameLoader);
if (frameLoader) {
bool success;
RenderFrameParent* renderFrame = new RenderFrameParent(frameLoader, &success);
uint64_t layersId = renderFrame->GetLayersId();
AddTabParentToTable(layersId, this);
Unused << SendPRenderFrameConstructor(renderFrame);
TextureFactoryIdentifier textureFactoryIdentifier;
renderFrame->GetTextureFactoryIdentifier(&textureFactoryIdentifier);
Unused << SendInitRendering(textureFactoryIdentifier, layersId, renderFrame);
}
} else {
// Otherwise, the child should have constructed the RenderFrame,
// and we should already know about it.
MOZ_ASSERT(GetRenderFrame());
}
}
void
TabParent::Show(const ScreenIntSize& size, bool aParentIsActive)
{
@ -628,28 +656,7 @@ TabParent::Show(const ScreenIntSize& size, bool aParentIsActive)
return;
}
TextureFactoryIdentifier textureFactoryIdentifier;
uint64_t layersId = 0;
bool success = false;
RenderFrameParent* renderFrame = nullptr;
if (IsInitedByParent()) {
// If TabParent is initialized by parent side then the RenderFrame must also
// be created here. If TabParent is initialized by child side,
// child side will create RenderFrame.
MOZ_ASSERT(!GetRenderFrame());
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
if (frameLoader) {
renderFrame = new RenderFrameParent(frameLoader, &success);
layersId = renderFrame->GetLayersId();
renderFrame->GetTextureFactoryIdentifier(&textureFactoryIdentifier);
AddTabParentToTable(layersId, this);
Unused << SendPRenderFrameConstructor(renderFrame);
}
} else {
// Otherwise, the child should have constructed the RenderFrame,
// and we should already know about it.
MOZ_ASSERT(GetRenderFrame());
}
MOZ_ASSERT(GetRenderFrame());
nsCOMPtr<nsISupports> container = mFrameElement->OwnerDoc()->GetContainer();
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container);
@ -657,8 +664,7 @@ TabParent::Show(const ScreenIntSize& size, bool aParentIsActive)
baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
mSizeMode = mainWidget ? mainWidget->SizeMode() : nsSizeMode_Normal;
Unused << SendShow(size, GetShowInfo(), textureFactoryIdentifier,
layersId, renderFrame, aParentIsActive, mSizeMode);
Unused << SendShow(size, GetShowInfo(), aParentIsActive, mSizeMode);
}
mozilla::ipc::IPCResult

View File

@ -368,6 +368,8 @@ public:
void LoadURL(nsIURI* aURI);
void InitRenderFrame();
// XXX/cjones: it's not clear what we gain by hiding these
// message-sending functions under a layer of indirection and
// eating the return values

View File

@ -31,7 +31,6 @@ gmp_privacy_info=Privacy Information
openH264_name=OpenH264 Video Codec provided by Cisco Systems, Inc.
openH264_description2=This plugin is automatically installed by Mozilla to comply with the WebRTC specification and to enable WebRTC calls with devices that require the H.264 video codec. Visit http://www.openh264.org/ to view the codec source code and learn more about the implementation.
eme-adobe_name=Primetime Content Decryption Module provided by Adobe Systems, Incorporated
eme-adobe_description=Play back protected web video.
cdm_description=Play back protected web video.
widevine_description=Widevine Content Decryption Module provided by Google Inc.

View File

@ -32,7 +32,6 @@ namespace mozilla {
NS_NAMED_LITERAL_CSTRING(kEMEKeySystemClearkey, "org.w3.clearkey");
NS_NAMED_LITERAL_CSTRING(kEMEKeySystemWidevine, "com.widevine.alpha");
NS_NAMED_LITERAL_CSTRING(kEMEKeySystemPrimetime, "com.adobe.primetime");
using layers::PlanarYCbCrImage;

View File

@ -46,7 +46,6 @@ class MediaContentType;
// EME Key System String.
extern const nsLiteralCString kEMEKeySystemClearkey;
extern const nsLiteralCString kEMEKeySystemWidevine;
extern const nsLiteralCString kEMEKeySystemPrimetime;
/**
* ReentrantMonitorConditionallyEnter

View File

@ -53,12 +53,6 @@ IsClearkeyKeySystem(const nsAString& aKeySystem)
return !CompareUTF8toUTF16(kEMEKeySystemClearkey, aKeySystem);
}
bool
IsPrimetimeKeySystem(const nsAString& aKeySystem)
{
return !CompareUTF8toUTF16(kEMEKeySystemPrimetime, aKeySystem);
}
bool
IsWidevineKeySystem(const nsAString& aKeySystem)
{
@ -68,9 +62,6 @@ IsWidevineKeySystem(const nsAString& aKeySystem)
nsString
KeySystemToGMPName(const nsAString& aKeySystem)
{
if (IsPrimetimeKeySystem(aKeySystem)) {
return NS_LITERAL_STRING("gmp-eme-adobe");
}
if (IsClearkeyKeySystem(aKeySystem)) {
return NS_LITERAL_STRING("gmp-clearkey");
}
@ -88,8 +79,6 @@ ToCDMTypeTelemetryEnum(const nsString& aKeySystem)
return CDMType::eWidevine;
} else if (IsClearkeyKeySystem(aKeySystem)) {
return CDMType::eClearKey;
} else if (IsPrimetimeKeySystem(aKeySystem)) {
return CDMType::ePrimetime;
}
return CDMType::eUnknown;
}

View File

@ -86,15 +86,15 @@ KeySystemToGMPName(const nsAString& aKeySystem);
bool
IsClearkeyKeySystem(const nsAString& aKeySystem);
bool
IsPrimetimeKeySystem(const nsAString& aKeySystem);
bool
IsWidevineKeySystem(const nsAString& aKeySystem);
// Note: Primetime is now unsupported, but we leave it in the enum so
// that the telemetry enum values are not changed; doing so would break
// existing telemetry probes.
enum CDMType {
eClearKey = 0,
ePrimetime = 1,
ePrimetime = 1, // Note: Unsupported.
eWidevine = 2,
eUnknown = 3
};

View File

@ -27,8 +27,6 @@
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsXULAppAPI.h"
#include "gmp-audio-decode.h"
#include "gmp-video-decode.h"
#include "DecoderDoctorDiagnostics.h"
#include "WebMDecoder.h"
#include "mozilla/StaticPtr.h"
@ -134,16 +132,6 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
return EnsureCDMInstalled(aKeySystem, aOutMessage);
}
if (Preferences::GetBool("media.gmp-eme-adobe.visible", false)) {
if (IsPrimetimeKeySystem(aKeySystem)) {
if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) {
aOutMessage = NS_LITERAL_CSTRING("Adobe EME disabled");
return MediaKeySystemStatus::Cdm_disabled;
}
return EnsureCDMInstalled(aKeySystem, aOutMessage);
}
}
if (IsWidevineKeySystem(aKeySystem)) {
if (Preferences::GetBool("media.gmp-widevinecdm.visible", false)) {
if (!Preferences::GetBool("media.gmp-widevinecdm.enabled", false)) {
@ -324,9 +312,8 @@ GetSupportedKeySystems()
#if defined(XP_WIN)
// Widevine CDM doesn't include an AAC decoder. So if WMF can't
// decode AAC, and a codec wasn't specified, be conservative
// and reject the MediaKeys request, since our policy is to prevent
// the Adobe GMP's unencrypted AAC decoding path being used to
// decode content decrypted by the Widevine CDM.
// and reject the MediaKeys request, since we assume Widevine
// will be used with AAC.
if (WMFDecoderModule::HasAAC()) {
widevine.mMP4.SetCanDecrypt(EME_CODEC_AAC);
}
@ -376,19 +363,6 @@ GetSupportedKeySystems()
keySystemConfigs.AppendElement(Move(widevine));
}
}
{
if (HavePluginForKeySystem(kEMEKeySystemPrimetime)) {
KeySystemConfig primetime;
primetime.mKeySystem = NS_ConvertUTF8toUTF16(kEMEKeySystemPrimetime);
primetime.mInitDataTypes.AppendElement(NS_LITERAL_STRING("cenc"));
primetime.mPersistentState = KeySystemFeatureSupport::Required;
primetime.mDistinctiveIdentifier = KeySystemFeatureSupport::Required;
primetime.mSessionTypes.AppendElement(MediaKeySessionType::Temporary);
primetime.mMP4.SetCanDecryptAndDecode(EME_CODEC_AAC);
primetime.mMP4.SetCanDecryptAndDecode(EME_CODEC_H264);
keySystemConfigs.AppendElement(Move(primetime));
}
}
return keySystemConfigs;
}
@ -453,9 +427,8 @@ CanDecryptAndDecode(const nsString& aKeySystem,
#if defined(XP_WIN)
// Widevine CDM doesn't include an AAC decoder. So if WMF can't
// decode AAC, and a codec wasn't specified, be conservative
// and reject the MediaKeys request, since our policy is to prevent
// the Adobe GMP's unencrypted AAC decoding path being used to
// decode content decrypted by the Widevine CDM.
// and reject the MediaKeys request, since we assume Widevine
// will be used with AAC.
if (codec == EME_CODEC_AAC &&
IsWidevineKeySystem(aKeySystem) &&
!WMFDecoderModule::HasAAC()) {

View File

@ -94,9 +94,7 @@ MediaKeySystemAccessManager::Request(DetailedPromise* aPromise,
DecoderDoctorDiagnostics diagnostics;
// Ensure keysystem is supported.
if (!IsWidevineKeySystem(aKeySystem) &&
!IsClearkeyKeySystem(aKeySystem) &&
!IsPrimetimeKeySystem(aKeySystem)) {
if (!IsWidevineKeySystem(aKeySystem) && !IsClearkeyKeySystem(aKeySystem)) {
// Not to inform user, because nothing to do if the keySystem is not
// supported.
aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
@ -132,7 +130,7 @@ MediaKeySystemAccessManager::Request(DetailedPromise* aPromise,
LogToBrowserConsole(NS_ConvertUTF8toUTF16(msg));
if (status == MediaKeySystemStatus::Cdm_not_installed &&
(IsPrimetimeKeySystem(aKeySystem) || IsWidevineKeySystem(aKeySystem))) {
IsWidevineKeySystem(aKeySystem)) {
// These are cases which could be resolved by downloading a new(er) CDM.
// When we send the status to chrome, chrome's GMPProvider will attempt to
// download or update the CDM. In AwaitInstall() we add listeners to wait

View File

@ -1,5 +1,5 @@
Name: fake
Description: Fake GMP Plugin, which deliberately uses GMP_API_DECRYPTOR_BACKWARDS_COMPAT for its decryptor.
Description: Fake GMP Plugin.
Version: 1.0
APIs: decode-video[h264:broken], eme-decrypt-v7[fake]
APIs: decode-video[h264:broken], eme-decrypt-v9[fake]
Libraries: dxva2.dll

View File

@ -72,7 +72,7 @@ extern "C" {
// happens when decoder init fails.
return GMPGenericErr;
#if defined(GMP_FAKE_SUPPORT_DECRYPT)
} else if (!strcmp (aApiName, GMP_API_DECRYPTOR_BACKWARDS_COMPAT)) {
} else if (!strcmp (aApiName, GMP_API_DECRYPTOR)) {
*aPluginApi = new FakeDecryptor(static_cast<GMPDecryptorHost*> (aHostAPI));
return GMPNoErr;
} else if (!strcmp (aApiName, GMP_API_ASYNC_SHUTDOWN)) {

View File

@ -11,12 +11,15 @@
#include <string>
#include "mozilla/Attributes.h"
class FakeDecryptor : public GMPDecryptor7 {
class FakeDecryptor : public GMPDecryptor {
public:
explicit FakeDecryptor(GMPDecryptorHost* aHost);
void Init(GMPDecryptorCallback* aCallback) override {
void Init(GMPDecryptorCallback* aCallback,
bool aDistinctiveIdentifierRequired,
bool aPersistentStateRequired) override
{
mCallback = aCallback;
}

View File

@ -1,172 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "GMPAudioDecoderChild.h"
#include "GMPContentChild.h"
#include "GMPAudioHost.h"
#include "mozilla/Unused.h"
#include <stdio.h>
namespace mozilla {
namespace gmp {
GMPAudioDecoderChild::GMPAudioDecoderChild(GMPContentChild* aPlugin)
: mPlugin(aPlugin)
, mAudioDecoder(nullptr)
{
MOZ_ASSERT(mPlugin);
}
GMPAudioDecoderChild::~GMPAudioDecoderChild()
{
}
void
GMPAudioDecoderChild::Init(GMPAudioDecoder* aDecoder)
{
MOZ_ASSERT(aDecoder, "Cannot initialize Audio decoder child without a Audio decoder!");
mAudioDecoder = aDecoder;
}
GMPAudioHostImpl&
GMPAudioDecoderChild::Host()
{
return mAudioHost;
}
void
GMPAudioDecoderChild::Decoded(GMPAudioSamples* aDecodedSamples)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
if (!aDecodedSamples) {
MOZ_CRASH("Not given decoded audio samples!");
}
GMPAudioDecodedSampleData samples;
samples.mData().AppendElements((int16_t*)aDecodedSamples->Buffer(),
aDecodedSamples->Size() / sizeof(int16_t));
samples.mTimeStamp() = aDecodedSamples->TimeStamp();
samples.mChannelCount() = aDecodedSamples->Channels();
samples.mSamplesPerSecond() = aDecodedSamples->Rate();
Unused << SendDecoded(samples);
aDecodedSamples->Destroy();
}
void
GMPAudioDecoderChild::InputDataExhausted()
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
Unused << SendInputDataExhausted();
}
void
GMPAudioDecoderChild::DrainComplete()
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
Unused << SendDrainComplete();
}
void
GMPAudioDecoderChild::ResetComplete()
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
Unused << SendResetComplete();
}
void
GMPAudioDecoderChild::Error(GMPErr aError)
{
MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current());
Unused << SendError(aError);
}
mozilla::ipc::IPCResult
GMPAudioDecoderChild::RecvInitDecode(const GMPAudioCodecData& a)
{
MOZ_ASSERT(mAudioDecoder);
if (!mAudioDecoder) {
return IPC_FAIL_NO_REASON(this);
}
GMPAudioCodec codec;
codec.mCodecType = a.mCodecType();
codec.mChannelCount = a.mChannelCount();
codec.mBitsPerChannel = a.mBitsPerChannel();
codec.mSamplesPerSecond = a.mSamplesPerSecond();
codec.mExtraData = a.mExtraData().Elements();
codec.mExtraDataLen = a.mExtraData().Length();
// Ignore any return code. It is OK for this to fail without killing the process.
mAudioDecoder->InitDecode(codec, this);
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPAudioDecoderChild::RecvDecode(const GMPAudioEncodedSampleData& aEncodedSamples)
{
if (!mAudioDecoder) {
return IPC_FAIL_NO_REASON(this);
}
GMPAudioSamples* samples = new GMPAudioSamplesImpl(aEncodedSamples);
// Ignore any return code. It is OK for this to fail without killing the process.
mAudioDecoder->Decode(samples);
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPAudioDecoderChild::RecvReset()
{
if (!mAudioDecoder) {
return IPC_FAIL_NO_REASON(this);
}
// Ignore any return code. It is OK for this to fail without killing the process.
mAudioDecoder->Reset();
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPAudioDecoderChild::RecvDrain()
{
if (!mAudioDecoder) {
return IPC_FAIL_NO_REASON(this);
}
// Ignore any return code. It is OK for this to fail without killing the process.
mAudioDecoder->Drain();
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPAudioDecoderChild::RecvDecodingComplete()
{
if (mAudioDecoder) {
// Ignore any return code. It is OK for this to fail without killing the process.
mAudioDecoder->DecodingComplete();
mAudioDecoder = nullptr;
}
mPlugin = nullptr;
Unused << Send__delete__(this);
return IPC_OK();
}
} // namespace gmp
} // namespace mozilla

View File

@ -1,51 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef GMPAudioDecoderChild_h_
#define GMPAudioDecoderChild_h_
#include "mozilla/gmp/PGMPAudioDecoderChild.h"
#include "gmp-audio-decode.h"
#include "GMPAudioHost.h"
namespace mozilla {
namespace gmp {
class GMPContentChild;
class GMPAudioDecoderChild : public PGMPAudioDecoderChild,
public GMPAudioDecoderCallback
{
public:
explicit GMPAudioDecoderChild(GMPContentChild* aPlugin);
virtual ~GMPAudioDecoderChild();
void Init(GMPAudioDecoder* aDecoder);
GMPAudioHostImpl& Host();
// GMPAudioDecoderCallback
void Decoded(GMPAudioSamples* aEncodedSamples) override;
void InputDataExhausted() override;
void DrainComplete() override;
void ResetComplete() override;
void Error(GMPErr aError) override;
private:
// PGMPAudioDecoderChild
mozilla::ipc::IPCResult RecvInitDecode(const GMPAudioCodecData& codecSettings) override;
mozilla::ipc::IPCResult RecvDecode(const GMPAudioEncodedSampleData& input) override;
mozilla::ipc::IPCResult RecvReset() override;
mozilla::ipc::IPCResult RecvDrain() override;
mozilla::ipc::IPCResult RecvDecodingComplete() override;
GMPContentChild* mPlugin;
GMPAudioDecoder* mAudioDecoder;
GMPAudioHostImpl mAudioHost;
};
} // namespace gmp
} // namespace mozilla
#endif // GMPAudioDecoderChild_h_

View File

@ -1,369 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "GMPAudioDecoderParent.h"
#include "GMPContentParent.h"
#include <stdio.h>
#include "mozilla/Unused.h"
#include "GMPMessageUtils.h"
#include "nsThreadUtils.h"
#include "mozilla/Logging.h"
namespace mozilla {
#ifdef LOG
#undef LOG
#endif
extern LogModule* GetGMPLog();
#define LOGV(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Verbose, msg)
#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg)
#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg)
namespace gmp {
GMPAudioDecoderParent::GMPAudioDecoderParent(GMPContentParent* aPlugin)
: mIsOpen(false)
, mShuttingDown(false)
, mActorDestroyed(false)
, mIsAwaitingResetComplete(false)
, mIsAwaitingDrainComplete(false)
, mPlugin(aPlugin)
, mCallback(nullptr)
{
MOZ_ASSERT(mPlugin);
}
GMPAudioDecoderParent::~GMPAudioDecoderParent()
{
}
nsresult
GMPAudioDecoderParent::InitDecode(GMPAudioCodecType aCodecType,
uint32_t aChannelCount,
uint32_t aBitsPerChannel,
uint32_t aSamplesPerSecond,
nsTArray<uint8_t>& aExtraData,
GMPAudioDecoderCallbackProxy* aCallback)
{
LOGD(("GMPAudioDecoderParent[%p]::InitDecode()", this));
if (mIsOpen) {
NS_WARNING("Trying to re-init an in-use GMP audio decoder!");
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (!aCallback) {
return NS_ERROR_FAILURE;
}
mCallback = aCallback;
GMPAudioCodecData data;
data.mCodecType() = aCodecType;
data.mChannelCount() = aChannelCount;
data.mBitsPerChannel() = aBitsPerChannel;
data.mSamplesPerSecond() = aSamplesPerSecond;
data.mExtraData() = aExtraData;
if (!SendInitDecode(data)) {
return NS_ERROR_FAILURE;
}
mIsOpen = true;
// Async IPC, we don't have access to a return value.
return NS_OK;
}
nsresult
GMPAudioDecoderParent::Decode(GMPAudioSamplesImpl& aEncodedSamples)
{
LOGV(("GMPAudioDecoderParent[%p]::Decode() timestamp=%lld",
this, aEncodedSamples.TimeStamp()));
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP Audio decoder!");
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
GMPAudioEncodedSampleData samples;
aEncodedSamples.RelinquishData(samples);
if (!SendDecode(samples)) {
return NS_ERROR_FAILURE;
}
// Async IPC, we don't have access to a return value.
return NS_OK;
}
nsresult
GMPAudioDecoderParent::Reset()
{
LOGD(("GMPAudioDecoderParent[%p]::Reset()", this));
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP Audio decoder!");
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (!SendReset()) {
return NS_ERROR_FAILURE;
}
mIsAwaitingResetComplete = true;
// Async IPC, we don't have access to a return value.
return NS_OK;
}
nsresult
GMPAudioDecoderParent::Drain()
{
LOGD(("GMPAudioDecoderParent[%p]::Drain()", this));
if (!mIsOpen) {
NS_WARNING("Trying to use a dead GMP Audio decoder!");
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (!SendDrain()) {
return NS_ERROR_FAILURE;
}
mIsAwaitingDrainComplete = true;
// Async IPC, we don't have access to a return value.
return NS_OK;
}
// Note: Consider keeping ActorDestroy sync'd up when making changes here.
nsresult
GMPAudioDecoderParent::Close()
{
LOGD(("GMPAudioDecoderParent[%p]::Close()", this));
MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread());
// Ensure if we've received a Close while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the close. This seems unlikely to happen, but better to be careful.
UnblockResetAndDrain();
// Consumer is done with us; we can shut down. No more callbacks should
// be made to mCallback. Note: do this before Shutdown()!
mCallback = nullptr;
// Let Shutdown mark us as dead so it knows if we had been alive
// In case this is the last reference
RefPtr<GMPAudioDecoderParent> kungfudeathgrip(this);
Release();
Shutdown();
return NS_OK;
}
// Note: Consider keeping ActorDestroy sync'd up when making changes here.
nsresult
GMPAudioDecoderParent::Shutdown()
{
LOGD(("GMPAudioDecoderParent[%p]::Shutdown()", this));
MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread());
if (mShuttingDown) {
return NS_OK;
}
mShuttingDown = true;
// Ensure if we've received a shutdown while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the shutdown.
UnblockResetAndDrain();
// Notify client we're gone! Won't occur after Close()
if (mCallback) {
mCallback->Terminated();
mCallback = nullptr;
}
mIsOpen = false;
if (!mActorDestroyed) {
Unused << SendDecodingComplete();
}
return NS_OK;
}
// Note: Keep this sync'd up with DecodingComplete
void
GMPAudioDecoderParent::ActorDestroy(ActorDestroyReason aWhy)
{
LOGD(("GMPAudioDecoderParent[%p]::ActorDestroy(reason=%d)", this, aWhy));
mIsOpen = false;
mActorDestroyed = true;
// Ensure if we've received a destroy while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the error.
UnblockResetAndDrain();
if (mCallback) {
// May call Close() (and Shutdown()) immediately or with a delay
mCallback->Terminated();
mCallback = nullptr;
}
if (mPlugin) {
// Ignore any return code. It is OK for this to fail without killing the process.
mPlugin->AudioDecoderDestroyed(this);
mPlugin = nullptr;
}
MaybeDisconnect(aWhy == AbnormalShutdown);
}
mozilla::ipc::IPCResult
GMPAudioDecoderParent::RecvDecoded(const GMPAudioDecodedSampleData& aDecoded)
{
LOGV(("GMPAudioDecoderParent[%p]::RecvDecoded() timestamp=%lld",
this, aDecoded.mTimeStamp()));
if (!mCallback) {
return IPC_FAIL_NO_REASON(this);
}
mCallback->Decoded(aDecoded.mData(),
aDecoded.mTimeStamp(),
aDecoded.mChannelCount(),
aDecoded.mSamplesPerSecond());
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPAudioDecoderParent::RecvInputDataExhausted()
{
LOGV(("GMPAudioDecoderParent[%p]::RecvInputDataExhausted()", this));
if (!mCallback) {
return IPC_FAIL_NO_REASON(this);
}
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->InputDataExhausted();
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPAudioDecoderParent::RecvDrainComplete()
{
LOGD(("GMPAudioDecoderParent[%p]::RecvDrainComplete()", this));
if (!mCallback) {
return IPC_FAIL_NO_REASON(this);
}
if (!mIsAwaitingDrainComplete) {
return IPC_OK();
}
mIsAwaitingDrainComplete = false;
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->DrainComplete();
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPAudioDecoderParent::RecvResetComplete()
{
LOGD(("GMPAudioDecoderParent[%p]::RecvResetComplete()", this));
if (!mCallback) {
return IPC_FAIL_NO_REASON(this);
}
if (!mIsAwaitingResetComplete) {
return IPC_OK();
}
mIsAwaitingResetComplete = false;
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->ResetComplete();
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPAudioDecoderParent::RecvError(const GMPErr& aError)
{
LOGD(("GMPAudioDecoderParent[%p]::RecvError(error=%d)", this, aError));
if (!mCallback) {
return IPC_FAIL_NO_REASON(this);
}
// Ensure if we've received an error while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the error.
UnblockResetAndDrain();
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->Error(aError);
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPAudioDecoderParent::RecvShutdown()
{
LOGD(("GMPAudioDecoderParent[%p]::RecvShutdown()", this));
Shutdown();
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPAudioDecoderParent::Recv__delete__()
{
LOGD(("GMPAudioDecoderParent[%p]::Recv__delete__()", this));
if (mPlugin) {
// Ignore any return code. It is OK for this to fail without killing the process.
mPlugin->AudioDecoderDestroyed(this);
mPlugin = nullptr;
}
return IPC_OK();
}
void
GMPAudioDecoderParent::UnblockResetAndDrain()
{
LOGD(("GMPAudioDecoderParent[%p]::UnblockResetAndDrain()", this));
if (!mCallback) {
MOZ_ASSERT(!mIsAwaitingResetComplete);
MOZ_ASSERT(!mIsAwaitingDrainComplete);
return;
}
if (mIsAwaitingResetComplete) {
mIsAwaitingResetComplete = false;
mCallback->ResetComplete();
}
if (mIsAwaitingDrainComplete) {
mIsAwaitingDrainComplete = false;
mCallback->DrainComplete();
}
}
} // namespace gmp
} // namespace mozilla

View File

@ -1,72 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef GMPAudioDecoderParent_h_
#define GMPAudioDecoderParent_h_
#include "mozilla/RefPtr.h"
#include "gmp-audio-decode.h"
#include "gmp-audio-codec.h"
#include "mozilla/gmp/PGMPAudioDecoderParent.h"
#include "GMPMessageUtils.h"
#include "GMPAudioDecoderProxy.h"
#include "GMPCrashHelperHolder.h"
namespace mozilla {
namespace gmp {
class GMPContentParent;
class GMPAudioDecoderParent final : public GMPAudioDecoderProxy
, public PGMPAudioDecoderParent
, public GMPCrashHelperHolder
{
public:
NS_INLINE_DECL_REFCOUNTING(GMPAudioDecoderParent)
explicit GMPAudioDecoderParent(GMPContentParent *aPlugin);
nsresult Shutdown();
// GMPAudioDecoderProxy
nsresult InitDecode(GMPAudioCodecType aCodecType,
uint32_t aChannelCount,
uint32_t aBitsPerChannel,
uint32_t aSamplesPerSecond,
nsTArray<uint8_t>& aExtraData,
GMPAudioDecoderCallbackProxy* aCallback) override;
nsresult Decode(GMPAudioSamplesImpl& aInput) override;
nsresult Reset() override;
nsresult Drain() override;
nsresult Close() override;
private:
~GMPAudioDecoderParent();
// PGMPAudioDecoderParent
void ActorDestroy(ActorDestroyReason aWhy) override;
mozilla::ipc::IPCResult RecvDecoded(const GMPAudioDecodedSampleData& aDecoded) override;
mozilla::ipc::IPCResult RecvInputDataExhausted() override;
mozilla::ipc::IPCResult RecvDrainComplete() override;
mozilla::ipc::IPCResult RecvResetComplete() override;
mozilla::ipc::IPCResult RecvError(const GMPErr& aError) override;
mozilla::ipc::IPCResult RecvShutdown() override;
mozilla::ipc::IPCResult Recv__delete__() override;
void UnblockResetAndDrain();
bool mIsOpen;
bool mShuttingDown;
bool mActorDestroyed;
bool mIsAwaitingResetComplete;
bool mIsAwaitingDrainComplete;
RefPtr<GMPContentParent> mPlugin;
GMPAudioDecoderCallbackProxy* mCallback;
};
} // namespace gmp
} // namespace mozilla
#endif // GMPAudioDecoderParent_h_

View File

@ -1,48 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef GMPAudioDecoderProxy_h_
#define GMPAudioDecoderProxy_h_
#include "GMPCallbackBase.h"
#include "gmp-audio-codec.h"
#include "GMPAudioHost.h"
#include "nsTArray.h"
#include "mozilla/gmp/GMPTypes.h"
class GMPAudioDecoderCallbackProxy : public GMPCallbackBase {
public:
virtual ~GMPAudioDecoderCallbackProxy() {}
// Note: aChannelCount and aSamplesPerSecond may not be consistent from
// one invocation to the next.
virtual void Decoded(const nsTArray<int16_t>& aPCM,
uint64_t aTimeStamp,
uint32_t aChannelCount,
uint32_t aSamplesPerSecond) = 0;
virtual void InputDataExhausted() = 0;
virtual void DrainComplete() = 0;
virtual void ResetComplete() = 0;
virtual void Error(GMPErr aError) = 0;
};
class GMPAudioDecoderProxy {
public:
virtual ~GMPAudioDecoderProxy() {}
virtual nsresult InitDecode(GMPAudioCodecType aCodecType,
uint32_t aChannelCount,
uint32_t aBitsPerChannel,
uint32_t aSamplesPerSecond,
nsTArray<uint8_t>& aExtraData,
GMPAudioDecoderCallbackProxy* aCallback) = 0;
virtual nsresult Decode(mozilla::gmp::GMPAudioSamplesImpl& aSamples) = 0;
virtual nsresult Reset() = 0;
virtual nsresult Drain() = 0;
// Call to tell GMP/plugin the consumer will no longer use this
// interface/codec.
virtual nsresult Close() = 0;
};
#endif // GMPAudioDecoderProxy_h_

View File

@ -1,162 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "GMPAudioHost.h"
#include "gmp-audio-samples.h"
#include "gmp-errors.h"
#include "GMPEncryptedBufferDataImpl.h"
#include "MediaData.h"
namespace mozilla {
namespace gmp {
GMPAudioSamplesImpl::GMPAudioSamplesImpl(GMPAudioFormat aFormat)
: mFormat(aFormat)
, mTimeStamp(0)
, mChannels(0)
, mRate(0)
{
}
GMPAudioSamplesImpl::GMPAudioSamplesImpl(const GMPAudioEncodedSampleData& aData)
: mFormat(kGMPAudioEncodedSamples)
, mBuffer(aData.mData())
, mTimeStamp(aData.mTimeStamp())
, mChannels(aData.mChannelCount())
, mRate(aData.mSamplesPerSecond())
{
if (aData.mDecryptionData().mKeyId().Length() > 0) {
mCrypto = new GMPEncryptedBufferDataImpl(aData.mDecryptionData());
}
}
GMPAudioSamplesImpl::GMPAudioSamplesImpl(MediaRawData* aSample,
uint32_t aChannels,
uint32_t aRate)
: mFormat(kGMPAudioEncodedSamples)
, mTimeStamp(aSample->mTime)
, mChannels(aChannels)
, mRate(aRate)
{
mBuffer.AppendElements(aSample->Data(), aSample->Size());
if (aSample->mCrypto.mValid) {
mCrypto = new GMPEncryptedBufferDataImpl(aSample->mCrypto);
}
}
GMPAudioSamplesImpl::~GMPAudioSamplesImpl()
{
}
GMPAudioFormat
GMPAudioSamplesImpl::GetFormat()
{
return mFormat;
}
void
GMPAudioSamplesImpl::Destroy()
{
delete this;
}
GMPErr
GMPAudioSamplesImpl::SetBufferSize(uint32_t aSize)
{
mBuffer.SetLength(aSize);
return GMPNoErr;
}
uint32_t
GMPAudioSamplesImpl::Size()
{
return mBuffer.Length();
}
void
GMPAudioSamplesImpl::SetTimeStamp(uint64_t aTimeStamp)
{
mTimeStamp = aTimeStamp;
}
uint64_t
GMPAudioSamplesImpl::TimeStamp()
{
return mTimeStamp;
}
const uint8_t*
GMPAudioSamplesImpl::Buffer() const
{
return mBuffer.Elements();
}
uint8_t*
GMPAudioSamplesImpl::Buffer()
{
return mBuffer.Elements();
}
const GMPEncryptedBufferMetadata*
GMPAudioSamplesImpl::GetDecryptionData() const
{
return mCrypto;
}
void
GMPAudioSamplesImpl::InitCrypto(const CryptoSample& aCrypto)
{
if (!aCrypto.mValid) {
return;
}
mCrypto = new GMPEncryptedBufferDataImpl(aCrypto);
}
void
GMPAudioSamplesImpl::RelinquishData(GMPAudioEncodedSampleData& aData)
{
aData.mData() = Move(mBuffer);
aData.mTimeStamp() = TimeStamp();
if (mCrypto) {
mCrypto->RelinquishData(aData.mDecryptionData());
}
}
uint32_t
GMPAudioSamplesImpl::Channels() const
{
return mChannels;
}
void
GMPAudioSamplesImpl::SetChannels(uint32_t aChannels)
{
mChannels = aChannels;
}
uint32_t
GMPAudioSamplesImpl::Rate() const
{
return mRate;
}
void
GMPAudioSamplesImpl::SetRate(uint32_t aRate)
{
mRate = aRate;
}
GMPErr
GMPAudioHostImpl::CreateSamples(GMPAudioFormat aFormat,
GMPAudioSamples** aSamples)
{
*aSamples = new GMPAudioSamplesImpl(aFormat);
return GMPNoErr;
}
} // namespace gmp
} // namespace mozilla

View File

@ -1,71 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef GMPAudioHost_h_
#define GMPAudioHost_h_
#include "gmp-audio-host.h"
#include "gmp-audio-samples.h"
#include "nsTArray.h"
#include "gmp-decryption.h"
#include "nsAutoPtr.h"
#include "GMPEncryptedBufferDataImpl.h"
#include "mozilla/gmp/GMPTypes.h"
namespace mozilla {
class CryptoSample;
class MediaRawData;
namespace gmp {
class GMPAudioSamplesImpl : public GMPAudioSamples {
public:
explicit GMPAudioSamplesImpl(GMPAudioFormat aFormat);
explicit GMPAudioSamplesImpl(const GMPAudioEncodedSampleData& aData);
GMPAudioSamplesImpl(MediaRawData* aSample,
uint32_t aChannels,
uint32_t aRate);
virtual ~GMPAudioSamplesImpl();
GMPAudioFormat GetFormat() override;
void Destroy() override;
GMPErr SetBufferSize(uint32_t aSize) override;
uint32_t Size() override;
void SetTimeStamp(uint64_t aTimeStamp) override;
uint64_t TimeStamp() override;
const uint8_t* Buffer() const override;
uint8_t* Buffer() override;
const GMPEncryptedBufferMetadata* GetDecryptionData() const override;
void InitCrypto(const CryptoSample& aCrypto);
void RelinquishData(GMPAudioEncodedSampleData& aData);
uint32_t Channels() const override;
void SetChannels(uint32_t aChannels) override;
uint32_t Rate() const override;
void SetRate(uint32_t aRate) override;
private:
GMPAudioFormat mFormat;
nsTArray<uint8_t> mBuffer;
int64_t mTimeStamp;
nsAutoPtr<GMPEncryptedBufferDataImpl> mCrypto;
uint32_t mChannels;
uint32_t mRate;
};
class GMPAudioHostImpl : public GMPAudioHost
{
public:
GMPErr CreateSamples(GMPAudioFormat aFormat,
GMPAudioSamples** aSamples) override;
private:
};
} // namespace gmp
} // namespace mozilla
#endif // GMPAudioHost_h_

View File

@ -9,7 +9,6 @@
#include "GMPLoader.h"
#include "GMPVideoDecoderChild.h"
#include "GMPVideoEncoderChild.h"
#include "GMPAudioDecoderChild.h"
#include "GMPDecryptorChild.h"
#include "GMPVideoHost.h"
#include "nsDebugImpl.h"

View File

@ -5,7 +5,6 @@
#include "GMPContentChild.h"
#include "GMPChild.h"
#include "GMPAudioDecoderChild.h"
#include "GMPDecryptorChild.h"
#include "GMPVideoDecoderChild.h"
#include "GMPVideoEncoderChild.h"
@ -49,19 +48,6 @@ GMPContentChild::ProcessingError(Result aCode, const char* aReason)
mGMPChild->ProcessingError(aCode, aReason);
}
PGMPAudioDecoderChild*
GMPContentChild::AllocPGMPAudioDecoderChild()
{
return new GMPAudioDecoderChild(this);
}
bool
GMPContentChild::DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor)
{
delete aActor;
return true;
}
PGMPDecryptorChild*
GMPContentChild::AllocPGMPDecryptorChild()
{
@ -109,96 +95,6 @@ GMPContentChild::DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor)
return true;
}
// Adapts GMPDecryptor7 to the current GMPDecryptor version.
class GMPDecryptor7BackwardsCompat : public GMPDecryptor {
public:
explicit GMPDecryptor7BackwardsCompat(GMPDecryptor7* aDecryptorV7)
: mDecryptorV7(aDecryptorV7)
{
}
void Init(GMPDecryptorCallback* aCallback,
bool aDistinctiveIdentifierRequired,
bool aPersistentStateRequired) override
{
// Distinctive identifier and persistent state arguments not present
// in v7 interface.
mDecryptorV7->Init(aCallback);
}
void CreateSession(uint32_t aCreateSessionToken,
uint32_t aPromiseId,
const char* aInitDataType,
uint32_t aInitDataTypeSize,
const uint8_t* aInitData,
uint32_t aInitDataSize,
GMPSessionType aSessionType) override
{
mDecryptorV7->CreateSession(aCreateSessionToken,
aPromiseId,
aInitDataType,
aInitDataTypeSize,
aInitData,
aInitDataSize,
aSessionType);
}
void LoadSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) override
{
mDecryptorV7->LoadSession(aPromiseId, aSessionId, aSessionIdLength);
}
void UpdateSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aResponse,
uint32_t aResponseSize) override
{
mDecryptorV7->UpdateSession(aPromiseId,
aSessionId,
aSessionIdLength,
aResponse,
aResponseSize);
}
void CloseSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) override
{
mDecryptorV7->CloseSession(aPromiseId, aSessionId, aSessionIdLength);
}
void RemoveSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) override
{
mDecryptorV7->RemoveSession(aPromiseId, aSessionId, aSessionIdLength);
}
void SetServerCertificate(uint32_t aPromiseId,
const uint8_t* aServerCert,
uint32_t aServerCertSize) override
{
mDecryptorV7->SetServerCertificate(aPromiseId, aServerCert, aServerCertSize);
}
void Decrypt(GMPBuffer* aBuffer,
GMPEncryptedBufferMetadata* aMetadata) override
{
mDecryptorV7->Decrypt(aBuffer, aMetadata);
}
void DecryptingComplete() override
{
mDecryptorV7->DecryptingComplete();
delete this;
}
private:
GMPDecryptor7* mDecryptorV7;
};
mozilla::ipc::IPCResult
GMPContentChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor)
{
@ -207,38 +103,11 @@ GMPContentChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor)
void* ptr = nullptr;
GMPErr err = mGMPChild->GetAPI(GMP_API_DECRYPTOR, host, &ptr, aActor->Id());
GMPDecryptor* decryptor = nullptr;
if (GMP_SUCCEEDED(err) && ptr) {
decryptor = static_cast<GMPDecryptor*>(ptr);
} else if (err != GMPNoErr) {
// We Adapt the previous GMPDecryptor version to the current, so that
// Gecko thinks it's only talking to the current version. v7 differs
// from v9 in its Init() function arguments, and v9 has extra enumeration
// members at the end of the key status enumerations.
err = mGMPChild->GetAPI(GMP_API_DECRYPTOR_BACKWARDS_COMPAT, host, &ptr);
if (err != GMPNoErr || !ptr) {
return IPC_FAIL_NO_REASON(this);
}
decryptor = new GMPDecryptor7BackwardsCompat(static_cast<GMPDecryptor7*>(ptr));
}
child->Init(decryptor);
return IPC_OK();
}
mozilla::ipc::IPCResult
GMPContentChild::RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor)
{
auto vdc = static_cast<GMPAudioDecoderChild*>(aActor);
void* vd = nullptr;
GMPErr err = mGMPChild->GetAPI(GMP_API_AUDIO_DECODER, &vdc->Host(), &vd);
if (err != GMPNoErr || !vd) {
if (err != GMPNoErr || !ptr) {
NS_WARNING("GMPGetAPI call failed trying to construct decryptor.");
return IPC_FAIL_NO_REASON(this);
}
vdc->Init(static_cast<GMPAudioDecoder*>(vd));
child->Init(static_cast<GMPDecryptor*>(ptr));
return IPC_OK();
}
@ -282,12 +151,6 @@ void
GMPContentChild::CloseActive()
{
// Invalidate and remove any remaining API objects.
const ManagedContainer<PGMPAudioDecoderChild>& audioDecoders =
ManagedPGMPAudioDecoderChild();
for (auto iter = audioDecoders.ConstIter(); !iter.Done(); iter.Next()) {
iter.Get()->GetKey()->SendShutdown();
}
const ManagedContainer<PGMPDecryptorChild>& decryptors =
ManagedPGMPDecryptorChild();
for (auto iter = decryptors.ConstIter(); !iter.Done(); iter.Next()) {
@ -310,8 +173,7 @@ GMPContentChild::CloseActive()
bool
GMPContentChild::IsUsed()
{
return !ManagedPGMPAudioDecoderChild().IsEmpty() ||
!ManagedPGMPDecryptorChild().IsEmpty() ||
return !ManagedPGMPDecryptorChild().IsEmpty() ||
!ManagedPGMPVideoDecoderChild().IsEmpty() ||
!ManagedPGMPVideoEncoderChild().IsEmpty();
}

View File

@ -23,14 +23,10 @@ public:
MessageLoop* GMPMessageLoop();
mozilla::ipc::IPCResult RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) override;
mozilla::ipc::IPCResult RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) override;
mozilla::ipc::IPCResult RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor, const uint32_t& aDecryptorId) override;
mozilla::ipc::IPCResult RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) override;
PGMPAudioDecoderChild* AllocPGMPAudioDecoderChild() override;
bool DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) override;
PGMPDecryptorChild* AllocPGMPDecryptorChild() override;
bool DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) override;

View File

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GMPContentParent.h"
#include "GMPAudioDecoderParent.h"
#include "GMPDecryptorParent.h"
#include "GMPParent.h"
#include "GMPServiceChild.h"
@ -66,8 +65,7 @@ private:
void
GMPContentParent::ActorDestroy(ActorDestroyReason aWhy)
{
MOZ_ASSERT(mAudioDecoders.IsEmpty() &&
mDecryptors.IsEmpty() &&
MOZ_ASSERT(mDecryptors.IsEmpty() &&
mVideoDecoders.IsEmpty() &&
mVideoEncoders.IsEmpty());
NS_DispatchToCurrentThread(new ReleaseGMPContentParent(this));
@ -79,15 +77,6 @@ GMPContentParent::CheckThread()
MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
}
void
GMPContentParent::AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder)
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
MOZ_ALWAYS_TRUE(mAudioDecoders.RemoveElement(aDecoder));
CloseIfUnused();
}
void
GMPContentParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder)
{
@ -135,8 +124,7 @@ GMPContentParent::RemoveCloseBlocker()
void
GMPContentParent::CloseIfUnused()
{
if (mAudioDecoders.IsEmpty() &&
mDecryptors.IsEmpty() &&
if (mDecryptors.IsEmpty() &&
mVideoDecoders.IsEmpty() &&
mVideoEncoders.IsEmpty() &&
mCloseBlockerCount == 0) {
@ -192,23 +180,6 @@ GMPContentParent::GMPThread()
return mGMPThread;
}
nsresult
GMPContentParent::GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD)
{
PGMPAudioDecoderParent* pvap = SendPGMPAudioDecoderConstructor();
if (!pvap) {
return NS_ERROR_FAILURE;
}
GMPAudioDecoderParent* vap = static_cast<GMPAudioDecoderParent*>(pvap);
// This addref corresponds to the Proxy pointer the consumer is returned.
// It's dropped by calling Close() on the interface.
NS_ADDREF(vap);
*aGMPAD = vap;
mAudioDecoders.AppendElement(vap);
return NS_OK;
}
nsresult
GMPContentParent::GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD,
uint32_t aDecryptorId)
@ -294,21 +265,5 @@ GMPContentParent::DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor)
return true;
}
PGMPAudioDecoderParent*
GMPContentParent::AllocPGMPAudioDecoderParent()
{
GMPAudioDecoderParent* vdp = new GMPAudioDecoderParent(this);
NS_ADDREF(vdp);
return vdp;
}
bool
GMPContentParent::DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor)
{
GMPAudioDecoderParent* vdp = static_cast<GMPAudioDecoderParent*>(aActor);
NS_RELEASE(vdp);
return true;
}
} // namespace gmp
} // namespace mozilla

View File

@ -13,7 +13,6 @@
namespace mozilla {
namespace gmp {
class GMPAudioDecoderParent;
class GMPDecryptorParent;
class GMPParent;
class GMPVideoDecoderParent;
@ -37,9 +36,6 @@ public:
nsresult GetGMPDecryptor(GMPDecryptorParent** aGMPKS);
void DecryptorDestroyed(GMPDecryptorParent* aSession);
nsresult GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD);
void AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder);
nsIThread* GMPThread();
// GMPSharedMem
@ -96,9 +92,6 @@ private:
PGMPDecryptorParent* AllocPGMPDecryptorParent() override;
bool DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor) override;
PGMPAudioDecoderParent* AllocPGMPAudioDecoderParent() override;
bool DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor) override;
void CloseIfUnused();
// Needed because NewRunnableMethod tried to use the class that the method
// lives on to store the receiver, but PGMPContentParent isn't refcounted.
@ -110,7 +103,6 @@ private:
nsTArray<RefPtr<GMPVideoDecoderParent>> mVideoDecoders;
nsTArray<RefPtr<GMPVideoEncoderParent>> mVideoEncoders;
nsTArray<RefPtr<GMPDecryptorParent>> mDecryptors;
nsTArray<RefPtr<GMPAudioDecoderParent>> mAudioDecoders;
nsCOMPtr<nsIThread> mGMPThread;
RefPtr<GMPParent> mParent;
nsCString mDisplayName;

View File

@ -24,8 +24,8 @@ namespace gmp {
class GMPLoaderImpl : public GMPLoader {
public:
explicit GMPLoaderImpl(SandboxStarter* aStarter)
: mSandboxStarter(aStarter)
explicit GMPLoaderImpl(UniquePtr<SandboxStarter> aStarter)
: mSandboxStarter(Move(aStarter))
, mAdapter(nullptr)
{}
~GMPLoaderImpl() override = default;
@ -49,12 +49,12 @@ public:
#endif
private:
SandboxStarter* mSandboxStarter;
UniquePtr<SandboxStarter> mSandboxStarter;
UniquePtr<GMPAdapter> mAdapter;
};
UniquePtr<GMPLoader> CreateGMPLoader(SandboxStarter* aStarter) {
return MakeUnique<GMPLoaderImpl>(aStarter);
UniquePtr<GMPLoader> CreateGMPLoader(UniquePtr<SandboxStarter> aStarter) {
return MakeUnique<GMPLoaderImpl>(Move(aStarter));
}
class PassThroughGMPAdapter : public GMPAdapter {

View File

@ -105,7 +105,7 @@ public:
// On Desktop, this function resides in plugin-container.
// On Mobile, this function resides in XUL.
UniquePtr<GMPLoader> CreateGMPLoader(SandboxStarter* aStarter);
UniquePtr<GMPLoader> CreateGMPLoader(UniquePtr<SandboxStarter> aStarter);
} // namespace gmp
} // namespace mozilla

View File

@ -8,7 +8,6 @@
#include "gmp-video-codec.h"
#include "gmp-video-frame-encoded.h"
#include "gmp-audio-codec.h"
#include "gmp-decryption.h"
namespace IPC {
@ -75,13 +74,6 @@ struct ParamTraits<GMPSessionType>
kGMPSessionInvalid>
{};
template <>
struct ParamTraits<GMPAudioCodecType>
: public ContiguousEnumSerializer<GMPAudioCodecType,
kGMPAudioCodecAAC,
kGMPAudioCodecInvalid>
{};
template <>
struct ParamTraits<GMPVideoCodecComplexity>
: public ContiguousEnumSerializer<GMPVideoCodecComplexity,

View File

@ -884,12 +884,6 @@ GMPParent::ReadGMPInfoFile(nsIFile* aFile)
}
}
// We support the current GMPDecryptor version, and the previous.
// We Adapt the previous to the current in the GMPContentChild.
if (cap.mAPIName.EqualsLiteral(GMP_API_DECRYPTOR_BACKWARDS_COMPAT)) {
cap.mAPIName.AssignLiteral(GMP_API_DECRYPTOR);
}
if (cap.mAPIName.EqualsLiteral(GMP_API_DECRYPTOR)) {
mCanDecrypt = true;
@ -901,15 +895,6 @@ GMPParent::ReadGMPInfoFile(nsIFile* aFile)
return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
#endif
#ifdef XP_WIN
// Adobe GMP doesn't work without SSE2. Check the tags to see if
// the decryptor is for the Adobe GMP, and refuse to load it if
// SSE2 isn't supported.
if (cap.mAPITags.Contains(kEMEKeySystemPrimetime) &&
!mozilla::supports_sse2()) {
return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
#endif // XP_WIN
}
mCapabilities.AppendElement(Move(cap));

View File

@ -8,7 +8,6 @@
#include "GMPProcessParent.h"
#include "GMPServiceParent.h"
#include "GMPAudioDecoderParent.h"
#include "GMPDecryptorParent.h"
#include "GMPVideoDecoderParent.h"
#include "GMPVideoEncoderParent.h"

View File

@ -22,7 +22,6 @@
#include "nsIConsoleService.h"
#include "mozilla/Unused.h"
#include "GMPDecryptorParent.h"
#include "GMPAudioDecoderParent.h"
#include "nsComponentManagerUtils.h"
#include "runnable_utils.h"
#include "VideoUtils.h"
@ -307,42 +306,6 @@ GeckoMediaPluginService::GetAbstractGMPThread()
return mAbstractGMPThread;
}
NS_IMETHODIMP
GeckoMediaPluginService::GetGMPAudioDecoder(GMPCrashHelper* aHelper,
nsTArray<nsCString>* aTags,
const nsACString& aNodeId,
UniquePtr<GetGMPAudioDecoderCallback>&& aCallback)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
NS_ENSURE_ARG(aCallback);
if (mShuttingDownOnGMPThread) {
return NS_ERROR_FAILURE;
}
GetGMPAudioDecoderCallback* rawCallback = aCallback.release();
RefPtr<AbstractThread> thread(GetAbstractGMPThread());
RefPtr<GMPCrashHelper> helper(aHelper);
GetContentParent(aHelper, aNodeId, NS_LITERAL_CSTRING(GMP_API_AUDIO_DECODER), *aTags)
->Then(thread, __func__,
[rawCallback, helper](RefPtr<GMPContentParent::CloseBlocker> wrapper) {
RefPtr<GMPContentParent> parent = wrapper->mParent;
UniquePtr<GetGMPAudioDecoderCallback> callback(rawCallback);
GMPAudioDecoderParent* actor = nullptr;
if (parent && NS_SUCCEEDED(parent->GetGMPAudioDecoder(&actor))) {
actor->SetCrashHelper(helper);
}
callback->Done(actor);
},
[rawCallback] {
UniquePtr<GetGMPAudioDecoderCallback> callback(rawCallback);
callback->Done(nullptr);
});
return NS_OK;
}
NS_IMETHODIMP
GeckoMediaPluginService::GetDecryptingGMPVideoDecoder(GMPCrashHelper* aHelper,
nsTArray<nsCString>* aTags,

View File

@ -59,11 +59,6 @@ public:
const nsACString& aNodeId,
UniquePtr<GetGMPVideoEncoderCallback>&& aCallback)
override;
NS_IMETHOD GetGMPAudioDecoder(GMPCrashHelper* aHelper,
nsTArray<nsCString>* aTags,
const nsACString& aNodeId,
UniquePtr<GetGMPAudioDecoderCallback>&& aCallback)
override;
NS_IMETHOD GetGMPDecryptor(GMPCrashHelper* aHelper,
nsTArray<nsCString>* aTags,
const nsACString& aNodeId,

View File

@ -23,7 +23,6 @@
#include "nsIConsoleService.h"
#include "mozilla/Unused.h"
#include "GMPDecryptorParent.h"
#include "GMPAudioDecoderParent.h"
#include "nsComponentManagerUtils.h"
#include "runnable_utils.h"
#include "VideoUtils.h"
@ -172,70 +171,6 @@ CloneAndAppend(nsIFile* aFile, const nsAString& aDir)
return f.forget();
}
static void
MoveAndOverwrite(nsIFile* aOldParentDir,
nsIFile* aNewParentDir,
const nsAString& aSubDir)
{
nsresult rv;
nsCOMPtr<nsIFile> srcDir(CloneAndAppend(aOldParentDir, aSubDir));
if (NS_WARN_IF(!srcDir)) {
return;
}
if (!FileExists(srcDir)) {
// No sub-directory to be migrated.
return;
}
// Ensure destination parent directory exists.
rv = aNewParentDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsIFile> dstDir(CloneAndAppend(aNewParentDir, aSubDir));
if (FileExists(dstDir)) {
// We must have migrated before already, and then ran an old version
// of Gecko again which created storage at the old location. Overwrite
// the previously migrated storage.
rv = dstDir->Remove(true);
if (NS_WARN_IF(NS_FAILED(rv))) {
// MoveTo will fail.
return;
}
}
rv = srcDir->MoveTo(aNewParentDir, EmptyString());
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
}
static void
MigratePreGecko42StorageDir(nsIFile* aOldStorageDir,
nsIFile* aNewStorageDir)
{
MoveAndOverwrite(aOldStorageDir, aNewStorageDir, NS_LITERAL_STRING("id"));
MoveAndOverwrite(aOldStorageDir, aNewStorageDir, NS_LITERAL_STRING("storage"));
}
static void
MigratePreGecko45StorageDir(nsIFile* aStorageDirBase)
{
nsCOMPtr<nsIFile> adobeStorageDir(CloneAndAppend(aStorageDirBase, NS_LITERAL_STRING("gmp-eme-adobe")));
if (NS_WARN_IF(!adobeStorageDir)) {
return;
}
// The base storage dir in pre-45 contained "id" and "storage" subdirs.
// We assume all storage in the base storage dir that aren't known to GMP
// storage are records for the Adobe GMP.
MoveAndOverwrite(aStorageDirBase, adobeStorageDir, NS_LITERAL_STRING("id"));
MoveAndOverwrite(aStorageDirBase, adobeStorageDir, NS_LITERAL_STRING("storage"));
}
static nsresult
GMPPlatformString(nsAString& aOutPlatform)
{
@ -322,19 +257,6 @@ GeckoMediaPluginServiceParent::InitStorage()
return rv;
}
// Prior to 42, GMP storage was stored in $profileDir/gmp/. After 42, it's
// stored in $profileDir/gmp/$platform/. So we must migrate any old records
// from the old location to the new location, for forwards compatibility.
MigratePreGecko42StorageDir(gmpDirWithoutPlatform, mStorageBaseDir);
// Prior to 45, GMP storage was not separated by plugin. In 45 and after,
// it's stored in $profile/gmp/$platform/$gmpName. So we must migrate old
// records from the old location to the new location, for forwards
// compatibility. We assume all directories in the base storage dir that
// aren't known to GMP storage are records for the Adobe GMP, since it
// was first.
MigratePreGecko45StorageDir(mStorageBaseDir);
return GeckoMediaPluginService::Init();
}

View File

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
using GMPBufferType from "gmp-video-codec.h";
using GMPAudioCodecType from "gmp-audio-codec.h";
using GMPMediaKeyStatus from "gmp-decryption.h";
namespace mozilla {
@ -50,33 +49,6 @@ struct GMPVideoi420FrameData
uint64_t mDuration; // microseconds
};
struct GMPAudioCodecData
{
GMPAudioCodecType mCodecType;
uint32_t mChannelCount;
uint32_t mBitsPerChannel;
uint32_t mSamplesPerSecond;
uint8_t[] mExtraData;
};
struct GMPAudioEncodedSampleData
{
uint8_t[] mData;
uint64_t mTimeStamp; // microseconds.
GMPDecryptionData mDecryptionData;
uint32_t mChannelCount;
uint32_t mSamplesPerSecond;
};
struct GMPAudioDecodedSampleData
{
int16_t[] mData;
uint64_t mTimeStamp; // microseconds.
uint32_t mChannelCount;
uint32_t mSamplesPerSecond;
};
struct GMPKeyInformation {
uint8_t[] keyId;
GMPMediaKeyStatus status;

View File

@ -1,37 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
include protocol PGMPContent;
include GMPTypes;
using GMPCodecSpecificInfo from "gmp-audio-codec.h";
using GMPErr from "gmp-errors.h";
include "GMPMessageUtils.h";
namespace mozilla {
namespace gmp {
async protocol PGMPAudioDecoder
{
manager PGMPContent;
child:
async InitDecode(GMPAudioCodecData aCodecSettings);
async Decode(GMPAudioEncodedSampleData aInput);
async Reset();
async Drain();
async DecodingComplete();
parent:
async __delete__();
async Decoded(GMPAudioDecodedSampleData aDecoded);
async InputDataExhausted();
async DrainComplete();
async ResetComplete();
async Error(GMPErr aErr);
async Shutdown();
};
} // namespace gmp
} // namespace mozilla

View File

@ -8,7 +8,6 @@ include protocol PGMPService;
include protocol PGMPVideoDecoder;
include protocol PGMPVideoEncoder;
include protocol PGMPDecryptor;
include protocol PGMPAudioDecoder;
namespace mozilla {
namespace gmp {
@ -17,13 +16,11 @@ intr protocol PGMPContent
{
bridges PGMPService, PGMP;
manages PGMPAudioDecoder;
manages PGMPDecryptor;
manages PGMPVideoDecoder;
manages PGMPVideoEncoder;
child:
async PGMPAudioDecoder();
async PGMPDecryptor();
async PGMPVideoDecoder(uint32_t aDecryptorId);
async PGMPVideoEncoder();

View File

@ -1,43 +0,0 @@
/*
* Copyright 2013, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GMP_AUDIO_CODEC_h_
#define GMP_AUDIO_CODEC_h_
#include <stdint.h>
enum GMPAudioCodecType
{
kGMPAudioCodecAAC,
kGMPAudioCodecVorbis,
kGMPAudioCodecInvalid // Should always be last.
};
struct GMPAudioCodec
{
GMPAudioCodecType mCodecType;
uint32_t mChannelCount;
uint32_t mBitsPerChannel;
uint32_t mSamplesPerSecond;
// Codec extra data, such as vorbis setup header, or
// AAC AudioSpecificConfig.
// These are null/0 if not externally negotiated
const uint8_t* mExtraData;
uint32_t mExtraDataLen;
};
#endif // GMP_AUDIO_CODEC_h_

View File

@ -1,84 +0,0 @@
/*
* Copyright 2013, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GMP_AUDIO_DECODE_h_
#define GMP_AUDIO_DECODE_h_
#include "gmp-errors.h"
#include "gmp-audio-samples.h"
#include "gmp-audio-codec.h"
#include <stdint.h>
// ALL METHODS MUST BE CALLED ON THE MAIN THREAD
class GMPAudioDecoderCallback
{
public:
virtual ~GMPAudioDecoderCallback() {}
virtual void Decoded(GMPAudioSamples* aDecodedSamples) = 0;
virtual void InputDataExhausted() = 0;
virtual void DrainComplete() = 0;
virtual void ResetComplete() = 0;
// Called when the decoder encounters a catestrophic error and cannot
// continue. Gecko will not send any more input for decoding.
virtual void Error(GMPErr aError) = 0;
};
#define GMP_API_AUDIO_DECODER "decode-audio"
// Audio decoding for a single stream. A GMP may be asked to create multiple
// decoders concurrently.
//
// API name macro: GMP_API_AUDIO_DECODER
// Host API: GMPAudioHost
//
// ALL METHODS MUST BE CALLED ON THE MAIN THREAD
class GMPAudioDecoder
{
public:
virtual ~GMPAudioDecoder() {}
// aCallback: Subclass should retain reference to it until DecodingComplete
// is called. Do not attempt to delete it, host retains ownership.
// TODO: Pass AudioHost so decoder can create GMPAudioEncodedFrame objects?
virtual void InitDecode(const GMPAudioCodec& aCodecSettings,
GMPAudioDecoderCallback* aCallback) = 0;
// Decode encoded audio frames (as a part of an audio stream). The decoded
// frames must be returned to the user through the decode complete callback.
virtual void Decode(GMPAudioSamples* aEncodedSamples) = 0;
// Reset decoder state and prepare for a new call to Decode(...).
// Flushes the decoder pipeline.
// The decoder should enqueue a task to run ResetComplete() on the main
// thread once the reset has finished.
virtual void Reset() = 0;
// Output decoded frames for any data in the pipeline, regardless of ordering.
// All remaining decoded frames should be immediately returned via callback.
// The decoder should enqueue a task to run DrainComplete() on the main
// thread once the reset has finished.
virtual void Drain() = 0;
// May free decoder memory.
virtual void DecodingComplete() = 0;
};
#endif // GMP_VIDEO_DECODE_h_

View File

@ -1,32 +0,0 @@
/*
* Copyright 2013, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GMP_AUDIO_HOST_h_
#define GMP_AUDIO_HOST_h_
#include "gmp-errors.h"
#include "gmp-audio-samples.h"
class GMPAudioHost
{
public:
// Construct various Audio API objects. Host does not retain reference,
// caller is owner and responsible for deleting.
virtual GMPErr CreateSamples(GMPAudioFormat aFormat,
GMPAudioSamples** aSamples) = 0;
};
#endif // GMP_AUDIO_HOST_h_

View File

@ -1,74 +0,0 @@
/*
* Copyright 2013, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GMP_AUDIO_FRAME_h_
#define GMP_AUDIO_FRAME_h_
#include <stdint.h>
#include "gmp-errors.h"
#include "gmp-decryption.h"
enum GMPAudioFormat
{
kGMPAudioEncodedSamples, // Raw compressed data, i.e. an AAC/Vorbis packet.
kGMPAudioIS16Samples, // Interleaved int16_t PCM samples.
kGMPAudioSamplesFormatInvalid // Should always be last.
};
class GMPAudioSamples {
public:
// The format of the buffer.
virtual GMPAudioFormat GetFormat() = 0;
virtual void Destroy() = 0;
// MAIN THREAD ONLY
// Buffer size must be exactly what's required to contain all samples in
// the buffer; every byte is assumed to be part of a sample.
virtual GMPErr SetBufferSize(uint32_t aSize) = 0;
// Size of the buffer in bytes.
virtual uint32_t Size() = 0;
// Timestamps are in microseconds, and are the playback start time of the
// first sample in the buffer.
virtual void SetTimeStamp(uint64_t aTimeStamp) = 0;
virtual uint64_t TimeStamp() = 0;
virtual const uint8_t* Buffer() const = 0;
virtual uint8_t* Buffer() = 0;
// Get metadata describing how this frame is encrypted, or nullptr if the
// buffer is not encrypted.
virtual const GMPEncryptedBufferMetadata* GetDecryptionData() const = 0;
virtual uint32_t Channels() const = 0;
virtual void SetChannels(uint32_t aChannels) = 0;
// Rate; the number of frames per second, where a "frame" is one sample for
// each channel.
//
// For IS16 samples, the number of samples should be:
// Size() / (Channels() * sizeof(int16_t)).
//
// Note: Channels() and Rate() may not be constant across a decoding
// session. For example the rate for decoded samples may be different
// than the rate advertised by the MP4 container for encoded samples
// for HE-AAC streams with SBR/PS, and an EME-GMP may need to downsample
// to satisfy DRM requirements.
virtual uint32_t Rate() const = 0;
virtual void SetRate(uint32_t aRate) = 0;
};
#endif // GMP_AUDIO_FRAME_h_

View File

@ -234,10 +234,7 @@ enum GMPSessionType {
kGMPSessionInvalid = 2 // Must always be last.
};
// Gecko supports the current GMPDecryptor version, and the obsolete
// version that the Adobe GMP still uses.
#define GMP_API_DECRYPTOR "eme-decrypt-v9"
#define GMP_API_DECRYPTOR_BACKWARDS_COMPAT "eme-decrypt-v7"
// API exposed by plugin library to manage decryption sessions.
// When the Host requests this by calling GMPGetAPIFunc().
@ -349,111 +346,4 @@ public:
virtual ~GMPDecryptor() {}
};
// v7 is the latest decryptor version supported by the Adobe GMP.
//
// API name macro: GMP_API_DECRYPTOR_BACKWARDS_COMPAT
// Host API: GMPDecryptorHost
class GMPDecryptor7 {
public:
// Sets the callback to use with the decryptor to return results
// to Gecko.
virtual void Init(GMPDecryptorCallback* aCallback) = 0;
// Initiates the creation of a session given |aType| and |aInitData|, and
// the generation of a license request message.
//
// This corresponds to a MediaKeySession.generateRequest() call in JS.
//
// The GMPDecryptor must do the following, in order, upon this method
// being called:
//
// 1. Generate a sessionId to expose to JS, and call
// GMPDecryptorCallback::SetSessionId(aCreateSessionToken, sessionId...)
// with the sessionId to be exposed to JS/EME on the MediaKeySession
// object on which generateRequest() was called, and then
// 2. send any messages to JS/EME required to generate a license request
// given the supplied initData, and then
// 3. generate a license request message, and send it to JS/EME, and then
// 4. call GMPDecryptorCallback::ResolvePromise().
//
// Note: GMPDecryptorCallback::SetSessionId(aCreateSessionToken, sessionId, ...)
// *must* be called before GMPDecryptorCallback::SendMessage(sessionId, ...)
// will work.
//
// If generating the request fails, reject aPromiseId by calling
// GMPDecryptorCallback::RejectPromise().
virtual void CreateSession(uint32_t aCreateSessionToken,
uint32_t aPromiseId,
const char* aInitDataType,
uint32_t aInitDataTypeSize,
const uint8_t* aInitData,
uint32_t aInitDataSize,
GMPSessionType aSessionType) = 0;
// Loads a previously loaded persistent session.
//
// This corresponds to a MediaKeySession.load() call in JS.
//
// The GMPDecryptor must do the following, in order, upon this method
// being called:
//
// 1. Send any messages to JS/EME, or read from storage, whatever is
// required to load the session, and then
// 2. if there is no session with the given sessionId loadable, call
// ResolveLoadSessionPromise(aPromiseId, false), otherwise
// 2. mark the session's keys as usable, and then
// 3. update the session's expiration, and then
// 4. call GMPDecryptorCallback::ResolveLoadSessionPromise(aPromiseId, true).
//
// If loading the session fails due to error, reject aPromiseId by calling
// GMPDecryptorCallback::RejectPromise().
virtual void LoadSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) = 0;
// Updates the session with |aResponse|.
// This corresponds to a MediaKeySession.update() call in JS.
virtual void UpdateSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aResponse,
uint32_t aResponseSize) = 0;
// Releases the resources (keys) for the specified session.
// This corresponds to a MediaKeySession.close() call in JS.
virtual void CloseSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) = 0;
// Removes the resources (keys) for the specified session.
// This corresponds to a MediaKeySession.remove() call in JS.
virtual void RemoveSession(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdLength) = 0;
// Resolve/reject promise on completion.
// This corresponds to a MediaKeySession.setServerCertificate() call in JS.
virtual void SetServerCertificate(uint32_t aPromiseId,
const uint8_t* aServerCert,
uint32_t aServerCertSize) = 0;
// Asynchronously decrypts aBuffer in place. When the decryption is
// complete, GMPDecryptor should write the decrypted data back into the
// same GMPBuffer object and return it to Gecko by calling Decrypted(),
// with the GMPNoErr successcode. If decryption fails, call Decrypted()
// with a failure code, and an error event will fire on the media element.
// Note: When Decrypted() is called and aBuffer is passed back, aBuffer
// is deleted. Don't forget to call Decrypted(), as otherwise aBuffer's
// memory will leak!
virtual void Decrypt(GMPBuffer* aBuffer,
GMPEncryptedBufferMetadata* aMetadata) = 0;
// Called when the decryption operations are complete.
// Do not call the GMPDecryptorCallback's functions after this is called.
virtual void DecryptingComplete() = 0;
virtual ~GMPDecryptor7() {}
};
#endif // GMP_DECRYPTION_h_

View File

@ -13,10 +13,6 @@ XPIDL_SOURCES += [
EXPORTS += [
'gmp-api/gmp-async-shutdown.h',
'gmp-api/gmp-audio-codec.h',
'gmp-api/gmp-audio-decode.h',
'gmp-api/gmp-audio-host.h',
'gmp-api/gmp-audio-samples.h',
'gmp-api/gmp-decryption.h',
'gmp-api/gmp-entrypoints.h',
'gmp-api/gmp-errors.h',
@ -30,10 +26,6 @@ EXPORTS += [
'gmp-api/gmp-video-frame.h',
'gmp-api/gmp-video-host.h',
'gmp-api/gmp-video-plane.h',
'GMPAudioDecoderChild.h',
'GMPAudioDecoderParent.h',
'GMPAudioDecoderProxy.h',
'GMPAudioHost.h',
'GMPCallbackBase.h',
'GMPCDMCallbackProxy.h',
'GMPCDMProxy.h',
@ -85,9 +77,6 @@ if CONFIG['OS_ARCH'] == 'Linux':
]
UNIFIED_SOURCES += [
'GMPAudioDecoderChild.cpp',
'GMPAudioDecoderParent.cpp',
'GMPAudioHost.cpp',
'GMPCDMCallbackProxy.cpp',
'GMPCDMProxy.cpp',
'GMPChild.cpp',
@ -130,7 +119,6 @@ DIRS += [
IPDL_SOURCES += [
'GMPTypes.ipdlh',
'PGMP.ipdl',
'PGMPAudioDecoder.ipdl',
'PGMPContent.ipdl',
'PGMPDecryptor.ipdl',
'PGMPService.ipdl',

View File

@ -10,7 +10,6 @@
#include "mozilla/UniquePtr.h"
#include "nsTArray.h"
#include "nsStringGlue.h"
class GMPAudioDecoderProxy;
class GMPDecryptorProxy;
class GMPVideoDecoderProxy;
class GMPVideoEncoderProxy;
@ -37,7 +36,6 @@ public:
virtual void Done(T*, GMPVideoHost*) = 0;
};
typedef GMPGetterCallback<GMPDecryptorProxy> GetGMPDecryptorCallback;
typedef GMPGetterCallback<GMPAudioDecoderProxy> GetGMPAudioDecoderCallback;
typedef GMPVideoGetterCallback<GMPVideoDecoderProxy> GetGMPVideoDecoderCallback;
typedef GMPVideoGetterCallback<GMPVideoEncoderProxy> GetGMPVideoEncoderCallback;
class GetNodeIdCallback
@ -51,7 +49,6 @@ public:
[ptr] native TagArray(nsTArray<nsCString>);
native GetGMPDecryptorCallback(mozilla::UniquePtr<GetGMPDecryptorCallback>&&);
native GetGMPAudioDecoderCallback(mozilla::UniquePtr<GetGMPAudioDecoderCallback>&&);
native GetGMPVideoDecoderCallback(mozilla::UniquePtr<GetGMPVideoDecoderCallback>&&);
native GetGMPVideoEncoderCallback(mozilla::UniquePtr<GetGMPVideoEncoderCallback>&&);
native GetNodeIdCallback(mozilla::UniquePtr<GetNodeIdCallback>&&);
@ -126,23 +123,6 @@ interface mozIGeckoMediaPluginService : nsISupports
[optional] in ACString nodeId,
in GetGMPVideoEncoderCallback callback);
/**
* Returns an audio decoder that supports the specified tags.
* The array of tags should at least contain a codec tag, and optionally
* other tags such as for EME keysystem.
* Callable only on GMP thread.
* This is an asynchronous operation, the Done method of the callback object
* will be called on the GMP thread with the result (which might be null in
* the case of failure). This method always takes ownership of the callback
* object, but if this method returns an error then the Done method of the
* callback object will not be called at all.
*/
[noscript]
void getGMPAudioDecoder(in GMPCrashHelperPtr helper,
in TagArray tags,
[optional] in ACString nodeId,
in GetGMPAudioDecoderCallback callback);
/**
* Returns a decryption session manager that supports the specified tags.
* The array of tags should at least contain a key system tag, and optionally

View File

@ -88,6 +88,7 @@ void
VPXDecoder::Shutdown()
{
vpx_codec_destroy(&mVPX);
vpx_codec_destroy(&mVPXAlpha);
}
RefPtr<MediaDataDecoder::InitPromise>

View File

@ -1,44 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#include "EMEAudioDecoder.h"
#include "mozilla/CDMProxy.h"
namespace mozilla {
void
EMEAudioCallbackAdapter::Error(GMPErr aErr)
{
if (aErr == GMPNoKeyErr) {
// The GMP failed to decrypt a frame due to not having a key. This can
// happen if a key expires or a session is closed during playback.
NS_WARNING("GMP failed to decrypt due to lack of key");
return;
}
AudioCallbackAdapter::Error(aErr);
}
EMEAudioDecoder::EMEAudioDecoder(CDMProxy* aProxy,
const GMPAudioDecoderParams& aParams)
: GMPAudioDecoder(GMPAudioDecoderParams(aParams).WithAdapter(
new EMEAudioCallbackAdapter(aParams.mCallback)))
, mProxy(aProxy)
{}
void
EMEAudioDecoder::InitTags(nsTArray<nsCString>& aTags)
{
aTags.AppendElement(NS_LITERAL_CSTRING("aac"));
aTags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem()));
}
nsCString
EMEAudioDecoder::GetNodeId()
{
return mProxy->GetNodeId();
}
} // namespace mozilla

View File

@ -1,37 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef EMEAudioDecoder_h_
#define EMEAudioDecoder_h_
#include "GMPAudioDecoder.h"
#include "PlatformDecoderModule.h"
namespace mozilla {
class EMEAudioCallbackAdapter : public AudioCallbackAdapter {
public:
explicit EMEAudioCallbackAdapter(MediaDataDecoderCallbackProxy* aCallback)
: AudioCallbackAdapter(aCallback)
{}
void Error(GMPErr aErr) override;
};
class EMEAudioDecoder : public GMPAudioDecoder {
public:
EMEAudioDecoder(CDMProxy* aProxy, const GMPAudioDecoderParams& aParams);
private:
void InitTags(nsTArray<nsCString>& aTags) override;
nsCString GetNodeId() override;
RefPtr<CDMProxy> mProxy;
};
} // namespace mozilla
#endif

View File

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "EMEDecoderModule.h"
#include "EMEAudioDecoder.h"
#include "EMEVideoDecoder.h"
#include "MediaDataDecoderProxy.h"
#include "mozIGeckoMediaPluginService.h"
@ -100,11 +99,7 @@ public:
}
} else {
MOZ_ASSERT(!mIsShutdown);
// The Adobe GMP AAC decoder gets confused if we pass it non-encrypted
// samples with valid crypto data. So clear the crypto data, since the
// sample should be decrypted now anyway. If we don't do this and we're
// using the Adobe GMP for unencrypted decoding of data that is decrypted
// by gmp-clearkey, decoding will fail.
// The sample is no longer encrypted, so clear its crypto metadata.
UniquePtr<MediaRawDataWriter> writer(aDecrypted.mSample->CreateWriter());
writer->mCrypto = CryptoSample();
mDecoder->Input(aDecrypted.mSample);
@ -264,16 +259,10 @@ EMEDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
{
MOZ_ASSERT(aParams.mConfig.mCrypto.mValid);
if (SupportsMimeType(aParams.mConfig.mMimeType, nullptr)) {
// GMP decodes. Assume that means it can decrypt too.
RefPtr<MediaDataDecoderProxy> wrapper =
CreateDecoderWrapper(aParams.mCallback, mProxy, aParams.mTaskQueue);
auto gmpParams = GMPAudioDecoderParams(aParams).WithCallback(wrapper);
wrapper->SetProxyTarget(new EMEAudioDecoder(mProxy, gmpParams));
return wrapper.forget();
}
// We don't support using the GMP to decode audio.
MOZ_ASSERT(!SupportsMimeType(aParams.mConfig.mMimeType, nullptr));
MOZ_ASSERT(mPDM);
RefPtr<MediaDataDecoder> decoder(mPDM->CreateDecoder(aParams));
if (!decoder) {
return nullptr;

View File

@ -5,14 +5,12 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS += [
'EMEAudioDecoder.h',
'EMEDecoderModule.h',
'EMEVideoDecoder.h',
'SamplesWaitingForKey.h',
]
UNIFIED_SOURCES += [
'EMEAudioDecoder.cpp',
'EMEDecoderModule.cpp',
'EMEVideoDecoder.cpp',
'SamplesWaitingForKey.cpp',

View File

@ -1,306 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#include "GMPAudioDecoder.h"
#include "nsServiceManagerUtils.h"
#include "MediaInfo.h"
#include "GMPDecoderModule.h"
#include "nsPrintfCString.h"
namespace mozilla {
#if defined(DEBUG)
bool IsOnGMPThread()
{
nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
MOZ_ASSERT(mps);
nsCOMPtr<nsIThread> gmpThread;
nsresult rv = mps->GetThread(getter_AddRefs(gmpThread));
MOZ_ASSERT(NS_SUCCEEDED(rv) && gmpThread);
return NS_GetCurrentThread() == gmpThread;
}
#endif
void
AudioCallbackAdapter::Decoded(const nsTArray<int16_t>& aPCM, uint64_t aTimeStamp, uint32_t aChannels, uint32_t aRate)
{
MOZ_ASSERT(IsOnGMPThread());
if (aRate == 0 || aChannels == 0) {
mCallback->Error(MediaResult(
NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL(
"Invalid rate or num channels returned on GMP audio samples")));
return;
}
size_t numFrames = aPCM.Length() / aChannels;
MOZ_ASSERT((aPCM.Length() % aChannels) == 0);
AlignedAudioBuffer audioData(aPCM.Length());
if (!audioData) {
mCallback->Error(
MediaResult(NS_ERROR_OUT_OF_MEMORY,
RESULT_DETAIL("Unable to allocate audio buffer")));
return;
}
for (size_t i = 0; i < aPCM.Length(); ++i) {
audioData[i] = AudioSampleToFloat(aPCM[i]);
}
if (mMustRecaptureAudioPosition) {
mAudioFrameSum = 0;
auto timestamp = UsecsToFrames(aTimeStamp, aRate);
if (!timestamp.isValid()) {
mCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
RESULT_DETAIL("Invalid timestamp")));
return;
}
mAudioFrameOffset = timestamp.value();
mMustRecaptureAudioPosition = false;
}
auto timestamp = FramesToUsecs(mAudioFrameOffset + mAudioFrameSum, aRate);
if (!timestamp.isValid()) {
mCallback->Error(
MediaResult(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
RESULT_DETAIL("Invalid timestamp on audio samples")));
return;
}
mAudioFrameSum += numFrames;
auto duration = FramesToUsecs(numFrames, aRate);
if (!duration.isValid()) {
mCallback->Error(
MediaResult(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
RESULT_DETAIL("Invalid duration on audio samples")));
return;
}
RefPtr<AudioData> audio(new AudioData(mLastStreamOffset,
timestamp.value(),
duration.value(),
numFrames,
Move(audioData),
aChannels,
aRate));
#ifdef LOG_SAMPLE_DECODE
LOG("Decoded audio sample! timestamp=%lld duration=%lld currentLength=%u",
timestamp, duration, currentLength);
#endif
mCallback->Output(audio);
}
void
AudioCallbackAdapter::InputDataExhausted()
{
MOZ_ASSERT(IsOnGMPThread());
mCallback->InputExhausted();
}
void
AudioCallbackAdapter::DrainComplete()
{
MOZ_ASSERT(IsOnGMPThread());
mCallback->DrainComplete();
}
void
AudioCallbackAdapter::ResetComplete()
{
MOZ_ASSERT(IsOnGMPThread());
mMustRecaptureAudioPosition = true;
mCallback->FlushComplete();
}
void
AudioCallbackAdapter::Error(GMPErr aErr)
{
MOZ_ASSERT(IsOnGMPThread());
mCallback->Error(MediaResult(aErr == GMPDecodeErr
? NS_ERROR_DOM_MEDIA_DECODE_ERR
: NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("GMPErr:%x", aErr)));
}
void
AudioCallbackAdapter::Terminated()
{
mCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Audio GMP decoder terminated.")));
}
GMPAudioDecoderParams::GMPAudioDecoderParams(const CreateDecoderParams& aParams)
: mConfig(aParams.AudioConfig())
, mTaskQueue(aParams.mTaskQueue)
, mCallback(nullptr)
, mAdapter(nullptr)
, mCrashHelper(aParams.mCrashHelper)
{}
GMPAudioDecoderParams&
GMPAudioDecoderParams::WithCallback(MediaDataDecoderProxy* aWrapper)
{
MOZ_ASSERT(aWrapper);
MOZ_ASSERT(!mCallback); // Should only be called once per instance.
mCallback = aWrapper->Callback();
mAdapter = nullptr;
return *this;
}
GMPAudioDecoderParams&
GMPAudioDecoderParams::WithAdapter(AudioCallbackAdapter* aAdapter)
{
MOZ_ASSERT(aAdapter);
MOZ_ASSERT(!mAdapter); // Should only be called once per instance.
mCallback = aAdapter->Callback();
mAdapter = aAdapter;
return *this;
}
GMPAudioDecoder::GMPAudioDecoder(const GMPAudioDecoderParams& aParams)
: mConfig(aParams.mConfig)
, mCallback(aParams.mCallback)
, mGMP(nullptr)
, mAdapter(aParams.mAdapter)
, mCrashHelper(aParams.mCrashHelper)
{
MOZ_ASSERT(!mAdapter || mCallback == mAdapter->Callback());
if (!mAdapter) {
mAdapter = new AudioCallbackAdapter(mCallback);
}
}
void
GMPAudioDecoder::InitTags(nsTArray<nsCString>& aTags)
{
aTags.AppendElement(NS_LITERAL_CSTRING("aac"));
const Maybe<nsCString> gmp(
GMPDecoderModule::PreferredGMP(NS_LITERAL_CSTRING("audio/mp4a-latm")));
if (gmp.isSome()) {
aTags.AppendElement(gmp.value());
}
}
nsCString
GMPAudioDecoder::GetNodeId()
{
return SHARED_GMP_DECODING_NODE_ID;
}
void
GMPAudioDecoder::GMPInitDone(GMPAudioDecoderProxy* aGMP)
{
MOZ_ASSERT(IsOnGMPThread());
if (!aGMP) {
mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
return;
}
if (mInitPromise.IsEmpty()) {
// GMP must have been shutdown while we were waiting for Init operation
// to complete.
aGMP->Close();
return;
}
nsTArray<uint8_t> codecSpecific;
codecSpecific.AppendElements(mConfig.mCodecSpecificConfig->Elements(),
mConfig.mCodecSpecificConfig->Length());
nsresult rv = aGMP->InitDecode(kGMPAudioCodecAAC,
mConfig.mChannels,
mConfig.mBitDepth,
mConfig.mRate,
codecSpecific,
mAdapter);
if (NS_FAILED(rv)) {
aGMP->Close();
mInitPromise.Reject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
return;
}
mGMP = aGMP;
mInitPromise.Resolve(TrackInfo::kAudioTrack, __func__);
}
RefPtr<MediaDataDecoder::InitPromise>
GMPAudioDecoder::Init()
{
MOZ_ASSERT(IsOnGMPThread());
mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
MOZ_ASSERT(mMPS);
RefPtr<InitPromise> promise(mInitPromise.Ensure(__func__));
nsTArray<nsCString> tags;
InitTags(tags);
UniquePtr<GetGMPAudioDecoderCallback> callback(new GMPInitDoneCallback(this));
if (NS_FAILED(mMPS->GetGMPAudioDecoder(mCrashHelper, &tags, GetNodeId(), Move(callback)))) {
mInitPromise.Reject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
}
return promise;
}
void
GMPAudioDecoder::Input(MediaRawData* aSample)
{
MOZ_ASSERT(IsOnGMPThread());
RefPtr<MediaRawData> sample(aSample);
if (!mGMP) {
mCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("mGMP not initialized")));
return;
}
mAdapter->SetLastStreamOffset(sample->mOffset);
gmp::GMPAudioSamplesImpl samples(sample, mConfig.mChannels, mConfig.mRate);
nsresult rv = mGMP->Decode(samples);
if (NS_FAILED(rv)) {
mCallback->Error(MediaResult(rv, __func__));
}
}
void
GMPAudioDecoder::Flush()
{
MOZ_ASSERT(IsOnGMPThread());
if (!mGMP || NS_FAILED(mGMP->Reset())) {
// Abort the flush.
mCallback->FlushComplete();
}
}
void
GMPAudioDecoder::Drain()
{
MOZ_ASSERT(IsOnGMPThread());
if (!mGMP || NS_FAILED(mGMP->Drain())) {
mCallback->DrainComplete();
}
}
void
GMPAudioDecoder::Shutdown()
{
mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
if (!mGMP) {
return;
}
// Note this unblocks flush and drain operations waiting for callbacks.
mGMP->Close();
mGMP = nullptr;
}
} // namespace mozilla

View File

@ -1,112 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#if !defined(GMPAudioDecoder_h_)
#define GMPAudioDecoder_h_
#include "GMPAudioDecoderProxy.h"
#include "MediaDataDecoderProxy.h"
#include "PlatformDecoderModule.h"
#include "mozIGeckoMediaPluginService.h"
#include "nsAutoPtr.h"
namespace mozilla {
class AudioCallbackAdapter : public GMPAudioDecoderCallbackProxy {
public:
explicit AudioCallbackAdapter(MediaDataDecoderCallbackProxy* aCallback)
: mCallback(aCallback)
, mLastStreamOffset(0)
, mAudioFrameSum(0)
, mAudioFrameOffset(0)
, mMustRecaptureAudioPosition(true)
{}
MediaDataDecoderCallbackProxy* Callback() const { return mCallback; }
// GMPAudioDecoderCallbackProxy
void Decoded(const nsTArray<int16_t>& aPCM, uint64_t aTimeStamp, uint32_t aChannels, uint32_t aRate) override;
void InputDataExhausted() override;
void DrainComplete() override;
void ResetComplete() override;
void Error(GMPErr aErr) override;
void Terminated() override;
void SetLastStreamOffset(int64_t aStreamOffset) {
mLastStreamOffset = aStreamOffset;
}
private:
MediaDataDecoderCallbackProxy* mCallback;
int64_t mLastStreamOffset;
int64_t mAudioFrameSum;
int64_t mAudioFrameOffset;
bool mMustRecaptureAudioPosition;
};
struct GMPAudioDecoderParams {
explicit GMPAudioDecoderParams(const CreateDecoderParams& aParams);
GMPAudioDecoderParams& WithCallback(MediaDataDecoderProxy* aWrapper);
GMPAudioDecoderParams& WithAdapter(AudioCallbackAdapter* aAdapter);
const AudioInfo& mConfig;
TaskQueue* mTaskQueue;
MediaDataDecoderCallbackProxy* mCallback;
AudioCallbackAdapter* mAdapter;
RefPtr<GMPCrashHelper> mCrashHelper;
};
class GMPAudioDecoder : public MediaDataDecoder {
public:
explicit GMPAudioDecoder(const GMPAudioDecoderParams& aParams);
RefPtr<InitPromise> Init() override;
void Input(MediaRawData* aSample) override;
void Flush() override;
void Drain() override;
void Shutdown() override;
const char* GetDescriptionName() const override
{
return "GMP audio decoder";
}
protected:
virtual void InitTags(nsTArray<nsCString>& aTags);
virtual nsCString GetNodeId();
private:
class GMPInitDoneCallback : public GetGMPAudioDecoderCallback
{
public:
explicit GMPInitDoneCallback(GMPAudioDecoder* aDecoder)
: mDecoder(aDecoder)
{
}
void Done(GMPAudioDecoderProxy* aGMP) override
{
mDecoder->GMPInitDone(aGMP);
}
private:
RefPtr<GMPAudioDecoder> mDecoder;
};
void GMPInitDone(GMPAudioDecoderProxy* aGMP);
const AudioInfo mConfig;
MediaDataDecoderCallbackProxy* mCallback;
nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
GMPAudioDecoderProxy* mGMP;
nsAutoPtr<AudioCallbackAdapter> mAdapter;
MozPromiseHolder<InitPromise> mInitPromise;
RefPtr<GMPCrashHelper> mCrashHelper;
};
} // namespace mozilla
#endif // GMPAudioDecoder_h_

View File

@ -6,7 +6,6 @@
#include "GMPDecoderModule.h"
#include "DecoderDoctorDiagnostics.h"
#include "GMPAudioDecoder.h"
#include "GMPVideoDecoder.h"
#include "GMPUtils.h"
#include "MediaDataDecoderProxy.h"
@ -15,7 +14,6 @@
#include "mozIGeckoMediaPluginService.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/StaticMutex.h"
#include "gmp-audio-decode.h"
#include "gmp-video-decode.h"
#include "MP4Decoder.h"
#include "VPXDecoder.h"
@ -57,13 +55,6 @@ GMPDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
return nullptr;
}
if (aParams.mDiagnostics) {
const Maybe<nsCString> preferredGMP = PreferredGMP(aParams.mConfig.mMimeType);
if (preferredGMP.isSome()) {
aParams.mDiagnostics->SetGMP(preferredGMP.value());
}
}
RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aParams.mCallback);
auto params = GMPVideoDecoderParams(aParams).WithCallback(wrapper);
wrapper->SetProxyTarget(new GMPVideoDecoder(params));
@ -73,21 +64,7 @@ GMPDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
already_AddRefed<MediaDataDecoder>
GMPDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
{
if (!aParams.mConfig.mMimeType.EqualsLiteral("audio/mp4a-latm")) {
return nullptr;
}
if (aParams.mDiagnostics) {
const Maybe<nsCString> preferredGMP = PreferredGMP(aParams.mConfig.mMimeType);
if (preferredGMP.isSome()) {
aParams.mDiagnostics->SetGMP(preferredGMP.value());
}
}
RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aParams.mCallback);
auto params = GMPAudioDecoderParams(aParams).WithCallback(wrapper);
wrapper->SetProxyTarget(new GMPAudioDecoder(params));
return wrapper.forget();
return nullptr;
}
PlatformDecoderModule::ConversionRequired
@ -101,30 +78,6 @@ GMPDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
}
}
/* static */
const Maybe<nsCString>
GMPDecoderModule::PreferredGMP(const nsACString& aMimeType)
{
Maybe<nsCString> rv;
if (aMimeType.EqualsLiteral("audio/mp4a-latm")) {
switch (MediaPrefs::GMPAACPreferred()) {
case 1: rv.emplace(kEMEKeySystemClearkey); break;
case 2: rv.emplace(kEMEKeySystemPrimetime); break;
default: break;
}
}
if (MP4Decoder::IsH264(aMimeType)) {
switch (MediaPrefs::GMPH264Preferred()) {
case 1: rv.emplace(kEMEKeySystemClearkey); break;
case 2: rv.emplace(kEMEKeySystemPrimetime); break;
default: break;
}
}
return rv;
}
/* static */
bool
GMPDecoderModule::SupportsMimeType(const nsACString& aMimeType,
@ -149,11 +102,6 @@ GMPDecoderModule::SupportsMimeType(const nsACString& aMimeType,
{ NS_LITERAL_CSTRING("vp8"), aGMP.value()});
}
if (MP4Decoder::IsAAC(aMimeType)) {
return HaveGMPFor(NS_LITERAL_CSTRING(GMP_API_AUDIO_DECODER),
{ NS_LITERAL_CSTRING("aac"), aGMP.value()});
}
return false;
}
@ -161,12 +109,7 @@ bool
GMPDecoderModule::SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const
{
const Maybe<nsCString> preferredGMP = PreferredGMP(aMimeType);
bool rv = SupportsMimeType(aMimeType, preferredGMP);
if (rv && aDiagnostics && preferredGMP.isSome()) {
aDiagnostics->SetGMP(preferredGMP.value());
}
return rv;
return false;
}
} // namespace mozilla

View File

@ -46,8 +46,6 @@ public:
SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;
static const Maybe<nsCString> PreferredGMP(const nsACString& aMimeType);
static bool SupportsMimeType(const nsACString& aMimeType,
const Maybe<nsCString>& aGMP);
};

View File

@ -15,7 +15,16 @@
namespace mozilla {
#if defined(DEBUG)
extern bool IsOnGMPThread();
static bool IsOnGMPThread()
{
nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
MOZ_ASSERT(mps);
nsCOMPtr<nsIThread> gmpThread;
nsresult rv = mps->GetThread(getter_AddRefs(gmpThread));
MOZ_ASSERT(NS_SUCCEEDED(rv) && gmpThread);
return NS_GetCurrentThread() == gmpThread;
}
#endif
void
@ -162,11 +171,6 @@ GMPVideoDecoder::InitTags(nsTArray<nsCString>& aTags)
{
if (MP4Decoder::IsH264(mConfig.mMimeType)) {
aTags.AppendElement(NS_LITERAL_CSTRING("h264"));
const Maybe<nsCString> gmp(
GMPDecoderModule::PreferredGMP(NS_LITERAL_CSTRING("video/avc")));
if (gmp.isSome()) {
aTags.AppendElement(gmp.value());
}
} else if (VPXDecoder::IsVP8(mConfig.mMimeType)) {
aTags.AppendElement(NS_LITERAL_CSTRING("vp8"));
} else if (VPXDecoder::IsVP9(mConfig.mMimeType)) {

View File

@ -5,14 +5,12 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS += [
'GMPAudioDecoder.h',
'GMPDecoderModule.h',
'GMPVideoDecoder.h',
'MediaDataDecoderProxy.h',
]
UNIFIED_SOURCES += [
'GMPAudioDecoder.cpp',
'GMPDecoderModule.cpp',
'GMPVideoDecoder.cpp',
'MediaDataDecoderProxy.cpp',

View File

@ -200,19 +200,6 @@ class NetworkBandwidthTestsMixin(object):
self.run_videos(timeout=120)
reset_adobe_gmp_script = """
navigator.requestMediaKeySystemAccess('com.adobe.primetime',
[{initDataTypes: ['cenc']}]).then(
function(access) {
marionetteScriptFinished('success');
},
function(ex) {
marionetteScriptFinished(ex);
}
);
"""
reset_widevine_gmp_script = """
navigator.requestMediaKeySystemAccess('com.widevine.alpha',
[{initDataTypes: ['cenc']}]).then(
@ -229,7 +216,7 @@ navigator.requestMediaKeySystemAccess('com.widevine.alpha',
class EMESetupMixin(object):
"""
An object that needs to use the Adobe or Widevine GMP system must inherit
An object that needs to use the Widevine GMP system must inherit
from this class, and then call check_eme_system() to insure that everything
is setup correctly.
"""
@ -238,7 +225,7 @@ class EMESetupMixin(object):
def check_eme_system(self):
"""
Download the most current version of the Adobe and Widevine GMP
Download the most current version of the Widevine GMP
Plugins. Verify that all MSE and EME prefs are set correctly. Raises
if things are not OK.
"""
@ -256,21 +243,12 @@ class EMESetupMixin(object):
def reset_GMP_version(self):
if EMESetupMixin.version_needs_reset:
with self.marionette.using_context(Marionette.CONTEXT_CHROME):
if self.marionette.get_pref('media.gmp-eme-adobe.version'):
self.marionette.reset_pref('media.gmp-eme-adobe.version')
if self.marionette.get_pref('media.gmp-widevinecdm.version'):
self.marionette.reset_pref('media.gmp-widevinecdm.version')
with self.marionette.using_context(Marionette.CONTEXT_CONTENT):
adobe_result = self.marionette.execute_async_script(
reset_adobe_gmp_script,
script_timeout=60000)
widevine_result = self.marionette.execute_async_script(
reset_widevine_gmp_script,
script_timeout=60000)
if not adobe_result == 'success':
raise VideoException(
'ERROR: Resetting Adobe GMP failed {}'
.format(adobe_result))
if not widevine_result == 'success':
raise VideoException(
'ERROR: Resetting Widevine GMP failed {}'
@ -351,10 +329,6 @@ class EMESetupMixin(object):
'media.eme.enabled', True),
self.check_and_log_boolean_pref(
'media.mediasource.mp4.enabled', True),
self.check_and_log_boolean_pref(
'media.gmp-eme-adobe.enabled', True),
self.check_and_log_integer_pref(
'media.gmp-eme-adobe.version', 1),
self.check_and_log_boolean_pref(
'media.gmp-widevinecdm.enabled', True),
self.chceck_and_log_version_string_pref(

View File

@ -486,7 +486,7 @@ function testCalcFontSize()
{
setupTest();
gCircleParent.setAttribute("font-size", "10px"); // At first: font-size: 10px
var anim = createAnimSetTo("font-size", "-moz-calc(110% + 0.1em)");
var anim = createAnimSetTo("font-size", "calc(110% + 0.1em)");
gSvg.setCurrentTime(0);
var fsize = parseInt(SMILUtil.getComputedStyleSimple(gCircle, "font-size"));

View File

@ -27,3 +27,18 @@ skip-if = !e10s
skip-if = !e10s
[test_appid_facet_subdomain.html]
skip-if = !e10s
[test_webauthn_loopback.html]
skip-if = !e10s
scheme = https
[test_webauthn_no_token.html]
skip-if = !e10s
scheme = https
[test_webauthn_make_credential.html]
skip-if = !e10s
scheme = https
[test_webauthn_get_assertion.html]
skip-if = !e10s
scheme = https
[test_webauthn_sameorigin.html]
skip-if = !e10s
scheme = https

View File

@ -0,0 +1,91 @@
<!DOCTYPE html>
<meta charset=utf-8>
<head>
<title>Tests for GetAssertion for W3C Web Authentication</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="u2futil.js"></script>
<script type="text/javascript" src="pkijs/common.js"></script>
<script type="text/javascript" src="pkijs/asn1.js"></script>
<script type="text/javascript" src="pkijs/x509_schema.js"></script>
<script type="text/javascript" src="pkijs/x509_simpl.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<h1>Tests for GetAssertion for W3C Web Authentication</h1>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1309284">Mozilla Bug 1309284</a>
<script class="testbody" type="text/javascript">
"use strict";
// Execute the full-scope test
SimpleTest.waitForExplicitFinish();
function arrivingHereIsBad(aResult) {
ok(false, "Bad result! Received a: " + aResult);
return Promise.resolve();
}
function expectNotAllowedError(aResult) {
ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError");
return Promise.resolve();
}
function expectTypeError(aResult) {
ok(aResult.toString().startsWith("TypeError"), "Expecting a TypeError");
return Promise.resolve();
}
SpecialPowers.pushPrefEnv({"set": [["security.webauth.w3c", true],
["security.webauth.u2f_enable_softtoken", true],
["security.webauth.u2f_enable_usbtoken", false]]},
function() {
isnot(navigator.authentication, undefined, "WebAuthn API endpoint must exist");
isnot(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential API endpoint must exist");
isnot(navigator.authentication.getAssertion, undefined, "WebAuthn getAssertion API endpoint must exist");
let authn = navigator.authentication;
let gAssertionChallenge = new Uint8Array(16);
window.crypto.getRandomValues(gAssertionChallenge);
let invalidCred = { type: "Magic", id: base64ToBytes("AAA=") };
let unknownCred = { type: "ScopedCred", id: base64ToBytes("AAA=") };
Promise.all([
// Test basic good call, but without giving a credential so expect failures
// this is OK by the standard, but not supported by U2F-backed authenticators
// like the soft token in use here.
authn.getAssertion(gAssertionChallenge)
.then(arrivingHereIsBad)
.catch(expectNotAllowedError),
// Test with an unexpected option
authn.getAssertion(gAssertionChallenge, { unknownValue: "hi" })
.then(arrivingHereIsBad)
.catch(expectNotAllowedError),
// Test with an invalid credential
authn.getAssertion(gAssertionChallenge, { allowList: [invalidCred] })
.then(arrivingHereIsBad)
.catch(expectTypeError),
// Test with an unknown credential
authn.getAssertion(gAssertionChallenge, { allowList: [unknownCred] })
.then(arrivingHereIsBad)
.catch(expectNotAllowedError),
// Test with an unexpected option and an invalid credential
authn.getAssertion(gAssertionChallenge, { unknownValue: "hi" })
.then(arrivingHereIsBad)
.catch(expectNotAllowedError)
])
.then(function(){
SimpleTest.finish();
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,170 @@
<!DOCTYPE html>
<meta charset=utf-8>
<head>
<title>Full-run test for MakeCredential/GetAssertion for W3C Web Authentication</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="u2futil.js"></script>
<script type="text/javascript" src="pkijs/common.js"></script>
<script type="text/javascript" src="pkijs/asn1.js"></script>
<script type="text/javascript" src="pkijs/x509_schema.js"></script>
<script type="text/javascript" src="pkijs/x509_simpl.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<h1>Full-run test for MakeCredential/GetAssertion for W3C Web Authentication</h1>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1309284">Mozilla Bug 1309284</a>
<script class="testbody" type="text/javascript">
"use strict";
// Execute the full-scope test
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["security.webauth.w3c", true],
["security.webauth.u2f_enable_softtoken", true],
["security.webauth.u2f_enable_usbtoken", false]]},
function() {
isnot(navigator.authentication, undefined, "WebAuthn API endpoint must exist");
isnot(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential API endpoint must exist");
isnot(navigator.authentication.getAssertion, undefined, "WebAuthn getAssertion API endpoint must exist");
let authn = navigator.authentication;
let gCredentialChallenge = new Uint8Array(16);
window.crypto.getRandomValues(gCredentialChallenge);
let gAssertionChallenge = new Uint8Array(16);
window.crypto.getRandomValues(gAssertionChallenge);
testMakeCredential();
function checkCredentialValid(aCredInfo) {
/* ScopedCredentialInfo
- Credential
-- ID: Key Handle buffer pulled from U2F Register() Response
-- Type: "ScopedCred"
- WebAuthnAttestation
-- Format: "u2f"
-- ClientData: serialized JSON
-- AuthenticatorData: RP ID Hash || U2F Sign() Response
-- Attestation: U2F Register() Response */
is(aCredInfo.credential.type, "ScopedCred", "Type is correct");
ok(aCredInfo.credential.id.length > 0, "Key ID exists");
is(aCredInfo.attestation.format, "u2f", "Format is correct");
is(aCredInfo.attestation.attestation[0], 0x05, "Reserved byte is correct");
ok(aCredInfo.attestation.authenticatorData.length > 0, "Authenticator data exists");
let clientData = JSON.parse(buffer2string(aCredInfo.attestation.clientData));
is(clientData.challenge, bytesToBase64UrlSafe(gCredentialChallenge), "Challenge is correct");
is(clientData.origin, window.location.origin, "Origin is correct");
is(clientData.hashAlg, "S256", "Hash algorithm is correct");
return decodeU2FRegistration(aCredInfo.attestation.attestation)
.then(function(u2fObj) {
aCredInfo.u2fReg = u2fObj;
return aCredInfo;
});
}
function checkAssertionAndSigValid(aPublicKey, aAssertion) {
/* WebAuthnAssertion
- Credential
-- ID: ID of Credential from AllowList that succeeded
-- Type: "ScopedCred"
- ClientData: serialized JSON
- AuthenticatorData: RP ID Hash || U2F Sign() Response
- Signature: U2F Sign() Response */
is(aAssertion.credential.type, "ScopedCred", "Type is correct");
ok(aAssertion.credential.id.length > 0, "Key ID exists");
ok(aAssertion.authenticatorData.length > 0, "Authenticator data exists");
let clientData = JSON.parse(buffer2string(aAssertion.clientData));
is(clientData.challenge, bytesToBase64UrlSafe(gAssertionChallenge), "Challenge is correct");
is(clientData.origin, window.location.origin, "Origin is correct");
is(clientData.hashAlg, "S256", "Hash algorithm is correct");
// Parse the signature data
if (aAssertion.signature[0] != 0x01) {
throw "User presence byte not set";
}
let presenceAndCounter = aAssertion.signature.slice(0,5);
let signatureValue = aAssertion.signature.slice(5);
let rpIdHash = aAssertion.authenticatorData.slice(0,32);
// Assemble the signed data and verify the signature
return deriveAppAndChallengeParam(clientData.origin, aAssertion.clientData)
.then(function(aParams) {
console.log(aParams.appParam, rpIdHash, presenceAndCounter, aParams.challengeParam);
console.log("ClientData buffer: ", hexEncode(aAssertion.clientData));
console.log("ClientDataHash: ", hexEncode(aParams.challengeParam));
return assembleSignedData(aParams.appParam, presenceAndCounter, aParams.challengeParam);
})
.then(function(aSignedData) {
console.log(aPublicKey, aSignedData, signatureValue);
return verifySignature(aPublicKey, aSignedData, signatureValue);
})
}
function testMakeCredential() {
let acct = {rpDisplayName: "none", displayName: "none", id: "none"};
let param = {type: "ScopedCred", algorithm: "p-256"};
authn.makeCredential(acct, [param], gCredentialChallenge)
.then(checkCredentialValid)
.then(testMakeDuplicate)
.catch(function(aReason) {
ok(false, aReason);
SimpleTest.finish();
});
}
function testMakeDuplicate(aCredInfo) {
let acct = {rpDisplayName: "none", displayName: "none", id: "none"};
let param = {type: "ScopedCred", algorithm: "p-256"};
let options = {rpId: document.origin,
excludeList: [aCredInfo.credential]};
authn.makeCredential(acct, [param], gCredentialChallenge, options)
.then(function() {
// We should have errored here!
ok(false, "The excludeList didn't stop a duplicate being created!");
SimpleTest.finish();
})
.catch(function(aReason) {
ok(aReason.toString().startsWith("NotAllowedError"), "Expect NotAllowedError, got" + aReason);
testAssertion(aCredInfo);
});
}
function testAssertion(aCredInfo) {
let newCredential = {
type: aCredInfo.credential.type,
id: Uint8Array.from(aCredInfo.credential.id),
transports: [ "usb" ],
}
let assertOptions = {rpId: document.origin, timeoutSeconds: 5,
allowList: [ newCredential ]};
authn.getAssertion(gAssertionChallenge, assertOptions)
.then(function(aAssertion) {
/* Pass along the pubKey. */
return checkAssertionAndSigValid(aCredInfo.u2fReg.publicKey, aAssertion);
})
.then(function(aSigVerifyResult) {
ok(aSigVerifyResult, "Signing signature verified");
SimpleTest.finish();
})
.catch(function(reason) {
ok(false, "Signing signature invalid: " + reason);
SimpleTest.finish();
});
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,158 @@
<!DOCTYPE html>
<meta charset=utf-8>
<head>
<title>Test for MakeCredential for W3C Web Authentication</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="u2futil.js"></script>
<script type="text/javascript" src="pkijs/common.js"></script>
<script type="text/javascript" src="pkijs/asn1.js"></script>
<script type="text/javascript" src="pkijs/x509_schema.js"></script>
<script type="text/javascript" src="pkijs/x509_simpl.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<h1>Test for MakeCredential for W3C Web Authentication</h1>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1309284">Mozilla Bug 1309284</a>
<script class="testbody" type="text/javascript">
"use strict";
// Execute the full-scope test
SimpleTest.waitForExplicitFinish();
function arrivingHereIsGood(aResult) {
ok(true, "Good result! Received a: " + aResult);
return Promise.resolve();
}
function arrivingHereIsBad(aResult) {
ok(false, "Bad result! Received a: " + aResult);
return Promise.resolve();
}
function expectNotAllowedError(aResult) {
ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError");
return Promise.resolve();
}
function expectTypeError(aResult) {
ok(aResult.toString().startsWith("TypeError"), "Expecting a TypeError");
return Promise.resolve();
}
function expectNotSupportedError(aResult) {
ok(aResult.toString().startsWith("NotSupportedError"), "Expecting a NotSupportedError");
return Promise.resolve();
}
SpecialPowers.pushPrefEnv({"set": [["security.webauth.w3c", true],
["security.webauth.u2f_enable_softtoken", true],
["security.webauth.u2f_enable_usbtoken", false]]},
function() {
isnot(navigator.authentication, undefined, "WebAuthn API endpoint must exist");
isnot(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential API endpoint must exist");
isnot(navigator.authentication.getAssertion, undefined, "WebAuthn getAssertion API endpoint must exist");
let authn = navigator.authentication;
let gCredentialChallenge = new Uint8Array(16);
window.crypto.getRandomValues(gCredentialChallenge);
let acct = {rpDisplayName: "none", displayName: "none", id: "none"};
let param = {type: "ScopedCred", algorithm: "p-256"};
let unsupportedParam = {type: "ScopedCred", algorithm: "3DES"};
let badParam = {type: "SimplePassword", algorithm: "MaxLength=2"};
Promise.all([
// Test basic good call
authn.makeCredential(acct, [param], gCredentialChallenge)
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad),
// Test empty account
authn.makeCredential({}, [param], gCredentialChallenge)
.then(arrivingHereIsBad)
.catch(expectTypeError),
// Test without a parameter
authn.makeCredential(acct, [], gCredentialChallenge)
.then(arrivingHereIsBad)
.catch(expectNotSupportedError),
// Test without a parameter array at all
authn.makeCredential(acct, null, gCredentialChallenge)
.then(arrivingHereIsBad)
.catch(expectTypeError),
// Test with an unsupported parameter
authn.makeCredential(acct, [unsupportedParam], gCredentialChallenge)
.then(arrivingHereIsBad)
.catch(expectNotSupportedError),
// Test with an unsupported parameter and a good one
authn.makeCredential(acct, [unsupportedParam, param], gCredentialChallenge)
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad),
// Test with a bad parameter
authn.makeCredential(acct, [badParam], gCredentialChallenge)
.then(arrivingHereIsBad)
.catch(expectTypeError),
// Test with an unsupported parameter, and a bad one
authn.makeCredential(acct, [unsupportedParam, badParam],
gCredentialChallenge)
.then(arrivingHereIsBad)
.catch(expectTypeError),
// Test with an unsupported parameter, a bad one, and a good one. This
// should still fail, as anything with a badParam should fail.
authn.makeCredential(acct, [unsupportedParam, badParam, param],
gCredentialChallenge)
.then(arrivingHereIsBad)
.catch(expectTypeError),
// Test without a challenge
authn.makeCredential(acct, [param], null)
.then(arrivingHereIsBad)
.catch(expectTypeError),
// Test with an invalid challenge
authn.makeCredential(acct, [param], "begone, thou ill-fitting moist glove!")
.then(arrivingHereIsBad)
.catch(expectTypeError),
// Test with duplicate parameters
authn.makeCredential(acct, [param, param, param], gCredentialChallenge)
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad),
// Test an incomplete account
authn.makeCredential({id: "none"}, [param], gCredentialChallenge)
.then(arrivingHereIsBad)
.catch(expectTypeError),
authn.makeCredential({name: "none", imageURL: "http://example.com/404"},
[param], gCredentialChallenge)
.then(arrivingHereIsBad)
.catch(expectTypeError),
// Test a complete account
authn.makeCredential({rpDisplayName: "Foxxy", displayName: "Foxxy V",
id: "foxes_are_the_best@example.com",
name: "Fox F. Foxington",
imageURL: "https://example.com/fox.svg"},
[param], gCredentialChallenge)
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad)
])
.then(function() {
SimpleTest.finish();
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,80 @@
<!DOCTYPE html>
<meta charset=utf-8>
<head>
<title>Test for W3C Web Authentication with no token</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="u2futil.js"></script>
<script type="text/javascript" src="pkijs/common.js"></script>
<script type="text/javascript" src="pkijs/asn1.js"></script>
<script type="text/javascript" src="pkijs/x509_schema.js"></script>
<script type="text/javascript" src="pkijs/x509_simpl.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<h1>Test for W3C Web Authentication with no token</h1>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1309284">Mozilla Bug 1309284</a>
<script class="testbody" type="text/javascript">
"use strict";
// Execute the full-scope test
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["security.webauth.w3c", true],
["security.webauth.u2f_enable_softtoken", false],
["security.webauth.u2f_enable_usbtoken", false]]},
function() {
isnot(navigator.authentication, undefined, "WebAuthn API endpoint must exist");
isnot(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential API endpoint must exist");
isnot(navigator.authentication.getAssertion, undefined, "WebAuthn getAssertion API endpoint must exist");
let authn = navigator.authentication;
let credentialChallenge = new Uint8Array(16);
window.crypto.getRandomValues(credentialChallenge);
let assertionChallenge = new Uint8Array(16);
window.crypto.getRandomValues(assertionChallenge);
let credentialId = new Uint8Array(128);
window.crypto.getRandomValues(credentialId);
testMakeCredential();
function testMakeCredential() {
let acct = {rpDisplayName: "none", displayName: "none", id: "none"};
let param = {type: "ScopedCred", algorithm: "p-256"};
authn.makeCredential(acct, [param], credentialChallenge)
.then(function(aResult) {
ok(false, "Should have failed.");
testAssertion();
})
.catch(function(aReason) {
ok(aReason.toString().startsWith("NotAllowedError"), aReason);
testAssertion();
});
}
function testAssertion() {
let newCredential = {
type: "ScopedCred",
id: credentialId,
transports: [ "usb" ],
}
let assertOptions = {rpId: document.origin, timeoutSeconds: 5,
allowList: [ newCredential ]};
authn.getAssertion(assertionChallenge, assertOptions)
.then(function(aResult) {
ok(false, "Should have failed.");
SimpleTest.finish();
})
.catch(function(aReason) {
ok(aReason.toString().startsWith("NotAllowedError"), aReason);
SimpleTest.finish();
})
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,162 @@
<!DOCTYPE html>
<meta charset=utf-8>
<head>
<title>Test for MakeCredential for W3C Web Authentication</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="u2futil.js"></script>
<script type="text/javascript" src="pkijs/common.js"></script>
<script type="text/javascript" src="pkijs/asn1.js"></script>
<script type="text/javascript" src="pkijs/x509_schema.js"></script>
<script type="text/javascript" src="pkijs/x509_simpl.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<h1>Test Same Origin Policy for W3C Web Authentication</h1>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1309284">Mozilla Bug 1309284</a>
<script class="testbody" type="text/javascript">
"use strict";
// Execute the full-scope test
SimpleTest.waitForExplicitFinish();
var gTrackedCredential = {};
function arrivingHereIsGood(aResult) {
ok(true, "Good result! Received a: " + aResult);
return Promise.resolve();
}
function arrivingHereIsBad(aResult) {
// TODO: Change to `ok` when Bug 1329764 lands
todo(false, "Bad result! Received a: " + aResult);
return Promise.resolve();
}
function expectSecurityError(aResult) {
// TODO: Change to `ok` when Bug 1329764 lands
todo(aResult.toString().startsWith("SecurityError"), "Expecting a SecurityError");
return Promise.resolve();
}
function keepThisScopedCredential(aScopedCredInfo) {
gTrackedCredential = {
type: aScopedCredInfo.credential.type,
id: Uint8Array.from(aScopedCredInfo.credential.id),
transports: [ "usb" ],
}
return Promise.resolve(aScopedCredInfo);
}
SpecialPowers.pushPrefEnv({"set": [["security.webauth.w3c", true],
["security.webauth.u2f_enable_softtoken", true],
["security.webauth.u2f_enable_usbtoken", false]]},
function() {
isnot(navigator.authentication, undefined, "WebAuthn API endpoint must exist");
isnot(navigator.authentication.makeCredential, undefined,
"WebAuthn makeCredential API endpoint must exist");
isnot(navigator.authentication.getAssertion, undefined,
"WebAuthn getAssertion API endpoint must exist");
let authn = navigator.authentication;
let chall = new Uint8Array(16);
window.crypto.getRandomValues(chall);
let acct = {rpDisplayName: "none", displayName: "none", id: "none"};
let param = {type: "ScopedCred", algorithm: "p-256"};
Promise.all([
// Test basic good call
authn.makeCredential(acct, [param], chall, {rpId: document.origin})
.then(keepThisScopedCredential)
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad),
// Test rpId being unset
authn.makeCredential(acct, [param], chall, {})
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad),
// Test this origin with optional fields
authn.makeCredential(acct, [param], chall,
{rpId: "user:pass@" + document.origin + ":8888"})
.then(arrivingHereIsBad)
.catch(expectSecurityError),
// Test blank rpId
authn.makeCredential(acct, [param], chall, {rpId: ""})
.then(arrivingHereIsBad)
.catch(expectSecurityError),
// Test subdomain of this origin
authn.makeCredential(acct, [param], chall,
{rpId: "subdomain." + document.origin})
.then(arrivingHereIsBad)
.catch(expectSecurityError),
// Test another origin
authn.makeCredential(acct, [param], chall, {rpId: "example.com"})
.then(arrivingHereIsBad)
.catch(expectSecurityError),
// est a different domain within the same TLD
authn.makeCredential(acct, [param], chall, {rpId: "alt.test"})
.then(arrivingHereIsBad)
.catch(expectSecurityError)
])
.then(function(){
return Promise.all([
// Test basic good call
authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
rpId: document.origin})
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad),
// Test rpId being unset
authn.getAssertion(chall, {allowList: [ gTrackedCredential ]})
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad),
// Test this origin with optional fields
authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
rpId: "user:pass@" + document.origin + ":8888"})
.then(arrivingHereIsBad)
.catch(expectSecurityError),
// Test blank rpId
authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
rpId: ""})
.then(arrivingHereIsBad)
.catch(expectSecurityError),
// Test subdomain of this origin
authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
rpId: "subdomain." + document.origin})
.then(arrivingHereIsBad)
.catch(expectSecurityError),
// Test another origin
authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
rpId: "example.com"})
.then(arrivingHereIsBad)
.catch(expectSecurityError),
// Test a different domain within the same TLD
authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
rpId: "alt.test"})
.then(arrivingHereIsBad)
.catch(expectSecurityError)
]);
})
.then(function(){
SimpleTest.finish();
});
});
</script>
</body>
</html>

View File

@ -127,6 +127,27 @@ function hexDecode(str) {
return new Uint8Array(str.match(/../g).map(x => parseInt(x, 16)));
}
function decodeU2FRegistration(aRegData) {
if (aRegData[0] != 0x05) {
return Promise.reject("Sentinal byte != 0x05");
}
let keyHandleLength = aRegData[66];
let u2fRegObj = {
publicKeyBytes: aRegData.slice(1, 66),
keyHandleBytes: aRegData.slice(67, 67 + keyHandleLength),
attestationBytes: aRegData.slice(67 + keyHandleLength)
}
u2fRegObj.keyHandle = bytesToBase64UrlSafe(u2fRegObj.keyHandleBytes);
return importPublicKey(u2fRegObj.publicKeyBytes)
.then(function(keyObj) {
u2fRegObj.publicKey = keyObj;
return u2fRegObj;
});
}
function importPublicKey(keyBytes) {
if (keyBytes[0] != 0x04 || keyBytes.byteLength != 65) {
throw "Bad public key octet string";

View File

@ -91,6 +91,6 @@ int main(int argc, char * argv[]) {
mozilla::SetStrongPtr(appData.directory, static_cast<nsIFile*>(appSubdir.get()));
greDir.forget(&appData.xreDirectory);
int result = XRE_main(argc, argv, &appData, 0);
int result = XRE_main(argc, argv, &appData);
return result;
}

View File

@ -6,8 +6,11 @@
#include "../contentproc/plugin-container.cpp"
#include "mozilla/Bootstrap.h"
#include "mozilla/WindowsDllBlocklist.h"
using namespace mozilla;
int
main(int argc, char *argv[])
{
@ -15,5 +18,10 @@ main(int argc, char *argv[])
DllBlocklist_Initialize();
#endif
return content_process_main(argc, argv);
Bootstrap::UniquePtr bootstrap;
XRE_GetBootstrap(bootstrap);
if (!bootstrap) {
return 2;
}
return content_process_main(bootstrap.get(), argc, argv);
}

View File

@ -7,6 +7,7 @@
#include "nsXPCOM.h"
#include "nsXULAppAPI.h"
#include "nsAutoPtr.h"
#include "mozilla/Bootstrap.h"
#ifdef XP_WIN
#include <windows.h>
@ -58,20 +59,20 @@ private:
};
#endif
mozilla::gmp::SandboxStarter*
mozilla::UniquePtr<mozilla::gmp::SandboxStarter>
MakeSandboxStarter()
{
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
return new WinSandboxStarter();
return mozilla::MakeUnique<WinSandboxStarter>();
#elif defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
return new MacSandboxStarter();
return mozilla::MakeUnique<MacSandboxStarter>();
#else
return nullptr;
#endif
}
int
content_process_main(int argc, char* argv[])
content_process_main(mozilla::Bootstrap* bootstrap, int argc, char* argv[])
{
// Check for the absolute minimum number of args we need to move
// forward here. We expect the last arg to be the child process type.
@ -93,13 +94,13 @@ content_process_main(int argc, char* argv[])
}
#endif
XRE_SetProcessType(argv[--argc]);
bootstrap->XRE_SetProcessType(argv[--argc]);
#ifdef XP_WIN
// For plugins, this is done in PluginProcessChild::Init, as we need to
// avoid it for unsupported plugins. See PluginProcessChild::Init for
// the details.
if (XRE_GetProcessType() != GeckoProcessType_Plugin) {
if (bootstrap->XRE_GetProcessType() != GeckoProcessType_Plugin) {
mozilla::SanitizeEnvironmentVariables();
SetDllDirectoryW(L"");
}
@ -107,13 +108,10 @@ content_process_main(int argc, char* argv[])
#if !defined(XP_LINUX) && defined(MOZ_PLUGIN_CONTAINER)
// On Windows and MacOS, the GMPLoader lives in plugin-container, so that its
// code can be covered by an EME/GMP vendor's voucher.
nsAutoPtr<mozilla::gmp::SandboxStarter> starter(MakeSandboxStarter());
if (XRE_GetProcessType() == GeckoProcessType_GMPlugin) {
childData.gmpLoader = mozilla::gmp::CreateGMPLoader(starter);
if (bootstrap->XRE_GetProcessType() == GeckoProcessType_GMPlugin) {
childData.gmpLoader = mozilla::gmp::CreateGMPLoader(MakeSandboxStarter());
}
#endif
nsresult rv = XRE_InitChildProcess(argc, argv, &childData);
NS_ENSURE_SUCCESS(rv, 1);
return 0;
nsresult rv = bootstrap->XRE_InitChildProcess(argc, argv, &childData);
return NS_FAILED(rv);
}

View File

@ -2,13 +2,16 @@
* 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/. */
#include "nsXULAppAPI.h"
#define MOZ_IPDL_TESTS
#include "mozilla/Bootstrap.h"
#if defined(XP_WIN)
#include <windows.h>
#include "nsWindowsWMain.cpp"
#endif
using namespace mozilla;
int
main(int argc, char** argv)
{
@ -16,5 +19,10 @@ main(int argc, char** argv)
if (argc < 2)
return 1;
return XRE_RunIPDLTest(argc, argv);
Bootstrap::UniquePtr bootstrap;
XRE_GetBootstrap(bootstrap);
if (!bootstrap) {
return 2;
}
return bootstrap->XRE_RunIPDLTest(argc, argv);
}

View File

@ -49,11 +49,14 @@ class CrossProcessCpowHolder : public CpowHolder
CrossProcessCpowHolder(dom::CPOWManagerGetter* managerGetter,
const InfallibleTArray<CpowEntry>& cpows);
~CrossProcessCpowHolder();
bool ToObject(JSContext* cx, JS::MutableHandleObject objp);
private:
CPOWManager* js_;
const InfallibleTArray<CpowEntry>& cpows_;
bool unwrapped_;
};
CPOWManager*

View File

@ -650,16 +650,38 @@ JavaScriptShared::fromObjectOrNullVariant(JSContext* cx, const ObjectOrNullVaria
CrossProcessCpowHolder::CrossProcessCpowHolder(dom::CPOWManagerGetter* managerGetter,
const InfallibleTArray<CpowEntry>& cpows)
: js_(nullptr),
cpows_(cpows)
cpows_(cpows),
unwrapped_(false)
{
// Only instantiate the CPOW manager if we might need it later.
if (cpows.Length())
js_ = managerGetter->GetCPOWManager();
}
CrossProcessCpowHolder::~CrossProcessCpowHolder()
{
if (cpows_.Length() && !unwrapped_) {
// This should only happen if a message manager message
// containing CPOWs gets ignored for some reason. We need to
// unwrap every incoming CPOW in this process to ensure that
// the corresponding part of the CPOW in the other process
// will eventually be collected. The scope for this object
// doesn't really matter, because it immediately becomes
// garbage.
AutoJSAPI jsapi;
if (!jsapi.Init(xpc::PrivilegedJunkScope()))
return;
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> cpows(cx);
js_->Unwrap(cx, cpows_, &cpows);
}
}
bool
CrossProcessCpowHolder::ToObject(JSContext* cx, JS::MutableHandleObject objp)
{
unwrapped_ = true;
if (!cpows_.Length())
return true;

View File

@ -717,7 +717,6 @@ WrapperOwner::hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue
return false;
ReturnStatus status;
JSVariant result;
if (!SendHasInstance(objId, vVar, &status, bp))
return ipcfail(cx);

View File

@ -63,7 +63,6 @@ var ignoreClasses = {
"JSLocaleCallbacks" : true,
"JSC::ExecutableAllocator" : true,
"PRIOMethods": true,
"XPCOMFunctions" : true, // I'm a little unsure of this one
"_MD_IOVector" : true,
"malloc_table_t": true, // replace_malloc
"malloc_hook_table_t": true, // replace_malloc

View File

@ -9,6 +9,7 @@
#include <stdio.h>
#include "mozilla/WindowsDllBlocklist.h"
#include "mozilla/Bootstrap.h"
#include "nsXULAppAPI.h"
#ifdef XP_MACOSX
@ -59,7 +60,13 @@ main(int argc, char** argv, char** envp)
mozilla::sandboxing::GetInitializedBrokerServices();
#endif
int result = XRE_XPCShellMain(argc, argv, envp, &shellData);
mozilla::Bootstrap::UniquePtr bootstrap;
XRE_GetBootstrap(bootstrap);
if (!bootstrap) {
return 2;
}
int result = bootstrap->XRE_XPCShellMain(argc, argv, envp, &shellData);
#ifdef XP_MACOSX
FinishAutoreleasePool();

View File

@ -16,10 +16,10 @@ setTimeout(function(){
document.addEventListener("DOMContentLoaded", initCF);
window.onload = initCF;
</script><!--
--> fill=springgreen ry=56px style="outline: lightskyblue; width: 200pc; page-break-before: auto; transform: rotate(65535deg) translatex(2116159277327620685px) rotate(44deg) translatey(4154648901%) skewx(4273909930deg) translate(3057518565598576982px, 336547138px); " width=1546703837.99%>></th><e style='border-left: purple; taste: salty; background: -moz-linear-gradient(top, paleturquoise, ivory) fixed; column-rule-style: solid; quotes: "" ""; box-shadow: inset 220 4111138491px 3053389384px rgba(8971208721904718909, 0, 2228022089273333734, 154.269191058), 9223372036854775808 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px 14321134px rgba(237, 3316992035388341101, -15, 118354783.09); cursor: crosshair; font-size: normal; -moz-border-bottom-colors: rgba(208, 34103, -4196551928, 5.13284545187x+18) rgba(709904815962541130, 29, -221, 209.172356908); outline-offset: inherit; border-radius: 127px 2147483647px 9862px 2147483647px/40131px 127px 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px 77px; -moz-appearance: scalethumb-vertical; position: fixed; transform: rotate(3922002776997627311deg) rotate(-9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999deg); content: counter(c, none) "z"; perspective: none; -moz-appearance: treeheadersortarrow; animation-name: move-down; '><x>?9(p`r|Agvc@m7]yrXKV.eI`mM+apR]d^UvtpnF xf]{HT~2rROiK(O,o]*XO_jgjJ+B?.EFba!(Fr v@4+=KNIKlC,<fieldset>Ta,c2 ph5ii?/duk?RWcLlmjq3!+U^6e?]^Y9 M5IglbqW;`Gwar.FPvHw0 ++cT2_(.,ZERlDsP|qL_oxzlWf7d=]1w[A%}4e1eNhq$VfqAn|TBq]Ez=.PH`GbZq PH{@L1Q[atH%XT@27m0uya/Z_-:sJ89S!/$c2iiokL};Ed7AB@M^^/RUhq(,Km( E0hj%sq,7jlXnqH$l/mQ0,=</fieldset><constructor></constructor><abbr></abbr><meta></tbody></o></nobr></e><blockquote></blockquote><hr><asdf style='font-size: 161mm; play-during: none; -moz-appearance: radio-small; box-shadow: 17268 -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px 220 hsla(1140355849941740746, 120%, 131%, 2903913.12919) inset; opacity: auto; content: "This> '>> style='margin: 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999em 8933668495516524730 -144.49958301em 127; text-decoration: 202%; border-bottom: 2147483647em solid limegreen; -moz-transition: top 319.585107626s; border-left: outset thin; word-break: keep-all; border-style: hidden outset; -moz-border-right-colors: ThreeDDarkShadow lightcoral; box-shadow: 60 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px -2953355671px hsla(103, 6839212866957213050%, 159%, 11.3751589012) inset, 191 6964375947664294657 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 60108px hsla(1475245254742113175, 47277189%, 255%, 148.45826034) inset, 29984 65535px 50252 hsla(247, 215%, -115%, 38497.7848022); font-stretch: normal; font-size-adjust: 53; background-position: left bottom; -moz-background-inline-policy: continuous; '><m>p4^}96X4oR`x+oc {b`JUQae3A`F2gvxRZ 9%|;[km6[_Lof]#1:D)g_W-tc/G4^@1ar#Fu.vH@D+[utM(9jt-,0i.KMcSfHKb4ZOeMV^(:8sM*d#?NB$eH!49rW_POT*|4@CBGqU;k_++V1AVHo2qI!UWxnXp)eH}O R]:3mjHpu[8E#O$K7Fpg4_e{Jeb<fooz style='top: -moz-calc(9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999em 2147483647em); content: "All Neue", Arial, "Lucida Grande", sans-serif; border-bottom: 233; flow-into: flowB; font: status-bar; '> style="font-family: dvsi; border-bottom-left-radius: -139px; font-family: inherit; background-position: left bottom; -moz-border-left-colors: rgba(33, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 58, 3983166662.49) mediumslateblue; counter-reset: c 128 f 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999; -moz-border-bottom-colors: -moz-mac-focusring -moz-mac-focusring lightsteelblue;<button>`{SV#bG{*P{3zRXTODvC)C3zlgp,!S81J.YH|,x]U=%P%8)U#]04H5o/Bno;gZDo]H1LMK I?~O,^Hqw@6k%J9FQ|{jkXv QgeAGtzM1# :Ue1-VAa+N0sNP`yINYAIy:d!?I{_FsB7sAx Jfr,4w~cV#:I3H0,z0b$5C.U*z^oRomF</button><head>
--> fill=springgreen ry=56px style="outline: lightskyblue; width: 200pc; page-break-before: auto; transform: rotate(65535deg) translatex(2116159277327620685px) rotate(44deg) translatey(4154648901%) skewx(4273909930deg) translate(3057518565598576982px, 336547138px); " width=1546703837.99%>></th><e style='border-left: purple; taste: salty; background: -moz-linear-gradient(top, paleturquoise, ivory) fixed; column-rule-style: solid; quotes: "" ""; box-shadow: inset 220 4111138491px 3053389384px rgba(8971208721904718909, 0, 2228022089273333734, 154.269191058), 9223372036854775808 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px 14321134px rgba(237, 3316992035388341101, -15, 118354783.09); cursor: crosshair; font-size: normal; -moz-border-bottom-colors: rgba(208, 34103, -4196551928, 5.13284545187x+18) rgba(709904815962541130, 29, -221, 209.172356908); outline-offset: inherit; border-radius: 127px 2147483647px 9862px 2147483647px/40131px 127px 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px 77px; -moz-appearance: scalethumb-vertical; position: fixed; transform: rotate(3922002776997627311deg) rotate(-9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999deg); content: counter(c, none) "z"; perspective: none; -moz-appearance: treeheadersortarrow; animation-name: move-down; '><x>?9(p`r|Agvc@m7]yrXKV.eI`mM+apR]d^UvtpnF xf]{HT~2rROiK(O,o]*XO_jgjJ+B?.EFba!(Fr v@4+=KNIKlC,<fieldset>Ta,c2 ph5ii?/duk?RWcLlmjq3!+U^6e?]^Y9 M5IglbqW;`Gwar.FPvHw0 ++cT2_(.,ZERlDsP|qL_oxzlWf7d=]1w[A%}4e1eNhq$VfqAn|TBq]Ez=.PH`GbZq PH{@L1Q[atH%XT@27m0uya/Z_-:sJ89S!/$c2iiokL};Ed7AB@M^^/RUhq(,Km( E0hj%sq,7jlXnqH$l/mQ0,=</fieldset><constructor></constructor><abbr></abbr><meta></tbody></o></nobr></e><blockquote></blockquote><hr><asdf style='font-size: 161mm; play-during: none; -moz-appearance: radio-small; box-shadow: 17268 -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px 220 hsla(1140355849941740746, 120%, 131%, 2903913.12919) inset; opacity: auto; content: "This> '>> style='margin: 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999em 8933668495516524730 -144.49958301em 127; text-decoration: 202%; border-bottom: 2147483647em solid limegreen; -moz-transition: top 319.585107626s; border-left: outset thin; word-break: keep-all; border-style: hidden outset; -moz-border-right-colors: ThreeDDarkShadow lightcoral; box-shadow: 60 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px -2953355671px hsla(103, 6839212866957213050%, 159%, 11.3751589012) inset, 191 6964375947664294657 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 60108px hsla(1475245254742113175, 47277189%, 255%, 148.45826034) inset, 29984 65535px 50252 hsla(247, 215%, -115%, 38497.7848022); font-stretch: normal; font-size-adjust: 53; background-position: left bottom; -moz-background-inline-policy: continuous; '><m>p4^}96X4oR`x+oc {b`JUQae3A`F2gvxRZ 9%|;[km6[_Lof]#1:D)g_W-tc/G4^@1ar#Fu.vH@D+[utM(9jt-,0i.KMcSfHKb4ZOeMV^(:8sM*d#?NB$eH!49rW_POT*|4@CBGqU;k_++V1AVHo2qI!UWxnXp)eH}O R]:3mjHpu[8E#O$K7Fpg4_e{Jeb<fooz style='top: calc(9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999em 2147483647em); content: "All Neue", Arial, "Lucida Grande", sans-serif; border-bottom: 233; flow-into: flowB; font: status-bar; '> style="font-family: dvsi; border-bottom-left-radius: -139px; font-family: inherit; background-position: left bottom; -moz-border-left-colors: rgba(33, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 58, 3983166662.49) mediumslateblue; counter-reset: c 128 f 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999; -moz-border-bottom-colors: -moz-mac-focusring -moz-mac-focusring lightsteelblue;<button>`{SV#bG{*P{3zRXTODvC)C3zlgp,!S81J.YH|,x]U=%P%8)U#]04H5o/Bno;gZDo]H1LMK I?~O,^Hqw@6k%J9FQ|{jkXv QgeAGtzM1# :Ue1-VAa+N0sNP`yINYAIy:d!?I{_FsB7sAx Jfr,4w~cV#:I3H0,z0b$5C.U*z^oRomF</button><head>
></title>
<link href=/tests/SimpleTest/test.css<b></b><frame>MS|;yTvb=DyYx=lZ5?NTu=.N@mwsqT!v:=zew_XR7O8YY1o%1=$Oqh=2%a|{M?e/q6]/0VH?s,l4wf!00M7BMNP+j*T?E:POnu? yKL8[Y_nlz+u%QSJB9<csaction>><bdi>w!7RF+P3o}#/~=5hL{2dypxHnV4|@}.jSm@IQ-Ia*i[^/cip/.PKGEX|`bu6+/2RG6}m_*iFTeK~5iI/Zvl.*~32e(_$L#f|1UEh~[Oc_Ej;5Ff:#-?/*W=SLD,kda-7.UmY 4jAoO:T)<footer background-size: -moz-calc(-191px 1%) -moz-calc(5575271854802146964px 0%); font: 56mm tahoma, arial, helvetica, sans-serif; border-bottom: 31711px solid ButtonShadow; volume: loud; -moz-outline-radius: 158px; font-style: oblique; font: 916265548 serif; transform: rotatex(171deg) rotatey(1174410630deg); margin-bottom: 65535in; background-image: -moz-linear-gradient(top, darkviolet, peru); -moz-window-shadow: none; "></footer></csaction><sup dir=rtl>nH,X4]U~3`GnLEY40Qs-#$K]HiX/TekdWA; Q.IGJJwTi%sB^TF^_MFf%3q; wo#]Jy[t8hywiU`ev+8no:+1!Vo?A1tbO{A$iee~-@3Xmt?jzISs1u]B!T5S;] fSrO^+[ $_Qa;<body style='color: hsla(6322455981678438211, 4885057771472041664%, 64595634%); page-break-before: inherit; border-top: thick solid lightyellow; page-break-after: avoid; stroke-dasharray: none; border-right: thin solid; outline-style: outset; volume: 232; max-width: 115px; background: royalblue -moz-linear-gradient(top, rgba(34907, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 4705143634018575181, 134.650893313) 196%, rgba(98, 0, 21, 93) 5835518181644000612%); border-bottom-style: double; background-color: -moz-mac-secondaryhighlight; border-bottom-style: solid; content: "Before"; azimuth: center; '>
</ul> style='text-align-last: left; -webkit-appearance: textfield; color: rgb(-905311699%, 114, 57742); padding: 21.8234098837em 9.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999em 9.51366390673em 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999em; border-color: rgba(202, 9223372036854775808, -127, 4.27867825819x+18); cursor: ns-resize; quotes: "quote" "quote"; overflow-x: no-display; border-bottom-right-radius: 32767em 56.2654742136em; box-shadow: 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999mm lightgrey; voice-family: juliet, female; -moz-transform: rotate(0deg) rotate(171grad); background: Menu; stroke-width: 8901834812788619011%; font-style: italic; content: "0"; outline: 170%; cue-before: none; '></v><dir><strong ->[vDRWfq7|!j5~J^5eQL.?J5VYFl{Vgied3%-fH^bH6?O 4mTi#]%o1xFl.O5hoZ3B;ZRx;1$T2,mgbh5dOeQ*m01547dC1/0V#Y.~WW$ragJ0n!EvBkg8Uegi+]ou1j/^QO*femQC2O!P!j,M5Vk@.-`g`$$+f+^ VP~G{1U</mi><noscript></noscript><rdf>Z[kyp(Mt0@4F~xj@v b=,K#nikG!cNac%qU(O/iUs62cwzV#,6jC[!1y5,PBNr@,Gh~Yn43l1B}p1KEh$m|bn}saNpLjZaspCwM4}XA?CWl)%V]lmIORhh y}o(CHz*vog3iSJ#On-w65NZ=}?5lh/x;xgps-#FD6l,MuASFyd$r.}x6;:v0iM4-S`El`hX%x</rdf><sub></sub><textarea>Fi~{@7J{EVzWdri*Uy+C2nP=gmz.Y;Wvp*:F]]VIVMqdJM=oU,.`Veo:L_x~1u`*f2(!*SGS*!Tsm+VYIeWA^CD10rrxyeMbNhM:SL-}Zf*A4Lf= 81Ka{/gieIN3Ru?#*Sl@~tYe]D.~pEm=s.=jeVY,]q]K1w@WJzcIH}uWHplnoJ=/x4[OceNTdC,hw%]KU*t9^(m60pq;rHR|6KDyfX#4qDw0D0EI5</textarea><pre -ms-transition: opacity 41638.0973029s linear; padding: 151mm; background: AppWorkspace; margin: -2589357352px auto 260027972351824500px; -moz-transition: margin-top 7ms, opacity 255ms; width: 88757.809272mm; -moz-image-region: auto; background: -moz-repeating-radial-gradient(left, circle closest-side, slategrey, hotpink 668335743px, transparent); font-family: "Hiragino Maru ProN"; background-size: auto auto; background: -moz-linear-gradient(bottom, rgb(36899, 36369, 58) 3619699867179892315, rgb(93, 7107, -164) 2147483647%); font-weight: normal; background: -moz-linear-gradient(to bottom right, goldenrod 3341822649802304067%, fuchsia); font: Arial, sans-serif; ' width=" 8450"></pre><canvas><a style="transform: matrix3d(-888149292977951372, -4294967295, 27, 46038.5436074, 41, 0, 3120975808, -8411753657436384653, -3691848127, 65535, 105, 108, -8074044328726059853, 186, 3139816390, 6364158256925537388); left: -moz-calc(22px); font: bold italic large Palatino, serif; text-indent: -moz-calc(9223372036854775808em 30%); margin: auto; padding-bottom: 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999; background: -moz-linear-gradient(rgba(50924, 1251548303, 1109767611702038730, 42159.1644524), rgba(55, 2591341078, 10, 143) 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999%, rgba(43, 246, 149, 1.28599451055x+18) 58741%, rgba(-69, 8229554636392401175, 33463, 67.9323179507)); border-top: -67.3406928376em solid; content: counter(item); border-bottom-width: medium; " target=_blank></a>
<link href=/tests/SimpleTest/test.css<b></b><frame>MS|;yTvb=DyYx=lZ5?NTu=.N@mwsqT!v:=zew_XR7O8YY1o%1=$Oqh=2%a|{M?e/q6]/0VH?s,l4wf!00M7BMNP+j*T?E:POnu? yKL8[Y_nlz+u%QSJB9<csaction>><bdi>w!7RF+P3o}#/~=5hL{2dypxHnV4|@}.jSm@IQ-Ia*i[^/cip/.PKGEX|`bu6+/2RG6}m_*iFTeK~5iI/Zvl.*~32e(_$L#f|1UEh~[Oc_Ej;5Ff:#-?/*W=SLD,kda-7.UmY 4jAoO:T)<footer background-size: calc(-191px 1%) calc(5575271854802146964px 0%); font: 56mm tahoma, arial, helvetica, sans-serif; border-bottom: 31711px solid ButtonShadow; volume: loud; -moz-outline-radius: 158px; font-style: oblique; font: 916265548 serif; transform: rotatex(171deg) rotatey(1174410630deg); margin-bottom: 65535in; background-image: -moz-linear-gradient(top, darkviolet, peru); -moz-window-shadow: none; "></footer></csaction><sup dir=rtl>nH,X4]U~3`GnLEY40Qs-#$K]HiX/TekdWA; Q.IGJJwTi%sB^TF^_MFf%3q; wo#]Jy[t8hywiU`ev+8no:+1!Vo?A1tbO{A$iee~-@3Xmt?jzISs1u]B!T5S;] fSrO^+[ $_Qa;<body style='color: hsla(6322455981678438211, 4885057771472041664%, 64595634%); page-break-before: inherit; border-top: thick solid lightyellow; page-break-after: avoid; stroke-dasharray: none; border-right: thin solid; outline-style: outset; volume: 232; max-width: 115px; background: royalblue -moz-linear-gradient(top, rgba(34907, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 4705143634018575181, 134.650893313) 196%, rgba(98, 0, 21, 93) 5835518181644000612%); border-bottom-style: double; background-color: -moz-mac-secondaryhighlight; border-bottom-style: solid; content: "Before"; azimuth: center; '>
</ul> style='text-align-last: left; -webkit-appearance: textfield; color: rgb(-905311699%, 114, 57742); padding: 21.8234098837em 9.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999em 9.51366390673em 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999em; border-color: rgba(202, 9223372036854775808, -127, 4.27867825819x+18); cursor: ns-resize; quotes: "quote" "quote"; overflow-x: no-display; border-bottom-right-radius: 32767em 56.2654742136em; box-shadow: 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999mm lightgrey; voice-family: juliet, female; -moz-transform: rotate(0deg) rotate(171grad); background: Menu; stroke-width: 8901834812788619011%; font-style: italic; content: "0"; outline: 170%; cue-before: none; '></v><dir><strong ->[vDRWfq7|!j5~J^5eQL.?J5VYFl{Vgied3%-fH^bH6?O 4mTi#]%o1xFl.O5hoZ3B;ZRx;1$T2,mgbh5dOeQ*m01547dC1/0V#Y.~WW$ragJ0n!EvBkg8Uegi+]ou1j/^QO*femQC2O!P!j,M5Vk@.-`g`$$+f+^ VP~G{1U</mi><noscript></noscript><rdf>Z[kyp(Mt0@4F~xj@v b=,K#nikG!cNac%qU(O/iUs62cwzV#,6jC[!1y5,PBNr@,Gh~Yn43l1B}p1KEh$m|bn}saNpLjZaspCwM4}XA?CWl)%V]lmIORhh y}o(CHz*vog3iSJ#On-w65NZ=}?5lh/x;xgps-#FD6l,MuASFyd$r.}x6;:v0iM4-S`El`hX%x</rdf><sub></sub><textarea>Fi~{@7J{EVzWdri*Uy+C2nP=gmz.Y;Wvp*:F]]VIVMqdJM=oU,.`Veo:L_x~1u`*f2(!*SGS*!Tsm+VYIeWA^CD10rrxyeMbNhM:SL-}Zf*A4Lf= 81Ka{/gieIN3Ru?#*Sl@~tYe]D.~pEm=s.=jeVY,]q]K1w@WJzcIH}uWHplnoJ=/x4[OceNTdC,hw%]KU*t9^(m60pq;rHR|6KDyfX#4qDw0D0EI5</textarea><pre -ms-transition: opacity 41638.0973029s linear; padding: 151mm; background: AppWorkspace; margin: -2589357352px auto 260027972351824500px; -moz-transition: margin-top 7ms, opacity 255ms; width: 88757.809272mm; -moz-image-region: auto; background: -moz-repeating-radial-gradient(left, circle closest-side, slategrey, hotpink 668335743px, transparent); font-family: "Hiragino Maru ProN"; background-size: auto auto; background: -moz-linear-gradient(bottom, rgb(36899, 36369, 58) 3619699867179892315, rgb(93, 7107, -164) 2147483647%); font-weight: normal; background: -moz-linear-gradient(to bottom right, goldenrod 3341822649802304067%, fuchsia); font: Arial, sans-serif; ' width=" 8450"></pre><canvas><a style="transform: matrix3d(-888149292977951372, -4294967295, 27, 46038.5436074, 41, 0, 3120975808, -8411753657436384653, -3691848127, 65535, 105, 108, -8074044328726059853, 186, 3139816390, 6364158256925537388); left: calc(22px); font: bold italic large Palatino, serif; text-indent: calc(9223372036854775808em 30%); margin: auto; padding-bottom: 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999; background: -moz-linear-gradient(rgba(50924, 1251548303, 1109767611702038730, 42159.1644524), rgba(55, 2591341078, 10, 143) 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999%, rgba(43, 246, 149, 1.28599451055x+18) 58741%, rgba(-69, 8229554636392401175, 33463, 67.9323179507)); border-top: -67.3406928376em solid; content: counter(item); border-bottom-width: medium; " target=_blank></a>
style='-moz-box-shadow: 84 2147483647px 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px rgba(-2858581034, 110, 2460321770, 164.188187767), inset 18 255px -2461791714 rgba(65, 2147483647, 118, 120365.670275); border-color: khaki rgb(9223372036854775808, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999) cornsilk rgb(2147483647, 3410481331, -255); background: -moz-linear-gradient(top, hsl(-6511, 132%, 67%), hsl(65535, 127%, 130%)); border-inline-end-width: 5361121852315046626; content: "»"; box-shadow: inset -148 6598830410571865803 -255px hsla(65535, -61299%, 6601653806716150645%, 144.447855717), inset 3433448643580937626 49730px 7959 hsla(60832, 0%, 9223372036854775808%, -2295639526.68); transform: translate3d(9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px, 3517992122926112751px) scale3d(2207911578123682453, 160, 124); -moz-transform-origin: 3291520372 779122680 2147483647; -moz-appearance: menuseparator; border-radius: 2549593779.31px 2.00538639825x+18px 65px 28px; transform: translate(127px, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px) translate(9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px, -176px); margin-left: 210.617676718em; border-inline-start: dotted lightgreen 37018px; word-spacing: 2174513215933018269ch; border-left: solid; columns: 64383 auto -3982463664em; -moz-transform: scale(9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); stroke-width: 3.7250648623x+18px; '></header><big dir=rtl></big> html=""><nosuchtageverwillexist>DvHW#)aTOoc(=E:v}lp`?)_zpj%f#fy$q~~w1,;%.rsdVNR9=AW8h#y**wpXSlY}R/L|vnxW7?EC`lK,4GcMz[9}{V#d+@d (`JUMD2gD:N1ci7Q#i_hR-p.,dM|s/D-bzFn@8g[.qr;+Kh!]tI3B?2xM;E,oW`GHsjqV>b(vf_HY9If%6.t7z2@ql6|L@SrsUoaG^AX{46e5^;p;8Pphf5f3_],qD)X!kizvdkcp8YtJZe!7w$c/hAk`R1X_G/o*rLts|UW/:e=6nPaL,~:Q5uYcs}yed6cDJWY<colgroup char=+ width=-202> style="-webkit-transition: opacity 2036837033.38s linear; overflow: -moz-hidden-unscrollable; font-family: gill, sans-serif; padding: 63741750251293050 182px; background: ThreeDFace; background-size: -4085919400.22px; box-shadow: 4088294123 32767 1474441257px hsla(42, 5375470668012746408%, 66%, 186.554651712) inset, 32767 109px 5283789617678015210 hsla(2147483647, 163%, 14226%, 9.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999); border-width: 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999px -170px 3284222322px 5.14851574865x+17px; box-shadow: inset 113 -0 -4px hsla(9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999, 35273%, 2245175778%, 47085.004822), inset 9223372036854775808 76px 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 hsla(2375057167019052381, 4294967295%, 127%, 5.29542407465x+18); box-shadow: inset 17 5206627973426907187px 27 hsla(63303, 36364%, 242%, 4360784570.91), inset 18428 0px 138 hsla(-357953447, 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999%, 8058132474996186951%, 100.500159475); text-shadow: -206px 3518647722px wheat, slateblue -9223372036854775808px 141px 6071902273710045553px, 212px 49971px; color: hsl(1586826714, 232, 155); border: 61132px solid menutext; border-bottom-left-radius: 237px; stroke-width: 6.74219888253x+18; -o-flow-into: flowB; "><legend>>>>>>></wbr>>> id=content lang=ja style="display: none">
</div>

Some files were not shown because too many files have changed in this diff Show More