This commit is contained in:
Ryan VanderMeulen 2015-04-14 16:01:51 -04:00
Родитель 2d03e67eb1 4fa8326641
Коммит 16c36d245d
359 изменённых файлов: 7463 добавлений и 5370 удалений

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

@ -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);

14
dom/cache/QuotaClient.cpp поставляемый
Просмотреть файл

@ -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

Двоичный файл не отображается.

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

@ -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()
{

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