diff --git a/CLOBBER b/CLOBBER
index bca2226c6513..ab48dbb49640 100644
--- a/CLOBBER
+++ b/CLOBBER
@@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
-Bug 1128037 needed a clobber to properly build on OS X
+Bug 1155494 seems to need a clobber to pick up a change the ipdl parser.
diff --git a/browser/base/content/browser-fullScreen.js b/browser/base/content/browser-fullScreen.js
index d764655a42c8..c74943b352f4 100644
--- a/browser/base/content/browser-fullScreen.js
+++ b/browser/base/content/browser-fullScreen.js
@@ -10,6 +10,7 @@ var FullScreen = {
// called when we go into full screen, even if initiated by a web page script
window.addEventListener("fullscreen", this, true);
window.messageManager.addMessageListener("MozEnteredDomFullscreen", this);
+ window.messageManager.addMessageListener("MozExitedDomFullscreen", this);
if (window.fullScreen)
this.toggle();
@@ -17,6 +18,7 @@ var FullScreen = {
uninit: function() {
window.messageManager.removeMessageListener("MozEnteredDomFullscreen", this);
+ window.messageManager.removeMessageListener("MozExitedDomFullscreen", this);
this.cleanup();
},
@@ -70,23 +72,16 @@ var FullScreen = {
document.addEventListener("keypress", this._keyToggleCallback, false);
document.addEventListener("popupshown", this._setPopupOpen, false);
document.addEventListener("popuphidden", this._setPopupOpen, false);
+ this._shouldAnimate = true;
// We don't animate the toolbar collapse if in DOM full-screen mode,
// as the size of the content area would still be changing after the
// mozfullscreenchange event fired, which could confuse content script.
- this._shouldAnimate = !document.mozFullScreen;
- this.mouseoverToggle(false);
+ this.hideNavToolbox(document.mozFullScreen);
}
else {
- // The user may quit fullscreen during an animation
- this._cancelAnimation();
- gNavToolbox.style.marginTop = "";
- if (this._isChromeCollapsed)
- this.mouseoverToggle(true);
+ this.showNavToolbox(false);
// This is needed if they use the context menu to quit fullscreen
this._isPopupOpen = false;
-
- document.documentElement.removeAttribute("inDOMFullscreen");
-
this.cleanup();
}
},
@@ -127,6 +122,16 @@ var FullScreen = {
windowUtils.remoteFrameFullscreenChanged(browser, data.origin);
}
this.enterDomFullscreen(browser, data.origin);
+ } else if (aMessage.name == "MozExitedDomFullscreen") {
+ document.documentElement.removeAttribute("inDOMFullscreen");
+ this.cleanupDomFullscreen();
+ this.showNavToolbox();
+ // If we are still in fullscreen mode, re-hide
+ // the toolbox with animation.
+ if (window.fullScreen) {
+ this._shouldAnimate = true;
+ this.hideNavToolbox();
+ }
}
},
@@ -172,8 +177,8 @@ var FullScreen = {
// Cancel any "hide the toolbar" animation which is in progress, and make
// the toolbar hide immediately.
- this._cancelAnimation();
- this.mouseoverToggle(false);
+ this.hideNavToolbox(true);
+ this._fullScrToggler.hidden = true;
},
cleanup: function () {
@@ -183,18 +188,22 @@ var FullScreen = {
document.removeEventListener("popupshown", this._setPopupOpen, false);
document.removeEventListener("popuphidden", this._setPopupOpen, false);
- this.cancelWarning();
- gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
- gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
- gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen);
- if (!this.useLionFullScreen)
- window.removeEventListener("activate", this);
-
- window.messageManager
- .broadcastAsyncMessage("DOMFullscreen:Cleanup");
+ this.cleanupDomFullscreen();
}
},
+ cleanupDomFullscreen: function () {
+ this.cancelWarning();
+ gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
+ gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
+ gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen);
+ if (!this.useLionFullScreen)
+ window.removeEventListener("activate", this);
+
+ window.messageManager
+ .broadcastAsyncMessage("DOMFullscreen:Cleanup");
+ },
+
getMouseTargetRect: function()
{
return this._mouseTargetRect;
@@ -203,23 +212,22 @@ var FullScreen = {
// Event callbacks
_expandCallback: function()
{
- FullScreen.mouseoverToggle(true);
+ FullScreen.showNavToolbox();
},
onMouseEnter: function()
{
- FullScreen.mouseoverToggle(false);
+ FullScreen.hideNavToolbox();
},
_keyToggleCallback: function(aEvent)
{
// if we can use the keyboard (eg Ctrl+L or Ctrl+E) to open the toolbars, we
// should provide a way to collapse them too.
if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
- FullScreen._shouldAnimate = false;
- FullScreen.mouseoverToggle(false, true);
+ FullScreen.hideNavToolbox(true);
}
// F6 is another shortcut to the address bar, but its not covered in OpenLocation()
else if (aEvent.keyCode == aEvent.DOM_VK_F6)
- FullScreen.mouseoverToggle(true);
+ FullScreen.showNavToolbox();
},
// Checks whether we are allowed to collapse the chrome
@@ -273,47 +281,6 @@ var FullScreen = {
// Animate the toolbars disappearing
_shouldAnimate: true,
- _isAnimating: false,
- _animationTimeout: 0,
- _animationHandle: 0,
- _animateUp: function() {
- // check again, the user may have done something before the animation was due to start
- if (!window.fullScreen || !this._safeToCollapse(false)) {
- this._isAnimating = false;
- this._shouldAnimate = true;
- return;
- }
-
- this._animateStartTime = window.mozAnimationStartTime;
- if (!this._animationHandle)
- this._animationHandle = window.mozRequestAnimationFrame(this);
- },
-
- sample: function (timeStamp) {
- const duration = 1500;
- const timePassed = timeStamp - this._animateStartTime;
- const pos = timePassed >= duration ? 1 :
- 1 - Math.pow(1 - timePassed / duration, 4);
-
- if (pos >= 1) {
- // We've animated enough
- this._cancelAnimation();
- gNavToolbox.style.marginTop = "";
- this.mouseoverToggle(false);
- return;
- }
-
- gNavToolbox.style.marginTop = (gNavToolbox.boxObject.height * pos * -1) + "px";
- this._animationHandle = window.mozRequestAnimationFrame(this);
- },
-
- _cancelAnimation: function() {
- window.mozCancelAnimationFrame(this._animationHandle);
- this._animationHandle = 0;
- clearTimeout(this._animationTimeout);
- this._isAnimating = false;
- this._shouldAnimate = false;
- },
cancelWarning: function(event) {
if (!this.warningBox)
@@ -470,38 +437,18 @@ var FullScreen = {
3000);
},
- mouseoverToggle: function(aShow, forceHide)
- {
- // Don't do anything if:
- // a) we're already in the state we want,
- // b) we're animating and will become collapsed soon, or
- // c) we can't collapse because it would be undesirable right now
- if (aShow != this._isChromeCollapsed || (!aShow && this._isAnimating) ||
- (!aShow && !this._safeToCollapse(forceHide)))
- return;
+ showNavToolbox: function(trackMouse = true) {
+ this._fullScrToggler.hidden = true;
+ gNavToolbox.removeAttribute("fullscreenShouldAnimate");
+ gNavToolbox.style.marginTop = "";
- // browser.fullscreen.animateUp
- // 0 - never animate up
- // 1 - animate only for first collapse after entering fullscreen (default for perf's sake)
- // 2 - animate every time it collapses
- if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 0)
- this._shouldAnimate = false;
-
- if (!aShow && this._shouldAnimate) {
- this._isAnimating = true;
- this._shouldAnimate = false;
- this._animationTimeout = setTimeout(this._animateUp.bind(this), 800);
+ if (!this._isChromeCollapsed) {
return;
}
- // Hiding/collapsing the toolbox interferes with the tab bar's scrollbox,
- // so we just move it off-screen instead. See bug 430687.
- gNavToolbox.style.marginTop =
- aShow ? "" : -gNavToolbox.getBoundingClientRect().height + "px";
-
- this._fullScrToggler.hidden = aShow || document.mozFullScreen;
-
- if (aShow) {
+ // Track whether mouse is near the toolbox
+ this._isChromeCollapsed = false;
+ if (trackMouse) {
let rect = gBrowser.mPanelContainer.getBoundingClientRect();
this._mouseTargetRect = {
top: rect.top + 50,
@@ -510,13 +457,49 @@ var FullScreen = {
right: rect.right
};
MousePosTracker.addListener(this);
- } else {
- MousePosTracker.removeListener(this);
+ }
+ },
+
+ hideNavToolbox: function(forceHide = false) {
+ this._fullScrToggler.hidden = document.mozFullScreen;
+ if (this._isChromeCollapsed) {
+ if (forceHide) {
+ gNavToolbox.removeAttribute("fullscreenShouldAnimate");
+ }
+ return;
+ }
+ if (!this._safeToCollapse(forceHide)) {
+ this._fullScrToggler.hidden = true;
+ return;
}
- this._isChromeCollapsed = !aShow;
- if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 2)
+ // browser.fullscreen.animateUp
+ // 0 - never animate up
+ // 1 - animate only for first collapse after entering fullscreen (default for perf's sake)
+ // 2 - animate every time it collapses
+ let animateUp = gPrefService.getIntPref("browser.fullscreen.animateUp");
+ if (animateUp == 0) {
+ this._shouldAnimate = false;
+ } else if (animateUp == 2) {
this._shouldAnimate = true;
+ }
+ if (this._shouldAnimate && !forceHide) {
+ gNavToolbox.setAttribute("fullscreenShouldAnimate", true);
+ this._shouldAnimate = false;
+ // Hide the fullscreen toggler until the transition ends.
+ let listener = () => {
+ gNavToolbox.removeEventListener("transitionend", listener, true);
+ if (this._isChromeCollapsed)
+ this._fullScrToggler.hidden = false;
+ };
+ gNavToolbox.addEventListener("transitionend", listener, true);
+ this._fullScrToggler.hidden = true;
+ }
+
+ gNavToolbox.style.marginTop =
+ -gNavToolbox.getBoundingClientRect().height + "px";
+ this._isChromeCollapsed = true;
+ MousePosTracker.removeListener(this);
},
showXULChrome: function(aTag, aShow)
diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css
index da971482e14a..a9341fc27a17 100644
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -300,6 +300,10 @@ toolbar[customizing] > .overflow-button {
visibility: collapse;
}
+#navigator-toolbox[fullscreenShouldAnimate] {
+ transition: 1.5s margin-top ease-out;
+}
+
/* Rules to help integrate SDK widgets */
toolbaritem[sdkstylewidget="true"] > toolbarbutton,
toolbarpaletteitem > toolbaritem[sdkstylewidget="true"] > iframe,
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 7691440d1809..ac73e1a2a8cc 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1955,7 +1955,7 @@ function loadOneOrMoreURIs(aURIString)
function focusAndSelectUrlBar() {
if (gURLBar) {
if (window.fullScreen)
- FullScreen.mouseoverToggle(true);
+ FullScreen.showNavToolbox();
gURLBar.select();
if (document.activeElement == gURLBar.inputField)
@@ -3418,7 +3418,7 @@ const BrowserSearch = {
}
if (searchBar) {
if (window.fullScreen)
- FullScreen.mouseoverToggle(true);
+ FullScreen.showNavToolbox();
searchBar.select();
}
openSearchPageIfFieldIsNotActive(searchBar);
diff --git a/browser/base/content/tab-content.js b/browser/base/content/tab-content.js
index db943faca904..e8011b5e2c05 100644
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -590,6 +590,7 @@ let DOMFullscreenHandler = {
addMessageListener("DOMFullscreen:Approved", this);
addMessageListener("DOMFullscreen:CleanUp", this);
addEventListener("MozEnteredDomFullscreen", this);
+ addEventListener("MozExitedDomFullscreen", this);
},
receiveMessage: function(aMessage) {
@@ -615,6 +616,8 @@ let DOMFullscreenHandler = {
sendAsyncMessage("MozEnteredDomFullscreen", {
origin: this._fullscreenDoc.nodePrincipal.origin,
});
+ } else if (aEvent.type == "MozExitedDomFullscreen") {
+ sendAsyncMessage("MozExitedDomFullscreen");
}
}
};
diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini
index b059746c81b6..4db0d3ad1891 100644
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -477,3 +477,4 @@ support-files =
[browser_bug1124271_readerModePinnedTab.js]
support-files =
readerModeArticle.html
+[browser_domFullscreen_fullscreenMode.js]
diff --git a/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js b/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
new file mode 100644
index 000000000000..7ca92c8c3abd
--- /dev/null
+++ b/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
@@ -0,0 +1,208 @@
+"use strict";
+
+let gMessageManager;
+
+function frameScript() {
+ addMessageListener("Test:RequestFullscreen", () => {
+ content.document.body.mozRequestFullScreen();
+ });
+ addMessageListener("Test:ExitFullscreen", () => {
+ content.document.mozCancelFullScreen();
+ });
+ addMessageListener("Test:QueryFullscreenState", () => {
+ sendAsyncMessage("Test:FullscreenState", {
+ inDOMFullscreen: content.document.mozFullScreen,
+ inFullscreen: content.fullScreen
+ });
+ });
+ content.document.addEventListener("mozfullscreenchange", () => {
+ sendAsyncMessage("Test:FullscreenChanged", {
+ inDOMFullscreen: content.document.mozFullScreen,
+ inFullscreen: content.fullScreen
+ });
+ });
+ function waitUntilActive() {
+ let doc = content.document;
+ if (doc.docShell.isActive && doc.hasFocus()) {
+ sendAsyncMessage("Test:Activated");
+ } else {
+ setTimeout(waitUntilActive, 10);
+ }
+ }
+ waitUntilActive();
+}
+
+function listenOneMessage(aMsg, aListener) {
+ function listener({ data }) {
+ gMessageManager.removeMessageListener(aMsg, listener);
+ aListener(data);
+ }
+ gMessageManager.addMessageListener(aMsg, listener);
+}
+
+function listenOneEvent(aEvent, aListener) {
+ function listener(evt) {
+ removeEventListener(aEvent, listener);
+ aListener(evt);
+ }
+ addEventListener(aEvent, listener);
+}
+
+function queryFullscreenState() {
+ return new Promise(resolve => {
+ listenOneMessage("Test:FullscreenState", resolve);
+ gMessageManager.sendAsyncMessage("Test:QueryFullscreenState");
+ });
+}
+
+function captureUnexpectedFullscreenChange() {
+ ok(false, "catched an unexpected fullscreen change");
+}
+
+const FS_CHANGE_DOM = 1 << 0;
+const FS_CHANGE_SIZE = 1 << 1;
+const FS_CHANGE_BOTH = FS_CHANGE_DOM | FS_CHANGE_SIZE;
+
+function waitForFullscreenChanges(aFlags) {
+ return new Promise(resolve => {
+ let fullscreenData = null;
+ let sizemodeChanged = false;
+ function tryResolve() {
+ if ((!(aFlags & FS_CHANGE_DOM) || fullscreenData) &&
+ (!(aFlags & FS_CHANGE_SIZE) || sizemodeChanged)) {
+ if (!fullscreenData) {
+ queryFullscreenState().then(resolve);
+ } else {
+ resolve(fullscreenData);
+ }
+ }
+ }
+ if (aFlags & FS_CHANGE_SIZE) {
+ listenOneEvent("sizemodechange", () => {
+ sizemodeChanged = true;
+ tryResolve();
+ });
+ }
+ if (aFlags & FS_CHANGE_DOM) {
+ gMessageManager.removeMessageListener(
+ "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+ listenOneMessage("Test:FullscreenChanged", data => {
+ gMessageManager.addMessageListener(
+ "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+ fullscreenData = data;
+ tryResolve();
+ });
+ }
+ });
+}
+
+let gTests = [
+ {
+ desc: "document method",
+ affectsFullscreenMode: false,
+ exitFunc: () => {
+ gMessageManager.sendAsyncMessage("Test:ExitFullscreen");
+ }
+ },
+ {
+ desc: "escape key",
+ affectsFullscreenMode: false,
+ exitFunc: () => {
+ executeSoon(() => EventUtils.synthesizeKey("VK_ESCAPE", {}));
+ }
+ },
+ {
+ desc: "F11 key",
+ affectsFullscreenMode: true,
+ exitFunc: function () {
+ executeSoon(() => EventUtils.synthesizeKey("VK_F11", {}));
+ }
+ }
+];
+
+add_task(function* () {
+ let tab = gBrowser.addTab("about:robots");
+ let browser = tab.linkedBrowser;
+ gBrowser.selectedTab = tab;
+ yield waitForDocLoadComplete();
+
+ registerCleanupFunction(() => {
+ if (browser.contentWindow.fullScreen) {
+ BrowserFullScreen();
+ }
+ gBrowser.removeTab(tab);
+ });
+
+ gMessageManager = browser.messageManager;
+ gMessageManager.loadFrameScript(
+ "data:,(" + frameScript.toString() + ")();", false);
+ gMessageManager.addMessageListener(
+ "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+
+ // Wait for the document being activated, so that
+ // fullscreen request won't be denied.
+ yield new Promise(resolve => listenOneMessage("Test:Activated", resolve));
+
+ for (let test of gTests) {
+ info("Testing exit DOM fullscreen via " + test.desc);
+
+ var { inDOMFullscreen, inFullscreen } = yield queryFullscreenState();
+ ok(!inDOMFullscreen, "Shouldn't have been in DOM fullscreen");
+ ok(!inFullscreen, "Shouldn't have been in fullscreen");
+
+ /* DOM fullscreen without fullscreen mode */
+
+ // Enter DOM fullscreen
+ gMessageManager.sendAsyncMessage("Test:RequestFullscreen");
+ var { inDOMFullscreen, inFullscreen } =
+ yield waitForFullscreenChanges(FS_CHANGE_BOTH);
+ ok(inDOMFullscreen, "Should now be in DOM fullscreen");
+ ok(inFullscreen, "Should now be in fullscreen");
+
+ // Exit DOM fullscreen
+ test.exitFunc();
+ var { inDOMFullscreen, inFullscreen } =
+ yield waitForFullscreenChanges(FS_CHANGE_BOTH);
+ ok(!inDOMFullscreen, "Should no longer be in DOM fullscreen");
+ ok(!inFullscreen, "Should no longer be in fullscreen");
+
+ /* DOM fullscreen with fullscreen mode */
+
+ // Enter fullscreen mode
+ // Need to be asynchronous because sizemodechange event could be
+ // dispatched synchronously, which would cause the event listener
+ // miss that event and wait infinitely.
+ executeSoon(() => BrowserFullScreen());
+ var { inDOMFullscreen, inFullscreen } =
+ yield waitForFullscreenChanges(FS_CHANGE_SIZE);
+ ok(!inDOMFullscreen, "Shouldn't have been in DOM fullscreen");
+ ok(inFullscreen, "Should now be in fullscreen mode");
+
+ // Enter DOM fullscreen
+ gMessageManager.sendAsyncMessage("Test:RequestFullscreen");
+ var { inDOMFullscreen, inFullscreen } =
+ yield waitForFullscreenChanges(FS_CHANGE_DOM);
+ ok(inDOMFullscreen, "Should now be in DOM fullscreen");
+ ok(inFullscreen, "Should still be in fullscreen");
+
+ // Exit DOM fullscreen
+ test.exitFunc();
+ var { inDOMFullscreen, inFullscreen } =
+ yield waitForFullscreenChanges(test.affectsFullscreenMode ?
+ FS_CHANGE_BOTH : FS_CHANGE_DOM);
+ ok(!inDOMFullscreen, "Should no longer be in DOM fullscreen");
+ if (test.affectsFullscreenMode) {
+ ok(!inFullscreen, "Should no longer be in fullscreen mode");
+ } else {
+ ok(inFullscreen, "Should still be in fullscreen mode");
+ }
+
+ /* Cleanup */
+
+ // Exit fullscreen mode if we are still in
+ if (browser.contentWindow.fullScreen) {
+ executeSoon(() => BrowserFullScreen());
+ yield waitForFullscreenChanges(FS_CHANGE_SIZE);
+ }
+ }
+});
diff --git a/browser/base/content/test/general/browser_windowopen_reflows.js b/browser/base/content/test/general/browser_windowopen_reflows.js
index 8d34636f79ec..072852e44b5a 100644
--- a/browser/base/content/test/general/browser_windowopen_reflows.js
+++ b/browser/base/content/test/general/browser_windowopen_reflows.js
@@ -23,6 +23,9 @@ const EXPECTED_REFLOWS = [
// Sometimes sessionstore collects data during this test, which causes a sync reflow
// (https://bugzilla.mozilla.org/show_bug.cgi?id=892154 will fix this)
"ssi_getWindowDimension@resource:///modules/sessionstore/SessionStore.jsm",
+
+ // We may get a resize event, see bug 1149555.
+ "PreviewController.prototype.wasResizedSinceLastPreview@resource:///modules/WindowsPreviewPerTab.jsm"
];
if (Services.appinfo.OS == "WINNT" || Services.appinfo.OS == "Darwin") {
diff --git a/browser/base/content/test/social/browser_social_chatwindow_resize.js b/browser/base/content/test/social/browser_social_chatwindow_resize.js
index 6f2a2477d0ab..a779dc8d5593 100644
--- a/browser/base/content/test/social/browser_social_chatwindow_resize.js
+++ b/browser/base/content/test/social/browser_social_chatwindow_resize.js
@@ -72,8 +72,8 @@ var tests = {
[chatWidth*2+popupWidth+2, 2, "big enough to fit 2 - nub remains visible as first is still hidden"],
[chatWidth*3+popupWidth-2, 2, "one smaller than the size necessary to display all three - first still hidden"],
[chatWidth*3+popupWidth+2, 3, "big enough to fit all - all exposed (which removes the nub)"],
- [chatWidth*3+2, 3, "now the nub is hidden we can resize back down to chatWidth*3 before overflow."],
- [chatWidth*3-2, 2, "2 pixels less and the first is again collapsed (and the nub re-appears)"],
+ [chatWidth*3+4, 3, "now the nub is hidden we can resize back down to chatWidth*3 before overflow."],
+ [chatWidth*3-4, 2, "4 pixels less and the first is again collapsed (and the nub re-appears)"],
[chatWidth*2+popupWidth+2, 2, "back down to just big enough to fit 2"],
[chatWidth*2+popupWidth-2, 1, "back down to just not enough to fit 2"],
[chatWidth*3+popupWidth+2, 3, "now a large jump to make all 3 visible (ie, affects 2)"],
diff --git a/browser/components/customizableui/test/browser_885052_customize_mode_observers_disabed.js b/browser/components/customizableui/test/browser_885052_customize_mode_observers_disabed.js
index 7849eec59880..8659c60aaa47 100644
--- a/browser/components/customizableui/test/browser_885052_customize_mode_observers_disabed.js
+++ b/browser/components/customizableui/test/browser_885052_customize_mode_observers_disabed.js
@@ -4,6 +4,11 @@
"use strict";
+function isFullscreenSizeMode() {
+ let sizemode = document.documentElement.getAttribute("sizemode");
+ return sizemode == "fullscreen";
+}
+
// Observers should be disabled when in customization mode.
add_task(function() {
// Open and close the panel to make sure that the
@@ -17,9 +22,10 @@ add_task(function() {
let fullscreenButton = document.getElementById("fullscreen-button");
ok(!fullscreenButton.checked, "Fullscreen button should not be checked when not in fullscreen.")
+ ok(!isFullscreenSizeMode(), "Should not be in fullscreen sizemode before we enter fullscreen.");
BrowserFullScreen();
- yield waitForCondition(function() fullscreenButton.checked);
+ yield waitForCondition(() => isFullscreenSizeMode());
ok(fullscreenButton.checked, "Fullscreen button should be checked when in fullscreen.")
yield startCustomizing();
@@ -34,6 +40,6 @@ add_task(function() {
BrowserFullScreen();
fullscreenButton = document.getElementById("fullscreen-button");
- yield waitForCondition(function() !fullscreenButton.checked);
+ yield waitForCondition(() => !isFullscreenSizeMode());
ok(!fullscreenButton.checked, "Fullscreen button should not be checked when not in fullscreen.")
});
diff --git a/browser/components/pocket/panels/js/saved.js b/browser/components/pocket/panels/js/saved.js
index ec278be156f9..4baef0e5abe5 100644
--- a/browser/components/pocket/panels/js/saved.js
+++ b/browser/components/pocket/panels/js/saved.js
@@ -105,7 +105,7 @@ var PKT_SAVED_OVERLAY = function (options)
};
this.startCloseTimer = function(manualtime)
{
- /*var settime = manualtime ? manualtime : myself.autocloseTiming;
+ var settime = manualtime ? manualtime : myself.autocloseTiming;
if (typeof myself.autocloseTimer == 'number')
{
clearTimeout(myself.autocloseTimer);
@@ -117,7 +117,7 @@ var PKT_SAVED_OVERLAY = function (options)
myself.preventCloseTimerCancel = false;
myself.closePopup();
}
- }, settime);*/
+ }, settime);
};
this.stopCloseTimer = function()
{
diff --git a/browser/components/preferences/in-content/sync.js b/browser/components/preferences/in-content/sync.js
index 6ff4e8cb623d..230aa9a73463 100644
--- a/browser/components/preferences/in-content/sync.js
+++ b/browser/components/preferences/in-content/sync.js
@@ -301,9 +301,15 @@ let gSyncPane = {
// If the account is verified the next promise in the chain will
// fetch profile data.
return data.verified;
- }).then(shouldGetProfile => {
- if (shouldGetProfile) {
- return fxAccounts.getSignedInUserProfile();
+ }).then(isVerified => {
+ if (isVerified) {
+ let enabled;
+ try {
+ enabled = Services.prefs.getBoolPref("identity.fxaccounts.profile_image.enabled");
+ } catch (ex) {}
+ if (enabled) {
+ return fxAccounts.getSignedInUserProfile();
+ }
}
}).then(data => {
if (data && data.avatar) {
diff --git a/browser/components/selfsupport/SelfSupportService.js b/browser/components/selfsupport/SelfSupportService.js
index d7e7f8c38c82..9a44377d4f5b 100644
--- a/browser/components/selfsupport/SelfSupportService.js
+++ b/browser/components/selfsupport/SelfSupportService.js
@@ -68,6 +68,11 @@ MozSelfSupportInterface.prototype = {
resetPref: function(name) {
Services.prefs.clearUserPref(name);
},
+
+ resetSearchEngines: function() {
+ Services.search.restoreDefaultEngines();
+ Services.search.resetToOriginalDefaultEngine();
+ },
}
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MozSelfSupportInterface]);
diff --git a/browser/components/selfsupport/test/browser_selfsupportAPI.js b/browser/components/selfsupport/test/browser_selfsupportAPI.js
index 93ca34a78740..2a54d4ae651c 100644
--- a/browser/components/selfsupport/test/browser_selfsupportAPI.js
+++ b/browser/components/selfsupport/test/browser_selfsupportAPI.js
@@ -1,6 +1,6 @@
Cu.import("resource://gre/modules/Preferences.jsm");
-function test() {
+function test_resetPref() {
const prefNewName = "browser.newpref.fake";
Assert.ok(!Preferences.has(prefNewName), "pref should not exist");
@@ -45,3 +45,44 @@ function test() {
// clearUserPref can't undo its action
// see discussion in bug 1075160
}
+
+function test_resetSearchEngines()
+{
+ const defaultEngineOriginal = Services.search.defaultEngine;
+ const visibleEnginesOriginal = Services.search.getVisibleEngines();
+
+ // 1. do nothing on unchanged search configuration
+ MozSelfSupport.resetSearchEngines();
+ Assert.equal(Services.search.defaultEngine, defaultEngineOriginal, "default engine should be reset");
+ Assert.deepEqual(Services.search.getVisibleEngines(), visibleEnginesOriginal,
+ "default visible engines set should be reset");
+
+ // 2. change the default search engine
+ const defaultEngineNew = visibleEnginesOriginal[3];
+ Assert.notEqual(defaultEngineOriginal, defaultEngineNew, "new default engine should be different from original");
+ Services.search.defaultEngine = defaultEngineNew;
+ Assert.equal(Services.search.defaultEngine, defaultEngineNew, "default engine should be set to new");
+ MozSelfSupport.resetSearchEngines();
+ Assert.equal(Services.search.defaultEngine, defaultEngineOriginal, "default engine should be reset");
+ Assert.deepEqual(Services.search.getVisibleEngines(), visibleEnginesOriginal,
+ "default visible engines set should be reset");
+
+ // 3. remove an engine
+ const engineRemoved = visibleEnginesOriginal[2];
+ Services.search.removeEngine(engineRemoved);
+ Assert.ok(Services.search.getVisibleEngines().indexOf(engineRemoved) == -1,
+ "removed engine should not be visible any more");
+ MozSelfSupport.resetSearchEngines();
+ Assert.equal(Services.search.defaultEngine, defaultEngineOriginal, "default engine should be reset");
+ Assert.deepEqual(Services.search.getVisibleEngines(), visibleEnginesOriginal,
+ "default visible engines set should be reset");
+
+ // 4. add an angine
+ // we don't remove user-added engines as they are only used if selected
+}
+
+function test()
+{
+ test_resetPref();
+ test_resetSearchEngines();
+}
diff --git a/caps/nsPrincipal.cpp b/caps/nsPrincipal.cpp
index 8c39a0dc5784..7f3159eabff6 100644
--- a/caps/nsPrincipal.cpp
+++ b/caps/nsPrincipal.cpp
@@ -638,7 +638,6 @@ IsOnFullDomainWhitelist(nsIURI* aURI)
// 0th entry only active when testing:
NS_LITERAL_CSTRING("test1.example.org"),
NS_LITERAL_CSTRING("map.baidu.com"),
- NS_LITERAL_CSTRING("music.baidu.com"),
NS_LITERAL_CSTRING("3g.163.com"),
NS_LITERAL_CSTRING("3glogo.gtimg.com"), // for 3g.163.com
NS_LITERAL_CSTRING("info.3g.qq.com"), // for 3g.qq.com
@@ -646,6 +645,16 @@ IsOnFullDomainWhitelist(nsIURI* aURI)
NS_LITERAL_CSTRING("img.m.baidu.com"), // for [shucheng|ks].baidu.com
NS_LITERAL_CSTRING("m.mogujie.com"),
NS_LITERAL_CSTRING("touch.qunar.com"),
+ NS_LITERAL_CSTRING("mjs.sinaimg.cn"), // for sina.cn
+ NS_LITERAL_CSTRING("static.qiyi.com"), // for m.iqiyi.com
+ NS_LITERAL_CSTRING("www.kuaidi100.com"), // for m.kuaidi100.com
+ NS_LITERAL_CSTRING("m.pc6.com"),
+ NS_LITERAL_CSTRING("m.haosou.com"),
+ NS_LITERAL_CSTRING("m.mi.com"),
+ NS_LITERAL_CSTRING("wappass.baidu.com"),
+ NS_LITERAL_CSTRING("m.video.baidu.com"),
+ NS_LITERAL_CSTRING("m.video.baidu.com"),
+ NS_LITERAL_CSTRING("imgcache.gtimg.cn"), // for m.v.qq.com
};
static const size_t sNumFullDomainsOnWhitelist =
MOZ_ARRAY_LENGTH(sFullDomainsOnWhitelist);
diff --git a/dom/base/URL.cpp b/dom/base/URL.cpp
index f82404feb8dc..9c927ae20d73 100644
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -18,6 +18,7 @@
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsIURL.h"
+#include "nsContentUtils.h"
namespace mozilla {
namespace dom {
@@ -42,7 +43,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URL)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
-URL::URL(nsIURI* aURI)
+URL::URL(already_AddRefed aURI)
: mURI(aURI)
{
}
@@ -57,56 +58,55 @@ URL::WrapObject(JSContext* aCx, JS::Handle aGivenProto, JS::MutableHa
URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
URL& aBase, ErrorResult& aRv)
{
- nsresult rv;
- nsCOMPtr ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
- if (NS_FAILED(rv)) {
- aRv.Throw(rv);
- return nullptr;
- }
-
- nsCOMPtr uri;
- rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aUrl), nullptr, aBase.GetURI(),
- getter_AddRefs(uri));
- if (NS_FAILED(rv)) {
- nsAutoString label(aUrl);
- aRv.ThrowTypeError(MSG_INVALID_URL, &label);
- return nullptr;
- }
-
- nsRefPtr url = new URL(uri);
- return url.forget();
+ return Constructor(aUrl, aBase.GetURI(), aRv);
}
/* static */ already_AddRefed
URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
- const nsAString& aBase, ErrorResult& aRv)
+ const Optional& aBase, ErrorResult& aRv)
{
- nsresult rv;
- nsCOMPtr ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
- if (NS_FAILED(rv)) {
- aRv.Throw(rv);
- return nullptr;
+ if (aBase.WasPassed()) {
+ return Constructor(aUrl, aBase.Value(), aRv);
}
+ return Constructor(aUrl, nullptr, aRv);
+}
+
+/* static */ already_AddRefed
+URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
+ const nsAString& aBase, ErrorResult& aRv)
+{
+ return Constructor(aUrl, aBase, aRv);
+}
+
+/* static */ already_AddRefed
+URL::Constructor(const nsAString& aUrl, const nsAString& aBase,
+ ErrorResult& aRv)
+{
nsCOMPtr baseUri;
- rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aBase), nullptr, nullptr,
- getter_AddRefs(baseUri));
- if (NS_FAILED(rv)) {
- nsAutoString label(aBase);
- aRv.ThrowTypeError(MSG_INVALID_URL, &label);
+ nsresult rv = NS_NewURI(getter_AddRefs(baseUri), aBase, nullptr, nullptr,
+ nsContentUtils::GetIOService());
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ aRv.ThrowTypeError(MSG_INVALID_URL, &aBase);
return nullptr;
}
+ return Constructor(aUrl, baseUri, aRv);
+}
+
+/* static */
+already_AddRefed
+URL::Constructor(const nsAString& aUrl, nsIURI* aBase, ErrorResult& aRv)
+{
nsCOMPtr uri;
- rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aUrl), nullptr, baseUri,
- getter_AddRefs(uri));
- if (NS_FAILED(rv)) {
- nsAutoString label(aUrl);
- aRv.ThrowTypeError(MSG_INVALID_URL, &label);
+ nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, nullptr, aBase,
+ nsContentUtils::GetIOService());
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ aRv.ThrowTypeError(MSG_INVALID_URL, &aUrl);
return nullptr;
}
- nsRefPtr url = new URL(uri);
+ nsRefPtr url = new URL(uri.forget());
return url.forget();
}
diff --git a/dom/base/URL.h b/dom/base/URL.h
index 81d315d78daa..f1ef8be9abb1 100644
--- a/dom/base/URL.h
+++ b/dom/base/URL.h
@@ -39,7 +39,7 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(URL)
- explicit URL(nsIURI* aURI);
+ explicit URL(already_AddRefed aURI);
// WebIDL methods
bool
@@ -49,8 +49,16 @@ public:
Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
URL& aBase, ErrorResult& aRv);
static already_AddRefed
+ Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
+ const Optional& aBase, ErrorResult& aRv);
+ // Versions of Constructor that we can share with workers and other code.
+ static already_AddRefed
Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
const nsAString& aBase, ErrorResult& aRv);
+ static already_AddRefed
+ Constructor(const nsAString& aUrl, const nsAString& aBase, ErrorResult& aRv);
+ static already_AddRefed
+ Constructor(const nsAString& aUrl, nsIURI* aBase, ErrorResult& aRv);
static void CreateObjectURL(const GlobalObject& aGlobal,
File& aBlob,
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index ba762e8106ee..44e39e0b60ab 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -11266,6 +11266,12 @@ ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
NS_ASSERTION(!root->IsFullScreenDoc(),
"Fullscreen root should no longer be a fullscreen doc...");
+ // Dispatch MozExitedDomFullscreen to the last document in
+ // the list since we want this event to follow the same path
+ // MozEnteredDomFullscreen dispatched.
+ nsRefPtr asyncDispatcher = new AsyncEventDispatcher(
+ changed.LastElement(), NS_LITERAL_STRING("MozExitedDomFullscreen"), true, true);
+ asyncDispatcher->PostDOMEvent();
// Move the top-level window out of fullscreen mode.
SetWindowFullScreen(root, false);
}
@@ -11422,6 +11428,9 @@ nsDocument::RestorePreviousFullScreenState()
// move the top-level window out of fullscreen mode.
NS_ASSERTION(!GetFullscreenRootDocument(this)->IsFullScreenDoc(),
"Should have cleared all docs' stacks");
+ nsRefPtr asyncDispatcher = new AsyncEventDispatcher(
+ this, NS_LITERAL_STRING("MozExitedDomFullscreen"), true, true);
+ asyncDispatcher->PostDOMEvent();
SetWindowFullScreen(this, false);
}
}
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index cf773990ad83..5020665fc9f6 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1084,6 +1084,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mAddActiveEventFuzzTime(true),
mIsFrozen(false),
mFullScreen(false),
+ mFullscreenMode(false),
mIsClosed(false),
mInClose(false),
mHavePendingClose(false),
@@ -6082,6 +6083,22 @@ nsGlobalWindow::SetFullScreenInternal(bool aFullScreen, bool aRequireTrust, gfx:
if (mFullScreen == aFullScreen)
return NS_OK;
+ // If a fullscreen is originated from chrome, we are switching to
+ // the fullscreen mode, otherwise, we are entering DOM fullscreen.
+ // Note that although entering DOM fullscreen could also cause
+ // consequential calls to this method, those calls will be skipped
+ // at the condition above.
+ if (aRequireTrust) {
+ mFullscreenMode = aFullScreen;
+ } else {
+ // If we are exiting from DOM fullscreen while we
+ // initially make the window fullscreen because of
+ // fullscreen mode, don't restore the window.
+ if (!aFullScreen && mFullscreenMode) {
+ return NS_OK;
+ }
+ }
+
// dispatch a "fullscreen" DOM event so that XUL apps can
// respond visually if we are kicked into full screen mode
if (!DispatchCustomEvent(NS_LITERAL_STRING("fullscreen"))) {
diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h
index 8d41e3668011..5ef8a39d4152 100644
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -1538,6 +1538,7 @@ protected:
// These members are only used on outer window objects. Make sure
// you never set any of these on an inner object!
bool mFullScreen : 1;
+ bool mFullscreenMode : 1;
bool mIsClosed : 1;
bool mInClose : 1;
// mHavePendingClose means we've got a termination function set to
diff --git a/dom/base/test/test_reentrant_flush.html b/dom/base/test/test_reentrant_flush.html
index fe1088526efd..74ecbf23ac2d 100644
--- a/dom/base/test/test_reentrant_flush.html
+++ b/dom/base/test/test_reentrant_flush.html
@@ -48,12 +48,11 @@ addLoadEvent(function() {
// Now flush out layout on the subdocument, to trigger the resize handler
is(bod.getBoundingClientRect().width, 50, "Width of body should still be 50px");
-
- is(resizeHandlerRan, true, "Resize handler should have run");
-
- win.removeEventListener("resize", handleResize, false);
-
- SimpleTest.finish();
+ window.requestAnimationFrame(function() {
+ is(resizeHandlerRan, true, "Resize handler should have run");
+ win.removeEventListener("resize", handleResize, false);
+ SimpleTest.finish();
+ });
});
diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp
index 160aa57a1a28..eee66a176253 100644
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -146,7 +146,7 @@ ErrorResult::ThrowErrorWithMessage(va_list ap, const dom::ErrNum errorNumber,
MOZ_ASSERT(argCount <= 10);
argCount = std::min(argCount, 10);
while (argCount--) {
- message->mArgs.AppendElement(*va_arg(ap, nsString*));
+ message->mArgs.AppendElement(*va_arg(ap, const nsAString*));
}
mMessage = message;
#ifdef DEBUG
diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h
index 0aff220953a3..6fc2edf2801d 100644
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1049,7 +1049,7 @@ WrapNewBindingNonWrapperCachedObject(JSContext* cx,
// We can end up here in all sorts of compartments, per above. Make
// sure to JS_WrapValue!
rval.set(JS::ObjectValue(*obj));
- return JS_WrapValue(cx, rval);
+ return MaybeWrapObjectValue(cx, rval);
}
// Create a JSObject wrapping "value", for cases when "value" is a
@@ -1097,7 +1097,7 @@ WrapNewBindingNonWrapperCachedObject(JSContext* cx,
// We can end up here in all sorts of compartments, per above. Make
// sure to JS_WrapValue!
rval.set(JS::ObjectValue(*obj));
- return JS_WrapValue(cx, rval);
+ return MaybeWrapObjectValue(cx, rval);
}
// Helper for smart pointers (nsRefPtr/nsCOMPtr).
diff --git a/dom/cache/CacheStorage.cpp b/dom/cache/CacheStorage.cpp
index a999e8e9a3f9..54563616203c 100644
--- a/dom/cache/CacheStorage.cpp
+++ b/dom/cache/CacheStorage.cpp
@@ -314,6 +314,30 @@ CacheStorage::PrefEnabled(JSContext* aCx, JSObject* aObj)
return Cache::PrefEnabled(aCx, aObj);
}
+// static
+already_AddRefed
+CacheStorage::Constructor(const GlobalObject& aGlobal,
+ CacheStorageNamespace aNamespace,
+ nsIPrincipal* aPrincipal, ErrorResult& aRv)
+{
+ if (NS_WARN_IF(!NS_IsMainThread())) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+
+ // TODO: remove Namespace in favor of CacheStorageNamespace
+ static_assert(DEFAULT_NAMESPACE == (uint32_t)CacheStorageNamespace::Content,
+ "Default namespace should match webidl Content enum");
+ static_assert(CHROME_ONLY_NAMESPACE == (uint32_t)CacheStorageNamespace::Chrome,
+ "Chrome namespace should match webidl Chrome enum");
+ static_assert(NUMBER_OF_NAMESPACES == (uint32_t)CacheStorageNamespace::EndGuard_,
+ "Number of namespace should match webidl endguard enum");
+
+ Namespace ns = static_cast(aNamespace);
+ nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports());
+ return CreateOnMainThread(ns, global, aPrincipal, aRv);
+}
+
nsISupports*
CacheStorage::GetParentObject() const
{
diff --git a/dom/cache/CacheStorage.h b/dom/cache/CacheStorage.h
index ff227e61e127..f646fcd72786 100644
--- a/dom/cache/CacheStorage.h
+++ b/dom/cache/CacheStorage.h
@@ -7,7 +7,6 @@
#ifndef mozilla_dom_cache_CacheStorage_h
#define mozilla_dom_cache_CacheStorage_h
-#include "mozilla/dom/CacheBinding.h"
#include "mozilla/dom/cache/Types.h"
#include "mozilla/dom/cache/TypeUtils.h"
#include "nsAutoPtr.h"
@@ -29,6 +28,7 @@ namespace ipc {
namespace dom {
+enum class CacheStorageNamespace : uint32_t;
class Promise;
namespace workers {
@@ -64,6 +64,11 @@ public:
already_AddRefed Delete(const nsAString& aKey, ErrorResult& aRv);
already_AddRefed Keys(ErrorResult& aRv);
+ // chrome-only webidl interface methods
+ static already_AddRefed
+ Constructor(const GlobalObject& aGlobal, CacheStorageNamespace aNamespace,
+ nsIPrincipal* aPrincipal, ErrorResult& aRv);
+
// binding methods
static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
diff --git a/dom/cache/moz.build b/dom/cache/moz.build
index 5862c86d3986..3f672aafff39 100644
--- a/dom/cache/moz.build
+++ b/dom/cache/moz.build
@@ -94,3 +94,7 @@ FINAL_LIBRARY = 'xul'
MOCHITEST_MANIFESTS += [
'test/mochitest/mochitest.ini',
]
+
+MOCHITEST_CHROME_MANIFESTS += [
+ 'test/mochitest/chrome.ini',
+]
diff --git a/dom/cache/test/mochitest/chrome.ini b/dom/cache/test/mochitest/chrome.ini
new file mode 100644
index 000000000000..d607bf2d8173
--- /dev/null
+++ b/dom/cache/test/mochitest/chrome.ini
@@ -0,0 +1 @@
+[test_chrome_constructor.html]
diff --git a/dom/cache/test/mochitest/test_chrome_constructor.html b/dom/cache/test/mochitest/test_chrome_constructor.html
new file mode 100644
index 000000000000..f888d0614cfb
--- /dev/null
+++ b/dom/cache/test/mochitest/test_chrome_constructor.html
@@ -0,0 +1,43 @@
+
+
+
+
+ Validate Interfaces Exposed to Workers
+
+
+
+
+
+
+
diff --git a/dom/canvas/test/webgl-mochitest.ini b/dom/canvas/test/webgl-mochitest.ini
index c9e8c2b33d50..78339ed07574 100644
--- a/dom/canvas/test/webgl-mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest.ini
@@ -21,6 +21,7 @@ skip-if = android_version == '10' || android_version == '18' #Android 2.3 and 4.
[webgl-mochitest/test_noprog_draw.html]
[webgl-mochitest/test_privileged_exts.html]
[webgl-mochitest/test_texsubimage_float.html]
+[webgl-mochitest/test_uninit_data.html]
[webgl-mochitest/test_webgl_available.html]
skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
#[webgl-mochitest/test_webgl_color_buffer_float.html]
diff --git a/dom/canvas/test/webgl-mochitest/test_uninit_data.html b/dom/canvas/test/webgl-mochitest/test_uninit_data.html
new file mode 100644
index 000000000000..541cfdbe51db
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/test_uninit_data.html
@@ -0,0 +1,84 @@
+
+
+
+
+
+ Test contents of uninitialized buffers
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp
index 869c45eeaaac..cb054eec40e4 100644
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -1528,6 +1528,9 @@ EventStateManager::BeginTrackingDragGesture(nsPresContext* aPresContext,
getter_AddRefs(mGestureDownContent));
mGestureDownFrameOwner = inDownFrame->GetContent();
+ if (!mGestureDownFrameOwner) {
+ mGestureDownFrameOwner = mGestureDownContent;
+ }
}
mGestureModifiers = inDownEvent->modifiers;
mGestureDownButtons = inDownEvent->buttons;
diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp
index efd4aa40907e..9116dfad082e 100644
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1566,13 +1566,6 @@ nsHTMLDocument::Open(JSContext* cx,
return nullptr;
}
- // We can't depend on channels implementing property bags, so do our
- // base URI manually after reset.
-
- if (rv.Failed()) {
- return nullptr;
- }
-
if (callerChannel) {
nsLoadFlags callerLoadFlags;
rv = callerChannel->GetLoadFlags(&callerLoadFlags);
diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl
index 3cc711e5c0d3..22e545baec7d 100644
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -51,7 +51,7 @@ interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
interface nsIObserver;
-[scriptable, uuid(9bb4a34f-de8f-43d3-a58c-10757cac95a0)]
+[scriptable, uuid(1a75c351-d115-4d51-94df-731dd1723a1f)]
interface nsIDOMWindowUtils : nsISupports {
/**
@@ -613,6 +613,11 @@ interface nsIDOMWindowUtils : nsISupports {
*/
const unsigned long MOUSESCROLL_PREFER_WIDGET_AT_POINT = 0x00000001;
+ /**
+ * Interpret the scroll delta values as lines rather than pixels.
+ */
+ const unsigned long MOUSESCROLL_SCROLL_LINES = 0x00000002;
+
/**
* The platform specific values of aAdditionalFlags. Must be over 0x00010000.
*/
diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl
index c836a937a8bc..8e12205b2c3d 100644
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -545,7 +545,7 @@ child:
CacheFileDescriptor(nsString path, FileDescriptor fd);
UpdateDimensions(IntRect rect, ScreenIntSize size, ScreenOrientation orientation,
- LayoutDeviceIntPoint chromeDisp) compress;
+ LayoutDeviceIntPoint chromeDisp) compressall;
UpdateFrame(FrameMetrics frame);
diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp
index a5a8e3dfda42..39bab3e59cbf 100644
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -934,11 +934,20 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
MOZ_ASSERT(mReader->IsWaitForDataSupported(),
"Readers that send WAITING_FOR_DATA need to implement WaitForData");
+ nsRefPtr self = this;
WaitRequestRef(aType).Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::WaitForData, aType)
- ->RefableThen(TaskQueue(), __func__, this,
- &MediaDecoderStateMachine::OnWaitForDataResolved,
- &MediaDecoderStateMachine::OnWaitForDataRejected));
+ ->RefableThen(TaskQueue(), __func__,
+ [self] (MediaData::Type aType) -> void {
+ ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
+ self->WaitRequestRef(aType).Complete();
+ self->DispatchDecodeTasksIfNeeded();
+ },
+ [self] (WaitForDataRejectValue aRejection) -> void {
+ ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
+ self->WaitRequestRef(aRejection.mType).Complete();
+ }));
+
return;
}
@@ -1901,12 +1910,24 @@ MediaDecoderStateMachine::InitiateSeek()
Reset();
// Do the seek.
+ nsRefPtr self = this;
mSeekRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::Seek, mCurrentSeek.mTarget.mTime,
GetEndTime())
- ->RefableThen(TaskQueue(), __func__, this,
- &MediaDecoderStateMachine::OnSeekCompleted,
- &MediaDecoderStateMachine::OnSeekFailed));
+ ->RefableThen(TaskQueue(), __func__,
+ [self] (int64_t) -> void {
+ ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
+ self->mSeekRequest.Complete();
+ // We must decode the first samples of active streams, so we can determine
+ // the new stream time. So dispatch tasks to do that.
+ self->mDecodeToSeekTarget = true;
+ self->DispatchDecodeTasksIfNeeded();
+ }, [self] (nsresult aResult) -> void {
+ ReentrantMonitorAutoEnter mon(self->mDecoder->GetReentrantMonitor());
+ self->mSeekRequest.Complete();
+ MOZ_ASSERT(NS_FAILED(aResult), "Cancels should also disconnect mSeekRequest");
+ self->DecodeError();
+ }));
}
nsresult
@@ -2386,30 +2407,6 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
return NS_OK;
}
-void
-MediaDecoderStateMachine::OnSeekCompleted(int64_t aTime)
-{
- MOZ_ASSERT(OnTaskQueue());
- ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
- mSeekRequest.Complete();
-
- // We must decode the first samples of active streams, so we can determine
- // the new stream time. So dispatch tasks to do that.
- mDecodeToSeekTarget = true;
-
- DispatchDecodeTasksIfNeeded();
-}
-
-void
-MediaDecoderStateMachine::OnSeekFailed(nsresult aResult)
-{
- MOZ_ASSERT(OnTaskQueue());
- ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
- mSeekRequest.Complete();
- MOZ_ASSERT(NS_FAILED(aResult), "Cancels should also disconnect mSeekRequest");
- DecodeError();
-}
-
void
MediaDecoderStateMachine::SeekCompleted()
{
diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h
index 2fbbc24cfcd8..c382490d06f2 100644
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -427,22 +427,6 @@ public:
OnNotDecoded(MediaData::VIDEO_DATA, aReason);
}
- void OnSeekCompleted(int64_t aTime);
- void OnSeekFailed(nsresult aResult);
-
- void OnWaitForDataResolved(MediaData::Type aType)
- {
- ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
- WaitRequestRef(aType).Complete();
- DispatchDecodeTasksIfNeeded();
- }
-
- void OnWaitForDataRejected(WaitForDataRejectValue aRejection)
- {
- ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
- WaitRequestRef(aRejection.mType).Complete();
- }
-
// Resets all state related to decoding and playback, emptying all buffers
// and aborting all pending operations on the decode task queue.
void Reset();
diff --git a/dom/media/MediaPromise.h b/dom/media/MediaPromise.h
index 61c914f5e35f..efd17839e735 100644
--- a/dom/media/MediaPromise.h
+++ b/dom/media/MediaPromise.h
@@ -49,6 +49,31 @@ class MediaPromise
public:
typedef ResolveValueT ResolveValueType;
typedef RejectValueT RejectValueType;
+ class ResolveOrRejectValue
+ {
+ public:
+ void SetResolve(ResolveValueType& aResolveValue)
+ {
+ MOZ_ASSERT(IsNothing());
+ mResolveValue.emplace(aResolveValue);
+ }
+
+ void SetReject(RejectValueType& aRejectValue)
+ {
+ MOZ_ASSERT(IsNothing());
+ mRejectValue.emplace(aRejectValue);
+ }
+
+ bool IsResolve() const { return mResolveValue.isSome(); }
+ bool IsReject() const { return mRejectValue.isSome(); }
+ bool IsNothing() const { return mResolveValue.isNothing() && mRejectValue.isNothing(); }
+ ResolveValueType& ResolveValue() { return mResolveValue.ref(); }
+ RejectValueType& RejectValue() { return mRejectValue.ref(); }
+
+ private:
+ Maybe mResolveValue;
+ Maybe mRejectValue;
+ };
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaPromise)
@@ -119,64 +144,74 @@ protected:
class ThenValueBase : public Consumer
{
public:
- class ResolveRunnable : public nsRunnable
+ class ResolveOrRejectRunnable : public nsRunnable
{
public:
- ResolveRunnable(ThenValueBase* aThenValue, ResolveValueType aResolveValue)
+ ResolveOrRejectRunnable(ThenValueBase* aThenValue, ResolveOrRejectValue& aValue)
: mThenValue(aThenValue)
- , mResolveValue(aResolveValue) {}
+ , mValue(aValue) {}
- ~ResolveRunnable()
+ ~ResolveOrRejectRunnable()
{
MOZ_DIAGNOSTIC_ASSERT(!mThenValue || mThenValue->IsDisconnected());
}
NS_IMETHODIMP Run()
{
- PROMISE_LOG("ResolveRunnable::Run() [this=%p]", this);
- mThenValue->DoResolve(mResolveValue);
+ PROMISE_LOG("ResolveOrRejectRunnable::Run() [this=%p]", this);
+ mThenValue->DoResolveOrReject(mValue);
mThenValue = nullptr;
return NS_OK;
}
private:
nsRefPtr mThenValue;
- ResolveValueType mResolveValue;
+ ResolveOrRejectValue mValue;
};
- class RejectRunnable : public nsRunnable
+ explicit ThenValueBase(AbstractThread* aResponseTarget, const char* aCallSite)
+ : mResponseTarget(aResponseTarget), mCallSite(aCallSite) {}
+
+ void Dispatch(MediaPromise *aPromise)
{
- public:
- RejectRunnable(ThenValueBase* aThenValue, RejectValueType aRejectValue)
- : mThenValue(aThenValue)
- , mRejectValue(aRejectValue) {}
+ aPromise->mMutex.AssertCurrentThreadOwns();
+ MOZ_ASSERT(!aPromise->IsPending());
- ~RejectRunnable()
- {
- MOZ_DIAGNOSTIC_ASSERT(!mThenValue || mThenValue->IsDisconnected());
- }
+ nsRefPtr runnable =
+ static_cast(new (typename ThenValueBase::ResolveOrRejectRunnable)(this, aPromise->mValue));
+ PROMISE_LOG("%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p]",
+ aPromise->mValue.IsResolve() ? "Resolving" : "Rejecting", ThenValueBase::mCallSite,
+ runnable.get(), aPromise, this);
- NS_IMETHODIMP Run()
- {
- PROMISE_LOG("RejectRunnable::Run() [this=%p]", this);
- mThenValue->DoReject(mRejectValue);
- mThenValue = nullptr;
- return NS_OK;
- }
+ // Promise consumers are allowed to disconnect the Consumer object and
+ // then shut down the thread or task queue that the promise result would
+ // be dispatched on. So we unfortunately can't assert that promise
+ // dispatch succeeds. :-(
+ mResponseTarget->Dispatch(runnable.forget(), AbstractThread::DontAssertDispatchSuccess);
+ }
- private:
- nsRefPtr mThenValue;
- RejectValueType mRejectValue;
- };
-
- explicit ThenValueBase(const char* aCallSite) : mCallSite(aCallSite) {}
-
- virtual void Dispatch(MediaPromise *aPromise) = 0;
+ virtual void Disconnect() override
+ {
+ MOZ_ASSERT(ThenValueBase::mResponseTarget->IsCurrentThreadIn());
+ MOZ_DIAGNOSTIC_ASSERT(!Consumer::mComplete);
+ Consumer::mDisconnected = true;
+ }
protected:
- virtual void DoResolve(ResolveValueType aResolveValue) = 0;
- virtual void DoReject(RejectValueType aRejectValue) = 0;
+ virtual void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) = 0;
+ void DoResolveOrReject(ResolveOrRejectValue& aValue)
+ {
+ Consumer::mComplete = true;
+ if (Consumer::mDisconnected) {
+ PROMISE_LOG("ThenValue::DoResolveOrReject disconnected - bailing out [this=%p]", this);
+ return;
+ }
+
+ DoResolveOrRejectInternal(aValue);
+ }
+
+ nsRefPtr mResponseTarget; // May be released on any thread.
const char* mCallSite;
};
@@ -207,51 +242,20 @@ protected:
}
template
- class ThenValue : public ThenValueBase
+ class MethodThenValue : public ThenValueBase
{
public:
- ThenValue(AbstractThread* aResponseTarget, ThisType* aThisVal,
- ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod,
- const char* aCallSite)
- : ThenValueBase(aCallSite)
- , mResponseTarget(aResponseTarget)
+ MethodThenValue(AbstractThread* aResponseTarget, ThisType* aThisVal,
+ ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod,
+ const char* aCallSite)
+ : ThenValueBase(aResponseTarget, aCallSite)
, mThisVal(aThisVal)
, mResolveMethod(aResolveMethod)
, mRejectMethod(aRejectMethod) {}
- void Dispatch(MediaPromise *aPromise) override
- {
- aPromise->mMutex.AssertCurrentThreadOwns();
- MOZ_ASSERT(!aPromise->IsPending());
- bool resolved = aPromise->mResolveValue.isSome();
- nsRefPtr runnable =
- resolved ? static_cast(new (typename ThenValueBase::ResolveRunnable)(this, aPromise->mResolveValue.ref()))
- : static_cast(new (typename ThenValueBase::RejectRunnable)(this, aPromise->mRejectValue.ref()));
- PROMISE_LOG("%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p]",
- resolved ? "Resolving" : "Rejecting", ThenValueBase::mCallSite,
- runnable.get(), aPromise, this);
-
- // Promise consumers are allowed to disconnect the Consumer object and
- // then shut down the thread or task queue that the promise result would
- // be dispatched on. So we unfortunately can't assert that promise
- // dispatch succeeds. :-(
- mResponseTarget->Dispatch(runnable.forget(), AbstractThread::DontAssertDispatchSuccess);
- }
-
-#ifdef DEBUG
- void AssertOnDispatchThread()
- {
- MOZ_ASSERT(mResponseTarget->IsCurrentThreadIn());
- }
-#else
- void AssertOnDispatchThread() {}
-#endif
-
virtual void Disconnect() override
{
- AssertOnDispatchThread();
- MOZ_DIAGNOSTIC_ASSERT(!Consumer::mComplete);
- Consumer::mDisconnected = true;
+ ThenValueBase::Disconnect();
// If a Consumer has been disconnected, we don't guarantee that the
// resolve/reject runnable will be dispatched. Null out our refcounted
@@ -260,32 +264,13 @@ protected:
}
protected:
- virtual void DoResolve(ResolveValueType aResolveValue) override
+ virtual void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override
{
- Consumer::mComplete = true;
- if (Consumer::mDisconnected) {
- MOZ_ASSERT(!mThisVal);
- PROMISE_LOG("ThenValue::DoResolve disconnected - bailing out [this=%p]", this);
- return;
+ if (aValue.IsResolve()) {
+ InvokeCallbackMethod(mThisVal.get(), mResolveMethod, aValue.ResolveValue());
+ } else {
+ InvokeCallbackMethod(mThisVal.get(), mRejectMethod, aValue.RejectValue());
}
- InvokeCallbackMethod(mThisVal.get(), mResolveMethod, aResolveValue);
-
- // Null out mThisVal after invoking the callback so that any references are
- // released predictably on the dispatch thread. Otherwise, it would be
- // released on whatever thread last drops its reference to the ThenValue,
- // which may or may not be ok.
- mThisVal = nullptr;
- }
-
- virtual void DoReject(RejectValueType aRejectValue) override
- {
- Consumer::mComplete = true;
- if (Consumer::mDisconnected) {
- MOZ_ASSERT(!mThisVal);
- PROMISE_LOG("ThenValue::DoReject disconnected - bailing out [this=%p]", this);
- return;
- }
- InvokeCallbackMethod(mThisVal.get(), mRejectMethod, aRejectValue);
// Null out mThisVal after invoking the callback so that any references are
// released predictably on the dispatch thread. Otherwise, it would be
@@ -295,31 +280,96 @@ protected:
}
private:
- nsRefPtr mResponseTarget; // May be released on any thread.
nsRefPtr mThisVal; // Only accessed and refcounted on dispatch thread.
ResolveMethodType mResolveMethod;
RejectMethodType mRejectMethod;
};
+
+ // NB: We could use std::function here instead of a template if it were supported. :-(
+ template
+ class FunctionThenValue : public ThenValueBase
+ {
+ public:
+ FunctionThenValue(AbstractThread* aResponseTarget,
+ ResolveFunction&& aResolveFunction,
+ RejectFunction&& aRejectFunction,
+ const char* aCallSite)
+ : ThenValueBase(aResponseTarget, aCallSite)
+ {
+ mResolveFunction.emplace(Move(aResolveFunction));
+ mRejectFunction.emplace(Move(aRejectFunction));
+ }
+
+ virtual void Disconnect() override
+ {
+ ThenValueBase::Disconnect();
+
+ // If a Consumer has been disconnected, we don't guarantee that the
+ // resolve/reject runnable will be dispatched. Destroy our callbacks
+ // now so that any references in closures are released predictable on
+ // the dispatch thread.
+ mResolveFunction.reset();
+ mRejectFunction.reset();
+ }
+
+ protected:
+ virtual void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override
+ {
+ if (aValue.IsResolve()) {
+ mResolveFunction.ref()(aValue.ResolveValue());
+ } else {
+ mRejectFunction.ref()(aValue.RejectValue());
+ }
+
+ // Destroy callbacks after invocation so that any references in closures are
+ // released predictably on the dispatch thread. Otherwise, they would be
+ // released on whatever thread last drops its reference to the ThenValue,
+ // which may or may not be ok.
+ mResolveFunction.reset();
+ mRejectFunction.reset();
+ }
+
+ private:
+ Maybe mResolveFunction; // Only accessed and deleted on dispatch thread.
+ Maybe mRejectFunction; // Only accessed and deleted on dispatch thread.
+ };
+
+public:
+ void ThenInternal(AbstractThread* aResponseThread, ThenValueBase* aThenValue,
+ const char* aCallSite)
+ {
+ MutexAutoLock lock(mMutex);
+ MOZ_ASSERT(aResponseThread->IsDispatchReliable());
+ MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveConsumer);
+ mHaveConsumer = true;
+ PROMISE_LOG("%s invoking Then() [this=%p, aThenValue=%p, isPending=%d]",
+ aCallSite, this, aThenValue, (int) IsPending());
+ if (!IsPending()) {
+ aThenValue->Dispatch(this);
+ } else {
+ mThenValues.AppendElement(aThenValue);
+ }
+ }
+
public:
template
already_AddRefed RefableThen(AbstractThread* aResponseThread, const char* aCallSite, ThisType* aThisVal,
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
{
- MutexAutoLock lock(mMutex);
- MOZ_ASSERT(aResponseThread->IsDispatchReliable());
- MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveConsumer);
- mHaveConsumer = true;
- nsRefPtr thenValue = new ThenValue(
+ nsRefPtr thenValue = new MethodThenValue(
aResponseThread, aThisVal, aResolveMethod, aRejectMethod, aCallSite);
- PROMISE_LOG("%s invoking Then() [this=%p, thenValue=%p, aThisVal=%p, isPending=%d]",
- aCallSite, this, thenValue.get(), aThisVal, (int) IsPending());
- if (!IsPending()) {
- thenValue->Dispatch(this);
- } else {
- mThenValues.AppendElement(thenValue);
- }
+ ThenInternal(aResponseThread, thenValue, aCallSite);
+ return thenValue.forget();
+ }
+ template
+ already_AddRefed RefableThen(AbstractThread* aResponseThread, const char* aCallSite,
+ ResolveFunction&& aResolveFunction, RejectFunction&& aRejectFunction)
+ {
+ nsRefPtr thenValue = new FunctionThenValue(aResponseThread,
+ Move(aResolveFunction), Move(aRejectFunction), aCallSite);
+ ThenInternal(aResponseThread, thenValue, aCallSite);
return thenValue.forget();
}
@@ -332,6 +382,15 @@ public:
return;
}
+ template
+ void Then(AbstractThread* aResponseThread, const char* aCallSite,
+ ResolveFunction&& aResolveFunction, RejectFunction&& aRejectFunction)
+ {
+ nsRefPtr c =
+ RefableThen(aResponseThread, aCallSite, Move(aResolveFunction), Move(aRejectFunction));
+ return;
+ }
+
void ChainTo(already_AddRefed aChainedPromise, const char* aCallSite)
{
MutexAutoLock lock(mMutex);
@@ -348,7 +407,7 @@ public:
}
protected:
- bool IsPending() { return mResolveValue.isNothing() && mRejectValue.isNothing(); }
+ bool IsPending() { return mValue.IsNothing(); }
void DispatchAll()
{
mMutex.AssertCurrentThreadOwns();
@@ -366,10 +425,10 @@ protected:
void ForwardTo(Private* aOther)
{
MOZ_ASSERT(!IsPending());
- if (mResolveValue.isSome()) {
- aOther->Resolve(mResolveValue.ref(), "");
+ if (mValue.IsResolve()) {
+ aOther->Resolve(mValue.ResolveValue(), "");
} else {
- aOther->Reject(mRejectValue.ref(), "");
+ aOther->Reject(mValue.RejectValue(), "");
}
}
@@ -383,8 +442,7 @@ protected:
const char* mCreationSite; // For logging
Mutex mMutex;
- Maybe mResolveValue;
- Maybe mRejectValue;
+ ResolveOrRejectValue mValue;
nsTArray> mThenValues;
nsTArray> mChainedPromises;
bool mHaveConsumer;
@@ -402,7 +460,7 @@ public:
MutexAutoLock lock(mMutex);
MOZ_ASSERT(IsPending());
PROMISE_LOG("%s resolving MediaPromise (%p created at %s)", aResolveSite, this, mCreationSite);
- mResolveValue.emplace(aResolveValue);
+ mValue.SetResolve(aResolveValue);
DispatchAll();
}
@@ -411,7 +469,7 @@ public:
MutexAutoLock lock(mMutex);
MOZ_ASSERT(IsPending());
PROMISE_LOG("%s rejecting MediaPromise (%p created at %s)", aRejectSite, this, mCreationSite);
- mRejectValue.emplace(aRejectValue);
+ mValue.SetReject(aRejectValue);
DispatchAll();
}
};
diff --git a/dom/media/fmp4/SharedDecoderManager.cpp b/dom/media/fmp4/SharedDecoderManager.cpp
index bc908f258f26..7c35f02d724c 100644
--- a/dom/media/fmp4/SharedDecoderManager.cpp
+++ b/dom/media/fmp4/SharedDecoderManager.cpp
@@ -98,9 +98,12 @@ SharedDecoderManager::CreateVideoDecoder(
mPDM = nullptr;
return nullptr;
}
- mPDM = aPDM;
nsresult rv = mDecoder->Init();
- NS_ENSURE_SUCCESS(rv, nullptr);
+ if (NS_FAILED(rv)) {
+ mDecoder = nullptr;
+ return nullptr;
+ }
+ mPDM = aPDM;
}
nsRefPtr proxy(new SharedDecoderProxy(this, aCallback));
@@ -147,11 +150,19 @@ void
SharedDecoderManager::SetIdle(MediaDataDecoder* aProxy)
{
if (aProxy && mActiveProxy == aProxy) {
- mWaitForInternalDrain = true;
- mActiveProxy->Drain();
MonitorAutoLock mon(mMonitor);
- while (mWaitForInternalDrain) {
- mon.Wait();
+ mWaitForInternalDrain = true;
+ nsresult rv;
+ {
+ // We don't want to hold the lock while calling Drain() has some
+ // platform implementations call DrainComplete() immediately.
+ MonitorAutoUnlock mon(mMonitor);
+ rv = mActiveProxy->Drain();
+ }
+ if (NS_SUCCEEDED(rv)) {
+ while (mWaitForInternalDrain) {
+ mon.Wait();
+ }
}
mActiveProxy->Flush();
mActiveProxy = nullptr;
@@ -161,13 +172,15 @@ SharedDecoderManager::SetIdle(MediaDataDecoder* aProxy)
void
SharedDecoderManager::DrainComplete()
{
- if (mWaitForInternalDrain) {
+ {
MonitorAutoLock mon(mMonitor);
- mWaitForInternalDrain = false;
- mon.NotifyAll();
- } else {
- mActiveCallback->DrainComplete();
+ if (mWaitForInternalDrain) {
+ mWaitForInternalDrain = false;
+ mon.NotifyAll();
+ return;
+ }
}
+ mActiveCallback->DrainComplete();
}
void
diff --git a/dom/media/fmp4/apple/AppleVDADecoder.cpp b/dom/media/fmp4/apple/AppleVDADecoder.cpp
index d5e903006788..bac166b2bd11 100644
--- a/dom/media/fmp4/apple/AppleVDADecoder.cpp
+++ b/dom/media/fmp4/apple/AppleVDADecoder.cpp
@@ -364,6 +364,7 @@ AppleVDADecoder::SubmitFrame(MediaRawData* aSample)
if (rv != noErr) {
NS_WARNING("AppleVDADecoder: Couldn't pass frame to decoder");
+ mCallback->Error();
return NS_ERROR_FAILURE;
}
diff --git a/dom/media/fmp4/apple/AppleVTDecoder.cpp b/dom/media/fmp4/apple/AppleVTDecoder.cpp
index ecc62300bdb7..dd023c0a8201 100644
--- a/dom/media/fmp4/apple/AppleVTDecoder.cpp
+++ b/dom/media/fmp4/apple/AppleVTDecoder.cpp
@@ -168,8 +168,7 @@ PlatformCallback(void* decompressionOutputRefCon,
return;
}
if (flags & kVTDecodeInfo_FrameDropped) {
- NS_WARNING(" ...frame dropped...");
- return;
+ NS_WARNING(" ...frame tagged as dropped...");
}
MOZ_ASSERT(CFGetTypeID(image) == CVPixelBufferGetTypeID(),
"VideoToolbox returned an unexpected image type");
@@ -246,7 +245,9 @@ AppleVTDecoder::SubmitFrame(MediaRawData* aSample)
CreateAppleFrameRef(aSample),
&infoFlags);
if (rv != noErr && !(infoFlags & kVTDecodeInfo_FrameDropped)) {
+ LOG("AppleVTDecoder: Error %d VTDecompressionSessionDecodeFrame", rv);
NS_WARNING("Couldn't pass frame to decoder");
+ mCallback->Error();
return NS_ERROR_FAILURE;
}
diff --git a/dom/tests/mochitest/bugs/test_sizetocontent_clamp.html b/dom/tests/mochitest/bugs/test_sizetocontent_clamp.html
index 95f1eff6604a..517f99e66cbe 100644
--- a/dom/tests/mochitest/bugs/test_sizetocontent_clamp.html
+++ b/dom/tests/mochitest/bugs/test_sizetocontent_clamp.html
@@ -37,23 +37,21 @@ var innerWidthMax = (isWin8 ? 125 : 100);
function test() {
var w = window.open('data:text/html,null', null, 'width=300,height=300');
- var nbResize = 0;
SimpleTest.waitForFocus(function() {
w.onresize = function() {
- nbResize++;
-
- if (nbResize == 1) {
+ if (!(w.innerWidth + epsilon >= innerWidthMin &&
+ w.innerWidth - epsilon <= innerWidthMax)) {
+ // We need still another resize event.
return;
}
-
- ok(w.innerWidth + epsilon >= innerWidthMin && w.innerWidth - epsilon <= innerWidthMax,
- "innerWidth should be between " + innerWidthMin + " and " + innerWidthMax);
- ok(w.innerHeight + epsilon >= 100 && w.innerHeight - epsilon <= 100,
- "innerHeight should be around 100");
-
- // It's not clear why 2 events are coming...
- is(nbResize, 2, "We should get 2 events.");
+ if (!(w.innerHeight + epsilon >= 100 &&
+ w.innerHeight - epsilon <= 100)) {
+ // ditto
+ return;
+ }
+ ok(true, "innerWidth should be between " + innerWidthMin + " and " + innerWidthMax);
+ ok(true, "innerHeight should be around 100");
w.close();
diff --git a/dom/tests/mochitest/chrome/MozEnteredDomFullscreen_chrome.xul b/dom/tests/mochitest/chrome/MozDomFullscreen_chrome.xul
similarity index 85%
rename from dom/tests/mochitest/chrome/MozEnteredDomFullscreen_chrome.xul
rename to dom/tests/mochitest/chrome/MozDomFullscreen_chrome.xul
index 63fa30e71ec4..5673b1b1c5fa 100644
--- a/dom/tests/mochitest/chrome/MozEnteredDomFullscreen_chrome.xul
+++ b/dom/tests/mochitest/chrome/MozDomFullscreen_chrome.xul
@@ -60,7 +60,18 @@ function thirdEntry(event) {
is(event.target, gOuterDoc, "Third MozEnteredDomFullscreen should be targeted at outer doc");
ok(gOuterDoc.mozFullScreenElement != null, "Outer doc return to fullscreen after cancel fullscreen in inner doc");
window.removeEventListener("MozEnteredDomFullscreen", thirdEntry, false);
+ window.removeEventListener("MozExitedDomFullscreen", earlyExit, false);
+ window.addEventListener("MozExitedDomFullscreen", lastExit, false);
gOuterDoc.mozCancelFullScreen();
+}
+
+function earlyExit(event) {
+ ok(false, "MozExitedDomFullscreen should only be triggered after cancel all fullscreen");
+}
+
+function lastExit(event) {
+ is(event.target, gOuterDoc, "MozExitedDomFullscreen should be targeted at the last exited doc");
+ ok(gOuterDoc.mozFullScreenElement == null, "Fullscreen should have been fully exited");
window.opener.wrappedJSObject.done();
}
@@ -71,6 +82,7 @@ function start() {
gOuterDoc = gBrowser.contentDocument;
gBrowser.contentWindow.focus();
window.addEventListener("MozEnteredDomFullscreen", firstEntry, false);
+ window.addEventListener("MozExitedDomFullscreen", earlyExit, false);
gOuterDoc.body.mozRequestFullScreen();
});
}
@@ -78,6 +90,6 @@ function start() {
]]>
-
+
diff --git a/dom/tests/mochitest/chrome/chrome.ini b/dom/tests/mochitest/chrome/chrome.ini
index 77119435002d..52950fd53f42 100644
--- a/dom/tests/mochitest/chrome/chrome.ini
+++ b/dom/tests/mochitest/chrome/chrome.ini
@@ -4,7 +4,7 @@ support-files =
489127.html
DOMWindowCreated_chrome.xul
DOMWindowCreated_content.html
- MozEnteredDomFullscreen_chrome.xul
+ MozDomFullscreen_chrome.xul
child_focus_frame.html
file_DOM_element_instanceof.xul
file_bug799299.xul
@@ -49,7 +49,7 @@ skip-if = os == 'linux'
[test_indexedSetter.html]
[test_moving_nodeList.xul]
[test_moving_xhr.xul]
-[test_MozEnteredDomFullscreen_event.xul]
+[test_MozDomFullscreen_event.xul]
# disabled on OS X for intermittent failures--bug-798848
skip-if = toolkit == 'cocoa'
[test_nodesFromRect.html]
diff --git a/dom/tests/mochitest/chrome/test_MozEnteredDomFullscreen_event.xul b/dom/tests/mochitest/chrome/test_MozDomFullscreen_event.xul
similarity index 93%
rename from dom/tests/mochitest/chrome/test_MozEnteredDomFullscreen_event.xul
rename to dom/tests/mochitest/chrome/test_MozDomFullscreen_event.xul
index d9ab22684b57..076e9db4e49c 100644
--- a/dom/tests/mochitest/chrome/test_MozEnteredDomFullscreen_event.xul
+++ b/dom/tests/mochitest/chrome/test_MozDomFullscreen_event.xul
@@ -36,7 +36,7 @@ SpecialPowers.pushPrefEnv({"set": [['full-screen-api.enabled', true],
['full-screen-api.allow-trusted-requests-only', false]]}, setup);
function setup() {
- newwindow = window.open("MozEnteredDomFullscreen_chrome.xul", "_blank","chrome,resizable=yes,width=400,height=400");
+ newwindow = window.open("MozDomFullscreen_chrome.xul", "_blank","chrome,resizable=yes,width=400,height=400");
}
function done()
diff --git a/dom/tests/mochitest/general/file_MozEnteredDomFullscreen.html b/dom/tests/mochitest/general/file_MozDomFullscreen.html
similarity index 100%
rename from dom/tests/mochitest/general/file_MozEnteredDomFullscreen.html
rename to dom/tests/mochitest/general/file_MozDomFullscreen.html
diff --git a/dom/tests/mochitest/general/mochitest.ini b/dom/tests/mochitest/general/mochitest.ini
index 492a2565189c..5cd5f731391e 100644
--- a/dom/tests/mochitest/general/mochitest.ini
+++ b/dom/tests/mochitest/general/mochitest.ini
@@ -1,7 +1,7 @@
[DEFAULT]
support-files =
497633.html
- file_MozEnteredDomFullscreen.html
+ file_MozDomFullscreen.html
file_bug628069.html
file_clonewrapper.html
file_domWindowUtils_scrollbarSize.html
diff --git a/dom/webidl/Cache.webidl b/dom/webidl/Cache.webidl
index 7df69a8f6e0c..b2c698bb0703 100644
--- a/dom/webidl/Cache.webidl
+++ b/dom/webidl/Cache.webidl
@@ -13,32 +13,32 @@
[Exposed=(Window,Worker),
Func="mozilla::dom::cache::Cache::PrefEnabled"]
interface Cache {
-[Throws]
-Promise match(RequestInfo request, optional CacheQueryOptions options);
-[Throws]
-Promise> matchAll(optional RequestInfo request, optional CacheQueryOptions options);
-[Throws]
-Promise add(RequestInfo request);
-[Throws]
-Promise addAll(sequence requests);
-[Throws]
-Promise put(RequestInfo request, Response response);
-[Throws]
-Promise delete(RequestInfo request, optional CacheQueryOptions options);
-[Throws]
-Promise> keys(optional RequestInfo request, optional CacheQueryOptions options);
+ [NewObject]
+ Promise match(RequestInfo request, optional CacheQueryOptions options);
+ [NewObject]
+ Promise> matchAll(optional RequestInfo request, optional CacheQueryOptions options);
+ [NewObject]
+ Promise add(RequestInfo request);
+ [NewObject]
+ Promise addAll(sequence requests);
+ [NewObject]
+ Promise put(RequestInfo request, Response response);
+ [NewObject]
+ Promise delete(RequestInfo request, optional CacheQueryOptions options);
+ [NewObject]
+ Promise> keys(optional RequestInfo request, optional CacheQueryOptions options);
};
dictionary CacheQueryOptions {
-boolean ignoreSearch = false;
-boolean ignoreMethod = false;
-boolean ignoreVary = false;
-DOMString cacheName;
+ boolean ignoreSearch = false;
+ boolean ignoreMethod = false;
+ boolean ignoreVary = false;
+ DOMString cacheName;
};
dictionary CacheBatchOperation {
-DOMString type;
-Request request;
-Response response;
-CacheQueryOptions options;
+ DOMString type;
+ Request request;
+ Response response;
+ CacheQueryOptions options;
};
diff --git a/dom/webidl/CacheStorage.webidl b/dom/webidl/CacheStorage.webidl
index ef845a64a1a5..cf5bad44b201 100644
--- a/dom/webidl/CacheStorage.webidl
+++ b/dom/webidl/CacheStorage.webidl
@@ -10,17 +10,25 @@
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cache-storage
+interface Principal;
+
[Exposed=(Window,Worker),
+ ChromeConstructor(CacheStorageNamespace namespace, Principal principal),
Func="mozilla::dom::cache::CacheStorage::PrefEnabled"]
interface CacheStorage {
-[Throws]
-Promise match(RequestInfo request, optional CacheQueryOptions options);
-[Throws]
-Promise has(DOMString cacheName);
-[Throws]
-Promise open(DOMString cacheName);
-[Throws]
-Promise delete(DOMString cacheName);
-[Throws]
-Promise> keys();
+ [NewObject]
+ Promise match(RequestInfo request, optional CacheQueryOptions options);
+ [NewObject]
+ Promise has(DOMString cacheName);
+ [NewObject]
+ Promise open(DOMString cacheName);
+ [NewObject]
+ Promise delete(DOMString cacheName);
+ [NewObject]
+ Promise> keys();
+};
+
+// chrome-only, gecko specific extension
+enum CacheStorageNamespace {
+ "content", "chrome"
};
diff --git a/dom/webidl/MozSelfSupport.webidl b/dom/webidl/MozSelfSupport.webidl
index 7ba73ba1f6c5..c4345bcc088b 100644
--- a/dom/webidl/MozSelfSupport.webidl
+++ b/dom/webidl/MozSelfSupport.webidl
@@ -50,4 +50,9 @@ interface MozSelfSupport
* The name of the pref to reset.
*/
void resetPref(DOMString name);
+
+ /**
+ * Resets original search engines, and resets the default one.
+ */
+ void resetSearchEngines();
};
diff --git a/dom/webidl/URL.webidl b/dom/webidl/URL.webidl
index 7fe970104372..dd28dec22ff9 100644
--- a/dom/webidl/URL.webidl
+++ b/dom/webidl/URL.webidl
@@ -14,7 +14,7 @@
// [Constructor(DOMString url, optional (URL or DOMString) base = "about:blank")]
[Constructor(DOMString url, URL base),
- Constructor(DOMString url, optional DOMString base = "about:blank"),
+ Constructor(DOMString url, optional DOMString base),
Exposed=(Window,Worker)]
interface URL {
};
diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp
index 5e50d394e4c3..9693ff629ade 100644
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -16,6 +16,7 @@
#include "nsIHttpHeaderVisitor.h"
#include "nsINetworkInterceptController.h"
#include "nsIMutableArray.h"
+#include "nsIUploadChannel2.h"
#include "nsPIDOMWindow.h"
#include "nsScriptLoader.h"
#include "nsDebug.h"
@@ -2357,6 +2358,7 @@ class FetchEventRunnable : public WorkerRunnable
RequestMode mRequestMode;
RequestCredentials mRequestCredentials;
nsContentPolicyType mContentPolicyType;
+ nsCOMPtr mUploadStream;
public:
FetchEventRunnable(WorkerPrivate* aWorkerPrivate,
nsMainThreadPtrHandle& aChannel,
@@ -2451,6 +2453,13 @@ public:
mContentPolicyType = loadInfo->GetContentPolicyType();
+ nsCOMPtr uploadChannel = do_QueryInterface(httpChannel);
+ if (uploadChannel) {
+ MOZ_ASSERT(!mUploadStream);
+ rv = uploadChannel->CloneUploadStream(getter_AddRefs(mUploadStream));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
return NS_OK;
}
@@ -2510,8 +2519,6 @@ private:
reqInit.mHeaders.Construct();
reqInit.mHeaders.Value().SetAsHeaders() = headers;
- //TODO(jdm): set request body
-
reqInit.mMode.Construct(mRequestMode);
reqInit.mCredentials.Construct(mRequestCredentials);
@@ -2525,6 +2532,8 @@ private:
MOZ_ASSERT(internalReq);
internalReq->SetCreatedByFetchEvent();
+ internalReq->SetBody(mUploadStream);
+
request->SetContentPolicyType(mContentPolicyType);
RootedDictionary init(aCx);
diff --git a/dom/workers/URL.cpp b/dom/workers/URL.cpp
index 21e10359c2b3..012c68270fe0 100644
--- a/dom/workers/URL.cpp
+++ b/dom/workers/URL.cpp
@@ -34,7 +34,7 @@ class URLProxy final
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(URLProxy)
- explicit URLProxy(mozilla::dom::URL* aURL)
+ explicit URLProxy(already_AddRefed aURL)
: mURL(aURL)
{
AssertIsOnMainThread();
@@ -228,7 +228,7 @@ class ConstructorRunnable : public WorkerMainThreadRunnable
private:
const nsString mURL;
- const nsString mBase;
+ nsString mBase; // IsVoid() if we have no base URI string.
nsRefPtr mBaseProxy;
mozilla::ErrorResult& mRv;
@@ -236,13 +236,17 @@ private:
public:
ConstructorRunnable(WorkerPrivate* aWorkerPrivate,
- const nsAString& aURL, const nsAString& aBase,
+ const nsAString& aURL, const Optional& aBase,
mozilla::ErrorResult& aRv)
: WorkerMainThreadRunnable(aWorkerPrivate)
, mURL(aURL)
- , mBase(aBase)
, mRv(aRv)
{
+ if (aBase.WasPassed()) {
+ mBase = aBase.Value();
+ } else {
+ mBase.SetIsVoid(true);
+ }
mWorkerPrivate->AssertIsOnWorkerThread();
}
@@ -254,6 +258,7 @@ public:
, mBaseProxy(aBaseProxy)
, mRv(aRv)
{
+ mBase.SetIsVoid(true);
mWorkerPrivate->AssertIsOnWorkerThread();
}
@@ -262,35 +267,20 @@ public:
{
AssertIsOnMainThread();
- nsresult rv;
- nsCOMPtr ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
- if (NS_FAILED(rv)) {
- mRv.Throw(rv);
- return true;
- }
-
- nsCOMPtr baseURL;
-
- if (!mBaseProxy) {
- rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mBase), nullptr, nullptr,
- getter_AddRefs(baseURL));
- if (NS_FAILED(rv)) {
- mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
- return true;
- }
+ nsRefPtr url;
+ if (mBaseProxy) {
+ url = mozilla::dom::URL::Constructor(mURL, mBaseProxy->URI(), mRv);
+ } else if (!mBase.IsVoid()) {
+ url = mozilla::dom::URL::Constructor(mURL, mBase, mRv);
} else {
- baseURL = mBaseProxy->URI();
+ url = mozilla::dom::URL::Constructor(mURL, nullptr, mRv);
}
- nsCOMPtr url;
- rv = ioService->NewURI(NS_ConvertUTF16toUTF8(mURL), nullptr, baseURL,
- getter_AddRefs(url));
- if (NS_FAILED(rv)) {
- mRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+ if (mRv.Failed()) {
return true;
}
- mRetval = new URLProxy(new mozilla::dom::URL(url));
+ mRetval = new URLProxy(url.forget());
return true;
}
@@ -522,18 +512,21 @@ URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
nsRefPtr runnable =
new ConstructorRunnable(workerPrivate, aUrl, aBase.GetURLProxy(), aRv);
- if (!runnable->Dispatch(cx)) {
- JS_ReportPendingException(cx);
- }
+ return FinishConstructor(cx, workerPrivate, runnable, aRv);
+}
- nsRefPtr proxy = runnable->GetURLProxy();
- if (!proxy) {
- aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
- return nullptr;
- }
+// static
+already_AddRefed
+URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
+ const Optional& aBase, ErrorResult& aRv)
+{
+ JSContext* cx = aGlobal.Context();
+ WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
- nsRefPtr url = new URL(workerPrivate, proxy);
- return url.forget();
+ nsRefPtr runnable =
+ new ConstructorRunnable(workerPrivate, aUrl, aBase, aRv);
+
+ return FinishConstructor(cx, workerPrivate, runnable, aRv);
}
// static
@@ -544,20 +537,34 @@ URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
JSContext* cx = aGlobal.Context();
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
+ Optional base;
+ base = &aBase;
nsRefPtr runnable =
- new ConstructorRunnable(workerPrivate, aUrl, aBase, aRv);
+ new ConstructorRunnable(workerPrivate, aUrl, base, aRv);
- if (!runnable->Dispatch(cx)) {
- JS_ReportPendingException(cx);
+ return FinishConstructor(cx, workerPrivate, runnable, aRv);
+}
+
+// static
+already_AddRefed
+URL::FinishConstructor(JSContext* aCx, WorkerPrivate* aPrivate,
+ ConstructorRunnable* aRunnable, ErrorResult& aRv)
+{
+ if (!aRunnable->Dispatch(aCx)) {
+ JS_ReportPendingException(aCx);
}
- nsRefPtr proxy = runnable->GetURLProxy();
+ if (aRv.Failed()) {
+ return nullptr;
+ }
+
+ nsRefPtr proxy = aRunnable->GetURLProxy();
if (!proxy) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return nullptr;
}
- nsRefPtr url = new URL(workerPrivate, proxy);
+ nsRefPtr url = new URL(aPrivate, proxy);
return url.forget();
}
diff --git a/dom/workers/URL.h b/dom/workers/URL.h
index 1c15c3b63405..85e1fcbd6a53 100644
--- a/dom/workers/URL.h
+++ b/dom/workers/URL.h
@@ -23,6 +23,7 @@ struct objectURLOptions;
BEGIN_WORKERS_NAMESPACE
class URLProxy;
+class ConstructorRunnable;
class URL final : public mozilla::dom::URLSearchParamsObserver
{
@@ -52,6 +53,9 @@ public:
Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
URL& aBase, ErrorResult& aRv);
static already_AddRefed
+ Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
+ const Optional& aBase, ErrorResult& aRv);
+ static already_AddRefed
Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
const nsAString& aBase, ErrorResult& aRv);
@@ -123,6 +127,10 @@ private:
return mURLProxy;
}
+ static already_AddRefed
+ FinishConstructor(JSContext* aCx, WorkerPrivate* aPrivate,
+ ConstructorRunnable* aRunnable, ErrorResult& aRv);
+
void CreateSearchParamsIfNeeded();
void SetSearchInternal(const nsAString& aSearch);
diff --git a/dom/workers/test/serviceworkers/fetch/fetch_tests.js b/dom/workers/test/serviceworkers/fetch/fetch_tests.js
index 15bc0bbed451..b256ca3b65d4 100644
--- a/dom/workers/test/serviceworkers/fetch/fetch_tests.js
+++ b/dom/workers/test/serviceworkers/fetch/fetch_tests.js
@@ -180,3 +180,73 @@ fetch('http://example.com/cors-for-no-cors', { mode: "no-cors" })
my_ok(false, "intercepted non-opaque response for no-cors request should resolve to opaque response. It should not fail.");
finish();
});
+
+function arrayBufferFromString(str) {
+ var arr = new Uint8Array(str.length);
+ for (var i = 0; i < str.length; ++i) {
+ arr[i] = str.charCodeAt(i);
+ }
+ return arr;
+}
+
+expectAsyncResult();
+fetch(new Request('body-simple', {method: 'POST', body: 'my body'}))
+.then(function(res) {
+ return res.text();
+}).then(function(body) {
+ my_ok(body == 'my bodymy body', "the body of the intercepted fetch should be visible in the SW");
+ finish();
+});
+
+expectAsyncResult();
+fetch(new Request('body-arraybufferview', {method: 'POST', body: arrayBufferFromString('my body')}))
+.then(function(res) {
+ return res.text();
+}).then(function(body) {
+ my_ok(body == 'my bodymy body', "the ArrayBufferView body of the intercepted fetch should be visible in the SW");
+ finish();
+});
+
+expectAsyncResult();
+fetch(new Request('body-arraybuffer', {method: 'POST', body: arrayBufferFromString('my body').buffer}))
+.then(function(res) {
+ return res.text();
+}).then(function(body) {
+ my_ok(body == 'my bodymy body', "the ArrayBuffer body of the intercepted fetch should be visible in the SW");
+ finish();
+});
+
+expectAsyncResult();
+var usp = new URLSearchParams();
+usp.set("foo", "bar");
+usp.set("baz", "qux");
+fetch(new Request('body-urlsearchparams', {method: 'POST', body: usp}))
+.then(function(res) {
+ return res.text();
+}).then(function(body) {
+ my_ok(body == 'foo=bar&baz=quxfoo=bar&baz=qux', "the URLSearchParams body of the intercepted fetch should be visible in the SW");
+ finish();
+});
+
+expectAsyncResult();
+var fd = new FormData();
+fd.set("foo", "bar");
+fd.set("baz", "qux");
+fetch(new Request('body-formdata', {method: 'POST', body: fd}))
+.then(function(res) {
+ return res.text();
+}).then(function(body) {
+ my_ok(body.indexOf("Content-Disposition: form-data; name=\"foo\"\r\n\r\nbar") <
+ body.indexOf("Content-Disposition: form-data; name=\"baz\"\r\n\r\nqux"),
+ "the FormData body of the intercepted fetch should be visible in the SW");
+ finish();
+});
+
+expectAsyncResult();
+fetch(new Request('body-blob', {method: 'POST', body: new Blob(new String('my body'))}))
+.then(function(res) {
+ return res.text();
+}).then(function(body) {
+ my_ok(body == 'my bodymy body', "the Blob body of the intercepted fetch should be visible in the SW");
+ finish();
+});
diff --git a/dom/workers/test/serviceworkers/fetch_event_worker.js b/dom/workers/test/serviceworkers/fetch_event_worker.js
index 5f35bf2fa309..ff7bc98b599b 100644
--- a/dom/workers/test/serviceworkers/fetch_event_worker.js
+++ b/dom/workers/test/serviceworkers/fetch_event_worker.js
@@ -172,4 +172,10 @@ onfetch = function(ev) {
ev.respondWith(fetch(ev.request.url));
}
}
+
+ else if (ev.request.url.includes("body-")) {
+ ev.respondWith(ev.request.text().then(function (body) {
+ return new Response(body + body);
+ }));
+ }
}
diff --git a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.html b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.html
index 3ba95a4f4b4b..60a5dfd1f22e 100644
--- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.html
+++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.html
@@ -94,12 +94,28 @@
SimpleTest.waitForExplicitFinish();
onload = function() {
- SpecialPowers.pushPrefEnv({"set": [
+ // The handling of "dom.caches.enabled" here is a bit complicated. What we
+ // want to happen is that Cache is always enabled in service workers. So
+ // if service workers are disabled by default we want to force on both
+ // service workers and "dom.caches.enabled". But if service workers are
+ // enabled by default, we do not want to mess with the "dom.caches.enabled"
+ // value, since that would defeat the purpose of the test. Use a subframe
+ // to decide whether service workers are enabled by default, so we don't
+ // force creation of our own Navigator object before our prefs are set.
+ var prefs = [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
- ["dom.caches.enabled", true]
- ]}, runTest);
+ ];
+
+ var subframe = document.createElement("iframe");
+ document.body.appendChild(subframe);
+ if (!("serviceWorker" in subframe.contentWindow.navigator)) {
+ prefs.push(["dom.caches.enabled", true]);
+ }
+ subframe.remove();
+
+ SpecialPowers.pushPrefEnv({"set": prefs}, runTest);
};
+Mozilla Bug 1161206
+
+
+
Scrolling the page should be async, but scrolling over the dark circle should not scroll the page and instead rotate the white ball.
+
+
+
+
+
+
+
diff --git a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
index 13caa0baf8a8..935b6108b1f7 100644
--- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
+++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
@@ -91,9 +91,9 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"BroadcastChannel",
// IMPORTANT: Do not change this list without review from a DOM peer!
- { name: "Cache", release: false },
+ "Cache",
// IMPORTANT: Do not change this list without review from a DOM peer!
- { name: "CacheStorage", release: false },
+ "CacheStorage",
// IMPORTANT: Do not change this list without review from a DOM peer!
"Client",
// IMPORTANT: Do not change this list without review from a DOM peer!
diff --git a/dom/workers/test/serviceworkers/test_workerupdatefoundevent.html b/dom/workers/test/serviceworkers/test_workerupdatefoundevent.html
index 7df52e74c3ee..3361eba08a3e 100644
--- a/dom/workers/test/serviceworkers/test_workerupdatefoundevent.html
+++ b/dom/workers/test/serviceworkers/test_workerupdatefoundevent.html
@@ -17,24 +17,18 @@
var registration;
var promise;
- SimpleTest.requestCompleteLog();
-
function start() {
- info("start got called");
return navigator.serviceWorker.register("worker_updatefoundevent.js",
{ scope: "./updatefoundevent.html" })
.then((swr) => registration = swr);
}
function startWaitForUpdateFound() {
- info("startWaitForUpdateFound got called");
registration.onupdatefound = function(e) {
- info("onupdatefound");
}
promise = new Promise(function(resolve, reject) {
window.onmessage = function(e) {
- info("Got message " + e.data);
if (e.data == "finish") {
ok(true, "Received updatefound");
@@ -52,18 +46,16 @@
}
function registerNext() {
- info("registerNext got called");
return navigator.serviceWorker.register("worker_updatefoundevent2.js",
{ scope: "./updatefoundevent.html" });
}
function waitForUpdateFound() {
- info("waitForUpdateFound got called");
return promise;
}
function unregister() {
- info("unregister got called");
+ window.onmessage = null;
return registration.unregister().then(function(result) {
ok(result, "Unregister should return true.");
});
@@ -85,7 +77,6 @@
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
- ["browser.dom.window.dump.enabled", true],
]}, runTest);
diff --git a/dom/workers/test/serviceworkers/worker_updatefoundevent.js b/dom/workers/test/serviceworkers/worker_updatefoundevent.js
index 2474c31cca18..a297bf455674 100644
--- a/dom/workers/test/serviceworkers/worker_updatefoundevent.js
+++ b/dom/workers/test/serviceworkers/worker_updatefoundevent.js
@@ -6,10 +6,8 @@
onactivate = function(e) {
e.waitUntil(new Promise(function(resolve, reject) {
registration.onupdatefound = function(e) {
- dump("Update found for scope " + registration.scope + "\n");
clients.matchAll().then(function(clients) {
if (!clients.length) {
- dump("No clients found\n");
reject("No clients found");
}
diff --git a/dom/workers/test/serviceworkers/worker_updatefoundevent2.js b/dom/workers/test/serviceworkers/worker_updatefoundevent2.js
index 681206711e48..da4c592aad80 100644
--- a/dom/workers/test/serviceworkers/worker_updatefoundevent2.js
+++ b/dom/workers/test/serviceworkers/worker_updatefoundevent2.js
@@ -1,2 +1 @@
// Not useful.
-dump("worker_updatefoundevent2.js loaded\n");
diff --git a/gfx/layers/apz/test/apz_test_native_event_utils.js b/gfx/layers/apz/test/apz_test_native_event_utils.js
new file mode 100644
index 000000000000..391f7647172c
--- /dev/null
+++ b/gfx/layers/apz/test/apz_test_native_event_utils.js
@@ -0,0 +1,72 @@
+// Utilities for synthesizing of native events.
+
+function getPlatform() {
+ if (navigator.platform.indexOf("Win") == 0) {
+ return "windows";
+ }
+ if (navigator.platform.indexOf("Mac") == 0) {
+ return "mac";
+ }
+ if (navigator.platform.indexOf("Linux") == 0) {
+ return "linux";
+ }
+ return "unknown";
+}
+
+function nativeVerticalWheelEventMsg() {
+ switch (getPlatform()) {
+ case "windows": return 0x020A; // WM_MOUSEWHEEL
+ case "mac": return 0; // value is unused, can be anything
+ }
+ throw "Native wheel events not supported on platform " + getPlatform();
+}
+
+function nativeHorizontalWheelEventMsg() {
+ switch (getPlatform()) {
+ case "windows": return 0x020E; // WM_MOUSEHWHEEL
+ case "mac": return 0; // value is unused, can be anything
+ }
+ throw "Native wheel events not supported on platform " + getPlatform();
+}
+
+// Synthesizes a native mousewheel event and returns immediately. This does not
+// guarantee anything; you probably want to use one of the other functions below
+// which actually wait for results.
+// aX and aY are relative to |window|'s top-left. aDeltaX and aDeltaY
+// are pixel deltas, and aObserver can be left undefined if not needed.
+function synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY, aObserver) {
+ aX += window.mozInnerScreenX;
+ aY += window.mozInnerScreenY;
+ if (aDeltaX && aDeltaY) {
+ throw "Simultaneous wheeling of horizontal and vertical is not supported on all platforms.";
+ }
+ var msg = aDeltaX ? nativeHorizontalWheelEventMsg() : nativeVerticalWheelEventMsg();
+ _getDOMWindowUtils().sendNativeMouseScrollEvent(aX, aY, msg, aDeltaX, aDeltaY, 0, 0, 0, aElement, aObserver);
+ return true;
+}
+
+// Synthesizes a native mousewheel event and invokes the callback once the
+// request has been successfully made to the OS. This does not necessarily
+// guarantee that the OS generates the event we requested. See
+// synthesizeNativeWheel for details on the parameters.
+function synthesizeNativeWheelAndWaitForObserver(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
+ var observer = {
+ observe: function(aSubject, aTopic, aData) {
+ if (aCallback && aTopic == "mousescrollevent") {
+ setTimeout(aCallback, 0);
+ }
+ }
+ };
+ return synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY, observer);
+}
+
+// Synthesizes a native mousewheel event and invokes the callback once the
+// wheel event is dispatched to the window. See synthesizeNativeWheel for
+// details on the parameters.
+function synthesizeNativeWheelAndWaitForEvent(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
+ window.addEventListener("wheel", function wheelWaiter(e) {
+ window.removeEventListener("wheel", wheelWaiter);
+ setTimeout(aCallback, 0);
+ });
+ return synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY);
+}
diff --git a/gfx/layers/apz/test/mochitest.ini b/gfx/layers/apz/test/mochitest.ini
index 52cf7e04f204..5d42cd251538 100644
--- a/gfx/layers/apz/test/mochitest.ini
+++ b/gfx/layers/apz/test/mochitest.ini
@@ -1,9 +1,13 @@
[DEFAULT]
support-files =
apz_test_utils.js
+ apz_test_native_event_utils.js
helper_bug982141.html
helper_bug1151663.html
+tags = apz
[test_bug982141.html]
skip-if = toolkit != 'gonk' # bug 991198
[test_bug1151663.html]
skip-if = toolkit != 'gonk' # bug 991198
+[test_wheel_scroll.html]
+skip-if = toolkit != 'windows' && toolkit != 'cocoa'
diff --git a/gfx/layers/apz/test/test_wheel_scroll.html b/gfx/layers/apz/test/test_wheel_scroll.html
new file mode 100644
index 000000000000..f3b4ff8e590a
--- /dev/null
+++ b/gfx/layers/apz/test/test_wheel_scroll.html
@@ -0,0 +1,109 @@
+
+
+
+