зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to b2g-inbound
This commit is contained in:
Коммит
a7ab8df169
|
@ -371,29 +371,30 @@ exports.testTabMove = function(assert, done) {
|
|||
};
|
||||
|
||||
exports.testIgnoreClosing = function(assert, done) {
|
||||
let originalWindow = browserWindows.activeWindow;
|
||||
let originalWindow = viewFor(browserWindows.activeWindow);
|
||||
openBrowserWindow(function(window, browser) {
|
||||
let url = "data:text/html;charset=utf-8,foobar";
|
||||
onFocus(window).then(() => {
|
||||
let url = "data:text/html;charset=utf-8,foobar";
|
||||
|
||||
assert.equal(tabs.length, 2, "should be two windows open each with one tab");
|
||||
assert.equal(tabs.length, 2, "should be two windows open each with one tab");
|
||||
|
||||
tabs.on('ready', function onReady(tab) {
|
||||
tabs.removeListener('ready', onReady);
|
||||
tabs.on('ready', function onReady(tab) {
|
||||
tabs.removeListener('ready', onReady);
|
||||
|
||||
let win = tab.window;
|
||||
assert.equal(win.tabs.length, 2, "should be two tabs in the new window");
|
||||
assert.equal(tabs.length, 3, "should be three tabs in total");
|
||||
let win = tab.window;
|
||||
assert.equal(win.tabs.length, 2, "should be two tabs in the new window");
|
||||
assert.equal(tabs.length, 3, "should be three tabs in total");
|
||||
|
||||
tab.close(function() {
|
||||
assert.equal(win.tabs.length, 1, "should be one tab in the new window");
|
||||
assert.equal(tabs.length, 2, "should be two tabs in total");
|
||||
tab.close(function() {
|
||||
assert.equal(win.tabs.length, 1, "should be one tab in the new window");
|
||||
assert.equal(tabs.length, 2, "should be two tabs in total");
|
||||
|
||||
originalWindow.once("activate", done);
|
||||
close(window);
|
||||
close(window).then(onFocus(originalWindow)).then(done).then(null, assert.fail);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
tabs.open(url);
|
||||
tabs.open(url);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ pref("browser.uitour.requireSecure", true);
|
|||
pref("browser.uitour.themeOrigin", "https://addons.mozilla.org/%LOCALE%/firefox/themes/");
|
||||
pref("browser.uitour.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tour/");
|
||||
// This is used as a regexp match against the page's URL.
|
||||
pref("browser.uitour.readerViewTrigger", "^https:\/\/www\.mozilla\.org\/[^\/]+\/firefox\/reading\/start");
|
||||
pref("browser.uitour.readerViewTrigger", "^https:\\/\\/www\\.mozilla\\.org\\/[^\\/]+\\/firefox\\/reading\\/start");
|
||||
|
||||
pref("browser.customizemode.tip0.shown", false);
|
||||
pref("browser.customizemode.tip0.learnMoreUrl", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/customize");
|
||||
|
@ -1880,12 +1880,9 @@ pref("dom.ipc.reportProcessHangs", false);
|
|||
pref("dom.ipc.reportProcessHangs", true);
|
||||
#endif
|
||||
|
||||
// Enable ReadingList browser UI by default.
|
||||
pref("browser.readinglist.enabled", true);
|
||||
pref("browser.readinglist.enabled", false);
|
||||
pref("browser.readinglist.sidebarEverOpened", false);
|
||||
|
||||
// Enable the readinglist engine by default.
|
||||
pref("readinglist.scheduler.enabled", true);
|
||||
pref("readinglist.scheduler.enabled", false);
|
||||
pref("readinglist.server", "https://readinglist.services.mozilla.com/v1");
|
||||
|
||||
// Don't limit how many nodes we care about on desktop:
|
||||
|
|
|
@ -8,9 +8,16 @@
|
|||
* Tests that we build a working leftpane in various corruption situations.
|
||||
*/
|
||||
|
||||
function run_test() {
|
||||
// Used to store the original leftPaneFolderId getter.
|
||||
let gLeftPaneFolderIdGetter;
|
||||
let gAllBookmarksFolderIdGetter;
|
||||
// Used to store the original left Pane status as a JSON string.
|
||||
let gReferenceHierarchy;
|
||||
let gLeftPaneFolderId;
|
||||
|
||||
add_task(function* () {
|
||||
// We want empty roots.
|
||||
remove_all_bookmarks();
|
||||
yield PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
// Sanity check.
|
||||
Assert.ok(!!PlacesUIUtils);
|
||||
|
@ -21,17 +28,8 @@ function run_test() {
|
|||
gAllBookmarksFolderIdGetter = Object.getOwnPropertyDescriptor(PlacesUIUtils, "allBookmarksFolderId");
|
||||
Assert.equal(typeof(gAllBookmarksFolderIdGetter.get), "function");
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
do_register_cleanup(remove_all_bookmarks);
|
||||
|
||||
// Used to store the original leftPaneFolderId getter.
|
||||
let gLeftPaneFolderIdGetter;
|
||||
let gAllBookmarksFolderIdGetter;
|
||||
// Used to store the original left Pane status as a JSON string.
|
||||
let gReferenceHierarchy;
|
||||
let gLeftPaneFolderId;
|
||||
do_register_cleanup(() => PlacesUtils.bookmarks.eraseEverything());
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
// Add a third party bogus annotated item. Should not be removed.
|
||||
|
|
|
@ -15,6 +15,7 @@ Cu.import("resource://gre/modules/Timer.jsm");
|
|||
do_get_profile();
|
||||
|
||||
let prefs = new Preferences("readinglist.scheduler.");
|
||||
prefs.set("enabled", true);
|
||||
|
||||
function promiseObserver(topic) {
|
||||
return new Promise(resolve => {
|
||||
|
|
|
@ -1829,6 +1829,7 @@ MarkupContainer.prototype = {
|
|||
this.hovered = false;
|
||||
this.markup.navigate(this);
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
// Start dragging the container after a delay.
|
||||
this.markup._dragStartEl = target;
|
||||
|
@ -2145,7 +2146,7 @@ MarkupElementContainer.prototype = Heritage.extend(MarkupContainer.prototype, {
|
|||
this.tooltipData.data = promise.resolve(res);
|
||||
});
|
||||
}, () => {
|
||||
this.tooltipData.data = promise.reject();
|
||||
this.tooltipData.data = promise.resolve({});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -2165,9 +2166,11 @@ MarkupElementContainer.prototype = Heritage.extend(MarkupContainer.prototype, {
|
|||
}
|
||||
|
||||
return this.tooltipData.data.then(({data, size}) => {
|
||||
tooltip.setImageContent(data, size);
|
||||
}, () => {
|
||||
tooltip.setBrokenImageContent();
|
||||
if (data && size) {
|
||||
tooltip.setImageContent(data, size);
|
||||
} else {
|
||||
tooltip.setBrokenImageContent();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -68,12 +68,14 @@ skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
|
|||
skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
|
||||
[browser_markupview_events_jquery_2.1.1.js]
|
||||
skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
|
||||
[browser_markupview_load_01.js]
|
||||
[browser_markupview_html_edit_01.js]
|
||||
[browser_markupview_html_edit_02.js]
|
||||
[browser_markupview_html_edit_03.js]
|
||||
[browser_markupview_image_tooltip.js]
|
||||
[browser_markupview_keybindings_01.js]
|
||||
[browser_markupview_keybindings_02.js]
|
||||
[browser_markupview_keybindings_03.js]
|
||||
[browser_markupview_mutation_01.js]
|
||||
[browser_markupview_mutation_02.js]
|
||||
[browser_markupview_navigation.js]
|
||||
|
|
|
@ -21,7 +21,8 @@ add_task(function*() {
|
|||
target: el.tagLine,
|
||||
pageX: rect.x,
|
||||
pageY: rect.y,
|
||||
stopPropagation: function() {}
|
||||
stopPropagation: function() {},
|
||||
preventDefault: function() {}
|
||||
});
|
||||
|
||||
is(el.isDragging, false, "isDragging should not be set to true immedietly");
|
||||
|
|
|
@ -64,7 +64,8 @@ function* dragContainer(selector, targetOffset, inspector) {
|
|||
target: container.tagLine,
|
||||
pageX: rect.x,
|
||||
pageY: rect.y,
|
||||
stopPropagation: function() {}
|
||||
stopPropagation: function() {},
|
||||
preventDefault: function() {}
|
||||
});
|
||||
|
||||
let targetX = rect.x + targetOffset.x,
|
||||
|
|
|
@ -157,16 +157,6 @@ const TEST_DATA = [
|
|||
" alert(8);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":894",
|
||||
|
@ -197,6 +187,16 @@ const TEST_DATA = [
|
|||
" return returnValue;\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":894",
|
||||
|
|
|
@ -171,16 +171,6 @@ const TEST_DATA = [
|
|||
" alert(8);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":1224",
|
||||
|
@ -221,6 +211,16 @@ const TEST_DATA = [
|
|||
" return returnValue;\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":1224",
|
||||
|
|
|
@ -103,16 +103,6 @@ const TEST_DATA = [
|
|||
" alert(8);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
|
@ -124,6 +114,16 @@ const TEST_DATA = [
|
|||
" return typeof m === K || a && m.event.triggered === a.type ? void 0 : m.event.dispatch.apply(k.elem, arguments)\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
|
@ -141,17 +141,6 @@ const TEST_DATA = [
|
|||
{
|
||||
selector: "#livediv",
|
||||
expected: [
|
||||
{
|
||||
type: "dragleave",
|
||||
filename: TEST_URL + ":30",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler3 = function liveDivDragLeave() {\n" +
|
||||
" alert(3);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragend",
|
||||
filename: TEST_URL + ":31",
|
||||
|
@ -164,14 +153,14 @@ const TEST_DATA = [
|
|||
"}"
|
||||
},
|
||||
{
|
||||
type: "drop",
|
||||
filename: TEST_URL + ":32",
|
||||
type: "dragleave",
|
||||
filename: TEST_URL + ":30",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler5 = function liveDivDrop() {\n" +
|
||||
" alert(5);\n" +
|
||||
handler: "var handler3 = function liveDivDragLeave() {\n" +
|
||||
" alert(3);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
|
@ -184,6 +173,17 @@ const TEST_DATA = [
|
|||
handler: "var handler6 = function liveDivDragOver() {\n" +
|
||||
" alert(6);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "drop",
|
||||
filename: TEST_URL + ":32",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler5 = function liveDivDrop() {\n" +
|
||||
" alert(5);\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -142,16 +142,6 @@ const TEST_DATA = [
|
|||
" alert(8);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":24",
|
||||
|
@ -166,6 +156,16 @@ const TEST_DATA = [
|
|||
" return val;\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":24",
|
||||
|
|
|
@ -16,17 +16,6 @@ const TEST_DATA = [
|
|||
{
|
||||
selector: "html",
|
||||
expected: [
|
||||
{
|
||||
type: "unload",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "function(H) {\n" +
|
||||
" n(this).unbind(H, D);\n" +
|
||||
" return (E || G).apply(this, arguments)\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
|
@ -108,7 +97,7 @@ const TEST_DATA = [
|
|||
"}"
|
||||
},
|
||||
{
|
||||
type: "unload",
|
||||
type: "load",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
|
@ -119,7 +108,18 @@ const TEST_DATA = [
|
|||
"}"
|
||||
},
|
||||
{
|
||||
type: "load",
|
||||
type: "unload",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "function(H) {\n" +
|
||||
" n(this).unbind(H, D);\n" +
|
||||
" return (E || G).apply(this, arguments)\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "unload",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
|
@ -154,16 +154,6 @@ const TEST_DATA = [
|
|||
" alert(8);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
|
@ -175,6 +165,16 @@ const TEST_DATA = [
|
|||
" return typeof n !== \"undefined\" && !n.event.triggered ? n.event.handle.apply(arguments.callee.elem, arguments) : g\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":19",
|
||||
|
|
|
@ -121,16 +121,6 @@ const TEST_DATA = [
|
|||
" alert(8);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":48",
|
||||
|
@ -142,6 +132,16 @@ const TEST_DATA = [
|
|||
" return typeof c !== \"undefined\" && !c.event.triggered ? c.event.handle.apply(j.elem, arguments) : w\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":48",
|
||||
|
@ -169,17 +169,6 @@ const TEST_DATA = [
|
|||
" alert(1);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragstart",
|
||||
filename: TEST_URL + ":29",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler2 = function liveDivDragStart() {\n" +
|
||||
" alert(2);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dblclick",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":17",
|
||||
|
@ -228,6 +217,17 @@ const TEST_DATA = [
|
|||
" return b\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragstart",
|
||||
filename: TEST_URL + ":29",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler2 = function liveDivDragStart() {\n" +
|
||||
" alert(2);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragstart",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":17",
|
||||
|
|
|
@ -118,16 +118,6 @@ const TEST_DATA = [
|
|||
" alert(8);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
|
@ -139,6 +129,16 @@ const TEST_DATA = [
|
|||
" return typeof f != \"undefined\" && (!a || f.event.triggered !== a.type) ? f.event.handle.apply(k.elem, arguments) : b\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
|
@ -166,39 +166,6 @@ const TEST_DATA = [
|
|||
" alert(1);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragstart",
|
||||
filename: TEST_URL + ":29",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler2 = function liveDivDragStart() {\n" +
|
||||
" alert(2);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragleave",
|
||||
filename: TEST_URL + ":30",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler3 = function liveDivDragLeave() {\n" +
|
||||
" alert(3);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragend",
|
||||
filename: TEST_URL + ":31",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler4 = function liveDivDragEnd() {\n" +
|
||||
" alert(4);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dblclick",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
|
@ -244,7 +211,18 @@ const TEST_DATA = [
|
|||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragstart",
|
||||
type: "dragend",
|
||||
filename: TEST_URL + ":31",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler4 = function liveDivDragEnd() {\n" +
|
||||
" alert(4);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragend",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
|
@ -287,6 +265,17 @@ const TEST_DATA = [
|
|||
" }\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragleave",
|
||||
filename: TEST_URL + ":30",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler3 = function liveDivDragLeave() {\n" +
|
||||
" alert(3);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragleave",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
|
@ -332,7 +321,18 @@ const TEST_DATA = [
|
|||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragend",
|
||||
type: "dragstart",
|
||||
filename: TEST_URL + ":29",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler2 = function liveDivDragStart() {\n" +
|
||||
" alert(2);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragstart",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":16",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
|
|
|
@ -118,16 +118,6 @@ const TEST_DATA = [
|
|||
" alert(8);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
|
@ -139,6 +129,16 @@ const TEST_DATA = [
|
|||
" return typeof f != \"undefined\" && (!a || f.event.triggered !== a.type) ? f.event.dispatch.apply(i.elem, arguments) : b\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
|
@ -167,14 +167,14 @@ const TEST_DATA = [
|
|||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragstart",
|
||||
filename: TEST_URL + ":29",
|
||||
type: "dragend",
|
||||
filename: TEST_URL + ":31",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler2 = function liveDivDragStart() {\n" +
|
||||
" alert(2);\n" +
|
||||
handler: "var handler4 = function liveDivDragEnd() {\n" +
|
||||
" alert(4);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
|
@ -189,14 +189,25 @@ const TEST_DATA = [
|
|||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragend",
|
||||
filename: TEST_URL + ":31",
|
||||
type: "dragover",
|
||||
filename: TEST_URL + ":33",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler4 = function liveDivDragEnd() {\n" +
|
||||
" alert(4);\n" +
|
||||
handler: "var handler6 = function liveDivDragOver() {\n" +
|
||||
" alert(6);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragstart",
|
||||
filename: TEST_URL + ":29",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler2 = function liveDivDragStart() {\n" +
|
||||
" alert(2);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
|
@ -209,17 +220,6 @@ const TEST_DATA = [
|
|||
handler: "var handler5 = function liveDivDrop() {\n" +
|
||||
" alert(5);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragover",
|
||||
filename: TEST_URL + ":33",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler6 = function liveDivDragOver() {\n" +
|
||||
" alert(6);\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -102,16 +102,6 @@ const TEST_DATA = [
|
|||
" alert(8);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
|
@ -123,6 +113,16 @@ const TEST_DATA = [
|
|||
" return typeof n !== U && n.event.triggered !== b.type ? n.event.dispatch.apply(a, arguments) : void 0\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL + ":36",
|
||||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "var handler9 = function divKeyDown() {\n" +
|
||||
" alert(9);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "keydown",
|
||||
filename: TEST_URL_ROOT + TEST_LIB + ":3",
|
||||
|
@ -139,17 +139,6 @@ const TEST_DATA = [
|
|||
{
|
||||
selector: "#livediv",
|
||||
expected: [
|
||||
{
|
||||
type: "dragleave",
|
||||
filename: TEST_URL + ":30",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler3 = function liveDivDragLeave() {\n" +
|
||||
" alert(3);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "dragend",
|
||||
filename: TEST_URL + ":31",
|
||||
|
@ -162,14 +151,14 @@ const TEST_DATA = [
|
|||
"}"
|
||||
},
|
||||
{
|
||||
type: "drop",
|
||||
filename: TEST_URL + ":32",
|
||||
type: "dragleave",
|
||||
filename: TEST_URL + ":30",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler5 = function liveDivDrop() {\n" +
|
||||
" alert(5);\n" +
|
||||
handler: "var handler3 = function liveDivDragLeave() {\n" +
|
||||
" alert(3);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
|
@ -182,6 +171,17 @@ const TEST_DATA = [
|
|||
handler: "var handler6 = function liveDivDragOver() {\n" +
|
||||
" alert(6);\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "drop",
|
||||
filename: TEST_URL + ":32",
|
||||
attributes: [
|
||||
"jQuery",
|
||||
"Live"
|
||||
],
|
||||
handler: "var handler5 = function liveDivDrop() {\n" +
|
||||
" alert(5);\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that selecting a node with the mouse (by clicking on the line) focuses
|
||||
// the first focusable element in the corresponding MarkupContainer so that the
|
||||
// keyboard can be used immediately.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf8,<div></div>Text node";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector, toolbox} = yield addTab(TEST_URL).then(openInspector);
|
||||
let {walker} = inspector;
|
||||
|
||||
info("Select the test node to have the 2 test containers visible");
|
||||
yield selectNode("div", inspector);
|
||||
|
||||
let divFront = yield walker.querySelector(walker.rootNode, "div");
|
||||
let textFront = yield walker.nextSibling(divFront);
|
||||
|
||||
info("Click on the MarkupContainer element for the text node");
|
||||
yield clickContainer(textFront, inspector);
|
||||
is(inspector.markup.doc.activeElement,
|
||||
getContainerForNodeFront(textFront, inspector).editor.value,
|
||||
"The currently focused element is the node's text content");
|
||||
|
||||
info("Click on the MarkupContainer element for the <div> node");
|
||||
yield clickContainer(divFront, inspector);
|
||||
is(inspector.markup.doc.activeElement,
|
||||
getContainerForNodeFront(divFront, inspector).editor.tag,
|
||||
"The currently focused element is the div's tagname");
|
||||
});
|
|
@ -0,0 +1,70 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that selecting an element with the 'Inspect Element' context
|
||||
// menu during a page reload doesn't cause the markup view to become empty.
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1036324
|
||||
|
||||
const server = createTestHTTPServer();
|
||||
|
||||
// Register a slow image handler so we can simulate a long time between
|
||||
// a reload and the load event firing.
|
||||
server.registerContentType("gif", "image/gif");
|
||||
server.registerPathHandler("/slow.gif", function (metadata, response) {
|
||||
info ("Image has been requested");
|
||||
response.processAsync();
|
||||
setTimeout(() => {
|
||||
info ("Image is responding");
|
||||
response.finish();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
// Test page load events.
|
||||
const TEST_URL = "data:text/html," +
|
||||
"<!DOCTYPE html>" +
|
||||
"<head><meta charset='utf-8' /></head>" +
|
||||
"<body>" +
|
||||
"<p>Slow script</p>" +
|
||||
"<img src='http://localhost:" + server.identity.primaryPort + "/slow.gif' /></script>" +
|
||||
"</body>" +
|
||||
"</html>";
|
||||
|
||||
add_task(function*() {
|
||||
let tab = yield addTab(TEST_URL);
|
||||
let {inspector} = yield openInspector();
|
||||
let domContentLoaded = waitForLinkedBrowserEvent(tab, "DOMContentLoaded");
|
||||
let pageLoaded = waitForLinkedBrowserEvent(tab, "load");
|
||||
|
||||
ok (inspector.markup, "There is a markup view");
|
||||
|
||||
// Select an element while the tab is in the middle of a slow reload.
|
||||
reloadTab();
|
||||
yield domContentLoaded;
|
||||
yield chooseWithInspectElementContextMenu("img");
|
||||
yield pageLoaded;
|
||||
|
||||
yield inspector.once("markuploaded");
|
||||
ok (inspector.markup, "There is a markup view");
|
||||
is (inspector.markup._elt.children.length, 1, "The markup view is rendering");
|
||||
});
|
||||
|
||||
function* chooseWithInspectElementContextMenu(selector) {
|
||||
yield executeInContent("Test:SynthesizeMouse", {
|
||||
center: true,
|
||||
selector: selector,
|
||||
options: {type: "contextmenu", button: 2}
|
||||
});
|
||||
executeInContent("Test:SynthesizeKey", {key: "Q", options: {}});
|
||||
}
|
||||
|
||||
function waitForLinkedBrowserEvent(tab, event) {
|
||||
let def = promise.defer();
|
||||
tab.linkedBrowser.addEventListener(event, function cb() {
|
||||
tab.linkedBrowser.removeEventListener(event, cb, true);
|
||||
def.resolve();
|
||||
}, true);
|
||||
return def.promise;
|
||||
}
|
|
@ -172,6 +172,13 @@ function executeInContent(name, data={}, objects={}, expectResponse=true) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the current tab location.
|
||||
*/
|
||||
function reloadTab() {
|
||||
return executeInContent("devtools:test:reload", {}, {}, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple DOM node accesor function that takes either a node or a string css
|
||||
* selector as argument and returns the corresponding node
|
||||
|
@ -647,3 +654,34 @@ function* waitForMultipleChildrenUpdates(inspector) {
|
|||
return yield waitForMultipleChildrenUpdates(inspector);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an HTTP server that can be used to simulate custom requests within
|
||||
* a test. It is automatically cleaned up when the test ends, so no need to
|
||||
* call `destroy`.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Httpd.js/HTTP_server_for_unit_tests
|
||||
* for more information about how to register handlers.
|
||||
*
|
||||
* The server can be accessed like:
|
||||
*
|
||||
* const server = createTestHTTPServer();
|
||||
* let url = "http://localhost: " + server.identity.primaryPort + "/path";
|
||||
*
|
||||
* @returns {HttpServer}
|
||||
*/
|
||||
function createTestHTTPServer() {
|
||||
const {HttpServer} = Cu.import("resource://testing-common/httpd.js", {});
|
||||
let server = new HttpServer();
|
||||
|
||||
registerCleanupFunction(function* cleanup() {
|
||||
let destroyed = promise.defer();
|
||||
server.stop(() => {
|
||||
destroyed.resolve();
|
||||
});
|
||||
yield destroyed.promise;
|
||||
});
|
||||
|
||||
server.start(-1);
|
||||
return server;
|
||||
}
|
||||
|
|
|
@ -1230,6 +1230,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
break;
|
||||
case "remoteAddress":
|
||||
requestItem.attachment.remoteAddress = value;
|
||||
this.updateMenuView(requestItem, key, value);
|
||||
break;
|
||||
case "remotePort":
|
||||
requestItem.attachment.remotePort = value;
|
||||
|
@ -1382,6 +1383,11 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
domain.setAttribute("tooltiptext", hostPort);
|
||||
break;
|
||||
}
|
||||
case "remoteAddress":
|
||||
let domain = $(".requests-menu-domain", target);
|
||||
let tooltip = domain.getAttribute("value") + " (" + aValue + ")";
|
||||
domain.setAttribute("tooltiptext", tooltip);
|
||||
break;
|
||||
case "securityState": {
|
||||
let tooltip = L10N.getStr("netmonitor.security.state." + aValue);
|
||||
let icon = $(".requests-security-state-icon", target);
|
||||
|
|
|
@ -275,34 +275,37 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
|
|||
let name = uri.fileName || "/";
|
||||
let query = uri.query;
|
||||
let hostPort = uri.hostPort;
|
||||
let remoteAddress = attachment.remoteAddress;
|
||||
|
||||
if (fuzzyUrl) {
|
||||
ok(attachment.method.startsWith(aMethod), "The attached method is incorrect.");
|
||||
ok(attachment.url.startsWith(aUrl), "The attached url is incorrect.");
|
||||
ok(attachment.method.startsWith(aMethod), "The attached method is correct.");
|
||||
ok(attachment.url.startsWith(aUrl), "The attached url is correct.");
|
||||
} else {
|
||||
is(attachment.method, aMethod, "The attached method is incorrect.");
|
||||
is(attachment.url, aUrl, "The attached url is incorrect.");
|
||||
is(attachment.method, aMethod, "The attached method is correct.");
|
||||
is(attachment.url, aUrl, "The attached url is correct.");
|
||||
}
|
||||
|
||||
is(target.querySelector(".requests-menu-method").getAttribute("value"),
|
||||
aMethod, "The displayed method is incorrect.");
|
||||
aMethod, "The displayed method is correct.");
|
||||
|
||||
if (fuzzyUrl) {
|
||||
ok(target.querySelector(".requests-menu-file").getAttribute("value").startsWith(
|
||||
name + (query ? "?" + query : "")), "The displayed file is incorrect.");
|
||||
name + (query ? "?" + query : "")), "The displayed file is correct.");
|
||||
ok(target.querySelector(".requests-menu-file").getAttribute("tooltiptext").startsWith(
|
||||
name + (query ? "?" + query : "")), "The tooltip file is incorrect.");
|
||||
name + (query ? "?" + query : "")), "The tooltip file is correct.");
|
||||
} else {
|
||||
is(target.querySelector(".requests-menu-file").getAttribute("value"),
|
||||
name + (query ? "?" + query : ""), "The displayed file is incorrect.");
|
||||
name + (query ? "?" + query : ""), "The displayed file is correct.");
|
||||
is(target.querySelector(".requests-menu-file").getAttribute("tooltiptext"),
|
||||
name + (query ? "?" + query : ""), "The tooltip file is incorrect.");
|
||||
name + (query ? "?" + query : ""), "The tooltip file is correct.");
|
||||
}
|
||||
|
||||
is(target.querySelector(".requests-menu-domain").getAttribute("value"),
|
||||
hostPort, "The displayed domain is incorrect.");
|
||||
hostPort, "The displayed domain is correct.");
|
||||
|
||||
let domainTooltip = hostPort + (remoteAddress ? " (" + remoteAddress + ")" : "");
|
||||
is(target.querySelector(".requests-menu-domain").getAttribute("tooltiptext"),
|
||||
hostPort, "The tooltip domain is incorrect.");
|
||||
domainTooltip, "The tooltip domain is correct.");
|
||||
|
||||
if (status !== undefined) {
|
||||
let value = target.querySelector(".requests-menu-status").getAttribute("code");
|
||||
|
@ -311,54 +314,54 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
|
|||
info("Displayed status: " + value);
|
||||
info("Displayed code: " + codeValue);
|
||||
info("Tooltip status: " + tooltip);
|
||||
is(value, status, "The displayed status is incorrect.");
|
||||
is(codeValue, status, "The displayed status code is incorrect.");
|
||||
is(tooltip, status + " " + statusText, "The tooltip status is incorrect.");
|
||||
is(value, status, "The displayed status is correct.");
|
||||
is(codeValue, status, "The displayed status code is correct.");
|
||||
is(tooltip, status + " " + statusText, "The tooltip status is correct.");
|
||||
}
|
||||
if (type !== undefined) {
|
||||
let value = target.querySelector(".requests-menu-type").getAttribute("value");
|
||||
let tooltip = target.querySelector(".requests-menu-type").getAttribute("tooltiptext");
|
||||
info("Displayed type: " + value);
|
||||
info("Tooltip type: " + tooltip);
|
||||
is(value, type, "The displayed type is incorrect.");
|
||||
is(tooltip, fullMimeType, "The tooltip type is incorrect.");
|
||||
is(value, type, "The displayed type is correct.");
|
||||
is(tooltip, fullMimeType, "The tooltip type is correct.");
|
||||
}
|
||||
if (transferred !== undefined) {
|
||||
let value = target.querySelector(".requests-menu-transferred").getAttribute("value");
|
||||
let tooltip = target.querySelector(".requests-menu-transferred").getAttribute("tooltiptext");
|
||||
info("Displayed transferred size: " + value);
|
||||
info("Tooltip transferred size: " + tooltip);
|
||||
is(value, transferred, "The displayed transferred size is incorrect.");
|
||||
is(tooltip, transferred, "The tooltip transferred size is incorrect.");
|
||||
is(value, transferred, "The displayed transferred size is correct.");
|
||||
is(tooltip, transferred, "The tooltip transferred size is correct.");
|
||||
}
|
||||
if (size !== undefined) {
|
||||
let value = target.querySelector(".requests-menu-size").getAttribute("value");
|
||||
let tooltip = target.querySelector(".requests-menu-size").getAttribute("tooltiptext");
|
||||
info("Displayed size: " + value);
|
||||
info("Tooltip size: " + tooltip);
|
||||
is(value, size, "The displayed size is incorrect.");
|
||||
is(tooltip, size, "The tooltip size is incorrect.");
|
||||
is(value, size, "The displayed size is correct.");
|
||||
is(tooltip, size, "The tooltip size is correct.");
|
||||
}
|
||||
if (time !== undefined) {
|
||||
let value = target.querySelector(".requests-menu-timings-total").getAttribute("value");
|
||||
let tooltip = target.querySelector(".requests-menu-timings-total").getAttribute("tooltiptext");
|
||||
info("Displayed time: " + value);
|
||||
info("Tooltip time: " + tooltip);
|
||||
ok(~~(value.match(/[0-9]+/)) >= 0, "The displayed time is incorrect.");
|
||||
ok(~~(tooltip.match(/[0-9]+/)) >= 0, "The tooltip time is incorrect.");
|
||||
ok(~~(value.match(/[0-9]+/)) >= 0, "The displayed time is correct.");
|
||||
ok(~~(tooltip.match(/[0-9]+/)) >= 0, "The tooltip time is correct.");
|
||||
}
|
||||
|
||||
if (visibleIndex != -1) {
|
||||
if (visibleIndex % 2 == 0) {
|
||||
ok(aRequestItem.target.hasAttribute("even"),
|
||||
"Unexpected 'even' attribute for " + aRequestItem.value);
|
||||
aRequestItem.value + " should have 'even' attribute.");
|
||||
ok(!aRequestItem.target.hasAttribute("odd"),
|
||||
"Unexpected 'odd' attribute for " + aRequestItem.value);
|
||||
aRequestItem.value + " shouldn't have 'odd' attribute.");
|
||||
} else {
|
||||
ok(!aRequestItem.target.hasAttribute("even"),
|
||||
"Unexpected 'even' attribute for " + aRequestItem.value);
|
||||
aRequestItem.value + " shouldn't have 'even' attribute.");
|
||||
ok(aRequestItem.target.hasAttribute("odd"),
|
||||
"Unexpected 'odd' attribute for " + aRequestItem.value);
|
||||
aRequestItem.value + " should have 'odd' attribute.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
const Cu = Components.utils;
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
devtools.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise");
|
||||
devtools.lazyImporter(this, "Task", "resource://gre/modules/Task.jsm", "Task");
|
||||
const loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader);
|
||||
let EventUtils = {};
|
||||
loader.loadSubScript("chrome://marionette/content/EventUtils.js", EventUtils);
|
||||
|
||||
addMessageListener("devtools:test:history", function ({ data }) {
|
||||
content.history[data.direction]();
|
||||
|
@ -189,6 +192,55 @@ addMessageListener("devtools:test:setAttribute", function(msg) {
|
|||
sendAsyncMessage("devtools:test:setAttribute");
|
||||
});
|
||||
|
||||
/**
|
||||
* Synthesize a mouse event on an element. This handler doesn't send a message
|
||||
* back. Consumers should listen to specific events on the inspector/highlighter
|
||||
* to know when the event got synthesized.
|
||||
* @param {Object} msg The msg.data part expects the following properties:
|
||||
* - {Number} x
|
||||
* - {Number} y
|
||||
* - {Boolean} center If set to true, x/y will be ignored and
|
||||
* synthesizeMouseAtCenter will be used instead
|
||||
* - {Object} options Other event options
|
||||
* - {String} selector An optional selector that will be used to find the node to
|
||||
* synthesize the event on, if msg.objects doesn't contain the CPOW.
|
||||
* The msg.objects part should be the element.
|
||||
* @param {Object} data Event detail properties:
|
||||
*/
|
||||
addMessageListener("Test:SynthesizeMouse", function(msg) {
|
||||
let {x, y, center, options, selector} = msg.data;
|
||||
let {node} = msg.objects;
|
||||
|
||||
if (!node && selector) {
|
||||
node = superQuerySelector(selector);
|
||||
}
|
||||
|
||||
if (center) {
|
||||
EventUtils.synthesizeMouseAtCenter(node, options, node.ownerDocument.defaultView);
|
||||
} else {
|
||||
EventUtils.synthesizeMouse(node, x, y, options, node.ownerDocument.defaultView);
|
||||
}
|
||||
|
||||
// Most consumers won't need to listen to this message, unless they want to
|
||||
// wait for the mouse event to be synthesized and don't have another event
|
||||
// to listen to instead.
|
||||
sendAsyncMessage("Test:SynthesizeMouse");
|
||||
});
|
||||
|
||||
/**
|
||||
* Synthesize a key event for an element. This handler doesn't send a message
|
||||
* back. Consumers should listen to specific events on the inspector/highlighter
|
||||
* to know when the event got synthesized.
|
||||
* @param {Object} msg The msg.data part expects the following properties:
|
||||
* - {String} key
|
||||
* - {Object} options
|
||||
*/
|
||||
addMessageListener("Test:SynthesizeKey", function(msg) {
|
||||
let {key, options} = msg.data;
|
||||
|
||||
EventUtils.synthesizeKey(key, options, content);
|
||||
});
|
||||
|
||||
/**
|
||||
* Like document.querySelector but can go into iframes too.
|
||||
* ".container iframe || .sub-container div" will first try to find the node
|
||||
|
|
|
@ -307,7 +307,6 @@ skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug intermittent)
|
|||
[browser_webconsole_certificate_messages.js]
|
||||
skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
|
||||
[browser_webconsole_show_subresource_security_errors.js]
|
||||
skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
|
||||
[browser_webconsole_cached_autocomplete.js]
|
||||
[browser_webconsole_change_font_size.js]
|
||||
[browser_webconsole_chrome.js]
|
||||
|
|
|
@ -3,37 +3,37 @@
|
|||
* 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 "AnimationPlayer.h"
|
||||
#include "Animation.h"
|
||||
#include "AnimationUtils.h"
|
||||
#include "mozilla/dom/AnimationPlayerBinding.h"
|
||||
#include "mozilla/dom/AnimationBinding.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include "AnimationCommon.h" // For AnimationPlayerCollection,
|
||||
#include "AnimationCommon.h" // For AnimationCollection,
|
||||
// CommonAnimationManager
|
||||
#include "nsIDocument.h" // For nsIDocument
|
||||
#include "nsIPresShell.h" // For nsIPresShell
|
||||
#include "nsLayoutUtils.h" // For PostRestyleEvent (remove after bug 1073336)
|
||||
#include "PendingPlayerTracker.h" // For PendingPlayerTracker
|
||||
#include "PendingAnimationTracker.h" // For PendingAnimationTracker
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationPlayer, mTimeline,
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Animation, mTimeline,
|
||||
mEffect, mReady, mFinished)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(AnimationPlayer)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(AnimationPlayer)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AnimationPlayer)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Animation)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Animation)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Animation)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
JSObject*
|
||||
AnimationPlayer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
Animation::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return dom::AnimationPlayerBinding::Wrap(aCx, this, aGivenProto);
|
||||
return dom::AnimationBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::SetStartTime(const Nullable<TimeDuration>& aNewStartTime)
|
||||
Animation::SetStartTime(const Nullable<TimeDuration>& aNewStartTime)
|
||||
{
|
||||
#if 1
|
||||
// Bug 1096776: once we support inactive/missing timelines we'll want to take
|
||||
|
@ -74,7 +74,7 @@ AnimationPlayer::SetStartTime(const Nullable<TimeDuration>& aNewStartTime)
|
|||
}
|
||||
|
||||
Nullable<TimeDuration>
|
||||
AnimationPlayer::GetCurrentTime() const
|
||||
Animation::GetCurrentTime() const
|
||||
{
|
||||
Nullable<TimeDuration> result;
|
||||
if (!mHoldTime.IsNull()) {
|
||||
|
@ -94,7 +94,7 @@ AnimationPlayer::GetCurrentTime() const
|
|||
|
||||
// Implements http://w3c.github.io/web-animations/#silently-set-the-current-time
|
||||
void
|
||||
AnimationPlayer::SilentlySetCurrentTime(const TimeDuration& aSeekTime)
|
||||
Animation::SilentlySetCurrentTime(const TimeDuration& aSeekTime)
|
||||
{
|
||||
if (!mHoldTime.IsNull() ||
|
||||
!mTimeline ||
|
||||
|
@ -115,7 +115,7 @@ AnimationPlayer::SilentlySetCurrentTime(const TimeDuration& aSeekTime)
|
|||
|
||||
// Implements http://w3c.github.io/web-animations/#set-the-current-time
|
||||
void
|
||||
AnimationPlayer::SetCurrentTime(const TimeDuration& aSeekTime)
|
||||
Animation::SetCurrentTime(const TimeDuration& aSeekTime)
|
||||
{
|
||||
SilentlySetCurrentTime(aSeekTime);
|
||||
|
||||
|
@ -132,7 +132,7 @@ AnimationPlayer::SetCurrentTime(const TimeDuration& aSeekTime)
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::SetPlaybackRate(double aPlaybackRate)
|
||||
Animation::SetPlaybackRate(double aPlaybackRate)
|
||||
{
|
||||
Nullable<TimeDuration> previousTime = GetCurrentTime();
|
||||
mPlaybackRate = aPlaybackRate;
|
||||
|
@ -144,7 +144,7 @@ AnimationPlayer::SetPlaybackRate(double aPlaybackRate)
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::SilentlySetPlaybackRate(double aPlaybackRate)
|
||||
Animation::SilentlySetPlaybackRate(double aPlaybackRate)
|
||||
{
|
||||
Nullable<TimeDuration> previousTime = GetCurrentTime();
|
||||
mPlaybackRate = aPlaybackRate;
|
||||
|
@ -156,7 +156,7 @@ AnimationPlayer::SilentlySetPlaybackRate(double aPlaybackRate)
|
|||
}
|
||||
|
||||
AnimationPlayState
|
||||
AnimationPlayer::PlayState() const
|
||||
Animation::PlayState() const
|
||||
{
|
||||
if (mPendingState != PendingState::NotPending) {
|
||||
return AnimationPlayState::Pending;
|
||||
|
@ -190,7 +190,7 @@ CreatePromise(DocumentTimeline* aTimeline, ErrorResult& aRv)
|
|||
}
|
||||
|
||||
Promise*
|
||||
AnimationPlayer::GetReady(ErrorResult& aRv)
|
||||
Animation::GetReady(ErrorResult& aRv)
|
||||
{
|
||||
if (!mReady) {
|
||||
mReady = CreatePromise(mTimeline, aRv); // Lazily create on demand
|
||||
|
@ -204,7 +204,7 @@ AnimationPlayer::GetReady(ErrorResult& aRv)
|
|||
}
|
||||
|
||||
Promise*
|
||||
AnimationPlayer::GetFinished(ErrorResult& aRv)
|
||||
Animation::GetFinished(ErrorResult& aRv)
|
||||
{
|
||||
if (!mFinished) {
|
||||
mFinished = CreatePromise(mTimeline, aRv); // Lazily create on demand
|
||||
|
@ -218,14 +218,14 @@ AnimationPlayer::GetFinished(ErrorResult& aRv)
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::Play(LimitBehavior aLimitBehavior)
|
||||
Animation::Play(LimitBehavior aLimitBehavior)
|
||||
{
|
||||
DoPlay(aLimitBehavior);
|
||||
PostUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::Pause()
|
||||
Animation::Pause()
|
||||
{
|
||||
// TODO: The DoPause() call should not be synchronous (bug 1109390). See
|
||||
// http://w3c.github.io/web-animations/#pausing-an-animation-section
|
||||
|
@ -234,25 +234,25 @@ AnimationPlayer::Pause()
|
|||
}
|
||||
|
||||
Nullable<double>
|
||||
AnimationPlayer::GetStartTimeAsDouble() const
|
||||
Animation::GetStartTimeAsDouble() const
|
||||
{
|
||||
return AnimationUtils::TimeDurationToDouble(mStartTime);
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::SetStartTimeAsDouble(const Nullable<double>& aStartTime)
|
||||
Animation::SetStartTimeAsDouble(const Nullable<double>& aStartTime)
|
||||
{
|
||||
return SetStartTime(AnimationUtils::DoubleToTimeDuration(aStartTime));
|
||||
}
|
||||
|
||||
|
||||
Nullable<double>
|
||||
AnimationPlayer::GetCurrentTimeAsDouble() const
|
||||
Animation::GetCurrentTimeAsDouble() const
|
||||
{
|
||||
return AnimationUtils::TimeDurationToDouble(GetCurrentTime());
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::SetCurrentTimeAsDouble(const Nullable<double>& aCurrentTime,
|
||||
Animation::SetCurrentTimeAsDouble(const Nullable<double>& aCurrentTime,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (aCurrentTime.IsNull()) {
|
||||
|
@ -266,7 +266,7 @@ AnimationPlayer::SetCurrentTimeAsDouble(const Nullable<double>& aCurrentTime,
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::SetEffect(KeyframeEffectReadonly* aEffect)
|
||||
Animation::SetEffect(KeyframeEffectReadonly* aEffect)
|
||||
{
|
||||
if (mEffect) {
|
||||
mEffect->SetParentTime(Nullable<TimeDuration>());
|
||||
|
@ -279,7 +279,7 @@ AnimationPlayer::SetEffect(KeyframeEffectReadonly* aEffect)
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::Tick()
|
||||
Animation::Tick()
|
||||
{
|
||||
// Since we are not guaranteed to get only one call per refresh driver tick,
|
||||
// it's possible that mPendingReadyTime is set to a time in the future.
|
||||
|
@ -292,9 +292,9 @@ AnimationPlayer::Tick()
|
|||
mPendingReadyTime.SetNull();
|
||||
}
|
||||
|
||||
if (IsPossiblyOrphanedPendingPlayer()) {
|
||||
if (IsPossiblyOrphanedPendingAnimation()) {
|
||||
MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(),
|
||||
"Orphaned pending players should have an active timeline");
|
||||
"Orphaned pending animtaions should have an active timeline");
|
||||
FinishPendingAt(mTimeline->GetCurrentTime().Value());
|
||||
}
|
||||
|
||||
|
@ -302,25 +302,26 @@ AnimationPlayer::Tick()
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::TriggerOnNextTick(const Nullable<TimeDuration>& aReadyTime)
|
||||
Animation::TriggerOnNextTick(const Nullable<TimeDuration>& aReadyTime)
|
||||
{
|
||||
// Normally we expect the play state to be pending but it's possible that,
|
||||
// due to the handling of possibly orphaned players in Tick(), this player got
|
||||
// started whilst still being in another document's pending player map.
|
||||
// due to the handling of possibly orphaned animations in Tick(), this
|
||||
// animation got started whilst still being in another document's pending
|
||||
// animation map.
|
||||
if (PlayState() != AnimationPlayState::Pending) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If aReadyTime.IsNull() we'll detect this in Tick() where we check for
|
||||
// orphaned players and trigger this animation anyway
|
||||
// orphaned animations and trigger this animation anyway
|
||||
mPendingReadyTime = aReadyTime;
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::TriggerNow()
|
||||
Animation::TriggerNow()
|
||||
{
|
||||
MOZ_ASSERT(PlayState() == AnimationPlayState::Pending,
|
||||
"Expected to start a pending player");
|
||||
"Expected to start a pending animation");
|
||||
MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(),
|
||||
"Expected an active timeline");
|
||||
|
||||
|
@ -328,7 +329,7 @@ AnimationPlayer::TriggerNow()
|
|||
}
|
||||
|
||||
Nullable<TimeDuration>
|
||||
AnimationPlayer::GetCurrentOrPendingStartTime() const
|
||||
Animation::GetCurrentOrPendingStartTime() const
|
||||
{
|
||||
Nullable<TimeDuration> result;
|
||||
|
||||
|
@ -349,7 +350,7 @@ AnimationPlayer::GetCurrentOrPendingStartTime() const
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::Cancel()
|
||||
Animation::Cancel()
|
||||
{
|
||||
if (mPendingState != PendingState::NotPending) {
|
||||
CancelPendingTasks();
|
||||
|
@ -371,7 +372,7 @@ AnimationPlayer::Cancel()
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::UpdateRelevance()
|
||||
Animation::UpdateRelevance()
|
||||
{
|
||||
bool wasRelevant = mIsRelevant;
|
||||
mIsRelevant = HasCurrentEffect() || IsInEffect();
|
||||
|
@ -385,7 +386,7 @@ AnimationPlayer::UpdateRelevance()
|
|||
}
|
||||
|
||||
bool
|
||||
AnimationPlayer::CanThrottle() const
|
||||
Animation::CanThrottle() const
|
||||
{
|
||||
if (!mEffect ||
|
||||
mEffect->IsFinishedTransition() ||
|
||||
|
@ -410,9 +411,9 @@ AnimationPlayer::CanThrottle() const
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
||||
nsCSSPropertySet& aSetProperties,
|
||||
bool& aNeedsRefreshes)
|
||||
Animation::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
||||
nsCSSPropertySet& aSetProperties,
|
||||
bool& aNeedsRefreshes)
|
||||
{
|
||||
if (!mEffect || mEffect->IsFinishedTransition()) {
|
||||
return;
|
||||
|
@ -493,7 +494,7 @@ AnimationPlayer::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::DoPlay(LimitBehavior aLimitBehavior)
|
||||
Animation::DoPlay(LimitBehavior aLimitBehavior)
|
||||
{
|
||||
bool abortedPause = mPendingState == PendingState::PausePending;
|
||||
|
||||
|
@ -548,7 +549,7 @@ AnimationPlayer::DoPlay(LimitBehavior aLimitBehavior)
|
|||
return;
|
||||
}
|
||||
|
||||
PendingPlayerTracker* tracker = doc->GetOrCreatePendingPlayerTracker();
|
||||
PendingAnimationTracker* tracker = doc->GetOrCreatePendingAnimationTracker();
|
||||
tracker->AddPlayPending(*this);
|
||||
|
||||
// We may have updated the current time when we set the hold time above.
|
||||
|
@ -556,7 +557,7 @@ AnimationPlayer::DoPlay(LimitBehavior aLimitBehavior)
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::DoPause()
|
||||
Animation::DoPause()
|
||||
{
|
||||
if (IsPausedOrPausing()) {
|
||||
return;
|
||||
|
@ -586,22 +587,22 @@ AnimationPlayer::DoPause()
|
|||
return;
|
||||
}
|
||||
|
||||
PendingPlayerTracker* tracker = doc->GetOrCreatePendingPlayerTracker();
|
||||
PendingAnimationTracker* tracker = doc->GetOrCreatePendingAnimationTracker();
|
||||
tracker->AddPausePending(*this);
|
||||
|
||||
UpdateFinishedState();
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::ResumeAt(const TimeDuration& aReadyTime)
|
||||
Animation::ResumeAt(const TimeDuration& aReadyTime)
|
||||
{
|
||||
// This method is only expected to be called for a player that is
|
||||
// This method is only expected to be called for an animation that is
|
||||
// waiting to play. We can easily adapt it to handle other states
|
||||
// but it's currently not necessary.
|
||||
MOZ_ASSERT(mPendingState == PendingState::PlayPending,
|
||||
"Expected to resume a play-pending player");
|
||||
"Expected to resume a play-pending animation");
|
||||
MOZ_ASSERT(mHoldTime.IsNull() != mStartTime.IsNull(),
|
||||
"A player in the play-pending state should have either a"
|
||||
"An animation in the play-pending state should have either a"
|
||||
" resolved hold time or resolved start time (but not both)");
|
||||
|
||||
// If we aborted a pending pause operation we will already have a start time
|
||||
|
@ -625,10 +626,10 @@ AnimationPlayer::ResumeAt(const TimeDuration& aReadyTime)
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::PauseAt(const TimeDuration& aReadyTime)
|
||||
Animation::PauseAt(const TimeDuration& aReadyTime)
|
||||
{
|
||||
MOZ_ASSERT(mPendingState == PendingState::PausePending,
|
||||
"Expected to pause a pause-pending player");
|
||||
"Expected to pause a pause-pending animation");
|
||||
|
||||
if (!mStartTime.IsNull()) {
|
||||
mHoldTime.SetValue((aReadyTime - mStartTime.Value())
|
||||
|
@ -645,7 +646,7 @@ AnimationPlayer::PauseAt(const TimeDuration& aReadyTime)
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::UpdateTiming()
|
||||
Animation::UpdateTiming()
|
||||
{
|
||||
// We call UpdateFinishedState before UpdateEffect because the former
|
||||
// can change the current time, which is used by the latter.
|
||||
|
@ -654,7 +655,7 @@ AnimationPlayer::UpdateTiming()
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::UpdateFinishedState(bool aSeekFlag)
|
||||
Animation::UpdateFinishedState(bool aSeekFlag)
|
||||
{
|
||||
Nullable<TimeDuration> currentTime = GetCurrentTime();
|
||||
TimeDuration effectEnd = TimeDuration(EffectEnd());
|
||||
|
@ -697,6 +698,9 @@ AnimationPlayer::UpdateFinishedState(bool aSeekFlag)
|
|||
} else if (!currentFinishedState && mIsPreviousStateFinished) {
|
||||
// Clear finished promise. We'll create a new one lazily.
|
||||
mFinished = nullptr;
|
||||
if (mEffect->AsTransition()) {
|
||||
mEffect->SetIsFinishedTransition(false);
|
||||
}
|
||||
}
|
||||
mIsPreviousStateFinished = currentFinishedState;
|
||||
// We must recalculate the current time to take account of any mHoldTime
|
||||
|
@ -705,7 +709,7 @@ AnimationPlayer::UpdateFinishedState(bool aSeekFlag)
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::UpdateEffect()
|
||||
Animation::UpdateEffect()
|
||||
{
|
||||
if (mEffect) {
|
||||
mEffect->SetParentTime(GetCurrentTime());
|
||||
|
@ -714,7 +718,7 @@ AnimationPlayer::UpdateEffect()
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::FlushStyle() const
|
||||
Animation::FlushStyle() const
|
||||
{
|
||||
nsIDocument* doc = GetRenderedDocument();
|
||||
if (doc) {
|
||||
|
@ -723,16 +727,16 @@ AnimationPlayer::FlushStyle() const
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::PostUpdate()
|
||||
Animation::PostUpdate()
|
||||
{
|
||||
AnimationPlayerCollection* collection = GetCollection();
|
||||
AnimationCollection* collection = GetCollection();
|
||||
if (collection) {
|
||||
collection->NotifyPlayerUpdated();
|
||||
collection->NotifyAnimationUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::CancelPendingTasks()
|
||||
Animation::CancelPendingTasks()
|
||||
{
|
||||
if (mPendingState == PendingState::NotPending) {
|
||||
return;
|
||||
|
@ -740,7 +744,7 @@ AnimationPlayer::CancelPendingTasks()
|
|||
|
||||
nsIDocument* doc = GetRenderedDocument();
|
||||
if (doc) {
|
||||
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
|
||||
PendingAnimationTracker* tracker = doc->GetPendingAnimationTracker();
|
||||
if (tracker) {
|
||||
if (mPendingState == PendingState::PlayPending) {
|
||||
tracker->RemovePlayPending(*this);
|
||||
|
@ -755,7 +759,7 @@ AnimationPlayer::CancelPendingTasks()
|
|||
}
|
||||
|
||||
bool
|
||||
AnimationPlayer::IsFinished() const
|
||||
Animation::IsFinished() const
|
||||
{
|
||||
// Unfortunately there's some weirdness in the spec at the moment where if
|
||||
// you're finished and paused, the playState is paused. This prevents us
|
||||
|
@ -768,7 +772,7 @@ AnimationPlayer::IsFinished() const
|
|||
}
|
||||
|
||||
bool
|
||||
AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
|
||||
Animation::IsPossiblyOrphanedPendingAnimation() const
|
||||
{
|
||||
// Check if we are pending but might never start because we are not being
|
||||
// tracked.
|
||||
|
@ -780,9 +784,9 @@ AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
|
|||
// (note that for the case of our effect changing we should handle
|
||||
// that in SetEffect)
|
||||
// * We started playing but our timeline became inactive.
|
||||
// In this case the pending player tracker will drop us from its hashmap
|
||||
// In this case the pending animation tracker will drop us from its hashmap
|
||||
// when we have been painted.
|
||||
// * When we started playing we couldn't find a PendingPlayerTracker to
|
||||
// * When we started playing we couldn't find a PendingAnimationTracker to
|
||||
// register with (perhaps the effect had no document) so we simply
|
||||
// set mPendingState in DoPlay and relied on this method to catch us on the
|
||||
// next tick.
|
||||
|
@ -805,7 +809,7 @@ AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
|
|||
}
|
||||
|
||||
// If we have no rendered document, or we're not in our rendered document's
|
||||
// PendingPlayerTracker then there's a good chance no one is tracking us.
|
||||
// PendingAnimationTracker then there's a good chance no one is tracking us.
|
||||
//
|
||||
// If we're wrong and another document is tracking us then, at worst, we'll
|
||||
// simply start/pause the animation one tick too soon. That's better than
|
||||
|
@ -815,14 +819,14 @@ AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
|
|||
return false;
|
||||
}
|
||||
|
||||
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
|
||||
PendingAnimationTracker* tracker = doc->GetPendingAnimationTracker();
|
||||
return !tracker ||
|
||||
(!tracker->IsWaitingToPlay(*this) &&
|
||||
!tracker->IsWaitingToPause(*this));
|
||||
}
|
||||
|
||||
StickyTimeDuration
|
||||
AnimationPlayer::EffectEnd() const
|
||||
Animation::EffectEnd() const
|
||||
{
|
||||
if (!mEffect) {
|
||||
return StickyTimeDuration(0);
|
||||
|
@ -833,7 +837,7 @@ AnimationPlayer::EffectEnd() const
|
|||
}
|
||||
|
||||
nsIDocument*
|
||||
AnimationPlayer::GetRenderedDocument() const
|
||||
Animation::GetRenderedDocument() const
|
||||
{
|
||||
if (!mEffect) {
|
||||
return nullptr;
|
||||
|
@ -850,7 +854,7 @@ AnimationPlayer::GetRenderedDocument() const
|
|||
}
|
||||
|
||||
nsPresContext*
|
||||
AnimationPlayer::GetPresContext() const
|
||||
Animation::GetPresContext() const
|
||||
{
|
||||
nsIDocument* doc = GetRenderedDocument();
|
||||
if (!doc) {
|
||||
|
@ -863,20 +867,21 @@ AnimationPlayer::GetPresContext() const
|
|||
return shell->GetPresContext();
|
||||
}
|
||||
|
||||
AnimationPlayerCollection*
|
||||
AnimationPlayer::GetCollection() const
|
||||
AnimationCollection*
|
||||
Animation::GetCollection() const
|
||||
{
|
||||
css::CommonAnimationManager* manager = GetAnimationManager();
|
||||
if (!manager) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(mEffect, "A player with an animation manager must have an effect");
|
||||
MOZ_ASSERT(mEffect,
|
||||
"An animation with an animation manager must have an effect");
|
||||
|
||||
Element* targetElement;
|
||||
nsCSSPseudoElements::Type targetPseudoType;
|
||||
mEffect->GetTarget(targetElement, targetPseudoType);
|
||||
MOZ_ASSERT(targetElement,
|
||||
"A player with an animation manager must have a target");
|
||||
"An animation with an animation manager must have a target");
|
||||
|
||||
return manager->GetAnimations(targetElement, targetPseudoType, false);
|
||||
}
|
|
@ -3,14 +3,14 @@
|
|||
* 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_AnimationPlayer_h
|
||||
#define mozilla_dom_AnimationPlayer_h
|
||||
#ifndef mozilla_dom_Animation_h
|
||||
#define mozilla_dom_Animation_h
|
||||
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
|
||||
#include "mozilla/dom/AnimationPlayerBinding.h" // for AnimationPlayState
|
||||
#include "mozilla/dom/AnimationBinding.h" // for AnimationPlayState
|
||||
#include "mozilla/dom/DocumentTimeline.h" // for DocumentTimeline
|
||||
#include "mozilla/dom/KeyframeEffect.h" // for KeyframeEffectReadonly
|
||||
#include "mozilla/dom/Promise.h" // for Promise
|
||||
|
@ -33,25 +33,26 @@ class nsIDocument;
|
|||
class nsPresContext;
|
||||
|
||||
namespace mozilla {
|
||||
struct AnimationPlayerCollection;
|
||||
struct AnimationCollection;
|
||||
namespace css {
|
||||
class AnimValuesStyleRule;
|
||||
class CommonAnimationManager;
|
||||
} // namespace css
|
||||
|
||||
class CSSAnimationPlayer;
|
||||
class CSSTransitionPlayer;
|
||||
class CSSAnimation;
|
||||
class CSSTransition;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class AnimationPlayer : public nsISupports,
|
||||
public nsWrapperCache
|
||||
class Animation
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
protected:
|
||||
virtual ~AnimationPlayer() {}
|
||||
virtual ~Animation() {}
|
||||
|
||||
public:
|
||||
explicit AnimationPlayer(DocumentTimeline* aTimeline)
|
||||
explicit Animation(DocumentTimeline* aTimeline)
|
||||
: mTimeline(aTimeline)
|
||||
, mPlaybackRate(1.0)
|
||||
, mPendingState(PendingState::NotPending)
|
||||
|
@ -63,14 +64,14 @@ public:
|
|||
}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationPlayer)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Animation)
|
||||
|
||||
DocumentTimeline* GetParentObject() const { return mTimeline; }
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
virtual CSSAnimationPlayer* AsCSSAnimationPlayer() { return nullptr; }
|
||||
virtual CSSTransitionPlayer* AsCSSTransitionPlayer() { return nullptr; }
|
||||
virtual CSSAnimation* AsCSSAnimation() { return nullptr; }
|
||||
virtual CSSTransition* AsCSSTransition() { return nullptr; }
|
||||
|
||||
// Flag to pass to DoPlay to indicate that it should not carry out finishing
|
||||
// behavior (reset the current time to the beginning of the active duration).
|
||||
|
@ -79,7 +80,7 @@ public:
|
|||
Continue = 1
|
||||
};
|
||||
|
||||
// AnimationPlayer methods
|
||||
// Animation methods
|
||||
KeyframeEffectReadonly* GetEffect() const { return mEffect; }
|
||||
DocumentTimeline* Timeline() const { return mTimeline; }
|
||||
Nullable<TimeDuration> GetStartTime() const { return mStartTime; }
|
||||
|
@ -97,7 +98,7 @@ public:
|
|||
virtual void Pause();
|
||||
bool IsRunningOnCompositor() const { return mIsRunningOnCompositor; }
|
||||
|
||||
// Wrapper functions for AnimationPlayer DOM methods when called
|
||||
// Wrapper functions for Animation DOM methods when called
|
||||
// from script. We often use the same methods internally and from
|
||||
// script but when called from script we (or one of our subclasses) perform
|
||||
// extra steps such as flushing style or converting the return type.
|
||||
|
@ -110,31 +111,31 @@ public:
|
|||
virtual void PlayFromJS() { Play(LimitBehavior::AutoRewind); }
|
||||
// PauseFromJS is currently only here for symmetry with PlayFromJS but
|
||||
// in future we will likely have to flush style in
|
||||
// CSSAnimationPlayer::PauseFromJS so we leave it for now.
|
||||
// CSSAnimation::PauseFromJS so we leave it for now.
|
||||
void PauseFromJS() { Pause(); }
|
||||
|
||||
void SetEffect(KeyframeEffectReadonly* aEffect);
|
||||
void Tick();
|
||||
|
||||
/**
|
||||
* Set the time to use for starting or pausing a pending player.
|
||||
* Set the time to use for starting or pausing a pending animation.
|
||||
*
|
||||
* Typically, when a player is played, it does not start immediately but is
|
||||
* added to a table of pending players on the document of its effect.
|
||||
* Typically, when an animation is played, it does not start immediately but
|
||||
* is added to a table of pending animations on the document of its effect.
|
||||
* In the meantime it sets its hold time to the time from which playback
|
||||
* should begin.
|
||||
*
|
||||
* When the document finishes painting, any pending players in its table
|
||||
* When the document finishes painting, any pending animations in its table
|
||||
* are marked as being ready to start by calling StartOnNextTick.
|
||||
* The moment when the paint completed is also recorded, converted to a
|
||||
* timeline time, and passed to StartOnTick. This is so that when these
|
||||
* players do start, they can be timed from the point when painting
|
||||
* animations do start, they can be timed from the point when painting
|
||||
* completed.
|
||||
*
|
||||
* After calling TriggerOnNextTick, players remain in the pending state until
|
||||
* the next refresh driver tick. At that time they transition out of the
|
||||
* pending state using the time passed to TriggerOnNextTick as the effective
|
||||
* time at which they resumed.
|
||||
* After calling TriggerOnNextTick, animations remain in the pending state
|
||||
* until the next refresh driver tick. At that time they transition out of
|
||||
* the pending state using the time passed to TriggerOnNextTick as the
|
||||
* effective time at which they resumed.
|
||||
*
|
||||
* This approach means that any setup time required for performing the
|
||||
* initial paint of an animation such as layerization is not deducted from
|
||||
|
@ -144,14 +145,14 @@ public:
|
|||
*
|
||||
* Furthermore:
|
||||
*
|
||||
* - Starting the player immediately when painting finishes is problematic
|
||||
* because the start time of the player will be ahead of its timeline
|
||||
* - Starting the animation immediately when painting finishes is problematic
|
||||
* because the start time of the animation will be ahead of its timeline
|
||||
* (since the timeline time is based on the refresh driver time).
|
||||
* That's a problem because the player is playing but its timing suggests
|
||||
* it starts in the future. We could update the timeline to match the start
|
||||
* time of the player but then we'd also have to update the timing and style
|
||||
* of all animations connected to that timeline or else be stuck in an
|
||||
* inconsistent state until the next refresh driver tick.
|
||||
* That's a problem because the animation is playing but its timing
|
||||
* suggests it starts in the future. We could update the timeline to match
|
||||
* the start time of the animation but then we'd also have to update the
|
||||
* timing and style of all animations connected to that timeline or else be
|
||||
* stuck in an inconsistent state until the next refresh driver tick.
|
||||
*
|
||||
* - If we simply use the refresh driver time on its next tick, the lag
|
||||
* between triggering an animation and its effective start is unacceptably
|
||||
|
@ -164,19 +165,19 @@ public:
|
|||
* animations could be paused immediately, we do it asynchronously for
|
||||
* consistency and so that animations paused together end up in step.
|
||||
*
|
||||
* Note that the caller of this method is responsible for removing the player
|
||||
* from any PendingPlayerTracker it may have been added to.
|
||||
* Note that the caller of this method is responsible for removing the
|
||||
* animation from any PendingAnimationTracker it may have been added to.
|
||||
*/
|
||||
void TriggerOnNextTick(const Nullable<TimeDuration>& aReadyTime);
|
||||
|
||||
// Testing only: Start or pause a pending player using the current timeline
|
||||
// Testing only: Start or pause a pending animation using the current timeline
|
||||
// time. This is used to support existing tests that expect animations to
|
||||
// begin immediately. Ideally we would rewrite the those tests and get rid of
|
||||
// this method, but there are a lot of them.
|
||||
//
|
||||
// As with TriggerOnNextTick, the caller of this method is responsible for
|
||||
// removing the player from any PendingPlayerTracker it may have been added
|
||||
// to.
|
||||
// removing the animation from any PendingAnimationTracker it may have been
|
||||
// added to.
|
||||
void TriggerNow();
|
||||
|
||||
/**
|
||||
|
@ -253,11 +254,11 @@ public:
|
|||
// running on the compositor).
|
||||
bool CanThrottle() const;
|
||||
|
||||
// Updates |aStyleRule| with the animation values of this player's effect,
|
||||
// Updates |aStyleRule| with the animation values of this animation's effect,
|
||||
// if any.
|
||||
// Any properties already contained in |aSetProperties| are not changed. Any
|
||||
// properties that are changed are added to |aSetProperties|.
|
||||
// |aNeedsRefreshes| will be set to true if this player expects to update
|
||||
// |aNeedsRefreshes| will be set to true if this animation expects to update
|
||||
// the style rule on the next refresh driver tick as well (because it
|
||||
// is running and has an effect to sample).
|
||||
void ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
||||
|
@ -286,7 +287,7 @@ protected:
|
|||
void FlushStyle() const;
|
||||
void PostUpdate();
|
||||
/**
|
||||
* Remove this player from the pending player tracker and reset
|
||||
* Remove this animation from the pending animation tracker and reset
|
||||
* mPendingState as necessary. The caller is responsible for resolving or
|
||||
* aborting the mReady promise as necessary.
|
||||
*/
|
||||
|
@ -294,21 +295,21 @@ protected:
|
|||
|
||||
bool IsFinished() const;
|
||||
|
||||
bool IsPossiblyOrphanedPendingPlayer() const;
|
||||
bool IsPossiblyOrphanedPendingAnimation() const;
|
||||
StickyTimeDuration EffectEnd() const;
|
||||
|
||||
nsIDocument* GetRenderedDocument() const;
|
||||
nsPresContext* GetPresContext() const;
|
||||
virtual css::CommonAnimationManager* GetAnimationManager() const = 0;
|
||||
AnimationPlayerCollection* GetCollection() const;
|
||||
AnimationCollection* GetCollection() const;
|
||||
|
||||
nsRefPtr<DocumentTimeline> mTimeline;
|
||||
nsRefPtr<KeyframeEffectReadonly> mEffect;
|
||||
// The beginning of the delay period.
|
||||
Nullable<TimeDuration> mStartTime; // Timeline timescale
|
||||
Nullable<TimeDuration> mHoldTime; // Player timescale
|
||||
Nullable<TimeDuration> mHoldTime; // Animation timescale
|
||||
Nullable<TimeDuration> mPendingReadyTime; // Timeline timescale
|
||||
Nullable<TimeDuration> mPreviousCurrentTime; // Player timescale
|
||||
Nullable<TimeDuration> mPreviousCurrentTime; // Animation timescale
|
||||
double mPlaybackRate;
|
||||
|
||||
// A Promise that is replaced on each call to Play() (and in future Pause())
|
||||
|
@ -324,11 +325,11 @@ protected:
|
|||
// See http://w3c.github.io/web-animations/#current-finished-promise
|
||||
nsRefPtr<Promise> mFinished;
|
||||
|
||||
// Indicates if the player is in the pending state (and what state it is
|
||||
// Indicates if the animation is in the pending state (and what state it is
|
||||
// waiting to enter when it finished pending). We use this rather than
|
||||
// checking if this player is tracked by a PendingPlayerTracker because the
|
||||
// player will continue to be pending even after it has been removed from the
|
||||
// PendingPlayerTracker while it is waiting for the next tick
|
||||
// checking if this animation is tracked by a PendingAnimationTracker because
|
||||
// the animation will continue to be pending even after it has been removed
|
||||
// from the PendingAnimationTracker while it is waiting for the next tick
|
||||
// (see TriggerOnNextTick for details).
|
||||
enum class PendingState { NotPending, PlayPending, PausePending };
|
||||
PendingState mPendingState;
|
||||
|
@ -346,4 +347,4 @@ protected:
|
|||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_AnimationPlayer_h
|
||||
#endif // mozilla_dom_Animation_h
|
|
@ -234,10 +234,10 @@ KeyframeEffectReadonly::ActiveDuration(const AnimationTiming& aTiming)
|
|||
|
||||
// http://w3c.github.io/web-animations/#in-play
|
||||
bool
|
||||
KeyframeEffectReadonly::IsInPlay(const AnimationPlayer& aPlayer) const
|
||||
KeyframeEffectReadonly::IsInPlay(const Animation& aAnimation) const
|
||||
{
|
||||
if (IsFinishedTransition() ||
|
||||
aPlayer.PlayState() == AnimationPlayState::Finished) {
|
||||
aAnimation.PlayState() == AnimationPlayState::Finished) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -246,10 +246,10 @@ KeyframeEffectReadonly::IsInPlay(const AnimationPlayer& aPlayer) const
|
|||
|
||||
// http://w3c.github.io/web-animations/#current
|
||||
bool
|
||||
KeyframeEffectReadonly::IsCurrent(const AnimationPlayer& aPlayer) const
|
||||
KeyframeEffectReadonly::IsCurrent(const Animation& aAnimation) const
|
||||
{
|
||||
if (IsFinishedTransition() ||
|
||||
aPlayer.PlayState() == AnimationPlayState::Finished) {
|
||||
aAnimation.PlayState() == AnimationPlayState::Finished) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -325,7 +325,7 @@ KeyframeEffectReadonly::ComposeStyle(
|
|||
"incorrect last to key");
|
||||
|
||||
if (aSetProperties.HasProperty(prop.mProperty)) {
|
||||
// Animations are composed by AnimationPlayerCollection by iterating
|
||||
// Animations are composed by AnimationCollection by iterating
|
||||
// from the last animation to first. For animations targetting the
|
||||
// same property, the later one wins. So if this property is already set,
|
||||
// we should not override it.
|
||||
|
|
|
@ -300,14 +300,14 @@ public:
|
|||
return mIsFinishedTransition;
|
||||
}
|
||||
|
||||
void SetIsFinishedTransition() {
|
||||
void SetIsFinishedTransition(bool aIsFinished) {
|
||||
MOZ_ASSERT(AsTransition(),
|
||||
"Calling SetIsFinishedTransition but it's not a transition");
|
||||
mIsFinishedTransition = true;
|
||||
mIsFinishedTransition = aIsFinished;
|
||||
}
|
||||
|
||||
bool IsInPlay(const AnimationPlayer& aPlayer) const;
|
||||
bool IsCurrent(const AnimationPlayer& aPlayer) const;
|
||||
bool IsInPlay(const Animation& aAnimation) const;
|
||||
bool IsCurrent(const Animation& aAnimation) const;
|
||||
bool IsInEffect() const;
|
||||
|
||||
const AnimationProperty*
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "PendingPlayerTracker.h"
|
||||
#include "PendingAnimationTracker.h"
|
||||
|
||||
#include "mozilla/dom/DocumentTimeline.h"
|
||||
#include "nsIFrame.h"
|
||||
|
@ -13,19 +13,19 @@ using namespace mozilla;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(PendingPlayerTracker,
|
||||
NS_IMPL_CYCLE_COLLECTION(PendingAnimationTracker,
|
||||
mPlayPendingSet,
|
||||
mPausePendingSet,
|
||||
mDocument)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PendingPlayerTracker, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PendingPlayerTracker, Release)
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PendingAnimationTracker, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PendingAnimationTracker, Release)
|
||||
|
||||
void
|
||||
PendingPlayerTracker::AddPending(dom::AnimationPlayer& aPlayer,
|
||||
AnimationPlayerSet& aSet)
|
||||
PendingAnimationTracker::AddPending(dom::Animation& aAnimation,
|
||||
AnimationSet& aSet)
|
||||
{
|
||||
aSet.PutEntry(&aPlayer);
|
||||
aSet.PutEntry(&aAnimation);
|
||||
|
||||
// Schedule a paint. Otherwise animations that don't trigger a paint by
|
||||
// themselves (e.g. CSS animations with an empty keyframes rule) won't
|
||||
|
@ -34,70 +34,70 @@ PendingPlayerTracker::AddPending(dom::AnimationPlayer& aPlayer,
|
|||
}
|
||||
|
||||
void
|
||||
PendingPlayerTracker::RemovePending(dom::AnimationPlayer& aPlayer,
|
||||
AnimationPlayerSet& aSet)
|
||||
PendingAnimationTracker::RemovePending(dom::Animation& aAnimation,
|
||||
AnimationSet& aSet)
|
||||
{
|
||||
aSet.RemoveEntry(&aPlayer);
|
||||
aSet.RemoveEntry(&aAnimation);
|
||||
}
|
||||
|
||||
bool
|
||||
PendingPlayerTracker::IsWaiting(const dom::AnimationPlayer& aPlayer,
|
||||
const AnimationPlayerSet& aSet) const
|
||||
PendingAnimationTracker::IsWaiting(const dom::Animation& aAnimation,
|
||||
const AnimationSet& aSet) const
|
||||
{
|
||||
return aSet.Contains(const_cast<dom::AnimationPlayer*>(&aPlayer));
|
||||
return aSet.Contains(const_cast<dom::Animation*>(&aAnimation));
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
TriggerPlayerAtTime(nsRefPtrHashKey<dom::AnimationPlayer>* aKey,
|
||||
TriggerAnimationAtTime(nsRefPtrHashKey<dom::Animation>* aKey,
|
||||
void* aReadyTime)
|
||||
{
|
||||
dom::AnimationPlayer* player = aKey->GetKey();
|
||||
dom::DocumentTimeline* timeline = player->Timeline();
|
||||
dom::Animation* animation = aKey->GetKey();
|
||||
dom::DocumentTimeline* timeline = animation->Timeline();
|
||||
|
||||
// When the timeline's refresh driver is under test control, its values
|
||||
// have no correspondance to wallclock times so we shouldn't try to convert
|
||||
// aReadyTime (which is a wallclock time) to a timeline value. Instead, the
|
||||
// animation player will be started/paused when the refresh driver is next
|
||||
// advanced since this will trigger a call to TriggerPendingPlayersNow.
|
||||
// animation will be started/paused when the refresh driver is next
|
||||
// advanced since this will trigger a call to TriggerPendingAnimationsNow.
|
||||
if (timeline->IsUnderTestControl()) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
Nullable<TimeDuration> readyTime =
|
||||
timeline->ToTimelineTime(*static_cast<const TimeStamp*>(aReadyTime));
|
||||
player->TriggerOnNextTick(readyTime);
|
||||
animation->TriggerOnNextTick(readyTime);
|
||||
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
PendingPlayerTracker::TriggerPendingPlayersOnNextTick(const TimeStamp&
|
||||
PendingAnimationTracker::TriggerPendingAnimationsOnNextTick(const TimeStamp&
|
||||
aReadyTime)
|
||||
{
|
||||
mPlayPendingSet.EnumerateEntries(TriggerPlayerAtTime,
|
||||
mPlayPendingSet.EnumerateEntries(TriggerAnimationAtTime,
|
||||
const_cast<TimeStamp*>(&aReadyTime));
|
||||
mPausePendingSet.EnumerateEntries(TriggerPlayerAtTime,
|
||||
mPausePendingSet.EnumerateEntries(TriggerAnimationAtTime,
|
||||
const_cast<TimeStamp*>(&aReadyTime));
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
TriggerPlayerNow(nsRefPtrHashKey<dom::AnimationPlayer>* aKey, void*)
|
||||
TriggerAnimationNow(nsRefPtrHashKey<dom::Animation>* aKey, void*)
|
||||
{
|
||||
aKey->GetKey()->TriggerNow();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
PendingPlayerTracker::TriggerPendingPlayersNow()
|
||||
PendingAnimationTracker::TriggerPendingAnimationsNow()
|
||||
{
|
||||
mPlayPendingSet.EnumerateEntries(TriggerPlayerNow, nullptr);
|
||||
mPlayPendingSet.EnumerateEntries(TriggerAnimationNow, nullptr);
|
||||
mPlayPendingSet.Clear();
|
||||
mPausePendingSet.EnumerateEntries(TriggerPlayerNow, nullptr);
|
||||
mPausePendingSet.EnumerateEntries(TriggerAnimationNow, nullptr);
|
||||
mPausePendingSet.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
PendingPlayerTracker::EnsurePaintIsScheduled()
|
||||
PendingAnimationTracker::EnsurePaintIsScheduled()
|
||||
{
|
||||
if (!mDocument) {
|
||||
return;
|
|
@ -0,0 +1,83 @@
|
|||
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
||||
/* 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_PendingAnimationTracker_h
|
||||
#define mozilla_dom_PendingAnimationTracker_h
|
||||
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsTHashtable.h"
|
||||
|
||||
class nsIFrame;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class PendingAnimationTracker final
|
||||
{
|
||||
public:
|
||||
explicit PendingAnimationTracker(nsIDocument* aDocument)
|
||||
: mDocument(aDocument)
|
||||
{ }
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PendingAnimationTracker)
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(PendingAnimationTracker)
|
||||
|
||||
void AddPlayPending(dom::Animation& aAnimation)
|
||||
{
|
||||
MOZ_ASSERT(!IsWaitingToPause(aAnimation),
|
||||
"Animation is already waiting to pause");
|
||||
AddPending(aAnimation, mPlayPendingSet);
|
||||
}
|
||||
void RemovePlayPending(dom::Animation& aAnimation)
|
||||
{
|
||||
RemovePending(aAnimation, mPlayPendingSet);
|
||||
}
|
||||
bool IsWaitingToPlay(const dom::Animation& aAnimation) const
|
||||
{
|
||||
return IsWaiting(aAnimation, mPlayPendingSet);
|
||||
}
|
||||
|
||||
void AddPausePending(dom::Animation& aAnimation)
|
||||
{
|
||||
MOZ_ASSERT(!IsWaitingToPlay(aAnimation),
|
||||
"Animation is already waiting to play");
|
||||
AddPending(aAnimation, mPausePendingSet);
|
||||
}
|
||||
void RemovePausePending(dom::Animation& aAnimation)
|
||||
{
|
||||
RemovePending(aAnimation, mPausePendingSet);
|
||||
}
|
||||
bool IsWaitingToPause(const dom::Animation& aAnimation) const
|
||||
{
|
||||
return IsWaiting(aAnimation, mPausePendingSet);
|
||||
}
|
||||
|
||||
void TriggerPendingAnimationsOnNextTick(const TimeStamp& aReadyTime);
|
||||
void TriggerPendingAnimationsNow();
|
||||
bool HasPendingAnimations() const {
|
||||
return mPlayPendingSet.Count() > 0 || mPausePendingSet.Count() > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
~PendingAnimationTracker() { }
|
||||
|
||||
void EnsurePaintIsScheduled();
|
||||
|
||||
typedef nsTHashtable<nsRefPtrHashKey<dom::Animation>> AnimationSet;
|
||||
|
||||
void AddPending(dom::Animation& aAnimation, AnimationSet& aSet);
|
||||
void RemovePending(dom::Animation& aAnimation, AnimationSet& aSet);
|
||||
bool IsWaiting(const dom::Animation& aAnimation,
|
||||
const AnimationSet& aSet) const;
|
||||
|
||||
AnimationSet mPlayPendingSet;
|
||||
AnimationSet mPausePendingSet;
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PendingAnimationTracker_h
|
|
@ -1,86 +0,0 @@
|
|||
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
||||
/* 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_PendingPlayerTracker_h
|
||||
#define mozilla_dom_PendingPlayerTracker_h
|
||||
|
||||
#include "mozilla/dom/AnimationPlayer.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsTHashtable.h"
|
||||
|
||||
class nsIFrame;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class PendingPlayerTracker final
|
||||
{
|
||||
public:
|
||||
explicit PendingPlayerTracker(nsIDocument* aDocument)
|
||||
: mDocument(aDocument)
|
||||
{ }
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PendingPlayerTracker)
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(PendingPlayerTracker)
|
||||
|
||||
void AddPlayPending(dom::AnimationPlayer& aPlayer)
|
||||
{
|
||||
MOZ_ASSERT(!IsWaitingToPause(aPlayer),
|
||||
"Player is already waiting to pause");
|
||||
AddPending(aPlayer, mPlayPendingSet);
|
||||
}
|
||||
void RemovePlayPending(dom::AnimationPlayer& aPlayer)
|
||||
{
|
||||
RemovePending(aPlayer, mPlayPendingSet);
|
||||
}
|
||||
bool IsWaitingToPlay(const dom::AnimationPlayer& aPlayer) const
|
||||
{
|
||||
return IsWaiting(aPlayer, mPlayPendingSet);
|
||||
}
|
||||
|
||||
void AddPausePending(dom::AnimationPlayer& aPlayer)
|
||||
{
|
||||
MOZ_ASSERT(!IsWaitingToPlay(aPlayer),
|
||||
"Player is already waiting to play");
|
||||
AddPending(aPlayer, mPausePendingSet);
|
||||
}
|
||||
void RemovePausePending(dom::AnimationPlayer& aPlayer)
|
||||
{
|
||||
RemovePending(aPlayer, mPausePendingSet);
|
||||
}
|
||||
bool IsWaitingToPause(const dom::AnimationPlayer& aPlayer) const
|
||||
{
|
||||
return IsWaiting(aPlayer, mPausePendingSet);
|
||||
}
|
||||
|
||||
void TriggerPendingPlayersOnNextTick(const TimeStamp& aReadyTime);
|
||||
void TriggerPendingPlayersNow();
|
||||
bool HasPendingPlayers() const {
|
||||
return mPlayPendingSet.Count() > 0 || mPausePendingSet.Count() > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
~PendingPlayerTracker() { }
|
||||
|
||||
void EnsurePaintIsScheduled();
|
||||
|
||||
typedef nsTHashtable<nsRefPtrHashKey<dom::AnimationPlayer>>
|
||||
AnimationPlayerSet;
|
||||
|
||||
void AddPending(dom::AnimationPlayer& aPlayer,
|
||||
AnimationPlayerSet& aSet);
|
||||
void RemovePending(dom::AnimationPlayer& aPlayer,
|
||||
AnimationPlayerSet& aSet);
|
||||
bool IsWaiting(const dom::AnimationPlayer& aPlayer,
|
||||
const AnimationPlayerSet& aSet) const;
|
||||
|
||||
AnimationPlayerSet mPlayPendingSet;
|
||||
AnimationPlayerSet mPausePendingSet;
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PendingPlayerTracker_h
|
|
@ -8,8 +8,8 @@ MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
|||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Animation.h',
|
||||
'AnimationEffectReadonly.h',
|
||||
'AnimationPlayer.h',
|
||||
'AnimationTimeline.h',
|
||||
'DocumentTimeline.h',
|
||||
'KeyframeEffect.h',
|
||||
|
@ -17,16 +17,16 @@ EXPORTS.mozilla.dom += [
|
|||
|
||||
EXPORTS.mozilla += [
|
||||
'AnimationUtils.h',
|
||||
'PendingPlayerTracker.h',
|
||||
'PendingAnimationTracker.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'Animation.cpp',
|
||||
'AnimationEffectReadonly.cpp',
|
||||
'AnimationPlayer.cpp',
|
||||
'AnimationTimeline.cpp',
|
||||
'DocumentTimeline.cpp',
|
||||
'KeyframeEffect.cpp',
|
||||
'PendingPlayerTracker.cpp',
|
||||
'PendingAnimationTracker.cpp',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
|
|
@ -193,11 +193,10 @@ function EventWatcher(watchedNode, eventTypes)
|
|||
// terms used in the Web Animations specification for specific phases of an
|
||||
// animation. The terms can be found here:
|
||||
//
|
||||
// http://w3c.github.io/web-animations/#animation-node-phases-and-states
|
||||
// https://w3c.github.io/web-animations/#animation-effect-phases-and-states
|
||||
//
|
||||
// Note the distinction between "player start time" and "animation start time".
|
||||
// The former is the start of the start delay. The latter is the start of the
|
||||
// active interval. (If there is no delay, they are the same.)
|
||||
// Note the distinction between the "animation start time" which occurs before
|
||||
// the start delay and the start of the active interval which occurs after it.
|
||||
|
||||
// Called when currentTime is set to zero (the beginning of the start delay).
|
||||
function checkStateOnSettingCurrentTimeToZero(animation)
|
|
@ -193,11 +193,10 @@ function EventWatcher(watchedNode, eventTypes)
|
|||
// terms used in the Web Animations specification for specific phases of an
|
||||
// animation. The terms can be found here:
|
||||
//
|
||||
// http://w3c.github.io/web-animations/#animation-node-phases-and-states
|
||||
// https://w3c.github.io/web-animations/#animation-effect-phases-and-states
|
||||
//
|
||||
// Note the distinction between "player start time" and "animation start time".
|
||||
// The former is the start of the start delay. The latter is the start of the
|
||||
// active interval. (If there is no delay, they are the same.)
|
||||
// Note the distinction between the "animation start time" which occurs before
|
||||
// the start delay and the start of the active interval which occurs after it.
|
||||
|
||||
// Called when the ready Promise's callbacks should happen
|
||||
function checkStateOnReadyPromiseResolved(animation)
|
|
@ -183,11 +183,10 @@ function EventWatcher(watchedNode, eventTypes)
|
|||
// terms used in the Web Animations specification for specific phases of an
|
||||
// animation. The terms can be found here:
|
||||
//
|
||||
// http://w3c.github.io/web-animations/#animation-effect-phases-and-states
|
||||
// https://w3c.github.io/web-animations/#animation-effect-phases-and-states
|
||||
//
|
||||
// Note the distinction between "player start time" and "animation start time".
|
||||
// The former is the start of the start delay. The latter is the start of the
|
||||
// active interval. (If there is no delay, they are the same.)
|
||||
// Note the distinction between the "animation start time" which occurs before
|
||||
// the start delay and the start of the active interval which occurs after it.
|
||||
|
||||
// Called when the ready Promise's callbacks should happen
|
||||
function checkStateOnReadyPromiseResolved(animation)
|
|
@ -4,22 +4,22 @@ support-files =
|
|||
|
||||
[css-animations/test_animations-dynamic-changes.html]
|
||||
[css-animations/test_animation-pausing.html]
|
||||
[css-animations/test_animation-player-currenttime.html]
|
||||
[css-animations/test_animation-player-finished.html]
|
||||
[css-animations/test_animation-player-playstate.html]
|
||||
[css-animations/test_animation-player-ready.html]
|
||||
[css-animations/test_animation-player-starttime.html]
|
||||
[css-animations/test_animation-currenttime.html]
|
||||
[css-animations/test_animation-finished.html]
|
||||
[css-animations/test_animation-playstate.html]
|
||||
[css-animations/test_animation-ready.html]
|
||||
[css-animations/test_animation-starttime.html]
|
||||
[css-animations/test_effect-name.html]
|
||||
[css-animations/test_effect-target.html]
|
||||
[css-animations/test_element-get-animation-players.html]
|
||||
[css-animations/test_element-get-animations.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[css-transitions/test_animation-pausing.html]
|
||||
[css-transitions/test_animation-player-currenttime.html]
|
||||
[css-transitions/test_animation-player-ready.html]
|
||||
[css-transitions/test_animation-player-starttime.html]
|
||||
[css-transitions/test_animation-currenttime.html]
|
||||
[css-transitions/test_animation-ready.html]
|
||||
[css-transitions/test_animation-starttime.html]
|
||||
[css-transitions/test_effect-name.html]
|
||||
[css-transitions/test_effect-target.html]
|
||||
[css-transitions/test_element-get-animation-players.html]
|
||||
[css-transitions/test_element-get-animations.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[document-timeline/test_document-timeline.html]
|
||||
[document-timeline/test_request_animation_frame.html]
|
||||
|
|
|
@ -1004,7 +1004,12 @@ MainProcessRunnable::Run()
|
|||
case eFailedToReadMetadata: {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
CacheMiss();
|
||||
if (mOpenMode == eOpenForRead) {
|
||||
CacheMiss();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Fail();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "AnimationCommon.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/dom/AnimationPlayer.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/Attr.h"
|
||||
#include "nsDOMAttributeMap.h"
|
||||
#include "nsIAtom.h"
|
||||
|
@ -3186,7 +3186,7 @@ Element::MozRequestPointerLock()
|
|||
}
|
||||
|
||||
void
|
||||
Element::GetAnimations(nsTArray<nsRefPtr<AnimationPlayer> >& aAnimations)
|
||||
Element::GetAnimations(nsTArray<nsRefPtr<Animation>>& aAnimations)
|
||||
{
|
||||
nsIDocument* doc = GetComposedDoc();
|
||||
if (doc) {
|
||||
|
@ -3197,18 +3197,18 @@ Element::GetAnimations(nsTArray<nsRefPtr<AnimationPlayer> >& aAnimations)
|
|||
nsGkAtoms::animationsProperty };
|
||||
for (size_t propIdx = 0; propIdx < MOZ_ARRAY_LENGTH(properties);
|
||||
propIdx++) {
|
||||
AnimationPlayerCollection* collection =
|
||||
static_cast<AnimationPlayerCollection*>(
|
||||
AnimationCollection* collection =
|
||||
static_cast<AnimationCollection*>(
|
||||
GetProperty(properties[propIdx]));
|
||||
if (!collection) {
|
||||
continue;
|
||||
}
|
||||
for (size_t playerIdx = 0;
|
||||
playerIdx < collection->mPlayers.Length();
|
||||
playerIdx++) {
|
||||
AnimationPlayer* player = collection->mPlayers[playerIdx];
|
||||
if (player->IsRelevant()) {
|
||||
aAnimations.AppendElement(player);
|
||||
for (size_t animIdx = 0;
|
||||
animIdx < collection->mAnimations.Length();
|
||||
animIdx++) {
|
||||
Animation* anim = collection->mAnimations[animIdx];
|
||||
if (anim->IsRelevant()) {
|
||||
aAnimations.AppendElement(anim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ class EventStateManager;
|
|||
|
||||
namespace dom {
|
||||
|
||||
class AnimationPlayer;
|
||||
class Animation;
|
||||
class Link;
|
||||
class UndoManager;
|
||||
class DOMRect;
|
||||
|
@ -808,7 +808,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
void GetAnimations(nsTArray<nsRefPtr<AnimationPlayer> >& aAnimations);
|
||||
void GetAnimations(nsTArray<nsRefPtr<Animation>>& aAnimations);
|
||||
|
||||
NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
|
||||
virtual void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "nsIDOMMutationEvent.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "mozilla/dom/AnimationPlayer.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/KeyframeEffect.h"
|
||||
|
||||
nsAutoTArray<nsRefPtr<nsDOMMutationObserver>, 4>*
|
||||
|
@ -325,10 +325,10 @@ void nsMutationReceiver::NodeWillBeDestroyed(const nsINode *aNode)
|
|||
}
|
||||
|
||||
void
|
||||
nsAnimationReceiver::RecordAnimationMutation(AnimationPlayer* aPlayer,
|
||||
nsAnimationReceiver::RecordAnimationMutation(Animation* aAnimation,
|
||||
AnimationMutation aMutationType)
|
||||
{
|
||||
KeyframeEffectReadonly* effect = aPlayer->GetEffect();
|
||||
KeyframeEffectReadonly* effect = aAnimation->GetEffect();
|
||||
if (!effect) {
|
||||
return;
|
||||
}
|
||||
|
@ -350,13 +350,13 @@ nsAnimationReceiver::RecordAnimationMutation(AnimationPlayer* aPlayer,
|
|||
|
||||
switch (aMutationType) {
|
||||
case eAnimationMutation_Added:
|
||||
nsAutoAnimationMutationBatch::AnimationAdded(aPlayer);
|
||||
nsAutoAnimationMutationBatch::AnimationAdded(aAnimation);
|
||||
break;
|
||||
case eAnimationMutation_Changed:
|
||||
nsAutoAnimationMutationBatch::AnimationChanged(aPlayer);
|
||||
nsAutoAnimationMutationBatch::AnimationChanged(aAnimation);
|
||||
break;
|
||||
case eAnimationMutation_Removed:
|
||||
nsAutoAnimationMutationBatch::AnimationRemoved(aPlayer);
|
||||
nsAutoAnimationMutationBatch::AnimationRemoved(aAnimation);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -373,33 +373,33 @@ nsAnimationReceiver::RecordAnimationMutation(AnimationPlayer* aPlayer,
|
|||
|
||||
switch (aMutationType) {
|
||||
case eAnimationMutation_Added:
|
||||
m->mAddedAnimations.AppendElement(aPlayer);
|
||||
m->mAddedAnimations.AppendElement(aAnimation);
|
||||
break;
|
||||
case eAnimationMutation_Changed:
|
||||
m->mChangedAnimations.AppendElement(aPlayer);
|
||||
m->mChangedAnimations.AppendElement(aAnimation);
|
||||
break;
|
||||
case eAnimationMutation_Removed:
|
||||
m->mRemovedAnimations.AppendElement(aPlayer);
|
||||
m->mRemovedAnimations.AppendElement(aAnimation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationReceiver::AnimationAdded(AnimationPlayer* aPlayer)
|
||||
nsAnimationReceiver::AnimationAdded(Animation* aAnimation)
|
||||
{
|
||||
RecordAnimationMutation(aPlayer, eAnimationMutation_Added);
|
||||
RecordAnimationMutation(aAnimation, eAnimationMutation_Added);
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationReceiver::AnimationChanged(AnimationPlayer* aPlayer)
|
||||
nsAnimationReceiver::AnimationChanged(Animation* aAnimation)
|
||||
{
|
||||
RecordAnimationMutation(aPlayer, eAnimationMutation_Changed);
|
||||
RecordAnimationMutation(aAnimation, eAnimationMutation_Changed);
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationReceiver::AnimationRemoved(AnimationPlayer* aPlayer)
|
||||
nsAnimationReceiver::AnimationRemoved(Animation* aAnimation)
|
||||
{
|
||||
RecordAnimationMutation(aPlayer, eAnimationMutation_Removed);
|
||||
RecordAnimationMutation(aAnimation, eAnimationMutation_Removed);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsAnimationReceiver, nsMutationReceiver,
|
||||
|
@ -1020,11 +1020,11 @@ nsAutoAnimationMutationBatch::Done()
|
|||
|
||||
for (const Entry& e : mEntries) {
|
||||
if (e.mState == eState_Added) {
|
||||
m->mAddedAnimations.AppendElement(e.mPlayer);
|
||||
m->mAddedAnimations.AppendElement(e.mAnimation);
|
||||
} else if (e.mState == eState_Removed) {
|
||||
m->mRemovedAnimations.AppendElement(e.mPlayer);
|
||||
m->mRemovedAnimations.AppendElement(e.mAnimation);
|
||||
} else if (e.mState == eState_RemainedPresent && e.mChanged) {
|
||||
m->mChangedAnimations.AppendElement(e.mPlayer);
|
||||
m->mChangedAnimations.AppendElement(e.mAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/dom/MutationObserverBinding.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "mozilla/dom/AnimationPlayer.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "nsIAnimationObserver.h"
|
||||
|
||||
class nsDOMMutationObserver;
|
||||
|
@ -36,7 +36,7 @@ class nsDOMMutationRecord final : public nsISupports,
|
|||
virtual ~nsDOMMutationRecord() {}
|
||||
|
||||
public:
|
||||
typedef nsTArray<nsRefPtr<mozilla::dom::AnimationPlayer>> AnimationPlayerArray;
|
||||
typedef nsTArray<nsRefPtr<mozilla::dom::Animation>> AnimationArray;
|
||||
|
||||
nsDOMMutationRecord(nsIAtom* aType, nsISupports* aOwner)
|
||||
: mType(aType), mAttrNamespace(NullString()), mPrevValue(NullString()), mOwner(aOwner)
|
||||
|
@ -95,17 +95,17 @@ public:
|
|||
aRetVal.SetOwnedString(mPrevValue);
|
||||
}
|
||||
|
||||
void GetAddedAnimations(AnimationPlayerArray& aRetVal) const
|
||||
void GetAddedAnimations(AnimationArray& aRetVal) const
|
||||
{
|
||||
aRetVal = mAddedAnimations;
|
||||
}
|
||||
|
||||
void GetRemovedAnimations(AnimationPlayerArray& aRetVal) const
|
||||
void GetRemovedAnimations(AnimationArray& aRetVal) const
|
||||
{
|
||||
aRetVal = mRemovedAnimations;
|
||||
}
|
||||
|
||||
void GetChangedAnimations(AnimationPlayerArray& aRetVal) const
|
||||
void GetChangedAnimations(AnimationArray& aRetVal) const
|
||||
{
|
||||
aRetVal = mChangedAnimations;
|
||||
}
|
||||
|
@ -119,9 +119,9 @@ public:
|
|||
nsRefPtr<nsSimpleContentList> mRemovedNodes;
|
||||
nsCOMPtr<nsINode> mPreviousSibling;
|
||||
nsCOMPtr<nsINode> mNextSibling;
|
||||
AnimationPlayerArray mAddedAnimations;
|
||||
AnimationPlayerArray mRemovedAnimations;
|
||||
AnimationPlayerArray mChangedAnimations;
|
||||
AnimationArray mAddedAnimations;
|
||||
AnimationArray mRemovedAnimations;
|
||||
AnimationArray mChangedAnimations;
|
||||
|
||||
nsRefPtr<nsDOMMutationRecord> mNext;
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
|
@ -434,7 +434,7 @@ private:
|
|||
eAnimationMutation_Removed
|
||||
};
|
||||
|
||||
void RecordAnimationMutation(mozilla::dom::AnimationPlayer* aPlayer,
|
||||
void RecordAnimationMutation(mozilla::dom::Animation* aAnimation,
|
||||
AnimationMutation aMutationType);
|
||||
};
|
||||
|
||||
|
@ -756,13 +756,13 @@ public:
|
|||
return sCurrentBatch->mBatchTarget;
|
||||
}
|
||||
|
||||
static void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer)
|
||||
static void AnimationAdded(mozilla::dom::Animation* aAnimation)
|
||||
{
|
||||
if (!IsBatching()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Entry* entry = sCurrentBatch->FindEntry(aPlayer);
|
||||
Entry* entry = sCurrentBatch->FindEntry(aAnimation);
|
||||
if (entry) {
|
||||
switch (entry->mState) {
|
||||
case eState_RemainedAbsent:
|
||||
|
@ -777,15 +777,15 @@ public:
|
|||
}
|
||||
} else {
|
||||
entry = sCurrentBatch->mEntries.AppendElement();
|
||||
entry->mPlayer = aPlayer;
|
||||
entry->mAnimation = aAnimation;
|
||||
entry->mState = eState_Added;
|
||||
entry->mChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer)
|
||||
static void AnimationChanged(mozilla::dom::Animation* aAnimation)
|
||||
{
|
||||
Entry* entry = sCurrentBatch->FindEntry(aPlayer);
|
||||
Entry* entry = sCurrentBatch->FindEntry(aAnimation);
|
||||
if (entry) {
|
||||
NS_ASSERTION(entry->mState == eState_RemainedPresent ||
|
||||
entry->mState == eState_Added,
|
||||
|
@ -794,15 +794,15 @@ public:
|
|||
entry->mChanged = true;
|
||||
} else {
|
||||
entry = sCurrentBatch->mEntries.AppendElement();
|
||||
entry->mPlayer = aPlayer;
|
||||
entry->mAnimation = aAnimation;
|
||||
entry->mState = eState_RemainedPresent;
|
||||
entry->mChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer)
|
||||
static void AnimationRemoved(mozilla::dom::Animation* aAnimation)
|
||||
{
|
||||
Entry* entry = sCurrentBatch->FindEntry(aPlayer);
|
||||
Entry* entry = sCurrentBatch->FindEntry(aAnimation);
|
||||
if (entry) {
|
||||
switch (entry->mState) {
|
||||
case eState_RemainedPresent:
|
||||
|
@ -817,17 +817,17 @@ public:
|
|||
}
|
||||
} else {
|
||||
entry = sCurrentBatch->mEntries.AppendElement();
|
||||
entry->mPlayer = aPlayer;
|
||||
entry->mAnimation = aAnimation;
|
||||
entry->mState = eState_Removed;
|
||||
entry->mChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Entry* FindEntry(mozilla::dom::AnimationPlayer* aPlayer)
|
||||
Entry* FindEntry(mozilla::dom::Animation* aAnimation)
|
||||
{
|
||||
for (Entry& e : mEntries) {
|
||||
if (e.mPlayer == aPlayer) {
|
||||
if (e.mAnimation == aAnimation) {
|
||||
return &e;
|
||||
}
|
||||
}
|
||||
|
@ -843,7 +843,7 @@ private:
|
|||
|
||||
struct Entry
|
||||
{
|
||||
nsRefPtr<mozilla::dom::AnimationPlayer> mPlayer;
|
||||
nsRefPtr<mozilla::dom::Animation> mAnimation;
|
||||
State mState;
|
||||
bool mChanged;
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "nsFrameManager.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "mozilla/dom/Touch.h"
|
||||
#include "mozilla/PendingPlayerTracker.h"
|
||||
#include "mozilla/PendingAnimationTracker.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
#include "nsFrame.h"
|
||||
#include "mozilla/layers/ShadowLayers.h"
|
||||
|
@ -2342,16 +2342,15 @@ nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds)
|
|||
// Before we advance the time, we should trigger any animations that are
|
||||
// waiting to start. This is because there are many tests that call this
|
||||
// which expect animations to start immediately. Ideally, we should make
|
||||
// all these tests do an asynchronous wait on the corresponding animation
|
||||
// player's 'ready' promise before continuing. Then we could remove the
|
||||
// special handling here and the code path followed when testing would
|
||||
// more closely match the code path during regular operation. Filed as
|
||||
// bug 1112957.
|
||||
// all these tests do an asynchronous wait on the corresponding animation's
|
||||
// 'ready' promise before continuing. Then we could remove the special
|
||||
// handling here and the code path followed when testing would more closely
|
||||
// match the code path during regular operation. Filed as bug 1112957.
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
if (doc) {
|
||||
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
|
||||
PendingAnimationTracker* tracker = doc->GetPendingAnimationTracker();
|
||||
if (tracker) {
|
||||
tracker->TriggerPendingPlayersNow();
|
||||
tracker->TriggerPendingAnimationsNow();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2019,7 +2019,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStateObjectCached)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUndoManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentTimeline)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingPlayerTracker)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingAnimationTracker)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTemplateContentsOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildrenCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRegistry)
|
||||
|
@ -2103,7 +2103,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedEncoder)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mUndoManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentTimeline)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingPlayerTracker)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingAnimationTracker)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateContentsOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRegistry)
|
||||
|
@ -7492,14 +7492,14 @@ nsDocument::GetAnimationController()
|
|||
return mAnimationController;
|
||||
}
|
||||
|
||||
PendingPlayerTracker*
|
||||
nsDocument::GetOrCreatePendingPlayerTracker()
|
||||
PendingAnimationTracker*
|
||||
nsDocument::GetOrCreatePendingAnimationTracker()
|
||||
{
|
||||
if (!mPendingPlayerTracker) {
|
||||
mPendingPlayerTracker = new PendingPlayerTracker(this);
|
||||
if (!mPendingAnimationTracker) {
|
||||
mPendingAnimationTracker = new PendingAnimationTracker(this);
|
||||
}
|
||||
|
||||
return mPendingPlayerTracker;
|
||||
return mPendingAnimationTracker;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/PendingPlayerTracker.h"
|
||||
#include "mozilla/PendingAnimationTracker.h"
|
||||
#include "mozilla/dom/DOMImplementation.h"
|
||||
#include "mozilla/dom/StyleSheetList.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
@ -1050,14 +1050,14 @@ public:
|
|||
// If HasAnimationController is true, this is guaranteed to return non-null.
|
||||
nsSMILAnimationController* GetAnimationController() override;
|
||||
|
||||
virtual mozilla::PendingPlayerTracker*
|
||||
GetPendingPlayerTracker() final override
|
||||
virtual mozilla::PendingAnimationTracker*
|
||||
GetPendingAnimationTracker() final override
|
||||
{
|
||||
return mPendingPlayerTracker;
|
||||
return mPendingAnimationTracker;
|
||||
}
|
||||
|
||||
virtual mozilla::PendingPlayerTracker*
|
||||
GetOrCreatePendingPlayerTracker() override;
|
||||
virtual mozilla::PendingAnimationTracker*
|
||||
GetOrCreatePendingAnimationTracker() override;
|
||||
|
||||
void SetImagesNeedAnimating(bool aAnimating) override;
|
||||
|
||||
|
@ -1540,9 +1540,9 @@ protected:
|
|||
// Array of observers
|
||||
nsTObserverArray<nsIDocumentObserver*> mObservers;
|
||||
|
||||
// Tracker for animation players that are waiting to start.
|
||||
// nullptr until GetOrCreatePendingPlayerTracker is called.
|
||||
nsRefPtr<mozilla::PendingPlayerTracker> mPendingPlayerTracker;
|
||||
// Tracker for animations that are waiting to start.
|
||||
// nullptr until GetOrCreatePendingAnimationTracker is called.
|
||||
nsRefPtr<mozilla::PendingAnimationTracker> mPendingAnimationTracker;
|
||||
|
||||
// Weak reference to the scope object (aka the script global object)
|
||||
// that, unlike mScriptGlobalObject, is never unset once set. This
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class AnimationPlayer;
|
||||
class Animation;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,36 +22,36 @@ class nsIAnimationObserver : public nsIMutationObserver
|
|||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IANIMATION_OBSERVER_IID)
|
||||
|
||||
virtual void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer) = 0;
|
||||
virtual void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer) = 0;
|
||||
virtual void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer) = 0;
|
||||
virtual void AnimationAdded(mozilla::dom::Animation* aAnimation) = 0;
|
||||
virtual void AnimationChanged(mozilla::dom::Animation* aAnimation) = 0;
|
||||
virtual void AnimationRemoved(mozilla::dom::Animation* aAnimation) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIAnimationObserver, NS_IANIMATION_OBSERVER_IID)
|
||||
|
||||
#define NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONADDED \
|
||||
virtual void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer) \
|
||||
virtual void AnimationAdded(mozilla::dom::Animation* aAnimation) \
|
||||
override;
|
||||
|
||||
#define NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONCHANGED \
|
||||
virtual void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer) \
|
||||
virtual void AnimationChanged(mozilla::dom::Animation* aAnimation) \
|
||||
override;
|
||||
|
||||
#define NS_DECL_NSIANIMATIONOBSERVER_ANIMATIONREMOVED \
|
||||
virtual void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer) \
|
||||
virtual void AnimationRemoved(mozilla::dom::Animation* aAnimation) \
|
||||
override;
|
||||
|
||||
#define NS_IMPL_NSIANIMATIONOBSERVER_STUB(class_) \
|
||||
void \
|
||||
class_::AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer) \
|
||||
class_::AnimationAdded(mozilla::dom::Animation* aAnimation) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
class_::AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer) \
|
||||
class_::AnimationChanged(mozilla::dom::Animation* aAnimation) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
class_::AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer) \
|
||||
class_::AnimationRemoved(mozilla::dom::Animation* aAnimation) \
|
||||
{ \
|
||||
} \
|
||||
NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(class_) \
|
||||
|
|
|
@ -88,7 +88,7 @@ namespace mozilla {
|
|||
class CSSStyleSheet;
|
||||
class ErrorResult;
|
||||
class EventStates;
|
||||
class PendingPlayerTracker;
|
||||
class PendingAnimationTracker;
|
||||
class SVGAttrAnimationRuleProcessor;
|
||||
|
||||
namespace css {
|
||||
|
@ -1837,16 +1837,17 @@ public:
|
|||
// mAnimationController isn't yet initialized.
|
||||
virtual nsSMILAnimationController* GetAnimationController() = 0;
|
||||
|
||||
// Gets the tracker for animation players that are waiting to start.
|
||||
// Returns nullptr if there is no pending player tracker for this document
|
||||
// Gets the tracker for animations that are waiting to start.
|
||||
// Returns nullptr if there is no pending animation tracker for this document
|
||||
// which will be the case if there have never been any CSS animations or
|
||||
// transitions on elements in the document.
|
||||
virtual mozilla::PendingPlayerTracker* GetPendingPlayerTracker() = 0;
|
||||
virtual mozilla::PendingAnimationTracker* GetPendingAnimationTracker() = 0;
|
||||
|
||||
// Gets the tracker for animation players that are waiting to start and
|
||||
// Gets the tracker for animations that are waiting to start and
|
||||
// creates it if it doesn't already exist. As a result, the return value
|
||||
// will never be nullptr.
|
||||
virtual mozilla::PendingPlayerTracker* GetOrCreatePendingPlayerTracker() = 0;
|
||||
virtual mozilla::PendingAnimationTracker*
|
||||
GetOrCreatePendingAnimationTracker() = 0;
|
||||
|
||||
// Makes the images on this document capable of having their animation
|
||||
// active or suspended. An Image will animate as long as at least one of its
|
||||
|
|
|
@ -1971,7 +1971,10 @@ protected:
|
|||
|
||||
nsRefPtr<mozilla::dom::NodeInfo> mNodeInfo;
|
||||
|
||||
nsINode* mParent;
|
||||
// mParent is an owning ref most of the time, except for the case of document
|
||||
// nodes, so it cannot be represented by nsCOMPtr, so mark is as
|
||||
// MOZ_OWNING_REF.
|
||||
nsINode* MOZ_OWNING_REF mParent;
|
||||
|
||||
private:
|
||||
// Boolean flags.
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "nsBindingManager.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/AnimationPlayer.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/HTMLImageElement.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/KeyframeEffect.h"
|
||||
|
@ -216,9 +216,9 @@ nsNodeUtils::ContentRemoved(nsINode* aContainer,
|
|||
}
|
||||
|
||||
static inline Element*
|
||||
GetTarget(AnimationPlayer* aPlayer)
|
||||
GetTarget(Animation* aAnimation)
|
||||
{
|
||||
KeyframeEffectReadonly* effect = aPlayer->GetEffect();
|
||||
KeyframeEffectReadonly* effect = aAnimation->GetEffect();
|
||||
if (!effect) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -238,44 +238,44 @@ GetTarget(AnimationPlayer* aPlayer)
|
|||
}
|
||||
|
||||
void
|
||||
nsNodeUtils::AnimationAdded(AnimationPlayer* aPlayer)
|
||||
nsNodeUtils::AnimationAdded(Animation* aAnimation)
|
||||
{
|
||||
Element* target = GetTarget(aPlayer);
|
||||
Element* target = GetTarget(aAnimation);
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
nsIDocument* doc = target->OwnerDoc();
|
||||
|
||||
if (doc->MayHaveAnimationObservers()) {
|
||||
IMPL_ANIMATION_NOTIFICATION(AnimationAdded, target, (aPlayer));
|
||||
IMPL_ANIMATION_NOTIFICATION(AnimationAdded, target, (aAnimation));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsNodeUtils::AnimationChanged(AnimationPlayer* aPlayer)
|
||||
nsNodeUtils::AnimationChanged(Animation* aAnimation)
|
||||
{
|
||||
Element* target = GetTarget(aPlayer);
|
||||
Element* target = GetTarget(aAnimation);
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
nsIDocument* doc = target->OwnerDoc();
|
||||
|
||||
if (doc->MayHaveAnimationObservers()) {
|
||||
IMPL_ANIMATION_NOTIFICATION(AnimationChanged, target, (aPlayer));
|
||||
IMPL_ANIMATION_NOTIFICATION(AnimationChanged, target, (aAnimation));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsNodeUtils::AnimationRemoved(AnimationPlayer* aPlayer)
|
||||
nsNodeUtils::AnimationRemoved(Animation* aAnimation)
|
||||
{
|
||||
Element* target = GetTarget(aPlayer);
|
||||
Element* target = GetTarget(aAnimation);
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
nsIDocument* doc = target->OwnerDoc();
|
||||
|
||||
if (doc->MayHaveAnimationObservers()) {
|
||||
IMPL_ANIMATION_NOTIFICATION(AnimationRemoved, target, (aPlayer));
|
||||
IMPL_ANIMATION_NOTIFICATION(AnimationRemoved, target, (aAnimation));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ template<class E> class nsCOMArray;
|
|||
class nsCycleCollectionTraversalCallback;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class AnimationPlayer;
|
||||
class Animation;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,9 +127,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static void AnimationAdded(mozilla::dom::AnimationPlayer* aPlayer);
|
||||
static void AnimationChanged(mozilla::dom::AnimationPlayer* aPlayer);
|
||||
static void AnimationRemoved(mozilla::dom::AnimationPlayer* aPlayer);
|
||||
static void AnimationAdded(mozilla::dom::Animation* aAnimation);
|
||||
static void AnimationChanged(mozilla::dom::Animation* aAnimation);
|
||||
static void AnimationRemoved(mozilla::dom::Animation* aAnimation);
|
||||
|
||||
/**
|
||||
* To be called when reference count of aNode drops to zero.
|
||||
|
|
|
@ -2733,8 +2733,10 @@ nsObjectLoadingContent::PluginDestroyed()
|
|||
// plugins in plugin host. Invalidate instance owner / prototype but otherwise
|
||||
// don't take any action.
|
||||
TeardownProtoChain();
|
||||
mInstanceOwner->Destroy();
|
||||
mInstanceOwner = nullptr;
|
||||
if (mInstanceOwner) {
|
||||
mInstanceOwner->Destroy();
|
||||
mInstanceOwner = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -8604,6 +8604,26 @@ class CGStaticMethodJitinfo(CGGeneric):
|
|||
IDLToCIdentifier(method.identifier.name))))
|
||||
|
||||
|
||||
class CGMethodIdentityTest(CGAbstractMethod):
|
||||
"""
|
||||
A class to generate a method-identity test for a given IDL operation.
|
||||
"""
|
||||
def __init__(self, descriptor, method):
|
||||
self.method = method
|
||||
name = "Is%sMethod" % MakeNativeName(method.identifier.name)
|
||||
CGAbstractMethod.__init__(self, descriptor, name, 'bool',
|
||||
[Argument('JS::Handle<JSObject*>', 'aObj')])
|
||||
|
||||
def definition_body(self):
|
||||
return dedent(
|
||||
"""
|
||||
MOZ_ASSERT(aObj);
|
||||
return js::IsFunctionObject(aObj) &&
|
||||
js::FunctionObjectIsNative(aObj) &&
|
||||
FUNCTION_VALUE_TO_JITINFO(JS::ObjectValue(*aObj)) == &%s_methodinfo;
|
||||
""" % IDLToCIdentifier(self.method.identifier.name))
|
||||
|
||||
|
||||
def getEnumValueName(value):
|
||||
# Some enum values can be empty strings. Others might have weird
|
||||
# characters in them. Deal with the former by returning "_empty",
|
||||
|
@ -11200,6 +11220,8 @@ class CGDescriptor(CGThing):
|
|||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||
if props.isCrossOriginMethod:
|
||||
crossOriginMethods.add(m.identifier.name)
|
||||
if m.getExtendedAttribute("MethodIdentityTestable"):
|
||||
cgThings.append(CGMethodIdentityTest(descriptor, m))
|
||||
elif m.isAttr():
|
||||
if m.stringifier:
|
||||
raise TypeError("Stringifier attributes not supported yet. "
|
||||
|
|
|
@ -2776,7 +2776,7 @@ class IDLBuiltinType(IDLType):
|
|||
self._typeTag == IDLBuiltinType.Types.unrestricted_double
|
||||
|
||||
def isSerializable(self):
|
||||
return self.isPrimitive() or self.isDOMString() or self.isDate()
|
||||
return self.isPrimitive() or self.isString() or self.isDate()
|
||||
|
||||
def includesRestrictedFloat(self):
|
||||
return self.isFloat() and not self.isUnrestricted()
|
||||
|
@ -4163,7 +4163,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
identifier == "Func" or
|
||||
identifier == "AvailableIn" or
|
||||
identifier == "CheckPermissions" or
|
||||
identifier == "BinaryName"):
|
||||
identifier == "BinaryName" or
|
||||
identifier == "MethodIdentityTestable"):
|
||||
# Known attributes that we don't need to do anything with here
|
||||
pass
|
||||
else:
|
||||
|
|
|
@ -701,18 +701,19 @@ Context::ThreadsafeHandle::ContextDestroyed(Context* aContext)
|
|||
|
||||
// static
|
||||
already_AddRefed<Context>
|
||||
Context::Create(Manager* aManager, Action* aQuotaIOThreadAction)
|
||||
Context::Create(Manager* aManager, Action* aQuotaIOThreadAction,
|
||||
Context* aOldContext)
|
||||
{
|
||||
nsRefPtr<Context> context = new Context(aManager);
|
||||
|
||||
// Do this here to avoid doing an AddRef() in the constructor
|
||||
context->mInitRunnable = new QuotaInitRunnable(context, aManager,
|
||||
aQuotaIOThreadAction);
|
||||
nsresult rv = context->mInitRunnable->Dispatch();
|
||||
if (NS_FAILED(rv)) {
|
||||
// Shutdown must be delayed until all Contexts are destroyed. Shutdown
|
||||
// must also prevent any new Contexts from being constructed. Crash
|
||||
// for this invariant violation.
|
||||
MOZ_CRASH("Failed to dispatch QuotaInitRunnable.");
|
||||
|
||||
if (aOldContext) {
|
||||
aOldContext->SetNextContext(context);
|
||||
} else {
|
||||
context->Start();
|
||||
}
|
||||
|
||||
return context.forget();
|
||||
|
@ -720,7 +721,7 @@ Context::Create(Manager* aManager, Action* aQuotaIOThreadAction)
|
|||
|
||||
Context::Context(Manager* aManager)
|
||||
: mManager(aManager)
|
||||
, mState(STATE_CONTEXT_INIT)
|
||||
, mState(STATE_CONTEXT_PREINIT)
|
||||
{
|
||||
MOZ_ASSERT(mManager);
|
||||
}
|
||||
|
@ -735,7 +736,8 @@ Context::Dispatch(nsIEventTarget* aTarget, Action* aAction)
|
|||
MOZ_ASSERT(mState != STATE_CONTEXT_CANCELED);
|
||||
if (mState == STATE_CONTEXT_CANCELED) {
|
||||
return;
|
||||
} else if (mState == STATE_CONTEXT_INIT) {
|
||||
} else if (mState == STATE_CONTEXT_INIT ||
|
||||
mState == STATE_CONTEXT_PREINIT) {
|
||||
PendingAction* pending = mPendingActions.AppendElement();
|
||||
pending->mTarget = aTarget;
|
||||
pending->mAction = aAction;
|
||||
|
@ -751,8 +753,15 @@ Context::CancelAll()
|
|||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Context);
|
||||
|
||||
if (mInitRunnable) {
|
||||
MOZ_ASSERT(mState == STATE_CONTEXT_INIT);
|
||||
// In PREINIT state we have not dispatch the init runnable yet. Just
|
||||
// forget it.
|
||||
if (mState == STATE_CONTEXT_PREINIT) {
|
||||
mInitRunnable = nullptr;
|
||||
|
||||
// In INIT state we have dispatched the runnable, but not received the
|
||||
// async completion yet. Cancel the runnable, but don't forget about it
|
||||
// until we get OnQuotaInit() callback.
|
||||
} else if (mState == STATE_CONTEXT_INIT) {
|
||||
mInitRunnable->Cancel();
|
||||
}
|
||||
|
||||
|
@ -823,6 +832,34 @@ Context::~Context()
|
|||
}
|
||||
|
||||
mManager->RemoveContext(this);
|
||||
|
||||
if (mNextContext) {
|
||||
mNextContext->Start();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Context::Start()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Context);
|
||||
|
||||
// Previous context closing delayed our start, but then we were canceled.
|
||||
// In this case, just do nothing here.
|
||||
if (mState == STATE_CONTEXT_CANCELED) {
|
||||
MOZ_ASSERT(!mInitRunnable);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState == STATE_CONTEXT_PREINIT);
|
||||
mState = STATE_CONTEXT_INIT;
|
||||
|
||||
nsresult rv = mInitRunnable->Dispatch();
|
||||
if (NS_FAILED(rv)) {
|
||||
// Shutdown must be delayed until all Contexts are destroyed. Shutdown
|
||||
// must also prevent any new Contexts from being constructed. Crash
|
||||
// for this invariant violation.
|
||||
MOZ_CRASH("Failed to dispatch QuotaInitRunnable.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -905,6 +942,15 @@ Context::CreateThreadsafeHandle()
|
|||
return ref.forget();
|
||||
}
|
||||
|
||||
void
|
||||
Context::SetNextContext(Context* aNextContext)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Context);
|
||||
MOZ_ASSERT(aNextContext);
|
||||
MOZ_ASSERT(!mNextContext);
|
||||
mNextContext = aNextContext;
|
||||
}
|
||||
|
||||
} // namespace cache
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -111,7 +111,7 @@ public:
|
|||
// will run on the QuotaManager IO thread. Note, this Action must
|
||||
// be execute synchronously.
|
||||
static already_AddRefed<Context>
|
||||
Create(Manager* aManager, Action* aQuotaIOThreadAction);
|
||||
Create(Manager* aManager, Action* aQuotaIOThreadAction, Context* aOldContext);
|
||||
|
||||
// Execute given action on the target once the quota manager has been
|
||||
// initialized.
|
||||
|
@ -157,6 +157,7 @@ private:
|
|||
|
||||
enum State
|
||||
{
|
||||
STATE_CONTEXT_PREINIT,
|
||||
STATE_CONTEXT_INIT,
|
||||
STATE_CONTEXT_READY,
|
||||
STATE_CONTEXT_CANCELED
|
||||
|
@ -170,6 +171,7 @@ private:
|
|||
|
||||
explicit Context(Manager* aManager);
|
||||
~Context();
|
||||
void Start();
|
||||
void DispatchAction(nsIEventTarget* aTarget, Action* aAction);
|
||||
void OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
|
||||
nsMainThreadPtrHandle<OfflineStorage>& aOfflineStorage);
|
||||
|
@ -177,6 +179,9 @@ private:
|
|||
already_AddRefed<ThreadsafeHandle>
|
||||
CreateThreadsafeHandle();
|
||||
|
||||
void
|
||||
SetNextContext(Context* aNextContext);
|
||||
|
||||
nsRefPtr<Manager> mManager;
|
||||
State mState;
|
||||
QuotaInfo mQuotaInfo;
|
||||
|
@ -194,6 +199,7 @@ private:
|
|||
nsRefPtr<ThreadsafeHandle> mThreadsafeHandle;
|
||||
|
||||
nsMainThreadPtrHandle<OfflineStorage> mOfflineStorage;
|
||||
nsRefPtr<Context> mNextContext;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(cache::Context)
|
||||
|
|
|
@ -157,7 +157,12 @@ public:
|
|||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
ref = new Manager(aManagerId, ioThread);
|
||||
ref->Init();
|
||||
|
||||
// There may be an old manager for this origin in the process of
|
||||
// cleaning up. We need to tell the new manager about this so
|
||||
// that it won't actually start until the old manager is done.
|
||||
nsRefPtr<Manager> oldManager = Get(aManagerId, Closing);
|
||||
ref->Init(oldManager);
|
||||
|
||||
MOZ_ASSERT(!sFactory->mManagerList.Contains(ref));
|
||||
sFactory->mManagerList.AppendElement(ref);
|
||||
|
@ -169,20 +174,20 @@ public:
|
|||
}
|
||||
|
||||
static already_AddRefed<Manager>
|
||||
Get(ManagerId* aManagerId)
|
||||
Get(ManagerId* aManagerId, State aState = Open)
|
||||
{
|
||||
mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
nsresult rv = MaybeCreateInstance();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; }
|
||||
|
||||
ManagerList::ForwardIterator iter(sFactory->mManagerList);
|
||||
// Iterate in reverse to find the most recent, matching Manager. This
|
||||
// is important when looking for a Closing Manager. If a new Manager
|
||||
// chains to an old Manager we want it to be the most recent one.
|
||||
ManagerList::BackwardIterator iter(sFactory->mManagerList);
|
||||
while (iter.HasMore()) {
|
||||
nsRefPtr<Manager> manager = iter.GetNext();
|
||||
// If there is an invalid Manager finishing up and a new Manager
|
||||
// is created for the same origin, then the new Manager will
|
||||
// be blocked until QuotaManager finishes clearing the origin.
|
||||
if (!manager->IsClosing() && *manager->mManagerId == *aManagerId) {
|
||||
if (aState == manager->GetState() && *manager->mManagerId == *aManagerId) {
|
||||
return manager.forget();
|
||||
}
|
||||
}
|
||||
|
@ -1450,7 +1455,7 @@ Manager::RemoveContext(Context* aContext)
|
|||
// Whether the Context destruction was triggered from the Manager going
|
||||
// idle or the underlying storage being invalidated, we should know we
|
||||
// are closing before the Conext is destroyed.
|
||||
MOZ_ASSERT(mClosing);
|
||||
MOZ_ASSERT(mState == Closing);
|
||||
|
||||
mContext = nullptr;
|
||||
|
||||
|
@ -1465,14 +1470,14 @@ Manager::NoteClosing()
|
|||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Manager);
|
||||
// This can be called more than once legitimately through different paths.
|
||||
mClosing = true;
|
||||
mState = Closing;
|
||||
}
|
||||
|
||||
bool
|
||||
Manager::IsClosing() const
|
||||
Manager::State
|
||||
Manager::GetState() const
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Manager);
|
||||
return mClosing;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1593,7 +1598,7 @@ Manager::ExecuteCacheOp(Listener* aListener, CacheId aCacheId,
|
|||
MOZ_ASSERT(aOpArgs.type() != CacheOpArgs::TCacheAddAllArgs);
|
||||
MOZ_ASSERT(aOpArgs.type() != CacheOpArgs::TCachePutAllArgs);
|
||||
|
||||
if (mClosing) {
|
||||
if (mState == Closing) {
|
||||
aListener->OnOpComplete(ErrorResult(NS_ERROR_FAILURE), void_t());
|
||||
return;
|
||||
}
|
||||
|
@ -1637,7 +1642,7 @@ Manager::ExecuteStorageOp(Listener* aListener, Namespace aNamespace,
|
|||
NS_ASSERT_OWNINGTHREAD(Manager);
|
||||
MOZ_ASSERT(aListener);
|
||||
|
||||
if (mClosing) {
|
||||
if (mState == Closing) {
|
||||
aListener->OnOpComplete(ErrorResult(NS_ERROR_FAILURE), void_t());
|
||||
return;
|
||||
}
|
||||
|
@ -1686,7 +1691,7 @@ Manager::ExecutePutAll(Listener* aListener, CacheId aCacheId,
|
|||
NS_ASSERT_OWNINGTHREAD(Manager);
|
||||
MOZ_ASSERT(aListener);
|
||||
|
||||
if (mClosing) {
|
||||
if (mState == Closing) {
|
||||
aListener->OnOpComplete(ErrorResult(NS_ERROR_FAILURE), CachePutAllResult());
|
||||
return;
|
||||
}
|
||||
|
@ -1708,7 +1713,7 @@ Manager::Manager(ManagerId* aManagerId, nsIThread* aIOThread)
|
|||
, mIOThread(aIOThread)
|
||||
, mContext(nullptr)
|
||||
, mShuttingDown(false)
|
||||
, mClosing(false)
|
||||
, mState(Open)
|
||||
{
|
||||
MOZ_ASSERT(mManagerId);
|
||||
MOZ_ASSERT(mIOThread);
|
||||
|
@ -1717,7 +1722,7 @@ Manager::Manager(ManagerId* aManagerId, nsIThread* aIOThread)
|
|||
Manager::~Manager()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Manager);
|
||||
MOZ_ASSERT(mClosing);
|
||||
MOZ_ASSERT(mState == Closing);
|
||||
MOZ_ASSERT(!mContext);
|
||||
|
||||
nsCOMPtr<nsIThread> ioThread;
|
||||
|
@ -1731,15 +1736,20 @@ Manager::~Manager()
|
|||
}
|
||||
|
||||
void
|
||||
Manager::Init()
|
||||
Manager::Init(Manager* aOldManager)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Manager);
|
||||
|
||||
nsRefPtr<Context> oldContext;
|
||||
if (aOldManager) {
|
||||
oldContext = aOldManager->mContext;
|
||||
}
|
||||
|
||||
// Create the context immediately. Since there can at most be one Context
|
||||
// per Manager now, this lets us cleanly call Factory::Remove() once the
|
||||
// Context goes away.
|
||||
nsRefPtr<Action> setupAction = new SetupAction();
|
||||
nsRefPtr<Context> ref = Context::Create(this, setupAction);
|
||||
nsRefPtr<Context> ref = Context::Create(this, setupAction, oldContext);
|
||||
mContext = ref;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,12 @@ public:
|
|||
~Listener() { }
|
||||
};
|
||||
|
||||
enum State
|
||||
{
|
||||
Open,
|
||||
Closing
|
||||
};
|
||||
|
||||
static nsresult GetOrCreate(ManagerId* aManagerId, Manager** aManagerOut);
|
||||
static already_AddRefed<Manager> Get(ManagerId* aManagerId);
|
||||
|
||||
|
@ -134,7 +140,8 @@ public:
|
|||
// Marks the Manager "invalid". Once the Context completes no new operations
|
||||
// will be permitted with this Manager. New actors will get a new Manager.
|
||||
void NoteClosing();
|
||||
bool IsClosing() const;
|
||||
|
||||
State GetState() const;
|
||||
|
||||
// If an actor represents a long term reference to a cache or body stream,
|
||||
// then they must call AddRefCacheId() or AddRefBodyId(). This will
|
||||
|
@ -185,7 +192,7 @@ private:
|
|||
|
||||
Manager(ManagerId* aManagerId, nsIThread* aIOThread);
|
||||
~Manager();
|
||||
void Init();
|
||||
void Init(Manager* aOldManager);
|
||||
void Shutdown();
|
||||
already_AddRefed<Context> CurrentContext();
|
||||
|
||||
|
@ -249,7 +256,7 @@ private:
|
|||
nsTArray<StreamList*> mStreamLists;
|
||||
|
||||
bool mShuttingDown;
|
||||
bool mClosing;
|
||||
State mState;
|
||||
|
||||
struct CacheIdRefCounter
|
||||
{
|
||||
|
|
|
@ -38,16 +38,7 @@ function serviceWorkerTestExec(testFile) {
|
|||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
navigator.serviceWorker.register("worker_wrapper.js", {scope: "."})
|
||||
.then(function(registration) {
|
||||
if (registration.installing) {
|
||||
registration.installing.onstatechange = function(e) {
|
||||
e.target.onstatechange = null;
|
||||
setupSW(registration);
|
||||
};
|
||||
} else {
|
||||
setupSW(registration);
|
||||
}
|
||||
});
|
||||
navigator.serviceWorker.ready.then(setupSW);
|
||||
navigator.serviceWorker.register("worker_wrapper.js", {scope: "."});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4269,7 +4269,10 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
|
|||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
}
|
||||
bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage.get(), srcImage->GetSize(), mVideoTexture, LOCAL_GL_TEXTURE_2D, 1);
|
||||
const gl::OriginPos destOrigin = gl::OriginPos::TopLeft;
|
||||
bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage.get(), srcImage->GetSize(),
|
||||
mVideoTexture, LOCAL_GL_TEXTURE_2D,
|
||||
destOrigin);
|
||||
if (ok) {
|
||||
NativeSurface texSurf;
|
||||
texSurf.mType = NativeSurfaceType::OPENGL_TEXTURE;
|
||||
|
|
|
@ -1837,11 +1837,13 @@ WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget,
|
|||
0, format, type, nullptr);
|
||||
}
|
||||
|
||||
const gl::OriginPos destOrigin = mPixelStoreFlipY ? gl::OriginPos::BottomLeft
|
||||
: gl::OriginPos::TopLeft;
|
||||
bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage.get(),
|
||||
srcImage->GetSize(),
|
||||
tex->GLName(),
|
||||
texImageTarget.get(),
|
||||
mPixelStoreFlipY);
|
||||
destOrigin);
|
||||
if (ok) {
|
||||
TexInternalFormat effectiveInternalFormat =
|
||||
EffectiveInternalFormatFromInternalFormatAndType(internalFormat,
|
||||
|
|
|
@ -198,29 +198,20 @@ Directory::RemoveInternal(const StringOrFileOrDirectory& aPath, bool aRecursive,
|
|||
|
||||
if (aPath.IsFile()) {
|
||||
file = aPath.GetAsFile().Impl();
|
||||
goto parameters_check_done;
|
||||
}
|
||||
|
||||
if (aPath.IsString()) {
|
||||
} else if (aPath.IsString()) {
|
||||
if (!DOMPathToRealPath(aPath.GetAsString(), realPath)) {
|
||||
error = NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
|
||||
}
|
||||
goto parameters_check_done;
|
||||
}
|
||||
|
||||
if (!mFileSystem->IsSafeDirectory(&aPath.GetAsDirectory())) {
|
||||
} else if (!mFileSystem->IsSafeDirectory(&aPath.GetAsDirectory())) {
|
||||
error = NS_ERROR_DOM_SECURITY_ERR;
|
||||
goto parameters_check_done;
|
||||
} else {
|
||||
realPath = aPath.GetAsDirectory().mPath;
|
||||
// The target must be a descendant of this directory.
|
||||
if (!FileSystemUtils::IsDescendantPath(mPath, realPath)) {
|
||||
error = NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
realPath = aPath.GetAsDirectory().mPath;
|
||||
// The target must be a descendant of this directory.
|
||||
if (!FileSystemUtils::IsDescendantPath(mPath, realPath)) {
|
||||
error = NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
parameters_check_done:
|
||||
|
||||
nsRefPtr<RemoveTask> task = new RemoveTask(mFileSystem, mPath, file, realPath,
|
||||
aRecursive, aRv);
|
||||
if (aRv.Failed()) {
|
||||
|
|
|
@ -1461,15 +1461,7 @@ HTMLTextAreaElement::IsPasswordTextControl() const
|
|||
NS_IMETHODIMP_(int32_t)
|
||||
HTMLTextAreaElement::GetCols()
|
||||
{
|
||||
const nsAttrValue* attr = GetParsedAttr(nsGkAtoms::cols);
|
||||
if (attr) {
|
||||
int32_t cols = attr->Type() == nsAttrValue::eInteger ?
|
||||
attr->GetIntegerValue() : 0;
|
||||
// XXX why a default of 1 char, why hide it
|
||||
return (cols <= 0) ? 1 : cols;
|
||||
}
|
||||
|
||||
return DEFAULT_COLS;
|
||||
return Cols();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(int32_t)
|
||||
|
|
|
@ -2360,6 +2360,13 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
|
|||
bool aSetupOffMainThreadCompositing,
|
||||
bool aSendRegisteredChrome)
|
||||
{
|
||||
if (aSendRegisteredChrome) {
|
||||
nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
|
||||
nsChromeRegistryChrome* chromeRegistry =
|
||||
static_cast<nsChromeRegistryChrome*>(registrySvc.get());
|
||||
chromeRegistry->SendRegisteredChrome(this);
|
||||
}
|
||||
|
||||
// Initialize the message manager (and load delayed scripts) now that we
|
||||
// have established communications with the child.
|
||||
mMessageManager->InitWithCallback(this);
|
||||
|
@ -2402,13 +2409,6 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
|
|||
#endif
|
||||
}
|
||||
|
||||
if (aSendRegisteredChrome) {
|
||||
nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
|
||||
nsChromeRegistryChrome* chromeRegistry =
|
||||
static_cast<nsChromeRegistryChrome*>(registrySvc.get());
|
||||
chromeRegistry->SendRegisteredChrome(this);
|
||||
}
|
||||
|
||||
if (gAppData) {
|
||||
nsCString version(gAppData->version);
|
||||
nsCString buildID(gAppData->buildID);
|
||||
|
|
|
@ -72,10 +72,14 @@ public:
|
|||
EGLImage CopySurface(layers::Image* img) {
|
||||
mGLContext->MakeCurrent();
|
||||
|
||||
GLuint tex = CreateTextureForOffscreen(mGLContext, mGLContext->GetGLFormats(), img->GetSize());
|
||||
GLuint tex = CreateTextureForOffscreen(mGLContext, mGLContext->GetGLFormats(),
|
||||
img->GetSize());
|
||||
|
||||
GLBlitHelper helper(mGLContext);
|
||||
if (!helper.BlitImageToTexture(img, img->GetSize(), tex, LOCAL_GL_TEXTURE_2D)) {
|
||||
auto helper = mGLContext->BlitHelper();
|
||||
const gl::OriginPos destOrigin = gl::OriginPos::TopLeft;
|
||||
if (!helper->BlitImageToTexture(img, img->GetSize(), tex, LOCAL_GL_TEXTURE_2D,
|
||||
destOrigin))
|
||||
{
|
||||
mGLContext->fDeleteTextures(1, &tex);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -134,7 +138,7 @@ public:
|
|||
data.mSync = eglSync;
|
||||
data.mOwns = true;
|
||||
data.mSize = mConfig.mDisplay;
|
||||
data.mOriginPos = gl::OriginPos::BottomLeft;
|
||||
data.mOriginPos = gl::OriginPos::TopLeft;
|
||||
|
||||
layers::EGLImageImage* typedImg = static_cast<layers::EGLImageImage*>(img.get());
|
||||
typedImg->SetData(data);
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace gmp {
|
|||
GMPAudioDecoderParent::GMPAudioDecoderParent(GMPContentParent* aPlugin)
|
||||
: mIsOpen(false)
|
||||
, mShuttingDown(false)
|
||||
, mActorDestroyed(false)
|
||||
, mPlugin(aPlugin)
|
||||
, mCallback(nullptr)
|
||||
{
|
||||
|
@ -174,7 +175,9 @@ GMPAudioDecoderParent::Shutdown()
|
|||
}
|
||||
|
||||
mIsOpen = false;
|
||||
unused << SendDecodingComplete();
|
||||
if (!mActorDestroyed) {
|
||||
unused << SendDecodingComplete();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -184,6 +187,7 @@ void
|
|||
GMPAudioDecoderParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mIsOpen = false;
|
||||
mActorDestroyed = true;
|
||||
if (mCallback) {
|
||||
// May call Close() (and Shutdown()) immediately or with a delay
|
||||
mCallback->Terminated();
|
||||
|
|
|
@ -55,6 +55,7 @@ private:
|
|||
|
||||
bool mIsOpen;
|
||||
bool mShuttingDown;
|
||||
bool mActorDestroyed;
|
||||
nsRefPtr<GMPContentParent> mPlugin;
|
||||
GMPAudioDecoderCallbackProxy* mCallback;
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace gmp {
|
|||
GMPDecryptorParent::GMPDecryptorParent(GMPContentParent* aPlugin)
|
||||
: mIsOpen(false)
|
||||
, mShuttingDown(false)
|
||||
, mActorDestroyed(false)
|
||||
, mPlugin(aPlugin)
|
||||
, mCallback(nullptr)
|
||||
#ifdef DEBUG
|
||||
|
@ -347,7 +348,9 @@ GMPDecryptorParent::Shutdown()
|
|||
}
|
||||
|
||||
mIsOpen = false;
|
||||
unused << SendDecryptingComplete();
|
||||
if (!mActorDestroyed) {
|
||||
unused << SendDecryptingComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Keep this sync'd up with Shutdown
|
||||
|
@ -355,6 +358,7 @@ void
|
|||
GMPDecryptorParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mIsOpen = false;
|
||||
mActorDestroyed = true;
|
||||
if (mCallback) {
|
||||
// May call Close() (and Shutdown()) immediately or with a delay
|
||||
mCallback->Terminated();
|
||||
|
|
|
@ -111,6 +111,7 @@ private:
|
|||
|
||||
bool mIsOpen;
|
||||
bool mShuttingDown;
|
||||
bool mActorDestroyed;
|
||||
nsRefPtr<GMPContentParent> mPlugin;
|
||||
nsCString mPluginId;
|
||||
GMPDecryptorProxyCallback* mCallback;
|
||||
|
|
|
@ -47,6 +47,7 @@ GMPVideoDecoderParent::GMPVideoDecoderParent(GMPContentParent* aPlugin)
|
|||
: GMPSharedMemManager(aPlugin)
|
||||
, mIsOpen(false)
|
||||
, mShuttingDown(false)
|
||||
, mActorDestroyed(false)
|
||||
, mPlugin(aPlugin)
|
||||
, mCallback(nullptr)
|
||||
, mVideoHost(this)
|
||||
|
@ -213,7 +214,9 @@ GMPVideoDecoderParent::Shutdown()
|
|||
}
|
||||
|
||||
mIsOpen = false;
|
||||
unused << SendDecodingComplete();
|
||||
if (!mActorDestroyed) {
|
||||
unused << SendDecodingComplete();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -223,6 +226,7 @@ void
|
|||
GMPVideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mIsOpen = false;
|
||||
mActorDestroyed = true;
|
||||
mVideoHost.DoneWithAPI();
|
||||
|
||||
if (mCallback) {
|
||||
|
|
|
@ -81,6 +81,7 @@ private:
|
|||
|
||||
bool mIsOpen;
|
||||
bool mShuttingDown;
|
||||
bool mActorDestroyed;
|
||||
nsRefPtr<GMPContentParent> mPlugin;
|
||||
GMPVideoDecoderCallbackProxy* mCallback;
|
||||
GMPVideoHostImpl mVideoHost;
|
||||
|
|
|
@ -54,6 +54,7 @@ GMPVideoEncoderParent::GMPVideoEncoderParent(GMPContentParent *aPlugin)
|
|||
: GMPSharedMemManager(aPlugin),
|
||||
mIsOpen(false),
|
||||
mShuttingDown(false),
|
||||
mActorDestroyed(false),
|
||||
mPlugin(aPlugin),
|
||||
mCallback(nullptr),
|
||||
mVideoHost(this)
|
||||
|
@ -235,7 +236,9 @@ GMPVideoEncoderParent::Shutdown()
|
|||
mVideoHost.DoneWithAPI();
|
||||
|
||||
mIsOpen = false;
|
||||
unused << SendEncodingComplete();
|
||||
if (!mActorDestroyed) {
|
||||
unused << SendEncodingComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -250,6 +253,7 @@ GMPVideoEncoderParent::ActorDestroy(ActorDestroyReason aWhy)
|
|||
{
|
||||
LOGD(("%s::%s: %p (%d)", __CLASS__, __FUNCTION__, this, (int) aWhy));
|
||||
mIsOpen = false;
|
||||
mActorDestroyed = true;
|
||||
if (mCallback) {
|
||||
// May call Close() (and Shutdown()) immediately or with a delay
|
||||
mCallback->Terminated();
|
||||
|
|
|
@ -77,6 +77,7 @@ private:
|
|||
|
||||
bool mIsOpen;
|
||||
bool mShuttingDown;
|
||||
bool mActorDestroyed;
|
||||
nsRefPtr<GMPContentParent> mPlugin;
|
||||
GMPVideoEncoderCallbackProxy* mCallback;
|
||||
GMPVideoHostImpl mVideoHost;
|
||||
|
|
|
@ -170,7 +170,7 @@ GetPromise(JSContext* aCx, JS::Handle<JSObject*> aFunc)
|
|||
}
|
||||
};
|
||||
|
||||
// Main thread runnable to resolve thenables.
|
||||
// Runnable to resolve thenables.
|
||||
// Equivalent to the specification's ResolvePromiseViaThenableTask.
|
||||
class ThenableResolverTask final : public nsRunnable
|
||||
{
|
||||
|
@ -201,6 +201,8 @@ protected:
|
|||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSObject*> wrapper(cx, mPromise->GetWrapper());
|
||||
MOZ_ASSERT(wrapper); // It was preserved!
|
||||
// If we ever change which compartment we're working in here, make sure to
|
||||
// fix the fast-path for resolved-with-a-Promise in ResolveInternal.
|
||||
JSAutoCompartment ac(cx, wrapper);
|
||||
|
||||
JS::Rooted<JSObject*> resolveFunc(cx,
|
||||
|
@ -271,6 +273,48 @@ private:
|
|||
NS_DECL_OWNINGTHREAD;
|
||||
};
|
||||
|
||||
// Fast version of ThenableResolverTask for use in the cases when we know we're
|
||||
// calling the canonical Promise.prototype.then on an actual DOM Promise. In
|
||||
// that case we can just bypass the jumping into and out of JS and call
|
||||
// AppendCallbacks on that promise directly.
|
||||
class FastThenableResolverTask final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
FastThenableResolverTask(PromiseCallback* aResolveCallback,
|
||||
PromiseCallback* aRejectCallback,
|
||||
Promise* aNextPromise)
|
||||
: mResolveCallback(aResolveCallback)
|
||||
, mRejectCallback(aRejectCallback)
|
||||
, mNextPromise(aNextPromise)
|
||||
{
|
||||
MOZ_ASSERT(aResolveCallback);
|
||||
MOZ_ASSERT(aRejectCallback);
|
||||
MOZ_ASSERT(aNextPromise);
|
||||
MOZ_COUNT_CTOR(FastThenableResolverTask);
|
||||
}
|
||||
|
||||
virtual
|
||||
~FastThenableResolverTask()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(FastThenableResolverTask);
|
||||
MOZ_COUNT_DTOR(FastThenableResolverTask);
|
||||
}
|
||||
|
||||
protected:
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(FastThenableResolverTask);
|
||||
mNextPromise->AppendCallbacks(mResolveCallback, mRejectCallback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<PromiseCallback> mResolveCallback;
|
||||
nsRefPtr<PromiseCallback> mRejectCallback;
|
||||
nsRefPtr<Promise> mNextPromise;
|
||||
};
|
||||
|
||||
// Promise
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Promise)
|
||||
|
@ -1198,6 +1242,37 @@ Promise::ResolveInternal(JSContext* aCx,
|
|||
if (then.isObject() && JS::IsCallable(&then.toObject())) {
|
||||
// This is the then() function of the thenable aValueObj.
|
||||
JS::Rooted<JSObject*> thenObj(aCx, &then.toObject());
|
||||
|
||||
// Add a fast path for the case when we're resolved with an actual
|
||||
// Promise. This has two requirements:
|
||||
//
|
||||
// 1) valueObj is a Promise.
|
||||
// 2) thenObj is a JSFunction backed by our actual Promise::Then
|
||||
// implementation.
|
||||
//
|
||||
// If those requirements are satisfied, then we know exactly what
|
||||
// thenObj.call(valueObj) will do, so we can optimize a bit and avoid ever
|
||||
// entering JS for this stuff.
|
||||
Promise* nextPromise;
|
||||
if (PromiseBinding::IsThenMethod(thenObj) &&
|
||||
NS_SUCCEEDED(UNWRAP_OBJECT(Promise, valueObj, nextPromise))) {
|
||||
// If we were taking the codepath that involves ThenableResolverTask and
|
||||
// PromiseInit below, then eventually, in ThenableResolverTask::Run, we
|
||||
// would create some JSFunctions in the compartment of
|
||||
// this->GetWrapper() and pass them to the PromiseInit. So by the time
|
||||
// we'd see the resolution value it would be wrapped into the
|
||||
// compartment of this->GetWrapper(). The global of that compartment is
|
||||
// this->GetGlobalJSObject(), so use that as the global for
|
||||
// ResolvePromiseCallback/RejectPromiseCallback.
|
||||
JS::Rooted<JSObject*> glob(aCx, GlobalJSObject());
|
||||
nsRefPtr<PromiseCallback> resolveCb = new ResolvePromiseCallback(this, glob);
|
||||
nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(this, glob);
|
||||
nsRefPtr<FastThenableResolverTask> task =
|
||||
new FastThenableResolverTask(resolveCb, rejectCb, nextPromise);
|
||||
DispatchToMicroTask(task);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<PromiseInit> thenCallback =
|
||||
new PromiseInit(thenObj, mozilla::dom::GetIncumbentGlobal());
|
||||
nsRefPtr<ThenableResolverTask> task =
|
||||
|
|
|
@ -85,6 +85,7 @@ class Promise : public nsISupports,
|
|||
friend class RejectPromiseCallback;
|
||||
friend class ResolvePromiseCallback;
|
||||
friend class ThenableResolverTask;
|
||||
friend class FastThenableResolverTask;
|
||||
friend class WrapperPromiseCallback;
|
||||
|
||||
public:
|
||||
|
|
|
@ -6,3 +6,4 @@
|
|||
[test_promise_utils.html]
|
||||
[test_resolve.html]
|
||||
[test_resolver_return_value.html]
|
||||
[test_thenable_vs_promise_ordering.html]
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test for promise resolution ordering with thenables and promises</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
var t = async_test("A promise resolved first (with a thenable) should trigger its callbacks before a promise resolved second (with a promise).");
|
||||
t.step(function() {
|
||||
var customThenCalled = false;
|
||||
var p0 = Promise.resolve();
|
||||
p0.then = function(resolved, rejected) {
|
||||
customThenCalled = true;
|
||||
Promise.prototype.then.call(this, resolved, rejected);
|
||||
}
|
||||
var p1 = new Promise(function(r) { r(p0); });
|
||||
delete p0.then;
|
||||
var p2 = new Promise(function(r) { r(p0); });
|
||||
var resolutionOrder = "";
|
||||
Promise.all([ p1.then(function() { resolutionOrder += "1"; }),
|
||||
p2.then(function() { resolutionOrder += "2"; }) ])
|
||||
.then(t.step_func_done(function() {
|
||||
assert_true(customThenCalled, "Should have called custom then");
|
||||
assert_equals(resolutionOrder, "12");
|
||||
}));
|
||||
});
|
||||
</script>
|
|
@ -35,6 +35,8 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
function unregister() {
|
||||
return registration.unregister().then(function(result) {
|
||||
ok(result, "Unregister should return true.");
|
||||
}, function(e) {
|
||||
dump("Unregistering the SW failed with " + e + "\n");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
function unregister() {
|
||||
return registration.unregister().then(function(result) {
|
||||
ok(result, "Unregister should return true.");
|
||||
}, function(e) {
|
||||
dump("Unregistering the SW failed with " + e + "\n");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
function unregister() {
|
||||
return registration.unregister().then(function(result) {
|
||||
ok(result, "Unregister should return true.");
|
||||
}, function(e) {
|
||||
dump("Unregistering the SW failed with " + e + "\n");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
function unregister() {
|
||||
return registration.unregister().then(function(result) {
|
||||
ok(result, "Unregister should return true.");
|
||||
}, function(e) {
|
||||
dump("Unregistering the SW failed with " + e + "\n");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -129,12 +129,12 @@ var interfaceNamesInGlobalScope =
|
|||
{name: "AlarmsManager", pref: "dom.mozAlarms.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"AnalyserNode",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "Animation", pref: "dom.animations-api.core.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "AnimationEffectReadonly", pref: "dom.animations-api.core.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"AnimationEvent",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "AnimationPlayer", pref: "dom.animations-api.core.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "AnimationTimeline", pref: "dom.animations-api.core.enabled"},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -13,5 +13,5 @@
|
|||
[NoInterfaceObject]
|
||||
interface Animatable {
|
||||
[Func="nsDocument::IsWebAnimationsEnabled"]
|
||||
sequence<AnimationPlayer> getAnimations();
|
||||
sequence<Animation> getAnimations();
|
||||
};
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dev.w3.org/fxtf/web-animations/#idl-def-AnimationPlayer
|
||||
* http://w3c.github.io/web-animations/#the-animation-interface
|
||||
*
|
||||
* Copyright © 2014 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
enum AnimationPlayState { "idle", "pending", "running", "paused", "finished" };
|
||||
|
||||
[Func="nsDocument::IsWebAnimationsEnabled"]
|
||||
interface AnimationPlayer {
|
||||
interface Animation {
|
||||
// Bug 1049975: Make 'effect' writeable
|
||||
[Pure]
|
||||
readonly attribute AnimationEffectReadonly? effect;
|
||||
|
@ -27,9 +27,9 @@ interface AnimationPlayer {
|
|||
[BinaryName="playStateFromJS"]
|
||||
readonly attribute AnimationPlayState playState;
|
||||
[Throws]
|
||||
readonly attribute Promise<AnimationPlayer> ready;
|
||||
readonly attribute Promise<Animation> ready;
|
||||
[Throws]
|
||||
readonly attribute Promise<AnimationPlayer> finished;
|
||||
readonly attribute Promise<Animation> finished;
|
||||
/*
|
||||
void cancel ();
|
||||
void finish ();
|
||||
|
@ -44,6 +44,6 @@ interface AnimationPlayer {
|
|||
};
|
||||
|
||||
// Non-standard extensions
|
||||
partial interface AnimationPlayer {
|
||||
partial interface Animation {
|
||||
[ChromeOnly] readonly attribute boolean isRunningOnCompositor;
|
||||
};
|
|
@ -15,6 +15,6 @@ interface AnimationTimeline {
|
|||
[BinaryName="currentTimeAsDouble"]
|
||||
readonly attribute double? currentTime;
|
||||
// Not yet implemented:
|
||||
// AnimationPlayer play (optional TimedItem? source = null);
|
||||
// sequence<AnimationPlayer> getAnimations ();
|
||||
// Animation play (optional TimedItem? source = null);
|
||||
// sequence<Animation> getAnimations ();
|
||||
};
|
||||
|
|
|
@ -29,11 +29,11 @@ interface MutationRecord {
|
|||
[Constant]
|
||||
readonly attribute DOMString? oldValue;
|
||||
[Constant,Cached,ChromeOnly]
|
||||
readonly attribute sequence<AnimationPlayer> addedAnimations;
|
||||
readonly attribute sequence<Animation> addedAnimations;
|
||||
[Constant,Cached,ChromeOnly]
|
||||
readonly attribute sequence<AnimationPlayer> changedAnimations;
|
||||
readonly attribute sequence<Animation> changedAnimations;
|
||||
[Constant,Cached,ChromeOnly]
|
||||
readonly attribute sequence<AnimationPlayer> removedAnimations;
|
||||
readonly attribute sequence<Animation> removedAnimations;
|
||||
};
|
||||
|
||||
[Constructor(MutationCallback mutationCallback)]
|
||||
|
|
|
@ -34,7 +34,7 @@ interface _Promise {
|
|||
|
||||
// The [TreatNonCallableAsNull] annotation is required since then() should do
|
||||
// nothing instead of throwing errors when non-callable arguments are passed.
|
||||
[NewObject]
|
||||
[NewObject, MethodIdentityTestable]
|
||||
Promise<any> then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
|
||||
[TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@ WEBIDL_FILES = [
|
|||
'AlarmsManager.webidl',
|
||||
'AnalyserNode.webidl',
|
||||
'Animatable.webidl',
|
||||
'Animation.webidl',
|
||||
'AnimationEffectReadonly.webidl',
|
||||
'AnimationEvent.webidl',
|
||||
'AnimationPlayer.webidl',
|
||||
'AnimationTimeline.webidl',
|
||||
'AnonymousContent.webidl',
|
||||
'AppInfo.webidl',
|
||||
|
|
|
@ -50,7 +50,13 @@
|
|||
|
||||
my_ok(navigator.serviceWorker.controller.scriptURL.match(/worker\.js$/),
|
||||
"Controller is still worker.js");
|
||||
finish();
|
||||
|
||||
e.unregister().then(function(result) {
|
||||
my_ok(result, "Unregistering the SW should succeed");
|
||||
finish();
|
||||
}, function(e) {
|
||||
dump("Error unregistering the SW: " + e + "\n");
|
||||
});
|
||||
});
|
||||
} else {
|
||||
my_ok(false, "Should've been controlled!");
|
||||
|
|
|
@ -4,23 +4,11 @@
|
|||
window.parent.postMessage({status: "ok", result: !!v, message: msg}, "*");
|
||||
}
|
||||
|
||||
var isDone = false;
|
||||
function done(reg) {
|
||||
if (!isDone) {
|
||||
ok(reg.waiting || reg.active, "Either active or waiting worker should be available.");
|
||||
window.parent.postMessage({status: "registrationdone"}, "*");
|
||||
isDone = true;
|
||||
}
|
||||
ok(reg.active, "The active worker should be available.");
|
||||
window.parent.postMessage({status: "registrationdone"}, "*");
|
||||
}
|
||||
|
||||
navigator.serviceWorker.register("context_test.js", {scope: "."})
|
||||
.then(function(registration) {
|
||||
if (registration.installing) {
|
||||
registration.installing.onstatechange = function(e) {
|
||||
done(registration);
|
||||
};
|
||||
} else {
|
||||
done(registration);
|
||||
}
|
||||
});
|
||||
navigator.serviceWorker.ready.then(done);
|
||||
navigator.serviceWorker.register("context_test.js", {scope: "."});
|
||||
</script>
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
if (success) {
|
||||
window.parent.postMessage({status: "unregistrationdone"}, "*");
|
||||
}
|
||||
}, function(e) {
|
||||
dump("Unregistering the SW failed with " + e + "\n");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -110,10 +110,10 @@ fetchXHR('hello.gz', function(xhr) {
|
|||
});
|
||||
|
||||
fetchXHR('hello-after-extracting.gz', function(xhr) {
|
||||
my_ok(xhr.status == 200, "gzip load should be successful");
|
||||
my_ok(xhr.responseText == expectedUncompressedResponse, "gzip load should have synthesized response.");
|
||||
my_ok(xhr.getResponseHeader("Content-Encoding") == "gzip", "Content-Encoding should be gzip.");
|
||||
my_ok(xhr.getResponseHeader("Content-Length") == "35", "Content-Length should be of original gzipped file.");
|
||||
my_ok(xhr.status == 200, "gzip load after extracting should be successful");
|
||||
my_ok(xhr.responseText == expectedUncompressedResponse, "gzip load after extracting should have synthesized response.");
|
||||
my_ok(xhr.getResponseHeader("Content-Encoding") == "gzip", "Content-Encoding after extracting should be gzip.");
|
||||
my_ok(xhr.getResponseHeader("Content-Length") == "35", "Content-Length after extracting should be of original gzipped file.");
|
||||
finish();
|
||||
});
|
||||
|
||||
|
|
|
@ -4,23 +4,11 @@
|
|||
window.parent.postMessage({status: "ok", result: !!v, message: msg}, "*");
|
||||
}
|
||||
|
||||
var isDone = false;
|
||||
function done(reg) {
|
||||
if (!isDone) {
|
||||
ok(reg.waiting || reg.active, "Either active or waiting worker should be available.");
|
||||
window.parent.postMessage({status: "registrationdone"}, "*");
|
||||
isDone = true;
|
||||
}
|
||||
ok(reg.active, "The active worker should be available.");
|
||||
window.parent.postMessage({status: "registrationdone"}, "*");
|
||||
}
|
||||
|
||||
navigator.serviceWorker.register("https_test.js", {scope: "."})
|
||||
.then(function(registration) {
|
||||
if (registration.installing) {
|
||||
registration.installing.onstatechange = function(e) {
|
||||
done(registration);
|
||||
};
|
||||
} else {
|
||||
done(registration);
|
||||
}
|
||||
});
|
||||
navigator.serviceWorker.ready.then(done);
|
||||
navigator.serviceWorker.register("https_test.js", {scope: "."});
|
||||
</script>
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
if (success) {
|
||||
window.parent.postMessage({status: "unregistrationdone"}, "*");
|
||||
}
|
||||
}, function(e) {
|
||||
dump("Unregistering the SW failed with " + e + "\n");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -4,23 +4,11 @@
|
|||
window.parent.postMessage({status: "ok", result: !!v, message: msg}, "*");
|
||||
}
|
||||
|
||||
var isDone = false;
|
||||
function done(reg) {
|
||||
if (!isDone) {
|
||||
ok(reg.waiting || reg.active, "Either active or waiting worker should be available.");
|
||||
window.parent.postMessage({status: "registrationdone"}, "*");
|
||||
isDone = true;
|
||||
}
|
||||
ok(reg.active, "The active worker should be available.");
|
||||
window.parent.postMessage({status: "registrationdone"}, "*");
|
||||
}
|
||||
|
||||
navigator.serviceWorker.register("https_test.js", {scope: "."})
|
||||
.then(function(registration) {
|
||||
if (registration.installing) {
|
||||
registration.installing.onstatechange = function(e) {
|
||||
done(registration);
|
||||
};
|
||||
} else {
|
||||
done(registration);
|
||||
}
|
||||
});
|
||||
navigator.serviceWorker.ready.then(done);
|
||||
navigator.serviceWorker.register("https_test.js", {scope: "."});
|
||||
</script>
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче