From c73140a5cf3fed4e0a422ba9e6f000551bbfa5dc Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Thu, 3 Jan 2019 06:39:12 -1000 Subject: [PATCH] Bug 1177346 Part 1 - Add setSuppressedEventListener interface, r=smaug. --HG-- extra : rebase_source : a01b747e49f06fe6ef7724e38648ea28601b2793 --- dom/base/Document.cpp | 13 +++++++++++++ dom/base/Document.h | 8 ++++++++ dom/webidl/Document.webidl | 8 ++++++++ layout/base/PresShell.cpp | 22 ++++++++++++++++++++++ 4 files changed, 51 insertions(+) diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index c74f486389a7..d0fc811f7920 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -1746,6 +1746,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(Document) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnonymousContents) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCommandDispatcher) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFeaturePolicy) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuppressedEventListener) // Traverse all our nsCOMArrays. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheets) @@ -1837,6 +1838,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Document) NS_IMPL_CYCLE_COLLECTION_UNLINK(mCommandDispatcher) NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentL10n); NS_IMPL_CYCLE_COLLECTION_UNLINK(mFeaturePolicy) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuppressedEventListener) tmp->mParentDocument = nullptr; @@ -8492,6 +8494,17 @@ void Document::AddSuspendedChannelEventQueue(net::ChannelEventQueue* aQueue) { mSuspendedQueues.AppendElement(aQueue); } +static bool SetSuppressedEventListenerInSubDocument(Document* aDocument, + void* aData) { + aDocument->SetSuppressedEventListener(static_cast(aData)); + return true; +} + +void Document::SetSuppressedEventListener(EventListener* aListener) { + mSuppressedEventListener = aListener; + EnumerateSubDocuments(SetSuppressedEventListenerInSubDocument, aListener); +} + nsISupports* Document::GetCurrentContentSink() { return mParser ? mParser->GetContentSink() : nullptr; } diff --git a/dom/base/Document.h b/dom/base/Document.h index 672da1f8c6b4..b2bb6e79508b 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -2446,6 +2446,12 @@ class Document : public nsINode, */ bool IsVisibleConsideringAncestors() const; + void SetSuppressedEventListener(EventListener* aListener); + + EventListener* GetSuppressedEventListener() { + return mSuppressedEventListener; + } + /** * Return true when this document is active, i.e., an active document * in a content viewer. Note that this will return true for bfcached @@ -4137,6 +4143,8 @@ class Document : public nsINode, // events were suppressed. nsTArray> mSuspendedQueues; + RefPtr mSuppressedEventListener; + /** * https://html.spec.whatwg.org/#ignore-destructive-writes-counter */ diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index 50d41efc9388..600d7609833d 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -505,6 +505,14 @@ partial interface Document { void notifyUserGestureActivation(); }; +// Extension to give chrome JS the ability to set an event handler which is +// called with certain events that happened while events were suppressed in the +// document or one of its subdocuments. +partial interface Document { + [ChromeOnly] + void setSuppressedEventListener(EventListener? aListener); +}; + // Extension to give chrome and XBL JS the ability to determine whether // the document is sandboxed without permission to run scripts // and whether inline scripts are blocked by the document's CSP. diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index 5f2b9d24e119..17f39627a61b 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -6785,6 +6785,28 @@ nsresult PresShell::HandleEvent(nsIFrame* aFrame, WidgetGUIEvent* aEvent, auto event = MakeUnique(aEvent->AsMouseEvent()); mDelayedEvents.AppendElement(std::move(event)); } + + // If there is a suppressed event listener associated with the document, + // notify it about the suppressed mouse event. This allows devtools + // features to continue receiving mouse events even when the devtools + // debugger has paused execution in a page. + RefPtr suppressedListener = + frame->PresContext()->Document()->GetSuppressedEventListener(); + if (suppressedListener && + aEvent->AsMouseEvent()->mReason != WidgetMouseEvent::eSynthesized) { + nsCOMPtr targetContent; + frame->GetContentForEvent(aEvent, getter_AddRefs(targetContent)); + if (targetContent) { + aEvent->mTarget = targetContent; + } + + nsCOMPtr et = aEvent->mTarget; + RefPtr event = EventDispatcher::CreateEvent( + et, frame->PresContext(), aEvent, EmptyString()); + + suppressedListener->HandleEvent(*event); + } + return NS_OK; }