Skip to content

Commit

Permalink
Bug 1680611 - part 1: Mark all nsFocusManager methods whose names e…
Browse files Browse the repository at this point in the history
…xplain that they may dispatch events as `MOZ_CAN_RUN_SCRIPT` r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D147060
  • Loading branch information
masayuki-nakano committed May 26, 2022
1 parent ce08aec commit 498eae6
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 40 deletions.
34 changes: 20 additions & 14 deletions dom/base/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12261,24 +12261,28 @@ void Document::NotifyAbortedLoad() {
}
}

static void FireOrClearDelayedEvents(nsTArray<nsCOMPtr<Document>>& aDocuments,
bool aFireEvents) {
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (!fm) return;
MOZ_CAN_RUN_SCRIPT static void FireOrClearDelayedEvents(
nsTArray<nsCOMPtr<Document>>&& aDocuments, bool aFireEvents) {
RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
if (MOZ_UNLIKELY(!fm)) {
return;
}

for (uint32_t i = 0; i < aDocuments.Length(); ++i) {
nsTArray<nsCOMPtr<Document>> documents = std::move(aDocuments);
for (uint32_t i = 0; i < documents.Length(); ++i) {
nsCOMPtr<Document> 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> presShell = aDocuments[i]->GetPresShell();
if (!document->EventHandlingSuppressed()) {
fm->FireDelayedEvents(document);
RefPtr<PresShell> 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);
}
}
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
}
}

Expand Down
3 changes: 2 additions & 1 deletion dom/base/Document.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand Down
43 changes: 23 additions & 20 deletions dom/base/nsFocusManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Element> oldFocusedElement = std::move(mFocusedElement);
const RefPtr<Element> oldFocusedElement = std::move(mFocusedElement);

nsCOMPtr<nsIDocShell> focusedDocShell = mFocusedWindow->GetDocShell();
if (!focusedDocShell) {
return;
}

RefPtr<PresShell> presShell = focusedDocShell->GetPresShell();
const RefPtr<PresShell> 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<Document> composedDoc = oldFocusedElement->GetComposedDoc();
SendFocusOrBlurEvent(eBlur, presShell, composedDoc, oldFocusedElement,
false);
}
}

Expand Down Expand Up @@ -2434,13 +2434,15 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear,
SetFocusedWindowInternal(nullptr, aActionId);
mFocusedElement = nullptr;

Document* doc = window->GetExtantDoc();
RefPtr<Document> 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<nsPIDOMWindowInner> innerWindow =
window->GetCurrentInnerWindow();
SendFocusOrBlurEvent(eBlur, presShell, doc, innerWindow, false);
}

// check if a different window was focused
Expand Down Expand Up @@ -2496,7 +2498,7 @@ void nsFocusManager::Focus(
return;
}

RefPtr<PresShell> presShell = docShell->GetPresShell();
const RefPtr<PresShell> presShell = docShell->GetPresShell();
if (!presShell) {
return;
}
Expand Down Expand Up @@ -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<Document> 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
Expand All @@ -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<nsPIDOMWindowInner> innerWindow =
aWindow->GetCurrentInnerWindow();
SendFocusOrBlurEvent(eFocus, presShell, doc, innerWindow, aWindowRaised);
}
}

Expand Down Expand Up @@ -2659,11 +2662,11 @@ void nsFocusManager::Focus(
}

if (!focusInOtherContentProcess) {
SendFocusOrBlurEvent(eFocus, presShell, aElement->GetComposedDoc(),
aElement, aWindowRaised, isRefocus,
aBlurredElementInfo
? aBlurredElementInfo->mElement.get()
: nullptr);
RefPtr<Document> composedDocument = aElement->GetComposedDoc();
RefPtr<Element> relatedTargetElement =
aBlurredElementInfo ? aBlurredElementInfo->mElement.get() : nullptr;
SendFocusOrBlurEvent(eFocus, presShell, composedDocument, aElement,
aWindowRaised, isRefocus, relatedTargetElement);
}
} else {
IMEStateManager::OnChangeFocus(presContext, nullptr,
Expand Down
11 changes: 6 additions & 5 deletions dom/base/nsFocusManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand All @@ -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,
Expand Down

0 comments on commit 498eae6

Please sign in to comment.