зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to m-c. a=merge
This commit is contained in:
Коммит
16c36d245d
|
@ -425,9 +425,9 @@ function testAccessibleTree(aAccOrElmOrID, aAccTree, aFlags)
|
|||
for (var offset in accTree[prop]) {
|
||||
if (prevOffset !=- 1) {
|
||||
var attrs = accTree[prop][prevOffset];
|
||||
testTextAttrs(acc, prevOffset, attrs, { }, prevOffset, offset, true);
|
||||
testTextAttrs(acc, prevOffset, attrs, { }, prevOffset, +offset, true);
|
||||
}
|
||||
prevOffset = offset;
|
||||
prevOffset = +offset;
|
||||
}
|
||||
|
||||
if (prevOffset != -1) {
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// Invokers
|
||||
|
||||
const kRemoval = 0;
|
||||
const kInsertion = 1;
|
||||
const kRemoval = false;
|
||||
const kInsertion = true;
|
||||
const kUnexpected = true;
|
||||
|
||||
function changeText(aContainerID, aValue, aEventList)
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
try {
|
||||
var endCol = propBag.getPropertyAsInt32("endcolumn");
|
||||
} catch (e if e.name == 'NS_ERROR_NOT_AVAILABLE') {
|
||||
startCol = null;
|
||||
endCol = null;
|
||||
}
|
||||
is(endCol, aEndCol,
|
||||
"Wrong 'endcolumn' of 'treeInvalidated' event on " + aMsg);
|
||||
|
|
|
@ -52,7 +52,7 @@ const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
|
|||
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
|
||||
const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
|
||||
|
||||
const kOrdinalState = 0;
|
||||
const kOrdinalState = false;
|
||||
const kExtraState = 1;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
aId + ": wrong number of selected columns");
|
||||
|
||||
if (!aSelIndexesArray) {
|
||||
is(selCols.value, null,
|
||||
is(selCols.value, undefined,
|
||||
aId + ": no columns should be selected");
|
||||
} else {
|
||||
for (var i = 0; i < selCols.length; i++) {
|
||||
|
@ -116,7 +116,7 @@
|
|||
aId + ": wrong number of selected rows");
|
||||
|
||||
if (!aSelIndexesArray) {
|
||||
is(selCols.value, null,
|
||||
is(selCols.value, undefined,
|
||||
aId + ": no row should be selected");
|
||||
} else {
|
||||
for (var i = 0; i < selCols.length; i++) {
|
||||
|
@ -159,7 +159,7 @@
|
|||
aId + ": wrong number of selected cells");
|
||||
|
||||
if (!aSelIndexesArray) {
|
||||
is(selCols.value, null,
|
||||
is(selCols.value, undefined,
|
||||
aId + ": no cells should be selected");
|
||||
} else {
|
||||
for (var i = 0; i < selCols.length; i++) {
|
||||
|
|
|
@ -1124,23 +1124,8 @@ pref("dom.mozSettings.allowForceReadOnly", false);
|
|||
// RequestSync API is enabled by default on B2G.
|
||||
pref("dom.requestSync.enabled", true);
|
||||
|
||||
// Only enable for kit kat and above devices
|
||||
// kit kat == 19, L = 21, 20 is kit-kat for wearables
|
||||
// 15 is for the ICS emulators which will fallback to software vsync
|
||||
#if ANDROID_VERSION == 19 || ANDROID_VERSION == 21 || ANDROID_VERSION == 15
|
||||
// Use vsync aligned rendering
|
||||
pref("gfx.vsync.hw-vsync.enabled", true);
|
||||
pref("gfx.vsync.compositor", true);
|
||||
pref("gfx.touch.resample", true);
|
||||
#else
|
||||
pref("gfx.vsync.hw-vsync.enabled", false);
|
||||
pref("gfx.vsync.compositor", false);
|
||||
pref("gfx.touch.resample", false);
|
||||
#endif
|
||||
|
||||
// Bug 1147753 - Weird issues with vsync refresh driver on L devices
|
||||
// so disable them on L, but enable on KK and ICS
|
||||
#if ANDROID_VERSION == 19 || ANDROID_VERSION == 15
|
||||
pref("gfx.vsync.refreshdriver", true);
|
||||
#else
|
||||
pref("gfx.vsync.refreshdriver", false);
|
||||
#endif
|
||||
|
|
|
@ -292,50 +292,45 @@ ContentPermissionPrompt.prototype = {
|
|||
return !type.deny && (type.action == Ci.nsIPermissionManager.PROMPT_ACTION || type.options.length > 0) ;
|
||||
});
|
||||
|
||||
let frame = request.element;
|
||||
|
||||
if (!frame) {
|
||||
if (!request.element) {
|
||||
this.delegatePrompt(request, typesInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
frame = frame.wrappedJSObject;
|
||||
var cancelRequest = function() {
|
||||
frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
request.requester.onVisibilityChange = null;
|
||||
request.cancel();
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var onVisibilityChange = function(evt) {
|
||||
if (evt.detail.visible === true)
|
||||
return;
|
||||
|
||||
self.cancelPrompt(request, typesInfo);
|
||||
cancelRequest();
|
||||
}
|
||||
|
||||
// If the request was initiated from a hidden iframe
|
||||
// we don't forward it to content and cancel it right away
|
||||
let domRequest = frame.getVisible();
|
||||
domRequest.onsuccess = function gv_success(evt) {
|
||||
if (!evt.target.result) {
|
||||
cancelRequest();
|
||||
return;
|
||||
request.requester.getVisibility( {
|
||||
notifyVisibility: function(isVisible) {
|
||||
if (!isVisible) {
|
||||
cancelRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
// Monitor the frame visibility and cancel the request if the frame goes
|
||||
// away but the request is still here.
|
||||
request.requester.onVisibilityChange = {
|
||||
notifyVisibility: function(isVisible) {
|
||||
if (isVisible)
|
||||
return;
|
||||
|
||||
self.cancelPrompt(request, typesInfo);
|
||||
cancelRequest();
|
||||
}
|
||||
}
|
||||
|
||||
self.delegatePrompt(request, typesInfo, function onCallback() {
|
||||
request.requester.onVisibilityChange = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Monitor the frame visibility and cancel the request if the frame goes
|
||||
// away but the request is still here.
|
||||
frame.addEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
|
||||
self.delegatePrompt(request, typesInfo, function onCallback() {
|
||||
frame.removeEventListener("mozbrowservisibilitychange", onVisibilityChange);
|
||||
});
|
||||
};
|
||||
|
||||
// Something went wrong. Let's cancel the request just in case.
|
||||
domRequest.onerror = function gv_error() {
|
||||
cancelRequest();
|
||||
}
|
||||
},
|
||||
|
||||
cancelPrompt: function(request, typesInfo) {
|
||||
|
|
|
@ -16,3 +16,4 @@ skip-if = true # Bug 1019572 - frequent timeouts
|
|||
[test_screenshot.html]
|
||||
[test_systemapp.html]
|
||||
[test_presentation_device_prompt.html]
|
||||
[test_permission_visibilitychange.html]
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=951997
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Permission Prompt Test</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1020179">Permission prompt visibilitychange test</a>
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
"use strict";
|
||||
|
||||
var gUrl = SimpleTest.getTestFileURL("permission_handler_chrome.js");
|
||||
var gScript = SpecialPowers.loadChromeScript(gUrl);
|
||||
|
||||
function testDone() {
|
||||
gScript.sendAsyncMessage("teardown", "");
|
||||
gScript.destroy();
|
||||
SimpleTest.finish();
|
||||
alert("setVisible::true");
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
function (pos) {
|
||||
ok(false, "unexpected success, permission request should be canceled");
|
||||
testDone();
|
||||
}, function (err) {
|
||||
ok(true, "success, permission request is canceled");
|
||||
testDone();
|
||||
});
|
||||
}
|
||||
|
||||
gScript.addMessageListener("permission-request", function (detail) {
|
||||
info("got permission-request!!!!\n");
|
||||
alert("setVisible::false");
|
||||
});
|
||||
|
||||
// Add permissions to this app. We use ALLOW_ACTION here. The ContentPermissionPrompt
|
||||
// should prompt for permission, not allow it without prompt.
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.navigator.permission.disabled", false]]},
|
||||
function() {
|
||||
SpecialPowers.addPermission("geolocation",
|
||||
SpecialPowers.Ci.nsIPermissionManager.PROMPT_ACTION, document);
|
||||
runTest();
|
||||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -19,19 +19,19 @@
|
|||
.securityUI;
|
||||
|
||||
var loadedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
|
||||
is(loadedMixedActive, false, "OK: Should not load mixed active content!");
|
||||
|
||||
var blockedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
|
||||
is(blockedMixedActive, false, "OK: Should not block mixed active content!");
|
||||
|
||||
var loadedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
|
||||
is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
|
||||
|
||||
var blockedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
|
||||
is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
|
||||
|
||||
var newValue = "Verifying MCB does not trigger warning/error for an http page with https css that includes http font";
|
||||
|
|
|
@ -19,19 +19,19 @@
|
|||
.securityUI;
|
||||
|
||||
var loadedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
|
||||
is(loadedMixedActive, false, "OK: Should not load mixed active content!");
|
||||
|
||||
var blockedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
|
||||
is(blockedMixedActive, false, "OK: Should not block mixed active content!");
|
||||
|
||||
var loadedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
|
||||
is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
|
||||
|
||||
var blockedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
|
||||
is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
|
||||
|
||||
var newValue = "Verifying MCB does not trigger warning/error for an http page ";
|
||||
|
|
|
@ -19,19 +19,19 @@
|
|||
.securityUI;
|
||||
|
||||
var loadedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
|
||||
is(loadedMixedActive, false, "OK: Should not load mixed active content!");
|
||||
|
||||
var blockedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
|
||||
is(blockedMixedActive, false, "OK: Should not block mixed active content!");
|
||||
|
||||
var loadedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
|
||||
is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
|
||||
|
||||
var blockedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
|
||||
!!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
|
||||
is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
|
||||
|
||||
var newValue = "Verifying MCB does not trigger warning/error for an http page with https css that includes http image";
|
||||
|
|
|
@ -514,8 +514,7 @@ function startAndCompleteDragOperation(aSource, aDest, aCallback) {
|
|||
synthesizeNativeMouseDrag(aDest, 10);
|
||||
synthesizeNativeMouseDrag(aDest);
|
||||
// Finally, release the drag and have it run the callback when done.
|
||||
synthesizeNativeMouseLUp(aDest);
|
||||
aCallback();
|
||||
synthesizeNativeMouseLUp(aDest).then(aCallback, Cu.reportError);
|
||||
} else if (isWindows) {
|
||||
// on Windows once the drag is initiated, Windows doesn't spin our
|
||||
// message loop at all, so with async event synthesization the async
|
||||
|
@ -527,8 +526,7 @@ function startAndCompleteDragOperation(aSource, aDest, aCallback) {
|
|||
// this only works for tests where aSource and aDest are sufficiently
|
||||
// far to trigger a drag, otherwise it may just end up doing a click.
|
||||
synthesizeNativeMouseLDown(aSource);
|
||||
synthesizeNativeMouseLUp(aDest);
|
||||
aCallback();
|
||||
synthesizeNativeMouseLUp(aDest).then(aCallback, Cu.reportError);
|
||||
} else if (isLinux) {
|
||||
// Start by pressing the left mouse button.
|
||||
synthesizeNativeMouseLDown(aSource);
|
||||
|
@ -564,8 +562,7 @@ function startAndCompleteDragOperation(aSource, aDest, aCallback) {
|
|||
aDest.removeEventListener("dragenter", onDragEnter);
|
||||
|
||||
// Finish the drop operation.
|
||||
synthesizeNativeMouseLUp(aDest, null);
|
||||
aCallback();
|
||||
synthesizeNativeMouseLUp(aDest).then(aCallback, Cu.reportError);
|
||||
});
|
||||
} else {
|
||||
throw "Unsupported platform";
|
||||
|
@ -621,7 +618,7 @@ function synthesizeNativeMouseLDown(aElement) {
|
|||
*/
|
||||
function synthesizeNativeMouseLUp(aElement) {
|
||||
let msg = isWindows ? 4 : (isMac ? 2 : 7);
|
||||
synthesizeNativeMouseEvent(aElement, msg);
|
||||
return synthesizeNativeMouseEvent(aElement, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -650,16 +647,25 @@ function synthesizeNativeMouseMove(aElement) {
|
|||
* @param aOffsetY The top offset that is added to the position (optional).
|
||||
*/
|
||||
function synthesizeNativeMouseEvent(aElement, aMsg, aOffsetX = 0, aOffsetY = 0) {
|
||||
let rect = aElement.getBoundingClientRect();
|
||||
let win = aElement.ownerDocument.defaultView;
|
||||
let x = aOffsetX + win.mozInnerScreenX + rect.left + rect.width / 2;
|
||||
let y = aOffsetY + win.mozInnerScreenY + rect.top + rect.height / 2;
|
||||
return new Promise((resolve, reject) => {
|
||||
let rect = aElement.getBoundingClientRect();
|
||||
let win = aElement.ownerDocument.defaultView;
|
||||
let x = aOffsetX + win.mozInnerScreenX + rect.left + rect.width / 2;
|
||||
let y = aOffsetY + win.mozInnerScreenY + rect.top + rect.height / 2;
|
||||
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let scale = utils.screenPixelsPerCSSPixel;
|
||||
utils.sendNativeMouseEvent(x * scale, y * scale, aMsg, 0, null);
|
||||
let scale = utils.screenPixelsPerCSSPixel;
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "mouseevent") {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
utils.sendNativeMouseEvent(x * scale, y * scale, aMsg, 0, null, observer);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -58,7 +58,7 @@ Bug 901519 - [app manager] data store for connections
|
|||
connection.port = 42;
|
||||
|
||||
is(host.textContent, "foobar", "host updated");
|
||||
is(port.textContent, 42, "port updated");
|
||||
is(port.textContent, "42", "port updated");
|
||||
|
||||
let been_through_connecting = false;
|
||||
let been_through_connected = false;
|
||||
|
|
|
@ -102,18 +102,18 @@ function addNewFieldInteger() {
|
|||
if (newField) {
|
||||
found = true;
|
||||
is(newField.type, "number", "Custom type is a number");
|
||||
is(newField.value, 1, "Custom integer value is correct");
|
||||
is(newField.value, "1", "Custom integer value is correct");
|
||||
}
|
||||
ok(found, "Found new integer field line");
|
||||
is(customName.value, "", "Custom integer name reset");
|
||||
is(customValue.value, 0, "Custom integer value reset");
|
||||
is(customValue.value, "", "Custom integer value reset");
|
||||
}
|
||||
|
||||
let editFieldInteger = Task.async(function*() {
|
||||
// Edit existing custom integer preference
|
||||
newField.value = 3;
|
||||
newField.click();
|
||||
is(newField.value, 3, "Custom integer existing value is correct");
|
||||
is(newField.value, "3", "Custom integer existing value is correct");
|
||||
|
||||
// Reset a custom field
|
||||
let resetBtn = doc.querySelector("#btn-new-integer-field");
|
||||
|
|
|
@ -233,7 +233,7 @@
|
|||
let defaults = Simulator.prototype._defaults;
|
||||
|
||||
for (let param in defaults) {
|
||||
is(form[param].value, defaults[param], "Default value for device " + param);
|
||||
is(form[param].value, String(defaults[param]), "Default value for device " + param);
|
||||
}
|
||||
|
||||
let width = 5000, height = 4000;
|
||||
|
@ -276,7 +276,7 @@
|
|||
// Test `device`.
|
||||
|
||||
for (let param in defaults) {
|
||||
is(form[param].value, defaults[param], "Default value for device " + param);
|
||||
is(form[param].value, String(defaults[param]), "Default value for device " + param);
|
||||
}
|
||||
|
||||
let devices = yield GetDevices();
|
||||
|
@ -286,8 +286,8 @@
|
|||
yield set(form.device, device.name);
|
||||
|
||||
is(form.device.value, device.name, "Device selector was changed");
|
||||
is(form.width.value, device.width, "New device width is correct");
|
||||
is(form.height.value, device.height, "New device height is correct");
|
||||
is(form.width.value, String(device.width), "New device width is correct");
|
||||
is(form.height.value, String(device.height), "New device height is correct");
|
||||
|
||||
params = yield runSimulator(1);
|
||||
|
||||
|
@ -300,7 +300,7 @@
|
|||
yield nextTick();
|
||||
|
||||
for (let param in defaults) {
|
||||
is(form[param].value, defaults[param], "Default value for device " + param);
|
||||
is(form[param].value, String(defaults[param]), "Default value for device " + param);
|
||||
}
|
||||
|
||||
// Uninstall the 2.0 addon and watch its Simulator object disappear.
|
||||
|
|
|
@ -77,7 +77,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=840488
|
|||
// We need to append 'name' to avoid running afoul of recursive frame detection.
|
||||
let frameURI = uri + "?name=" + name;
|
||||
navigateFrame(ifr, frameURI).then(function() {
|
||||
is(ifr.contentWindow.location, frameURI, "Successful load");
|
||||
is(String(ifr.contentWindow.location), frameURI, "Successful load");
|
||||
is(!!ifr.contentWindow.wrappedJSObject.gFiredOnload, expectOnload,
|
||||
"onload should only fire when scripts are enabled");
|
||||
deferred.resolve();
|
||||
|
|
|
@ -59,7 +59,7 @@ var nextTest =function() {
|
|||
}
|
||||
|
||||
var step1 =function() {
|
||||
window.is(testWindow.location, gTallRedBoxURI, "Ensure red page loaded.");
|
||||
window.is(String(testWindow.location), gTallRedBoxURI, "Ensure red page loaded.");
|
||||
|
||||
// Navigate down and up.
|
||||
is(testWindow.document.body.scrollTop, 0,
|
||||
|
@ -87,7 +87,7 @@ var step1 =function() {
|
|||
|
||||
|
||||
var step2 =function() {
|
||||
window.is(testWindow.location, gTallBlueBoxURI, "Ensure blue page loaded.");
|
||||
window.is(String(testWindow.location), gTallBlueBoxURI, "Ensure blue page loaded.");
|
||||
|
||||
// Scroll around a bit.
|
||||
is(testWindow.document.body.scrollTop, 0,
|
||||
|
@ -111,7 +111,7 @@ var step2 =function() {
|
|||
}
|
||||
|
||||
var step3 =function() {
|
||||
window.is(testWindow.location, gTallRedBoxURI,
|
||||
window.is(String(testWindow.location), gTallRedBoxURI,
|
||||
"Ensure red page restored from history.");
|
||||
|
||||
// Check we can still scroll with the keys.
|
||||
|
|
|
@ -229,7 +229,7 @@ function runTest() {
|
|||
size: 0,
|
||||
readyToApplyDownload: false
|
||||
};
|
||||
PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, 2, expected,
|
||||
PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, "2", expected,
|
||||
true, false, continueTest);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -58,24 +58,6 @@ function checkUninstallApp(aApp) {
|
|||
};
|
||||
}
|
||||
|
||||
function checkInstalledApp(aMiniManifestURL,
|
||||
aVersion,
|
||||
aExpectedApp,
|
||||
aLaunchable,
|
||||
aCb) {
|
||||
var req = navigator.mozApps.checkInstalled(aMiniManifestURL);
|
||||
req.onsuccess = function(evt) {
|
||||
ok(req.result, "The app is installed");
|
||||
|
||||
if (!req.result) {
|
||||
PackagedTestHelper.finish();
|
||||
}
|
||||
|
||||
PackagedTestHelper.checkAppState(evt.application, aVersion, aExpectedApp,
|
||||
aLaunchable, false, aCb);
|
||||
};
|
||||
}
|
||||
|
||||
var gIconData =
|
||||
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52" +
|
||||
"\x00\x00\x00\x0F\x00\x00\x00\x0F\x08\x03\x00\x00\x00\x0C\x08\x65" +
|
||||
|
@ -240,7 +222,7 @@ var steps = [
|
|||
size: 0,
|
||||
readyToApplyDownload: false
|
||||
};
|
||||
PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, 2, expected,
|
||||
PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, "2", expected,
|
||||
true, false, PackagedTestHelper.next);
|
||||
};
|
||||
};
|
||||
|
@ -327,7 +309,7 @@ var steps = [
|
|||
size: 0,
|
||||
readyToApplyDownload: alreadyCanceled
|
||||
};
|
||||
PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, 3, expected,
|
||||
PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, "3", expected,
|
||||
true, false, function() {});
|
||||
};
|
||||
|
||||
|
@ -345,7 +327,7 @@ var steps = [
|
|||
size: 0,
|
||||
readyToApplyDownload: false
|
||||
};
|
||||
PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, 3, expected,
|
||||
PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, "3", expected,
|
||||
true, false, PackagedTestHelper.next);
|
||||
}
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ var steps = [
|
|||
};
|
||||
PackagedTestHelper.gApp.ondownloadsuccess =
|
||||
checkLastAppState.bind(undefined, miniManifestURL, false, false,
|
||||
2, PackagedTestHelper.next);
|
||||
"2", PackagedTestHelper.next);
|
||||
};
|
||||
|
||||
var request = navigator.mozApps.installPackage(miniManifestURL);
|
||||
|
@ -232,7 +232,7 @@ var steps = [
|
|||
},
|
||||
function() {
|
||||
info("== TEST == Update packaged app");
|
||||
updateApp(true, 2, 3);
|
||||
updateApp(true, "2", "3");
|
||||
},
|
||||
function() {
|
||||
info("== TEST == Check that saved permissions were kept");
|
||||
|
@ -251,14 +251,14 @@ var steps = [
|
|||
},
|
||||
function() {
|
||||
info("== TEST == Check that name changes in an update are ignored");
|
||||
updateApp(true, 3, 4);
|
||||
updateApp(true, "3", "4");
|
||||
},
|
||||
function() {
|
||||
PackagedTestHelper.setAppVersion(5, PackagedTestHelper.next, true);
|
||||
},
|
||||
function() {
|
||||
info("== TEST == Update packaged app - same package");
|
||||
updateApp(false, 4, 4, true);
|
||||
updateApp(false, "4", "4", true);
|
||||
},
|
||||
function() {
|
||||
info("== TEST == Check for Update after getting the same package");
|
||||
|
|
|
@ -1835,18 +1835,6 @@ public:
|
|||
ReleaseIOThreadObjects() override
|
||||
{ }
|
||||
|
||||
virtual bool
|
||||
IsFileServiceUtilized() override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
IsTransactionServiceActivated() override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void
|
||||
WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
|
||||
nsIRunnable* aCallback) override
|
||||
|
@ -1855,7 +1843,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void
|
||||
ShutdownTransactionService() override
|
||||
ShutdownWorkThreads() override
|
||||
{ }
|
||||
|
||||
private:
|
||||
|
|
|
@ -792,7 +792,7 @@ AudioChannelService::WindowDestroyedEnumerator(AudioChannelAgent* aAgent,
|
|||
MOZ_ASSERT(data);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aAgent->Window());
|
||||
if (!window->IsInnerWindow()) {
|
||||
if (window && !window->IsInnerWindow()) {
|
||||
window = window->GetCurrentInnerWindow();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <map>
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "GonkPermission.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#endif // MOZ_WIDGET_GONK
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/PContentPermission.h"
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
|
@ -24,11 +26,82 @@
|
|||
#include "nsJSUtils.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsWeakPtr.h"
|
||||
|
||||
using mozilla::unused; // <snicker>
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla;
|
||||
|
||||
#define kVisibilityChange "visibilitychange"
|
||||
|
||||
NS_IMPL_ISUPPORTS(VisibilityChangeListener, nsIDOMEventListener)
|
||||
|
||||
VisibilityChangeListener::VisibilityChangeListener(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
mWindow = do_GetWeakReference(aWindow);
|
||||
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
|
||||
if (doc) {
|
||||
doc->AddSystemEventListener(NS_LITERAL_STRING(kVisibilityChange),
|
||||
/* listener */ this,
|
||||
/* use capture */ true,
|
||||
/* wants untrusted */ false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VisibilityChangeListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsAutoString type;
|
||||
aEvent->GetType(type);
|
||||
if (!type.EqualsLiteral(kVisibilityChange)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc =
|
||||
do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
|
||||
MOZ_ASSERT(doc);
|
||||
|
||||
if (mCallback) {
|
||||
mCallback->NotifyVisibility(!doc->Hidden());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
VisibilityChangeListener::RemoveListener()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<EventTarget> target = do_QueryInterface(window->GetExtantDoc());
|
||||
if (target) {
|
||||
target->RemoveSystemEventListener(NS_LITERAL_STRING(kVisibilityChange),
|
||||
/* listener */ this,
|
||||
/* use capture */ true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VisibilityChangeListener::SetCallback(nsIContentPermissionRequestCallback *aCallback)
|
||||
{
|
||||
mCallback = aCallback;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIContentPermissionRequestCallback>
|
||||
VisibilityChangeListener::GetCallback()
|
||||
{
|
||||
nsCOMPtr<nsIContentPermissionRequestCallback> callback = mCallback;
|
||||
return callback.forget();
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -49,6 +122,7 @@ class ContentPermissionRequestParent : public PContentPermissionRequestParent
|
|||
|
||||
private:
|
||||
virtual bool Recvprompt();
|
||||
virtual bool RecvNotifyVisibility(const bool& aIsVisible);
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
};
|
||||
|
||||
|
@ -79,6 +153,16 @@ ContentPermissionRequestParent::Recvprompt()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentPermissionRequestParent::RecvNotifyVisibility(const bool& aIsVisible)
|
||||
{
|
||||
if (!mProxy) {
|
||||
return false;
|
||||
}
|
||||
mProxy->NotifyVisibility(aIsVisible);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
|
@ -90,10 +174,10 @@ ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
|
|||
bool
|
||||
ContentPermissionRequestParent::IsBeingDestroyed()
|
||||
{
|
||||
// When TabParent::Destroy() is called, we are being destroyed. It's unsafe
|
||||
// to send out any message now.
|
||||
TabParent* tabParent = TabParent::GetFrom(Manager());
|
||||
return tabParent->IsDestroyed();
|
||||
// When ContentParent::MarkAsDead() is called, we are being destroyed.
|
||||
// It's unsafe to send out any message now.
|
||||
ContentParent* contentParent = static_cast<ContentParent*>(Manager());
|
||||
return !contentParent->IsAlive();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(ContentPermissionType, nsIContentPermissionType)
|
||||
|
@ -205,6 +289,13 @@ nsContentPermissionUtils::ConvertArrayToPermissionRequest(nsIArray* aSrcArray,
|
|||
return len;
|
||||
}
|
||||
|
||||
static std::map<PContentPermissionRequestParent*, TabId>&
|
||||
ContentPermissionRequestParentMap()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
static std::map<PContentPermissionRequestParent*, TabId> sPermissionRequestParentMap;
|
||||
return sPermissionRequestParentMap;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsContentPermissionUtils::CreatePermissionArray(const nsACString& aType,
|
||||
|
@ -225,9 +316,14 @@ nsContentPermissionUtils::CreatePermissionArray(const nsACString& aType,
|
|||
/* static */ PContentPermissionRequestParent*
|
||||
nsContentPermissionUtils::CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||
Element* element,
|
||||
const IPC::Principal& principal)
|
||||
const IPC::Principal& principal,
|
||||
const TabId& aTabId)
|
||||
{
|
||||
return new ContentPermissionRequestParent(aRequests, element, principal);
|
||||
PContentPermissionRequestParent* parent =
|
||||
new ContentPermissionRequestParent(aRequests, element, principal);
|
||||
ContentPermissionRequestParentMap()[parent] = aTabId;
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
|
@ -259,9 +355,11 @@ nsContentPermissionUtils::AskPermission(nsIContentPermissionRequest* aRequest, n
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
req->IPDLAddRef();
|
||||
child->SendPContentPermissionRequestConstructor(req,
|
||||
permArray,
|
||||
IPC::Principal(principal));
|
||||
ContentChild::GetSingleton()->SendPContentPermissionRequestConstructor(
|
||||
req,
|
||||
permArray,
|
||||
IPC::Principal(principal),
|
||||
child->GetTabId());
|
||||
|
||||
req->Sendprompt();
|
||||
return NS_OK;
|
||||
|
@ -276,9 +374,139 @@ nsContentPermissionUtils::AskPermission(nsIContentPermissionRequest* aRequest, n
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ nsTArray<PContentPermissionRequestParent*>
|
||||
nsContentPermissionUtils::GetContentPermissionRequestParentById(const TabId& aTabId)
|
||||
{
|
||||
nsTArray<PContentPermissionRequestParent*> parentArray;
|
||||
for (auto& it : ContentPermissionRequestParentMap()) {
|
||||
if (it.second == aTabId) {
|
||||
parentArray.AppendElement(it.first);
|
||||
}
|
||||
}
|
||||
|
||||
return Move(parentArray);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentPermissionUtils::NotifyRemoveContentPermissionRequestParent(
|
||||
PContentPermissionRequestParent* aParent)
|
||||
{
|
||||
auto it = ContentPermissionRequestParentMap().find(aParent);
|
||||
MOZ_ASSERT(it != ContentPermissionRequestParentMap().end());
|
||||
|
||||
ContentPermissionRequestParentMap().erase(it);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsContentPermissionRequester, nsIContentPermissionRequester)
|
||||
|
||||
nsContentPermissionRequester::nsContentPermissionRequester(nsPIDOMWindow* aWindow)
|
||||
: mWindow(aWindow)
|
||||
{
|
||||
mListener = new VisibilityChangeListener(mWindow);
|
||||
}
|
||||
|
||||
nsContentPermissionRequester::~nsContentPermissionRequester()
|
||||
{
|
||||
mListener->RemoveListener();
|
||||
mListener = nullptr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequester::GetVisibility(nsIContentPermissionRequestCallback* aCallback)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
if (!mWindow) {
|
||||
MOZ_ASSERT(false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docshell = mWindow->GetDocShell();
|
||||
if (!docshell) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool isActive = false;
|
||||
docshell->GetIsActive(&isActive);
|
||||
aCallback->NotifyVisibility(isActive);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequester::SetOnVisibilityChange(nsIContentPermissionRequestCallback* aCallback)
|
||||
{
|
||||
mListener->SetCallback(aCallback);
|
||||
|
||||
if (!aCallback) {
|
||||
mListener->RemoveListener();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequester::GetOnVisibilityChange(nsIContentPermissionRequestCallback** aCallback)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
nsCOMPtr<nsIContentPermissionRequestCallback> callback = mListener->GetCallback();
|
||||
callback.forget(aCallback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsContentPermissionRequestProxy::nsContentPermissionRequesterProxy,
|
||||
nsIContentPermissionRequester)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequestProxy::nsContentPermissionRequesterProxy
|
||||
::GetVisibility(nsIContentPermissionRequestCallback* aCallback)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
mGetCallback = aCallback;
|
||||
mWaitGettingResult = true;
|
||||
unused << mParent->SendGetVisibility();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequestProxy::nsContentPermissionRequesterProxy
|
||||
::SetOnVisibilityChange(nsIContentPermissionRequestCallback* aCallback)
|
||||
{
|
||||
mOnChangeCallback = aCallback;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequestProxy::nsContentPermissionRequesterProxy
|
||||
::GetOnVisibilityChange(nsIContentPermissionRequestCallback** aCallback)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
nsCOMPtr<nsIContentPermissionRequestCallback> callback = mOnChangeCallback;
|
||||
callback.forget(aCallback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsContentPermissionRequestProxy::nsContentPermissionRequesterProxy
|
||||
::NotifyVisibilityResult(const bool& aIsVisible)
|
||||
{
|
||||
if (mWaitGettingResult) {
|
||||
MOZ_ASSERT(mGetCallback);
|
||||
mWaitGettingResult = false;
|
||||
mGetCallback->NotifyVisibility(aIsVisible);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mOnChangeCallback) {
|
||||
mOnChangeCallback->NotifyVisibility(aIsVisible);
|
||||
}
|
||||
}
|
||||
|
||||
nsContentPermissionRequestProxy::nsContentPermissionRequestProxy()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsContentPermissionRequestProxy);
|
||||
|
@ -296,6 +524,7 @@ nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& request
|
|||
NS_ASSERTION(parent, "null parent");
|
||||
mParent = parent;
|
||||
mPermissionRequests = requests;
|
||||
mRequester = new nsContentPermissionRequesterProxy(mParent);
|
||||
|
||||
nsCOMPtr<nsIContentPermissionPrompt> prompt = do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
|
||||
if (!prompt) {
|
||||
|
@ -309,6 +538,7 @@ nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& request
|
|||
void
|
||||
nsContentPermissionRequestProxy::OnParentDestroyed()
|
||||
{
|
||||
mRequester = nullptr;
|
||||
mParent = nullptr;
|
||||
}
|
||||
|
||||
|
@ -397,12 +627,12 @@ nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
|
|||
if (mPermissionRequests[i].type().EqualsLiteral("audio-capture")) {
|
||||
GonkPermissionService::GetInstance()->addGrantInfo(
|
||||
"android.permission.RECORD_AUDIO",
|
||||
TabParent::GetFrom(mParent->Manager())->Manager()->AsContentParent()->Pid());
|
||||
static_cast<ContentParent*>(mParent->Manager())->Pid());
|
||||
}
|
||||
if (mPermissionRequests[i].type().EqualsLiteral("video-capture")) {
|
||||
GonkPermissionService::GetInstance()->addGrantInfo(
|
||||
"android.permission.CAMERA",
|
||||
TabParent::GetFrom(mParent->Manager())->Manager()->AsContentParent()->Pid());
|
||||
static_cast<ContentParent*>(mParent->Manager())->Pid());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -442,9 +672,27 @@ nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsContentPermissionRequestProxy::NotifyVisibility(const bool& aIsVisible)
|
||||
{
|
||||
MOZ_ASSERT(mRequester);
|
||||
|
||||
mRequester->NotifyVisibilityResult(aIsVisible);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequestProxy::GetRequester(nsIContentPermissionRequester** aRequester)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRequester);
|
||||
|
||||
nsRefPtr<nsContentPermissionRequesterProxy> requester = mRequester;
|
||||
requester.forget(aRequester);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// RemotePermissionRequest
|
||||
|
||||
NS_IMPL_ISUPPORTS0(RemotePermissionRequest)
|
||||
NS_IMPL_ISUPPORTS(RemotePermissionRequest, nsIContentPermissionRequestCallback);
|
||||
|
||||
RemotePermissionRequest::RemotePermissionRequest(
|
||||
nsIContentPermissionRequest* aRequest,
|
||||
|
@ -453,6 +701,8 @@ RemotePermissionRequest::RemotePermissionRequest(
|
|||
, mWindow(aWindow)
|
||||
, mIPCOpen(false)
|
||||
{
|
||||
mListener = new VisibilityChangeListener(mWindow);
|
||||
mListener->SetCallback(this);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -474,6 +724,9 @@ bool
|
|||
RemotePermissionRequest::Recv__delete__(const bool& aAllow,
|
||||
InfallibleTArray<PermissionChoice>&& aChoices)
|
||||
{
|
||||
mListener->RemoveListener();
|
||||
mListener = nullptr;
|
||||
|
||||
if (aAllow && mWindow->IsCurrentInnerWindow()) {
|
||||
// Use 'undefined' if no choice is provided.
|
||||
if (aChoices.IsEmpty()) {
|
||||
|
@ -507,3 +760,28 @@ RemotePermissionRequest::Recv__delete__(const bool& aAllow,
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
RemotePermissionRequest::RecvGetVisibility()
|
||||
{
|
||||
nsCOMPtr<nsIDocShell> docshell = mWindow->GetDocShell();
|
||||
if (!docshell) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isActive = false;
|
||||
docshell->GetIsActive(&isActive);
|
||||
unused << SendNotifyVisibility(isActive);
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RemotePermissionRequest::NotifyVisibility(bool isVisible)
|
||||
{
|
||||
if (!mIPCOpen) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
unused << SendNotifyVisibility(isVisible);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#include "nsTArray.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "mozilla/dom/PContentPermissionRequestChild.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
||||
// Microsoft's API Name hackery sucks
|
||||
// XXXbz Doing this in a header is a gigantic footgun. See
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=932421#c3 for why.
|
||||
|
@ -27,6 +30,25 @@ namespace IPC {
|
|||
class Principal;
|
||||
}
|
||||
|
||||
class VisibilityChangeListener final : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
explicit VisibilityChangeListener(nsPIDOMWindow* aWindow);
|
||||
|
||||
void RemoveListener();
|
||||
void SetCallback(nsIContentPermissionRequestCallback* aCallback);
|
||||
already_AddRefed<nsIContentPermissionRequestCallback> GetCallback();
|
||||
|
||||
private:
|
||||
virtual ~VisibilityChangeListener() {}
|
||||
|
||||
nsWeakPtr mWindow;
|
||||
nsCOMPtr<nsIContentPermissionRequestCallback> mCallback;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -73,44 +95,92 @@ public:
|
|||
static PContentPermissionRequestParent*
|
||||
CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
|
||||
Element* element,
|
||||
const IPC::Principal& principal);
|
||||
const IPC::Principal& principal,
|
||||
const TabId& aTabId);
|
||||
|
||||
static nsresult
|
||||
AskPermission(nsIContentPermissionRequest* aRequest, nsPIDOMWindow* aWindow);
|
||||
|
||||
static nsTArray<PContentPermissionRequestParent*>
|
||||
GetContentPermissionRequestParentById(const TabId& aTabId);
|
||||
|
||||
static void
|
||||
NotifyRemoveContentPermissionRequestParent(PContentPermissionRequestParent* aParent);
|
||||
};
|
||||
|
||||
class nsContentPermissionRequester final : public nsIContentPermissionRequester
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPERMISSIONREQUESTER
|
||||
|
||||
explicit nsContentPermissionRequester(nsPIDOMWindow* aWindow);
|
||||
|
||||
private:
|
||||
virtual ~nsContentPermissionRequester();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
nsRefPtr<VisibilityChangeListener> mListener;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
using mozilla::dom::ContentPermissionRequestParent;
|
||||
|
||||
class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
|
||||
{
|
||||
public:
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPERMISSIONREQUEST
|
||||
|
||||
nsContentPermissionRequestProxy();
|
||||
|
||||
nsresult Init(const nsTArray<mozilla::dom::PermissionRequest>& requests,
|
||||
mozilla::dom::ContentPermissionRequestParent* parent);
|
||||
ContentPermissionRequestParent* parent);
|
||||
|
||||
void OnParentDestroyed();
|
||||
|
||||
private:
|
||||
void NotifyVisibility(const bool& aIsVisible);
|
||||
|
||||
private:
|
||||
class nsContentPermissionRequesterProxy final : public nsIContentPermissionRequester {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPERMISSIONREQUESTER
|
||||
|
||||
explicit nsContentPermissionRequesterProxy(ContentPermissionRequestParent* aParent)
|
||||
: mParent(aParent)
|
||||
, mWaitGettingResult(false) {}
|
||||
|
||||
void NotifyVisibilityResult(const bool& aIsVisible);
|
||||
|
||||
private:
|
||||
virtual ~nsContentPermissionRequesterProxy() {}
|
||||
|
||||
ContentPermissionRequestParent* mParent;
|
||||
bool mWaitGettingResult;
|
||||
nsCOMPtr<nsIContentPermissionRequestCallback> mGetCallback;
|
||||
nsCOMPtr<nsIContentPermissionRequestCallback> mOnChangeCallback;
|
||||
};
|
||||
|
||||
virtual ~nsContentPermissionRequestProxy();
|
||||
|
||||
// Non-owning pointer to the ContentPermissionRequestParent object which owns this proxy.
|
||||
mozilla::dom::ContentPermissionRequestParent* mParent;
|
||||
ContentPermissionRequestParent* mParent;
|
||||
nsTArray<mozilla::dom::PermissionRequest> mPermissionRequests;
|
||||
nsRefPtr<nsContentPermissionRequesterProxy> mRequester;
|
||||
};
|
||||
|
||||
/**
|
||||
* RemotePermissionRequest will send a prompt ipdl request to b2g process.
|
||||
*/
|
||||
class RemotePermissionRequest final : public nsISupports
|
||||
class RemotePermissionRequest final : public nsIContentPermissionRequestCallback
|
||||
, public mozilla::dom::PContentPermissionRequestChild
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPERMISSIONREQUESTCALLBACK
|
||||
|
||||
RemotePermissionRequest(nsIContentPermissionRequest* aRequest,
|
||||
nsPIDOMWindow* aWindow);
|
||||
|
@ -119,6 +189,8 @@ public:
|
|||
virtual bool Recv__delete__(const bool &aAllow,
|
||||
InfallibleTArray<PermissionChoice>&& aChoices) override;
|
||||
|
||||
virtual bool RecvGetVisibility() override;
|
||||
|
||||
void IPDLAddRef()
|
||||
{
|
||||
mIPCOpen = true;
|
||||
|
@ -143,6 +215,7 @@ private:
|
|||
nsCOMPtr<nsIContentPermissionRequest> mRequest;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
bool mIPCOpen;
|
||||
nsRefPtr<VisibilityChangeListener> mListener;
|
||||
};
|
||||
|
||||
#endif // nsContentPermissionHelper_h
|
||||
|
|
|
@ -1301,7 +1301,8 @@ nsDOMWindowUtils::SendNativeKeyEvent(int32_t aNativeKeyboardLayout,
|
|||
int32_t aNativeKeyCode,
|
||||
int32_t aModifiers,
|
||||
const nsAString& aCharacters,
|
||||
const nsAString& aUnmodifiedCharacters)
|
||||
const nsAString& aUnmodifiedCharacters,
|
||||
nsIObserver* aObserver)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
|
||||
|
@ -1310,8 +1311,11 @@ nsDOMWindowUtils::SendNativeKeyEvent(int32_t aNativeKeyboardLayout,
|
|||
if (!widget)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return widget->SynthesizeNativeKeyEvent(aNativeKeyboardLayout, aNativeKeyCode,
|
||||
aModifiers, aCharacters, aUnmodifiedCharacters);
|
||||
NS_DispatchToMainThread(NS_NewRunnableMethodWithArgs
|
||||
<int32_t, int32_t, uint32_t, nsString, nsString, nsIObserver*>
|
||||
(widget, &nsIWidget::SynthesizeNativeKeyEvent, aNativeKeyboardLayout,
|
||||
aNativeKeyCode, aModifiers, aCharacters, aUnmodifiedCharacters, aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1319,7 +1323,8 @@ nsDOMWindowUtils::SendNativeMouseEvent(int32_t aScreenX,
|
|||
int32_t aScreenY,
|
||||
int32_t aNativeMessage,
|
||||
int32_t aModifierFlags,
|
||||
nsIDOMElement* aElement)
|
||||
nsIDOMElement* aElement,
|
||||
nsIObserver* aObserver)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
|
||||
|
@ -1328,8 +1333,12 @@ nsDOMWindowUtils::SendNativeMouseEvent(int32_t aScreenX,
|
|||
if (!widget)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return widget->SynthesizeNativeMouseEvent(LayoutDeviceIntPoint(aScreenX, aScreenY),
|
||||
aNativeMessage, aModifierFlags);
|
||||
NS_DispatchToMainThread(NS_NewRunnableMethodWithArgs
|
||||
<LayoutDeviceIntPoint, int32_t, int32_t, nsIObserver*>
|
||||
(widget, &nsIWidget::SynthesizeNativeMouseEvent,
|
||||
LayoutDeviceIntPoint(aScreenX, aScreenY), aNativeMessage, aModifierFlags,
|
||||
aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1341,7 +1350,8 @@ nsDOMWindowUtils::SendNativeMouseScrollEvent(int32_t aScreenX,
|
|||
double aDeltaZ,
|
||||
uint32_t aModifierFlags,
|
||||
uint32_t aAdditionalFlags,
|
||||
nsIDOMElement* aElement)
|
||||
nsIDOMElement* aElement,
|
||||
nsIObserver* aObserver)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
|
||||
|
@ -1351,12 +1361,12 @@ nsDOMWindowUtils::SendNativeMouseScrollEvent(int32_t aScreenX,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return widget->SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint(aScreenX,
|
||||
aScreenY),
|
||||
aNativeMessage,
|
||||
aDeltaX, aDeltaY, aDeltaZ,
|
||||
aModifierFlags,
|
||||
aAdditionalFlags);
|
||||
NS_DispatchToMainThread(NS_NewRunnableMethodWithArgs
|
||||
<mozilla::LayoutDeviceIntPoint, uint32_t, double, double, double, uint32_t, uint32_t, nsIObserver*>
|
||||
(widget, &nsIWidget::SynthesizeNativeMouseScrollEvent,
|
||||
LayoutDeviceIntPoint(aScreenX, aScreenY), aNativeMessage, aDeltaX, aDeltaY,
|
||||
aDeltaZ, aModifierFlags, aAdditionalFlags, aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1365,7 +1375,8 @@ nsDOMWindowUtils::SendNativeTouchPoint(uint32_t aPointerId,
|
|||
int32_t aScreenX,
|
||||
int32_t aScreenY,
|
||||
double aPressure,
|
||||
uint32_t aOrientation)
|
||||
uint32_t aOrientation,
|
||||
nsIObserver* aObserver)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
|
||||
|
@ -1378,16 +1389,19 @@ nsDOMWindowUtils::SendNativeTouchPoint(uint32_t aPointerId,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return widget->SynthesizeNativeTouchPoint(aPointerId,
|
||||
(nsIWidget::TouchPointerState)aTouchState,
|
||||
nsIntPoint(aScreenX, aScreenY),
|
||||
aPressure, aOrientation);
|
||||
NS_DispatchToMainThread(NS_NewRunnableMethodWithArgs
|
||||
<uint32_t, nsIWidget::TouchPointerState, nsIntPoint, double, uint32_t, nsIObserver*>
|
||||
(widget, &nsIWidget::SynthesizeNativeTouchPoint, aPointerId,
|
||||
(nsIWidget::TouchPointerState)aTouchState, nsIntPoint(aScreenX, aScreenY),
|
||||
aPressure, aOrientation, aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SendNativeTouchTap(int32_t aScreenX,
|
||||
int32_t aScreenY,
|
||||
bool aLongTap)
|
||||
bool aLongTap,
|
||||
nsIObserver* aObserver)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
|
||||
|
@ -1395,11 +1409,16 @@ nsDOMWindowUtils::SendNativeTouchTap(int32_t aScreenX,
|
|||
if (!widget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return widget->SynthesizeNativeTouchTap(nsIntPoint(aScreenX, aScreenY), aLongTap);
|
||||
|
||||
NS_DispatchToMainThread(NS_NewRunnableMethodWithArgs
|
||||
<nsIntPoint, bool, nsIObserver*>
|
||||
(widget, &nsIWidget::SynthesizeNativeTouchTap,
|
||||
nsIntPoint(aScreenX, aScreenY), aLongTap, aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::ClearNativeTouchSequence()
|
||||
nsDOMWindowUtils::ClearNativeTouchSequence(nsIObserver* aObserver)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
|
||||
|
@ -1407,7 +1426,10 @@ nsDOMWindowUtils::ClearNativeTouchSequence()
|
|||
if (!widget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return widget->ClearNativeTouchSequence();
|
||||
|
||||
NS_DispatchToMainThread(NS_NewRunnableMethodWithArgs<nsIObserver*>
|
||||
(widget, &nsIWidget::ClearNativeTouchSequence, aObserver));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -12009,7 +12009,13 @@ public:
|
|||
nsPointerLockPermissionRequest(Element* aElement, bool aUserInputOrChromeCaller)
|
||||
: mElement(do_GetWeakReference(aElement)),
|
||||
mDocument(do_GetWeakReference(aElement->OwnerDoc())),
|
||||
mUserInputOrChromeCaller(aUserInputOrChromeCaller) {}
|
||||
mUserInputOrChromeCaller(aUserInputOrChromeCaller)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
||||
if (doc) {
|
||||
mRequester = new nsContentPermissionRequester(doc->GetInnerWindow());
|
||||
}
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSICONTENTPERMISSIONREQUEST
|
||||
|
@ -12069,6 +12075,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual ~nsPointerLockPermissionRequest() {}
|
||||
nsCOMPtr<nsIContentPermissionRequester> mRequester;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsPointerLockPermissionRequest,
|
||||
|
@ -12174,6 +12181,16 @@ nsPointerLockPermissionRequest::Allow(JS::HandleValue aChoices)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPointerLockPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRequester);
|
||||
|
||||
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
|
||||
requester.forget(aRequester);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::SetApprovedForFullscreen(bool aIsApproved)
|
||||
{
|
||||
|
|
|
@ -60,7 +60,7 @@ window.checkResults = function(reportObj) {
|
|||
is(cspReport["script-sample"], "\n var foo = \"propEscFoo\";\n var bar...",
|
||||
"Incorrect script-sample");
|
||||
|
||||
is(cspReport["line-number"], "7", "Incorrect line-number");
|
||||
is(cspReport["line-number"], 7, "Incorrect line-number");
|
||||
}
|
||||
|
||||
// This is used to watch requests go out so we can see if the report is
|
||||
|
|
|
@ -25,8 +25,8 @@ function doe3() {
|
|||
}
|
||||
|
||||
function doe4() {
|
||||
opener.is(window.frames[0].location, url1, "History.go(-1) didn't work?");
|
||||
opener.is(window.frames[1].location, "about:blank",
|
||||
opener.is(String(window.frames[0].location), url1, "History.go(-1) didn't work?");
|
||||
opener.is(String(window.frames[1].location), "about:blank",
|
||||
"History.go(-1) didn't work?");
|
||||
close();
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ function doe4() {
|
|||
}
|
||||
|
||||
function doe5() {
|
||||
opener.is(win0.location, url1, "History.go(-1) didn't work?");
|
||||
opener.is(String(win0.location), url1, "History.go(-1) didn't work?");
|
||||
close();
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -55,7 +55,7 @@ function testFile(file, contents, test) {
|
|||
file.type ? file.type : null,
|
||||
"request content-type in XMLHttpRequest send of " + test);
|
||||
is(event.target.getResponseHeader("Result-Content-Length"),
|
||||
file.size,
|
||||
String(file.size),
|
||||
"request content-length in XMLHttpRequest send of " + test);
|
||||
};
|
||||
xhr.addEventListener("load",
|
||||
|
|
|
@ -694,7 +694,7 @@ function runTest() {
|
|||
is(res.responseHeaders[header], null,
|
||||
"|xhr.getResponseHeader()|wrong response header (" + header + ") in test for " +
|
||||
test.toSource());
|
||||
is(res.allResponseHeaders[header], null,
|
||||
is(res.allResponseHeaders[header], undefined,
|
||||
"|xhr.getAllResponseHeaderss()|wrong response header (" + header + ") in test for " +
|
||||
test.toSource());
|
||||
}
|
||||
|
|
|
@ -232,7 +232,9 @@ try {
|
|||
}
|
||||
|
||||
if (test.resContentLength) {
|
||||
is(xhr.getResponseHeader("Result-Content-Length"), test.resContentLength, "Wrong Content-Length sent");
|
||||
is(xhr.getResponseHeader("Result-Content-Length"),
|
||||
String(test.resContentLength),
|
||||
"Wrong Content-Length sent");
|
||||
}
|
||||
|
||||
if (test.resType == "arraybuffer") {
|
||||
|
|
|
@ -23,10 +23,10 @@ function runTest() {
|
|||
|
||||
is(utils.audioVolume, 1.0, "By default utils.audioVolume is 1.0");
|
||||
utils.audioVolume = 0.4;
|
||||
is(utils.audioVolume.toFixed(2), 0.4, "utils.audioVolume is ok");
|
||||
is(utils.audioVolume.toFixed(2), "0.40", "utils.audioVolume is ok");
|
||||
utils.audioMuted = true;
|
||||
is(utils.audioMuted, true, "utils.audioMuted is true");
|
||||
is(utils.audioVolume.toFixed(2), 0.4, "utils.audioVolume is ok");
|
||||
is(utils.audioVolume.toFixed(2), "0.40", "utils.audioVolume is ok");
|
||||
utils.audioMuted = false;
|
||||
|
||||
utils.audioVolume = 2.0;
|
||||
|
@ -60,10 +60,10 @@ function runTest() {
|
|||
|
||||
is(utils.audioVolume, 1.0, "By default utils.audioVolume is 1.0");
|
||||
utils.audioVolume = 0.4;
|
||||
is(utils.audioVolume.toFixed(2), 0.4, "utils.audioVolume is ok");
|
||||
is(utils.audioVolume.toFixed(2), "0.40", "utils.audioVolume is ok");
|
||||
utils.audioMuted = true;
|
||||
is(utils.audioMuted, true, "utils.audioMuted is true");
|
||||
is(utils.audioVolume.toFixed(2), 0.4, "utils.audioVolume is ok");
|
||||
is(utils.audioVolume.toFixed(2), "0.40", "utils.audioVolume is ok");
|
||||
utils.audioMuted = false;
|
||||
|
||||
utils.audioVolume = 2.0;
|
||||
|
|
|
@ -25,9 +25,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=346485
|
|||
* This test is testing DOMSettableTokenList used by the output element.
|
||||
*/
|
||||
|
||||
function checkHtmlFor(htmlFor, list, msg) {
|
||||
var length = htmlFor.length;
|
||||
is(length, list.length, htmlFor + ": incorrect htmlFor length (" + msg + ")");
|
||||
for (var i = 0; i < length; ++i) {
|
||||
is(htmlFor[i], list[i], htmlFor + ": wrong element at " + i + " (" + msg + ")");
|
||||
}
|
||||
}
|
||||
|
||||
var o = document.getElementById('o');
|
||||
|
||||
is(o.htmlFor, 'a b',
|
||||
is(String(o.htmlFor), 'a b',
|
||||
"htmlFor IDL attribute should reflect for content attribute");
|
||||
|
||||
is(o.htmlFor.value, 'a b',
|
||||
|
@ -42,32 +50,25 @@ is(o.htmlFor.item(0), 'a', "First item is 'a' token'");
|
|||
is(o.htmlFor.item(42), null, "Out-of-range should return null");
|
||||
|
||||
o.htmlFor.add('c');
|
||||
is(o.htmlFor, 'a b c', "'c' token should have been added");
|
||||
is(o.htmlFor.length, 3, "Size should be '3'");
|
||||
checkHtmlFor(o.htmlFor, ['a', 'b', 'c'], "'c' token should have been added");
|
||||
|
||||
o.htmlFor.add('a');
|
||||
is(o.htmlFor, 'a b c', "Nothing should have changed");
|
||||
is(o.htmlFor.length, 3, "Size should be '3'");
|
||||
checkHtmlFor(o.htmlFor, ['a', 'b', 'c'], "Nothing should have changed");
|
||||
|
||||
o.htmlFor.remove('a');
|
||||
is(o.htmlFor, 'b c', "'a' token should have been removed");
|
||||
is(o.htmlFor.length, 2, "Size should be '2'");
|
||||
checkHtmlFor(o.htmlFor, ['b', 'c'], "'a' token should have been removed");
|
||||
|
||||
o.htmlFor.remove('d');
|
||||
is(o.htmlFor, 'b c', "Nothing should have been removed");
|
||||
is(o.htmlFor.length, 2, "Size should be '2'");
|
||||
checkHtmlFor(o.htmlFor, ['b', 'c'], "Nothing should have been removed");
|
||||
|
||||
o.htmlFor.toggle('a');
|
||||
is(o.htmlFor, 'b c a', "'a' token should have been added");
|
||||
is(o.htmlFor.length, 3, "Size should be '3'");
|
||||
checkHtmlFor(o.htmlFor, ['b', 'c', 'a'], "'a' token should have been added");
|
||||
|
||||
o.htmlFor.toggle('b');
|
||||
is(o.htmlFor, 'c a', "Nothing should have changed");
|
||||
is(o.htmlFor.length, 2, "Size should be '2'");
|
||||
checkHtmlFor(o.htmlFor, ['c', 'a'], "Nothing should have changed");
|
||||
|
||||
o.htmlFor.value = "foo bar";
|
||||
is(o.htmlFor, 'foo bar', "The underlying string should have changed");
|
||||
is(o.htmlFor.length, 2, "Size should be '2'");
|
||||
checkHtmlFor(o.htmlFor, ['foo', 'bar'], "The underlying string should have changed");
|
||||
ok(o.htmlFor.contains('foo'), "It should contain 'foo'");
|
||||
|
||||
</script>
|
||||
|
|
|
@ -26,7 +26,7 @@ function done() {
|
|||
nodes = document.getElementsByTagName('span');
|
||||
is(nodes.length, 3, "wrong length");
|
||||
for (i = 0; i < nodes.length; ++i) {
|
||||
is(nodes[i].textContent, i+1, "wrong order");
|
||||
is(nodes[i].textContent, String(i + 1), "wrong order");
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
|
|
@ -30,13 +30,13 @@ function innerLoaded(inner) {
|
|||
// Here, we're being called through inner's onload handler, so our referrer
|
||||
// should be inner's URL.
|
||||
var referrer = inner.doXHR();
|
||||
is (referrer, inner.document.location, 'Expected inner frame location');
|
||||
is (referrer, String(inner.document.location), 'Expected inner frame location');
|
||||
|
||||
// Now change the location of the inner frame. This should be reflected in
|
||||
// the XHR's referrer.
|
||||
inner.history.pushState('', '', Math.random());
|
||||
referrer = inner.doXHR();
|
||||
is (referrer, inner.document.location, 'Expected inner frame location after pushstate');
|
||||
is (referrer, String(inner.document.location), 'Expected inner frame location after pushstate');
|
||||
|
||||
innerFinishedLoading = true;
|
||||
}
|
||||
|
@ -50,11 +50,11 @@ function callXHR() {
|
|||
if (innerFinishedLoading && dataWindowFinishedLoading) {
|
||||
var inner = document.getElementById('iframe').contentWindow;
|
||||
var referrer = inner.doXHR();
|
||||
is (referrer, inner.document.location,
|
||||
is (referrer, String(inner.document.location),
|
||||
'Expected inner frame location when called from outer frame.');
|
||||
|
||||
var referrer = inner.doXHR(new XMLHttpRequest());
|
||||
is (referrer, document.location,
|
||||
is (referrer, String(document.location),
|
||||
"Expected outer frame location when called with outer's XHR object.");
|
||||
|
||||
// Now do a request within the inner window using an XMLHttpRequest
|
||||
|
@ -62,7 +62,7 @@ function callXHR() {
|
|||
// data: URI.
|
||||
var dataWindow = document.getElementById('dataWindow').contentWindow;
|
||||
var referrer = inner.doXHR(dataWindow.getXHRObject());
|
||||
is (referrer, document.location,
|
||||
is (referrer, String(document.location),
|
||||
"Expected outer frame location when called with data's XHR object.");
|
||||
|
||||
// Now do that test again, but after having changed the outer window's URI.
|
||||
|
@ -71,7 +71,7 @@ function callXHR() {
|
|||
history.replaceState('', '', Math.random());
|
||||
|
||||
var referrer = inner.doXHR(dataWindow.getXHRObject());
|
||||
todo_is (referrer, document.location,
|
||||
todo_is (referrer, String(document.location),
|
||||
"Expected outer frame location when called with data's XHR object " +
|
||||
"after replaceState.");
|
||||
|
||||
|
|
|
@ -43,9 +43,9 @@
|
|||
* Init & destroy.
|
||||
*/
|
||||
function initDOMRequestHelperTest(aMessages) {
|
||||
is(dummy._requests, undefined, "Request is undefined");
|
||||
is_loosely(dummy._requests, undefined, "Request is undefined");
|
||||
is(dummy._messages, undefined, "Messages is undefined");
|
||||
is(dummy._window, undefined, "Window is undefined");
|
||||
is_loosely(dummy._window, undefined, "Window is undefined");
|
||||
|
||||
dummy.initDOMRequestHelper(window, aMessages);
|
||||
|
||||
|
@ -59,9 +59,9 @@
|
|||
function destroyDOMRequestHelperTest() {
|
||||
dummy.destroyDOMRequestHelper();
|
||||
|
||||
is(dummy._requests, undefined, "Request is undefined");
|
||||
is_loosely(dummy._requests, undefined, "Request is undefined");
|
||||
is(dummy._messages, undefined, "Messages is undefined");
|
||||
is(dummy._window, undefined, "Window is undefined");
|
||||
is_loosely(dummy._window, undefined, "Window is undefined");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -388,7 +388,7 @@
|
|||
is(req, req_, "Got correct request");
|
||||
dummy.removeRequest(id);
|
||||
req = dummy.getRequest(id);
|
||||
is(req, null, "No request");
|
||||
is(req, undefined, "No request");
|
||||
next();
|
||||
},
|
||||
function() {
|
||||
|
|
|
@ -311,7 +311,7 @@
|
|||
url = new URL("http://localhost/");
|
||||
url.host = "[2001::1]:30";
|
||||
is(url.hostname, "[2001::1]", "IPv6 hostname");
|
||||
is(url.port, 30, "Port");
|
||||
is(url.port, "30", "Port");
|
||||
is(url.host, "[2001::1]:30", "IPv6 host");
|
||||
|
||||
url = new URL("http://localhost/");
|
||||
|
|
|
@ -24,14 +24,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=930450
|
|||
<script type="application/javascript">
|
||||
|
||||
var url = new URL('http://www.example.com:8080');
|
||||
is(url.port, 8080, 'URL.port is 8080');
|
||||
is(url.port, '8080', 'URL.port is 8080');
|
||||
url.port = '';
|
||||
ise(url.port, '', 'URL.port is \'\'');
|
||||
url.port = 0;
|
||||
ise(url.port, '0', 'URL.port is 0');
|
||||
|
||||
var link = document.getElementById("link");
|
||||
is(link.port, 8080, 'URL.port is 8080');
|
||||
is(link.port, '8080', 'URL.port is 8080');
|
||||
link.port = '';
|
||||
is(link.href, 'http://www.example.com/', "link.href matches");
|
||||
ise(link.port, '', 'URL.port is \'\'');
|
||||
|
@ -40,7 +40,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=930450
|
|||
ise(link.port, '0', 'URL.port is 0');
|
||||
|
||||
var area = document.getElementById("area");
|
||||
is(area.port, 8080, 'URL.port is 8080');
|
||||
is(area.port, '8080', 'URL.port is 8080');
|
||||
area.port = '';
|
||||
is(area.href, 'http://www.example.com/', "area.href matches");
|
||||
ise(area.port, '', 'URL.port is \'\'');
|
||||
|
|
|
@ -6662,6 +6662,22 @@ class CGPerSignatureCall(CGThing):
|
|||
return false;
|
||||
}
|
||||
""")))
|
||||
|
||||
if idlNode.getExtendedAttribute("Deprecated"):
|
||||
cgThings.append(CGGeneric(dedent(
|
||||
"""
|
||||
{
|
||||
GlobalObject global(cx, obj);
|
||||
if (global.Failed()) {
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(global.GetAsSupports());
|
||||
if (pWindow && pWindow->GetExtantDoc()) {
|
||||
pWindow->GetExtantDoc()->WarnOnceAbout(nsIDocument::e%s);
|
||||
}
|
||||
}
|
||||
""" % idlNode.getExtendedAttribute("Deprecated")[0])))
|
||||
|
||||
lenientFloatCode = None
|
||||
if idlNode.getExtendedAttribute('LenientFloat') is not None:
|
||||
if setter:
|
||||
|
@ -12405,6 +12421,12 @@ class CGBindingRoot(CGThing):
|
|||
iface = desc.interface
|
||||
return any(m.getExtendedAttribute("Pref") for m in iface.members + [iface])
|
||||
|
||||
def descriptorDeprecated(desc):
|
||||
iface = desc.interface
|
||||
return any(m.getExtendedAttribute("Deprecated") for m in iface.members + [iface])
|
||||
|
||||
bindingHeaders["nsIDocument.h"] = any(
|
||||
descriptorDeprecated(d) for d in descriptors)
|
||||
bindingHeaders["mozilla/Preferences.h"] = any(
|
||||
descriptorRequiresPreferences(d) for d in descriptors)
|
||||
bindingHeaders["mozilla/dom/DOMJSProxyHandler.h"] = any(
|
||||
|
|
|
@ -3504,6 +3504,7 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
[attr.location, self.location])
|
||||
self._setDependsOn(attr.value())
|
||||
elif (identifier == "Pref" or
|
||||
identifier == "Deprecated" or
|
||||
identifier == "SetterThrows" or
|
||||
identifier == "Throws" or
|
||||
identifier == "GetterThrows" or
|
||||
|
@ -4139,6 +4140,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
identifier == "ChromeOnly" or
|
||||
identifier == "UnsafeInPrerendering" or
|
||||
identifier == "Pref" or
|
||||
identifier == "Deprecated" or
|
||||
identifier == "Func" or
|
||||
identifier == "AvailableIn" or
|
||||
identifier == "CheckPermissions" or
|
||||
|
|
|
@ -737,12 +737,24 @@ public:
|
|||
already_AddRefed<TestInterface> ExerciseTypedefInterfaces2(TestInterface*);
|
||||
void ExerciseTypedefInterfaces3(TestInterface&);
|
||||
|
||||
// Deprecated methods and attributes
|
||||
int8_t DeprecatedAttribute();
|
||||
int8_t SetDeprecatedAttribute(int8_t);
|
||||
int8_t DeprecatedMethod();
|
||||
int8_t DeprecatedMethodWithContext(JSContext*, JS::Value);
|
||||
|
||||
// Static methods and attributes
|
||||
static void StaticMethod(const GlobalObject&, bool);
|
||||
static void StaticMethodWithContext(const GlobalObject&, JS::Value);
|
||||
static bool StaticAttribute(const GlobalObject&);
|
||||
static void SetStaticAttribute(const GlobalObject&, bool);
|
||||
|
||||
// Deprecated static methods and attributes
|
||||
static int8_t StaticDeprecatedAttribute(const GlobalObject&);
|
||||
static int8_t SetStaticDeprecatedAttribute(const GlobalObject&, int8_t);
|
||||
static int8_t StaticDeprecatedMethod(const GlobalObject&);
|
||||
static int8_t StaticDeprecatedMethodWithContext(const GlobalObject&, JS::Value);
|
||||
|
||||
// Overload resolution tests
|
||||
bool Overload1(TestInterface&);
|
||||
TestInterface* Overload1(const nsAString&, TestInterface&);
|
||||
|
|
|
@ -725,11 +725,27 @@ interface TestInterface {
|
|||
AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
|
||||
void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
|
||||
|
||||
// Deprecated methods and attributes
|
||||
[Deprecated="GetAttributeNode"]
|
||||
attribute byte deprecatedAttribute;
|
||||
[Deprecated="GetAttributeNode"]
|
||||
byte deprecatedMethod();
|
||||
[Deprecated="GetAttributeNode"]
|
||||
byte deprecatedMethodWithContext(any arg);
|
||||
|
||||
// Static methods and attributes
|
||||
static attribute boolean staticAttribute;
|
||||
static void staticMethod(boolean arg);
|
||||
static void staticMethodWithContext(any arg);
|
||||
|
||||
// Deprecated static methods and attributes
|
||||
[Deprecated="GetAttributeNode"]
|
||||
static attribute byte staticDeprecatedAttribute;
|
||||
[Deprecated="GetAttributeNode"]
|
||||
static void staticDeprecatedMethod();
|
||||
[Deprecated="GetAttributeNode"]
|
||||
static void staticDeprecatedMethodWithContext(any arg);
|
||||
|
||||
// Overload resolution tests
|
||||
//void overload1(DOMString... strs);
|
||||
boolean overload1(TestInterface arg);
|
||||
|
|
|
@ -589,11 +589,27 @@ interface TestExampleInterface {
|
|||
AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
|
||||
void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
|
||||
|
||||
// Deprecated methods and attributes
|
||||
[Deprecated="GetAttributeNode"]
|
||||
attribute boolean deprecatedAttribute;
|
||||
[Deprecated="GetAttributeNode"]
|
||||
void deprecatedMethod(boolean arg);
|
||||
[Deprecated="GetAttributeNode"]
|
||||
void deprecatedMethodWithContext(any arg);
|
||||
|
||||
// Static methods and attributes
|
||||
static attribute boolean staticAttribute;
|
||||
static void staticMethod(boolean arg);
|
||||
static void staticMethodWithContext(any arg);
|
||||
|
||||
// Deprecated methods and attributes;
|
||||
[Deprecated="GetAttributeNode"]
|
||||
static attribute boolean staticDeprecatedAttribute;
|
||||
[Deprecated="GetAttributeNode"]
|
||||
static void staticDeprecatedMethod(boolean arg);
|
||||
[Deprecated="GetAttributeNode"]
|
||||
static void staticDeprecatedMethodWithContext(any arg);
|
||||
|
||||
// Overload resolution tests
|
||||
//void overload1(DOMString... strs);
|
||||
boolean overload1(TestInterface arg);
|
||||
|
|
|
@ -602,12 +602,28 @@ interface TestJSImplInterface {
|
|||
AnotherNameForTestJSImplInterface exerciseTypedefInterfaces2(NullableTestJSImplInterface arg);
|
||||
void exerciseTypedefInterfaces3(YetAnotherNameForTestJSImplInterface arg);
|
||||
|
||||
// Deprecated methods and attributes
|
||||
[Deprecated="GetAttributeNode"]
|
||||
attribute byte deprecatedAttribute;
|
||||
[Deprecated="GetAttributeNode"]
|
||||
byte deprecatedMethod();
|
||||
[Deprecated="GetAttributeNode"]
|
||||
void deprecatedMethodWithContext(any arg);
|
||||
|
||||
// Static methods and attributes
|
||||
// FIXME: Bug 863952 Static things are not supported yet
|
||||
/*
|
||||
static attribute boolean staticAttribute;
|
||||
static void staticMethod(boolean arg);
|
||||
static void staticMethodWithContext(any arg);
|
||||
|
||||
// Deprecated static methods and attributes
|
||||
[Deprecated="GetAttributeNode"]
|
||||
static attribute byte staticDeprecatedAttribute;
|
||||
[Deprecated="GetAttributeNode"]
|
||||
static byte staticDeprecatedMethod();
|
||||
[Deprecated="GetAttributeNode"]
|
||||
static byte staticDeprecatedMethodWithContext();
|
||||
*/
|
||||
|
||||
// Overload resolution tests
|
||||
|
|
|
@ -22,7 +22,7 @@ function runTest()
|
|||
|
||||
var numPrompts = 0;
|
||||
iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
|
||||
is(e.detail.message, numPrompts, "prompt message");
|
||||
is(e.detail.message, String(numPrompts), "prompt message");
|
||||
if (numPrompts / 10 < 1) {
|
||||
is(e.detail.promptType, 'alert');
|
||||
}
|
||||
|
|
|
@ -18,15 +18,15 @@ function runTest() {
|
|||
document.body.appendChild(iframe);
|
||||
|
||||
var prompts = [
|
||||
{msg: 1, type: 'alert', rv: 42, expected: 'undefined'},
|
||||
{msg: 2, type: 'confirm', rv: true, expected: 'true'},
|
||||
{msg: 3, type: 'confirm', rv: false, expected: 'false'},
|
||||
{msg: '1', type: 'alert', rv: 42, expected: 'undefined'},
|
||||
{msg: '2', type: 'confirm', rv: true, expected: 'true'},
|
||||
{msg: '3', type: 'confirm', rv: false, expected: 'false'},
|
||||
|
||||
// rv == 42 should be coerced to 'true' for confirm.
|
||||
{msg: 4, type: 'confirm', rv: 42, expected: 'true'},
|
||||
{msg: 5, type: 'prompt', rv: 'worked', expected: 'worked'},
|
||||
{msg: 6, type: 'prompt', rv: null, expected: 'null'},
|
||||
{msg: 7, type: 'prompt', rv: '', expected: ''}
|
||||
{msg: '4', type: 'confirm', rv: 42, expected: 'true'},
|
||||
{msg: '5', type: 'prompt', rv: 'worked', expected: 'worked'},
|
||||
{msg: '6', type: 'prompt', rv: null, expected: 'null'},
|
||||
{msg: '7', type: 'prompt', rv: '', expected: ''}
|
||||
];
|
||||
|
||||
iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
|
||||
|
|
|
@ -100,7 +100,7 @@ function runTest() {
|
|||
is(e.detail.message, expectedMessage.message);
|
||||
is(e.detail.buttons.length, 2);
|
||||
is(e.detail.showCheckbox, false);
|
||||
is(e.detail.checkMessage, null);
|
||||
is(e.detail.checkboxMessage, null);
|
||||
e.detail.unblock();
|
||||
|
||||
if (!doRepost) {
|
||||
|
|
|
@ -52,7 +52,7 @@ function runTest() {
|
|||
// increased by one.
|
||||
var p = Promise.all([
|
||||
expectProcessCreated('FOREGROUND'),
|
||||
expectPriorityWithLRUSet(childID, 'FOREGROUND', 1)
|
||||
expectPriorityWithLRUSet(childID, 'FOREGROUND', '1')
|
||||
]);
|
||||
|
||||
document.body.appendChild(iframe2);
|
||||
|
@ -61,7 +61,7 @@ function runTest() {
|
|||
}).then(function() {
|
||||
// Now hide the second and third processes, this will send them into the
|
||||
// background and make the first process LRU value to be decreased.
|
||||
var p = expectPriorityWithLRUSet(childID, 'FOREGROUND', 0)
|
||||
var p = expectPriorityWithLRUSet(childID, 'FOREGROUND', '0')
|
||||
|
||||
iframe2.setVisible(false);
|
||||
|
||||
|
|
|
@ -198,18 +198,6 @@ public:
|
|||
// automatically.
|
||||
}
|
||||
|
||||
virtual bool
|
||||
IsFileServiceUtilized() override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
IsTransactionServiceActivated() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void
|
||||
WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
|
||||
nsIRunnable* aCallback) override
|
||||
|
@ -231,7 +219,7 @@ public:
|
|||
|
||||
|
||||
virtual void
|
||||
ShutdownTransactionService() override
|
||||
ShutdownWorkThreads() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
|
|
@ -151,6 +151,7 @@ public:
|
|||
, mCameraId(aCameraId)
|
||||
, mInitialConfig(aInitialConfig)
|
||||
, mPromise(aPromise)
|
||||
, mRequester(new nsContentPermissionRequester(mWindow))
|
||||
{ }
|
||||
|
||||
protected:
|
||||
|
@ -165,6 +166,7 @@ protected:
|
|||
uint32_t mCameraId;
|
||||
CameraConfiguration mInitialConfig;
|
||||
nsRefPtr<Promise> mPromise;
|
||||
nsCOMPtr<nsIContentPermissionRequester> mRequester;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(CameraPermissionRequest, mWindow, mPromise)
|
||||
|
@ -218,6 +220,16 @@ CameraPermissionRequest::Allow(JS::HandleValue aChoices)
|
|||
return DispatchCallback(nsIPermissionManager::ALLOW_ACTION);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CameraPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRequester);
|
||||
|
||||
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
|
||||
requester.forget(aRequester);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CameraPermissionRequest::DispatchCallback(uint32_t aPermission)
|
||||
{
|
||||
|
|
|
@ -150,7 +150,7 @@ var steps = [
|
|||
// Some manual testing. Testint the testfunctions
|
||||
// tel: [{type: ["work"], value: "123456", carrier: "testCarrier"} , {type: ["home", "fax"], value: "+55 (31) 9876-3456"}],
|
||||
is(findResult1.tel[0].carrier, "testCarrier", "Same Carrier");
|
||||
is(findResult1.tel[0].type, "work", "Same type");
|
||||
is(String(findResult1.tel[0].type), "work", "Same type");
|
||||
is(findResult1.tel[0].value, "123456", "Same Value");
|
||||
is(findResult1.tel[1].type[1], "fax", "Same type");
|
||||
is(findResult1.tel[1].value, "+55 (31) 9876-3456", "Same Value");
|
||||
|
@ -158,7 +158,7 @@ var steps = [
|
|||
is(findResult1.adr[0].countryName, "country 1", "Same country");
|
||||
|
||||
// email: [{type: ["work"], value: "x@y.com"}]
|
||||
is(findResult1.email[0].type, "work", "Same Type");
|
||||
is(String(findResult1.email[0].type), "work", "Same Type");
|
||||
is(findResult1.email[0].value, "x@y.com", "Same Value");
|
||||
next();
|
||||
};
|
||||
|
|
|
@ -230,7 +230,7 @@ var steps = [
|
|||
ok(cloned.id, "The contact now has an ID.");
|
||||
is(cloned.email[0].value, "new email!", "Same Email");
|
||||
isnot(createResult1.email[0].value, cloned.email[0].value, "Clone has different email");
|
||||
is(cloned.givenName, "Tom", "New Name");
|
||||
is(String(cloned.givenName), "Tom", "New Name");
|
||||
next();
|
||||
}
|
||||
req.onerror = onFailure;
|
||||
|
|
|
@ -2176,6 +2176,7 @@ nsDOMDeviceStorageCursor::nsDOMDeviceStorageCursor(nsPIDOMWindow* aWindow,
|
|||
, mSince(aSince)
|
||||
, mFile(aFile)
|
||||
, mPrincipal(aPrincipal)
|
||||
, mRequester(new nsContentPermissionRequester(GetOwner()))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -2265,6 +2266,16 @@ nsDOMDeviceStorageCursor::Allow(JS::HandleValue aChoices)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorageCursor::GetRequester(nsIContentPermissionRequester** aRequester)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRequester);
|
||||
|
||||
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
|
||||
requester.forget(aRequester);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMDeviceStorageCursor::Continue(ErrorResult& aRv)
|
||||
{
|
||||
|
@ -2851,6 +2862,7 @@ public:
|
|||
, mFile(aFile)
|
||||
, mRequest(aRequest)
|
||||
, mDeviceStorage(aDeviceStorage)
|
||||
, mRequester(new nsContentPermissionRequester(mWindow))
|
||||
{
|
||||
MOZ_ASSERT(mWindow);
|
||||
MOZ_ASSERT(mPrincipal);
|
||||
|
@ -2871,6 +2883,7 @@ public:
|
|||
, mFile(aFile)
|
||||
, mRequest(aRequest)
|
||||
, mBlob(aBlob)
|
||||
, mRequester(new nsContentPermissionRequester(mWindow))
|
||||
{
|
||||
MOZ_ASSERT(mWindow);
|
||||
MOZ_ASSERT(mPrincipal);
|
||||
|
@ -2890,6 +2903,7 @@ public:
|
|||
, mFile(aFile)
|
||||
, mRequest(aRequest)
|
||||
, mDSFileDescriptor(aDSFileDescriptor)
|
||||
, mRequester(new nsContentPermissionRequester(mWindow))
|
||||
{
|
||||
MOZ_ASSERT(mRequestType == DEVICE_STORAGE_REQUEST_CREATEFD);
|
||||
MOZ_ASSERT(mWindow);
|
||||
|
@ -3299,6 +3313,15 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP GetRequester(nsIContentPermissionRequester** aRequester)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRequester);
|
||||
|
||||
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
|
||||
requester.forget(aRequester);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~DeviceStorageRequest() {}
|
||||
|
||||
|
@ -3311,6 +3334,7 @@ private:
|
|||
nsCOMPtr<nsIDOMBlob> mBlob;
|
||||
nsRefPtr<nsDOMDeviceStorage> mDeviceStorage;
|
||||
nsRefPtr<DeviceStorageFileDescriptor> mDSFileDescriptor;
|
||||
nsCOMPtr<nsIContentPermissionRequester> mRequester;
|
||||
};
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeviceStorageRequest)
|
||||
|
|
|
@ -220,6 +220,7 @@ private:
|
|||
|
||||
nsRefPtr<DeviceStorageFile> mFile;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIContentPermissionRequester> mRequester;
|
||||
};
|
||||
|
||||
//helpers
|
||||
|
|
|
@ -472,6 +472,7 @@ nsresult
|
|||
EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
nsIFrame* aTargetFrame,
|
||||
nsIContent* aTargetContent,
|
||||
nsEventStatus* aStatus)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aStatus);
|
||||
|
@ -481,6 +482,11 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
NS_WARN_IF_FALSE(!aTargetFrame ||
|
||||
!aTargetFrame->GetContent() ||
|
||||
aTargetFrame->GetContent() == aTargetContent,
|
||||
"aTargetContent should be related with aTargetFrame");
|
||||
|
||||
mCurrentTarget = aTargetFrame;
|
||||
mCurrentTargetContent = nullptr;
|
||||
|
||||
|
@ -507,10 +513,9 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
WheelTransaction::OnEvent(aEvent);
|
||||
|
||||
// Focus events don't necessarily need a frame.
|
||||
if (NS_EVENT_NEEDS_FRAME(aEvent)) {
|
||||
if (!mCurrentTarget) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (!mCurrentTarget && !aTargetContent) {
|
||||
NS_ERROR("mCurrentTarget and aTargetContent are null");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (aEvent->HasDragEventMessage() && sIsPointerLocked) {
|
||||
|
@ -1515,10 +1520,12 @@ EventStateManager::BeginTrackingDragGesture(nsPresContext* aPresContext,
|
|||
// synthesized mouse move event.
|
||||
mGestureDownPoint = inDownEvent->refPoint + inDownEvent->widget->WidgetToScreenOffset();
|
||||
|
||||
inDownFrame->GetContentForEvent(inDownEvent,
|
||||
getter_AddRefs(mGestureDownContent));
|
||||
if (inDownFrame) {
|
||||
inDownFrame->GetContentForEvent(inDownEvent,
|
||||
getter_AddRefs(mGestureDownContent));
|
||||
|
||||
mGestureDownFrameOwner = inDownFrame->GetContent();
|
||||
mGestureDownFrameOwner = inDownFrame->GetContent();
|
||||
}
|
||||
mGestureModifiers = inDownEvent->modifiers;
|
||||
mGestureDownButtons = inDownEvent->buttons;
|
||||
|
||||
|
@ -4088,7 +4095,7 @@ EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
|
|||
// in the other branch here.
|
||||
sSynthCenteringPoint = center;
|
||||
aMouseEvent->widget->SynthesizeNativeMouseMove(
|
||||
center + aMouseEvent->widget->WidgetToScreenOffset());
|
||||
center + aMouseEvent->widget->WidgetToScreenOffset(), nullptr);
|
||||
} else if (aMouseEvent->refPoint == sSynthCenteringPoint) {
|
||||
// This is the "synthetic native" event we dispatched to re-center the
|
||||
// pointer. Cancel it so we don't expose the centering move to content.
|
||||
|
@ -4223,7 +4230,8 @@ EventStateManager::SetPointerLock(nsIWidget* aWidget,
|
|||
sLastRefPoint = GetWindowInnerRectCenter(aElement->OwnerDoc()->GetWindow(),
|
||||
aWidget,
|
||||
mPresContext);
|
||||
aWidget->SynthesizeNativeMouseMove(sLastRefPoint + aWidget->WidgetToScreenOffset());
|
||||
aWidget->SynthesizeNativeMouseMove(sLastRefPoint + aWidget->WidgetToScreenOffset(),
|
||||
nullptr);
|
||||
|
||||
// Retarget all events to this element via capture.
|
||||
nsIPresShell::SetCapturingContent(aElement, CAPTURE_POINTERLOCK);
|
||||
|
@ -4238,7 +4246,8 @@ EventStateManager::SetPointerLock(nsIWidget* aWidget,
|
|||
// pre-pointerlock position, so that the synthetic mouse event reports
|
||||
// no movement.
|
||||
sLastRefPoint = mPreLockPoint;
|
||||
aWidget->SynthesizeNativeMouseMove(mPreLockPoint + aWidget->WidgetToScreenOffset());
|
||||
aWidget->SynthesizeNativeMouseMove(mPreLockPoint + aWidget->WidgetToScreenOffset(),
|
||||
nullptr);
|
||||
|
||||
// Don't retarget events to this element any more.
|
||||
nsIPresShell::SetCapturingContent(nullptr, CAPTURE_POINTERLOCK);
|
||||
|
@ -4395,7 +4404,9 @@ EventStateManager::SetClickCount(nsPresContext* aPresContext,
|
|||
{
|
||||
nsCOMPtr<nsIContent> mouseContent;
|
||||
nsIContent* mouseContentParent = nullptr;
|
||||
mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(mouseContent));
|
||||
if (mCurrentTarget) {
|
||||
mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(mouseContent));
|
||||
}
|
||||
if (mouseContent) {
|
||||
if (mouseContent->IsNodeOfType(nsINode::eTEXT)) {
|
||||
mouseContent = mouseContent->GetParent();
|
||||
|
|
|
@ -94,6 +94,7 @@ public:
|
|||
nsresult PreHandleEvent(nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
nsIFrame* aTargetFrame,
|
||||
nsIContent* aTargetContent,
|
||||
nsEventStatus* aStatus);
|
||||
|
||||
/* The PostHandleEvent method should contain all system processing which
|
||||
|
|
|
@ -31,7 +31,7 @@ is(div.onscroll.toString(), "function onscroll(event) {\ndiv\n}",
|
|||
|
||||
div.setAttribute("onpopstate", "div");
|
||||
is(window.onpopstate, null, "div should not forward onpopstate");
|
||||
is(div.onpopstate, null, "div should not have onpopstate handler");
|
||||
is("onpopstate" in div, false, "div should not have onpopstate handler");
|
||||
|
||||
var body = document.createElement("body");
|
||||
body.setAttribute("onclick", "body");
|
||||
|
|
|
@ -168,7 +168,7 @@ function test_DataTransfer(dt)
|
|||
is(dt.getData(""), "", "invalid type getData"),
|
||||
dt.mozSetDataAt("", "Invalid Type", 0);
|
||||
is(dt.types.length, 0, "invalid type setDataAt");
|
||||
is(dt.mozGetDataAt("", 0), null, "invalid type getDataAt"),
|
||||
is(dt.mozGetDataAt("", 0), undefined, "invalid type getDataAt"),
|
||||
|
||||
// similar with clearDataAt and getDataAt
|
||||
expectError(function() dt.mozGetDataAt("text/plain", 1),
|
||||
|
@ -501,8 +501,8 @@ function checkOneDataItem(dt, expectedtypes, expecteddata, index, testid)
|
|||
checkTypes(dt, expectedtypes, index, testid);
|
||||
for (var f = 0; f < expectedtypes.length; f++) {
|
||||
if (index == 0)
|
||||
is(dt.getData(expectedtypes[f]), expecteddata[f], testid + " getData " + expectedtypes[f]);
|
||||
is(dt.mozGetDataAt(expectedtypes[f], index), expecteddata[f] ? expecteddata[f] : null,
|
||||
is_loosely(dt.getData(expectedtypes[f]), expecteddata[f], testid + " getData " + expectedtypes[f]);
|
||||
is_loosely(dt.mozGetDataAt(expectedtypes[f], index), expecteddata[f] ? expecteddata[f] : null,
|
||||
testid + " getDataAt " + expectedtypes[f]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=848294
|
|||
is(e.data, 'data' in test ? test.data : undefined, 'MessageEvent.data is ok');
|
||||
is(e.origin, 'origin' in test ? test.origin : '', 'MessageEvent.origin is ok');
|
||||
is(e.lastEventId, 'lastEventId' in test ? test.lastEventId : '', 'MessageEvent.lastEventId is ok');
|
||||
is(e.source, 'source' in test ? test.source : undefined, 'MessageEvent.source is ok');
|
||||
is(e.source, 'source' in test ? test.source : null, 'MessageEvent.source is ok');
|
||||
|
||||
if (test.ports != undefined) {
|
||||
is(e.ports.length, test.ports.length, 'MessageEvent.ports is ok');
|
||||
|
|
|
@ -32,7 +32,7 @@ AsyncHelper::AsyncWork(nsIRequestObserver* aObserver, nsISupports* aCtxt)
|
|||
FileService* service = FileService::GetOrCreate();
|
||||
NS_ENSURE_TRUE(service, NS_ERROR_FAILURE);
|
||||
|
||||
nsIEventTarget* target = service->StreamTransportTarget();
|
||||
nsIEventTarget* target = service->ThreadPoolTarget();
|
||||
|
||||
rv = target->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -592,7 +592,7 @@ FileHandleBase::Finish()
|
|||
FileService* service = FileService::Get();
|
||||
MOZ_ASSERT(service, "This should never be null");
|
||||
|
||||
nsIEventTarget* target = service->StreamTransportTarget();
|
||||
nsIEventTarget* target = service->ThreadPoolTarget();
|
||||
|
||||
nsresult rv = target->Dispatch(helper, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -739,7 +739,7 @@ ReadHelper::DoAsyncRun(nsISupports* aStream)
|
|||
FileService* service = FileService::Get();
|
||||
MOZ_ASSERT(service, "This should never be null");
|
||||
|
||||
nsIEventTarget* target = service->StreamTransportTarget();
|
||||
nsIEventTarget* target = service->ThreadPoolTarget();
|
||||
|
||||
nsCOMPtr<nsIAsyncStreamCopier> copier;
|
||||
nsresult rv =
|
||||
|
@ -814,7 +814,7 @@ WriteHelper::DoAsyncRun(nsISupports* aStream)
|
|||
FileService* service = FileService::Get();
|
||||
MOZ_ASSERT(service, "This should never be null");
|
||||
|
||||
nsIEventTarget* target = service->StreamTransportTarget();
|
||||
nsIEventTarget* target = service->ThreadPoolTarget();
|
||||
|
||||
nsCOMPtr<nsIAsyncStreamCopier> copier;
|
||||
nsresult rv =
|
||||
|
|
|
@ -12,10 +12,9 @@
|
|||
#include "MutableFile.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIOfflineStorage.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadPool.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -23,49 +22,70 @@ namespace dom {
|
|||
|
||||
namespace {
|
||||
|
||||
FileService* gInstance = nullptr;
|
||||
const uint32_t kThreadLimit = 5;
|
||||
const uint32_t kIdleThreadLimit = 1;
|
||||
const uint32_t kIdleThreadTimeoutMs = 30000;
|
||||
|
||||
StaticAutoPtr<FileService> gInstance;
|
||||
bool gShutdown = false;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
FileService::FileService()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!gInstance, "More than one instance!");
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!gInstance);
|
||||
}
|
||||
|
||||
FileService::~FileService()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!gInstance, "More than one instance!");
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
nsresult
|
||||
FileService::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
mStreamTransportTarget =
|
||||
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
|
||||
mThreadPool = new nsThreadPool();
|
||||
|
||||
return rv;
|
||||
nsresult rv = mThreadPool->SetName(NS_LITERAL_CSTRING("FileHandleTrans"));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mThreadPool->SetThreadLimit(kThreadLimit);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mThreadPool->SetIdleThreadLimit(kIdleThreadLimit);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mThreadPool->SetIdleThreadTimeout(kIdleThreadTimeoutMs);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FileService::Cleanup()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsIThread* thread = NS_GetCurrentThread();
|
||||
while (mStorageInfos.Count()) {
|
||||
if (!NS_ProcessNextEvent(thread)) {
|
||||
NS_ERROR("Failed to process next event!");
|
||||
break;
|
||||
}
|
||||
MOZ_ASSERT(thread);
|
||||
|
||||
nsresult rv = mThreadPool->Shutdown();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Make sure the service is still accessible while any generated callbacks
|
||||
// are processed.
|
||||
nsresult rv = NS_ProcessPendingEvents(thread);
|
||||
rv = NS_ProcessPendingEvents(thread);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mCompleteCallbacks.IsEmpty()) {
|
||||
|
@ -95,20 +115,12 @@ FileService::GetOrCreate()
|
|||
}
|
||||
|
||||
if (!gInstance) {
|
||||
nsRefPtr<FileService> service(new FileService);
|
||||
nsAutoPtr<FileService> service(new FileService());
|
||||
|
||||
nsresult rv = service->Init();
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
rv = obs->AddObserver(service, "profile-before-change", false);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
// The observer service now owns us.
|
||||
gInstance = service;
|
||||
gInstance = service.forget();
|
||||
}
|
||||
|
||||
return gInstance;
|
||||
|
@ -254,55 +266,29 @@ FileService::NotifyFileHandleCompleted(FileHandleBase* aFileHandle)
|
|||
}
|
||||
|
||||
void
|
||||
FileService::WaitForStoragesToComplete(
|
||||
nsTArray<nsCOMPtr<nsIOfflineStorage> >& aStorages,
|
||||
nsIRunnable* aCallback)
|
||||
FileService::WaitForStoragesToComplete(nsTArray<nsCString>& aStorageIds,
|
||||
nsIRunnable* aCallback)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aStorages.IsEmpty(), "No databases to wait on!");
|
||||
NS_ASSERTION(aCallback, "Null pointer!");
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!aStorageIds.IsEmpty());
|
||||
MOZ_ASSERT(aCallback);
|
||||
|
||||
StoragesCompleteCallback* callback = mCompleteCallbacks.AppendElement();
|
||||
callback->mCallback = aCallback;
|
||||
callback->mStorages.SwapElements(aStorages);
|
||||
callback->mStorageIds.SwapElements(aStorageIds);
|
||||
|
||||
if (MaybeFireCallback(*callback)) {
|
||||
mCompleteCallbacks.RemoveElementAt(mCompleteCallbacks.Length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileService::AbortFileHandlesForStorage(nsIOfflineStorage* aStorage)
|
||||
nsIEventTarget*
|
||||
FileService::ThreadPoolTarget() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
MOZ_ASSERT(aStorage, "Null pointer!");
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mThreadPool);
|
||||
|
||||
StorageInfo* storageInfo;
|
||||
if (!mStorageInfos.Get(aStorage->Id(), &storageInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoTArray<nsRefPtr<FileHandleBase>, 10> fileHandles;
|
||||
storageInfo->CollectRunningAndDelayedFileHandles(aStorage, fileHandles);
|
||||
|
||||
for (uint32_t index = 0; index < fileHandles.Length(); index++) {
|
||||
ErrorResult ignored;
|
||||
fileHandles[index]->Abort(ignored);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(FileService, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileService::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!strcmp(aTopic, "profile-before-change"), "Wrong topic!");
|
||||
|
||||
Shutdown();
|
||||
|
||||
return NS_OK;
|
||||
return mThreadPool;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -310,8 +296,8 @@ FileService::MaybeFireCallback(StoragesCompleteCallback& aCallback)
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
for (uint32_t index = 0; index < aCallback.mStorages.Length(); index++) {
|
||||
if (mStorageInfos.Get(aCallback.mStorages[index]->Id(), nullptr)) {
|
||||
for (uint32_t index = 0; index < aCallback.mStorageIds.Length(); index++) {
|
||||
if (mStorageInfos.Get(aCallback.mStorageIds[index], nullptr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -489,25 +475,5 @@ FileService::StorageInfo::CreateDelayedEnqueueInfo(FileHandleBase* aFileHandle,
|
|||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
FileService::StorageInfo::CollectRunningAndDelayedFileHandles(
|
||||
nsIOfflineStorage* aStorage,
|
||||
nsTArray<nsRefPtr<FileHandleBase>>& aFileHandles)
|
||||
{
|
||||
for (uint32_t index = 0; index < mFileHandleQueues.Length(); index++) {
|
||||
FileHandleBase* fileHandle = mFileHandleQueues[index]->mFileHandle;
|
||||
if (fileHandle->MutableFile()->Storage() == aStorage) {
|
||||
aFileHandles.AppendElement(fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t index = 0; index < mDelayedEnqueueInfos.Length(); index++) {
|
||||
FileHandleBase* fileHandle = mDelayedEnqueueInfos[index].mFileHandle;
|
||||
if (fileHandle->MutableFile()->Storage() == aStorage) {
|
||||
aFileHandles.AppendElement(fileHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/FileHelper.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
|
@ -20,20 +20,20 @@
|
|||
|
||||
class nsAString;
|
||||
class nsIEventTarget;
|
||||
class nsIOfflineStorage;
|
||||
class nsIRunnable;
|
||||
class nsThreadPool;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FileHandleBase;
|
||||
|
||||
class FileService final : public nsIObserver
|
||||
class FileService final
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
friend class nsAutoPtr<FileService>;
|
||||
friend class StaticAutoPtr<FileService>;
|
||||
|
||||
public:
|
||||
// Returns a non-owning reference!
|
||||
static FileService*
|
||||
GetOrCreate();
|
||||
|
@ -56,18 +56,11 @@ public:
|
|||
NotifyFileHandleCompleted(FileHandleBase* aFileHandle);
|
||||
|
||||
void
|
||||
WaitForStoragesToComplete(nsTArray<nsCOMPtr<nsIOfflineStorage> >& aStorages,
|
||||
WaitForStoragesToComplete(nsTArray<nsCString>& aStorageIds,
|
||||
nsIRunnable* aCallback);
|
||||
|
||||
void
|
||||
AbortFileHandlesForStorage(nsIOfflineStorage* aStorage);
|
||||
|
||||
nsIEventTarget*
|
||||
StreamTransportTarget()
|
||||
{
|
||||
NS_ASSERTION(mStreamTransportTarget, "This should never be null!");
|
||||
return mStreamTransportTarget;
|
||||
}
|
||||
ThreadPoolTarget() const;
|
||||
|
||||
private:
|
||||
class FileHandleQueue final : public FileHelperListener
|
||||
|
@ -136,11 +129,6 @@ private:
|
|||
CreateDelayedEnqueueInfo(FileHandleBase* aFileHandle,
|
||||
FileHelper* aFileHelper);
|
||||
|
||||
inline void
|
||||
CollectRunningAndDelayedFileHandles(
|
||||
nsIOfflineStorage* aStorage,
|
||||
nsTArray<nsRefPtr<FileHandleBase>>& aFileHandles);
|
||||
|
||||
void
|
||||
LockFileForReading(const nsAString& aFileName)
|
||||
{
|
||||
|
@ -178,7 +166,7 @@ private:
|
|||
|
||||
struct StoragesCompleteCallback
|
||||
{
|
||||
nsTArray<nsCOMPtr<nsIOfflineStorage> > mStorages;
|
||||
nsTArray<nsCString> mStorageIds;
|
||||
nsCOMPtr<nsIRunnable> mCallback;
|
||||
};
|
||||
|
||||
|
@ -194,7 +182,7 @@ private:
|
|||
bool
|
||||
MaybeFireCallback(StoragesCompleteCallback& aCallback);
|
||||
|
||||
nsCOMPtr<nsIEventTarget> mStreamTransportTarget;
|
||||
nsRefPtr<nsThreadPool> mThreadPool;
|
||||
nsClassHashtable<nsCStringHashKey, StorageInfo> mStorageInfos;
|
||||
nsTArray<StoragesCompleteCallback> mCompleteCallbacks;
|
||||
};
|
||||
|
|
|
@ -35,3 +35,7 @@ LOCAL_INCLUDES += [
|
|||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/xpcom/threads',
|
||||
]
|
||||
|
|
|
@ -55,6 +55,7 @@ FileSystemPermissionRequest::FileSystemPermissionRequest(
|
|||
}
|
||||
|
||||
mPrincipal = doc->NodePrincipal();
|
||||
mRequester = new nsContentPermissionRequester(mWindow);
|
||||
}
|
||||
|
||||
FileSystemPermissionRequest::~FileSystemPermissionRequest()
|
||||
|
@ -135,5 +136,15 @@ FileSystemPermissionRequest::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileSystemPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRequester);
|
||||
|
||||
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
|
||||
requester.forget(aRequester);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} /* namespace dom */
|
||||
} /* namespace mozilla */
|
||||
|
|
|
@ -42,6 +42,7 @@ private:
|
|||
nsRefPtr<FileSystemTaskBase> mTask;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIContentPermissionRequester> mRequester;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -111,6 +111,7 @@ class nsGeolocationRequest final
|
|||
|
||||
int32_t mWatchId;
|
||||
bool mShutdown;
|
||||
nsCOMPtr<nsIContentPermissionRequester> mRequester;
|
||||
};
|
||||
|
||||
static PositionOptions*
|
||||
|
@ -356,6 +357,13 @@ nsGeolocationRequest::nsGeolocationRequest(Geolocation* aLocator,
|
|||
mWatchId(aWatchId),
|
||||
mShutdown(false)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> win = do_QueryReferent(mLocator->GetOwner());
|
||||
if (win) {
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(win);
|
||||
if (window) {
|
||||
mRequester = new nsContentPermissionRequester(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsGeolocationRequest::~nsGeolocationRequest()
|
||||
|
@ -500,6 +508,16 @@ nsGeolocationRequest::Allow(JS::HandleValue aChoices)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeolocationRequest::GetRequester(nsIContentPermissionRequester** aRequester)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRequester);
|
||||
|
||||
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
|
||||
requester.forget(aRequester);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsGeolocationRequest::SetTimeoutTimer()
|
||||
{
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
#include "HTMLSplitOnSpacesTokenizer.h"
|
||||
#include "nsIController.h"
|
||||
#include "nsIMIMEInfo.h"
|
||||
#include "nsFrameSelection.h"
|
||||
|
||||
// input type=date
|
||||
#include "js/Date.h"
|
||||
|
@ -3285,6 +3286,19 @@ HTMLInputElement::Select()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsTextEditorState* tes = GetEditorState();
|
||||
if (tes) {
|
||||
nsFrameSelection* fs = tes->GetConstFrameSelection();
|
||||
if (fs && fs->MouseDownRecorded()) {
|
||||
// This means that we're being called while the frame selection has a mouse
|
||||
// down event recorded to adjust the caret during the mouse up event.
|
||||
// We are probably called from the focus event handler. We should override
|
||||
// the delayed caret data in this case to ensure that this select() call
|
||||
// takes effect.
|
||||
fs->SetDelayedCaretData(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
|
||||
nsRefPtr<nsPresContext> presContext = GetPresContext(eForComposedDoc);
|
||||
|
|
|
@ -182,7 +182,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=722599
|
|||
is(numberChange, 0, "Change event shouldn't be dispatched on number input element for keyboard input until it loses focus");
|
||||
number.blur();
|
||||
is(numberChange, 1, "Change event should be dispatched on number input element on blur");
|
||||
is(number.value, 12, "Sanity check that number keys were actually handled");
|
||||
is(number.value, "12", "Sanity check that number keys were actually handled");
|
||||
if (isDesktop) { // up/down arrow keys not supported on android/b2g
|
||||
number.value = "";
|
||||
number.focus();
|
||||
|
@ -190,7 +190,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=722599
|
|||
synthesizeKey("VK_UP", {});
|
||||
synthesizeKey("VK_DOWN", {});
|
||||
is(numberChange, 4, "Change event should be dispatched on number input element for up/down arrow keys (a special case)");
|
||||
is(number.value, 1, "Sanity check that number and arrow keys were actually handled");
|
||||
is(number.value, "1", "Sanity check that number and arrow keys were actually handled");
|
||||
}
|
||||
|
||||
// Special case type=range
|
||||
|
|
|
@ -191,11 +191,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
|||
number.focus();
|
||||
synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" });
|
||||
is(numberInput, 1, "input event should be dispatched for up/down arrow key keypress");
|
||||
is(number.value, 1, "sanity check value of number control after keypress");
|
||||
is(number.value, "1", "sanity check value of number control after keypress");
|
||||
|
||||
synthesizeKey("KEY_ArrowDown", { code: "ArrowDown", repeat: 3 });
|
||||
is(numberInput, 4, "input event should be dispatched for each up/down arrow key keypress event, even when rapidly repeated");
|
||||
is(number.value, -2, "sanity check value of number control after multiple keydown events");
|
||||
is(number.value, "-2", "sanity check value of number control after multiple keydown events");
|
||||
|
||||
number.blur();
|
||||
is(numberInput, 4, "input event shouldn't be dispatched on blur");
|
||||
|
|
|
@ -159,34 +159,34 @@ function test() {
|
|||
oldVal = elem.value = -1;
|
||||
expectedVal = expectedValAfterKeyEvent(key, elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for number control with value set between min/max (" + oldVal + ")");
|
||||
is(elem.value, String(expectedVal), "Test " + key + " for number control with value set between min/max (" + oldVal + ")");
|
||||
|
||||
// Same again:
|
||||
expectedVal = expectedValAfterKeyEvent(key, elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test repeat of " + key + " for number control");
|
||||
is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control");
|
||||
|
||||
// Start at maximum:
|
||||
oldVal = elem.value = elem.max;
|
||||
expectedVal = expectedValAfterKeyEvent(key, elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for number control with value set to the maximum (" + oldVal + ")");
|
||||
is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the maximum (" + oldVal + ")");
|
||||
|
||||
// Same again:
|
||||
expectedVal = expectedValAfterKeyEvent(key, elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test repeat of " + key + " for number control");
|
||||
is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control");
|
||||
|
||||
// Start at minimum:
|
||||
oldVal = elem.value = elem.min;
|
||||
expectedVal = expectedValAfterKeyEvent(key, elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for number control with value set to the minimum (" + oldVal + ")");
|
||||
is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the minimum (" + oldVal + ")");
|
||||
|
||||
// Same again:
|
||||
expectedVal = expectedValAfterKeyEvent(key, elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test repeat of " + key + " for number control");
|
||||
is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control");
|
||||
|
||||
// Test preventDefault():
|
||||
elem.addEventListener("keypress", function(evt) {
|
||||
|
@ -196,7 +196,7 @@ function test() {
|
|||
oldVal = elem.value = 0;
|
||||
expectedVal = 0;
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for number control where scripted preventDefault() should prevent the value changing");
|
||||
is(elem.value, String(expectedVal), "Test " + key + " for number control where scripted preventDefault() should prevent the value changing");
|
||||
|
||||
// Test step="any" behavior:
|
||||
var oldStep = elem.step;
|
||||
|
@ -204,7 +204,7 @@ function test() {
|
|||
oldVal = elem.value = 0;
|
||||
expectedVal = expectedValAfterKeyEvent(key, elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for number control with value set to the midpoint and step='any' (" + oldVal + ")");
|
||||
is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the midpoint and step='any' (" + oldVal + ")");
|
||||
elem.step = oldStep; // restore
|
||||
|
||||
// Test that invalid input blocks UI initiated stepping:
|
||||
|
@ -220,12 +220,12 @@ function test() {
|
|||
elem.select();
|
||||
expectedVal = expectedValAfterKeyEvent(key, elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for number control with value set to the empty string and with the 'required' attribute set");
|
||||
is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the empty string and with the 'required' attribute set");
|
||||
|
||||
// Same again:
|
||||
expectedVal = expectedValAfterKeyEvent(key, elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test repeat of " + key + " for number control");
|
||||
is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control");
|
||||
|
||||
// Reset 'required' attribute:
|
||||
elem.removeAttribute("required");
|
||||
|
|
|
@ -40,13 +40,13 @@ function runTest(test) {
|
|||
elem.focus();
|
||||
elem.select();
|
||||
sendString(test.inputWithGrouping);
|
||||
is(elem.value, test.value, "Test " + test.desc + " ('" + test.langTag +
|
||||
"') localization with grouping separator");
|
||||
is(elem.value, String(test.value), "Test " + test.desc + " ('" + test.langTag +
|
||||
"') localization with grouping separator");
|
||||
elem.value = 0;
|
||||
elem.select();
|
||||
sendString(test.inputWithoutGrouping);
|
||||
is(elem.value, test.value, "Test " + test.desc + " ('" + test.langTag +
|
||||
"') localization without grouping separator");
|
||||
is(elem.value, String(test.value), "Test " + test.desc + " ('" + test.langTag +
|
||||
"') localization without grouping separator");
|
||||
}
|
||||
|
||||
function startTests() {
|
||||
|
|
|
@ -53,28 +53,28 @@ function test() {
|
|||
|
||||
// Test click on spin-up button:
|
||||
synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" });
|
||||
is(input.value, 1, "Test step-up on mousedown on spin-up button");
|
||||
is(input.value, "1", "Test step-up on mousedown on spin-up button");
|
||||
synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" });
|
||||
is(input.value, 1, "Test mouseup on spin-up button");
|
||||
is(input.value, "1", "Test mouseup on spin-up button");
|
||||
|
||||
// Test click on spin-down button:
|
||||
synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" });
|
||||
is(input.value, 0, "Test step-down on mousedown on spin-down button");
|
||||
is(input.value, "0", "Test step-down on mousedown on spin-down button");
|
||||
synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" });
|
||||
is(input.value, 0, "Test mouseup on spin-down button");
|
||||
is(input.value, "0", "Test mouseup on spin-down button");
|
||||
|
||||
// Test step="any" behavior:
|
||||
input.value = 0;
|
||||
var oldStep = input.step;
|
||||
input.step = "any";
|
||||
synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" });
|
||||
is(input.value, 1, "Test step-up on mousedown on spin-up button with step='any'");
|
||||
is(input.value, "1", "Test step-up on mousedown on spin-up button with step='any'");
|
||||
synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" });
|
||||
is(input.value, 1, "Test mouseup on spin-up button with step='any'");
|
||||
is(input.value, "1", "Test mouseup on spin-up button with step='any'");
|
||||
synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" });
|
||||
is(input.value, 0, "Test step-down on mousedown on spin-down button with step='any'");
|
||||
is(input.value, "0", "Test step-down on mousedown on spin-down button with step='any'");
|
||||
synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" });
|
||||
is(input.value, 0, "Test mouseup on spin-down button with step='any'");
|
||||
is(input.value, "0", "Test mouseup on spin-down button with step='any'");
|
||||
input.step = oldStep; // restore
|
||||
|
||||
// Test that preventDefault() works:
|
||||
|
@ -84,9 +84,9 @@ function test() {
|
|||
input.value = 1;
|
||||
input.addEventListener("mousedown", preventDefault, false);
|
||||
synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, {});
|
||||
is(input.value, 1, "Test that preventDefault() works for click on spin-up button");
|
||||
is(input.value, "1", "Test that preventDefault() works for click on spin-up button");
|
||||
synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, {});
|
||||
is(input.value, 1, "Test that preventDefault() works for click on spin-down button");
|
||||
is(input.value, "1", "Test that preventDefault() works for click on spin-down button");
|
||||
input.removeEventListener("mousedown", preventDefault, false);
|
||||
|
||||
// Run the spin tests:
|
||||
|
@ -113,10 +113,10 @@ var spinTests = [
|
|||
input.addEventListener("input", function(evt) {
|
||||
++inputEventCount;
|
||||
if (inputEventCount == 3) {
|
||||
ok(input.value, 3, "Testing spin-up button");
|
||||
is(input.value, "3", "Testing spin-up button");
|
||||
synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousemove" });
|
||||
} else if (inputEventCount == 6) {
|
||||
ok(input.value, 0, "Testing spin direction is reversed after mouse moves from spin-up button to spin-down button");
|
||||
is(input.value, "0", "Testing spin direction is reversed after mouse moves from spin-up button to spin-down button");
|
||||
input.removeEventListener("input", arguments.callee, false);
|
||||
synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" });
|
||||
runNextSpinTest();
|
||||
|
@ -133,10 +133,10 @@ var spinTests = [
|
|||
input.addEventListener("input", function(evt) {
|
||||
++inputEventCount;
|
||||
if (inputEventCount == 3) {
|
||||
ok(input.value, -3, "Testing spin-down button");
|
||||
is(input.value, "-3", "Testing spin-down button");
|
||||
synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousemove" });
|
||||
} else if (inputEventCount == 6) {
|
||||
ok(input.value, 0, "Testing spin direction is reversed after mouse moves from spin-down button to spin-up button");
|
||||
is(input.value, "0", "Testing spin direction is reversed after mouse moves from spin-down button to spin-up button");
|
||||
input.removeEventListener("input", arguments.callee, false);
|
||||
synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" });
|
||||
runNextSpinTest();
|
||||
|
@ -156,8 +156,8 @@ var spinTests = [
|
|||
synthesizeMouse(input, -1, -1, { type: "mousemove" });
|
||||
var eventHandler = arguments.callee;
|
||||
setTimeout(function() {
|
||||
ok(input.value, 3, "Testing moving the mouse outside the spin buttons stops the spin");
|
||||
ok(inputEventCount, 3, "Testing moving the mouse outside the spin buttons stops the spin input events");
|
||||
is(input.value, "3", "Testing moving the mouse outside the spin buttons stops the spin");
|
||||
is(inputEventCount, 3, "Testing moving the mouse outside the spin buttons stops the spin input events");
|
||||
input.removeEventListener("input", eventHandler, false);
|
||||
synthesizeMouse(input, -1, -1, { type: "mouseup" });
|
||||
runNextSpinTest();
|
||||
|
@ -177,8 +177,8 @@ var spinTests = [
|
|||
input.type = "text"
|
||||
var eventHandler = arguments.callee;
|
||||
setTimeout(function() {
|
||||
ok(input.value, 3, "Testing changing input type during a spin stops the spin");
|
||||
ok(inputEventCount, 3, "Testing changing input type during a spin stops the spin input events");
|
||||
is(input.value, "-3", "Testing changing input type during a spin stops the spin");
|
||||
is(inputEventCount, 3, "Testing changing input type during a spin stops the spin input events");
|
||||
input.removeEventListener("input", eventHandler, false);
|
||||
synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" });
|
||||
input.type = "number"; // restore
|
||||
|
|
|
@ -158,46 +158,46 @@ function test() {
|
|||
elem.value = oldVal = defaultValue(elem);
|
||||
expectedVal = expectedFunc(elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for " + dir + " range with value set to the midpoint (" + oldVal + ")");
|
||||
is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with value set to the midpoint (" + oldVal + ")");
|
||||
|
||||
// Same again:
|
||||
expectedVal = expectedFunc(elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test repeat of " + key + " for " + dir + " range");
|
||||
is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range");
|
||||
|
||||
// Start at maximum:
|
||||
elem.value = oldVal = maximum(elem);
|
||||
expectedVal = expectedFunc(elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for " + dir + " range with value set to the maximum (" + oldVal + ")");
|
||||
is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with value set to the maximum (" + oldVal + ")");
|
||||
|
||||
// Same again:
|
||||
expectedVal = expectedFunc(elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test repeat of " + key + " for " + dir + " range");
|
||||
is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range");
|
||||
|
||||
// Start at minimum:
|
||||
elem.value = oldVal = minimum(elem);
|
||||
expectedVal = expectedFunc(elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for " + dir + " range with value set to the minimum (" + oldVal + ")");
|
||||
is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with value set to the minimum (" + oldVal + ")");
|
||||
|
||||
// Same again:
|
||||
expectedVal = expectedFunc(elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test repeat of " + key + " for " + dir + " range");
|
||||
is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range");
|
||||
|
||||
// Test for a step value that is greater than 10% of the range:
|
||||
elem.step = 20;
|
||||
elem.value = 60;
|
||||
expectedVal = expectedFunc(elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test " + key + " for " + dir + " range with a step that is greater than 10% of the range (step=" + elem.step + ")");
|
||||
is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with a step that is greater than 10% of the range (step=" + elem.step + ")");
|
||||
|
||||
// Same again:
|
||||
expectedVal = expectedFunc(elem);
|
||||
synthesizeKey(key, {});
|
||||
is(elem.value, expectedVal, "Test repeat of " + key + " for " + dir + " range");
|
||||
is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range");
|
||||
|
||||
// reset step:
|
||||
elem.step = 2;
|
||||
|
|
|
@ -43,11 +43,11 @@ SimpleTest.waitForFocus(function() {
|
|||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
const MIDDLE_OF_RANGE = 50;
|
||||
const MINIMUM_OF_RANGE = 0;
|
||||
const MAXIMUM_OF_RANGE = 100;
|
||||
const QUARTER_OF_RANGE = 25;
|
||||
const THREE_QUARTERS_OF_RANGE = 75;
|
||||
const MIDDLE_OF_RANGE = "50";
|
||||
const MINIMUM_OF_RANGE = "0";
|
||||
const MAXIMUM_OF_RANGE = "100";
|
||||
const QUARTER_OF_RANGE = "25";
|
||||
const THREE_QUARTERS_OF_RANGE = "75";
|
||||
|
||||
function flush() {
|
||||
// Flush style, specifically to flush the 'direction' property so that the
|
||||
|
|
|
@ -47,16 +47,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=597650
|
|||
testControl(label, inputH, type, true);
|
||||
testControl(labelForH, inputH, type, true);
|
||||
} else {
|
||||
testControl(label, inputI, type, false);
|
||||
testControl(labelForH, undefined, type, false);
|
||||
testControl(label, inputI, type, false);
|
||||
testControl(labelForH, null, type, false);
|
||||
|
||||
inputH.type = "text";
|
||||
testControl(label, inputH, "text", true);
|
||||
testControl(labelForH, inputH, "text", true);
|
||||
|
||||
inputH.type = type;
|
||||
testControl(label, inputI, type, false);
|
||||
testControl(labelForH, undefined, type, false);
|
||||
testControl(label, inputI, type, false);
|
||||
testControl(labelForH, null, type, false);
|
||||
|
||||
label.removeChild(inputH);
|
||||
testControl(label, inputI, "text", true);
|
||||
|
|
|
@ -31,7 +31,7 @@ function checkFormIDLAttribute(aElement)
|
|||
function checkAttribute(aElement, aAttribute, aNewValue, aExpectedValueForIDL)
|
||||
{
|
||||
var expectedValueForIDL = aNewValue;
|
||||
var expectedValueForContent = aNewValue;
|
||||
var expectedValueForContent = String(aNewValue);
|
||||
|
||||
if (aExpectedValueForIDL !== undefined) {
|
||||
expectedValueForIDL = aExpectedValueForIDL;
|
||||
|
@ -53,8 +53,8 @@ function checkAttribute(aElement, aAttribute, aNewValue, aExpectedValueForIDL)
|
|||
}
|
||||
} else {
|
||||
aElement.removeAttribute(aAttribute);
|
||||
is(aElement.getAttribute(aAttribute), expectedValueForContent,
|
||||
aAttribute + " content attribute should be " + expectedValueForContent);
|
||||
is(aElement.getAttribute(aAttribute), null,
|
||||
aAttribute + " content attribute should be null");
|
||||
is(aElement[aAttribute], expectedValueForIDL,
|
||||
aAttribute + " IDL attribute should be " + expectedValueForIDL);
|
||||
}
|
||||
|
|
|
@ -106,12 +106,12 @@ function checkFormIDLAttribute(element)
|
|||
|
||||
function checkHtmlForIDLAttribute(element)
|
||||
{
|
||||
is(element.htmlFor, 'a b',
|
||||
is(String(element.htmlFor), 'a b',
|
||||
"htmlFor IDL attribute should reflect the for content attribute");
|
||||
|
||||
// DOMSettableTokenList is tested in another bug so we just test assignation
|
||||
element.htmlFor.value = 'a b c';
|
||||
is(element.htmlFor, 'a b c', "htmlFor should have changed");
|
||||
is(String(element.htmlFor), 'a b c', "htmlFor should have changed");
|
||||
}
|
||||
|
||||
function submitForm()
|
||||
|
|
|
@ -35,7 +35,7 @@ function checkFormIDLAttribute(aElement)
|
|||
function checkAttribute(aElement, aAttribute, aNewValue, aExpectedValueForIDL)
|
||||
{
|
||||
var expectedValueForIDL = aNewValue;
|
||||
var expectedValueForContent = aNewValue;
|
||||
var expectedValueForContent = String(aNewValue);
|
||||
|
||||
if (aExpectedValueForIDL !== undefined) {
|
||||
expectedValueForIDL = aExpectedValueForIDL;
|
||||
|
@ -57,8 +57,8 @@ function checkAttribute(aElement, aAttribute, aNewValue, aExpectedValueForIDL)
|
|||
}
|
||||
} else {
|
||||
aElement.removeAttribute(aAttribute);
|
||||
is(aElement.getAttribute(aAttribute), expectedValueForContent,
|
||||
aAttribute + " content attribute should be " + expectedValueForContent);
|
||||
is(aElement.getAttribute(aAttribute), null,
|
||||
aAttribute + " content attribute should be null");
|
||||
is(aElement[aAttribute], expectedValueForIDL,
|
||||
aAttribute + " IDL attribute should be " + expectedValueForIDL);
|
||||
}
|
||||
|
|
|
@ -423,44 +423,44 @@ for (var test of data) {
|
|||
// When step=0, the allowed value step is 1.
|
||||
input.step = '0';
|
||||
input.value = '1.2';
|
||||
is(input.value, 1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '1';
|
||||
is(input.value, 1, "check that the value coincides with a step");
|
||||
is(input.value, '1', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '0';
|
||||
is(input.value, 0, "check that the value coincides with a step");
|
||||
is(input.value, '0', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
// When step is NaN, the allowed step value is 1.
|
||||
input.step = 'foo';
|
||||
input.value = '1';
|
||||
is(input.value, 1, "check that the value coincides with a step");
|
||||
is(input.value, '1', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '1.5';
|
||||
is(input.value, 2, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
// When step is negative, the allowed step value is 1.
|
||||
input.step = '-0.1';
|
||||
is(input.value, 2, "check that the value still coincides with a step");
|
||||
is(input.value, '2', "check that the value still coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '1';
|
||||
is(input.value, 1, "check that the value coincides with a step");
|
||||
is(input.value, '1', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
// When step is missing, the allowed step value is 1.
|
||||
input.removeAttribute('step');
|
||||
input.value = '1.5';
|
||||
is(input.value, 2, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '1';
|
||||
is(input.value, 1, "check that the value coincides with a step");
|
||||
is(input.value, '1', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
// When step is 'any', all values are fine wrt to step.
|
||||
|
@ -469,132 +469,132 @@ for (var test of data) {
|
|||
|
||||
input.step = 'aNy';
|
||||
input.value = '97';
|
||||
is(input.value, 97, "check that the value for step=aNy is unchanged");
|
||||
is(input.value, '97', "check that the value for step=aNy is unchanged");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.step = 'AnY';
|
||||
input.value = '0.1';
|
||||
is(input.value, 0.1, "check that a positive fractional value with step=AnY is unchanged");
|
||||
is(input.value, '0.1', "check that a positive fractional value with step=AnY is unchanged");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.step = 'ANY';
|
||||
input.min = -100;
|
||||
input.value = '-13.37';
|
||||
is(input.value, -13.37, "check that a negative fractional value with step=ANY is unchanged");
|
||||
is(input.value, '-13.37', "check that a negative fractional value with step=ANY is unchanged");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
// When min is set to a valid float, there is a step base.
|
||||
input.min = '1'; // the step base
|
||||
input.step = '2';
|
||||
input.value = '3';
|
||||
is(input.value, 3, "check that the value coincides with a step");
|
||||
is(input.value, '3', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '2';
|
||||
is(input.value, 3, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '1.99';
|
||||
is(input.value, 1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.removeAttribute('step'); // step = 1
|
||||
input.min = '0.5'; // step base
|
||||
input.value = '5.5';
|
||||
is(input.value, 5.5, "check that the value coincides with a step");
|
||||
is(input.value, '5.5', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '1';
|
||||
is(input.value, 1.5, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '1.5', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.min = '-0.1'; // step base
|
||||
input.step = '1';
|
||||
input.value = '0.9';
|
||||
is(input.value, 0.9, "the value should be a valid step");
|
||||
is(input.value, '0.9', "the value should be a valid step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '0.1';
|
||||
is(input.value, -0.1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '-0.1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
// When min is set to NaN, the step base is the value.
|
||||
input.min = 'foo';
|
||||
input.step = '1';
|
||||
input.value = '1';
|
||||
is(input.value, 1, "check that the value coincides with a step");
|
||||
is(input.value, '1', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '0.5';
|
||||
is(input.value, 1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.min = '';
|
||||
input.value = '1';
|
||||
is(input.value, 1, "check that the value coincides with a step");
|
||||
is(input.value, '1', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '0.5';
|
||||
is(input.value, 1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.removeAttribute('min');
|
||||
|
||||
// Test when the value isn't a number
|
||||
input.value = '';
|
||||
is(input.value, 50, "value be should default to the value midway between the minimum (0) and the maximum (100)");
|
||||
is(input.value, '50', "value be should default to the value midway between the minimum (0) and the maximum (100)");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
// Regular situations.
|
||||
input.step = '2';
|
||||
input.value = '1.5';
|
||||
is(input.value, 2, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = '42.0';
|
||||
is(input.value, 42, "check that the value coincides with a step");
|
||||
is(input.value, '42.0', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.step = '0.1';
|
||||
input.value = '-0.1';
|
||||
is(input.value, 0, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '0', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.step = '2';
|
||||
input.removeAttribute('min');
|
||||
input.max = '10';
|
||||
input.value = '-9';
|
||||
is(input.value, 0, "check the value is clamped to the minimum's default of zero");
|
||||
is(input.value, '0', "check the value is clamped to the minimum's default of zero");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
// If @value is defined but not @min, the step base is @value.
|
||||
input = getFreshElement(test.type);
|
||||
input.setAttribute('value', '1');
|
||||
input.step = 2;
|
||||
is(input.value, 1, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = 3;
|
||||
is(input.value, 3, "check that the value coincides with a step");
|
||||
is(input.value, '3', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = 2;
|
||||
is(input.value, 3, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
// Should also work with defaultValue.
|
||||
input = getFreshElement(test.type);
|
||||
input.defaultValue = 1;
|
||||
input.step = 2;
|
||||
is(input.value, 1, "check that the value coincides with a step");
|
||||
is(input.value, '1', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = 3;
|
||||
is(input.value, 3, "check that the value coincides with a step");
|
||||
is(input.value, '3', "check that the value coincides with a step");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
input.value = 2;
|
||||
is(input.value, 3, "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
|
||||
checkValidity(input, true, apply);
|
||||
|
||||
// Check contrived error case where there are no valid steps in range:
|
||||
|
@ -604,7 +604,7 @@ for (var test of data) {
|
|||
input.step = '3';
|
||||
input.max = '1';
|
||||
input.defaultValue = '-1';
|
||||
is(input.value, 0, "the value should have been clamped to the default minimum, zero");
|
||||
is(input.value, '0', "the value should have been clamped to the default minimum, zero");
|
||||
checkValidity(input, false, apply, {low: -1, high: -1});
|
||||
|
||||
// Check that when the closest of the two steps that the value is between
|
||||
|
@ -614,7 +614,7 @@ for (var test of data) {
|
|||
input.min = '1';
|
||||
input.max = '10.9';
|
||||
input.value = '10.8'; // closest step in 11, but 11 > maximum
|
||||
is(input.value, 9, "check that the value coincides with a step");
|
||||
is(input.value, '9', "check that the value coincides with a step");
|
||||
|
||||
// The way that step base is defined, the converse (the value not being
|
||||
// on a step, and the nearest step being a value that would be underflow)
|
||||
|
|
|
@ -185,9 +185,15 @@ function checkDateGet()
|
|||
|
||||
for (data of invalidData) {
|
||||
element.value = data[0];
|
||||
is(element.valueAsDate, data[1] ? "Invalid Date" : null,
|
||||
"valueAsDate should return null " +
|
||||
"when the element value is not a valid date");
|
||||
if (data[1]) {
|
||||
is(String(element.valueAsDate), "Invalid Date",
|
||||
"valueAsDate should return an invalid Date object " +
|
||||
"when the element value is not a valid date");
|
||||
} else {
|
||||
is(element.valueAsDate, null,
|
||||
"valueAsDate should return null " +
|
||||
"when the element value is not a valid date");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -150,11 +150,11 @@ function checkNumberSet()
|
|||
// Setting a string will set NaN.
|
||||
["foo", ""],
|
||||
// "" is converted to 0.
|
||||
["", 0],
|
||||
["", "0"],
|
||||
[42, "42"], // Keep this here, it is used by the next test.
|
||||
// Setting Infinity should throw and not change the current value.
|
||||
[Infinity, 42, true],
|
||||
[-Infinity, 42, true],
|
||||
[Infinity, "42", true],
|
||||
[-Infinity, "42", true],
|
||||
// Setting NaN should change the value to the empty string.
|
||||
[NaN, ""],
|
||||
];
|
||||
|
@ -225,7 +225,7 @@ function checkRangeSet()
|
|||
{
|
||||
var min = -200;
|
||||
var max = 200;
|
||||
var defaultValue = min + (max - min)/2;
|
||||
var defaultValue = String(min + (max - min)/2);
|
||||
|
||||
var testData =
|
||||
[
|
||||
|
|
|
@ -34,7 +34,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1045270
|
|||
SimpleTest.executeSoon(function() {
|
||||
synthesizeKey("2", {});
|
||||
SimpleTest.executeSoon(function() {
|
||||
is(input.value, 12, "Reframe should restore focus and selection properly");
|
||||
is(input.value, "12", "Reframe should restore focus and selection properly");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -25,12 +25,12 @@
|
|||
form2.insertBefore(newInput, F2I2);
|
||||
form1.insertBefore(newInput, form1.firstChild);
|
||||
|
||||
is(form1.elements.length, "3", "Form 1 has the correct length");
|
||||
is(form1.elements.length, 3, "Form 1 has the correct length");
|
||||
is(form1.elements[0].value, "13", "Form 1 element 1 is correct");
|
||||
is(form1.elements[1].value, "11", "Form 1 element 2 is correct");
|
||||
is(form1.elements[2].value, "12", "Form 1 element 3 is correct");
|
||||
|
||||
is(form2.elements.length, "2", "Form 2 has the correct length");
|
||||
is(form2.elements.length, 2, "Form 2 has the correct length");
|
||||
is(form2.elements[0].value, "21", "Form 2 element 1 is correct");
|
||||
is(form2.elements[1].value, "22", "Form 2 element 2 is correct");
|
||||
</script>
|
||||
|
|
|
@ -45,11 +45,11 @@
|
|||
var form1 = document.getElementById("form1");
|
||||
var form2 = document.getElementById("form2");
|
||||
|
||||
is(form1.elements.length, "2", "Form 1 has the correct length");
|
||||
is(form1.elements.length, 2, "Form 1 has the correct length");
|
||||
is(form1.elements[0].value, "12", "Form 1 element 1 is correct");
|
||||
is(form1.elements[1].value, "10", "Form 1 element 2 is correct");
|
||||
|
||||
is(form2.elements.length, "3", "Form 2 has the correct length");
|
||||
is(form2.elements.length, 3, "Form 2 has the correct length");
|
||||
is(form2.elements[0].value, "11", "Form 2 element 1 is correct");
|
||||
is(form2.elements[1].value, "21", "Form 2 element 2 is correct");
|
||||
is(form2.elements[2].value, "22", "Form 2 element 2 is correct");
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
var form1 = document.getElementById("form1");
|
||||
form1.insertBefore(input2, input1);
|
||||
|
||||
is(form1.elements["input"].length, "3", "Form 1 'input' has the correct length");
|
||||
is(form1.elements["input"].length, 3, "Form 1 'input' has the correct length");
|
||||
is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct");
|
||||
is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct");
|
||||
is(form1.elements["input"][2].value, "3", "Form 1 element 3 is correct");
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
var form1 = document.getElementById("form1");
|
||||
form1.insertBefore(input2, input1);
|
||||
|
||||
is(form1.elements["input"].length, "3", "Form 1 'input' has the correct length");
|
||||
is(form1.elements["input"].length, 3, "Form 1 'input' has the correct length");
|
||||
is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct");
|
||||
is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct");
|
||||
is(form1.elements["input"][2].value, "3", "Form 1 element 3 is correct");
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
var form1 = document.getElementById("form1");
|
||||
form1.insertBefore(input2, input1);
|
||||
|
||||
is(form1.elements["input"].length, "3", "Form 1 'input' has the correct length");
|
||||
is(form1.elements["input"].length, 3, "Form 1 'input' has the correct length");
|
||||
is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct");
|
||||
is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct");
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
form1.insertBefore(input8, input4);
|
||||
form1.insertBefore(input9, input2);
|
||||
|
||||
is(form1.elements["input"].length, "10", "Form 1 'input' has the correct length");
|
||||
is(form1.elements["input"].length, 10, "Form 1 'input' has the correct length");
|
||||
is(form1.elements["input"][0].value, "9", "Form 1 element 1 is correct");
|
||||
is(form1.elements["input"][1].value, "2", "Form 1 element 2 is correct");
|
||||
is(form1.elements["input"][2].value, "1", "Form 1 element 3 is correct");
|
||||
|
|
|
@ -28,7 +28,7 @@ sel.options.remove(0);
|
|||
sel.options.remove(1000);
|
||||
sel.options.remove(-1);
|
||||
is(sel.length, 1, "Unexpected option collection length");
|
||||
is(sel[0].value, 10, "Unexpected remained option");
|
||||
is(sel[0].value, "10", "Unexpected remained option");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -28,7 +28,7 @@ function checkNegativeMaxLength(element)
|
|||
|
||||
element.setAttribute('maxLength', -15);
|
||||
is(element.maxLength, -1, "negative maxLength is not processed correctly when set dynamically");
|
||||
is(element.getAttribute('maxLength'), -15, "maxLength attribute doesn't return the correct value");
|
||||
is(element.getAttribute('maxLength'), "-15", "maxLength attribute doesn't return the correct value");
|
||||
|
||||
element.setAttribute('maxLength', 0);
|
||||
is(element.maxLength, 0, "negative maxLength is not processed correctly");
|
||||
|
|
|
@ -40,7 +40,7 @@ function checkNegativeMaxLengthException(element)
|
|||
}
|
||||
ok(caught, "Setting negative maxLength from the DOM should throw an exception");
|
||||
|
||||
is(element.getAttribute('maxLength'), -10, "When the exception is raised, the maxLength attribute shouldn't change");
|
||||
is(element.getAttribute('maxLength'), "-10", "When the exception is raised, the maxLength attribute shouldn't change");
|
||||
}
|
||||
|
||||
/* TODO: correct behavior may be checked for email, telephone, url and search input types */
|
||||
|
|
|
@ -32,25 +32,25 @@ function checkSizeReflection(element, defaultValue)
|
|||
element.setAttribute('size', -15);
|
||||
is(element.size, defaultValue,
|
||||
"The reflecting IDL attribute should return the default value when content attribute value is invalid");
|
||||
is(element.getAttribute('size'), -15,
|
||||
is(element.getAttribute('size'), "-15",
|
||||
"The content attribute should containt the previously set value");
|
||||
|
||||
element.setAttribute('size', 0);
|
||||
is(element.size, 0,
|
||||
"0 should be considered as a valid value");
|
||||
is(element.getAttribute('size'), 0,
|
||||
is(element.getAttribute('size'), "0",
|
||||
"The content attribute should containt the previously set value");
|
||||
|
||||
element.setAttribute('size', 2147483647); /* PR_INT32_MAX */
|
||||
is(element.size, 2147483647,
|
||||
"PR_INT32_MAX should be considered as a valid value");
|
||||
is(element.getAttribute('size'), 2147483647,
|
||||
is(element.getAttribute('size'), "2147483647",
|
||||
"The content attribute should containt the previously set value");
|
||||
|
||||
element.setAttribute('size', -2147483648); /* PR_INT32_MIN */
|
||||
is(element.size, defaultValue,
|
||||
"The reflecting IDL attribute should return the default value when content attribute value is invalid");
|
||||
is(element.getAttribute('size'), -2147483648,
|
||||
is(element.getAttribute('size'), "-2147483648",
|
||||
"The content attribute should containt the previously set value");
|
||||
|
||||
element.setAttribute('size', 'non-numerical-value');
|
||||
|
@ -62,13 +62,13 @@ function checkSizeReflection(element, defaultValue)
|
|||
element.setAttribute('size', 4294967294); /* PR_INT32_MAX * 2 */
|
||||
is(element.size, defaultValue,
|
||||
"Value greater than PR_INT32_MAX should be considered as invalid");
|
||||
is(element.getAttribute('size'), 4294967294,
|
||||
is(element.getAttribute('size'), "4294967294",
|
||||
"The content attribute should containt the previously set value");
|
||||
|
||||
element.setAttribute('size', -4294967296); /* PR_INT32_MIN * 2 */
|
||||
is(element.size, defaultValue,
|
||||
"The reflecting IDL attribute should return the default value when content attribute value is invalid");
|
||||
is(element.getAttribute('size'), -4294967296,
|
||||
is(element.getAttribute('size'), "-4294967296",
|
||||
"The content attribute should containt the previously set value");
|
||||
|
||||
element.size = defaultValue + 1;
|
||||
|
@ -135,7 +135,7 @@ function checkSizeWhenChangeMultiple(element, aDefaultNonMultiple, aDefaultMulti
|
|||
s.multiple = true;
|
||||
is(s.size, aDefaultMultiple, "Size IDL attribute should be 4");
|
||||
|
||||
is(s.getAttribute('size'), -1, "Size content attribute should be -1");
|
||||
is(s.getAttribute('size'), "-1", "Size content attribute should be -1");
|
||||
|
||||
s.setAttribute('size', -2);
|
||||
is(s.size, aDefaultMultiple, "Size IDL attribute should be 4");
|
||||
|
@ -143,7 +143,7 @@ function checkSizeWhenChangeMultiple(element, aDefaultNonMultiple, aDefaultMulti
|
|||
s.multiple = false;
|
||||
is(s.size, aDefaultNonMultiple, "Size IDL attribute should be 1");
|
||||
|
||||
is(s.getAttribute('size'), -2, "Size content attribute should be -2");
|
||||
is(s.getAttribute('size'), "-2", "Size content attribute should be -2");
|
||||
}
|
||||
|
||||
var s = document.getElementById('s');
|
||||
|
|
|
@ -26,18 +26,18 @@ addLoadEvent(runTests);
|
|||
|
||||
var testData = [
|
||||
// Object 0
|
||||
[ 0, null, "-1" ],
|
||||
[ 0, "1", "1" ],
|
||||
[ 0, "-1", "-1" ],
|
||||
[ 0, "0", "0" ],
|
||||
[ 0, "foo", "-1" ],
|
||||
[ 0, null, -1 ],
|
||||
[ 0, "1", 1 ],
|
||||
[ 0, "-1", -1 ],
|
||||
[ 0, "0", 0 ],
|
||||
[ 0, "foo", -1 ],
|
||||
// Object 1
|
||||
[ 1, null, "-1" ],
|
||||
[ 1, "1", "1" ],
|
||||
[ 1, null, -1 ],
|
||||
[ 1, "1", 1 ],
|
||||
// Object 2
|
||||
[ 2, null, "0" ],
|
||||
[ 2, "1", "1" ],
|
||||
[ 2, "-1", "-1" ],
|
||||
[ 2, null, 0 ],
|
||||
[ 2, "1", 1 ],
|
||||
[ 2, "-1", -1 ],
|
||||
];
|
||||
|
||||
var objects = document.getElementsByTagName("object");
|
||||
|
|
Двоичные данные
dom/html/test/test_bug615595.html
Двоичные данные
dom/html/test/test_bug615595.html
Двоичный файл не отображается.
|
@ -31,7 +31,8 @@ p = document.getElementById("content");
|
|||
|
||||
// Test that several elements with the same id or name behave correctly
|
||||
function testNumSame() {
|
||||
is(document.all.id0, null, "no ids");
|
||||
is(document.all.id0, undefined, "no ids");
|
||||
is(document.all.namedItem("id0"), null, "no ids");
|
||||
is(document.all.id1, p.children[0], "one id");
|
||||
is(document.all.id2[0], p.children[1], "two ids");
|
||||
is(document.all.id2[1], p.children[2], "two ids");
|
||||
|
@ -79,7 +80,8 @@ id3list = document.all.id3;
|
|||
rC(child[3]);
|
||||
is(id3list.length, 1, "now one length");
|
||||
rC(child[5]);
|
||||
is(document.all.id3, null, "now none");
|
||||
is(document.all.id3, undefined, "now none");
|
||||
is(document.all.namedItem("id3"), null, "now none (namedItem)");
|
||||
is(id3list.length, 0, "now none length");
|
||||
|
||||
// Give an element both a name and id and check that it appears in two lists
|
||||
|
@ -135,7 +137,8 @@ elementNames.forEach(function (name) {
|
|||
hasName.shift();
|
||||
}
|
||||
else {
|
||||
is(document.all[nameval], null, "shouldn't have name");
|
||||
is(document.all[nameval], undefined, "shouldn't have name");
|
||||
is(document.all.namedItem(nameval), null, "shouldn't have name (namedItem)");
|
||||
}
|
||||
});
|
||||
is(hasName.length, 0, "found all names");
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "mozilla/unused.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FileService.h"
|
||||
#include "mozilla/dom/StructuredCloneTags.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/dom/indexedDB/PBackgroundIDBCursorParent.h"
|
||||
|
@ -5452,6 +5453,66 @@ private:
|
|||
override;
|
||||
};
|
||||
|
||||
class WaitForTransactionsHelper final
|
||||
: public nsRunnable
|
||||
{
|
||||
nsCOMPtr<nsIEventTarget> mOwningThread;
|
||||
const nsCString mDatabaseId;
|
||||
nsCOMPtr<nsIRunnable> mCallback;
|
||||
|
||||
enum
|
||||
{
|
||||
State_Initial = 0,
|
||||
State_WaitingForTransactions,
|
||||
State_DispatchToMainThread,
|
||||
State_WaitingForFileHandles,
|
||||
State_DispatchToOwningThread,
|
||||
State_Complete
|
||||
} mState;
|
||||
|
||||
public:
|
||||
WaitForTransactionsHelper(const nsCString& aDatabaseId,
|
||||
nsIRunnable* aCallback)
|
||||
: mOwningThread(NS_GetCurrentThread())
|
||||
, mDatabaseId(aDatabaseId)
|
||||
, mCallback(aCallback)
|
||||
, mState(State_Initial)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(!aDatabaseId.IsEmpty());
|
||||
MOZ_ASSERT(aCallback);
|
||||
}
|
||||
|
||||
void
|
||||
WaitForTransactions();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
private:
|
||||
~WaitForTransactionsHelper()
|
||||
{
|
||||
MOZ_ASSERT(!mCallback);
|
||||
MOZ_ASSERT(mState = State_Complete);
|
||||
}
|
||||
|
||||
void
|
||||
MaybeWaitForTransactions();
|
||||
|
||||
void
|
||||
DispatchToMainThread();
|
||||
|
||||
void
|
||||
MaybeWaitForFileHandles();
|
||||
|
||||
void
|
||||
DispatchToOwningThread();
|
||||
|
||||
void
|
||||
CallCallback();
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
class Database final
|
||||
: public PBackgroundIDBDatabaseParent
|
||||
{
|
||||
|
@ -5471,6 +5532,7 @@ private:
|
|||
const nsCString mOrigin;
|
||||
const nsCString mId;
|
||||
const nsString mFilePath;
|
||||
uint32_t mFileHandleCount;
|
||||
const PersistenceType mPersistenceType;
|
||||
const bool mChromeWriteAccessAllowed;
|
||||
bool mClosed;
|
||||
|
@ -5651,7 +5713,7 @@ private:
|
|||
CloseInternal();
|
||||
|
||||
void
|
||||
CloseConnection();
|
||||
MaybeCloseConnection();
|
||||
|
||||
void
|
||||
ConnectionClosedCallback();
|
||||
|
@ -5711,6 +5773,12 @@ private:
|
|||
|
||||
virtual bool
|
||||
RecvClose() override;
|
||||
|
||||
virtual bool
|
||||
RecvNewFileHandle() override;
|
||||
|
||||
virtual bool
|
||||
RecvFileHandleFinished() override;
|
||||
};
|
||||
|
||||
class Database::StartTransactionOp final
|
||||
|
@ -6334,11 +6402,11 @@ protected:
|
|||
State_DatabaseWorkVersionChange,
|
||||
|
||||
// Waiting to send/sending results on the PBackground thread. Next step is
|
||||
// UnblockingQuotaManager.
|
||||
// State_UnblockingQuotaManager.
|
||||
State_SendingResults,
|
||||
|
||||
// Notifying the QuotaManager that it can proceed to the next operation on
|
||||
// the main thread. Next step is Completed.
|
||||
// the main thread. Next step is State_Completed.
|
||||
State_UnblockingQuotaManager,
|
||||
|
||||
// All done.
|
||||
|
@ -7630,8 +7698,8 @@ private:
|
|||
class QuotaClient final
|
||||
: public mozilla::dom::quota::Client
|
||||
{
|
||||
class ShutdownTransactionThreadPoolRunnable;
|
||||
friend class ShutdownTransactionThreadPoolRunnable;
|
||||
class ShutdownWorkThreadsRunnable;
|
||||
friend class ShutdownWorkThreadsRunnable;
|
||||
|
||||
class WaitForTransactionsRunnable;
|
||||
friend class WaitForTransactionsRunnable;
|
||||
|
@ -7639,7 +7707,7 @@ class QuotaClient final
|
|||
static QuotaClient* sInstance;
|
||||
|
||||
nsCOMPtr<nsIEventTarget> mBackgroundThread;
|
||||
nsRefPtr<ShutdownTransactionThreadPoolRunnable> mShutdownRunnable;
|
||||
nsRefPtr<ShutdownWorkThreadsRunnable> mShutdownRunnable;
|
||||
|
||||
bool mShutdownRequested;
|
||||
|
||||
|
@ -7710,18 +7778,12 @@ public:
|
|||
virtual void
|
||||
ReleaseIOThreadObjects() override;
|
||||
|
||||
virtual bool
|
||||
IsFileServiceUtilized() override;
|
||||
|
||||
virtual bool
|
||||
IsTransactionServiceActivated() override;
|
||||
|
||||
virtual void
|
||||
WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
|
||||
nsIRunnable* aCallback) override;
|
||||
|
||||
virtual void
|
||||
ShutdownTransactionService() override;
|
||||
ShutdownWorkThreads() override;
|
||||
|
||||
private:
|
||||
~QuotaClient();
|
||||
|
@ -7737,7 +7799,7 @@ private:
|
|||
bool aDatabaseFiles);
|
||||
};
|
||||
|
||||
class QuotaClient::ShutdownTransactionThreadPoolRunnable final
|
||||
class QuotaClient::ShutdownWorkThreadsRunnable final
|
||||
: public nsRunnable
|
||||
{
|
||||
nsRefPtr<QuotaClient> mQuotaClient;
|
||||
|
@ -7745,7 +7807,7 @@ class QuotaClient::ShutdownTransactionThreadPoolRunnable final
|
|||
|
||||
public:
|
||||
|
||||
explicit ShutdownTransactionThreadPoolRunnable(QuotaClient* aQuotaClient)
|
||||
explicit ShutdownWorkThreadsRunnable(QuotaClient* aQuotaClient)
|
||||
: mQuotaClient(aQuotaClient)
|
||||
, mHasRequestedShutDown(false)
|
||||
{
|
||||
|
@ -7758,7 +7820,7 @@ public:
|
|||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
private:
|
||||
~ShutdownTransactionThreadPoolRunnable()
|
||||
~ShutdownWorkThreadsRunnable()
|
||||
{
|
||||
MOZ_ASSERT(!mQuotaClient);
|
||||
}
|
||||
|
@ -7777,7 +7839,8 @@ class QuotaClient::WaitForTransactionsRunnable final
|
|||
{
|
||||
State_Initial = 0,
|
||||
State_WaitingForTransactions,
|
||||
State_CallingCallback,
|
||||
State_DispatchToMainThread,
|
||||
State_WaitingForFileHandles,
|
||||
State_Complete
|
||||
} mState;
|
||||
|
||||
|
@ -7809,10 +7872,13 @@ private:
|
|||
}
|
||||
|
||||
void
|
||||
MaybeWait();
|
||||
MaybeWaitForTransactions();
|
||||
|
||||
void
|
||||
SendToMainThread();
|
||||
DispatchToMainThread();
|
||||
|
||||
void
|
||||
MaybeWaitForFileHandles();
|
||||
|
||||
void
|
||||
CallCallback();
|
||||
|
@ -11238,6 +11304,135 @@ Factory::DeallocPBackgroundIDBDatabaseParent(
|
|||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* WaitForTransactionsHelper
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
WaitForTransactionsHelper::WaitForTransactions()
|
||||
{
|
||||
MOZ_ASSERT(mState == State_Initial);
|
||||
|
||||
unused << this->Run();
|
||||
}
|
||||
|
||||
void
|
||||
WaitForTransactionsHelper::MaybeWaitForTransactions()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mState == State_Initial);
|
||||
|
||||
nsRefPtr<ConnectionPool> connectionPool = gConnectionPool.get();
|
||||
if (connectionPool) {
|
||||
nsTArray<nsCString> ids(1);
|
||||
ids.AppendElement(mDatabaseId);
|
||||
|
||||
mState = State_WaitingForTransactions;
|
||||
|
||||
connectionPool->WaitForDatabasesToComplete(Move(ids), this);
|
||||
return;
|
||||
}
|
||||
|
||||
DispatchToMainThread();
|
||||
}
|
||||
|
||||
void
|
||||
WaitForTransactionsHelper::DispatchToMainThread()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mState == State_Initial || mState == State_WaitingForTransactions);
|
||||
|
||||
mState = State_DispatchToMainThread;
|
||||
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(this)));
|
||||
}
|
||||
|
||||
void
|
||||
WaitForTransactionsHelper::MaybeWaitForFileHandles()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mState == State_DispatchToMainThread);
|
||||
|
||||
FileService* service = FileService::Get();
|
||||
if (service) {
|
||||
nsTArray<nsCString> ids(1);
|
||||
ids.AppendElement(mDatabaseId);
|
||||
|
||||
mState = State_WaitingForFileHandles;
|
||||
|
||||
service->WaitForStoragesToComplete(ids, this);
|
||||
|
||||
MOZ_ASSERT(ids.IsEmpty());
|
||||
return;
|
||||
}
|
||||
|
||||
DispatchToOwningThread();
|
||||
}
|
||||
|
||||
void
|
||||
WaitForTransactionsHelper::DispatchToOwningThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mState == State_DispatchToMainThread ||
|
||||
mState == State_WaitingForFileHandles);
|
||||
|
||||
mState = State_DispatchToOwningThread;
|
||||
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(mOwningThread->Dispatch(this,
|
||||
NS_DISPATCH_NORMAL)));
|
||||
}
|
||||
|
||||
void
|
||||
WaitForTransactionsHelper::CallCallback()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mState == State_DispatchToOwningThread);
|
||||
|
||||
nsCOMPtr<nsIRunnable> callback;
|
||||
mCallback.swap(callback);
|
||||
|
||||
callback->Run();
|
||||
|
||||
mState = State_Complete;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(WaitForTransactionsHelper,
|
||||
nsRunnable)
|
||||
|
||||
NS_IMETHODIMP
|
||||
WaitForTransactionsHelper::Run()
|
||||
{
|
||||
MOZ_ASSERT(mState != State_Complete);
|
||||
MOZ_ASSERT(mCallback);
|
||||
|
||||
switch (mState) {
|
||||
case State_Initial:
|
||||
MaybeWaitForTransactions();
|
||||
break;
|
||||
|
||||
case State_WaitingForTransactions:
|
||||
DispatchToMainThread();
|
||||
break;
|
||||
|
||||
case State_DispatchToMainThread:
|
||||
MaybeWaitForFileHandles();
|
||||
break;
|
||||
|
||||
case State_WaitingForFileHandles:
|
||||
DispatchToOwningThread();
|
||||
break;
|
||||
|
||||
case State_DispatchToOwningThread:
|
||||
CallCallback();
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Should never get here!");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Database
|
||||
******************************************************************************/
|
||||
|
@ -11259,6 +11454,7 @@ Database::Database(Factory* aFactory,
|
|||
, mOrigin(aOrigin)
|
||||
, mId(aMetadata->mDatabaseId)
|
||||
, mFilePath(aMetadata->mFilePath)
|
||||
, mFileHandleCount(0)
|
||||
, mPersistenceType(aMetadata->mCommonMetadata.persistenceType())
|
||||
, mChromeWriteAccessAllowed(aChromeWriteAccessAllowed)
|
||||
, mClosed(false)
|
||||
|
@ -11404,9 +11600,7 @@ Database::UnregisterTransaction(TransactionBase* aTransaction)
|
|||
|
||||
mTransactions.RemoveEntry(aTransaction);
|
||||
|
||||
if (!mTransactions.Count() && IsClosed() && mOfflineStorage) {
|
||||
CloseConnection();
|
||||
}
|
||||
MaybeCloseConnection();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -11455,31 +11649,28 @@ Database::CloseInternal()
|
|||
|
||||
if (mOfflineStorage) {
|
||||
mOfflineStorage->CloseOnOwningThread();
|
||||
|
||||
if (!mTransactions.Count()) {
|
||||
CloseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
MaybeCloseConnection();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Database::CloseConnection()
|
||||
Database::MaybeCloseConnection()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mClosed);
|
||||
MOZ_ASSERT(!mTransactions.Count());
|
||||
|
||||
if (gConnectionPool) {
|
||||
nsTArray<nsCString> ids(1);
|
||||
ids.AppendElement(Id());
|
||||
|
||||
if (!mTransactions.Count() &&
|
||||
!mFileHandleCount &&
|
||||
IsClosed() &&
|
||||
mOfflineStorage) {
|
||||
nsCOMPtr<nsIRunnable> callback =
|
||||
NS_NewRunnableMethod(this, &Database::ConnectionClosedCallback);
|
||||
gConnectionPool->WaitForDatabasesToComplete(Move(ids), callback);
|
||||
} else {
|
||||
ConnectionClosedCallback();
|
||||
|
||||
nsRefPtr<WaitForTransactionsHelper> helper =
|
||||
new WaitForTransactionsHelper(Id(), callback);
|
||||
helper->WaitForTransactions();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11489,6 +11680,7 @@ Database::ConnectionClosedCallback()
|
|||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mClosed);
|
||||
MOZ_ASSERT(!mTransactions.Count());
|
||||
MOZ_ASSERT(!mFileHandleCount);
|
||||
|
||||
if (mOfflineStorage) {
|
||||
DatabaseOfflineStorage::UnregisterOnOwningThread(mOfflineStorage.forget());
|
||||
|
@ -11804,6 +11996,43 @@ Database::RecvClose()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Database::RecvNewFileHandle()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
if (!mOfflineStorage) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mFileHandleCount == UINT32_MAX) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return false;
|
||||
}
|
||||
|
||||
++mFileHandleCount;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Database::RecvFileHandleFinished()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
if (mFileHandleCount == 0) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return false;
|
||||
}
|
||||
|
||||
--mFileHandleCount;
|
||||
|
||||
MaybeCloseConnection();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Database::
|
||||
StartTransactionOp::RunOnConnectionThread()
|
||||
|
@ -14761,22 +14990,6 @@ QuotaClient::ReleaseIOThreadObjects()
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
QuotaClient::IsFileServiceUtilized()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
QuotaClient::IsTransactionServiceActivated()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
QuotaClient::WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
|
||||
nsIRunnable* aCallback)
|
||||
|
@ -14827,7 +15040,7 @@ QuotaClient::WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
|
|||
}
|
||||
|
||||
void
|
||||
QuotaClient::ShutdownTransactionService()
|
||||
QuotaClient::ShutdownWorkThreads()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mShutdownRunnable);
|
||||
|
@ -14836,8 +15049,8 @@ QuotaClient::ShutdownTransactionService()
|
|||
mShutdownRequested = true;
|
||||
|
||||
if (mBackgroundThread) {
|
||||
nsRefPtr<ShutdownTransactionThreadPoolRunnable> runnable =
|
||||
new ShutdownTransactionThreadPoolRunnable(this);
|
||||
nsRefPtr<ShutdownWorkThreadsRunnable> runnable =
|
||||
new ShutdownWorkThreadsRunnable(this);
|
||||
|
||||
if (NS_FAILED(mBackgroundThread->Dispatch(runnable, NS_DISPATCH_NORMAL))) {
|
||||
// This can happen if the thread has shut down already.
|
||||
|
@ -14853,6 +15066,8 @@ QuotaClient::ShutdownTransactionService()
|
|||
MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(currentThread));
|
||||
}
|
||||
}
|
||||
|
||||
FileService::Shutdown();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -14977,7 +15192,7 @@ QuotaClient::GetUsageForDirectoryInternal(nsIFile* aDirectory,
|
|||
|
||||
void
|
||||
QuotaClient::
|
||||
WaitForTransactionsRunnable::MaybeWait()
|
||||
WaitForTransactionsRunnable::MaybeWaitForTransactions()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mState == State_Initial);
|
||||
|
@ -14985,27 +15200,52 @@ WaitForTransactionsRunnable::MaybeWait()
|
|||
|
||||
nsRefPtr<ConnectionPool> connectionPool = gConnectionPool.get();
|
||||
if (connectionPool) {
|
||||
// Have to copy here in case the file service needs a list too.
|
||||
nsTArray<nsCString> databaseIds(mDatabaseIds);
|
||||
|
||||
mState = State_WaitingForTransactions;
|
||||
|
||||
connectionPool->WaitForDatabasesToComplete(Move(mDatabaseIds), this);
|
||||
connectionPool->WaitForDatabasesToComplete(Move(databaseIds), this);
|
||||
return;
|
||||
}
|
||||
|
||||
DispatchToMainThread();
|
||||
}
|
||||
|
||||
void
|
||||
QuotaClient::
|
||||
WaitForTransactionsRunnable::DispatchToMainThread()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mState == State_Initial || mState == State_WaitingForTransactions);
|
||||
|
||||
mState = State_DispatchToMainThread;
|
||||
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(this)));
|
||||
}
|
||||
|
||||
void
|
||||
QuotaClient::
|
||||
WaitForTransactionsRunnable::MaybeWaitForFileHandles()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mState == State_DispatchToMainThread);
|
||||
|
||||
FileService* service = FileService::Get();
|
||||
if (service) {
|
||||
mState = State_WaitingForFileHandles;
|
||||
|
||||
service->WaitForStoragesToComplete(mDatabaseIds, this);
|
||||
|
||||
MOZ_ASSERT(mDatabaseIds.IsEmpty());
|
||||
return;
|
||||
}
|
||||
|
||||
mDatabaseIds.Clear();
|
||||
|
||||
SendToMainThread();
|
||||
}
|
||||
mState = State_WaitingForFileHandles;
|
||||
|
||||
void
|
||||
QuotaClient::
|
||||
WaitForTransactionsRunnable::SendToMainThread()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(mState == State_Initial || mState == State_WaitingForTransactions);
|
||||
|
||||
mState = State_CallingCallback;
|
||||
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(this)));
|
||||
CallCallback();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -15013,7 +15253,7 @@ QuotaClient::
|
|||
WaitForTransactionsRunnable::CallCallback()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mState == State_CallingCallback);
|
||||
MOZ_ASSERT(mState == State_WaitingForFileHandles);
|
||||
|
||||
nsRefPtr<QuotaClient> quotaClient;
|
||||
mQuotaClient.swap(quotaClient);
|
||||
|
@ -15038,14 +15278,18 @@ WaitForTransactionsRunnable::Run()
|
|||
|
||||
switch (mState) {
|
||||
case State_Initial:
|
||||
MaybeWait();
|
||||
MaybeWaitForTransactions();
|
||||
break;
|
||||
|
||||
case State_WaitingForTransactions:
|
||||
SendToMainThread();
|
||||
DispatchToMainThread();
|
||||
break;
|
||||
|
||||
case State_CallingCallback:
|
||||
case State_DispatchToMainThread:
|
||||
MaybeWaitForFileHandles();
|
||||
break;
|
||||
|
||||
case State_WaitingForFileHandles:
|
||||
CallCallback();
|
||||
break;
|
||||
|
||||
|
@ -15056,12 +15300,12 @@ WaitForTransactionsRunnable::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(QuotaClient::ShutdownTransactionThreadPoolRunnable,
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(QuotaClient::ShutdownWorkThreadsRunnable,
|
||||
nsRunnable)
|
||||
|
||||
NS_IMETHODIMP
|
||||
QuotaClient::
|
||||
ShutdownTransactionThreadPoolRunnable::Run()
|
||||
ShutdownWorkThreadsRunnable::Run()
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
MOZ_ASSERT(mHasRequestedShutDown);
|
||||
|
@ -16346,16 +16590,11 @@ FactoryOp::WaitForTransactions()
|
|||
nsTArray<nsCString> databaseIds;
|
||||
databaseIds.AppendElement(mDatabaseId);
|
||||
|
||||
nsRefPtr<ConnectionPool> connectionPool = gConnectionPool.get();
|
||||
MOZ_ASSERT(connectionPool);
|
||||
|
||||
// WaitForDatabasesToComplete() will run this op immediately if there are no
|
||||
// transactions blocking it, so be sure to set the next state here before
|
||||
// calling it.
|
||||
mState = State_WaitingForTransactionsToComplete;
|
||||
|
||||
connectionPool->WaitForDatabasesToComplete(Move(databaseIds), this);
|
||||
return;
|
||||
nsRefPtr<WaitForTransactionsHelper> helper =
|
||||
new WaitForTransactionsHelper(mDatabaseId, this);
|
||||
helper->WaitForTransactions();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -17643,17 +17882,12 @@ OpenDatabaseOp::SendResults()
|
|||
if (NS_FAILED(mResultCode) && mOfflineStorage) {
|
||||
mOfflineStorage->CloseOnOwningThread();
|
||||
|
||||
if (gConnectionPool) {
|
||||
nsTArray<nsCString> ids(1);
|
||||
ids.AppendElement(mDatabaseId);
|
||||
nsCOMPtr<nsIRunnable> callback =
|
||||
NS_NewRunnableMethod(this, &OpenDatabaseOp::ConnectionClosedCallback);
|
||||
|
||||
nsCOMPtr<nsIRunnable> callback =
|
||||
NS_NewRunnableMethod(this, &OpenDatabaseOp::ConnectionClosedCallback);
|
||||
|
||||
gConnectionPool->WaitForDatabasesToComplete(Move(ids), callback);
|
||||
} else {
|
||||
ConnectionClosedCallback();
|
||||
}
|
||||
nsRefPtr<WaitForTransactionsHelper> helper =
|
||||
new WaitForTransactionsHelper(mDatabaseId, callback);
|
||||
helper->WaitForTransactions();
|
||||
}
|
||||
|
||||
// Make sure to release the database on this thread.
|
||||
|
|
|
@ -1283,6 +1283,26 @@ IDBDatabase::NoteFinishedMutableFile(IDBMutableFile* aMutableFile)
|
|||
mLiveMutableFiles.RemoveElement(aMutableFile);
|
||||
}
|
||||
|
||||
void
|
||||
IDBDatabase::OnNewFileHandle()
|
||||
{
|
||||
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mBackgroundActor);
|
||||
|
||||
mBackgroundActor->SendNewFileHandle();
|
||||
}
|
||||
|
||||
void
|
||||
IDBDatabase::OnFileHandleFinished()
|
||||
{
|
||||
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mBackgroundActor);
|
||||
|
||||
mBackgroundActor->SendFileHandleFinished();
|
||||
}
|
||||
|
||||
void
|
||||
IDBDatabase::InvalidateMutableFiles()
|
||||
{
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче