From cdfbc99cdf18ddc9e4f5f9722ac21d13979cdd7e Mon Sep 17 00:00:00 2001
From: Masayuki Nakano <masayuki@d-toybox.com>
Date: Thu, 26 May 2022 04:37:19 +0000
Subject: [PATCH] Bug 1680611 - part 6: Mark
 `nsFocusManager::MoveCaretToFocus()` and its callers in `nsFocusManager` as
 `MOZ_CAN_RUN_SCRIPT` r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D147065
---
 dom/base/nsFocusManager.cpp                   | 20 +++++++++++--------
 dom/base/nsFocusManager.h                     | 16 ++++++++-------
 dom/interfaces/base/nsIFocusManager.idl       |  1 +
 editor/libeditor/EditorBase.cpp               |  4 +++-
 editor/libeditor/EditorBase.h                 |  2 +-
 .../typeaheadfind/nsTypeAheadFind.cpp         |  5 ++---
 6 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp
index cb12fe5ad1ebc..3ee9fc3b7437d 100644
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -216,7 +216,9 @@ void nsFocusManager::Shutdown() { sInstance = nullptr; }
 
 // static
 void nsFocusManager::PrefChanged(const char* aPref, void* aSelf) {
-  static_cast<nsFocusManager*>(aSelf)->PrefChanged(aPref);
+  if (RefPtr<nsFocusManager> fm = static_cast<nsFocusManager*>(aSelf)) {
+    fm->PrefChanged(aPref);
+  }
 }
 
 void nsFocusManager::PrefChanged(const char* aPref) {
@@ -643,9 +645,8 @@ nsFocusManager::MoveCaretToFocus(mozIDOMWindowProxy* aWindow) {
       NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
       nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
-      nsCOMPtr<nsIContent> content = window->GetFocusedElement();
-      if (content) {
-        MoveCaretToFocus(presShell, content);
+      if (RefPtr<Element> focusedElement = window->GetFocusedElement()) {
+        MoveCaretToFocus(presShell, focusedElement);
       }
     }
   }
@@ -2693,9 +2694,11 @@ void nsFocusManager::Focus(
   // needed. If this is a different document than was focused before, also
   // update the caret's visibility. If this is the same document, the caret
   // visibility should be the same as before so there is no need to update it.
-  if (mFocusedElement == aElement)
+  if (mFocusedElement == aElement) {
+    RefPtr<Element> focusedElement = mFocusedElement;
     UpdateCaret(aFocusChanged && !(aFlags & FLAG_BYMOUSE), aIsNewDocument,
-                mFocusedElement);
+                focusedElement);
+  }
 }
 
 class FocusBlurEvent : public Runnable {
@@ -2995,7 +2998,8 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow,
 }
 
 void nsFocusManager::UpdateCaretForCaretBrowsingMode() {
-  UpdateCaret(false, true, mFocusedElement);
+  RefPtr<Element> focusedElement = mFocusedElement;
+  UpdateCaret(false, true, focusedElement);
 }
 
 void nsFocusManager::UpdateCaret(bool aMoveCaretToFocus, bool aUpdateVisibility,
@@ -3019,7 +3023,7 @@ void nsFocusManager::UpdateCaret(bool aMoveCaretToFocus, bool aUpdateVisibility,
 
   bool browseWithCaret = Preferences::GetBool("accessibility.browsewithcaret");
 
-  RefPtr<PresShell> presShell = focusedDocShell->GetPresShell();
+  const RefPtr<PresShell> presShell = focusedDocShell->GetPresShell();
   if (!presShell) {
     return;
   }
diff --git a/dom/base/nsFocusManager.h b/dom/base/nsFocusManager.h
index aca51b4950e9a..556fad90a5881 100644
--- a/dom/base/nsFocusManager.h
+++ b/dom/base/nsFocusManager.h
@@ -64,8 +64,9 @@ class nsFocusManager final : public nsIFocusManager,
   MOZ_CAN_RUN_SCRIPT static void FocusWindow(
       nsPIDOMWindowOuter* aWindow, mozilla::dom::CallerType aCallerType);
 
-  static void PrefChanged(const char* aPref, void* aSelf);
-  void PrefChanged(const char* aPref);
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY static void PrefChanged(const char* aPref,
+                                                      void* aSelf);
+  MOZ_CAN_RUN_SCRIPT void PrefChanged(const char* aPref);
 
   /**
    * Retrieve the single focus manager.
@@ -161,7 +162,7 @@ class nsFocusManager final : public nsIFocusManager,
   /**
    * Update the caret with current mode (whether in caret browsing mode or not).
    */
-  void UpdateCaretForCaretBrowsingMode();
+  MOZ_CAN_RUN_SCRIPT void UpdateCaretForCaretBrowsingMode();
 
   /** @see nsIFocusManager.getLastFocusMethod() */
   uint32_t GetLastFocusMethod(nsPIDOMWindowOuter*) const;
@@ -531,14 +532,15 @@ class nsFocusManager final : public nsIFocusManager,
    * aUpdateVisibility should be true to update whether the caret is
    * visible or not.
    */
-  void UpdateCaret(bool aMoveCaretToFocus, bool aUpdateVisibility,
-                   nsIContent* aContent);
+  MOZ_CAN_RUN_SCRIPT void UpdateCaret(bool aMoveCaretToFocus,
+                                      bool aUpdateVisibility,
+                                      nsIContent* aContent);
 
   /**
    * Helper method to move the caret to the focused element aContent.
    */
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY void MoveCaretToFocus(
-      mozilla::PresShell* aPresShell, nsIContent* aContent);
+  MOZ_CAN_RUN_SCRIPT void MoveCaretToFocus(mozilla::PresShell* aPresShell,
+                                           nsIContent* aContent);
 
   /**
    * Makes the caret visible or not, depending on aVisible.
diff --git a/dom/interfaces/base/nsIFocusManager.idl b/dom/interfaces/base/nsIFocusManager.idl
index 6c05185d66d3b..056da78770499 100644
--- a/dom/interfaces/base/nsIFocusManager.idl
+++ b/dom/interfaces/base/nsIFocusManager.idl
@@ -159,6 +159,7 @@ interface nsIFocusManager : nsISupports
   /**
    * Moves the selection caret within aWindow to the current focus.
    */
+  [can_run_script]
   void moveCaretToFocus(in mozIDOMWindowProxy aWindow);
 
   /***
diff --git a/editor/libeditor/EditorBase.cpp b/editor/libeditor/EditorBase.cpp
index 0029c6acfe52d..01010689f189d 100644
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -5332,10 +5332,12 @@ nsresult EditorBase::FinalizeSelection() {
         "nsISelectionController::SetCaretEnabled(false) failed, but ignored");
   }
 
-  nsFocusManager* focusManager = nsFocusManager::GetFocusManager();
+  RefPtr<nsFocusManager> focusManager = nsFocusManager::GetFocusManager();
   if (NS_WARN_IF(!focusManager)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
+  // TODO: Running script from here makes harder to handle blur events.  We
+  //       should do this asynchronously.
   focusManager->UpdateCaretForCaretBrowsingMode();
   if (nsCOMPtr<nsINode> node = do_QueryInterface(GetDOMEventTarget())) {
     if (node->OwnerDoc()->GetUnretargetedFocusedContent() != node) {
diff --git a/editor/libeditor/EditorBase.h b/editor/libeditor/EditorBase.h
index 9c2662481170d..c06713cb52ff8 100644
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -292,7 +292,7 @@ class EditorBase : public nsIEditor,
   /**
    * Finalizes selection and caret for the editor.
    */
-  nsresult FinalizeSelection();
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult FinalizeSelection();
 
   /**
    * Returns true if selection is in an editable element and both the range
diff --git a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
index 8d4b00d5e1fd4..316091cfe4c52 100644
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
@@ -983,9 +983,8 @@ nsresult nsTypeAheadFind::FindInternal(uint32_t aMode,
       nsCOMPtr<Document> document = presShell->GetDocument();
       if (!document) return NS_ERROR_UNEXPECTED;
 
-      nsFocusManager* fm = nsFocusManager::GetFocusManager();
-      if (fm) {
-        nsPIDOMWindowOuter* window = document->GetWindow();
+      if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
+        nsCOMPtr<nsPIDOMWindowOuter> window = document->GetWindow();
         RefPtr<Element> focusedElement;
         nsCOMPtr<mozIDOMWindowProxy> focusedWindow;
         fm->GetFocusedElementForWindow(window, false,
-- 
GitLab