Merge m-c to b2g-inbound. a=merge

This commit is contained in:
Ryan VanderMeulen 2014-06-07 14:16:54 -04:00
Родитель a228069888 4ae256cf80
Коммит 875db4dc4a
294 изменённых файлов: 7361 добавлений и 1820 удалений

Просмотреть файл

@ -29,6 +29,7 @@
# Build directories for js shell # Build directories for js shell
_DBG\.OBJ/ _DBG\.OBJ/
_OPT\.OBJ/ _OPT\.OBJ/
^js/src/.*-obj/
# SpiderMonkey configury # SpiderMonkey configury
^js/src/configure$ ^js/src/configure$

Просмотреть файл

@ -22,5 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please # changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more. # don't change CLOBBER for WebIDL changes any more.
Bug 904723 (Array.from) needs a clobber once again because of changes to js.msg Bug 973238 part 9 needs clobber due to self-hosted code (bug 1019955).
and self-hosted code (see bug 1019955).

Просмотреть файл

@ -955,9 +955,14 @@ pref("apz.axis_lock_mode", 2);
pref("apz.subframe.enabled", true); pref("apz.subframe.enabled", true);
// Overscroll-related settings // Overscroll-related settings
pref("apz.overscroll.enabled", false); pref("apz.overscroll.enabled", true);
pref("apz.overscroll.snap_back_accel", "0.003"); pref("apz.overscroll.fling_friction", "0.02");
pref("apz.overscroll.snap_back_init_vel", "1"); pref("apz.overscroll.fling_stopped_threshold", "0.4");
pref("apz.overscroll.clamping", "0.5");
pref("apz.overscroll.z_effect", "0.2");
pref("apz.overscroll.snap_back.spring_stiffness", "0.6");
pref("apz.overscroll.snap_back.spring_friction", "0.1");
pref("apz.overscroll.snap_back.mass", "1000");
// This preference allows FirefoxOS apps (and content, I think) to force // This preference allows FirefoxOS apps (and content, I think) to force
// the use of software (instead of hardware accelerated) 2D canvases by // the use of software (instead of hardware accelerated) 2D canvases by

Просмотреть файл

@ -650,7 +650,7 @@ let settingsToObserve = {
prefName: 'dom.browser_frames.useAsyncPanZoom', prefName: 'dom.browser_frames.useAsyncPanZoom',
defaultValue: false defaultValue: false
}, },
'apz.overscroll.enabled': false, 'apz.overscroll.enabled': true,
'debug.fps.enabled': { 'debug.fps.enabled': {
prefName: 'layers.acceleration.draw-fps', prefName: 'layers.acceleration.draw-fps',
defaultValue: false defaultValue: false

Просмотреть файл

@ -1,4 +1,5 @@
[DEFAULT] [DEFAULT]
run-if = toolkit == "gonk"
support-files = support-files =
permission_handler_chrome.js permission_handler_chrome.js
SandboxPromptTest.html SandboxPromptTest.html
@ -6,11 +7,8 @@ support-files =
systemapp_helper.js systemapp_helper.js
[test_sandbox_permission.html] [test_sandbox_permission.html]
run-if = toolkit == "gonk" skip-if = true # bug 984274 - frequent timeouts
[test_filepicker_path.html] [test_filepicker_path.html]
run-if = toolkit == "gonk"
[test_permission_deny.html] [test_permission_deny.html]
run-if = toolkit == "gonk"
[test_permission_gum_remember.html] [test_permission_gum_remember.html]
run-if = toolkit == "gonk"
[test_systemapp.html] [test_systemapp.html]

Просмотреть файл

@ -486,6 +486,8 @@
@BINPATH@/components/nsFormHistory.js @BINPATH@/components/nsFormHistory.js
@BINPATH@/components/FormHistoryStartup.js @BINPATH@/components/FormHistoryStartup.js
@BINPATH@/components/nsInputListAutoComplete.js @BINPATH@/components/nsInputListAutoComplete.js
@BINPATH@/components/formautofill.manifest
@BINPATH@/components/AutofillController.js
@BINPATH@/components/contentSecurityPolicy.manifest @BINPATH@/components/contentSecurityPolicy.manifest
@BINPATH@/components/contentSecurityPolicy.js @BINPATH@/components/contentSecurityPolicy.js
@BINPATH@/components/contentAreaDropListener.manifest @BINPATH@/components/contentAreaDropListener.manifest

Просмотреть файл

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1400782040000"> <blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1401837170000">
<emItems> <emItems>
<emItem blockID="i454" id="sqlmoz@facebook.com"> <emItem blockID="i454" id="sqlmoz@facebook.com">
<versionRange minVersion="0" maxVersion="*" severity="3"> <versionRange minVersion="0" maxVersion="*" severity="3">
@ -871,6 +871,12 @@
<emItem blockID="i43" id="supportaccessplugin@gmail.com"> <emItem blockID="i43" id="supportaccessplugin@gmail.com">
<prefs> <prefs>
</prefs> </prefs>
</emItem>
<emItem blockID="i588" id="quick_start@gmail.com">
<versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange>
<prefs>
</prefs>
</emItem> </emItem>
<emItem blockID="i340" id="chiang@programmer.net"> <emItem blockID="i340" id="chiang@programmer.net">
<versionRange minVersion="0" maxVersion="*" severity="3"> <versionRange minVersion="0" maxVersion="*" severity="3">
@ -1278,8 +1284,8 @@
<prefs> <prefs>
</prefs> </prefs>
</emItem> </emItem>
<emItem blockID="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}"> <emItem blockID="i586" id="jid1-0xtMKhXFEs4jIg@jetpack">
<versionRange minVersion="1.1b1" maxVersion="1.1b1"> <versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange> </versionRange>
<prefs> <prefs>
</prefs> </prefs>
@ -1289,6 +1295,12 @@
</versionRange> </versionRange>
<prefs> <prefs>
</prefs> </prefs>
</emItem>
<emItem blockID="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}">
<versionRange minVersion="1.1b1" maxVersion="1.1b1">
</versionRange>
<prefs>
</prefs>
</emItem> </emItem>
<emItem blockID="i531" id="/^(4cb61367-efbf-4aa1-8e3a-7f776c9d5763@cdece6e9-b2ef-40a9-b178-291da9870c59\.com|0efc9c38-1ec7-49ed-8915-53a48b6b7600@e7f17679-2a42-4659-83c5-7ba961fdf75a\.com|6be3335b-ef79-4b0b-a0ba-b87afbc6f4ad@6bbb4d2e-e33e-4fa5-9b37-934f4fb50182\.com)$/"> <emItem blockID="i531" id="/^(4cb61367-efbf-4aa1-8e3a-7f776c9d5763@cdece6e9-b2ef-40a9-b178-291da9870c59\.com|0efc9c38-1ec7-49ed-8915-53a48b6b7600@e7f17679-2a42-4659-83c5-7ba961fdf75a\.com|6be3335b-ef79-4b0b-a0ba-b87afbc6f4ad@6bbb4d2e-e33e-4fa5-9b37-934f4fb50182\.com)$/">
<versionRange minVersion="0" maxVersion="*" severity="1"> <versionRange minVersion="0" maxVersion="*" severity="1">
@ -1409,6 +1421,12 @@
</versionRange> </versionRange>
<prefs> <prefs>
</prefs> </prefs>
</emItem>
<emItem blockID="i590" id="{94cd2cc3-083f-49ba-a218-4cda4b4829fd}">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
<prefs>
</prefs>
</emItem> </emItem>
<emItem blockID="i544" id="/^(93abedcf-8e3a-4d02-b761-d1441e437c09@243f129d-aee2-42c2-bcd1-48858e1c22fd\.com|9acfc440-ac2d-417a-a64c-f6f14653b712@09f9a966-9258-4b12-af32-da29bdcc28c5\.com|58ad0086-1cfb-48bb-8ad2-33a8905572bc@5715d2be-69b9-4930-8f7e-64bdeb961cfd\.com)$/"> <emItem blockID="i544" id="/^(93abedcf-8e3a-4d02-b761-d1441e437c09@243f129d-aee2-42c2-bcd1-48858e1c22fd\.com|9acfc440-ac2d-417a-a64c-f6f14653b712@09f9a966-9258-4b12-af32-da29bdcc28c5\.com|58ad0086-1cfb-48bb-8ad2-33a8905572bc@5715d2be-69b9-4930-8f7e-64bdeb961cfd\.com)$/">
<versionRange minVersion="0" maxVersion="*" severity="1"> <versionRange minVersion="0" maxVersion="*" severity="1">

Просмотреть файл

@ -1237,8 +1237,12 @@ pref("devtools.appmanager.enabled", true);
pref("devtools.appmanager.lastTab", "help"); pref("devtools.appmanager.lastTab", "help");
pref("devtools.appmanager.manifestEditor.enabled", true); pref("devtools.appmanager.manifestEditor.enabled", true);
// Disable devtools webide until bug 1007059 // Enable devtools webide
#ifdef MOZ_DEVTOOLS_WEBIDE
pref("devtools.webide.enabled", true);
#else
pref("devtools.webide.enabled", false); pref("devtools.webide.enabled", false);
#endif
// Toolbox preferences // Toolbox preferences
pref("devtools.toolbox.footer.height", 250); pref("devtools.toolbox.footer.height", 250);
@ -1561,6 +1565,8 @@ pref("identity.fxaccounts.settings.uri", "https://accounts.firefox.com/settings"
pref("ui.key.menuAccessKeyFocuses", true); pref("ui.key.menuAccessKeyFocuses", true);
#endif #endif
// Encrypted media extensions.
pref("media.eme.enabled", false);
// Delete HTTP cache v2 data of users that didn't opt-in manually // Delete HTTP cache v2 data of users that didn't opt-in manually
pref("browser.cache.auto_delete_cache_version", 1); pref("browser.cache.auto_delete_cache_version", 1);

Просмотреть файл

@ -445,7 +445,7 @@ nsContextMenu.prototype = {
this.showItem("context-media-showcontrols", onMedia && !this.target.controls); this.showItem("context-media-showcontrols", onMedia && !this.target.controls);
this.showItem("context-media-hidecontrols", onMedia && this.target.controls); this.showItem("context-media-hidecontrols", onMedia && this.target.controls);
this.showItem("context-video-fullscreen", this.onVideo && this.target.ownerDocument.mozFullScreenElement == null); this.showItem("context-video-fullscreen", this.onVideo && this.target.ownerDocument.mozFullScreenElement == null);
var statsShowing = this.onVideo && XPCNativeWrapper.unwrap(this.target).mozMediaStatisticsShowing; var statsShowing = this.onVideo && this.target.mozMediaStatisticsShowing;
this.showItem("context-video-showstats", this.onVideo && this.target.controls && !statsShowing); this.showItem("context-video-showstats", this.onVideo && this.target.controls && !statsShowing);
this.showItem("context-video-hidestats", this.onVideo && this.target.controls && statsShowing); this.showItem("context-video-hidestats", this.onVideo && this.target.controls && statsShowing);

Просмотреть файл

@ -28,9 +28,11 @@ DIRS += [
'tilt', 'tilt',
'webaudioeditor', 'webaudioeditor',
'webconsole', 'webconsole',
'webide',
] ]
if CONFIG['MOZ_DEVTOOLS_WEBIDE']:
DIRS += ['webide']
EXTRA_COMPONENTS += [ EXTRA_COMPONENTS += [
'devtools-clhandler.js', 'devtools-clhandler.js',
'devtools-clhandler.manifest', 'devtools-clhandler.manifest',

Просмотреть файл

@ -157,14 +157,12 @@ let UI = {
unbusy: function() { unbusy: function() {
document.querySelector("window").classList.remove("busy") document.querySelector("window").classList.remove("busy")
this.updateCommands(); this.updateCommands();
this._busyPromise = null;
}, },
busyUntil: function(promise, operationDescription) { busyUntil: function(promise, operationDescription) {
// Freeze the UI until the promise is resolved. A 30s timeout // Freeze the UI until the promise is resolved. A 30s timeout
// will unfreeze the UI, just in case the promise never gets // will unfreeze the UI, just in case the promise never gets
// resolved. // resolved.
this._busyPromise = promise;
let timeout = setTimeout(() => { let timeout = setTimeout(() => {
this.unbusy(); this.unbusy();
UI.reportError("error_operationTimeout", operationDescription); UI.reportError("error_operationTimeout", operationDescription);

Просмотреть файл

@ -62,15 +62,17 @@ function closeWebIDE(win) {
} }
function removeAllProjects() { function removeAllProjects() {
return Task.spawn(function* () { let deferred = promise.defer();
yield AppProjects.load(); AppProjects.load().then(() => {
let projects = AppProjects.store.object.projects; let projects = AppProjects.store.object.projects;
for (let i = 0; i < projects.length; i++) { for (let i = 0; i < projects.length; i++) {
yield AppProjects.remove(projects[i].location); AppProjects.remove(projects[i].location);
} }
deferred.resolve();
}); });
}
return deferred.promise;
}
function nextTick() { function nextTick() {
let deferred = promise.defer(); let deferred = promise.defer();
SimpleTest.executeSoon(() => { SimpleTest.executeSoon(() => {

Просмотреть файл

@ -19,12 +19,15 @@
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
Task.spawn(function* () { Task.spawn(function* () {
let clClass = Components.classes["@mozilla.org/toolkit/command-line;1"].createInstance();
Cu.import("resource://gre/modules/devtools/dbg-server.jsm"); Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
DebuggerServer.init(function () { return true; }); DebuggerServer.init(function () { return true; });
DebuggerServer.addBrowserActors(); DebuggerServer.addBrowserActors();
let win = yield openWebIDE(); let win = yield openWebIDE();
let packagedAppLocation = getTestFilePath("app"); let packagedAppLocation = getTestFilePath("app");
let cli = "actions=addPackagedApp&location=" + packagedAppLocation; let cli = "actions=addPackagedApp&location=" + packagedAppLocation;

Просмотреть файл

@ -22,9 +22,6 @@
let win = yield openWebIDE(); let win = yield openWebIDE();
let packagedAppLocation = getTestFilePath("app"); let packagedAppLocation = getTestFilePath("app");
yield win.AppProjects.load();
is(win.AppProjects.store.object.projects.length, 0, "IDB is empty");
yield win.Cmds.importPackagedApp(packagedAppLocation); yield win.Cmds.importPackagedApp(packagedAppLocation);
let project = win.AppManager.selectedProject; let project = win.AppManager.selectedProject;

Просмотреть файл

@ -49,9 +49,10 @@
win.AppManager.update("runtimelist"); win.AppManager.update("runtimelist");
let packagedAppLocation = getTestFilePath("app"); let hostedAppManifest = TEST_BASE + "hosted_app.manifest";
yield win.Cmds.importHostedApp(hostedAppManifest);
yield win.Cmds.importPackagedApp(packagedAppLocation); yield win.Cmds.showRuntimePanel();
let panelNode = win.document.querySelector("#runtime-panel"); let panelNode = win.document.querySelector("#runtime-panel");
let items = panelNode.querySelectorAll(".runtime-panel-item-usb"); let items = panelNode.querySelectorAll(".runtime-panel-item-usb");
@ -64,27 +65,36 @@
items[0].click(); items[0].click();
ok(win.document.querySelector("window").className, "busy", "UI is busy"); yield deferred.promise;
yield win.UI._busyPromise;
is(Object.keys(DebuggerServer._connections).length, 1, "Connected"); is(Object.keys(DebuggerServer._connections).length, 1, "Connected");
ok(isPlayActive(), "play button is enabled 1");
ok(!isStopActive(), "stop button is disabled 1");
let oldProject = win.AppManager.selectedProject;
win.AppManager.selectedProject = null;
yield nextTick(); yield nextTick();
ok(!isPlayActive(), "play button is disabled 2"); ok(!isPlayActive(), "play button is disabled 2");
ok(!isStopActive(), "stop button is disabled 2"); ok(!isStopActive(), "stop button is disabled 2");
win.AppManager._selectedProject = oldProject;
win.AppManager.selectedProject.errorsCount = 0;
win.UI.updateCommands(); win.UI.updateCommands();
yield nextTick(); yield nextTick();
ok(isPlayActive(), "play button is enabled 3"); ok(isPlayActive(), "play button is enabled 3");
ok(!isStopActive(), "stop button is disabled 3"); ok(!isStopActive(), "stop button is disabled 3");
let oldProject = win.AppManager.selectedProject;
win.AppManager.selectedProject = null;
yield nextTick();
ok(!isPlayActive(), "play button is disabled 4");
ok(!isStopActive(), "stop button is disabled 4");
win.AppManager._selectedProject = oldProject;
win.UI.updateCommands();
yield nextTick();
ok(isPlayActive(), "play button is enabled 5");
ok(!isStopActive(), "stop button is disabled 5");
yield win.Cmds.disconnectRuntime(); yield win.Cmds.disconnectRuntime();
@ -92,8 +102,8 @@
is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected"); is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected");
ok(win.AppManager.selectedProject, "A project is still selected"); ok(win.AppManager.selectedProject, "A project is still selected");
ok(!isPlayActive(), "play button is disabled 4"); ok(!isPlayActive(), "play button is disabled 6");
ok(!isStopActive(), "stop button is disabled 4"); ok(!isStopActive(), "stop button is disabled 6");
deferred = promise.defer(); deferred = promise.defer();
win.AppManager.connection.once( win.AppManager.connection.once(
@ -112,8 +122,6 @@
DebuggerServer.destroy(); DebuggerServer.destroy();
yield removeAllProjects();
SimpleTest.finish(); SimpleTest.finish();
}); });

Просмотреть файл

@ -454,6 +454,8 @@
@BINPATH@/components/nsFormHistory.js @BINPATH@/components/nsFormHistory.js
@BINPATH@/components/FormHistoryStartup.js @BINPATH@/components/FormHistoryStartup.js
@BINPATH@/components/nsInputListAutoComplete.js @BINPATH@/components/nsInputListAutoComplete.js
@BINPATH@/components/formautofill.manifest
@BINPATH@/components/AutofillController.js
@BINPATH@/components/contentSecurityPolicy.manifest @BINPATH@/components/contentSecurityPolicy.manifest
@BINPATH@/components/contentSecurityPolicy.js @BINPATH@/components/contentSecurityPolicy.js
@BINPATH@/components/contentAreaDropListener.manifest @BINPATH@/components/contentAreaDropListener.manifest
@ -636,9 +638,11 @@
#endif #endif
; [Webide Files] ; [Webide Files]
#ifdef MOZ_DEVTOOLS_WEBIDE
@BINPATH@/browser/chrome/webide@JAREXT@ @BINPATH@/browser/chrome/webide@JAREXT@
@BINPATH@/browser/chrome/webide.manifest @BINPATH@/browser/chrome/webide.manifest
@BINPATH@/browser/@PREF_DIR@/webide-prefs.js @BINPATH@/browser/@PREF_DIR@/webide-prefs.js
#endif
; shell icons ; shell icons
#ifdef XP_UNIX #ifdef XP_UNIX

Просмотреть файл

@ -510,6 +510,8 @@
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0, 1px, 2px; background-position: 0, 1px, 2px;
} }
#toolbox-buttons:empty + #toolbox-controls-separator,
#toolbox-controls-separator[invisible] { #toolbox-controls-separator[invisible] {
visibility: hidden; visibility: hidden;
} }

Просмотреть файл

@ -7680,6 +7680,19 @@ if test "$MOZ_CHROME_FILE_FORMAT" != "jar" &&
AC_MSG_ERROR([--enable-chrome-format must be set to either jar, flat, or omni]) AC_MSG_ERROR([--enable-chrome-format must be set to either jar, flat, or omni])
fi fi
dnl ========================================================
dnl = Enable Support for devtools webide
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(devtools-webide,
[ --enable-devtools-webide Set compile flags necessary for compiling devtools webide ],
MOZ_DEVTOOLS_WEBIDE=1,
MOZ_DEVTOOLS_WEBIDE= )
if test -n "$MOZ_DEVTOOLS_WEBIDE"; then
AC_DEFINE(MOZ_DEVTOOLS_WEBIDE)
fi
AC_SUBST(MOZ_DEVTOOLS_WEBIDE)
dnl ========================================================= dnl =========================================================
dnl Omnijar packaging (bug 552121) dnl Omnijar packaging (bug 552121)
dnl ========================================================= dnl =========================================================

Просмотреть файл

@ -883,10 +883,10 @@ public:
*/ */
nsIFrame* GetPrimaryFrame() const nsIFrame* GetPrimaryFrame() const
{ {
return IsInDoc() ? mPrimaryFrame : nullptr; return (IsInDoc() || HasFlag(NODE_IS_IN_SHADOW_TREE)) ? mPrimaryFrame : nullptr;
} }
void SetPrimaryFrame(nsIFrame* aFrame) { void SetPrimaryFrame(nsIFrame* aFrame) {
NS_ASSERTION(IsInDoc(), "This will end badly!"); MOZ_ASSERT(IsInDoc() || HasFlag(NODE_IS_IN_SHADOW_TREE), "This will end badly!");
NS_PRECONDITION(!aFrame || !mPrimaryFrame || aFrame == mPrimaryFrame, NS_PRECONDITION(!aFrame || !mPrimaryFrame || aFrame == mPrimaryFrame,
"Losing track of existing primary frame"); "Losing track of existing primary frame");
mPrimaryFrame = aFrame; mPrimaryFrame = aFrame;

Просмотреть файл

@ -525,6 +525,19 @@ public:
return IsInDoc() ? OwnerDoc() : nullptr; return IsInDoc() ? OwnerDoc() : nullptr;
} }
/**
* This method gets the current doc of the node hosting this content
* or the current doc of this content if it is not being hosted. This
* method walks through ShadowRoot boundaries until it reach the host
* that is located in the root of the "tree of trees" (see Shadow DOM
* spec) and returns the current doc for that host.
*/
nsIDocument* GetCrossShadowCurrentDoc() const
{
return HasFlag(NODE_IS_IN_SHADOW_TREE) ?
GetCrossShadowCurrentDocInternal() : GetCurrentDoc();
}
/** /**
* The values returned by this function are the ones defined for * The values returned by this function are the ones defined for
* nsIDOMNode.nodeType * nsIDOMNode.nodeType
@ -808,29 +821,7 @@ public:
* null. It may return 'this' (e.g. for document nodes, and nodes that * null. It may return 'this' (e.g. for document nodes, and nodes that
* are the roots of disconnected subtrees). * are the roots of disconnected subtrees).
*/ */
nsINode* SubtreeRoot() const nsINode* SubtreeRoot() const;
{
// There are three cases of interest here. nsINodes that are really:
// 1. nsIDocument nodes - Are always in the document.
// 2. nsIContent nodes - Are either in the document, or mSubtreeRoot
// is updated in BindToTree/UnbindFromTree.
// 3. nsIAttribute nodes - Are never in the document, and mSubtreeRoot
// is always 'this' (as set in nsINode's ctor).
nsINode* node = IsInDoc() ? OwnerDocAsNode() : mSubtreeRoot;
NS_ASSERTION(node, "Should always have a node here!");
#ifdef DEBUG
{
const nsINode* slowNode = this;
const nsINode* iter = slowNode;
while ((iter = iter->GetParentNode())) {
slowNode = iter;
}
NS_ASSERTION(slowNode == node, "These should always be in sync!");
}
#endif
return node;
}
/** /**
* See nsIDOMEventTarget * See nsIDOMEventTarget
@ -1205,6 +1196,8 @@ public:
private: private:
nsIDocument* GetCrossShadowCurrentDocInternal() const;
nsIContent* GetNextNodeImpl(const nsINode* aRoot, nsIContent* GetNextNodeImpl(const nsINode* aRoot,
const bool aSkipChildren) const const bool aSkipChildren) const
{ {
@ -1520,7 +1513,8 @@ protected:
void SetSubtreeRootPointer(nsINode* aSubtreeRoot) void SetSubtreeRootPointer(nsINode* aSubtreeRoot)
{ {
NS_ASSERTION(aSubtreeRoot, "aSubtreeRoot can never be null!"); NS_ASSERTION(aSubtreeRoot, "aSubtreeRoot can never be null!");
NS_ASSERTION(!(IsNodeOfType(eCONTENT) && IsInDoc()), "Shouldn't be here!"); NS_ASSERTION(!(IsNodeOfType(eCONTENT) && IsInDoc()) &&
!HasFlag(NODE_IS_IN_SHADOW_TREE), "Shouldn't be here!");
mSubtreeRoot = aSubtreeRoot; mSubtreeRoot = aSubtreeRoot;
} }

Просмотреть файл

@ -190,7 +190,7 @@ Element::IntrinsicState() const
void void
Element::NotifyStateChange(EventStates aStates) Element::NotifyStateChange(EventStates aStates)
{ {
nsIDocument* doc = GetCurrentDoc(); nsIDocument* doc = GetCrossShadowCurrentDoc();
if (doc) { if (doc) {
nsAutoScriptBlocker scriptBlocker; nsAutoScriptBlocker scriptBlocker;
doc->ContentStateChanged(this, aStates); doc->ContentStateChanged(this, aStates);
@ -831,7 +831,7 @@ Element::CreateShadowRoot(ErrorResult& aError)
// Recreate the frame for the bound content because binding a ShadowRoot // Recreate the frame for the bound content because binding a ShadowRoot
// changes how things are rendered. // changes how things are rendered.
nsIDocument* doc = GetCurrentDoc(); nsIDocument* doc = GetCrossShadowCurrentDoc();
if (doc) { if (doc) {
nsIPresShell *shell = doc->GetShell(); nsIPresShell *shell = doc->GetShell();
if (shell) { if (shell) {
@ -1231,6 +1231,7 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
SetFlags(NODE_CHROME_ONLY_ACCESS); SetFlags(NODE_CHROME_ONLY_ACCESS);
} }
if (aParent->HasFlag(NODE_IS_IN_SHADOW_TREE)) { if (aParent->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
ClearSubtreeRootPointer();
SetFlags(NODE_IS_IN_SHADOW_TREE); SetFlags(NODE_IS_IN_SHADOW_TREE);
} }
ShadowRoot* parentContainingShadow = aParent->GetContainingShadow(); ShadowRoot* parentContainingShadow = aParent->GetContainingShadow();
@ -1291,8 +1292,9 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
// Propagate scoped style sheet tracking bit. // Propagate scoped style sheet tracking bit.
SetIsElementInStyleScope(mParent->IsElementInStyleScope()); SetIsElementInStyleScope(mParent->IsElementInStyleScope());
} else { } else if (!HasFlag(NODE_IS_IN_SHADOW_TREE)) {
// If we're not in the doc, update our subtree pointer. // If we're not in the doc and not in a shadow tree,
// update our subtree pointer.
SetSubtreeRootPointer(aParent->SubtreeRoot()); SetSubtreeRootPointer(aParent->SubtreeRoot());
} }
@ -1435,6 +1437,7 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
SetParentIsContent(false); SetParentIsContent(false);
} }
ClearInDocument(); ClearInDocument();
UnsetFlags(NODE_IS_IN_SHADOW_TREE);
// Begin keeping track of our subtree root. // Begin keeping track of our subtree root.
SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot()); SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
@ -1470,7 +1473,7 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
} }
// Unset this since that's what the old code effectively did. // Unset this since that's what the old code effectively did.
UnsetFlags(NODE_FORCE_XBL_BINDINGS | NODE_IS_IN_SHADOW_TREE); UnsetFlags(NODE_FORCE_XBL_BINDINGS);
#ifdef MOZ_XUL #ifdef MOZ_XUL
nsXULElement* xulElem = nsXULElement::FromContent(this); nsXULElement* xulElem = nsXULElement::FromContent(this);

Просмотреть файл

@ -72,9 +72,14 @@ ShadowRoot::ShadowRoot(nsIContent* aContent,
mInsertionPointChanged(false) mInsertionPointChanged(false)
{ {
SetHost(aContent); SetHost(aContent);
// Nodes in a shadow tree should never store a value
// in the subtree root pointer, nodes in the shadow tree
// track the subtree root using GetContainingShadow().
ClearSubtreeRootPointer();
SetFlags(NODE_IS_IN_SHADOW_TREE); SetFlags(NODE_IS_IN_SHADOW_TREE);
// ShadowRoot isn't really in the document but it behaves like it is.
SetInDocument();
DOMSlots()->mBindingParent = aContent; DOMSlots()->mBindingParent = aContent;
DOMSlots()->mContainingShadow = this; DOMSlots()->mContainingShadow = this;
@ -92,7 +97,11 @@ ShadowRoot::~ShadowRoot()
mPoolHost->RemoveMutationObserver(this); mPoolHost->RemoveMutationObserver(this);
} }
ClearInDocument(); UnsetFlags(NODE_IS_IN_SHADOW_TREE);
// nsINode destructor expects mSubtreeRoot == this.
SetSubtreeRootPointer(this);
SetHost(nullptr); SetHost(nullptr);
} }
@ -115,14 +124,14 @@ ShadowRoot::FromNode(nsINode* aNode)
} }
void void
ShadowRoot::Restyle() ShadowRoot::StyleSheetChanged()
{ {
mProtoBinding->FlushSkinSheets(); mProtoBinding->FlushSkinSheets();
nsIPresShell* shell = OwnerDoc()->GetShell(); nsIPresShell* shell = OwnerDoc()->GetShell();
if (shell) { if (shell) {
OwnerDoc()->BeginUpdate(UPDATE_STYLE); OwnerDoc()->BeginUpdate(UPDATE_STYLE);
shell->RestyleShadowRoot(this); shell->RecordShadowStyleChange(this);
OwnerDoc()->EndUpdate(UPDATE_STYLE); OwnerDoc()->EndUpdate(UPDATE_STYLE);
} }
} }
@ -157,7 +166,9 @@ ShadowRoot::InsertSheet(nsCSSStyleSheet* aSheet,
} }
} }
Restyle(); if (aSheet->IsApplicable()) {
StyleSheetChanged();
}
} }
void void
@ -171,7 +182,9 @@ ShadowRoot::RemoveSheet(nsCSSStyleSheet* aSheet)
MOZ_ASSERT(found, "Trying to remove a sheet from a ShadowRoot " MOZ_ASSERT(found, "Trying to remove a sheet from a ShadowRoot "
"that does not exist."); "that does not exist.");
Restyle(); if (aSheet->IsApplicable()) {
StyleSheetChanged();
}
} }
Element* Element*
@ -494,7 +507,7 @@ ShadowRoot::SetApplyAuthorStyles(bool aApplyAuthorStyles)
nsIPresShell* shell = OwnerDoc()->GetShell(); nsIPresShell* shell = OwnerDoc()->GetShell();
if (shell) { if (shell) {
OwnerDoc()->BeginUpdate(UPDATE_STYLE); OwnerDoc()->BeginUpdate(UPDATE_STYLE);
shell->RestyleShadowRoot(this); shell->RecordShadowStyleChange(this);
OwnerDoc()->EndUpdate(UPDATE_STYLE); OwnerDoc()->EndUpdate(UPDATE_STYLE);
} }
} }

Просмотреть файл

@ -127,8 +127,8 @@ public:
GetElementsByClassName(const nsAString& aClasses); GetElementsByClassName(const nsAString& aClasses);
void GetInnerHTML(nsAString& aInnerHTML); void GetInnerHTML(nsAString& aInnerHTML);
void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError); void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError);
void StyleSheetChanged();
protected: protected:
void Restyle();
// The pool host is the parent of the nodes that will be distributed // The pool host is the parent of the nodes that will be distributed
// into the insertion points in this ShadowRoot. See |ChangeShadowRoot|. // into the insertion points in this ShadowRoot. See |ChangeShadowRoot|.

Просмотреть файл

@ -492,6 +492,7 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
SetFlags(NODE_CHROME_ONLY_ACCESS); SetFlags(NODE_CHROME_ONLY_ACCESS);
} }
if (aParent->HasFlag(NODE_IS_IN_SHADOW_TREE)) { if (aParent->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
ClearSubtreeRootPointer();
SetFlags(NODE_IS_IN_SHADOW_TREE); SetFlags(NODE_IS_IN_SHADOW_TREE);
} }
ShadowRoot* parentContainingShadow = aParent->GetContainingShadow(); ShadowRoot* parentContainingShadow = aParent->GetContainingShadow();
@ -527,8 +528,9 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
} }
// Clear the lazy frame construction bits. // Clear the lazy frame construction bits.
UnsetFlags(NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES); UnsetFlags(NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES);
} else { } else if (!HasFlag(NODE_IS_IN_SHADOW_TREE)) {
// If we're not in the doc, update our subtree pointer. // If we're not in the doc and not in a shadow tree,
// update our subtree pointer.
SetSubtreeRootPointer(aParent->SubtreeRoot()); SetSubtreeRootPointer(aParent->SubtreeRoot());
} }
@ -549,10 +551,7 @@ nsGenericDOMDataNode::UnbindFromTree(bool aDeep, bool aNullParent)
{ {
// Unset frame flags; if we need them again later, they'll get set again. // Unset frame flags; if we need them again later, they'll get set again.
UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE | UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
NS_REFRAME_IF_WHITESPACE | NS_REFRAME_IF_WHITESPACE);
// Also unset the shadow tree flag because it can
// no longer be a descendant of a ShadowRoot.
NODE_IS_IN_SHADOW_TREE);
nsIDocument *document = GetCurrentDoc(); nsIDocument *document = GetCurrentDoc();
if (document) { if (document) {
@ -571,6 +570,7 @@ nsGenericDOMDataNode::UnbindFromTree(bool aDeep, bool aNullParent)
SetParentIsContent(false); SetParentIsContent(false);
} }
ClearInDocument(); ClearInDocument();
UnsetFlags(NODE_IS_IN_SHADOW_TREE);
// Begin keeping track of our subtree root. // Begin keeping track of our subtree root.
SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot()); SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());

Просмотреть файл

@ -497,6 +497,7 @@ GK_ATOM(keydown, "keydown")
GK_ATOM(keygen, "keygen") GK_ATOM(keygen, "keygen")
GK_ATOM(keypress, "keypress") GK_ATOM(keypress, "keypress")
GK_ATOM(keyset, "keyset") GK_ATOM(keyset, "keyset")
GK_ATOM(keysystem, "keysystem")
GK_ATOM(keytext, "keytext") GK_ATOM(keytext, "keytext")
GK_ATOM(keyup, "keyup") GK_ATOM(keyup, "keyup")
GK_ATOM(kind, "kind") GK_ATOM(kind, "kind")
@ -1944,6 +1945,8 @@ GK_ATOM(oncuechange, "oncuechange")
GK_ATOM(oncurrentchange, "oncurrentchange") GK_ATOM(oncurrentchange, "oncurrentchange")
GK_ATOM(onenter, "onenter") GK_ATOM(onenter, "onenter")
GK_ATOM(onexit, "onexit") GK_ATOM(onexit, "onexit")
GK_ATOM(onneedkey, "onneedkey")
GK_ATOM(needkey, "needkey")
GK_ATOM(onremovetrack, "onremovetrack") GK_ATOM(onremovetrack, "onremovetrack")
GK_ATOM(loadstart, "loadstart") GK_ATOM(loadstart, "loadstart")
GK_ATOM(suspend, "suspend") GK_ATOM(suspend, "suspend")

Просмотреть файл

@ -235,6 +235,41 @@ nsINode::GetTextEditorRootContent(nsIEditor** aEditor)
return nullptr; return nullptr;
} }
nsINode*
nsINode::SubtreeRoot() const
{
// There are four cases of interest here. nsINodes that are really:
// 1. nsIDocument nodes - Are always in the document.
// 2.a nsIContent nodes not in a shadow tree - Are either in the document,
// or mSubtreeRoot is updated in BindToTree/UnbindFromTree.
// 2.b nsIContent nodes in a shadow tree - Are never in the document,
// ignore mSubtreeRoot and return the containing shadow root.
// 4. nsIAttribute nodes - Are never in the document, and mSubtreeRoot
// is always 'this' (as set in nsINode's ctor).
nsINode* node;
if (IsInDoc()) {
node = OwnerDocAsNode();
} else if (IsContent()) {
ShadowRoot* containingShadow = AsContent()->GetContainingShadow();
node = containingShadow ? containingShadow : mSubtreeRoot;
} else {
node = mSubtreeRoot;
}
NS_ASSERTION(node, "Should always have a node here!");
#ifdef DEBUG
{
const nsINode* slowNode = this;
const nsINode* iter = slowNode;
while ((iter = iter->GetParentNode())) {
slowNode = iter;
}
NS_ASSERTION(slowNode == node, "These should always be in sync!");
}
#endif
return node;
}
static nsIContent* GetRootForContentSubtree(nsIContent* aContent) static nsIContent* GetRootForContentSubtree(nsIContent* aContent)
{ {
NS_ENSURE_TRUE(aContent, nullptr); NS_ENSURE_TRUE(aContent, nullptr);
@ -268,7 +303,7 @@ nsINode::GetSelectionRootContent(nsIPresShell* aPresShell)
if (!IsNodeOfType(eCONTENT)) if (!IsNodeOfType(eCONTENT))
return nullptr; return nullptr;
if (GetCurrentDoc() != aPresShell->GetDocument()) { if (GetCrossShadowCurrentDoc() != aPresShell->GetDocument()) {
return nullptr; return nullptr;
} }
@ -284,7 +319,7 @@ nsINode::GetSelectionRootContent(nsIPresShell* aPresShell)
nsIEditor* editor = nsContentUtils::GetHTMLEditor(presContext); nsIEditor* editor = nsContentUtils::GetHTMLEditor(presContext);
if (editor) { if (editor) {
// This node is in HTML editor. // This node is in HTML editor.
nsIDocument* doc = GetCurrentDoc(); nsIDocument* doc = GetCrossShadowCurrentDoc();
if (!doc || doc->HasFlag(NODE_IS_EDITABLE) || if (!doc || doc->HasFlag(NODE_IS_EDITABLE) ||
!HasFlag(NODE_IS_EDITABLE)) { !HasFlag(NODE_IS_EDITABLE)) {
nsIContent* editorRoot = GetEditorRootContent(editor); nsIContent* editorRoot = GetEditorRootContent(editor);
@ -348,6 +383,17 @@ nsINode::GetTextContentInternal(nsAString& aTextContent)
SetDOMStringToNull(aTextContent); SetDOMStringToNull(aTextContent);
} }
nsIDocument*
nsINode::GetCrossShadowCurrentDocInternal() const
{
MOZ_ASSERT(HasFlag(NODE_IS_IN_SHADOW_TREE) && IsContent(),
"Should only be caled on nodes in the shadow tree.");
// Cross ShadowRoot boundary.
ShadowRoot* containingShadow = AsContent()->GetContainingShadow();
return containingShadow->GetHost()->GetCrossShadowCurrentDoc();
}
#ifdef DEBUG #ifdef DEBUG
void void
nsINode::CheckNotNativeAnonymous() const nsINode::CheckNotNativeAnonymous() const
@ -1461,7 +1507,7 @@ nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
// Do this before checking the child-count since this could cause mutations // Do this before checking the child-count since this could cause mutations
nsIDocument* doc = GetCurrentDoc(); nsIDocument* doc = GetCurrentDoc();
mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); mozAutoDocUpdate updateBatch(GetCrossShadowCurrentDoc(), UPDATE_CONTENT_MODEL, aNotify);
if (OwnerDoc() != aKid->OwnerDoc()) { if (OwnerDoc() != aKid->OwnerDoc()) {
rv = AdoptNodeIntoOwnerDoc(this, aKid); rv = AdoptNodeIntoOwnerDoc(this, aKid);
@ -1601,10 +1647,7 @@ nsINode::doRemoveChildAt(uint32_t aIndex, bool aNotify,
IndexOf(aKid) == (int32_t)aIndex, "Bogus aKid"); IndexOf(aKid) == (int32_t)aIndex, "Bogus aKid");
nsMutationGuard::DidMutate(); nsMutationGuard::DidMutate();
mozAutoDocUpdate updateBatch(GetCrossShadowCurrentDoc(), UPDATE_CONTENT_MODEL, aNotify);
nsIDocument* doc = GetCurrentDoc();
mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
nsIContent* previousSibling = aKid->GetPreviousSibling(); nsIContent* previousSibling = aKid->GetPreviousSibling();
@ -2042,7 +2085,7 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
} }
} }
mozAutoDocUpdate batch(GetCurrentDoc(), UPDATE_CONTENT_MODEL, true); mozAutoDocUpdate batch(GetCrossShadowCurrentDoc(), UPDATE_CONTENT_MODEL, true);
nsAutoMutationBatch mb; nsAutoMutationBatch mb;
// Figure out which index we want to insert at. Note that we use // Figure out which index we want to insert at. Note that we use

Просмотреть файл

@ -114,8 +114,8 @@ nsScriptElement::MaybeProcessScript()
NS_ASSERTION(cont->DebugGetSlots()->mMutationObservers.Contains(this), NS_ASSERTION(cont->DebugGetSlots()->mMutationObservers.Contains(this),
"You forgot to add self as observer"); "You forgot to add self as observer");
if (mAlreadyStarted || !mDoneAddingChildren || !cont->IsInDoc() || if (mAlreadyStarted || !mDoneAddingChildren ||
mMalformed || !HasScriptContent()) { !cont->GetCrossShadowCurrentDoc() || mMalformed || !HasScriptContent()) {
return false; return false;
} }

Просмотреть файл

@ -317,11 +317,16 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
Element* oldScopeElement = GetScopeElement(mStyleSheet); Element* oldScopeElement = GetScopeElement(mStyleSheet);
if (mStyleSheet && aOldDocument) { if (mStyleSheet && (aOldDocument || aOldShadowRoot)) {
// We're removing the link element from the document, unload the MOZ_ASSERT(!(aOldDocument && aOldShadowRoot),
// stylesheet. We want to do this even if updates are disabled, since "ShadowRoot content is never in document, thus "
// otherwise a sheet with a stale linking element pointer will be hanging "there should not be a old document and old "
// around -- not good! "ShadowRoot simultaneously.");
// We're removing the link element from the document or shadow tree,
// unload the stylesheet. We want to do this even if updates are
// disabled, since otherwise a sheet with a stale linking element pointer
// will be hanging around -- not good!
if (aOldShadowRoot) { if (aOldShadowRoot) {
aOldShadowRoot->RemoveSheet(mStyleSheet); aOldShadowRoot->RemoveSheet(mStyleSheet);
} else { } else {
@ -342,8 +347,7 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
return NS_OK; return NS_OK;
} }
nsCOMPtr<nsIDocument> doc = thisContent->GetDocument(); nsCOMPtr<nsIDocument> doc = thisContent->GetCrossShadowCurrentDoc();
if (!doc || !doc->CSSLoader()->GetEnabled()) { if (!doc || !doc->CSSLoader()->GetEnabled()) {
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -28,10 +28,6 @@ function examiner() {
examiner.prototype = { examiner.prototype = {
observe: function(subject, topic, data) { observe: function(subject, topic, data) {
// subject should be an nsURI
if(!SpecialPowers.can_QI(subject))
return;
if (topic === "specialpowers-http-notify-request") { if (topic === "specialpowers-http-notify-request") {
// this is used to fail the test - if we see the POST to the target of the redirect // this is used to fail the test - if we see the POST to the target of the redirect
// we know this is a fail // we know this is a fail

Просмотреть файл

@ -28,10 +28,6 @@ function examiner() {
examiner.prototype = { examiner.prototype = {
observe: function(subject, topic, data) { observe: function(subject, topic, data) {
// subject should be an nsURI
if(!SpecialPowers.can_QI(subject))
return;
if (topic === "specialpowers-http-notify-request") { if (topic === "specialpowers-http-notify-request") {
// this is used to fail the test - if we see the POST to the target of the redirect // this is used to fail the test - if we see the POST to the target of the redirect
// we know this is a fail // we know this is a fail

Просмотреть файл

@ -28,10 +28,6 @@ function examiner() {
examiner.prototype = { examiner.prototype = {
observe: function(subject, topic, data) { observe: function(subject, topic, data) {
// subject should be an nsURI
if(!SpecialPowers.can_QI(subject))
return;
if (topic === "specialpowers-http-notify-request") { if (topic === "specialpowers-http-notify-request") {
// this is used to fail the test - if we see the POST to the target of the redirect // this is used to fail the test - if we see the POST to the target of the redirect
// we know this is a fail // we know this is a fail

Просмотреть файл

@ -28,10 +28,6 @@ function examiner() {
examiner.prototype = { examiner.prototype = {
observe: function(subject, topic, data) { observe: function(subject, topic, data) {
// subject should be an nsURI
if(!SpecialPowers.can_QI(subject))
return;
if (topic === "specialpowers-http-notify-request") { if (topic === "specialpowers-http-notify-request") {
// this is used to fail the test - if we see the POST to the target of the redirect // this is used to fail the test - if we see the POST to the target of the redirect
// we know this is a fail // we know this is a fail

Просмотреть файл

@ -20,6 +20,16 @@
#include "mozilla/dom/AudioChannelBinding.h" #include "mozilla/dom/AudioChannelBinding.h"
#include "mozilla/dom/TextTrackManager.h" #include "mozilla/dom/TextTrackManager.h"
#include "MediaDecoder.h" #include "MediaDecoder.h"
#include "mozilla/dom/MediaKeys.h"
// Something on Linux #defines None, which is an entry in the
// MediaWaitingFor enum, so undef it here before including the binfing,
// so that the build doesn't fail...
#ifdef None
#undef None
#endif
#include "mozilla/dom/HTMLMediaElementBinding.h"
// Define to output information on decoding and painting framerate // Define to output information on decoding and painting framerate
/* #define DEBUG_FRAME_RATE 1 */ /* #define DEBUG_FRAME_RATE 1 */
@ -37,6 +47,7 @@ class MediaResource;
class MediaDecoder; class MediaDecoder;
class VideoFrameContainer; class VideoFrameContainer;
namespace dom { namespace dom {
class MediaKeys;
class TextTrack; class TextTrack;
class TimeRanges; class TimeRanges;
class WakeLock; class WakeLock;
@ -467,6 +478,16 @@ public:
SetHTMLBoolAttr(nsGkAtoms::muted, aMuted, aRv); SetHTMLBoolAttr(nsGkAtoms::muted, aMuted, aRv);
} }
bool MozMediaStatisticsShowing() const
{
return mStatsShowing;
}
void SetMozMediaStatisticsShowing(bool aShow)
{
mStatsShowing = aShow;
}
already_AddRefed<DOMMediaStream> GetMozSrcObject() const; already_AddRefed<DOMMediaStream> GetMozSrcObject() const;
void SetMozSrcObject(DOMMediaStream& aValue); void SetMozSrcObject(DOMMediaStream& aValue);
@ -478,6 +499,22 @@ public:
// XPCOM MozPreservesPitch() is OK // XPCOM MozPreservesPitch() is OK
MediaKeys* GetMediaKeys() const;
already_AddRefed<Promise> SetMediaKeys(MediaKeys* mediaKeys,
ErrorResult& aRv);
MediaWaitingFor WaitingFor() const;
mozilla::dom::EventHandlerNonNull* GetOnneedkey();
void SetOnneedkey(mozilla::dom::EventHandlerNonNull* listener);
void DispatchNeedKey(const nsTArray<uint8_t>& aInitData,
const nsAString& aInitDataType);
bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
bool MozAutoplayEnabled() const bool MozAutoplayEnabled() const
{ {
return mAutoplayEnabled; return mAutoplayEnabled;
@ -1010,6 +1047,9 @@ protected:
// Range of time played. // Range of time played.
nsRefPtr<TimeRanges> mPlayed; nsRefPtr<TimeRanges> mPlayed;
// Encrypted Media Extension media keys.
nsRefPtr<MediaKeys> mMediaKeys;
// Stores the time at the start of the current 'played' range. // Stores the time at the start of the current 'played' range.
double mCurrentPlayRangeStart; double mCurrentPlayRangeStart;
@ -1048,6 +1088,10 @@ protected:
uint32_t mMuted; uint32_t mMuted;
// True if the media statistics are currently being shown by the builtin
// video controls
bool mStatsShowing;
// True if the sound is being captured. // True if the sound is being captured.
bool mAudioCaptured; bool mAudioCaptured;
@ -1139,6 +1183,8 @@ protected:
nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent; nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
nsRefPtr<TextTrackManager> mTextTrackManager; nsRefPtr<TextTrackManager> mTextTrackManager;
MediaWaitingFor mWaitingFor;
}; };
} // namespace dom } // namespace dom

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/EventDispatcher.h" #include "mozilla/EventDispatcher.h"
#include "mozilla/EventStateManager.h" #include "mozilla/EventStateManager.h"
#include "mozilla/EventStates.h" #include "mozilla/EventStates.h"
#include "mozilla/dom/AutocompleteErrorEvent.h"
#include "mozilla/dom/HTMLFormControlsCollection.h" #include "mozilla/dom/HTMLFormControlsCollection.h"
#include "mozilla/dom/HTMLFormElementBinding.h" #include "mozilla/dom/HTMLFormElementBinding.h"
#include "mozilla/Move.h" #include "mozilla/Move.h"
@ -28,6 +29,7 @@
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsIMutableArray.h" #include "nsIMutableArray.h"
#include "nsIAutofillController.h"
// form submission // form submission
#include "nsIFormSubmitObserver.h" #include "nsIFormSubmitObserver.h"
@ -300,6 +302,28 @@ HTMLFormElement::CheckValidity(bool* retVal)
return NS_OK; return NS_OK;
} }
void
HTMLFormElement::RequestAutocomplete()
{
bool dummy;
nsCOMPtr<nsIDOMWindow> win = do_QueryInterface(OwnerDoc()->GetScriptHandlingObject(dummy));
nsCOMPtr<nsIAutofillController> controller(do_GetService("@mozilla.org/autofill-controller;1"));
if (!controller || !win) {
AutocompleteErrorEventInit init;
init.mBubbles = true;
init.mCancelable = false;
init.mReason = AutoCompleteErrorReason::Disabled;
nsRefPtr<AutocompleteErrorEvent> event =
AutocompleteErrorEvent::Constructor(this, NS_LITERAL_STRING("autocompleteerror"), init);
(new AsyncEventDispatcher(this, event))->PostDOMEvent();
return;
}
controller->RequestAutocomplete(this, win);
}
bool bool
HTMLFormElement::ParseAttribute(int32_t aNamespaceID, HTMLFormElement::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute, nsIAtom* aAttribute,

Просмотреть файл

@ -410,6 +410,8 @@ public:
js::ExpandoAndGeneration mExpandoAndGeneration; js::ExpandoAndGeneration mExpandoAndGeneration;
void RequestAutocomplete();
protected: protected:
virtual JSObject* WrapNode(JSContext* aCx) MOZ_OVERRIDE; virtual JSObject* WrapNode(JSContext* aCx) MOZ_OVERRIDE;

Просмотреть файл

@ -190,13 +190,13 @@ static const nsAttrValue::EnumTable kInputInputmodeTable[] = {
// Default inputmode value is "auto". // Default inputmode value is "auto".
static const nsAttrValue::EnumTable* kInputDefaultInputmode = &kInputInputmodeTable[0]; static const nsAttrValue::EnumTable* kInputDefaultInputmode = &kInputInputmodeTable[0];
const Decimal HTMLInputElement::kStepScaleFactorDate = 86400000; const Decimal HTMLInputElement::kStepScaleFactorDate = Decimal(86400000);
const Decimal HTMLInputElement::kStepScaleFactorNumberRange = 1; const Decimal HTMLInputElement::kStepScaleFactorNumberRange = Decimal(1);
const Decimal HTMLInputElement::kStepScaleFactorTime = 1000; const Decimal HTMLInputElement::kStepScaleFactorTime = Decimal(1000);
const Decimal HTMLInputElement::kDefaultStepBase = 0; const Decimal HTMLInputElement::kDefaultStepBase = Decimal(0);
const Decimal HTMLInputElement::kDefaultStep = 1; const Decimal HTMLInputElement::kDefaultStep = Decimal(1);
const Decimal HTMLInputElement::kDefaultStepTime = 60; const Decimal HTMLInputElement::kDefaultStepTime = Decimal(60);
const Decimal HTMLInputElement::kStepAny = 0; const Decimal HTMLInputElement::kStepAny = Decimal(0);
#define NS_INPUT_ELEMENT_STATE_IID \ #define NS_INPUT_ELEMENT_STATE_IID \
{ /* dc3b3d14-23e2-4479-b513-7b369343e3a0 */ \ { /* dc3b3d14-23e2-4479-b513-7b369343e3a0 */ \
@ -1754,7 +1754,7 @@ HTMLInputElement::ConvertStringToNumber(nsAString& aValue,
return false; return false;
} }
aResultValue = int32_t(milliseconds); aResultValue = Decimal(int32_t(milliseconds));
return true; return true;
default: default:
MOZ_ASSERT(false, "Unrecognized input type"); MOZ_ASSERT(false, "Unrecognized input type");
@ -1929,7 +1929,7 @@ HTMLInputElement::ConvertNumberToString(Decimal aValue,
// Per spec, we need to truncate |aValue| and we should only represent // Per spec, we need to truncate |aValue| and we should only represent
// times inside a day [00:00, 24:00[, which means that we should do a // times inside a day [00:00, 24:00[, which means that we should do a
// modulo on |aValue| using the number of milliseconds in a day (86400000). // modulo on |aValue| using the number of milliseconds in a day (86400000).
uint32_t value = NS_floorModulo(aValue.floor(), 86400000).toDouble(); uint32_t value = NS_floorModulo(aValue.floor(), Decimal(86400000)).toDouble();
uint16_t milliseconds = value % 1000; uint16_t milliseconds = value % 1000;
value /= 1000; value /= 1000;
@ -2055,7 +2055,7 @@ HTMLInputElement::GetMinimum() const
// Only type=range has a default minimum // Only type=range has a default minimum
Decimal defaultMinimum = Decimal defaultMinimum =
mType == NS_FORM_INPUT_RANGE ? 0 : Decimal::nan(); mType == NS_FORM_INPUT_RANGE ? Decimal(0) : Decimal::nan();
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::min)) { if (!HasAttr(kNameSpaceID_None, nsGkAtoms::min)) {
return defaultMinimum; return defaultMinimum;
@ -2076,7 +2076,7 @@ HTMLInputElement::GetMaximum() const
// Only type=range has a default maximum // Only type=range has a default maximum
Decimal defaultMaximum = Decimal defaultMaximum =
mType == NS_FORM_INPUT_RANGE ? 100 : Decimal::nan(); mType == NS_FORM_INPUT_RANGE ? Decimal(100) : Decimal::nan();
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::max)) { if (!HasAttr(kNameSpaceID_None, nsGkAtoms::max)) {
return defaultMaximum; return defaultMaximum;
@ -2138,7 +2138,7 @@ HTMLInputElement::GetValueIfStepped(int32_t aStep,
Decimal value = GetValueAsDecimal(); Decimal value = GetValueAsDecimal();
if (value.isNaN()) { if (value.isNaN()) {
value = 0; value = Decimal(0);
} }
Decimal minimum = GetMinimum(); Decimal minimum = GetMinimum();
@ -2176,14 +2176,14 @@ HTMLInputElement::GetValueIfStepped(int32_t aStep,
} }
} }
value += step * aStep; value += step * Decimal(aStep);
// For date inputs, the value can hold a string that is not a day. We do not // For date inputs, the value can hold a string that is not a day. We do not
// want to round it, as it might result in a step mismatch. Instead we want to // want to round it, as it might result in a step mismatch. Instead we want to
// clamp to the next valid value. // clamp to the next valid value.
if (mType == NS_FORM_INPUT_DATE && if (mType == NS_FORM_INPUT_DATE &&
NS_floorModulo(value - GetStepBase(), GetStepScaleFactor()) != 0) { NS_floorModulo(Decimal(value - GetStepBase()), GetStepScaleFactor()) != Decimal(0)) {
MOZ_ASSERT(GetStep() > 0); MOZ_ASSERT(GetStep() > Decimal(0));
Decimal validStep = EuclidLCM<Decimal>(GetStep().floor(), Decimal validStep = EuclidLCM<Decimal>(GetStep().floor(),
GetStepScaleFactor().floor()); GetStepScaleFactor().floor());
if (aStep > 0) { if (aStep > 0) {
@ -4116,10 +4116,10 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
case NS_VK_PAGE_UP: case NS_VK_PAGE_UP:
// For PgUp/PgDn we jump 10% of the total range, unless step // For PgUp/PgDn we jump 10% of the total range, unless step
// requires us to jump more. // requires us to jump more.
newValue = value + std::max(step, (maximum - minimum) / 10); newValue = value + std::max(step, (maximum - minimum) / Decimal(10));
break; break;
case NS_VK_PAGE_DOWN: case NS_VK_PAGE_DOWN:
newValue = value - std::max(step, (maximum - minimum) / 10); newValue = value - std::max(step, (maximum - minimum) / Decimal(10));
break; break;
} }
SetValueOfRangeForUserEvent(newValue); SetValueOfRangeForUserEvent(newValue);
@ -4567,7 +4567,7 @@ HTMLInputElement::SanitizeValue(nsAString& aValue)
if (!ok) { if (!ok) {
needSanitization = true; needSanitization = true;
// Set value to midway between minimum and maximum. // Set value to midway between minimum and maximum.
value = maximum <= minimum ? minimum : minimum + (maximum - minimum)/2; value = maximum <= minimum ? minimum : minimum + (maximum - minimum)/Decimal(2);
} else if (value < minimum || maximum < minimum) { } else if (value < minimum || maximum < minimum) {
needSanitization = true; needSanitization = true;
value = minimum; value = minimum;
@ -4583,17 +4583,17 @@ HTMLInputElement::SanitizeValue(nsAString& aValue)
// numbers, but let's ignore that until ECMAScript supplies us with a // numbers, but let's ignore that until ECMAScript supplies us with a
// decimal number type. // decimal number type.
Decimal deltaToStep = NS_floorModulo(value - stepBase, step); Decimal deltaToStep = NS_floorModulo(value - stepBase, step);
if (deltaToStep != 0) { if (deltaToStep != Decimal(0)) {
// "suffering from a step mismatch" // "suffering from a step mismatch"
// Round the element's value to the nearest number for which the // Round the element's value to the nearest number for which the
// element would not suffer from a step mismatch, and which is // element would not suffer from a step mismatch, and which is
// greater than or equal to the minimum, and, if the maximum is not // greater than or equal to the minimum, and, if the maximum is not
// less than the minimum, which is less than or equal to the // less than the minimum, which is less than or equal to the
// maximum, if there is a number that matches these constraints: // maximum, if there is a number that matches these constraints:
MOZ_ASSERT(deltaToStep > 0, "stepBelow/stepAbove will be wrong"); MOZ_ASSERT(deltaToStep > Decimal(0), "stepBelow/stepAbove will be wrong");
Decimal stepBelow = value - deltaToStep; Decimal stepBelow = value - deltaToStep;
Decimal stepAbove = value - deltaToStep + step; Decimal stepAbove = value - deltaToStep + step;
Decimal halfStep = step / 2; Decimal halfStep = step / Decimal(2);
bool stepAboveIsClosest = (stepAbove - value) <= halfStep; bool stepAboveIsClosest = (stepAbove - value) <= halfStep;
bool stepAboveInRange = stepAbove >= minimum && bool stepAboveInRange = stepAbove >= minimum &&
stepAbove <= maximum; stepAbove <= maximum;
@ -6276,7 +6276,7 @@ HTMLInputElement::GetStep() const
} }
Decimal step = StringToDecimal(stepStr); Decimal step = StringToDecimal(stepStr);
if (!step.isFinite() || step <= 0) { if (!step.isFinite() || step <= Decimal(0)) {
step = GetDefaultStep(); step = GetDefaultStep();
} }
@ -6462,7 +6462,7 @@ HTMLInputElement::HasStepMismatch(bool aUseZeroIfValueNaN) const
Decimal value = GetValueAsDecimal(); Decimal value = GetValueAsDecimal();
if (value.isNaN()) { if (value.isNaN()) {
if (aUseZeroIfValueNaN) { if (aUseZeroIfValueNaN) {
value = 0; value = Decimal(0);
} else { } else {
// The element can't suffer from step mismatch if it's value isn't a number. // The element can't suffer from step mismatch if it's value isn't a number.
return false; return false;
@ -6475,7 +6475,7 @@ HTMLInputElement::HasStepMismatch(bool aUseZeroIfValueNaN) const
} }
// Value has to be an integral multiple of step. // Value has to be an integral multiple of step.
return NS_floorModulo(value - GetStepBase(), step) != 0; return NS_floorModulo(value - GetStepBase(), step) != Decimal(0);
} }
/** /**
@ -6881,7 +6881,7 @@ HTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
MOZ_ASSERT(!value.isNaN()); MOZ_ASSERT(!value.isNaN());
Decimal step = GetStep(); Decimal step = GetStep();
MOZ_ASSERT(step != kStepAny && step > 0); MOZ_ASSERT(step != kStepAny && step > Decimal(0));
// In case this is a date and the step is not an integer, we don't want to // In case this is a date and the step is not an integer, we don't want to
// display the dates corresponding to the truncated timestamps of valueLow // display the dates corresponding to the truncated timestamps of valueLow

Просмотреть файл

@ -9,6 +9,8 @@
#include "mozilla/dom/ElementInlines.h" #include "mozilla/dom/ElementInlines.h"
#include "mozilla/ArrayUtils.h" #include "mozilla/ArrayUtils.h"
#include "mozilla/MathAlgorithms.h" #include "mozilla/MathAlgorithms.h"
#include "mozilla/dom/MediaKeyNeededEvent.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "base/basictypes.h" #include "base/basictypes.h"
#include "nsIDOMHTMLMediaElement.h" #include "nsIDOMHTMLMediaElement.h"
@ -423,6 +425,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM
} }
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlayed); NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlayed);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeys)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLElement) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
@ -439,10 +442,11 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLE
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioChannelAgent) NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioChannelAgent)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mError) NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) { for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) {
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputStreams[i].mStream); NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputStreams[i].mStream)
} }
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlayed); NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlayed)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextTrackManager) NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextTrackManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaKeys)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLMediaElement) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLMediaElement)
@ -895,6 +899,9 @@ void HTMLMediaElement::LoadFromSourceChildren()
ReportLoadError("MediaLoadUnsupportedTypeAttribute", params, ArrayLength(params)); ReportLoadError("MediaLoadUnsupportedTypeAttribute", params, ArrayLength(params));
continue; continue;
} }
// TODO: "If candidate has a keySystem attribute whose value represents a
// Key System that the user agent knows it cannot use with type,
// then end the synchronous section[...]" (Bug 1016707)
nsAutoString media; nsAutoString media;
if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::media, media) && !media.IsEmpty()) { if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::media, media) && !media.IsEmpty()) {
nsCSSParser cssParser; nsCSSParser cssParser;
@ -1982,6 +1989,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<nsINodeInfo>& aNodeInfo)
mAutoplayEnabled(true), mAutoplayEnabled(true),
mPaused(true), mPaused(true),
mMuted(0), mMuted(0),
mStatsShowing(false),
mAudioCaptured(false), mAudioCaptured(false),
mPlayingBeforeSeek(false), mPlayingBeforeSeek(false),
mPausedForInactiveDocumentOrChannel(false), mPausedForInactiveDocumentOrChannel(false),
@ -2003,7 +2011,8 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<nsINodeInfo>& aNodeInfo)
mHasAudio(false), mHasAudio(false),
mDownloadSuspendedByCache(false), mDownloadSuspendedByCache(false),
mAudioChannelFaded(false), mAudioChannelFaded(false),
mPlayingThroughTheAudioChannel(false) mPlayingThroughTheAudioChannel(false),
mWaitingFor(MediaWaitingFor::None)
{ {
#ifdef PR_LOGGING #ifdef PR_LOGGING
if (!gMediaElementLog) { if (!gMediaElementLog) {
@ -3894,6 +3903,72 @@ NS_IMETHODIMP HTMLMediaElement::CanPlayChanged(int32_t canPlay)
return NS_OK; return NS_OK;
} }
MediaKeys*
HTMLMediaElement::GetMediaKeys() const
{
return mMediaKeys;
}
already_AddRefed<Promise>
HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(OwnerDoc()->GetInnerWindow());
if (!global) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
// TODO: Need to shutdown existing MediaKeys instance? bug 1016709.
nsRefPtr<Promise> promise = new Promise(global);
if (mMediaKeys != aMediaKeys) {
mMediaKeys = aMediaKeys;
}
promise->MaybeResolve(JS::UndefinedHandleValue);
return promise.forget();
}
MediaWaitingFor
HTMLMediaElement::WaitingFor() const
{
return mWaitingFor;
}
EventHandlerNonNull*
HTMLMediaElement::GetOnneedkey()
{
EventListenerManager *elm = GetExistingListenerManager();
return elm ? elm->GetEventHandler(nsGkAtoms::onneedkey, EmptyString())
: nullptr;
}
void
HTMLMediaElement::SetOnneedkey(EventHandlerNonNull* handler)
{
EventListenerManager *elm = GetOrCreateListenerManager();
if (elm) {
elm->SetEventHandler(nsGkAtoms::onneedkey, EmptyString(), handler);
}
}
void
HTMLMediaElement::DispatchNeedKey(const nsTArray<uint8_t>& aInitData,
const nsAString& aInitDataType)
{
nsRefPtr<MediaKeyNeededEvent> event(
MediaKeyNeededEvent::Constructor(this, aInitDataType, aInitData));
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, event);
asyncDispatcher->PostDOMEvent();
}
bool
HTMLMediaElement::IsEventAttributeName(nsIAtom* aName)
{
return aName == nsGkAtoms::onneedkey ||
nsGenericHTMLElement::IsEventAttributeName(aName);
}
NS_IMETHODIMP HTMLMediaElement::WindowVolumeChanged() NS_IMETHODIMP HTMLMediaElement::WindowVolumeChanged()
{ {
SetVolumeInternal(); SetVolumeInternal();

Просмотреть файл

@ -62,7 +62,7 @@ HTMLScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
aCompileEventHandlers); aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (aDocument) { if (GetCrossShadowCurrentDoc()) {
MaybeProcessScript(); MaybeProcessScript();
} }

Просмотреть файл

@ -64,6 +64,16 @@ public:
SetHTMLAttr(nsGkAtoms::media, aMedia, rv); SetHTMLAttr(nsGkAtoms::media, aMedia, rv);
} }
void GetKeySystem(nsString& aKeySystem) const
{
GetHTMLAttr(nsGkAtoms::keysystem, aKeySystem);
}
void SetKeySystem(const nsAString& aKeySystem)
{
SetHTMLAttr(nsGkAtoms::keysystem, aKeySystem);
}
protected: protected:
virtual JSObject* WrapNode(JSContext* aCx) MOZ_OVERRIDE; virtual JSObject* WrapNode(JSContext* aCx) MOZ_OVERRIDE;

Просмотреть файл

@ -0,0 +1,199 @@
/* -*- 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 "mozilla/CDMProxy.h"
#include "nsString.h"
#include "mozilla/dom/MediaKeys.h"
#include "mozilla/dom/MediaKeySession.h"
#include "mozIGeckoMediaPluginService.h"
#include "nsContentCID.h"
#include "nsServiceManagerUtils.h"
#include "MainThreadUtils.h"
// TODO: Change the functions in this file to do IPC via the Gecko Media
// Plugins API. In the meantime, the code here merely implements the
// interface we expect will be required when the IPC is working.
namespace mozilla {
CDMProxy::CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem)
: mKeys(aKeys)
, mKeySystem(aKeySystem)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_CTOR(CDMProxy);
}
CDMProxy::~CDMProxy()
{
MOZ_COUNT_DTOR(CDMProxy);
}
void
CDMProxy::Init(PromiseId aPromiseId)
{
MOZ_ASSERT(NS_IsMainThread());
if (!mGMPThread) {
nsCOMPtr<mozIGeckoMediaPluginService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (!mps) {
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
mps->GetThread(getter_AddRefs(mGMPThread));
if (!mGMPThread) {
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
}
// TODO: Dispatch task to GMPThread to initialize CDM via IPC.
mKeys->OnCDMCreated(aPromiseId);
}
static int sFakeSessionIdNum = 0;
void
CDMProxy::CreateSession(dom::SessionType aSessionType,
PromiseId aPromiseId,
const nsAString& aInitDataType,
const Uint8Array& aInitData)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mGMPThread);
// TODO: Dispatch task to GMPThread to call CDM CreateSession via IPC.
// Make a fake session id. We'll get this from the CDM normally.
nsAutoString id;
id.AppendASCII("FakeSessionId_");
id.AppendInt(sFakeSessionIdNum++);
mKeys->OnSessionActivated(aPromiseId, id);
}
void
CDMProxy::LoadSession(PromiseId aPromiseId,
const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mGMPThread);
// TODO: Dispatch task to GMPThread to call CDM LoadSession via IPC.
// make MediaKeys::mPendingSessions CC'd
mKeys->OnSessionActivated(aPromiseId, aSessionId);
}
void
CDMProxy::SetServerCertificate(PromiseId aPromiseId,
const Uint8Array& aCertData)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mGMPThread);
// TODO: Dispatch task to GMPThread to call CDM SetServerCertificate via IPC.
ResolvePromise(aPromiseId);
}
static int sUpdateCount = 0;
void
CDMProxy::UpdateSession(const nsAString& aSessionId,
PromiseId aPromiseId,
const Uint8Array& aResponse)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mGMPThread);
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
// TODO: Dispatch task to GMPThread to call CDM UpdateSession via IPC.
nsRefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
nsAutoCString str(NS_LITERAL_CSTRING("Update_"));
str.AppendInt(sUpdateCount++);
nsTArray<uint8_t> msg;
msg.AppendElements(str.get(), str.Length());
session->DispatchKeyMessage(msg, NS_LITERAL_STRING("http://bogus.url"));
ResolvePromise(aPromiseId);
}
void
CDMProxy::CloseSession(const nsAString& aSessionId,
PromiseId aPromiseId)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
// TODO: Dispatch task to GMPThread to call CDM CloseSession via IPC.
nsRefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
// Pretend that the CDM actually does close the session...
// "...the [MediaKeySession's] closed attribute promise is resolved
// when the session is closed."
session->OnClosed();
// "The promise is resolved when the request has been processed."
ResolvePromise(aPromiseId);
}
void
CDMProxy::RemoveSession(const nsAString& aSessionId,
PromiseId aPromiseId)
{
MOZ_ASSERT(NS_IsMainThread());
// TODO: Dispatch task to GMPThread to call CDM RemoveSession via IPC.
// Assume CDM immediately removes session's data, then close the session
// as per the spec.
CloseSession(aSessionId, aPromiseId);
}
void
CDMProxy::Shutdown()
{
MOZ_ASSERT(NS_IsMainThread());
mKeys.Clear();
}
void
CDMProxy::RejectPromise(PromiseId aId, nsresult aCode)
{
if (NS_IsMainThread()) {
if (!mKeys.IsNull()) {
mKeys->RejectPromise(aId, aCode);
} else {
NS_WARNING("CDMProxy unable to reject promise!");
}
} else {
nsRefPtr<nsIRunnable> task(new RejectPromiseTask(this, aId, aCode));
NS_DispatchToMainThread(task);
}
}
void
CDMProxy::ResolvePromise(PromiseId aId)
{
if (NS_IsMainThread()) {
if (!mKeys.IsNull()) {
mKeys->ResolvePromise(aId);
} else {
NS_WARNING("CDMProxy unable to resolve promise!");
}
} else {
nsRefPtr<nsIRunnable> task;
task = NS_NewRunnableMethodWithArg<PromiseId>(this,
&CDMProxy::ResolvePromise,
aId);
NS_DispatchToMainThread(task);
}
}
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,171 @@
/* -*- 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 CDMProxy_h_
#define CDMProxy_h_
#include "nsString.h"
#include "nsAutoPtr.h"
#include "nsProxyRelease.h"
#include "mozilla/dom/MediaKeys.h"
#include "mozilla/dom/TypedArray.h"
class nsIThread;
namespace mozilla {
namespace dom {
class MediaKeySession;
}
// A placeholder proxy to the CDM.
// TODO: The functions here need to do IPC to talk to the CDM via the
// Gecko Media Plugin API, which we'll need to extend for H.264 and EME
// content.
// Note: Promises are passed in via a PromiseId, so that the ID can be
// passed via IPC to the CDM, which can then signal when to reject or
// resolve the promise using its PromiseId.
class CDMProxy {
typedef dom::PromiseId PromiseId;
typedef dom::SessionType SessionType;
typedef dom::Uint8Array Uint8Array;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMProxy)
// Main thread only.
CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem);
// Main thread only.
// Loads the CDM corresponding to mKeySystem.
// Calls MediaKeys::OnCDMCreated() when the CDM is created.
void Init(PromiseId aPromiseId);
// Main thread only.
// Uses the CDM to create a key session.
// Caller is responsible for calling aInitData.ComputeLengthAndData().
// Calls MediaKeys::OnSessionActivated() when session is created.
void CreateSession(dom::SessionType aSessionType,
PromiseId aPromiseId,
const nsAString& aInitDataType,
const Uint8Array& aInitData);
// Main thread only.
// Uses the CDM to load a presistent session stored on disk.
// Calls MediaKeys::OnSessionActivated() when session is loaded.
void LoadSession(PromiseId aPromiseId,
const nsAString& aSessionId);
// Main thread only.
// Sends a new certificate to the CDM.
// Caller is responsible for calling aCert.ComputeLengthAndData().
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
// processed the request.
void SetServerCertificate(PromiseId aPromiseId,
const Uint8Array& aCert);
// Main thread only.
// Sends an update to the CDM.
// Caller is responsible for calling aResponse.ComputeLengthAndData().
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
// processed the request.
void UpdateSession(const nsAString& aSessionId,
PromiseId aPromiseId,
const Uint8Array& aResponse);
// Main thread only.
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
// processed the request.
// If processing this operation results in the session actually closing,
// we also call MediaKeySession::OnClosed(), which in turn calls
// MediaKeys::OnSessionClosed().
void CloseSession(const nsAString& aSessionId,
PromiseId aPromiseId);
// Main thread only.
// Removes all data for a persisent session.
// Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has
// processed the request.
void RemoveSession(const nsAString& aSessionId,
PromiseId aPromiseId);
// Main thread only.
void Shutdown();
private:
class RejectPromiseTask : public nsRunnable {
public:
RejectPromiseTask(CDMProxy* aProxy,
PromiseId aId,
nsresult aCode)
: mProxy(aProxy)
, mId(aId)
, mCode(aCode)
{
}
NS_METHOD Run() {
mProxy->RejectPromise(mId, mCode);
return NS_OK;
}
private:
nsRefPtr<CDMProxy> mProxy;
PromiseId mId;
nsresult mCode;
};
// Reject promise with DOMException corresponding to aExceptionCode.
// Can be called from any thread.
void RejectPromise(PromiseId aId, nsresult aExceptionCode);
// Resolves promise with "undefined".
// Can be called from any thread.
void ResolvePromise(PromiseId aId);
~CDMProxy();
// Helper to enforce that a raw pointer is only accessed on the main thread.
template<class Type>
class MainThreadOnlyRawPtr {
public:
MainThreadOnlyRawPtr(Type* aPtr)
: mPtr(aPtr)
{
MOZ_ASSERT(NS_IsMainThread());
}
bool IsNull() const {
MOZ_ASSERT(NS_IsMainThread());
return !mPtr;
}
void Clear() {
MOZ_ASSERT(NS_IsMainThread());
mPtr = nullptr;
}
Type* operator->() const {
MOZ_ASSERT(NS_IsMainThread());
return mPtr;
}
private:
Type* mPtr;
};
// Our reference back to the MediaKeys object.
// WARNING: This is a non-owning reference that is cleared by MediaKeys
// destructor. only use on main thread, and always nullcheck before using!
MainThreadOnlyRawPtr<dom::MediaKeys> mKeys;
const nsAutoString mKeySystem;
// Gecko Media Plugin thread. All interactions with the out-of-process
// EME plugin must come from this thread.
nsRefPtr<nsIThread> mGMPThread;
};
} // namespace mozilla
#endif // CDMProxy_h_

Просмотреть файл

@ -0,0 +1,32 @@
/* -*- 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 "EMELog.h"
#include "mozilla/NullPtr.h"
namespace mozilla {
#ifdef PR_LOGGING
PRLogModuleInfo* GetEMELog() {
static PRLogModuleInfo* log = nullptr;
if (!log) {
log = PR_NewLogModule("EME");
}
return log;
}
PRLogModuleInfo* GetEMEVerboseLog() {
static PRLogModuleInfo* log = nullptr;
if (!log) {
log = PR_NewLogModule("EMEV");
}
return log;
}
#endif
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,35 @@
/* -*- 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 "prlog.h"
namespace mozilla {
#ifdef PR_LOGGING
#ifndef EME_LOG
PRLogModuleInfo* GetEMELog();
#define EME_LOG(...) PR_LOG(GetEMELog(), PR_LOG_DEBUG, (__VA_ARGS__))
#endif
#ifndef EME_VERBOSE_LOG
PRLogModuleInfo* GetEMEVerboseLog();
#define EME_VERBOSE_LOG(...) PR_LOG(GetEMEVerboseLog(), PR_LOG_DEBUG, (__VA_ARGS__))
#else
#ifndef EME_LOG
#define EME_LOG(...)
#endif
#ifndef EME_VERBOSE_LOG
#define EME_VERBOSE_LOG(...)
#endif
#endif
#endif // PR_LOGGING
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,39 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaKeyError.h"
#include "mozilla/dom/MediaKeyErrorBinding.h"
#include "nsContentUtils.h"
namespace mozilla {
namespace dom {
MediaKeyError::MediaKeyError(EventTarget* aOwner, uint32_t aSystemCode)
: Event(aOwner, nullptr, nullptr)
, mSystemCode(aSystemCode)
{
SetIsDOMBinding();
}
MediaKeyError::~MediaKeyError()
{
}
uint32_t
MediaKeyError::SystemCode() const
{
return mSystemCode;
}
JSObject*
MediaKeyError::WrapObject(JSContext* aCx)
{
return MediaKeyErrorBinding::Wrap(aCx, this);
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_MediaKeyError_h
#define mozilla_dom_MediaKeyError_h
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "nsWrapperCache.h"
#include "mozilla/dom/Event.h"
#include "js/TypeDecls.h"
namespace mozilla {
namespace dom {
class MediaKeyError MOZ_FINAL : public Event
{
public:
NS_FORWARD_TO_EVENT
MediaKeyError(EventTarget* aOwner, uint32_t aSystemCode);
~MediaKeyError();
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
uint32_t SystemCode() const;
private:
uint32_t mSystemCode;
};
} // namespace dom
} // namespace mozilla
#endif

Просмотреть файл

@ -0,0 +1,127 @@
/* -*- 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 "mozilla/dom/MediaKeyMessageEvent.h"
#include "mozilla/dom/MediaKeyMessageEventBinding.h"
#include "js/GCAPI.h"
#include "jsfriendapi.h"
#include "mozilla/dom/Nullable.h"
#include "mozilla/dom/PrimitiveConversions.h"
#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/dom/TypedArray.h"
#include "nsContentUtils.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(MediaKeyMessageEvent)
NS_IMPL_ADDREF_INHERITED(MediaKeyMessageEvent, Event)
NS_IMPL_RELEASE_INHERITED(MediaKeyMessageEvent, Event)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaKeyMessageEvent, Event)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MediaKeyMessageEvent, Event)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMessage)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaKeyMessageEvent, Event)
tmp->mMessage = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaKeyMessageEvent)
NS_INTERFACE_MAP_END_INHERITING(Event)
MediaKeyMessageEvent::MediaKeyMessageEvent(EventTarget* aOwner)
: Event(aOwner, nullptr, nullptr)
{
mozilla::HoldJSObjects(this);
}
MediaKeyMessageEvent::~MediaKeyMessageEvent()
{
mMessage = nullptr;
mozilla::DropJSObjects(this);
}
MediaKeyMessageEvent*
MediaKeyMessageEvent::AsMediaKeyMessageEvent()
{
return this;
}
JSObject*
MediaKeyMessageEvent::WrapObject(JSContext* aCx)
{
return MediaKeyMessageEventBinding::Wrap(aCx, this);
}
already_AddRefed<MediaKeyMessageEvent>
MediaKeyMessageEvent::Constructor(EventTarget* aOwner,
const nsAString& aURL,
const nsTArray<uint8_t>& aMessage)
{
nsRefPtr<MediaKeyMessageEvent> e = new MediaKeyMessageEvent(aOwner);
e->InitEvent(NS_LITERAL_STRING("message"), false, false);
e->mRawMessage = aMessage;
e->mDestinationURL = aURL;
e->SetTrusted(true);
return e.forget();
}
already_AddRefed<MediaKeyMessageEvent>
MediaKeyMessageEvent::Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const MediaKeyMessageEventInit& aEventInitDict,
ErrorResult& aRv)
{
nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
nsRefPtr<MediaKeyMessageEvent> e = new MediaKeyMessageEvent(owner);
bool trusted = e->Init(owner);
e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable);
if (aEventInitDict.mMessage.WasPassed()) {
const auto& a = aEventInitDict.mMessage.Value();
a.ComputeLengthAndData();
e->mMessage = Uint8Array::Create(aGlobal.GetContext(), owner, a.Length(), a.Data());
} else {
e->mMessage = Uint8Array::Create(aGlobal.GetContext(), owner, 0, nullptr);
}
if (!e->mMessage) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
e->mDestinationURL = aEventInitDict.mDestinationURL;
e->SetTrusted(trusted);
return e.forget();
}
JSObject*
MediaKeyMessageEvent::GetMessage(JSContext* cx, ErrorResult& aRv)
{
if (!mMessage) {
mMessage = Uint8Array::Create(cx,
this,
mRawMessage.Length(),
mRawMessage.Elements());
if (!mMessage) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
mRawMessage.Clear();
}
JS::ExposeObjectToActiveJS(mMessage);
return mMessage;
}
void
MediaKeyMessageEvent::GetDestinationURL(nsString& aRetVal) const
{
aRetVal = mDestinationURL;
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,65 @@
/* -*- 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_dom_MediaKeyMessageEvent_h__
#define mozilla_dom_MediaKeyMessageEvent_h__
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "nsCOMPtr.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/TypedArray.h"
#include "js/TypeDecls.h"
#include "mozilla/dom/MediaKeyMessageEventBinding.h"
namespace mozilla {
namespace dom {
class MediaKeyMessageEventInit;
class MediaKeyMessageEvent MOZ_FINAL : public Event
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MediaKeyMessageEvent, Event)
virtual ~MediaKeyMessageEvent();
protected:
MediaKeyMessageEvent(EventTarget* aOwner);
JS::Heap<JSObject*> mMessage;
nsString mDestinationURL;
public:
virtual MediaKeyMessageEvent* AsMediaKeyMessageEvent();
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
static already_AddRefed<MediaKeyMessageEvent>
Constructor(EventTarget* aOwner,
const nsAString& aURL,
const nsTArray<uint8_t>& aMessage);
static already_AddRefed<MediaKeyMessageEvent>
Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const MediaKeyMessageEventInit& aEventInitDict,
ErrorResult& aRv);
JSObject* GetMessage(JSContext* cx, ErrorResult& aRv);
void GetDestinationURL(nsString& aRetVal) const;
private:
nsTArray<uint8_t> mRawMessage;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_MediaKeyMessageEvent_h__

Просмотреть файл

@ -0,0 +1,118 @@
/* -*- 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 "MediaKeyNeededEvent.h"
#include "mozilla/dom/MediaKeyNeededEventBinding.h"
#include "nsContentUtils.h"
#include "jsfriendapi.h"
#include "nsINode.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(MediaKeyNeededEvent)
NS_IMPL_ADDREF_INHERITED(MediaKeyNeededEvent, Event)
NS_IMPL_RELEASE_INHERITED(MediaKeyNeededEvent, Event)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaKeyNeededEvent, Event)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MediaKeyNeededEvent, Event)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mInitData)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaKeyNeededEvent, Event)
tmp->mInitData = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaKeyNeededEvent)
NS_INTERFACE_MAP_END_INHERITING(Event)
MediaKeyNeededEvent::MediaKeyNeededEvent(EventTarget* aOwner)
: Event(aOwner, nullptr, nullptr)
{
mozilla::HoldJSObjects(this);
}
MediaKeyNeededEvent::~MediaKeyNeededEvent()
{
mInitData = nullptr;
mozilla::DropJSObjects(this);
}
JSObject*
MediaKeyNeededEvent::WrapObject(JSContext* aCx)
{
return MediaKeyNeededEventBinding::Wrap(aCx, this);
}
already_AddRefed<MediaKeyNeededEvent>
MediaKeyNeededEvent::Constructor(EventTarget* aOwner,
const nsAString& aInitDataType,
const nsTArray<uint8_t>& aInitData)
{
nsRefPtr<MediaKeyNeededEvent> e = new MediaKeyNeededEvent(aOwner);
e->InitEvent(NS_LITERAL_STRING("needkey"), false, false);
e->mInitDataType = aInitDataType;
e->mRawInitData = aInitData;
e->SetTrusted(true);
return e.forget();
}
already_AddRefed<MediaKeyNeededEvent>
MediaKeyNeededEvent::Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const MediaKeyNeededEventInit& aEventInitDict,
ErrorResult& aRv)
{
nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
nsRefPtr<MediaKeyNeededEvent> e = new MediaKeyNeededEvent(owner);
bool trusted = e->Init(owner);
e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable);
e->mInitDataType = aEventInitDict.mInitDataType;
if (aEventInitDict.mInitData.WasPassed() &&
!aEventInitDict.mInitData.Value().IsNull()) {
const auto& a = aEventInitDict.mInitData.Value().Value();
a.ComputeLengthAndData();
e->mInitData = Uint8Array::Create(aGlobal.GetContext(), owner, a.Length(), a.Data());
if (!e->mInitData) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
}
e->SetTrusted(trusted);
return e.forget();
}
void
MediaKeyNeededEvent::GetInitDataType(nsString& aRetVal) const
{
aRetVal = mInitDataType;
}
JSObject*
MediaKeyNeededEvent::GetInitData(JSContext* cx, ErrorResult& aRv)
{
if (mRawInitData.Length()) {
mInitData = Uint8Array::Create(cx,
this,
mRawInitData.Length(),
mRawInitData.Elements());
if (!mInitData) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
mRawInitData.Clear();
}
if (mInitData) {
JS::ExposeObjectToActiveJS(mInitData);
}
return mInitData;
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,62 @@
/* -*- 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_dom_MediaKeyNeededEvent_h__
#define mozilla_dom_MediaKeyNeededEvent_h__
#include "mozilla/dom/MediaKeyNeededEventBinding.h"
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "nsCOMPtr.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/BindingUtils.h"
#include "js/TypeDecls.h"
namespace mozilla {
namespace dom {
class MediaKeyNeededEvent MOZ_FINAL : public Event
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MediaKeyNeededEvent, Event)
virtual ~MediaKeyNeededEvent();
protected:
MediaKeyNeededEvent(EventTarget* aOwner);
nsString mInitDataType;
JS::Heap<JSObject*> mInitData;
public:
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
static already_AddRefed<MediaKeyNeededEvent>
Constructor(EventTarget* aOwner,
const nsAString& aInitDataType,
const nsTArray<uint8_t>& aInitData);
static already_AddRefed<MediaKeyNeededEvent>
Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const MediaKeyNeededEventInit& aEventInitDict,
ErrorResult& aRv);
void GetInitDataType(nsString& aRetVal) const;
JSObject* GetInitData(JSContext* cx, ErrorResult& aRv);
private:
nsTArray<uint8_t> mRawInitData;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_MediaKeyNeededEvent_h__

Просмотреть файл

@ -0,0 +1,178 @@
/* -*- 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 "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/dom/MediaKeySession.h"
#include "mozilla/dom/MediaKeyError.h"
#include "mozilla/dom/MediaKeyMessageEvent.h"
#include "mozilla/dom/MediaKeyNeededEvent.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/CDMProxy.h"
#include "mozilla/AsyncEventDispatcher.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaKeySession,
DOMEventTargetHelper,
mMediaKeyError,
mKeys,
mClosed)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaKeySession)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(MediaKeySession, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(MediaKeySession, DOMEventTargetHelper)
MediaKeySession::MediaKeySession(nsPIDOMWindow* aParent,
MediaKeys* aKeys,
const nsAString& aKeySystem,
SessionType aSessionType)
: DOMEventTargetHelper(aParent)
, mKeys(aKeys)
, mKeySystem(aKeySystem)
, mSessionType(aSessionType)
, mIsClosed(false)
{
MOZ_ASSERT(aParent);
mClosed = mKeys->MakePromise();
}
void MediaKeySession::Init(const nsAString& aSessionId)
{
mSessionId = aSessionId;
}
MediaKeySession::~MediaKeySession()
{
}
MediaKeyError*
MediaKeySession::GetError() const
{
return mMediaKeyError;
}
void
MediaKeySession::GetKeySystem(nsString& aKeySystem) const
{
aKeySystem = mKeySystem;
}
void
MediaKeySession::GetSessionId(nsString& aSessionId) const
{
aSessionId = mSessionId;
}
JSObject*
MediaKeySession::WrapObject(JSContext* aCx)
{
return MediaKeySessionBinding::Wrap(aCx, this);
}
double
MediaKeySession::Expiration() const
{
return JS::GenericNaN();
}
Promise*
MediaKeySession::Closed() const
{
return mClosed;
}
already_AddRefed<Promise>
MediaKeySession::Update(const Uint8Array& aResponse)
{
nsRefPtr<Promise> promise(mKeys->MakePromise());
aResponse.ComputeLengthAndData();
if (IsClosed() ||
!mKeys->GetCDMProxy() ||
!aResponse.Length()) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return promise.forget();
}
mKeys->GetCDMProxy()->UpdateSession(mSessionId,
mKeys->StorePromise(promise),
aResponse);
return promise.forget();
}
already_AddRefed<Promise>
MediaKeySession::Close()
{
nsRefPtr<Promise> promise(mKeys->MakePromise());
if (IsClosed() || !mKeys->GetCDMProxy()) {
promise->MaybeResolve(JS::UndefinedHandleValue);
return promise.forget();
}
mKeys->GetCDMProxy()->CloseSession(mSessionId, mKeys->StorePromise(promise));
return promise.forget();
}
void
MediaKeySession::OnClosed()
{
if (IsClosed()) {
return;
}
mIsClosed = true;
// TODO: reset usableKeyIds
mKeys->OnSessionClosed(this);
mKeys = nullptr;
mClosed->MaybeResolve(JS::UndefinedHandleValue);
}
bool
MediaKeySession::IsClosed() const
{
return mIsClosed;
}
already_AddRefed<Promise>
MediaKeySession::Remove()
{
nsRefPtr<Promise> promise(mKeys->MakePromise());
if (mSessionType != SessionType::Persistent) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
// "The operation is not supported on session type sessions."
return promise.forget();
}
if (IsClosed() || !mKeys->GetCDMProxy()) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
// "The session is closed."
return promise.forget();
}
mKeys->GetCDMProxy()->RemoveSession(mSessionId, mKeys->StorePromise(promise));
return promise.forget();
}
void
MediaKeySession::DispatchKeyMessage(const nsTArray<uint8_t>& aMessage,
const nsString& aURL)
{
nsRefPtr<MediaKeyMessageEvent> event(
MediaKeyMessageEvent::Constructor(this, aURL, aMessage));
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, event);
asyncDispatcher->PostDOMEvent();
}
void
MediaKeySession::DispatchKeyError(uint32_t aSystemCode)
{
RefPtr<MediaKeyError> event(new MediaKeyError(this, aSystemCode));
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, event);
asyncDispatcher->PostDOMEvent();
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,93 @@
/* -*- 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_dom_MediaKeySession_h
#define mozilla_dom_MediaKeySession_h
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "nsCOMPtr.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/Mutex.h"
#include "mozilla/dom/Date.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/MediaKeySessionBinding.h"
#include "mozilla/dom/MediaKeysBinding.h"
struct JSContext;
namespace mozilla {
class CDMProxy;
namespace dom {
class MediaKeyError;
class MediaKeySession MOZ_FINAL : public DOMEventTargetHelper
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaKeySession,
DOMEventTargetHelper)
public:
MediaKeySession(nsPIDOMWindow* aParent,
MediaKeys* aKeys,
const nsAString& aKeySystem,
SessionType aSessionType);
void Init(const nsAString& aSessionId);
~MediaKeySession();
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// Mark this as resultNotAddRefed to return raw pointers
MediaKeyError* GetError() const;
void GetKeySystem(nsString& aRetval) const;
void GetSessionId(nsString& aRetval) const;
// Number of ms since epoch at which expiration occurs, or NaN if unknown.
// TODO: The type of this attribute is still under contention.
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=25902
double Expiration() const;
Promise* Closed() const;
already_AddRefed<Promise> Update(const Uint8Array& response);
already_AddRefed<Promise> Close();
already_AddRefed<Promise> Remove();
void DispatchKeyMessage(const nsTArray<uint8_t>& aMessage,
const nsString& aURL);
void DispatchKeyError(uint32_t system_code);
void OnClosed();
bool IsClosed() const;
private:
nsRefPtr<Promise> mClosed;
nsRefPtr<MediaKeyError> mMediaKeyError;
nsRefPtr<MediaKeys> mKeys;
const nsString mKeySystem;
nsString mSessionId;
const SessionType mSessionType;
bool mIsClosed;
};
} // namespace dom
} // namespace mozilla
#endif

Просмотреть файл

@ -0,0 +1,291 @@
/* -*- 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 "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/dom/MediaKeys.h"
#include "mozilla/dom/MediaKeysBinding.h"
#include "mozilla/dom/MediaKeyMessageEvent.h"
#include "mozilla/dom/MediaKeyError.h"
#include "mozilla/dom/MediaKeySession.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/CDMProxy.h"
#include "nsContentUtils.h"
#include "EMELog.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeys,
mParent,
mKeySessions,
mPromises,
mPendingSessions);
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeys)
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeys)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeys)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
MediaKeys::MediaKeys(nsPIDOMWindow* aParent, const nsAString& aKeySystem)
: mParent(aParent),
mKeySystem(aKeySystem)
{
SetIsDOMBinding();
}
MediaKeys::~MediaKeys()
{
if (mProxy) {
mProxy->Shutdown();
mProxy = nullptr;
}
}
nsPIDOMWindow*
MediaKeys::GetParentObject() const
{
return mParent;
}
JSObject*
MediaKeys::WrapObject(JSContext* aCx)
{
return MediaKeysBinding::Wrap(aCx, this);
}
void
MediaKeys::GetKeySystem(nsString& retval) const
{
retval = mKeySystem;
}
already_AddRefed<Promise>
MediaKeys::SetServerCertificate(const Uint8Array& aCert)
{
aCert.ComputeLengthAndData();
nsRefPtr<Promise> promise(MakePromise());
mProxy->SetServerCertificate(StorePromise(promise), aCert);
return promise.forget();
}
/* static */
IsTypeSupportedResult
MediaKeys::IsTypeSupported(const GlobalObject& aGlobal,
const nsAString& aKeySystem,
const Optional<nsAString>& aInitDataType,
const Optional<nsAString>& aContentType,
const Optional<nsAString>& aCapability)
{
// TODO: Query list of known CDMs and their supported content types.
// TODO: Should really get spec changed to this is async, so we can wait
// for user to consent to running plugin.
return IsTypeSupportedResult::Maybe;
}
already_AddRefed<Promise>
MediaKeys::MakePromise()
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
NS_WARNING("Passed non-global to MediaKeys ctor!");
return nullptr;
}
nsRefPtr<Promise> promise = new Promise(global);
return promise.forget();
}
PromiseId
MediaKeys::StorePromise(Promise* aPromise)
{
static uint32_t sEMEPromiseCount = 1;
MOZ_ASSERT(aPromise);
uint32_t id = sEMEPromiseCount++;
mPromises.Put(id, aPromise);
return id;
}
already_AddRefed<Promise>
MediaKeys::RetrievePromise(PromiseId aId)
{
nsRefPtr<Promise> promise;
mPromises.Remove(aId, getter_AddRefs(promise));
return promise.forget();
}
void
MediaKeys::RejectPromise(PromiseId aId, nsresult aExceptionCode)
{
nsRefPtr<Promise> promise(RetrievePromise(aId));
if (!promise) {
NS_WARNING("MediaKeys tried to reject a non-existent promise");
return;
}
if (mPendingSessions.Contains(aId)) {
// This promise could be a createSession or loadSession promise,
// so we might have a pending session waiting to be resolved into
// the promise on success. We've been directed to reject to promise,
// so we can throw away the corresponding session object.
mPendingSessions.Remove(aId);
}
MOZ_ASSERT(NS_FAILED(aExceptionCode));
promise->MaybeReject(aExceptionCode);
}
void
MediaKeys::ResolvePromise(PromiseId aId)
{
nsRefPtr<Promise> promise(RetrievePromise(aId));
if (!promise) {
NS_WARNING("MediaKeys tried to resolve a non-existent promise");
return;
}
// We should not resolve CreateSession or LoadSession calls via this path,
// OnSessionActivated() should be called instead.
MOZ_ASSERT(!mPendingSessions.Contains(aId));
promise->MaybeResolve(JS::UndefinedHandleValue);
}
/* static */
already_AddRefed<Promise>
MediaKeys::Create(const GlobalObject& aGlobal,
const nsAString& aKeySystem,
ErrorResult& aRv)
{
// CDMProxy keeps MediaKeys alive until it resolves the promise and thus
// returns the MediaKeys object to JS.
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
if (!window) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<MediaKeys> keys = new MediaKeys(window, aKeySystem);
nsRefPtr<Promise> promise(keys->MakePromise());
if (!promise) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
if (!aKeySystem.EqualsASCII("org.w3.clearkey")) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
keys->mProxy = new CDMProxy(keys, aKeySystem);
keys->mProxy->Init(keys->StorePromise(promise));
return promise.forget();
}
void
MediaKeys::OnCDMCreated(PromiseId aId)
{
nsRefPtr<Promise> promise(RetrievePromise(aId));
if (!promise) {
NS_WARNING("MediaKeys tried to resolve a non-existent promise");
return;
}
nsRefPtr<MediaKeys> keys(this);
promise->MaybeResolve(keys);
}
already_AddRefed<Promise>
MediaKeys::LoadSession(const nsAString& aSessionId)
{
nsRefPtr<Promise> promise(MakePromise());
if (aSessionId.IsEmpty()) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
// "The sessionId parameter is empty."
return promise.forget();
}
// TODO: The spec doesn't specify what to do in this case...
if (mKeySessions.Contains(aSessionId)) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return promise.forget();
}
// Create session.
nsRefPtr<MediaKeySession> session(
new MediaKeySession(GetParentObject(), this, mKeySystem, SessionType::Persistent));
// Proxy owns session object until resolving promise.
mProxy->LoadSession(StorePromise(promise),
aSessionId);
return promise.forget();
}
already_AddRefed<Promise>
MediaKeys::CreateSession(const nsAString& initDataType,
const Uint8Array& aInitData,
SessionType aSessionType)
{
aInitData.ComputeLengthAndData();
nsRefPtr<Promise> promise(MakePromise());
nsRefPtr<MediaKeySession> session = new MediaKeySession(GetParentObject(),
this,
mKeySystem,
aSessionType);
auto pid = StorePromise(promise);
// Hang onto session until the CDM has finished setting it up.
mPendingSessions.Put(pid, session);
mProxy->CreateSession(aSessionType,
pid,
initDataType,
aInitData);
return promise.forget();
}
void
MediaKeys::OnSessionActivated(PromiseId aId, const nsAString& aSessionId)
{
nsRefPtr<Promise> promise(RetrievePromise(aId));
if (!promise) {
NS_WARNING("MediaKeys tried to resolve a non-existent promise");
return;
}
MOZ_ASSERT(mPendingSessions.Contains(aId));
nsRefPtr<MediaKeySession> session;
if (!mPendingSessions.Get(aId, getter_AddRefs(session)) || !session) {
NS_WARNING("Received activation for non-existent session!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
// Session has completed creation/loading, remove it from mPendingSessions,
// and resolve the promise with it. We store it in mKeySessions, so we can
// find it again if we need to send messages to it etc.
mPendingSessions.Remove(aId);
session->Init(aSessionId);
mKeySessions.Put(aSessionId, session);
promise->MaybeResolve(session);
}
void
MediaKeys::OnSessionClosed(MediaKeySession* aSession)
{
nsAutoString id;
aSession->GetSessionId(id);
mKeySessions.Remove(id);
}
already_AddRefed<MediaKeySession>
MediaKeys::GetSession(const nsAString& aSessionId)
{
nsRefPtr<MediaKeySession> session;
mKeySessions.Get(aSessionId, getter_AddRefs(session));
return session.forget();
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,120 @@
/* -*- 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_dom_mediakeys_h__
#define mozilla_dom_mediakeys_h__
#include "nsIDOMMediaError.h"
#include "nsWrapperCache.h"
#include "nsISupports.h"
#include "mozilla/Attributes.h"
#include "mozilla/RefPtr.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsRefPtrHashtable.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/MediaKeysBinding.h"
namespace mozilla {
class CDMProxy;
namespace dom {
class MediaKeySession;
typedef nsRefPtrHashtable<nsStringHashKey, MediaKeySession> KeySessionHashMap;
typedef nsRefPtrHashtable<nsUint32HashKey, dom::Promise> PromiseHashMap;
typedef nsRefPtrHashtable<nsUint32HashKey, MediaKeySession> PendingKeySessionsHashMap;
typedef uint32_t PromiseId;
// This class is used on the main thread only.
// Note: it's addref/release is not (and can't be) thread safe!
class MediaKeys MOZ_FINAL : public nsISupports,
public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeys)
MediaKeys(nsPIDOMWindow* aParentWindow, const nsAString& aKeySystem);
~MediaKeys();
nsPIDOMWindow* GetParentObject() const;
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// Javascript: readonly attribute DOMString keySystem;
void GetKeySystem(nsString& retval) const;
// JavaScript: MediaKeys.createSession()
already_AddRefed<Promise> CreateSession(const nsAString& aInitDataType,
const Uint8Array& aInitData,
SessionType aSessionType);
// JavaScript: MediaKeys.loadSession()
already_AddRefed<Promise> LoadSession(const nsAString& aSessionId);
// JavaScript: MediaKeys.SetServerCertificate()
already_AddRefed<Promise> SetServerCertificate(const Uint8Array& aServerCertificate);
// JavaScript: MediaKeys.create()
static
already_AddRefed<Promise> Create(const GlobalObject& aGlobal,
const nsAString& aKeySystem,
ErrorResult& aRv);
// JavaScript: MediaKeys.IsTypeSupported()
static IsTypeSupportedResult IsTypeSupported(const GlobalObject& aGlobal,
const nsAString& aKeySystem,
const Optional<nsAString>& aInitDataType,
const Optional<nsAString>& aContentType,
const Optional<nsAString>& aCapability);
already_AddRefed<MediaKeySession> GetSession(const nsAString& aSessionId);
// Called once a Create() operation succeeds.
void OnCDMCreated(PromiseId aId);
// Called once a CreateSession or LoadSession succeeds.
void OnSessionActivated(PromiseId aId, const nsAString& aSessionId);
// Called once a session has closed.
void OnSessionClosed(MediaKeySession* aSession);
CDMProxy* GetCDMProxy() { return mProxy; }
// Makes a new promise, or nullptr on failure.
already_AddRefed<Promise> MakePromise();
// Stores promise in mPromises, returning an ID that can be used to retrieve
// it later. The ID is passed to the CDM, so that it can signal specific
// promises to be resolved.
PromiseId StorePromise(Promise* aPromise);
// Reject promise with DOMException corresponding to aExceptionCode.
void RejectPromise(PromiseId aId, nsresult aExceptionCode);
// Resolves promise with "undefined".
void ResolvePromise(PromiseId aId);
private:
// Removes promise from mPromises, and returns it.
already_AddRefed<Promise> RetrievePromise(PromiseId aId);
// Owning ref to proxy. The proxy has a weak reference back to the MediaKeys,
// and the MediaKeys destructor clears the proxy's reference to the MediaKeys.
nsRefPtr<CDMProxy> mProxy;
nsCOMPtr<nsPIDOMWindow> mParent;
nsString mKeySystem;
KeySessionHashMap mKeySessions;
PromiseHashMap mPromises;
PendingKeySessionsHashMap mPendingSessions;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_mediakeys_h__

Просмотреть файл

@ -0,0 +1,31 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.dom += [
'MediaKeyError.h',
'MediaKeyMessageEvent.h',
'MediaKeyNeededEvent.h',
'MediaKeys.h',
'MediaKeySession.h',
]
EXPORTS.mozilla += [
'CDMProxy.h',
]
UNIFIED_SOURCES += [
'CDMProxy.cpp',
'EMELog.cpp',
'MediaKeyError.cpp',
'MediaKeyMessageEvent.cpp',
'MediaKeyNeededEvent.cpp',
'MediaKeys.cpp',
'MediaKeySession.cpp',
]
FINAL_LIBRARY = 'gklayout'
FAIL_ON_WARNINGS = True

Просмотреть файл

@ -246,6 +246,9 @@ TEST(VP8VideoTrackEncoder, FetchMetaData)
} }
// Encode test // Encode test
// XXX(bug 1018402): Disable this test when compiled with VS2013 because it
// crashes.
#if !defined(_MSC_VER) || _MSC_VER < 1800
TEST(VP8VideoTrackEncoder, FrameEncode) TEST(VP8VideoTrackEncoder, FrameEncode)
{ {
// Initiate VP8 encoder // Initiate VP8 encoder
@ -275,6 +278,7 @@ TEST(VP8VideoTrackEncoder, FrameEncode)
EncodedFrameContainer container; EncodedFrameContainer container;
EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container))); EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
} }
#endif // _MSC_VER
// EOS test // EOS test
TEST(VP8VideoTrackEncoder, EncodeComplete) TEST(VP8VideoTrackEncoder, EncodeComplete)

Просмотреть файл

@ -50,6 +50,8 @@ if CONFIG['MOZ_OMX_DECODER']:
PARALLEL_DIRS += ['webspeech'] PARALLEL_DIRS += ['webspeech']
PARALLEL_DIRS += ['eme']
TEST_DIRS += [ TEST_DIRS += [
'test', 'test',
'gtest', 'gtest',

Просмотреть файл

@ -300,25 +300,20 @@ support-files =
[test_audio1.html] [test_audio1.html]
[test_audio2.html] [test_audio2.html]
[test_audioDocumentTitle.html] [test_audioDocumentTitle.html]
skip-if = true # bug 475110 skip-if = true # bug 475110 - disabled since we don't play Wave files standalone
[test_autoplay.html] [test_autoplay.html]
[test_autoplay_contentEditable.html] [test_autoplay_contentEditable.html]
skip-if = buildapp == 'b2g' # bug 899074 - timeouts
[test_buffered.html] [test_buffered.html]
skip-if = toolkit == 'android' || os == "win" || (toolkit == 'gonk' && !debug) # See bug 832768 and 864682, b2g(assertion failures)
[test_bug448534.html] [test_bug448534.html]
skip-if = buildapp == 'b2g' # b2g(Timed out, bug 894922? Bug 902677 is for the timing out of a lot of media tests) skip-if = os == 'win' # bug 894922
[test_bug463162.xhtml] [test_bug463162.xhtml]
[test_bug465498.html] [test_bug465498.html]
skip-if = os == "win" || (toolkit == 'gonk' && !debug) # See bug 832768 and 864682
[test_bug493187.html] [test_bug493187.html]
skip-if = os == "win" || (toolkit == 'gonk' && !debug) # See bug 707777
[test_bug495145.html] [test_bug495145.html]
[test_bug495300.html] [test_bug495300.html]
[test_bug654550.html] [test_bug654550.html]
[test_bug686942.html] [test_bug686942.html]
[test_bug726904.html] [test_bug726904.html]
skip-if = true # bug 754860
[test_bug874897.html] [test_bug874897.html]
[test_bug883173.html] [test_bug883173.html]
[test_bug895091.html] [test_bug895091.html]
@ -327,12 +322,11 @@ skip-if = true # bug 754860
[test_bug957847.html] [test_bug957847.html]
[test_can_play_type.html] [test_can_play_type.html]
[test_can_play_type_mpeg.html] [test_can_play_type_mpeg.html]
skip-if = buildapp == 'b2g' # b2g(7 failures out of 27) skip-if = buildapp == 'b2g' # bug 1021675
[test_can_play_type_no_ogg.html] [test_can_play_type_no_ogg.html]
[test_can_play_type_ogg.html] [test_can_play_type_ogg.html]
skip-if = buildapp == 'b2g' || e10s skip-if = buildapp == 'b2g' || e10s # b2g(bug 1021675)
[test_chaining.html] [test_chaining.html]
skip-if = buildapp == 'b2g' # timeouts
[test_clone_media_element.html] [test_clone_media_element.html]
[test_closing_connections.html] [test_closing_connections.html]
[test_constants.html] [test_constants.html]
@ -349,13 +343,11 @@ skip-if = buildapp == 'b2g' # timeouts
[test_decoder_disable.html] [test_decoder_disable.html]
[test_defaultMuted.html] [test_defaultMuted.html]
[test_delay_load.html] [test_delay_load.html]
skip-if = buildapp == 'b2g' # b2g(6 failures) skip-if = buildapp == 'b2g' # bug 1021676
[test_error_in_video_document.html] [test_error_in_video_document.html]
skip-if = true # bug 608634
[test_error_on_404.html] [test_error_on_404.html]
[test_fastSeek.html] [test_fastSeek.html]
[test_info_leak.html] [test_info_leak.html]
skip-if = buildapp == 'b2g' # b2g(2 failures)
[test_invalid_reject.html] [test_invalid_reject.html]
[test_load.html] [test_load.html]
[test_load_candidates.html] [test_load_candidates.html]
@ -363,18 +355,18 @@ skip-if = buildapp == 'b2g' # b2g(2 failures)
[test_load_source.html] [test_load_source.html]
[test_loop.html] [test_loop.html]
[test_media_selection.html] [test_media_selection.html]
skip-if = os == "win" || (toolkit == 'gonk' && !debug) # See bug 897843, b2g(timed out) skip-if = toolkit == 'gonk' && !debug # bug 1021677
[test_media_sniffer.html] [test_media_sniffer.html]
[test_mediarecorder_avoid_recursion.html] [test_mediarecorder_avoid_recursion.html]
[test_mediarecorder_creation.html] [test_mediarecorder_creation.html]
[test_mediarecorder_creation_fail.html] [test_mediarecorder_creation_fail.html]
[test_mediarecorder_getencodeddata.html] [test_mediarecorder_getencodeddata.html]
[test_mediarecorder_record_4ch_audiocontext.html] [test_mediarecorder_record_4ch_audiocontext.html]
skip-if = (toolkit == 'gonk' && !debug) skip-if = toolkit == 'gonk' && !debug # bug 1021678
[test_mediarecorder_record_audiocontext.html] [test_mediarecorder_record_audiocontext.html]
[test_mediarecorder_record_audiocontext_mlk.html] [test_mediarecorder_record_audiocontext_mlk.html]
[test_mediarecorder_record_gum_video_timeslice.html] [test_mediarecorder_record_gum_video_timeslice.html]
skip-if = buildapp == 'b2g' || (toolkit == 'android') # mimetype check, bug 969289 skip-if = buildapp == 'b2g' || toolkit == 'android' # mimetype check, bug 969289
[test_mediarecorder_record_immediate_stop.html] [test_mediarecorder_record_immediate_stop.html]
[test_mediarecorder_record_no_timeslice.html] [test_mediarecorder_record_no_timeslice.html]
[test_mediarecorder_record_nosrc.html] [test_mediarecorder_record_nosrc.html]
@ -386,7 +378,7 @@ skip-if = buildapp == 'b2g' || (toolkit == 'android') # mimetype check, bug 9692
[test_mediarecorder_unsupported_src.html] [test_mediarecorder_unsupported_src.html]
[test_metadata.html] [test_metadata.html]
[test_mixed_principals.html] [test_mixed_principals.html]
skip-if = true # bug 567954 and 574586 skip-if = (os == 'linux' && debug) || (toolkit == 'android' && debug) || toolkit == 'gonk' # bug 567954 and intermittent leaks
[test_mozHasAudio.html] [test_mozHasAudio.html]
[test_networkState.html] [test_networkState.html]
[test_new_audio.html] [test_new_audio.html]
@ -402,13 +394,14 @@ skip-if = appname == "seamonkey" || toolkit == 'gonk' || toolkit == 'android'
skip-if = buildapp == 'b2g' || toolkit == 'android' # Disabled on Android & B2G due to bug 668973 skip-if = buildapp == 'b2g' || toolkit == 'android' # Disabled on Android & B2G due to bug 668973
[test_playback_errors.html] [test_playback_errors.html]
[test_playback_rate.html] [test_playback_rate.html]
# Win: Bug 814533, B2G & Android Debug: Bug 1020538 # Win: Bug 814533, B2G & Android Debug: Bug 1020538, see assertion annotations in test also
skip-if = os == 'win' || buildapp == 'b2g' || (toolkit == 'android' && debug) skip-if = os == 'win' || buildapp == 'b2g' || (toolkit == 'android' && debug)
[test_playback_rate_playpause.html] [test_playback_rate_playpause.html]
skip-if = true # bug 897108 skip-if = os == 'linux' || os == 'win' # bug 897108, see assertion annotations in test also
[test_played.html] [test_played.html]
skip-if = true # bug 751539 skip-if = true # bug 1021794
[test_preload_actions.html] [test_preload_actions.html]
skip-if = toolkit == 'android' # bug 886188
[test_preload_attribute.html] [test_preload_attribute.html]
[test_preload_suspend.html] [test_preload_suspend.html]
skip-if = true # bug 493692 skip-if = true # bug 493692
@ -420,15 +413,13 @@ skip-if = true # bug 493692
[test_reset_events_async.html] [test_reset_events_async.html]
[test_reset_src.html] [test_reset_src.html]
[test_resume.html] [test_resume.html]
skip-if = true # disabled - No bug :-( skip-if = true # bug 1021673
[test_seek_out_of_range.html] [test_seek_out_of_range.html]
[test_seek.html] [test_seek.html]
skip-if = toolkit == 'android' || (toolkit == 'gonk' && !debug) # See bug 832678, 795271, and 857424 # android(bug 845162) androidx86(bug 845162)
[test_seek2.html] [test_seek2.html]
[test_seekable1.html] [test_seekable1.html]
[test_seekable2.html] [test_seekable2.html]
[test_seekable3.html] [test_seekable3.html]
skip-if = buildapp == 'b2g' # timeouts
[test_seekLies.html] [test_seekLies.html]
[test_source.html] [test_source.html]
[test_source_media.html] [test_source_media.html]
@ -442,7 +433,7 @@ skip-if = buildapp == 'b2g' # timeouts
[test_streams_element_capture_reset.html] [test_streams_element_capture_reset.html]
skip-if = buildapp == 'b2g' # bug 901102 skip-if = buildapp == 'b2g' # bug 901102
[test_streams_gc.html] [test_streams_gc.html]
skip-if = buildapp == 'b2g' # Value being assigned to HTMLMediaElement.currentTime is not a finite floating-point value skip-if = buildapp == 'b2g' # bug 1021682
[test_streams_srcObject.html] [test_streams_srcObject.html]
[test_streams_tracks.html] [test_streams_tracks.html]
[test_texttrack.html] [test_texttrack.html]
@ -453,10 +444,8 @@ skip-if = buildapp == 'b2g' # Value being assigned to HTMLMediaElement.currentTi
[test_trackelementevent.html] [test_trackelementevent.html]
[test_trackevent.html] [test_trackevent.html]
[test_unseekable.html] [test_unseekable.html]
skip-if = buildapp == 'b2g'
[test_video_to_canvas.html] [test_video_to_canvas.html]
[test_videoDocumentTitle.html] [test_videoDocumentTitle.html]
skip-if = true # bug 492821
[test_VideoPlaybackQuality.html] [test_VideoPlaybackQuality.html]
[test_VideoPlaybackQuality_disabled.html] [test_VideoPlaybackQuality_disabled.html]
[test_volume.html] [test_volume.html]

Просмотреть файл

@ -21,8 +21,6 @@
SimpleTest.expectAssertions(5, 9); SimpleTest.expectAssertions(5, 9);
if (navigator.platform.startsWith("Win")) { if (navigator.platform.startsWith("Win")) {
SimpleTest.expectAssertions(4, 5); SimpleTest.expectAssertions(4, 5);
} else if (navigator.platform.startsWith("Mac")) {
SimpleTest.expectAssertions(5, 7);
} }
let manager = new MediaTestManager; let manager = new MediaTestManager;

Просмотреть файл

@ -10,13 +10,16 @@
<pre id="test"> <pre id="test">
<script class="testbody" type='application/javascript;version=1.8'> <script class="testbody" type='application/javascript;version=1.8'>
// In varying quantities:
// ASSERTION: Clock should go forwards if the playback rate is > 0.:
// 'mCurrentFrameTime <= clock_time || mPlaybackRate <= 0',
// file MediaDecoderStateMachine.cpp, line 2379
if (navigator.platform.startsWith("Win")) { if (navigator.platform.startsWith("Win")) {
SimpleTest.expectAssertions(0, 1); SimpleTest.expectAssertions(1, 6);
} else if (navigator.platform.startsWith("Mac")) { } else if (navigator.platform.startsWith("Mac")) {
SimpleTest.expectAssertions(0, 2); SimpleTest.expectAssertions(3, 7);
} else if (navigator.platform.startsWith("Linux")) { } else if (navigator.platform.startsWith("Linux arm")) {
// Bug 897024 SimpleTest.expectAssertions(4, 11);
SimpleTest.expectAssertions(0, 2);
} }
let manager = new MediaTestManager; let manager = new MediaTestManager;

Просмотреть файл

@ -43,7 +43,7 @@ private:
uint32_t mChunkSize; uint32_t mChunkSize;
// chunking to 10ms support // chunking to 10ms support
nsAutoPtr<FarEndAudioChunk> mSaved; FarEndAudioChunk *mSaved; // can't be nsAutoPtr since we need to use moz_free()
uint32_t mSamplesSaved; uint32_t mSamplesSaved;
}; };

Просмотреть файл

@ -54,6 +54,7 @@ AudioOutputObserver::AudioOutputObserver()
: mPlayoutFreq(0) : mPlayoutFreq(0)
, mPlayoutChannels(0) , mPlayoutChannels(0)
, mChunkSize(0) , mChunkSize(0)
, mSaved(nullptr)
, mSamplesSaved(0) , mSamplesSaved(0)
{ {
// Buffers of 10ms chunks // Buffers of 10ms chunks
@ -69,8 +70,9 @@ void
AudioOutputObserver::Clear() AudioOutputObserver::Clear()
{ {
while (mPlayoutFifo->size() > 0) { while (mPlayoutFifo->size() > 0) {
(void) mPlayoutFifo->Pop(); moz_free(mPlayoutFifo->Pop());
} }
moz_free(mSaved);
mSaved = nullptr; mSaved = nullptr;
} }
@ -154,7 +156,8 @@ AudioOutputObserver::InsertFarEnd(const AudioDataValue *aBuffer, uint32_t aSampl
// thread safety issues. // thread safety issues.
break; break;
} else { } else {
mPlayoutFifo->Push((int8_t *) mSaved.forget()); // takes ownership mPlayoutFifo->Push((int8_t *) mSaved); // takes ownership
mSaved = nullptr;
mSamplesSaved = 0; mSamplesSaved = 0;
} }
} }
@ -517,8 +520,7 @@ MediaEngineWebRTCAudioSource::Process(int channel,
if (!mStarted) { if (!mStarted) {
mStarted = true; mStarted = true;
while (gFarendObserver->Size() > 1) { while (gFarendObserver->Size() > 1) {
FarEndAudioChunk *buffer = gFarendObserver->Pop(); // only call if size() > 0 moz_free(gFarendObserver->Pop()); // only call if size() > 0
free(buffer);
} }
} }
@ -526,15 +528,16 @@ MediaEngineWebRTCAudioSource::Process(int channel,
FarEndAudioChunk *buffer = gFarendObserver->Pop(); // only call if size() > 0 FarEndAudioChunk *buffer = gFarendObserver->Pop(); // only call if size() > 0
if (buffer) { if (buffer) {
int length = buffer->mSamples; int length = buffer->mSamples;
if (mVoERender->ExternalPlayoutData(buffer->mData, int res = mVoERender->ExternalPlayoutData(buffer->mData,
gFarendObserver->PlayoutFrequency(), gFarendObserver->PlayoutFrequency(),
gFarendObserver->PlayoutChannels(), gFarendObserver->PlayoutChannels(),
mPlayoutDelay, mPlayoutDelay,
length) == -1) { length);
moz_free(buffer);
if (res == -1) {
return; return;
} }
} }
free(buffer);
} }
#ifdef PR_LOGGING #ifdef PR_LOGGING

Просмотреть файл

@ -83,3 +83,4 @@ skip-if = toolkit == "gtk2"
[test_principalInherit.xul] [test_principalInherit.xul]
[test_private_hidden_window.html] [test_private_hidden_window.html]
[test_viewsource_forbidden_in_iframe.xul] [test_viewsource_forbidden_in_iframe.xul]
skip-if = true # bug 1019315

Просмотреть файл

@ -163,7 +163,7 @@ this.PermissionsTable = { geolocation: {
}, },
attention: { attention: {
app: DENY_ACTION, app: DENY_ACTION,
privileged: DENY_ACTION, privileged: ALLOW_ACTION,
certified: ALLOW_ACTION certified: ALLOW_ACTION
}, },
"webapps-manage": { "webapps-manage": {
@ -298,7 +298,7 @@ this.PermissionsTable = { geolocation: {
"audio-capture": { "audio-capture": {
app: PROMPT_ACTION, app: PROMPT_ACTION,
privileged: PROMPT_ACTION, privileged: PROMPT_ACTION,
certified: PROMPT_ACTION certified: ALLOW_ACTION
}, },
"nfc": { "nfc": {
app: DENY_ACTION, app: DENY_ACTION,
@ -324,7 +324,7 @@ this.PermissionsTable = { geolocation: {
"video-capture": { "video-capture": {
app: PROMPT_ACTION, app: PROMPT_ACTION,
privileged: PROMPT_ACTION, privileged: PROMPT_ACTION,
certified: PROMPT_ACTION certified: ALLOW_ACTION
}, },
"feature-detection": { "feature-detection": {
app: DENY_ACTION, app: DENY_ACTION,

Просмотреть файл

@ -948,9 +948,12 @@ this.DOMApplicationRegistry = {
delete this.webapps[aResult.id]; delete this.webapps[aResult.id];
return; return;
} }
app.name = manifest.name;
let localeManifest = new ManifestHelper(manifest, app.origin);
app.name = localeManifest.name;
app.csp = manifest.csp || ""; app.csp = manifest.csp || "";
app.role = manifest.role || ""; app.role = localeManifest.role;
if (app.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) { if (app.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
app.redirects = this.sanitizeRedirects(manifest.redirects); app.redirects = this.sanitizeRedirects(manifest.redirects);
} }
@ -1333,12 +1336,12 @@ this.DOMApplicationRegistry = {
let app = this.webapps[id]; let app = this.webapps[id];
if (!app) { if (!app) {
debug("startDownload: No app found for " + aManifestURL); debug("startDownload: No app found for " + aManifestURL);
return; throw new Error("NO_SUCH_APP");
} }
if (app.downloading) { if (app.downloading) {
debug("app is already downloading. Ignoring."); debug("app is already downloading. Ignoring.");
return; throw new Error("APP_IS_DOWNLOADING");
} }
// If the caller is trying to start a download but we have nothing to // If the caller is trying to start a download but we have nothing to
@ -1352,7 +1355,7 @@ this.DOMApplicationRegistry = {
eventType: "downloaderror", eventType: "downloaderror",
manifestURL: app.manifestURL manifestURL: app.manifestURL
}); });
return; throw new Error("NO_DOWNLOAD_AVAILABLE");
} }
// First of all, we check if the download is supposed to update an // First of all, we check if the download is supposed to update an
@ -1409,7 +1412,7 @@ this.DOMApplicationRegistry = {
if (!json) { if (!json) {
debug("startDownload: No update manifest found at " + file.path + " " + debug("startDownload: No update manifest found at " + file.path + " " +
aManifestURL); aManifestURL);
return; throw new Error("MISSING_UPDATE_MANIFEST");
} }
let manifest = new ManifestHelper(json, app.manifestURL); let manifest = new ManifestHelper(json, app.manifestURL);
@ -1450,104 +1453,103 @@ this.DOMApplicationRegistry = {
} }
}), }),
applyDownload: function applyDownload(aManifestURL) { applyDownload: Task.async(function*(aManifestURL) {
debug("applyDownload for " + aManifestURL); debug("applyDownload for " + aManifestURL);
let id = this._appIdForManifestURL(aManifestURL); let id = this._appIdForManifestURL(aManifestURL);
let app = this.webapps[id]; let app = this.webapps[id];
if (!app || (app && !app.readyToApplyDownload)) { if (!app) {
return; throw new Error("NO_SUCH_APP");
}
if (!app.readyToApplyDownload) {
throw new Error("NOT_READY_TO_APPLY_DOWNLOAD");
} }
// We need to get the old manifest to unregister web activities. // We need to get the old manifest to unregister web activities.
this.getManifestFor(aManifestURL).then((aOldManifest) => { let oldManifest = yield this.getManifestFor(aManifestURL);
// Move the application.zip and manifest.webapp files out of TmpD // Move the application.zip and manifest.webapp files out of TmpD
let tmpDir = FileUtils.getDir("TmpD", ["webapps", id], true, true); let tmpDir = FileUtils.getDir("TmpD", ["webapps", id], true, true);
let manFile = tmpDir.clone(); let manFile = tmpDir.clone();
manFile.append("manifest.webapp"); manFile.append("manifest.webapp");
let appFile = tmpDir.clone(); let appFile = tmpDir.clone();
appFile.append("application.zip"); appFile.append("application.zip");
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true); let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
appFile.moveTo(dir, "application.zip"); appFile.moveTo(dir, "application.zip");
manFile.moveTo(dir, "manifest.webapp"); manFile.moveTo(dir, "manifest.webapp");
// Move the staged update manifest to a non staged one. // Move the staged update manifest to a non staged one.
let staged = dir.clone(); let staged = dir.clone();
staged.append("staged-update.webapp"); staged.append("staged-update.webapp");
// If we are applying after a restarted download, we have no // If we are applying after a restarted download, we have no
// staged update manifest. // staged update manifest.
if (staged.exists()) { if (staged.exists()) {
staged.moveTo(dir, "update.webapp"); staged.moveTo(dir, "update.webapp");
}
try {
tmpDir.remove(true);
} catch(e) { }
// Clean up the deprecated manifest cache if needed.
if (id in this._manifestCache) {
delete this._manifestCache[id];
}
// Flush the zip reader cache to make sure we use the new application.zip
// when re-launching the application.
let zipFile = dir.clone();
zipFile.append("application.zip");
Services.obs.notifyObservers(zipFile, "flush-cache-entry", null);
// Get the manifest, and set properties.
let newManifest = yield this.getManifestFor(aManifestURL);
app.downloading = false;
app.downloadAvailable = false;
app.downloadSize = 0;
app.installState = "installed";
app.readyToApplyDownload = false;
// Update the staged properties.
if (app.staged) {
for (let prop in app.staged) {
app[prop] = app.staged[prop];
} }
delete app.staged;
}
try { delete app.retryingDownload;
tmpDir.remove(true);
} catch(e) { }
// Clean up the deprecated manifest cache if needed. // Update the asm.js scripts we need to compile.
if (id in this._manifestCache) { yield ScriptPreloader.preload(app, newManifest);
delete this._manifestCache[id]; yield this._saveApps();
} // Update the handlers and permissions for this app.
this.updateAppHandlers(oldManifest, newManifest, app);
// Flush the zip reader cache to make sure we use the new application.zip let updateManifest = yield AppsUtils.loadJSONAsync(staged.path);
// when re-launching the application. let appObject = AppsUtils.cloneAppObject(app);
let zipFile = dir.clone(); appObject.updateManifest = updateManifest;
zipFile.append("application.zip"); this.notifyUpdateHandlers(appObject, newManifest, appFile.path);
Services.obs.notifyObservers(zipFile, "flush-cache-entry", null);
// Get the manifest, and set properties. if (supportUseCurrentProfile()) {
this.getManifestFor(aManifestURL).then((aData) => { PermissionsInstaller.installPermissions(
app.downloading = false; { manifest: newManifest,
app.downloadAvailable = false; origin: app.origin,
app.downloadSize = 0; manifestURL: app.manifestURL },
app.installState = "installed"; true);
app.readyToApplyDownload = false; }
this.updateDataStore(this.webapps[id].localId, app.origin,
// Update the staged properties. app.manifestURL, newManifest, app.appStatus);
if (app.staged) { this.broadcastMessage("Webapps:UpdateState", {
for (let prop in app.staged) { app: app,
app[prop] = app.staged[prop]; manifest: newManifest,
} manifestURL: app.manifestURL
delete app.staged;
}
delete app.retryingDownload;
// Update the asm.js scripts we need to compile.
ScriptPreloader.preload(app, aData)
.then(() => this._saveApps()).then(() => {
// Update the handlers and permissions for this app.
this.updateAppHandlers(aOldManifest, aData, app);
AppsUtils.loadJSONAsync(staged.path).then((aUpdateManifest) => {
let appObject = AppsUtils.cloneAppObject(app);
appObject.updateManifest = aUpdateManifest;
this.notifyUpdateHandlers(appObject, aData, appFile.path);
});
if (supportUseCurrentProfile()) {
PermissionsInstaller.installPermissions(
{ manifest: aData,
origin: app.origin,
manifestURL: app.manifestURL },
true);
}
this.updateDataStore(this.webapps[id].localId, app.origin,
app.manifestURL, aData, app.appStatus);
this.broadcastMessage("Webapps:UpdateState", {
app: app,
manifest: aData,
manifestURL: app.manifestURL
});
this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadapplied",
manifestURL: app.manifestURL
});
});
});
}); });
}, this.broadcastMessage("Webapps:FireEvent", {
eventType: "downloadapplied",
manifestURL: app.manifestURL
});
}),
startOfflineCacheDownload: function(aManifest, aApp, aProfileDir, aIsUpdate) { startOfflineCacheDownload: function(aManifest, aApp, aProfileDir, aIsUpdate) {
if (!aManifest.appcache_path) { if (!aManifest.appcache_path) {
@ -2773,9 +2775,11 @@ this.DOMApplicationRegistry = {
if (oldPackage) { if (oldPackage) {
debug("package's etag or hash unchanged; sending 'applied' event"); debug("package's etag or hash unchanged; sending 'applied' event");
// The package's Etag or hash has not changed. // The package's Etag or hash has not changed.
// We send a "applied" event right away. // We send an "applied" event right away so code awaiting that event
// can proceed to access the app. We also throw an error to alert
// the caller that the package wasn't downloaded.
this._sendAppliedEvent(aNewApp, oldApp, id); this._sendAppliedEvent(aNewApp, oldApp, id);
return; throw new Error("PACKAGE_UNCHANGED");
} }
let newManifest = yield this._openAndReadPackage(zipFile, oldApp, aNewApp, let newManifest = yield this._openAndReadPackage(zipFile, oldApp, aNewApp,
@ -3488,6 +3492,8 @@ this.DOMApplicationRegistry = {
}); });
}); });
AppDownloadManager.remove(aNewApp.manifestURL); AppDownloadManager.remove(aNewApp.manifestURL);
throw aError;
}, },
doUninstall: function(aData, aMm) { doUninstall: function(aData, aMm) {

Просмотреть файл

@ -798,7 +798,7 @@ Navigator::Vibrate(const nsTArray<uint32_t>& aPattern)
nsTArray<uint32_t> pattern(aPattern); nsTArray<uint32_t> pattern(aPattern);
if (pattern.Length() > sMaxVibrateListLen) { if (pattern.Length() > sMaxVibrateListLen) {
pattern.SetLength(sMaxVibrateMS); pattern.SetLength(sMaxVibrateListLen);
} }
for (size_t i = 0; i < pattern.Length(); ++i) { for (size_t i = 0; i < pattern.Length(); ++i) {

Просмотреть файл

@ -33,7 +33,6 @@ public:
{ {
switch (mHash->Mechanism()) { switch (mHash->Mechanism()) {
case CKM_SHA_1: mMechanism = CKM_SHA_1_HMAC; break; case CKM_SHA_1: mMechanism = CKM_SHA_1_HMAC; break;
case CKM_SHA224: mMechanism = CKM_SHA224_HMAC; break;
case CKM_SHA256: mMechanism = CKM_SHA256_HMAC; break; case CKM_SHA256: mMechanism = CKM_SHA256_HMAC; break;
case CKM_SHA384: mMechanism = CKM_SHA384_HMAC; break; case CKM_SHA384: mMechanism = CKM_SHA384_HMAC; break;
case CKM_SHA512: mMechanism = CKM_SHA512_HMAC; break; case CKM_SHA512: mMechanism = CKM_SHA512_HMAC; break;

Просмотреть файл

@ -40,8 +40,6 @@ KeyAlgorithm::KeyAlgorithm(nsIGlobalObject* aGlobal, const nsString& aName)
mMechanism = CKM_AES_GCM; mMechanism = CKM_AES_GCM;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) { } else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
mMechanism = CKM_SHA_1; mMechanism = CKM_SHA_1;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA224)) {
mMechanism = CKM_SHA224;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) { } else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
mMechanism = CKM_SHA256; mMechanism = CKM_SHA256;
} else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) { } else if (mName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {

Просмотреть файл

@ -18,7 +18,6 @@
#define WEBCRYPTO_ALG_AES_GCM "AES-GCM" #define WEBCRYPTO_ALG_AES_GCM "AES-GCM"
#define WEBCRYPTO_ALG_SHA1 "SHA-1" #define WEBCRYPTO_ALG_SHA1 "SHA-1"
#define WEBCRYPTO_ALG_SHA256 "SHA-256" #define WEBCRYPTO_ALG_SHA256 "SHA-256"
#define WEBCRYPTO_ALG_SHA224 "SHA-224"
#define WEBCRYPTO_ALG_SHA384 "SHA-384" #define WEBCRYPTO_ALG_SHA384 "SHA-384"
#define WEBCRYPTO_ALG_SHA512 "SHA-512" #define WEBCRYPTO_ALG_SHA512 "SHA-512"
#define WEBCRYPTO_ALG_HMAC "HMAC" #define WEBCRYPTO_ALG_HMAC "HMAC"

Просмотреть файл

@ -489,8 +489,6 @@ public:
switch (hashAlg->Mechanism()) { switch (hashAlg->Mechanism()) {
case CKM_SHA_1: case CKM_SHA_1:
mOidTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; break; mOidTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; break;
case CKM_SHA224:
mOidTag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION; break;
case CKM_SHA256: case CKM_SHA256:
mOidTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; break; mOidTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; break;
case CKM_SHA384: case CKM_SHA384:
@ -598,8 +596,6 @@ public:
if (algName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) { if (algName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
mOidTag = SEC_OID_SHA1; mOidTag = SEC_OID_SHA1;
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_SHA224)) {
mOidTag = SEC_OID_SHA224;
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) { } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
mOidTag = SEC_OID_SHA256; mOidTag = SEC_OID_SHA256;
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) { } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
@ -1022,8 +1018,7 @@ public:
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) { } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
RootedDictionary<HmacKeyGenParams> params(aCx); RootedDictionary<HmacKeyGenParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm); mEarlyRv = Coerce(aCx, params, aAlgorithm);
if (NS_FAILED(mEarlyRv) || !params.mLength.WasPassed() || if (NS_FAILED(mEarlyRv) || !params.mHash.WasPassed()) {
!params.mHash.WasPassed()) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR; mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return; return;
} }
@ -1041,7 +1036,24 @@ public:
hashName.Assign(hashAlg.mName.Value()); hashName.Assign(hashAlg.mName.Value());
} }
mLength = params.mLength.Value(); if (params.mLength.WasPassed()) {
mLength = params.mLength.Value();
} else {
KeyAlgorithm hashAlg(global, hashName);
switch (hashAlg.Mechanism()) {
case CKM_SHA_1: mLength = 128; break;
case CKM_SHA256: mLength = 256; break;
case CKM_SHA384: mLength = 384; break;
case CKM_SHA512: mLength = 512; break;
default: mLength = 0; break;
}
}
if (mLength == 0) {
mEarlyRv = NS_ERROR_DOM_DATA_ERR;
return;
}
algorithm = new HmacKeyAlgorithm(global, algName, mLength, hashName); algorithm = new HmacKeyAlgorithm(global, algName, mLength, hashName);
allowedUsages = Key::SIGN | Key::VERIFY; allowedUsages = Key::SIGN | Key::VERIFY;
} else { } else {

Просмотреть файл

@ -309,6 +309,62 @@ TestArray.addTest(
} }
); );
// -----------------------------------------------------------------------------
TestArray.addTest(
"Generate a 256-bit HMAC-SHA-256 key",
function() {
var that = this;
var alg = { name: "HMAC", length: 256, hash: {name: "SHA-256"} };
crypto.subtle.generateKey(alg, true, ["sign", "verify"]).then(
complete(that, function(x) {
return hasKeyFields(x) && x.algorithm.length == 256;
}),
error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Generate a 256-bit HMAC-SHA-256 key without specifying a key length",
function() {
var that = this;
var alg = { name: "HMAC", hash: {name: "SHA-256"} };
crypto.subtle.generateKey(alg, true, ["sign", "verify"]).then(
complete(that, function(x) {
return hasKeyFields(x) && x.algorithm.length == 256;
}),
error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Fail generating an HMAC key when specifying an invalid hash algorithm",
function() {
var that = this;
var alg = { name: "HMAC", hash: {name: "SHA-123"} };
crypto.subtle.generateKey(alg, true, ["sign", "verify"]).then(
error(that),
complete(that, function() { return true; })
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Fail generating an HMAC key when specifying a zero length",
function() {
var that = this;
var alg = { name: "HMAC", hash: {name: "SHA-256"}, length: 0 };
crypto.subtle.generateKey(alg, true, ["sign", "verify"]).then(
error(that),
complete(that, function() { return true; })
);
}
);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TestArray.addTest( TestArray.addTest(
"Generate a 192-bit AES key", "Generate a 192-bit AES key",

Просмотреть файл

@ -293,7 +293,6 @@ EVENT(mozpointerlockerror,
NS_POINTERLOCKERROR, NS_POINTERLOCKERROR,
EventNameType_HTML, EventNameType_HTML,
NS_EVENT) NS_EVENT)
EVENT(pointerdown, EVENT(pointerdown,
NS_POINTER_DOWN, NS_POINTER_DOWN,
EventNameType_All, EventNameType_All,

Просмотреть файл

@ -1440,7 +1440,7 @@ EventStateManager::FireContextClick()
} }
} }
nsIDocument* doc = mGestureDownContent->GetCurrentDoc(); nsIDocument* doc = mGestureDownContent->GetCrossShadowCurrentDoc();
AutoHandlingUserInputStatePusher userInpStatePusher(true, &event, doc); AutoHandlingUserInputStatePusher userInpStatePusher(true, &event, doc);
// dispatch to DOM // dispatch to DOM
@ -2011,7 +2011,7 @@ EventStateManager::DoScrollZoom(nsIFrame* aTargetFrame,
// positive adjustment to decrease zoom, negative to increase // positive adjustment to decrease zoom, negative to increase
int32_t change = (adjustment > 0) ? -1 : 1; int32_t change = (adjustment > 0) ? -1 : 1;
if (Preferences::GetBool("browser.zoom.full") || content->GetCurrentDoc()->IsSyntheticDocument()) { if (Preferences::GetBool("browser.zoom.full") || content->OwnerDoc()->IsSyntheticDocument()) {
ChangeFullZoom(change); ChangeFullZoom(change);
} else { } else {
ChangeTextSize(change); ChangeTextSize(change);
@ -2752,7 +2752,7 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
// NOTE: The newFocus isn't editable that also means it's not in // NOTE: The newFocus isn't editable that also means it's not in
// designMode. In designMode, all contents are not focusable. // designMode. In designMode, all contents are not focusable.
if (newFocus && !newFocus->IsEditable()) { if (newFocus && !newFocus->IsEditable()) {
nsIDocument *doc = newFocus->GetCurrentDoc(); nsIDocument *doc = newFocus->GetCrossShadowCurrentDoc();
if (doc && newFocus == doc->GetRootElement()) { if (doc && newFocus == doc->GetRootElement()) {
nsIContent *bodyContent = nsIContent *bodyContent =
nsLayoutUtils::GetEditableRootContentByContentEditable(doc); nsLayoutUtils::GetEditableRootContentByContentEditable(doc);
@ -4633,7 +4633,8 @@ EventStateManager::SetContentState(nsIContent* aContent, EventStates aState)
newHover = aContent; newHover = aContent;
} else { } else {
NS_ASSERTION(!aContent || NS_ASSERTION(!aContent ||
aContent->GetCurrentDoc() == mPresContext->PresShell()->GetDocument(), aContent->GetCrossShadowCurrentDoc() ==
mPresContext->PresShell()->GetDocument(),
"Unexpected document"); "Unexpected document");
nsIFrame *frame = aContent ? aContent->GetPrimaryFrame() : nullptr; nsIFrame *frame = aContent ? aContent->GetPrimaryFrame() : nullptr;
if (frame && nsLayoutUtils::IsViewportScrollbarFrame(frame)) { if (frame && nsLayoutUtils::IsViewportScrollbarFrame(frame)) {

Просмотреть файл

@ -38,17 +38,6 @@ public:
{ {
} }
MOZ_CONSTEXPR EventStates(const EventStates& aEventStates)
: mStates(aEventStates.mStates)
{
}
EventStates& operator=(const EventStates& aEventStates)
{
mStates = aEventStates.mStates;
return *this;
}
EventStates MOZ_CONSTEXPR operator|(const EventStates& aEventStates) const EventStates MOZ_CONSTEXPR operator|(const EventStates& aEventStates) const
{ {
return EventStates(mStates | aEventStates.mStates); return EventStates(mStates | aEventStates.mStates);

Просмотреть файл

@ -10,68 +10,66 @@ support-files =
turnConfig.js turnConfig.js
[test_dataChannel_basicAudio.html] [test_dataChannel_basicAudio.html]
skip-if = toolkit == 'gonk' #Bug 962984 for debug, bug 963244 for opt skip-if = toolkit == 'gonk' # Bug 962984 for debug, bug 963244 for opt
[test_dataChannel_basicAudioVideo.html] [test_dataChannel_basicAudioVideo.html]
# Disabled on OS X for bug 930481 timeouts skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
skip-if = os == 'mac' || toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_dataChannel_basicAudioVideoCombined.html] [test_dataChannel_basicAudioVideoCombined.html]
# Disabled on OS X for bug 930481 timeouts skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
skip-if = os == 'mac' || toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_dataChannel_basicDataOnly.html] [test_dataChannel_basicDataOnly.html]
[test_dataChannel_basicVideo.html] [test_dataChannel_basicVideo.html]
skip-if = toolkit=='gonk' # b2g emulator seems to bee too slow (Bug 1016498 and 1008080) skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_dataChannel_bug1013809.html] [test_dataChannel_bug1013809.html]
skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) skip-if = (toolkit == 'gonk' && debug) # b2g emulator seems to be too slow (Bug 1016498 and 1008080)
[test_dataChannel_noOffer.html] [test_dataChannel_noOffer.html]
[test_getUserMedia_basicAudio.html] [test_getUserMedia_basicAudio.html]
skip-if = (toolkit == 'gonk' && debug) #debug-only failure skip-if = (toolkit == 'gonk' && debug) # debug-only failure
[test_getUserMedia_basicVideo.html] [test_getUserMedia_basicVideo.html]
skip-if = (toolkit == 'gonk' && debug) #debug-only failure skip-if = (toolkit == 'gonk' && debug) # debug-only failure
[test_getUserMedia_basicVideoAudio.html] [test_getUserMedia_basicVideoAudio.html]
skip-if = (toolkit == 'gonk' && debug) #debug-only failure, turned an intermittent (bug 962579) into a permanant orange skip-if = (toolkit == 'gonk' && debug) # debug-only failure, turned an intermittent (bug 962579) into a permanant orange
[test_getUserMedia_constraints.html] [test_getUserMedia_constraints.html]
skip-if = (toolkit=='gonk' || toolkit=='android') # Bug 907352, backwards-compatible behavior on mobile only skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 907352, backwards-compatible behavior on mobile only
[test_getUserMedia_constraints_mobile.html] [test_getUserMedia_constraints_mobile.html]
skip-if = (toolkit!='gonk' && toolkit!='android') # Bug 907352, backwards-compatible behavior on mobile only skip-if = toolkit != 'gonk' && toolkit != 'android' # Bug 907352, backwards-compatible behavior on mobile only
[test_getUserMedia_exceptions.html] [test_getUserMedia_exceptions.html]
[test_getUserMedia_gumWithinGum.html] [test_getUserMedia_gumWithinGum.html]
[test_getUserMedia_playAudioTwice.html] [test_getUserMedia_playAudioTwice.html]
[test_getUserMedia_playVideoAudioTwice.html] [test_getUserMedia_playVideoAudioTwice.html]
skip-if = (toolkit == 'gonk' && debug) #debug-only failure; bug 926558 skip-if = (toolkit == 'gonk' && debug) # debug-only failure; bug 926558
[test_getUserMedia_playVideoTwice.html] [test_getUserMedia_playVideoTwice.html]
[test_getUserMedia_stopAudioStream.html] [test_getUserMedia_stopAudioStream.html]
[test_getUserMedia_stopAudioStreamWithFollowupAudio.html] [test_getUserMedia_stopAudioStreamWithFollowupAudio.html]
[test_getUserMedia_stopVideoAudioStream.html] [test_getUserMedia_stopVideoAudioStream.html]
skip-if = (toolkit == 'gonk' && debug) #debug-only failure skip-if = (toolkit == 'gonk' && debug) # debug-only failure
[test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html] [test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html]
[test_getUserMedia_stopVideoStream.html] [test_getUserMedia_stopVideoStream.html]
[test_getUserMedia_stopVideoStreamWithFollowupVideo.html] [test_getUserMedia_stopVideoStreamWithFollowupVideo.html]
[test_getUserMedia_peerIdentity.html] [test_getUserMedia_peerIdentity.html]
[test_peerConnection_addCandidateInHaveLocalOffer.html] [test_peerConnection_addCandidateInHaveLocalOffer.html]
[test_peerConnection_basicAudio.html] [test_peerConnection_basicAudio.html]
skip-if = (toolkit == 'gonk' && debug) #Bug 962984, test fail on b2g debug build skip-if = (toolkit == 'gonk' && debug) # Bug 962984, test fail on b2g debug build
[test_peerConnection_basicAudioVideo.html] [test_peerConnection_basicAudioVideo.html]
skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_basicAudioVideoCombined.html] [test_peerConnection_basicAudioVideoCombined.html]
skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_basicVideo.html] [test_peerConnection_basicVideo.html]
skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_bug822674.html] [test_peerConnection_bug822674.html]
[test_peerConnection_bug825703.html] [test_peerConnection_bug825703.html]
[test_peerConnection_bug827843.html] [test_peerConnection_bug827843.html]
skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_bug834153.html] [test_peerConnection_bug834153.html]
[test_peerConnection_bug835370.html] [test_peerConnection_bug835370.html]
skip-if = toolkit=='gonk' # b2g emulator seems to bee too slow (Bug 1016498 and 1008080)
[test_peerConnection_bug1013809.html] [test_peerConnection_bug1013809.html]
skip-if = (toolkit == 'gonk' && debug) # b2g emulator seems to be too slow (Bug 1016498 and 1008080)
[test_peerConnection_close.html] [test_peerConnection_close.html]
[test_peerConnection_errorCallbacks.html] [test_peerConnection_errorCallbacks.html]
[test_peerConnection_offerRequiresReceiveAudio.html] [test_peerConnection_offerRequiresReceiveAudio.html]
skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_offerRequiresReceiveVideo.html] [test_peerConnection_offerRequiresReceiveVideo.html]
skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_offerRequiresReceiveVideoAudio.html] [test_peerConnection_offerRequiresReceiveVideoAudio.html]
skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_setLocalAnswerInHaveLocalOffer.html] [test_peerConnection_setLocalAnswerInHaveLocalOffer.html]
[test_peerConnection_setLocalAnswerInStable.html] [test_peerConnection_setLocalAnswerInStable.html]
[test_peerConnection_setLocalOfferInHaveRemoteOffer.html] [test_peerConnection_setLocalOfferInHaveRemoteOffer.html]
@ -79,7 +77,7 @@ skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled
[test_peerConnection_setRemoteAnswerInStable.html] [test_peerConnection_setRemoteAnswerInStable.html]
[test_peerConnection_setRemoteOfferInHaveLocalOffer.html] [test_peerConnection_setRemoteOfferInHaveLocalOffer.html]
[test_peerConnection_throwInCallbacks.html] [test_peerConnection_throwInCallbacks.html]
skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_toJSON.html] [test_peerConnection_toJSON.html]
# Bug 950317: Hack for making a cleanup hook after finishing all WebRTC cases # Bug 950317: Hack for making a cleanup hook after finishing all WebRTC cases

Просмотреть файл

@ -6,3 +6,4 @@ tail =
[test_multisend.js] [test_multisend.js]
[test_tcpserversocket.js] [test_tcpserversocket.js]
run-sequentially = Uses hardcoded port, bug 903830. run-sequentially = Uses hardcoded port, bug 903830.
skip-if = os == 'mac' # bug 953208 - frequent timeouts on OSX

Просмотреть файл

@ -396,8 +396,13 @@ NS_IMETHODIMP
NotificationObserver::Observe(nsISupports* aSubject, const char* aTopic, NotificationObserver::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) const char16_t* aData)
{ {
nsCOMPtr<nsPIDOMWindow> window = mNotification->GetOwner();
if (!window) {
// Window has been closed, this observer is not valid anymore
return NS_ERROR_FAILURE;
}
if (!strcmp("alertclickcallback", aTopic)) { if (!strcmp("alertclickcallback", aTopic)) {
nsCOMPtr<nsPIDOMWindow> window = mNotification->GetOwner();
nsIDocument* doc = window ? window->GetExtantDoc() : nullptr; nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
if (doc) { if (doc) {
nsContentUtils::DispatchChromeEvent(doc, window, nsContentUtils::DispatchChromeEvent(doc, window,

Просмотреть файл

@ -122,7 +122,7 @@ WifiGeoPositionProvider.prototype = {
// This platform doesn't have the settings interface, and that is just peachy // This platform doesn't have the settings interface, and that is just peachy
} }
if (gWifiScanningEnabled) { if (gWifiScanningEnabled && Cc["@mozilla.org/wifi/monitor;1"]) {
this.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor); this.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
this.wifiService.startWatching(this); this.wifiService.startWatching(this);
} }

Просмотреть файл

@ -10,10 +10,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=806506
</head> </head>
<body> <body>
<div class="tall" id="bodydiv"></div> <div class="tall" id="bodydiv"></div>
<div id="container"></div>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=806506">Bug 806506</a> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=806506">Bug 806506</a>
<script> <script>
// Create ShadowRoot. // Create ShadowRoot.
var container = document.getElementById("container");
var elem = document.createElement("div"); var elem = document.createElement("div");
container.appendChild(elem); // Put ShadowRoot host in document.
var root = elem.createShadowRoot(); var root = elem.createShadowRoot();
// A style element that will be appended into the ShadowRoot. // A style element that will be appended into the ShadowRoot.

Просмотреть файл

@ -10,10 +10,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=806506
</head> </head>
<body> <body>
<div class="tall" id="bodydiv"></div> <div class="tall" id="bodydiv"></div>
<div id="container"></div>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=806506">Bug 806506</a> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=806506">Bug 806506</a>
<script> <script>
// Create ShadowRoot. // Create ShadowRoot.
var container = document.getElementById("container");
var elem = document.createElement("div"); var elem = document.createElement("div");
container.appendChild(elem); // Put ShadowRoot host in document.
var firstRoot = elem.createShadowRoot(); var firstRoot = elem.createShadowRoot();
var secondRoot = elem.createShadowRoot(); var secondRoot = elem.createShadowRoot();
var thirdRoot = elem.createShadowRoot(); var thirdRoot = elem.createShadowRoot();

Просмотреть файл

@ -9,10 +9,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=806506
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head> </head>
<body> <body>
<div id="container"></div>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=806506">Bug 806506</a> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=806506">Bug 806506</a>
<script> <script>
// Create ShadowRoot. // Create ShadowRoot.
var container = document.getElementById("container");
var elem = document.createElement("div"); var elem = document.createElement("div");
container.appendChild(elem); // Put ShadowRoot host in document.
var root = elem.createShadowRoot(); var root = elem.createShadowRoot();
// Style elements that will be appended into the ShadowRoot. // Style elements that will be appended into the ShadowRoot.

Просмотреть файл

@ -0,0 +1,23 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
enum AutoCompleteErrorReason {
"",
"cancel",
"disabled",
"invalid"
};
[Pref="dom.forms.requestAutocomplete",
Constructor(DOMString type, optional AutocompleteErrorEventInit eventInitDict)]
interface AutocompleteErrorEvent : Event
{
readonly attribute AutoCompleteErrorReason reason;
};
dictionary AutocompleteErrorEventInit : EventInit
{
AutoCompleteErrorReason reason = "";
};

Просмотреть файл

@ -45,4 +45,7 @@ interface HTMLFormElement : HTMLElement {
void submit(); void submit();
void reset(); void reset();
boolean checkValidity(); boolean checkValidity();
[Pref="dom.forms.requestAutocomplete"]
void requestAutocomplete();
}; };

Просмотреть файл

@ -102,6 +102,9 @@ partial interface HTMLMediaElement {
attribute boolean mozPreservesPitch; attribute boolean mozPreservesPitch;
readonly attribute boolean mozAutoplayEnabled; readonly attribute boolean mozAutoplayEnabled;
// NB: for internal use with the video controls:
[Func="IsChromeOrXBL"] attribute boolean mozMediaStatisticsShowing;
// Mozilla extension: stream capture // Mozilla extension: stream capture
[Throws] [Throws]
MediaStream mozCaptureStream(); MediaStream mozCaptureStream();
@ -130,3 +133,25 @@ partial interface HTMLMediaElement {
// because of the audiochannel manager. // because of the audiochannel manager.
// * onmozinterruptend - called when the interruption is concluded // * onmozinterruptend - called when the interruption is concluded
}; };
enum MediaWaitingFor {
"none",
"data",
"key"
};
// Encrypted Media Extensions
partial interface HTMLMediaElement {
[Pref="media.eme.enabled"]
readonly attribute MediaKeys? mediaKeys;
// Promise<any>
[Pref="media.eme.enabled", Throws, NewObject]
Promise setMediaKeys(MediaKeys? mediaKeys);
[Pref="media.eme.enabled"]
attribute EventHandler onneedkey;
[Pref="media.eme.enabled"]
readonly attribute MediaWaitingFor waitingFor;
};

Просмотреть файл

@ -19,3 +19,9 @@ interface HTMLSourceElement : HTMLElement {
[SetterThrows] [SetterThrows]
attribute DOMString media; attribute DOMString media;
}; };
// Encrypted Media Extensions
partial interface HTMLSourceElement {
[Pref="media.eme.enabled"]
attribute DOMString keySystem;
};

Просмотреть файл

@ -0,0 +1,19 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
*
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
* W3C liability, trademark and document use rules apply.
*/
// According to the spec, "The future of error events and MediaKeyError
// is uncertain."
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=21798
[Pref="media.eme.enabled"]
interface MediaKeyError : Event {
readonly attribute unsigned long systemCode;
};

Просмотреть файл

@ -0,0 +1,23 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
*
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
* W3C liability, trademark and document use rules apply.
*/
[Pref="media.eme.enabled", Constructor(DOMString type, optional MediaKeyMessageEventInit eventInitDict)]
interface MediaKeyMessageEvent : Event {
[Throws]
readonly attribute Uint8Array message;
readonly attribute DOMString? destinationURL;
};
dictionary MediaKeyMessageEventInit : EventInit {
Uint8Array message;
DOMString? destinationURL = "";
};

Просмотреть файл

@ -0,0 +1,23 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
*
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
* W3C liability, trademark and document use rules apply.
*/
[Pref="media.eme.enabled", Constructor(DOMString type, optional MediaKeyNeededEventInit eventInitDict)]
interface MediaKeyNeededEvent : Event {
readonly attribute DOMString initDataType;
[Throws]
readonly attribute Uint8Array? initData;
};
dictionary MediaKeyNeededEventInit : EventInit {
DOMString initDataType = "";
Uint8Array? initData;
};

Просмотреть файл

@ -0,0 +1,43 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
*
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
* W3C liability, trademark and document use rules apply.
*/
[Pref="media.eme.enabled"]
interface MediaKeySession : EventTarget {
// error state
readonly attribute MediaKeyError? error;
// session properties
readonly attribute DOMString keySystem;
readonly attribute DOMString sessionId;
// Invalid WebIDL, doesn't work.
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=25594
// readonly attribute Array<Uint8Array> usableKeyIds;
readonly attribute unrestricted double expiration;
// Promise<any>
readonly attribute Promise closed;
// session operations
//Promise<any>
[NewObject]
Promise update(Uint8Array response);
// Promise<any>
[NewObject]
Promise close();
// Promise<any>
[NewObject]
Promise remove();
};

Просмотреть файл

@ -0,0 +1,37 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
*
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
* W3C liability, trademark and document use rules apply.
*/
enum IsTypeSupportedResult { "" /* empty string */, "maybe", "probably" };
enum SessionType { "temporary", "persistent" };
[Pref="media.eme.enabled"]
interface MediaKeys {
readonly attribute DOMString keySystem;
// Promise<MediaKeySession>
[NewObject]
Promise createSession(DOMString initDataType, Uint8Array initData, optional SessionType sessionType = "temporary");
// Promise<MediaKeySession>
[NewObject]
Promise loadSession(DOMString sessionId);
// Promise<any>
[NewObject]
Promise setServerCertificate(Uint8Array serverCertificate);
// Promise<MediaKeys>
[Throws,NewObject]
static Promise create(DOMString keySystem);
static IsTypeSupportedResult isTypeSupported(DOMString keySystem, optional DOMString initDataType, optional DOMString contentType, optional DOMString capability);
};

Просмотреть файл

@ -231,6 +231,11 @@ WEBIDL_FILES = [
'LockedFile.webidl', 'LockedFile.webidl',
'MediaElementAudioSourceNode.webidl', 'MediaElementAudioSourceNode.webidl',
'MediaError.webidl', 'MediaError.webidl',
'MediaKeyError.webidl',
'MediaKeyMessageEvent.webidl',
'MediaKeyNeededEvent.webidl',
'MediaKeys.webidl',
'MediaKeySession.webidl',
'MediaList.webidl', 'MediaList.webidl',
'MediaQueryList.webidl', 'MediaQueryList.webidl',
'MediaRecorder.webidl', 'MediaRecorder.webidl',
@ -623,6 +628,7 @@ if not CONFIG['MOZ_DISABLE_CRYPTOLEGACY']:
] ]
GENERATED_EVENTS_WEBIDL_FILES = [ GENERATED_EVENTS_WEBIDL_FILES = [
'AutocompleteErrorEvent.webidl',
'BlobEvent.webidl', 'BlobEvent.webidl',
'CallGroupErrorEvent.webidl', 'CallGroupErrorEvent.webidl',
'CFStateChangeEvent.webidl', 'CFStateChangeEvent.webidl',

Просмотреть файл

@ -28,6 +28,12 @@ BEGIN_WORKERS_NAMESPACE
* | Killing | yes | yes | doesn't run | * | Killing | yes | yes | doesn't run |
* +-------------+-------------+-----------------+----------------+ * +-------------+-------------+-----------------+----------------+
*/ */
#ifdef Status
/* Xlib headers insist on this for some reason... Nuke it because
it'll override our member name */
#undef Status
#endif
enum Status enum Status
{ {
// Not yet scheduled. // Not yet scheduled.

Просмотреть файл

@ -445,6 +445,27 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent,
} }
} }
break; break;
} case PANGESTURE_INPUT: {
const PanGestureInput& panInput = aEvent.AsPanGestureInput();
bool inOverscrolledApzc = false;
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(panInput.mPanStartPoint,
&inOverscrolledApzc);
if (apzc) {
if (panInput.mType == PanGestureInput::PANGESTURE_START ||
panInput.mType == PanGestureInput::PANGESTURE_MOMENTUMSTART) {
BuildOverscrollHandoffChain(apzc);
}
apzc->GetGuid(aOutTargetGuid);
GetInputTransforms(apzc, transformToApzc, transformToGecko);
PanGestureInput inputForApzc(panInput);
ApplyTransform(&(inputForApzc.mPanStartPoint), transformToApzc);
result = apzc->ReceiveInputEvent(inputForApzc);
if (panInput.mType == PanGestureInput::PANGESTURE_END ||
panInput.mType == PanGestureInput::PANGESTURE_MOMENTUMEND) {
ClearOverscrollHandoffChain();
}
}
break;
} case PINCHGESTURE_INPUT: { } case PINCHGESTURE_INPUT: {
const PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput(); const PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput();
bool inOverscrolledApzc = false; bool inOverscrolledApzc = false;

Просмотреть файл

@ -216,13 +216,36 @@ typedef GeckoContentController::APZStateChange APZStateChange;
* Pref that enables overscrolling. If this is disabled, excess scroll that * Pref that enables overscrolling. If this is disabled, excess scroll that
* cannot be handed off is discarded. * cannot be handed off is discarded.
* *
* "apz.overscroll.snap_back_accel" * "apz.overscroll.fling_friction"
* Amount of acceleration applied during the snap-back animation. * Amount of friction applied during flings when in overscroll.
* *
* "apz.overscroll.snap_back_init_vel" * "apz.overscroll.fling_stopped_threshold"
* Initial velocity of a snap-back animation along one axis. * When flinging in an overscrolled state, if the velocity goes below this
* number, we stop the fling.
* Units: screen pixels per millisecond * Units: screen pixels per millisecond
* requests. *
* "apz.overscroll.clamping"
* The maximum proportion of the composition bounds which can become blank
* as a result of overscroll, along the axis of overscroll.
*
* "apz.overscroll.z_effect"
* The fraction of "apz.overscroll.clamping" which can become blank as a result
* of overscroll, along the axis opposite to the axis of overscroll. Called
* "z_effect" because the shrinking that brings about the blank space on the
* opposite axis creates the effect of the page moving away from you along a
* "z" axis.
*
* "apz.overscroll.snap_back.spring_stiffness"
* The stiffness of the spring used in the physics model for the overscroll
* snap-back animation.
*
* "apz.overscroll.snap_back.spring_damping"
* The friction of the spring used in the physics model for the overscroll
* snap-back animation.
*
* "apz.overscroll.snap_back.mass"
* The mass of the page in the physics model for the overscroll snap-back
* animation.
* *
* "apz.pan_repaint_interval" * "apz.pan_repaint_interval"
* Maximum amount of time while panning before sending a viewport change. This * Maximum amount of time while panning before sending a viewport change. This
@ -471,17 +494,15 @@ private:
class OverscrollSnapBackAnimation: public AsyncPanZoomAnimation { class OverscrollSnapBackAnimation: public AsyncPanZoomAnimation {
public: public:
OverscrollSnapBackAnimation(AsyncPanZoomController& aApzc) OverscrollSnapBackAnimation(AsyncPanZoomController& aApzc)
: mApzc(aApzc) : mApzc(aApzc) {}
{
mApzc.mX.StartSnapBack();
mApzc.mY.StartSnapBack();
}
virtual bool Sample(FrameMetrics& aFrameMetrics, virtual bool Sample(FrameMetrics& aFrameMetrics,
const TimeDuration& aDelta) MOZ_OVERRIDE const TimeDuration& aDelta) MOZ_OVERRIDE
{ {
return mApzc.mX.SampleSnapBack(aDelta) // Can't inline these variables due to short-circuit evaluation.
|| mApzc.mY.SampleSnapBack(aDelta); bool continueX = mApzc.mX.SampleSnapBack(aDelta);
bool continueY = mApzc.mY.SampleSnapBack(aDelta);
return continueX || continueY;
} }
private: private:
@ -693,6 +714,21 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent)
} }
break; break;
} }
case PANGESTURE_INPUT: {
const PanGestureInput& panGestureInput = aEvent.AsPanGestureInput();
switch (panGestureInput.mType) {
case PanGestureInput::PANGESTURE_MAYSTART: rv = OnPanMayBegin(panGestureInput); break;
case PanGestureInput::PANGESTURE_CANCELLED: rv = OnPanCancelled(panGestureInput); break;
case PanGestureInput::PANGESTURE_START: rv = OnPanBegin(panGestureInput); break;
case PanGestureInput::PANGESTURE_PAN: rv = OnPan(panGestureInput, true); break;
case PanGestureInput::PANGESTURE_END: rv = OnPanEnd(panGestureInput); break;
case PanGestureInput::PANGESTURE_MOMENTUMSTART: rv = OnPanMomentumStart(panGestureInput); break;
case PanGestureInput::PANGESTURE_MOMENTUMPAN: rv = OnPan(panGestureInput, false); break;
case PanGestureInput::PANGESTURE_MOMENTUMEND: rv = OnPanMomentumEnd(panGestureInput); break;
default: NS_WARNING("Unhandled pan gesture"); break;
}
break;
}
default: NS_WARNING("Unhandled input event"); break; default: NS_WARNING("Unhandled input event"); break;
} }
@ -1064,6 +1100,93 @@ AsyncPanZoomController::ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut
return false; return false;
} }
nsEventStatus AsyncPanZoomController::OnPanMayBegin(const PanGestureInput& aEvent) {
APZC_LOG("%p got a pan-maybegin in state %d\n", this, mState);
mX.StartTouch(aEvent.mPanStartPoint.x, aEvent.mTime);
mY.StartTouch(aEvent.mPanStartPoint.y, aEvent.mTime);
CancelAnimation();
return nsEventStatus_eConsumeNoDefault;
}
nsEventStatus AsyncPanZoomController::OnPanCancelled(const PanGestureInput& aEvent) {
APZC_LOG("%p got a pan-cancelled in state %d\n", this, mState);
mX.CancelTouch();
mY.CancelTouch();
return nsEventStatus_eConsumeNoDefault;
}
nsEventStatus AsyncPanZoomController::OnPanBegin(const PanGestureInput& aEvent) {
APZC_LOG("%p got a pan-begin in state %d\n", this, mState);
mX.StartTouch(aEvent.mPanStartPoint.x, aEvent.mTime);
mY.StartTouch(aEvent.mPanStartPoint.y, aEvent.mTime);
if (GetAxisLockMode() == FREE) {
SetState(PANNING);
return nsEventStatus_eConsumeNoDefault;
}
float dx = aEvent.mPanDisplacement.x, dy = aEvent.mPanDisplacement.y;
double angle = atan2(dy, dx); // range [-pi, pi]
angle = fabs(angle); // range [0, pi]
HandlePanning(angle);
return nsEventStatus_eConsumeNoDefault;
}
nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool aFingersOnTouchpad) {
APZC_LOG("%p got a pan-pan in state %d\n", this, mState);
// We need to update the axis velocity in order to get a useful display port
// size and position. We need to do so even if this is a momentum pan (i.e.
// aFingersOnTouchpad == false); in that case the "with touch" part is not
// really appropriate, so we may want to rethink this at some point.
mX.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.x, aEvent.mTime);
mY.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.y, aEvent.mTime);
HandlePanningUpdate(aEvent.mPanDisplacement.x, aEvent.mPanDisplacement.y);
CallDispatchScroll(aEvent.mPanStartPoint, aEvent.mPanStartPoint + aEvent.mPanDisplacement, 0);
return nsEventStatus_eConsumeNoDefault;
}
nsEventStatus AsyncPanZoomController::OnPanEnd(const PanGestureInput& aEvent) {
APZC_LOG("%p got a pan-end in state %d\n", this, mState);
mX.EndTouch(aEvent.mTime);
mY.EndTouch(aEvent.mTime);
RequestContentRepaint();
return nsEventStatus_eConsumeNoDefault;
}
nsEventStatus AsyncPanZoomController::OnPanMomentumStart(const PanGestureInput& aEvent) {
APZC_LOG("%p got a pan-momentumstart in state %d\n", this, mState);
return nsEventStatus_eConsumeNoDefault;
}
nsEventStatus AsyncPanZoomController::OnPanMomentumEnd(const PanGestureInput& aEvent) {
APZC_LOG("%p got a pan-momentumend in state %d\n", this, mState);
// We need to reset the velocity to zero. We don't really have a "touch"
// here because the touch has already ended long before the momentum
// animation started, but I guess it doesn't really matter for now.
mX.CancelTouch();
mY.CancelTouch();
RequestContentRepaint();
return nsEventStatus_eConsumeNoDefault;
}
nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) { nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) {
APZC_LOG("%p got a long-press in state %d\n", this, mState); APZC_LOG("%p got a long-press in state %d\n", this, mState);
nsRefPtr<GeckoContentController> controller = GetGeckoContentController(); nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
@ -1214,6 +1337,7 @@ void AsyncPanZoomController::HandlePanningWithTouchAction(double aAngle, TouchBe
} }
void AsyncPanZoomController::HandlePanning(double aAngle) { void AsyncPanZoomController::HandlePanning(double aAngle) {
ReentrantMonitorAutoEnter lock(mMonitor);
if (!gfxPrefs::APZCrossSlideEnabled() && (!mX.CanScrollNow() || !mY.CanScrollNow())) { if (!gfxPrefs::APZCrossSlideEnabled() && (!mX.CanScrollNow() || !mY.CanScrollNow())) {
SetState(PANNING); SetState(PANNING);
} else if (IsCloseToHorizontal(aAngle, AXIS_LOCK_ANGLE)) { } else if (IsCloseToHorizontal(aAngle, AXIS_LOCK_ANGLE)) {
@ -1237,6 +1361,31 @@ void AsyncPanZoomController::HandlePanning(double aAngle) {
} }
} }
void AsyncPanZoomController::HandlePanningUpdate(float aDX, float aDY) {
// If we're axis-locked, check if the user is trying to break the lock
if (GetAxisLockMode() == STICKY && !mPanDirRestricted) {
double angle = atan2(aDY, aDX); // range [-pi, pi]
angle = fabs(angle); // range [0, pi]
float breakThreshold = AXIS_BREAKOUT_THRESHOLD * APZCTreeManager::GetDPI();
if (fabs(aDX) > breakThreshold || fabs(aDY) > breakThreshold) {
if (mState == PANNING_LOCKED_X || mState == CROSS_SLIDING_X) {
if (!IsCloseToHorizontal(angle, AXIS_BREAKOUT_ANGLE)) {
mY.SetAxisLocked(false);
SetState(PANNING);
}
} else if (mState == PANNING_LOCKED_Y || mState == CROSS_SLIDING_Y) {
if (!IsCloseToVertical(angle, AXIS_BREAKOUT_ANGLE)) {
mX.SetAxisLocked(false);
SetState(PANNING);
}
}
}
}
}
nsEventStatus AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) { nsEventStatus AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) {
ReentrantMonitorAutoEnter lock(mMonitor); ReentrantMonitorAutoEnter lock(mMonitor);
@ -1414,31 +1563,9 @@ void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
ScreenIntPoint prevTouchPoint(mX.GetPos(), mY.GetPos()); ScreenIntPoint prevTouchPoint(mX.GetPos(), mY.GetPos());
ScreenIntPoint touchPoint = GetFirstTouchScreenPoint(aEvent); ScreenIntPoint touchPoint = GetFirstTouchScreenPoint(aEvent);
// If we're axis-locked, check if the user is trying to break the lock float dx = mX.PanDistance(touchPoint.x);
if (GetAxisLockMode() == STICKY && !mPanDirRestricted) { float dy = mY.PanDistance(touchPoint.y);
ScreenIntPoint point = GetFirstTouchScreenPoint(aEvent); HandlePanningUpdate(dx, dy);
float dx = mX.PanDistance(point.x);
float dy = mY.PanDistance(point.y);
double angle = atan2(dy, dx); // range [-pi, pi]
angle = fabs(angle); // range [0, pi]
float breakThreshold = AXIS_BREAKOUT_THRESHOLD * APZCTreeManager::GetDPI();
if (fabs(dx) > breakThreshold || fabs(dy) > breakThreshold) {
if (mState == PANNING_LOCKED_X || mState == CROSS_SLIDING_X) {
if (!IsCloseToHorizontal(angle, AXIS_BREAKOUT_ANGLE)) {
mY.SetAxisLocked(false);
SetState(PANNING);
}
} else if (mState == PANNING_LOCKED_Y || mState == CROSS_SLIDING_Y) {
if (!IsCloseToVertical(angle, AXIS_BREAKOUT_ANGLE)) {
mX.SetAxisLocked(false);
SetState(PANNING);
}
}
}
}
UpdateWithTouchAtDevicePoint(aEvent); UpdateWithTouchAtDevicePoint(aEvent);
@ -1466,8 +1593,14 @@ bool FlingAnimation::Sample(FrameMetrics& aFrameMetrics,
return true; return true;
} }
bool shouldContinueFlingX = mApzc.mX.FlingApplyFrictionOrCancel(aDelta), bool overscrolled = mApzc.IsOverscrolled();
shouldContinueFlingY = mApzc.mY.FlingApplyFrictionOrCancel(aDelta); float friction = overscrolled ? gfxPrefs::APZOverscrollFlingFriction()
: gfxPrefs::APZFlingFriction();
float threshold = overscrolled ? gfxPrefs::APZOverscrollFlingStoppedThreshold()
: gfxPrefs::APZFlingStoppedThreshold();
bool shouldContinueFlingX = mApzc.mX.FlingApplyFrictionOrCancel(aDelta, friction, threshold),
shouldContinueFlingY = mApzc.mY.FlingApplyFrictionOrCancel(aDelta, friction, threshold);
// If we shouldn't continue the fling, let's just stop and repaint. // If we shouldn't continue the fling, let's just stop and repaint.
if (!shouldContinueFlingX && !shouldContinueFlingY) { if (!shouldContinueFlingX && !shouldContinueFlingY) {
// If we are in overscroll, schedule the snap-back animation that relieves it. // If we are in overscroll, schedule the snap-back animation that relieves it.
@ -1821,15 +1954,11 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
void AsyncPanZoomController::ApplyOverscrollEffect(ViewTransform* aTransform) const { void AsyncPanZoomController::ApplyOverscrollEffect(ViewTransform* aTransform) const {
// The overscroll effect applied here is a combination of a translation in // The overscroll effect applied here is a combination of a translation in
// the direction of overscroll, and shrinking in both directions. For // the direction of overscroll, and shrinking in both directions.
// example, when overscrolling past the top of the page, the rectangle of
// content that filled the composition bounds will now fill a smaller
// rectangle at the bottom of the composition bounds, centred horizontally.
// The magnitude of the translation and the shrinking depends on the amount
// of the overscroll.
// With the effect applied, we can think of the composited region as being // With the effect applied, we can think of the composited region as being
// made up of the following subregions. // made up of the following subregions.
// (1) The shrunk content that used to fill the composited region. // (1) The shrunk content (or a portion of it) that used to fill the
// composited region.
// (2) The space created along the axis that has overscroll. This space is // (2) The space created along the axis that has overscroll. This space is
// blank, filled by the background color of the overscrolled content. // blank, filled by the background color of the overscrolled content.
// TODO(botond): Implement handling of background color. // TODO(botond): Implement handling of background color.
@ -1846,61 +1975,71 @@ void AsyncPanZoomController::ApplyOverscrollEffect(ViewTransform* aTransform) co
// The maximum proportion of the composition length which can become blank // The maximum proportion of the composition length which can become blank
// space along an axis as we overscroll along that axis. // space along an axis as we overscroll along that axis.
const float CLAMPING = 0.5; const float kClamping = gfxPrefs::APZOverscrollClamping();
// The proportion of the composition length which will become blank space // The proportion of the composition length which will become blank space
// along each axis as a result of overscroll along that axis. Since // along each axis as a result of overscroll along that axis. Since
// Axis::ApplyResistance() keeps the magnitude of the overscroll in the range // Axis::ApplyResistance() keeps the magnitude of the overscroll in the range
// [0, GetCompositionLength()], these scale factors should be in the range // [0, GetCompositionLength()], these scale factors should be in the range
// [0, CLAMPING]. // [0, kClamping].
float spacePropX = CLAMPING * fabsf(mX.GetOverscroll()) / mX.GetCompositionLength(); float spacePropX = kClamping * fabsf(mX.GetOverscroll()) / mX.GetCompositionLength();
float spacePropY = CLAMPING * fabsf(mY.GetOverscroll()) / mY.GetCompositionLength(); float spacePropY = kClamping * fabsf(mY.GetOverscroll()) / mY.GetCompositionLength();
// The fraction of the proportions above which will become blank space along
// the _opposite_ axis as we zoom out as a result of overscroll along an axis.
// This creates a 3D effect, as in the layer were moving backward along a "z"
// axis.
const float kZEffect = gfxPrefs::APZOverscrollZEffect();
// The translation to apply for overscroll along the x axis. // The translation to apply for overscroll along the x axis.
CSSPoint translationX; CSSPoint translationX;
if (mX.GetOverscroll() < 0) { if (mX.IsOverscrolled()) {
// Overscroll on left. // Keep the content centred vertically as we zoom out.
// Keep content at the midpoint of the screen's right edge fixed. translationX.y = (spacePropX * kZEffect * mY.GetCompositionLength()) / 2;
translationX.x = spacePropX * mX.GetCompositionLength();
translationX.y = (spacePropX * mY.GetCompositionLength()) / 2; if (mX.GetOverscroll() < 0) {
} else if (mX.GetOverscroll() > 0) { // Overscroll on left.
// Overscroll on right. translationX.x = spacePropX * mX.GetCompositionLength();
// Keep content at the midpoint of the screen's left edge fixed. } else {
translationX.y = (spacePropX * mY.GetCompositionLength()) / 2; // Overscroll on right.
// Note that zooming out already moves the content at the right edge
// of the composition bounds to the left, but since the zooming is
// dampened by kZEffect, it doesn't take us as far as we want to go.
translationX.x = - (spacePropX * (1 - kZEffect) * mX.GetCompositionLength());
}
} }
// The translation to apply for overscroll along the y axis. // The translation to apply for overscroll along the y axis.
CSSPoint translationY; CSSPoint translationY;
if (mY.GetOverscroll() < 0) { if (mY.IsOverscrolled()) {
// Overscroll at top. // Keep the content centred horizontally as we zoom out.
// Keep content at the midpoint of the screen's bottom edge fixed. translationY.x = (spacePropY * kZEffect * mX.GetCompositionLength()) / 2;
translationY.x = (spacePropY * mX.GetCompositionLength()) / 2;
translationY.y = spacePropY * mY.GetCompositionLength(); if (mY.GetOverscroll() < 0) {
} else if (mY.GetOverscroll() > 0) { // Overscroll at top.
// Overscroll at bottom. translationY.y = spacePropY * mY.GetCompositionLength();
// Keep content at the midpoint of the screen's top edge fixed. } else {
translationY.x = (spacePropY * mX.GetCompositionLength()) / 2; // Overscroll at bottom.
// Note that zooming out already moves the content at the bottom edge
// of the composition bounds up, but since the zooming is
// dampened by kZEffect, it doesn't take us as far as we want to go.
translationY.y = - (spacePropY * (1 - kZEffect) * mY.GetCompositionLength());
}
} }
// Combine the transformations along the two axes. // Combine the transformations along the two axes.
// TODO(botond): This method of combination is imperfect, and results in a float spaceProp = sqrtf(spacePropX * spacePropX + spacePropY * spacePropY);
// funny-looking snap-back animation when we have overscroll along both axes. CSSPoint translation = translationX + translationY;
// We should fine-tune this.
float spaceProp = std::max(spacePropX, spacePropY);
CSSPoint translation(std::max(translationX.x, translationY.x),
std::max(translationX.y, translationY.y));
// The prpoportion of the composition length which will be taken up by the float scale = 1 - (kZEffect * spaceProp);
// original content; this is the scale we will apply to the content.
float contentProp = 1 - spaceProp;
// In a ViewTransform, the translation is applied before the scale. We want // In a ViewTransform, the translation is applied before the scale. We want
// to apply our translation after our scale, so we compensate for that here. // to apply our translation after our scale, so we compensate for that here.
translation.x /= contentProp; translation.x /= scale;
translation.y /= contentProp; translation.y /= scale;
// Finally, apply the transformations. // Finally, apply the transformations.
aTransform->mScale.scale *= contentProp; aTransform->mScale.scale *= scale;
aTransform->mTranslation += translation * mFrameMetrics.LayersPixelsPerCSSPixel(); aTransform->mTranslation += translation * mFrameMetrics.LayersPixelsPerCSSPixel();
} }
@ -1923,9 +2062,11 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
aScrollOffset = mFrameMetrics.GetScrollOffset() * mFrameMetrics.GetZoom(); aScrollOffset = mFrameMetrics.GetScrollOffset() * mFrameMetrics.GetZoom();
*aNewTransform = GetCurrentAsyncTransform(); *aNewTransform = GetCurrentAsyncTransform();
// GetCurrentAsyncTransform() does not consider any overscroll we may have. if (IsOverscrolled()) {
// Adjust the transform to account for that. // GetCurrentAsyncTransform() does not consider any overscroll we may have.
ApplyOverscrollEffect(aNewTransform); // Adjust the transform to account for that.
ApplyOverscrollEffect(aNewTransform);
}
LogRendertraceRect(GetGuid(), "viewport", "red", LogRendertraceRect(GetGuid(), "viewport", "red",
CSSRect(mFrameMetrics.GetScrollOffset(), CSSRect(mFrameMetrics.GetScrollOffset(),

Просмотреть файл

@ -387,6 +387,17 @@ protected:
*/ */
nsEventStatus OnScaleEnd(const PinchGestureInput& aEvent); nsEventStatus OnScaleEnd(const PinchGestureInput& aEvent);
/**
* Helper methods for handling pan events.
*/
nsEventStatus OnPanMayBegin(const PanGestureInput& aEvent);
nsEventStatus OnPanCancelled(const PanGestureInput& aEvent);
nsEventStatus OnPanBegin(const PanGestureInput& aEvent);
nsEventStatus OnPan(const PanGestureInput& aEvent, bool aFingersOnTouchpad);
nsEventStatus OnPanEnd(const PanGestureInput& aEvent);
nsEventStatus OnPanMomentumStart(const PanGestureInput& aEvent);
nsEventStatus OnPanMomentumEnd(const PanGestureInput& aEvent);
/** /**
* Helper methods for long press gestures. * Helper methods for long press gestures.
*/ */
@ -471,6 +482,11 @@ protected:
*/ */
void HandlePanning(double angle); void HandlePanning(double angle);
/**
* Update the panning state and axis locks.
*/
void HandlePanningUpdate(float aDX, float aDY);
/** /**
* Sets up anything needed for panning. This takes us out of the "TOUCHING" * Sets up anything needed for panning. This takes us out of the "TOUCHING"
* state and starts actually panning us. * state and starts actually panning us.

Просмотреть файл

@ -121,21 +121,27 @@ float Axis::GetOverscroll() const {
return mOverscroll; return mOverscroll;
} }
void Axis::StartSnapBack() {
float initialSnapBackVelocity = gfxPrefs::APZSnapBackInitialVelocity();
if (mOverscroll > 0) {
mVelocity = -initialSnapBackVelocity;
} else {
mVelocity = initialSnapBackVelocity;
}
}
bool Axis::SampleSnapBack(const TimeDuration& aDelta) { bool Axis::SampleSnapBack(const TimeDuration& aDelta) {
// Accelerate the snap-back as time goes on. // Apply spring physics to the snap-back as time goes on.
// Note: this method of acceleration isn't perfectly smooth, as it assumes // Note: this method of sampling isn't perfectly smooth, as it assumes
// a constant velocity over 'aDelta', instead of an accelerating velocity. // a constant velocity over 'aDelta', instead of an accelerating velocity.
// (The way we applying friction to flings has the same issue.) // (The way we applying friction to flings has the same issue.)
mVelocity *= pow(1.0f + gfxPrefs::APZSnapBackAcceleration(), float(aDelta.ToMilliseconds())); // Hooke's law with damping:
// F = -kx - bv
// where
// k is a constant related to the stiffness of the spring
// The larger the constant, the stiffer the spring.
// x is the displacement of the end of the spring from its equilibrium
// In our scenario, it's the amount of overscroll on the axis.
// b is a constant that provides damping (friction)
// v is the velocity of the point at the end of the spring
// See http://gafferongames.com/game-physics/spring-physics/
const float kSpringStiffness = gfxPrefs::APZOverscrollSnapBackSpringStiffness();
const float kSpringFriction = gfxPrefs::APZOverscrollSnapBackSpringFriction();
const float kMass = gfxPrefs::APZOverscrollSnapBackMass();
float force = -1 * kSpringStiffness * mOverscroll - kSpringFriction * mVelocity;
float acceleration = force / kMass;
mVelocity += acceleration * aDelta.ToMilliseconds();
float screenDisplacement = mVelocity * aDelta.ToMilliseconds(); float screenDisplacement = mVelocity * aDelta.ToMilliseconds();
float cssDisplacement = screenDisplacement / GetFrameMetrics().GetZoom().scale; float cssDisplacement = screenDisplacement / GetFrameMetrics().GetZoom().scale;
if (mOverscroll > 0) { if (mOverscroll > 0) {
@ -210,15 +216,17 @@ bool Axis::CanScrollNow() const {
return !mAxisLocked && CanScroll(); return !mAxisLocked && CanScroll();
} }
bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta) { bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta,
if (fabsf(mVelocity) <= gfxPrefs::APZFlingStoppedThreshold()) { float aFriction,
float aThreshold) {
if (fabsf(mVelocity) <= aThreshold) {
// If the velocity is very low, just set it to 0 and stop the fling, // If the velocity is very low, just set it to 0 and stop the fling,
// otherwise we'll just asymptotically approach 0 and the user won't // otherwise we'll just asymptotically approach 0 and the user won't
// actually see any changes. // actually see any changes.
mVelocity = 0.0f; mVelocity = 0.0f;
return false; return false;
} else { } else {
mVelocity *= pow(1.0f - gfxPrefs::APZFlingFriction(), float(aDelta.ToMilliseconds())); mVelocity *= pow(1.0f - aFriction, float(aDelta.ToMilliseconds()));
} }
return true; return true;
} }

Просмотреть файл

@ -98,11 +98,6 @@ public:
*/ */
float GetOverscroll() const; float GetOverscroll() const;
/**
* Start a snap-back animation to relieve overscroll.
*/
void StartSnapBack();
/** /**
* Sample the snap-back animation to relieve overscroll. * Sample the snap-back animation to relieve overscroll.
* |aDelta| is the time since the last sample. * |aDelta| is the time since the last sample.
@ -130,10 +125,15 @@ public:
/** /**
* Applies friction during a fling, or cancels the fling if the velocity is * Applies friction during a fling, or cancels the fling if the velocity is
* too low. Returns true if the fling should continue to another frame, or * too low. Returns true if the fling should continue to another frame, or
* false if it should end. |aDelta| is the amount of time that has passed * false if it should end.
* since the last time friction was applied. * |aDelta| is the amount of time that has passed since the last time
* friction was applied.
* |aFriction| is the amount of friction to apply.
* |aThreshold| is the velocity below which the fling is cancelled.
*/ */
bool FlingApplyFrictionOrCancel(const TimeDuration& aDelta); bool FlingApplyFrictionOrCancel(const TimeDuration& aDelta,
float aFriction,
float aThreshold);
/** /**
* Returns true if the page has room to be scrolled along this axis. * Returns true if the page has room to be scrolled along this axis.

Просмотреть файл

@ -309,7 +309,7 @@ EXPORTS.skia += [
'trunk/src/ports/SkMutex_pthread.h', 'trunk/src/ports/SkMutex_pthread.h',
'trunk/src/ports/SkMutex_win.h', 'trunk/src/ports/SkMutex_win.h',
] ]
SOURCES += [ UNIFIED_SOURCES += [
'trunk/src/core/SkAAClip.cpp', 'trunk/src/core/SkAAClip.cpp',
'trunk/src/core/SkAdvancedTypefaceMetrics.cpp', 'trunk/src/core/SkAdvancedTypefaceMetrics.cpp',
'trunk/src/core/SkAlphaRuns.cpp', 'trunk/src/core/SkAlphaRuns.cpp',
@ -323,16 +323,11 @@ SOURCES += [
'trunk/src/core/SkBitmapHeap.cpp', 'trunk/src/core/SkBitmapHeap.cpp',
'trunk/src/core/SkBitmapProcShader.cpp', 'trunk/src/core/SkBitmapProcShader.cpp',
'trunk/src/core/SkBitmapProcState.cpp', 'trunk/src/core/SkBitmapProcState.cpp',
'trunk/src/core/SkBitmapProcState_matrixProcs.cpp',
'trunk/src/core/SkBitmapScaler.cpp', 'trunk/src/core/SkBitmapScaler.cpp',
'trunk/src/core/SkBlitMask_D32.cpp', 'trunk/src/core/SkBlitMask_D32.cpp',
'trunk/src/core/SkBlitRow_D16.cpp', 'trunk/src/core/SkBlitRow_D16.cpp',
'trunk/src/core/SkBlitRow_D32.cpp', 'trunk/src/core/SkBlitRow_D32.cpp',
'trunk/src/core/SkBlitter.cpp', 'trunk/src/core/SkBlitter.cpp',
'trunk/src/core/SkBlitter_A8.cpp',
'trunk/src/core/SkBlitter_ARGB32.cpp',
'trunk/src/core/SkBlitter_RGB16.cpp',
'trunk/src/core/SkBlitter_Sprite.cpp',
'trunk/src/core/SkBuffer.cpp', 'trunk/src/core/SkBuffer.cpp',
'trunk/src/core/SkCanvas.cpp', 'trunk/src/core/SkCanvas.cpp',
'trunk/src/core/SkChunkAlloc.cpp', 'trunk/src/core/SkChunkAlloc.cpp',
@ -418,7 +413,6 @@ SOURCES += [
'trunk/src/core/SkScaledImageCache.cpp', 'trunk/src/core/SkScaledImageCache.cpp',
'trunk/src/core/SkScalerContext.cpp', 'trunk/src/core/SkScalerContext.cpp',
'trunk/src/core/SkScan.cpp', 'trunk/src/core/SkScan.cpp',
'trunk/src/core/SkScan_Antihair.cpp',
'trunk/src/core/SkScan_AntiPath.cpp', 'trunk/src/core/SkScan_AntiPath.cpp',
'trunk/src/core/SkScan_Hairline.cpp', 'trunk/src/core/SkScan_Hairline.cpp',
'trunk/src/core/SkScan_Path.cpp', 'trunk/src/core/SkScan_Path.cpp',
@ -553,7 +547,6 @@ SOURCES += [
'trunk/src/gpu/GrAAConvexPathRenderer.cpp', 'trunk/src/gpu/GrAAConvexPathRenderer.cpp',
'trunk/src/gpu/GrAAHairLinePathRenderer.cpp', 'trunk/src/gpu/GrAAHairLinePathRenderer.cpp',
'trunk/src/gpu/GrAARectRenderer.cpp', 'trunk/src/gpu/GrAARectRenderer.cpp',
'trunk/src/gpu/GrAddPathRenderers_default.cpp',
'trunk/src/gpu/GrAllocPool.cpp', 'trunk/src/gpu/GrAllocPool.cpp',
'trunk/src/gpu/GrAtlas.cpp', 'trunk/src/gpu/GrAtlas.cpp',
'trunk/src/gpu/GrBitmapTextContext.cpp', 'trunk/src/gpu/GrBitmapTextContext.cpp',
@ -565,7 +558,6 @@ SOURCES += [
'trunk/src/gpu/GrClipMaskManager.cpp', 'trunk/src/gpu/GrClipMaskManager.cpp',
'trunk/src/gpu/GrContext.cpp', 'trunk/src/gpu/GrContext.cpp',
'trunk/src/gpu/GrDefaultPathRenderer.cpp', 'trunk/src/gpu/GrDefaultPathRenderer.cpp',
'trunk/src/gpu/GrDistanceFieldTextContext.cpp',
'trunk/src/gpu/GrDrawState.cpp', 'trunk/src/gpu/GrDrawState.cpp',
'trunk/src/gpu/GrDrawTarget.cpp', 'trunk/src/gpu/GrDrawTarget.cpp',
'trunk/src/gpu/GrEffect.cpp', 'trunk/src/gpu/GrEffect.cpp',
@ -663,7 +655,6 @@ SOURCES += [
'trunk/src/utils/SkCamera.cpp', 'trunk/src/utils/SkCamera.cpp',
'trunk/src/utils/SkCanvasStack.cpp', 'trunk/src/utils/SkCanvasStack.cpp',
'trunk/src/utils/SkCanvasStateUtils.cpp', 'trunk/src/utils/SkCanvasStateUtils.cpp',
'trunk/src/utils/SkCondVar.cpp',
'trunk/src/utils/SkCountdown.cpp', 'trunk/src/utils/SkCountdown.cpp',
'trunk/src/utils/SkCubicInterval.cpp', 'trunk/src/utils/SkCubicInterval.cpp',
'trunk/src/utils/SkCullPoints.cpp', 'trunk/src/utils/SkCullPoints.cpp',
@ -681,7 +672,6 @@ SOURCES += [
'trunk/src/utils/SkNullCanvas.cpp', 'trunk/src/utils/SkNullCanvas.cpp',
'trunk/src/utils/SkNWayCanvas.cpp', 'trunk/src/utils/SkNWayCanvas.cpp',
'trunk/src/utils/SkOSFile.cpp', 'trunk/src/utils/SkOSFile.cpp',
'trunk/src/utils/SkParse.cpp',
'trunk/src/utils/SkParseColor.cpp', 'trunk/src/utils/SkParseColor.cpp',
'trunk/src/utils/SkParsePath.cpp', 'trunk/src/utils/SkParsePath.cpp',
'trunk/src/utils/SkPathUtils.cpp', 'trunk/src/utils/SkPathUtils.cpp',
@ -691,6 +681,18 @@ SOURCES += [
'trunk/src/utils/SkSHA1.cpp', 'trunk/src/utils/SkSHA1.cpp',
'trunk/src/utils/SkUnitMappers.cpp', 'trunk/src/utils/SkUnitMappers.cpp',
] ]
SOURCES += [
'trunk/src/core/SkBitmapProcState_matrixProcs.cpp',
'trunk/src/core/SkBlitter_A8.cpp',
'trunk/src/core/SkBlitter_ARGB32.cpp',
'trunk/src/core/SkBlitter_RGB16.cpp',
'trunk/src/core/SkBlitter_Sprite.cpp',
'trunk/src/core/SkScan_Antihair.cpp',
'trunk/src/gpu/GrAddPathRenderers_default.cpp',
'trunk/src/gpu/GrDistanceFieldTextContext.cpp',
'trunk/src/utils/SkCondVar.cpp',
'trunk/src/utils/SkParse.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'): if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
SOURCES += [ SOURCES += [
'trunk/src/images/SkImageRef_ashmem.cpp', 'trunk/src/images/SkImageRef_ashmem.cpp',

Просмотреть файл

@ -0,0 +1,148 @@
# HG changeset patch
# Parent c8288d0c7a1544a590a0cac9c39397ac10c8a45b
Bug 974900 - Add missing include guards to Skia headers - r=gw280
diff --git a/gfx/skia/trunk/include/images/SkImages.h b/gfx/skia/trunk/include/images/SkImages.h
--- a/gfx/skia/trunk/include/images/SkImages.h
+++ b/gfx/skia/trunk/include/images/SkImages.h
@@ -1,14 +1,19 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+#ifndef SkImages_DEFINED
+#define SkImages_DEFINED
+
class SkImages {
public:
/**
* Initializes flattenables in the images project.
*/
static void InitializeFlattenables();
};
+
+#endif
diff --git a/gfx/skia/trunk/src/core/SkConvolver.h b/gfx/skia/trunk/src/core/SkConvolver.h
--- a/gfx/skia/trunk/src/core/SkConvolver.h
+++ b/gfx/skia/trunk/src/core/SkConvolver.h
@@ -8,16 +8,18 @@
#include "SkSize.h"
#include "SkTypes.h"
#include "SkTArray.h"
// avoid confusion with Mac OS X's math library (Carbon)
#if defined(__APPLE__)
#undef FloatToConvolutionFixed
#undef ConvolutionFixedToFloat
+#undef FloatToFixed
+#undef FixedToFloat
#endif
// Represents a filter in one dimension. Each output pixel has one entry in this
// object for the filter values contributing to it. You build up the filter
// list by calling AddFilter for each output pixel (in order).
//
// We do 2-dimensional convolution by first convolving each row by one
// SkConvolutionFilter1D, then convolving each column by another one.
diff --git a/gfx/skia/trunk/src/gpu/GrAAConvexPathRenderer.h b/gfx/skia/trunk/src/gpu/GrAAConvexPathRenderer.h
--- a/gfx/skia/trunk/src/gpu/GrAAConvexPathRenderer.h
+++ b/gfx/skia/trunk/src/gpu/GrAAConvexPathRenderer.h
@@ -3,24 +3,28 @@
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrPathRenderer.h"
+#ifndef GrAAConvexPathRenderer_DEFINED
+#define GrAAConvexPathRenderer_DEFINED
class GrAAConvexPathRenderer : public GrPathRenderer {
public:
GrAAConvexPathRenderer();
virtual bool canDrawPath(const SkPath& path,
const SkStrokeRec& stroke,
const GrDrawTarget* target,
bool antiAlias) const SK_OVERRIDE;
protected:
virtual bool onDrawPath(const SkPath& path,
const SkStrokeRec& stroke,
GrDrawTarget* target,
bool antiAlias) SK_OVERRIDE;
};
+
+#endif
diff --git a/gfx/skia/trunk/src/gpu/GrReducedClip.h b/gfx/skia/trunk/src/gpu/GrReducedClip.h
--- a/gfx/skia/trunk/src/gpu/GrReducedClip.h
+++ b/gfx/skia/trunk/src/gpu/GrReducedClip.h
@@ -1,16 +1,19 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+#ifndef GrReducedClip_DEFINED
+#define GrReducedClip_DEFINED
+
#include "SkClipStack.h"
#include "SkTLList.h"
namespace GrReducedClip {
typedef SkTLList<SkClipStack::Element> ElementList;
enum InitialState {
@@ -36,8 +39,10 @@ SK_API void ReduceClipStack(const SkClip
const SkIRect& queryBounds,
ElementList* result,
int32_t* resultGenID,
InitialState* initialState,
SkIRect* tighterBounds = NULL,
bool* requiresAA = NULL);
} // namespace GrReducedClip
+
+#endif
diff --git a/gfx/skia/trunk/src/pathops/SkLineParameters.h b/gfx/skia/trunk/src/pathops/SkLineParameters.h
--- a/gfx/skia/trunk/src/pathops/SkLineParameters.h
+++ b/gfx/skia/trunk/src/pathops/SkLineParameters.h
@@ -1,14 +1,18 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
+#ifndef SkLineParameters_DEFINED
+#define SkLineParameters_DEFINED
+
#include "SkPathOpsCubic.h"
#include "SkPathOpsLine.h"
#include "SkPathOpsQuad.h"
// Sources
// computer-aided design - volume 22 number 9 november 1990 pp 538 - 549
// online at http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf
@@ -164,8 +168,10 @@ public:
return -a;
}
private:
double a;
double b;
double c;
};
+
+#endif

Просмотреть файл

@ -0,0 +1,27 @@
# HG changeset patch
# Parent b12f9a408740aa5fd93c296a7d41e1b5f54c1b20
Bug 974900 - #undef interface defined by windows headers - r=gw280
diff --git a/gfx/skia/trunk/src/gpu/gl/GrGLCaps.h b/gfx/skia/trunk/src/gpu/gl/GrGLCaps.h
--- a/gfx/skia/trunk/src/gpu/gl/GrGLCaps.h
+++ b/gfx/skia/trunk/src/gpu/gl/GrGLCaps.h
@@ -9,16 +9,19 @@
#ifndef GrGLCaps_DEFINED
#define GrGLCaps_DEFINED
#include "GrDrawTargetCaps.h"
#include "GrGLStencilBuffer.h"
#include "SkTArray.h"
#include "SkTDArray.h"
+// defined in Windows headers
+#undef interface
+
class GrGLContextInfo;
/**
* Stores some capabilities of a GL context. Most are determined by the GL
* version and the extensions string. It also tracks formats that have passed
* the FBO completeness test.
*/
class GrGLCaps : public GrDrawTargetCaps {

Просмотреть файл

@ -5,6 +5,9 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef SkImages_DEFINED
#define SkImages_DEFINED
class SkImages { class SkImages {
public: public:
/** /**
@ -12,3 +15,5 @@ public:
*/ */
static void InitializeFlattenables(); static void InitializeFlattenables();
}; };
#endif

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше