Merge m-c to b2g-inbound

This commit is contained in:
Wes Kocher 2013-09-27 20:39:01 -07:00
commit bf6885efcb
425 changed files with 9056 additions and 6213 deletions

View File

@ -144,7 +144,7 @@ nsCoreUtils::DispatchTouchEvent(uint32_t aEventType, int32_t aX, int32_t aY,
if (!nsDOMTouchEvent::PrefEnabled()) if (!nsDOMTouchEvent::PrefEnabled())
return; return;
nsTouchEvent event(true, aEventType, aRootWidget); WidgetTouchEvent event(true, aEventType, aRootWidget);
event.time = PR_IntervalNow(); event.time = PR_IntervalNow();

View File

@ -188,13 +188,14 @@ HyperTextAccessible::GetBoundsForString(nsIFrame* aFrame, uint32_t aStartRendere
nsPoint frameTextStartPoint; nsPoint frameTextStartPoint;
rv = frame->GetPointFromOffset(startContentOffset, &frameTextStartPoint); rv = frame->GetPointFromOffset(startContentOffset, &frameTextStartPoint);
NS_ENSURE_SUCCESS(rv, nsIntRect()); NS_ENSURE_SUCCESS(rv, nsIntRect());
frameScreenRect.x += frameTextStartPoint.x;
// Use the point for the end offset to calculate the width // Use the point for the end offset to calculate the width
nsPoint frameTextEndPoint; nsPoint frameTextEndPoint;
rv = frame->GetPointFromOffset(startContentOffset + frameSubStringLength, &frameTextEndPoint); rv = frame->GetPointFromOffset(startContentOffset + frameSubStringLength, &frameTextEndPoint);
NS_ENSURE_SUCCESS(rv, nsIntRect()); NS_ENSURE_SUCCESS(rv, nsIntRect());
frameScreenRect.width = frameTextEndPoint.x - frameTextStartPoint.x;
frameScreenRect.x += std::min(frameTextStartPoint.x, frameTextEndPoint.x);
frameScreenRect.width = std::abs(frameTextStartPoint.x - frameTextEndPoint.x);
screenRect.UnionRect(frameScreenRect, screenRect); screenRect.UnionRect(frameScreenRect, screenRect);

View File

@ -21,21 +21,25 @@
src="../browser.js"></script> src="../browser.js"></script>
<script type="application/javascript"> <script type="application/javascript">
function doTest() function testTextNode(aDoc, aContainerID)
{ {
var tabDocument = currentTabDocument(); var hyperTextNode = aDoc.getElementById(aContainerID);
var hyperTextNode = tabDocument.getElementById("paragraph");
var textNode = hyperTextNode.firstChild; var textNode = hyperTextNode.firstChild;
var [x, y, width, height] = getBounds(textNode); var [x, y, width, height] = getBounds(textNode);
testTextBounds(hyperTextNode, 0, -1, [x, y, width, height], testTextBounds(hyperTextNode, 0, -1, [x, y, width, height],
COORDTYPE_SCREEN_RELATIVE); COORDTYPE_SCREEN_RELATIVE);
}
function doTest()
{
var tabDocument = currentTabDocument();
testTextNode(tabDocument, "p1");
testTextNode(tabDocument, "p2");
zoomDocument(tabDocument, 2.0); zoomDocument(tabDocument, 2.0);
var [x, y, width, height] = getBounds(textNode); testTextNode(tabDocument, "p1");
testTextBounds(hyperTextNode, 0, -1, [x, y, width, height],
COORDTYPE_SCREEN_RELATIVE);
zoomDocument(tabDocument, 1.0); zoomDocument(tabDocument, 1.0);
@ -46,7 +50,8 @@
var url = "data:text/html,<html>" + var url = "data:text/html,<html>" +
"<meta http-equiv='Content-Type' content='text/html;charset=utf-8'>" + "<meta http-equiv='Content-Type' content='text/html;charset=utf-8'>" +
"</meta><body>" + "</meta><body>" +
"<p id='paragraph' style='font-family: monospace;'>Tilimilitryamdiya</p>" + "<p id='p1' style='font-family: monospace;'>Tilimilitryamdiya</p>" +
"<p id='p2'>ل</p>"
"</body></html>"; "</body></html>";
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();

View File

@ -158,7 +158,8 @@ function testTextBounds(aID, aStartOffset, aEndOffset, aRect, aCoordOrigin)
var xObj = {}, yObj = {}, widthObj = {}, heightObj = {}; var xObj = {}, yObj = {}, widthObj = {}, heightObj = {};
var hyperText = getAccessible(aID, [nsIAccessibleText]); var hyperText = getAccessible(aID, [nsIAccessibleText]);
hyperText.getRangeExtents(0, -1, xObj, yObj, widthObj, heightObj, aCoordOrigin); hyperText.getRangeExtents(aStartOffset, aEndOffset,
xObj, yObj, widthObj, heightObj, aCoordOrigin);
is(xObj.value, expectedX, is(xObj.value, expectedX,
"Wrong x coordinate of text between offsets (" + aStartOffset + ", " + "Wrong x coordinate of text between offsets (" + aStartOffset + ", " +
aEndOffset + ") for " + prettyName(aID)); aEndOffset + ") for " + prettyName(aID));

View File

@ -818,3 +818,6 @@ pref("dom.telephony.enabled", true);
// The url of the page used to display network error details. // The url of the page used to display network error details.
pref("b2g.neterror.url", "app://system.gaiamobile.org/net_error.html"); pref("b2g.neterror.url", "app://system.gaiamobile.org/net_error.html");
// Enable Web Speech synthesis API
pref("media.webspeech.synth.enabled", true);

View File

@ -38,7 +38,7 @@ const EXPECTED_REFLOWS = [
"TabItem__reconnect@chrome://browser/content/tabview.js|" + "TabItem__reconnect@chrome://browser/content/tabview.js|" +
"TabItem@chrome://browser/content/tabview.js|" + "TabItem@chrome://browser/content/tabview.js|" +
"TabItems_link@chrome://browser/content/tabview.js|" + "TabItems_link@chrome://browser/content/tabview.js|" +
"@chrome://browser/content/tabview.js|", "TabItems_init/this._eventListeners.open@chrome://browser/content/tabview.js|",
// SessionStore.getWindowDimensions() // SessionStore.getWindowDimensions()
"ssi_getWindowDimension@resource:///modules/sessionstore/SessionStore.jsm|" + "ssi_getWindowDimension@resource:///modules/sessionstore/SessionStore.jsm|" +

View File

@ -9,7 +9,11 @@ MOCHITEST_BROWSER_FILES = \
browser_observableobject.js \ browser_observableobject.js \
browser_layoutHelpers.js \ browser_layoutHelpers.js \
browser_require_basic.js \ browser_require_basic.js \
browser_telemetry_buttonsandsidebar.js \ browser_telemetry_sidebar.js \
browser_telemetry_button_responsive.js \
browser_telemetry_button_scratchpad.js \
browser_telemetry_button_tilt.js \
browser_telemetry_button_paintflashing.js \
browser_telemetry_toolboxtabs_inspector.js \ browser_telemetry_toolboxtabs_inspector.js \
browser_telemetry_toolboxtabs_jsdebugger.js \ browser_telemetry_toolboxtabs_jsdebugger.js \
browser_telemetry_toolboxtabs_jsprofiler.js \ browser_telemetry_toolboxtabs_jsprofiler.js \

View File

@ -0,0 +1,127 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_paintflashing.js</p>";
// Because we need to gather stats for the period of time that a tool has been
// opened we make use of setTimeout() to create tool active times.
const TOOL_DELAY = 200;
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
let Telemetry = require("devtools/shared/telemetry");
function init() {
Telemetry.prototype.telemetryInfo = {};
Telemetry.prototype._oldlog = Telemetry.prototype.log;
Telemetry.prototype.log = function(histogramId, value) {
if (histogramId) {
if (!this.telemetryInfo[histogramId]) {
this.telemetryInfo[histogramId] = [];
}
this.telemetryInfo[histogramId].push(value);
}
};
testButton("command-button-paintflashing");
}
function testButton(id) {
info("Testing " + id);
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
info("inspector opened");
let button = toolbox.doc.querySelector("#" + id);
ok(button, "Captain, we have the button");
delayedClicks(button, 4).then(function() {
checkResults("_PAINTFLASHING_");
});
}).then(null, console.error);
}
function delayedClicks(node, clicks) {
let deferred = promise.defer();
let clicked = 0;
// See TOOL_DELAY for why we need setTimeout here
setTimeout(function delayedClick() {
info("Clicking button " + node.id);
node.click();
clicked++;
if (clicked >= clicks) {
deferred.resolve(node);
} else {
setTimeout(delayedClick, TOOL_DELAY);
}
}, TOOL_DELAY);
return deferred.promise;
}
function checkResults(histIdFocus) {
let result = Telemetry.prototype.telemetryInfo;
for (let [histId, value] of Iterator(result)) {
if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
!histId.contains(histIdFocus)) {
// Inspector stats are tested in
// browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
// because we only open the inspector once for this test.
continue;
}
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId.endsWith("OPENED_BOOLEAN")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element === true;
});
ok(okay, "All " + histId + " entries are === true");
} else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element > 0;
});
ok(okay, "All " + histId + " entries have time > 0");
}
}
finishUp();
}
function finishUp() {
gBrowser.removeCurrentTab();
Telemetry.prototype.log = Telemetry.prototype._oldlog;
delete Telemetry.prototype._oldlog;
delete Telemetry.prototype.telemetryInfo;
TargetFactory = Services = promise = require = null;
finish();
}
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
waitForFocus(init, content);
}, true);
content.location = TEST_URI;
}

View File

@ -0,0 +1,127 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_responsive.js</p>";
// Because we need to gather stats for the period of time that a tool has been
// opened we make use of setTimeout() to create tool active times.
const TOOL_DELAY = 200;
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
let Telemetry = require("devtools/shared/telemetry");
function init() {
Telemetry.prototype.telemetryInfo = {};
Telemetry.prototype._oldlog = Telemetry.prototype.log;
Telemetry.prototype.log = function(histogramId, value) {
if (histogramId) {
if (!this.telemetryInfo[histogramId]) {
this.telemetryInfo[histogramId] = [];
}
this.telemetryInfo[histogramId].push(value);
}
};
testButton("command-button-responsive");
}
function testButton(id) {
info("Testing " + id);
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
info("inspector opened");
let button = toolbox.doc.querySelector("#" + id);
ok(button, "Captain, we have the button");
delayedClicks(button, 4).then(function() {
checkResults("_RESPONSIVE_");
});
}).then(null, console.error);
}
function delayedClicks(node, clicks) {
let deferred = promise.defer();
let clicked = 0;
// See TOOL_DELAY for why we need setTimeout here
setTimeout(function delayedClick() {
info("Clicking button " + node.id);
node.click();
clicked++;
if (clicked >= clicks) {
deferred.resolve(node);
} else {
setTimeout(delayedClick, TOOL_DELAY);
}
}, TOOL_DELAY);
return deferred.promise;
}
function checkResults(histIdFocus) {
let result = Telemetry.prototype.telemetryInfo;
for (let [histId, value] of Iterator(result)) {
if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
!histId.contains(histIdFocus)) {
// Inspector stats are tested in
// browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
// because we only open the inspector once for this test.
continue;
}
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId.endsWith("OPENED_BOOLEAN")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element === true;
});
ok(okay, "All " + histId + " entries are === true");
} else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element > 0;
});
ok(okay, "All " + histId + " entries have time > 0");
}
}
finishUp();
}
function finishUp() {
gBrowser.removeCurrentTab();
Telemetry.prototype.log = Telemetry.prototype._oldlog;
delete Telemetry.prototype._oldlog;
delete Telemetry.prototype.telemetryInfo;
TargetFactory = Services = promise = require = null;
finish();
}
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
waitForFocus(init, content);
}, true);
content.location = TEST_URI;
}

View File

@ -0,0 +1,155 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_scratchpad.js</p>";
// Because we need to gather stats for the period of time that a tool has been
// opened we make use of setTimeout() to create tool active times.
const TOOL_DELAY = 200;
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
let Telemetry = require("devtools/shared/telemetry");
let numScratchpads = 0;
function init() {
Telemetry.prototype.telemetryInfo = {};
Telemetry.prototype._oldlog = Telemetry.prototype.log;
Telemetry.prototype.log = function(histogramId, value) {
if (histogramId) {
if (!this.telemetryInfo[histogramId]) {
this.telemetryInfo[histogramId] = [];
}
this.telemetryInfo[histogramId].push(value);
}
};
Services.ww.registerNotification(windowObserver);
testButton("command-button-scratchpad");
}
function testButton(id) {
info("Testing " + id);
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
info("inspector opened");
let button = toolbox.doc.querySelector("#" + id);
ok(button, "Captain, we have the button");
delayedClicks(button, 4).then(null, console.error);
}).then(null, console.error);
}
function windowObserver(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
if (win.Scratchpad) {
win.Scratchpad.addObserver({
onReady: function() {
win.Scratchpad.removeObserver(this);
numScratchpads++;
win.close();
info("another scratchpad was opened and closed, count is now " + numScratchpads);
if (numScratchpads === 4) {
Services.ww.unregisterNotification(windowObserver);
info("4 scratchpads have been opened and closed, checking results");
checkResults("_SCRATCHPAD_");
}
},
});
}
}, false);
}
}
function delayedClicks(node, clicks) {
let deferred = promise.defer();
let clicked = 0;
// See TOOL_DELAY for why we need setTimeout here
setTimeout(function delayedClick() {
info("Clicking button " + node.id);
node.click();
clicked++;
if (clicked >= clicks) {
deferred.resolve(node);
} else {
setTimeout(delayedClick, TOOL_DELAY);
}
}, TOOL_DELAY);
return deferred.promise;
}
function checkResults(histIdFocus) {
let result = Telemetry.prototype.telemetryInfo;
for (let [histId, value] of Iterator(result)) {
if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
!histId.contains(histIdFocus)) {
// Inspector stats are tested in
// browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
// because we only open the inspector once for this test.
continue;
}
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId.endsWith("OPENED_BOOLEAN")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element === true;
});
ok(okay, "All " + histId + " entries are === true");
} else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element > 0;
});
ok(okay, "All " + histId + " entries have time > 0");
}
}
finishUp();
}
function finishUp() {
gBrowser.removeCurrentTab();
Telemetry.prototype.log = Telemetry.prototype._oldlog;
delete Telemetry.prototype._oldlog;
delete Telemetry.prototype.telemetryInfo;
TargetFactory = Services = promise = require = numScratchpads = null;
finish();
}
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
waitForFocus(init, content);
}, true);
content.location = TEST_URI;
}

View File

@ -0,0 +1,127 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_tilt.js</p>";
// Because we need to gather stats for the period of time that a tool has been
// opened we make use of setTimeout() to create tool active times.
const TOOL_DELAY = 200;
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
let Telemetry = require("devtools/shared/telemetry");
function init() {
Telemetry.prototype.telemetryInfo = {};
Telemetry.prototype._oldlog = Telemetry.prototype.log;
Telemetry.prototype.log = function(histogramId, value) {
if (histogramId) {
if (!this.telemetryInfo[histogramId]) {
this.telemetryInfo[histogramId] = [];
}
this.telemetryInfo[histogramId].push(value);
}
};
testButton("command-button-tilt");
}
function testButton(id) {
info("Testing " + id);
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
info("inspector opened");
let button = toolbox.doc.querySelector("#" + id);
ok(button, "Captain, we have the button");
delayedClicks(button, 4).then(function() {
checkResults("_TILT_");
});
}).then(null, console.error);
}
function delayedClicks(node, clicks) {
let deferred = promise.defer();
let clicked = 0;
// See TOOL_DELAY for why we need setTimeout here
setTimeout(function delayedClick() {
info("Clicking button " + node.id);
node.click();
clicked++;
if (clicked >= clicks) {
deferred.resolve(node);
} else {
setTimeout(delayedClick, TOOL_DELAY);
}
}, TOOL_DELAY);
return deferred.promise;
}
function checkResults(histIdFocus) {
let result = Telemetry.prototype.telemetryInfo;
for (let [histId, value] of Iterator(result)) {
if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
!histId.contains(histIdFocus)) {
// Inspector stats are tested in
// browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
// because we only open the inspector once for this test.
continue;
}
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId.endsWith("OPENED_BOOLEAN")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element === true;
});
ok(okay, "All " + histId + " entries are === true");
} else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element > 0;
});
ok(okay, "All " + histId + " entries have time > 0");
}
}
finishUp();
}
function finishUp() {
gBrowser.removeCurrentTab();
Telemetry.prototype.log = Telemetry.prototype._oldlog;
delete Telemetry.prototype._oldlog;
delete Telemetry.prototype.telemetryInfo;
TargetFactory = Services = promise = require = null;
finish();
}
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
waitForFocus(init, content);
}, true);
content.location = TEST_URI;
}

View File

@ -1,7 +1,7 @@
/* Any copyright is dedicated to the Public Domain. /* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */ http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_buttonsandsidebar.js</p>"; const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_sidebar.js</p>";
// Because we need to gather stats for the period of time that a tool has been // Because we need to gather stats for the period of time that a tool has been
// opened we make use of setTimeout() to create tool active times. // opened we make use of setTimeout() to create tool active times.
@ -24,66 +24,9 @@ function init() {
this.telemetryInfo[histogramId].push(value); this.telemetryInfo[histogramId].push(value);
} }
} };
testButtons();
}
function testButtons() {
info("Testing buttons");
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
let container = toolbox.doc.getElementById("toolbox-buttons");
let buttons = container.getElementsByTagName("toolbarbutton");
// Copy HTMLCollection to array.
buttons = Array.prototype.slice.call(buttons);
(function testButton() {
let button = buttons.pop();
if (button) {
info("Clicking button " + button.id);
button.click();
delayedClicks(button, 3).then(function(button) {
if (buttons.length == 0) {
// Remove scratchpads
let wins = Services.wm.getEnumerator("devtools:scratchpad");
while (wins.hasMoreElements()) {
let win = wins.getNext();
info("Closing scratchpad window");
win.close();
}
testSidebar(); testSidebar();
} else {
setTimeout(testButton, TOOL_DELAY);
}
});
}
})();
}).then(null, reportError);
}
function delayedClicks(node, clicks) {
let deferred = promise.defer();
let clicked = 0;
setTimeout(function delayedClick() {
info("Clicking button " + node.id);
node.click();
clicked++;
if (clicked >= clicks) {
deferred.resolve(node);
} else {
setTimeout(delayedClick, TOOL_DELAY);
}
}, TOOL_DELAY);
return deferred.promise;
} }
function testSidebar() { function testSidebar() {
@ -98,6 +41,7 @@ function testSidebar() {
// Concatenate the array with itself so that we can open each tool twice. // Concatenate the array with itself so that we can open each tool twice.
sidebarTools.push.apply(sidebarTools, sidebarTools); sidebarTools.push.apply(sidebarTools, sidebarTools);
// See TOOL_DELAY for why we need setTimeout here
setTimeout(function selectSidebarTab() { setTimeout(function selectSidebarTab() {
let tool = sidebarTools.pop(); let tool = sidebarTools.pop();
if (tool) { if (tool) {
@ -147,14 +91,6 @@ function checkResults() {
finishUp(); finishUp();
} }
function reportError(error) {
let stack = " " + error.stack.replace(/\n?.*?@/g, "\n JS frame :: ");
ok(false, "ERROR: " + error + " at " + error.fileName + ":" +
error.lineNumber + "\n\nStack trace:" + stack);
finishUp();
}
function finishUp() { function finishUp() {
gBrowser.removeCurrentTab(); gBrowser.removeCurrentTab();

View File

@ -4,6 +4,7 @@
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}); let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let TargetFactory = devtools.TargetFactory; let TargetFactory = devtools.TargetFactory;
let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
/** /**
* Open a new tab at a URL and call a callback on load * Open a new tab at a URL and call a callback on load

View File

@ -1730,7 +1730,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
} }
if (aFireMutation) { if (aFireMutation) {
nsMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED); InternalMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
nsAutoString ns; nsAutoString ns;
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns); nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
@ -1911,7 +1911,7 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
if (hasMutationListeners) { if (hasMutationListeners) {
nsMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED); InternalMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
mutation.mRelatedNode = attrNode; mutation.mRelatedNode = attrNode;
mutation.mAttrName = aName; mutation.mAttrName = aName;
@ -2138,7 +2138,7 @@ Element::PreHandleEventForLinks(nsEventChainPreVisitor& aVisitor)
// FALL THROUGH // FALL THROUGH
case NS_FOCUS_CONTENT: case NS_FOCUS_CONTENT:
if (aVisitor.mEvent->eventStructType != NS_FOCUS_EVENT || if (aVisitor.mEvent->eventStructType != NS_FOCUS_EVENT ||
!static_cast<nsFocusEvent*>(aVisitor.mEvent)->isRefocus) { !static_cast<InternalFocusEvent*>(aVisitor.mEvent)->isRefocus) {
nsAutoString target; nsAutoString target;
GetLinkTarget(target); GetLinkTarget(target);
nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target, nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,

View File

@ -1021,7 +1021,7 @@ FragmentOrElement::FireNodeInserted(nsIDocument* aDoc,
if (nsContentUtils::HasMutationListeners(childContent, if (nsContentUtils::HasMutationListeners(childContent,
NS_EVENT_BITS_MUTATION_NODEINSERTED, aParent)) { NS_EVENT_BITS_MUTATION_NODEINSERTED, aParent)) {
nsMutationEvent mutation(true, NS_MUTATION_NODEINSERTED); InternalMutationEvent mutation(true, NS_MUTATION_NODEINSERTED);
mutation.mRelatedNode = do_QueryInterface(aParent); mutation.mRelatedNode = do_QueryInterface(aParent);
mozAutoSubtreeModified subtree(aDoc, aParent); mozAutoSubtreeModified subtree(aDoc, aParent);

View File

@ -3708,7 +3708,7 @@ nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent,
if (HasMutationListeners(aChild, if (HasMutationListeners(aChild,
NS_EVENT_BITS_MUTATION_NODEREMOVED, aParent)) { NS_EVENT_BITS_MUTATION_NODEREMOVED, aParent)) {
nsMutationEvent mutation(true, NS_MUTATION_NODEREMOVED); InternalMutationEvent mutation(true, NS_MUTATION_NODEREMOVED);
mutation.mRelatedNode = do_QueryInterface(aParent); mutation.mRelatedNode = do_QueryInterface(aParent);
mozAutoSubtreeModified subtree(aOwnerDoc, aParent); mozAutoSubtreeModified subtree(aOwnerDoc, aParent);

View File

@ -649,7 +649,7 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
clipboardData = new nsDOMDataTransfer(aType, aType == NS_PASTE, aClipboardType); clipboardData = new nsDOMDataTransfer(aType, aType == NS_PASTE, aClipboardType);
nsEventStatus status = nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;
nsClipboardEvent evt(true, aType); InternalClipboardEvent evt(true, aType);
evt.clipboardData = clipboardData; evt.clipboardData = clipboardData;
nsEventDispatcher::Dispatch(content, presShell->GetPresContext(), &evt, nullptr, nsEventDispatcher::Dispatch(content, presShell->GetPresContext(), &evt, nullptr,
&status); &status);

View File

@ -8194,7 +8194,7 @@ nsDocument::MutationEventDispatched(nsINode* aTarget)
int32_t realTargetCount = realTargets.Count(); int32_t realTargetCount = realTargets.Count();
for (int32_t k = 0; k < realTargetCount; ++k) { for (int32_t k = 0; k < realTargetCount; ++k) {
nsMutationEvent mutation(true, NS_MUTATION_SUBTREEMODIFIED); InternalMutationEvent mutation(true, NS_MUTATION_SUBTREEMODIFIED);
(new nsAsyncDOMEvent(realTargets[k], mutation))->RunDOMEventWhenSafe(); (new nsAsyncDOMEvent(realTargets[k], mutation))->RunDOMEventWhenSafe();
} }
} }

View File

@ -363,7 +363,7 @@ nsGenericDOMDataNode::SetTextInternal(uint32_t aOffset, uint32_t aCount,
nsNodeUtils::CharacterDataChanged(this, &info); nsNodeUtils::CharacterDataChanged(this, &info);
if (haveMutationListeners) { if (haveMutationListeners) {
nsMutationEvent mutation(true, NS_MUTATION_CHARACTERDATAMODIFIED); InternalMutationEvent mutation(true, NS_MUTATION_CHARACTERDATAMODIFIED);
mutation.mPrevAttrValue = oldValue; mutation.mPrevAttrValue = oldValue;
if (aLength > 0) { if (aLength > 0) {

View File

@ -193,8 +193,7 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
return NS_ERROR_DOM_BAD_URI; return NS_ERROR_DOM_BAD_URI;
} }
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(info->mObject); nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(info->mObject);
nsCOMPtr<mozilla::dom::MediaSource> mediasource = do_QueryInterface(info->mObject); if (!blob) {
if (!blob && !mediasource) {
return NS_ERROR_DOM_BAD_URI; return NS_ERROR_DOM_BAD_URI;
} }
@ -208,12 +207,7 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
#endif #endif
nsCOMPtr<nsIInputStream> stream; nsCOMPtr<nsIInputStream> stream;
nsresult rv = NS_OK; nsresult rv = blob->GetInternalStream(getter_AddRefs(stream));
if (blob) {
rv = blob->GetInternalStream(getter_AddRefs(stream));
} else {
stream = mediasource->CreateInternalStream();
}
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIChannel> channel; nsCOMPtr<nsIChannel> channel;
@ -225,14 +219,9 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
nsCOMPtr<nsISupports> owner = do_QueryInterface(info->mPrincipal); nsCOMPtr<nsISupports> owner = do_QueryInterface(info->mPrincipal);
nsString type; nsString type;
if (blob) {
rv = blob->GetType(type); rv = blob->GetType(type);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
uint64_t size;
rv = blob->GetSize(&size);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(info->mObject); nsCOMPtr<nsIDOMFile> file = do_QueryInterface(info->mObject);
if (file) { if (file) {
nsString filename; nsString filename;
@ -241,14 +230,14 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
channel->SetContentDispositionFilename(filename); channel->SetContentDispositionFilename(filename);
} }
channel->SetContentLength(size); uint64_t size;
} else { rv = blob->GetSize(&size);
type = mediasource->GetType(); NS_ENSURE_SUCCESS(rv, rv);
}
channel->SetOwner(owner); channel->SetOwner(owner);
channel->SetOriginalURI(uri); channel->SetOriginalURI(uri);
channel->SetContentType(NS_ConvertUTF16toUTF8(type)); channel->SetContentType(NS_ConvertUTF16toUTF8(type));
channel->SetContentLength(size);
channel.forget(result); channel.forget(result);

View File

@ -1405,7 +1405,7 @@ nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
if (nsContentUtils::HasMutationListeners(aKid, if (nsContentUtils::HasMutationListeners(aKid,
NS_EVENT_BITS_MUTATION_NODEINSERTED, this)) { NS_EVENT_BITS_MUTATION_NODEINSERTED, this)) {
nsMutationEvent mutation(true, NS_MUTATION_NODEINSERTED); InternalMutationEvent mutation(true, NS_MUTATION_NODEINSERTED);
mutation.mRelatedNode = do_QueryInterface(this); mutation.mRelatedNode = do_QueryInterface(this);
mozAutoSubtreeModified subtree(OwnerDoc(), this); mozAutoSubtreeModified subtree(OwnerDoc(), this);

View File

@ -55,7 +55,4 @@ public:
} // namespace mozilla } // namespace mozilla
// TODO: Remove following typedef
typedef mozilla::InternalMutationEvent nsMutationEvent;
#endif // mozilla_MutationEvent_h__ #endif // mozilla_MutationEvent_h__

View File

@ -7,14 +7,15 @@
#include "prtime.h" #include "prtime.h"
#include "mozilla/ContentEvents.h" #include "mozilla/ContentEvents.h"
using namespace mozilla;
nsDOMAnimationEvent::nsDOMAnimationEvent(mozilla::dom::EventTarget* aOwner, nsDOMAnimationEvent::nsDOMAnimationEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext *aPresContext, nsPresContext *aPresContext,
nsAnimationEvent *aEvent) InternalAnimationEvent* aEvent)
: nsDOMEvent(aOwner, aPresContext, : nsDOMEvent(aOwner, aPresContext,
aEvent ? aEvent : new nsAnimationEvent(false, 0, aEvent ? aEvent :
EmptyString(), new InternalAnimationEvent(false, 0, EmptyString(),
0.0, 0.0, EmptyString()))
EmptyString()))
{ {
if (aEvent) { if (aEvent) {
mEventIsInternal = false; mEventIsInternal = false;
@ -86,7 +87,7 @@ nsresult
NS_NewDOMAnimationEvent(nsIDOMEvent **aInstancePtrResult, NS_NewDOMAnimationEvent(nsIDOMEvent **aInstancePtrResult,
mozilla::dom::EventTarget* aOwner, mozilla::dom::EventTarget* aOwner,
nsPresContext *aPresContext, nsPresContext *aPresContext,
nsAnimationEvent *aEvent) InternalAnimationEvent *aEvent)
{ {
nsDOMAnimationEvent* it = nsDOMAnimationEvent* it =
new nsDOMAnimationEvent(aOwner, aPresContext, aEvent); new nsDOMAnimationEvent(aOwner, aPresContext, aEvent);

View File

@ -18,7 +18,7 @@ class nsDOMAnimationEvent : public nsDOMEvent,
public: public:
nsDOMAnimationEvent(mozilla::dom::EventTarget* aOwner, nsDOMAnimationEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext *aPresContext, nsPresContext *aPresContext,
nsAnimationEvent *aEvent); mozilla::InternalAnimationEvent* aEvent);
~nsDOMAnimationEvent(); ~nsDOMAnimationEvent();
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
@ -47,10 +47,10 @@ public:
} }
private: private:
nsAnimationEvent* AnimationEvent() { mozilla::InternalAnimationEvent* AnimationEvent() {
NS_ABORT_IF_FALSE(mEvent->eventStructType == NS_ANIMATION_EVENT, NS_ABORT_IF_FALSE(mEvent->eventStructType == NS_ANIMATION_EVENT,
"unexpected struct type"); "unexpected struct type");
return static_cast<nsAnimationEvent*>(mEvent); return static_cast<mozilla::InternalAnimationEvent*>(mEvent);
} }
}; };

View File

@ -8,11 +8,13 @@
#include "nsIClipboard.h" #include "nsIClipboard.h"
#include "mozilla/ContentEvents.h" #include "mozilla/ContentEvents.h"
using namespace mozilla;
nsDOMClipboardEvent::nsDOMClipboardEvent(mozilla::dom::EventTarget* aOwner, nsDOMClipboardEvent::nsDOMClipboardEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsClipboardEvent* aEvent) InternalClipboardEvent* aEvent)
: nsDOMEvent(aOwner, aPresContext, aEvent ? aEvent : : nsDOMEvent(aOwner, aPresContext, aEvent ? aEvent :
new nsClipboardEvent(false, 0)) new InternalClipboardEvent(false, 0))
{ {
if (aEvent) { if (aEvent) {
mEventIsInternal = false; mEventIsInternal = false;
@ -25,7 +27,7 @@ nsDOMClipboardEvent::nsDOMClipboardEvent(mozilla::dom::EventTarget* aOwner,
nsDOMClipboardEvent::~nsDOMClipboardEvent() nsDOMClipboardEvent::~nsDOMClipboardEvent()
{ {
if (mEventIsInternal && mEvent->eventStructType == NS_CLIPBOARD_EVENT) { if (mEventIsInternal && mEvent->eventStructType == NS_CLIPBOARD_EVENT) {
delete static_cast<nsClipboardEvent*>(mEvent); delete static_cast<InternalClipboardEvent*>(mEvent);
mEvent = nullptr; mEvent = nullptr;
} }
} }
@ -44,7 +46,7 @@ nsDOMClipboardEvent::InitClipboardEvent(const nsAString & aType, bool aCanBubble
nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsClipboardEvent* event = static_cast<nsClipboardEvent*>(mEvent); InternalClipboardEvent* event = static_cast<InternalClipboardEvent*>(mEvent);
event->clipboardData = clipboardData; event->clipboardData = clipboardData;
return NS_OK; return NS_OK;
@ -63,7 +65,8 @@ nsDOMClipboardEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal,
nsRefPtr<nsDOMDataTransfer> clipboardData; nsRefPtr<nsDOMDataTransfer> clipboardData;
if (e->mEventIsInternal) { if (e->mEventIsInternal) {
nsClipboardEvent* event = static_cast<nsClipboardEvent*>(e->mEvent); InternalClipboardEvent* event =
static_cast<InternalClipboardEvent*>(e->mEvent);
if (event) { if (event) {
// Always create a clipboardData for the copy event. If this is changed to // Always create a clipboardData for the copy event. If this is changed to
// support other types of events, make sure that read/write privileges are // support other types of events, make sure that read/write privileges are
@ -89,7 +92,7 @@ nsDOMClipboardEvent::GetClipboardData(nsIDOMDataTransfer** aClipboardData)
nsIDOMDataTransfer* nsIDOMDataTransfer*
nsDOMClipboardEvent::GetClipboardData() nsDOMClipboardEvent::GetClipboardData()
{ {
nsClipboardEvent* event = static_cast<nsClipboardEvent*>(mEvent); InternalClipboardEvent* event = static_cast<InternalClipboardEvent*>(mEvent);
if (!event->clipboardData) { if (!event->clipboardData) {
if (mEventIsInternal) { if (mEventIsInternal) {
@ -106,7 +109,7 @@ nsDOMClipboardEvent::GetClipboardData()
nsresult NS_NewDOMClipboardEvent(nsIDOMEvent** aInstancePtrResult, nsresult NS_NewDOMClipboardEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner, mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsClipboardEvent *aEvent) InternalClipboardEvent* aEvent)
{ {
nsDOMClipboardEvent* it = nsDOMClipboardEvent* it =
new nsDOMClipboardEvent(aOwner, aPresContext, aEvent); new nsDOMClipboardEvent(aOwner, aPresContext, aEvent);

View File

@ -17,7 +17,7 @@ class nsDOMClipboardEvent : public nsDOMEvent,
public: public:
nsDOMClipboardEvent(mozilla::dom::EventTarget* aOwner, nsDOMClipboardEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsClipboardEvent* aEvent); mozilla::InternalClipboardEvent* aEvent);
virtual ~nsDOMClipboardEvent(); virtual ~nsDOMClipboardEvent();
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED

View File

@ -7,11 +7,13 @@
#include "prtime.h" #include "prtime.h"
#include "mozilla/MiscEvents.h" #include "mozilla/MiscEvents.h"
using namespace mozilla;
nsDOMCommandEvent::nsDOMCommandEvent(mozilla::dom::EventTarget* aOwner, nsDOMCommandEvent::nsDOMCommandEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsCommandEvent* aEvent) WidgetCommandEvent* aEvent)
: nsDOMEvent(aOwner, aPresContext, aEvent ? aEvent : : nsDOMEvent(aOwner, aPresContext, aEvent ? aEvent :
new nsCommandEvent(false, nullptr, nullptr, nullptr)) new WidgetCommandEvent(false, nullptr, nullptr, nullptr))
{ {
mEvent->time = PR_Now(); mEvent->time = PR_Now();
if (aEvent) { if (aEvent) {
@ -24,7 +26,7 @@ nsDOMCommandEvent::nsDOMCommandEvent(mozilla::dom::EventTarget* aOwner,
nsDOMCommandEvent::~nsDOMCommandEvent() nsDOMCommandEvent::~nsDOMCommandEvent()
{ {
if (mEventIsInternal && mEvent->eventStructType == NS_COMMAND_EVENT) { if (mEventIsInternal && mEvent->eventStructType == NS_COMMAND_EVENT) {
delete static_cast<nsCommandEvent*>(mEvent); delete static_cast<WidgetCommandEvent*>(mEvent);
mEvent = nullptr; mEvent = nullptr;
} }
} }
@ -39,7 +41,7 @@ NS_IMPL_RELEASE_INHERITED(nsDOMCommandEvent, nsDOMEvent)
NS_IMETHODIMP NS_IMETHODIMP
nsDOMCommandEvent::GetCommand(nsAString& aCommand) nsDOMCommandEvent::GetCommand(nsAString& aCommand)
{ {
nsIAtom* command = static_cast<nsCommandEvent*>(mEvent)->command; nsIAtom* command = static_cast<WidgetCommandEvent*>(mEvent)->command;
if (command) { if (command) {
command->ToString(aCommand); command->ToString(aCommand);
} else { } else {
@ -57,14 +59,14 @@ nsDOMCommandEvent::InitCommandEvent(const nsAString& aTypeArg,
nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg); nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
static_cast<nsCommandEvent*>(mEvent)->command = do_GetAtom(aCommand); static_cast<WidgetCommandEvent*>(mEvent)->command = do_GetAtom(aCommand);
return NS_OK; return NS_OK;
} }
nsresult NS_NewDOMCommandEvent(nsIDOMEvent** aInstancePtrResult, nsresult NS_NewDOMCommandEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner, mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsCommandEvent* aEvent) WidgetCommandEvent* aEvent)
{ {
nsDOMCommandEvent* it = new nsDOMCommandEvent(aOwner, aPresContext, aEvent); nsDOMCommandEvent* it = new nsDOMCommandEvent(aOwner, aPresContext, aEvent);

View File

@ -17,7 +17,7 @@ class nsDOMCommandEvent : public nsDOMEvent,
public: public:
nsDOMCommandEvent(mozilla::dom::EventTarget* aOwner, nsDOMCommandEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsCommandEvent* aEvent); mozilla::WidgetCommandEvent* aEvent);
virtual ~nsDOMCommandEvent(); virtual ~nsDOMCommandEvent();
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED

View File

@ -150,13 +150,15 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEvent)
static_cast<nsMouseEvent_base*>(tmp->mEvent)->relatedTarget = nullptr; static_cast<nsMouseEvent_base*>(tmp->mEvent)->relatedTarget = nullptr;
break; break;
case NS_CLIPBOARD_EVENT: case NS_CLIPBOARD_EVENT:
static_cast<nsClipboardEvent*>(tmp->mEvent)->clipboardData = nullptr; static_cast<InternalClipboardEvent*>(tmp->mEvent)->clipboardData =
nullptr;
break; break;
case NS_MUTATION_EVENT: case NS_MUTATION_EVENT:
static_cast<nsMutationEvent*>(tmp->mEvent)->mRelatedNode = nullptr; static_cast<InternalMutationEvent*>(tmp->mEvent)->mRelatedNode =
nullptr;
break; break;
case NS_FOCUS_EVENT: case NS_FOCUS_EVENT:
static_cast<nsFocusEvent*>(tmp->mEvent)->relatedTarget = nullptr; static_cast<InternalFocusEvent*>(tmp->mEvent)->relatedTarget = nullptr;
break; break;
default: default:
break; break;
@ -193,17 +195,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEvent)
case NS_CLIPBOARD_EVENT: case NS_CLIPBOARD_EVENT:
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->clipboardData"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->clipboardData");
cb.NoteXPCOMChild( cb.NoteXPCOMChild(
static_cast<nsClipboardEvent*>(tmp->mEvent)->clipboardData); static_cast<InternalClipboardEvent*>(tmp->mEvent)->clipboardData);
break; break;
case NS_MUTATION_EVENT: case NS_MUTATION_EVENT:
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->mRelatedNode"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->mRelatedNode");
cb.NoteXPCOMChild( cb.NoteXPCOMChild(
static_cast<nsMutationEvent*>(tmp->mEvent)->mRelatedNode); static_cast<InternalMutationEvent*>(tmp->mEvent)->mRelatedNode);
break; break;
case NS_FOCUS_EVENT: case NS_FOCUS_EVENT:
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->relatedTarget"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->relatedTarget");
cb.NoteXPCOMChild( cb.NoteXPCOMChild(
static_cast<nsFocusEvent*>(tmp->mEvent)->relatedTarget); static_cast<InternalFocusEvent*>(tmp->mEvent)->relatedTarget);
break; break;
default: default:
break; break;
@ -562,17 +564,20 @@ nsDOMEvent::DuplicatePrivateData()
} }
case NS_CLIPBOARD_EVENT: case NS_CLIPBOARD_EVENT:
{ {
nsClipboardEvent* oldClipboardEvent = static_cast<nsClipboardEvent*>(mEvent); InternalClipboardEvent* oldClipboardEvent =
nsClipboardEvent* clipboardEvent = new nsClipboardEvent(false, msg); static_cast<InternalClipboardEvent*>(mEvent);
InternalClipboardEvent* clipboardEvent =
new InternalClipboardEvent(false, msg);
clipboardEvent->AssignClipboardEventData(*oldClipboardEvent, true); clipboardEvent->AssignClipboardEventData(*oldClipboardEvent, true);
newEvent = clipboardEvent; newEvent = clipboardEvent;
break; break;
} }
case NS_SCRIPT_ERROR_EVENT: case NS_SCRIPT_ERROR_EVENT:
{ {
nsScriptErrorEvent* oldScriptErrorEvent = InternalScriptErrorEvent* oldScriptErrorEvent =
static_cast<nsScriptErrorEvent*>(mEvent); static_cast<InternalScriptErrorEvent*>(mEvent);
nsScriptErrorEvent* scriptErrorEvent = new nsScriptErrorEvent(false, msg); InternalScriptErrorEvent* scriptErrorEvent =
new InternalScriptErrorEvent(false, msg);
scriptErrorEvent->AssignScriptErrorEventData(*oldScriptErrorEvent, true); scriptErrorEvent->AssignScriptErrorEventData(*oldScriptErrorEvent, true);
newEvent = scriptErrorEvent; newEvent = scriptErrorEvent;
break; break;
@ -615,54 +620,57 @@ nsDOMEvent::DuplicatePrivateData()
} }
case NS_SCROLLPORT_EVENT: case NS_SCROLLPORT_EVENT:
{ {
nsScrollPortEvent* oldScrollPortEvent = InternalScrollPortEvent* oldScrollPortEvent =
static_cast<nsScrollPortEvent*>(mEvent); static_cast<InternalScrollPortEvent*>(mEvent);
nsScrollPortEvent* scrollPortEvent = InternalScrollPortEvent* scrollPortEvent =
new nsScrollPortEvent(false, msg, nullptr); new InternalScrollPortEvent(false, msg, nullptr);
scrollPortEvent->AssignScrollPortEventData(*oldScrollPortEvent, true); scrollPortEvent->AssignScrollPortEventData(*oldScrollPortEvent, true);
newEvent = scrollPortEvent; newEvent = scrollPortEvent;
break; break;
} }
case NS_SCROLLAREA_EVENT: case NS_SCROLLAREA_EVENT:
{ {
nsScrollAreaEvent* oldScrollAreaEvent = InternalScrollAreaEvent* oldScrollAreaEvent =
static_cast<nsScrollAreaEvent*>(mEvent); static_cast<InternalScrollAreaEvent*>(mEvent);
nsScrollAreaEvent* scrollAreaEvent = InternalScrollAreaEvent* scrollAreaEvent =
new nsScrollAreaEvent(false, msg, nullptr); new InternalScrollAreaEvent(false, msg, nullptr);
scrollAreaEvent->AssignScrollAreaEventData(*oldScrollAreaEvent, true); scrollAreaEvent->AssignScrollAreaEventData(*oldScrollAreaEvent, true);
newEvent = scrollAreaEvent; newEvent = scrollAreaEvent;
break; break;
} }
case NS_MUTATION_EVENT: case NS_MUTATION_EVENT:
{ {
nsMutationEvent* mutationEvent = new nsMutationEvent(false, msg); InternalMutationEvent* mutationEvent =
nsMutationEvent* oldMutationEvent = new InternalMutationEvent(false, msg);
static_cast<nsMutationEvent*>(mEvent); InternalMutationEvent* oldMutationEvent =
static_cast<InternalMutationEvent*>(mEvent);
mutationEvent->AssignMutationEventData(*oldMutationEvent, true); mutationEvent->AssignMutationEventData(*oldMutationEvent, true);
newEvent = mutationEvent; newEvent = mutationEvent;
break; break;
} }
case NS_FORM_EVENT: case NS_FORM_EVENT:
{ {
nsFormEvent* oldFormEvent = static_cast<nsFormEvent*>(mEvent); InternalFormEvent* oldFormEvent = static_cast<InternalFormEvent*>(mEvent);
nsFormEvent* formEvent = new nsFormEvent(false, msg); InternalFormEvent* formEvent = new InternalFormEvent(false, msg);
formEvent->AssignFormEventData(*oldFormEvent, true); formEvent->AssignFormEventData(*oldFormEvent, true);
newEvent = formEvent; newEvent = formEvent;
break; break;
} }
case NS_FOCUS_EVENT: case NS_FOCUS_EVENT:
{ {
nsFocusEvent* newFocusEvent = new nsFocusEvent(false, msg); InternalFocusEvent* newFocusEvent = new InternalFocusEvent(false, msg);
nsFocusEvent* oldFocusEvent = static_cast<nsFocusEvent*>(mEvent); InternalFocusEvent* oldFocusEvent =
static_cast<InternalFocusEvent*>(mEvent);
newFocusEvent->AssignFocusEventData(*oldFocusEvent, true); newFocusEvent->AssignFocusEventData(*oldFocusEvent, true);
newEvent = newFocusEvent; newEvent = newFocusEvent;
break; break;
} }
case NS_COMMAND_EVENT: case NS_COMMAND_EVENT:
{ {
nsCommandEvent* oldCommandEvent = static_cast<nsCommandEvent*>(mEvent); WidgetCommandEvent* oldCommandEvent =
nsCommandEvent* commandEvent = static_cast<WidgetCommandEvent*>(mEvent);
new nsCommandEvent(false, mEvent->userType, WidgetCommandEvent* commandEvent =
new WidgetCommandEvent(false, mEvent->userType,
oldCommandEvent->command, nullptr); oldCommandEvent->command, nullptr);
commandEvent->AssignCommandEventData(*oldCommandEvent, true); commandEvent->AssignCommandEventData(*oldCommandEvent, true);
newEvent = commandEvent; newEvent = commandEvent;
@ -696,10 +704,10 @@ nsDOMEvent::DuplicatePrivateData()
} }
case NS_SIMPLE_GESTURE_EVENT: case NS_SIMPLE_GESTURE_EVENT:
{ {
nsSimpleGestureEvent* oldSimpleGestureEvent = WidgetSimpleGestureEvent* oldSimpleGestureEvent =
static_cast<nsSimpleGestureEvent*>(mEvent); static_cast<WidgetSimpleGestureEvent*>(mEvent);
nsSimpleGestureEvent* simpleGestureEvent = WidgetSimpleGestureEvent* simpleGestureEvent =
new nsSimpleGestureEvent(false, msg, nullptr, 0, 0.0); new WidgetSimpleGestureEvent(false, msg, nullptr, 0, 0.0);
simpleGestureEvent-> simpleGestureEvent->
AssignSimpleGestureEventData(*oldSimpleGestureEvent, true); AssignSimpleGestureEventData(*oldSimpleGestureEvent, true);
newEvent = simpleGestureEvent; newEvent = simpleGestureEvent;
@ -707,10 +715,10 @@ nsDOMEvent::DuplicatePrivateData()
} }
case NS_TRANSITION_EVENT: case NS_TRANSITION_EVENT:
{ {
nsTransitionEvent* oldTransitionEvent = InternalTransitionEvent* oldTransitionEvent =
static_cast<nsTransitionEvent*>(mEvent); static_cast<InternalTransitionEvent*>(mEvent);
nsTransitionEvent* transitionEvent = InternalTransitionEvent* transitionEvent =
new nsTransitionEvent(false, msg, new InternalTransitionEvent(false, msg,
oldTransitionEvent->propertyName, oldTransitionEvent->propertyName,
oldTransitionEvent->elapsedTime, oldTransitionEvent->elapsedTime,
oldTransitionEvent->pseudoElement); oldTransitionEvent->pseudoElement);
@ -720,10 +728,10 @@ nsDOMEvent::DuplicatePrivateData()
} }
case NS_ANIMATION_EVENT: case NS_ANIMATION_EVENT:
{ {
nsAnimationEvent* oldAnimationEvent = InternalAnimationEvent* oldAnimationEvent =
static_cast<nsAnimationEvent*>(mEvent); static_cast<InternalAnimationEvent*>(mEvent);
nsAnimationEvent* animationEvent = InternalAnimationEvent* animationEvent =
new nsAnimationEvent(false, msg, new InternalAnimationEvent(false, msg,
oldAnimationEvent->animationName, oldAnimationEvent->animationName,
oldAnimationEvent->elapsedTime, oldAnimationEvent->elapsedTime,
oldAnimationEvent->pseudoElement); oldAnimationEvent->pseudoElement);
@ -733,8 +741,8 @@ nsDOMEvent::DuplicatePrivateData()
} }
case NS_TOUCH_EVENT: case NS_TOUCH_EVENT:
{ {
nsTouchEvent* oldTouchEvent = static_cast<nsTouchEvent*>(mEvent); WidgetTouchEvent* oldTouchEvent = static_cast<WidgetTouchEvent*>(mEvent);
nsTouchEvent* touchEvent = new nsTouchEvent(false, oldTouchEvent); WidgetTouchEvent* touchEvent = new WidgetTouchEvent(false, oldTouchEvent);
touchEvent->AssignTouchEventData(*oldTouchEvent, true); touchEvent->AssignTouchEventData(*oldTouchEvent, true);
newEvent = touchEvent; newEvent = touchEvent;
break; break;

View File

@ -13,10 +13,11 @@ using namespace mozilla::dom;
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMFocusEvent, nsDOMUIEvent, nsIDOMFocusEvent) NS_IMPL_ISUPPORTS_INHERITED1(nsDOMFocusEvent, nsDOMUIEvent, nsIDOMFocusEvent)
nsDOMFocusEvent::nsDOMFocusEvent(mozilla::dom::EventTarget* aOwner, nsDOMFocusEvent::nsDOMFocusEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsFocusEvent* aEvent) nsPresContext* aPresContext,
: nsDOMUIEvent(aOwner, aPresContext, aEvent ? InternalFocusEvent* aEvent)
static_cast<nsGUIEvent*>(aEvent) : : nsDOMUIEvent(aOwner, aPresContext,
static_cast<nsGUIEvent*>(new nsFocusEvent(false, NS_FOCUS_CONTENT))) aEvent ? aEvent :
new InternalFocusEvent(false, NS_FOCUS_CONTENT))
{ {
if (aEvent) { if (aEvent) {
mEventIsInternal = false; mEventIsInternal = false;
@ -29,7 +30,7 @@ nsDOMFocusEvent::nsDOMFocusEvent(mozilla::dom::EventTarget* aOwner,
nsDOMFocusEvent::~nsDOMFocusEvent() nsDOMFocusEvent::~nsDOMFocusEvent()
{ {
if (mEventIsInternal && mEvent) { if (mEventIsInternal && mEvent) {
delete static_cast<nsFocusEvent*>(mEvent); delete static_cast<InternalFocusEvent*>(mEvent);
mEvent = nullptr; mEvent = nullptr;
} }
} }
@ -46,7 +47,7 @@ nsDOMFocusEvent::GetRelatedTarget(nsIDOMEventTarget** aRelatedTarget)
mozilla::dom::EventTarget* mozilla::dom::EventTarget*
nsDOMFocusEvent::GetRelatedTarget() nsDOMFocusEvent::GetRelatedTarget()
{ {
return static_cast<nsFocusEvent*>(mEvent)->relatedTarget; return static_cast<InternalFocusEvent*>(mEvent)->relatedTarget;
} }
nsresult nsresult
@ -59,7 +60,7 @@ nsDOMFocusEvent::InitFocusEvent(const nsAString& aType,
{ {
nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail); nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
static_cast<nsFocusEvent*>(mEvent)->relatedTarget = aRelatedTarget; static_cast<InternalFocusEvent*>(mEvent)->relatedTarget = aRelatedTarget;
return NS_OK; return NS_OK;
} }
@ -81,7 +82,7 @@ nsDOMFocusEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal,
nsresult NS_NewDOMFocusEvent(nsIDOMEvent** aInstancePtrResult, nsresult NS_NewDOMFocusEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner, mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsFocusEvent* aEvent) InternalFocusEvent* aEvent)
{ {
nsDOMFocusEvent* it = new nsDOMFocusEvent(aOwner, aPresContext, aEvent); nsDOMFocusEvent* it = new nsDOMFocusEvent(aOwner, aPresContext, aEvent);
return CallQueryInterface(it, aInstancePtrResult); return CallQueryInterface(it, aInstancePtrResult);

View File

@ -27,7 +27,8 @@ public:
} }
nsDOMFocusEvent(mozilla::dom::EventTarget* aOwner, nsDOMFocusEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsFocusEvent* aEvent); nsPresContext* aPresContext,
mozilla::InternalFocusEvent* aEvent);
mozilla::dom::EventTarget* GetRelatedTarget(); mozilla::dom::EventTarget* GetRelatedTarget();

View File

@ -17,7 +17,8 @@ class nsDOMMutationEvent : public nsDOMEvent,
{ {
public: public:
nsDOMMutationEvent(mozilla::dom::EventTarget* aOwner, nsDOMMutationEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsMutationEvent* aEvent); nsPresContext* aPresContext,
mozilla::InternalMutationEvent* aEvent);
virtual ~nsDOMMutationEvent(); virtual ~nsDOMMutationEvent();

View File

@ -10,9 +10,11 @@
#include "nsDOMScrollAreaEvent.h" #include "nsDOMScrollAreaEvent.h"
#include "nsClientRect.h" #include "nsClientRect.h"
using namespace mozilla;
nsDOMScrollAreaEvent::nsDOMScrollAreaEvent(mozilla::dom::EventTarget* aOwner, nsDOMScrollAreaEvent::nsDOMScrollAreaEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext *aPresContext, nsPresContext *aPresContext,
nsScrollAreaEvent *aEvent) InternalScrollAreaEvent* aEvent)
: nsDOMUIEvent(aOwner, aPresContext, aEvent) : nsDOMUIEvent(aOwner, aPresContext, aEvent)
, mClientArea(nullptr) , mClientArea(nullptr)
{ {
@ -23,7 +25,7 @@ nsDOMScrollAreaEvent::~nsDOMScrollAreaEvent()
{ {
if (mEventIsInternal && mEvent) { if (mEventIsInternal && mEvent) {
if (mEvent->eventStructType == NS_SCROLLAREA_EVENT) { if (mEvent->eventStructType == NS_SCROLLAREA_EVENT) {
delete static_cast<nsScrollAreaEvent *>(mEvent); delete static_cast<InternalScrollAreaEvent*>(mEvent);
mEvent = nullptr; mEvent = nullptr;
} }
} }
@ -102,7 +104,7 @@ nsresult
NS_NewDOMScrollAreaEvent(nsIDOMEvent **aInstancePtrResult, NS_NewDOMScrollAreaEvent(nsIDOMEvent **aInstancePtrResult,
mozilla::dom::EventTarget* aOwner, mozilla::dom::EventTarget* aOwner,
nsPresContext *aPresContext, nsPresContext *aPresContext,
nsScrollAreaEvent *aEvent) InternalScrollAreaEvent* aEvent)
{ {
nsDOMScrollAreaEvent* ev = nsDOMScrollAreaEvent* ev =
new nsDOMScrollAreaEvent(aOwner, aPresContext, aEvent); new nsDOMScrollAreaEvent(aOwner, aPresContext, aEvent);

View File

@ -20,7 +20,7 @@ class nsDOMScrollAreaEvent : public nsDOMUIEvent,
public: public:
nsDOMScrollAreaEvent(mozilla::dom::EventTarget* aOwner, nsDOMScrollAreaEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext *aPresContext, nsPresContext *aPresContext,
nsScrollAreaEvent *aEvent); mozilla::InternalScrollAreaEvent* aEvent);
virtual ~nsDOMScrollAreaEvent(); virtual ~nsDOMScrollAreaEvent();
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED

View File

@ -7,11 +7,15 @@
#include "prtime.h" #include "prtime.h"
#include "mozilla/TouchEvents.h" #include "mozilla/TouchEvents.h"
using namespace mozilla;
nsDOMSimpleGestureEvent::nsDOMSimpleGestureEvent(mozilla::dom::EventTarget* aOwner, nsDOMSimpleGestureEvent::nsDOMSimpleGestureEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsSimpleGestureEvent* aEvent) WidgetSimpleGestureEvent* aEvent)
: nsDOMMouseEvent(aOwner, aPresContext, : nsDOMMouseEvent(aOwner, aPresContext,
aEvent ? aEvent : new nsSimpleGestureEvent(false, 0, nullptr, 0, 0.0)) aEvent ? aEvent :
new WidgetSimpleGestureEvent(false, 0, nullptr,
0, 0.0))
{ {
NS_ASSERTION(mEvent->eventStructType == NS_SIMPLE_GESTURE_EVENT, "event type mismatch"); NS_ASSERTION(mEvent->eventStructType == NS_SIMPLE_GESTURE_EVENT, "event type mismatch");
@ -28,7 +32,7 @@ nsDOMSimpleGestureEvent::nsDOMSimpleGestureEvent(mozilla::dom::EventTarget* aOwn
nsDOMSimpleGestureEvent::~nsDOMSimpleGestureEvent() nsDOMSimpleGestureEvent::~nsDOMSimpleGestureEvent()
{ {
if (mEventIsInternal) { if (mEventIsInternal) {
delete static_cast<nsSimpleGestureEvent*>(mEvent); delete static_cast<WidgetSimpleGestureEvent*>(mEvent);
mEvent = nullptr; mEvent = nullptr;
} }
} }
@ -46,14 +50,14 @@ nsDOMSimpleGestureEvent::GetAllowedDirections(uint32_t *aAllowedDirections)
{ {
NS_ENSURE_ARG_POINTER(aAllowedDirections); NS_ENSURE_ARG_POINTER(aAllowedDirections);
*aAllowedDirections = *aAllowedDirections =
static_cast<nsSimpleGestureEvent*>(mEvent)->allowedDirections; static_cast<WidgetSimpleGestureEvent*>(mEvent)->allowedDirections;
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDOMSimpleGestureEvent::SetAllowedDirections(uint32_t aAllowedDirections) nsDOMSimpleGestureEvent::SetAllowedDirections(uint32_t aAllowedDirections)
{ {
static_cast<nsSimpleGestureEvent*>(mEvent)->allowedDirections = static_cast<WidgetSimpleGestureEvent*>(mEvent)->allowedDirections =
aAllowedDirections; aAllowedDirections;
return NS_OK; return NS_OK;
} }
@ -123,7 +127,8 @@ nsDOMSimpleGestureEvent::InitSimpleGestureEvent(const nsAString& aTypeArg,
aRelatedTarget); aRelatedTarget);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsSimpleGestureEvent* simpleGestureEvent = static_cast<nsSimpleGestureEvent*>(mEvent); WidgetSimpleGestureEvent* simpleGestureEvent =
static_cast<WidgetSimpleGestureEvent*>(mEvent);
simpleGestureEvent->allowedDirections = aAllowedDirectionsArg; simpleGestureEvent->allowedDirections = aAllowedDirectionsArg;
simpleGestureEvent->direction = aDirectionArg; simpleGestureEvent->direction = aDirectionArg;
simpleGestureEvent->delta = aDeltaArg; simpleGestureEvent->delta = aDeltaArg;
@ -135,7 +140,7 @@ nsDOMSimpleGestureEvent::InitSimpleGestureEvent(const nsAString& aTypeArg,
nsresult NS_NewDOMSimpleGestureEvent(nsIDOMEvent** aInstancePtrResult, nsresult NS_NewDOMSimpleGestureEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner, mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsSimpleGestureEvent *aEvent) WidgetSimpleGestureEvent* aEvent)
{ {
nsDOMSimpleGestureEvent* it = nsDOMSimpleGestureEvent* it =
new nsDOMSimpleGestureEvent(aOwner, aPresContext, aEvent); new nsDOMSimpleGestureEvent(aOwner, aPresContext, aEvent);

View File

@ -17,7 +17,7 @@ class nsDOMSimpleGestureEvent : public nsDOMMouseEvent,
{ {
public: public:
nsDOMSimpleGestureEvent(mozilla::dom::EventTarget* aOwner, nsDOMSimpleGestureEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext*, nsSimpleGestureEvent*); nsPresContext*, mozilla::WidgetSimpleGestureEvent*);
virtual ~nsDOMSimpleGestureEvent(); virtual ~nsDOMSimpleGestureEvent();
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
@ -35,22 +35,23 @@ public:
uint32_t AllowedDirections() uint32_t AllowedDirections()
{ {
return static_cast<nsSimpleGestureEvent*>(mEvent)->allowedDirections; return static_cast<mozilla::WidgetSimpleGestureEvent*>(mEvent)->
allowedDirections;
} }
uint32_t Direction() uint32_t Direction()
{ {
return static_cast<nsSimpleGestureEvent*>(mEvent)->direction; return static_cast<mozilla::WidgetSimpleGestureEvent*>(mEvent)->direction;
} }
double Delta() double Delta()
{ {
return static_cast<nsSimpleGestureEvent*>(mEvent)->delta; return static_cast<mozilla::WidgetSimpleGestureEvent*>(mEvent)->delta;
} }
uint32_t ClickCount() uint32_t ClickCount()
{ {
return static_cast<nsSimpleGestureEvent*>(mEvent)->clickCount; return static_cast<mozilla::WidgetSimpleGestureEvent*>(mEvent)->clickCount;
} }
void InitSimpleGestureEvent(const nsAString& aType, void InitSimpleGestureEvent(const nsAString& aType,

View File

@ -54,9 +54,9 @@ nsDOMTouchList::IdentifiedTouch(int32_t aIdentifier) const
nsDOMTouchEvent::nsDOMTouchEvent(mozilla::dom::EventTarget* aOwner, nsDOMTouchEvent::nsDOMTouchEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsTouchEvent* aEvent) WidgetTouchEvent* aEvent)
: nsDOMUIEvent(aOwner, aPresContext, : nsDOMUIEvent(aOwner, aPresContext,
aEvent ? aEvent : new nsTouchEvent(false, 0, nullptr)) aEvent ? aEvent : new WidgetTouchEvent(false, 0, nullptr))
{ {
if (aEvent) { if (aEvent) {
mEventIsInternal = false; mEventIsInternal = false;
@ -74,7 +74,7 @@ nsDOMTouchEvent::nsDOMTouchEvent(mozilla::dom::EventTarget* aOwner,
nsDOMTouchEvent::~nsDOMTouchEvent() nsDOMTouchEvent::~nsDOMTouchEvent()
{ {
if (mEventIsInternal && mEvent) { if (mEventIsInternal && mEvent) {
delete static_cast<nsTouchEvent*>(mEvent); delete static_cast<WidgetTouchEvent*>(mEvent);
mEvent = nullptr; mEvent = nullptr;
} }
} }
@ -126,7 +126,7 @@ nsDOMTouchList*
nsDOMTouchEvent::Touches() nsDOMTouchEvent::Touches()
{ {
if (!mTouches) { if (!mTouches) {
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent); WidgetTouchEvent* touchEvent = static_cast<WidgetTouchEvent*>(mEvent);
if (mEvent->message == NS_TOUCH_END || mEvent->message == NS_TOUCH_CANCEL) { if (mEvent->message == NS_TOUCH_END || mEvent->message == NS_TOUCH_CANCEL) {
// for touchend events, remove any changed touches from the touches array // for touchend events, remove any changed touches from the touches array
nsTArray< nsRefPtr<Touch> > unchangedTouches; nsTArray< nsRefPtr<Touch> > unchangedTouches;
@ -149,7 +149,7 @@ nsDOMTouchEvent::TargetTouches()
{ {
if (!mTargetTouches) { if (!mTargetTouches) {
nsTArray< nsRefPtr<Touch> > targetTouches; nsTArray< nsRefPtr<Touch> > targetTouches;
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent); WidgetTouchEvent* touchEvent = static_cast<WidgetTouchEvent*>(mEvent);
const nsTArray< nsRefPtr<Touch> >& touches = touchEvent->touches; const nsTArray< nsRefPtr<Touch> >& touches = touchEvent->touches;
for (uint32_t i = 0; i < touches.Length(); ++i) { for (uint32_t i = 0; i < touches.Length(); ++i) {
// for touchend/cancel events, don't append to the target list if this is a // for touchend/cancel events, don't append to the target list if this is a
@ -171,7 +171,7 @@ nsDOMTouchEvent::ChangedTouches()
{ {
if (!mChangedTouches) { if (!mChangedTouches) {
nsTArray< nsRefPtr<Touch> > changedTouches; nsTArray< nsRefPtr<Touch> > changedTouches;
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent); WidgetTouchEvent* touchEvent = static_cast<WidgetTouchEvent*>(mEvent);
const nsTArray< nsRefPtr<Touch> >& touches = touchEvent->touches; const nsTArray< nsRefPtr<Touch> >& touches = touchEvent->touches;
for (uint32_t i = 0; i < touches.Length(); ++i) { for (uint32_t i = 0; i < touches.Length(); ++i) {
if (touches[i]->mChanged) { if (touches[i]->mChanged) {
@ -225,7 +225,7 @@ nsresult
NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult, NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult,
mozilla::dom::EventTarget* aOwner, mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsPresContext* aPresContext,
nsTouchEvent *aEvent) WidgetTouchEvent* aEvent)
{ {
nsDOMTouchEvent* it = new nsDOMTouchEvent(aOwner, aPresContext, aEvent); nsDOMTouchEvent* it = new nsDOMTouchEvent(aOwner, aPresContext, aEvent);
return CallQueryInterface(it, aInstancePtrResult); return CallQueryInterface(it, aInstancePtrResult);

View File

@ -82,7 +82,8 @@ class nsDOMTouchEvent : public nsDOMUIEvent
{ {
public: public:
nsDOMTouchEvent(mozilla::dom::EventTarget* aOwner, nsDOMTouchEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsTouchEvent* aEvent); nsPresContext* aPresContext,
mozilla::WidgetTouchEvent* aEvent);
virtual ~nsDOMTouchEvent(); virtual ~nsDOMTouchEvent();
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED

View File

@ -7,14 +7,15 @@
#include "prtime.h" #include "prtime.h"
#include "mozilla/ContentEvents.h" #include "mozilla/ContentEvents.h"
using namespace mozilla;
nsDOMTransitionEvent::nsDOMTransitionEvent(mozilla::dom::EventTarget* aOwner, nsDOMTransitionEvent::nsDOMTransitionEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext *aPresContext, nsPresContext *aPresContext,
nsTransitionEvent *aEvent) InternalTransitionEvent* aEvent)
: nsDOMEvent(aOwner, aPresContext, : nsDOMEvent(aOwner, aPresContext,
aEvent ? aEvent : new nsTransitionEvent(false, 0, aEvent ? aEvent :
EmptyString(), new InternalTransitionEvent(false, 0, EmptyString(),
0.0, 0.0, EmptyString()))
EmptyString()))
{ {
if (aEvent) { if (aEvent) {
mEventIsInternal = false; mEventIsInternal = false;
@ -86,7 +87,7 @@ nsresult
NS_NewDOMTransitionEvent(nsIDOMEvent **aInstancePtrResult, NS_NewDOMTransitionEvent(nsIDOMEvent **aInstancePtrResult,
mozilla::dom::EventTarget* aOwner, mozilla::dom::EventTarget* aOwner,
nsPresContext *aPresContext, nsPresContext *aPresContext,
nsTransitionEvent *aEvent) InternalTransitionEvent* aEvent)
{ {
nsDOMTransitionEvent *it = nsDOMTransitionEvent *it =
new nsDOMTransitionEvent(aOwner, aPresContext, aEvent); new nsDOMTransitionEvent(aOwner, aPresContext, aEvent);

View File

@ -18,7 +18,7 @@ class nsDOMTransitionEvent : public nsDOMEvent,
public: public:
nsDOMTransitionEvent(mozilla::dom::EventTarget* aOwner, nsDOMTransitionEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext *aPresContext, nsPresContext *aPresContext,
nsTransitionEvent *aEvent); mozilla::InternalTransitionEvent* aEvent);
~nsDOMTransitionEvent(); ~nsDOMTransitionEvent();
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
@ -47,10 +47,10 @@ public:
} }
private: private:
nsTransitionEvent* TransitionEvent() { mozilla::InternalTransitionEvent* TransitionEvent() {
NS_ABORT_IF_FALSE(mEvent->eventStructType == NS_TRANSITION_EVENT, NS_ABORT_IF_FALSE(mEvent->eventStructType == NS_TRANSITION_EVENT,
"unexpected struct type"); "unexpected struct type");
return static_cast<nsTransitionEvent*>(mEvent); return static_cast<mozilla::InternalTransitionEvent*>(mEvent);
} }
}; };

View File

@ -52,7 +52,8 @@ nsDOMUIEvent::nsDOMUIEvent(mozilla::dom::EventTarget* aOwner,
case NS_SCROLLPORT_EVENT: case NS_SCROLLPORT_EVENT:
{ {
nsScrollPortEvent* scrollEvent = static_cast<nsScrollPortEvent*>(mEvent); InternalScrollPortEvent* scrollEvent =
static_cast<InternalScrollPortEvent*>(mEvent);
mDetail = (int32_t)scrollEvent->orient; mDetail = (int32_t)scrollEvent->orient;
break; break;
} }

View File

@ -690,7 +690,7 @@ nsEventDispatcher::CreateEvent(mozilla::dom::EventTarget* aOwner,
switch(aEvent->eventStructType) { switch(aEvent->eventStructType) {
case NS_MUTATION_EVENT: case NS_MUTATION_EVENT:
return NS_NewDOMMutationEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMMutationEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsMutationEvent*>(aEvent)); static_cast<InternalMutationEvent*>(aEvent));
case NS_GUI_EVENT: case NS_GUI_EVENT:
case NS_SCROLLPORT_EVENT: case NS_SCROLLPORT_EVENT:
case NS_UI_EVENT: case NS_UI_EVENT:
@ -698,7 +698,7 @@ nsEventDispatcher::CreateEvent(mozilla::dom::EventTarget* aOwner,
static_cast<nsGUIEvent*>(aEvent)); static_cast<nsGUIEvent*>(aEvent));
case NS_SCROLLAREA_EVENT: case NS_SCROLLAREA_EVENT:
return NS_NewDOMScrollAreaEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMScrollAreaEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsScrollAreaEvent *>(aEvent)); static_cast<InternalScrollAreaEvent*>(aEvent));
case NS_KEY_EVENT: case NS_KEY_EVENT:
return NS_NewDOMKeyboardEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMKeyboardEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsKeyEvent*>(aEvent)); static_cast<nsKeyEvent*>(aEvent));
@ -711,7 +711,7 @@ nsEventDispatcher::CreateEvent(mozilla::dom::EventTarget* aOwner,
static_cast<nsInputEvent*>(aEvent)); static_cast<nsInputEvent*>(aEvent));
case NS_FOCUS_EVENT: case NS_FOCUS_EVENT:
return NS_NewDOMFocusEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMFocusEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsFocusEvent*>(aEvent)); static_cast<InternalFocusEvent*>(aEvent));
case NS_MOUSE_SCROLL_EVENT: case NS_MOUSE_SCROLL_EVENT:
return NS_NewDOMMouseScrollEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMMouseScrollEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsInputEvent*>(aEvent)); static_cast<nsInputEvent*>(aEvent));
@ -726,7 +726,7 @@ nsEventDispatcher::CreateEvent(mozilla::dom::EventTarget* aOwner,
static_cast<nsTextEvent*>(aEvent)); static_cast<nsTextEvent*>(aEvent));
case NS_CLIPBOARD_EVENT: case NS_CLIPBOARD_EVENT:
return NS_NewDOMClipboardEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMClipboardEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsClipboardEvent*>(aEvent)); static_cast<InternalClipboardEvent*>(aEvent));
case NS_SVGZOOM_EVENT: case NS_SVGZOOM_EVENT:
return NS_NewDOMSVGZoomEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMSVGZoomEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsGUIEvent*>(aEvent)); static_cast<nsGUIEvent*>(aEvent));
@ -735,19 +735,19 @@ nsEventDispatcher::CreateEvent(mozilla::dom::EventTarget* aOwner,
case NS_COMMAND_EVENT: case NS_COMMAND_EVENT:
return NS_NewDOMCommandEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMCommandEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsCommandEvent*>(aEvent)); static_cast<WidgetCommandEvent*>(aEvent));
case NS_SIMPLE_GESTURE_EVENT: case NS_SIMPLE_GESTURE_EVENT:
return NS_NewDOMSimpleGestureEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMSimpleGestureEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsSimpleGestureEvent*>(aEvent)); static_cast<WidgetSimpleGestureEvent*>(aEvent));
case NS_TOUCH_EVENT: case NS_TOUCH_EVENT:
return NS_NewDOMTouchEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMTouchEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsTouchEvent*>(aEvent)); static_cast<WidgetTouchEvent*>(aEvent));
case NS_TRANSITION_EVENT: case NS_TRANSITION_EVENT:
return NS_NewDOMTransitionEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMTransitionEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsTransitionEvent*>(aEvent)); static_cast<InternalTransitionEvent*>(aEvent));
case NS_ANIMATION_EVENT: case NS_ANIMATION_EVENT:
return NS_NewDOMAnimationEvent(aDOMEvent, aOwner, aPresContext, return NS_NewDOMAnimationEvent(aDOMEvent, aOwner, aPresContext,
static_cast<nsAnimationEvent*>(aEvent)); static_cast<InternalAnimationEvent*>(aEvent));
default: default:
// For all other types of events, create a vanilla event object. // For all other types of events, create a vanilla event object.
return NS_NewDOMEvent(aDOMEvent, aOwner, aPresContext, aEvent); return NS_NewDOMEvent(aDOMEvent, aOwner, aPresContext, aEvent);

View File

@ -1073,12 +1073,13 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
case NS_CONTENT_COMMAND_REDO: case NS_CONTENT_COMMAND_REDO:
case NS_CONTENT_COMMAND_PASTE_TRANSFERABLE: case NS_CONTENT_COMMAND_PASTE_TRANSFERABLE:
{ {
DoContentCommandEvent(static_cast<nsContentCommandEvent*>(aEvent)); DoContentCommandEvent(static_cast<WidgetContentCommandEvent*>(aEvent));
} }
break; break;
case NS_CONTENT_COMMAND_SCROLL: case NS_CONTENT_COMMAND_SCROLL:
{ {
DoContentCommandScrollEvent(static_cast<nsContentCommandEvent*>(aEvent)); DoContentCommandScrollEvent(
static_cast<WidgetContentCommandEvent*>(aEvent));
} }
break; break;
case NS_TEXT_TEXT: case NS_TEXT_TEXT:
@ -1398,7 +1399,7 @@ nsEventStateManager::DispatchCrossProcessEvent(nsEvent* aEvent,
// Let the child process synthesize a mouse event if needed, and // Let the child process synthesize a mouse event if needed, and
// ensure we don't synthesize one in this process. // ensure we don't synthesize one in this process.
*aStatus = nsEventStatus_eConsumeNoDefault; *aStatus = nsEventStatus_eConsumeNoDefault;
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent); WidgetTouchEvent* touchEvent = static_cast<WidgetTouchEvent*>(aEvent);
return remote->SendRealTouchEvent(*touchEvent); return remote->SendRealTouchEvent(*touchEvent);
} }
default: { default: {
@ -1515,7 +1516,7 @@ nsEventStateManager::HandleCrossProcessEvent(nsEvent *aEvent,
// //
// This loop is similar to the one used in // This loop is similar to the one used in
// PresShell::DispatchTouchEvent(). // PresShell::DispatchTouchEvent().
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent); WidgetTouchEvent* touchEvent = static_cast<WidgetTouchEvent*>(aEvent);
const nsTArray< nsRefPtr<Touch> >& touches = touchEvent->touches; const nsTArray< nsRefPtr<Touch> >& touches = touchEvent->touches;
for (uint32_t i = 0; i < touches.Length(); ++i) { for (uint32_t i = 0; i < touches.Length(); ++i) {
Touch* touch = touches[i]; Touch* touch = touches[i];
@ -2808,7 +2809,7 @@ nsEventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame,
} }
void void
nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent, nsEventStateManager::DecideGestureEvent(WidgetGestureNotifyEvent* aEvent,
nsIFrame* targetFrame) nsIFrame* targetFrame)
{ {
@ -2827,7 +2828,8 @@ nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent,
* *
* Note: we'll have to one-off various cases to ensure a good usable behavior * Note: we'll have to one-off various cases to ensure a good usable behavior
*/ */
nsGestureNotifyEvent::ePanDirection panDirection = nsGestureNotifyEvent::ePanNone; WidgetGestureNotifyEvent::ePanDirection panDirection =
WidgetGestureNotifyEvent::ePanNone;
bool displayPanFeedback = false; bool displayPanFeedback = false;
for (nsIFrame* current = targetFrame; current; for (nsIFrame* current = targetFrame; current;
current = nsLayoutUtils::GetCrossDocParentFrame(current)) { current = nsLayoutUtils::GetCrossDocParentFrame(current)) {
@ -2836,7 +2838,7 @@ nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent,
// Scrollbars should always be draggable // Scrollbars should always be draggable
if (currentFrameType == nsGkAtoms::scrollbarFrame) { if (currentFrameType == nsGkAtoms::scrollbarFrame) {
panDirection = nsGestureNotifyEvent::ePanNone; panDirection = WidgetGestureNotifyEvent::ePanNone;
break; break;
} }
@ -2845,10 +2847,10 @@ nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent,
nsTreeBodyFrame* treeFrame = do_QueryFrame(current); nsTreeBodyFrame* treeFrame = do_QueryFrame(current);
if (treeFrame) { if (treeFrame) {
if (treeFrame->GetHorizontalOverflow()) { if (treeFrame->GetHorizontalOverflow()) {
panDirection = nsGestureNotifyEvent::ePanHorizontal; panDirection = WidgetGestureNotifyEvent::ePanHorizontal;
} }
if (treeFrame->GetVerticalOverflow()) { if (treeFrame->GetVerticalOverflow()) {
panDirection = nsGestureNotifyEvent::ePanVertical; panDirection = WidgetGestureNotifyEvent::ePanVertical;
} }
break; break;
} }
@ -2872,12 +2874,12 @@ nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent,
// Vertical panning has priority over horizontal panning, so // Vertical panning has priority over horizontal panning, so
// when vertical movement is possible we can just finish the loop. // when vertical movement is possible we can just finish the loop.
if (scrollRange.height > 0) { if (scrollRange.height > 0) {
panDirection = nsGestureNotifyEvent::ePanVertical; panDirection = WidgetGestureNotifyEvent::ePanVertical;
break; break;
} }
if (canScrollHorizontally) { if (canScrollHorizontally) {
panDirection = nsGestureNotifyEvent::ePanHorizontal; panDirection = WidgetGestureNotifyEvent::ePanHorizontal;
displayPanFeedback = false; displayPanFeedback = false;
} }
} else { //Not a XUL box } else { //Not a XUL box
@ -2885,13 +2887,13 @@ nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent,
//Check if we have visible scrollbars //Check if we have visible scrollbars
if (scrollbarVisibility & nsIScrollableFrame::VERTICAL) { if (scrollbarVisibility & nsIScrollableFrame::VERTICAL) {
panDirection = nsGestureNotifyEvent::ePanVertical; panDirection = WidgetGestureNotifyEvent::ePanVertical;
displayPanFeedback = true; displayPanFeedback = true;
break; break;
} }
if (scrollbarVisibility & nsIScrollableFrame::HORIZONTAL) { if (scrollbarVisibility & nsIScrollableFrame::HORIZONTAL) {
panDirection = nsGestureNotifyEvent::ePanHorizontal; panDirection = WidgetGestureNotifyEvent::ePanHorizontal;
displayPanFeedback = true; displayPanFeedback = true;
} }
} }
@ -3221,7 +3223,8 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
case NS_GESTURENOTIFY_EVENT_START: case NS_GESTURENOTIFY_EVENT_START:
{ {
if (nsEventStatus_eConsumeNoDefault != *aStatus) if (nsEventStatus_eConsumeNoDefault != *aStatus)
DecideGestureEvent(static_cast<nsGestureNotifyEvent*>(aEvent), mCurrentTarget); DecideGestureEvent(static_cast<WidgetGestureNotifyEvent*>(aEvent),
mCurrentTarget);
} }
break; break;
@ -4921,7 +4924,7 @@ nsEventStateManager::IsShellVisible(nsIDocShell* aShell)
} }
nsresult nsresult
nsEventStateManager::DoContentCommandEvent(nsContentCommandEvent* aEvent) nsEventStateManager::DoContentCommandEvent(WidgetContentCommandEvent* aEvent)
{ {
EnsureDocument(mPresContext); EnsureDocument(mPresContext);
NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE); NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
@ -4996,7 +4999,8 @@ nsEventStateManager::DoContentCommandEvent(nsContentCommandEvent* aEvent)
} }
nsresult nsresult
nsEventStateManager::DoContentCommandScrollEvent(nsContentCommandEvent* aEvent) nsEventStateManager::DoContentCommandScrollEvent(
WidgetContentCommandEvent* aEvent)
{ {
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE); NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE);
nsIPresShell* ps = mPresContext->GetPresShell(); nsIPresShell* ps = mPresContext->GetPresShell();
@ -5005,13 +5009,13 @@ nsEventStateManager::DoContentCommandScrollEvent(nsContentCommandEvent* aEvent)
nsIScrollableFrame::ScrollUnit scrollUnit; nsIScrollableFrame::ScrollUnit scrollUnit;
switch (aEvent->mScroll.mUnit) { switch (aEvent->mScroll.mUnit) {
case nsContentCommandEvent::eCmdScrollUnit_Line: case WidgetContentCommandEvent::eCmdScrollUnit_Line:
scrollUnit = nsIScrollableFrame::LINES; scrollUnit = nsIScrollableFrame::LINES;
break; break;
case nsContentCommandEvent::eCmdScrollUnit_Page: case WidgetContentCommandEvent::eCmdScrollUnit_Page:
scrollUnit = nsIScrollableFrame::PAGES; scrollUnit = nsIScrollableFrame::PAGES;
break; break;
case nsContentCommandEvent::eCmdScrollUnit_Whole: case WidgetContentCommandEvent::eCmdScrollUnit_Whole:
scrollUnit = nsIScrollableFrame::WHOLE; scrollUnit = nsIScrollableFrame::WHOLE;
break; break;
default: default:

View File

@ -655,7 +655,8 @@ protected:
* the target element, as well as the orientation to trigger panning and * the target element, as well as the orientation to trigger panning and
* display visual boundary feedback. The decision is stored back in aEvent. * display visual boundary feedback. The decision is stored back in aEvent.
*/ */
void DecideGestureEvent(nsGestureNotifyEvent* aEvent, nsIFrame* targetFrame); void DecideGestureEvent(mozilla::WidgetGestureNotifyEvent* aEvent,
nsIFrame* targetFrame);
// routines for the d&d gesture tracking state machine // routines for the d&d gesture tracking state machine
void BeginTrackingDragGesture ( nsPresContext* aPresContext, nsMouseEvent* inDownEvent, void BeginTrackingDragGesture ( nsPresContext* aPresContext, nsMouseEvent* inDownEvent,
@ -704,8 +705,9 @@ protected:
*/ */
void FillInEventFromGestureDown(nsMouseEvent* aEvent); void FillInEventFromGestureDown(nsMouseEvent* aEvent);
nsresult DoContentCommandEvent(nsContentCommandEvent* aEvent); nsresult DoContentCommandEvent(mozilla::WidgetContentCommandEvent* aEvent);
nsresult DoContentCommandScrollEvent(nsContentCommandEvent* aEvent); nsresult DoContentCommandScrollEvent(
mozilla::WidgetContentCommandEvent* aEvent);
void DoQuerySelectedText(nsQueryContentEvent* aEvent); void DoQuerySelectedText(nsQueryContentEvent* aEvent);

View File

@ -347,9 +347,8 @@ HTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
if (aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT) { if (aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT) {
if (mForm && (mType == NS_FORM_BUTTON_SUBMIT || if (mForm && (mType == NS_FORM_BUTTON_SUBMIT ||
mType == NS_FORM_BUTTON_RESET)) { mType == NS_FORM_BUTTON_RESET)) {
nsFormEvent event(true, InternalFormEvent event(true,
(mType == NS_FORM_BUTTON_RESET) (mType == NS_FORM_BUTTON_RESET) ? NS_FORM_RESET : NS_FORM_SUBMIT);
? NS_FORM_RESET : NS_FORM_SUBMIT);
event.originator = this; event.originator = this;
nsEventStatus status = nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;

View File

@ -422,7 +422,7 @@ HTMLFormElement::Submit()
NS_IMETHODIMP NS_IMETHODIMP
HTMLFormElement::Reset() HTMLFormElement::Reset()
{ {
nsFormEvent event(true, NS_FORM_RESET); InternalFormEvent event(true, NS_FORM_RESET);
nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), nullptr, nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), nullptr,
&event); &event);
return NS_OK; return NS_OK;
@ -822,13 +822,15 @@ HTMLFormElement::BuildSubmission(nsFormSubmission** aFormSubmission,
nsGenericHTMLElement* originatingElement = nullptr; nsGenericHTMLElement* originatingElement = nullptr;
if (aEvent) { if (aEvent) {
if (NS_FORM_EVENT == aEvent->eventStructType) { if (NS_FORM_EVENT == aEvent->eventStructType) {
nsIContent* originator = ((nsFormEvent *)aEvent)->originator; nsIContent* originator =
static_cast<InternalFormEvent*>(aEvent)->originator;
if (originator) { if (originator) {
if (!originator->IsHTML()) { if (!originator->IsHTML()) {
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
originatingElement = originatingElement =
static_cast<nsGenericHTMLElement*>(((nsFormEvent *)aEvent)->originator); static_cast<nsGenericHTMLElement*>(
static_cast<InternalFormEvent*>(aEvent)->originator);
} }
} }
} }

View File

@ -2810,7 +2810,7 @@ HTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
// If there's only one text control, just submit the form // If there's only one text control, just submit the form
// Hold strong ref across the event // Hold strong ref across the event
nsRefPtr<mozilla::dom::HTMLFormElement> form = mForm; nsRefPtr<mozilla::dom::HTMLFormElement> form = mForm;
nsFormEvent event(true, NS_FORM_SUBMIT); InternalFormEvent event(true, NS_FORM_SUBMIT);
nsEventStatus status = nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;
shell->HandleDOMEventWithTarget(mForm, &event, &status); shell->HandleDOMEventWithTarget(mForm, &event, &status);
} }
@ -3393,7 +3393,7 @@ HTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
// just because we raised a window. // just because we raised a window.
nsIFocusManager* fm = nsFocusManager::GetFocusManager(); nsIFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm && IsSingleLineTextControl(false) && if (fm && IsSingleLineTextControl(false) &&
!(static_cast<nsFocusEvent*>(aVisitor.mEvent))->fromRaise && !(static_cast<InternalFocusEvent*>(aVisitor.mEvent))->fromRaise &&
SelectTextFieldOnFocus()) { SelectTextFieldOnFocus()) {
nsIDocument* document = GetCurrentDoc(); nsIDocument* document = GetCurrentDoc();
if (document) { if (document) {
@ -3616,8 +3616,8 @@ HTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
case NS_FORM_INPUT_SUBMIT: case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_IMAGE: case NS_FORM_INPUT_IMAGE:
if (mForm) { if (mForm) {
nsFormEvent event(true, (mType == NS_FORM_INPUT_RESET) ? InternalFormEvent event(true,
NS_FORM_RESET : NS_FORM_SUBMIT); (mType == NS_FORM_INPUT_RESET) ? NS_FORM_RESET : NS_FORM_SUBMIT);
event.originator = this; event.originator = this;
nsEventStatus status = nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;
@ -3709,7 +3709,8 @@ HTMLInputElement::PostHandleEventForRangeThumb(nsEventChainPostVisitor& aVisitor
CancelRangeThumbDrag(); CancelRangeThumbDrag();
} }
} else { } else {
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aVisitor.mEvent); WidgetTouchEvent* touchEvent =
static_cast<WidgetTouchEvent*>(aVisitor.mEvent);
if (touchEvent->touches.Length() == 1) { if (touchEvent->touches.Length() == 1) {
StartRangeThumbDrag(inputEvent); StartRangeThumbDrag(inputEvent);
} else if (mIsDraggingRange) { } else if (mIsDraggingRange) {

View File

@ -68,6 +68,7 @@
#include "nsHostObjectProtocolHandler.h" #include "nsHostObjectProtocolHandler.h"
#include "mozilla/dom/MediaSource.h" #include "mozilla/dom/MediaSource.h"
#include "MediaMetadataManager.h" #include "MediaMetadataManager.h"
#include "MediaSourceDecoder.h"
#include "AudioChannelService.h" #include "AudioChannelService.h"
@ -601,7 +602,7 @@ void HTMLMediaElement::AbortExistingLoads()
EndSrcMediaStreamPlayback(); EndSrcMediaStreamPlayback();
} }
if (mMediaSource) { if (mMediaSource) {
mMediaSource->DetachElement(); mMediaSource->Detach();
mMediaSource = nullptr; mMediaSource = nullptr;
} }
if (mAudioStream) { if (mAudioStream) {
@ -1135,16 +1136,15 @@ nsresult HTMLMediaElement::LoadResource()
return rv; return rv;
} }
mMediaSource = source.forget(); mMediaSource = source.forget();
if (!mMediaSource->AttachElement(this)) { nsRefPtr<MediaSourceDecoder> decoder = new MediaSourceDecoder(this);
// XXX(kinetik): Handle failure: run "If the media data cannot be if (!mMediaSource->Attach(decoder)) {
// fetched at all, due to network errors, causing the user agent to // TODO: Handle failure: run "If the media data cannot be fetched at
// give up trying to fetch the resource" section of resource fetch // all, due to network errors, causing the user agent to give up
// algorithm. // trying to fetch the resource" section of resource fetch algorithm.
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
// XXX(kinetik): Bug 881512. Wire this up properly; return from here (as nsRefPtr<MediaResource> resource = new MediaSourceResource();
// MediaStreams setup does) rather than relying on mediasource->channel return FinishDecoderSetup(decoder, resource, nullptr, nullptr);
// conversion.
} }
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup(); nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
@ -1406,6 +1406,7 @@ HTMLMediaElement::Seekable() const
} else if (mDecoder && mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) { } else if (mDecoder && mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) {
mDecoder->GetSeekable(ranges); mDecoder->GetSeekable(ranges);
} }
ranges->Normalize();
return ranges.forget(); return ranges.forget();
} }
@ -1989,7 +1990,7 @@ HTMLMediaElement::~HTMLMediaElement()
EndSrcMediaStreamPlayback(); EndSrcMediaStreamPlayback();
} }
if (mMediaSource) { if (mMediaSource) {
mMediaSource->DetachElement(); mMediaSource->Detach();
mMediaSource = nullptr; mMediaSource = nullptr;
} }
@ -3561,6 +3562,7 @@ HTMLMediaElement::Buffered() const
// time ranges we found up till the error. // time ranges we found up till the error.
mDecoder->GetBuffered(ranges); mDecoder->GetBuffered(ranges);
} }
ranges->Normalize();
return ranges.forget(); return ranges.forget();
} }

View File

@ -24,7 +24,6 @@ SimpleTest.waitForExplicitFinish();
function testViewport() { function testViewport() {
/* We need to access the document headers, which are chrome-only. */ /* We need to access the document headers, which are chrome-only. */
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
/* Grab Viewport Metadata from the document header. */ /* Grab Viewport Metadata from the document header. */
var windowUtils = SpecialPowers.getDOMWindowUtils(window); var windowUtils = SpecialPowers.getDOMWindowUtils(window);

View File

@ -20,7 +20,7 @@ namespace mozilla {
class BufferDecoder : public AbstractMediaDecoder class BufferDecoder : public AbstractMediaDecoder
{ {
public: public:
// This class holds a weak pointer to MediaResouce. It's the responsibility // This class holds a weak pointer to MediaResource. It's the responsibility
// of the caller to manage the memory of the MediaResource object. // of the caller to manage the memory of the MediaResource object.
explicit BufferDecoder(MediaResource* aResource); explicit BufferDecoder(MediaResource* aResource);
virtual ~BufferDecoder(); virtual ~BufferDecoder();
@ -30,51 +30,51 @@ public:
// This has to be called before decoding begins // This has to be called before decoding begins
void BeginDecoding(nsIThread* aDecodeThread); void BeginDecoding(nsIThread* aDecodeThread);
ReentrantMonitor& GetReentrantMonitor() MOZ_OVERRIDE; virtual ReentrantMonitor& GetReentrantMonitor() MOZ_OVERRIDE;
bool IsShutdown() const MOZ_FINAL MOZ_OVERRIDE; virtual bool IsShutdown() const MOZ_FINAL MOZ_OVERRIDE;
bool OnStateMachineThread() const MOZ_OVERRIDE; virtual bool OnStateMachineThread() const MOZ_OVERRIDE;
bool OnDecodeThread() const MOZ_OVERRIDE; virtual bool OnDecodeThread() const MOZ_OVERRIDE;
MediaResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE; virtual MediaResource* GetResource() const MOZ_OVERRIDE;
void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE; virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_FINAL MOZ_OVERRIDE; virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_FINAL MOZ_OVERRIDE;
int64_t GetEndMediaTime() const MOZ_FINAL MOZ_OVERRIDE; virtual int64_t GetEndMediaTime() const MOZ_FINAL MOZ_OVERRIDE;
int64_t GetMediaDuration() MOZ_FINAL MOZ_OVERRIDE; virtual int64_t GetMediaDuration() MOZ_FINAL MOZ_OVERRIDE;
void SetMediaDuration(int64_t aDuration) MOZ_OVERRIDE; virtual void SetMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_OVERRIDE; virtual void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE; virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
void SetTransportSeekable(bool aTransportSeekable) MOZ_OVERRIDE; virtual void SetTransportSeekable(bool aTransportSeekable) MOZ_OVERRIDE;
VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE; virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE; virtual layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
bool IsTransportSeekable() MOZ_FINAL MOZ_OVERRIDE; virtual bool IsTransportSeekable() MOZ_FINAL MOZ_OVERRIDE;
bool IsMediaSeekable() MOZ_FINAL MOZ_OVERRIDE; virtual bool IsMediaSeekable() MOZ_FINAL MOZ_OVERRIDE;
void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE; virtual void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
void QueueMetadata(int64_t aTime, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE; virtual void QueueMetadata(int64_t aTime, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
void SetMediaEndTime(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE; virtual void SetMediaEndTime(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
void UpdatePlaybackPosition(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE; virtual void UpdatePlaybackPosition(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
void OnReadMetadataCompleted() MOZ_FINAL MOZ_OVERRIDE; virtual void OnReadMetadataCompleted() MOZ_FINAL MOZ_OVERRIDE;
MediaDecoderOwner* GetOwner() MOZ_FINAL MOZ_OVERRIDE; virtual MediaDecoderOwner* GetOwner() MOZ_FINAL MOZ_OVERRIDE;
private: protected:
// This monitor object is not really used to synchronize access to anything. // This monitor object is not really used to synchronize access to anything.
// It's just there in order for us to be able to override // It's just there in order for us to be able to override
// GetReentrantMonitor correctly. // GetReentrantMonitor correctly.

View File

@ -535,8 +535,8 @@ nsresult MediaDecoderReader::DecodeToTarget(int64_t aTarget)
const AudioData* audio = AudioQueue().PeekFront(); const AudioData* audio = AudioQueue().PeekFront();
if (!audio) if (!audio)
break; break;
CheckedInt64 startFrame = UsecsToFrames(audio->mTime, mInfo.mAudioRate); CheckedInt64 startFrame = UsecsToFrames(audio->mTime, mInfo.mAudio.mRate);
CheckedInt64 targetFrame = UsecsToFrames(aTarget, mInfo.mAudioRate); CheckedInt64 targetFrame = UsecsToFrames(aTarget, mInfo.mAudio.mRate);
if (!startFrame.isValid() || !targetFrame.isValid()) { if (!startFrame.isValid() || !targetFrame.isValid()) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -580,7 +580,7 @@ nsresult MediaDecoderReader::DecodeToTarget(int64_t aTarget)
memcpy(audioData.get(), memcpy(audioData.get(),
audio->mAudioData.get() + (framesToPrune * channels), audio->mAudioData.get() + (framesToPrune * channels),
frames * channels * sizeof(AudioDataValue)); frames * channels * sizeof(AudioDataValue));
CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudioRate); CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudio.mRate);
if (!duration.isValid()) { if (!duration.isValid()) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }

View File

@ -31,11 +31,8 @@ class TimeRanges;
class VideoInfo { class VideoInfo {
public: public:
VideoInfo() VideoInfo()
: mAudioRate(44100), : mDisplay(0,0),
mAudioChannels(2),
mDisplay(0,0),
mStereoMode(STEREO_MODE_MONO), mStereoMode(STEREO_MODE_MONO),
mHasAudio(false),
mHasVideo(false) mHasVideo(false)
{} {}
@ -47,12 +44,6 @@ public:
const nsIntRect& aPicture, const nsIntRect& aPicture,
const nsIntSize& aDisplay); const nsIntSize& aDisplay);
// Sample rate.
uint32_t mAudioRate;
// Number of audio channels.
uint32_t mAudioChannels;
// Size in pixels at which the video is rendered. This is after it has // Size in pixels at which the video is rendered. This is after it has
// been scaled by its aspect ratio. // been scaled by its aspect ratio.
nsIntSize mDisplay; nsIntSize mDisplay;
@ -60,13 +51,49 @@ public:
// Indicates the frame layout for single track stereo videos. // Indicates the frame layout for single track stereo videos.
StereoMode mStereoMode; StereoMode mStereoMode;
// True if we have an active audio bitstream.
bool mHasAudio;
// True if we have an active video bitstream. // True if we have an active video bitstream.
bool mHasVideo; bool mHasVideo;
}; };
class AudioInfo {
public:
AudioInfo()
: mRate(44100),
mChannels(2),
mHasAudio(false)
{}
// Sample rate.
uint32_t mRate;
// Number of audio channels.
uint32_t mChannels;
// True if we have an active audio bitstream.
bool mHasAudio;
};
class MediaInfo {
public:
bool HasVideo() const
{
return mVideo.mHasVideo;
}
bool HasAudio() const
{
return mAudio.mHasAudio;
}
bool HasValidMedia() const
{
return HasVideo() || HasAudio();
}
VideoInfo mVideo;
AudioInfo mAudio;
};
// Holds chunk a decoded audio frames. // Holds chunk a decoded audio frames.
class AudioData { class AudioData {
public: public:
@ -448,7 +475,7 @@ public:
// the data required to present the media, and optionally fills *aTags // the data required to present the media, and optionally fills *aTags
// with tag metadata from the file. // with tag metadata from the file.
// Returns NS_OK on success, or NS_ERROR_FAILURE on failure. // Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
virtual nsresult ReadMetadata(VideoInfo* aInfo, virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) = 0; MetadataTags** aTags) = 0;
// Stores the presentation time of the first frame we'd be able to play if // Stores the presentation time of the first frame we'd be able to play if
@ -558,7 +585,7 @@ protected:
AbstractMediaDecoder* mDecoder; AbstractMediaDecoder* mDecoder;
// Stores presentation info required for playback. // Stores presentation info required for playback.
VideoInfo mInfo; MediaInfo mInfo;
// Whether we should accept media that we know we can't play // Whether we should accept media that we know we can't play
// directly, because they have a number of channel higher than // directly, because they have a number of channel higher than

View File

@ -558,9 +558,9 @@ void MediaDecoderStateMachine::SendStreamAudio(AudioData* aAudio,
// This logic has to mimic AudioLoop closely to make sure we write // This logic has to mimic AudioLoop closely to make sure we write
// the exact same silences // the exact same silences
CheckedInt64 audioWrittenOffset = UsecsToFrames(mInfo.mAudioRate, CheckedInt64 audioWrittenOffset = UsecsToFrames(mInfo.mAudio.mRate,
aStream->mInitialTime + mStartTime) + aStream->mAudioFramesWritten; aStream->mInitialTime + mStartTime) + aStream->mAudioFramesWritten;
CheckedInt64 frameOffset = UsecsToFrames(mInfo.mAudioRate, aAudio->mTime); CheckedInt64 frameOffset = UsecsToFrames(mInfo.mAudio.mRate, aAudio->mTime);
if (!audioWrittenOffset.isValid() || !frameOffset.isValid()) if (!audioWrittenOffset.isValid() || !frameOffset.isValid())
return; return;
if (audioWrittenOffset.value() < frameOffset.value()) { if (audioWrittenOffset.value() < frameOffset.value()) {
@ -641,18 +641,18 @@ void MediaDecoderStateMachine::SendStreamData()
StreamTime endPosition = 0; StreamTime endPosition = 0;
if (!stream->mStreamInitialized) { if (!stream->mStreamInitialized) {
if (mInfo.mHasAudio) { if (mInfo.HasAudio()) {
AudioSegment* audio = new AudioSegment(); AudioSegment* audio = new AudioSegment();
mediaStream->AddTrack(TRACK_AUDIO, mInfo.mAudioRate, 0, audio); mediaStream->AddTrack(TRACK_AUDIO, mInfo.mAudio.mRate, 0, audio);
} }
if (mInfo.mHasVideo) { if (mInfo.HasVideo()) {
VideoSegment* video = new VideoSegment(); VideoSegment* video = new VideoSegment();
mediaStream->AddTrack(TRACK_VIDEO, RATE_VIDEO, 0, video); mediaStream->AddTrack(TRACK_VIDEO, RATE_VIDEO, 0, video);
} }
stream->mStreamInitialized = true; stream->mStreamInitialized = true;
} }
if (mInfo.mHasAudio) { if (mInfo.HasAudio()) {
nsAutoTArray<AudioData*,10> audio; nsAutoTArray<AudioData*,10> audio;
// It's OK to hold references to the AudioData because while audio // It's OK to hold references to the AudioData because while audio
// is captured, only the decoder thread pops from the queue (see below). // is captured, only the decoder thread pops from the queue (see below).
@ -670,10 +670,10 @@ void MediaDecoderStateMachine::SendStreamData()
} }
minLastAudioPacketTime = std::min(minLastAudioPacketTime, stream->mLastAudioPacketTime); minLastAudioPacketTime = std::min(minLastAudioPacketTime, stream->mLastAudioPacketTime);
endPosition = std::max(endPosition, endPosition = std::max(endPosition,
TicksToTimeRoundDown(mInfo.mAudioRate, stream->mAudioFramesWritten)); TicksToTimeRoundDown(mInfo.mAudio.mRate, stream->mAudioFramesWritten));
} }
if (mInfo.mHasVideo) { if (mInfo.HasVideo()) {
nsAutoTArray<VideoData*,10> video; nsAutoTArray<VideoData*,10> video;
// It's OK to hold references to the VideoData only the decoder thread // It's OK to hold references to the VideoData only the decoder thread
// pops from the queue. // pops from the queue.
@ -723,8 +723,8 @@ void MediaDecoderStateMachine::SendStreamData()
} }
bool finished = bool finished =
(!mInfo.mHasAudio || mReader->AudioQueue().IsFinished()) && (!mInfo.HasAudio() || mReader->AudioQueue().IsFinished()) &&
(!mInfo.mHasVideo || mReader->VideoQueue().IsFinished()); (!mInfo.HasVideo() || mReader->VideoQueue().IsFinished());
if (finished && !stream->mHaveSentFinish) { if (finished && !stream->mHaveSentFinish) {
stream->mHaveSentFinish = true; stream->mHaveSentFinish = true;
stream->mStream->Finish(); stream->mStream->Finish();
@ -1045,8 +1045,8 @@ void MediaDecoderStateMachine::AudioLoop()
mAudioCompleted = false; mAudioCompleted = false;
audioStartTime = mAudioStartTime; audioStartTime = mAudioStartTime;
NS_ASSERTION(audioStartTime != -1, "Should have audio start time by now"); NS_ASSERTION(audioStartTime != -1, "Should have audio start time by now");
channels = mInfo.mAudioChannels; channels = mInfo.mAudio.mChannels;
rate = mInfo.mAudioRate; rate = mInfo.mAudio.mRate;
audioChannelType = mDecoder->GetAudioChannelType(); audioChannelType = mDecoder->GetAudioChannelType();
volume = mVolume; volume = mVolume;
@ -1898,7 +1898,7 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
LOG(PR_LOG_DEBUG, ("%p Decoding Media Headers", mDecoder.get())); LOG(PR_LOG_DEBUG, ("%p Decoding Media Headers", mDecoder.get()));
nsresult res; nsresult res;
VideoInfo info; MediaInfo info;
MetadataTags* tags; MetadataTags* tags;
{ {
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
@ -1912,7 +1912,7 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
mInfo = info; mInfo = info;
if (NS_FAILED(res) || (!info.mHasVideo && !info.mHasAudio)) { if (NS_FAILED(res) || (!info.HasValidMedia())) {
// Dispatch the event to call DecodeError synchronously. This ensures // Dispatch the event to call DecodeError synchronously. This ensures
// we're in shutdown state by the time we exit the decode thread. // we're in shutdown state by the time we exit the decode thread.
// If we just moved to shutdown state here on the decode thread, we may // If we just moved to shutdown state here on the decode thread, we may
@ -1957,18 +1957,18 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
// if there is audio, let the MozAudioAvailable event manager know about // if there is audio, let the MozAudioAvailable event manager know about
// the metadata. // the metadata.
if (HasAudio()) { if (HasAudio()) {
mEventManager.Init(mInfo.mAudioChannels, mInfo.mAudioRate); mEventManager.Init(mInfo.mAudio.mChannels, mInfo.mAudio.mRate);
// Set the buffer length at the decoder level to be able, to be able // Set the buffer length at the decoder level to be able, to be able
// to retrive the value via media element method. The RequestFrameBufferLength // to retrive the value via media element method. The RequestFrameBufferLength
// will call the MediaDecoderStateMachine::SetFrameBufferLength(). // will call the MediaDecoderStateMachine::SetFrameBufferLength().
uint32_t frameBufferLength = mInfo.mAudioChannels * FRAMEBUFFER_LENGTH_PER_CHANNEL; uint32_t frameBufferLength = mInfo.mAudio.mChannels * FRAMEBUFFER_LENGTH_PER_CHANNEL;
mDecoder->RequestFrameBufferLength(frameBufferLength); mDecoder->RequestFrameBufferLength(frameBufferLength);
} }
nsCOMPtr<nsIRunnable> metadataLoadedEvent = nsCOMPtr<nsIRunnable> metadataLoadedEvent =
new AudioMetadataEventRunner(mDecoder, new AudioMetadataEventRunner(mDecoder,
mInfo.mAudioChannels, mInfo.mAudio.mChannels,
mInfo.mAudioRate, mInfo.mAudio.mRate,
HasAudio(), HasAudio(),
HasVideo(), HasVideo(),
tags); tags);

View File

@ -228,14 +228,14 @@ public:
// The decoder monitor must be obtained before calling this. // The decoder monitor must be obtained before calling this.
bool HasAudio() const { bool HasAudio() const {
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn(); mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
return mInfo.mHasAudio; return mInfo.HasAudio();
} }
// This is called on the state machine thread and audio thread. // This is called on the state machine thread and audio thread.
// The decoder monitor must be obtained before calling this. // The decoder monitor must be obtained before calling this.
bool HasVideo() const { bool HasVideo() const {
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn(); mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
return mInfo.mHasVideo; return mInfo.HasVideo();
} }
// Should be called by main thread. // Should be called by main thread.
@ -810,7 +810,7 @@ private:
// Stores presentation info required for playback. The decoder monitor // Stores presentation info required for playback. The decoder monitor
// must be held when accessing this. // must be held when accessing this.
VideoInfo mInfo; MediaInfo mInfo;
mozilla::MediaMetadataManager mMetadataManager; mozilla::MediaMetadataManager mMetadataManager;

View File

@ -360,7 +360,7 @@ GetProperty(AudioFileStreamID aAudioFileStream,
nsresult nsresult
AppleMP3Reader::ReadMetadata(VideoInfo* aInfo, AppleMP3Reader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MetadataTags** aTags)
{ {
MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread"); MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread");
@ -398,9 +398,9 @@ AppleMP3Reader::ReadMetadata(VideoInfo* aInfo,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
aInfo->mAudioRate = mAudioSampleRate; aInfo->mAudio.mRate = mAudioSampleRate;
aInfo->mAudioChannels = mAudioChannels; aInfo->mAudio.mChannels = mAudioChannels;
aInfo->mHasAudio = mStreamReady; aInfo->mAudio.mHasAudio = mStreamReady;
{ {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());

View File

@ -30,7 +30,7 @@ public:
virtual bool HasAudio() MOZ_OVERRIDE; virtual bool HasAudio() MOZ_OVERRIDE;
virtual bool HasVideo() MOZ_OVERRIDE; virtual bool HasVideo() MOZ_OVERRIDE;
virtual nsresult ReadMetadata(VideoInfo* aInfo, virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MOZ_OVERRIDE; MetadataTags** aTags) MOZ_OVERRIDE;
virtual nsresult Seek(int64_t aTime, virtual nsresult Seek(int64_t aTime,

View File

@ -172,7 +172,7 @@ DASHReader::DecodeAudioData()
} }
nsresult nsresult
DASHReader::ReadMetadata(VideoInfo* aInfo, DASHReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MetadataTags** aTags)
{ {
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@ -191,7 +191,7 @@ DASHReader::ReadMetadata(VideoInfo* aInfo,
*aTags = nullptr; *aTags = nullptr;
// Get metadata from child readers. // Get metadata from child readers.
VideoInfo audioInfo, videoInfo; MediaInfo audioInfo, videoInfo;
// Read metadata for all video streams. // Read metadata for all video streams.
for (uint i = 0; i < mVideoReaders.Length(); i++) { for (uint i = 0; i < mVideoReaders.Length(); i++) {
@ -201,8 +201,7 @@ DASHReader::ReadMetadata(VideoInfo* aInfo,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Use metadata from current video sub reader to populate aInfo. // Use metadata from current video sub reader to populate aInfo.
if (mVideoReaders[i] == mVideoReader) { if (mVideoReaders[i] == mVideoReader) {
mInfo.mHasVideo = videoInfo.mHasVideo; mInfo.mVideo = videoInfo.mVideo;
mInfo.mDisplay = videoInfo.mDisplay;
} }
} }
// Read metadata for audio stream. // Read metadata for audio stream.
@ -211,10 +210,7 @@ DASHReader::ReadMetadata(VideoInfo* aInfo,
if (mAudioReader) { if (mAudioReader) {
rv = mAudioReader->ReadMetadata(&audioInfo, aTags); rv = mAudioReader->ReadMetadata(&audioInfo, aTags);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
mInfo.mHasAudio = audioInfo.mHasAudio; mInfo.mAudio = audioInfo.mAudio;
mInfo.mAudioRate = audioInfo.mAudioRate;
mInfo.mAudioChannels = audioInfo.mAudioChannels;
mInfo.mStereoMode = audioInfo.mStereoMode;
} }
*aInfo = mInfo; *aInfo = mInfo;

View File

@ -38,7 +38,7 @@ public:
// Waits for metadata bytes to be downloaded, then reads and parses them. // Waits for metadata bytes to be downloaded, then reads and parses them.
// Called on the decode thread only. // Called on the decode thread only.
nsresult ReadMetadata(VideoInfo* aInfo, nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MOZ_OVERRIDE; MetadataTags** aTags) MOZ_OVERRIDE;
// Waits for |ReadyToReadMetadata| or |NotifyDecoderShuttingDown| // Waits for |ReadyToReadMetadata| or |NotifyDecoderShuttingDown|

View File

@ -73,7 +73,7 @@ static const GUID CLSID_MPEG_LAYER_3_DECODER_FILTER =
{ 0x38BE3000, 0xDBF4, 0x11D0, 0x86, 0x0E, 0x00, 0xA0, 0x24, 0xCF, 0xEF, 0x6D }; { 0x38BE3000, 0xDBF4, 0x11D0, 0x86, 0x0E, 0x00, 0xA0, 0x24, 0xCF, 0xEF, 0x6D };
nsresult nsresult
DirectShowReader::ReadMetadata(VideoInfo* aInfo, DirectShowReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MetadataTags** aTags)
{ {
MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread."); MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@ -164,11 +164,10 @@ DirectShowReader::ReadMetadata(VideoInfo* aInfo,
mAudioSinkFilter->GetSampleSink()->GetAudioFormat(&format); mAudioSinkFilter->GetSampleSink()->GetAudioFormat(&format);
NS_ENSURE_TRUE(format.wFormatTag == WAVE_FORMAT_PCM, NS_ERROR_FAILURE); NS_ENSURE_TRUE(format.wFormatTag == WAVE_FORMAT_PCM, NS_ERROR_FAILURE);
mInfo.mAudioChannels = mNumChannels = format.nChannels; mInfo.mAudio.mChannels = mNumChannels = format.nChannels;
mInfo.mAudioRate = mAudioRate = format.nSamplesPerSec; mInfo.mAudio.mRate = mAudioRate = format.nSamplesPerSec;
mBytesPerSample = format.wBitsPerSample / 8; mBytesPerSample = format.wBitsPerSample / 8;
mInfo.mHasAudio = true; mInfo.mAudio.mHasAudio = true;
mInfo.mHasVideo = false;
*aInfo = mInfo; *aInfo = mInfo;
// Note: The SourceFilter strips ID3v2 tags out of the stream. // Note: The SourceFilter strips ID3v2 tags out of the stream.
@ -194,8 +193,8 @@ DirectShowReader::ReadMetadata(VideoInfo* aInfo,
LOG("Successfully initialized DirectShow MP3 decoder."); LOG("Successfully initialized DirectShow MP3 decoder.");
LOG("Channels=%u Hz=%u duration=%lld bytesPerSample=%d", LOG("Channels=%u Hz=%u duration=%lld bytesPerSample=%d",
mInfo.mAudioChannels, mInfo.mAudio.mChannels,
mInfo.mAudioRate, mInfo.mAudio.mRate,
RefTimeToUsecs(duration), RefTimeToUsecs(duration),
mBytesPerSample); mBytesPerSample);

View File

@ -57,7 +57,7 @@ public:
bool HasAudio() MOZ_OVERRIDE; bool HasAudio() MOZ_OVERRIDE;
bool HasVideo() MOZ_OVERRIDE; bool HasVideo() MOZ_OVERRIDE;
nsresult ReadMetadata(VideoInfo* aInfo, nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MOZ_OVERRIDE; MetadataTags** aTags) MOZ_OVERRIDE;
nsresult Seek(int64_t aTime, nsresult Seek(int64_t aTime,

View File

@ -243,7 +243,7 @@ void GStreamerReader::PlayBinSourceSetup(GstAppSrc* aSource)
gst_caps_unref(caps); gst_caps_unref(caps);
} }
nsresult GStreamerReader::ReadMetadata(VideoInfo* aInfo, nsresult GStreamerReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MetadataTags** aTags)
{ {
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@ -354,8 +354,8 @@ nsresult GStreamerReader::ReadMetadata(VideoInfo* aInfo,
int n_video = 0, n_audio = 0; int n_video = 0, n_audio = 0;
g_object_get(mPlayBin, "n-video", &n_video, "n-audio", &n_audio, nullptr); g_object_get(mPlayBin, "n-video", &n_video, "n-audio", &n_audio, nullptr);
mInfo.mHasVideo = n_video != 0; mInfo.mVideo.mHasVideo = n_video != 0;
mInfo.mHasAudio = n_audio != 0; mInfo.mAudio.mHasAudio = n_audio != 0;
*aInfo = mInfo; *aInfo = mInfo;
@ -490,12 +490,12 @@ bool GStreamerReader::DecodeAudioData()
int64_t offset = GST_BUFFER_OFFSET(buffer); int64_t offset = GST_BUFFER_OFFSET(buffer);
unsigned int size = GST_BUFFER_SIZE(buffer); unsigned int size = GST_BUFFER_SIZE(buffer);
int32_t frames = (size / sizeof(AudioDataValue)) / mInfo.mAudioChannels; int32_t frames = (size / sizeof(AudioDataValue)) / mInfo.mAudio.mChannels;
ssize_t outSize = static_cast<size_t>(size / sizeof(AudioDataValue)); ssize_t outSize = static_cast<size_t>(size / sizeof(AudioDataValue));
nsAutoArrayPtr<AudioDataValue> data(new AudioDataValue[outSize]); nsAutoArrayPtr<AudioDataValue> data(new AudioDataValue[outSize]);
memcpy(data, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); memcpy(data, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer));
AudioData* audio = new AudioData(offset, timestamp, duration, AudioData* audio = new AudioData(offset, timestamp, duration,
frames, data.forget(), mInfo.mAudioChannels); frames, data.forget(), mInfo.mAudio.mChannels);
mAudioQueue.Push(audio); mAudioQueue.Push(audio);
gst_buffer_unref(buffer); gst_buffer_unref(buffer);
@ -623,7 +623,7 @@ bool GStreamerReader::DecodeVideoFrame(bool &aKeyFrameSkip,
isKeyframe = !GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT); isKeyframe = !GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
/* XXX ? */ /* XXX ? */
int64_t offset = 0; int64_t offset = 0;
VideoData* video = VideoData::Create(mInfo, image, offset, VideoData* video = VideoData::Create(mInfo.mVideo, image, offset,
timestamp, nextTimestamp, b, timestamp, nextTimestamp, b,
isKeyframe, -1, mPicture); isKeyframe, -1, mPicture);
mVideoQueue.Push(video); mVideoQueue.Push(video);
@ -656,7 +656,7 @@ nsresult GStreamerReader::Seek(int64_t aTarget,
nsresult GStreamerReader::GetBuffered(TimeRanges* aBuffered, nsresult GStreamerReader::GetBuffered(TimeRanges* aBuffered,
int64_t aStartTime) int64_t aStartTime)
{ {
if (!mInfo.mHasVideo && !mInfo.mHasAudio) { if (!mInfo.HasValidMedia()) {
return NS_OK; return NS_OK;
} }
@ -933,14 +933,14 @@ void GStreamerReader::AudioPreroll()
GstPad* sinkpad = gst_element_get_pad(GST_ELEMENT(mAudioAppSink), "sink"); GstPad* sinkpad = gst_element_get_pad(GST_ELEMENT(mAudioAppSink), "sink");
GstCaps* caps = gst_pad_get_negotiated_caps(sinkpad); GstCaps* caps = gst_pad_get_negotiated_caps(sinkpad);
GstStructure* s = gst_caps_get_structure(caps, 0); GstStructure* s = gst_caps_get_structure(caps, 0);
mInfo.mAudioRate = mInfo.mAudioChannels = 0; mInfo.mAudio.mRate = mInfo.mAudio.mChannels = 0;
gst_structure_get_int(s, "rate", (gint*) &mInfo.mAudioRate); gst_structure_get_int(s, "rate", (gint*) &mInfo.mAudio.mRate);
gst_structure_get_int(s, "channels", (gint*) &mInfo.mAudioChannels); gst_structure_get_int(s, "channels", (gint*) &mInfo.mAudio.mChannels);
NS_ASSERTION(mInfo.mAudioRate != 0, ("audio rate is zero")); NS_ASSERTION(mInfo.mAudio.mRate != 0, ("audio rate is zero"));
NS_ASSERTION(mInfo.mAudioChannels != 0, ("audio channels is zero")); NS_ASSERTION(mInfo.mAudio.mChannels != 0, ("audio channels is zero"));
NS_ASSERTION(mInfo.mAudioChannels > 0 && mInfo.mAudioChannels <= MAX_CHANNELS, NS_ASSERTION(mInfo.mAudio.mChannels > 0 && mInfo.mAudio.mChannels <= MAX_CHANNELS,
"invalid audio channels number"); "invalid audio channels number");
mInfo.mHasAudio = true; mInfo.mAudio.mHasAudio = true;
gst_caps_unref(caps); gst_caps_unref(caps);
gst_object_unref(sinkpad); gst_object_unref(sinkpad);
} }
@ -955,8 +955,8 @@ void GStreamerReader::VideoPreroll()
GstStructure* structure = gst_caps_get_structure(caps, 0); GstStructure* structure = gst_caps_get_structure(caps, 0);
gst_structure_get_fraction(structure, "framerate", &fpsNum, &fpsDen); gst_structure_get_fraction(structure, "framerate", &fpsNum, &fpsDen);
NS_ASSERTION(mPicture.width && mPicture.height, "invalid video resolution"); NS_ASSERTION(mPicture.width && mPicture.height, "invalid video resolution");
mInfo.mDisplay = nsIntSize(mPicture.width, mPicture.height); mInfo.mVideo.mDisplay = nsIntSize(mPicture.width, mPicture.height);
mInfo.mHasVideo = true; mInfo.mVideo.mHasVideo = true;
gst_caps_unref(caps); gst_caps_unref(caps);
gst_object_unref(sinkpad); gst_object_unref(sinkpad);
} }

View File

@ -44,7 +44,7 @@ public:
virtual bool DecodeAudioData(); virtual bool DecodeAudioData();
virtual bool DecodeVideoFrame(bool &aKeyframeSkip, virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
int64_t aTimeThreshold); int64_t aTimeThreshold);
virtual nsresult ReadMetadata(VideoInfo* aInfo, virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags); MetadataTags** aTags);
virtual nsresult Seek(int64_t aTime, virtual nsresult Seek(int64_t aTime,
int64_t aStartTime, int64_t aStartTime,
@ -53,11 +53,11 @@ public:
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime); virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime);
virtual bool HasAudio() { virtual bool HasAudio() {
return mInfo.mHasAudio; return mInfo.HasAudio();
} }
virtual bool HasVideo() { virtual bool HasVideo() {
return mInfo.mHasVideo; return mInfo.HasVideo();
} }
private: private:

View File

@ -12,15 +12,15 @@
namespace mozilla { namespace mozilla {
template <typename T> template <typename T>
class AsyncEventRunnner : public nsRunnable class AsyncEventRunner : public nsRunnable
{ {
public: public:
AsyncEventRunnner(T* aTarget, const char* aName) AsyncEventRunner(T* aTarget, const char* aName)
: mTarget(aTarget) : mTarget(aTarget)
, mName(aName) , mName(aName)
{} {}
NS_IMETHOD Run() NS_IMETHOD Run() MOZ_OVERRIDE
{ {
mTarget->DispatchSimpleEvent(mName); mTarget->DispatchSimpleEvent(mName);
return NS_OK; return NS_OK;

View File

@ -6,12 +6,27 @@
#include "MediaSource.h" #include "MediaSource.h"
#include "mozilla/dom/HTMLMediaElement.h" #include "AsyncEventRunner.h"
#include "MediaSourceInputAdapter.h" #include "DecoderTraits.h"
#include "SourceBuffer.h" #include "SourceBuffer.h"
#include "SourceBufferList.h" #include "SourceBufferList.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/mozalloc.h"
#include "nsContentTypeParser.h" #include "nsContentTypeParser.h"
#include "nsIInputStream.h" #include "nsDebug.h"
#include "nsError.h"
#include "nsIEventTarget.h"
#include "nsIRunnable.h"
#include "nsPIDOMWindow.h"
#include "nsStringGlue.h"
#include "nsThreadUtils.h"
#include "prlog.h"
struct JSContext;
class JSObject;
#ifdef PR_LOGGING #ifdef PR_LOGGING
PRLogModuleInfo* gMediaSourceLog; PRLogModuleInfo* gMediaSourceLog;
@ -20,16 +35,12 @@ PRLogModuleInfo* gMediaSourceLog;
#define LOG(type, msg) #define LOG(type, msg)
#endif #endif
namespace mozilla { // Arbitrary limit.
namespace dom { static const unsigned int MAX_SOURCE_BUFFERS = 16;
already_AddRefed<nsIInputStream> namespace mozilla {
MediaSource::CreateInternalStream()
{ namespace dom {
nsRefPtr<MediaSourceInputAdapter> adapter = new MediaSourceInputAdapter(this);
mAdapters.AppendElement(adapter);
return adapter.forget();
}
/* static */ already_AddRefed<MediaSource> /* static */ already_AddRefed<MediaSource>
MediaSource::Constructor(const GlobalObject& aGlobal, MediaSource::Constructor(const GlobalObject& aGlobal,
@ -95,8 +106,7 @@ MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
if (!IsTypeSupportedInternal(aType, aRv)) { if (!IsTypeSupportedInternal(aType, aRv)) {
return nullptr; return nullptr;
} }
// TODO: Temporary limit until multiple decoders are supported. Bug 881512. if (mSourceBuffers->Length() >= MAX_SOURCE_BUFFERS) {
if (mSourceBuffers->Length() >= 1) {
aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR); aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
return nullptr; return nullptr;
} }
@ -104,10 +114,17 @@ MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr; return nullptr;
} }
mContentType = aType; nsContentTypeParser parser(aType);
nsRefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(this); nsAutoString mimeType;
nsresult rv = parser.GetType(mimeType);
if (NS_FAILED(rv)) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
nsRefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(this, NS_ConvertUTF16toUTF8(mimeType));
mSourceBuffers->Append(sourceBuffer); mSourceBuffers->Append(sourceBuffer);
sourceBuffer->Attach(); LOG(PR_LOG_DEBUG, ("%p AddSourceBuffer(Type=%s) -> %p", this,
NS_ConvertUTF16toUTF8(mimeType).get(), sourceBuffer.get()));
return sourceBuffer.forget(); return sourceBuffer.forget();
} }
@ -137,7 +154,6 @@ MediaSource::RemoveSourceBuffer(SourceBuffer& aSourceBuffer, ErrorResult& aRv)
mActiveSourceBuffers->Remove(sourceBuffer); mActiveSourceBuffers->Remove(sourceBuffer);
} }
mSourceBuffers->Remove(sourceBuffer); mSourceBuffers->Remove(sourceBuffer);
sourceBuffer->Detach();
// TODO: Free all resources associated with sourceBuffer // TODO: Free all resources associated with sourceBuffer
} }
@ -160,49 +176,37 @@ MediaSource::IsTypeSupported(const GlobalObject& aGlobal,
return IsTypeSupportedInternal(aType, unused); return IsTypeSupportedInternal(aType, unused);
} }
void
MediaSource::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
MonitorAutoLock mon(mMonitor);
LOG(PR_LOG_DEBUG, ("%p Append(ArrayBuffer=%u) mData=%u", this, aLength, mData.Length()));
mData.AppendElements(aData, aLength);
NotifyListeners();
}
bool bool
MediaSource::AttachElement(HTMLMediaElement* aElement) MediaSource::Attach(MediaSourceDecoder* aDecoder)
{ {
LOG(PR_LOG_DEBUG, ("%p Attaching element %p", this, aElement)); LOG(PR_LOG_DEBUG, ("%p Attaching decoder %p owner %p", this, aDecoder, aDecoder->GetOwner()));
MOZ_ASSERT(aElement); MOZ_ASSERT(aDecoder);
mElement = aElement;
if (mReadyState != MediaSourceReadyState::Closed) { if (mReadyState != MediaSourceReadyState::Closed) {
return false; return false;
} }
mDecoder = aDecoder;
mDecoder->AttachMediaSource(this);
SetReadyState(MediaSourceReadyState::Open); SetReadyState(MediaSourceReadyState::Open);
return true; return true;
} }
void void
MediaSource::DetachElement() MediaSource::Detach()
{ {
LOG(PR_LOG_DEBUG, ("%p Detaching element %p", this, mElement.get())); LOG(PR_LOG_DEBUG, ("%p Detaching decoder %p owner %p", this, mDecoder.get(), mDecoder->GetOwner()));
MOZ_ASSERT(mElement); MOZ_ASSERT(mDecoder);
mElement = nullptr; mDecoder->DetachMediaSource();
mDecoder = nullptr;
mDuration = UnspecifiedNaN(); mDuration = UnspecifiedNaN();
mActiveSourceBuffers->Clear(); mActiveSourceBuffers->Clear();
mSourceBuffers->DetachAndClear(); mSourceBuffers->Clear();
SetReadyState(MediaSourceReadyState::Closed); SetReadyState(MediaSourceReadyState::Closed);
for (uint32_t i = 0; i < mAdapters.Length(); ++i) {
mAdapters[i]->Close();
}
mAdapters.Clear();
} }
MediaSource::MediaSource(nsPIDOMWindow* aWindow) MediaSource::MediaSource(nsPIDOMWindow* aWindow)
: nsDOMEventTargetHelper(aWindow) : nsDOMEventTargetHelper(aWindow)
, mDuration(UnspecifiedNaN()) , mDuration(UnspecifiedNaN())
, mMonitor("mozilla::dom::MediaSource::mMonitor") , mDecoder(nullptr)
, mReadyState(MediaSourceReadyState::Closed) , mReadyState(MediaSourceReadyState::Closed)
{ {
mSourceBuffers = new SourceBufferList(this); mSourceBuffers = new SourceBufferList(this);
@ -219,9 +223,6 @@ void
MediaSource::SetReadyState(MediaSourceReadyState aState) MediaSource::SetReadyState(MediaSourceReadyState aState)
{ {
MOZ_ASSERT(aState != mReadyState); MOZ_ASSERT(aState != mReadyState);
MonitorAutoLock mon(mMonitor);
NotifyListeners();
if ((mReadyState == MediaSourceReadyState::Closed || if ((mReadyState == MediaSourceReadyState::Closed ||
mReadyState == MediaSourceReadyState::Ended) && mReadyState == MediaSourceReadyState::Ended) &&
@ -269,18 +270,10 @@ void
MediaSource::QueueAsyncSimpleEvent(const char* aName) MediaSource::QueueAsyncSimpleEvent(const char* aName)
{ {
LOG(PR_LOG_DEBUG, ("%p Queuing event %s to MediaSource", this, aName)); LOG(PR_LOG_DEBUG, ("%p Queuing event %s to MediaSource", this, aName));
nsCOMPtr<nsIRunnable> event = new AsyncEventRunnner<MediaSource>(this, aName); nsCOMPtr<nsIRunnable> event = new AsyncEventRunner<MediaSource>(this, aName);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
} }
void
MediaSource::NotifyListeners()
{
for (uint32_t i = 0; i < mAdapters.Length(); ++i) {
mAdapters[i]->NotifyListener();
}
}
void void
MediaSource::DurationChange(double aNewDuration, ErrorResult& aRv) MediaSource::DurationChange(double aNewDuration, ErrorResult& aRv)
{ {
@ -303,6 +296,7 @@ void
MediaSource::EndOfStreamInternal(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv) MediaSource::EndOfStreamInternal(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv)
{ {
SetReadyState(MediaSourceReadyState::Ended); SetReadyState(MediaSourceReadyState::Ended);
mSourceBuffers->Ended();
if (!aError.WasPassed()) { if (!aError.WasPassed()) {
// TODO: // TODO:
// Run duration change algorithm. // Run duration change algorithm.
@ -385,8 +379,8 @@ MediaSource::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
return MediaSourceBinding::Wrap(aCx, aScope, this); return MediaSourceBinding::Wrap(aCx, aScope, this);
} }
NS_IMPL_CYCLE_COLLECTION_INHERITED_4(MediaSource, nsDOMEventTargetHelper, NS_IMPL_CYCLE_COLLECTION_INHERITED_2(MediaSource, nsDOMEventTargetHelper,
mSourceBuffers, mActiveSourceBuffers, mAdapters, mElement) mSourceBuffers, mActiveSourceBuffers)
NS_IMPL_ADDREF_INHERITED(MediaSource, nsDOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(MediaSource, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(MediaSource, nsDOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(MediaSource, nsDOMEventTargetHelper)
@ -396,4 +390,5 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaSource)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -7,27 +7,36 @@
#ifndef mozilla_dom_MediaSource_h_ #ifndef mozilla_dom_MediaSource_h_
#define mozilla_dom_MediaSource_h_ #define mozilla_dom_MediaSource_h_
#include "AsyncEventRunner.h" #include "MediaSourceDecoder.h"
#include "js/RootingAPI.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Monitor.h"
#include "mozilla/dom/MediaSourceBinding.h" #include "mozilla/dom/MediaSourceBinding.h"
#include "mozilla/dom/TypedArray.h" #include "nsAutoPtr.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsCycleCollectionNoteChild.h"
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
#include "nsDOMEventTargetHelper.h" #include "nsDOMEventTargetHelper.h"
#include "nsWrapperCache.h" #include "nsID.h"
#include "nsISupports.h"
#include "nscore.h" #include "nscore.h"
class nsIInputStream; struct JSContext;
class JSObject;
class nsPIDOMWindow;
namespace mozilla { namespace mozilla {
class ErrorResult;
template <typename T> class AsyncEventRunner;
namespace dom { namespace dom {
class HTMLMediaElement; class GlobalObject;
class MediaSourceInputAdapter;
class SourceBufferList;
class SourceBuffer; class SourceBuffer;
class SourceBufferList;
class TimeRanges; class TimeRanges;
template <typename T> class Optional;
#define MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID \ #define MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID \
{ 0x3839d699, 0x22c5, 0x439f, \ { 0x3839d699, 0x22c5, 0x439f, \
@ -64,50 +73,28 @@ public:
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE; JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
const nsString& GetType() // Attach this MediaSource to Decoder aDecoder. Returns false if already attached.
{ bool Attach(MediaSourceDecoder* aDecoder);
return mContentType; void Detach();
}
already_AddRefed<nsIInputStream> CreateInternalStream();
void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
// Semi-private, for MediaSourceInputAdapter only.
nsTArray<uint8_t> const& GetData()
{
return mData;
}
Monitor& GetMonitor()
{
return mMonitor;
}
bool AppendDone() const
{
return mReadyState == MediaSourceReadyState::Closed || mReadyState == MediaSourceReadyState::Ended;
}
// Attach this MediaSource to MediaElement aElement. Returns false if already attached.
bool AttachElement(HTMLMediaElement* aElement);
void DetachElement();
// Set mReadyState to aState and fire the required events at the MediaSource. // Set mReadyState to aState and fire the required events at the MediaSource.
void SetReadyState(MediaSourceReadyState aState); void SetReadyState(MediaSourceReadyState aState);
void GetBuffered(TimeRanges* aRanges); void GetBuffered(TimeRanges* aRanges);
// Used by SourceBuffer to call CreateSubDecoder.
MediaSourceDecoder* GetDecoder()
{
return mDecoder;
}
private: private:
explicit MediaSource(nsPIDOMWindow* aWindow); explicit MediaSource(nsPIDOMWindow* aWindow);
friend class AsyncEventRunnner<MediaSource>; friend class AsyncEventRunner<MediaSource>;
void DispatchSimpleEvent(const char* aName); void DispatchSimpleEvent(const char* aName);
void QueueAsyncSimpleEvent(const char* aName); void QueueAsyncSimpleEvent(const char* aName);
void NotifyListeners();
void DurationChange(double aNewDuration, ErrorResult& aRv); void DurationChange(double aNewDuration, ErrorResult& aRv);
void EndOfStreamInternal(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv); void EndOfStreamInternal(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv);
@ -115,25 +102,17 @@ private:
double mDuration; double mDuration;
nsTArray<nsRefPtr<MediaSourceInputAdapter> > mAdapters;
// Protected by monitor.
nsTArray<uint8_t> mData;
// Protects access to mData.
Monitor mMonitor;
nsRefPtr<SourceBufferList> mSourceBuffers; nsRefPtr<SourceBufferList> mSourceBuffers;
nsRefPtr<SourceBufferList> mActiveSourceBuffers; nsRefPtr<SourceBufferList> mActiveSourceBuffers;
nsRefPtr<HTMLMediaElement> mElement; nsRefPtr<MediaSourceDecoder> mDecoder;
nsString mContentType;
MediaSourceReadyState mReadyState; MediaSourceReadyState mReadyState;
}; };
NS_DEFINE_STATIC_IID_ACCESSOR(MediaSource, MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID) NS_DEFINE_STATIC_IID_ACCESSOR(MediaSource, MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla
#endif /* mozilla_dom_MediaSource_h_ */ #endif /* mozilla_dom_MediaSource_h_ */

View File

@ -0,0 +1,209 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaSourceDecoder.h"
#include "AbstractMediaDecoder.h"
#include "MediaDecoderReader.h"
#include "MediaDecoderStateMachine.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/mozalloc.h"
#include "nsISupports.h"
#include "prlog.h"
#include "SubBufferDecoder.h"
#include "SourceBufferResource.h"
#ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaSourceLog;
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
#else
#define LOG(type, msg)
#endif
namespace mozilla {
namespace dom {
class TimeRanges;
} // namespace dom
class MediaSourceReader : public MediaDecoderReader
{
public:
MediaSourceReader(MediaSourceDecoder* aDecoder)
: MediaDecoderReader(aDecoder)
{
}
nsresult Init(MediaDecoderReader* aCloneDonor) MOZ_OVERRIDE
{
return NS_ERROR_NOT_IMPLEMENTED;
}
bool DecodeAudioData() MOZ_OVERRIDE
{
if (GetAudioReader()) {
return GetAudioReader()->DecodeAudioData();
}
return false;
}
bool DecodeVideoFrame(bool& aKeyFrameSkip, int64_t aTimeThreshold) MOZ_OVERRIDE
{
if (GetVideoReader()) {
return GetVideoReader()->DecodeVideoFrame(aKeyFrameSkip, aTimeThreshold);
}
return false;
}
bool HasVideo() MOZ_OVERRIDE
{
return mInfo.HasVideo();
}
bool HasAudio() MOZ_OVERRIDE
{
return mInfo.HasAudio();
}
nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) MOZ_OVERRIDE;
nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
int64_t aCurrentTime) MOZ_OVERRIDE
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime) MOZ_OVERRIDE
{
// XXX: Merge result with audio reader.
return GetVideoReader()->GetBuffered(aBuffered, aStartTime);
}
MediaQueue<AudioData>& AudioQueue() MOZ_OVERRIDE
{
// TODO: Share AudioQueue with SubReaders.
if (GetAudioReader()) {
return GetAudioReader()->AudioQueue();
}
return MediaDecoderReader::AudioQueue();
}
MediaQueue<VideoData>& VideoQueue() MOZ_OVERRIDE
{
// TODO: Share VideoQueue with SubReaders.
if (GetVideoReader()) {
return GetVideoReader()->VideoQueue();
}
return MediaDecoderReader::VideoQueue();
}
private:
MediaDecoderReader* GetVideoReader()
{
MediaSourceDecoder* decoder = static_cast<MediaSourceDecoder*>(mDecoder);
return decoder->GetVideoReader();
}
MediaDecoderReader* GetAudioReader()
{
MediaSourceDecoder* decoder = static_cast<MediaSourceDecoder*>(mDecoder);
return decoder->GetAudioReader();
}
};
MediaSourceDecoder::MediaSourceDecoder(HTMLMediaElement* aElement)
: mMediaSource(nullptr)
, mVideoReader(nullptr),
mAudioReader(nullptr)
{
Init(aElement);
}
MediaDecoder*
MediaSourceDecoder::Clone()
{
// TODO: Sort out cloning.
return nullptr;
}
MediaDecoderStateMachine*
MediaSourceDecoder::CreateStateMachine()
{
return new MediaDecoderStateMachine(this, new MediaSourceReader(this));
}
nsresult
MediaSourceDecoder::Load(nsIStreamListener**, MediaDecoder*)
{
return NS_OK;
}
void
MediaSourceDecoder::AttachMediaSource(MediaSource* aMediaSource)
{
MOZ_ASSERT(!mMediaSource && !mDecoderStateMachine);
mMediaSource = aMediaSource;
mDecoderStateMachine = CreateStateMachine();
}
void
MediaSourceDecoder::DetachMediaSource()
{
mMediaSource = nullptr;
}
SubBufferDecoder*
MediaSourceDecoder::CreateSubDecoder(const nsACString& aType)
{
MediaResource* resource = new SourceBufferResource(nullptr, aType);
nsRefPtr<SubBufferDecoder> decoder = new SubBufferDecoder(resource, this);
nsAutoPtr<MediaDecoderReader> reader(DecoderTraits::CreateReader(aType, decoder));
reader->Init(nullptr);
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mDecoders.AppendElement(decoder);
mReaders.AppendElement(reader);
LOG(PR_LOG_DEBUG, ("Registered subdecoder %p subreader %p", decoder.get(), reader.get()));
mon.NotifyAll();
decoder->SetReader(reader.forget());
return decoder;
}
nsresult
MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
{
mDecoder->SetMediaSeekable(true);
mDecoder->SetTransportSeekable(false);
MediaSourceDecoder* decoder = static_cast<MediaSourceDecoder*>(mDecoder);
const nsTArray<MediaDecoderReader*>& readers = decoder->GetReaders();
for (uint32_t i = 0; i < readers.Length(); ++i) {
MediaDecoderReader* reader = readers[i];
MediaInfo mi;
nsresult rv = reader->ReadMetadata(&mi, aTags);
LOG(PR_LOG_DEBUG, ("ReadMetadata on SB reader %p", reader));
if (NS_FAILED(rv)) {
return rv;
}
if (mi.HasVideo() && !mInfo.HasVideo()) {
mInfo.mVideo = mi.mVideo;
decoder->SetVideoReader(reader);
}
if (mi.HasAudio() && !mInfo.HasAudio()) {
mInfo.mAudio = mi.mAudio;
decoder->SetAudioReader(reader);
}
}
*aInfo = mInfo;
return NS_OK;
}
} // namespace mozilla

View File

@ -0,0 +1,137 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_MEDIASOURCEDECODER_H_
#define MOZILLA_MEDIASOURCEDECODER_H_
#include "MediaCache.h"
#include "MediaDecoder.h"
#include "MediaResource.h"
#include "mozilla/Attributes.h"
#include "mozilla/ReentrantMonitor.h"
#include "nsCOMPtr.h"
#include "nsError.h"
#include "nsStringGlue.h"
#include "nsTArray.h"
class nsIPrincipal;
class nsIStreamListener;
namespace mozilla {
class MediaDecoderReader;
class MediaDecoderStateMachine;
class SubBufferDecoder;
namespace dom {
class HTMLMediaElement;
class MediaSource;
} // namespace dom
class MediaSourceDecoder : public MediaDecoder
{
public:
MediaSourceDecoder(HTMLMediaElement* aElement);
virtual MediaDecoder* Clone() MOZ_OVERRIDE;
virtual MediaDecoderStateMachine* CreateStateMachine() MOZ_OVERRIDE;
virtual nsresult Load(nsIStreamListener**, MediaDecoder*) MOZ_OVERRIDE;
void AttachMediaSource(MediaSource* aMediaSource);
void DetachMediaSource();
SubBufferDecoder* CreateSubDecoder(const nsACString& aType);
const nsTArray<MediaDecoderReader*>& GetReaders()
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
while (mReaders.Length() == 0) {
mon.Wait();
}
return mReaders;
}
void SetVideoReader(MediaDecoderReader* aReader)
{
MOZ_ASSERT(aReader && !mVideoReader);
mVideoReader = aReader;
}
void SetAudioReader(MediaDecoderReader* aReader)
{
MOZ_ASSERT(aReader && !mAudioReader);
mAudioReader = aReader;
}
MediaDecoderReader* GetVideoReader()
{
return mVideoReader;
}
MediaDecoderReader* GetAudioReader()
{
return mAudioReader;
}
private:
MediaSource* mMediaSource;
nsTArray<nsRefPtr<SubBufferDecoder> > mDecoders;
nsTArray<MediaDecoderReader*> mReaders; // Readers owned by Decoders.
MediaDecoderReader* mVideoReader;
MediaDecoderReader* mAudioReader;
};
class MediaSourceResource MOZ_FINAL : public MediaResource
{
public:
MediaSourceResource() {}
virtual nsresult Close() MOZ_OVERRIDE { return NS_OK; }
virtual void Suspend(bool aCloseImmediately) MOZ_OVERRIDE {}
virtual void Resume() MOZ_OVERRIDE {}
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() MOZ_OVERRIDE { return nullptr; }
virtual bool CanClone() MOZ_OVERRIDE { return false; }
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) MOZ_OVERRIDE { return nullptr; }
virtual void SetReadMode(MediaCacheStream::ReadMode aMode) MOZ_OVERRIDE {}
virtual void SetPlaybackRate(uint32_t aBytesPerSecond) MOZ_OVERRIDE {}
virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
virtual nsresult ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
virtual nsresult Seek(int32_t aWhence, int64_t aOffset) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
virtual void StartSeekingForMetadata() MOZ_OVERRIDE {}
virtual void EndSeekingForMetadata() MOZ_OVERRIDE {}
virtual int64_t Tell() MOZ_OVERRIDE { return -1; }
virtual void Pin() MOZ_OVERRIDE {}
virtual void Unpin() MOZ_OVERRIDE {}
virtual double GetDownloadRate(bool* aIsReliable) MOZ_OVERRIDE { return 0; }
virtual int64_t GetLength() MOZ_OVERRIDE { return -1; }
virtual int64_t GetNextCachedData(int64_t aOffset) MOZ_OVERRIDE { return aOffset; }
virtual int64_t GetCachedDataEnd(int64_t aOffset) MOZ_OVERRIDE { return GetLength(); }
virtual bool IsDataCachedToEndOfResource(int64_t aOffset) MOZ_OVERRIDE { return true; }
virtual bool IsSuspendedByCache() MOZ_OVERRIDE { return false; }
virtual bool IsSuspended() MOZ_OVERRIDE { return false; }
virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
virtual nsresult Open(nsIStreamListener** aStreamListener) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) MOZ_OVERRIDE
{
aRanges.AppendElement(MediaByteRange(0, GetLength()));
return NS_OK;
}
virtual bool IsTransportSeekable() MOZ_OVERRIDE { return true; }
virtual const nsCString& GetContentType() const MOZ_OVERRIDE { return mType; }
private:
const nsAutoCString mType;
};
} // namespace mozilla
#endif /* MOZILLA_MEDIASOURCEDECODER_H_ */

View File

@ -1,176 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaSourceInputAdapter.h"
#include "nsStreamUtils.h"
#include "nsCycleCollectionParticipant.h"
#ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaSourceLog;
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
#else
#define LOG(type, msg)
#endif
namespace mozilla {
namespace dom {
NS_IMETHODIMP
MediaSourceInputAdapter::Close()
{
MonitorAutoLock mon(mMediaSource->GetMonitor());
LOG(PR_LOG_DEBUG, ("%p IA::Close", this));
//MOZ_ASSERT(!mClosed);
mClosed = true;
NotifyListener();
return NS_OK;
}
NS_IMETHODIMP
MediaSourceInputAdapter::Available(uint64_t* aAvailable)
{
MonitorAutoLock mon(mMediaSource->GetMonitor());
if (mClosed) {
LOG(PR_LOG_DEBUG, ("%p IA::Available (closed)", this));
return NS_BASE_STREAM_CLOSED;
}
*aAvailable = Available();
LOG(PR_LOG_DEBUG, ("%p IA::Available available=%llu", this, *aAvailable));
return NS_OK;
}
NS_IMETHODIMP
MediaSourceInputAdapter::Read(char* aBuf, uint32_t aCount, uint32_t* aWriteCount)
{
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, aWriteCount);
}
NS_IMETHODIMP
MediaSourceInputAdapter::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t* aWriteCount)
{
MonitorAutoLock mon(mMediaSource->GetMonitor());
uint32_t available = Available();
LOG(PR_LOG_DEBUG, ("%p IA::ReadSegments aCount=%u available=%u appendDone=%d rv=%x",
this, aCount, available, mMediaSource->AppendDone(),
mMediaSource->AppendDone() ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK));
if (available == 0) {
*aWriteCount = 0;
return mMediaSource->AppendDone() ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
}
uint32_t count = std::min(aCount, available);
nsresult rv = aWriter(this, aClosure,
reinterpret_cast<const char*>(&mMediaSource->GetData()[mOffset]),
0, count, aWriteCount);
if (NS_SUCCEEDED(rv)) {
MOZ_ASSERT(*aWriteCount <= count);
mOffset += *aWriteCount;
}
return NS_OK;
}
NS_IMETHODIMP
MediaSourceInputAdapter::IsNonBlocking(bool* aNonBlocking)
{
LOG(PR_LOG_DEBUG, ("%p IA::IsNonBlocking", this));
*aNonBlocking = true;
return NS_OK;
}
NS_IMETHODIMP
MediaSourceInputAdapter::CloseWithStatus(nsresult aStatus)
{
return Close();
}
NS_IMETHODIMP
MediaSourceInputAdapter::AsyncWait(nsIInputStreamCallback* aCallback, uint32_t aFlags,
uint32_t aRequestedCount, nsIEventTarget* aTarget)
{
LOG(PR_LOG_DEBUG, ("%p IA::AsyncWait aCallback=%p aFlags=%u aRequestedCount=%u aTarget=%p",
this, aCallback, aFlags, aRequestedCount, aTarget));
if (aFlags != 0) {
return NS_ERROR_NOT_IMPLEMENTED;
}
if (mCallback || mCallbackTarget) {
return NS_ERROR_UNEXPECTED;
}
mCallback = aCallback;
mCallbackTarget = aTarget;
mNotifyThreshold = aRequestedCount;
if (!aRequestedCount) {
mNotifyThreshold = 1024;
}
NotifyListener();
return NS_OK;
}
void
MediaSourceInputAdapter::NotifyListener()
{
if (!mCallback) {
return;
}
// Don't notify unless more data is available than the threshold, except
// in the case that there's no more data coming.
if (Available() < mNotifyThreshold && !mClosed && !mMediaSource->AppendDone()) {
return;
}
nsCOMPtr<nsIInputStreamCallback> callback;
if (mCallbackTarget) {
callback = NS_NewInputStreamReadyEvent(mCallback, mCallbackTarget);
} else {
callback = mCallback;
}
MOZ_ASSERT(callback);
mCallback = nullptr;
mCallbackTarget = nullptr;
mNotifyThreshold = 0;
LOG(PR_LOG_DEBUG, ("%p IA::NotifyListener", this));
callback->OnInputStreamReady(this);
}
uint64_t
MediaSourceInputAdapter::Available()
{
return mMediaSource->GetData().Length() - mOffset;
}
MediaSourceInputAdapter::~MediaSourceInputAdapter()
{
LOG(PR_LOG_DEBUG, ("%p Destroy input adapter", this));
}
MediaSourceInputAdapter::MediaSourceInputAdapter(MediaSource* aMediaSource)
: mMediaSource(aMediaSource)
, mOffset(0)
, mClosed(false)
{
LOG(PR_LOG_DEBUG, ("%p Create input adapter for %p", this, aMediaSource));
}
NS_IMPL_CYCLE_COLLECTION_1(MediaSourceInputAdapter, mMediaSource)
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaSourceInputAdapter)
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaSourceInputAdapter)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaSourceInputAdapter)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStream)
NS_INTERFACE_MAP_END
} // namespace dom
} // namespace mozilla

View File

@ -1,43 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_MEDIASOURCEINPUTADAPTER_H_
#define MOZILLA_MEDIASOURCEINPUTADAPTER_H_
#include "nsIAsyncInputStream.h"
#include "nsCycleCollectionParticipant.h"
#include "MediaSource.h"
namespace mozilla {
namespace dom {
class MediaSourceInputAdapter MOZ_FINAL : public nsIAsyncInputStream
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(MediaSourceInputAdapter)
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
MediaSourceInputAdapter(MediaSource* aMediaSource);
~MediaSourceInputAdapter();
void NotifyListener();
private:
uint64_t Available();
nsRefPtr<MediaSource> mMediaSource;
nsCOMPtr<nsIInputStreamCallback> mCallback;
nsCOMPtr<nsIEventTarget> mCallbackTarget;
int64_t mOffset;
uint32_t mNotifyThreshold;
bool mClosed;
};
} // namespace dom
} // namespace mozilla
#endif /* MOZILLA_MEDIASOURCEINPUTADAPTER_H_ */

View File

@ -5,6 +5,25 @@
#include "SourceBuffer.h" #include "SourceBuffer.h"
#include "AsyncEventRunner.h"
#include "DecoderTraits.h"
#include "MediaDecoder.h"
#include "MediaSourceDecoder.h"
#include "SourceBufferResource.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/dom/MediaSourceBinding.h"
#include "mozilla/dom/TimeRanges.h"
#include "nsError.h"
#include "nsIEventTarget.h"
#include "nsIRunnable.h"
#include "nsThreadUtils.h"
#include "prlog.h"
#include "SubBufferDecoder.h"
struct JSContext;
class JSObject;
#ifdef PR_LOGGING #ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaSourceLog; extern PRLogModuleInfo* gMediaSourceLog;
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg) #define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
@ -13,30 +32,96 @@ extern PRLogModuleInfo* gMediaSourceLog;
#endif #endif
namespace mozilla { namespace mozilla {
class MediaResource;
class ReentrantMonitor;
namespace layers {
class ImageContainer;
} // namespace layers
ReentrantMonitor&
SubBufferDecoder::GetReentrantMonitor()
{
return mParentDecoder->GetReentrantMonitor();
}
bool
SubBufferDecoder::OnStateMachineThread() const
{
return mParentDecoder->OnStateMachineThread();
}
bool
SubBufferDecoder::OnDecodeThread() const
{
return mParentDecoder->OnDecodeThread();
}
SourceBufferResource*
SubBufferDecoder::GetResource() const
{
return static_cast<SourceBufferResource*>(mResource.get());
}
void
SubBufferDecoder::SetMediaDuration(int64_t aDuration)
{
mParentDecoder->SetMediaDuration(aDuration);
}
void
SubBufferDecoder::UpdateEstimatedMediaDuration(int64_t aDuration)
{
mParentDecoder->UpdateEstimatedMediaDuration(aDuration);
}
void
SubBufferDecoder::SetMediaSeekable(bool aMediaSeekable)
{
mParentDecoder->SetMediaSeekable(aMediaSeekable);
}
void
SubBufferDecoder::SetTransportSeekable(bool aTransportSeekable)
{
mParentDecoder->SetTransportSeekable(aTransportSeekable);
}
layers::ImageContainer*
SubBufferDecoder::GetImageContainer()
{
return mParentDecoder->GetImageContainer();
}
namespace dom { namespace dom {
void void
SourceBuffer::SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv) SourceBuffer::SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv)
{ {
if (!mAttached || mUpdating) { if (!IsAttached() || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return; return;
} }
MOZ_ASSERT(mMediaSource->ReadyState() != MediaSourceReadyState::Closed);
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) { if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
mMediaSource->SetReadyState(MediaSourceReadyState::Open); mMediaSource->SetReadyState(MediaSourceReadyState::Open);
} }
// TODO:: Test append state. // TODO: Test append state.
// TODO:: If aMode is "sequence", set sequence start time. // TODO: If aMode is "sequence", set sequence start time.
mAppendMode = aMode; mAppendMode = aMode;
} }
void void
SourceBuffer::SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv) SourceBuffer::SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv)
{ {
if (!mAttached || mUpdating) { if (!IsAttached() || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return; return;
} }
MOZ_ASSERT(mMediaSource->ReadyState() != MediaSourceReadyState::Closed);
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) { if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
mMediaSource->SetReadyState(MediaSourceReadyState::Open); mMediaSource->SetReadyState(MediaSourceReadyState::Open);
} }
@ -48,19 +133,19 @@ SourceBuffer::SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv)
already_AddRefed<TimeRanges> already_AddRefed<TimeRanges>
SourceBuffer::GetBuffered(ErrorResult& aRv) SourceBuffer::GetBuffered(ErrorResult& aRv)
{ {
if (!mAttached) { if (!IsAttached()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr; return nullptr;
} }
nsRefPtr<TimeRanges> ranges = new TimeRanges(); nsRefPtr<TimeRanges> ranges = new TimeRanges();
// TODO: Populate ranges. mDecoder->GetBuffered(ranges);
return ranges.forget(); return ranges.forget();
} }
void void
SourceBuffer::SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv) SourceBuffer::SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv)
{ {
if (!mAttached || mUpdating) { if (!IsAttached() || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return; return;
} }
@ -74,7 +159,7 @@ SourceBuffer::SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv)
void void
SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv) SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv)
{ {
if (!mAttached || mUpdating) { if (!IsAttached() || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return; return;
} }
@ -101,7 +186,7 @@ SourceBuffer::AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv)
void void
SourceBuffer::Abort(ErrorResult& aRv) SourceBuffer::Abort(ErrorResult& aRv)
{ {
if (!mAttached) { if (!IsAttached()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return; return;
} }
@ -114,7 +199,6 @@ SourceBuffer::Abort(ErrorResult& aRv)
AbortUpdating(); AbortUpdating();
} }
// TODO: Run reset parser algorithm. // TODO: Run reset parser algorithm.
// XXX: Need to run these two resets through setters?
mAppendWindowStart = 0; mAppendWindowStart = 0;
mAppendWindowEnd = PositiveInfinity(); mAppendWindowEnd = PositiveInfinity();
} }
@ -122,36 +206,36 @@ SourceBuffer::Abort(ErrorResult& aRv)
void void
SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv) SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
{ {
if (!IsAttached() || mUpdating ||
mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (aStart < 0 || aStart > mMediaSource->Duration() || if (aStart < 0 || aStart > mMediaSource->Duration() ||
aEnd <= aStart) { aEnd <= aStart) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return; return;
} }
if (!mAttached || mUpdating ||
mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
StartUpdating(); StartUpdating();
/// TODO: Run coded frame removal algorithm asynchronously (would call StopUpdating()). /// TODO: Run coded frame removal algorithm asynchronously (would call StopUpdating()).
StopUpdating(); StopUpdating();
} }
void void
SourceBuffer::Attach() SourceBuffer::Detach()
{ {
MOZ_ASSERT(!mAttached); Ended();
mAttached = true; mDecoder = nullptr;
mMediaSource = nullptr;
} }
void void
SourceBuffer::Detach() SourceBuffer::Ended()
{ {
MOZ_ASSERT(mAttached); mDecoder->GetResource()->Ended();
mAttached = false;
} }
SourceBuffer::SourceBuffer(MediaSource* aMediaSource) SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
: nsDOMEventTargetHelper(aMediaSource->GetParentObject()) : nsDOMEventTargetHelper(aMediaSource->GetParentObject())
, mMediaSource(aMediaSource) , mMediaSource(aMediaSource)
, mAppendWindowStart(0) , mAppendWindowStart(0)
@ -159,9 +243,18 @@ SourceBuffer::SourceBuffer(MediaSource* aMediaSource)
, mTimestampOffset(0) , mTimestampOffset(0)
, mAppendMode(SourceBufferAppendMode::Segments) , mAppendMode(SourceBufferAppendMode::Segments)
, mUpdating(false) , mUpdating(false)
, mAttached(false)
{ {
MOZ_ASSERT(aMediaSource); MOZ_ASSERT(aMediaSource);
MediaSourceDecoder* parentDecoder = aMediaSource->GetDecoder();
mDecoder = parentDecoder->CreateSubDecoder(aType);
MOZ_ASSERT(mDecoder);
}
SourceBuffer::~SourceBuffer()
{
if (mDecoder) {
mDecoder->GetResource()->Ended();
}
} }
MediaSource* MediaSource*
@ -187,7 +280,7 @@ void
SourceBuffer::QueueAsyncSimpleEvent(const char* aName) SourceBuffer::QueueAsyncSimpleEvent(const char* aName)
{ {
LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBuffer", this, aName)); LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBuffer", this, aName));
nsCOMPtr<nsIRunnable> event = new AsyncEventRunnner<SourceBuffer>(this, aName); nsCOMPtr<nsIRunnable> event = new AsyncEventRunner<SourceBuffer>(this, aName);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
} }
@ -220,7 +313,7 @@ SourceBuffer::AbortUpdating()
void void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv) SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{ {
if (!mAttached || mUpdating) { if (!IsAttached() || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return; return;
} }
@ -229,9 +322,14 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
} }
// TODO: Run coded frame eviction algorithm. // TODO: Run coded frame eviction algorithm.
// TODO: Test buffer full flag. // TODO: Test buffer full flag.
mMediaSource->AppendData(aData, aLength, aRv); // XXX: Appending to input buffer. LOG(PR_LOG_DEBUG, ("%p Append(ArrayBuffer=%u)", this, aLength));
StartUpdating(); StartUpdating();
// XXX: For future reference: NDA call must run on the main thread.
mDecoder->NotifyDataArrived(reinterpret_cast<const char*>(aData),
aLength,
mDecoder->GetResource()->GetLength());
// TODO: Run buffer append algorithm asynchronously (would call StopUpdating()). // TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
mDecoder->GetResource()->AppendData(aData, aLength);
StopUpdating(); StopUpdating();
} }
@ -244,4 +342,5 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SourceBuffer)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -7,22 +7,37 @@
#ifndef mozilla_dom_SourceBuffer_h_ #ifndef mozilla_dom_SourceBuffer_h_
#define mozilla_dom_SourceBuffer_h_ #define mozilla_dom_SourceBuffer_h_
#include "AsyncEventRunner.h" #include "MediaDecoderReader.h"
#include "MediaSource.h" #include "MediaSource.h"
#include "js/RootingAPI.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/dom/SourceBufferBinding.h" #include "mozilla/dom/SourceBufferBinding.h"
#include "mozilla/dom/TimeRanges.h"
#include "mozilla/dom/TypedArray.h" #include "mozilla/dom/TypedArray.h"
#include "mozilla/ErrorResult.h" #include "mozilla/mozalloc.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nscore.h" #include "nsCycleCollectionNoteChild.h"
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
#include "nsDOMEventTargetHelper.h" #include "nsDOMEventTargetHelper.h"
#include "nsWrapperCache.h" #include "nsISupports.h"
#include "nsStringGlue.h"
#include "nscore.h"
class JSObject;
struct JSContext;
namespace mozilla { namespace mozilla {
class ErrorResult;
class SourceBufferResource;
class SubBufferDecoder;
template <typename T> class AsyncEventRunner;
namespace dom { namespace dom {
class TimeRanges;
class SourceBuffer MOZ_FINAL : public nsDOMEventTargetHelper class SourceBuffer MOZ_FINAL : public nsDOMEventTargetHelper
{ {
public: public:
@ -73,19 +88,25 @@ public:
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SourceBuffer, nsDOMEventTargetHelper) NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SourceBuffer, nsDOMEventTargetHelper)
explicit SourceBuffer(MediaSource* aMediaSource); explicit SourceBuffer(MediaSource* aMediaSource, const nsACString& aType);
~SourceBuffer();
MediaSource* GetParentObject() const; MediaSource* GetParentObject() const;
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE; JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
// Notify the SourceBuffer that it has been attached to or detached from // Notify the SourceBuffer that it has been detached from the
// the MediaSource's sourceBuffer list. // MediaSource's sourceBuffer list.
void Attach();
void Detach(); void Detach();
bool IsAttached() const
{
return mMediaSource != nullptr;
}
void Ended();
private: private:
friend class AsyncEventRunnner<SourceBuffer>; friend class AsyncEventRunner<SourceBuffer>;
void DispatchSimpleEvent(const char* aName); void DispatchSimpleEvent(const char* aName);
void QueueAsyncSimpleEvent(const char* aName); void QueueAsyncSimpleEvent(const char* aName);
@ -99,6 +120,8 @@ private:
nsRefPtr<MediaSource> mMediaSource; nsRefPtr<MediaSource> mMediaSource;
nsRefPtr<SubBufferDecoder> mDecoder;
double mAppendWindowStart; double mAppendWindowStart;
double mAppendWindowEnd; double mAppendWindowEnd;
@ -106,10 +129,9 @@ private:
SourceBufferAppendMode mAppendMode; SourceBufferAppendMode mAppendMode;
bool mUpdating; bool mUpdating;
bool mAttached;
}; };
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla
#endif /* mozilla_dom_SourceBuffer_h_ */ #endif /* mozilla_dom_SourceBuffer_h_ */

View File

@ -6,7 +6,19 @@
#include "SourceBufferList.h" #include "SourceBufferList.h"
#include "AsyncEventRunner.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/SourceBufferListBinding.h" #include "mozilla/dom/SourceBufferListBinding.h"
#include "mozilla/mozalloc.h"
#include "nsCOMPtr.h"
#include "nsIEventTarget.h"
#include "nsIRunnable.h"
#include "nsStringGlue.h"
#include "nsThreadUtils.h"
#include "prlog.h"
struct JSContext;
class JSObject;
#ifdef PR_LOGGING #ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaSourceLog; extern PRLogModuleInfo* gMediaSourceLog;
@ -16,6 +28,7 @@ extern PRLogModuleInfo* gMediaSourceLog;
#endif #endif
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
SourceBuffer* SourceBuffer*
@ -42,6 +55,7 @@ void
SourceBufferList::Remove(SourceBuffer* aSourceBuffer) SourceBufferList::Remove(SourceBuffer* aSourceBuffer)
{ {
MOZ_ALWAYS_TRUE(mSourceBuffers.RemoveElement(aSourceBuffer)); MOZ_ALWAYS_TRUE(mSourceBuffers.RemoveElement(aSourceBuffer));
aSourceBuffer->Detach();
QueueAsyncSimpleEvent("removesourcebuffer"); QueueAsyncSimpleEvent("removesourcebuffer");
} }
@ -54,6 +68,9 @@ SourceBufferList::Contains(SourceBuffer* aSourceBuffer)
void void
SourceBufferList::Clear() SourceBufferList::Clear()
{ {
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
mSourceBuffers[i]->Detach();
}
mSourceBuffers.Clear(); mSourceBuffers.Clear();
QueueAsyncSimpleEvent("removesourcebuffer"); QueueAsyncSimpleEvent("removesourcebuffer");
} }
@ -64,15 +81,6 @@ SourceBufferList::IsEmpty()
return mSourceBuffers.IsEmpty(); return mSourceBuffers.IsEmpty();
} }
void
SourceBufferList::DetachAndClear()
{
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
mSourceBuffers[i]->Detach();
}
Clear();
}
bool bool
SourceBufferList::AnyUpdating() SourceBufferList::AnyUpdating()
{ {
@ -95,6 +103,14 @@ SourceBufferList::Remove(double aStart, double aEnd, ErrorResult& aRv)
} }
} }
void
SourceBufferList::Ended()
{
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
mSourceBuffers[i]->Ended();
}
}
void void
SourceBufferList::DispatchSimpleEvent(const char* aName) SourceBufferList::DispatchSimpleEvent(const char* aName)
{ {
@ -106,7 +122,7 @@ void
SourceBufferList::QueueAsyncSimpleEvent(const char* aName) SourceBufferList::QueueAsyncSimpleEvent(const char* aName)
{ {
LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBufferList", this, aName)); LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBufferList", this, aName));
nsCOMPtr<nsIRunnable> event = new AsyncEventRunnner<SourceBufferList>(this, aName); nsCOMPtr<nsIRunnable> event = new AsyncEventRunner<SourceBufferList>(this, aName);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
} }
@ -139,4 +155,5 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SourceBufferList)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -7,17 +7,25 @@
#ifndef mozilla_dom_SourceBufferList_h_ #ifndef mozilla_dom_SourceBufferList_h_
#define mozilla_dom_SourceBufferList_h_ #define mozilla_dom_SourceBufferList_h_
#include "AsyncEventRunner.h"
#include "MediaSource.h"
#include "SourceBuffer.h" #include "SourceBuffer.h"
#include "js/RootingAPI.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "nsCOMPtr.h" #include "nsAutoPtr.h"
#include "nsCycleCollectionNoteChild.h"
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
#include "nsDOMEventTargetHelper.h" #include "nsDOMEventTargetHelper.h"
#include "nsWrapperCache.h" #include "nsISupports.h"
#include "nscore.h" #include "nsTArray.h"
struct JSContext;
class JSObject;
namespace mozilla { namespace mozilla {
class ErrorResult;
template <typename T> class AsyncEventRunner;
namespace dom { namespace dom {
class MediaSource; class MediaSource;
@ -55,9 +63,6 @@ public:
// True if list has zero entries. // True if list has zero entries.
bool IsEmpty(); bool IsEmpty();
// Detach and remove all SourceBuffers and fire a single "removesourcebuffer" at the list.
void DetachAndClear();
// Returns true if updating is true on any SourceBuffers in the list. // Returns true if updating is true on any SourceBuffers in the list.
bool AnyUpdating(); bool AnyUpdating();
@ -65,8 +70,11 @@ public:
// first error, with result returned in aRv. // first error, with result returned in aRv.
void Remove(double aStart, double aEnd, ErrorResult& aRv); void Remove(double aStart, double aEnd, ErrorResult& aRv);
// Mark all SourceBuffers input buffers as ended.
void Ended();
private: private:
friend class AsyncEventRunnner<SourceBufferList>; friend class AsyncEventRunner<SourceBufferList>;
void DispatchSimpleEvent(const char* aName); void DispatchSimpleEvent(const char* aName);
void QueueAsyncSimpleEvent(const char* aName); void QueueAsyncSimpleEvent(const char* aName);
@ -75,5 +83,6 @@ private:
}; };
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla
#endif /* mozilla_dom_SourceBufferList_h_ */ #endif /* mozilla_dom_SourceBufferList_h_ */

View File

@ -0,0 +1,162 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SourceBufferResource.h"
#include <string.h>
#include <algorithm>
#include "nsISeekableStream.h"
#include "nsTraceRefcnt.h"
#include "prenv.h"
#include "prlog.h"
#ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaSourceLog;
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
#else
#define LOG(type, msg)
#endif
namespace mozilla {
namespace dom {
class SourceBuffer;
} // namespace dom
nsresult
SourceBufferResource::Close()
{
ReentrantMonitorAutoEnter mon(mMonitor);
LOG(PR_LOG_DEBUG, ("%p SBR::Close", this));
//MOZ_ASSERT(!mClosed);
mClosed = true;
mon.NotifyAll();
return NS_OK;
}
nsresult
SourceBufferResource::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
{
ReentrantMonitorAutoEnter mon(mMonitor);
bool blockingRead = !!aBytes;
while (blockingRead && !mEnded && mOffset + aCount > GetLength()) {
LOG(PR_LOG_DEBUG, ("%p SBR::Read waiting for data", this));
mon.Wait();
}
uint32_t available = GetLength() - mOffset;
uint32_t count = std::min(aCount, available);
if (!PR_GetEnv("MOZ_QUIET")) {
LOG(PR_LOG_DEBUG, ("%p SBR::Read aCount=%u length=%u offset=%u "
"available=%u count=%u, blocking=%d bufComplete=%d",
this, aCount, GetLength(), mOffset, available, count,
blockingRead, mEnded));
}
if (available == 0) {
LOG(PR_LOG_DEBUG, ("%p SBR::Read EOF", this));
*aBytes = 0;
return NS_OK;
}
memcpy(aBuffer, &mInputBuffer[mOffset], count);
*aBytes = count;
mOffset += count;
return NS_OK;
}
nsresult
SourceBufferResource::ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount, uint32_t* aBytes)
{
ReentrantMonitorAutoEnter mon(mMonitor);
nsresult rv = Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
if (NS_FAILED(rv)) {
return rv;
}
return Read(aBuffer, aCount, aBytes);
}
nsresult
SourceBufferResource::Seek(int32_t aWhence, int64_t aOffset)
{
ReentrantMonitorAutoEnter mon(mMonitor);
if (mClosed) {
return NS_ERROR_FAILURE;
}
int64_t newOffset = mOffset;
switch (aWhence) {
case nsISeekableStream::NS_SEEK_END:
newOffset = GetLength() - aOffset;
break;
case nsISeekableStream::NS_SEEK_CUR:
newOffset += aOffset;
break;
case nsISeekableStream::NS_SEEK_SET:
newOffset = aOffset;
break;
}
if (newOffset < 0 || newOffset > GetLength()) {
return NS_ERROR_FAILURE;
}
mOffset = newOffset;
mon.NotifyAll();
return NS_OK;
}
nsresult
SourceBufferResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount)
{
ReentrantMonitorAutoEnter mon(mMonitor);
nsresult rv = Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
if (NS_FAILED(rv)) {
return rv;
}
return Read(aBuffer, aCount, nullptr);
}
void
SourceBufferResource::AppendData(const uint8_t* aData, uint32_t aLength)
{
ReentrantMonitorAutoEnter mon(mMonitor);
mInputBuffer.AppendElements(aData, aLength);
mon.NotifyAll();
}
void
SourceBufferResource::Ended()
{
ReentrantMonitorAutoEnter mon(mMonitor);
mEnded = true;
mon.NotifyAll();
}
SourceBufferResource::~SourceBufferResource()
{
MOZ_COUNT_DTOR(SourceBufferResource);
LOG(PR_LOG_DEBUG, ("%p SBR::~SBR", this));
}
SourceBufferResource::SourceBufferResource(nsIPrincipal* aPrincipal,
const nsACString& aType)
: mPrincipal(aPrincipal)
, mType(aType)
, mMonitor("mozilla::SourceBufferResource::mMonitor")
, mOffset(0)
, mClosed(false)
, mEnded(false)
{
MOZ_COUNT_CTOR(SourceBufferResource);
LOG(PR_LOG_DEBUG, ("%p SBR::SBR()", this));
}
} // namespace mozilla

View File

@ -0,0 +1,104 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_SOURCEBUFFERRESOURCE_H_
#define MOZILLA_SOURCEBUFFERRESOURCE_H_
#include "MediaCache.h"
#include "MediaResource.h"
#include "mozilla/Attributes.h"
#include "mozilla/ReentrantMonitor.h"
#include "nsCOMPtr.h"
#include "nsError.h"
#include "nsIPrincipal.h"
#include "nsStringGlue.h"
#include "nsTArray.h"
#include "nscore.h"
class nsIStreamListener;
namespace mozilla {
class MediaDecoder;
namespace dom {
class SourceBuffer;
} // namespace dom
class SourceBufferResource MOZ_FINAL : public MediaResource
{
public:
SourceBufferResource(nsIPrincipal* aPrincipal,
const nsACString& aType);
~SourceBufferResource();
virtual nsresult Close() MOZ_OVERRIDE;
virtual void Suspend(bool aCloseImmediately) MOZ_OVERRIDE {}
virtual void Resume() MOZ_OVERRIDE {}
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() MOZ_OVERRIDE
{
return nsCOMPtr<nsIPrincipal>(mPrincipal).forget();
}
virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) MOZ_OVERRIDE
{
return nullptr;
}
virtual void SetReadMode(MediaCacheStream::ReadMode aMode) MOZ_OVERRIDE {}
virtual void SetPlaybackRate(uint32_t aBytesPerSecond) MOZ_OVERRIDE {}
virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE;
virtual nsresult ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE;
virtual nsresult Seek(int32_t aWhence, int64_t aOffset) MOZ_OVERRIDE;
virtual void StartSeekingForMetadata() MOZ_OVERRIDE { }
virtual void EndSeekingForMetadata() MOZ_OVERRIDE {}
virtual int64_t Tell() MOZ_OVERRIDE { return mOffset; }
virtual void Pin() MOZ_OVERRIDE {}
virtual void Unpin() MOZ_OVERRIDE {}
virtual double GetDownloadRate(bool* aIsReliable) MOZ_OVERRIDE { return 0; }
virtual int64_t GetLength() MOZ_OVERRIDE { return mInputBuffer.Length(); }
virtual int64_t GetNextCachedData(int64_t aOffset) MOZ_OVERRIDE { return aOffset; }
virtual int64_t GetCachedDataEnd(int64_t aOffset) MOZ_OVERRIDE { return GetLength(); }
virtual bool IsDataCachedToEndOfResource(int64_t aOffset) MOZ_OVERRIDE { return true; }
virtual bool IsSuspendedByCache() MOZ_OVERRIDE { return false; }
virtual bool IsSuspended() MOZ_OVERRIDE { return false; }
virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount) MOZ_OVERRIDE;
virtual bool IsTransportSeekable() MOZ_OVERRIDE { return true; }
virtual nsresult Open(nsIStreamListener** aStreamListener) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) MOZ_OVERRIDE
{
aRanges.AppendElement(MediaByteRange(0, GetLength()));
return NS_OK;
}
virtual const nsCString& GetContentType() const MOZ_OVERRIDE { return mType; }
// Used by SourceBuffer.
void AppendData(const uint8_t* aData, uint32_t aLength);
void Ended();
private:
nsCOMPtr<nsIPrincipal> mPrincipal;
const nsAutoCString mType;
// Provides synchronization between SourceBuffers and InputAdapters.
// Protects all of the member variables below. Read() will await a
// Notify() (from Seek, AppendData, Ended, or Close) when insufficient
// data is available in mData.
ReentrantMonitor mMonitor;
nsTArray<uint8_t> mInputBuffer;
int64_t mOffset;
bool mClosed;
bool mEnded;
};
} // namespace mozilla
#endif /* MOZILLA_SOURCEBUFFERRESOURCE_H_ */

View File

@ -0,0 +1,64 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_SUBBUFFERDECODER_H_
#define MOZILLA_SUBBUFFERDECODER_H_
#include "BufferDecoder.h"
#include "SourceBufferResource.h"
namespace mozilla {
class MediaSourceDecoder;
class SubBufferDecoder : public BufferDecoder
{
public:
// This class holds a weak pointer to MediaResource. It's the responsibility
// of the caller to manage the memory of the MediaResource object.
SubBufferDecoder(MediaResource* aResource, MediaSourceDecoder* aParentDecoder)
: BufferDecoder(aResource), mParentDecoder(aParentDecoder), mReader(nullptr)
{
}
void SetReader(MediaDecoderReader* aReader)
{
MOZ_ASSERT(!mReader);
mReader = aReader;
}
virtual ReentrantMonitor& GetReentrantMonitor() MOZ_OVERRIDE;
virtual bool OnStateMachineThread() const MOZ_OVERRIDE;
virtual bool OnDecodeThread() const MOZ_OVERRIDE;
virtual SourceBufferResource* GetResource() const MOZ_OVERRIDE;
virtual void SetMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
virtual void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
virtual void SetTransportSeekable(bool aTransportSeekable) MOZ_OVERRIDE;
virtual layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
{
mReader->NotifyDataArrived(aBuffer, aLength, aOffset);
// XXX: aOffset makes no sense here, need view of "data timeline".
mParentDecoder->NotifyDataArrived(aBuffer, aLength, aOffset);
}
nsresult GetBuffered(TimeRanges* aBuffered)
{
// XXX: Need mStartTime (from StateMachine) instead of passing 0.
return mReader->GetBuffered(aBuffered, 0);
}
private:
MediaSourceDecoder* mParentDecoder;
nsAutoPtr<MediaDecoderReader> mReader;
};
} // namespace mozilla
#endif /* MOZILLA_SUBBUFFERDECODER_H_ */

View File

@ -11,6 +11,7 @@ MODULE = 'content'
EXPORTS += [ EXPORTS += [
'AsyncEventRunner.h', 'AsyncEventRunner.h',
'MediaSourceDecoder.h',
] ]
EXPORTS.mozilla.dom += [ EXPORTS.mozilla.dom += [
@ -21,9 +22,10 @@ EXPORTS.mozilla.dom += [
CPP_SOURCES += [ CPP_SOURCES += [
'MediaSource.cpp', 'MediaSource.cpp',
'MediaSourceInputAdapter.cpp', 'MediaSourceDecoder.cpp',
'SourceBuffer.cpp', 'SourceBuffer.cpp',
'SourceBufferList.cpp', 'SourceBufferList.cpp',
'SourceBufferResource.cpp',
] ]
FAIL_ON_WARNINGS = True FAIL_ON_WARNINGS = True

View File

@ -13,11 +13,6 @@ SimpleTest.waitForExplicitFinish();
addLoadEvent(function() { addLoadEvent(function() {
ok(!window.MediaSource, "MediaSource should be hidden behind a pref"); ok(!window.MediaSource, "MediaSource should be hidden behind a pref");
if (navigator.appVersion.indexOf("Android") != -1) {
todo(false, "Fix this test on Android: bug 889712.");
SimpleTest.finish();
return;
}
var accessThrows = false; var accessThrows = false;
try { try {
new MediaSource(); new MediaSource();
@ -25,6 +20,8 @@ addLoadEvent(function() {
accessThrows = true; accessThrows = true;
} }
ok(accessThrows, "MediaSource should be hidden behind a pref"); ok(accessThrows, "MediaSource should be hidden behind a pref");
SpecialPowers.pushPrefEnv({"set": [[ "media.mediasource.enabled", true ]]},
function () {
SpecialPowers.setBoolPref("media.mediasource.enabled", true); SpecialPowers.setBoolPref("media.mediasource.enabled", true);
var ms = new MediaSource(); var ms = new MediaSource();
ok(ms, "Create a MediaSource object"); ok(ms, "Create a MediaSource object");
@ -35,6 +32,7 @@ addLoadEvent(function() {
var o = URL.createObjectURL(ms); var o = URL.createObjectURL(ms);
ok(o, "Create an objectURL from the MediaSource"); ok(o, "Create an objectURL from the MediaSource");
var v = document.createElement("video"); var v = document.createElement("video");
v.preload = "auto";
document.body.appendChild(v); document.body.appendChild(v);
v.src = o; v.src = o;
ms.addEventListener("sourceopen", function () { ms.addEventListener("sourceopen", function () {
@ -58,13 +56,13 @@ addLoadEvent(function() {
ok(true, "Receive a sourceended event"); ok(true, "Receive a sourceended event");
is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended"); is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
}); });
v.addEventListener("playing", function () { v.addEventListener("ended", function () {
is(v.duration, 4, "Video has correct duration"); is(v.duration, 4, "Video has correct duration");
v.parentNode.removeChild(v); v.parentNode.removeChild(v);
SpecialPowers.clearUserPref("media.mediasource.enabled");
SimpleTest.finish(); SimpleTest.finish();
}); });
}); });
});
function fetch(src, cb) { function fetch(src, cb) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();

View File

@ -168,7 +168,7 @@ void OggReader::BuildSerialList(nsTArray<uint32_t>& aTracks)
} }
} }
nsresult OggReader::ReadMetadata(VideoInfo* aInfo, nsresult OggReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MetadataTags** aTags)
{ {
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@ -277,8 +277,8 @@ nsresult OggReader::ReadMetadata(VideoInfo* aInfo,
mTheoraState->mInfo.frame_height); mTheoraState->mInfo.frame_height);
if (VideoInfo::ValidateVideoRegion(frameSize, picture, displaySize)) { if (VideoInfo::ValidateVideoRegion(frameSize, picture, displaySize)) {
// Video track's frame sizes will not overflow. Activate the video track. // Video track's frame sizes will not overflow. Activate the video track.
mInfo.mHasVideo = true; mInfo.mVideo.mHasVideo = true;
mInfo.mDisplay = displaySize; mInfo.mVideo.mDisplay = displaySize;
mPicture = picture; mPicture = picture;
VideoFrameContainer* container = mDecoder->GetVideoFrameContainer(); VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
@ -295,9 +295,9 @@ nsresult OggReader::ReadMetadata(VideoInfo* aInfo,
} }
if (mVorbisState && ReadHeaders(mVorbisState)) { if (mVorbisState && ReadHeaders(mVorbisState)) {
mInfo.mHasAudio = true; mInfo.mAudio.mHasAudio = true;
mInfo.mAudioRate = mVorbisState->mInfo.rate; mInfo.mAudio.mRate = mVorbisState->mInfo.rate;
mInfo.mAudioChannels = mVorbisState->mInfo.channels > 2 ? 2 : mVorbisState->mInfo.channels; mInfo.mAudio.mChannels = mVorbisState->mInfo.channels > 2 ? 2 : mVorbisState->mInfo.channels;
// Copy Vorbis info data for time computations on other threads. // Copy Vorbis info data for time computations on other threads.
memcpy(&mVorbisInfo, &mVorbisState->mInfo, sizeof(mVorbisInfo)); memcpy(&mVorbisInfo, &mVorbisState->mInfo, sizeof(mVorbisInfo));
mVorbisInfo.codec_setup = NULL; mVorbisInfo.codec_setup = NULL;
@ -308,9 +308,9 @@ nsresult OggReader::ReadMetadata(VideoInfo* aInfo,
} }
#ifdef MOZ_OPUS #ifdef MOZ_OPUS
if (mOpusState && ReadHeaders(mOpusState)) { if (mOpusState && ReadHeaders(mOpusState)) {
mInfo.mHasAudio = true; mInfo.mAudio.mHasAudio = true;
mInfo.mAudioRate = mOpusState->mRate; mInfo.mAudio.mRate = mOpusState->mRate;
mInfo.mAudioChannels = mOpusState->mChannels > 2 ? 2 : mOpusState->mChannels; mInfo.mAudio.mChannels = mOpusState->mChannels > 2 ? 2 : mOpusState->mChannels;
mOpusSerial = mOpusState->mSerial; mOpusSerial = mOpusState->mSerial;
mOpusPreSkip = mOpusState->mPreSkip; mOpusPreSkip = mOpusState->mPreSkip;
@ -799,7 +799,7 @@ nsresult OggReader::DecodeTheora(ogg_packet* aPacket, int64_t aTimeThreshold)
b.mPlanes[i].mOffset = b.mPlanes[i].mSkip = 0; b.mPlanes[i].mOffset = b.mPlanes[i].mSkip = 0;
} }
VideoData *v = VideoData::Create(mInfo, VideoData *v = VideoData::Create(mInfo.mVideo,
mDecoder->GetImageContainer(), mDecoder->GetImageContainer(),
mDecoder->GetResource()->Tell(), mDecoder->GetResource()->Tell(),
time, time,
@ -1768,7 +1768,7 @@ nsresult OggReader::GetBuffered(TimeRanges* aBuffered, int64_t aStartTime)
// HasAudio and HasVideo are not used here as they take a lock and cause // HasAudio and HasVideo are not used here as they take a lock and cause
// a deadlock. Accessing mInfo doesn't require a lock - it doesn't change // a deadlock. Accessing mInfo doesn't require a lock - it doesn't change
// after metadata is read. // after metadata is read.
if (!mInfo.mHasVideo && !mInfo.mHasAudio) { if (!mInfo.HasValidMedia()) {
// No need to search through the file if there are no audio or video tracks // No need to search through the file if there are no audio or video tracks
return NS_OK; return NS_OK;
} }

View File

@ -70,7 +70,7 @@ public:
return mTheoraState != 0 && mTheoraState->mActive; return mTheoraState != 0 && mTheoraState->mActive;
} }
virtual nsresult ReadMetadata(VideoInfo* aInfo, virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags); MetadataTags** aTags);
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime); virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime); virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime);

View File

@ -69,7 +69,7 @@ void MediaOmxReader::ReleaseMediaResources()
} }
} }
nsresult MediaOmxReader::ReadMetadata(VideoInfo* aInfo, nsresult MediaOmxReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MetadataTags** aTags)
{ {
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@ -113,8 +113,8 @@ nsresult MediaOmxReader::ReadMetadata(VideoInfo* aInfo,
} }
// Video track's frame sizes will not overflow. Activate the video track. // Video track's frame sizes will not overflow. Activate the video track.
mHasVideo = mInfo.mHasVideo = true; mHasVideo = mInfo.mVideo.mHasVideo = true;
mInfo.mDisplay = displaySize; mInfo.mVideo.mDisplay = displaySize;
mPicture = pictureRect; mPicture = pictureRect;
mInitialFrame = frameSize; mInitialFrame = frameSize;
VideoFrameContainer* container = mDecoder->GetVideoFrameContainer(); VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
@ -128,9 +128,9 @@ nsresult MediaOmxReader::ReadMetadata(VideoInfo* aInfo,
if (mOmxDecoder->HasAudio()) { if (mOmxDecoder->HasAudio()) {
int32_t numChannels, sampleRate; int32_t numChannels, sampleRate;
mOmxDecoder->GetAudioParameters(&numChannels, &sampleRate); mOmxDecoder->GetAudioParameters(&numChannels, &sampleRate);
mHasAudio = mInfo.mHasAudio = true; mHasAudio = mInfo.mAudio.mHasAudio = true;
mInfo.mAudioChannels = numChannels; mInfo.mAudio.mChannels = numChannels;
mInfo.mAudioRate = sampleRate; mInfo.mAudio.mRate = sampleRate;
} }
*aInfo = mInfo; *aInfo = mInfo;
@ -232,7 +232,7 @@ bool MediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
b.mPlanes[2].mOffset = frame.Cr.mOffset; b.mPlanes[2].mOffset = frame.Cr.mOffset;
b.mPlanes[2].mSkip = frame.Cr.mSkip; b.mPlanes[2].mSkip = frame.Cr.mSkip;
v = VideoData::Create(mInfo, v = VideoData::Create(mInfo.mVideo,
mDecoder->GetImageContainer(), mDecoder->GetImageContainer(),
pos, pos,
frame.mTimeUs, frame.mTimeUs,
@ -242,7 +242,7 @@ bool MediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
-1, -1,
picture); picture);
} else { } else {
v = VideoData::Create(mInfo, v = VideoData::Create(mInfo.mVideo,
mDecoder->GetImageContainer(), mDecoder->GetImageContainer(),
pos, pos,
frame.mTimeUs, frame.mTimeUs,

View File

@ -62,7 +62,7 @@ public:
virtual bool IsDormantNeeded(); virtual bool IsDormantNeeded();
virtual void ReleaseMediaResources(); virtual void ReleaseMediaResources();
virtual nsresult ReadMetadata(VideoInfo* aInfo, virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags); MetadataTags** aTags);
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime); virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
virtual nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered, int64_t aStartTime); virtual nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered, int64_t aStartTime);

View File

@ -41,7 +41,7 @@ nsresult MediaPluginReader::Init(MediaDecoderReader* aCloneDonor)
return NS_OK; return NS_OK;
} }
nsresult MediaPluginReader::ReadMetadata(VideoInfo* aInfo, nsresult MediaPluginReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MetadataTags** aTags)
{ {
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@ -75,8 +75,8 @@ nsresult MediaPluginReader::ReadMetadata(VideoInfo* aInfo,
} }
// Video track's frame sizes will not overflow. Activate the video track. // Video track's frame sizes will not overflow. Activate the video track.
mHasVideo = mInfo.mHasVideo = true; mHasVideo = mInfo.mVideo.mHasVideo = true;
mInfo.mDisplay = displaySize; mInfo.mVideo.mDisplay = displaySize;
mPicture = pictureRect; mPicture = pictureRect;
mInitialFrame = frameSize; mInitialFrame = frameSize;
VideoFrameContainer* container = mDecoder->GetVideoFrameContainer(); VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
@ -90,9 +90,9 @@ nsresult MediaPluginReader::ReadMetadata(VideoInfo* aInfo,
if (mPlugin->HasAudio(mPlugin)) { if (mPlugin->HasAudio(mPlugin)) {
int32_t numChannels, sampleRate; int32_t numChannels, sampleRate;
mPlugin->GetAudioParameters(mPlugin, &numChannels, &sampleRate); mPlugin->GetAudioParameters(mPlugin, &numChannels, &sampleRate);
mHasAudio = mInfo.mHasAudio = true; mHasAudio = mInfo.mAudio.mHasAudio = true;
mInfo.mAudioChannels = numChannels; mInfo.mAudio.mChannels = numChannels;
mInfo.mAudioRate = sampleRate; mInfo.mAudio.mRate = sampleRate;
} }
*aInfo = mInfo; *aInfo = mInfo;
@ -186,7 +186,7 @@ bool MediaPluginReader::DecodeVideoFrame(bool &aKeyframeSkip,
picture.height = (frameSize.height * mPicture.height) / mInitialFrame.height; picture.height = (frameSize.height * mPicture.height) / mInitialFrame.height;
} }
v = VideoData::CreateFromImage(mInfo, v = VideoData::CreateFromImage(mInfo.mVideo,
mDecoder->GetImageContainer(), mDecoder->GetImageContainer(),
pos, pos,
frame.mTimeUs, frame.mTimeUs,
@ -232,7 +232,7 @@ bool MediaPluginReader::DecodeVideoFrame(bool &aKeyframeSkip,
} }
// This is the approximate byte position in the stream. // This is the approximate byte position in the stream.
v = VideoData::Create(mInfo, v = VideoData::Create(mInfo.mVideo,
mDecoder->GetImageContainer(), mDecoder->GetImageContainer(),
pos, pos,
frame.mTimeUs, frame.mTimeUs,

View File

@ -61,7 +61,7 @@ public:
return mHasVideo; return mHasVideo;
} }
virtual nsresult ReadMetadata(VideoInfo* aInfo, virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags); MetadataTags** aTags);
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime); virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
virtual nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered, int64_t aStartTime); virtual nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered, int64_t aStartTime);

View File

@ -35,7 +35,7 @@ nsresult RawReader::ResetDecode()
return MediaDecoderReader::ResetDecode(); return MediaDecoderReader::ResetDecode();
} }
nsresult RawReader::ReadMetadata(VideoInfo* aInfo, nsresult RawReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MetadataTags** aTags)
{ {
NS_ASSERTION(mDecoder->OnDecodeThread(), NS_ASSERTION(mDecoder->OnDecodeThread(),
@ -75,9 +75,8 @@ nsresult RawReader::ReadMetadata(VideoInfo* aInfo,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
mInfo.mHasVideo = true; mInfo.mVideo.mHasVideo = true;
mInfo.mHasAudio = false; mInfo.mVideo.mDisplay = display;
mInfo.mDisplay = display;
mFrameRate = static_cast<float>(mMetadata.framerateNumerator) / mFrameRate = static_cast<float>(mMetadata.framerateNumerator) /
mMetadata.framerateDenominator; mMetadata.framerateDenominator;
@ -208,7 +207,7 @@ bool RawReader::DecodeVideoFrame(bool &aKeyframeSkip,
b.mPlanes[2].mWidth = mMetadata.frameWidth / 2; b.mPlanes[2].mWidth = mMetadata.frameWidth / 2;
b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0; b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0;
VideoData *v = VideoData::Create(mInfo, VideoData *v = VideoData::Create(mInfo.mVideo,
mDecoder->GetImageContainer(), mDecoder->GetImageContainer(),
-1, -1,
currentFrameTime, currentFrameTime,

View File

@ -34,7 +34,7 @@ public:
return true; return true;
} }
virtual nsresult ReadMetadata(VideoInfo* aInfo, virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags); MetadataTags** aTags);
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime); virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime); virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime);

View File

@ -78,11 +78,11 @@ var gVideo = null;
var gTestedRemoved = false; var gTestedRemoved = false;
function eventHandler(event) { function eventHandler(event) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
//dump((gTestNum - 1) + ": " + event.type + "\n"); //dump((gTestNum - 1) + ": " + event.type + "\n");
var video = event.target; var video = event.target;
opener.is(event.type, video.expectedResult, video.testDescription + opener.postMessage({"result": (event.type == video.expectedResult),
(gTestedRemoved ? " (element not in document)" : " (element in document)")); "message": video.testDescription + (gTestedRemoved ? " (element not in document)" : " (element in document)")},
"http://mochi.test:8888");
// Make sure any extra events cause an error // Make sure any extra events cause an error
video.expectedResult = "<none>"; video.expectedResult = "<none>";
nextTest(); nextTest();
@ -97,10 +97,9 @@ function createVideo() {
} }
function load() { function load() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); opener.postMessage({"result": (window.location.href == "http://example.org/tests/content/media/test/file_access_controls.html"),
opener.is(window.location.href, "message": "We must be on a example.org:80"},
"http://example.org/tests/content/media/test/file_access_controls.html", "http://mochi.test:8888");
"We must be on a example.org:80");
nextTest(); nextTest();
} }
@ -125,7 +124,7 @@ function nextTest() {
gVideo.parentNode.removeChild(gVideo); gVideo.parentNode.removeChild(gVideo);
gVideo = null; gVideo = null;
opener.SpecialPowers.forceGC(); SpecialPowers.forceGC();
gVideo = createVideo(); gVideo = createVideo();
gVideo.expectedResult = gTests[gTestNum].result; gVideo.expectedResult = gTests[gTestNum].result;
@ -148,7 +147,7 @@ function nextTest() {
} }
function done() { function done() {
opener.done(); opener.postMessage({"done": "true"}, "http://mochi.test:8888");
} }
</script> </script>

View File

@ -31,6 +31,21 @@ function done() {
addLoadEvent(run); addLoadEvent(run);
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
if (event.origin !== "http://example.org") {
ok(false, "Received message from wrong domain");
return;
}
if (event.data.done == "true")
return done();
ok(event.data.result, event.data.message);
}
</script> </script>
</pre> </pre>
</body> </body>

View File

@ -34,7 +34,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=479711
v._name + ":" + v.id + " is not ready before onload fired (" + v.readyState + ")"); v._name + ":" + v.id + " is not ready before onload fired (" + v.readyState + ")");
} }
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
for (i=0; i<testWindows.length; ++i) { for (i=0; i<testWindows.length; ++i) {
testWindows[i].close(); testWindows[i].close();
} }
@ -94,9 +93,6 @@ document.body.appendChild(v);
v = createVideo(test.name, test.type, "3"); v = createVideo(test.name, test.type, "3");
v.load(); v.load();
// Load and move to another document.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
// Open a new window for the following test. We open it here instead of in // Open a new window for the following test. We open it here instead of in
// the event handler to ensure that our document load event doesn't fire while // the event handler to ensure that our document load event doesn't fire while
// window.open is spinning the event loop. // window.open is spinning the event loop.

View File

@ -125,7 +125,7 @@ nsresult WaveReader::Init(MediaDecoderReader* aCloneDonor)
return NS_OK; return NS_OK;
} }
nsresult WaveReader::ReadMetadata(VideoInfo* aInfo, nsresult WaveReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MetadataTags** aTags)
{ {
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@ -142,10 +142,9 @@ nsresult WaveReader::ReadMetadata(VideoInfo* aInfo,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
mInfo.mHasAudio = true; mInfo.mAudio.mHasAudio = true;
mInfo.mHasVideo = false; mInfo.mAudio.mRate = mSampleRate;
mInfo.mAudioRate = mSampleRate; mInfo.mAudio.mChannels = mChannels;
mInfo.mAudioChannels = mChannels;
*aInfo = mInfo; *aInfo = mInfo;
@ -273,7 +272,7 @@ static double RoundToUsecs(double aSeconds) {
nsresult WaveReader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime) nsresult WaveReader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime)
{ {
if (!mInfo.mHasAudio) { if (!mInfo.HasAudio()) {
return NS_OK; return NS_OK;
} }
int64_t startOffset = mDecoder->GetResource()->GetNextCachedData(mWavePCMOffset); int64_t startOffset = mDecoder->GetResource()->GetNextCachedData(mWavePCMOffset);

View File

@ -38,7 +38,7 @@ public:
return false; return false;
} }
virtual nsresult ReadMetadata(VideoInfo* aInfo, virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags); MetadataTags** aTags);
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime); virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime); virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime);

View File

@ -268,9 +268,9 @@ MediaDecodeTask::Decode()
mDecoderReader->OnDecodeThreadStart(); mDecoderReader->OnDecodeThreadStart();
VideoInfo videoInfo; MediaInfo mediaInfo;
nsAutoPtr<MetadataTags> tags; nsAutoPtr<MetadataTags> tags;
nsresult rv = mDecoderReader->ReadMetadata(&videoInfo, getter_Transfers(tags)); nsresult rv = mDecoderReader->ReadMetadata(&mediaInfo, getter_Transfers(tags));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
ReportFailureOnMainThread(WebAudioDecodeJob::InvalidContent); ReportFailureOnMainThread(WebAudioDecodeJob::InvalidContent);
return; return;
@ -290,8 +290,8 @@ MediaDecodeTask::Decode()
MediaQueue<AudioData>& audioQueue = mDecoderReader->AudioQueue(); MediaQueue<AudioData>& audioQueue = mDecoderReader->AudioQueue();
uint32_t frameCount = audioQueue.FrameCount(); uint32_t frameCount = audioQueue.FrameCount();
uint32_t channelCount = videoInfo.mAudioChannels; uint32_t channelCount = mediaInfo.mAudio.mChannels;
uint32_t sampleRate = videoInfo.mAudioRate; uint32_t sampleRate = mediaInfo.mAudio.mRate;
if (!frameCount || !channelCount || !sampleRate) { if (!frameCount || !channelCount || !sampleRate) {
ReportFailureOnMainThread(WebAudioDecodeJob::InvalidContent); ReportFailureOnMainThread(WebAudioDecodeJob::InvalidContent);

View File

@ -256,7 +256,7 @@ void WebMReader::Cleanup()
} }
} }
nsresult WebMReader::ReadMetadata(VideoInfo* aInfo, nsresult WebMReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MetadataTags** aTags)
{ {
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@ -297,8 +297,6 @@ nsresult WebMReader::ReadMetadata(VideoInfo* aInfo,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
mInfo.mHasAudio = false;
mInfo.mHasVideo = false;
for (uint32_t track = 0; track < ntracks; ++track) { for (uint32_t track = 0; track < ntracks; ++track) {
int id = nestegg_track_codec_id(mContext, track); int id = nestegg_track_codec_id(mContext, track);
if (id == -1) { if (id == -1) {
@ -344,27 +342,27 @@ nsresult WebMReader::ReadMetadata(VideoInfo* aInfo,
mVideoTrack = track; mVideoTrack = track;
mHasVideo = true; mHasVideo = true;
mInfo.mHasVideo = true; mInfo.mVideo.mHasVideo = true;
mInfo.mDisplay = displaySize; mInfo.mVideo.mDisplay = displaySize;
mPicture = pictureRect; mPicture = pictureRect;
mInitialFrame = frameSize; mInitialFrame = frameSize;
switch (params.stereo_mode) { switch (params.stereo_mode) {
case NESTEGG_VIDEO_MONO: case NESTEGG_VIDEO_MONO:
mInfo.mStereoMode = STEREO_MODE_MONO; mInfo.mVideo.mStereoMode = STEREO_MODE_MONO;
break; break;
case NESTEGG_VIDEO_STEREO_LEFT_RIGHT: case NESTEGG_VIDEO_STEREO_LEFT_RIGHT:
mInfo.mStereoMode = STEREO_MODE_LEFT_RIGHT; mInfo.mVideo.mStereoMode = STEREO_MODE_LEFT_RIGHT;
break; break;
case NESTEGG_VIDEO_STEREO_BOTTOM_TOP: case NESTEGG_VIDEO_STEREO_BOTTOM_TOP:
mInfo.mStereoMode = STEREO_MODE_BOTTOM_TOP; mInfo.mVideo.mStereoMode = STEREO_MODE_BOTTOM_TOP;
break; break;
case NESTEGG_VIDEO_STEREO_TOP_BOTTOM: case NESTEGG_VIDEO_STEREO_TOP_BOTTOM:
mInfo.mStereoMode = STEREO_MODE_TOP_BOTTOM; mInfo.mVideo.mStereoMode = STEREO_MODE_TOP_BOTTOM;
break; break;
case NESTEGG_VIDEO_STEREO_RIGHT_LEFT: case NESTEGG_VIDEO_STEREO_RIGHT_LEFT:
mInfo.mStereoMode = STEREO_MODE_RIGHT_LEFT; mInfo.mVideo.mStereoMode = STEREO_MODE_RIGHT_LEFT;
break; break;
} }
} }
@ -378,7 +376,7 @@ nsresult WebMReader::ReadMetadata(VideoInfo* aInfo,
mAudioTrack = track; mAudioTrack = track;
mHasAudio = true; mHasAudio = true;
mInfo.mHasAudio = true; mInfo.mAudio.mHasAudio = true;
// Get the Vorbis header data // Get the Vorbis header data
unsigned int nheaders = 0; unsigned int nheaders = 0;
@ -421,9 +419,9 @@ nsresult WebMReader::ReadMetadata(VideoInfo* aInfo,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
mInfo.mAudioRate = mVorbisDsp.vi->rate; mInfo.mAudio.mRate = mVorbisDsp.vi->rate;
mInfo.mAudioChannels = mVorbisDsp.vi->channels; mInfo.mAudio.mChannels = mVorbisDsp.vi->channels;
mChannels = mInfo.mAudioChannels; mChannels = mInfo.mAudio.mChannels;
} }
} }
@ -905,7 +903,7 @@ bool WebMReader::DecodeVideoFrame(bool &aKeyframeSkip,
picture.height = (img->d_h * mPicture.height) / mInitialFrame.height; picture.height = (img->d_h * mPicture.height) / mInitialFrame.height;
} }
VideoData *v = VideoData::Create(mInfo, VideoData *v = VideoData::Create(mInfo.mVideo,
mDecoder->GetImageContainer(), mDecoder->GetImageContainer(),
holder->mOffset, holder->mOffset,
tstamp_usecs, tstamp_usecs,

View File

@ -133,7 +133,7 @@ public:
return mHasVideo; return mHasVideo;
} }
virtual nsresult ReadMetadata(VideoInfo* aInfo, virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags); MetadataTags** aTags);
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime); virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime); virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime);

View File

@ -60,6 +60,11 @@ public:
} }
} }
virtual void NotifyRemoved(MediaStreamGraph* aGraph)
{
mSpeechTask = nullptr;
}
private: private:
// Raw pointer; if we exist, the stream exists, // Raw pointer; if we exist, the stream exists,
// and 'mSpeechTask' exclusively owns it and therefor exists as well. // and 'mSpeechTask' exclusively owns it and therefor exists as well.
@ -283,10 +288,15 @@ nsSpeechTask::DispatchEndImpl(float aElapsedTime, uint32_t aCharIndex)
mSpeechSynthesis->OnEnd(this); mSpeechSynthesis->OnEnd(this);
} }
if (utterance->mState == SpeechSynthesisUtterance::STATE_PENDING) {
utterance->mState = SpeechSynthesisUtterance::STATE_NONE;
} else {
utterance->mState = SpeechSynthesisUtterance::STATE_ENDED; utterance->mState = SpeechSynthesisUtterance::STATE_ENDED;
utterance->DispatchSpeechSynthesisEvent(NS_LITERAL_STRING("end"), utterance->DispatchSpeechSynthesisEvent(NS_LITERAL_STRING("end"),
aCharIndex, aElapsedTime, aCharIndex, aElapsedTime,
NS_LITERAL_STRING("")); EmptyString());
}
return NS_OK; return NS_OK;
} }

View File

@ -414,7 +414,7 @@ WMFReader::ConfigureVideoFrameGeometry(IMFMediaType* aMediaType)
} }
// Success! Save state. // Success! Save state.
mInfo.mDisplay = displaySize; mInfo.mVideo.mDisplay = displaySize;
GetDefaultStride(aMediaType, &mVideoStride); GetDefaultStride(aMediaType, &mVideoStride);
mVideoWidth = width; mVideoWidth = width;
mVideoHeight = height; mVideoHeight = height;
@ -470,7 +470,7 @@ WMFReader::ConfigureVideoDecoder()
LOG("Successfully configured video stream"); LOG("Successfully configured video stream");
mHasVideo = mInfo.mHasVideo = true; mHasVideo = mInfo.mVideo.mHasVideo = true;
return S_OK; return S_OK;
} }
@ -534,9 +534,9 @@ WMFReader::ConfigureAudioDecoder()
mAudioChannels = MFGetAttributeUINT32(mediaType, MF_MT_AUDIO_NUM_CHANNELS, 0); mAudioChannels = MFGetAttributeUINT32(mediaType, MF_MT_AUDIO_NUM_CHANNELS, 0);
mAudioBytesPerSample = MFGetAttributeUINT32(mediaType, MF_MT_AUDIO_BITS_PER_SAMPLE, 16) / 8; mAudioBytesPerSample = MFGetAttributeUINT32(mediaType, MF_MT_AUDIO_BITS_PER_SAMPLE, 16) / 8;
mInfo.mAudioChannels = mAudioChannels; mInfo.mAudio.mChannels = mAudioChannels;
mInfo.mAudioRate = mAudioRate; mInfo.mAudio.mRate = mAudioRate;
mHasAudio = mInfo.mHasAudio = true; mHasAudio = mInfo.mAudio.mHasAudio = true;
LOG("Successfully configured audio stream. rate=%u channels=%u bitsPerSample=%u", LOG("Successfully configured audio stream. rate=%u channels=%u bitsPerSample=%u",
mAudioRate, mAudioChannels, mAudioBytesPerSample); mAudioRate, mAudioChannels, mAudioBytesPerSample);
@ -545,7 +545,7 @@ WMFReader::ConfigureAudioDecoder()
} }
nsresult nsresult
WMFReader::ReadMetadata(VideoInfo* aInfo, WMFReader::ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MetadataTags** aTags)
{ {
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@ -578,7 +578,7 @@ WMFReader::ReadMetadata(VideoInfo* aInfo,
hr = ConfigureAudioDecoder(); hr = ConfigureAudioDecoder();
NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
if (mUseHwAccel && mInfo.mHasVideo) { if (mUseHwAccel && mInfo.mVideo.mHasVideo) {
RefPtr<IMFTransform> videoDecoder; RefPtr<IMFTransform> videoDecoder;
hr = mSourceReader->GetServiceForStream(MF_SOURCE_READER_FIRST_VIDEO_STREAM, hr = mSourceReader->GetServiceForStream(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
GUID_NULL, GUID_NULL,
@ -608,12 +608,12 @@ WMFReader::ReadMetadata(VideoInfo* aInfo,
hr = ConfigureVideoDecoder(); hr = ConfigureVideoDecoder();
} }
} }
if (mInfo.mHasVideo) { if (mInfo.HasVideo()) {
LOG("Using DXVA: %s", (mUseHwAccel ? "Yes" : "No")); LOG("Using DXVA: %s", (mUseHwAccel ? "Yes" : "No"));
} }
// Abort if both video and audio failed to initialize. // Abort if both video and audio failed to initialize.
NS_ENSURE_TRUE(mInfo.mHasAudio || mInfo.mHasVideo, NS_ERROR_FAILURE); NS_ENSURE_TRUE(mInfo.HasValidMedia(), NS_ERROR_FAILURE);
// Get the duration, and report it to the decoder if we have it. // Get the duration, and report it to the decoder if we have it.
int64_t duration = 0; int64_t duration = 0;
@ -841,7 +841,7 @@ WMFReader::CreateBasicVideoFrame(IMFSample* aSample,
b.mPlanes[2].mOffset = 0; b.mPlanes[2].mOffset = 0;
b.mPlanes[2].mSkip = 0; b.mPlanes[2].mSkip = 0;
VideoData *v = VideoData::Create(mInfo, VideoData *v = VideoData::Create(mInfo.mVideo,
mDecoder->GetImageContainer(), mDecoder->GetImageContainer(),
aOffsetBytes, aOffsetBytes,
aTimestampUsecs, aTimestampUsecs,
@ -884,7 +884,7 @@ WMFReader::CreateD3DVideoFrame(IMFSample* aSample,
NS_ENSURE_TRUE(SUCCEEDED(hr), hr); NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
NS_ENSURE_TRUE(image, E_FAIL); NS_ENSURE_TRUE(image, E_FAIL);
VideoData *v = VideoData::CreateFromImage(mInfo, VideoData *v = VideoData::CreateFromImage(mInfo.mVideo,
mDecoder->GetImageContainer(), mDecoder->GetImageContainer(),
aOffsetBytes, aOffsetBytes,
aTimestampUsecs, aTimestampUsecs,

View File

@ -40,7 +40,7 @@ public:
bool HasAudio() MOZ_OVERRIDE; bool HasAudio() MOZ_OVERRIDE;
bool HasVideo() MOZ_OVERRIDE; bool HasVideo() MOZ_OVERRIDE;
nsresult ReadMetadata(VideoInfo* aInfo, nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MOZ_OVERRIDE; MetadataTags** aTags) MOZ_OVERRIDE;
nsresult Seek(int64_t aTime, nsresult Seek(int64_t aTime,

View File

@ -307,7 +307,6 @@ public:
mozilla::dom::SVGSVGElement* GetOwnerSVGElement(); mozilla::dom::SVGSVGElement* GetOwnerSVGElement();
nsSVGElement* GetViewportElement(); nsSVGElement* GetViewportElement();
already_AddRefed<mozilla::dom::SVGAnimatedString> ClassName(); already_AddRefed<mozilla::dom::SVGAnimatedString> ClassName();
already_AddRefed<mozilla::dom::CSSValue> GetPresentationAttribute(const nsAString& aName, mozilla::ErrorResult& rv);
protected: protected:
virtual JSObject* WrapNode(JSContext *cx, virtual JSObject* WrapNode(JSContext *cx,
JS::Handle<JSObject*> scope) MOZ_OVERRIDE; JS::Handle<JSObject*> scope) MOZ_OVERRIDE;

View File

@ -403,6 +403,8 @@ NS_IMETHODIMP nsDefaultURIFixup::KeywordToURI(const nsACString& aKeyword,
// the search engine's name through various function calls. // the search engine's name through various function calls.
nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService(); nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
if (obsSvc) { if (obsSvc) {
// Note that "keyword-search" refers to a search via the url
// bar, not a bookmarks keyword search.
obsSvc->NotifyObservers(defaultEngine, "keyword-search", NS_ConvertUTF8toUTF16(keyword).get()); obsSvc->NotifyObservers(defaultEngine, "keyword-search", NS_ConvertUTF8toUTF16(keyword).get());
} }

View File

@ -5,6 +5,8 @@
#ifndef mozilla_dom_apps_InterAppComm_h #ifndef mozilla_dom_apps_InterAppComm_h
#define mozilla_dom_apps_InterAppComm_h #define mozilla_dom_apps_InterAppComm_h
#include "mozilla/dom/MozInterAppMessageEvent.h"
// Forward declarations. // Forward declarations.
struct JSContext; struct JSContext;
class JSObject; class JSObject;

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