From 498eae63287e2198f7ed3af85a8366e9d2259091 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Thu, 26 May 2022 04:37:17 +0000 Subject: [PATCH] Bug 1680611 - part 1: Mark all `nsFocusManager` methods whose names explain that they may dispatch events as `MOZ_CAN_RUN_SCRIPT` r=smaug Differential Revision: https://phabricator.services.mozilla.com/D147060 --- dom/base/Document.cpp | 34 +++++++++++++++++------------ dom/base/Document.h | 3 ++- dom/base/nsFocusManager.cpp | 43 ++++++++++++++++++++----------------- dom/base/nsFocusManager.h | 11 +++++----- 4 files changed, 51 insertions(+), 40 deletions(-) diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index eebe7c2810e65..b8e940b3ec868 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -12261,24 +12261,28 @@ void Document::NotifyAbortedLoad() { } } -static void FireOrClearDelayedEvents(nsTArray>& aDocuments, - bool aFireEvents) { - nsFocusManager* fm = nsFocusManager::GetFocusManager(); - if (!fm) return; +MOZ_CAN_RUN_SCRIPT static void FireOrClearDelayedEvents( + nsTArray>&& aDocuments, bool aFireEvents) { + RefPtr fm = nsFocusManager::GetFocusManager(); + if (MOZ_UNLIKELY(!fm)) { + return; + } - for (uint32_t i = 0; i < aDocuments.Length(); ++i) { + nsTArray> documents = std::move(aDocuments); + for (uint32_t i = 0; i < documents.Length(); ++i) { + nsCOMPtr document = std::move(documents[i]); // NB: Don't bother trying to fire delayed events on documents that were // closed before this event ran. - if (!aDocuments[i]->EventHandlingSuppressed()) { - fm->FireDelayedEvents(aDocuments[i]); - RefPtr presShell = aDocuments[i]->GetPresShell(); + if (!document->EventHandlingSuppressed()) { + fm->FireDelayedEvents(document); + RefPtr presShell = document->GetPresShell(); if (presShell) { // Only fire events for active documents. - bool fire = aFireEvents && aDocuments[i]->GetInnerWindow() && - aDocuments[i]->GetInnerWindow()->IsCurrentInnerWindow(); + bool fire = aFireEvents && document->GetInnerWindow() && + document->GetInnerWindow()->IsCurrentInnerWindow(); presShell->FireOrClearDelayedEvents(fire); } - aDocuments[i]->FireOrClearPostMessageEvents(aFireEvents); + document->FireOrClearPostMessageEvents(aFireEvents); } } } @@ -12612,8 +12616,10 @@ class nsDelayedEventDispatcher : public Runnable { mDocuments(std::move(aDocuments)) {} virtual ~nsDelayedEventDispatcher() = default; - NS_IMETHOD Run() override { - FireOrClearDelayedEvents(mDocuments, true); + // MOZ_CAN_RUN_SCRIPT_BOUNDARY until Runnable::Run is MOZ_CAN_RUN_SCRIPT. See + // bug 1535398. + MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD Run() override { + FireOrClearDelayedEvents(std::move(mDocuments), true); return NS_OK; } @@ -12674,7 +12680,7 @@ void Document::UnsuppressEventHandlingAndFireEvents(bool aFireEvents) { new nsDelayedEventDispatcher(std::move(documents)); Dispatch(TaskCategory::Other, ded.forget()); } else { - FireOrClearDelayedEvents(documents, false); + FireOrClearDelayedEvents(std::move(documents), false); } } diff --git a/dom/base/Document.h b/dom/base/Document.h index 9a34d59ca545b..d04aee703c53e 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -2772,7 +2772,8 @@ class Document : public nsINode, * @param aFireEvents If true, delayed events (focus/blur) will be fired * asynchronously. */ - void UnsuppressEventHandlingAndFireEvents(bool aFireEvents); + MOZ_CAN_RUN_SCRIPT_BOUNDARY void UnsuppressEventHandlingAndFireEvents( + bool aFireEvents); uint32_t EventHandlingSuppressed() const { return mEventsSuppressed; } diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index ffeb42544dccb..68903676cfcb5 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -1038,23 +1038,23 @@ void nsFocusManager::WindowHidden(mozIDOMWindowProxy* aWindow, // window, or an ancestor of the focused window. Either way, the focus is no // longer valid, so it needs to be updated. - RefPtr oldFocusedElement = std::move(mFocusedElement); + const RefPtr oldFocusedElement = std::move(mFocusedElement); nsCOMPtr focusedDocShell = mFocusedWindow->GetDocShell(); if (!focusedDocShell) { return; } - RefPtr presShell = focusedDocShell->GetPresShell(); + const RefPtr presShell = focusedDocShell->GetPresShell(); if (oldFocusedElement && oldFocusedElement->IsInComposedDoc()) { NotifyFocusStateChange(oldFocusedElement, nullptr, 0, false, false); window->UpdateCommands(u"focus"_ns, nullptr, 0); if (presShell) { - SendFocusOrBlurEvent(eBlur, presShell, - oldFocusedElement->GetComposedDoc(), - oldFocusedElement, false); + RefPtr composedDoc = oldFocusedElement->GetComposedDoc(); + SendFocusOrBlurEvent(eBlur, presShell, composedDoc, oldFocusedElement, + false); } } @@ -2434,13 +2434,15 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, SetFocusedWindowInternal(nullptr, aActionId); mFocusedElement = nullptr; - Document* doc = window->GetExtantDoc(); + RefPtr doc = window->GetExtantDoc(); if (doc) { - SendFocusOrBlurEvent(eBlur, presShell, doc, ToSupports(doc), false); + SendFocusOrBlurEvent(eBlur, presShell, doc, + MOZ_KnownLive(ToSupports(doc)), false); } if (!GetFocusedBrowsingContext()) { - SendFocusOrBlurEvent(eBlur, presShell, doc, - window->GetCurrentInnerWindow(), false); + nsCOMPtr innerWindow = + window->GetCurrentInnerWindow(); + SendFocusOrBlurEvent(eBlur, presShell, doc, innerWindow, false); } // check if a different window was focused @@ -2496,7 +2498,7 @@ void nsFocusManager::Focus( return; } - RefPtr presShell = docShell->GetPresShell(); + const RefPtr presShell = docShell->GetPresShell(); if (!presShell) { return; } @@ -2594,7 +2596,7 @@ void nsFocusManager::Focus( // if switching to a new document, first fire the focus event on the // document and then the window. if (aIsNewDocument) { - Document* doc = aWindow->GetExtantDoc(); + RefPtr doc = aWindow->GetExtantDoc(); // The focus change should be notified to IMEStateManager from here if: // * the focused element is in design mode or // * nobody gets focus and the document is in design mode @@ -2606,13 +2608,14 @@ void nsFocusManager::Focus( GetFocusMoveActionCause(aFlags)); } if (doc && !focusInOtherContentProcess) { - SendFocusOrBlurEvent(eFocus, presShell, doc, ToSupports(doc), - aWindowRaised); + SendFocusOrBlurEvent(eFocus, presShell, doc, + MOZ_KnownLive(ToSupports(doc)), aWindowRaised); } if (GetFocusedBrowsingContext() == aWindow->GetBrowsingContext() && !mFocusedElement && !focusInOtherContentProcess) { - SendFocusOrBlurEvent(eFocus, presShell, doc, - aWindow->GetCurrentInnerWindow(), aWindowRaised); + nsCOMPtr innerWindow = + aWindow->GetCurrentInnerWindow(); + SendFocusOrBlurEvent(eFocus, presShell, doc, innerWindow, aWindowRaised); } } @@ -2659,11 +2662,11 @@ void nsFocusManager::Focus( } if (!focusInOtherContentProcess) { - SendFocusOrBlurEvent(eFocus, presShell, aElement->GetComposedDoc(), - aElement, aWindowRaised, isRefocus, - aBlurredElementInfo - ? aBlurredElementInfo->mElement.get() - : nullptr); + RefPtr composedDocument = aElement->GetComposedDoc(); + RefPtr relatedTargetElement = + aBlurredElementInfo ? aBlurredElementInfo->mElement.get() : nullptr; + SendFocusOrBlurEvent(eFocus, presShell, composedDocument, aElement, + aWindowRaised, isRefocus, relatedTargetElement); } } else { IMEStateManager::OnChangeFocus(presContext, nullptr, diff --git a/dom/base/nsFocusManager.h b/dom/base/nsFocusManager.h index fc54a7945942a..c2ba6df550726 100644 --- a/dom/base/nsFocusManager.h +++ b/dom/base/nsFocusManager.h @@ -251,12 +251,13 @@ class nsFocusManager final : public nsIFocusManager, * Called when a document in a window has been hidden or otherwise can no * longer accept focus. */ - void WindowHidden(mozIDOMWindowProxy* aWindow, uint64_t aActionId); + MOZ_CAN_RUN_SCRIPT_BOUNDARY void WindowHidden(mozIDOMWindowProxy* aWindow, + uint64_t aActionId); /** * Fire any events that have been delayed due to synchronized actions. */ - void FireDelayedEvents(Document* aDocument); + MOZ_CAN_RUN_SCRIPT void FireDelayedEvents(Document* aDocument); void WasNuked(nsPIDOMWindowOuter* aWindow); @@ -480,7 +481,7 @@ class nsFocusManager final : public nsIFocusManager, * * aWindowRaised should only be true if called from WindowRaised. */ - void SendFocusOrBlurEvent( + MOZ_CAN_RUN_SCRIPT void SendFocusOrBlurEvent( mozilla::EventMessage aEventMessage, mozilla::PresShell* aPresShell, Document* aDocument, nsISupports* aTarget, bool aWindowRaised, bool aIsRefocus = false, @@ -493,7 +494,7 @@ class nsFocusManager final : public nsIFocusManager, * * aWindowRaised should only be true if called from WindowRaised. */ - void FireFocusOrBlurEvent( + MOZ_CAN_RUN_SCRIPT void FireFocusOrBlurEvent( mozilla::EventMessage aEventMessage, mozilla::PresShell* aPresShell, nsISupports* aTarget, bool aWindowRaised, bool aIsRefocus = false, mozilla::dom::EventTarget* aRelatedTarget = nullptr); @@ -515,7 +516,7 @@ class nsFocusManager final : public nsIFocusManager, * aRelatedTarget is the content related to the event (the object * losing focus for focusin, the object getting focus for focusout). */ - void FireFocusInOrOutEvent( + MOZ_CAN_RUN_SCRIPT void FireFocusInOrOutEvent( mozilla::EventMessage aEventMessage, mozilla::PresShell* aPresShell, nsISupports* aTarget, nsPIDOMWindowOuter* aCurrentFocusedWindow, nsIContent* aCurrentFocusedContent,