зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1730117) for causing wpt failures in no_window_open_when_term_nesting_level_nonzero. CLOSED TREE
Backed out changeset bafc4ddc87f6 (bug 1730117) Backed out changeset 27a1d92e550c (bug 1730117)
This commit is contained in:
Родитель
58c40e3491
Коммит
8bb72e737f
|
@ -15,33 +15,6 @@
|
|||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
/**
|
||||
* Suppresses event handling and suspends for all in-process documents in a
|
||||
* BrowsingContext subtree.
|
||||
*/
|
||||
class MOZ_RAII AutoSuppressEventHandling
|
||||
: private AutoWalkBrowsingContextGroup {
|
||||
public:
|
||||
explicit AutoSuppressEventHandling(BrowsingContext* aContext) {
|
||||
if (aContext) {
|
||||
SuppressBrowsingContext(aContext);
|
||||
}
|
||||
}
|
||||
|
||||
explicit AutoSuppressEventHandling(BrowsingContextGroup* aGroup) {
|
||||
if (aGroup) {
|
||||
SuppressBrowsingContextGroup(aGroup);
|
||||
}
|
||||
}
|
||||
|
||||
~AutoSuppressEventHandling();
|
||||
|
||||
protected:
|
||||
void SuppressDocument(Document* aDocument) override;
|
||||
void UnsuppressDocument(Document* aDocument) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Suppresses event handling and suspends the active inner window for all
|
||||
* in-process documents in a BrowsingContextGroup. This should be used while
|
||||
|
@ -49,16 +22,21 @@ class MOZ_RAII AutoSuppressEventHandling
|
|||
* which affects operations in any other window in the same BrowsingContext
|
||||
* group.
|
||||
*/
|
||||
|
||||
class MOZ_RAII AutoSuppressEventHandlingAndSuspend
|
||||
: private AutoSuppressEventHandling {
|
||||
: private AutoWalkBrowsingContextGroup {
|
||||
public:
|
||||
explicit AutoSuppressEventHandlingAndSuspend(BrowsingContextGroup* aGroup)
|
||||
: AutoSuppressEventHandling(aGroup) {}
|
||||
explicit AutoSuppressEventHandlingAndSuspend(BrowsingContextGroup* aGroup) {
|
||||
if (aGroup) {
|
||||
SuppressBrowsingContextGroup(aGroup);
|
||||
}
|
||||
}
|
||||
|
||||
~AutoSuppressEventHandlingAndSuspend();
|
||||
|
||||
protected:
|
||||
void SuppressDocument(Document* aDocument) override;
|
||||
void UnsuppressDocument(Document* aDocument) override;
|
||||
|
||||
private:
|
||||
AutoTArray<nsCOMPtr<nsPIDOMWindowInner>, 16> mWindows;
|
||||
|
|
|
@ -673,7 +673,7 @@ class SameOriginCheckerImpl final : public nsIChannelEventSink,
|
|||
|
||||
} // namespace
|
||||
|
||||
void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) {
|
||||
void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) {
|
||||
// Note: Document::SuppressEventHandling will also automatically suppress
|
||||
// event handling for any in-process sub-documents. However, since we need
|
||||
// to deal with cases where remote BrowsingContexts may be interleaved
|
||||
|
@ -682,28 +682,21 @@ void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) {
|
|||
// suppressions maintain a count of current blockers, it does not cause
|
||||
// any problems.
|
||||
aDoc->SuppressEventHandling();
|
||||
}
|
||||
|
||||
void AutoSuppressEventHandling::UnsuppressDocument(Document* aDoc) {
|
||||
aDoc->UnsuppressEventHandlingAndFireEvents(true);
|
||||
}
|
||||
|
||||
AutoSuppressEventHandling::~AutoSuppressEventHandling() {
|
||||
UnsuppressDocuments();
|
||||
}
|
||||
|
||||
void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) {
|
||||
AutoSuppressEventHandling::SuppressDocument(aDoc);
|
||||
if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) {
|
||||
win->Suspend();
|
||||
mWindows.AppendElement(win);
|
||||
}
|
||||
}
|
||||
|
||||
void AutoSuppressEventHandlingAndSuspend::UnsuppressDocument(Document* aDoc) {
|
||||
aDoc->UnsuppressEventHandlingAndFireEvents(true);
|
||||
}
|
||||
|
||||
AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() {
|
||||
for (const auto& win : mWindows) {
|
||||
win->Resume();
|
||||
}
|
||||
UnsuppressDocuments();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1635,13 +1635,13 @@ nsDOMWindowUtils::DisableNonTestMouseEvents(bool aDisable) {
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SuppressEventHandling(bool aSuppress) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_STATE(window);
|
||||
nsCOMPtr<Document> doc = GetDocument();
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||
|
||||
if (aSuppress) {
|
||||
window->SuppressEventHandling();
|
||||
doc->SuppressEventHandling();
|
||||
} else {
|
||||
window->UnsuppressEventHandling();
|
||||
doc->UnsuppressEventHandlingAndFireEvents(true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -1492,7 +1492,7 @@ void nsGlobalWindowOuter::ShutDown() {
|
|||
void nsGlobalWindowOuter::DropOuterWindowDocs() {
|
||||
MOZ_ASSERT_IF(mDoc, !mDoc->EventHandlingSuppressed());
|
||||
mDoc = nullptr;
|
||||
mSuspendedDocs.Clear();
|
||||
mSuspendedDoc = nullptr;
|
||||
}
|
||||
|
||||
void nsGlobalWindowOuter::CleanUp() {
|
||||
|
@ -1597,7 +1597,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowOuter)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArguments)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuspendedDocs)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuspendedDoc)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentStoragePrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPartitionedPrincipal)
|
||||
|
@ -1629,7 +1629,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowOuter)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mArguments)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuspendedDocs)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuspendedDoc)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentStoragePrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPartitionedPrincipal)
|
||||
|
@ -2157,9 +2157,9 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument,
|
|||
mDelayedCloseForPrinting = false;
|
||||
mDelayedPrintUntilAfterLoad = false;
|
||||
|
||||
// Take this opportunity to clear mSuspendedDocs. Our old inner window is now
|
||||
// Take this opportunity to clear mSuspendedDoc. Our old inner window is now
|
||||
// responsible for unsuspending it.
|
||||
mSuspendedDocs.Clear();
|
||||
mSuspendedDoc = nullptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
mLastOpenedURI = aDocument->GetDocumentURI();
|
||||
|
@ -6356,44 +6356,6 @@ void nsGlobalWindowOuter::ReallyCloseWindow() {
|
|||
CleanUp();
|
||||
}
|
||||
|
||||
void nsGlobalWindowOuter::SuppressEventHandling() {
|
||||
if (mSuppressEventHandlingDepth == 0) {
|
||||
if (BrowsingContext* bc = GetBrowsingContext()) {
|
||||
bc->PreOrderWalk([&](BrowsingContext* aBC) {
|
||||
if (nsCOMPtr<nsPIDOMWindowOuter> win = aBC->GetDOMWindow()) {
|
||||
if (RefPtr<Document> doc = win->GetExtantDoc()) {
|
||||
mSuspendedDocs.AppendElement(doc);
|
||||
// Note: Document::SuppressEventHandling will also automatically
|
||||
// suppress event handling for any in-process sub-documents.
|
||||
// However, since we need to deal with cases where remote
|
||||
// BrowsingContexts may be interleaved with in-process ones, we
|
||||
// still need to walk the entire tree ourselves. This may be
|
||||
// slightly redundant in some cases, but since event handling
|
||||
// suppressions maintain a count of current blockers, it does not
|
||||
// cause any problems.
|
||||
doc->SuppressEventHandling();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
mSuppressEventHandlingDepth++;
|
||||
}
|
||||
|
||||
void nsGlobalWindowOuter::UnsuppressEventHandling() {
|
||||
MOZ_ASSERT(mSuppressEventHandlingDepth != 0);
|
||||
mSuppressEventHandlingDepth--;
|
||||
|
||||
if (mSuppressEventHandlingDepth == 0 && mSuspendedDocs.Length()) {
|
||||
RefPtr<Document> currentDoc = GetExtantDoc();
|
||||
bool fireEvent = currentDoc == mSuspendedDocs[0];
|
||||
nsTArray<RefPtr<Document>> suspendedDocs = std::move(mSuspendedDocs);
|
||||
for (const auto& doc : suspendedDocs) {
|
||||
doc->UnsuppressEventHandlingAndFireEvents(fireEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsGlobalWindowOuter* nsGlobalWindowOuter::EnterModalState() {
|
||||
// GetInProcessScriptableTop, not GetInProcessTop, so that EnterModalState
|
||||
// works properly with <iframe mozbrowser>.
|
||||
|
@ -6444,7 +6406,12 @@ nsGlobalWindowOuter* nsGlobalWindowOuter::EnterModalState() {
|
|||
}
|
||||
|
||||
if (topWin->mModalStateDepth == 0) {
|
||||
topWin->SuppressEventHandling();
|
||||
NS_ASSERTION(!topWin->mSuspendedDoc, "Shouldn't have mSuspendedDoc here!");
|
||||
|
||||
topWin->mSuspendedDoc = topDoc;
|
||||
if (topDoc) {
|
||||
topDoc->SuppressEventHandling();
|
||||
}
|
||||
|
||||
if (nsGlobalWindowInner* inner = topWin->GetCurrentInnerWindowInternal()) {
|
||||
inner->Suspend();
|
||||
|
@ -6478,7 +6445,12 @@ void nsGlobalWindowOuter::LeaveModalState() {
|
|||
inner->Resume();
|
||||
}
|
||||
|
||||
UnsuppressEventHandling();
|
||||
if (mSuspendedDoc) {
|
||||
nsCOMPtr<Document> currentDoc = GetExtantDoc();
|
||||
mSuspendedDoc->UnsuppressEventHandlingAndFireEvents(currentDoc ==
|
||||
mSuspendedDoc);
|
||||
mSuspendedDoc = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Remember the time of the last dialog quit.
|
||||
|
@ -7739,7 +7711,6 @@ mozilla::dom::DocGroup* nsPIDOMWindowOuter::GetDocGroup() const {
|
|||
nsPIDOMWindowOuter::nsPIDOMWindowOuter(uint64_t aWindowID)
|
||||
: mFrameElement(nullptr),
|
||||
mModalStateDepth(0),
|
||||
mSuppressEventHandlingDepth(0),
|
||||
mIsBackground(false),
|
||||
mMediaSuspend(StaticPrefs::media_block_autoplay_until_in_foreground()
|
||||
? nsISuspendedTypes::SUSPENDED_BLOCK
|
||||
|
|
|
@ -328,9 +328,6 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
|
|||
// Outer windows only.
|
||||
virtual void EnsureSizeAndPositionUpToDate() override;
|
||||
|
||||
virtual void SuppressEventHandling() override;
|
||||
virtual void UnsuppressEventHandling() override;
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual nsGlobalWindowOuter* EnterModalState()
|
||||
override;
|
||||
virtual void LeaveModalState() override;
|
||||
|
@ -1131,10 +1128,10 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
|
|||
|
||||
// It's useful when we get matched EnterModalState/LeaveModalState calls, in
|
||||
// which case the outer window is responsible for unsuspending events on the
|
||||
// documents. If we don't (for example, if the outer window is closed before
|
||||
// the LeaveModalState call), then the inner window whose mDoc is in our
|
||||
// mSuspendedDocs is responsible for unsuspending.
|
||||
nsTArray<RefPtr<Document>> mSuspendedDocs;
|
||||
// document. If we don't (for example, if the outer window is closed before
|
||||
// the LeaveModalState call), then the inner window whose mDoc is our
|
||||
// mSuspendedDoc is responsible for unsuspending it.
|
||||
RefPtr<Document> mSuspendedDoc;
|
||||
|
||||
// This is the CC generation the last time we called CanSkip.
|
||||
uint32_t mCanSkipCCGeneration;
|
||||
|
|
|
@ -910,13 +910,6 @@ class nsPIDOMWindowOuter : public mozIDOMWindowProxy {
|
|||
*/
|
||||
virtual void EnsureSizeAndPositionUpToDate() = 0;
|
||||
|
||||
/**
|
||||
* Suppresses/unsuppresses user initiated event handling in window's document
|
||||
* and all in-process descendant documents.
|
||||
*/
|
||||
virtual void SuppressEventHandling() = 0;
|
||||
virtual void UnsuppressEventHandling() = 0;
|
||||
|
||||
/**
|
||||
* Callback for notifying a window about a modal dialog being
|
||||
* opened/closed with the window as a parent.
|
||||
|
@ -1131,8 +1124,6 @@ class nsPIDOMWindowOuter : public mozIDOMWindowProxy {
|
|||
|
||||
uint32_t mModalStateDepth;
|
||||
|
||||
uint32_t mSuppressEventHandlingDepth;
|
||||
|
||||
// Tracks whether our docshell is active. If it is, mIsBackground
|
||||
// is false. Too bad we have so many different concepts of
|
||||
// "active".
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test event suppression</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>Inner</div>
|
||||
<script type="application/javascript">
|
||||
|
||||
window.onload = function() {
|
||||
top.postMessage("ready", "*");
|
||||
};
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,10 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test event suppression</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>Middle</div>
|
||||
<iframe src="http://mochi.test:8888/tests/dom/base/test/file_suppressed_events_inner.html"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -1,79 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test event suppression</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>Top</div>
|
||||
<script type="application/javascript">
|
||||
|
||||
function waitForMessage(aMsg, aCallback) {
|
||||
window.addEventListener("message", function handler(e) {
|
||||
if (e.data != aMsg) {
|
||||
return;
|
||||
}
|
||||
|
||||
info(`received: ${e.data}`);
|
||||
window.removeEventListener("message", handler);
|
||||
if (aCallback) {
|
||||
aCallback(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function waitForClickEvent(aElement, aWindow) {
|
||||
return new Promise((aResolve) => {
|
||||
aElement.addEventListener("click", aResolve, { once: true });
|
||||
synthesizeMouseAtCenter(aElement, { type: "mousedown" }, aWindow);
|
||||
synthesizeMouseAtCenter(aElement, { type: "mouseup" }, aWindow);
|
||||
});
|
||||
}
|
||||
|
||||
waitForMessage("ready", async function(e) {
|
||||
await waitUntilApzStable();
|
||||
|
||||
let innerWin = e.source;
|
||||
let innerDiv = innerWin.document.querySelector("div");
|
||||
|
||||
let eventCount = 0;
|
||||
innerDiv.addEventListener("mousemove", function() {
|
||||
eventCount++;
|
||||
});
|
||||
|
||||
// Test that event handling is suppressed.
|
||||
let utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
utils.suppressEventHandling(true);
|
||||
const TOTAL = 100;
|
||||
for (let i = 0; i < TOTAL; i++) {
|
||||
synthesizeMouseAtCenter(innerDiv, { type: "mousemove" }, innerWin);
|
||||
}
|
||||
utils.suppressEventHandling(false);
|
||||
|
||||
// Wait for click event to ensure we have received all mousemove events.
|
||||
await waitForClickEvent(innerDiv, innerWin);
|
||||
opener.info(`eventCount: ${eventCount}`);
|
||||
opener.ok(eventCount < TOTAL, "event should be suspressed");
|
||||
|
||||
// Test that event handling is not suppressed.
|
||||
eventCount = 0;
|
||||
for (let i = 0; i < TOTAL; i++) {
|
||||
synthesizeMouseAtCenter(innerDiv, { type: "mousemove" }, innerWin);
|
||||
}
|
||||
|
||||
// Wait for click event to ensure we have received all mousemove events.
|
||||
await waitForClickEvent(innerDiv, innerWin);
|
||||
opener.info(`eventCount: ${eventCount}`);
|
||||
opener.is(eventCount, TOTAL, "event should not be suspressed");
|
||||
|
||||
opener.postMessage("done", "*");
|
||||
});
|
||||
|
||||
</script>
|
||||
<iframe src="http://example.org/tests/dom/base/test/file_suppressed_events_middle.html"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -1,79 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test event suppression</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>Top</div>
|
||||
<script type="application/javascript">
|
||||
|
||||
function waitForMessage(aMsg, aCallback) {
|
||||
window.addEventListener("message", function handler(e) {
|
||||
if (e.data != aMsg) {
|
||||
return;
|
||||
}
|
||||
|
||||
info(`received: ${e.data}`);
|
||||
window.removeEventListener("message", handler);
|
||||
if (aCallback) {
|
||||
aCallback(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function waitForClickEvent(aElement, aWindow) {
|
||||
return new Promise((aResolve) => {
|
||||
aElement.addEventListener("click", aResolve, { once: true });
|
||||
synthesizeMouseAtCenter(aElement, { type: "mousedown" }, aWindow);
|
||||
synthesizeMouseAtCenter(aElement, { type: "mouseup" }, aWindow);
|
||||
});
|
||||
}
|
||||
|
||||
waitForMessage("ready", async function(e) {
|
||||
await waitUntilApzStable();
|
||||
|
||||
let innerWin = e.source;
|
||||
let innerDiv = innerWin.document.querySelector("div");
|
||||
|
||||
let eventCount = 0;
|
||||
innerDiv.addEventListener("mousemove", function() {
|
||||
eventCount++;
|
||||
});
|
||||
|
||||
// Test that event handling is suppressed.
|
||||
let utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
utils.enterModalState();
|
||||
const TOTAL = 100;
|
||||
for (let i = 0; i < TOTAL; i++) {
|
||||
synthesizeMouseAtCenter(innerDiv, { type: "mousemove" }, innerWin);
|
||||
}
|
||||
utils.leaveModalState();
|
||||
|
||||
// Wait for click event to ensure we have received all mousemove events.
|
||||
await waitForClickEvent(innerDiv, innerWin);
|
||||
opener.info(`eventCount: ${eventCount}`);
|
||||
opener.ok(eventCount < TOTAL, "event should be suspressed");
|
||||
|
||||
// Test that event handling is not suppressed.
|
||||
eventCount = 0;
|
||||
for (let i = 0; i < TOTAL; i++) {
|
||||
synthesizeMouseAtCenter(innerDiv, { type: "mousemove" }, innerWin);
|
||||
}
|
||||
|
||||
// Wait for click event to ensure we have received all mousemove events.
|
||||
await waitForClickEvent(innerDiv, innerWin);
|
||||
opener.info(`eventCount: ${eventCount}`);
|
||||
opener.is(eventCount, TOTAL, "event should not be suspressed");
|
||||
|
||||
opener.postMessage("done", "*");
|
||||
});
|
||||
|
||||
</script>
|
||||
<iframe src="http://example.org/tests/dom/base/test/file_suppressed_events_middle.html"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -1,82 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test event suppression</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>Top</div>
|
||||
<script type="application/javascript">
|
||||
|
||||
function waitForMessage(aMsg, aCallback) {
|
||||
window.addEventListener("message", function handler(e) {
|
||||
if (e.data != aMsg) {
|
||||
return;
|
||||
}
|
||||
|
||||
info(`received: ${e.data}`);
|
||||
window.removeEventListener("message", handler);
|
||||
if (aCallback) {
|
||||
aCallback(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function waitForClickEvent(aElement, aWindow) {
|
||||
return new Promise((aResolve) => {
|
||||
aElement.addEventListener("click", aResolve, { once: true });
|
||||
synthesizeMouseAtCenter(aElement, { type: "mousedown" }, aWindow);
|
||||
synthesizeMouseAtCenter(aElement, { type: "mouseup" }, aWindow);
|
||||
});
|
||||
}
|
||||
|
||||
waitForMessage("ready", async function(e) {
|
||||
await waitUntilApzStable();
|
||||
|
||||
let innerWin = e.source;
|
||||
let innerDiv = innerWin.document.querySelector("div");
|
||||
|
||||
let eventCount = 0;
|
||||
innerDiv.addEventListener("mousemove", function() {
|
||||
eventCount++;
|
||||
});
|
||||
|
||||
// Test that event handling is suppressed.
|
||||
let xhr = new XMLHttpRequest();
|
||||
opener.info("xhr open");
|
||||
xhr.open('GET', 'slow.sjs', false);
|
||||
|
||||
const TOTAL = 100;
|
||||
for (let i = 0; i < TOTAL; i++) {
|
||||
synthesizeMouseAtCenter(innerDiv, { type: "mousemove" }, innerWin);
|
||||
}
|
||||
xhr.send();
|
||||
opener.info(`xhr done`);
|
||||
|
||||
// Wait for click event to ensure we have received all mousemove events.
|
||||
await waitForClickEvent(innerDiv, innerWin);
|
||||
opener.info(`eventCount: ${eventCount}`);
|
||||
opener.ok(eventCount < TOTAL, "event should be suspressed");
|
||||
|
||||
// Test that event handling is not suppressed.
|
||||
eventCount = 0;
|
||||
for (let i = 0; i < TOTAL; i++) {
|
||||
synthesizeMouseAtCenter(innerDiv, { type: "mousemove" }, innerWin);
|
||||
}
|
||||
|
||||
// Wait for click event to ensure we have received all mousemove events.
|
||||
await waitForClickEvent(innerDiv, innerWin);
|
||||
opener.info(`eventCount: ${eventCount}`);
|
||||
opener.is(eventCount, TOTAL, "event should not be suspressed");
|
||||
|
||||
opener.postMessage("done", "*");
|
||||
});
|
||||
|
||||
</script>
|
||||
<iframe src="http://example.org/tests/dom/base/test/file_suppressed_events_middle.html"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -774,15 +774,6 @@ skip-if = debug == false
|
|||
[test_suppressed_events_and_scrolling.html]
|
||||
support-files =
|
||||
file_suppressed_events_and_scrolling.html
|
||||
[test_suppressed_events_nested_iframe.html]
|
||||
skip-if = os == "android"
|
||||
support-files =
|
||||
file_suppressed_events_top_xhr.html
|
||||
file_suppressed_events_top_modalstate.html
|
||||
file_suppressed_events_top.html
|
||||
file_suppressed_events_middle.html
|
||||
file_suppressed_events_inner.html
|
||||
!/gfx/layers/apz/test/mochitest/apz_test_utils.js
|
||||
[test_suppressed_microtasks.html]
|
||||
skip-if = debug || asan || verify || toolkit == 'android' # The test needs to run reasonably fast.
|
||||
[test_text_wholeText.html]
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1730117
|
||||
-->
|
||||
<head>
|
||||
<title>Test event suppression on nested iframe</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1730117">Mozilla Bug 1730117</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
function waitForMessage(aMsg) {
|
||||
return new Promise((aResolve) => {
|
||||
window.addEventListener("message", function handler(e) {
|
||||
info(`receive: ${e.data}`);
|
||||
if (e.data != aMsg) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.removeEventListener("message", handler);
|
||||
aResolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** Test for Bug 1730117 **/
|
||||
|
||||
add_task(async function test_sync_xhr() {
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["test.events.async.enabled", true],
|
||||
["dom.events.coalesce.mousemove", false],
|
||||
]});
|
||||
|
||||
let w = window.open("file_suppressed_events_top_xhr.html");
|
||||
await waitForMessage("done");
|
||||
w.close();
|
||||
});
|
||||
|
||||
add_task(async function test_modalstate() {
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["test.events.async.enabled", false],
|
||||
["dom.events.coalesce.mousemove", false],
|
||||
]});
|
||||
|
||||
let w = window.open("file_suppressed_events_top_modalstate.html");
|
||||
await waitForMessage("done");
|
||||
w.close();
|
||||
});
|
||||
|
||||
add_task(async function test_suppress_event_handling() {
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["test.events.async.enabled", false],
|
||||
["dom.events.coalesce.mousemove", false],
|
||||
]});
|
||||
|
||||
let w = window.open("file_suppressed_events_top.html");
|
||||
await waitForMessage("done");
|
||||
w.close();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -14,7 +14,6 @@
|
|||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/Components.h"
|
||||
#include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
|
||||
#include "mozilla/dom/BlobBinding.h"
|
||||
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
|
@ -2798,10 +2797,15 @@ void XMLHttpRequestMainThread::EnsureChannelContentType() {
|
|||
}
|
||||
}
|
||||
|
||||
void XMLHttpRequestMainThread::ResumeTimeout() {
|
||||
void XMLHttpRequestMainThread::UnsuppressEventHandlingAndResume() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mFlagSynchronous);
|
||||
|
||||
if (mSuspendedDoc) {
|
||||
mSuspendedDoc->UnsuppressEventHandlingAndFireEvents(true);
|
||||
mSuspendedDoc = nullptr;
|
||||
}
|
||||
|
||||
if (mResumeTimeoutRunnable) {
|
||||
DispatchToMainThread(mResumeTimeoutRunnable.forget());
|
||||
mResumeTimeoutRunnable = nullptr;
|
||||
|
@ -3024,15 +3028,7 @@ void XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody,
|
|||
mFlagSend = true;
|
||||
|
||||
// If we're synchronous, spin an event loop here and wait
|
||||
RefPtr<Document> suspendedDoc;
|
||||
if (mFlagSynchronous) {
|
||||
auto scopeExit = MakeScopeExit([&] {
|
||||
CancelSyncTimeoutTimer();
|
||||
ResumeTimeout();
|
||||
ResumeEventDispatching();
|
||||
});
|
||||
Maybe<AutoSuppressEventHandling> autoSuppress;
|
||||
|
||||
mFlagSyncLooping = true;
|
||||
|
||||
if (GetOwner()) {
|
||||
|
@ -3040,8 +3036,10 @@ void XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody,
|
|||
GetOwner()->GetOuterWindow()->GetInProcessTop()) {
|
||||
if (nsCOMPtr<nsPIDOMWindowInner> topInner =
|
||||
topWindow->GetCurrentInnerWindow()) {
|
||||
suspendedDoc = topWindow->GetExtantDoc();
|
||||
autoSuppress.emplace(topWindow->GetBrowsingContext());
|
||||
mSuspendedDoc = topWindow->GetExtantDoc();
|
||||
if (mSuspendedDoc) {
|
||||
mSuspendedDoc->SuppressEventHandling();
|
||||
}
|
||||
topInner->Suspend();
|
||||
mResumeTimeoutRunnable = new nsResumeTimeoutsEvent(topInner);
|
||||
}
|
||||
|
@ -3050,6 +3048,11 @@ void XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody,
|
|||
|
||||
SuspendEventDispatching();
|
||||
StopProgressEventTimer();
|
||||
auto scopeExit = MakeScopeExit([&] {
|
||||
CancelSyncTimeoutTimer();
|
||||
UnsuppressEventHandlingAndResume();
|
||||
ResumeEventDispatching();
|
||||
});
|
||||
|
||||
SyncTimeoutType syncTimeoutType = MaybeStartSyncTimeoutTimer();
|
||||
if (syncTimeoutType == eErrorOrExpired) {
|
||||
|
@ -3058,7 +3061,7 @@ void XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody,
|
|||
return;
|
||||
}
|
||||
|
||||
nsAutoSyncOperation sync(suspendedDoc,
|
||||
nsAutoSyncOperation sync(mSuspendedDoc,
|
||||
SyncOperationBehavior::eSuspendInput);
|
||||
if (!SpinEventLoopUntil([&]() { return !mFlagSyncLooping; })) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
|
|
|
@ -304,7 +304,7 @@ class XMLHttpRequestMainThread final : public XMLHttpRequest,
|
|||
bool IsCrossSiteCORSRequest() const;
|
||||
bool IsDeniedCrossSiteCORSRequest();
|
||||
|
||||
void ResumeTimeout();
|
||||
void UnsuppressEventHandlingAndResume();
|
||||
|
||||
void MaybeLowerChannelPriority();
|
||||
|
||||
|
@ -679,6 +679,7 @@ class XMLHttpRequestMainThread final : public XMLHttpRequest,
|
|||
void StartTimeoutTimer();
|
||||
void HandleTimeoutCallback();
|
||||
|
||||
RefPtr<Document> mSuspendedDoc;
|
||||
nsCOMPtr<nsIRunnable> mResumeTimeoutRunnable;
|
||||
|
||||
nsCOMPtr<nsITimer> mSyncTimeoutTimer;
|
||||
|
|
Загрузка…
Ссылка в новой задаче