commit 4b9ab67d81cc608a8029323433f5d1374ae8d319
parent eb132871cd06207600d97fc1408f6901259ef858
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Tue, 4 Nov 2025 17:42:54 +0000
Bug 1998203 - Factor out some view code into a PresShell::GetInProcessEmbedderElement(). r=jwatt
No meaningful behavior change.
mViewManager needs to get cleared after frame destruction is done.
Differential Revision: https://phabricator.services.mozilla.com/D271246
Diffstat:
4 files changed, 49 insertions(+), 69 deletions(-)
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
@@ -1213,13 +1213,6 @@ void PresShell::Destroy() {
mPendingScrollAnchorAdjustment.Clear();
mPendingScrollResnap.Clear();
- if (mViewManager) {
- // Clear the view manager's weak pointer back to |this| in case it
- // was leaked.
- mViewManager->SetPresShell(nullptr);
- mViewManager = nullptr;
- }
-
// This shell must be removed from the document before the frame
// hierarchy is torn down to avoid finding deleted frames through
// this presshell while the frames are being torn down
@@ -1261,6 +1254,13 @@ void PresShell::Destroy() {
mAccessibleCaretEventHub = nullptr;
}
+ if (mViewManager) {
+ // Clear the view manager's weak pointer back to |this| in case it
+ // was leaked.
+ mViewManager->SetPresShell(nullptr);
+ mViewManager = nullptr;
+ }
+
if (mPresContext) {
// We hold a reference to the pres context, and it holds a weak link back
// to us. To avoid the pres context having a dangling reference, set its
@@ -5645,10 +5645,8 @@ nsIWidget* PresShell::GetNearestWidget() const {
}
}
}
- if (auto* el = mDocument->GetEmbedderElement()) {
- if (auto* f = el->GetPrimaryFrame()) {
- return f->GetNearestWidget();
- }
+ if (auto* embedder = GetInProcessEmbedderFrame()) {
+ return embedder->GetNearestWidget();
}
return GetRootWidget();
}
@@ -10355,6 +10353,29 @@ void PresShell::DidPaintWindow() {
}
}
+nsSubDocumentFrame* PresShell::GetInProcessEmbedderFrame() const {
+ if (!mViewManager) {
+ return nullptr;
+ }
+ // We may not have a root frame yet, so use views.
+ nsView* view = mViewManager->GetRootView();
+ if (!view) {
+ return nullptr;
+ }
+ view = view->GetParent(); // anonymous inner view
+ if (!view) {
+ return nullptr;
+ }
+ view = view->GetParent(); // subdocumentframe's view
+ if (!view) {
+ return nullptr;
+ }
+
+ nsIFrame* f = view->GetFrame();
+ MOZ_ASSERT_IF(f, f->IsSubDocumentFrame());
+ return do_QueryFrame(f);
+}
+
bool PresShell::IsVisible() const {
return mIsActive && !IsUnderHiddenEmbedderElement();
}
diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h
@@ -76,6 +76,7 @@ class nsRange;
class nsRefreshDriver;
class nsRegion;
class nsTextFrame;
+class nsSubDocumentFrame;
class nsView;
class nsViewManager;
class nsWindowSizes;
@@ -460,6 +461,9 @@ class PresShell final : public nsStubDocumentObserver,
// popup).
nsIWidget* GetNearestWidget() const;
+ // Get the current frame of our embedder, if it's in our same process.
+ nsSubDocumentFrame* GetInProcessEmbedderFrame() const;
+
/**
* Get root scroll container frame from the frame constructor.
*/
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
@@ -1019,32 +1019,14 @@ nsIFrame* nsLayoutUtils::GetFloatFromPlaceholder(nsIFrame* aFrame) {
// static
nsIFrame* nsLayoutUtils::GetCrossDocParentFrameInProcess(
const nsIFrame* aFrame, nsPoint* aCrossDocOffset) {
- nsIFrame* p = aFrame->GetParent();
- if (p) {
+ if (nsIFrame* p = aFrame->GetParent()) {
return p;
}
-
- nsView* v = aFrame->GetView();
- if (!v) {
- return nullptr;
+ auto* embedder = aFrame->PresShell()->GetInProcessEmbedderFrame();
+ if (embedder && aCrossDocOffset) {
+ *aCrossDocOffset += embedder->GetExtraOffset();
}
- v = v->GetParent(); // anonymous inner view
- if (!v) {
- return nullptr;
- }
- v = v->GetParent(); // subdocumentframe's view
- if (!v) {
- return nullptr;
- }
-
- p = v->GetFrame();
- if (p && aCrossDocOffset) {
- nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(p);
- MOZ_ASSERT(subdocumentFrame);
- *aCrossDocOffset += subdocumentFrame->GetExtraOffset();
- }
-
- return p;
+ return embedder;
}
// static
diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp
@@ -91,6 +91,7 @@
#include "nsPIDOMWindow.h"
#include "nsPIWindowRoot.h"
#include "nsRefreshDriver.h"
+#include "nsSubDocumentFrame.h"
#include "nsThreadUtils.h"
#include "nsTransitionManager.h"
#include "nsViewManager.h"
@@ -1134,26 +1135,12 @@ void nsPresContext::UpdateCharSet(NotNull<const Encoding*> aCharSet) {
}
nsPresContext* nsPresContext::GetParentPresContext() const {
- mozilla::PresShell* presShell = GetPresShell();
- if (presShell) {
- nsViewManager* viewManager = presShell->GetViewManager();
- if (viewManager) {
- nsView* view = viewManager->GetRootView();
- if (view) {
- view = view->GetParent(); // anonymous inner view
- if (view) {
- view = view->GetParent(); // subdocumentframe's view
- if (view) {
- nsIFrame* f = view->GetFrame();
- if (f) {
- return f->PresContext();
- }
- }
- }
- }
- }
+ mozilla::PresShell* ps = GetPresShell();
+ if (!ps) {
+ return nullptr;
}
- return nullptr;
+ auto* embedder = ps->GetInProcessEmbedderFrame();
+ return embedder ? embedder->PresContext() : nullptr;
}
nsPresContext* nsPresContext::GetInProcessRootContentDocumentPresContext() {
@@ -2656,22 +2643,8 @@ bool nsPresContext::IsRootContentDocumentInProcess() const {
if (IsChrome()) {
return false;
}
- // We may not have a root frame, so use views.
- nsView* view = PresShell()->GetViewManager()->GetRootView();
- if (!view) {
- return false;
- }
- view = view->GetParent(); // anonymous inner view
- if (!view) {
- return true;
- }
- view = view->GetParent(); // subdocumentframe's view
- if (!view) {
- return true;
- }
-
- nsIFrame* f = view->GetFrame();
- return (f && f->PresContext()->IsChrome());
+ auto* embedder = PresShell()->GetInProcessEmbedderFrame();
+ return !embedder || embedder->PresContext()->IsChrome();
}
bool nsPresContext::IsRootContentDocumentCrossProcess() const {