зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to fx-team
This commit is contained in:
Коммит
9dcf234c97
|
@ -132,6 +132,9 @@ endif
|
|||
$(addprefix install-,$(filter dist/%,$(install_manifests))): install-dist/%: $(install_manifest_depends)
|
||||
$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )$(DIST)/$* _build_manifests/install/dist_$*)
|
||||
|
||||
# Dummy wrapper rule to allow the faster backend to piggy back
|
||||
install-dist_%: install-dist/% ;
|
||||
|
||||
install-_tests: $(install_manifest_depends)
|
||||
$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )_tests _build_manifests/install/tests)
|
||||
|
||||
|
|
|
@ -1613,34 +1613,21 @@ DocAccessible::AddDependentIDsFor(Accessible* aRelProvider, nsIAtom* aRelAttr)
|
|||
mInvalidationList.AppendElement(dependentContent);
|
||||
}
|
||||
|
||||
// Update ARIA owns cache.
|
||||
if (relAttr == nsGkAtoms::aria_owns) {
|
||||
// Dependent content cannot point to other aria-owns content or
|
||||
// their parents. Ignore it if so.
|
||||
// XXX: note, this alg may make invalid the scenario when X owns Y
|
||||
// and Y owns Z, we should have something smarter to handle that.
|
||||
bool isvalid = true;
|
||||
for (auto it = mARIAOwnsHash.Iter(); !it.Done(); it.Next()) {
|
||||
Accessible* owner = it.Key();
|
||||
nsIContent* parentEl = owner->GetContent();
|
||||
while (parentEl && parentEl != dependentContent) {
|
||||
parentEl = parentEl->GetParent();
|
||||
}
|
||||
if (parentEl) {
|
||||
isvalid = false;
|
||||
break;
|
||||
}
|
||||
// ARIA owns cannot refer to itself or a parent. Ignore
|
||||
// the element if so.
|
||||
nsIContent* parentEl = relProviderEl;
|
||||
while (parentEl && parentEl != dependentContent) {
|
||||
parentEl = parentEl->GetParent();
|
||||
}
|
||||
if (isvalid) {
|
||||
// ARIA owns also cannot refer to itself or a parent.
|
||||
nsIContent* parentEl = relProviderEl;
|
||||
while (parentEl && parentEl != dependentContent) {
|
||||
parentEl = parentEl->GetParent();
|
||||
}
|
||||
if (parentEl) {
|
||||
isvalid = false;
|
||||
}
|
||||
|
||||
if (isvalid) {
|
||||
if (!parentEl) {
|
||||
// ARIA owns element cannot refer to an element in parents chain
|
||||
// of other ARIA owns element (including that ARIA owns element)
|
||||
// if it's inside of a dependent element subtree of that
|
||||
// ARIA owns element. Applied recursively.
|
||||
if (!IsInARIAOwnsLoop(relProviderEl, dependentContent)) {
|
||||
nsTArray<nsIContent*>* list =
|
||||
mARIAOwnsHash.LookupOrAdd(aRelProvider);
|
||||
list->AppendElement(dependentContent);
|
||||
|
@ -1759,6 +1746,45 @@ DocAccessible::RemoveDependentIDsFor(Accessible* aRelProvider,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessible::IsInARIAOwnsLoop(nsIContent* aOwnerEl, nsIContent* aDependentEl)
|
||||
{
|
||||
// ARIA owns element cannot refer to an element in parents chain of other ARIA
|
||||
// owns element (including that ARIA owns element) if it's inside of
|
||||
// a dependent element subtree of that ARIA owns element.
|
||||
for (auto it = mARIAOwnsHash.Iter(); !it.Done(); it.Next()) {
|
||||
Accessible* otherOwner = it.Key();
|
||||
nsIContent* parentEl = otherOwner->GetContent();
|
||||
while (parentEl && parentEl != aDependentEl) {
|
||||
parentEl = parentEl->GetParent();
|
||||
}
|
||||
|
||||
// The dependent element of this ARIA owns element contains some other ARIA
|
||||
// owns element, make sure this ARIA owns element is not in a subtree of
|
||||
// a dependent element of that other ARIA owns element. If not then
|
||||
// continue a check recursively.
|
||||
if (parentEl) {
|
||||
nsTArray<nsIContent*>* childEls = it.UserData();
|
||||
for (uint32_t idx = 0; idx < childEls->Length(); idx++) {
|
||||
nsIContent* childEl = childEls->ElementAt(idx);
|
||||
nsIContent* parentEl = aOwnerEl;
|
||||
while (parentEl && parentEl != childEl) {
|
||||
parentEl = parentEl->GetParent();
|
||||
}
|
||||
if (parentEl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsInARIAOwnsLoop(aOwnerEl, childEl)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessible::UpdateAccessibleOnAttrChange(dom::Element* aElement,
|
||||
nsIAtom* aAttribute)
|
||||
|
|
|
@ -436,6 +436,12 @@ protected:
|
|||
void RemoveDependentIDsFor(Accessible* aRelProvider,
|
||||
nsIAtom* aRelAttr = nullptr);
|
||||
|
||||
/**
|
||||
* Return true if given ARIA owner element and its referred content make
|
||||
* the loop closed.
|
||||
*/
|
||||
bool IsInARIAOwnsLoop(nsIContent* aOwnerEl, nsIContent* aDependentEl);
|
||||
|
||||
/**
|
||||
* Update or recreate an accessible depending on a changed attribute.
|
||||
*
|
||||
|
|
|
@ -744,6 +744,9 @@ var Input = {
|
|||
case 'tripletap3':
|
||||
Utils.dispatchChromeEvent('accessibility-control', 'toggle-shade');
|
||||
break;
|
||||
case 'tap2':
|
||||
Utils.dispatchChromeEvent('accessibility-control', 'toggle-pause');
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -213,8 +213,7 @@ this.GestureTracker = { // jshint ignore:line
|
|||
*/
|
||||
handle: function GestureTracker_handle(aDetail, aTimeStamp) {
|
||||
Logger.gesture(() => {
|
||||
return ['Pointer event', aDetail.type, 'at:', aTimeStamp,
|
||||
JSON.stringify(aDetail.points)];
|
||||
return ['Pointer event', Utils.dpi, 'at:', aTimeStamp, JSON.stringify(aDetail)];
|
||||
});
|
||||
this[this.current ? '_update' : '_init'](aDetail, aTimeStamp);
|
||||
},
|
||||
|
@ -403,7 +402,12 @@ Gesture.prototype = {
|
|||
let identifier = point.identifier;
|
||||
let gesturePoint = this.points[identifier];
|
||||
if (gesturePoint) {
|
||||
gesturePoint.update(point);
|
||||
if (aType === 'pointerdown' && aCanCreate) {
|
||||
// scratch the previous pointer with that id.
|
||||
this.points[identifier] = new Point(point);
|
||||
} else {
|
||||
gesturePoint.update(point);
|
||||
}
|
||||
if (aNeedComplete) {
|
||||
// Since the gesture is completing and at least one of the gesture
|
||||
// points is updated, set the return value to true.
|
||||
|
|
|
@ -454,11 +454,11 @@ function testAccessibleTree(aAccOrElmOrID, aAccTree, aFlags)
|
|||
|
||||
if (accTree.children.length != childCount) {
|
||||
for (var i = 0; i < Math.max(accTree.children.length, childCount); i++) {
|
||||
var accChild;
|
||||
var accChild = null, testChild = null;
|
||||
try {
|
||||
testChild = accTree.children[i];
|
||||
accChild = children.queryElementAt(i, nsIAccessible);
|
||||
|
||||
testChild = accTree.children[i];
|
||||
if (!testChild) {
|
||||
ok(false, prettyName(acc) + " has an extra child at index " + i +
|
||||
" : " + prettyName(accChild));
|
||||
|
@ -481,10 +481,10 @@ function testAccessibleTree(aAccOrElmOrID, aAccTree, aFlags)
|
|||
}
|
||||
info("Matching " + prettyName(accTree) + " and " + prettyName(acc) +
|
||||
" child at index " + i + " : " + prettyName(accChild));
|
||||
|
||||
} catch (e) {
|
||||
ok(false, prettyName(accTree) + " has an extra child at index " + i +
|
||||
ok(false, prettyName(accTree) + " is expected to have a child at index " + i +
|
||||
" : " + prettyName(testChild) + ", " + e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -109,9 +109,10 @@ var originalConsecutiveGestureDelay =
|
|||
* Attach a listener for the mozAccessFuGesture event that tests its
|
||||
* type.
|
||||
* @param {Array} aExpectedGestures A stack of expected event types.
|
||||
* @param {String} aTitle Title of this sequence, if any.
|
||||
* Note: the listener is removed once the stack reaches 0.
|
||||
*/
|
||||
function testMozAccessFuGesture(aExpectedGestures) {
|
||||
function testMozAccessFuGesture(aExpectedGestures, aTitle) {
|
||||
var types = aExpectedGestures;
|
||||
function handleGesture(aEvent) {
|
||||
if (aEvent.detail.type !== types[0].type) {
|
||||
|
@ -120,8 +121,10 @@ function testMozAccessFuGesture(aExpectedGestures) {
|
|||
return;
|
||||
}
|
||||
is(!!aEvent.detail.edge, !!types[0].edge);
|
||||
is(aEvent.detail.touches.length, types[0].fingers || 1,
|
||||
'failed to count fingers: ' + types[0].type);
|
||||
ok(true, 'Received correct mozAccessFuGesture: ' +
|
||||
JSON.stringify(types.shift()) + '.');
|
||||
JSON.stringify(types.shift()) + '. (' + aTitle + ')');
|
||||
if (types.length === 0) {
|
||||
win.removeEventListener('mozAccessFuGesture', handleGesture);
|
||||
if (AccessFuTest.sequenceCleanup) {
|
||||
|
@ -168,7 +171,7 @@ function resetTimers() {
|
|||
*/
|
||||
AccessFuTest.addSequence = function AccessFuTest_addSequence(aSequence) {
|
||||
AccessFuTest.addFunc(function testSequence() {
|
||||
testMozAccessFuGesture(aSequence.expectedGestures);
|
||||
testMozAccessFuGesture(aSequence.expectedGestures, aSequence.title);
|
||||
var events = aSequence.events;
|
||||
function fireEvent(aEvent) {
|
||||
var event = {
|
||||
|
|
|
@ -162,7 +162,7 @@
|
|||
{"type": "pointerup", "points": [{"x": 1.5, "y": 1, "identifier": 1},
|
||||
{"x": 1.5, "y": 1.5, "identifier": 2}]}
|
||||
],
|
||||
"expectedGestures": [{ "type": "swiperight" }]
|
||||
"expectedGestures": [{ "type": "swiperight", "fingers": 2 }]
|
||||
},
|
||||
{
|
||||
"events": [
|
||||
|
@ -173,7 +173,7 @@
|
|||
{"type": "pointerup", "points": [{"x": 1.5, "y": 1, "identifier": 1}]},
|
||||
{"type": "pointerup", "points": [{"x": 1.5, "y": 1.5, "identifier": 2}]}
|
||||
],
|
||||
"expectedGestures": [{ "type": "swiperight" }]
|
||||
"expectedGestures": [{ "type": "swiperight", "fingers": 2 }]
|
||||
},
|
||||
{
|
||||
"events": [
|
||||
|
@ -187,7 +187,7 @@
|
|||
{"x": 1.5, "y": 1.5, "identifier": 2},
|
||||
{"x": 1.5, "y": 2, "identifier": 3}]}
|
||||
],
|
||||
"expectedGestures": [{ "type": "swiperight" }]
|
||||
"expectedGestures": [{ "type": "swiperight", "fingers": 3 }]
|
||||
},
|
||||
{
|
||||
"events": [
|
||||
|
@ -263,6 +263,96 @@
|
|||
{"type": "pointerup", "points": [{"x": 1.5, "y": 1, "identifier": 1},
|
||||
{"x": 1.5, "y": 1.5, "identifier": 2}]}
|
||||
],
|
||||
"expectedGestures": [{ "type": "swiperight", "edge": true }]
|
||||
"expectedGestures": [{ "type": "swiperight", "edge": true, "fingers": 2 }]
|
||||
},
|
||||
{
|
||||
"title": "Bug 1182311 - 3 finger triple tap is not reliable 1/2",
|
||||
"events": [
|
||||
{"points": [
|
||||
{"y": 1.88467, "x": 0.89311, "identifier": 0},
|
||||
{"y": 2.78481, "x": 0.56259, "identifier": 1},
|
||||
{"y": 1.35021, "x": 1.37834, "identifier": 2}], "type": "pointerdown"},
|
||||
{"points": [
|
||||
{"y": 1.88467, "x": 0.89311, "identifier": 0},
|
||||
{"y": 2.78481, "x": 0.56259, "identifier": 1},
|
||||
{"y": 1.35021, "x": 1.37834, "identifier": 2}], "type": "pointerup"},
|
||||
{"points": [
|
||||
{"y": 1.76512, "x": 0.98453, "identifier": 0},
|
||||
{"y": 1.1744, "x": 1.4346, "identifier": 1},
|
||||
{"y": 2.5879, "x": 0.61181, "identifier": 2}], "type": "pointerdown"},
|
||||
{"points": [
|
||||
{"y": 1.76512, "x": 0.98453, "identifier": 0},
|
||||
{"y": 1.1744, "x": 1.4346, "identifier": 1},
|
||||
{"y": 2.5879, "x": 0.61181, "identifier": 2}], "type": "pointerup"},
|
||||
{"points": [
|
||||
{"y": 1.30098, "x": 1.52602, "identifier": 0},
|
||||
{"y": 1.94093, "x": 1.02672, "identifier": 1},
|
||||
{"y": 2.67229, "x": 0.75246, "identifier": 2}], "type": "pointerdown"},
|
||||
{"points": [
|
||||
{"y": 1.30098, "x": 1.52602, "identifier": 0},
|
||||
{"y": 1.94093, "x": 1.02672, "identifier": 1},
|
||||
{"y": 2.67229, "x": 0.75246, "identifier": 2}], "type": "pointerup",
|
||||
"removeConsecutiveGestureDelay": false}],
|
||||
"expectedGestures": [{ "type": "tripletap", "fingers": 3 }]
|
||||
},
|
||||
{
|
||||
"title": "Bug 1182311 - 3 finger triple tap is not reliable 2/2",
|
||||
"events": [
|
||||
{"type": "pointerdown",
|
||||
"points": [{"identifier": 0, "x": 2.21875, "y": 1.510417}]},
|
||||
{"type": "pointerdown",
|
||||
"points": [{"identifier": 1, "x": 1.479167, "y": 2.53125}]},
|
||||
{"type": "pointerdown",
|
||||
"points": [{"identifier": 2, "x": 1.072917, "y": 3.739583}]},
|
||||
{"type": "pointermove",
|
||||
"points": [{"identifier": 1, "x": 1.46875, "y": 2.53125}]},
|
||||
{"type": "pointermove",
|
||||
"points": [{"identifier": 1, "x": 1.447917, "y": 2.46875}]},
|
||||
{"type": "pointerup",
|
||||
"points": [{"identifier": 0, "x": 2.21875, "y": 1.510417}]},
|
||||
{"type": "pointerup",
|
||||
"points": [{"identifier": 1, "x": 1.447917, "y": 2.489583}]},
|
||||
{"type": "pointerup",
|
||||
"points": [{"identifier": 2, "x": 1.072917, "y": 3.739583}]},
|
||||
{"type": "pointerdown",
|
||||
"points": [{"identifier": 0, "x": 2.114583, "y": 1.572917}]},
|
||||
{"type": "pointerdown",
|
||||
"points": [{"identifier": 1, "x": 1.364583, "y": 2.614583}]},
|
||||
{"type": "pointerdown",
|
||||
"points": [{"identifier": 2, "x": 0.927083, "y": 3.864583}]},
|
||||
{"type": "pointermove",
|
||||
"points": [{"identifier": 1, "x": 1.364583, "y": 2.614583}]},
|
||||
{"type": "pointermove",
|
||||
"points": [{"identifier": 0, "x": 2.114583, "y": 1.572917}]},
|
||||
{"type": "pointerup",
|
||||
"points": [{"identifier": 1, "x": 1.364583, "y": 2.614583}]},
|
||||
{"type": "pointerup",
|
||||
"points": [{"identifier": 2, "x": 0.927083, "y": 3.864583}]},
|
||||
{"type": "pointerup",
|
||||
"points": [{"identifier": 0, "x": 2.114583, "y": 1.572917}]},
|
||||
{"type": "pointerdown",
|
||||
"points": [{"identifier": 0, "x": 1.4375, "y": 2.59375}]},
|
||||
{"type": "pointerdown",
|
||||
"points": [{"identifier": 1, "x": 1.083333, "y": 3.71875}]},
|
||||
{"type": "pointerdown",
|
||||
"points": [{"identifier": 2, "x": 2.15625, "y": 1.489583}]},
|
||||
{"type": "pointermove",
|
||||
"points": [{"identifier": 0, "x": 1.4375, "y": 2.59375},
|
||||
{"identifier": 2, "x": 2.15625, "y": 1.489583}]},
|
||||
{"type": "pointermove",
|
||||
"points": [{"identifier": 0, "x": 1.4375, "y": 2.59375},
|
||||
{"identifier": 2, "x": 2.15625, "y": 1.489583}]},
|
||||
{"type": "pointerup",
|
||||
"points": [{"identifier": 1, "x": 1.083333, "y": 3.71875}]},
|
||||
{"type": "pointermove",
|
||||
"points": [{"identifier": 0, "x": 1.427083, "y": 2.59375}]},
|
||||
{"type": "pointerup",
|
||||
"points": [{"identifier": 0, "x": 1.427083, "y": 2.59375}]},
|
||||
{"type": "pointerup",
|
||||
"points": [{"identifier": 2, "x": 2.15625, "y": 1.489583}],
|
||||
"removeConsecutiveGestureDelay": false}
|
||||
],
|
||||
"expectedGestures": [{ "type": "tripletap", "fingers": 3 }]
|
||||
}
|
||||
|
||||
]
|
||||
|
|
|
@ -10,6 +10,7 @@ skip-if = true # Bug 561508
|
|||
[test_aria_imgmap.html]
|
||||
[test_aria_list.html]
|
||||
[test_aria_menu.html]
|
||||
[test_aria_owns.html]
|
||||
[test_aria_presentation.html]
|
||||
[test_aria_table.html]
|
||||
[test_brokencontext.html]
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>@aria-owns attribute testing</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Tests
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//enableLogging("tree"); // debug stuff
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [ // t1_1
|
||||
{ SECTION: [ // t1_2
|
||||
// no kids, no loop
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree("t1_1", tree);
|
||||
|
||||
tree =
|
||||
{ SECTION: [ // t2_1
|
||||
{ SECTION: [ // t2_2
|
||||
{ SECTION: [ // t2_3
|
||||
// no kids, no loop
|
||||
] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree("t2_1", tree);
|
||||
|
||||
tree =
|
||||
{ SECTION: [ // t3_3
|
||||
{ SECTION: [ // t3_1
|
||||
{ SECTION: [ // t3_2
|
||||
{ SECTION: [ // DOM child of t3_2
|
||||
// no kids, no loop
|
||||
] }
|
||||
] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree("t3_3", tree);
|
||||
|
||||
tree =
|
||||
{ SECTION: [ // t4_1
|
||||
{ SECTION: [ // DOM child of t4_1
|
||||
// no kids, no loop
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree("t4_1", tree);
|
||||
|
||||
tree =
|
||||
{ SECTION: [ // t5_1
|
||||
{ SECTION: [ // DOM child of t5_1
|
||||
{ SECTION: [ // t5_2
|
||||
{ SECTION: [ // DOM child of t5_2
|
||||
{ SECTION: [ // t5_3
|
||||
{ SECTION: [ // DOM child of t5_3
|
||||
// no kids, no loop
|
||||
]}
|
||||
]}
|
||||
]}
|
||||
] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree("t5_1", tree);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<div id="t1_1" aria-owns="t1_2"></div>
|
||||
<div id="t1_2" aria-owns="t1_1"></div>
|
||||
|
||||
<div id="t2_2" aria-owns="t2_3"></div>
|
||||
<div id="t2_1" aria-owns="t2_2"></div>
|
||||
<div id="t2_3" aria-owns="t2_1"></div>
|
||||
|
||||
<div id="t3_1" aria-owns="t3_2"></div>
|
||||
<div id="t3_2">
|
||||
<div aria-owns="t3_3"></div>
|
||||
</div>
|
||||
<div id="t3_3" aria-owns="t3_1"></div>
|
||||
|
||||
<div id="t4_1"><div aria-owns="t4_1"></div></div>
|
||||
|
||||
<div id="t5_1"><div aria-owns="t5_2"></div>
|
||||
<div id="t5_2"><div aria-owns="t5_3"></div></div>
|
||||
<div id="t5_3"><div aria-owns="t5_1"></div></div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -172,25 +172,13 @@
|
|||
// Test
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
gA11yEventDumpToConsole = true;
|
||||
enableLogging("tree"); // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
//enableLogging("tree"); // debug stuff
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
// nested and recursive aria-owns
|
||||
var tree =
|
||||
{ SECTION: [ // container
|
||||
{ SECTION: [ // child
|
||||
{ SECTION: [ // mid div
|
||||
{ SECTION: [] } // grandchild
|
||||
] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree("container", tree);
|
||||
|
||||
// dynamic tests
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new removeARIAOwns());
|
||||
|
@ -214,12 +202,6 @@
|
|||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<div id="container" aria-owns="child" aria-label="container"></div>
|
||||
<div id="child" aria-label="child">
|
||||
<div aria-owns="grandchild" aria-label="midchild"></div>
|
||||
</div>
|
||||
<div id="grandchild" aria-owns="container" aria-label="grandchild"></div>
|
||||
|
||||
<div id="container2" aria-owns="t2_checkbox t2_button">
|
||||
<div role="button" id="t2_button"></div>
|
||||
<div role="checkbox" id="t2_checkbox">
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1bc0b19527777ffee494962b48db4be857b07d64"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="14a64f1ebd353bccc3f1c0399e1a01a03327749e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1bc0b19527777ffee494962b48db4be857b07d64"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="14a64f1ebd353bccc3f1c0399e1a01a03327749e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1bc0b19527777ffee494962b48db4be857b07d64"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="14a64f1ebd353bccc3f1c0399e1a01a03327749e"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1bc0b19527777ffee494962b48db4be857b07d64"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="14a64f1ebd353bccc3f1c0399e1a01a03327749e"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1bc0b19527777ffee494962b48db4be857b07d64"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="14a64f1ebd353bccc3f1c0399e1a01a03327749e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1bc0b19527777ffee494962b48db4be857b07d64"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="14a64f1ebd353bccc3f1c0399e1a01a03327749e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1bc0b19527777ffee494962b48db4be857b07d64"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="14a64f1ebd353bccc3f1c0399e1a01a03327749e"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1bc0b19527777ffee494962b48db4be857b07d64"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="14a64f1ebd353bccc3f1c0399e1a01a03327749e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "1bc0b19527777ffee494962b48db4be857b07d64",
|
||||
"git_revision": "14a64f1ebd353bccc3f1c0399e1a01a03327749e",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "d8e220a9a7bc3083b1cd9bc94f5a524e5b114384",
|
||||
"revision": "72d170d61e82726b0fd2a398d21796b11ab2ad66",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1bc0b19527777ffee494962b48db4be857b07d64"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="14a64f1ebd353bccc3f1c0399e1a01a03327749e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1bc0b19527777ffee494962b48db4be857b07d64"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="14a64f1ebd353bccc3f1c0399e1a01a03327749e"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1bc0b19527777ffee494962b48db4be857b07d64"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="14a64f1ebd353bccc3f1c0399e1a01a03327749e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
|
|
|
@ -1885,7 +1885,7 @@ pref("browser.tabs.remote.autostart.2", true);
|
|||
#endif
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
#ifndef MOZ_MULET
|
||||
pref("layers.async-pan-zoom.enabled", true);
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -472,15 +472,24 @@ var gTests = [
|
|||
})
|
||||
},
|
||||
{
|
||||
desc: "Sync button should open about:accounts page with `abouthome` entrypoint",
|
||||
desc: "Sync button should open about:preferences#sync",
|
||||
setup: function () {},
|
||||
run: Task.async(function* () {
|
||||
let syncButton = gBrowser.selectedBrowser.contentDocument.getElementById("sync");
|
||||
let oldOpenPrefs = window.openPreferences;
|
||||
let openPrefsPromise = new Promise(resolve => {
|
||||
window.openPreferences = function (pane, params) {
|
||||
resolve({ pane: pane, params: params });
|
||||
};
|
||||
});
|
||||
|
||||
yield EventUtils.synthesizeMouseAtCenter(syncButton, {}, gBrowser.contentWindow);
|
||||
|
||||
yield promiseTabLoadEvent(gBrowser.selectedTab, null, "load");
|
||||
is(gBrowser.currentURI.spec, "about:accounts?entrypoint=abouthome",
|
||||
"Entry point should be `abouthome`.");
|
||||
let result = yield openPrefsPromise;
|
||||
window.openPreferences = oldOpenPrefs;
|
||||
|
||||
is(result.pane, "paneSync", "openPreferences should be called with paneSync");
|
||||
is(result.params.urlParams.entrypoint, "abouthome", "openPreferences should be called with abouthome entrypoint");
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ add_task(function* ()
|
|||
yield* expectFocusOnF6(false, "html1", "html1",
|
||||
true, "basic focus content page with button focused");
|
||||
|
||||
return ContentTask.spawn(gBrowser.selectedBrowser, { }, function* () {
|
||||
yield ContentTask.spawn(gBrowser.selectedBrowser, { }, function* () {
|
||||
return content.document.getElementById("button1").focus();
|
||||
});
|
||||
|
||||
|
|
|
@ -30,5 +30,10 @@ ac_add_options --enable-warnings-as-errors
|
|||
|
||||
. $topsrcdir/build/win64/mozconfig.vs2013
|
||||
|
||||
# Enable Adobe Primetime CDM on 64-bit Windows in Mozilla builds.
|
||||
# Enabled here on the assumption that downstream vendors will not be using
|
||||
# these build configs.
|
||||
ac_add_options --enable-eme=adobe
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
|
|
@ -143,21 +143,7 @@ var AboutHome = {
|
|||
break;
|
||||
|
||||
case "AboutHome:Sync":
|
||||
let weave = Cc["@mozilla.org/weave/service;1"]
|
||||
.getService(Ci.nsISupports)
|
||||
.wrappedJSObject;
|
||||
|
||||
if (weave.fxAccountsEnabled) {
|
||||
fxAccounts.getSignedInUser().then(userData => {
|
||||
if (userData) {
|
||||
window.openPreferences("paneSync");
|
||||
} else {
|
||||
window.loadURI("about:accounts?entrypoint=abouthome");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
window.openPreferences("paneSync");
|
||||
}
|
||||
window.openPreferences("paneSync", { urlParams: { entrypoint: "abouthome" } });
|
||||
break;
|
||||
|
||||
case "AboutHome:Settings":
|
||||
|
|
|
@ -90,8 +90,8 @@
|
|||
.tab-icon-overlay {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: -12px;
|
||||
-moz-margin-start: -16px;
|
||||
margin-top: -8px;
|
||||
margin-inline-start: -15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@
|
|||
|
||||
.tab-icon-overlay[soundplaying],
|
||||
.tab-icon-overlay[muted]:not([crashed]) {
|
||||
border-radius: 8px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.tab-icon-overlay[soundplaying]:hover,
|
||||
|
|
|
@ -28,7 +28,7 @@ define([AC_SUBST_SET],
|
|||
[ifdef([AC_SUBST_SET_$1], ,
|
||||
[define([AC_SUBST_SET_$1], )dnl
|
||||
AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
|
||||
(''' $1 ''', set(r''' [$]$1 '''.split()))
|
||||
(''' $1 ''', unique_list(r''' [$]$1 '''.split()))
|
||||
AC_DIVERT_POP()dnl
|
||||
])])])])
|
||||
|
||||
|
@ -129,6 +129,13 @@ topsrcdir = os.path.normpath(topsrcdir)
|
|||
|
||||
topobjdir = os.path.abspath(os.path.dirname(<<<__file__>>>))
|
||||
|
||||
def unique_list(l):
|
||||
result = []
|
||||
for i in l:
|
||||
if l not in result:
|
||||
result.append(i)
|
||||
return result
|
||||
|
||||
dnl All defines and substs are stored with an additional space at the beginning
|
||||
dnl and at the end of the string, to avoid any problem with values starting or
|
||||
dnl ending with quotes.
|
||||
|
@ -232,5 +239,5 @@ MOZ_ARG_ENABLE_STRING(build-backend,
|
|||
Enable additional build backends],
|
||||
[ BUILD_BACKENDS="RecursiveMake `echo $enableval | sed 's/,/ /g'`"])
|
||||
|
||||
AC_SUBST_LIST([BUILD_BACKENDS])
|
||||
AC_SUBST_SET([BUILD_BACKENDS])
|
||||
])
|
||||
|
|
|
@ -30,14 +30,6 @@ typedef ASTConsumer *ASTConsumerPtr;
|
|||
|
||||
namespace {
|
||||
|
||||
QualType GetCallReturnType(const CallExpr *expr) {
|
||||
#if CLANG_VERSION_FULL >= 307
|
||||
return expr->getCallReturnType(expr->getCalleeDecl()->getASTContext());
|
||||
#else
|
||||
return expr->getCallReturnType();
|
||||
#endif
|
||||
}
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
class DiagnosticsMatcher {
|
||||
public:
|
||||
|
@ -503,13 +495,6 @@ const FieldDecl *getClassRefCntMember(const CXXRecordDecl *D) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
const FieldDecl *getClassRefCntMember(QualType T) {
|
||||
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
|
||||
T = arrTy->getElementType();
|
||||
CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
|
||||
return clazz ? getClassRefCntMember(clazz) : 0;
|
||||
}
|
||||
|
||||
const FieldDecl *getBaseRefCntMember(QualType T);
|
||||
|
||||
const FieldDecl *getBaseRefCntMember(const CXXRecordDecl *D) {
|
||||
|
@ -1317,8 +1302,6 @@ void DiagnosticsMatcher::NonMemMovableChecker::run(
|
|||
const ClassTemplateSpecializationDecl *specialization =
|
||||
Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("specialization");
|
||||
SourceLocation requestLoc = specialization->getPointOfInstantiation();
|
||||
const CXXRecordDecl *templ =
|
||||
specialization->getSpecializedTemplate()->getTemplatedDecl();
|
||||
|
||||
// Report an error for every template argument which is non-memmovable
|
||||
const TemplateArgumentList &args =
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
#! /usr/bin/env 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/.
|
||||
|
||||
'''Prints the given arguments in sorted order with duplicates removed.'''
|
||||
|
||||
import sys
|
||||
|
||||
print(' '.join(sorted(set(sys.argv[1:]))))
|
|
@ -53,6 +53,9 @@ default: $(TOPOBJDIR)/dist/bin/greprefs.js
|
|||
default: $(TOPOBJDIR)/dist/bin/platform.ini
|
||||
default: $(TOPOBJDIR)/dist/bin/webapprt/webapprt.ini
|
||||
|
||||
# Targets from the recursive make backend to be built for a default build
|
||||
default: $(TOPOBJDIR)/config/makefiles/xpidl/xpidl
|
||||
|
||||
.PHONY: FORCE
|
||||
|
||||
# Extra define to trigger some workarounds. We should strive to limit the
|
||||
|
@ -189,15 +192,6 @@ jar-browser-themes-%-jar.mn: \
|
|||
$(TOPOBJDIR)/browser/themes/%/tab-selected-end.svg \
|
||||
$(TOPOBJDIR)/browser/themes/%/tab-selected-start.svg
|
||||
|
||||
# These files are manually generated from
|
||||
# toolkit/components/urlformatter/Makefile.in and are force-included so that
|
||||
# the corresponding defines don't end up in the command lines.
|
||||
KEYS = mozilla_api_key google_api_key google_oauth_api_key bing_api_key
|
||||
$(TOPOBJDIR)/dist/bin/components/nsURLFormatter.js: \
|
||||
$(addprefix $(TOPOBJDIR)/toolkit/components/urlformatter/, $(KEYS))
|
||||
$(TOPOBJDIR)/dist/bin/components/nsURLFormatter.js: defines += \
|
||||
$(addprefix -I $(TOPOBJDIR)/toolkit/components/urlformatter/,$(KEYS))
|
||||
|
||||
# Extra dependencies and/or definitions for preprocessed files.
|
||||
$(TOPOBJDIR)/dist/bin/application.ini: $(TOPOBJDIR)/config/buildid
|
||||
$(TOPOBJDIR)/dist/bin/application.ini: defines += \
|
||||
|
@ -207,3 +201,7 @@ $(TOPOBJDIR)/dist/bin/application.ini: defines += \
|
|||
$(TOPOBJDIR)/dist/bin/greprefs.js: $(TOPOBJDIR)/modules/libpref/greprefs.js
|
||||
$(TOPOBJDIR)/dist/bin/platform.ini: $(TOPOBJDIR)/toolkit/xre/platform.ini
|
||||
$(TOPOBJDIR)/dist/bin/webapprt/webapprt.ini: $(TOPOBJDIR)/webapprt/webapprt.ini
|
||||
|
||||
# The xpidl target in config/makefiles/xpidl requires the install manifest for
|
||||
# dist/idl to have been processed.
|
||||
$(TOPOBJDIR)/config/makefiles/xpidl/xpidl: $(TOPOBJDIR)/install-dist_idl
|
||||
|
|
14
configure.in
14
configure.in
|
@ -2242,9 +2242,6 @@ ia64*-hpux*)
|
|||
# the same thing as C4244, we disable C4267, too.
|
||||
# MSVC warning C4345 warns of newly conformant behavior as of VS2003.
|
||||
# MSVC warning C4351 warns of newly conformant behavior as of VS2005.
|
||||
# MSVC warning C4482 warns when an enum value is refered specifing the
|
||||
# name of the enum itself. This behavior is allowed in C++11, and the
|
||||
# warning has been removed in VS2012.
|
||||
# MSVC warning C4800 warns when a value is implicitly cast to bool,
|
||||
# because this also forces narrowing to a single byte, which can be a
|
||||
# perf hit. But this matters so little in practice (and often we want
|
||||
|
@ -2252,7 +2249,7 @@ ia64*-hpux*)
|
|||
# MSVC warning C4819 warns some UTF-8 characters (e.g. copyright sign)
|
||||
# on non-Western system locales even if it is in a comment.
|
||||
CFLAGS="$CFLAGS -wd4244 -wd4267 -wd4819"
|
||||
CXXFLAGS="$CXXFLAGS -wd4251 -wd4244 -wd4267 -wd4345 -wd4351 -wd4482 -wd4800 -wd4819"
|
||||
CXXFLAGS="$CXXFLAGS -wd4251 -wd4244 -wd4267 -wd4345 -wd4351 -wd4800 -wd4819"
|
||||
if test -n "$CLANG_CL"; then
|
||||
# Suppress the clang-cl warning for the inline 'new' and 'delete' in mozalloc
|
||||
CXXFLAGS="$CXXFLAGS -Wno-inline-new-delete"
|
||||
|
@ -4034,6 +4031,8 @@ esac
|
|||
case "$MOZ_BUILD_APP" in
|
||||
browser)
|
||||
AC_DEFINE(MOZ_PHOENIX)
|
||||
|
||||
BUILD_BACKENDS="$BUILD_BACKENDS FasterMake"
|
||||
;;
|
||||
|
||||
xulrunner)
|
||||
|
@ -6309,9 +6308,6 @@ if test `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
|
|||
fi
|
||||
AC_SUBST(MOZ_GIO_COMPONENT)
|
||||
|
||||
dnl Remove dupes
|
||||
MOZ_EXTENSIONS=`$PYTHON ${srcdir}/build/unix/uniq.py ${MOZ_EXTENSIONS}`
|
||||
|
||||
dnl Ensure every extension exists, to avoid mostly-inscrutable error messages
|
||||
dnl when trying to build a nonexistent extension.
|
||||
for extension in $MOZ_EXTENSIONS; do
|
||||
|
@ -8382,8 +8378,6 @@ MOZ_ARG_ENABLE_STRING(necko-protocols,
|
|||
fi
|
||||
done],
|
||||
NECKO_PROTOCOLS="$NECKO_PROTOCOLS_DEFAULT")
|
||||
dnl Remove dupes
|
||||
NECKO_PROTOCOLS=`$PYTHON ${srcdir}/build/unix/uniq.py ${NECKO_PROTOCOLS}`
|
||||
AC_SUBST_SET(NECKO_PROTOCOLS)
|
||||
for p in $NECKO_PROTOCOLS; do
|
||||
AC_DEFINE_UNQUOTED(NECKO_PROTOCOL_$p)
|
||||
|
@ -8567,7 +8561,7 @@ AC_SUBST(MOZ_DEBUG_ENABLE_DEFS)
|
|||
AC_SUBST(MOZ_DEBUG_DISABLE_DEFS)
|
||||
AC_SUBST(MOZ_DEBUG_LDFLAGS)
|
||||
AC_SUBST(WARNINGS_AS_ERRORS)
|
||||
AC_SUBST(MOZ_EXTENSIONS)
|
||||
AC_SUBST_SET(MOZ_EXTENSIONS)
|
||||
AC_SUBST(MOZ_ENABLE_PROFILER_SPS)
|
||||
AC_SUBST(MOZ_JPROF)
|
||||
AC_SUBST(MOZ_INSTRUMENTS)
|
||||
|
|
|
@ -14,6 +14,12 @@
|
|||
|
||||
struct JSContext;
|
||||
|
||||
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
|
||||
// GetTickCount().
|
||||
#ifdef GetCurrentTime
|
||||
#undef GetCurrentTime
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
|
|
@ -11338,6 +11338,16 @@ LogFullScreenDenied(bool aLogFailure, const char* aMessage, nsIDocument* aDoc)
|
|||
aMessage);
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateViewportScrollbarOverrideForFullscreen(nsIDocument* aDoc)
|
||||
{
|
||||
if (nsIPresShell* presShell = aDoc->GetShell()) {
|
||||
if (nsPresContext* presContext = presShell->GetPresContext()) {
|
||||
presContext->UpdateViewportScrollbarStylesOverride();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::CleanupFullscreenState()
|
||||
{
|
||||
|
@ -11357,6 +11367,7 @@ nsDocument::CleanupFullscreenState()
|
|||
}
|
||||
mFullScreenStack.Clear();
|
||||
mFullscreenRoot = nullptr;
|
||||
UpdateViewportScrollbarOverrideForFullscreen(this);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -11370,6 +11381,7 @@ nsDocument::FullScreenStackPush(Element* aElement)
|
|||
EventStateManager::SetFullScreenState(aElement, true);
|
||||
mFullScreenStack.AppendElement(do_GetWeakReference(aElement));
|
||||
NS_ASSERTION(GetFullScreenElement() == aElement, "Should match");
|
||||
UpdateViewportScrollbarOverrideForFullscreen(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -11409,6 +11421,8 @@ nsDocument::FullScreenStackPop()
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateViewportScrollbarOverrideForFullscreen(this);
|
||||
}
|
||||
|
||||
Element*
|
||||
|
|
|
@ -2469,7 +2469,11 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindow* aWindow,
|
|||
nsCOMPtr<nsPIDOMWindow> focusedWindow;
|
||||
startContent = GetFocusedDescendant(aWindow, true, getter_AddRefs(focusedWindow));
|
||||
}
|
||||
else {
|
||||
else if (aType != MOVEFOCUS_LASTDOC) {
|
||||
// Otherwise, start at the focused node. If MOVEFOCUS_LASTDOC is used,
|
||||
// then we are document-navigating backwards from chrome to the content
|
||||
// process, and we don't want to use this so that we start from the end
|
||||
// of the document.
|
||||
startContent = aWindow->GetFocusedNode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<script>
|
||||
var ac = new AudioContext();
|
||||
var runningPromise = new Promise(resolve => {
|
||||
ac.onstatechange = event => {
|
||||
if (ac.state == "running") {
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
});
|
||||
fetch("audio.ogg").then(response => {
|
||||
return response.arrayBuffer();
|
||||
}).then(ab => {
|
||||
|
@ -17,7 +24,9 @@ fetch("audio.ogg").then(response => {
|
|||
|
||||
var suspendPromise;
|
||||
function suspendAC() {
|
||||
suspendPromise = ac.suspend();
|
||||
runningPromise.then(() => {
|
||||
suspendPromise = ac.suspend();
|
||||
});
|
||||
}
|
||||
|
||||
var resumePromise;
|
||||
|
|
|
@ -4,6 +4,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/. */
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include "BatteryManager.h"
|
||||
#include "Constants.h"
|
||||
|
@ -12,6 +13,7 @@
|
|||
#include "mozilla/dom/BatteryManagerBinding.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
/**
|
||||
* We have to use macros here because our leak analysis tool things we are
|
||||
|
@ -129,6 +131,20 @@ void
|
|||
BatteryManager::UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo)
|
||||
{
|
||||
mLevel = aBatteryInfo.level();
|
||||
|
||||
// Round to the nearest ten percent for non-chrome and non-certified apps
|
||||
nsIDocument* doc = GetOwner()->GetDoc();
|
||||
uint16_t status = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
|
||||
if (doc) {
|
||||
doc->NodePrincipal()->GetAppStatus(&status);
|
||||
}
|
||||
|
||||
if (!nsContentUtils::IsChromeDoc(doc) &&
|
||||
status != nsIPrincipal::APP_STATUS_CERTIFIED)
|
||||
{
|
||||
mLevel = lround(mLevel * 10.0) / 10.0;
|
||||
}
|
||||
|
||||
mCharging = aBatteryInfo.charging();
|
||||
mRemainingTime = aBatteryInfo.remainingTime();
|
||||
|
||||
|
|
|
@ -66,10 +66,14 @@ private:
|
|||
*/
|
||||
void UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo);
|
||||
|
||||
/**
|
||||
* Represents the battery level, ranging from 0.0 (dead or removed?)
|
||||
* to 1.0 (fully charged)
|
||||
*/
|
||||
double mLevel;
|
||||
bool mCharging;
|
||||
/**
|
||||
* Represents the discharging time or the charging time, dpending on the
|
||||
* Represents the discharging time or the charging time, depending on the
|
||||
* current battery status (charging or not).
|
||||
*/
|
||||
double mRemainingTime;
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Test for Bug 1201798</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="file_fullscreen-utils.js"></script>
|
||||
<style>
|
||||
html, body, #measure {
|
||||
width: 100%; height: 100%;
|
||||
}
|
||||
#ref-outer { width: 100px; height: 100px; overflow: scroll; }
|
||||
#ref-inner { width: 100%; height: 100%; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="measure"></div>
|
||||
<div style="height: 1000vh; width: 1000vw"></div>
|
||||
<div id="ref-outer">
|
||||
<div id="ref-inner"></div>
|
||||
</div>
|
||||
<div id="fullscreen"></div>
|
||||
<script type="text/javascript">
|
||||
|
||||
/** Test for Bug 1201798 */
|
||||
|
||||
var info = msg => opener.info("[scrollbar] " + msg);
|
||||
var ok = (cond, msg) => opener.ok(cond, "[scrollbar] " + msg);
|
||||
var is = (a, b, msg) => opener.is(a, b, "[scrollbar] " + msg);
|
||||
|
||||
var gVerticalScrollbarWidth, gHorizontalScrollbarWidth;
|
||||
var gMeasureDiv = document.getElementById("measure");
|
||||
var gFullscreenDiv = document.getElementById("fullscreen");
|
||||
|
||||
function getMeasureRect() {
|
||||
return gMeasureDiv.getBoundingClientRect();
|
||||
}
|
||||
|
||||
function triggerFrameReconstruction() {
|
||||
info("Triggering a force frame reconstruction");
|
||||
var docElem = document.documentElement;
|
||||
var wm = window.getComputedStyle(docElem).writingMode;
|
||||
if (wm == "horizontal-tb") {
|
||||
docElem.style.writingMode = "vertical-rl";
|
||||
} else {
|
||||
docElem.style.writingMode = "horizontal-tb";
|
||||
}
|
||||
docElem.getBoundingClientRect();
|
||||
}
|
||||
|
||||
function assertHasScrollbars(elem) {
|
||||
var rect = getMeasureRect();
|
||||
is(rect.width, screen.width - gVerticalScrollbarWidth,
|
||||
`Should have vertical scrollbar when ${elem} is in fullscreen`);
|
||||
is(rect.height, screen.height - gHorizontalScrollbarWidth,
|
||||
`Should have horizontal scrollbar when ${elem} is in fullscreen`);
|
||||
}
|
||||
|
||||
function assertHasNoScrollbars(elem) {
|
||||
var rect = getMeasureRect();
|
||||
is(rect.width, screen.width,
|
||||
`Should not have vertical scrollbar when ${elem} is in fullscreen`);
|
||||
is(rect.height, screen.height,
|
||||
`Should not have horizontal scrollbar when ${elem} is in fullscreen`);
|
||||
}
|
||||
|
||||
function checkScrollbars(elem, shouldHaveScrollbars) {
|
||||
is(elem, document.mozFullScreenElement,
|
||||
"Should only check the current fullscreen element");
|
||||
var assertFunc = shouldHaveScrollbars ?
|
||||
assertHasScrollbars : assertHasNoScrollbars;
|
||||
assertFunc(elem);
|
||||
triggerFrameReconstruction();
|
||||
assertFunc(elem);
|
||||
}
|
||||
|
||||
function begin() {
|
||||
if (window.matchMedia("(-moz-overlay-scrollbar").matches) {
|
||||
// If overlay scrollbar is enabled, the scrollbar is not measurable,
|
||||
// so we skip this test in that case.
|
||||
info("Skip this test because of overlay scrollbar");
|
||||
opener.nextTest();
|
||||
return;
|
||||
}
|
||||
|
||||
var rectOuter = document.getElementById("ref-outer").getBoundingClientRect();
|
||||
var rectInner = document.getElementById("ref-inner").getBoundingClientRect();
|
||||
gVerticalScrollbarWidth = rectOuter.width - rectInner.width;
|
||||
gHorizontalScrollbarWidth = rectOuter.height - rectInner.height;
|
||||
ok(gVerticalScrollbarWidth != 0, "Should have vertical scrollbar");
|
||||
ok(gHorizontalScrollbarWidth != 0, "Should have horizontal scrollbar");
|
||||
|
||||
info("Entering fullscreen on root");
|
||||
addFullscreenChangeContinuation("enter", enteredFullscreenOnRoot);
|
||||
document.documentElement.mozRequestFullScreen();
|
||||
}
|
||||
|
||||
function enteredFullscreenOnRoot() {
|
||||
checkScrollbars(document.documentElement, true);
|
||||
info("Entering fullscreen on div");
|
||||
addFullscreenChangeContinuation("enter", enteredFullscreenOnDiv);
|
||||
gFullscreenDiv.mozRequestFullScreen();
|
||||
}
|
||||
|
||||
function enteredFullscreenOnDiv() {
|
||||
checkScrollbars(gFullscreenDiv, false);
|
||||
info("Exiting fullscreen on div");
|
||||
addFullscreenChangeContinuation("exit", exitedFullscreenOnDiv);
|
||||
document.mozCancelFullScreen();
|
||||
}
|
||||
|
||||
function exitedFullscreenOnDiv() {
|
||||
checkScrollbars(document.documentElement, true);
|
||||
info("Exiting fullscreen on root");
|
||||
addFullscreenChangeContinuation("exit", exitedFullscreenOnRoot);
|
||||
document.mozCancelFullScreen();
|
||||
}
|
||||
|
||||
function exitedFullscreenOnRoot() {
|
||||
opener.nextTest();
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -60,6 +60,7 @@ support-files =
|
|||
file_fullscreen-navigation.html
|
||||
file_fullscreen-plugins.html
|
||||
file_fullscreen-rollback.html
|
||||
file_fullscreen-scrollbar.html
|
||||
file_fullscreen-selector.html
|
||||
file_fullscreen-svg-element.html
|
||||
file_fullscreen-utils.js
|
||||
|
|
|
@ -40,6 +40,7 @@ var gTestWindows = [
|
|||
"file_fullscreen-hidden.html",
|
||||
"file_fullscreen-svg-element.html",
|
||||
"file_fullscreen-navigation.html",
|
||||
"file_fullscreen-scrollbar.html",
|
||||
"file_fullscreen-selector.html"
|
||||
];
|
||||
|
||||
|
|
|
@ -647,10 +647,6 @@ ContentChild::Init(MessageLoop* aIOLoop,
|
|||
}
|
||||
sSingleton = this;
|
||||
|
||||
// Make sure there's an nsAutoScriptBlocker on the stack when dispatching
|
||||
// urgent messages.
|
||||
GetIPCChannel()->BlockScripts();
|
||||
|
||||
// If communications with the parent have broken down, take the process
|
||||
// down so it's not hanging around.
|
||||
bool abortOnError = true;
|
||||
|
|
|
@ -163,11 +163,6 @@ public:
|
|||
// Observe and it should never be called directly.
|
||||
NS_IMETHOD Observe(nsISupports *aSubject, const char * aTopic, const char16_t * aData) override
|
||||
{ MOZ_CRASH("Forbidden method"); return NS_OK; }
|
||||
|
||||
#ifdef MOZ_EME
|
||||
virtual nsresult SetCDMProxy(CDMProxy* aProxy) { return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
virtual CDMProxy* GetCDMProxy() { return nullptr; }
|
||||
#endif
|
||||
};
|
||||
|
||||
class MetadataContainer
|
||||
|
|
|
@ -140,7 +140,6 @@ void
|
|||
MediaDecoder::NotifyOwnerActivityChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
||||
if (!mOwner) {
|
||||
NS_WARNING("MediaDecoder without a decoder owner, can't update dormant");
|
||||
|
@ -155,6 +154,8 @@ MediaDecoder::NotifyOwnerActivityChanged()
|
|||
bool
|
||||
MediaDecoder::IsHeuristicDormantSupported() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
return
|
||||
#if defined(MOZ_EME)
|
||||
// We disallow dormant for encrypted media until bug 1181864 is fixed.
|
||||
|
@ -168,7 +169,6 @@ void
|
|||
MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
|
||||
if (!mDecoderStateMachine ||
|
||||
mPlayState == PLAY_STATE_SHUTDOWN ||
|
||||
|
@ -242,7 +242,6 @@ MediaDecoder::DormantTimerExpired(nsITimer* aTimer, void* aClosure)
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aClosure);
|
||||
MediaDecoder* decoder = static_cast<MediaDecoder*>(aClosure);
|
||||
ReentrantMonitorAutoEnter mon(decoder->GetReentrantMonitor());
|
||||
decoder->UpdateDormantState(true /* aDormantTimeout */,
|
||||
false /* aActivity */);
|
||||
}
|
||||
|
@ -287,7 +286,6 @@ void
|
|||
MediaDecoder::Pause()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
if (mPlayState == PLAY_STATE_LOADING ||
|
||||
IsEnded()) {
|
||||
mNextState = PLAY_STATE_PAUSED;
|
||||
|
@ -356,6 +354,9 @@ MediaDecoder::MediaDecoder() :
|
|||
mLogicalPosition(0.0),
|
||||
mDuration(std::numeric_limits<double>::quiet_NaN()),
|
||||
mReentrantMonitor("media.decoder"),
|
||||
#ifdef MOZ_EME
|
||||
mCDMProxyPromise(mCDMProxyPromiseHolder.Ensure(__func__)),
|
||||
#endif
|
||||
mIgnoreProgressData(false),
|
||||
mInfiniteStream(false),
|
||||
mOwner(nullptr),
|
||||
|
@ -463,6 +464,10 @@ MediaDecoder::Shutdown()
|
|||
|
||||
mShuttingDown = true;
|
||||
|
||||
#ifdef MOZ_EME
|
||||
mCDMProxyPromiseHolder.RejectIfExists(true, __func__);
|
||||
#endif
|
||||
|
||||
// This changes the decoder state to SHUTDOWN and does other things
|
||||
// necessary to unblock the state machine thread if it's blocked, so
|
||||
// the asynchronous shutdown in nsDestroyStateMachine won't deadlock.
|
||||
|
@ -501,17 +506,7 @@ MediaDecoder::OpenResource(nsIStreamListener** aStreamListener)
|
|||
if (aStreamListener) {
|
||||
*aStreamListener = nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
// Hold the lock while we do this to set proper lock ordering
|
||||
// expectations for dynamic deadlock detectors: decoder lock(s)
|
||||
// should be grabbed before the cache lock
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
||||
nsresult rv = mResource->Open(aStreamListener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return NS_OK;
|
||||
return mResource->Open(aStreamListener);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -575,7 +570,6 @@ nsresult
|
|||
MediaDecoder::Play()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
UpdateDormantState(false /* aDormantTimeout */, true /* aActivity */);
|
||||
|
||||
NS_ASSERTION(mDecoderStateMachine != nullptr, "Should have state machine.");
|
||||
|
@ -598,7 +592,6 @@ nsresult
|
|||
MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
NS_ENSURE_TRUE(!mShuttingDown, NS_ERROR_FAILURE);
|
||||
|
||||
UpdateDormantState(false /* aDormantTimeout */, true /* aActivity */);
|
||||
|
@ -795,7 +788,6 @@ void
|
|||
MediaDecoder::UpdateSameOriginStatus(bool aSameOrigin)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
mSameOriginMedia = aSameOrigin;
|
||||
}
|
||||
|
||||
|
@ -850,7 +842,6 @@ MediaStatistics
|
|||
MediaDecoder::GetStatistics()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
MOZ_ASSERT(mResource);
|
||||
|
||||
MediaStatistics result;
|
||||
|
@ -868,7 +859,6 @@ void
|
|||
MediaDecoder::ComputePlaybackRate()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
MOZ_ASSERT(mResource);
|
||||
|
||||
int64_t length = mResource->GetLength();
|
||||
|
@ -887,7 +877,6 @@ void
|
|||
MediaDecoder::UpdatePlaybackRate()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
MOZ_ASSERT(mResource);
|
||||
|
||||
ComputePlaybackRate();
|
||||
|
@ -919,10 +908,7 @@ void
|
|||
MediaDecoder::NotifyBytesDownloaded()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
UpdatePlaybackRate();
|
||||
}
|
||||
UpdatePlaybackRate();
|
||||
if (mOwner) {
|
||||
mOwner->DownloadProgressed();
|
||||
}
|
||||
|
@ -943,10 +929,7 @@ MediaDecoder::NotifyDownloadEnded(nsresult aStatus)
|
|||
return;
|
||||
}
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
UpdatePlaybackRate();
|
||||
}
|
||||
UpdatePlaybackRate();
|
||||
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
// A final progress event will be fired by the MediaResource calling
|
||||
|
@ -977,7 +960,6 @@ MediaDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
|
|||
}
|
||||
|
||||
MOZ_ASSERT(mDecoderStateMachine);
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
if (aOffset >= mDecoderPosition) {
|
||||
mPlaybackStatistics->AddBytes(aBytes);
|
||||
}
|
||||
|
@ -995,8 +977,6 @@ MediaDecoder::OnSeekResolved(SeekResolveValue aVal)
|
|||
|
||||
bool fireEnded = false;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
||||
// An additional seek was requested while the current seek was
|
||||
// in operation.
|
||||
UnpinForSeek();
|
||||
|
@ -1037,7 +1017,6 @@ void
|
|||
MediaDecoder::ChangeState(PlayState aState)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
||||
if (mNextState == aState) {
|
||||
mNextState = PLAY_STATE_PAUSED;
|
||||
|
@ -1094,7 +1073,6 @@ void
|
|||
MediaDecoder::DurationChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
|
||||
double oldDuration = mDuration;
|
||||
if (IsInfinite()) {
|
||||
|
@ -1150,7 +1128,6 @@ MediaDecoder::UpdateEstimatedMediaDuration(int64_t aDuration)
|
|||
void
|
||||
MediaDecoder::SetMediaSeekable(bool aMediaSeekable) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
mMediaSeekable = aMediaSeekable;
|
||||
}
|
||||
|
||||
|
@ -1363,12 +1340,14 @@ MediaDecoder::NotifyDataArrived(uint32_t aLength,
|
|||
// Provide access to the state machine object
|
||||
MediaDecoderStateMachine*
|
||||
MediaDecoder::GetStateMachine() const {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mDecoderStateMachine;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoder::NotifyWaitingForResourcesStatusChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mDecoderStateMachine) {
|
||||
mDecoderStateMachine->DispatchWaitingForResourcesStatusChanged();
|
||||
}
|
||||
|
@ -1377,6 +1356,7 @@ MediaDecoder::NotifyWaitingForResourcesStatusChanged()
|
|||
// Drop reference to state machine. Only called during shutdown dance.
|
||||
void
|
||||
MediaDecoder::BreakCycles() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
SetStateMachine(nullptr);
|
||||
}
|
||||
|
||||
|
@ -1428,22 +1408,30 @@ MediaDecoder::CanPlayThrough()
|
|||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
nsresult
|
||||
nsRefPtr<MediaDecoder::CDMProxyPromise>
|
||||
MediaDecoder::RequestCDMProxy() const
|
||||
{
|
||||
return mCDMProxyPromise;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoder::SetCDMProxy(CDMProxy* aProxy)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
mProxy = aProxy;
|
||||
// Awaken any readers waiting for the proxy.
|
||||
NotifyWaitingForResourcesStatusChanged();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
CDMProxy*
|
||||
MediaDecoder::GetCDMProxy()
|
||||
{
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
return mProxy;
|
||||
nsRefPtr<CDMProxy> proxy = aProxy;
|
||||
{
|
||||
CDMCaps::AutoLock caps(aProxy->Capabilites());
|
||||
if (!caps.AreCapsKnown()) {
|
||||
nsRefPtr<MediaDecoder> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
|
||||
self->mCDMProxyPromiseHolder.ResolveIfExists(proxy, __func__);
|
||||
});
|
||||
caps.CallOnMainThreadWhenCapsAvailable(r);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mCDMProxyPromiseHolder.ResolveIfExists(proxy, __func__);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -664,11 +664,13 @@ public:
|
|||
MediaDecoderOwner* GetOwner() override;
|
||||
|
||||
#ifdef MOZ_EME
|
||||
// This takes the decoder monitor.
|
||||
virtual nsresult SetCDMProxy(CDMProxy* aProxy) override;
|
||||
typedef MozPromise<nsRefPtr<CDMProxy>, bool /* aIgnored */, /* IsExclusive = */ true> CDMProxyPromise;
|
||||
|
||||
// Decoder monitor must be held.
|
||||
virtual CDMProxy* GetCDMProxy() override;
|
||||
// Resolved when a CDMProxy is available and the capabilities are known or
|
||||
// rejected when this decoder is about to shut down.
|
||||
nsRefPtr<CDMProxyPromise> RequestCDMProxy() const;
|
||||
|
||||
void SetCDMProxy(CDMProxy* aProxy);
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_RAW
|
||||
|
@ -818,7 +820,8 @@ private:
|
|||
ReentrantMonitor mReentrantMonitor;
|
||||
|
||||
#ifdef MOZ_EME
|
||||
nsRefPtr<CDMProxy> mProxy;
|
||||
MozPromiseHolder<CDMProxyPromise> mCDMProxyPromiseHolder;
|
||||
nsRefPtr<CDMProxyPromise> mCDMProxyPromise;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
|
|
@ -259,20 +259,10 @@ MediaDecoderReader::AsyncReadMetadata()
|
|||
mDecoder->GetReentrantMonitor().AssertNotCurrentThreadIn();
|
||||
DECODER_LOG("MediaDecoderReader::AsyncReadMetadata");
|
||||
|
||||
if (IsWaitingMediaResources()) {
|
||||
return MetadataPromise::CreateAndReject(Reason::WAITING_FOR_RESOURCES, __func__);
|
||||
}
|
||||
|
||||
// Attempt to read the metadata.
|
||||
nsRefPtr<MetadataHolder> metadata = new MetadataHolder();
|
||||
nsresult rv = ReadMetadata(&metadata->mInfo, getter_Transfers(metadata->mTags));
|
||||
|
||||
// Reading metadata can cause us to discover that we need resources (a hardware
|
||||
// resource initialized but not yet ready for use).
|
||||
if (IsWaitingMediaResources()) {
|
||||
return MetadataPromise::CreateAndReject(Reason::WAITING_FOR_RESOURCES, __func__);
|
||||
}
|
||||
|
||||
// We're not waiting for anything. If we didn't get the metadata, that's an
|
||||
// error.
|
||||
if (NS_FAILED(rv) || !metadata->mInfo.HasValidMedia()) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
class CDMProxy;
|
||||
class MediaDecoderReader;
|
||||
|
||||
struct WaitForDataRejectValue
|
||||
|
@ -94,11 +95,6 @@ public:
|
|||
// on failure.
|
||||
virtual nsresult Init(MediaDecoderReader* aCloneDonor) = 0;
|
||||
|
||||
// True if this reader is waiting media resource allocation
|
||||
virtual bool IsWaitingMediaResources() { return false; }
|
||||
// True if this reader is waiting for a Content Decryption Module to become
|
||||
// available.
|
||||
virtual bool IsWaitingOnCDMResource() { return false; }
|
||||
// Release media resources they should be released in dormant state
|
||||
// The reader can be made usable again by calling ReadMetadata().
|
||||
virtual void ReleaseMediaResources() {};
|
||||
|
@ -195,6 +191,10 @@ public:
|
|||
// when to call SetIdle().
|
||||
virtual void SetIdle() { }
|
||||
|
||||
#ifdef MOZ_EME
|
||||
virtual void SetCDMProxy(CDMProxy* aProxy) {}
|
||||
#endif
|
||||
|
||||
// Tell the reader that the data decoded are not for direct playback, so it
|
||||
// can accept more files, in particular those which have more channels than
|
||||
// available in the audio output.
|
||||
|
|
|
@ -205,7 +205,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
|||
mQuickBufferingLowDataThresholdUsecs(detail::QUICK_BUFFERING_LOW_DATA_USECS),
|
||||
mIsAudioPrerolling(false),
|
||||
mIsVideoPrerolling(false),
|
||||
mAudioCaptured(false),
|
||||
mAudioCaptured(false, "MediaDecoderStateMachine::mAudioCaptured"),
|
||||
mAudioCompleted(false, "MediaDecoderStateMachine::mAudioCompleted"),
|
||||
mNotifyMetadataBeforeFirstFrame(false),
|
||||
mDispatchedEventToDecode(false),
|
||||
|
@ -219,7 +219,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
|||
mCorruptFrames(60),
|
||||
mDecodingFirstFrame(true),
|
||||
mSentLoadedMetadataEvent(false),
|
||||
mSentFirstFrameLoadedEvent(false),
|
||||
mSentFirstFrameLoadedEvent(false, "MediaDecoderStateMachine::mSentFirstFrameLoadedEvent"),
|
||||
mSentPlaybackEndedEvent(false),
|
||||
mStreamSink(new DecodedStream(mTaskQueue, mAudioQueue, mVideoQueue)),
|
||||
mResource(aDecoder->GetResource()),
|
||||
|
@ -302,6 +302,13 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
|||
mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
|
||||
|
||||
mMediaSink = CreateAudioSink();
|
||||
|
||||
#ifdef MOZ_EME
|
||||
mCDMProxyPromise.Begin(mDecoder->RequestCDMProxy()->Then(
|
||||
OwnerThread(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnCDMProxyReady,
|
||||
&MediaDecoderStateMachine::OnCDMProxyNotReady));
|
||||
#endif
|
||||
}
|
||||
|
||||
MediaDecoderStateMachine::~MediaDecoderStateMachine()
|
||||
|
@ -350,6 +357,8 @@ MediaDecoderStateMachine::InitializationTask()
|
|||
mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::PlayStateChanged);
|
||||
mWatchManager.Watch(mLogicallySeeking, &MediaDecoderStateMachine::LogicallySeekingChanged);
|
||||
mWatchManager.Watch(mSameOriginMedia, &MediaDecoderStateMachine::SameOriginMediaChanged);
|
||||
mWatchManager.Watch(mSentFirstFrameLoadedEvent, &MediaDecoderStateMachine::AdjustAudioThresholds);
|
||||
mWatchManager.Watch(mAudioCaptured, &MediaDecoderStateMachine::AdjustAudioThresholds);
|
||||
|
||||
// Propagate mSameOriginMedia to mDecodedStream.
|
||||
SameOriginMediaChanged();
|
||||
|
@ -1315,6 +1324,10 @@ void MediaDecoderStateMachine::Shutdown()
|
|||
mPendingSeek.RejectIfExists(__func__);
|
||||
mCurrentSeek.RejectIfExists(__func__);
|
||||
|
||||
#ifdef MOZ_EME
|
||||
mCDMProxyPromise.DisconnectIfExists();
|
||||
#endif
|
||||
|
||||
if (IsPlaying()) {
|
||||
StopPlayback();
|
||||
}
|
||||
|
@ -1403,9 +1416,6 @@ MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged()
|
|||
// Try again.
|
||||
SetState(DECODER_STATE_DECODING_NONE);
|
||||
ScheduleStateMachine();
|
||||
} else if (mState == DECODER_STATE_WAIT_FOR_CDM &&
|
||||
!mReader->IsWaitingOnCDMResource()) {
|
||||
StartDecoding();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2000,12 +2010,18 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
|
|||
// feeding in the CDM, which we need to decode the first frame (and
|
||||
// thus get the metadata). We could fix this if we could compute the start
|
||||
// time by demuxing without necessaring decoding.
|
||||
mNotifyMetadataBeforeFirstFrame = mDuration.Ref().isSome() || mReader->IsWaitingOnCDMResource();
|
||||
bool waitingForCDM =
|
||||
#ifdef MOZ_EME
|
||||
mInfo.IsEncrypted() && !mCDMProxy;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
mNotifyMetadataBeforeFirstFrame = mDuration.Ref().isSome() || waitingForCDM;
|
||||
if (mNotifyMetadataBeforeFirstFrame) {
|
||||
EnqueueLoadedMetadataEvent();
|
||||
}
|
||||
|
||||
if (mReader->IsWaitingOnCDMResource()) {
|
||||
if (waitingForCDM) {
|
||||
// Metadata parsing was successful but we're still waiting for CDM caps
|
||||
// to become available so that we can build the correct decryptor/decoder.
|
||||
SetState(DECODER_STATE_WAIT_FOR_CDM);
|
||||
|
@ -2070,6 +2086,33 @@ MediaDecoderStateMachine::IsDecodingFirstFrame()
|
|||
return mState == DECODER_STATE_DECODING && mDecodingFirstFrame;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::AdjustAudioThresholds()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
|
||||
// Experiments show that we need to buffer more if audio is captured to avoid
|
||||
// audio glitch. See bug 1188643 comment 16 for the details.
|
||||
int64_t divisor = mAudioCaptured ? NO_VIDEO_AMPLE_AUDIO_DIVISOR / 2
|
||||
: NO_VIDEO_AMPLE_AUDIO_DIVISOR;
|
||||
|
||||
// We're playing audio only. We don't need to worry about slow video
|
||||
// decodes causing audio underruns, so don't buffer so much audio in
|
||||
// order to reduce memory usage.
|
||||
if (HasAudio() && !HasVideo() && mSentFirstFrameLoadedEvent) {
|
||||
mAmpleAudioThresholdUsecs = detail::AMPLE_AUDIO_USECS / divisor;
|
||||
mLowAudioThresholdUsecs = detail::LOW_AUDIO_USECS / divisor;
|
||||
mQuickBufferingLowDataThresholdUsecs =
|
||||
detail::QUICK_BUFFERING_LOW_DATA_USECS / divisor;
|
||||
|
||||
// Check if we need to stop audio prerolling for thresholds changed.
|
||||
if (mIsAudioPrerolling && DonePrerollingAudio()) {
|
||||
StopPrerollingAudio();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::FinishDecodeFirstFrame()
|
||||
{
|
||||
|
@ -2090,15 +2133,6 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
|
|||
"transportSeekable=%d, mediaSeekable=%d",
|
||||
Duration().ToMicroseconds(), mResource->IsTransportSeekable(), mMediaSeekable.Ref());
|
||||
|
||||
if (HasAudio() && !HasVideo() && !mSentFirstFrameLoadedEvent) {
|
||||
// We're playing audio only. We don't need to worry about slow video
|
||||
// decodes causing audio underruns, so don't buffer so much audio in
|
||||
// order to reduce memory usage.
|
||||
mAmpleAudioThresholdUsecs /= NO_VIDEO_AMPLE_AUDIO_DIVISOR;
|
||||
mLowAudioThresholdUsecs /= NO_VIDEO_AMPLE_AUDIO_DIVISOR;
|
||||
mQuickBufferingLowDataThresholdUsecs /= NO_VIDEO_AMPLE_AUDIO_DIVISOR;
|
||||
}
|
||||
|
||||
// Get potentially updated metadata
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
|
@ -3021,6 +3055,27 @@ void MediaDecoderStateMachine::OnMediaSinkError()
|
|||
DecodeError();
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
void
|
||||
MediaDecoderStateMachine::OnCDMProxyReady(nsRefPtr<CDMProxy> aProxy)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
mCDMProxyPromise.Complete();
|
||||
mCDMProxy = aProxy;
|
||||
mReader->SetCDMProxy(aProxy);
|
||||
if (mState == DECODER_STATE_WAIT_FOR_CDM) {
|
||||
StartDecoding();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::OnCDMProxyNotReady()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
mCDMProxyPromise.Complete();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::SetAudioCaptured(bool aCaptured)
|
||||
{
|
||||
|
|
|
@ -654,6 +654,8 @@ private:
|
|||
// play time.
|
||||
bool NeedToSkipToNextKeyframe();
|
||||
|
||||
void AdjustAudioThresholds();
|
||||
|
||||
// The decoder object that created this state machine. The state machine
|
||||
// holds a strong reference to the decoder to ensure that the decoder stays
|
||||
// alive once media element has started the decoder shutdown process, and has
|
||||
|
@ -1136,7 +1138,7 @@ private:
|
|||
// True if we shouldn't play our audio (but still write it to any capturing
|
||||
// streams). When this is true, the audio thread will never start again after
|
||||
// it has stopped.
|
||||
bool mAudioCaptured;
|
||||
Watchable<bool> mAudioCaptured;
|
||||
|
||||
// True if the audio playback thread has finished. It is finished
|
||||
// when either all the audio frames have completed playing, or we've moved
|
||||
|
@ -1228,7 +1230,7 @@ private:
|
|||
// SetStartTime because the mStartTime already set before. Also we don't need
|
||||
// to decode any audio/video since the MediaDecoder will trigger a seek
|
||||
// operation soon.
|
||||
bool mSentFirstFrameLoadedEvent;
|
||||
Watchable<bool> mSentFirstFrameLoadedEvent;
|
||||
|
||||
bool mSentPlaybackEndedEvent;
|
||||
|
||||
|
@ -1247,6 +1249,13 @@ private:
|
|||
MediaEventListener mAudioQueueListener;
|
||||
MediaEventListener mVideoQueueListener;
|
||||
|
||||
#ifdef MOZ_EME
|
||||
void OnCDMProxyReady(nsRefPtr<CDMProxy> aProxy);
|
||||
void OnCDMProxyNotReady();
|
||||
nsRefPtr<CDMProxy> mCDMProxy;
|
||||
MozPromiseRequestHolder<MediaDecoder::CDMProxyPromise> mCDMProxyPromise;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// The buffered range. Mirrored from the decoder thread.
|
||||
Mirror<media::TimeIntervals> mBuffered;
|
||||
|
|
|
@ -213,29 +213,24 @@ private:
|
|||
nsTArray<uint8_t> mInitData;
|
||||
nsString mInitDataType;
|
||||
};
|
||||
|
||||
void
|
||||
MediaFormatReader::SetCDMProxy(CDMProxy* aProxy)
|
||||
{
|
||||
nsRefPtr<CDMProxy> proxy = aProxy;
|
||||
nsRefPtr<MediaFormatReader> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
|
||||
self->mCDMProxy = proxy;
|
||||
});
|
||||
OwnerThread()->DispatchDirectTask(r.forget());
|
||||
}
|
||||
#endif // MOZ_EME
|
||||
|
||||
bool MediaFormatReader::IsWaitingOnCDMResource() {
|
||||
bool
|
||||
MediaFormatReader::IsWaitingOnCDMResource() {
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
#ifdef MOZ_EME
|
||||
nsRefPtr<CDMProxy> proxy;
|
||||
{
|
||||
if (!IsEncrypted()) {
|
||||
// Not encrypted, no need to wait for CDMProxy.
|
||||
return false;
|
||||
}
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
proxy = mDecoder->GetCDMProxy();
|
||||
if (!proxy) {
|
||||
// We're encrypted, we need a CDMProxy to decrypt file.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// We'll keep waiting if the CDM hasn't informed Gecko of its capabilities.
|
||||
{
|
||||
CDMCaps::AutoLock caps(proxy->Capabilites());
|
||||
LOG("capsKnown=%d", caps.AreCapsKnown());
|
||||
return !caps.AreCapsKnown();
|
||||
}
|
||||
return IsEncrypted() && !mCDMProxy;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
@ -392,18 +387,8 @@ MediaFormatReader::EnsureDecodersCreated()
|
|||
// even if EME is disabled, so that if script tries and fails to create
|
||||
// a CDM, we can detect that and notify chrome and show some UI
|
||||
// explaining that we failed due to EME being disabled.
|
||||
nsRefPtr<CDMProxy> proxy;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
proxy = mDecoder->GetCDMProxy();
|
||||
MOZ_ASSERT(proxy);
|
||||
|
||||
CDMCaps::AutoLock caps(proxy->Capabilites());
|
||||
mInfo.mVideo.mIsRenderedExternally = caps.CanRenderVideo();
|
||||
mInfo.mAudio.mIsRenderedExternally = caps.CanRenderAudio();
|
||||
}
|
||||
|
||||
mPlatform = PlatformDecoderModule::CreateCDMWrapper(proxy);
|
||||
MOZ_ASSERT(mCDMProxy);
|
||||
mPlatform = PlatformDecoderModule::CreateCDMWrapper(mCDMProxy);
|
||||
NS_ENSURE_TRUE(mPlatform, false);
|
||||
#else
|
||||
// EME not supported.
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
class CDMProxy;
|
||||
|
||||
class MediaFormatReader final : public MediaDecoderReader
|
||||
{
|
||||
typedef TrackInfo::TrackType TrackType;
|
||||
|
@ -86,14 +88,18 @@ public:
|
|||
bool IsWaitForDataSupported() override { return true; }
|
||||
nsRefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType) override;
|
||||
|
||||
bool IsWaitingOnCDMResource() override;
|
||||
|
||||
bool UseBufferingHeuristics() override
|
||||
{
|
||||
return mTrackDemuxersMayBlock;
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
void SetCDMProxy(CDMProxy* aProxy) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool IsWaitingOnCDMResource();
|
||||
|
||||
bool InitDemuxer();
|
||||
// Notify the demuxer that new data has been received.
|
||||
// The next queued task calling GetBuffered() is guaranteed to have up to date
|
||||
|
@ -391,10 +397,6 @@ private:
|
|||
{
|
||||
return mIsEncrypted;
|
||||
}
|
||||
// Accessed from multiple thread, in particular the MediaDecoderStateMachine,
|
||||
// however the value doesn't currently change after reading the metadata.
|
||||
// TODO handle change of encryption half-way. The above assumption will then
|
||||
// become incorrect.
|
||||
bool mIsEncrypted;
|
||||
|
||||
// Set to true if any of our track buffers may be blocking.
|
||||
|
|
|
@ -487,6 +487,12 @@ public:
|
|||
NS_ASSERTION(0 <= aTime && aTime <= STREAM_TIME_MAX, "Bad time");
|
||||
return (aTime*1000000)/mBuffer.GraphRate();
|
||||
}
|
||||
StreamTime SecondsToNearestStreamTime(double aSeconds)
|
||||
{
|
||||
NS_ASSERTION(0 <= aSeconds && aSeconds <= TRACK_TICKS_MAX/TRACK_RATE_MAX,
|
||||
"Bad seconds");
|
||||
return mBuffer.GraphRate() * aSeconds + 0.5;
|
||||
}
|
||||
StreamTime MicrosecondsToStreamTimeRoundDown(int64_t aMicroseconds) {
|
||||
return (aMicroseconds*mBuffer.GraphRate())/1000000;
|
||||
}
|
||||
|
|
|
@ -51,25 +51,6 @@ MediaDecoderStateMachine* MP4Decoder::CreateStateMachine()
|
|||
return new MediaDecoderStateMachine(this, reader);
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
nsresult
|
||||
MP4Decoder::SetCDMProxy(CDMProxy* aProxy)
|
||||
{
|
||||
nsresult rv = MediaDecoder::SetCDMProxy(aProxy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (aProxy) {
|
||||
// The MediaFormatReader can't decrypt EME content until it has a CDMProxy,
|
||||
// and the CDMProxy knows the capabilities of the CDM. The MediaFormatReader
|
||||
// remains in "waiting for resources" state until then.
|
||||
CDMCaps::AutoLock caps(aProxy->Capabilites());
|
||||
nsCOMPtr<nsIRunnable> task(
|
||||
NS_NewRunnableMethod(this, &MediaDecoder::NotifyWaitingForResourcesStatusChanged));
|
||||
caps.CallOnMainThreadWhenCapsAvailable(task);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
IsSupportedAudioCodec(const nsAString& aCodec,
|
||||
bool& aOutContainsAAC,
|
||||
|
|
|
@ -25,10 +25,6 @@ public:
|
|||
|
||||
virtual MediaDecoderStateMachine* CreateStateMachine() override;
|
||||
|
||||
#ifdef MOZ_EME
|
||||
virtual nsresult SetCDMProxy(CDMProxy* aProxy) override;
|
||||
#endif
|
||||
|
||||
// Returns true if aMIMEType is a type that we think we can render with the
|
||||
// a MP4 platform decoder backend. If aCodecs is non emtpy, it is filled
|
||||
// with a comma-delimited list of codecs to check support for. Notes in
|
||||
|
|
|
@ -606,10 +606,21 @@ GMPChild::GetGMPStorage()
|
|||
return mStorage;
|
||||
}
|
||||
|
||||
bool
|
||||
GMPChild::RecvCrashPluginNow()
|
||||
static MOZ_NEVER_INLINE void
|
||||
CrashForApiTimeout()
|
||||
{
|
||||
MOZ_CRASH();
|
||||
// Never inline so that crash reports are distinctive.
|
||||
MOZ_CRASH("Bug 1209385; GMP API actor failed to respond.");
|
||||
}
|
||||
|
||||
bool
|
||||
GMPChild::RecvCrashPluginNow(const GMPCrashReason& aReason)
|
||||
{
|
||||
if (aReason == kGmpApiTimeout) {
|
||||
CrashForApiTimeout();
|
||||
} else {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ private:
|
|||
ProcessId aOtherPid) override;
|
||||
void GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild);
|
||||
|
||||
virtual bool RecvCrashPluginNow() override;
|
||||
virtual bool RecvCrashPluginNow(const GMPCrashReason& aReason) override;
|
||||
virtual bool RecvBeginAsyncShutdown() override;
|
||||
virtual bool RecvCloseActive() override;
|
||||
|
||||
|
|
|
@ -118,6 +118,18 @@ GMPContentParent::DecryptorDestroyed(GMPDecryptorParent* aSession)
|
|||
CloseIfUnused();
|
||||
}
|
||||
|
||||
void
|
||||
GMPContentParent::CrashPluginNow(GMPCrashReason aReason)
|
||||
{
|
||||
if (mParent) {
|
||||
mParent->Crash(aReason);
|
||||
} else {
|
||||
nsRefPtr<GeckoMediaPluginServiceChild> gmp(
|
||||
GeckoMediaPluginServiceChild::GetSingleton());
|
||||
gmp->CrashPluginNow(mPluginId, aReason);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GMPContentParent::CloseIfUnused()
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/gmp/PGMPContentParent.h"
|
||||
#include "GMPSharedMemManager.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "GMPUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
@ -61,6 +62,8 @@ public:
|
|||
return mPluginId;
|
||||
}
|
||||
|
||||
void CrashPluginNow(GMPCrashReason aReason);
|
||||
|
||||
private:
|
||||
~GMPContentParent();
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "gmp-audio-codec.h"
|
||||
#include "gmp-decryption.h"
|
||||
|
||||
#include "GMPUtils.h"
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template <>
|
||||
|
@ -247,6 +249,13 @@ struct ParamTraits<GMPVideoCodec>
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::GMPCrashReason>
|
||||
: public ContiguousEnumSerializer<mozilla::GMPCrashReason,
|
||||
mozilla::kPrefChange,
|
||||
mozilla::kInvalid>
|
||||
{};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // GMPMessageUtils_h_
|
||||
|
|
|
@ -119,10 +119,10 @@ GMPParent::Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir)
|
|||
}
|
||||
|
||||
void
|
||||
GMPParent::Crash()
|
||||
GMPParent::Crash(GMPCrashReason aReason)
|
||||
{
|
||||
if (mState != GMPStateNotLoaded) {
|
||||
unused << SendCrashPluginNow();
|
||||
unused << SendCrashPluginNow(aReason);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "nsTArray.h"
|
||||
#include "nsIFile.h"
|
||||
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
|
||||
#include "GMPUtils.h"
|
||||
|
||||
class nsIThread;
|
||||
|
||||
|
@ -79,7 +80,7 @@ public:
|
|||
nsresult Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir);
|
||||
nsresult CloneFrom(const GMPParent* aOther);
|
||||
|
||||
void Crash();
|
||||
void Crash(GMPCrashReason aReason);
|
||||
|
||||
nsresult LoadProcess();
|
||||
|
||||
|
|
|
@ -215,6 +215,38 @@ GeckoMediaPluginServiceChild::UpdateTrialCreateState(const nsAString& aKeySystem
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceChild::CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason)
|
||||
{
|
||||
if (NS_GetCurrentThread() != mGMPThread) {
|
||||
mGMPThread->Dispatch(NS_NewRunnableMethodWithArgs<uint32_t, GMPCrashReason>(
|
||||
this, &GeckoMediaPluginServiceChild::CrashPluginNow,
|
||||
aPluginId, aReason), NS_DISPATCH_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
class Callback : public GetServiceChildCallback
|
||||
{
|
||||
public:
|
||||
Callback(uint32_t aPluginId, GMPCrashReason aReason)
|
||||
: mPluginId(aPluginId)
|
||||
, mReason(aReason)
|
||||
{ }
|
||||
|
||||
virtual void Done(GMPServiceChild* aService) override
|
||||
{
|
||||
aService->SendCrashPluginNow(mPluginId, mReason);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t mPluginId;
|
||||
GMPCrashReason mReason;
|
||||
};
|
||||
|
||||
UniquePtr<GetServiceChildCallback> callback(new Callback(aPluginId, aReason));
|
||||
GetServiceChild(Move(callback));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/ipc/Transport.h"
|
||||
#include "mozilla/gmp/PGMPServiceChild.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "GMPUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
@ -52,6 +53,8 @@ public:
|
|||
NS_IMETHOD UpdateTrialCreateState(const nsAString& aKeySystem,
|
||||
uint32_t aState) override;
|
||||
|
||||
void CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason);
|
||||
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
void SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild);
|
||||
|
|
|
@ -83,6 +83,7 @@ NS_IMPL_ISUPPORTS_INHERITED(GeckoMediaPluginServiceParent,
|
|||
|
||||
static int32_t sMaxAsyncShutdownWaitMs = 0;
|
||||
static bool sHaveSetTimeoutPrefCache = false;
|
||||
static bool sKillHungPlugins = true;
|
||||
|
||||
GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent()
|
||||
: mShuttingDown(false)
|
||||
|
@ -98,6 +99,9 @@ GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent()
|
|||
Preferences::AddIntVarCache(&sMaxAsyncShutdownWaitMs,
|
||||
"media.gmp.async-shutdown-timeout",
|
||||
GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT);
|
||||
Preferences::AddBoolVarCache(&sKillHungPlugins,
|
||||
"media.gmp.kill-hung-plugins",
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -511,7 +515,7 @@ GeckoMediaPluginServiceParent::CrashPlugins()
|
|||
|
||||
MutexAutoLock lock(mMutex);
|
||||
for (size_t i = 0; i < mPlugins.Length(); i++) {
|
||||
mPlugins[i]->Crash();
|
||||
mPlugins[i]->Crash(kPrefChange);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1221,6 +1225,24 @@ GeckoMediaPluginServiceParent::UpdateTrialCreateState(const nsAString& aKeySyste
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceParent::CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason)
|
||||
{
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
if (aReason == kGmpApiTimeout && !sKillHungPlugins) {
|
||||
LOGD(("%s::%s(%u, %u) but killing hung plugins disabled.",
|
||||
__CLASS__, __FUNCTION__, aPluginId, aReason));
|
||||
return;
|
||||
}
|
||||
LOGD(("%s::%s(%u, %u)", __CLASS__, __FUNCTION__, aPluginId, aReason));
|
||||
MutexAutoLock lock(mMutex);
|
||||
for (const auto& plugin : mPlugins) {
|
||||
if (plugin->GetPluginId() == aPluginId) {
|
||||
plugin->Crash(aReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ExtractHostName(const nsACString& aOrigin, nsACString& aOutData)
|
||||
{
|
||||
|
@ -1555,6 +1577,14 @@ GMPServiceParent::~GMPServiceParent()
|
|||
new DeleteTask<Transport>(GetTransport()));
|
||||
}
|
||||
|
||||
bool
|
||||
GMPServiceParent::RecvCrashPluginNow(const uint32_t& aPluginId,
|
||||
const GMPCrashReason& aReason)
|
||||
{
|
||||
mService->CrashPluginNow(aPluginId, aReason);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "nsDataHashtable.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "GMPUtils.h"
|
||||
|
||||
template <class> struct already_AddRefed;
|
||||
|
||||
|
@ -57,6 +58,8 @@ public:
|
|||
void SetAsyncShutdownPluginState(GMPParent* aGMPParent, char aId, const nsCString& aState);
|
||||
#endif // MOZ_CRASHREPORTER
|
||||
|
||||
void CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason);
|
||||
|
||||
private:
|
||||
friend class GMPServiceParent;
|
||||
|
||||
|
@ -223,6 +226,8 @@ public:
|
|||
nsCString* aVersion);
|
||||
virtual bool RecvUpdateGMPTrialCreateState(const nsString& aKeySystem,
|
||||
const uint32_t& aState) override;
|
||||
virtual bool RecvCrashPluginNow(const uint32_t& aPluginId,
|
||||
const GMPCrashReason& aReason) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
|
|
|
@ -37,6 +37,12 @@ SplitAt(const char* aDelims,
|
|||
nsCString
|
||||
ToBase64(const nsTArray<uint8_t>& aBytes);
|
||||
|
||||
enum GMPCrashReason {
|
||||
kPrefChange, // media.gmp.plugin.crash has been toggled.
|
||||
kGmpApiTimeout, // Some API did not respond.
|
||||
kInvalid,
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
|
|
@ -188,6 +188,7 @@ GMPVideoDecoderParent::Reset()
|
|||
LOGD(("GMPVideoDecoderParent[%p]::ResetCompleteTimeout() timed out waiting for ResetComplete", self.get()));
|
||||
self->mResetCompleteTimeout = nullptr;
|
||||
LogToBrowserConsole(NS_LITERAL_STRING("GMPVideoDecoderParent timed out waiting for ResetComplete()"));
|
||||
self->mPlugin->CrashPluginNow(kGmpApiTimeout);
|
||||
});
|
||||
CancelResetCompleteTimeout();
|
||||
mResetCompleteTimeout = SimpleTimer::Create(task, 5000, mPlugin->GMPThread());
|
||||
|
|
|
@ -9,6 +9,7 @@ include protocol PGMPTimer;
|
|||
include protocol PGMPStorage;
|
||||
|
||||
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
|
||||
using mozilla::GMPCrashReason from "GMPUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
@ -33,7 +34,7 @@ parent:
|
|||
|
||||
child:
|
||||
async BeginAsyncShutdown();
|
||||
async CrashPluginNow();
|
||||
async CrashPluginNow(GMPCrashReason aReason);
|
||||
intr StartPlugin();
|
||||
async SetNodeId(nsCString nodeId);
|
||||
async CloseActive();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
include protocol PGMP;
|
||||
|
||||
using base::ProcessId from "base/process.h";
|
||||
using mozilla::GMPCrashReason from "GMPUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
@ -23,6 +24,8 @@ parent:
|
|||
returns (nsCString id);
|
||||
|
||||
async UpdateGMPTrialCreateState(nsString keySystem, uint32_t status);
|
||||
|
||||
async CrashPluginNow(uint32_t pluginId, GMPCrashReason aReason);
|
||||
};
|
||||
|
||||
} // namespace gmp
|
||||
|
|
|
@ -231,28 +231,6 @@ MediaSourceDecoder::GetMozDebugReaderData(nsAString& aString)
|
|||
mDemuxer->GetMozDebugReaderData(aString);
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
nsresult
|
||||
MediaSourceDecoder::SetCDMProxy(CDMProxy* aProxy)
|
||||
{
|
||||
nsresult rv = MediaDecoder::SetCDMProxy(aProxy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (aProxy) {
|
||||
// The sub readers can't decrypt EME content until they have a CDMProxy,
|
||||
// and the CDMProxy knows the capabilities of the CDM. The MediaSourceReader
|
||||
// remains in "waiting for resources" state until then. We need to kick the
|
||||
// reader out of waiting if the CDM gets added with known capabilities.
|
||||
CDMCaps::AutoLock caps(aProxy->Capabilites());
|
||||
if (!caps.AreCapsKnown()) {
|
||||
nsCOMPtr<nsIRunnable> task(
|
||||
NS_NewRunnableMethod(this, &MediaDecoder::NotifyWaitingForResourcesStatusChanged));
|
||||
caps.CallOnMainThreadWhenCapsAvailable(task);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
double
|
||||
MediaSourceDecoder::GetDuration()
|
||||
{
|
||||
|
|
|
@ -66,10 +66,6 @@ public:
|
|||
void SetMediaSourceDuration(double aDuration, MSRangeRemovalAction aAction);
|
||||
double GetMediaSourceDuration();
|
||||
|
||||
#ifdef MOZ_EME
|
||||
virtual nsresult SetCDMProxy(CDMProxy* aProxy) override;
|
||||
#endif
|
||||
|
||||
MediaSourceDemuxer* GetDemuxer()
|
||||
{
|
||||
return mDemuxer;
|
||||
|
|
|
@ -69,9 +69,8 @@ public:
|
|||
virtual void RecvTimelineEvent(uint32_t aIndex,
|
||||
dom::AudioTimelineEvent& aEvent) override
|
||||
{
|
||||
MOZ_ASSERT(mSource && mDestination);
|
||||
MOZ_ASSERT(mDestination);
|
||||
WebAudioUtils::ConvertAudioTimelineEventToTicks(aEvent,
|
||||
mSource,
|
||||
mDestination);
|
||||
|
||||
switch (aIndex) {
|
||||
|
@ -98,8 +97,7 @@ public:
|
|||
switch (aIndex) {
|
||||
case AudioBufferSourceNode::START:
|
||||
MOZ_ASSERT(!mStart, "Another START?");
|
||||
mStart =
|
||||
mSource->FractionalTicksFromDestinationTime(mDestination, aParam);
|
||||
mStart = mDestination->SecondsToNearestStreamTime(aParam);
|
||||
// Round to nearest
|
||||
mBeginProcessing = mStart + 0.5;
|
||||
break;
|
||||
|
@ -471,7 +469,7 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
StreamTime streamPosition = aStream->GraphTimeToStreamTime(aFrom);
|
||||
StreamTime streamPosition = mDestination->GraphTimeToStreamTime(aFrom);
|
||||
// We've finished if we've gone past mStop, or if we're past mDuration when
|
||||
// looping is disabled.
|
||||
if (streamPosition >= mStop ||
|
||||
|
@ -670,7 +668,7 @@ AudioBufferSourceNode::Start(double aWhen, double aOffset,
|
|||
|
||||
// Don't set parameter unnecessarily
|
||||
if (aWhen > 0.0) {
|
||||
ns->SetDoubleParameter(START, mContext->DOMTimeToStreamTime(aWhen));
|
||||
ns->SetDoubleParameter(START, aWhen);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -304,16 +304,6 @@ public:
|
|||
void RegisterNode(AudioNode* aNode);
|
||||
void UnregisterNode(AudioNode* aNode);
|
||||
|
||||
double DOMTimeToStreamTime(double aTime) const
|
||||
{
|
||||
return aTime;
|
||||
}
|
||||
|
||||
double StreamTimeToDOMTime(double aTime) const
|
||||
{
|
||||
return aTime;
|
||||
}
|
||||
|
||||
void OnStateChanged(void* aPromise, AudioContextState aNewState);
|
||||
|
||||
BasicWaveFormCache* GetBasicWaveFormCache();
|
||||
|
|
|
@ -324,7 +324,8 @@ public:
|
|||
* ProcessBlock() will be called later, and it then should not change
|
||||
* aOutput. This is used only for DelayNodeEngine in a feedback loop.
|
||||
*/
|
||||
virtual void ProduceBlockBeforeInput(GraphTime aFrom,
|
||||
virtual void ProduceBlockBeforeInput(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
AudioBlock* aOutput)
|
||||
{
|
||||
NS_NOTREACHED("ProduceBlockBeforeInput called on wrong engine\n");
|
||||
|
|
|
@ -148,15 +148,15 @@ AudioNodeStream::SetStreamTimeParameter(uint32_t aIndex, AudioContext* aContext,
|
|||
};
|
||||
|
||||
GraphImpl()->AppendMessage(new Message(this, aIndex,
|
||||
aContext->DestinationStream(),
|
||||
aContext->DOMTimeToStreamTime(aStreamTime)));
|
||||
aContext->DestinationStream(),
|
||||
aStreamTime));
|
||||
}
|
||||
|
||||
void
|
||||
AudioNodeStream::SetStreamTimeParameterImpl(uint32_t aIndex, MediaStream* aRelativeToStream,
|
||||
double aStreamTime)
|
||||
{
|
||||
StreamTime ticks = TicksFromDestinationTime(aRelativeToStream, aStreamTime);
|
||||
StreamTime ticks = aRelativeToStream->SecondsToNearestStreamTime(aStreamTime);
|
||||
mEngine->SetStreamTimeParameter(aIndex, ticks);
|
||||
}
|
||||
|
||||
|
@ -617,7 +617,7 @@ AudioNodeStream::ProduceOutputBeforeInput(GraphTime aFrom)
|
|||
if (!mIsActive) {
|
||||
mLastChunks[0].SetNull(WEBAUDIO_BLOCK_SIZE);
|
||||
} else {
|
||||
mEngine->ProduceBlockBeforeInput(aFrom, &mLastChunks[0]);
|
||||
mEngine->ProduceBlockBeforeInput(this, aFrom, &mLastChunks[0]);
|
||||
NS_ASSERTION(mLastChunks[0].GetDuration() == WEBAUDIO_BLOCK_SIZE,
|
||||
"Invalid WebAudio chunk size");
|
||||
if (mDisabledTrackIDs.Contains(static_cast<TrackID>(AUDIO_TRACK))) {
|
||||
|
@ -666,50 +666,6 @@ AudioNodeStream::FinishOutput()
|
|||
}
|
||||
}
|
||||
|
||||
double
|
||||
AudioNodeStream::FractionalTicksFromDestinationTime(AudioNodeStream* aDestination,
|
||||
double aSeconds)
|
||||
{
|
||||
MOZ_ASSERT(aDestination->SampleRate() == SampleRate());
|
||||
MOZ_ASSERT(SampleRate() == GraphRate());
|
||||
|
||||
double destinationSeconds = std::max(0.0, aSeconds);
|
||||
double destinationFractionalTicks = destinationSeconds * SampleRate();
|
||||
MOZ_ASSERT(destinationFractionalTicks < STREAM_TIME_MAX);
|
||||
StreamTime destinationStreamTime = destinationFractionalTicks; // round down
|
||||
// MediaTime does not have the resolution of double
|
||||
double offset = destinationFractionalTicks - destinationStreamTime;
|
||||
|
||||
GraphTime graphTime =
|
||||
aDestination->StreamTimeToGraphTime(destinationStreamTime);
|
||||
StreamTime thisStreamTime = GraphTimeToStreamTime(graphTime);
|
||||
double thisFractionalTicks = thisStreamTime + offset;
|
||||
return thisFractionalTicks;
|
||||
}
|
||||
|
||||
StreamTime
|
||||
AudioNodeStream::TicksFromDestinationTime(MediaStream* aDestination,
|
||||
double aSeconds)
|
||||
{
|
||||
AudioNodeStream* destination = aDestination->AsAudioNodeStream();
|
||||
MOZ_ASSERT(destination);
|
||||
|
||||
double thisSeconds =
|
||||
FractionalTicksFromDestinationTime(destination, aSeconds);
|
||||
return NS_round(thisSeconds);
|
||||
}
|
||||
|
||||
double
|
||||
AudioNodeStream::DestinationTimeFromTicks(AudioNodeStream* aDestination,
|
||||
StreamTime aPosition)
|
||||
{
|
||||
MOZ_ASSERT(SampleRate() == aDestination->SampleRate());
|
||||
|
||||
GraphTime graphTime = StreamTimeToGraphTime(aPosition);
|
||||
StreamTime destinationTime = aDestination->GraphTimeToStreamTime(graphTime);
|
||||
return StreamTimeToSeconds(destinationTime);
|
||||
}
|
||||
|
||||
void
|
||||
AudioNodeStream::AddInput(MediaInputPort* aPort)
|
||||
{
|
||||
|
|
|
@ -150,25 +150,6 @@ public:
|
|||
AudioNodeEngine* Engine() { return mEngine; }
|
||||
TrackRate SampleRate() const { return mSampleRate; }
|
||||
|
||||
/**
|
||||
* Convert a time in seconds on the destination stream to ticks
|
||||
* on this stream, including fractional position between ticks.
|
||||
*/
|
||||
double FractionalTicksFromDestinationTime(AudioNodeStream* aDestination,
|
||||
double aSeconds);
|
||||
/**
|
||||
* Convert a time in seconds on the destination stream to StreamTime
|
||||
* on this stream.
|
||||
*/
|
||||
StreamTime TicksFromDestinationTime(MediaStream* aDestination,
|
||||
double aSeconds);
|
||||
/**
|
||||
* Get the destination stream time in seconds corresponding to a position on
|
||||
* this stream.
|
||||
*/
|
||||
double DestinationTimeFromTicks(AudioNodeStream* aDestination,
|
||||
StreamTime aPosition);
|
||||
|
||||
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
|
|
|
@ -42,11 +42,6 @@ public:
|
|||
return mNode->Context();
|
||||
}
|
||||
|
||||
double DOMTimeToStreamTime(double aTime) const
|
||||
{
|
||||
return mNode->Context()->DOMTimeToStreamTime(aTime);
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// We override SetValueCurveAtTime to convert the Float32Array to the wrapper
|
||||
|
@ -129,13 +124,10 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
double streamTime = DOMTimeToStreamTime(aStartTime);
|
||||
|
||||
// Remove some events on the main thread copy.
|
||||
AudioEventTimeline::CancelScheduledValues(streamTime);
|
||||
AudioEventTimeline::CancelScheduledValues(aStartTime);
|
||||
|
||||
AudioTimelineEvent event(AudioTimelineEvent::Cancel,
|
||||
streamTime, 0.0f);
|
||||
AudioTimelineEvent event(AudioTimelineEvent::Cancel, aStartTime, 0.0f);
|
||||
|
||||
mCallback(mNode, event);
|
||||
}
|
||||
|
@ -214,8 +206,7 @@ private:
|
|||
const float* aCurve = nullptr,
|
||||
uint32_t aCurveLength = 0)
|
||||
{
|
||||
AudioTimelineEvent event(aType,
|
||||
DOMTimeToStreamTime(aTime), aValue,
|
||||
AudioTimelineEvent event(aType, aTime, aValue,
|
||||
aTimeConstant, aDuration, aCurve, aCurveLength);
|
||||
|
||||
if (!ValidateEvent(event, aRv)) {
|
||||
|
|
|
@ -78,7 +78,6 @@ class BiquadFilterNodeEngine final : public AudioNodeEngine
|
|||
public:
|
||||
BiquadFilterNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination)
|
||||
: AudioNodeEngine(aNode)
|
||||
, mSource(nullptr)
|
||||
, mDestination(aDestination->Stream())
|
||||
// Keep the default values in sync with the default values in
|
||||
// BiquadFilterNode::BiquadFilterNode
|
||||
|
@ -90,11 +89,6 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
void SetSourceStream(AudioNodeStream* aSource)
|
||||
{
|
||||
mSource = aSource;
|
||||
}
|
||||
|
||||
enum Parameteres {
|
||||
TYPE,
|
||||
FREQUENCY,
|
||||
|
@ -113,10 +107,9 @@ public:
|
|||
void RecvTimelineEvent(uint32_t aIndex,
|
||||
AudioTimelineEvent& aEvent) override
|
||||
{
|
||||
MOZ_ASSERT(mSource && mDestination);
|
||||
MOZ_ASSERT(mDestination);
|
||||
|
||||
WebAudioUtils::ConvertAudioTimelineEventToTicks(aEvent,
|
||||
mSource,
|
||||
mDestination);
|
||||
|
||||
switch (aIndex) {
|
||||
|
@ -187,7 +180,7 @@ public:
|
|||
uint32_t numberOfChannels = mBiquads.Length();
|
||||
aOutput->AllocateChannels(numberOfChannels);
|
||||
|
||||
StreamTime pos = aStream->GraphTimeToStreamTime(aFrom);
|
||||
StreamTime pos = mDestination->GraphTimeToStreamTime(aFrom);
|
||||
|
||||
double freq = mFrequency.GetValueAtTime(pos);
|
||||
double q = mQ.GetValueAtTime(pos);
|
||||
|
@ -221,7 +214,6 @@ public:
|
|||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
|
||||
{
|
||||
// Not owned:
|
||||
// - mSource - probably not owned
|
||||
// - mDestination - probably not owned
|
||||
// - AudioParamTimelines - counted in the AudioNode
|
||||
size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
@ -235,7 +227,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
AudioNodeStream* mSource;
|
||||
AudioNodeStream* mDestination;
|
||||
BiquadFilterType mType;
|
||||
AudioParamTimeline mFrequency;
|
||||
|
@ -259,7 +250,6 @@ BiquadFilterNode::BiquadFilterNode(AudioContext* aContext)
|
|||
BiquadFilterNodeEngine* engine = new BiquadFilterNodeEngine(this, aContext->Destination());
|
||||
mStream = AudioNodeStream::Create(aContext, engine,
|
||||
AudioNodeStream::NO_STREAM_FLAGS);
|
||||
engine->SetSourceStream(mStream);
|
||||
}
|
||||
|
||||
BiquadFilterNode::~BiquadFilterNode()
|
||||
|
|
|
@ -32,7 +32,6 @@ public:
|
|||
DelayNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination,
|
||||
double aMaxDelayTicks)
|
||||
: AudioNodeEngine(aNode)
|
||||
, mSource(nullptr)
|
||||
, mDestination(aDestination->Stream())
|
||||
// Keep the default value in sync with the default value in DelayNode::DelayNode.
|
||||
, mDelay(0.f)
|
||||
|
@ -52,20 +51,14 @@ public:
|
|||
return this;
|
||||
}
|
||||
|
||||
void SetSourceStream(AudioNodeStream* aSource)
|
||||
{
|
||||
mSource = aSource;
|
||||
}
|
||||
|
||||
enum Parameters {
|
||||
DELAY,
|
||||
};
|
||||
void RecvTimelineEvent(uint32_t aIndex,
|
||||
AudioTimelineEvent& aEvent) override
|
||||
{
|
||||
MOZ_ASSERT(mSource && mDestination);
|
||||
MOZ_ASSERT(mDestination);
|
||||
WebAudioUtils::ConvertAudioTimelineEventToTicks(aEvent,
|
||||
mSource,
|
||||
mDestination);
|
||||
|
||||
switch (aIndex) {
|
||||
|
@ -83,7 +76,6 @@ public:
|
|||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
{
|
||||
MOZ_ASSERT(mSource == aStream, "Invalid source stream");
|
||||
MOZ_ASSERT(aStream->SampleRate() == mDestination->SampleRate());
|
||||
|
||||
if (!aInput.IsSilentOrSubnormal()) {
|
||||
|
@ -118,18 +110,19 @@ public:
|
|||
// Skip output update if mLastChunks has already been set by
|
||||
// ProduceBlockBeforeInput() when in a cycle.
|
||||
if (!mHaveProducedBeforeInput) {
|
||||
UpdateOutputBlock(aFrom, aOutput, 0.0);
|
||||
UpdateOutputBlock(aStream, aFrom, aOutput, 0.0);
|
||||
}
|
||||
mHaveProducedBeforeInput = false;
|
||||
mBuffer.NextBlock();
|
||||
}
|
||||
|
||||
void UpdateOutputBlock(GraphTime aFrom, AudioBlock* aOutput, double minDelay)
|
||||
void UpdateOutputBlock(AudioNodeStream* aStream, GraphTime aFrom,
|
||||
AudioBlock* aOutput, double minDelay)
|
||||
{
|
||||
double maxDelay = mMaxDelay;
|
||||
double sampleRate = mSource->SampleRate();
|
||||
double sampleRate = aStream->SampleRate();
|
||||
ChannelInterpretation channelInterpretation =
|
||||
mSource->GetChannelInterpretation();
|
||||
aStream->GetChannelInterpretation();
|
||||
if (mDelay.HasSimpleValue()) {
|
||||
// If this DelayNode is in a cycle, make sure the delay value is at least
|
||||
// one block, even if that is greater than maxDelay.
|
||||
|
@ -141,7 +134,7 @@ public:
|
|||
// Compute the delay values for the duration of the input AudioChunk
|
||||
// If this DelayNode is in a cycle, make sure the delay value is at least
|
||||
// one block.
|
||||
StreamTime tick = mSource->GraphTimeToStreamTime(aFrom);
|
||||
StreamTime tick = mDestination->GraphTimeToStreamTime(aFrom);
|
||||
float values[WEBAUDIO_BLOCK_SIZE];
|
||||
mDelay.GetValuesAtTime(tick, values,WEBAUDIO_BLOCK_SIZE);
|
||||
|
||||
|
@ -156,13 +149,14 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void ProduceBlockBeforeInput(GraphTime aFrom,
|
||||
virtual void ProduceBlockBeforeInput(AudioNodeStream* aStream,
|
||||
GraphTime aFrom,
|
||||
AudioBlock* aOutput) override
|
||||
{
|
||||
if (mLeftOverData <= 0) {
|
||||
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
|
||||
} else {
|
||||
UpdateOutputBlock(aFrom, aOutput, WEBAUDIO_BLOCK_SIZE);
|
||||
UpdateOutputBlock(aStream, aFrom, aOutput, WEBAUDIO_BLOCK_SIZE);
|
||||
}
|
||||
mHaveProducedBeforeInput = true;
|
||||
}
|
||||
|
@ -176,7 +170,6 @@ public:
|
|||
{
|
||||
size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
|
||||
// Not owned:
|
||||
// - mSource - probably not owned
|
||||
// - mDestination - probably not owned
|
||||
// - mDelay - shares ref with AudioNode, don't count
|
||||
amount += mBuffer.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
@ -188,7 +181,6 @@ public:
|
|||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
AudioNodeStream* mSource;
|
||||
AudioNodeStream* mDestination;
|
||||
AudioParamTimeline mDelay;
|
||||
DelayBuffer mBuffer;
|
||||
|
@ -211,7 +203,6 @@ DelayNode::DelayNode(AudioContext* aContext, double aMaxDelay)
|
|||
aContext->SampleRate() * aMaxDelay);
|
||||
mStream = AudioNodeStream::Create(aContext, engine,
|
||||
AudioNodeStream::NO_STREAM_FLAGS);
|
||||
engine->SetSourceStream(mStream);
|
||||
}
|
||||
|
||||
DelayNode::~DelayNode()
|
||||
|
|
|
@ -36,7 +36,6 @@ public:
|
|||
explicit DynamicsCompressorNodeEngine(AudioNode* aNode,
|
||||
AudioDestinationNode* aDestination)
|
||||
: AudioNodeEngine(aNode)
|
||||
, mSource(nullptr)
|
||||
, mDestination(aDestination->Stream())
|
||||
// Keep the default value in sync with the default value in
|
||||
// DynamicsCompressorNode::DynamicsCompressorNode.
|
||||
|
@ -49,11 +48,6 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
void SetSourceStream(AudioNodeStream* aSource)
|
||||
{
|
||||
mSource = aSource;
|
||||
}
|
||||
|
||||
enum Parameters {
|
||||
THRESHOLD,
|
||||
KNEE,
|
||||
|
@ -64,10 +58,9 @@ public:
|
|||
void RecvTimelineEvent(uint32_t aIndex,
|
||||
AudioTimelineEvent& aEvent) override
|
||||
{
|
||||
MOZ_ASSERT(mSource && mDestination);
|
||||
MOZ_ASSERT(mDestination);
|
||||
|
||||
WebAudioUtils::ConvertAudioTimelineEventToTicks(aEvent,
|
||||
mSource,
|
||||
mDestination);
|
||||
|
||||
switch (aIndex) {
|
||||
|
@ -110,7 +103,7 @@ public:
|
|||
aInput.ChannelCount());
|
||||
}
|
||||
|
||||
StreamTime pos = aStream->GraphTimeToStreamTime(aFrom);
|
||||
StreamTime pos = mDestination->GraphTimeToStreamTime(aFrom);
|
||||
mCompressor->setParameterValue(DynamicsCompressor::ParamThreshold,
|
||||
mThreshold.GetValueAtTime(pos));
|
||||
mCompressor->setParameterValue(DynamicsCompressor::ParamKnee,
|
||||
|
@ -132,7 +125,6 @@ public:
|
|||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
|
||||
{
|
||||
// Not owned:
|
||||
// - mSource (probably)
|
||||
// - mDestination (probably)
|
||||
// - Don't count the AudioParamTimelines, their inner refs are owned by the
|
||||
// AudioNode.
|
||||
|
@ -180,7 +172,6 @@ private:
|
|||
}
|
||||
|
||||
private:
|
||||
AudioNodeStream* mSource;
|
||||
AudioNodeStream* mDestination;
|
||||
AudioParamTimeline mThreshold;
|
||||
AudioParamTimeline mKnee;
|
||||
|
@ -205,7 +196,6 @@ DynamicsCompressorNode::DynamicsCompressorNode(AudioContext* aContext)
|
|||
DynamicsCompressorNodeEngine* engine = new DynamicsCompressorNodeEngine(this, aContext->Destination());
|
||||
mStream = AudioNodeStream::Create(aContext, engine,
|
||||
AudioNodeStream::NO_STREAM_FLAGS);
|
||||
engine->SetSourceStream(mStream);
|
||||
}
|
||||
|
||||
DynamicsCompressorNode::~DynamicsCompressorNode()
|
||||
|
|
|
@ -28,27 +28,20 @@ class GainNodeEngine final : public AudioNodeEngine
|
|||
public:
|
||||
GainNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination)
|
||||
: AudioNodeEngine(aNode)
|
||||
, mSource(nullptr)
|
||||
, mDestination(aDestination->Stream())
|
||||
// Keep the default value in sync with the default value in GainNode::GainNode.
|
||||
, mGain(1.f)
|
||||
{
|
||||
}
|
||||
|
||||
void SetSourceStream(AudioNodeStream* aSource)
|
||||
{
|
||||
mSource = aSource;
|
||||
}
|
||||
|
||||
enum Parameters {
|
||||
GAIN
|
||||
};
|
||||
void RecvTimelineEvent(uint32_t aIndex,
|
||||
AudioTimelineEvent& aEvent) override
|
||||
{
|
||||
MOZ_ASSERT(mSource && mDestination);
|
||||
MOZ_ASSERT(mDestination);
|
||||
WebAudioUtils::ConvertAudioTimelineEventToTicks(aEvent,
|
||||
mSource,
|
||||
mDestination);
|
||||
|
||||
switch (aIndex) {
|
||||
|
@ -66,8 +59,6 @@ public:
|
|||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
{
|
||||
MOZ_ASSERT(mSource == aStream, "Invalid source stream");
|
||||
|
||||
if (aInput.IsNull()) {
|
||||
// If input is silent, so is the output
|
||||
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
|
||||
|
@ -87,7 +78,7 @@ public:
|
|||
aOutput->AllocateChannels(aInput.ChannelCount());
|
||||
|
||||
// Compute the gain values for the duration of the input AudioChunk
|
||||
StreamTime tick = aStream->GraphTimeToStreamTime(aFrom);
|
||||
StreamTime tick = mDestination->GraphTimeToStreamTime(aFrom);
|
||||
float computedGain[WEBAUDIO_BLOCK_SIZE];
|
||||
mGain.GetValuesAtTime(tick, computedGain, WEBAUDIO_BLOCK_SIZE);
|
||||
|
||||
|
@ -107,7 +98,6 @@ public:
|
|||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
|
||||
{
|
||||
// Not owned:
|
||||
// - mSource (probably)
|
||||
// - mDestination (probably)
|
||||
// - mGain - Internal ref owned by AudioNode
|
||||
return AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
@ -118,7 +108,6 @@ public:
|
|||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
AudioNodeStream* mSource;
|
||||
AudioNodeStream* mDestination;
|
||||
AudioParamTimeline mGain;
|
||||
};
|
||||
|
@ -133,7 +122,6 @@ GainNode::GainNode(AudioContext* aContext)
|
|||
GainNodeEngine* engine = new GainNodeEngine(this, aContext->Destination());
|
||||
mStream = AudioNodeStream::Create(aContext, engine,
|
||||
AudioNodeStream::NO_STREAM_FLAGS);
|
||||
engine->SetSourceStream(mStream);
|
||||
}
|
||||
|
||||
GainNode::~GainNode()
|
||||
|
|
|
@ -62,10 +62,9 @@ public:
|
|||
{
|
||||
mRecomputeParameters = true;
|
||||
|
||||
MOZ_ASSERT(mSource && mDestination);
|
||||
MOZ_ASSERT(mDestination);
|
||||
|
||||
WebAudioUtils::ConvertAudioTimelineEventToTicks(aEvent,
|
||||
mSource,
|
||||
mDestination);
|
||||
|
||||
switch (aIndex) {
|
||||
|
@ -295,7 +294,7 @@ public:
|
|||
{
|
||||
MOZ_ASSERT(mSource == aStream, "Invalid source stream");
|
||||
|
||||
StreamTime ticks = aStream->GraphTimeToStreamTime(aFrom);
|
||||
StreamTime ticks = mDestination->GraphTimeToStreamTime(aFrom);
|
||||
if (mStart == -1) {
|
||||
ComputeSilence(aOutput);
|
||||
return;
|
||||
|
|
|
@ -245,20 +245,14 @@ public:
|
|||
uint32_t aBufferSize,
|
||||
uint32_t aNumberOfInputChannels)
|
||||
: AudioNodeEngine(aNode)
|
||||
, mSource(nullptr)
|
||||
, mDestination(aDestination->Stream())
|
||||
, mSharedBuffers(new SharedBuffers(mDestination->SampleRate()))
|
||||
, mBufferSize(aBufferSize)
|
||||
, mInputChannelCount(aNumberOfInputChannels)
|
||||
, mInputWriteIndex(0)
|
||||
{
|
||||
}
|
||||
|
||||
void SetSourceStream(AudioNodeStream* aSource)
|
||||
{
|
||||
mSource = aSource;
|
||||
mSharedBuffers = new SharedBuffers(mSource->SampleRate());
|
||||
}
|
||||
|
||||
SharedBuffers* GetSharedBuffers() const
|
||||
{
|
||||
return mSharedBuffers;
|
||||
|
@ -345,7 +339,6 @@ public:
|
|||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
|
||||
{
|
||||
// Not owned:
|
||||
// - mSource (probably)
|
||||
// - mDestination (probably)
|
||||
size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mSharedBuffers->SizeOfIncludingThis(aMallocSizeOf);
|
||||
|
@ -365,14 +358,13 @@ private:
|
|||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
// we now have a full input buffer ready to be sent to the main thread.
|
||||
StreamTime playbackTick = mSource->GraphTimeToStreamTime(aFrom);
|
||||
StreamTime playbackTick = mDestination->GraphTimeToStreamTime(aFrom);
|
||||
// Add the duration of the current sample
|
||||
playbackTick += WEBAUDIO_BLOCK_SIZE;
|
||||
// Add the delay caused by the main thread
|
||||
playbackTick += mSharedBuffers->DelaySoFar();
|
||||
// Compute the playback time in the coordinate system of the destination
|
||||
double playbackTime =
|
||||
mSource->DestinationTimeFromTicks(mDestination, playbackTick);
|
||||
double playbackTime = mDestination->StreamTimeToSeconds(playbackTick);
|
||||
|
||||
class Command final : public nsRunnable
|
||||
{
|
||||
|
@ -448,9 +440,7 @@ private:
|
|||
// them. Otherwise, we may be able to get away without creating them!
|
||||
nsRefPtr<AudioProcessingEvent> event =
|
||||
new AudioProcessingEvent(aNode, nullptr, nullptr);
|
||||
event->InitEvent(inputBuffer,
|
||||
inputChannelCount,
|
||||
context->StreamTimeToDOMTime(mPlaybackTime));
|
||||
event->InitEvent(inputBuffer, inputChannelCount, mPlaybackTime);
|
||||
aNode->DispatchTrustedEvent(event);
|
||||
|
||||
// Steal the output buffers if they have been set.
|
||||
|
@ -480,9 +470,8 @@ private:
|
|||
|
||||
friend class ScriptProcessorNode;
|
||||
|
||||
nsAutoPtr<SharedBuffers> mSharedBuffers;
|
||||
AudioNodeStream* mSource;
|
||||
AudioNodeStream* mDestination;
|
||||
nsAutoPtr<SharedBuffers> mSharedBuffers;
|
||||
nsRefPtr<ThreadSharedFloatArrayBufferList> mInputBuffer;
|
||||
const uint32_t mBufferSize;
|
||||
const uint32_t mInputChannelCount;
|
||||
|
@ -512,7 +501,6 @@ ScriptProcessorNode::ScriptProcessorNode(AudioContext* aContext,
|
|||
aNumberOfInputChannels);
|
||||
mStream = AudioNodeStream::Create(aContext, engine,
|
||||
AudioNodeStream::NO_STREAM_FLAGS);
|
||||
engine->SetSourceStream(mStream);
|
||||
}
|
||||
|
||||
ScriptProcessorNode::~ScriptProcessorNode()
|
||||
|
|
|
@ -33,7 +33,6 @@ public:
|
|||
StereoPannerNodeEngine(AudioNode* aNode,
|
||||
AudioDestinationNode* aDestination)
|
||||
: AudioNodeEngine(aNode)
|
||||
, mSource(nullptr)
|
||||
, mDestination(aDestination->Stream())
|
||||
// Keep the default value in sync with the default value in
|
||||
// StereoPannerNode::StereoPannerNode.
|
||||
|
@ -41,20 +40,14 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
void SetSourceStream(AudioNodeStream* aSource)
|
||||
{
|
||||
mSource = aSource;
|
||||
}
|
||||
|
||||
enum Parameters {
|
||||
PAN
|
||||
};
|
||||
void RecvTimelineEvent(uint32_t aIndex,
|
||||
AudioTimelineEvent& aEvent) override
|
||||
{
|
||||
MOZ_ASSERT(mSource && mDestination);
|
||||
MOZ_ASSERT(mDestination);
|
||||
WebAudioUtils::ConvertAudioTimelineEventToTicks(aEvent,
|
||||
mSource,
|
||||
mDestination);
|
||||
|
||||
switch (aIndex) {
|
||||
|
@ -116,8 +109,6 @@ public:
|
|||
AudioBlock* aOutput,
|
||||
bool *aFinished) override
|
||||
{
|
||||
MOZ_ASSERT(mSource == aStream, "Invalid source stream");
|
||||
|
||||
// The output of this node is always stereo, no matter what the inputs are.
|
||||
MOZ_ASSERT(aInput.ChannelCount() <= 2);
|
||||
aOutput->AllocateChannels(2);
|
||||
|
@ -149,7 +140,7 @@ public:
|
|||
bool onLeft[WEBAUDIO_BLOCK_SIZE];
|
||||
|
||||
float values[WEBAUDIO_BLOCK_SIZE];
|
||||
StreamTime tick = aStream->GraphTimeToStreamTime(aFrom);
|
||||
StreamTime tick = mDestination->GraphTimeToStreamTime(aFrom);
|
||||
mPan.GetValuesAtTime(tick, values, WEBAUDIO_BLOCK_SIZE);
|
||||
|
||||
for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
|
||||
|
@ -171,7 +162,6 @@ public:
|
|||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
AudioNodeStream* mSource;
|
||||
AudioNodeStream* mDestination;
|
||||
AudioParamTimeline mPan;
|
||||
};
|
||||
|
@ -186,7 +176,6 @@ StereoPannerNode::StereoPannerNode(AudioContext* aContext)
|
|||
StereoPannerNodeEngine* engine = new StereoPannerNodeEngine(this, aContext->Destination());
|
||||
mStream = AudioNodeStream::Create(aContext, engine,
|
||||
AudioNodeStream::NO_STREAM_FLAGS);
|
||||
engine->SetSourceStream(mStream);
|
||||
}
|
||||
|
||||
StereoPannerNode::~StereoPannerNode()
|
||||
|
|
|
@ -13,14 +13,12 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
|
||||
void WebAudioUtils::ConvertAudioTimelineEventToTicks(AudioTimelineEvent& aEvent,
|
||||
AudioNodeStream* aSource,
|
||||
AudioNodeStream* aDest)
|
||||
{
|
||||
MOZ_ASSERT(!aSource || aSource->SampleRate() == aDest->SampleRate());
|
||||
aEvent.SetTimeInTicks(
|
||||
aSource->TicksFromDestinationTime(aDest, aEvent.Time<double>()));
|
||||
aEvent.mTimeConstant *= aSource->SampleRate();
|
||||
aEvent.mDuration *= aSource->SampleRate();
|
||||
aDest->SecondsToNearestStreamTime(aEvent.Time<double>()));
|
||||
aEvent.mTimeConstant *= aDest->SampleRate();
|
||||
aEvent.mDuration *= aDest->SampleRate();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -64,7 +64,6 @@ namespace WebAudioUtils {
|
|||
* destination streams as well.
|
||||
*/
|
||||
void ConvertAudioTimelineEventToTicks(AudioTimelineEvent& aEvent,
|
||||
AudioNodeStream* aSource,
|
||||
AudioNodeStream* aDest);
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,31 +10,41 @@
|
|||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestFlakyTimeout("This test needs to wait until after the AudioContext's timer has started.");
|
||||
addLoadEvent(
|
||||
function() {
|
||||
const delay = 0.1;
|
||||
var context = new AudioContext();
|
||||
SimpleTest.executeSoon( // to ensure that AudioContext has started
|
||||
function() {
|
||||
setTimeout( // wait for |delay|
|
||||
function() {
|
||||
var sp = context.createScriptProcessor(256);
|
||||
sp.connect(context.destination);
|
||||
sp.onaudioprocess =
|
||||
function(e) {
|
||||
var minimum =
|
||||
(delay + e.inputBuffer.length/context.sampleRate) *
|
||||
(1.0 - 1.0/Math.pow(2.0,52.0)); // double precision
|
||||
ok(e.playbackTime >= minimum,
|
||||
"playbackTime " + e.playbackTime +
|
||||
" beyond expected minimum " + minimum);
|
||||
sp.onaudioprocess = null;
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}, 1000 * delay);
|
||||
});
|
||||
});
|
||||
|
||||
var context = new AudioContext();
|
||||
const delay = 0.1;
|
||||
|
||||
function doTest() {
|
||||
const processorBufferLength = 256;
|
||||
// |currentTime| may include double precision floating point
|
||||
// rounding errors, so round to nearest integer sample to ignore these.
|
||||
var minimumPlaybackSample =
|
||||
Math.round(context.currentTime * context.sampleRate) +
|
||||
processorBufferLength;
|
||||
var sp = context.createScriptProcessor(processorBufferLength);
|
||||
sp.connect(context.destination);
|
||||
sp.onaudioprocess =
|
||||
function(e) {
|
||||
is(e.inputBuffer.length, processorBufferLength,
|
||||
"expected buffer length");
|
||||
var playbackSample = Math.round(e.playbackTime * context.sampleRate)
|
||||
ok(playbackSample >= minimumPlaybackSample,
|
||||
"playbackSample " + playbackSample +
|
||||
" beyond expected minimum " + minimumPlaybackSample);
|
||||
sp.onaudioprocess = null;
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
|
||||
// Wait until AudioDestinationNode has accumulated enough 'extra' time so that
|
||||
// a failure would be easily detected.
|
||||
(function waitForExtraTime() {
|
||||
if (context.currentTime < delay) {
|
||||
SimpleTest.executeSoon(waitForExtraTime);
|
||||
} else {
|
||||
doTest();
|
||||
}
|
||||
})();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -27,6 +27,9 @@ function handleRequest(request, response)
|
|||
if (secData.allowOrigin)
|
||||
response.setHeader("Access-Control-Allow-Origin", secData.allowOrigin);
|
||||
|
||||
if (secData.withCred)
|
||||
response.setHeader("Access-Control-Allow-Credentials", "true");
|
||||
|
||||
if (isPreflight) {
|
||||
if (secData.allowHeaders)
|
||||
response.setHeader("Access-Control-Allow-Headers", secData.allowHeaders);
|
||||
|
|
|
@ -417,6 +417,86 @@ function runTest() {
|
|||
{ pass: 0,
|
||||
method: "DELETE"
|
||||
},
|
||||
{ newTest: "*******" },
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
withCred: true,
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
cacheTime: 3600
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
withCred: true,
|
||||
headers: { "x-my-header": "myValue" },
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
},
|
||||
{ newTest: "*******" },
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
withCred: true,
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
cacheTime: 3600
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "y-my-header": "myValue" },
|
||||
allowHeaders: "y-my-header",
|
||||
cacheTime: 2
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "y-my-header": "myValue" },
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
withCred: true,
|
||||
headers: { "x-my-header": "myValue" },
|
||||
},
|
||||
{ pause: 2.1 },
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
withCred: true,
|
||||
headers: { "x-my-header": "myValue" },
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "y-my-header": "myValue" },
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
withCred: true,
|
||||
headers: { "y-my-header": "myValue" },
|
||||
},
|
||||
{ newTest: "*******" },
|
||||
{ pass: 1,
|
||||
method: "DELETE",
|
||||
allowMethods: "DELETE",
|
||||
cacheTime: 3600
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "DELETE": "myvalue" },
|
||||
},
|
||||
{ newTest: "*******" },
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
cacheTime: 3600
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "3600",
|
||||
headers: { "x-my-header": "myvalue" },
|
||||
},
|
||||
];
|
||||
|
||||
for (let i = 0; i < 110; i++) {
|
||||
|
@ -448,12 +528,14 @@ function runTest() {
|
|||
url: baseURL + "c=" + unique,
|
||||
method: test.method,
|
||||
headers: test.headers,
|
||||
withCred: test.withCred,
|
||||
};
|
||||
|
||||
sec = { allowOrigin: test.noOrigin ? "" : origin,
|
||||
allowHeaders: test.allowHeaders,
|
||||
allowMethods: test.allowMethods,
|
||||
cacheTime: test.cacheTime };
|
||||
cacheTime: test.cacheTime,
|
||||
withCred: test.withCred };
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", setStateURL + escape(sec.toSource()), true);
|
||||
xhr.onloadend = function() { gen.next(); }
|
||||
|
|
|
@ -6,3 +6,4 @@ skip-if = buildapp == 'b2g' || os == 'android'
|
|||
[test_offsets.js]
|
||||
[test_offsets.xul]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_spacetopagedown.html]
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Components.utils.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
var windowUtils = SpecialPowers.getDOMWindowUtils(window);
|
||||
|
||||
function pressKey(isShift)
|
||||
{
|
||||
return new Promise(resolve => {
|
||||
synthesizeKey(" ", { shiftKey: isShift });
|
||||
windowUtils.advanceTimeAndRefresh(100);
|
||||
SimpleTest.executeSoon(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function initTest()
|
||||
{
|
||||
SpecialPowers.pushPrefEnv({"set":[["general.smoothScroll", false]]}, runTest);
|
||||
}
|
||||
|
||||
function runTest()
|
||||
{
|
||||
Task.async(function () {
|
||||
yield pressKey(false);
|
||||
|
||||
ok(window.scrollY > 0, "Space with no focus" + window.scrollY);
|
||||
yield pressKey(true);
|
||||
is(window.scrollY, 0, "Shift+Space with no focus");
|
||||
|
||||
let checkbox = document.getElementById("checkbox");
|
||||
checkbox.focus();
|
||||
yield pressKey(false);
|
||||
|
||||
is(window.scrollY, 0, "Space with checkbox focused");
|
||||
ok(checkbox.checked, "Space with checkbox focused, checked");
|
||||
yield pressKey(true);
|
||||
is(window.scrollY, 0, "Shift+Space with checkbox focused");
|
||||
ok(!checkbox.checked, "Space with checkbox focused, unchecked");
|
||||
|
||||
let input = document.getElementById("input");
|
||||
input.focus();
|
||||
yield pressKey(false);
|
||||
is(window.scrollY, 0, "Space with input focused");
|
||||
is(input.value, " ", "Space with input focused, value");
|
||||
yield pressKey(true);
|
||||
is(window.scrollY, 0, "Shift+Space with input focused");
|
||||
is(input.value, " ", "Space with input focused, value");
|
||||
|
||||
windowUtils.restoreNormalRefresh();
|
||||
SimpleTest.finish();
|
||||
})();
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="SimpleTest.waitForFocus(initTest)">
|
||||
|
||||
<input id="checkbox" type="checkbox">Checkbox
|
||||
<input id="input">
|
||||
<p style="height: 4000px">Text</p>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -459,6 +459,10 @@ nsXBLPrototypeHandler::DispatchXBLCommand(EventTarget* aTarget, nsIDOMEvent* aEv
|
|||
else
|
||||
controller = GetController(aTarget); // We're attached to the receiver possibly.
|
||||
|
||||
// We are the default action for this command.
|
||||
// Stop any other default action from executing.
|
||||
aEvent->PreventDefault();
|
||||
|
||||
if (mEventName == nsGkAtoms::keypress &&
|
||||
mDetail == nsIDOMKeyEvent::DOM_VK_SPACE &&
|
||||
mMisc == 1) {
|
||||
|
@ -491,10 +495,6 @@ nsXBLPrototypeHandler::DispatchXBLCommand(EventTarget* aTarget, nsIDOMEvent* aEv
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We are the default action for this command.
|
||||
// Stop any other default action from executing.
|
||||
aEvent->PreventDefault();
|
||||
|
||||
if (controller)
|
||||
controller->DoCommand(command.get());
|
||||
|
|
|
@ -2555,25 +2555,12 @@ XULDocument::LoadOverlayInternal(nsIURI* aURI, bool aIsDynamic,
|
|||
if (aIsDynamic)
|
||||
mResolutionPhase = nsForwardReference::eStart;
|
||||
|
||||
// Chrome documents are allowed to load overlays from anywhere.
|
||||
// In all other cases, the overlay is only allowed to load if
|
||||
// the master document and prototype document have the same origin.
|
||||
|
||||
bool documentIsChrome = IsChromeURI(mDocumentURI);
|
||||
if (!documentIsChrome) {
|
||||
// Make sure we're allowed to load this overlay.
|
||||
rv = NodePrincipal()->CheckMayLoad(aURI, true, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
*aFailureFromContent = true;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Look in the prototype cache for the prototype document with
|
||||
// the specified overlay URI. Only use the cache if the containing
|
||||
// document is chrome otherwise it may not have a system principal and
|
||||
// the cached document will, see bug 565610.
|
||||
bool overlayIsChrome = IsChromeURI(aURI);
|
||||
bool documentIsChrome = IsChromeURI(mDocumentURI);
|
||||
mCurrentPrototype = overlayIsChrome && documentIsChrome ?
|
||||
nsXULPrototypeCache::GetInstance()->GetPrototype(aURI) : nullptr;
|
||||
|
||||
|
@ -2657,12 +2644,13 @@ XULDocument::LoadOverlayInternal(nsIURI* aURI, bool aIsDynamic,
|
|||
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
aURI,
|
||||
NodePrincipal(),
|
||||
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS |
|
||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
group);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = channel->AsyncOpen(listener, nullptr);
|
||||
rv = channel->AsyncOpen2(listener);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
# 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/.
|
||||
|
||||
DIRS += CONFIG['MOZ_EXTENSIONS'].split()
|
||||
DIRS += CONFIG['MOZ_EXTENSIONS']
|
||||
|
|
|
@ -27,8 +27,12 @@ public:
|
|||
virtual IntSize GetSize() const { return mA->GetSize(); }
|
||||
virtual SurfaceFormat GetFormat() const { return mA->GetFormat(); }
|
||||
|
||||
/* Readback from this surface type is not supported! */
|
||||
virtual already_AddRefed<DataSourceSurface> GetDataSurface() { return nullptr; }
|
||||
// This is implemented for debugging purposes only (used by dumping
|
||||
// client-side textures for paint dumps), for which we don't care about
|
||||
// component alpha, so we just use the first of the two surfaces.
|
||||
virtual already_AddRefed<DataSourceSurface> GetDataSurface() {
|
||||
return mA->GetDataSurface();
|
||||
}
|
||||
private:
|
||||
friend class DualSurface;
|
||||
friend class DualPattern;
|
||||
|
|
|
@ -16,17 +16,22 @@ Autodesk, Inc.
|
|||
BlackBerry Limited
|
||||
Cable Television Laboratories, Inc.
|
||||
Cloud Party, Inc.
|
||||
Imagination Technologies Ltd.
|
||||
Intel Corporation
|
||||
Mozilla Corporation
|
||||
Turbulenz
|
||||
Klarälvdalens Datakonsult AB
|
||||
Microsoft Corporation
|
||||
Microsoft Open Technologies, Inc.
|
||||
NVIDIA Corporation
|
||||
Opera Software ASA
|
||||
The Qt Company Ltd.
|
||||
|
||||
Jacek Caban
|
||||
Mark Callow
|
||||
Ginn Chen
|
||||
Tibor den Ouden
|
||||
Régis Fénéon
|
||||
James Hauxwell
|
||||
Sam Hocevar
|
||||
Pierre Leveille
|
||||
|
@ -35,3 +40,4 @@ Boying Lu
|
|||
Aitor Moreno
|
||||
Yuri O'Donnell
|
||||
Josh Soref
|
||||
Maks Naumov
|
||||
|
|
|
@ -2,26 +2,20 @@
|
|||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
if (is_win) {
|
||||
# Only needed on Windows.
|
||||
gles_gypi = exec_script(
|
||||
"//build/gypi_to_gn.py",
|
||||
[ rebase_path("src/libGLESv2.gypi") ],
|
||||
"scope",
|
||||
[ "src/libGLESv2.gypi" ])
|
||||
# import the use_x11 variable
|
||||
import("//build/config/ui.gni")
|
||||
|
||||
egl_gypi = exec_script(
|
||||
"//build/gypi_to_gn.py",
|
||||
[ rebase_path("src/libEGL.gypi") ],
|
||||
"scope",
|
||||
[ "src/libEGL.gypi" ])
|
||||
}
|
||||
gles_gypi = exec_script(
|
||||
"//build/gypi_to_gn.py",
|
||||
[ rebase_path("src/libGLESv2.gypi") ],
|
||||
"scope",
|
||||
[ "src/libGLESv2.gypi" ])
|
||||
|
||||
compiler_gypi = exec_script(
|
||||
"//build/gypi_to_gn.py",
|
||||
[ rebase_path("src/compiler.gypi") ],
|
||||
"scope",
|
||||
[ "src/compiler.gypi" ])
|
||||
"//build/gypi_to_gn.py",
|
||||
[ rebase_path("src/compiler.gypi") ],
|
||||
"scope",
|
||||
[ "src/compiler.gypi" ])
|
||||
|
||||
# This config is exported to dependent targets (and also applied to internal
|
||||
# ones).
|
||||
|
@ -39,6 +33,32 @@ config("internal_config") {
|
|||
]
|
||||
}
|
||||
|
||||
angle_enable_d3d9 = false
|
||||
angle_enable_d3d11 = false
|
||||
angle_enable_gl = false
|
||||
|
||||
if (is_win) {
|
||||
angle_enable_d3d9 = true
|
||||
angle_enable_d3d11 = true
|
||||
angle_enable_gl = true
|
||||
|
||||
import("//build/config/win/visual_studio_version.gni")
|
||||
copy("copy_compiler_dll") {
|
||||
sources = [ "$windows_sdk_path/Redist/D3D/$target_cpu/d3dcompiler_47.dll" ]
|
||||
outputs = [ "$root_build_dir/d3dcompiler_47.dll" ]
|
||||
}
|
||||
} # is_win
|
||||
|
||||
if (is_linux) {
|
||||
angle_enable_gl = true
|
||||
}
|
||||
|
||||
angle_enable_hlsl = false
|
||||
|
||||
if (angle_enable_d3d9 || angle_enable_d3d11) {
|
||||
angle_enable_hlsl = true
|
||||
}
|
||||
|
||||
component("translator") {
|
||||
sources = [
|
||||
"src/compiler/translator/ShaderLang.cpp",
|
||||
|
@ -47,6 +67,11 @@ component("translator") {
|
|||
|
||||
defines = [ "ANGLE_TRANSLATOR_IMPLEMENTATION" ]
|
||||
|
||||
if (angle_enable_hlsl) {
|
||||
sources += rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
|
||||
defines += [ "ANGLE_ENABLE_HLSL" ]
|
||||
}
|
||||
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [
|
||||
":internal_config",
|
||||
|
@ -89,9 +114,32 @@ config("translator_static_config") {
|
|||
defines = [ "ANGLE_TRANSLATOR_STATIC" ]
|
||||
}
|
||||
|
||||
config("debug_annotations_config") {
|
||||
if (is_debug) {
|
||||
defines = [
|
||||
"ANGLE_ENABLE_DEBUG_ANNOTATIONS",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
static_library("angle_common") {
|
||||
sources = rebase_path(gles_gypi.libangle_common_sources, ".", "src")
|
||||
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [
|
||||
":internal_config",
|
||||
":debug_annotations_config",
|
||||
"//build/config/compiler:no_chromium_code",
|
||||
]
|
||||
}
|
||||
|
||||
static_library("translator_lib") {
|
||||
sources = rebase_path(compiler_gypi.angle_translator_lib_sources, ".", "src")
|
||||
|
||||
if (angle_enable_hlsl) {
|
||||
sources += rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
|
||||
defines = [ "ANGLE_ENABLE_HLSL" ]
|
||||
}
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [
|
||||
":internal_config",
|
||||
|
@ -104,6 +152,10 @@ static_library("translator_lib") {
|
|||
":includes",
|
||||
":preprocessor",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
":angle_common",
|
||||
]
|
||||
}
|
||||
|
||||
static_library("translator_static") {
|
||||
|
@ -112,6 +164,10 @@ static_library("translator_static") {
|
|||
"src/compiler/translator/ShaderVars.cpp",
|
||||
]
|
||||
|
||||
if (angle_enable_hlsl) {
|
||||
defines = [ "ANGLE_ENABLE_HLSL" ]
|
||||
}
|
||||
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [
|
||||
":internal_config",
|
||||
|
@ -143,97 +199,150 @@ action("commit_id") {
|
|||
public_configs = [ ":commit_id_config" ]
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
angle_enable_d3d9 = true
|
||||
angle_enable_d3d11 = true
|
||||
config("libANGLE_config") {
|
||||
cflags = []
|
||||
defines = []
|
||||
if (angle_enable_d3d9) {
|
||||
defines += [ "ANGLE_ENABLE_D3D9" ]
|
||||
}
|
||||
if (angle_enable_d3d11) {
|
||||
defines += [ "ANGLE_ENABLE_D3D11" ]
|
||||
}
|
||||
if (angle_enable_gl) {
|
||||
defines += [ "ANGLE_ENABLE_OPENGL" ]
|
||||
}
|
||||
if (use_x11) {
|
||||
defines += [ "ANGLE_USE_X11" ]
|
||||
}
|
||||
defines += [
|
||||
"GL_APICALL=",
|
||||
"GL_GLEXT_PROTOTYPES=",
|
||||
"EGLAPI=",
|
||||
]
|
||||
if (is_win) {
|
||||
cflags += [ "/wd4530" ] # C++ exception handler used, but unwind semantics are not enabled.
|
||||
}
|
||||
}
|
||||
|
||||
shared_library("libGLESv2") {
|
||||
sources = rebase_path(gles_gypi.angle_libangle_sources, ".", "src")
|
||||
sources += [
|
||||
"src/libGLESv2/libGLESv2.cpp",
|
||||
"src/libGLESv2/libGLESv2.def",
|
||||
"src/libGLESv2/libGLESv2.rc",
|
||||
]
|
||||
static_library("libANGLE") {
|
||||
sources = rebase_path(gles_gypi.libangle_sources, ".", "src")
|
||||
|
||||
defines = [
|
||||
include_dirs = []
|
||||
libs = []
|
||||
defines = [
|
||||
"LIBANGLE_IMPLEMENTATION",
|
||||
]
|
||||
|
||||
# Shared D3D sources.
|
||||
if (angle_enable_d3d9 || angle_enable_d3d11) {
|
||||
sources += rebase_path(gles_gypi.libangle_d3d_shared_sources, ".", "src")
|
||||
|
||||
defines += [
|
||||
"ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ " +
|
||||
"\"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }",
|
||||
"GL_APICALL=",
|
||||
"GL_GLEXT_PROTOTYPES=",
|
||||
"EGLAPI=",
|
||||
]
|
||||
libs = []
|
||||
|
||||
# Windows-specific sources.
|
||||
sources += rebase_path(gles_gypi.angle_libangle_win_sources, ".", "src")
|
||||
|
||||
# Shared D3dD sources.
|
||||
if (angle_enable_d3d9 || angle_enable_d3d11) {
|
||||
sources += rebase_path(gles_gypi.angle_d3d_shared_sources, ".", "src")
|
||||
}
|
||||
|
||||
if (angle_enable_d3d9) {
|
||||
sources += rebase_path(gles_gypi.angle_d3d9_sources, ".", "src")
|
||||
defines += [ "ANGLE_ENABLE_D3D9" ]
|
||||
libs += [ "d3d9.lib" ]
|
||||
}
|
||||
|
||||
if (angle_enable_d3d11) {
|
||||
sources += rebase_path(gles_gypi.angle_d3d11_sources, ".", "src")
|
||||
defines += [ "ANGLE_ENABLE_D3D11" ]
|
||||
libs += [ "dxguid.lib" ]
|
||||
}
|
||||
|
||||
if (is_debug) {
|
||||
defines += [ "ANGLE_ENABLE_PERF" ]
|
||||
libs += [ "d3d9.lib" ]
|
||||
}
|
||||
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [
|
||||
":internal_config",
|
||||
"//build/config/compiler:no_chromium_code",
|
||||
]
|
||||
|
||||
include_dirs = [ "src/libGLESv2" ]
|
||||
|
||||
deps = [
|
||||
":commit_id",
|
||||
":includes",
|
||||
":translator",
|
||||
#":copy_compiler_dll", TODO(GYP)
|
||||
"\"d3dcompiler_47.dll\", \"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }",
|
||||
]
|
||||
}
|
||||
|
||||
shared_library("libEGL") {
|
||||
sources = rebase_path(egl_gypi.angle_libegl_sources, ".", "src")
|
||||
if (angle_enable_d3d9) {
|
||||
sources += rebase_path(gles_gypi.libangle_d3d9_sources, ".", "src")
|
||||
libs += [ "d3d9.lib" ]
|
||||
}
|
||||
|
||||
defines = [
|
||||
"GL_APICALL=",
|
||||
"GL_GLEXT_PROTOTYPES=",
|
||||
"EGLAPI=",
|
||||
]
|
||||
if (angle_enable_d3d11) {
|
||||
sources += rebase_path(gles_gypi.libangle_d3d11_sources, ".", "src")
|
||||
sources += rebase_path(gles_gypi.libangle_d3d11_win32_sources, ".", "src")
|
||||
libs += [ "dxguid.lib" ]
|
||||
}
|
||||
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [
|
||||
":internal_config",
|
||||
"//build/config/compiler:no_chromium_code",
|
||||
]
|
||||
if (angle_enable_gl) {
|
||||
sources += rebase_path(gles_gypi.libangle_gl_sources, ".", "src")
|
||||
include_dirs += [ "src/third_party/khronos" ]
|
||||
|
||||
if (is_debug) {
|
||||
defines += [
|
||||
"ANGLE_ENABLE_PERF",
|
||||
"ANGLE_GENERATE_SHADER_DEBUG_INFO"
|
||||
]
|
||||
if (is_win) {
|
||||
sources += rebase_path(gles_gypi.libangle_gl_wgl_sources, ".", "src")
|
||||
}
|
||||
if (use_x11) {
|
||||
sources += rebase_path(gles_gypi.libangle_gl_glx_sources, ".", "src")
|
||||
libs += [ "X11" ]
|
||||
}
|
||||
}
|
||||
|
||||
include_dirs = [ "src/libGLESv2" ]
|
||||
libs = [ "d3d9.lib" ]
|
||||
|
||||
deps = [
|
||||
":commit_id",
|
||||
":includes",
|
||||
":libGLESv2",
|
||||
if (is_debug) {
|
||||
defines += [
|
||||
"ANGLE_GENERATE_SHADER_DEBUG_INFO",
|
||||
]
|
||||
}
|
||||
} # is_win
|
||||
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [
|
||||
":commit_id_config",
|
||||
":debug_annotations_config",
|
||||
":libANGLE_config",
|
||||
":internal_config",
|
||||
"//build/config/compiler:no_chromium_code",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":commit_id",
|
||||
":includes",
|
||||
":translator_static",
|
||||
":angle_common",
|
||||
]
|
||||
|
||||
if (is_win) {
|
||||
deps += [ ":copy_compiler_dll" ]
|
||||
}
|
||||
}
|
||||
|
||||
shared_library("libGLESv2") {
|
||||
sources = rebase_path(gles_gypi.libglesv2_sources, ".", "src")
|
||||
|
||||
if (is_win) {
|
||||
ldflags = [ "/DEF:" +
|
||||
rebase_path("src/libGLESv2/libGLESv2.def", root_build_dir) ]
|
||||
}
|
||||
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [
|
||||
":internal_config",
|
||||
":commit_id_config",
|
||||
":debug_annotations_config",
|
||||
":libANGLE_config",
|
||||
"//build/config/compiler:no_chromium_code",
|
||||
]
|
||||
|
||||
defines = [
|
||||
"LIBGLESV2_IMPLEMENTATION",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":includes",
|
||||
":libANGLE",
|
||||
]
|
||||
}
|
||||
|
||||
shared_library("libEGL") {
|
||||
sources = rebase_path(gles_gypi.libegl_sources, ".", "src")
|
||||
|
||||
if (is_win) {
|
||||
ldflags = [ "/DEF:" +
|
||||
rebase_path("src/libEGL/libEGL.def", root_build_dir) ]
|
||||
}
|
||||
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [
|
||||
":internal_config",
|
||||
":commit_id_config",
|
||||
":libANGLE_config",
|
||||
"//build/config/compiler:no_chromium_code",
|
||||
]
|
||||
|
||||
defines = [
|
||||
"LIBEGL_IMPLEMENTATION",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":includes",
|
||||
":libGLESv2",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# This is the official list of people who can contribute
|
||||
# This is the official list of people who can contribute
|
||||
# (and who have contributed) code to the ANGLE project
|
||||
# repository.
|
||||
# The AUTHORS file lists the copyright holders; this file
|
||||
|
@ -40,6 +40,7 @@ Google Inc.
|
|||
thestig@chromium.org
|
||||
Justin Schuh
|
||||
Scott Graham
|
||||
Corentin Wallez
|
||||
|
||||
Adobe Systems Inc.
|
||||
Alexandru Chiculita
|
||||
|
@ -52,9 +53,12 @@ Autodesk, Inc.
|
|||
Cloud Party, Inc.
|
||||
Conor Dickinson
|
||||
|
||||
Digia Plc
|
||||
The Qt Company Ltd.
|
||||
Andrew Knight
|
||||
|
||||
Imagination Technologies Ltd.
|
||||
Gregoire Payen de La Garanderie
|
||||
|
||||
Intel Corporation
|
||||
Jin Yang
|
||||
Andy Chen
|
||||
|
@ -80,10 +84,23 @@ Mark Banner (standard8mbp)
|
|||
David Kilzer
|
||||
Jacek Caban
|
||||
Tibor den Ouden
|
||||
Régis Fénéon
|
||||
|
||||
Microsoft Corporation
|
||||
Cooper Partin
|
||||
Austin Kinross
|
||||
Minmin Gong
|
||||
Shawn Hargreaves
|
||||
|
||||
Microsoft Open Technologies, Inc.
|
||||
Cooper Partin
|
||||
Austin Kinross
|
||||
Cooper Partin
|
||||
Austin Kinross
|
||||
|
||||
NVIDIA Corporation
|
||||
Olli Etuaho
|
||||
Arun Patole
|
||||
Qingqing Deng
|
||||
Kimmo Kinnunen
|
||||
|
||||
Opera Software ASA
|
||||
Daniel Bratell
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче