mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-09 04:25:38 +00:00
Merge m-c to elm
This commit is contained in:
commit
8d05c5f298
@ -144,7 +144,7 @@ nsCoreUtils::DispatchTouchEvent(uint32_t aEventType, int32_t aX, int32_t aY,
|
||||
if (!nsDOMTouchEvent::PrefEnabled())
|
||||
return;
|
||||
|
||||
nsTouchEvent event(true, aEventType, aRootWidget);
|
||||
WidgetTouchEvent event(true, aEventType, aRootWidget);
|
||||
|
||||
event.time = PR_IntervalNow();
|
||||
|
||||
|
@ -188,13 +188,14 @@ HyperTextAccessible::GetBoundsForString(nsIFrame* aFrame, uint32_t aStartRendere
|
||||
nsPoint frameTextStartPoint;
|
||||
rv = frame->GetPointFromOffset(startContentOffset, &frameTextStartPoint);
|
||||
NS_ENSURE_SUCCESS(rv, nsIntRect());
|
||||
frameScreenRect.x += frameTextStartPoint.x;
|
||||
|
||||
// Use the point for the end offset to calculate the width
|
||||
nsPoint frameTextEndPoint;
|
||||
rv = frame->GetPointFromOffset(startContentOffset + frameSubStringLength, &frameTextEndPoint);
|
||||
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);
|
||||
|
||||
|
@ -21,21 +21,25 @@
|
||||
src="../browser.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function doTest()
|
||||
function testTextNode(aDoc, aContainerID)
|
||||
{
|
||||
var tabDocument = currentTabDocument();
|
||||
var hyperTextNode = tabDocument.getElementById("paragraph");
|
||||
var hyperTextNode = aDoc.getElementById(aContainerID);
|
||||
var textNode = hyperTextNode.firstChild;
|
||||
|
||||
var [x, y, width, height] = getBounds(textNode);
|
||||
testTextBounds(hyperTextNode, 0, -1, [x, y, width, height],
|
||||
COORDTYPE_SCREEN_RELATIVE);
|
||||
}
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var tabDocument = currentTabDocument();
|
||||
testTextNode(tabDocument, "p1");
|
||||
testTextNode(tabDocument, "p2");
|
||||
|
||||
zoomDocument(tabDocument, 2.0);
|
||||
|
||||
var [x, y, width, height] = getBounds(textNode);
|
||||
testTextBounds(hyperTextNode, 0, -1, [x, y, width, height],
|
||||
COORDTYPE_SCREEN_RELATIVE);
|
||||
testTextNode(tabDocument, "p1");
|
||||
|
||||
zoomDocument(tabDocument, 1.0);
|
||||
|
||||
@ -46,7 +50,8 @@
|
||||
var url = "data:text/html,<html>" +
|
||||
"<meta http-equiv='Content-Type' content='text/html;charset=utf-8'>" +
|
||||
"</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>";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
@ -158,7 +158,8 @@ function testTextBounds(aID, aStartOffset, aEndOffset, aRect, aCoordOrigin)
|
||||
|
||||
var xObj = {}, yObj = {}, widthObj = {}, heightObj = {};
|
||||
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,
|
||||
"Wrong x coordinate of text between offsets (" + aStartOffset + ", " +
|
||||
aEndOffset + ") for " + prettyName(aID));
|
||||
|
@ -184,10 +184,14 @@ pref("content.sink.perf_deflect_count", 1000000);
|
||||
pref("content.sink.perf_parse_time", 50000000);
|
||||
|
||||
// Maximum scripts runtime before showing an alert
|
||||
pref("dom.max_chrome_script_run_time", 0); // disable slow script dialog for chrome
|
||||
// Disable the watchdog thread for B2G. See bug 870043 comment 31.
|
||||
pref("dom.use_watchdog", false);
|
||||
|
||||
// The slow script dialog can be triggered from inside the JS engine as well,
|
||||
// ensure that those calls don't accidentally trigger the dialog.
|
||||
pref("dom.max_script_run_time", 0);
|
||||
pref("dom.max_chrome_script_run_time", 0);
|
||||
|
||||
// plugins
|
||||
pref("plugin.disable", true);
|
||||
pref("dom.ipc.plugins.enabled", true);
|
||||
@ -433,7 +437,7 @@ pref("services.push.udp.wakeupEnabled", true);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
pref("dom.mozNetworkStats.enabled", true);
|
||||
pref("ril.cellbroadcast.disabled", false);
|
||||
pref("dom.webapps.firstRunWithSIM", false);
|
||||
pref("dom.webapps.firstRunWithSIM", true);
|
||||
#endif
|
||||
|
||||
// WebSettings
|
||||
@ -448,6 +452,9 @@ pref("media.realtime_decoder.enabled", true);
|
||||
// TCPSocket
|
||||
pref("dom.mozTCPSocket.enabled", true);
|
||||
|
||||
// WebPayment
|
||||
pref("dom.mozPay.enabled", true);
|
||||
|
||||
// "Preview" landing of bug 710563, which is bogged down in analysis
|
||||
// of talos regression. This is a needed change for higher-framerate
|
||||
// CSS animations, and incidentally works around an apparent bug in
|
||||
@ -794,6 +801,9 @@ pref("dom.inter-app-communication-api.enabled", true);
|
||||
// 0 disables the timer.
|
||||
pref("b2g.adb.timeout-hours", 12);
|
||||
|
||||
// InputMethod so we can do soft keyboards
|
||||
pref("dom.mozInputMethod.enabled", true);
|
||||
|
||||
// Absolute path to the devtool unix domain socket file used
|
||||
// to communicate with a usb cable via adb forward
|
||||
pref("devtools.debugger.unix-domain-socket", "/data/local/debugger-socket");
|
||||
@ -808,3 +818,6 @@ pref("dom.telephony.enabled", true);
|
||||
|
||||
// The url of the page used to display network error details.
|
||||
pref("b2g.neterror.url", "app://system.gaiamobile.org/net_error.html");
|
||||
|
||||
// Enable Web Speech synthesis API
|
||||
pref("media.webspeech.synth.enabled", true);
|
||||
|
@ -15,14 +15,6 @@ component {88b3eb21-d072-4e3b-886d-f89d8c49fe59} UpdatePrompt.js
|
||||
contract @mozilla.org/updates/update-prompt;1 {88b3eb21-d072-4e3b-886d-f89d8c49fe59}
|
||||
#endif
|
||||
|
||||
# MozKeyboard.js
|
||||
component {397a7fdf-2254-47be-b74e-76625a1a66d5} MozKeyboard.js
|
||||
contract @mozilla.org/b2g-keyboard;1 {397a7fdf-2254-47be-b74e-76625a1a66d5}
|
||||
category JavaScript-navigator-property mozKeyboard @mozilla.org/b2g-keyboard;1
|
||||
|
||||
component {4607330d-e7d2-40a4-9eb8-43967eae0142} MozKeyboard.js
|
||||
contract @mozilla.org/b2g-inputmethod;1 {4607330d-e7d2-40a4-9eb8-43967eae0142}
|
||||
|
||||
# DirectoryProvider.js
|
||||
component {9181eb7c-6f87-11e1-90b1-4f59d80dd2e5} DirectoryProvider.js
|
||||
contract @mozilla.org/browser/directory-provider;1 {9181eb7c-6f87-11e1-90b1-4f59d80dd2e5}
|
||||
|
@ -13,7 +13,11 @@ const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
|
||||
const PROMPT_FOR_UNKNOWN = ["geolocation", "desktop-notification", "audio-capture"];
|
||||
const PROMPT_FOR_UNKNOWN = ["geolocation", "desktop-notification",
|
||||
"audio-capture"];
|
||||
// Due to privary issue, permission requests like GetUserMedia should prompt
|
||||
// every time instead of providing session persistence.
|
||||
const PERMISSION_NO_SESSION = ["audio-capture"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
@ -43,7 +47,7 @@ function rememberPermission(aPermission, aPrincipal, aSession)
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
} else {
|
||||
} else if (PERMISSION_NO_SESSION.indexOf(aPermission) < 0) {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
|
@ -4,77 +4,9 @@
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
interface nsIDOMDOMRequest;
|
||||
|
||||
[scriptable, uuid(3615a616-571d-4194-bf54-ccf546067b14)]
|
||||
interface nsIB2GCameraContent : nsISupports
|
||||
{
|
||||
/* temporary solution, waiting for getUserMedia */
|
||||
DOMString getCameraURI([optional] in jsval options);
|
||||
};
|
||||
|
||||
[scriptable, uuid(40ad96b2-9efa-41fb-84c7-fbcec9b153f0)]
|
||||
interface nsIB2GKeyboard : nsISupports
|
||||
{
|
||||
void sendKey(in long keyCode, in long charCode);
|
||||
|
||||
// Select the <select> option specified by index.
|
||||
// If this method is called on a <select> that support multiple
|
||||
// selection, then the option specified by index will be added to
|
||||
// the selection.
|
||||
// If this method is called for a select that does not support multiple
|
||||
// selection the previous element will be unselected.
|
||||
void setSelectedOption(in jsval index);
|
||||
|
||||
// Select the <select> options specified by indexes. All other options
|
||||
// will be deselected.
|
||||
// If this method is called for a <select> that does not support multiple
|
||||
// selection, then the last index specified in indexes will be selected.
|
||||
void setSelectedOptions(in jsval indexes);
|
||||
|
||||
// Set the value on the currently focused element. This has to be used
|
||||
// for special situations where the value had to be chosen amongst a
|
||||
// list (type=month) or a widget (type=date, time, etc.).
|
||||
// If the value passed in parameter isn't valid (in the term of HTML5
|
||||
// Forms Validation), the value will simply be ignored by the element.
|
||||
void setValue(in jsval value);
|
||||
|
||||
void removeFocus();
|
||||
|
||||
attribute nsIDOMEventListener onfocuschange;
|
||||
|
||||
// Fires when user moves the cursor, changes the selection, or alters the
|
||||
// composing text length
|
||||
attribute nsIDOMEventListener onselectionchange;
|
||||
|
||||
// The start position of the selection.
|
||||
readonly attribute long selectionStart;
|
||||
|
||||
// The stop position of the selection.
|
||||
readonly attribute long selectionEnd;
|
||||
|
||||
/*
|
||||
* Set the selection range of the the editable text.
|
||||
*
|
||||
* @param start The beginning of the selected text.
|
||||
* @param end The end of the selected text.
|
||||
*
|
||||
* Note that the start position should be less or equal to the end position.
|
||||
* To move the cursor, set the start and end position to the same value.
|
||||
*/
|
||||
void setSelectionRange(in long start, in long end);
|
||||
|
||||
/*
|
||||
* Replace text around the beginning of the current selection range of the
|
||||
* editable text.
|
||||
*
|
||||
* @param text The string to be replaced with.
|
||||
* @param beforeLength The number of characters to be deleted before the
|
||||
* beginning of the current selection range. Defaults to 0.
|
||||
* @param afterLength The number of characters to be deleted after the
|
||||
* beginning of the current selection range. Defaults to 0.
|
||||
*/
|
||||
void replaceSurroundingText(in DOMString text,
|
||||
[optional] in long beforeLength,
|
||||
[optional] in long afterLength);
|
||||
};
|
||||
|
@ -20,7 +20,6 @@ EXTRA_COMPONENTS += [
|
||||
'ContentPermissionPrompt.js',
|
||||
'FilePicker.js',
|
||||
'MailtoProtocolHandler.js',
|
||||
'MozKeyboard.js',
|
||||
'PaymentGlue.js',
|
||||
'ProcessGlobal.js',
|
||||
'SmsProtocolHandler.js',
|
||||
@ -42,7 +41,6 @@ if CONFIG['MOZ_UPDATER']:
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'ErrorPage.jsm',
|
||||
'Keyboard.jsm',
|
||||
'SignInToWebsite.jsm',
|
||||
'TelURIParser.jsm',
|
||||
'WebappsUpdater.jsm',
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "6b82ab58ac7e7cbce89a6718659311a1ce6b7436",
|
||||
"revision": "e836e146aa9bdc2b4141dfa86662eed46d735fb2",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -190,6 +190,7 @@
|
||||
@BINPATH@/components/dom_notification.xpt
|
||||
@BINPATH@/components/dom_html.xpt
|
||||
@BINPATH@/components/dom_indexeddb.xpt
|
||||
@BINPATH@/components/dom_inputmethod.xpt
|
||||
@BINPATH@/components/dom_offline.xpt
|
||||
@BINPATH@/components/dom_payment.xpt
|
||||
@BINPATH@/components/dom_json.xpt
|
||||
@ -547,6 +548,10 @@
|
||||
@BINPATH@/components/PaymentRequestInfo.js
|
||||
@BINPATH@/components/Payment.manifest
|
||||
|
||||
; InputMethod API
|
||||
@BINPATH@/components/MozKeyboard.js
|
||||
@BINPATH@/components/InputMethod.manifest
|
||||
|
||||
; Modules
|
||||
@BINPATH@/modules/*
|
||||
|
||||
@ -748,7 +753,6 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
|
||||
@BINPATH@/components/UpdatePrompt.js
|
||||
#endif
|
||||
@BINPATH@/components/WebappsUpdateTimer.js
|
||||
@BINPATH@/components/MozKeyboard.js
|
||||
@BINPATH@/components/DirectoryProvider.js
|
||||
@BINPATH@/components/ActivitiesGlue.js
|
||||
@BINPATH@/components/ProcessGlobal.js
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1379696114000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1380130116000">
|
||||
<emItems>
|
||||
<emItem blockID="i454" id="sqlmoz@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
@ -738,6 +738,10 @@
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i455" id="7d51fb17-b199-4d8f-894e-decaff4fc36a@a298838b-7f50-4c7c-9277-df6abbd42a0c.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i21" id="support@update-firefox.com">
|
||||
</emItem>
|
||||
<emItem blockID="i322" id="jid0-Y6TVIzs0r7r4xkOogmJPNAGFGBw@jetpack">
|
||||
|
@ -38,7 +38,7 @@ const EXPECTED_REFLOWS = [
|
||||
"TabItem__reconnect@chrome://browser/content/tabview.js|" +
|
||||
"TabItem@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()
|
||||
"ssi_getWindowDimension@resource:///modules/sessionstore/SessionStore.jsm|" +
|
||||
|
@ -58,3 +58,5 @@ if test "$OS_TARGET" = "WINNT" -o "$OS_TARGET" = "Darwin"; then
|
||||
MOZ_FOLD_LIBS=1
|
||||
fi
|
||||
MOZ_WEBGL_CONFORMANT=1
|
||||
# Enable navigator.mozPay
|
||||
MOZ_PAY=1
|
||||
|
@ -9,7 +9,11 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_observableobject.js \
|
||||
browser_layoutHelpers.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_jsdebugger.js \
|
||||
browser_telemetry_toolboxtabs_jsprofiler.js \
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
127
browser/devtools/shared/test/browser_telemetry_button_tilt.js
Normal file
127
browser/devtools/shared/test/browser_telemetry_button_tilt.js
Normal 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;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/* 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_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
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
@ -24,66 +24,9 @@ function init() {
|
||||
|
||||
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();
|
||||
} 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;
|
||||
testSidebar();
|
||||
}
|
||||
|
||||
function testSidebar() {
|
||||
@ -98,6 +41,7 @@ function testSidebar() {
|
||||
// Concatenate the array with itself so that we can open each tool twice.
|
||||
sidebarTools.push.apply(sidebarTools, sidebarTools);
|
||||
|
||||
// See TOOL_DELAY for why we need setTimeout here
|
||||
setTimeout(function selectSidebarTab() {
|
||||
let tool = sidebarTools.pop();
|
||||
if (tool) {
|
||||
@ -147,14 +91,6 @@ function checkResults() {
|
||||
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() {
|
||||
gBrowser.removeCurrentTab();
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
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
|
||||
|
@ -200,6 +200,7 @@
|
||||
@BINPATH@/components/dom_notification.xpt
|
||||
@BINPATH@/components/dom_html.xpt
|
||||
@BINPATH@/components/dom_indexeddb.xpt
|
||||
@BINPATH@/components/dom_inputmethod.xpt
|
||||
@BINPATH@/components/dom_offline.xpt
|
||||
@BINPATH@/components/dom_json.xpt
|
||||
@BINPATH@/components/dom_power.xpt
|
||||
@ -222,6 +223,7 @@
|
||||
#ifdef MOZ_GAMEPAD
|
||||
@BINPATH@/components/dom_gamepad.xpt
|
||||
#endif
|
||||
@BINPATH@/components/dom_payment.xpt
|
||||
@BINPATH@/components/downloads.xpt
|
||||
@BINPATH@/components/editor.xpt
|
||||
@BINPATH@/components/embed_base.xpt
|
||||
@ -539,6 +541,11 @@
|
||||
@BINPATH@/components/AppProtocolHandler.js
|
||||
@BINPATH@/components/AppProtocolHandler.manifest
|
||||
|
||||
@BINPATH@/components/Payment.js
|
||||
@BINPATH@/components/PaymentFlowInfo.js
|
||||
@BINPATH@/components/PaymentRequestInfo.js
|
||||
@BINPATH@/components/Payment.manifest
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
@BINPATH@/components/PeerConnection.js
|
||||
@BINPATH@/components/PeerConnection.manifest
|
||||
@ -556,6 +563,10 @@
|
||||
@BINPATH@/components/dom_webspeechsynth.xpt
|
||||
#endif
|
||||
|
||||
; InputMethod API
|
||||
@BINPATH@/components/MozKeyboard.js
|
||||
@BINPATH@/components/InputMethod.manifest
|
||||
|
||||
; Modules
|
||||
@BINPATH@/browser/modules/*
|
||||
@BINPATH@/modules/*
|
||||
@ -767,6 +778,7 @@ bin/libfreebl_32int64_3.so
|
||||
@BINPATH@/webapprt/components/CommandLineHandler.js
|
||||
@BINPATH@/webapprt/components/ContentPermission.js
|
||||
@BINPATH@/webapprt/components/DirectoryProvider.js
|
||||
@BINPATH@/webapprt/components/PaymentUIGlue.js
|
||||
@BINPATH@/webapprt/components/components.manifest
|
||||
@BINPATH@/webapprt/defaults/preferences/prefs.js
|
||||
@BINPATH@/webapprt/modules/Startup.jsm
|
||||
|
@ -1730,7 +1730,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
|
||||
}
|
||||
|
||||
if (aFireMutation) {
|
||||
nsMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
|
||||
InternalMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
|
||||
|
||||
nsAutoString ns;
|
||||
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
|
||||
@ -1911,7 +1911,7 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
}
|
||||
|
||||
if (hasMutationListeners) {
|
||||
nsMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
|
||||
InternalMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
|
||||
|
||||
mutation.mRelatedNode = attrNode;
|
||||
mutation.mAttrName = aName;
|
||||
@ -2138,7 +2138,7 @@ Element::PreHandleEventForLinks(nsEventChainPreVisitor& aVisitor)
|
||||
// FALL THROUGH
|
||||
case NS_FOCUS_CONTENT:
|
||||
if (aVisitor.mEvent->eventStructType != NS_FOCUS_EVENT ||
|
||||
!static_cast<nsFocusEvent*>(aVisitor.mEvent)->isRefocus) {
|
||||
!static_cast<InternalFocusEvent*>(aVisitor.mEvent)->isRefocus) {
|
||||
nsAutoString target;
|
||||
GetLinkTarget(target);
|
||||
nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
|
||||
|
@ -1021,7 +1021,7 @@ FragmentOrElement::FireNodeInserted(nsIDocument* aDoc,
|
||||
|
||||
if (nsContentUtils::HasMutationListeners(childContent,
|
||||
NS_EVENT_BITS_MUTATION_NODEINSERTED, aParent)) {
|
||||
nsMutationEvent mutation(true, NS_MUTATION_NODEINSERTED);
|
||||
InternalMutationEvent mutation(true, NS_MUTATION_NODEINSERTED);
|
||||
mutation.mRelatedNode = do_QueryInterface(aParent);
|
||||
|
||||
mozAutoSubtreeModified subtree(aDoc, aParent);
|
||||
|
@ -3708,7 +3708,7 @@ nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent,
|
||||
|
||||
if (HasMutationListeners(aChild,
|
||||
NS_EVENT_BITS_MUTATION_NODEREMOVED, aParent)) {
|
||||
nsMutationEvent mutation(true, NS_MUTATION_NODEREMOVED);
|
||||
InternalMutationEvent mutation(true, NS_MUTATION_NODEREMOVED);
|
||||
mutation.mRelatedNode = do_QueryInterface(aParent);
|
||||
|
||||
mozAutoSubtreeModified subtree(aOwnerDoc, aParent);
|
||||
|
@ -649,7 +649,7 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
|
||||
clipboardData = new nsDOMDataTransfer(aType, aType == NS_PASTE, aClipboardType);
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsClipboardEvent evt(true, aType);
|
||||
InternalClipboardEvent evt(true, aType);
|
||||
evt.clipboardData = clipboardData;
|
||||
nsEventDispatcher::Dispatch(content, presShell->GetPresContext(), &evt, nullptr,
|
||||
&status);
|
||||
|
@ -8194,7 +8194,7 @@ nsDocument::MutationEventDispatched(nsINode* aTarget)
|
||||
|
||||
int32_t realTargetCount = realTargets.Count();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -363,7 +363,7 @@ nsGenericDOMDataNode::SetTextInternal(uint32_t aOffset, uint32_t aCount,
|
||||
nsNodeUtils::CharacterDataChanged(this, &info);
|
||||
|
||||
if (haveMutationListeners) {
|
||||
nsMutationEvent mutation(true, NS_MUTATION_CHARACTERDATAMODIFIED);
|
||||
InternalMutationEvent mutation(true, NS_MUTATION_CHARACTERDATAMODIFIED);
|
||||
|
||||
mutation.mPrevAttrValue = oldValue;
|
||||
if (aLength > 0) {
|
||||
|
@ -193,8 +193,7 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(info->mObject);
|
||||
nsCOMPtr<mozilla::dom::MediaSource> mediasource = do_QueryInterface(info->mObject);
|
||||
if (!blob && !mediasource) {
|
||||
if (!blob) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
@ -208,12 +207,7 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
nsresult rv = NS_OK;
|
||||
if (blob) {
|
||||
rv = blob->GetInternalStream(getter_AddRefs(stream));
|
||||
} else {
|
||||
stream = mediasource->CreateInternalStream();
|
||||
}
|
||||
nsresult rv = blob->GetInternalStream(getter_AddRefs(stream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
@ -225,30 +219,25 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
||||
nsCOMPtr<nsISupports> owner = do_QueryInterface(info->mPrincipal);
|
||||
|
||||
nsString type;
|
||||
if (blob) {
|
||||
rv = blob->GetType(type);
|
||||
rv = blob->GetType(type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(info->mObject);
|
||||
if (file) {
|
||||
nsString filename;
|
||||
rv = file->GetName(filename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint64_t size;
|
||||
rv = blob->GetSize(&size);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(info->mObject);
|
||||
if (file) {
|
||||
nsString filename;
|
||||
rv = file->GetName(filename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
channel->SetContentDispositionFilename(filename);
|
||||
}
|
||||
|
||||
channel->SetContentLength(size);
|
||||
} else {
|
||||
type = mediasource->GetType();
|
||||
channel->SetContentDispositionFilename(filename);
|
||||
}
|
||||
|
||||
uint64_t size;
|
||||
rv = blob->GetSize(&size);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
channel->SetOwner(owner);
|
||||
channel->SetOriginalURI(uri);
|
||||
channel->SetContentType(NS_ConvertUTF16toUTF8(type));
|
||||
channel->SetContentLength(size);
|
||||
|
||||
channel.forget(result);
|
||||
|
||||
|
@ -1405,7 +1405,7 @@ nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
|
||||
if (nsContentUtils::HasMutationListeners(aKid,
|
||||
NS_EVENT_BITS_MUTATION_NODEINSERTED, this)) {
|
||||
nsMutationEvent mutation(true, NS_MUTATION_NODEINSERTED);
|
||||
InternalMutationEvent mutation(true, NS_MUTATION_NODEINSERTED);
|
||||
mutation.mRelatedNode = do_QueryInterface(this);
|
||||
|
||||
mozAutoSubtreeModified subtree(OwnerDoc(), this);
|
||||
|
@ -55,7 +55,4 @@ public:
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
// TODO: Remove following typedef
|
||||
typedef mozilla::InternalMutationEvent nsMutationEvent;
|
||||
|
||||
#endif // mozilla_MutationEvent_h__
|
||||
|
@ -7,14 +7,15 @@
|
||||
#include "prtime.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsDOMAnimationEvent::nsDOMAnimationEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext *aPresContext,
|
||||
nsAnimationEvent *aEvent)
|
||||
InternalAnimationEvent* aEvent)
|
||||
: nsDOMEvent(aOwner, aPresContext,
|
||||
aEvent ? aEvent : new nsAnimationEvent(false, 0,
|
||||
EmptyString(),
|
||||
0.0,
|
||||
EmptyString()))
|
||||
aEvent ? aEvent :
|
||||
new InternalAnimationEvent(false, 0, EmptyString(),
|
||||
0.0, EmptyString()))
|
||||
{
|
||||
if (aEvent) {
|
||||
mEventIsInternal = false;
|
||||
@ -86,7 +87,7 @@ nsresult
|
||||
NS_NewDOMAnimationEvent(nsIDOMEvent **aInstancePtrResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext *aPresContext,
|
||||
nsAnimationEvent *aEvent)
|
||||
InternalAnimationEvent *aEvent)
|
||||
{
|
||||
nsDOMAnimationEvent* it =
|
||||
new nsDOMAnimationEvent(aOwner, aPresContext, aEvent);
|
||||
|
@ -18,7 +18,7 @@ class nsDOMAnimationEvent : public nsDOMEvent,
|
||||
public:
|
||||
nsDOMAnimationEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext *aPresContext,
|
||||
nsAnimationEvent *aEvent);
|
||||
mozilla::InternalAnimationEvent* aEvent);
|
||||
~nsDOMAnimationEvent();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -47,10 +47,10 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
nsAnimationEvent* AnimationEvent() {
|
||||
mozilla::InternalAnimationEvent* AnimationEvent() {
|
||||
NS_ABORT_IF_FALSE(mEvent->eventStructType == NS_ANIMATION_EVENT,
|
||||
"unexpected struct type");
|
||||
return static_cast<nsAnimationEvent*>(mEvent);
|
||||
return static_cast<mozilla::InternalAnimationEvent*>(mEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -8,11 +8,13 @@
|
||||
#include "nsIClipboard.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsDOMClipboardEvent::nsDOMClipboardEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
nsClipboardEvent* aEvent)
|
||||
InternalClipboardEvent* aEvent)
|
||||
: nsDOMEvent(aOwner, aPresContext, aEvent ? aEvent :
|
||||
new nsClipboardEvent(false, 0))
|
||||
new InternalClipboardEvent(false, 0))
|
||||
{
|
||||
if (aEvent) {
|
||||
mEventIsInternal = false;
|
||||
@ -25,7 +27,7 @@ nsDOMClipboardEvent::nsDOMClipboardEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsDOMClipboardEvent::~nsDOMClipboardEvent()
|
||||
{
|
||||
if (mEventIsInternal && mEvent->eventStructType == NS_CLIPBOARD_EVENT) {
|
||||
delete static_cast<nsClipboardEvent*>(mEvent);
|
||||
delete static_cast<InternalClipboardEvent*>(mEvent);
|
||||
mEvent = nullptr;
|
||||
}
|
||||
}
|
||||
@ -44,7 +46,7 @@ nsDOMClipboardEvent::InitClipboardEvent(const nsAString & aType, bool aCanBubble
|
||||
nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsClipboardEvent* event = static_cast<nsClipboardEvent*>(mEvent);
|
||||
InternalClipboardEvent* event = static_cast<InternalClipboardEvent*>(mEvent);
|
||||
event->clipboardData = clipboardData;
|
||||
|
||||
return NS_OK;
|
||||
@ -63,7 +65,8 @@ nsDOMClipboardEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal,
|
||||
|
||||
nsRefPtr<nsDOMDataTransfer> clipboardData;
|
||||
if (e->mEventIsInternal) {
|
||||
nsClipboardEvent* event = static_cast<nsClipboardEvent*>(e->mEvent);
|
||||
InternalClipboardEvent* event =
|
||||
static_cast<InternalClipboardEvent*>(e->mEvent);
|
||||
if (event) {
|
||||
// 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
|
||||
@ -89,7 +92,7 @@ nsDOMClipboardEvent::GetClipboardData(nsIDOMDataTransfer** aClipboardData)
|
||||
nsIDOMDataTransfer*
|
||||
nsDOMClipboardEvent::GetClipboardData()
|
||||
{
|
||||
nsClipboardEvent* event = static_cast<nsClipboardEvent*>(mEvent);
|
||||
InternalClipboardEvent* event = static_cast<InternalClipboardEvent*>(mEvent);
|
||||
|
||||
if (!event->clipboardData) {
|
||||
if (mEventIsInternal) {
|
||||
@ -106,7 +109,7 @@ nsDOMClipboardEvent::GetClipboardData()
|
||||
nsresult NS_NewDOMClipboardEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
nsClipboardEvent *aEvent)
|
||||
InternalClipboardEvent* aEvent)
|
||||
{
|
||||
nsDOMClipboardEvent* it =
|
||||
new nsDOMClipboardEvent(aOwner, aPresContext, aEvent);
|
||||
|
@ -17,7 +17,7 @@ class nsDOMClipboardEvent : public nsDOMEvent,
|
||||
public:
|
||||
nsDOMClipboardEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
nsClipboardEvent* aEvent);
|
||||
mozilla::InternalClipboardEvent* aEvent);
|
||||
virtual ~nsDOMClipboardEvent();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -7,11 +7,13 @@
|
||||
#include "prtime.h"
|
||||
#include "mozilla/MiscEvents.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsDOMCommandEvent::nsDOMCommandEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
nsCommandEvent* aEvent)
|
||||
WidgetCommandEvent* aEvent)
|
||||
: nsDOMEvent(aOwner, aPresContext, aEvent ? aEvent :
|
||||
new nsCommandEvent(false, nullptr, nullptr, nullptr))
|
||||
new WidgetCommandEvent(false, nullptr, nullptr, nullptr))
|
||||
{
|
||||
mEvent->time = PR_Now();
|
||||
if (aEvent) {
|
||||
@ -24,7 +26,7 @@ nsDOMCommandEvent::nsDOMCommandEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsDOMCommandEvent::~nsDOMCommandEvent()
|
||||
{
|
||||
if (mEventIsInternal && mEvent->eventStructType == NS_COMMAND_EVENT) {
|
||||
delete static_cast<nsCommandEvent*>(mEvent);
|
||||
delete static_cast<WidgetCommandEvent*>(mEvent);
|
||||
mEvent = nullptr;
|
||||
}
|
||||
}
|
||||
@ -39,7 +41,7 @@ NS_IMPL_RELEASE_INHERITED(nsDOMCommandEvent, nsDOMEvent)
|
||||
NS_IMETHODIMP
|
||||
nsDOMCommandEvent::GetCommand(nsAString& aCommand)
|
||||
{
|
||||
nsIAtom* command = static_cast<nsCommandEvent*>(mEvent)->command;
|
||||
nsIAtom* command = static_cast<WidgetCommandEvent*>(mEvent)->command;
|
||||
if (command) {
|
||||
command->ToString(aCommand);
|
||||
} else {
|
||||
@ -57,14 +59,14 @@ nsDOMCommandEvent::InitCommandEvent(const nsAString& aTypeArg,
|
||||
nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
static_cast<nsCommandEvent*>(mEvent)->command = do_GetAtom(aCommand);
|
||||
static_cast<WidgetCommandEvent*>(mEvent)->command = do_GetAtom(aCommand);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_NewDOMCommandEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
nsCommandEvent* aEvent)
|
||||
WidgetCommandEvent* aEvent)
|
||||
{
|
||||
nsDOMCommandEvent* it = new nsDOMCommandEvent(aOwner, aPresContext, aEvent);
|
||||
|
||||
|
@ -17,7 +17,7 @@ class nsDOMCommandEvent : public nsDOMEvent,
|
||||
public:
|
||||
nsDOMCommandEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
nsCommandEvent* aEvent);
|
||||
mozilla::WidgetCommandEvent* aEvent);
|
||||
virtual ~nsDOMCommandEvent();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -150,13 +150,15 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEvent)
|
||||
static_cast<nsMouseEvent_base*>(tmp->mEvent)->relatedTarget = nullptr;
|
||||
break;
|
||||
case NS_CLIPBOARD_EVENT:
|
||||
static_cast<nsClipboardEvent*>(tmp->mEvent)->clipboardData = nullptr;
|
||||
static_cast<InternalClipboardEvent*>(tmp->mEvent)->clipboardData =
|
||||
nullptr;
|
||||
break;
|
||||
case NS_MUTATION_EVENT:
|
||||
static_cast<nsMutationEvent*>(tmp->mEvent)->mRelatedNode = nullptr;
|
||||
static_cast<InternalMutationEvent*>(tmp->mEvent)->mRelatedNode =
|
||||
nullptr;
|
||||
break;
|
||||
case NS_FOCUS_EVENT:
|
||||
static_cast<nsFocusEvent*>(tmp->mEvent)->relatedTarget = nullptr;
|
||||
static_cast<InternalFocusEvent*>(tmp->mEvent)->relatedTarget = nullptr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -193,17 +195,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEvent)
|
||||
case NS_CLIPBOARD_EVENT:
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->clipboardData");
|
||||
cb.NoteXPCOMChild(
|
||||
static_cast<nsClipboardEvent*>(tmp->mEvent)->clipboardData);
|
||||
static_cast<InternalClipboardEvent*>(tmp->mEvent)->clipboardData);
|
||||
break;
|
||||
case NS_MUTATION_EVENT:
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->mRelatedNode");
|
||||
cb.NoteXPCOMChild(
|
||||
static_cast<nsMutationEvent*>(tmp->mEvent)->mRelatedNode);
|
||||
static_cast<InternalMutationEvent*>(tmp->mEvent)->mRelatedNode);
|
||||
break;
|
||||
case NS_FOCUS_EVENT:
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->relatedTarget");
|
||||
cb.NoteXPCOMChild(
|
||||
static_cast<nsFocusEvent*>(tmp->mEvent)->relatedTarget);
|
||||
static_cast<InternalFocusEvent*>(tmp->mEvent)->relatedTarget);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -562,17 +564,20 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
}
|
||||
case NS_CLIPBOARD_EVENT:
|
||||
{
|
||||
nsClipboardEvent* oldClipboardEvent = static_cast<nsClipboardEvent*>(mEvent);
|
||||
nsClipboardEvent* clipboardEvent = new nsClipboardEvent(false, msg);
|
||||
InternalClipboardEvent* oldClipboardEvent =
|
||||
static_cast<InternalClipboardEvent*>(mEvent);
|
||||
InternalClipboardEvent* clipboardEvent =
|
||||
new InternalClipboardEvent(false, msg);
|
||||
clipboardEvent->AssignClipboardEventData(*oldClipboardEvent, true);
|
||||
newEvent = clipboardEvent;
|
||||
break;
|
||||
}
|
||||
case NS_SCRIPT_ERROR_EVENT:
|
||||
{
|
||||
nsScriptErrorEvent* oldScriptErrorEvent =
|
||||
static_cast<nsScriptErrorEvent*>(mEvent);
|
||||
nsScriptErrorEvent* scriptErrorEvent = new nsScriptErrorEvent(false, msg);
|
||||
InternalScriptErrorEvent* oldScriptErrorEvent =
|
||||
static_cast<InternalScriptErrorEvent*>(mEvent);
|
||||
InternalScriptErrorEvent* scriptErrorEvent =
|
||||
new InternalScriptErrorEvent(false, msg);
|
||||
scriptErrorEvent->AssignScriptErrorEventData(*oldScriptErrorEvent, true);
|
||||
newEvent = scriptErrorEvent;
|
||||
break;
|
||||
@ -615,55 +620,58 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
}
|
||||
case NS_SCROLLPORT_EVENT:
|
||||
{
|
||||
nsScrollPortEvent* oldScrollPortEvent =
|
||||
static_cast<nsScrollPortEvent*>(mEvent);
|
||||
nsScrollPortEvent* scrollPortEvent =
|
||||
new nsScrollPortEvent(false, msg, nullptr);
|
||||
InternalScrollPortEvent* oldScrollPortEvent =
|
||||
static_cast<InternalScrollPortEvent*>(mEvent);
|
||||
InternalScrollPortEvent* scrollPortEvent =
|
||||
new InternalScrollPortEvent(false, msg, nullptr);
|
||||
scrollPortEvent->AssignScrollPortEventData(*oldScrollPortEvent, true);
|
||||
newEvent = scrollPortEvent;
|
||||
break;
|
||||
}
|
||||
case NS_SCROLLAREA_EVENT:
|
||||
{
|
||||
nsScrollAreaEvent* oldScrollAreaEvent =
|
||||
static_cast<nsScrollAreaEvent*>(mEvent);
|
||||
nsScrollAreaEvent* scrollAreaEvent =
|
||||
new nsScrollAreaEvent(false, msg, nullptr);
|
||||
InternalScrollAreaEvent* oldScrollAreaEvent =
|
||||
static_cast<InternalScrollAreaEvent*>(mEvent);
|
||||
InternalScrollAreaEvent* scrollAreaEvent =
|
||||
new InternalScrollAreaEvent(false, msg, nullptr);
|
||||
scrollAreaEvent->AssignScrollAreaEventData(*oldScrollAreaEvent, true);
|
||||
newEvent = scrollAreaEvent;
|
||||
break;
|
||||
}
|
||||
case NS_MUTATION_EVENT:
|
||||
{
|
||||
nsMutationEvent* mutationEvent = new nsMutationEvent(false, msg);
|
||||
nsMutationEvent* oldMutationEvent =
|
||||
static_cast<nsMutationEvent*>(mEvent);
|
||||
InternalMutationEvent* mutationEvent =
|
||||
new InternalMutationEvent(false, msg);
|
||||
InternalMutationEvent* oldMutationEvent =
|
||||
static_cast<InternalMutationEvent*>(mEvent);
|
||||
mutationEvent->AssignMutationEventData(*oldMutationEvent, true);
|
||||
newEvent = mutationEvent;
|
||||
break;
|
||||
}
|
||||
case NS_FORM_EVENT:
|
||||
{
|
||||
nsFormEvent* oldFormEvent = static_cast<nsFormEvent*>(mEvent);
|
||||
nsFormEvent* formEvent = new nsFormEvent(false, msg);
|
||||
InternalFormEvent* oldFormEvent = static_cast<InternalFormEvent*>(mEvent);
|
||||
InternalFormEvent* formEvent = new InternalFormEvent(false, msg);
|
||||
formEvent->AssignFormEventData(*oldFormEvent, true);
|
||||
newEvent = formEvent;
|
||||
break;
|
||||
}
|
||||
case NS_FOCUS_EVENT:
|
||||
{
|
||||
nsFocusEvent* newFocusEvent = new nsFocusEvent(false, msg);
|
||||
nsFocusEvent* oldFocusEvent = static_cast<nsFocusEvent*>(mEvent);
|
||||
InternalFocusEvent* newFocusEvent = new InternalFocusEvent(false, msg);
|
||||
InternalFocusEvent* oldFocusEvent =
|
||||
static_cast<InternalFocusEvent*>(mEvent);
|
||||
newFocusEvent->AssignFocusEventData(*oldFocusEvent, true);
|
||||
newEvent = newFocusEvent;
|
||||
break;
|
||||
}
|
||||
case NS_COMMAND_EVENT:
|
||||
{
|
||||
nsCommandEvent* oldCommandEvent = static_cast<nsCommandEvent*>(mEvent);
|
||||
nsCommandEvent* commandEvent =
|
||||
new nsCommandEvent(false, mEvent->userType,
|
||||
oldCommandEvent->command, nullptr);
|
||||
WidgetCommandEvent* oldCommandEvent =
|
||||
static_cast<WidgetCommandEvent*>(mEvent);
|
||||
WidgetCommandEvent* commandEvent =
|
||||
new WidgetCommandEvent(false, mEvent->userType,
|
||||
oldCommandEvent->command, nullptr);
|
||||
commandEvent->AssignCommandEventData(*oldCommandEvent, true);
|
||||
newEvent = commandEvent;
|
||||
break;
|
||||
@ -696,10 +704,10 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
}
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
{
|
||||
nsSimpleGestureEvent* oldSimpleGestureEvent =
|
||||
static_cast<nsSimpleGestureEvent*>(mEvent);
|
||||
nsSimpleGestureEvent* simpleGestureEvent =
|
||||
new nsSimpleGestureEvent(false, msg, nullptr, 0, 0.0);
|
||||
WidgetSimpleGestureEvent* oldSimpleGestureEvent =
|
||||
static_cast<WidgetSimpleGestureEvent*>(mEvent);
|
||||
WidgetSimpleGestureEvent* simpleGestureEvent =
|
||||
new WidgetSimpleGestureEvent(false, msg, nullptr, 0, 0.0);
|
||||
simpleGestureEvent->
|
||||
AssignSimpleGestureEventData(*oldSimpleGestureEvent, true);
|
||||
newEvent = simpleGestureEvent;
|
||||
@ -707,34 +715,34 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
}
|
||||
case NS_TRANSITION_EVENT:
|
||||
{
|
||||
nsTransitionEvent* oldTransitionEvent =
|
||||
static_cast<nsTransitionEvent*>(mEvent);
|
||||
nsTransitionEvent* transitionEvent =
|
||||
new nsTransitionEvent(false, msg,
|
||||
oldTransitionEvent->propertyName,
|
||||
oldTransitionEvent->elapsedTime,
|
||||
oldTransitionEvent->pseudoElement);
|
||||
InternalTransitionEvent* oldTransitionEvent =
|
||||
static_cast<InternalTransitionEvent*>(mEvent);
|
||||
InternalTransitionEvent* transitionEvent =
|
||||
new InternalTransitionEvent(false, msg,
|
||||
oldTransitionEvent->propertyName,
|
||||
oldTransitionEvent->elapsedTime,
|
||||
oldTransitionEvent->pseudoElement);
|
||||
transitionEvent->AssignTransitionEventData(*oldTransitionEvent, true);
|
||||
newEvent = transitionEvent;
|
||||
break;
|
||||
}
|
||||
case NS_ANIMATION_EVENT:
|
||||
{
|
||||
nsAnimationEvent* oldAnimationEvent =
|
||||
static_cast<nsAnimationEvent*>(mEvent);
|
||||
nsAnimationEvent* animationEvent =
|
||||
new nsAnimationEvent(false, msg,
|
||||
oldAnimationEvent->animationName,
|
||||
oldAnimationEvent->elapsedTime,
|
||||
oldAnimationEvent->pseudoElement);
|
||||
InternalAnimationEvent* oldAnimationEvent =
|
||||
static_cast<InternalAnimationEvent*>(mEvent);
|
||||
InternalAnimationEvent* animationEvent =
|
||||
new InternalAnimationEvent(false, msg,
|
||||
oldAnimationEvent->animationName,
|
||||
oldAnimationEvent->elapsedTime,
|
||||
oldAnimationEvent->pseudoElement);
|
||||
animationEvent->AssignAnimationEventData(*oldAnimationEvent, true);
|
||||
newEvent = animationEvent;
|
||||
break;
|
||||
}
|
||||
case NS_TOUCH_EVENT:
|
||||
{
|
||||
nsTouchEvent* oldTouchEvent = static_cast<nsTouchEvent*>(mEvent);
|
||||
nsTouchEvent* touchEvent = new nsTouchEvent(false, oldTouchEvent);
|
||||
WidgetTouchEvent* oldTouchEvent = static_cast<WidgetTouchEvent*>(mEvent);
|
||||
WidgetTouchEvent* touchEvent = new WidgetTouchEvent(false, oldTouchEvent);
|
||||
touchEvent->AssignTouchEventData(*oldTouchEvent, true);
|
||||
newEvent = touchEvent;
|
||||
break;
|
||||
|
@ -13,10 +13,11 @@ using namespace mozilla::dom;
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMFocusEvent, nsDOMUIEvent, nsIDOMFocusEvent)
|
||||
|
||||
nsDOMFocusEvent::nsDOMFocusEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext, nsFocusEvent* aEvent)
|
||||
: nsDOMUIEvent(aOwner, aPresContext, aEvent ?
|
||||
static_cast<nsGUIEvent*>(aEvent) :
|
||||
static_cast<nsGUIEvent*>(new nsFocusEvent(false, NS_FOCUS_CONTENT)))
|
||||
nsPresContext* aPresContext,
|
||||
InternalFocusEvent* aEvent)
|
||||
: nsDOMUIEvent(aOwner, aPresContext,
|
||||
aEvent ? aEvent :
|
||||
new InternalFocusEvent(false, NS_FOCUS_CONTENT))
|
||||
{
|
||||
if (aEvent) {
|
||||
mEventIsInternal = false;
|
||||
@ -29,7 +30,7 @@ nsDOMFocusEvent::nsDOMFocusEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsDOMFocusEvent::~nsDOMFocusEvent()
|
||||
{
|
||||
if (mEventIsInternal && mEvent) {
|
||||
delete static_cast<nsFocusEvent*>(mEvent);
|
||||
delete static_cast<InternalFocusEvent*>(mEvent);
|
||||
mEvent = nullptr;
|
||||
}
|
||||
}
|
||||
@ -46,7 +47,7 @@ nsDOMFocusEvent::GetRelatedTarget(nsIDOMEventTarget** aRelatedTarget)
|
||||
mozilla::dom::EventTarget*
|
||||
nsDOMFocusEvent::GetRelatedTarget()
|
||||
{
|
||||
return static_cast<nsFocusEvent*>(mEvent)->relatedTarget;
|
||||
return static_cast<InternalFocusEvent*>(mEvent)->relatedTarget;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -59,7 +60,7 @@ nsDOMFocusEvent::InitFocusEvent(const nsAString& aType,
|
||||
{
|
||||
nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
static_cast<nsFocusEvent*>(mEvent)->relatedTarget = aRelatedTarget;
|
||||
static_cast<InternalFocusEvent*>(mEvent)->relatedTarget = aRelatedTarget;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -81,7 +82,7 @@ nsDOMFocusEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal,
|
||||
nsresult NS_NewDOMFocusEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
nsFocusEvent* aEvent)
|
||||
InternalFocusEvent* aEvent)
|
||||
{
|
||||
nsDOMFocusEvent* it = new nsDOMFocusEvent(aOwner, aPresContext, aEvent);
|
||||
return CallQueryInterface(it, aInstancePtrResult);
|
||||
|
@ -27,7 +27,8 @@ public:
|
||||
}
|
||||
|
||||
nsDOMFocusEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext, nsFocusEvent* aEvent);
|
||||
nsPresContext* aPresContext,
|
||||
mozilla::InternalFocusEvent* aEvent);
|
||||
|
||||
mozilla::dom::EventTarget* GetRelatedTarget();
|
||||
|
||||
|
@ -17,7 +17,8 @@ class nsDOMMutationEvent : public nsDOMEvent,
|
||||
{
|
||||
public:
|
||||
nsDOMMutationEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext, nsMutationEvent* aEvent);
|
||||
nsPresContext* aPresContext,
|
||||
mozilla::InternalMutationEvent* aEvent);
|
||||
|
||||
virtual ~nsDOMMutationEvent();
|
||||
|
||||
|
@ -10,9 +10,11 @@
|
||||
#include "nsDOMScrollAreaEvent.h"
|
||||
#include "nsClientRect.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsDOMScrollAreaEvent::nsDOMScrollAreaEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext *aPresContext,
|
||||
nsScrollAreaEvent *aEvent)
|
||||
InternalScrollAreaEvent* aEvent)
|
||||
: nsDOMUIEvent(aOwner, aPresContext, aEvent)
|
||||
, mClientArea(nullptr)
|
||||
{
|
||||
@ -23,7 +25,7 @@ nsDOMScrollAreaEvent::~nsDOMScrollAreaEvent()
|
||||
{
|
||||
if (mEventIsInternal && mEvent) {
|
||||
if (mEvent->eventStructType == NS_SCROLLAREA_EVENT) {
|
||||
delete static_cast<nsScrollAreaEvent *>(mEvent);
|
||||
delete static_cast<InternalScrollAreaEvent*>(mEvent);
|
||||
mEvent = nullptr;
|
||||
}
|
||||
}
|
||||
@ -102,7 +104,7 @@ nsresult
|
||||
NS_NewDOMScrollAreaEvent(nsIDOMEvent **aInstancePtrResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext *aPresContext,
|
||||
nsScrollAreaEvent *aEvent)
|
||||
InternalScrollAreaEvent* aEvent)
|
||||
{
|
||||
nsDOMScrollAreaEvent* ev =
|
||||
new nsDOMScrollAreaEvent(aOwner, aPresContext, aEvent);
|
||||
|
@ -20,7 +20,7 @@ class nsDOMScrollAreaEvent : public nsDOMUIEvent,
|
||||
public:
|
||||
nsDOMScrollAreaEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext *aPresContext,
|
||||
nsScrollAreaEvent *aEvent);
|
||||
mozilla::InternalScrollAreaEvent* aEvent);
|
||||
virtual ~nsDOMScrollAreaEvent();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -7,11 +7,15 @@
|
||||
#include "prtime.h"
|
||||
#include "mozilla/TouchEvents.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsDOMSimpleGestureEvent::nsDOMSimpleGestureEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
nsSimpleGestureEvent* aEvent)
|
||||
WidgetSimpleGestureEvent* aEvent)
|
||||
: 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");
|
||||
|
||||
@ -28,7 +32,7 @@ nsDOMSimpleGestureEvent::nsDOMSimpleGestureEvent(mozilla::dom::EventTarget* aOwn
|
||||
nsDOMSimpleGestureEvent::~nsDOMSimpleGestureEvent()
|
||||
{
|
||||
if (mEventIsInternal) {
|
||||
delete static_cast<nsSimpleGestureEvent*>(mEvent);
|
||||
delete static_cast<WidgetSimpleGestureEvent*>(mEvent);
|
||||
mEvent = nullptr;
|
||||
}
|
||||
}
|
||||
@ -46,14 +50,14 @@ nsDOMSimpleGestureEvent::GetAllowedDirections(uint32_t *aAllowedDirections)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAllowedDirections);
|
||||
*aAllowedDirections =
|
||||
static_cast<nsSimpleGestureEvent*>(mEvent)->allowedDirections;
|
||||
static_cast<WidgetSimpleGestureEvent*>(mEvent)->allowedDirections;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMSimpleGestureEvent::SetAllowedDirections(uint32_t aAllowedDirections)
|
||||
{
|
||||
static_cast<nsSimpleGestureEvent*>(mEvent)->allowedDirections =
|
||||
static_cast<WidgetSimpleGestureEvent*>(mEvent)->allowedDirections =
|
||||
aAllowedDirections;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -123,7 +127,8 @@ nsDOMSimpleGestureEvent::InitSimpleGestureEvent(const nsAString& aTypeArg,
|
||||
aRelatedTarget);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsSimpleGestureEvent* simpleGestureEvent = static_cast<nsSimpleGestureEvent*>(mEvent);
|
||||
WidgetSimpleGestureEvent* simpleGestureEvent =
|
||||
static_cast<WidgetSimpleGestureEvent*>(mEvent);
|
||||
simpleGestureEvent->allowedDirections = aAllowedDirectionsArg;
|
||||
simpleGestureEvent->direction = aDirectionArg;
|
||||
simpleGestureEvent->delta = aDeltaArg;
|
||||
@ -135,7 +140,7 @@ nsDOMSimpleGestureEvent::InitSimpleGestureEvent(const nsAString& aTypeArg,
|
||||
nsresult NS_NewDOMSimpleGestureEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
nsSimpleGestureEvent *aEvent)
|
||||
WidgetSimpleGestureEvent* aEvent)
|
||||
{
|
||||
nsDOMSimpleGestureEvent* it =
|
||||
new nsDOMSimpleGestureEvent(aOwner, aPresContext, aEvent);
|
||||
|
@ -17,7 +17,7 @@ class nsDOMSimpleGestureEvent : public nsDOMMouseEvent,
|
||||
{
|
||||
public:
|
||||
nsDOMSimpleGestureEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext*, nsSimpleGestureEvent*);
|
||||
nsPresContext*, mozilla::WidgetSimpleGestureEvent*);
|
||||
virtual ~nsDOMSimpleGestureEvent();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -35,22 +35,23 @@ public:
|
||||
|
||||
uint32_t AllowedDirections()
|
||||
{
|
||||
return static_cast<nsSimpleGestureEvent*>(mEvent)->allowedDirections;
|
||||
return static_cast<mozilla::WidgetSimpleGestureEvent*>(mEvent)->
|
||||
allowedDirections;
|
||||
}
|
||||
|
||||
uint32_t Direction()
|
||||
{
|
||||
return static_cast<nsSimpleGestureEvent*>(mEvent)->direction;
|
||||
return static_cast<mozilla::WidgetSimpleGestureEvent*>(mEvent)->direction;
|
||||
}
|
||||
|
||||
double Delta()
|
||||
{
|
||||
return static_cast<nsSimpleGestureEvent*>(mEvent)->delta;
|
||||
return static_cast<mozilla::WidgetSimpleGestureEvent*>(mEvent)->delta;
|
||||
}
|
||||
|
||||
uint32_t ClickCount()
|
||||
{
|
||||
return static_cast<nsSimpleGestureEvent*>(mEvent)->clickCount;
|
||||
return static_cast<mozilla::WidgetSimpleGestureEvent*>(mEvent)->clickCount;
|
||||
}
|
||||
|
||||
void InitSimpleGestureEvent(const nsAString& aType,
|
||||
|
@ -54,9 +54,9 @@ nsDOMTouchList::IdentifiedTouch(int32_t aIdentifier) const
|
||||
|
||||
nsDOMTouchEvent::nsDOMTouchEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
nsTouchEvent* aEvent)
|
||||
WidgetTouchEvent* aEvent)
|
||||
: nsDOMUIEvent(aOwner, aPresContext,
|
||||
aEvent ? aEvent : new nsTouchEvent(false, 0, nullptr))
|
||||
aEvent ? aEvent : new WidgetTouchEvent(false, 0, nullptr))
|
||||
{
|
||||
if (aEvent) {
|
||||
mEventIsInternal = false;
|
||||
@ -74,7 +74,7 @@ nsDOMTouchEvent::nsDOMTouchEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsDOMTouchEvent::~nsDOMTouchEvent()
|
||||
{
|
||||
if (mEventIsInternal && mEvent) {
|
||||
delete static_cast<nsTouchEvent*>(mEvent);
|
||||
delete static_cast<WidgetTouchEvent*>(mEvent);
|
||||
mEvent = nullptr;
|
||||
}
|
||||
}
|
||||
@ -126,7 +126,7 @@ nsDOMTouchList*
|
||||
nsDOMTouchEvent::Touches()
|
||||
{
|
||||
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) {
|
||||
// for touchend events, remove any changed touches from the touches array
|
||||
nsTArray< nsRefPtr<Touch> > unchangedTouches;
|
||||
@ -149,7 +149,7 @@ nsDOMTouchEvent::TargetTouches()
|
||||
{
|
||||
if (!mTargetTouches) {
|
||||
nsTArray< nsRefPtr<Touch> > targetTouches;
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
|
||||
WidgetTouchEvent* touchEvent = static_cast<WidgetTouchEvent*>(mEvent);
|
||||
const nsTArray< nsRefPtr<Touch> >& touches = touchEvent->touches;
|
||||
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
||||
// for touchend/cancel events, don't append to the target list if this is a
|
||||
@ -171,7 +171,7 @@ nsDOMTouchEvent::ChangedTouches()
|
||||
{
|
||||
if (!mChangedTouches) {
|
||||
nsTArray< nsRefPtr<Touch> > changedTouches;
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
|
||||
WidgetTouchEvent* touchEvent = static_cast<WidgetTouchEvent*>(mEvent);
|
||||
const nsTArray< nsRefPtr<Touch> >& touches = touchEvent->touches;
|
||||
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
||||
if (touches[i]->mChanged) {
|
||||
@ -225,7 +225,7 @@ nsresult
|
||||
NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
nsTouchEvent *aEvent)
|
||||
WidgetTouchEvent* aEvent)
|
||||
{
|
||||
nsDOMTouchEvent* it = new nsDOMTouchEvent(aOwner, aPresContext, aEvent);
|
||||
return CallQueryInterface(it, aInstancePtrResult);
|
||||
|
@ -82,7 +82,8 @@ class nsDOMTouchEvent : public nsDOMUIEvent
|
||||
{
|
||||
public:
|
||||
nsDOMTouchEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext, nsTouchEvent* aEvent);
|
||||
nsPresContext* aPresContext,
|
||||
mozilla::WidgetTouchEvent* aEvent);
|
||||
virtual ~nsDOMTouchEvent();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -7,14 +7,15 @@
|
||||
#include "prtime.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsDOMTransitionEvent::nsDOMTransitionEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext *aPresContext,
|
||||
nsTransitionEvent *aEvent)
|
||||
InternalTransitionEvent* aEvent)
|
||||
: nsDOMEvent(aOwner, aPresContext,
|
||||
aEvent ? aEvent : new nsTransitionEvent(false, 0,
|
||||
EmptyString(),
|
||||
0.0,
|
||||
EmptyString()))
|
||||
aEvent ? aEvent :
|
||||
new InternalTransitionEvent(false, 0, EmptyString(),
|
||||
0.0, EmptyString()))
|
||||
{
|
||||
if (aEvent) {
|
||||
mEventIsInternal = false;
|
||||
@ -86,7 +87,7 @@ nsresult
|
||||
NS_NewDOMTransitionEvent(nsIDOMEvent **aInstancePtrResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext *aPresContext,
|
||||
nsTransitionEvent *aEvent)
|
||||
InternalTransitionEvent* aEvent)
|
||||
{
|
||||
nsDOMTransitionEvent *it =
|
||||
new nsDOMTransitionEvent(aOwner, aPresContext, aEvent);
|
||||
|
@ -18,7 +18,7 @@ class nsDOMTransitionEvent : public nsDOMEvent,
|
||||
public:
|
||||
nsDOMTransitionEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext *aPresContext,
|
||||
nsTransitionEvent *aEvent);
|
||||
mozilla::InternalTransitionEvent* aEvent);
|
||||
~nsDOMTransitionEvent();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -47,10 +47,10 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
nsTransitionEvent* TransitionEvent() {
|
||||
mozilla::InternalTransitionEvent* TransitionEvent() {
|
||||
NS_ABORT_IF_FALSE(mEvent->eventStructType == NS_TRANSITION_EVENT,
|
||||
"unexpected struct type");
|
||||
return static_cast<nsTransitionEvent*>(mEvent);
|
||||
return static_cast<mozilla::InternalTransitionEvent*>(mEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -52,7 +52,8 @@ nsDOMUIEvent::nsDOMUIEvent(mozilla::dom::EventTarget* aOwner,
|
||||
|
||||
case NS_SCROLLPORT_EVENT:
|
||||
{
|
||||
nsScrollPortEvent* scrollEvent = static_cast<nsScrollPortEvent*>(mEvent);
|
||||
InternalScrollPortEvent* scrollEvent =
|
||||
static_cast<InternalScrollPortEvent*>(mEvent);
|
||||
mDetail = (int32_t)scrollEvent->orient;
|
||||
break;
|
||||
}
|
||||
|
@ -690,7 +690,7 @@ nsEventDispatcher::CreateEvent(mozilla::dom::EventTarget* aOwner,
|
||||
switch(aEvent->eventStructType) {
|
||||
case NS_MUTATION_EVENT:
|
||||
return NS_NewDOMMutationEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsMutationEvent*>(aEvent));
|
||||
static_cast<InternalMutationEvent*>(aEvent));
|
||||
case NS_GUI_EVENT:
|
||||
case NS_SCROLLPORT_EVENT:
|
||||
case NS_UI_EVENT:
|
||||
@ -698,7 +698,7 @@ nsEventDispatcher::CreateEvent(mozilla::dom::EventTarget* aOwner,
|
||||
static_cast<nsGUIEvent*>(aEvent));
|
||||
case NS_SCROLLAREA_EVENT:
|
||||
return NS_NewDOMScrollAreaEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsScrollAreaEvent *>(aEvent));
|
||||
static_cast<InternalScrollAreaEvent*>(aEvent));
|
||||
case NS_KEY_EVENT:
|
||||
return NS_NewDOMKeyboardEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsKeyEvent*>(aEvent));
|
||||
@ -711,7 +711,7 @@ nsEventDispatcher::CreateEvent(mozilla::dom::EventTarget* aOwner,
|
||||
static_cast<nsInputEvent*>(aEvent));
|
||||
case NS_FOCUS_EVENT:
|
||||
return NS_NewDOMFocusEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsFocusEvent*>(aEvent));
|
||||
static_cast<InternalFocusEvent*>(aEvent));
|
||||
case NS_MOUSE_SCROLL_EVENT:
|
||||
return NS_NewDOMMouseScrollEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsInputEvent*>(aEvent));
|
||||
@ -726,7 +726,7 @@ nsEventDispatcher::CreateEvent(mozilla::dom::EventTarget* aOwner,
|
||||
static_cast<nsTextEvent*>(aEvent));
|
||||
case NS_CLIPBOARD_EVENT:
|
||||
return NS_NewDOMClipboardEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsClipboardEvent*>(aEvent));
|
||||
static_cast<InternalClipboardEvent*>(aEvent));
|
||||
case NS_SVGZOOM_EVENT:
|
||||
return NS_NewDOMSVGZoomEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsGUIEvent*>(aEvent));
|
||||
@ -735,19 +735,19 @@ nsEventDispatcher::CreateEvent(mozilla::dom::EventTarget* aOwner,
|
||||
|
||||
case NS_COMMAND_EVENT:
|
||||
return NS_NewDOMCommandEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsCommandEvent*>(aEvent));
|
||||
static_cast<WidgetCommandEvent*>(aEvent));
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
return NS_NewDOMSimpleGestureEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsSimpleGestureEvent*>(aEvent));
|
||||
static_cast<WidgetSimpleGestureEvent*>(aEvent));
|
||||
case NS_TOUCH_EVENT:
|
||||
return NS_NewDOMTouchEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsTouchEvent*>(aEvent));
|
||||
static_cast<WidgetTouchEvent*>(aEvent));
|
||||
case NS_TRANSITION_EVENT:
|
||||
return NS_NewDOMTransitionEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsTransitionEvent*>(aEvent));
|
||||
static_cast<InternalTransitionEvent*>(aEvent));
|
||||
case NS_ANIMATION_EVENT:
|
||||
return NS_NewDOMAnimationEvent(aDOMEvent, aOwner, aPresContext,
|
||||
static_cast<nsAnimationEvent*>(aEvent));
|
||||
static_cast<InternalAnimationEvent*>(aEvent));
|
||||
default:
|
||||
// For all other types of events, create a vanilla event object.
|
||||
return NS_NewDOMEvent(aDOMEvent, aOwner, aPresContext, aEvent);
|
||||
|
@ -1073,12 +1073,13 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
case NS_CONTENT_COMMAND_REDO:
|
||||
case NS_CONTENT_COMMAND_PASTE_TRANSFERABLE:
|
||||
{
|
||||
DoContentCommandEvent(static_cast<nsContentCommandEvent*>(aEvent));
|
||||
DoContentCommandEvent(static_cast<WidgetContentCommandEvent*>(aEvent));
|
||||
}
|
||||
break;
|
||||
case NS_CONTENT_COMMAND_SCROLL:
|
||||
{
|
||||
DoContentCommandScrollEvent(static_cast<nsContentCommandEvent*>(aEvent));
|
||||
DoContentCommandScrollEvent(
|
||||
static_cast<WidgetContentCommandEvent*>(aEvent));
|
||||
}
|
||||
break;
|
||||
case NS_TEXT_TEXT:
|
||||
@ -1398,7 +1399,7 @@ nsEventStateManager::DispatchCrossProcessEvent(nsEvent* aEvent,
|
||||
// Let the child process synthesize a mouse event if needed, and
|
||||
// ensure we don't synthesize one in this process.
|
||||
*aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||
WidgetTouchEvent* touchEvent = static_cast<WidgetTouchEvent*>(aEvent);
|
||||
return remote->SendRealTouchEvent(*touchEvent);
|
||||
}
|
||||
default: {
|
||||
@ -1515,7 +1516,7 @@ nsEventStateManager::HandleCrossProcessEvent(nsEvent *aEvent,
|
||||
//
|
||||
// This loop is similar to the one used in
|
||||
// PresShell::DispatchTouchEvent().
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||
WidgetTouchEvent* touchEvent = static_cast<WidgetTouchEvent*>(aEvent);
|
||||
const nsTArray< nsRefPtr<Touch> >& touches = touchEvent->touches;
|
||||
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
||||
Touch* touch = touches[i];
|
||||
@ -2808,7 +2809,7 @@ nsEventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame,
|
||||
}
|
||||
|
||||
void
|
||||
nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent,
|
||||
nsEventStateManager::DecideGestureEvent(WidgetGestureNotifyEvent* aEvent,
|
||||
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
|
||||
*/
|
||||
nsGestureNotifyEvent::ePanDirection panDirection = nsGestureNotifyEvent::ePanNone;
|
||||
WidgetGestureNotifyEvent::ePanDirection panDirection =
|
||||
WidgetGestureNotifyEvent::ePanNone;
|
||||
bool displayPanFeedback = false;
|
||||
for (nsIFrame* current = targetFrame; current;
|
||||
current = nsLayoutUtils::GetCrossDocParentFrame(current)) {
|
||||
@ -2836,7 +2838,7 @@ nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent,
|
||||
|
||||
// Scrollbars should always be draggable
|
||||
if (currentFrameType == nsGkAtoms::scrollbarFrame) {
|
||||
panDirection = nsGestureNotifyEvent::ePanNone;
|
||||
panDirection = WidgetGestureNotifyEvent::ePanNone;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2845,10 +2847,10 @@ nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent,
|
||||
nsTreeBodyFrame* treeFrame = do_QueryFrame(current);
|
||||
if (treeFrame) {
|
||||
if (treeFrame->GetHorizontalOverflow()) {
|
||||
panDirection = nsGestureNotifyEvent::ePanHorizontal;
|
||||
panDirection = WidgetGestureNotifyEvent::ePanHorizontal;
|
||||
}
|
||||
if (treeFrame->GetVerticalOverflow()) {
|
||||
panDirection = nsGestureNotifyEvent::ePanVertical;
|
||||
panDirection = WidgetGestureNotifyEvent::ePanVertical;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2872,12 +2874,12 @@ nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent,
|
||||
// Vertical panning has priority over horizontal panning, so
|
||||
// when vertical movement is possible we can just finish the loop.
|
||||
if (scrollRange.height > 0) {
|
||||
panDirection = nsGestureNotifyEvent::ePanVertical;
|
||||
panDirection = WidgetGestureNotifyEvent::ePanVertical;
|
||||
break;
|
||||
}
|
||||
|
||||
if (canScrollHorizontally) {
|
||||
panDirection = nsGestureNotifyEvent::ePanHorizontal;
|
||||
panDirection = WidgetGestureNotifyEvent::ePanHorizontal;
|
||||
displayPanFeedback = false;
|
||||
}
|
||||
} else { //Not a XUL box
|
||||
@ -2885,13 +2887,13 @@ nsEventStateManager::DecideGestureEvent(nsGestureNotifyEvent* aEvent,
|
||||
|
||||
//Check if we have visible scrollbars
|
||||
if (scrollbarVisibility & nsIScrollableFrame::VERTICAL) {
|
||||
panDirection = nsGestureNotifyEvent::ePanVertical;
|
||||
panDirection = WidgetGestureNotifyEvent::ePanVertical;
|
||||
displayPanFeedback = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (scrollbarVisibility & nsIScrollableFrame::HORIZONTAL) {
|
||||
panDirection = nsGestureNotifyEvent::ePanHorizontal;
|
||||
panDirection = WidgetGestureNotifyEvent::ePanHorizontal;
|
||||
displayPanFeedback = true;
|
||||
}
|
||||
}
|
||||
@ -3221,7 +3223,8 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
case NS_GESTURENOTIFY_EVENT_START:
|
||||
{
|
||||
if (nsEventStatus_eConsumeNoDefault != *aStatus)
|
||||
DecideGestureEvent(static_cast<nsGestureNotifyEvent*>(aEvent), mCurrentTarget);
|
||||
DecideGestureEvent(static_cast<WidgetGestureNotifyEvent*>(aEvent),
|
||||
mCurrentTarget);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -4921,7 +4924,7 @@ nsEventStateManager::IsShellVisible(nsIDocShell* aShell)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEventStateManager::DoContentCommandEvent(nsContentCommandEvent* aEvent)
|
||||
nsEventStateManager::DoContentCommandEvent(WidgetContentCommandEvent* aEvent)
|
||||
{
|
||||
EnsureDocument(mPresContext);
|
||||
NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
|
||||
@ -4996,7 +4999,8 @@ nsEventStateManager::DoContentCommandEvent(nsContentCommandEvent* aEvent)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEventStateManager::DoContentCommandScrollEvent(nsContentCommandEvent* aEvent)
|
||||
nsEventStateManager::DoContentCommandScrollEvent(
|
||||
WidgetContentCommandEvent* aEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE);
|
||||
nsIPresShell* ps = mPresContext->GetPresShell();
|
||||
@ -5005,13 +5009,13 @@ nsEventStateManager::DoContentCommandScrollEvent(nsContentCommandEvent* aEvent)
|
||||
|
||||
nsIScrollableFrame::ScrollUnit scrollUnit;
|
||||
switch (aEvent->mScroll.mUnit) {
|
||||
case nsContentCommandEvent::eCmdScrollUnit_Line:
|
||||
case WidgetContentCommandEvent::eCmdScrollUnit_Line:
|
||||
scrollUnit = nsIScrollableFrame::LINES;
|
||||
break;
|
||||
case nsContentCommandEvent::eCmdScrollUnit_Page:
|
||||
case WidgetContentCommandEvent::eCmdScrollUnit_Page:
|
||||
scrollUnit = nsIScrollableFrame::PAGES;
|
||||
break;
|
||||
case nsContentCommandEvent::eCmdScrollUnit_Whole:
|
||||
case WidgetContentCommandEvent::eCmdScrollUnit_Whole:
|
||||
scrollUnit = nsIScrollableFrame::WHOLE;
|
||||
break;
|
||||
default:
|
||||
|
@ -655,7 +655,8 @@ protected:
|
||||
* the target element, as well as the orientation to trigger panning and
|
||||
* 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
|
||||
void BeginTrackingDragGesture ( nsPresContext* aPresContext, nsMouseEvent* inDownEvent,
|
||||
@ -704,8 +705,9 @@ protected:
|
||||
*/
|
||||
void FillInEventFromGestureDown(nsMouseEvent* aEvent);
|
||||
|
||||
nsresult DoContentCommandEvent(nsContentCommandEvent* aEvent);
|
||||
nsresult DoContentCommandScrollEvent(nsContentCommandEvent* aEvent);
|
||||
nsresult DoContentCommandEvent(mozilla::WidgetContentCommandEvent* aEvent);
|
||||
nsresult DoContentCommandScrollEvent(
|
||||
mozilla::WidgetContentCommandEvent* aEvent);
|
||||
|
||||
void DoQuerySelectedText(nsQueryContentEvent* aEvent);
|
||||
|
||||
|
@ -347,9 +347,8 @@ HTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
if (aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT) {
|
||||
if (mForm && (mType == NS_FORM_BUTTON_SUBMIT ||
|
||||
mType == NS_FORM_BUTTON_RESET)) {
|
||||
nsFormEvent event(true,
|
||||
(mType == NS_FORM_BUTTON_RESET)
|
||||
? NS_FORM_RESET : NS_FORM_SUBMIT);
|
||||
InternalFormEvent event(true,
|
||||
(mType == NS_FORM_BUTTON_RESET) ? NS_FORM_RESET : NS_FORM_SUBMIT);
|
||||
event.originator = this;
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
|
||||
|
@ -422,7 +422,7 @@ HTMLFormElement::Submit()
|
||||
NS_IMETHODIMP
|
||||
HTMLFormElement::Reset()
|
||||
{
|
||||
nsFormEvent event(true, NS_FORM_RESET);
|
||||
InternalFormEvent event(true, NS_FORM_RESET);
|
||||
nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), nullptr,
|
||||
&event);
|
||||
return NS_OK;
|
||||
@ -822,13 +822,15 @@ HTMLFormElement::BuildSubmission(nsFormSubmission** aFormSubmission,
|
||||
nsGenericHTMLElement* originatingElement = nullptr;
|
||||
if (aEvent) {
|
||||
if (NS_FORM_EVENT == aEvent->eventStructType) {
|
||||
nsIContent* originator = ((nsFormEvent *)aEvent)->originator;
|
||||
nsIContent* originator =
|
||||
static_cast<InternalFormEvent*>(aEvent)->originator;
|
||||
if (originator) {
|
||||
if (!originator->IsHTML()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
originatingElement =
|
||||
static_cast<nsGenericHTMLElement*>(((nsFormEvent *)aEvent)->originator);
|
||||
static_cast<nsGenericHTMLElement*>(
|
||||
static_cast<InternalFormEvent*>(aEvent)->originator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2810,7 +2810,7 @@ HTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
|
||||
// If there's only one text control, just submit the form
|
||||
// Hold strong ref across the event
|
||||
nsRefPtr<mozilla::dom::HTMLFormElement> form = mForm;
|
||||
nsFormEvent event(true, NS_FORM_SUBMIT);
|
||||
InternalFormEvent event(true, NS_FORM_SUBMIT);
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
shell->HandleDOMEventWithTarget(mForm, &event, &status);
|
||||
}
|
||||
@ -3393,7 +3393,7 @@ HTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
// just because we raised a window.
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm && IsSingleLineTextControl(false) &&
|
||||
!(static_cast<nsFocusEvent*>(aVisitor.mEvent))->fromRaise &&
|
||||
!(static_cast<InternalFocusEvent*>(aVisitor.mEvent))->fromRaise &&
|
||||
SelectTextFieldOnFocus()) {
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
@ -3616,8 +3616,8 @@ HTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
case NS_FORM_INPUT_SUBMIT:
|
||||
case NS_FORM_INPUT_IMAGE:
|
||||
if (mForm) {
|
||||
nsFormEvent event(true, (mType == NS_FORM_INPUT_RESET) ?
|
||||
NS_FORM_RESET : NS_FORM_SUBMIT);
|
||||
InternalFormEvent event(true,
|
||||
(mType == NS_FORM_INPUT_RESET) ? NS_FORM_RESET : NS_FORM_SUBMIT);
|
||||
event.originator = this;
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
|
||||
@ -3709,7 +3709,8 @@ HTMLInputElement::PostHandleEventForRangeThumb(nsEventChainPostVisitor& aVisitor
|
||||
CancelRangeThumbDrag();
|
||||
}
|
||||
} else {
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aVisitor.mEvent);
|
||||
WidgetTouchEvent* touchEvent =
|
||||
static_cast<WidgetTouchEvent*>(aVisitor.mEvent);
|
||||
if (touchEvent->touches.Length() == 1) {
|
||||
StartRangeThumbDrag(inputEvent);
|
||||
} else if (mIsDraggingRange) {
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include "nsHostObjectProtocolHandler.h"
|
||||
#include "mozilla/dom/MediaSource.h"
|
||||
#include "MediaMetadataManager.h"
|
||||
#include "MediaSourceDecoder.h"
|
||||
|
||||
#include "AudioChannelService.h"
|
||||
|
||||
@ -601,7 +602,7 @@ void HTMLMediaElement::AbortExistingLoads()
|
||||
EndSrcMediaStreamPlayback();
|
||||
}
|
||||
if (mMediaSource) {
|
||||
mMediaSource->DetachElement();
|
||||
mMediaSource->Detach();
|
||||
mMediaSource = nullptr;
|
||||
}
|
||||
if (mAudioStream) {
|
||||
@ -1135,16 +1136,15 @@ nsresult HTMLMediaElement::LoadResource()
|
||||
return rv;
|
||||
}
|
||||
mMediaSource = source.forget();
|
||||
if (!mMediaSource->AttachElement(this)) {
|
||||
// XXX(kinetik): Handle failure: run "If the media data cannot be
|
||||
// fetched at all, due to network errors, causing the user agent to
|
||||
// give up trying to fetch the resource" section of resource fetch
|
||||
// algorithm.
|
||||
nsRefPtr<MediaSourceDecoder> decoder = new MediaSourceDecoder(this);
|
||||
if (!mMediaSource->Attach(decoder)) {
|
||||
// TODO: Handle failure: run "If the media data cannot be fetched at
|
||||
// all, due to network errors, causing the user agent to give up
|
||||
// trying to fetch the resource" section of resource fetch algorithm.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// XXX(kinetik): Bug 881512. Wire this up properly; return from here (as
|
||||
// MediaStreams setup does) rather than relying on mediasource->channel
|
||||
// conversion.
|
||||
nsRefPtr<MediaResource> resource = new MediaSourceResource();
|
||||
return FinishDecoderSetup(decoder, resource, nullptr, nullptr);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
|
||||
@ -1406,6 +1406,7 @@ HTMLMediaElement::Seekable() const
|
||||
} else if (mDecoder && mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) {
|
||||
mDecoder->GetSeekable(ranges);
|
||||
}
|
||||
ranges->Normalize();
|
||||
return ranges.forget();
|
||||
}
|
||||
|
||||
@ -1989,7 +1990,7 @@ HTMLMediaElement::~HTMLMediaElement()
|
||||
EndSrcMediaStreamPlayback();
|
||||
}
|
||||
if (mMediaSource) {
|
||||
mMediaSource->DetachElement();
|
||||
mMediaSource->Detach();
|
||||
mMediaSource = nullptr;
|
||||
}
|
||||
|
||||
@ -3561,6 +3562,7 @@ HTMLMediaElement::Buffered() const
|
||||
// time ranges we found up till the error.
|
||||
mDecoder->GetBuffered(ranges);
|
||||
}
|
||||
ranges->Normalize();
|
||||
return ranges.forget();
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@ SimpleTest.waitForExplicitFinish();
|
||||
function testViewport() {
|
||||
|
||||
/* We need to access the document headers, which are chrome-only. */
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
/* Grab Viewport Metadata from the document header. */
|
||||
var windowUtils = SpecialPowers.getDOMWindowUtils(window);
|
||||
|
@ -20,7 +20,7 @@ namespace mozilla {
|
||||
class BufferDecoder : public AbstractMediaDecoder
|
||||
{
|
||||
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.
|
||||
explicit BufferDecoder(MediaResource* aResource);
|
||||
virtual ~BufferDecoder();
|
||||
@ -30,51 +30,51 @@ public:
|
||||
// This has to be called before decoding begins
|
||||
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;
|
||||
layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
|
||||
virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL 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;
|
||||
void QueueMetadata(int64_t aTime, 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;
|
||||
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.
|
||||
// It's just there in order for us to be able to override
|
||||
// GetReentrantMonitor correctly.
|
||||
|
@ -535,8 +535,8 @@ nsresult MediaDecoderReader::DecodeToTarget(int64_t aTarget)
|
||||
const AudioData* audio = AudioQueue().PeekFront();
|
||||
if (!audio)
|
||||
break;
|
||||
CheckedInt64 startFrame = UsecsToFrames(audio->mTime, mInfo.mAudioRate);
|
||||
CheckedInt64 targetFrame = UsecsToFrames(aTarget, mInfo.mAudioRate);
|
||||
CheckedInt64 startFrame = UsecsToFrames(audio->mTime, mInfo.mAudio.mRate);
|
||||
CheckedInt64 targetFrame = UsecsToFrames(aTarget, mInfo.mAudio.mRate);
|
||||
if (!startFrame.isValid() || !targetFrame.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -580,7 +580,7 @@ nsresult MediaDecoderReader::DecodeToTarget(int64_t aTarget)
|
||||
memcpy(audioData.get(),
|
||||
audio->mAudioData.get() + (framesToPrune * channels),
|
||||
frames * channels * sizeof(AudioDataValue));
|
||||
CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudioRate);
|
||||
CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudio.mRate);
|
||||
if (!duration.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -31,11 +31,8 @@ class TimeRanges;
|
||||
class VideoInfo {
|
||||
public:
|
||||
VideoInfo()
|
||||
: mAudioRate(44100),
|
||||
mAudioChannels(2),
|
||||
mDisplay(0,0),
|
||||
: mDisplay(0,0),
|
||||
mStereoMode(STEREO_MODE_MONO),
|
||||
mHasAudio(false),
|
||||
mHasVideo(false)
|
||||
{}
|
||||
|
||||
@ -47,12 +44,6 @@ public:
|
||||
const nsIntRect& aPicture,
|
||||
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
|
||||
// been scaled by its aspect ratio.
|
||||
nsIntSize mDisplay;
|
||||
@ -60,13 +51,49 @@ public:
|
||||
// Indicates the frame layout for single track stereo videos.
|
||||
StereoMode mStereoMode;
|
||||
|
||||
// True if we have an active audio bitstream.
|
||||
bool mHasAudio;
|
||||
|
||||
// True if we have an active video bitstream.
|
||||
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.
|
||||
class AudioData {
|
||||
public:
|
||||
@ -448,7 +475,7 @@ public:
|
||||
// the data required to present the media, and optionally fills *aTags
|
||||
// with tag metadata from the file.
|
||||
// Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
|
||||
virtual nsresult ReadMetadata(VideoInfo* aInfo,
|
||||
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags) = 0;
|
||||
|
||||
// Stores the presentation time of the first frame we'd be able to play if
|
||||
@ -558,7 +585,7 @@ protected:
|
||||
AbstractMediaDecoder* mDecoder;
|
||||
|
||||
// Stores presentation info required for playback.
|
||||
VideoInfo mInfo;
|
||||
MediaInfo mInfo;
|
||||
|
||||
// Whether we should accept media that we know we can't play
|
||||
// directly, because they have a number of channel higher than
|
||||
|
@ -558,9 +558,9 @@ void MediaDecoderStateMachine::SendStreamAudio(AudioData* aAudio,
|
||||
|
||||
// This logic has to mimic AudioLoop closely to make sure we write
|
||||
// the exact same silences
|
||||
CheckedInt64 audioWrittenOffset = UsecsToFrames(mInfo.mAudioRate,
|
||||
CheckedInt64 audioWrittenOffset = UsecsToFrames(mInfo.mAudio.mRate,
|
||||
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())
|
||||
return;
|
||||
if (audioWrittenOffset.value() < frameOffset.value()) {
|
||||
@ -641,18 +641,18 @@ void MediaDecoderStateMachine::SendStreamData()
|
||||
StreamTime endPosition = 0;
|
||||
|
||||
if (!stream->mStreamInitialized) {
|
||||
if (mInfo.mHasAudio) {
|
||||
if (mInfo.HasAudio()) {
|
||||
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();
|
||||
mediaStream->AddTrack(TRACK_VIDEO, RATE_VIDEO, 0, video);
|
||||
}
|
||||
stream->mStreamInitialized = true;
|
||||
}
|
||||
|
||||
if (mInfo.mHasAudio) {
|
||||
if (mInfo.HasAudio()) {
|
||||
nsAutoTArray<AudioData*,10> 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).
|
||||
@ -670,10 +670,10 @@ void MediaDecoderStateMachine::SendStreamData()
|
||||
}
|
||||
minLastAudioPacketTime = std::min(minLastAudioPacketTime, stream->mLastAudioPacketTime);
|
||||
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;
|
||||
// It's OK to hold references to the VideoData only the decoder thread
|
||||
// pops from the queue.
|
||||
@ -723,8 +723,8 @@ void MediaDecoderStateMachine::SendStreamData()
|
||||
}
|
||||
|
||||
bool finished =
|
||||
(!mInfo.mHasAudio || mReader->AudioQueue().IsFinished()) &&
|
||||
(!mInfo.mHasVideo || mReader->VideoQueue().IsFinished());
|
||||
(!mInfo.HasAudio() || mReader->AudioQueue().IsFinished()) &&
|
||||
(!mInfo.HasVideo() || mReader->VideoQueue().IsFinished());
|
||||
if (finished && !stream->mHaveSentFinish) {
|
||||
stream->mHaveSentFinish = true;
|
||||
stream->mStream->Finish();
|
||||
@ -1045,8 +1045,8 @@ void MediaDecoderStateMachine::AudioLoop()
|
||||
mAudioCompleted = false;
|
||||
audioStartTime = mAudioStartTime;
|
||||
NS_ASSERTION(audioStartTime != -1, "Should have audio start time by now");
|
||||
channels = mInfo.mAudioChannels;
|
||||
rate = mInfo.mAudioRate;
|
||||
channels = mInfo.mAudio.mChannels;
|
||||
rate = mInfo.mAudio.mRate;
|
||||
|
||||
audioChannelType = mDecoder->GetAudioChannelType();
|
||||
volume = mVolume;
|
||||
@ -1898,7 +1898,7 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
|
||||
|
||||
LOG(PR_LOG_DEBUG, ("%p Decoding Media Headers", mDecoder.get()));
|
||||
nsresult res;
|
||||
VideoInfo info;
|
||||
MediaInfo info;
|
||||
MetadataTags* tags;
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
@ -1912,7 +1912,7 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
|
||||
|
||||
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
|
||||
// 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
|
||||
@ -1957,18 +1957,18 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
|
||||
// if there is audio, let the MozAudioAvailable event manager know about
|
||||
// the metadata.
|
||||
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
|
||||
// to retrive the value via media element method. The RequestFrameBufferLength
|
||||
// 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);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> metadataLoadedEvent =
|
||||
new AudioMetadataEventRunner(mDecoder,
|
||||
mInfo.mAudioChannels,
|
||||
mInfo.mAudioRate,
|
||||
mInfo.mAudio.mChannels,
|
||||
mInfo.mAudio.mRate,
|
||||
HasAudio(),
|
||||
HasVideo(),
|
||||
tags);
|
||||
|
@ -228,14 +228,14 @@ public:
|
||||
// The decoder monitor must be obtained before calling this.
|
||||
bool HasAudio() const {
|
||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
return mInfo.mHasAudio;
|
||||
return mInfo.HasAudio();
|
||||
}
|
||||
|
||||
// This is called on the state machine thread and audio thread.
|
||||
// The decoder monitor must be obtained before calling this.
|
||||
bool HasVideo() const {
|
||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
return mInfo.mHasVideo;
|
||||
return mInfo.HasVideo();
|
||||
}
|
||||
|
||||
// Should be called by main thread.
|
||||
@ -810,7 +810,7 @@ private:
|
||||
|
||||
// Stores presentation info required for playback. The decoder monitor
|
||||
// must be held when accessing this.
|
||||
VideoInfo mInfo;
|
||||
MediaInfo mInfo;
|
||||
|
||||
mozilla::MediaMetadataManager mMetadataManager;
|
||||
|
||||
|
@ -183,6 +183,12 @@ public:
|
||||
if (!mReadThread) {
|
||||
nsresult rv = NS_NewNamedThread("Media Encoder", getter_AddRefs(mReadThread));
|
||||
if (NS_FAILED(rv)) {
|
||||
if (mInputPort.get()) {
|
||||
mInputPort->Destroy();
|
||||
}
|
||||
if (mTrackUnionStream.get()) {
|
||||
mTrackUnionStream->Destroy();
|
||||
}
|
||||
mRecorder->NotifyError(rv);
|
||||
return;
|
||||
}
|
||||
@ -363,6 +369,16 @@ MediaRecorder::Start(const Optional<int32_t>& aTimeSlice, ErrorResult& aResult)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mStream->GetPrincipal()) {
|
||||
aResult.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CheckPrincipal()) {
|
||||
aResult.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t timeSlice = 0;
|
||||
if (aTimeSlice.WasPassed()) {
|
||||
if (aTimeSlice.Value() < 0) {
|
||||
@ -373,11 +389,6 @@ MediaRecorder::Start(const Optional<int32_t>& aTimeSlice, ErrorResult& aResult)
|
||||
timeSlice = aTimeSlice.Value();
|
||||
}
|
||||
|
||||
if (!CheckPrincipal()) {
|
||||
aResult.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
mState = RecordingState::Recording;
|
||||
// Start a session
|
||||
mSession = new Session(this, timeSlice);
|
||||
|
@ -113,6 +113,7 @@ TextTrack::AddRegion(TextTrackRegion& aRegion)
|
||||
{
|
||||
TextTrackRegion* region = mRegionList->GetRegionById(aRegion.Id());
|
||||
if (!region) {
|
||||
aRegion.SetTextTrack(this);
|
||||
mRegionList->AddTextTrackRegion(&aRegion);
|
||||
return;
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
* 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 "mozilla/dom/TextTrack.h"
|
||||
#include "mozilla/dom/TextTrackRegion.h"
|
||||
#include "mozilla/dom/VTTRegionBinding.h"
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsString.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/TextTrack.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -144,6 +145,11 @@ public:
|
||||
|
||||
/** end WebIDL Methods. */
|
||||
|
||||
void SetTextTrack(TextTrack* aTrack)
|
||||
{
|
||||
mTrack = aTrack;
|
||||
}
|
||||
|
||||
// Helper to aid copying of a given TextTrackRegion's width, lines,
|
||||
// anchor, viewport and scroll values.
|
||||
void CopyValues(TextTrackRegion& aRegion);
|
||||
|
@ -360,7 +360,7 @@ GetProperty(AudioFileStreamID aAudioFileStream,
|
||||
|
||||
|
||||
nsresult
|
||||
AppleMP3Reader::ReadMetadata(VideoInfo* aInfo,
|
||||
AppleMP3Reader::ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
{
|
||||
MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread");
|
||||
@ -398,9 +398,9 @@ AppleMP3Reader::ReadMetadata(VideoInfo* aInfo,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aInfo->mAudioRate = mAudioSampleRate;
|
||||
aInfo->mAudioChannels = mAudioChannels;
|
||||
aInfo->mHasAudio = mStreamReady;
|
||||
aInfo->mAudio.mRate = mAudioSampleRate;
|
||||
aInfo->mAudio.mChannels = mAudioChannels;
|
||||
aInfo->mAudio.mHasAudio = mStreamReady;
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
virtual bool HasAudio() MOZ_OVERRIDE;
|
||||
virtual bool HasVideo() MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult ReadMetadata(VideoInfo* aInfo,
|
||||
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult Seek(int64_t aTime,
|
||||
|
@ -172,7 +172,7 @@ DASHReader::DecodeAudioData()
|
||||
}
|
||||
|
||||
nsresult
|
||||
DASHReader::ReadMetadata(VideoInfo* aInfo,
|
||||
DASHReader::ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
{
|
||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
||||
@ -191,7 +191,7 @@ DASHReader::ReadMetadata(VideoInfo* aInfo,
|
||||
*aTags = nullptr;
|
||||
|
||||
// Get metadata from child readers.
|
||||
VideoInfo audioInfo, videoInfo;
|
||||
MediaInfo audioInfo, videoInfo;
|
||||
|
||||
// Read metadata for all video streams.
|
||||
for (uint i = 0; i < mVideoReaders.Length(); i++) {
|
||||
@ -201,8 +201,7 @@ DASHReader::ReadMetadata(VideoInfo* aInfo,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Use metadata from current video sub reader to populate aInfo.
|
||||
if (mVideoReaders[i] == mVideoReader) {
|
||||
mInfo.mHasVideo = videoInfo.mHasVideo;
|
||||
mInfo.mDisplay = videoInfo.mDisplay;
|
||||
mInfo.mVideo = videoInfo.mVideo;
|
||||
}
|
||||
}
|
||||
// Read metadata for audio stream.
|
||||
@ -211,10 +210,7 @@ DASHReader::ReadMetadata(VideoInfo* aInfo,
|
||||
if (mAudioReader) {
|
||||
rv = mAudioReader->ReadMetadata(&audioInfo, aTags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mInfo.mHasAudio = audioInfo.mHasAudio;
|
||||
mInfo.mAudioRate = audioInfo.mAudioRate;
|
||||
mInfo.mAudioChannels = audioInfo.mAudioChannels;
|
||||
mInfo.mStereoMode = audioInfo.mStereoMode;
|
||||
mInfo.mAudio = audioInfo.mAudio;
|
||||
}
|
||||
|
||||
*aInfo = mInfo;
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
|
||||
// Waits for metadata bytes to be downloaded, then reads and parses them.
|
||||
// Called on the decode thread only.
|
||||
nsresult ReadMetadata(VideoInfo* aInfo,
|
||||
nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags) MOZ_OVERRIDE;
|
||||
|
||||
// Waits for |ReadyToReadMetadata| or |NotifyDecoderShuttingDown|
|
||||
|
@ -73,7 +73,7 @@ static const GUID CLSID_MPEG_LAYER_3_DECODER_FILTER =
|
||||
{ 0x38BE3000, 0xDBF4, 0x11D0, 0x86, 0x0E, 0x00, 0xA0, 0x24, 0xCF, 0xEF, 0x6D };
|
||||
|
||||
nsresult
|
||||
DirectShowReader::ReadMetadata(VideoInfo* aInfo,
|
||||
DirectShowReader::ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
{
|
||||
MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
||||
@ -164,11 +164,10 @@ DirectShowReader::ReadMetadata(VideoInfo* aInfo,
|
||||
mAudioSinkFilter->GetSampleSink()->GetAudioFormat(&format);
|
||||
NS_ENSURE_TRUE(format.wFormatTag == WAVE_FORMAT_PCM, NS_ERROR_FAILURE);
|
||||
|
||||
mInfo.mAudioChannels = mNumChannels = format.nChannels;
|
||||
mInfo.mAudioRate = mAudioRate = format.nSamplesPerSec;
|
||||
mInfo.mAudio.mChannels = mNumChannels = format.nChannels;
|
||||
mInfo.mAudio.mRate = mAudioRate = format.nSamplesPerSec;
|
||||
mBytesPerSample = format.wBitsPerSample / 8;
|
||||
mInfo.mHasAudio = true;
|
||||
mInfo.mHasVideo = false;
|
||||
mInfo.mAudio.mHasAudio = true;
|
||||
|
||||
*aInfo = mInfo;
|
||||
// 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("Channels=%u Hz=%u duration=%lld bytesPerSample=%d",
|
||||
mInfo.mAudioChannels,
|
||||
mInfo.mAudioRate,
|
||||
mInfo.mAudio.mChannels,
|
||||
mInfo.mAudio.mRate,
|
||||
RefTimeToUsecs(duration),
|
||||
mBytesPerSample);
|
||||
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
bool HasAudio() MOZ_OVERRIDE;
|
||||
bool HasVideo() MOZ_OVERRIDE;
|
||||
|
||||
nsresult ReadMetadata(VideoInfo* aInfo,
|
||||
nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags) MOZ_OVERRIDE;
|
||||
|
||||
nsresult Seek(int64_t aTime,
|
||||
|
@ -243,7 +243,7 @@ void GStreamerReader::PlayBinSourceSetup(GstAppSrc* aSource)
|
||||
gst_caps_unref(caps);
|
||||
}
|
||||
|
||||
nsresult GStreamerReader::ReadMetadata(VideoInfo* aInfo,
|
||||
nsresult GStreamerReader::ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
{
|
||||
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;
|
||||
g_object_get(mPlayBin, "n-video", &n_video, "n-audio", &n_audio, nullptr);
|
||||
mInfo.mHasVideo = n_video != 0;
|
||||
mInfo.mHasAudio = n_audio != 0;
|
||||
mInfo.mVideo.mHasVideo = n_video != 0;
|
||||
mInfo.mAudio.mHasAudio = n_audio != 0;
|
||||
|
||||
*aInfo = mInfo;
|
||||
|
||||
@ -490,12 +490,12 @@ bool GStreamerReader::DecodeAudioData()
|
||||
|
||||
int64_t offset = GST_BUFFER_OFFSET(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));
|
||||
nsAutoArrayPtr<AudioDataValue> data(new AudioDataValue[outSize]);
|
||||
memcpy(data, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer));
|
||||
AudioData* audio = new AudioData(offset, timestamp, duration,
|
||||
frames, data.forget(), mInfo.mAudioChannels);
|
||||
frames, data.forget(), mInfo.mAudio.mChannels);
|
||||
|
||||
mAudioQueue.Push(audio);
|
||||
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);
|
||||
/* XXX ? */
|
||||
int64_t offset = 0;
|
||||
VideoData* video = VideoData::Create(mInfo, image, offset,
|
||||
VideoData* video = VideoData::Create(mInfo.mVideo, image, offset,
|
||||
timestamp, nextTimestamp, b,
|
||||
isKeyframe, -1, mPicture);
|
||||
mVideoQueue.Push(video);
|
||||
@ -656,7 +656,7 @@ nsresult GStreamerReader::Seek(int64_t aTarget,
|
||||
nsresult GStreamerReader::GetBuffered(TimeRanges* aBuffered,
|
||||
int64_t aStartTime)
|
||||
{
|
||||
if (!mInfo.mHasVideo && !mInfo.mHasAudio) {
|
||||
if (!mInfo.HasValidMedia()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -933,14 +933,14 @@ void GStreamerReader::AudioPreroll()
|
||||
GstPad* sinkpad = gst_element_get_pad(GST_ELEMENT(mAudioAppSink), "sink");
|
||||
GstCaps* caps = gst_pad_get_negotiated_caps(sinkpad);
|
||||
GstStructure* s = gst_caps_get_structure(caps, 0);
|
||||
mInfo.mAudioRate = mInfo.mAudioChannels = 0;
|
||||
gst_structure_get_int(s, "rate", (gint*) &mInfo.mAudioRate);
|
||||
gst_structure_get_int(s, "channels", (gint*) &mInfo.mAudioChannels);
|
||||
NS_ASSERTION(mInfo.mAudioRate != 0, ("audio rate is zero"));
|
||||
NS_ASSERTION(mInfo.mAudioChannels != 0, ("audio channels is zero"));
|
||||
NS_ASSERTION(mInfo.mAudioChannels > 0 && mInfo.mAudioChannels <= MAX_CHANNELS,
|
||||
mInfo.mAudio.mRate = mInfo.mAudio.mChannels = 0;
|
||||
gst_structure_get_int(s, "rate", (gint*) &mInfo.mAudio.mRate);
|
||||
gst_structure_get_int(s, "channels", (gint*) &mInfo.mAudio.mChannels);
|
||||
NS_ASSERTION(mInfo.mAudio.mRate != 0, ("audio rate is zero"));
|
||||
NS_ASSERTION(mInfo.mAudio.mChannels != 0, ("audio channels is zero"));
|
||||
NS_ASSERTION(mInfo.mAudio.mChannels > 0 && mInfo.mAudio.mChannels <= MAX_CHANNELS,
|
||||
"invalid audio channels number");
|
||||
mInfo.mHasAudio = true;
|
||||
mInfo.mAudio.mHasAudio = true;
|
||||
gst_caps_unref(caps);
|
||||
gst_object_unref(sinkpad);
|
||||
}
|
||||
@ -955,8 +955,8 @@ void GStreamerReader::VideoPreroll()
|
||||
GstStructure* structure = gst_caps_get_structure(caps, 0);
|
||||
gst_structure_get_fraction(structure, "framerate", &fpsNum, &fpsDen);
|
||||
NS_ASSERTION(mPicture.width && mPicture.height, "invalid video resolution");
|
||||
mInfo.mDisplay = nsIntSize(mPicture.width, mPicture.height);
|
||||
mInfo.mHasVideo = true;
|
||||
mInfo.mVideo.mDisplay = nsIntSize(mPicture.width, mPicture.height);
|
||||
mInfo.mVideo.mHasVideo = true;
|
||||
gst_caps_unref(caps);
|
||||
gst_object_unref(sinkpad);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
virtual bool DecodeAudioData();
|
||||
virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
int64_t aTimeThreshold);
|
||||
virtual nsresult ReadMetadata(VideoInfo* aInfo,
|
||||
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags);
|
||||
virtual nsresult Seek(int64_t aTime,
|
||||
int64_t aStartTime,
|
||||
@ -53,11 +53,11 @@ public:
|
||||
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime);
|
||||
|
||||
virtual bool HasAudio() {
|
||||
return mInfo.mHasAudio;
|
||||
return mInfo.HasAudio();
|
||||
}
|
||||
|
||||
virtual bool HasVideo() {
|
||||
return mInfo.mHasVideo;
|
||||
return mInfo.HasVideo();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -12,15 +12,15 @@
|
||||
namespace mozilla {
|
||||
|
||||
template <typename T>
|
||||
class AsyncEventRunnner : public nsRunnable
|
||||
class AsyncEventRunner : public nsRunnable
|
||||
{
|
||||
public:
|
||||
AsyncEventRunnner(T* aTarget, const char* aName)
|
||||
AsyncEventRunner(T* aTarget, const char* aName)
|
||||
: mTarget(aTarget)
|
||||
, mName(aName)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
NS_IMETHOD Run() MOZ_OVERRIDE
|
||||
{
|
||||
mTarget->DispatchSimpleEvent(mName);
|
||||
return NS_OK;
|
||||
|
@ -6,12 +6,27 @@
|
||||
|
||||
#include "MediaSource.h"
|
||||
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "MediaSourceInputAdapter.h"
|
||||
#include "AsyncEventRunner.h"
|
||||
#include "DecoderTraits.h"
|
||||
#include "SourceBuffer.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 "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
|
||||
PRLogModuleInfo* gMediaSourceLog;
|
||||
@ -20,16 +35,12 @@ PRLogModuleInfo* gMediaSourceLog;
|
||||
#define LOG(type, msg)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
// Arbitrary limit.
|
||||
static const unsigned int MAX_SOURCE_BUFFERS = 16;
|
||||
|
||||
already_AddRefed<nsIInputStream>
|
||||
MediaSource::CreateInternalStream()
|
||||
{
|
||||
nsRefPtr<MediaSourceInputAdapter> adapter = new MediaSourceInputAdapter(this);
|
||||
mAdapters.AppendElement(adapter);
|
||||
return adapter.forget();
|
||||
}
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
|
||||
/* static */ already_AddRefed<MediaSource>
|
||||
MediaSource::Constructor(const GlobalObject& aGlobal,
|
||||
@ -95,8 +106,7 @@ MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
|
||||
if (!IsTypeSupportedInternal(aType, aRv)) {
|
||||
return nullptr;
|
||||
}
|
||||
// TODO: Temporary limit until multiple decoders are supported. Bug 881512.
|
||||
if (mSourceBuffers->Length() >= 1) {
|
||||
if (mSourceBuffers->Length() >= MAX_SOURCE_BUFFERS) {
|
||||
aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
@ -104,10 +114,17 @@ MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
mContentType = aType;
|
||||
nsRefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(this);
|
||||
nsContentTypeParser parser(aType);
|
||||
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);
|
||||
sourceBuffer->Attach();
|
||||
LOG(PR_LOG_DEBUG, ("%p AddSourceBuffer(Type=%s) -> %p", this,
|
||||
NS_ConvertUTF16toUTF8(mimeType).get(), sourceBuffer.get()));
|
||||
return sourceBuffer.forget();
|
||||
}
|
||||
|
||||
@ -137,7 +154,6 @@ MediaSource::RemoveSourceBuffer(SourceBuffer& aSourceBuffer, ErrorResult& aRv)
|
||||
mActiveSourceBuffers->Remove(sourceBuffer);
|
||||
}
|
||||
mSourceBuffers->Remove(sourceBuffer);
|
||||
sourceBuffer->Detach();
|
||||
// TODO: Free all resources associated with sourceBuffer
|
||||
}
|
||||
|
||||
@ -160,49 +176,37 @@ MediaSource::IsTypeSupported(const GlobalObject& aGlobal,
|
||||
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
|
||||
MediaSource::AttachElement(HTMLMediaElement* aElement)
|
||||
MediaSource::Attach(MediaSourceDecoder* aDecoder)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Attaching element %p", this, aElement));
|
||||
MOZ_ASSERT(aElement);
|
||||
mElement = aElement;
|
||||
LOG(PR_LOG_DEBUG, ("%p Attaching decoder %p owner %p", this, aDecoder, aDecoder->GetOwner()));
|
||||
MOZ_ASSERT(aDecoder);
|
||||
if (mReadyState != MediaSourceReadyState::Closed) {
|
||||
return false;
|
||||
}
|
||||
mDecoder = aDecoder;
|
||||
mDecoder->AttachMediaSource(this);
|
||||
SetReadyState(MediaSourceReadyState::Open);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::DetachElement()
|
||||
MediaSource::Detach()
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("%p Detaching element %p", this, mElement.get()));
|
||||
MOZ_ASSERT(mElement);
|
||||
mElement = nullptr;
|
||||
LOG(PR_LOG_DEBUG, ("%p Detaching decoder %p owner %p", this, mDecoder.get(), mDecoder->GetOwner()));
|
||||
MOZ_ASSERT(mDecoder);
|
||||
mDecoder->DetachMediaSource();
|
||||
mDecoder = nullptr;
|
||||
mDuration = UnspecifiedNaN();
|
||||
mActiveSourceBuffers->Clear();
|
||||
mSourceBuffers->DetachAndClear();
|
||||
mSourceBuffers->Clear();
|
||||
SetReadyState(MediaSourceReadyState::Closed);
|
||||
|
||||
for (uint32_t i = 0; i < mAdapters.Length(); ++i) {
|
||||
mAdapters[i]->Close();
|
||||
}
|
||||
mAdapters.Clear();
|
||||
}
|
||||
|
||||
MediaSource::MediaSource(nsPIDOMWindow* aWindow)
|
||||
: nsDOMEventTargetHelper(aWindow)
|
||||
, mDuration(UnspecifiedNaN())
|
||||
, mMonitor("mozilla::dom::MediaSource::mMonitor")
|
||||
, mDecoder(nullptr)
|
||||
, mReadyState(MediaSourceReadyState::Closed)
|
||||
{
|
||||
mSourceBuffers = new SourceBufferList(this);
|
||||
@ -219,9 +223,6 @@ void
|
||||
MediaSource::SetReadyState(MediaSourceReadyState aState)
|
||||
{
|
||||
MOZ_ASSERT(aState != mReadyState);
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
|
||||
NotifyListeners();
|
||||
|
||||
if ((mReadyState == MediaSourceReadyState::Closed ||
|
||||
mReadyState == MediaSourceReadyState::Ended) &&
|
||||
@ -269,18 +270,10 @@ void
|
||||
MediaSource::QueueAsyncSimpleEvent(const char* 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);
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::NotifyListeners()
|
||||
{
|
||||
for (uint32_t i = 0; i < mAdapters.Length(); ++i) {
|
||||
mAdapters[i]->NotifyListener();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::DurationChange(double aNewDuration, ErrorResult& aRv)
|
||||
{
|
||||
@ -303,6 +296,7 @@ void
|
||||
MediaSource::EndOfStreamInternal(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv)
|
||||
{
|
||||
SetReadyState(MediaSourceReadyState::Ended);
|
||||
mSourceBuffers->Ended();
|
||||
if (!aError.WasPassed()) {
|
||||
// TODO:
|
||||
// Run duration change algorithm.
|
||||
@ -385,8 +379,8 @@ MediaSource::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
return MediaSourceBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_4(MediaSource, nsDOMEventTargetHelper,
|
||||
mSourceBuffers, mActiveSourceBuffers, mAdapters, mElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_2(MediaSource, nsDOMEventTargetHelper,
|
||||
mSourceBuffers, mActiveSourceBuffers)
|
||||
|
||||
NS_IMPL_ADDREF_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)
|
||||
|
||||
} // namespace dom
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -7,27 +7,36 @@
|
||||
#ifndef 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/Monitor.h"
|
||||
#include "mozilla/dom/MediaSourceBinding.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionNoteChild.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsID.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nscore.h"
|
||||
|
||||
class nsIInputStream;
|
||||
struct JSContext;
|
||||
class JSObject;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
template <typename T> class AsyncEventRunner;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class HTMLMediaElement;
|
||||
class MediaSourceInputAdapter;
|
||||
class SourceBufferList;
|
||||
class GlobalObject;
|
||||
class SourceBuffer;
|
||||
class SourceBufferList;
|
||||
class TimeRanges;
|
||||
template <typename T> class Optional;
|
||||
|
||||
#define MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID \
|
||||
{ 0x3839d699, 0x22c5, 0x439f, \
|
||||
@ -64,50 +73,28 @@ public:
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
const nsString& GetType()
|
||||
{
|
||||
return mContentType;
|
||||
}
|
||||
|
||||
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();
|
||||
// Attach this MediaSource to Decoder aDecoder. Returns false if already attached.
|
||||
bool Attach(MediaSourceDecoder* aDecoder);
|
||||
void Detach();
|
||||
|
||||
// Set mReadyState to aState and fire the required events at the MediaSource.
|
||||
void SetReadyState(MediaSourceReadyState aState);
|
||||
|
||||
void GetBuffered(TimeRanges* aRanges);
|
||||
|
||||
// Used by SourceBuffer to call CreateSubDecoder.
|
||||
MediaSourceDecoder* GetDecoder()
|
||||
{
|
||||
return mDecoder;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit MediaSource(nsPIDOMWindow* aWindow);
|
||||
|
||||
friend class AsyncEventRunnner<MediaSource>;
|
||||
friend class AsyncEventRunner<MediaSource>;
|
||||
void DispatchSimpleEvent(const char* aName);
|
||||
void QueueAsyncSimpleEvent(const char* aName);
|
||||
|
||||
void NotifyListeners();
|
||||
|
||||
void DurationChange(double aNewDuration, ErrorResult& aRv);
|
||||
void EndOfStreamInternal(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv);
|
||||
|
||||
@ -115,25 +102,17 @@ private:
|
||||
|
||||
double mDuration;
|
||||
|
||||
nsTArray<nsRefPtr<MediaSourceInputAdapter> > mAdapters;
|
||||
|
||||
// Protected by monitor.
|
||||
nsTArray<uint8_t> mData;
|
||||
|
||||
// Protects access to mData.
|
||||
Monitor mMonitor;
|
||||
|
||||
nsRefPtr<SourceBufferList> mSourceBuffers;
|
||||
nsRefPtr<SourceBufferList> mActiveSourceBuffers;
|
||||
|
||||
nsRefPtr<HTMLMediaElement> mElement;
|
||||
nsRefPtr<MediaSourceDecoder> mDecoder;
|
||||
|
||||
nsString mContentType;
|
||||
MediaSourceReadyState mReadyState;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(MediaSource, MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)
|
||||
|
||||
} // namespace dom
|
||||
|
||||
} // namespace mozilla
|
||||
#endif /* mozilla_dom_MediaSource_h_ */
|
||||
|
209
content/media/mediasource/MediaSourceDecoder.cpp
Normal file
209
content/media/mediasource/MediaSourceDecoder.cpp
Normal 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
|
137
content/media/mediasource/MediaSourceDecoder.h
Normal file
137
content/media/mediasource/MediaSourceDecoder.h
Normal 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_ */
|
@ -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
|
@ -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_ */
|
@ -5,6 +5,25 @@
|
||||
|
||||
#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
|
||||
extern PRLogModuleInfo* gMediaSourceLog;
|
||||
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
|
||||
@ -13,30 +32,96 @@ extern PRLogModuleInfo* gMediaSourceLog;
|
||||
#endif
|
||||
|
||||
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 {
|
||||
|
||||
void
|
||||
SourceBuffer::SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached || mUpdating) {
|
||||
if (!IsAttached() || mUpdating) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mMediaSource->ReadyState() != MediaSourceReadyState::Closed);
|
||||
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
|
||||
mMediaSource->SetReadyState(MediaSourceReadyState::Open);
|
||||
}
|
||||
// TODO:: Test append state.
|
||||
// TODO:: If aMode is "sequence", set sequence start time.
|
||||
// TODO: Test append state.
|
||||
// TODO: If aMode is "sequence", set sequence start time.
|
||||
mAppendMode = aMode;
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached || mUpdating) {
|
||||
if (!IsAttached() || mUpdating) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mMediaSource->ReadyState() != MediaSourceReadyState::Closed);
|
||||
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
|
||||
mMediaSource->SetReadyState(MediaSourceReadyState::Open);
|
||||
}
|
||||
@ -48,19 +133,19 @@ SourceBuffer::SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv)
|
||||
already_AddRefed<TimeRanges>
|
||||
SourceBuffer::GetBuffered(ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached) {
|
||||
if (!IsAttached()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<TimeRanges> ranges = new TimeRanges();
|
||||
// TODO: Populate ranges.
|
||||
mDecoder->GetBuffered(ranges);
|
||||
return ranges.forget();
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached || mUpdating) {
|
||||
if (!IsAttached() || mUpdating) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
@ -74,7 +159,7 @@ SourceBuffer::SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv)
|
||||
void
|
||||
SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached || mUpdating) {
|
||||
if (!IsAttached() || mUpdating) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
@ -101,7 +186,7 @@ SourceBuffer::AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv)
|
||||
void
|
||||
SourceBuffer::Abort(ErrorResult& aRv)
|
||||
{
|
||||
if (!mAttached) {
|
||||
if (!IsAttached()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
@ -114,7 +199,6 @@ SourceBuffer::Abort(ErrorResult& aRv)
|
||||
AbortUpdating();
|
||||
}
|
||||
// TODO: Run reset parser algorithm.
|
||||
// XXX: Need to run these two resets through setters?
|
||||
mAppendWindowStart = 0;
|
||||
mAppendWindowEnd = PositiveInfinity();
|
||||
}
|
||||
@ -122,36 +206,36 @@ SourceBuffer::Abort(ErrorResult& aRv)
|
||||
void
|
||||
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() ||
|
||||
aEnd <= aStart) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
if (!mAttached || mUpdating ||
|
||||
mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
StartUpdating();
|
||||
/// TODO: Run coded frame removal algorithm asynchronously (would call StopUpdating()).
|
||||
StopUpdating();
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::Attach()
|
||||
SourceBuffer::Detach()
|
||||
{
|
||||
MOZ_ASSERT(!mAttached);
|
||||
mAttached = true;
|
||||
Ended();
|
||||
mDecoder = nullptr;
|
||||
mMediaSource = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::Detach()
|
||||
SourceBuffer::Ended()
|
||||
{
|
||||
MOZ_ASSERT(mAttached);
|
||||
mAttached = false;
|
||||
mDecoder->GetResource()->Ended();
|
||||
}
|
||||
|
||||
SourceBuffer::SourceBuffer(MediaSource* aMediaSource)
|
||||
SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
|
||||
: nsDOMEventTargetHelper(aMediaSource->GetParentObject())
|
||||
, mMediaSource(aMediaSource)
|
||||
, mAppendWindowStart(0)
|
||||
@ -159,9 +243,18 @@ SourceBuffer::SourceBuffer(MediaSource* aMediaSource)
|
||||
, mTimestampOffset(0)
|
||||
, mAppendMode(SourceBufferAppendMode::Segments)
|
||||
, mUpdating(false)
|
||||
, mAttached(false)
|
||||
{
|
||||
MOZ_ASSERT(aMediaSource);
|
||||
MediaSourceDecoder* parentDecoder = aMediaSource->GetDecoder();
|
||||
mDecoder = parentDecoder->CreateSubDecoder(aType);
|
||||
MOZ_ASSERT(mDecoder);
|
||||
}
|
||||
|
||||
SourceBuffer::~SourceBuffer()
|
||||
{
|
||||
if (mDecoder) {
|
||||
mDecoder->GetResource()->Ended();
|
||||
}
|
||||
}
|
||||
|
||||
MediaSource*
|
||||
@ -187,7 +280,7 @@ void
|
||||
SourceBuffer::QueueAsyncSimpleEvent(const char* 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);
|
||||
}
|
||||
|
||||
@ -220,7 +313,7 @@ SourceBuffer::AbortUpdating()
|
||||
void
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@ -229,9 +322,14 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
|
||||
}
|
||||
// TODO: Run coded frame eviction algorithm.
|
||||
// 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();
|
||||
// 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()).
|
||||
mDecoder->GetResource()->AppendData(aData, aLength);
|
||||
StopUpdating();
|
||||
}
|
||||
|
||||
@ -244,4 +342,5 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SourceBuffer)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
} // namespace dom
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -7,22 +7,37 @@
|
||||
#ifndef mozilla_dom_SourceBuffer_h_
|
||||
#define mozilla_dom_SourceBuffer_h_
|
||||
|
||||
#include "AsyncEventRunner.h"
|
||||
#include "MediaDecoderReader.h"
|
||||
#include "MediaSource.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/SourceBufferBinding.h"
|
||||
#include "mozilla/dom/TimeRanges.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/mozalloc.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nscore.h"
|
||||
#include "nsCycleCollectionNoteChild.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nscore.h"
|
||||
|
||||
class JSObject;
|
||||
struct JSContext;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
class SourceBufferResource;
|
||||
class SubBufferDecoder;
|
||||
template <typename T> class AsyncEventRunner;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class TimeRanges;
|
||||
|
||||
class SourceBuffer MOZ_FINAL : public nsDOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
@ -73,19 +88,25 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SourceBuffer, nsDOMEventTargetHelper)
|
||||
|
||||
explicit SourceBuffer(MediaSource* aMediaSource);
|
||||
explicit SourceBuffer(MediaSource* aMediaSource, const nsACString& aType);
|
||||
~SourceBuffer();
|
||||
|
||||
MediaSource* GetParentObject() const;
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
// Notify the SourceBuffer that it has been attached to or detached from
|
||||
// the MediaSource's sourceBuffer list.
|
||||
void Attach();
|
||||
// Notify the SourceBuffer that it has been detached from the
|
||||
// MediaSource's sourceBuffer list.
|
||||
void Detach();
|
||||
bool IsAttached() const
|
||||
{
|
||||
return mMediaSource != nullptr;
|
||||
}
|
||||
|
||||
void Ended();
|
||||
|
||||
private:
|
||||
friend class AsyncEventRunnner<SourceBuffer>;
|
||||
friend class AsyncEventRunner<SourceBuffer>;
|
||||
void DispatchSimpleEvent(const char* aName);
|
||||
void QueueAsyncSimpleEvent(const char* aName);
|
||||
|
||||
@ -99,6 +120,8 @@ private:
|
||||
|
||||
nsRefPtr<MediaSource> mMediaSource;
|
||||
|
||||
nsRefPtr<SubBufferDecoder> mDecoder;
|
||||
|
||||
double mAppendWindowStart;
|
||||
double mAppendWindowEnd;
|
||||
|
||||
@ -106,10 +129,9 @@ private:
|
||||
|
||||
SourceBufferAppendMode mAppendMode;
|
||||
bool mUpdating;
|
||||
|
||||
bool mAttached;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
} // namespace mozilla
|
||||
#endif /* mozilla_dom_SourceBuffer_h_ */
|
||||
|
@ -6,7 +6,19 @@
|
||||
|
||||
#include "SourceBufferList.h"
|
||||
|
||||
#include "AsyncEventRunner.h"
|
||||
#include "mozilla/ErrorResult.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
|
||||
extern PRLogModuleInfo* gMediaSourceLog;
|
||||
@ -16,6 +28,7 @@ extern PRLogModuleInfo* gMediaSourceLog;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
|
||||
SourceBuffer*
|
||||
@ -42,6 +55,7 @@ void
|
||||
SourceBufferList::Remove(SourceBuffer* aSourceBuffer)
|
||||
{
|
||||
MOZ_ALWAYS_TRUE(mSourceBuffers.RemoveElement(aSourceBuffer));
|
||||
aSourceBuffer->Detach();
|
||||
QueueAsyncSimpleEvent("removesourcebuffer");
|
||||
}
|
||||
|
||||
@ -54,6 +68,9 @@ SourceBufferList::Contains(SourceBuffer* aSourceBuffer)
|
||||
void
|
||||
SourceBufferList::Clear()
|
||||
{
|
||||
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
|
||||
mSourceBuffers[i]->Detach();
|
||||
}
|
||||
mSourceBuffers.Clear();
|
||||
QueueAsyncSimpleEvent("removesourcebuffer");
|
||||
}
|
||||
@ -64,15 +81,6 @@ SourceBufferList::IsEmpty()
|
||||
return mSourceBuffers.IsEmpty();
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferList::DetachAndClear()
|
||||
{
|
||||
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
|
||||
mSourceBuffers[i]->Detach();
|
||||
}
|
||||
Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
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
|
||||
SourceBufferList::DispatchSimpleEvent(const char* aName)
|
||||
{
|
||||
@ -106,7 +122,7 @@ void
|
||||
SourceBufferList::QueueAsyncSimpleEvent(const char* 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);
|
||||
}
|
||||
|
||||
@ -139,4 +155,5 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SourceBufferList)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
} // namespace dom
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -7,17 +7,25 @@
|
||||
#ifndef mozilla_dom_SourceBufferList_h_
|
||||
#define mozilla_dom_SourceBufferList_h_
|
||||
|
||||
#include "AsyncEventRunner.h"
|
||||
#include "MediaSource.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionNoteChild.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
struct JSContext;
|
||||
class JSObject;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
template <typename T> class AsyncEventRunner;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class MediaSource;
|
||||
@ -55,9 +63,6 @@ public:
|
||||
// True if list has zero entries.
|
||||
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.
|
||||
bool AnyUpdating();
|
||||
|
||||
@ -65,8 +70,11 @@ public:
|
||||
// first error, with result returned in aRv.
|
||||
void Remove(double aStart, double aEnd, ErrorResult& aRv);
|
||||
|
||||
// Mark all SourceBuffers input buffers as ended.
|
||||
void Ended();
|
||||
|
||||
private:
|
||||
friend class AsyncEventRunnner<SourceBufferList>;
|
||||
friend class AsyncEventRunner<SourceBufferList>;
|
||||
void DispatchSimpleEvent(const char* aName);
|
||||
void QueueAsyncSimpleEvent(const char* aName);
|
||||
|
||||
@ -75,5 +83,6 @@ private:
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
} // namespace mozilla
|
||||
#endif /* mozilla_dom_SourceBufferList_h_ */
|
||||
|
162
content/media/mediasource/SourceBufferResource.cpp
Normal file
162
content/media/mediasource/SourceBufferResource.cpp
Normal 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
|
104
content/media/mediasource/SourceBufferResource.h
Normal file
104
content/media/mediasource/SourceBufferResource.h
Normal 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_ */
|
64
content/media/mediasource/SubBufferDecoder.h
Normal file
64
content/media/mediasource/SubBufferDecoder.h
Normal 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_ */
|
@ -11,6 +11,7 @@ MODULE = 'content'
|
||||
|
||||
EXPORTS += [
|
||||
'AsyncEventRunner.h',
|
||||
'MediaSourceDecoder.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
@ -21,9 +22,10 @@ EXPORTS.mozilla.dom += [
|
||||
|
||||
CPP_SOURCES += [
|
||||
'MediaSource.cpp',
|
||||
'MediaSourceInputAdapter.cpp',
|
||||
'MediaSourceDecoder.cpp',
|
||||
'SourceBuffer.cpp',
|
||||
'SourceBufferList.cpp',
|
||||
'SourceBufferResource.cpp',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
@ -13,11 +13,6 @@ SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(function() {
|
||||
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;
|
||||
try {
|
||||
new MediaSource();
|
||||
@ -25,44 +20,47 @@ addLoadEvent(function() {
|
||||
accessThrows = true;
|
||||
}
|
||||
ok(accessThrows, "MediaSource should be hidden behind a pref");
|
||||
SpecialPowers.setBoolPref("media.mediasource.enabled", true);
|
||||
var ms = new MediaSource();
|
||||
ok(ms, "Create a MediaSource object");
|
||||
ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
|
||||
is(ms.readyState, "closed", "New MediaSource must be in closed state");
|
||||
// Force wrapper creation, tests for leaks.
|
||||
ms.foo = null;
|
||||
var o = URL.createObjectURL(ms);
|
||||
ok(o, "Create an objectURL from the MediaSource");
|
||||
var v = document.createElement("video");
|
||||
document.body.appendChild(v);
|
||||
v.src = o;
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
ok(true, "Receive a sourceopen event");
|
||||
is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
|
||||
var sb = ms.addSourceBuffer("video/webm");
|
||||
ok(sb, "Create a SourceBuffer");
|
||||
is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
|
||||
is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
|
||||
fetch("seek.webm", function (blob) {
|
||||
var r = new FileReader();
|
||||
r.addEventListener("load", function (e) {
|
||||
sb.appendBuffer(new Uint8Array(e.target.result));
|
||||
ms.endOfStream();
|
||||
v.play();
|
||||
SpecialPowers.pushPrefEnv({"set": [[ "media.mediasource.enabled", true ]]},
|
||||
function () {
|
||||
SpecialPowers.setBoolPref("media.mediasource.enabled", true);
|
||||
var ms = new MediaSource();
|
||||
ok(ms, "Create a MediaSource object");
|
||||
ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
|
||||
is(ms.readyState, "closed", "New MediaSource must be in closed state");
|
||||
// Force wrapper creation, tests for leaks.
|
||||
ms.foo = null;
|
||||
var o = URL.createObjectURL(ms);
|
||||
ok(o, "Create an objectURL from the MediaSource");
|
||||
var v = document.createElement("video");
|
||||
v.preload = "auto";
|
||||
document.body.appendChild(v);
|
||||
v.src = o;
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
ok(true, "Receive a sourceopen event");
|
||||
is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
|
||||
var sb = ms.addSourceBuffer("video/webm");
|
||||
ok(sb, "Create a SourceBuffer");
|
||||
is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
|
||||
is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
|
||||
fetch("seek.webm", function (blob) {
|
||||
var r = new FileReader();
|
||||
r.addEventListener("load", function (e) {
|
||||
sb.appendBuffer(new Uint8Array(e.target.result));
|
||||
ms.endOfStream();
|
||||
v.play();
|
||||
});
|
||||
r.readAsArrayBuffer(blob);
|
||||
});
|
||||
r.readAsArrayBuffer(blob);
|
||||
});
|
||||
});
|
||||
ms.addEventListener("sourceended", function () {
|
||||
ok(true, "Receive a sourceended event");
|
||||
is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
|
||||
});
|
||||
v.addEventListener("playing", function () {
|
||||
is(v.duration, 4, "Video has correct duration");
|
||||
v.parentNode.removeChild(v);
|
||||
SpecialPowers.clearUserPref("media.mediasource.enabled");
|
||||
SimpleTest.finish();
|
||||
ms.addEventListener("sourceended", function () {
|
||||
ok(true, "Receive a sourceended event");
|
||||
is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
|
||||
});
|
||||
v.addEventListener("ended", function () {
|
||||
is(v.duration, 4, "Video has correct duration");
|
||||
v.parentNode.removeChild(v);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -168,8 +168,8 @@ void OggReader::BuildSerialList(nsTArray<uint32_t>& aTracks)
|
||||
}
|
||||
}
|
||||
|
||||
nsresult OggReader::ReadMetadata(VideoInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
nsresult OggReader::ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
{
|
||||
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
|
||||
|
||||
@ -277,8 +277,8 @@ nsresult OggReader::ReadMetadata(VideoInfo* aInfo,
|
||||
mTheoraState->mInfo.frame_height);
|
||||
if (VideoInfo::ValidateVideoRegion(frameSize, picture, displaySize)) {
|
||||
// Video track's frame sizes will not overflow. Activate the video track.
|
||||
mInfo.mHasVideo = true;
|
||||
mInfo.mDisplay = displaySize;
|
||||
mInfo.mVideo.mHasVideo = true;
|
||||
mInfo.mVideo.mDisplay = displaySize;
|
||||
mPicture = picture;
|
||||
|
||||
VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
|
||||
@ -295,9 +295,9 @@ nsresult OggReader::ReadMetadata(VideoInfo* aInfo,
|
||||
}
|
||||
|
||||
if (mVorbisState && ReadHeaders(mVorbisState)) {
|
||||
mInfo.mHasAudio = true;
|
||||
mInfo.mAudioRate = mVorbisState->mInfo.rate;
|
||||
mInfo.mAudioChannels = mVorbisState->mInfo.channels > 2 ? 2 : mVorbisState->mInfo.channels;
|
||||
mInfo.mAudio.mHasAudio = true;
|
||||
mInfo.mAudio.mRate = mVorbisState->mInfo.rate;
|
||||
mInfo.mAudio.mChannels = mVorbisState->mInfo.channels > 2 ? 2 : mVorbisState->mInfo.channels;
|
||||
// Copy Vorbis info data for time computations on other threads.
|
||||
memcpy(&mVorbisInfo, &mVorbisState->mInfo, sizeof(mVorbisInfo));
|
||||
mVorbisInfo.codec_setup = NULL;
|
||||
@ -308,9 +308,9 @@ nsresult OggReader::ReadMetadata(VideoInfo* aInfo,
|
||||
}
|
||||
#ifdef MOZ_OPUS
|
||||
if (mOpusState && ReadHeaders(mOpusState)) {
|
||||
mInfo.mHasAudio = true;
|
||||
mInfo.mAudioRate = mOpusState->mRate;
|
||||
mInfo.mAudioChannels = mOpusState->mChannels > 2 ? 2 : mOpusState->mChannels;
|
||||
mInfo.mAudio.mHasAudio = true;
|
||||
mInfo.mAudio.mRate = mOpusState->mRate;
|
||||
mInfo.mAudio.mChannels = mOpusState->mChannels > 2 ? 2 : mOpusState->mChannels;
|
||||
mOpusSerial = mOpusState->mSerial;
|
||||
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;
|
||||
}
|
||||
|
||||
VideoData *v = VideoData::Create(mInfo,
|
||||
VideoData *v = VideoData::Create(mInfo.mVideo,
|
||||
mDecoder->GetImageContainer(),
|
||||
mDecoder->GetResource()->Tell(),
|
||||
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
|
||||
// a deadlock. Accessing mInfo doesn't require a lock - it doesn't change
|
||||
// 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
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ public:
|
||||
return mTheoraState != 0 && mTheoraState->mActive;
|
||||
}
|
||||
|
||||
virtual nsresult ReadMetadata(VideoInfo* aInfo,
|
||||
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags);
|
||||
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
|
||||
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime);
|
||||
|
@ -69,7 +69,7 @@ void MediaOmxReader::ReleaseMediaResources()
|
||||
}
|
||||
}
|
||||
|
||||
nsresult MediaOmxReader::ReadMetadata(VideoInfo* aInfo,
|
||||
nsresult MediaOmxReader::ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
{
|
||||
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.
|
||||
mHasVideo = mInfo.mHasVideo = true;
|
||||
mInfo.mDisplay = displaySize;
|
||||
mHasVideo = mInfo.mVideo.mHasVideo = true;
|
||||
mInfo.mVideo.mDisplay = displaySize;
|
||||
mPicture = pictureRect;
|
||||
mInitialFrame = frameSize;
|
||||
VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
|
||||
@ -128,9 +128,9 @@ nsresult MediaOmxReader::ReadMetadata(VideoInfo* aInfo,
|
||||
if (mOmxDecoder->HasAudio()) {
|
||||
int32_t numChannels, sampleRate;
|
||||
mOmxDecoder->GetAudioParameters(&numChannels, &sampleRate);
|
||||
mHasAudio = mInfo.mHasAudio = true;
|
||||
mInfo.mAudioChannels = numChannels;
|
||||
mInfo.mAudioRate = sampleRate;
|
||||
mHasAudio = mInfo.mAudio.mHasAudio = true;
|
||||
mInfo.mAudio.mChannels = numChannels;
|
||||
mInfo.mAudio.mRate = sampleRate;
|
||||
}
|
||||
|
||||
*aInfo = mInfo;
|
||||
@ -232,7 +232,7 @@ bool MediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
b.mPlanes[2].mOffset = frame.Cr.mOffset;
|
||||
b.mPlanes[2].mSkip = frame.Cr.mSkip;
|
||||
|
||||
v = VideoData::Create(mInfo,
|
||||
v = VideoData::Create(mInfo.mVideo,
|
||||
mDecoder->GetImageContainer(),
|
||||
pos,
|
||||
frame.mTimeUs,
|
||||
@ -242,7 +242,7 @@ bool MediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
-1,
|
||||
picture);
|
||||
} else {
|
||||
v = VideoData::Create(mInfo,
|
||||
v = VideoData::Create(mInfo.mVideo,
|
||||
mDecoder->GetImageContainer(),
|
||||
pos,
|
||||
frame.mTimeUs,
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
virtual bool IsDormantNeeded();
|
||||
virtual void ReleaseMediaResources();
|
||||
|
||||
virtual nsresult ReadMetadata(VideoInfo* aInfo,
|
||||
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags);
|
||||
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);
|
||||
|
@ -41,8 +41,8 @@ nsresult MediaPluginReader::Init(MediaDecoderReader* aCloneDonor)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult MediaPluginReader::ReadMetadata(VideoInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
nsresult MediaPluginReader::ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
{
|
||||
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.
|
||||
mHasVideo = mInfo.mHasVideo = true;
|
||||
mInfo.mDisplay = displaySize;
|
||||
mHasVideo = mInfo.mVideo.mHasVideo = true;
|
||||
mInfo.mVideo.mDisplay = displaySize;
|
||||
mPicture = pictureRect;
|
||||
mInitialFrame = frameSize;
|
||||
VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
|
||||
@ -90,9 +90,9 @@ nsresult MediaPluginReader::ReadMetadata(VideoInfo* aInfo,
|
||||
if (mPlugin->HasAudio(mPlugin)) {
|
||||
int32_t numChannels, sampleRate;
|
||||
mPlugin->GetAudioParameters(mPlugin, &numChannels, &sampleRate);
|
||||
mHasAudio = mInfo.mHasAudio = true;
|
||||
mInfo.mAudioChannels = numChannels;
|
||||
mInfo.mAudioRate = sampleRate;
|
||||
mHasAudio = mInfo.mAudio.mHasAudio = true;
|
||||
mInfo.mAudio.mChannels = numChannels;
|
||||
mInfo.mAudio.mRate = sampleRate;
|
||||
}
|
||||
|
||||
*aInfo = mInfo;
|
||||
@ -186,7 +186,7 @@ bool MediaPluginReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
picture.height = (frameSize.height * mPicture.height) / mInitialFrame.height;
|
||||
}
|
||||
|
||||
v = VideoData::CreateFromImage(mInfo,
|
||||
v = VideoData::CreateFromImage(mInfo.mVideo,
|
||||
mDecoder->GetImageContainer(),
|
||||
pos,
|
||||
frame.mTimeUs,
|
||||
@ -232,7 +232,7 @@ bool MediaPluginReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
}
|
||||
|
||||
// This is the approximate byte position in the stream.
|
||||
v = VideoData::Create(mInfo,
|
||||
v = VideoData::Create(mInfo.mVideo,
|
||||
mDecoder->GetImageContainer(),
|
||||
pos,
|
||||
frame.mTimeUs,
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
return mHasVideo;
|
||||
}
|
||||
|
||||
virtual nsresult ReadMetadata(VideoInfo* aInfo,
|
||||
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags);
|
||||
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);
|
||||
|
@ -35,8 +35,8 @@ nsresult RawReader::ResetDecode()
|
||||
return MediaDecoderReader::ResetDecode();
|
||||
}
|
||||
|
||||
nsresult RawReader::ReadMetadata(VideoInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
nsresult RawReader::ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags)
|
||||
{
|
||||
NS_ASSERTION(mDecoder->OnDecodeThread(),
|
||||
"Should be on decode thread.");
|
||||
@ -75,9 +75,8 @@ nsresult RawReader::ReadMetadata(VideoInfo* aInfo,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mInfo.mHasVideo = true;
|
||||
mInfo.mHasAudio = false;
|
||||
mInfo.mDisplay = display;
|
||||
mInfo.mVideo.mHasVideo = true;
|
||||
mInfo.mVideo.mDisplay = display;
|
||||
|
||||
mFrameRate = static_cast<float>(mMetadata.framerateNumerator) /
|
||||
mMetadata.framerateDenominator;
|
||||
@ -208,7 +207,7 @@ bool RawReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
b.mPlanes[2].mWidth = mMetadata.frameWidth / 2;
|
||||
b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0;
|
||||
|
||||
VideoData *v = VideoData::Create(mInfo,
|
||||
VideoData *v = VideoData::Create(mInfo.mVideo,
|
||||
mDecoder->GetImageContainer(),
|
||||
-1,
|
||||
currentFrameTime,
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual nsresult ReadMetadata(VideoInfo* aInfo,
|
||||
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags);
|
||||
virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
|
||||
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime);
|
||||
|
@ -121,6 +121,7 @@ MOCHITEST_FILES = \
|
||||
test_mediarecorder_record_timeslice.html \
|
||||
test_mediarecorder_record_audiocontext.html \
|
||||
test_mediarecorder_record_stopms.html \
|
||||
test_mediarecorder_record_nosrc.html \
|
||||
test_mozHasAudio.html \
|
||||
test_source_media.html \
|
||||
test_autoplay_contentEditable.html \
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user