Bug 1668106 - Store subdocument intrinsic size and ratio on content rather than frame. r=dholbert

This avoids a problem where we receive the IPC message from the child
with updated intrinsics before an <embed> or <object> has had its frame
constructed in the parent, and drop the update.

Differential Revision: https://phabricator.services.mozilla.com/D99304
This commit is contained in:
Cameron McCormack 2020-12-10 21:34:38 +00:00
Родитель 11c32bb13e
Коммит 5e3e854648
6 изменённых файлов: 78 добавлений и 38 удалений

Просмотреть файл

@ -3545,6 +3545,25 @@ bool nsObjectLoadingContent::BlockEmbedOrObjectContentLoading() {
return false;
}
void nsObjectLoadingContent::SubdocumentIntrinsicSizeOrRatioChanged(
const Maybe<IntrinsicSize>& aIntrinsicSize,
const Maybe<AspectRatio>& aIntrinsicRatio) {
if (aIntrinsicSize == mSubdocumentIntrinsicSize &&
aIntrinsicRatio == mSubdocumentIntrinsicRatio) {
return;
}
mSubdocumentIntrinsicSize = aIntrinsicSize;
mSubdocumentIntrinsicRatio = aIntrinsicRatio;
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
if (nsSubDocumentFrame* sdf = do_QueryFrame(thisContent->GetPrimaryFrame())) {
sdf->SubdocumentIntrinsicSizeOrRatioChanged();
}
}
// SetupProtoChainRunner implementation
nsObjectLoadingContent::SetupProtoChainRunner::SetupProtoChainRunner(
nsObjectLoadingContent* aContent)

Просмотреть файл

@ -14,6 +14,7 @@
#define NSOBJECTLOADINGCONTENT_H_
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "nsIFrame.h" // for WeakFrame only
#include "nsImageLoadingContent.h"
@ -235,6 +236,20 @@ class nsObjectLoadingContent : public nsImageLoadingContent,
mozilla::dom::WindowProxyHolder>& aOpenerWindow,
mozilla::ErrorResult& aRv);
const mozilla::Maybe<mozilla::IntrinsicSize>& GetSubdocumentIntrinsicSize()
const {
return mSubdocumentIntrinsicSize;
}
const mozilla::Maybe<mozilla::AspectRatio>& GetSubdocumentIntrinsicRatio()
const {
return mSubdocumentIntrinsicRatio;
}
void SubdocumentIntrinsicSizeOrRatioChanged(
const mozilla::Maybe<mozilla::IntrinsicSize>& aIntrinsicSize,
const mozilla::Maybe<mozilla::AspectRatio>& aIntrinsicRatio);
protected:
/**
* Begins loading the object when called
@ -693,6 +708,16 @@ class nsObjectLoadingContent : public nsImageLoadingContent,
RefPtr<nsPluginInstanceOwner> mInstanceOwner;
nsTArray<mozilla::dom::MozPluginParameter> mCachedAttributes;
nsTArray<mozilla::dom::MozPluginParameter> mCachedParameters;
// The intrinsic size and aspect ratio from a child SVG document that
// we should use. These are only set when we are an <object> or <embed>
// and the inner document is SVG.
//
// We store these here rather than on nsSubDocumentFrame since we are
// sometimes notified of our child's intrinsics before we've constructed
// our own frame.
mozilla::Maybe<mozilla::IntrinsicSize> mSubdocumentIntrinsicSize;
mozilla::Maybe<mozilla::AspectRatio> mSubdocumentIntrinsicRatio;
};
#endif

Просмотреть файл

@ -21,6 +21,7 @@
#include "nsFocusManager.h"
#include "nsFrameLoader.h"
#include "nsFrameLoaderOwner.h"
#include "nsObjectLoadingContent.h"
#include "nsQueryObject.h"
#include "nsSubDocumentFrame.h"
#include "nsView.h"
@ -248,11 +249,10 @@ mozilla::ipc::IPCResult BrowserBridgeChild::RecvIntrinsicSizeOrRatioChanged(
const Maybe<IntrinsicSize>& aIntrinsicSize,
const Maybe<AspectRatio>& aIntrinsicRatio) {
if (RefPtr<Element> owner = mFrameLoader->GetOwnerContent()) {
if (nsIFrame* f = owner->GetPrimaryFrame()) {
if (nsSubDocumentFrame* sdf = do_QueryFrame(f)) {
sdf->SubdocumentIntrinsicSizeOrRatioChanged(aIntrinsicSize,
aIntrinsicRatio);
}
if (nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(owner)) {
static_cast<nsObjectLoadingContent*>(olc.get())
->SubdocumentIntrinsicSizeOrRatioChanged(aIntrinsicSize,
aIntrinsicRatio);
}
}
return IPC_OK();

Просмотреть файл

@ -45,6 +45,7 @@
#include "nsServiceManagerUtils.h"
#include "nsQueryObject.h"
#include "RetainedDisplayListBuilder.h"
#include "nsObjectLoadingContent.h"
#include "Layers.h"
#include "BasicLayers.h"
@ -585,7 +586,10 @@ nscoord nsSubDocumentFrame::GetMinISize(gfxContext* aRenderingContext) {
nscoord result;
DISPLAY_MIN_INLINE_SIZE(this, result);
if (mSubdocumentIntrinsicSize) {
nsCOMPtr<nsIObjectLoadingContent> iolc = do_QueryInterface(mContent);
auto olc = static_cast<nsObjectLoadingContent*>(iolc.get());
if (olc && olc->GetSubdocumentIntrinsicSize()) {
// The subdocument is an SVG document, so technically we should call
// SVGOuterSVGFrame::GetMinISize() on its root frame. That method always
// returns 0, though, so we can just do that & don't need to bother with
@ -621,9 +625,13 @@ IntrinsicSize nsSubDocumentFrame::GetIntrinsicSize() {
return IntrinsicSize(0, 0);
}
if (mSubdocumentIntrinsicSize) {
// Use the intrinsic size from the child SVG document, if available.
return *mSubdocumentIntrinsicSize;
if (nsCOMPtr<nsIObjectLoadingContent> iolc = do_QueryInterface(mContent)) {
auto olc = static_cast<nsObjectLoadingContent*>(iolc.get());
if (auto size = olc->GetSubdocumentIntrinsicSize()) {
// Use the intrinsic size from the child SVG document, if available.
return *size;
}
}
if (!IsInline()) {
@ -643,9 +651,15 @@ AspectRatio nsSubDocumentFrame::GetIntrinsicRatio() const {
// FIXME(emilio): This should probably respect contain: size and return no
// ratio in the case subDocRoot is non-null. Otherwise we do it by virtue of
// using a zero-size below and reusing GetIntrinsicSize().
if (mSubdocumentIntrinsicRatio && *mSubdocumentIntrinsicRatio) {
// Use the intrinsic aspect ratio from the child SVG document, if available.
return *mSubdocumentIntrinsicRatio;
if (nsCOMPtr<nsIObjectLoadingContent> iolc = do_QueryInterface(mContent)) {
auto olc = static_cast<nsObjectLoadingContent*>(iolc.get());
auto ratio = olc->GetSubdocumentIntrinsicRatio();
if (ratio && *ratio) {
// Use the intrinsic aspect ratio from the child SVG document, if
// available.
return *ratio;
}
}
// NOTE(emilio): Even though we have an intrinsic size, we may not have an
@ -1156,16 +1170,7 @@ nsPoint nsSubDocumentFrame::GetExtraOffset() const {
return mInnerView->GetPosition();
}
void nsSubDocumentFrame::SubdocumentIntrinsicSizeOrRatioChanged(
const Maybe<IntrinsicSize>& aIntrinsicSize,
const Maybe<AspectRatio>& aIntrinsicRatio) {
if (mSubdocumentIntrinsicSize == aIntrinsicSize &&
mSubdocumentIntrinsicRatio == aIntrinsicRatio) {
return;
}
mSubdocumentIntrinsicSize = aIntrinsicSize;
mSubdocumentIntrinsicRatio = aIntrinsicRatio;
void nsSubDocumentFrame::SubdocumentIntrinsicSizeOrRatioChanged() {
if (MOZ_UNLIKELY(HasAllStateBits(NS_FRAME_IS_DIRTY))) {
// We will be reflowed soon anyway.
return;

Просмотреть файл

@ -135,9 +135,7 @@ class nsSubDocumentFrame final : public nsAtomicContainerFrame,
void ClearDisplayItems();
void SubdocumentIntrinsicSizeOrRatioChanged(
const mozilla::Maybe<mozilla::IntrinsicSize>& aIntrinsicSize,
const mozilla::Maybe<mozilla::AspectRatio>& aIntrinsicRatio);
void SubdocumentIntrinsicSizeOrRatioChanged();
protected:
friend class AsyncFrameInit;
@ -171,12 +169,6 @@ class nsSubDocumentFrame final : public nsAtomicContainerFrame,
nsView* mOuterView;
nsView* mInnerView;
// The intrinsic size and aspect ratio from a child SVG document that
// we should use. These are only set when we are an <object> or <embed>
// and the inner document is SVG.
mozilla::Maybe<mozilla::IntrinsicSize> mSubdocumentIntrinsicSize;
mozilla::Maybe<mozilla::AspectRatio> mSubdocumentIntrinsicRatio;
bool mIsInline;
bool mPostedReflowCallback;
bool mDidCreateDoc;

Просмотреть файл

@ -11,7 +11,7 @@
#include "gfxContext.h"
#include "nsDisplayList.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIObjectLoadingContent.h"
#include "nsObjectLoadingContent.h"
#include "nsSubDocumentFrame.h"
#include "mozilla/PresShell.h"
#include "mozilla/SVGForeignObjectFrame.h"
@ -923,13 +923,12 @@ void SVGOuterSVGFrame::MaybeSendIntrinsicSizeAndRatioToEmbedder(
if (bc->GetParent()->IsInProcess()) {
if (Element* embedder = bc->GetEmbedderElement()) {
nsSubDocumentFrame* sdf = do_QueryFrame(embedder->GetPrimaryFrame());
if (!sdf) {
return;
if (nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(embedder)) {
static_cast<nsObjectLoadingContent*>(olc.get())
->SubdocumentIntrinsicSizeOrRatioChanged(aIntrinsicSize,
aIntrinsicRatio);
}
sdf->SubdocumentIntrinsicSizeOrRatioChanged(aIntrinsicSize,
aIntrinsicRatio);
return;
}
}