mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Merge m-i to m-c, a=merge
This commit is contained in:
commit
a747e7e178
@ -154,10 +154,12 @@ install-manifests: $(addprefix install-,$(install_manifests))
|
||||
|
||||
# If we're using the hybrid FasterMake/RecursiveMake backend, we want
|
||||
# to recurse in the faster/ directory in parallel of install manifests.
|
||||
# But dist/idl needs to happen before (cf. dependencies in
|
||||
# config/faster/rules.mk)
|
||||
ifneq (,$(filter FasterMake+RecursiveMake,$(BUILD_BACKENDS)))
|
||||
install-manifests: faster
|
||||
.PHONY: faster
|
||||
faster:
|
||||
faster: install-dist/idl
|
||||
$(MAKE) -C faster FASTER_RECURSIVE_MAKE=1
|
||||
endif
|
||||
|
||||
@ -181,7 +183,7 @@ endif
|
||||
$(addprefix $(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )$*) ,$(wildcard _build_manifests/install/$(subst /,_,$*)))
|
||||
|
||||
# Dummy wrapper rule to allow the faster backend to piggy back
|
||||
install-dist_%: install-dist/% ;
|
||||
$(addprefix install-,$(subst /,_,$(filter dist/%,$(install_manifests)))): install-dist_%: install-dist/% ;
|
||||
|
||||
# For compatibility
|
||||
.PHONY: install-tests
|
||||
|
@ -677,7 +677,7 @@ getRoleCB(AtkObject *aAtkObj)
|
||||
#include "RoleMap.h"
|
||||
default:
|
||||
MOZ_CRASH("Unknown role.");
|
||||
};
|
||||
}
|
||||
|
||||
#undef ROLE
|
||||
|
||||
|
@ -251,7 +251,7 @@ ia2Accessible::role(long* aRole)
|
||||
#include "RoleMap.h"
|
||||
default:
|
||||
MOZ_CRASH("Unknown role.");
|
||||
};
|
||||
}
|
||||
|
||||
#undef ROLE
|
||||
|
||||
|
@ -452,7 +452,7 @@ AccessibleWrap::get_accRole(
|
||||
#include "RoleMap.h"
|
||||
default:
|
||||
MOZ_CRASH("Unknown role.");
|
||||
};
|
||||
}
|
||||
|
||||
#undef ROLE
|
||||
|
||||
|
@ -346,7 +346,7 @@ xpcAccessible::GetBounds(int32_t* aX, int32_t* aY,
|
||||
*aX = rect.x;
|
||||
*aY = rect.y;
|
||||
*aWidth = rect.width;
|
||||
*aHeight = rect.height;;
|
||||
*aHeight = rect.height;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
18
addon-sdk/source/app-extension/bootstrap.js
vendored
18
addon-sdk/source/app-extension/bootstrap.js
vendored
@ -26,6 +26,8 @@ const appInfo = Cc["@mozilla.org/xre/app-info;1"].
|
||||
const vc = Cc["@mozilla.org/xpcom/version-comparator;1"].
|
||||
getService(Ci.nsIVersionComparator);
|
||||
|
||||
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
|
||||
|
||||
const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
|
||||
|
||||
|
||||
@ -48,18 +50,12 @@ function setResourceSubstitution(domain, uri) {
|
||||
// Utility function that synchronously reads local resource from the given
|
||||
// `uri` and returns content string.
|
||||
function readURI(uri) {
|
||||
let ioservice = Cc['@mozilla.org/network/io-service;1'].
|
||||
getService(Ci.nsIIOService);
|
||||
let channel = NetUtil.newChannel({
|
||||
uri: NetUtil.newURI(uri, 'UTF-8'),
|
||||
loadUsingSystemPrincipal: true
|
||||
});
|
||||
|
||||
let channel = ioservice.newChannel2(uri,
|
||||
'UTF-8',
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
systemPrincipal,
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
let stream = channel.open();
|
||||
let stream = channel.open2();
|
||||
|
||||
let cstream = Cc['@mozilla.org/intl/converter-input-stream;1'].
|
||||
createInstance(Ci.nsIConverterInputStream);
|
||||
|
@ -81,7 +81,7 @@ function readURISync(uri, charset) {
|
||||
let channel = NetUtil.newChannel({
|
||||
uri: NetUtil.newURI(uri, charset),
|
||||
loadUsingSystemPrincipal: true});
|
||||
let stream = channel.open();
|
||||
let stream = channel.open2();
|
||||
|
||||
let count = stream.available();
|
||||
let data = NetUtil.readInputStreamToString(stream, count, { charset : charset });
|
||||
|
@ -15,8 +15,8 @@
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 193213220,
|
||||
"digest": "58b8ebd8de923117831dcbba71172a53e26c25bd16c2b2bb363a1254f2cd4e87f95e2c5f41e2dce10e18e43a17e0a395637c9ddcbf1e27673582792f9095c62e",
|
||||
"size": 80164520,
|
||||
"digest": "26fd5301aaf6174a0e4f2ac3a8d19f39573f78a051aa78e876c065d60421b2b62207c11fbf1f20f92ba61acc4b9ce58d05409bf5af886943891b04c3d22f5e04",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
@ -1046,16 +1046,33 @@ var PageInfoListener = {
|
||||
document = content.document;
|
||||
}
|
||||
|
||||
let imageElement = message.objects.imageElement;
|
||||
|
||||
let pageInfoData = {metaViewRows: this.getMetaInfo(document),
|
||||
docInfo: this.getDocumentInfo(document),
|
||||
feeds: this.getFeedsInfo(document, strings),
|
||||
windowInfo: this.getWindowInfo(window)};
|
||||
windowInfo: this.getWindowInfo(window),
|
||||
imageInfo: this.getImageInfo(imageElement)};
|
||||
|
||||
sendAsyncMessage("PageInfo:data", pageInfoData);
|
||||
|
||||
// Separate step so page info dialog isn't blank while waiting for this to finish.
|
||||
this.getMediaInfo(document, window, strings);
|
||||
},
|
||||
|
||||
getImageInfo: function(imageElement) {
|
||||
let imageInfo = null;
|
||||
if (imageElement) {
|
||||
imageInfo = {
|
||||
currentSrc: imageElement.currentSrc,
|
||||
width: imageElement.width,
|
||||
height: imageElement.height,
|
||||
imageText: imageElement.title || imageElement.alt
|
||||
};
|
||||
}
|
||||
return imageInfo;
|
||||
},
|
||||
|
||||
getMetaInfo: function(document) {
|
||||
let metaViewRows = [];
|
||||
|
||||
|
@ -1069,6 +1069,9 @@ nsContextMenu.prototype = {
|
||||
},
|
||||
|
||||
viewImageInfo: function() {
|
||||
// Don't need to pass in ownerDocument.defaultView.top.document here;
|
||||
// window.gBrowser.selectedBrowser.currentURI.spec does the job without
|
||||
// using CPOWs
|
||||
BrowserPageInfo(null, "mediaTab", this.target);
|
||||
},
|
||||
|
||||
|
@ -349,7 +349,7 @@ function onLoadPageInfo()
|
||||
.notifyObservers(window, "page-info-dialog-loaded", null);
|
||||
}
|
||||
|
||||
function loadPageInfo(frameOuterWindowID)
|
||||
function loadPageInfo(frameOuterWindowID, imageElement)
|
||||
{
|
||||
let mm = window.opener.gBrowser.selectedBrowser.messageManager;
|
||||
|
||||
@ -361,7 +361,8 @@ function loadPageInfo(frameOuterWindowID)
|
||||
|
||||
// Look for pageInfoListener in content.js. Sends message to listener with arguments.
|
||||
mm.sendAsyncMessage("PageInfo:getData", {strings: gStrings,
|
||||
frameOuterWindowID: frameOuterWindowID});
|
||||
frameOuterWindowID: frameOuterWindowID},
|
||||
{ imageElement });
|
||||
|
||||
let pageInfoData;
|
||||
|
||||
@ -375,6 +376,8 @@ function loadPageInfo(frameOuterWindowID)
|
||||
docInfo.documentURIObject.originCharset);
|
||||
gDocInfo = docInfo;
|
||||
|
||||
gImageElement = pageInfoData.imageInfo;
|
||||
|
||||
var titleFormat = windowInfo.isTopWindow ? "pageInfo.page.title"
|
||||
: "pageInfo.frame.title";
|
||||
document.title = gBundle.getFormattedString(titleFormat, [docInfo.location]);
|
||||
@ -478,19 +481,11 @@ function loadTab(args)
|
||||
// If the "View Image Info" context menu item was used, the related image
|
||||
// element is provided as an argument. This can't be a background image.
|
||||
let imageElement = args && args.imageElement;
|
||||
if (imageElement) {
|
||||
gImageElement = {currentSrc: imageElement.currentSrc,
|
||||
width: imageElement.width, height: imageElement.height,
|
||||
imageText: imageElement.title || imageElement.alt};
|
||||
}
|
||||
else {
|
||||
gImageElement = null;
|
||||
}
|
||||
|
||||
let frameOuterWindowID = args && args.frameOuterWindowID;
|
||||
|
||||
/* Load the page info */
|
||||
loadPageInfo(frameOuterWindowID);
|
||||
loadPageInfo(frameOuterWindowID, imageElement);
|
||||
|
||||
var initialTab = (args && args.initialTab) || "generalTab";
|
||||
var radioGroup = document.getElementById("viewGroup");
|
||||
|
@ -42,7 +42,7 @@
|
||||
<description when-mixedcontent="active-loaded">&identity.activeLoaded;</description>
|
||||
<description class="identity-popup-warning-yellow"
|
||||
when-ciphers="weak">&identity.weakEncryption;</description>
|
||||
<description when-loginforms="insecure">&identity.insecureLoginForms;</description>
|
||||
<description when-loginforms="insecure">&identity.insecureLoginForms2;</description>
|
||||
</vbox>
|
||||
</vbox>
|
||||
<button id="identity-popup-security-expander"
|
||||
|
@ -83,38 +83,21 @@ var gMainPane = {
|
||||
setEventListener("e10sAutoStart", "command",
|
||||
gMainPane.enableE10SChange);
|
||||
let e10sCheckbox = document.getElementById("e10sAutoStart");
|
||||
e10sCheckbox.checked = Services.appinfo.browserTabsRemoteAutostart;
|
||||
|
||||
// If e10s is blocked for some reason unrelated to prefs, we want to disable
|
||||
// the checkbox.
|
||||
if (!Services.appinfo.browserTabsRemoteAutostart) {
|
||||
let e10sBlockedReason = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
|
||||
let appinfo = Services.appinfo.QueryInterface(Ci.nsIObserver);
|
||||
appinfo.observe(e10sBlockedReason, "getE10SBlocked", "")
|
||||
if (e10sBlockedReason.data) {
|
||||
if (e10sBlockedReason.data == "Safe mode") {
|
||||
// If the only reason we're disabled is because of safe mode, then
|
||||
// we want to allow the user to un-toggle the pref.
|
||||
// We're relying on the nsAppRunner code only specifying "Safe mode"
|
||||
// as the reason if the pref is otherwise enabled, and there are no
|
||||
// other reasons to block e10s.
|
||||
// Update the checkbox to reflect the pref state.
|
||||
e10sCheckbox.checked = true;
|
||||
} else {
|
||||
e10sCheckbox.disabled = true;
|
||||
let updateChannel = UpdateUtils.UpdateChannel;
|
||||
// only add this label on developer channels
|
||||
if (updateChannel == "default" ||
|
||||
updateChannel == "nightly" ||
|
||||
updateChannel == "aurora") {
|
||||
e10sCheckbox.label += " (disabled: " + e10sBlockedReason.data + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
let e10sPref = document.getElementById("browser.tabs.remote.autostart");
|
||||
let e10sTempPref = document.getElementById("e10sTempPref");
|
||||
let e10sForceEnable = document.getElementById("e10sForceEnable");
|
||||
|
||||
let preffedOn = e10sPref.value || e10sTempPref.value || e10sForceEnable.value;
|
||||
|
||||
if (preffedOn) {
|
||||
// The checkbox is checked if e10s is preffed on.
|
||||
e10sCheckbox.checked = true;
|
||||
|
||||
// but if it's force disabled, then the checkbox is disabled.
|
||||
e10sCheckbox.disabled = !Services.appinfo.browserTabsRemoteAutostart;
|
||||
}
|
||||
|
||||
// If E10S is blocked because of safe mode, we want the checkbox to be
|
||||
// enabled
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_DEV_EDITION
|
||||
|
@ -16,6 +16,9 @@
|
||||
<preference id="e10sTempPref"
|
||||
name="browser.tabs.remote.autostart.2"
|
||||
type="bool"/>
|
||||
<preference id="e10sForceEnable"
|
||||
name="browser.tabs.remote.force-enable"
|
||||
type="bool"/>
|
||||
#endif
|
||||
|
||||
<!-- Startup -->
|
||||
|
@ -14,8 +14,8 @@
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 193213220,
|
||||
"digest": "58b8ebd8de923117831dcbba71172a53e26c25bd16c2b2bb363a1254f2cd4e87f95e2c5f41e2dce10e18e43a17e0a395637c9ddcbf1e27673582792f9095c62e",
|
||||
"size": 80164520,
|
||||
"digest": "26fd5301aaf6174a0e4f2ac3a8d19f39573f78a051aa78e876c065d60421b2b62207c11fbf1f20f92ba61acc4b9ce58d05409bf5af886943891b04c3d22f5e04",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
@ -10,8 +10,8 @@
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 215952362,
|
||||
"digest": "5e9825dbe83b2a157879076da70fc5c989a1638e30d3b14a9901b166db09013c356a9dc4eaf6c16209a1832d9cb1c67ca869e9b9003cab8355a7f03b3dc08775",
|
||||
"size": 93295855,
|
||||
"digest": "2b8fd0c1ba337a7035090c420305a7892e663ce6781569b100b36fa21cc26146e67f44a34c7715f0004f48bbe46c232bbbf2928c9d0595243d2584530770b504",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.bz2",
|
||||
"unpack": true
|
||||
|
@ -19,6 +19,7 @@ XPCSHELL_TESTS_MANIFESTS += ['chrome/test/xpcshell/xpcshell.ini']
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'chrome/test/mochitest/browser.ini',
|
||||
]
|
||||
MARIONETTE_LOOP_MANIFESTS += ['manifest.ini']
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Loop', 'Client')
|
||||
|
@ -748,7 +748,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
||||
<!ENTITY identity.connectionFile "This page is stored on your computer.">
|
||||
<!ENTITY identity.connectionVerified1 "You are securely connected to this site, run by:">
|
||||
<!ENTITY identity.connectionInternal "This is a secure &brandShortName; page.">
|
||||
<!ENTITY identity.insecureLoginForms "Your login could be compromised.">
|
||||
<!ENTITY identity.insecureLoginForms2 "Logins entered on this page could be compromised.">
|
||||
|
||||
<!-- Strings for connection state warnings. -->
|
||||
<!ENTITY identity.activeBlocked "&brandShortName; has blocked parts of this page that are not secure.">
|
||||
|
@ -68,10 +68,6 @@ endif
|
||||
# toolkit/content/buildconfig.html and browser/locales/jar.mn.
|
||||
ACDEFINES += -DBUILD_FASTER
|
||||
|
||||
# Generic rule to fall back to the recursive make backend
|
||||
$(TOPOBJDIR)/%: FORCE
|
||||
$(MAKE) -C $(dir $@) $(notdir $@)
|
||||
|
||||
# Files under the faster/ sub-directory, however, are not meant to use the
|
||||
# fallback
|
||||
$(TOPOBJDIR)/faster/%: ;
|
||||
@ -83,6 +79,13 @@ $(TOPOBJDIR)/dist/%:
|
||||
mkdir -p $(@D)
|
||||
cp $< $@
|
||||
|
||||
# Generic rule to fall back to the recursive make backend.
|
||||
# This needs to stay after other $(TOPOBJDIR)/* rules because GNU Make
|
||||
# <3.82 apply pattern rules in definition order, not stem length like
|
||||
# modern GNU Make.
|
||||
$(TOPOBJDIR)/%: FORCE
|
||||
$(MAKE) -C $(dir $@) $(notdir $@)
|
||||
|
||||
# Install files using install manifests
|
||||
#
|
||||
# The list of base directories is given in INSTALL_MANIFESTS. The
|
||||
@ -114,8 +117,12 @@ $(TOPOBJDIR)/dist/bin/platform.ini: $(TOPOBJDIR)/toolkit/xre/platform.ini
|
||||
$(TOPOBJDIR)/toolkit/xre/platform.ini: $(TOPOBJDIR)/config/buildid
|
||||
|
||||
# The xpidl target in config/makefiles/xpidl requires the install manifest for
|
||||
# dist/idl to have been processed.
|
||||
# dist/idl to have been processed. When using the hybrid
|
||||
# FasterMake/RecursiveMake backend, this dependency is handled in the top-level
|
||||
# Makefile.
|
||||
ifndef FASTER_RECURSIVE_MAKE
|
||||
$(TOPOBJDIR)/config/makefiles/xpidl/xpidl: $(TOPOBJDIR)/install-dist_idl
|
||||
endif
|
||||
# It also requires all the install manifests for dist/bin to have been processed
|
||||
# because it adds interfaces.manifest references with buildlist.py.
|
||||
$(TOPOBJDIR)/config/makefiles/xpidl/xpidl: $(addprefix install-,$(filter dist/bin%,$(INSTALL_MANIFESTS)))
|
||||
|
@ -44,6 +44,11 @@ static RedirEntry kRedirMap[] = {
|
||||
"buildconfig", "chrome://global/content/buildconfig.html",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
|
||||
},
|
||||
{
|
||||
"checkerboard", "chrome://global/content/aboutCheckerboard.xhtml",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT
|
||||
},
|
||||
{ "config", "chrome://global/content/config.xul", 0 },
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
{ "crashes", "chrome://global/content/crashes.xhtml", 0 },
|
||||
|
@ -24,12 +24,9 @@ protected:
|
||||
virtual ~nsAboutRedirector() {}
|
||||
};
|
||||
|
||||
#define NS_ABOUT_REDIRECTOR_MODULE_CID \
|
||||
{ /* f0acde16-1dd1-11b2-9e35-f5786fff5a66*/ \
|
||||
0xf0acde16, \
|
||||
0x1dd1, \
|
||||
0x11b2, \
|
||||
{0x9e, 0x35, 0xf5, 0x78, 0x6f, 0xff, 0x5a, 0x66} \
|
||||
}
|
||||
/* 56ebedd4-6ccf-48e8-bdae-adc77f044567 */
|
||||
#define NS_ABOUT_REDIRECTOR_MODULE_CID \
|
||||
{ 0x56ebedd4, 0x6ccf, 0x48e8, \
|
||||
{ 0xbd, 0xae, 0xad, 0xc7, 0x7f, 0x04, 0x45, 0x67 } }
|
||||
|
||||
#endif // nsAboutRedirector_h__
|
||||
|
@ -163,6 +163,7 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "about", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "addons", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "buildconfig", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "checkerboard", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "config", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "crashes", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
|
@ -5,43 +5,14 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsString.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct FeedWriterEnabled {
|
||||
static bool IsEnabled(JSContext* cx, JSObject* aGlobal)
|
||||
{
|
||||
// Make sure the global is a window
|
||||
nsGlobalWindow* win = xpc::WindowGlobalOrNull(aGlobal);
|
||||
if (!win) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure that the principal is about:feeds.
|
||||
nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
|
||||
NS_ENSURE_TRUE(principal, false);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
principal->GetURI(getter_AddRefs(uri));
|
||||
if (!uri) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// First check the scheme to avoid getting long specs in the common case.
|
||||
bool isAbout = false;
|
||||
uri->SchemeIs("about", &isAbout);
|
||||
if (!isAbout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now check the spec itself
|
||||
nsAutoCString spec;
|
||||
uri->GetSpec(spec);
|
||||
return spec.EqualsLiteral("about:feeds");
|
||||
return nsContentUtils::IsSpecificAboutPage(aGlobal, "about:feeds");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -239,10 +239,15 @@ dom::Element*
|
||||
nsIContent::GetEditingHost()
|
||||
{
|
||||
// If this isn't editable, return nullptr.
|
||||
NS_ENSURE_TRUE(IsEditableInternal(), nullptr);
|
||||
if (!IsEditableInternal()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIDocument* doc = GetComposedDoc();
|
||||
NS_ENSURE_TRUE(doc, nullptr);
|
||||
if (!doc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If this is in designMode, we should return <body>
|
||||
if (doc->HasFlag(NODE_IS_EDITABLE) && !IsInShadowTree()) {
|
||||
return doc->GetBodyElement();
|
||||
|
@ -40,6 +40,25 @@ using namespace mozilla;
|
||||
|
||||
#define kVisibilityChange "visibilitychange"
|
||||
|
||||
class VisibilityChangeListener final : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
explicit VisibilityChangeListener(nsPIDOMWindow* aWindow);
|
||||
|
||||
void RemoveListener();
|
||||
void SetCallback(nsIContentPermissionRequestCallback* aCallback);
|
||||
already_AddRefed<nsIContentPermissionRequestCallback> GetCallback();
|
||||
|
||||
private:
|
||||
virtual ~VisibilityChangeListener() {}
|
||||
|
||||
nsWeakPtr mWindow;
|
||||
nsCOMPtr<nsIContentPermissionRequestCallback> mCallback;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(VisibilityChangeListener, nsIDOMEventListener)
|
||||
|
||||
VisibilityChangeListener::VisibilityChangeListener(nsPIDOMWindow* aWindow)
|
||||
@ -756,6 +775,11 @@ RemotePermissionRequest::RemotePermissionRequest(
|
||||
mListener->SetCallback(this);
|
||||
}
|
||||
|
||||
RemotePermissionRequest::~RemotePermissionRequest()
|
||||
{
|
||||
MOZ_ASSERT(!mIPCOpen, "Protocol must not be open when RemotePermissionRequest is destroyed.");
|
||||
}
|
||||
|
||||
void
|
||||
RemotePermissionRequest::DoCancel()
|
||||
{
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
class nsPIDOMWindow;
|
||||
class nsContentPermissionRequestProxy;
|
||||
class VisibilityChangeListener;
|
||||
|
||||
// Forward declare IPC::Principal here which is defined in
|
||||
// PermissionMessageUtils.h. Include this file will transitively includes
|
||||
@ -32,25 +33,6 @@ namespace IPC {
|
||||
class Principal;
|
||||
} // namespace IPC
|
||||
|
||||
class VisibilityChangeListener final : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
explicit VisibilityChangeListener(nsPIDOMWindow* aWindow);
|
||||
|
||||
void RemoveListener();
|
||||
void SetCallback(nsIContentPermissionRequestCallback* aCallback);
|
||||
already_AddRefed<nsIContentPermissionRequestCallback> GetCallback();
|
||||
|
||||
private:
|
||||
virtual ~VisibilityChangeListener() {}
|
||||
|
||||
nsWeakPtr mWindow;
|
||||
nsCOMPtr<nsIContentPermissionRequestCallback> mCallback;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@ -216,10 +198,7 @@ public:
|
||||
bool IPCOpen() const { return mIPCOpen && !mDestroyed; }
|
||||
|
||||
private:
|
||||
virtual ~RemotePermissionRequest()
|
||||
{
|
||||
MOZ_ASSERT(!mIPCOpen, "Protocol must not be open when RemotePermissionRequest is destroyed.");
|
||||
}
|
||||
virtual ~RemotePermissionRequest();
|
||||
|
||||
void DoAllow(JS::HandleValue aChoices);
|
||||
void DoCancel();
|
||||
|
@ -8894,3 +8894,37 @@ nsContentUtils::SerializeNodeToMarkup(nsINode* aRoot,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri)
|
||||
{
|
||||
// aUri must start with about: or this isn't the right function to be using.
|
||||
MOZ_ASSERT(strncmp(aUri, "about:", 6) == 0);
|
||||
|
||||
// Make sure the global is a window
|
||||
nsGlobalWindow* win = xpc::WindowGlobalOrNull(aGlobal);
|
||||
if (!win) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure that the principal is about:feeds.
|
||||
nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
|
||||
NS_ENSURE_TRUE(principal, false);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
principal->GetURI(getter_AddRefs(uri));
|
||||
if (!uri) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// First check the scheme to avoid getting long specs in the common case.
|
||||
bool isAbout = false;
|
||||
uri->SchemeIs("about", &isAbout);
|
||||
if (!isAbout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now check the spec itself
|
||||
nsAutoCString spec;
|
||||
uri->GetSpec(spec);
|
||||
return spec.EqualsASCII(aUri);
|
||||
}
|
||||
|
@ -2565,6 +2565,14 @@ public:
|
||||
bool aDescendentsOnly,
|
||||
nsAString& aOut);
|
||||
|
||||
/*
|
||||
* Returns true iff the provided JSObject is a global, and its URI matches
|
||||
* the provided about: URI.
|
||||
* @param aGlobal the JSObject whose URI to check, if it is a global.
|
||||
* @param aUri the URI to match, e.g. "about:feeds"
|
||||
*/
|
||||
static bool IsSpecificAboutPage(JSObject* aGlobal, const char* aUri);
|
||||
|
||||
private:
|
||||
static bool InitializeEventTable();
|
||||
|
||||
|
@ -1622,6 +1622,9 @@ nsGlobalWindow::FreeInnerObjects()
|
||||
// other members that the window destroyed observers could
|
||||
// re-create.
|
||||
NotifyDOMWindowDestroyed(this);
|
||||
if (auto* reporter = nsWindowMemoryReporter::Get()) {
|
||||
reporter->ObserveDOMWindowDetached(this);
|
||||
}
|
||||
|
||||
mInnerObjectsFreed = true;
|
||||
|
||||
@ -2932,8 +2935,9 @@ nsGlobalWindow::DetachFromDocShell()
|
||||
inner->FreeInnerObjects();
|
||||
}
|
||||
|
||||
// Make sure that this is called before we null out the document.
|
||||
NotifyDOMWindowDestroyed(this);
|
||||
if (auto* reporter = nsWindowMemoryReporter::Get()) {
|
||||
reporter->ObserveDOMWindowDetached(this);
|
||||
}
|
||||
|
||||
NotifyWindowIDDestroyed("outer-window-destroyed");
|
||||
|
||||
@ -11039,7 +11043,7 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
fireMozStorageChanged = mLocalStorage == changingStorage;
|
||||
if (fireMozStorageChanged) {
|
||||
eventType.AssignLiteral("MozLocalStorageChanged");
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1437,7 +1437,7 @@ nsObjectLoadingContent::ObjectState() const
|
||||
case eFallbackVulnerableNoUpdate:
|
||||
return NS_EVENT_STATE_VULNERABLE_NO_UPDATE;
|
||||
}
|
||||
};
|
||||
}
|
||||
NS_NOTREACHED("unknown type?");
|
||||
return NS_EVENT_STATE_LOADING;
|
||||
}
|
||||
@ -2422,7 +2422,7 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
case eType_Null:
|
||||
// Handled below, silence compiler warnings
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Loaded, handle notifications and fallback
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "js/TypeDecls.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
// Only fired for inner windows.
|
||||
#define DOM_WINDOW_DESTROYED_TOPIC "dom-window-destroyed"
|
||||
#define DOM_WINDOW_FROZEN_TOPIC "dom-window-frozen"
|
||||
#define DOM_WINDOW_THAWED_TOPIC "dom-window-thawed"
|
||||
|
@ -111,10 +111,6 @@ nsWindowMemoryReporter::Init()
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
// DOM_WINDOW_DESTROYED_TOPIC announces what we call window "detachment",
|
||||
// when a window's docshell is set to nullptr.
|
||||
os->AddObserver(sWindowReporter, DOM_WINDOW_DESTROYED_TOPIC,
|
||||
/* weakRef = */ true);
|
||||
os->AddObserver(sWindowReporter, "after-minimize-memory-usage",
|
||||
/* weakRef = */ true);
|
||||
os->AddObserver(sWindowReporter, "cycle-collector-begin",
|
||||
@ -127,6 +123,12 @@ nsWindowMemoryReporter::Init()
|
||||
RegisterGhostWindowsDistinguishedAmount(GhostWindowsReporter::DistinguishedAmount);
|
||||
}
|
||||
|
||||
/* static */ nsWindowMemoryReporter*
|
||||
nsWindowMemoryReporter::Get()
|
||||
{
|
||||
return sWindowReporter;
|
||||
}
|
||||
|
||||
static already_AddRefed<nsIURI>
|
||||
GetWindowURI(nsIDOMWindow *aWindow)
|
||||
{
|
||||
@ -614,9 +616,7 @@ NS_IMETHODIMP
|
||||
nsWindowMemoryReporter::Observe(nsISupports *aSubject, const char *aTopic,
|
||||
const char16_t *aData)
|
||||
{
|
||||
if (!strcmp(aTopic, DOM_WINDOW_DESTROYED_TOPIC)) {
|
||||
ObserveDOMWindowDetached(aSubject);
|
||||
} else if (!strcmp(aTopic, "after-minimize-memory-usage")) {
|
||||
if (!strcmp(aTopic, "after-minimize-memory-usage")) {
|
||||
ObserveAfterMinimizeMemoryUsage();
|
||||
} else if (!strcmp(aTopic, "cycle-collector-begin")) {
|
||||
if (mCheckTimer) {
|
||||
@ -638,9 +638,9 @@ nsWindowMemoryReporter::Observe(nsISupports *aSubject, const char *aTopic,
|
||||
}
|
||||
|
||||
void
|
||||
nsWindowMemoryReporter::ObserveDOMWindowDetached(nsISupports* aWindow)
|
||||
nsWindowMemoryReporter::ObserveDOMWindowDetached(nsGlobalWindow* aWindow)
|
||||
{
|
||||
nsWeakPtr weakWindow = do_GetWeakReference(aWindow);
|
||||
nsWeakPtr weakWindow = do_GetWeakReference(static_cast<nsIDOMEventTarget*>(aWindow));
|
||||
if (!weakWindow) {
|
||||
NS_WARNING("Couldn't take weak reference to a window?");
|
||||
return;
|
||||
|
@ -158,6 +158,9 @@ public:
|
||||
static void UnlinkGhostWindows();
|
||||
#endif
|
||||
|
||||
static nsWindowMemoryReporter* Get();
|
||||
void ObserveDOMWindowDetached(nsGlobalWindow* aWindow);
|
||||
|
||||
private:
|
||||
~nsWindowMemoryReporter();
|
||||
|
||||
@ -199,7 +202,6 @@ private:
|
||||
*/
|
||||
uint32_t GetGhostTimeout();
|
||||
|
||||
void ObserveDOMWindowDetached(nsISupports* aWindow);
|
||||
void ObserveAfterMinimizeMemoryUsage();
|
||||
|
||||
/**
|
||||
|
@ -80,10 +80,6 @@ DOMInterfaces = {
|
||||
'nativeType': 'mozilla::dom::Activity',
|
||||
},
|
||||
|
||||
'MozAbortablePromise': {
|
||||
'nativeType': 'mozilla::dom::AbortablePromise',
|
||||
},
|
||||
|
||||
'AbstractWorker': {
|
||||
'concrete': False
|
||||
},
|
||||
|
@ -5037,11 +5037,6 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
return JSToNativeConversionInfo(template, declType=declType,
|
||||
dealWithOptional=isOptional)
|
||||
|
||||
if descriptor.interface.identifier.name == "AbortablePromise":
|
||||
raise TypeError("Need to figure out what argument conversion "
|
||||
"should look like for AbortablePromise: %s" %
|
||||
sourceDescription)
|
||||
|
||||
# This is an interface that we implement as a concrete class
|
||||
# or an XPCOM interface.
|
||||
|
||||
@ -7149,8 +7144,7 @@ class CGPerSignatureCall(CGThing):
|
||||
|
||||
# Hack for making Promise.prototype.then work well over Xrays.
|
||||
if (not static and
|
||||
(descriptor.name == "Promise" or
|
||||
descriptor.name == "MozAbortablePromise") and
|
||||
descriptor.name == "Promise" and
|
||||
idlNode.isMethod() and
|
||||
idlNode.identifier.name == "then"):
|
||||
cgThings.append(CGGeneric(dedent(
|
||||
@ -7162,7 +7156,7 @@ class CGPerSignatureCall(CGThing):
|
||||
needsUnwrap = False
|
||||
argsPost = []
|
||||
if isConstructor:
|
||||
if descriptor.name == "Promise" or descriptor.name == "MozAbortablePromise":
|
||||
if descriptor.name == "Promise":
|
||||
# Hack for Promise for now: pass in our desired proto so the
|
||||
# implementation can create the reflector with the right proto.
|
||||
argsPost.append("desiredProto")
|
||||
|
2
dom/cache/DBSchema.cpp
vendored
2
dom/cache/DBSchema.cpp
vendored
@ -1256,7 +1256,7 @@ MatchByVaryHeader(mozIStorageConnection* aConn,
|
||||
ErrorResult errorResult;
|
||||
|
||||
cachedHeaders->Append(name, value, errorResult);
|
||||
if (errorResult.Failed()) { return errorResult.StealNSResult(); };
|
||||
if (errorResult.Failed()) { return errorResult.StealNSResult(); }
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
|
@ -140,7 +140,7 @@ void MurmurHash3_x86_32 ( const void * key, int len,
|
||||
case 2: k1 ^= tail[1] << 8;
|
||||
case 1: k1 ^= tail[0];
|
||||
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
|
||||
};
|
||||
}
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
@ -233,7 +233,7 @@ void MurmurHash3_x86_128 ( const void * key, const int len,
|
||||
case 2: k1 ^= tail[ 1] << 8;
|
||||
case 1: k1 ^= tail[ 0] << 0;
|
||||
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
|
||||
};
|
||||
}
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
@ -318,7 +318,7 @@ void MurmurHash3_x64_128 ( const void * key, const int len,
|
||||
case 2: k1 ^= uint64_t(tail[ 1]) << 8;
|
||||
case 1: k1 ^= uint64_t(tail[ 0]) << 0;
|
||||
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
|
||||
};
|
||||
}
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
|
@ -1324,8 +1324,7 @@ IsFormatAndTypeUnpackable(GLenum format, GLenum type, bool isWebGL2)
|
||||
switch (format) {
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
if (!isWebGL2)
|
||||
return false;
|
||||
return isWebGL2;
|
||||
case LOCAL_GL_ALPHA:
|
||||
case LOCAL_GL_RED:
|
||||
case LOCAL_GL_RED_INTEGER:
|
||||
|
@ -192,7 +192,7 @@ GetDirectoryListingTask::Work()
|
||||
NS_FAILED(currFile->IsSpecial(&isSpecial))) ||
|
||||
isLink || isSpecial) {
|
||||
continue;
|
||||
};
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(currFile->IsFile(&isFile)) ||
|
||||
NS_FAILED(currFile->IsDirectory(&isDir))) ||
|
||||
!(isFile || isDir)) {
|
||||
|
@ -10299,7 +10299,7 @@ DatabaseConnection::Close()
|
||||
AssertIsOnConnectionThread();
|
||||
MOZ_ASSERT(mStorageConnection);
|
||||
MOZ_ASSERT(!mDEBUGSavepointCount);
|
||||
MOZ_ASSERT(!mInWriteTransaction);
|
||||
MOZ_RELEASE_ASSERT(!mInWriteTransaction);
|
||||
|
||||
PROFILER_LABEL("IndexedDB",
|
||||
"DatabaseConnection::Close",
|
||||
|
@ -5,7 +5,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIPushObserverNotification.idl',
|
||||
'nsIPushNotifier.idl',
|
||||
'nsIPushService.idl',
|
||||
]
|
||||
|
||||
|
41
dom/interfaces/push/nsIPushNotifier.idl
Normal file
41
dom/interfaces/push/nsIPushNotifier.idl
Normal file
@ -0,0 +1,41 @@
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIPrincipal;
|
||||
|
||||
/**
|
||||
* Fires service worker events for push messages sent to content subscriptions,
|
||||
* and XPCOM observer notifications for system subscriptions. This service
|
||||
* can only be used from the parent process.
|
||||
*/
|
||||
[scriptable, uuid(b00dfdeb-14e5-425b-adc7-b531442e3216)]
|
||||
interface nsIPushNotifier : nsISupports
|
||||
{
|
||||
void notifyPush(in ACString scope, in nsIPrincipal principal);
|
||||
|
||||
void notifyPushWithData(in ACString scope, in nsIPrincipal principal,
|
||||
[optional] in uint32_t dataLen,
|
||||
[array, size_is(dataLen)] in uint8_t data);
|
||||
|
||||
void notifySubscriptionChange(in ACString scope, in nsIPrincipal principal);
|
||||
};
|
||||
|
||||
/**
|
||||
* A push message sent to a system subscription, used as the subject of a
|
||||
* `push-message` observer notification. System subscriptions are created by
|
||||
* the system principal, and do not use worker events.
|
||||
*
|
||||
* This interface resembles the `PushMessageData` WebIDL interface.
|
||||
*/
|
||||
[scriptable, uuid(136dc8fd-8c56-4176-9170-eaa86b6ba99e)]
|
||||
interface nsIPushMessage : nsISupports
|
||||
{
|
||||
/** Extracts the data as a UTF-8 text string. */
|
||||
DOMString text();
|
||||
|
||||
/** Extracts the data as a JSON value. */
|
||||
[implicit_jscontext] jsval json();
|
||||
|
||||
/** Extracts the raw binary data. */
|
||||
void binary([optional] out uint32_t dataLen,
|
||||
[array, retval, size_is(dataLen)] out uint8_t data);
|
||||
};
|
@ -1,40 +0,0 @@
|
||||
/* -*- Mode: IDL; 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 "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* A push message received by an `nsIPushService`, used as the subject of a
|
||||
* `push-notification` observer notification.
|
||||
*/
|
||||
[scriptable, uuid(56f57607-28b6-44b0-aa56-3d4d3c88be15)]
|
||||
interface nsIPushObserverNotification : nsISupports
|
||||
{
|
||||
/* The URL that receives push messages from an application server. */
|
||||
attribute string pushEndpoint;
|
||||
|
||||
/**
|
||||
* The notification version sent by the application server. This is a
|
||||
* monotonically increasing number.
|
||||
*/
|
||||
attribute long long version;
|
||||
|
||||
/**
|
||||
* The notification payload. Delivery is not guaranteed; if the browser is
|
||||
* offline when the application server sends the push message, the payload
|
||||
* may be discarded.
|
||||
*/
|
||||
attribute string data;
|
||||
|
||||
/**
|
||||
* How many times has a push event occured against this pushEndpoint
|
||||
*/
|
||||
attribute long long pushCount;
|
||||
|
||||
/**
|
||||
* The last time a push occured against this this pushEndpoint
|
||||
*/
|
||||
attribute long long lastPush;
|
||||
};
|
@ -81,9 +81,8 @@ interface nsIPushService : nsISupports
|
||||
* The |endpoint| property of the subscription record is a URL string
|
||||
* that can be used to send push messages to subscribers.
|
||||
*
|
||||
* Each incoming message fires a `push-notification` observer
|
||||
* notification, with an `nsIPushObserverNotification` as the subject and
|
||||
* the |scope| as the data.
|
||||
* Each incoming message fires a `push-message` observer notification, with
|
||||
* an `nsIPushMessage` as the subject and the |scope| as the data.
|
||||
*
|
||||
* If the server drops a subscription, a `push-subscription-change` observer
|
||||
* will be fired, with the subject set to `null` and the data set to |scope|.
|
||||
|
@ -163,6 +163,10 @@
|
||||
#include "mozilla/dom/GamepadService.h"
|
||||
#endif
|
||||
|
||||
#ifndef MOZ_SIMPLEPUSH
|
||||
#include "mozilla/dom/PushNotifier.h"
|
||||
#endif
|
||||
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/cellbroadcast/CellBroadcastIPCService.h"
|
||||
#include "mozilla/dom/icc/IccChild.h"
|
||||
@ -1804,7 +1808,7 @@ ContentChild::SendPMobileConnectionConstructor(PMobileConnectionChild* aActor,
|
||||
static_cast<MobileConnectionChild*>(aActor)->AddRef();
|
||||
return PContentChild::SendPMobileConnectionConstructor(aActor, aClientId);
|
||||
#else
|
||||
MOZ_CRASH("No support for mobileconnection on this platform!");;
|
||||
MOZ_CRASH("No support for mobileconnection on this platform!");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1815,7 +1819,7 @@ ContentChild::AllocPMobileConnectionChild(const uint32_t& aClientId)
|
||||
MOZ_CRASH("No one should be allocating PMobileConnectionChild actors");
|
||||
return nullptr;
|
||||
#else
|
||||
MOZ_CRASH("No support for mobileconnection on this platform!");;
|
||||
MOZ_CRASH("No support for mobileconnection on this platform!");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -3217,5 +3221,62 @@ ContentChild::RecvTestGraphicsDeviceReset(const uint32_t& aResetReason)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvPush(const nsCString& aScope,
|
||||
const IPC::Principal& aPrincipal)
|
||||
{
|
||||
#ifndef MOZ_SIMPLEPUSH
|
||||
nsCOMPtr<nsIPushNotifier> pushNotifierIface =
|
||||
do_GetService("@mozilla.org/push/Notifier;1");
|
||||
if (NS_WARN_IF(!pushNotifierIface)) {
|
||||
return true;
|
||||
}
|
||||
PushNotifier* pushNotifier =
|
||||
static_cast<PushNotifier*>(pushNotifierIface.get());
|
||||
nsresult rv = pushNotifier->NotifyPushWorkers(aScope, aPrincipal, Nothing());
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvPushWithData(const nsCString& aScope,
|
||||
const IPC::Principal& aPrincipal,
|
||||
InfallibleTArray<uint8_t>&& aData)
|
||||
{
|
||||
#ifndef MOZ_SIMPLEPUSH
|
||||
nsCOMPtr<nsIPushNotifier> pushNotifierIface =
|
||||
do_GetService("@mozilla.org/push/Notifier;1");
|
||||
if (NS_WARN_IF(!pushNotifierIface)) {
|
||||
return true;
|
||||
}
|
||||
PushNotifier* pushNotifier =
|
||||
static_cast<PushNotifier*>(pushNotifierIface.get());
|
||||
nsresult rv = pushNotifier->NotifyPushWorkers(aScope, aPrincipal,
|
||||
Some(aData));
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvPushSubscriptionChange(const nsCString& aScope,
|
||||
const IPC::Principal& aPrincipal)
|
||||
{
|
||||
#ifndef MOZ_SIMPLEPUSH
|
||||
nsCOMPtr<nsIPushNotifier> pushNotifierIface =
|
||||
do_GetService("@mozilla.org/push/Notifier;1");
|
||||
if (NS_WARN_IF(!pushNotifierIface)) {
|
||||
return true;
|
||||
}
|
||||
PushNotifier* pushNotifier =
|
||||
static_cast<PushNotifier*>(pushNotifierIface.get());
|
||||
nsresult rv = pushNotifier->NotifySubscriptionChangeWorkers(aScope,
|
||||
aPrincipal);
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -526,6 +526,19 @@ public:
|
||||
virtual bool RecvEndDragSession(const bool& aDoneDrag,
|
||||
const bool& aUserCancelled) override;
|
||||
|
||||
virtual bool
|
||||
RecvPush(const nsCString& aScope,
|
||||
const IPC::Principal& aPrincipal) override;
|
||||
|
||||
virtual bool
|
||||
RecvPushWithData(const nsCString& aScope,
|
||||
const IPC::Principal& aPrincipal,
|
||||
InfallibleTArray<uint8_t>&& aData) override;
|
||||
|
||||
virtual bool
|
||||
RecvPushSubscriptionChange(const nsCString& aScope,
|
||||
const IPC::Principal& aPrincipal) override;
|
||||
|
||||
#ifdef ANDROID
|
||||
gfx::IntSize GetScreenSize() { return mScreenSize; }
|
||||
#endif
|
||||
|
@ -728,6 +728,21 @@ child:
|
||||
*/
|
||||
async NotifyGMPsChanged();
|
||||
|
||||
/**
|
||||
* Send a `push` event without data to a service worker in the child.
|
||||
*/
|
||||
Push(nsCString scope, Principal principal);
|
||||
|
||||
/**
|
||||
* Send a `push` event with data to a service worker in the child.
|
||||
*/
|
||||
PushWithData(nsCString scope, Principal principal, uint8_t[] data);
|
||||
|
||||
/**
|
||||
* Send a `pushsubscriptionchange` event to a service worker in the child.
|
||||
*/
|
||||
PushSubscriptionChange(nsCString scope, Principal principal);
|
||||
|
||||
parent:
|
||||
/**
|
||||
* Tell the content process some attributes of itself. This is
|
||||
|
@ -12,6 +12,7 @@ const {
|
||||
} = Components;
|
||||
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/NetUtil.jsm');
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
/** This little class ensures that redirects maintain an https:// origin */
|
||||
@ -44,17 +45,16 @@ function ResourceLoader(res, rej) {
|
||||
ResourceLoader.load = function(uri, doc) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let listener = new ResourceLoader(resolve, reject);
|
||||
let ioService = Cc['@mozilla.org/network/io-service;1']
|
||||
.getService(Ci.nsIIOService);
|
||||
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
|
||||
// the '2' identifies this as a script load
|
||||
let ioChannel = ioService.newChannelFromURI2(uri, doc, doc.nodePrincipal,
|
||||
systemPrincipal, 0,
|
||||
Ci.nsIContentPolicy.TYPE_INTERNAL_SCRIPT);
|
||||
let ioChannel = NetUtil.newChannel({
|
||||
uri: uri,
|
||||
loadingNode: doc,
|
||||
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_SCRIPT
|
||||
});
|
||||
|
||||
ioChannel.loadGroup = doc.documentLoadGroup.QueryInterface(Ci.nsILoadGroup);
|
||||
ioChannel.notificationCallbacks = new RedirectHttpsOnly();
|
||||
ioChannel.asyncOpen(listener, null);
|
||||
ioChannel.asyncOpen2(listener);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -674,20 +674,7 @@ public:
|
||||
VideoDevice *aVideoDevice) :
|
||||
mListener(aListener),
|
||||
mAudioDevice(aAudioDevice),
|
||||
mVideoDevice(aVideoDevice),
|
||||
mEchoOn(true),
|
||||
mAgcOn(false),
|
||||
mNoiseOn(true),
|
||||
#ifdef MOZ_WEBRTC
|
||||
mEcho(webrtc::kEcDefault),
|
||||
mAgc(webrtc::kAgcDefault),
|
||||
mNoise(webrtc::kNsDefault),
|
||||
#else
|
||||
mEcho(0),
|
||||
mAgc(0),
|
||||
mNoise(0),
|
||||
#endif
|
||||
mPlayoutDelay(20)
|
||||
mVideoDevice(aVideoDevice)
|
||||
{}
|
||||
|
||||
virtual ~nsDOMUserMediaStream()
|
||||
@ -790,21 +777,6 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
AudioConfig(bool aEchoOn, uint32_t aEcho,
|
||||
bool aAgcOn, uint32_t aAgc,
|
||||
bool aNoiseOn, uint32_t aNoise,
|
||||
int32_t aPlayoutDelay)
|
||||
{
|
||||
mEchoOn = aEchoOn;
|
||||
mEcho = aEcho;
|
||||
mAgcOn = aAgcOn;
|
||||
mAgc = aAgc;
|
||||
mNoiseOn = aNoiseOn;
|
||||
mNoise = aNoise;
|
||||
mPlayoutDelay = aPlayoutDelay;
|
||||
}
|
||||
|
||||
void RemoveDirectListener(MediaStreamDirectListener *aListener) override
|
||||
{
|
||||
if (GetSourceStream()) {
|
||||
@ -842,14 +814,6 @@ public:
|
||||
RefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
|
||||
RefPtr<AudioDevice> mAudioDevice; // so we can turn on AEC
|
||||
RefPtr<VideoDevice> mVideoDevice;
|
||||
bool mEchoOn;
|
||||
bool mAgcOn;
|
||||
bool mNoiseOn;
|
||||
bool mFullDuplex;
|
||||
uint32_t mEcho;
|
||||
uint32_t mAgc;
|
||||
uint32_t mNoise;
|
||||
uint32_t mPlayoutDelay;
|
||||
};
|
||||
|
||||
|
||||
@ -954,16 +918,6 @@ public:
|
||||
NS_IMETHOD
|
||||
Run()
|
||||
{
|
||||
#ifdef MOZ_WEBRTC
|
||||
int32_t aec = (int32_t) webrtc::kEcUnchanged;
|
||||
int32_t agc = (int32_t) webrtc::kAgcUnchanged;
|
||||
int32_t noise = (int32_t) webrtc::kNsUnchanged;
|
||||
#else
|
||||
int32_t aec = 0, agc = 0, noise = 0;
|
||||
#endif
|
||||
bool aec_on = false, agc_on = false, noise_on = false;
|
||||
int32_t playout_delay = 0;
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
|
||||
(nsGlobalWindow::GetInnerWindowWithId(mWindowID));
|
||||
@ -976,25 +930,6 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
// Right now these configs are only of use if webrtc is available
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
|
||||
|
||||
if (branch) {
|
||||
branch->GetBoolPref("media.getusermedia.aec_enabled", &aec_on);
|
||||
branch->GetIntPref("media.getusermedia.aec", &aec);
|
||||
branch->GetBoolPref("media.getusermedia.agc_enabled", &agc_on);
|
||||
branch->GetIntPref("media.getusermedia.agc", &agc);
|
||||
branch->GetBoolPref("media.getusermedia.noise_enabled", &noise_on);
|
||||
branch->GetIntPref("media.getusermedia.noise", &noise);
|
||||
branch->GetIntPref("media.getusermedia.playout_delay", &playout_delay);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MediaStreamGraph::GraphDriverType graphDriverType =
|
||||
mAudioDevice ? MediaStreamGraph::AUDIO_THREAD_DRIVER
|
||||
: MediaStreamGraph::SYSTEM_THREAD_DRIVER;
|
||||
@ -1073,11 +1008,6 @@ public:
|
||||
TracksAvailableCallback* tracksAvailableCallback =
|
||||
new TracksAvailableCallback(mManager, mOnSuccess, mWindowID, domStream);
|
||||
|
||||
mListener->AudioConfig(aec_on, (uint32_t) aec,
|
||||
agc_on, (uint32_t) agc,
|
||||
noise_on, (uint32_t) noise,
|
||||
playout_delay);
|
||||
|
||||
// Dispatch to the media thread to ask it to start the sources,
|
||||
// because that can take a while.
|
||||
// Pass ownership of domStream to the MediaOperationTask
|
||||
@ -1515,11 +1445,24 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
|
||||
MediaManager::MediaManager()
|
||||
: mMediaThread(nullptr)
|
||||
, mBackend(nullptr) {
|
||||
mPrefs.mFreq = 1000; // 1KHz test tone
|
||||
mPrefs.mWidth = 0; // adaptive default
|
||||
mPrefs.mHeight = 0; // adaptive default
|
||||
mPrefs.mFPS = MediaEngine::DEFAULT_VIDEO_FPS;
|
||||
mPrefs.mMinFPS = MediaEngine::DEFAULT_VIDEO_MIN_FPS;
|
||||
mPrefs.mFreq = 1000; // 1KHz test tone
|
||||
mPrefs.mWidth = 0; // adaptive default
|
||||
mPrefs.mHeight = 0; // adaptive default
|
||||
mPrefs.mFPS = MediaEngine::DEFAULT_VIDEO_FPS;
|
||||
mPrefs.mMinFPS = MediaEngine::DEFAULT_VIDEO_MIN_FPS;
|
||||
mPrefs.mAecOn = false;
|
||||
mPrefs.mAgcOn = false;
|
||||
mPrefs.mNoiseOn = false;
|
||||
#ifdef MOZ_WEBRTC
|
||||
mPrefs.mAec = webrtc::kEcUnchanged;
|
||||
mPrefs.mAgc = webrtc::kAgcUnchanged;
|
||||
mPrefs.mNoise = webrtc::kNsUnchanged;
|
||||
#else
|
||||
mPrefs.mAec = 0;
|
||||
mPrefs.mAgc = 0;
|
||||
mPrefs.mNoise = 0;
|
||||
#endif
|
||||
mPrefs.mPlayoutDelay = 0;
|
||||
mPrefs.mFullDuplex = false;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
|
||||
@ -1529,9 +1472,12 @@ MediaManager::MediaManager()
|
||||
GetPrefs(branch, nullptr);
|
||||
}
|
||||
}
|
||||
LOG(("%s: default prefs: %dx%d @%dfps (min %d), %dHz test tones, %sfull-duplex", __FUNCTION__,
|
||||
mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mMinFPS, mPrefs.mFreq,
|
||||
mPrefs.mFullDuplex ? "" : "not "));
|
||||
LOG(("%s: default prefs: %dx%d @%dfps (min %d), %dHz test tones, aec: %s,"
|
||||
"agc: %s, noise: %s, aec level: %d, agc level: %d, noise level: %d,"
|
||||
"playout delay: %d, %sfull_duplex", __FUNCTION__, mPrefs.mWidth, mPrefs.mHeight,
|
||||
mPrefs.mFPS, mPrefs.mMinFPS, mPrefs.mFreq, mPrefs.mAecOn ? "on" : "off",
|
||||
mPrefs.mAgcOn ? "on": "off", mPrefs.mNoiseOn ? "on": "off", mPrefs.mAec,
|
||||
mPrefs.mAgc, mPrefs.mNoise, mPrefs.mPlayoutDelay, mPrefs.mFullDuplex ? "" : "not "));
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(MediaManager, nsIMediaManagerService, nsIObserver)
|
||||
@ -1595,6 +1541,15 @@ MediaManager::Get() {
|
||||
prefs->AddObserver("media.navigator.video.default_minfps", sSingleton, false);
|
||||
prefs->AddObserver("media.navigator.audio.fake_frequency", sSingleton, false);
|
||||
prefs->AddObserver("media.navigator.audio.full_duplex", sSingleton, false);
|
||||
#ifdef MOZ_WEBRTC
|
||||
prefs->AddObserver("media.getusermedia.aec_enabled", sSingleton, false);
|
||||
prefs->AddObserver("media.getusermedia.aec", sSingleton, false);
|
||||
prefs->AddObserver("media.getusermedia.agc_enabled", sSingleton, false);
|
||||
prefs->AddObserver("media.getusermedia.agc", sSingleton, false);
|
||||
prefs->AddObserver("media.getusermedia.noise_enabled", sSingleton, false);
|
||||
prefs->AddObserver("media.getusermedia.noise", sSingleton, false);
|
||||
prefs->AddObserver("media.getusermedia.playout_delay", sSingleton, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Prepare async shutdown
|
||||
@ -2628,6 +2583,15 @@ MediaManager::GetPrefs(nsIPrefBranch *aBranch, const char *aData)
|
||||
GetPref(aBranch, "media.navigator.video.default_fps", aData, &mPrefs.mFPS);
|
||||
GetPref(aBranch, "media.navigator.video.default_minfps", aData, &mPrefs.mMinFPS);
|
||||
GetPref(aBranch, "media.navigator.audio.fake_frequency", aData, &mPrefs.mFreq);
|
||||
#ifdef MOZ_WEBRTC
|
||||
GetPrefBool(aBranch, "media.getusermedia.aec_enabled", aData, &mPrefs.mAecOn);
|
||||
GetPrefBool(aBranch, "media.getusermedia.agc_enabled", aData, &mPrefs.mAgcOn);
|
||||
GetPrefBool(aBranch, "media.getusermedia.noise_enabled", aData, &mPrefs.mNoiseOn);
|
||||
GetPref(aBranch, "media.getusermedia.aec", aData, &mPrefs.mAec);
|
||||
GetPref(aBranch, "media.getusermedia.agc", aData, &mPrefs.mAgc);
|
||||
GetPref(aBranch, "media.getusermedia.noise", aData, &mPrefs.mNoise);
|
||||
GetPref(aBranch, "media.getusermedia.playout_delay", aData, &mPrefs.mPlayoutDelay);
|
||||
#endif
|
||||
GetPrefBool(aBranch, "media.navigator.audio.full_duplex", aData, &mPrefs.mFullDuplex);
|
||||
}
|
||||
|
||||
@ -2655,6 +2619,15 @@ MediaManager::Shutdown()
|
||||
prefs->RemoveObserver("media.navigator.video.default_fps", this);
|
||||
prefs->RemoveObserver("media.navigator.video.default_minfps", this);
|
||||
prefs->RemoveObserver("media.navigator.audio.fake_frequency", this);
|
||||
#ifdef MOZ_WEBRTC
|
||||
prefs->RemoveObserver("media.getusermedia.aec_enabled", this);
|
||||
prefs->RemoveObserver("media.getusermedia.aec", this);
|
||||
prefs->RemoveObserver("media.getusermedia.agc_enabled", this);
|
||||
prefs->RemoveObserver("media.getusermedia.agc", this);
|
||||
prefs->RemoveObserver("media.getusermedia.noise_enabled", this);
|
||||
prefs->RemoveObserver("media.getusermedia.noise", this);
|
||||
prefs->RemoveObserver("media.getusermedia.playout_delay", this);
|
||||
#endif
|
||||
prefs->RemoveObserver("media.navigator.audio.full_duplex", this);
|
||||
}
|
||||
|
||||
@ -3127,23 +3100,6 @@ MediaManager::IsActivelyCapturingOrHasAPermission(uint64_t aWindowId)
|
||||
video == nsIPermissionManager::ALLOW_ACTION;
|
||||
}
|
||||
|
||||
void
|
||||
GetUserMediaCallbackMediaStreamListener::AudioConfig(bool aEchoOn,
|
||||
uint32_t aEcho,
|
||||
bool aAgcOn, uint32_t aAGC,
|
||||
bool aNoiseOn, uint32_t aNoise,
|
||||
int32_t aPlayoutDelay)
|
||||
{
|
||||
if (mAudioDevice) {
|
||||
#ifdef MOZ_WEBRTC
|
||||
MediaManager::PostTask(FROM_HERE,
|
||||
NewRunnableMethod(mAudioDevice->GetSource(), &MediaEngineSource::Config,
|
||||
aEchoOn, aEcho, aAgcOn, aAGC, aNoiseOn,
|
||||
aNoise, aPlayoutDelay));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GetUserMediaCallbackMediaStreamListener::Invalidate()
|
||||
{
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "AudioNodeStream.h"
|
||||
#include "AudioNodeExternalInputStream.h"
|
||||
#include "mozilla/dom/AudioContextBinding.h"
|
||||
#include "mozilla/media/MediaUtils.h"
|
||||
#include <algorithm>
|
||||
#include "DOMMediaStream.h"
|
||||
#include "GeckoProfiler.h"
|
||||
@ -1405,17 +1406,20 @@ MediaStreamGraphImpl::ApplyStreamUpdate(StreamUpdate* aUpdate)
|
||||
}
|
||||
|
||||
void
|
||||
MediaStreamGraphImpl::ForceShutDown()
|
||||
MediaStreamGraphImpl::ForceShutDown(ShutdownTicket* aShutdownTicket)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread");
|
||||
STREAM_LOG(LogLevel::Debug, ("MediaStreamGraph %p ForceShutdown", this));
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mForceShutDown = true;
|
||||
mForceShutdownTicket = aShutdownTicket;
|
||||
EnsureNextIterationLocked();
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ StaticRefPtr<nsIAsyncShutdownBlocker> gMediaStreamGraphShutdownBlocker;
|
||||
|
||||
namespace {
|
||||
|
||||
class MediaStreamGraphShutDownRunnable : public nsRunnable {
|
||||
@ -1444,6 +1448,13 @@ public:
|
||||
mGraph->mDriver->Shutdown(); // This will wait until it's shutdown since
|
||||
// we'll start tearing down the graph after this
|
||||
|
||||
// We may be one of several graphs. Drop ticket to eventually unblock shutdown.
|
||||
mGraph->mForceShutdownTicket = nullptr;
|
||||
|
||||
// We can't block past the final LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION
|
||||
// stage, since completion of that stage requires all streams to be freed,
|
||||
// which requires shutdown to proceed.
|
||||
|
||||
// mGraph's thread is not running so it's OK to do whatever here
|
||||
if (mGraph->IsEmpty()) {
|
||||
// mGraph is no longer needed, so delete it.
|
||||
@ -1510,14 +1521,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class MediaStreamGraphShutdownObserver final : public nsIObserver
|
||||
{
|
||||
~MediaStreamGraphShutdownObserver() {}
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
@ -2800,26 +2803,6 @@ MediaStreamGraphImpl::Destroy()
|
||||
mSelfRef = nullptr;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(MediaStreamGraphShutdownObserver, nsIObserver)
|
||||
|
||||
static bool gShutdownObserverRegistered = false;
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaStreamGraphShutdownObserver::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
const char16_t *aData)
|
||||
{
|
||||
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
||||
for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
|
||||
MediaStreamGraphImpl* graph = iter.UserData();
|
||||
graph->ForceShutDown();
|
||||
}
|
||||
nsContentUtils::UnregisterShutdownObserver(this);
|
||||
gShutdownObserverRegistered = false;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MediaStreamGraph*
|
||||
MediaStreamGraph::GetInstance(MediaStreamGraph::GraphDriverType aGraphDriverRequested,
|
||||
dom::AudioChannel aChannel)
|
||||
@ -2830,9 +2813,38 @@ MediaStreamGraph::GetInstance(MediaStreamGraph::GraphDriverType aGraphDriverRequ
|
||||
MediaStreamGraphImpl* graph = nullptr;
|
||||
|
||||
if (!gGraphs.Get(channel, &graph)) {
|
||||
if (!gShutdownObserverRegistered) {
|
||||
gShutdownObserverRegistered = true;
|
||||
nsContentUtils::RegisterShutdownObserver(new MediaStreamGraphShutdownObserver());
|
||||
if (!gMediaStreamGraphShutdownBlocker) {
|
||||
|
||||
class Blocker : public media::ShutdownBlocker
|
||||
{
|
||||
public:
|
||||
Blocker()
|
||||
: media::ShutdownBlocker(NS_LITERAL_STRING(
|
||||
"MediaStreamGraph shutdown: blocking on msg thread")) {}
|
||||
|
||||
NS_IMETHOD
|
||||
BlockShutdown(nsIAsyncShutdownClient* aProfileBeforeChange) override
|
||||
{
|
||||
// Distribute the global async shutdown blocker in a ticket. If there
|
||||
// are zero graphs then shutdown is unblocked when we go out of scope.
|
||||
RefPtr<MediaStreamGraphImpl::ShutdownTicket> ticket =
|
||||
new MediaStreamGraphImpl::ShutdownTicket(gMediaStreamGraphShutdownBlocker.get());
|
||||
gMediaStreamGraphShutdownBlocker = nullptr;
|
||||
|
||||
for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.UserData()->ForceShutDown(ticket);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
gMediaStreamGraphShutdownBlocker = new Blocker();
|
||||
nsCOMPtr<nsIAsyncShutdownClient> barrier = MediaStreamGraphImpl::GetShutdownBarrier();
|
||||
nsresult rv = barrier->
|
||||
AddBlocker(gMediaStreamGraphShutdownBlocker,
|
||||
NS_LITERAL_STRING(__FILE__), __LINE__,
|
||||
NS_LITERAL_STRING("MediaStreamGraph shutdown"));
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
||||
CubebUtils::InitPreferredSampleRate();
|
||||
@ -2880,7 +2892,7 @@ MediaStreamGraph::DestroyNonRealtimeInstance(MediaStreamGraph* aGraph)
|
||||
// Start the graph, but don't produce anything
|
||||
graph->StartNonRealtimeProcessing(0);
|
||||
}
|
||||
graph->ForceShutDown();
|
||||
graph->ForceShutDown(nullptr);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(MediaStreamGraphImpl, nsIMemoryReporter)
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIAsyncShutdown.h"
|
||||
#include "Latency.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "GraphDriver.h"
|
||||
@ -139,13 +140,48 @@ public:
|
||||
* during RunInStableState; the messages will run on the graph thread.
|
||||
*/
|
||||
void AppendMessage(ControlMessage* aMessage);
|
||||
|
||||
// Shutdown helpers.
|
||||
|
||||
static already_AddRefed<nsIAsyncShutdownClient>
|
||||
GetShutdownBarrier()
|
||||
{
|
||||
nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown();
|
||||
MOZ_RELEASE_ASSERT(svc);
|
||||
|
||||
nsCOMPtr<nsIAsyncShutdownClient> barrier;
|
||||
nsresult rv = svc->GetProfileBeforeChange(getter_AddRefs(barrier));
|
||||
if (!barrier) {
|
||||
// We are probably in a content process.
|
||||
rv = svc->GetContentChildShutdown(getter_AddRefs(barrier));
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
MOZ_RELEASE_ASSERT(barrier);
|
||||
return barrier.forget();
|
||||
}
|
||||
|
||||
class ShutdownTicket final
|
||||
{
|
||||
public:
|
||||
explicit ShutdownTicket(nsIAsyncShutdownBlocker* aBlocker) : mBlocker(aBlocker) {}
|
||||
NS_INLINE_DECL_REFCOUNTING(ShutdownTicket)
|
||||
private:
|
||||
~ShutdownTicket()
|
||||
{
|
||||
nsCOMPtr<nsIAsyncShutdownClient> barrier = GetShutdownBarrier();
|
||||
barrier->RemoveBlocker(mBlocker);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAsyncShutdownBlocker> mBlocker;
|
||||
};
|
||||
|
||||
/**
|
||||
* Make this MediaStreamGraph enter forced-shutdown state. This state
|
||||
* will be noticed by the media graph thread, which will shut down all streams
|
||||
* and other state controlled by the media graph thread.
|
||||
* This is called during application shutdown.
|
||||
*/
|
||||
void ForceShutDown();
|
||||
void ForceShutDown(ShutdownTicket* aShutdownTicket);
|
||||
/**
|
||||
* Shutdown() this MediaStreamGraph's threads and return when they've shut down.
|
||||
*/
|
||||
@ -692,6 +728,12 @@ public:
|
||||
* True when we need to do a forced shutdown during application shutdown.
|
||||
*/
|
||||
bool mForceShutDown;
|
||||
|
||||
/**
|
||||
* Drop this reference during shutdown to unblock shutdown.
|
||||
**/
|
||||
RefPtr<ShutdownTicket> mForceShutdownTicket;
|
||||
|
||||
/**
|
||||
* True when we have posted an event to the main thread to run
|
||||
* RunInStableState() and the event hasn't run yet.
|
||||
|
@ -1108,6 +1108,10 @@ RTCPeerConnection.prototype = {
|
||||
return this._receivers;
|
||||
},
|
||||
|
||||
mozSelectSsrc: function(receiver, ssrcIndex) {
|
||||
this._impl.selectSsrc(receiver.track, ssrcIndex);
|
||||
},
|
||||
|
||||
get localDescription() {
|
||||
this._checkClosed();
|
||||
let sdp = this._impl.localDescription;
|
||||
|
@ -1448,7 +1448,7 @@ bool SkeletonState::DecodeFisbone(ogg_packet* aPacket)
|
||||
}
|
||||
msgLength--;
|
||||
msgProbe++;
|
||||
};
|
||||
}
|
||||
|
||||
if (!mMsgFieldStore.Contains(serialno)) {
|
||||
mMsgFieldStore.Put(serialno, field.forget());
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
int64_t GetMediaTimeUs() override;
|
||||
|
||||
// To update progress bar when the element is visible
|
||||
void SetElementVisibility(bool aIsVisible) override;;
|
||||
void SetElementVisibility(bool aIsVisible) override;
|
||||
|
||||
// Update ready state based on current play state. Not checking data
|
||||
// availability since offloading is currently done only when whole compressed
|
||||
|
@ -58,7 +58,6 @@ bool PDMFactory::sAndroidMCDecoderPreferred = false;
|
||||
bool PDMFactory::sGMPDecoderEnabled = false;
|
||||
#ifdef MOZ_FFVPX
|
||||
bool PDMFactory::sFFVPXDecoderEnabled = false;
|
||||
using namespace ffvpx;
|
||||
#endif
|
||||
#ifdef MOZ_FFMPEG
|
||||
bool PDMFactory::sFFmpegDecoderEnabled = false;
|
||||
@ -124,10 +123,10 @@ PDMFactory::Init()
|
||||
AppleDecoderModule::Init();
|
||||
#endif
|
||||
#ifdef MOZ_FFVPX
|
||||
FFVPXRuntimeLinker::Link();
|
||||
FFVPXRuntimeLinker::Init();
|
||||
#endif
|
||||
#ifdef MOZ_FFMPEG
|
||||
FFmpegRuntimeLinker::Link();
|
||||
FFmpegRuntimeLinker::Init();
|
||||
#endif
|
||||
GMPDecoderModule::Init();
|
||||
}
|
||||
|
@ -148,6 +148,12 @@ OpusDataDecoder::DoDecode(MediaRawData* aSample)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mLastFrameTime || mLastFrameTime.ref() != aSample->mTime) {
|
||||
// We are starting a new block.
|
||||
mFrames = 0;
|
||||
mLastFrameTime = Some(aSample->mTime);
|
||||
}
|
||||
|
||||
// Maximum value is 63*2880, so there's no chance of overflow.
|
||||
int32_t frames_number = opus_packet_get_nb_frames(aSample->Data(),
|
||||
aSample->Size());
|
||||
@ -253,8 +259,9 @@ OpusDataDecoder::DoDecode(MediaRawData* aSample)
|
||||
NS_WARNING("OpusDataDecoder: Int overflow converting WebM audio duration");
|
||||
return -1;
|
||||
}
|
||||
CheckedInt64 time = startTime - FramesToUsecs(mOpusParser->mPreSkip,
|
||||
mOpusParser->mRate);
|
||||
CheckedInt64 time =
|
||||
startTime - FramesToUsecs(mOpusParser->mPreSkip, mOpusParser->mRate) +
|
||||
FramesToUsecs(mFrames, mOpusParser->mRate);
|
||||
if (!time.isValid()) {
|
||||
NS_WARNING("OpusDataDecoder: Int overflow shifting tstamp by codec delay");
|
||||
return -1;
|
||||
@ -295,7 +302,7 @@ OpusDataDecoder::Flush()
|
||||
opus_multistream_decoder_ctl(mOpusDecoder, OPUS_RESET_STATE);
|
||||
mSkip = mOpusParser->mPreSkip;
|
||||
mPaddingDiscarded = false;
|
||||
mFrames = 0;
|
||||
mLastFrameTime.reset();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "OpusParser.h"
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -53,6 +54,7 @@ private:
|
||||
// will raise an error so we can indicate that the file is invalid.
|
||||
bool mPaddingDiscarded;
|
||||
int64_t mFrames;
|
||||
Maybe<int64_t> mLastFrameTime;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "mozilla/TaskQueue.h"
|
||||
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#include "FFmpegAudioDecoder.h"
|
||||
#include "TimeUnits.h"
|
||||
|
||||
@ -15,10 +14,10 @@
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
FFmpegAudioDecoder<LIBAV_VER>::FFmpegAudioDecoder(
|
||||
FFmpegAudioDecoder<LIBAV_VER>::FFmpegAudioDecoder(FFmpegLibWrapper* aLib,
|
||||
FlushableTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
|
||||
const AudioInfo& aConfig)
|
||||
: FFmpegDataDecoder(aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
|
||||
: FFmpegDataDecoder(aLib, aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
|
||||
{
|
||||
MOZ_COUNT_CTOR(FFmpegAudioDecoder);
|
||||
// Use a new MediaByteBuffer as the object will be modified during initialization.
|
||||
@ -44,11 +43,9 @@ FFmpegAudioDecoder<LIBAV_VER>::InitCodecContext()
|
||||
// isn't implemented.
|
||||
mCodecContext->thread_count = 1;
|
||||
// FFmpeg takes this as a suggestion for what format to use for audio samples.
|
||||
uint32_t major, minor, micro;
|
||||
FFmpegRuntimeLinker::GetVersion(major, minor, micro);
|
||||
// LibAV 0.8 produces rubbish float interleaved samples, request 16 bits audio.
|
||||
mCodecContext->request_sample_fmt =
|
||||
(major == 53) ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLT;
|
||||
(mLib->mVersion == 53) ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLT;
|
||||
}
|
||||
|
||||
static UniquePtr<AudioDataValue[]>
|
||||
@ -101,7 +98,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MediaRawData* aSample)
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
AVPacket packet;
|
||||
AV_CALL(av_init_packet(&packet));
|
||||
mLib->av_init_packet(&packet);
|
||||
|
||||
packet.data = const_cast<uint8_t*>(aSample->Data());
|
||||
packet.size = aSample->Size();
|
||||
@ -118,7 +115,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MediaRawData* aSample)
|
||||
while (packet.size > 0) {
|
||||
int decoded;
|
||||
int bytesConsumed =
|
||||
AV_CALL(avcodec_decode_audio4(mCodecContext, mFrame, &decoded, &packet));
|
||||
mLib->avcodec_decode_audio4(mCodecContext, mFrame, &decoded, &packet);
|
||||
|
||||
if (bytesConsumed < 0) {
|
||||
NS_WARNING("FFmpeg audio decoder error.");
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef __FFmpegAACDecoder_h__
|
||||
#define __FFmpegAACDecoder_h__
|
||||
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "FFmpegDataDecoder.h"
|
||||
|
||||
namespace mozilla
|
||||
@ -20,7 +21,7 @@ template <>
|
||||
class FFmpegAudioDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
|
||||
{
|
||||
public:
|
||||
FFmpegAudioDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
FFmpegAudioDecoder(FFmpegLibWrapper* aLib, FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
const AudioInfo& aConfig);
|
||||
virtual ~FFmpegAudioDecoder();
|
||||
|
@ -18,13 +18,14 @@
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
bool FFmpegDataDecoder<LIBAV_VER>::sFFmpegInitDone = false;
|
||||
StaticMutex FFmpegDataDecoder<LIBAV_VER>::sMonitor;
|
||||
|
||||
FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
AVCodecID aCodecID)
|
||||
: mTaskQueue(aTaskQueue)
|
||||
FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FFmpegLibWrapper* aLib,
|
||||
FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
AVCodecID aCodecID)
|
||||
: mLib(aLib)
|
||||
, mTaskQueue(aTaskQueue)
|
||||
, mCallback(aCallback)
|
||||
, mCodecContext(nullptr)
|
||||
, mFrame(NULL)
|
||||
@ -33,6 +34,7 @@ FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
, mMonitor("FFMpegaDataDecoder")
|
||||
, mIsFlushing(false)
|
||||
{
|
||||
MOZ_ASSERT(aLib);
|
||||
MOZ_COUNT_CTOR(FFmpegDataDecoder);
|
||||
}
|
||||
|
||||
@ -46,7 +48,7 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
|
||||
{
|
||||
FFMPEG_LOG("Initialising FFmpeg decoder.");
|
||||
|
||||
AVCodec* codec = FindAVCodec(mCodecID);
|
||||
AVCodec* codec = FindAVCodec(mLib, mCodecID);
|
||||
if (!codec) {
|
||||
NS_WARNING("Couldn't find ffmpeg decoder");
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -54,7 +56,7 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
|
||||
|
||||
StaticMutexAutoLock mon(sMonitor);
|
||||
|
||||
if (!(mCodecContext = AV_CALL(avcodec_alloc_context3(codec)))) {
|
||||
if (!(mCodecContext = mLib->avcodec_alloc_context3(codec))) {
|
||||
NS_WARNING("Couldn't init ffmpeg context");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -77,10 +79,10 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
|
||||
mCodecContext->flags |= CODEC_FLAG_EMU_EDGE;
|
||||
}
|
||||
|
||||
if (AV_CALL(avcodec_open2(mCodecContext, codec, nullptr)) < 0) {
|
||||
if (mLib->avcodec_open2(mCodecContext, codec, nullptr) < 0) {
|
||||
NS_WARNING("Couldn't initialise ffmpeg decoder");
|
||||
AV_CALL(avcodec_close(mCodecContext));
|
||||
AV_CALL(av_freep(&mCodecContext));
|
||||
mLib->avcodec_close(mCodecContext);
|
||||
mLib->av_freep(&mCodecContext);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -141,7 +143,7 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessFlush()
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
if (mCodecContext) {
|
||||
AV_CALL(avcodec_flush_buffers(mCodecContext));
|
||||
mLib->avcodec_flush_buffers(mCodecContext);
|
||||
}
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
mIsFlushing = false;
|
||||
@ -153,13 +155,13 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessShutdown()
|
||||
{
|
||||
StaticMutexAutoLock mon(sMonitor);
|
||||
|
||||
if (sFFmpegInitDone && mCodecContext) {
|
||||
AV_CALL(avcodec_close(mCodecContext));
|
||||
AV_CALL(av_freep(&mCodecContext));
|
||||
if (mCodecContext) {
|
||||
mLib->avcodec_close(mCodecContext);
|
||||
mLib->av_freep(&mCodecContext);
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 55
|
||||
AV_CALL(av_frame_free(&mFrame));
|
||||
mLib->av_frame_free(&mFrame);
|
||||
#elif LIBAVCODEC_VERSION_MAJOR == 54
|
||||
AV_CALL(avcodec_free_frame(&mFrame));
|
||||
mLib->avcodec_free_frame(&mFrame);
|
||||
#else
|
||||
delete mFrame;
|
||||
mFrame = nullptr;
|
||||
@ -173,36 +175,29 @@ FFmpegDataDecoder<LIBAV_VER>::PrepareFrame()
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 55
|
||||
if (mFrame) {
|
||||
AV_CALL(av_frame_unref(mFrame));
|
||||
mLib->av_frame_unref(mFrame);
|
||||
} else {
|
||||
mFrame = AV_CALL(av_frame_alloc());
|
||||
mFrame = mLib->av_frame_alloc();
|
||||
}
|
||||
#elif LIBAVCODEC_VERSION_MAJOR == 54
|
||||
if (mFrame) {
|
||||
AV_CALL(avcodec_get_frame_defaults(mFrame));
|
||||
mLib->avcodec_get_frame_defaults(mFrame);
|
||||
} else {
|
||||
mFrame = AV_CALL(avcodec_alloc_frame());
|
||||
mFrame = mLib->avcodec_alloc_frame();
|
||||
}
|
||||
#else
|
||||
delete mFrame;
|
||||
mFrame = new AVFrame;
|
||||
AV_CALL(avcodec_get_frame_defaults(mFrame));
|
||||
mLib->avcodec_get_frame_defaults(mFrame);
|
||||
#endif
|
||||
return mFrame;
|
||||
}
|
||||
|
||||
/* static */ AVCodec*
|
||||
FFmpegDataDecoder<LIBAV_VER>::FindAVCodec(AVCodecID aCodec)
|
||||
FFmpegDataDecoder<LIBAV_VER>::FindAVCodec(FFmpegLibWrapper* aLib,
|
||||
AVCodecID aCodec)
|
||||
{
|
||||
StaticMutexAutoLock mon(sMonitor);
|
||||
if (!sFFmpegInitDone) {
|
||||
AV_CALL(avcodec_register_all());
|
||||
#ifdef DEBUG
|
||||
AV_CALL(av_log_set_level(AV_LOG_DEBUG));
|
||||
#endif
|
||||
sFFmpegInitDone = true;
|
||||
}
|
||||
return AV_CALL(avcodec_find_decoder(aCodec));
|
||||
return aLib->avcodec_find_decoder(aCodec);
|
||||
}
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -8,9 +8,9 @@
|
||||
#define __FFmpegDataDecoder_h__
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "FFmpegLibs.h"
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "FFmpegLibs.h"
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
@ -24,7 +24,7 @@ template <>
|
||||
class FFmpegDataDecoder<LIBAV_VER> : public MediaDataDecoder
|
||||
{
|
||||
public:
|
||||
FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
FFmpegDataDecoder(FFmpegLibWrapper* aLib, FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
AVCodecID aCodecID);
|
||||
virtual ~FFmpegDataDecoder();
|
||||
@ -37,7 +37,7 @@ public:
|
||||
nsresult Drain() override;
|
||||
nsresult Shutdown() override;
|
||||
|
||||
static AVCodec* FindAVCodec(AVCodecID aCodec);
|
||||
static AVCodec* FindAVCodec(FFmpegLibWrapper* aLib, AVCodecID aCodec);
|
||||
|
||||
protected:
|
||||
// Flush and Drain operation, always run
|
||||
@ -48,6 +48,7 @@ protected:
|
||||
AVFrame* PrepareFrame();
|
||||
nsresult InitDecoder();
|
||||
|
||||
FFmpegLibWrapper* mLib;
|
||||
RefPtr<FlushableTaskQueue> mTaskQueue;
|
||||
MediaDataDecoderCallback* mCallback;
|
||||
|
||||
@ -65,7 +66,6 @@ protected:
|
||||
Atomic<bool> mIsFlushing;
|
||||
|
||||
private:
|
||||
static bool sFFmpegInitDone;
|
||||
static StaticMutex sMonitor;
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define __FFmpegDecoderModule_h__
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "FFmpegAudioDecoder.h"
|
||||
#include "FFmpegVideoDecoder.h"
|
||||
|
||||
@ -19,14 +20,14 @@ class FFmpegDecoderModule : public PlatformDecoderModule
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<PlatformDecoderModule>
|
||||
Create()
|
||||
Create(FFmpegLibWrapper* aLib)
|
||||
{
|
||||
RefPtr<PlatformDecoderModule> pdm = new FFmpegDecoderModule();
|
||||
RefPtr<PlatformDecoderModule> pdm = new FFmpegDecoderModule(aLib);
|
||||
|
||||
return pdm.forget();
|
||||
}
|
||||
|
||||
FFmpegDecoderModule() {}
|
||||
explicit FFmpegDecoderModule(FFmpegLibWrapper* aLib) : mLib(aLib) {}
|
||||
virtual ~FFmpegDecoderModule() {}
|
||||
|
||||
already_AddRefed<MediaDataDecoder>
|
||||
@ -37,7 +38,7 @@ public:
|
||||
MediaDataDecoderCallback* aCallback) override
|
||||
{
|
||||
RefPtr<MediaDataDecoder> decoder =
|
||||
new FFmpegVideoDecoder<V>(aVideoTaskQueue, aCallback, aConfig,
|
||||
new FFmpegVideoDecoder<V>(mLib, aVideoTaskQueue, aCallback, aConfig,
|
||||
aImageContainer);
|
||||
return decoder.forget();
|
||||
}
|
||||
@ -51,7 +52,7 @@ public:
|
||||
return nullptr;
|
||||
#else
|
||||
RefPtr<MediaDataDecoder> decoder =
|
||||
new FFmpegAudioDecoder<V>(aAudioTaskQueue, aCallback, aConfig);
|
||||
new FFmpegAudioDecoder<V>(mLib, aAudioTaskQueue, aCallback, aConfig);
|
||||
return decoder.forget();
|
||||
#endif
|
||||
}
|
||||
@ -68,7 +69,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
AVCodecID codec = audioCodec != AV_CODEC_ID_NONE ? audioCodec : videoCodec;
|
||||
return !!FFmpegDataDecoder<V>::FindAVCodec(codec);
|
||||
return !!FFmpegDataDecoder<V>::FindAVCodec(mLib, codec);
|
||||
}
|
||||
|
||||
ConversionRequired
|
||||
@ -83,6 +84,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
FFmpegLibWrapper* mLib;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -1,39 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
/* libavcodec */
|
||||
AV_FUNC(avcodec_alloc_context3, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_close, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_decode_audio4, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_decode_video2, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_find_decoder, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_flush_buffers, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_open2, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_register_all, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_init_packet, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_init, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_close, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_parse2, AV_FUNC_AVCODEC_ALL)
|
||||
#if LIBAVCODEC_VERSION_MAJOR <= 54 || defined(LIBAVCODEC_ALLVERSION)
|
||||
AV_FUNC(avcodec_get_frame_defaults, (AV_FUNC_53 | AV_FUNC_54))
|
||||
#endif
|
||||
|
||||
/* libavutil */
|
||||
AV_FUNC(av_log_set_level, AV_FUNC_AVUTIL_ALL)
|
||||
AV_FUNC(av_malloc, AV_FUNC_AVUTIL_ALL)
|
||||
AV_FUNC(av_freep, AV_FUNC_AVUTIL_ALL)
|
||||
|
||||
#if defined(LIBAVCODEC_VERSION_MAJOR) || defined(LIBAVCODEC_ALLVERSION)
|
||||
#if LIBAVCODEC_VERSION_MAJOR == 54 || defined(LIBAVCODEC_ALLVERSION)
|
||||
/* libavutil v54 only */
|
||||
AV_FUNC(avcodec_alloc_frame, AV_FUNC_AVUTIL_54)
|
||||
AV_FUNC(avcodec_free_frame, AV_FUNC_AVUTIL_54)
|
||||
#endif
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 55 || defined(LIBAVCODEC_ALLVERSION)
|
||||
/* libavutil v55 and later only */
|
||||
AV_FUNC(av_frame_alloc, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
AV_FUNC(av_frame_free, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
AV_FUNC(av_frame_unref, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
#endif
|
||||
#endif
|
149
dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
Normal file
149
dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
/* 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 "FFmpegLibWrapper.h"
|
||||
#include "FFmpegLog.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "prlink.h"
|
||||
|
||||
#define AV_LOG_DEBUG 48
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
FFmpegLibWrapper::FFmpegLibWrapper()
|
||||
{
|
||||
PodZero(this);
|
||||
}
|
||||
|
||||
FFmpegLibWrapper::~FFmpegLibWrapper()
|
||||
{
|
||||
Unlink();
|
||||
}
|
||||
|
||||
bool
|
||||
FFmpegLibWrapper::Link()
|
||||
{
|
||||
if (!mAVCodecLib || !mAVUtilLib) {
|
||||
Unlink();
|
||||
return false;
|
||||
}
|
||||
|
||||
avcodec_version =
|
||||
(decltype(avcodec_version))PR_FindSymbol(mAVCodecLib, "avcodec_version");
|
||||
if (!avcodec_version) {
|
||||
Unlink();
|
||||
return false;
|
||||
}
|
||||
uint32_t version = avcodec_version();
|
||||
mVersion = (version >> 16) & 0xff;
|
||||
uint32_t micro = version & 0xff;
|
||||
if (mVersion == 57 && micro != 100) {
|
||||
// a micro version of 100 indicates that it's FFmpeg (as opposed to LibAV).
|
||||
// Due to current AVCodecContext binary incompatibility we can only
|
||||
// support FFmpeg 57 at this stage.
|
||||
Unlink();
|
||||
return false;
|
||||
}
|
||||
|
||||
enum {
|
||||
AV_FUNC_AVUTIL_MASK = 1 << 8,
|
||||
AV_FUNC_53 = 1 << 0,
|
||||
AV_FUNC_54 = 1 << 1,
|
||||
AV_FUNC_55 = 1 << 2,
|
||||
AV_FUNC_56 = 1 << 3,
|
||||
AV_FUNC_57 = 1 << 4,
|
||||
AV_FUNC_AVUTIL_53 = AV_FUNC_53 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_54 = AV_FUNC_54 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_55 = AV_FUNC_55 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_56 = AV_FUNC_56 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_57 = AV_FUNC_57 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVCODEC_ALL = AV_FUNC_53 | AV_FUNC_54 | AV_FUNC_55 | AV_FUNC_56 | AV_FUNC_57,
|
||||
AV_FUNC_AVUTIL_ALL = AV_FUNC_AVCODEC_ALL | AV_FUNC_AVUTIL_MASK
|
||||
};
|
||||
|
||||
switch (mVersion) {
|
||||
case 53:
|
||||
version = AV_FUNC_53;
|
||||
break;
|
||||
case 54:
|
||||
version = AV_FUNC_54;
|
||||
break;
|
||||
case 55:
|
||||
version = AV_FUNC_55;
|
||||
break;
|
||||
case 56:
|
||||
version = AV_FUNC_56;
|
||||
break;
|
||||
case 57:
|
||||
version = AV_FUNC_57;
|
||||
break;
|
||||
default:
|
||||
FFMPEG_LOG("Unknown avcodec version");
|
||||
Unlink();
|
||||
return false;
|
||||
}
|
||||
|
||||
#define AV_FUNC(func, ver) \
|
||||
if ((ver) & version) { \
|
||||
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? mAVUtilLib : mAVCodecLib, #func))) { \
|
||||
FFMPEG_LOG("Couldn't load function " # func); \
|
||||
Unlink(); \
|
||||
return false; \
|
||||
} \
|
||||
} else { \
|
||||
func = (decltype(func))nullptr; \
|
||||
}
|
||||
AV_FUNC(av_lockmgr_register, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_alloc_context3, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_close, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_decode_audio4, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_decode_video2, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_find_decoder, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_flush_buffers, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_open2, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_register_all, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_init_packet, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_init, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_close, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(av_parser_parse2, AV_FUNC_AVCODEC_ALL)
|
||||
AV_FUNC(avcodec_get_frame_defaults, (AV_FUNC_53 | AV_FUNC_54))
|
||||
AV_FUNC(av_log_set_level, AV_FUNC_AVUTIL_ALL)
|
||||
AV_FUNC(av_malloc, AV_FUNC_AVUTIL_ALL)
|
||||
AV_FUNC(av_freep, AV_FUNC_AVUTIL_ALL)
|
||||
AV_FUNC(avcodec_alloc_frame, AV_FUNC_AVUTIL_54)
|
||||
AV_FUNC(avcodec_free_frame, AV_FUNC_AVUTIL_54)
|
||||
AV_FUNC(av_frame_alloc, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
AV_FUNC(av_frame_free, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
AV_FUNC(av_frame_unref, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
|
||||
#undef AV_FUNC
|
||||
|
||||
avcodec_register_all();
|
||||
#ifdef DEBUG
|
||||
av_log_set_level(AV_LOG_DEBUG);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
FFmpegLibWrapper::Unlink()
|
||||
{
|
||||
if (av_lockmgr_register) {
|
||||
// Registering a null lockmgr cause the destruction of libav* global mutexes
|
||||
// as the default lockmgr that allocated them will be deregistered.
|
||||
// This prevents ASAN and valgrind to report sizeof(pthread_mutex_t) leaks.
|
||||
av_lockmgr_register(nullptr);
|
||||
}
|
||||
if (mAVUtilLib && mAVUtilLib != mAVCodecLib) {
|
||||
PR_UnloadLibrary(mAVUtilLib);
|
||||
}
|
||||
if (mAVCodecLib) {
|
||||
PR_UnloadLibrary(mAVCodecLib);
|
||||
}
|
||||
PodZero(this);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
79
dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
Normal file
79
dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* 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 __FFmpegLibWrapper_h__
|
||||
#define __FFmpegLibWrapper_h__
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
struct AVCodec;
|
||||
struct AVCodecContext;
|
||||
struct AVFrame;
|
||||
struct AVPacket;
|
||||
struct AVDictionary;
|
||||
struct AVCodecParserContext;
|
||||
struct PRLibrary;
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
struct FFmpegLibWrapper
|
||||
{
|
||||
FFmpegLibWrapper();
|
||||
~FFmpegLibWrapper();
|
||||
|
||||
// Attempt to resolve all symbols. Return true of successful.
|
||||
// Upon failure, the entire object will be reset and any attached libraries
|
||||
// will be unlinked.
|
||||
bool Link();
|
||||
|
||||
// Reset the wrapper and unlink all attached libraries.
|
||||
void Unlink();
|
||||
|
||||
// indicate the version of libavcodec linked to.
|
||||
// 0 indicates that the function wasn't initialized with Link().
|
||||
int mVersion;
|
||||
|
||||
// libavcodec
|
||||
unsigned (*avcodec_version)();
|
||||
int (*av_lockmgr_register)(int (*cb)(void** mutex, int op));
|
||||
AVCodecContext* (*avcodec_alloc_context3)(const AVCodec* codec);
|
||||
int (*avcodec_close)(AVCodecContext* avctx);
|
||||
int (*avcodec_decode_audio4)(AVCodecContext* avctx, AVFrame* frame, int* got_frame_ptr, const AVPacket* avpkt);
|
||||
int (*avcodec_decode_video2)(AVCodecContext* avctx, AVFrame* picture, int* got_picture_ptr, const AVPacket* avpkt);
|
||||
AVCodec* (*avcodec_find_decoder)(int id);
|
||||
void (*avcodec_flush_buffers)(AVCodecContext *avctx);
|
||||
int (*avcodec_open2)(AVCodecContext *avctx, const AVCodec* codec, AVDictionary** options);
|
||||
void (*avcodec_register_all)();
|
||||
void (*av_init_packet)(AVPacket* pkt);
|
||||
AVCodecParserContext* (*av_parser_init)(int codec_id);
|
||||
void (*av_parser_close)(AVCodecParserContext* s);
|
||||
int (*av_parser_parse2)(AVCodecParserContext* s, AVCodecContext* avctx, uint8_t** poutbuf, int* poutbuf_size, const uint8_t* buf, int buf_size, int64_t pts, int64_t dts, int64_t pos);
|
||||
|
||||
// only used in libavcodec <= 54
|
||||
void (*avcodec_get_frame_defaults)(AVFrame* pic);
|
||||
|
||||
// libavutil
|
||||
void (*av_log_set_level)(int level);
|
||||
void* (*av_malloc)(size_t size);
|
||||
void (*av_freep)(void *ptr);
|
||||
|
||||
// libavutil v54 only
|
||||
AVFrame* (*avcodec_alloc_frame)();
|
||||
void (*avcodec_free_frame)(AVFrame** frame);
|
||||
|
||||
// libavutil v55 and later only
|
||||
AVFrame* (*av_frame_alloc)();
|
||||
void (*av_frame_free)(AVFrame** frame);
|
||||
void (*av_frame_unref)(AVFrame* frame);
|
||||
|
||||
PRLibrary* mAVCodecLib;
|
||||
PRLibrary* mAVUtilLib;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // FFmpegLibWrapper
|
@ -7,8 +7,6 @@
|
||||
#ifndef __FFmpegLibs_h__
|
||||
#define __FFmpegLibs_h__
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
extern "C" {
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC visibility push(default)
|
||||
@ -37,23 +35,4 @@ enum { LIBAV_VER = FFVPX_VERSION };
|
||||
enum { LIBAV_VER = LIBAVCODEC_VERSION_MAJOR };
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef USING_MOZFFVPX
|
||||
namespace ffvpx {
|
||||
#endif
|
||||
|
||||
#define AV_FUNC(func, ver) extern decltype(func)* func;
|
||||
#include "FFmpegFunctionList.h"
|
||||
#undef AV_FUNC
|
||||
|
||||
#ifdef USING_MOZFFVPX
|
||||
} // namespace ffvpx
|
||||
#define AV_CALL(func) mozilla::ffvpx::func
|
||||
#else
|
||||
#define AV_CALL(func) mozilla::func
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // __FFmpegLibs_h__
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef __FFmpegLog_h__
|
||||
#define __FFmpegLog_h__
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define FFMPEG_LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "FFmpegLog.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "prlink.h"
|
||||
|
||||
namespace mozilla
|
||||
@ -19,9 +19,11 @@ FFmpegRuntimeLinker::LinkStatus FFmpegRuntimeLinker::sLinkStatus =
|
||||
template <int V> class FFmpegDecoderModule
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<PlatformDecoderModule> Create();
|
||||
static already_AddRefed<PlatformDecoderModule> Create(FFmpegLibWrapper*);
|
||||
};
|
||||
|
||||
static FFmpegLibWrapper sLibAV;
|
||||
|
||||
static const char* sLibs[] = {
|
||||
#if defined(XP_DARWIN)
|
||||
"libavcodec.57.dylib",
|
||||
@ -40,30 +42,8 @@ static const char* sLibs[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
PRLibrary* FFmpegRuntimeLinker::sLinkedLib = nullptr;
|
||||
PRLibrary* FFmpegRuntimeLinker::sLinkedUtilLib = nullptr;
|
||||
static unsigned (*avcodec_version)() = nullptr;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define AV_FUNC(func, ver) void (*func)();
|
||||
#define LIBAVCODEC_ALLVERSION
|
||||
#else
|
||||
#define AV_FUNC(func, ver) decltype(func)* func;
|
||||
#endif
|
||||
#include "FFmpegFunctionList.h"
|
||||
#undef AV_FUNC
|
||||
|
||||
static PRLibrary*
|
||||
MozAVLink(const char* aName)
|
||||
{
|
||||
PRLibSpec lspec;
|
||||
lspec.type = PR_LibSpec_Pathname;
|
||||
lspec.value.pathname = aName;
|
||||
return PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFmpegRuntimeLinker::Link()
|
||||
FFmpegRuntimeLinker::Init()
|
||||
{
|
||||
if (sLinkStatus) {
|
||||
return sLinkStatus == LinkStatus_SUCCEEDED;
|
||||
@ -72,15 +52,16 @@ FFmpegRuntimeLinker::Link()
|
||||
|
||||
for (size_t i = 0; i < ArrayLength(sLibs); i++) {
|
||||
const char* lib = sLibs[i];
|
||||
sLinkedLib = MozAVLink(lib);
|
||||
if (sLinkedLib) {
|
||||
sLinkedUtilLib = sLinkedLib;
|
||||
if (Bind(lib)) {
|
||||
PRLibSpec lspec;
|
||||
lspec.type = PR_LibSpec_Pathname;
|
||||
lspec.value.pathname = lib;
|
||||
sLibAV.mAVCodecLib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
|
||||
if (sLibAV.mAVCodecLib) {
|
||||
sLibAV.mAVUtilLib = sLibAV.mAVCodecLib;
|
||||
if (sLibAV.Link()) {
|
||||
sLinkStatus = LinkStatus_SUCCEEDED;
|
||||
return true;
|
||||
}
|
||||
// Shouldn't happen but if it does then we try the next lib..
|
||||
Unlink();
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,113 +71,26 @@ FFmpegRuntimeLinker::Link()
|
||||
}
|
||||
FFMPEG_LOG(" ]\n");
|
||||
|
||||
Unlink();
|
||||
|
||||
sLinkStatus = LinkStatus_FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFmpegRuntimeLinker::Bind(const char* aLibName)
|
||||
{
|
||||
avcodec_version = (decltype(avcodec_version))PR_FindSymbol(sLinkedLib,
|
||||
"avcodec_version");
|
||||
uint32_t major, minor, micro;
|
||||
if (!GetVersion(major, minor, micro)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int version;
|
||||
switch (major) {
|
||||
case 53:
|
||||
version = AV_FUNC_53;
|
||||
break;
|
||||
case 54:
|
||||
version = AV_FUNC_54;
|
||||
break;
|
||||
case 56:
|
||||
// We use libavcodec 55 code instead. Fallback
|
||||
case 55:
|
||||
version = AV_FUNC_55;
|
||||
break;
|
||||
case 57:
|
||||
if (micro != 100) {
|
||||
// a micro version of 100 indicates that it's FFmpeg (as opposed to LibAV.
|
||||
// Due to current AVCodecContext binary incompatibility we can only
|
||||
// support FFmpeg at this stage.
|
||||
return false;
|
||||
}
|
||||
version = AV_FUNC_57;
|
||||
break;
|
||||
default:
|
||||
// Not supported at this stage.
|
||||
return false;
|
||||
}
|
||||
|
||||
#define AV_FUNC(func, ver) \
|
||||
if ((ver) & version) { \
|
||||
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? sLinkedUtilLib : sLinkedLib, #func))) { \
|
||||
FFMPEG_LOG("Couldn't load function " #func " from %s.", aLibName); \
|
||||
return false; \
|
||||
} \
|
||||
} else { \
|
||||
func = (decltype(func))nullptr; \
|
||||
}
|
||||
#include "FFmpegFunctionList.h"
|
||||
#undef AV_FUNC
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<PlatformDecoderModule>
|
||||
FFmpegRuntimeLinker::CreateDecoderModule()
|
||||
{
|
||||
if (!Link()) {
|
||||
if (!Init()) {
|
||||
return nullptr;
|
||||
}
|
||||
uint32_t major, minor, micro;
|
||||
if (!GetVersion(major, minor, micro)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PlatformDecoderModule> module;
|
||||
switch (major) {
|
||||
case 53: module = FFmpegDecoderModule<53>::Create(); break;
|
||||
case 54: module = FFmpegDecoderModule<54>::Create(); break;
|
||||
switch (sLibAV.mVersion) {
|
||||
case 53: module = FFmpegDecoderModule<53>::Create(&sLibAV); break;
|
||||
case 54: module = FFmpegDecoderModule<54>::Create(&sLibAV); break;
|
||||
case 55:
|
||||
case 56: module = FFmpegDecoderModule<55>::Create(); break;
|
||||
case 57: module = FFmpegDecoderModule<57>::Create(); break;
|
||||
case 56: module = FFmpegDecoderModule<55>::Create(&sLibAV); break;
|
||||
case 57: module = FFmpegDecoderModule<57>::Create(&sLibAV); break;
|
||||
default: module = nullptr;
|
||||
}
|
||||
return module.forget();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
FFmpegRuntimeLinker::Unlink()
|
||||
{
|
||||
if (sLinkedUtilLib && sLinkedUtilLib != sLinkedLib) {
|
||||
PR_UnloadLibrary(sLinkedUtilLib);
|
||||
}
|
||||
if (sLinkedLib) {
|
||||
PR_UnloadLibrary(sLinkedLib);
|
||||
sLinkedLib = nullptr;
|
||||
sLinkStatus = LinkStatus_INIT;
|
||||
avcodec_version = nullptr;
|
||||
}
|
||||
sLinkedUtilLib = nullptr;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFmpegRuntimeLinker::GetVersion(uint32_t& aMajor, uint32_t& aMinor, uint32_t& aMicro)
|
||||
{
|
||||
if (!avcodec_version) {
|
||||
return false;
|
||||
}
|
||||
uint32_t version = avcodec_version();
|
||||
aMajor = (version >> 16) & 0xff;
|
||||
aMinor = (version >> 8) & 0xff;
|
||||
aMicro = version & 0xff;
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef LIBAVCODEC_ALLVERSION
|
||||
} // namespace mozilla
|
||||
|
@ -8,43 +8,17 @@
|
||||
#define __FFmpegRuntimeLinker_h__
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include <stdint.h>
|
||||
|
||||
struct PRLibrary;
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
enum {
|
||||
AV_FUNC_AVUTIL_MASK = 1 << 8,
|
||||
AV_FUNC_53 = 1 << 0,
|
||||
AV_FUNC_54 = 1 << 1,
|
||||
AV_FUNC_55 = 1 << 2,
|
||||
AV_FUNC_56 = 1 << 3,
|
||||
AV_FUNC_57 = 1 << 4,
|
||||
AV_FUNC_AVUTIL_53 = AV_FUNC_53 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_54 = AV_FUNC_54 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_55 = AV_FUNC_55 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_56 = AV_FUNC_56 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVUTIL_57 = AV_FUNC_57 | AV_FUNC_AVUTIL_MASK,
|
||||
AV_FUNC_AVCODEC_ALL = AV_FUNC_53 | AV_FUNC_54 | AV_FUNC_55 | AV_FUNC_56 | AV_FUNC_57,
|
||||
AV_FUNC_AVUTIL_ALL = AV_FUNC_AVCODEC_ALL | AV_FUNC_AVUTIL_MASK
|
||||
};
|
||||
|
||||
class FFmpegRuntimeLinker
|
||||
{
|
||||
public:
|
||||
static bool Link();
|
||||
static void Unlink();
|
||||
static bool Init();
|
||||
static already_AddRefed<PlatformDecoderModule> CreateDecoderModule();
|
||||
static bool GetVersion(uint32_t& aMajor, uint32_t& aMinor, uint32_t& aMicro);
|
||||
|
||||
private:
|
||||
static PRLibrary* sLinkedLib;
|
||||
static PRLibrary* sLinkedUtilLib;
|
||||
|
||||
static bool Bind(const char* aLibName);
|
||||
|
||||
static enum LinkStatus {
|
||||
LinkStatus_INIT = 0,
|
||||
LinkStatus_FAILED,
|
||||
|
@ -98,11 +98,11 @@ FFmpegVideoDecoder<LIBAV_VER>::PtsCorrectionContext::Reset()
|
||||
mLastDts = INT64_MIN;
|
||||
}
|
||||
|
||||
FFmpegVideoDecoder<LIBAV_VER>::FFmpegVideoDecoder(
|
||||
FFmpegVideoDecoder<LIBAV_VER>::FFmpegVideoDecoder(FFmpegLibWrapper* aLib,
|
||||
FlushableTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
|
||||
const VideoInfo& aConfig,
|
||||
ImageContainer* aImageContainer)
|
||||
: FFmpegDataDecoder(aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
|
||||
: FFmpegDataDecoder(aLib, aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
|
||||
, mImageContainer(aImageContainer)
|
||||
, mDisplay(aConfig.mDisplay)
|
||||
, mImage(aConfig.mImage)
|
||||
@ -151,7 +151,7 @@ FFmpegVideoDecoder<LIBAV_VER>::InitCodecContext()
|
||||
// FFmpeg will call back to this to negotiate a video pixel format.
|
||||
mCodecContext->get_format = ChoosePixelFormat;
|
||||
|
||||
mCodecParser = AV_CALL(av_parser_init(mCodecID));
|
||||
mCodecParser = mLib->av_parser_init(mCodecID);
|
||||
if (mCodecParser) {
|
||||
mCodecParser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
|
||||
}
|
||||
@ -175,10 +175,10 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
|
||||
while (inputSize) {
|
||||
uint8_t* data;
|
||||
int size;
|
||||
int len = AV_CALL(av_parser_parse2(mCodecParser, mCodecContext, &data, &size,
|
||||
inputData, inputSize,
|
||||
aSample->mTime, aSample->mTimecode,
|
||||
aSample->mOffset));
|
||||
int len = mLib->av_parser_parse2(mCodecParser, mCodecContext, &data, &size,
|
||||
inputData, inputSize,
|
||||
aSample->mTime, aSample->mTimecode,
|
||||
aSample->mOffset);
|
||||
if (size_t(len) > inputSize) {
|
||||
mCallback->Error();
|
||||
return DecodeResult::DECODE_ERROR;
|
||||
@ -210,7 +210,7 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
|
||||
AVPacket packet;
|
||||
AV_CALL(av_init_packet(&packet));
|
||||
mLib->av_init_packet(&packet);
|
||||
|
||||
packet.data = aData;
|
||||
packet.size = aSize;
|
||||
@ -237,7 +237,7 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
|
||||
|
||||
int decoded;
|
||||
int bytesConsumed =
|
||||
AV_CALL(avcodec_decode_video2(mCodecContext, mFrame, &decoded, &packet));
|
||||
mLib->avcodec_decode_video2(mCodecContext, mFrame, &decoded, &packet);
|
||||
|
||||
FFMPEG_LOG("DoDecodeFrame:decode_video: rv=%d decoded=%d "
|
||||
"(Input: pts(%lld) dts(%lld) Output: pts(%lld) "
|
||||
@ -361,7 +361,7 @@ FFmpegVideoDecoder<LIBAV_VER>::~FFmpegVideoDecoder()
|
||||
{
|
||||
MOZ_COUNT_DTOR(FFmpegVideoDecoder);
|
||||
if (mCodecParser) {
|
||||
AV_CALL(av_parser_close(mCodecParser));
|
||||
mLib->av_parser_close(mCodecParser);
|
||||
mCodecParser = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef __FFmpegVideoDecoder_h__
|
||||
#define __FFmpegVideoDecoder_h__
|
||||
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "FFmpegDataDecoder.h"
|
||||
#include "mozilla/Pair.h"
|
||||
#include "nsTArray.h"
|
||||
@ -32,10 +33,10 @@ class FFmpegVideoDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
|
||||
};
|
||||
|
||||
public:
|
||||
FFmpegVideoDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
const VideoInfo& aConfig,
|
||||
ImageContainer* aImageContainer);
|
||||
FFmpegVideoDecoder(FFmpegLibWrapper* aLib, FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
const VideoInfo& aConfig,
|
||||
ImageContainer* aImageContainer);
|
||||
virtual ~FFmpegVideoDecoder();
|
||||
|
||||
RefPtr<InitPromise> Init() override;
|
||||
|
@ -5,47 +5,27 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FFVPXRuntimeLinker.h"
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#include "FFmpegLibWrapper.h"
|
||||
#include "FFmpegLog.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsXPCOMPrivate.h" // for XUL_DLL
|
||||
#include "prmem.h"
|
||||
#include "prlink.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/avutil.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
template <int V> class FFmpegDecoderModule
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<PlatformDecoderModule> Create();
|
||||
static already_AddRefed<PlatformDecoderModule> Create(FFmpegLibWrapper*);
|
||||
};
|
||||
|
||||
namespace ffvpx
|
||||
{
|
||||
static FFmpegLibWrapper sFFVPXLib;
|
||||
|
||||
FFVPXRuntimeLinker::LinkStatus FFVPXRuntimeLinker::sLinkStatus =
|
||||
LinkStatus_INIT;
|
||||
|
||||
PRLibrary* FFVPXRuntimeLinker::sLinkedLib = nullptr;
|
||||
PRLibrary* FFVPXRuntimeLinker::sLinkedUtilLib = nullptr;
|
||||
static unsigned (*avcodec_version)() = nullptr;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define AV_FUNC(func, ver) void (*func)();
|
||||
#define LIBAVCODEC_ALLVERSION
|
||||
#else
|
||||
#define AV_FUNC(func, ver) decltype(func)* func;
|
||||
#endif
|
||||
#include "FFmpegFunctionList.h"
|
||||
#undef AV_FUNC
|
||||
|
||||
static PRLibrary*
|
||||
MozAVLink(const char* aName)
|
||||
{
|
||||
@ -56,7 +36,7 @@ MozAVLink(const char* aName)
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFVPXRuntimeLinker::Link()
|
||||
FFVPXRuntimeLinker::Init()
|
||||
{
|
||||
if (sLinkStatus) {
|
||||
return sLinkStatus == LinkStatus_SUCCEEDED;
|
||||
@ -67,7 +47,7 @@ FFVPXRuntimeLinker::Link()
|
||||
// We retrieve the path of the XUL library as this is where mozavcodec and
|
||||
// mozavutil libs are located.
|
||||
char* path =
|
||||
PR_GetLibraryFilePathname(XUL_DLL, (PRFuncPtr)&FFVPXRuntimeLinker::Link);
|
||||
PR_GetLibraryFilePathname(XUL_DLL, (PRFuncPtr)&FFVPXRuntimeLinker::Init);
|
||||
if (!path) {
|
||||
return false;
|
||||
}
|
||||
@ -94,69 +74,29 @@ FFVPXRuntimeLinker::Link()
|
||||
if (!libname) {
|
||||
return false;
|
||||
}
|
||||
sLinkedUtilLib = MozAVLink(libname);
|
||||
sFFVPXLib.mAVUtilLib = MozAVLink(libname);
|
||||
PR_FreeLibraryName(libname);
|
||||
libname = PR_GetLibraryName(rootPath.get(), "mozavcodec");
|
||||
if (libname) {
|
||||
sLinkedLib = MozAVLink(libname);
|
||||
sFFVPXLib.mAVCodecLib = MozAVLink(libname);
|
||||
PR_FreeLibraryName(libname);
|
||||
if (sLinkedLib && sLinkedUtilLib) {
|
||||
if (Bind("mozavcodec")) {
|
||||
sLinkStatus = LinkStatus_SUCCEEDED;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Unlink();
|
||||
|
||||
if (sFFVPXLib.Link()) {
|
||||
sLinkStatus = LinkStatus_SUCCEEDED;
|
||||
return true;
|
||||
}
|
||||
sLinkStatus = LinkStatus_FAILED;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FFVPXRuntimeLinker::Bind(const char* aLibName)
|
||||
{
|
||||
int version = AV_FUNC_57;
|
||||
|
||||
#define AV_FUNC(func, ver) \
|
||||
if ((ver) & version) { \
|
||||
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? sLinkedUtilLib : sLinkedLib, #func))) { \
|
||||
FFMPEG_LOG("Couldn't load function " #func " from %s.", aLibName); \
|
||||
return false; \
|
||||
} \
|
||||
} else { \
|
||||
func = (decltype(func))nullptr; \
|
||||
}
|
||||
#include "FFmpegFunctionList.h"
|
||||
#undef AV_FUNC
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<PlatformDecoderModule>
|
||||
FFVPXRuntimeLinker::CreateDecoderModule()
|
||||
{
|
||||
if (!Link()) {
|
||||
if (!Init()) {
|
||||
return nullptr;
|
||||
}
|
||||
return FFmpegDecoderModule<FFVPX_VERSION>::Create();
|
||||
return FFmpegDecoderModule<FFVPX_VERSION>::Create(&sFFVPXLib);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
FFVPXRuntimeLinker::Unlink()
|
||||
{
|
||||
if (sLinkedUtilLib && sLinkedUtilLib != sLinkedLib) {
|
||||
PR_UnloadLibrary(sLinkedUtilLib);
|
||||
}
|
||||
if (sLinkedLib) {
|
||||
PR_UnloadLibrary(sLinkedLib);
|
||||
sLinkedLib = nullptr;
|
||||
sLinkStatus = LinkStatus_INIT;
|
||||
avcodec_version = nullptr;
|
||||
}
|
||||
sLinkedUtilLib = nullptr;
|
||||
}
|
||||
|
||||
#undef LIBAVCODEC_ALLVERSION
|
||||
} // namespace ffvpx
|
||||
} // namespace mozilla
|
||||
|
@ -9,35 +9,23 @@
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
struct PRLibrary;
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
namespace ffvpx
|
||||
{
|
||||
|
||||
class FFVPXRuntimeLinker
|
||||
{
|
||||
public:
|
||||
static bool Link();
|
||||
static void Unlink();
|
||||
static bool Init();
|
||||
static already_AddRefed<PlatformDecoderModule> CreateDecoderModule();
|
||||
|
||||
private:
|
||||
static PRLibrary* sLinkedLib;
|
||||
static PRLibrary* sLinkedUtilLib;
|
||||
static enum LinkStatus {
|
||||
LinkStatus_INIT = 0,
|
||||
LinkStatus_FAILED,
|
||||
LinkStatus_SUCCEEDED
|
||||
} sLinkStatus;
|
||||
|
||||
static bool Bind(const char* aLibName);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* __FFVPXRuntimeLinker_h__ */
|
||||
|
22
dom/media/platforms/ffmpeg/moz.build
Normal file
22
dom/media/platforms/ffmpeg/moz.build
Normal file
@ -0,0 +1,22 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
EXPORTS += [
|
||||
'FFmpegRuntimeLinker.h',
|
||||
]
|
||||
|
||||
DIRS += [
|
||||
'libav53',
|
||||
'libav54',
|
||||
'libav55',
|
||||
'ffmpeg57',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'FFmpegRuntimeLinker.cpp',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
@ -38,23 +38,20 @@ if CONFIG['MOZ_WMF']:
|
||||
if CONFIG['MOZ_EME']:
|
||||
DIRS += ['agnostic/eme']
|
||||
|
||||
if CONFIG['MOZ_FFVPX'] or CONFIG['MOZ_FFMPEG']:
|
||||
# common code to either FFmpeg or FFVPX
|
||||
UNIFIED_SOURCES += [
|
||||
'ffmpeg/FFmpegLibWrapper.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_FFVPX']:
|
||||
DIRS += [
|
||||
'ffmpeg/ffvpx',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_FFMPEG']:
|
||||
EXPORTS += [
|
||||
'ffmpeg/FFmpegRuntimeLinker.h',
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
'ffmpeg/FFmpegRuntimeLinker.cpp',
|
||||
]
|
||||
DIRS += [
|
||||
'ffmpeg/libav53',
|
||||
'ffmpeg/libav54',
|
||||
'ffmpeg/libav55',
|
||||
'ffmpeg/ffmpeg57',
|
||||
'ffmpeg',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_APPLEMEDIA']:
|
||||
|
@ -1,7 +0,0 @@
|
||||
exclude MANIFEST.in
|
||||
include requirements.txt
|
||||
include setup.py
|
||||
recursive-include firefox_media_tests *
|
||||
recursive-include media_utils *
|
||||
|
||||
|
5
dom/media/test/external/MANIFEST.in
vendored
Normal file
5
dom/media/test/external/MANIFEST.in
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
exclude MANIFEST.in
|
||||
recursive-include external_media_harness *
|
||||
recursive-include external_media_tests *
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
firefox-media-tests
|
||||
external-media-tests
|
||||
===================
|
||||
|
||||
[Marionette Python tests][marionette-python-tests] for media playback in Mozilla Firefox. MediaTestCase uses [Firefox Puppeteer][ff-puppeteer-docs] library.
|
||||
@ -6,7 +6,7 @@ firefox-media-tests
|
||||
Setup
|
||||
-----
|
||||
|
||||
The instructions below assume you have a copy of the project in `some/path/firefox-media-tests` and they refer to this path as `$PROJECT_HOME`.
|
||||
Normally, you get this source by cloning a firefox repo such as mozilla-central. The path to these tests would be in <mozilla-central>/dom/media/test/external, and these instuctions refer to this path as '$PROJECT_HOME'.
|
||||
|
||||
* Create a virtualenv called `foo`.
|
||||
|
||||
@ -15,13 +15,13 @@ The instructions below assume you have a copy of the project in `some/path/firef
|
||||
$ source foo/bin/activate #or `foo\Scripts\activate` on Windows
|
||||
```
|
||||
|
||||
* Install `firefox-media-tests` in development mode. (To get an environment that is closer to what is actually used in Mozilla's automation jobs, run `pip install -r requirements.txt` first.)
|
||||
* Install `external-media-tests` in development mode. (To get an environment that is closer to what is actually used in Mozilla's automation jobs, run `pip install -r requirements.txt` first.)
|
||||
|
||||
```sh
|
||||
$ python setup.py develop
|
||||
```
|
||||
|
||||
Now `firefox-media-tests` should be a recognized command. Try `firefox-media-tests --help` to see if it works.
|
||||
Now `external-media-tests` should be a recognized command. Try `external-media-tests --help` to see if it works.
|
||||
|
||||
|
||||
Running the Tests
|
||||
@ -29,28 +29,28 @@ Running the Tests
|
||||
|
||||
In the examples below, `$FF_PATH` is a path to a recent Firefox binary.
|
||||
|
||||
This runs all the tests listed in `$PROJECT_HOME/firefox_media_tests/manifest.ini`:
|
||||
This runs all the tests listed in `$PROJECT_HOME/external_media_tests/manifest.ini`:
|
||||
|
||||
```sh
|
||||
$ firefox-media-tests --binary $FF_PATH
|
||||
$ external-media-tests --binary $FF_PATH
|
||||
```
|
||||
|
||||
You can also run all the tests at a particular path:
|
||||
|
||||
```sh
|
||||
$ firefox-media-tests --binary $FF_PATH some/path/foo
|
||||
$ external-media-tests --binary $FF_PATH some/path/foo
|
||||
```
|
||||
|
||||
Or you can run the tests that are listed in a manifest file of your choice.
|
||||
|
||||
```sh
|
||||
$ firefox-media-tests --binary $FF_PATH some/other/path/manifest.ini
|
||||
$ external-media-tests --binary $FF_PATH some/other/path/manifest.ini
|
||||
```
|
||||
|
||||
By default, the urls listed in `firefox_media_tests/urls/default.ini` are used for the tests, but you can also supply your own ini file of urls:
|
||||
By default, the urls listed in `external_media_tests/urls/default.ini` are used for the tests, but you can also supply your own ini file of urls:
|
||||
|
||||
```sh
|
||||
$ firefox-media-tests --binary $FF_PATH --urls some/other/path/my_urls.ini
|
||||
$ external-media-tests --binary $FF_PATH --urls some/other/path/my_urls.ini
|
||||
```
|
||||
|
||||
### Running EME tests
|
||||
@ -58,7 +58,7 @@ By default, the urls listed in `firefox_media_tests/urls/default.ini` are used f
|
||||
In order to run EME tests, you must use a Firefox profile that has a signed plugin-container.exe and voucher.bin. With Netflix, this will be created when you log in and save the credentials. You must also use a custom .ini file for urls to the provider's content and indicate which test to run, like above. Ex:
|
||||
|
||||
```sh
|
||||
$ firefox-media-tests --binary $FF_PATH some/path/tests.ini --profile custom_profile --urls some/path/provider-urls.ini
|
||||
$ external-media-tests --binary $FF_PATH some/path/tests.ini --profile custom_profile --urls some/path/provider-urls.ini
|
||||
```
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ What if Firefox crashes during a test run? You want to know why! To report usefu
|
||||
5. Run the tests with a `--symbols-path` flag
|
||||
|
||||
```sh
|
||||
$ firefox-media-tests --binary $FF_PATH --symbols-path path/to/example/firefox-38.0a2.en-US.win32.crashreporter-symbols
|
||||
$ external-media-tests --binary $FF_PATH --symbols-path path/to/example/firefox-38.0a2.en-US.win32.crashreporter-symbols
|
||||
```
|
||||
|
||||
To check whether the above setup is working for you, trigger a (silly) Firefox crash while the tests are running. One way to do this is with the [crashme add-on](https://github.com/luser/crashme) -- you can add it to Firefox even while the tests are running. Another way on Linux and Mac OS systems:
|
||||
@ -101,7 +101,7 @@ To check whether the above setup is working for you, trigger a (silly) Firefox c
|
||||
$ kill -6 1234
|
||||
```
|
||||
|
||||
Somewhere in the output produced by `firefox-media-tests`, you should see something like:
|
||||
Somewhere in the output produced by `external-media-tests`, you should see something like:
|
||||
|
||||
```
|
||||
0:12.68 CRASH: MainThread pid:1234. Test:test_basic_playback.py TestVideoPlayback.test_playback_starts.
|
||||
@ -137,11 +137,11 @@ On Windows, use browsermob-proxy.bat.
|
||||
You can then call browsermob to shape the network. You can find an example in firefox_media_tests/playback/test_playback_limiting_bandwidth.py. Another example can be found at https://dxr.mozilla.org/mozilla-central/source/testing/marionette/client/marionette/tests/unit/test_browsermobproxy.py.
|
||||
|
||||
### A warning about video URLs
|
||||
The ini files in `firefox_media_tests/urls` may contain URLs pulled from Firefox crash or bug data. Automated tests don't care about video content, but you might: visit these at your own risk and be aware that they may be NSFW. We do not intend to ever moderate or filter these URLs.
|
||||
The ini files in `external_media_tests/urls` may contain URLs pulled from Firefox crash or bug data. Automated tests don't care about video content, but you might: visit these at your own risk and be aware that they may be NSFW. We do not intend to ever moderate or filter these URLs.
|
||||
|
||||
Writing a test
|
||||
--------------
|
||||
Write your test in a new or existing `test_*.py` file under `$PROJECT_HOME/firefox_media_tests`. Add it to the appropriate `manifest.ini` file(s) as well. Look in `media_utils` for useful video-playback functions.
|
||||
Write your test in a new or existing `test_*.py` file under `$PROJECT_HOME/external_media_tests`. Add it to the appropriate `manifest.ini` file(s) as well. Look in `media_utils` for useful video-playback functions.
|
||||
|
||||
* [Marionette docs][marionette-docs]
|
||||
- [Marionette Command Line Options](https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options)
|
@ -11,9 +11,9 @@ from marionette.runner import BrowserMobProxyArguments
|
||||
from marionette.runtests import MarionetteHarness, cli as mn_cli
|
||||
import mozlog
|
||||
|
||||
import media_tests
|
||||
import external_media_tests
|
||||
from testcase import MediaTestCase
|
||||
from media_utils.video_puppeteer import debug_script
|
||||
from external_media_tests.media_utils.video_puppeteer import debug_script
|
||||
|
||||
|
||||
class MediaTestArgumentsBase(object):
|
||||
@ -21,7 +21,7 @@ class MediaTestArgumentsBase(object):
|
||||
args = [
|
||||
[['--urls'], {
|
||||
'help': 'ini file of urls to make available to all tests',
|
||||
'default': os.path.join(media_tests.urls, 'default.ini'),
|
||||
'default': os.path.join(external_media_tests.urls, 'default.ini'),
|
||||
}],
|
||||
]
|
||||
|
||||
@ -35,7 +35,7 @@ class MediaTestArgumentsBase(object):
|
||||
|
||||
def parse_args_handler(self, args):
|
||||
if not args.tests:
|
||||
args.tests = [media_tests.manifest]
|
||||
args.tests = [external_media_tests.manifest]
|
||||
|
||||
|
||||
@staticmethod
|
||||
@ -55,7 +55,7 @@ class MediaTestRunner(BaseMarionetteTestRunner):
|
||||
def __init__(self, **kwargs):
|
||||
BaseMarionetteTestRunner.__init__(self, **kwargs)
|
||||
if not self.server_root:
|
||||
self.server_root = media_tests.resources
|
||||
self.server_root = external_media_tests.resources
|
||||
# pick up prefs from marionette_driver.geckoinstance.DesktopInstance
|
||||
self.app = 'fxdesktop'
|
||||
self.test_handlers = [MediaTestCase]
|
||||
@ -86,17 +86,6 @@ class MediaTestRunner(BaseMarionetteTestRunner):
|
||||
|
||||
|
||||
class FirefoxMediaHarness(MarionetteHarness):
|
||||
def __init__(self,
|
||||
runner_class=MediaTestRunner,
|
||||
parser_class=MediaTestArguments):
|
||||
# workaround until next marionette-client release - Bug 1227918
|
||||
try:
|
||||
MarionetteHarness.__init__(self, runner_class, parser_class)
|
||||
except Exception:
|
||||
logger = mozlog.commandline.setup_logging('Media-test harness', {})
|
||||
logger.error('Failure setting up harness', exc_info=True)
|
||||
raise
|
||||
|
||||
def parse_args(self, *args, **kwargs):
|
||||
return MarionetteHarness.parse_args(self, {'mach': sys.stdout})
|
||||
|
@ -10,8 +10,8 @@ from marionette_driver.errors import TimeoutException
|
||||
from marionette.marionette_test import SkipTest
|
||||
|
||||
from firefox_puppeteer.testcases import FirefoxTestCase
|
||||
from media_tests.utils import (timestamp_now, verbose_until)
|
||||
from media_utils.video_puppeteer import (playback_done, playback_started,
|
||||
from external_media_tests.utils import (timestamp_now, verbose_until)
|
||||
from external_media_tests.media_utils.video_puppeteer import (playback_done, playback_started,
|
||||
VideoException, VideoPuppeteer as VP)
|
||||
|
||||
|
@ -6,7 +6,7 @@ from time import clock, sleep
|
||||
|
||||
from marionette_driver import By, expected, Wait
|
||||
|
||||
from media_tests.utils import verbose_until
|
||||
from external_media_tests.utils import verbose_until
|
||||
|
||||
|
||||
# Adapted from
|
@ -9,7 +9,7 @@ from json import loads
|
||||
from marionette_driver import By, expected, Wait
|
||||
from marionette_driver.errors import TimeoutException, NoSuchElementException
|
||||
from video_puppeteer import VideoPuppeteer, VideoException
|
||||
from media_tests.utils import verbose_until
|
||||
from external_media_tests.utils import verbose_until
|
||||
|
||||
|
||||
class YouTubePuppeteer(VideoPuppeteer):
|
@ -4,7 +4,7 @@
|
||||
|
||||
import re
|
||||
|
||||
from harness.testcase import MediaTestCase, VideoPlaybackTestsMixin
|
||||
from external_media_harness.testcase import MediaTestCase, VideoPlaybackTestsMixin
|
||||
|
||||
|
||||
class TestEMEPlayback(MediaTestCase, VideoPlaybackTestsMixin):
|
@ -3,8 +3,8 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
|
||||
from harness.testcase import MediaTestCase
|
||||
from media_utils.video_puppeteer import VideoPuppeteer
|
||||
from external_media_harness.testcase import MediaTestCase
|
||||
from external_media_tests.media_utils.video_puppeteer import VideoPuppeteer
|
||||
|
||||
|
||||
class TestFullPlayback(MediaTestCase):
|
@ -4,7 +4,7 @@
|
||||
|
||||
from marionette import BrowserMobProxyTestCaseMixin
|
||||
|
||||
from harness.testcase import NetworkBandwidthTestCase
|
||||
from external_media_harness.testcase import NetworkBandwidthTestCase
|
||||
|
||||
|
||||
class TestPlaybackLimitingBandwidth(NetworkBandwidthTestCase,
|
@ -4,7 +4,7 @@
|
||||
|
||||
from marionette import BrowserMobProxyTestCaseMixin
|
||||
|
||||
from harness.testcase import NetworkBandwidthTestCase
|
||||
from external_media_harness.testcase import NetworkBandwidthTestCase
|
||||
|
||||
|
||||
class TestUltraLowBandwidth(NetworkBandwidthTestCase,
|
@ -2,7 +2,7 @@
|
||||
# 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/.
|
||||
|
||||
from harness.testcase import (
|
||||
from external_media_harness.testcase import (
|
||||
MediaTestCase,
|
||||
VideoPlaybackTestsMixin
|
||||
)
|
@ -5,10 +5,10 @@
|
||||
from marionette_driver import Wait
|
||||
from marionette_driver.errors import TimeoutException
|
||||
|
||||
from media_tests.utils import verbose_until
|
||||
from harness.testcase import MediaTestCase
|
||||
from media_utils.video_puppeteer import VideoException
|
||||
from media_utils.youtube_puppeteer import (YouTubePuppeteer, playback_done,
|
||||
from external_media_tests.utils import verbose_until
|
||||
from external_media_harness.testcase import MediaTestCase
|
||||
from external_media_tests.media_utils.video_puppeteer import VideoException
|
||||
from external_media_tests.media_utils.youtube_puppeteer import (YouTubePuppeteer, playback_done,
|
||||
wait_for_almost_done)
|
||||
|
||||
|
@ -2,11 +2,11 @@
|
||||
# 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/.
|
||||
|
||||
from harness.testcase import MediaTestCase
|
||||
from external_media_harness.testcase import MediaTestCase
|
||||
from marionette_driver import Wait
|
||||
|
||||
from media_tests.utils import verbose_until
|
||||
from media_utils.youtube_puppeteer import YouTubePuppeteer
|
||||
from external_media_tests.utils import verbose_until
|
||||
from external_media_tests.media_utils.youtube_puppeteer import YouTubePuppeteer
|
||||
|
||||
|
||||
class TestMediaSourcePrefs(MediaTestCase):
|
@ -1,4 +1,4 @@
|
||||
from harness.testcase import MediaTestCase
|
||||
from external_media_harness.testcase import MediaTestCase
|
||||
|
||||
|
||||
class TestSomethingElse(MediaTestCase):
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user