Bug 1342800 - ComputeSize should not treat iframe as object r=firefox-svg-reviewers,longsonr

We should not treat <iframe> as <object> for SVG, otherwise there will
be unexpected sizing and other webcompat problem (e.g. getScreenCTM).

It behaved correctly before, the change was introduced to solve a double
zooming problem (bug 843480) for <iframe>. Actually the zooming problem
can be solved by avoiding zooming when the window frame is an <iframe>.

Differential Revision: https://phabricator.services.mozilla.com/D28313

--HG--
extra : moz-landing-system : lando
This commit is contained in:
violet 2019-04-22 16:32:14 +00:00
Родитель 6d71ad8258
Коммит 60a266004c
3 изменённых файлов: 41 добавлений и 28 удалений

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

@ -70,31 +70,31 @@ function runTest() {
/* Tests the consistency with farthestViewportElement /* Tests the consistency with farthestViewportElement
(code is from test_viewport.html) */ (code is from test_viewport.html) */
// root.farthestViewportElement == null (but actually == root) // root.farthestViewportElement == null (but actually == root)
is((function() { try { return root.getScreenCTM().e; } catch (e) { return e; } })(), 91.5, "root.getScreenCTM().e"); is((function() { try { return root.getScreenCTM().e; } catch (e) { return e; } })(), 11, "root.getScreenCTM().e");
is((function() { try { return root.getScreenCTM().f; } catch (e) { return e; } })(), 33, "root.getScreenCTM().f"); is((function() { try { return root.getScreenCTM().f; } catch (e) { return e; } })(), 22, "root.getScreenCTM().f");
// inner.farthestViewportElement == root // inner.farthestViewportElement == root
is((function() { try { return inner.getScreenCTM().e; } catch (e) { return e; } })(), 97.5, "inner.getScreenCTM().e"); is((function() { try { return inner.getScreenCTM().e; } catch (e) { return e; } })(), 15, "inner.getScreenCTM().e");
is((function() { try { return inner.getScreenCTM().f; } catch (e) { return e; } })(), 42, "inner.getScreenCTM().f"); is((function() { try { return inner.getScreenCTM().f; } catch (e) { return e; } })(), 28, "inner.getScreenCTM().f");
// g1.farthestViewportElement == root // g1.farthestViewportElement == root
is((function() { try { return g1.getScreenCTM().e; } catch (e) { return e; } })(), 142.5, "g1.getScreenCTM().e"); is((function() { try { return g1.getScreenCTM().e; } catch (e) { return e; } })(), 45, "g1.getScreenCTM().e");
is((function() { try { return g1.getScreenCTM().f; } catch (e) { return e; } })(), 102, "g1.getScreenCTM().f"); is((function() { try { return g1.getScreenCTM().f; } catch (e) { return e; } })(), 68, "g1.getScreenCTM().f");
// outer.farthestViewportElement == null (but actually == root) // outer.farthestViewportElement == null (but actually == root)
is((function() { try { return outer.getScreenCTM().e; } catch (e) { return e; } })(), 144, "outer.getScreenCTM().e"); is((function() { try { return outer.getScreenCTM().e; } catch (e) { return e; } })(), 46, "outer.getScreenCTM().e");
is((function() { try { return outer.getScreenCTM().f; } catch (e) { return e; } })(), 103.5, "outer.getScreenCTM().f"); is((function() { try { return outer.getScreenCTM().f; } catch (e) { return e; } })(), 69, "outer.getScreenCTM().f");
// outer.farthestViewportElement == null (but actually == root) // outer.farthestViewportElement == null (but actually == root)
is((function() { try { return outer2.getScreenCTM().e; } catch (e) { return e; } })(), -19, "outer2.getScreenCTM().e"); is((function() { try { return outer2.getScreenCTM().e; } catch (e) { return e; } })(), -19, "outer2.getScreenCTM().e");
is((function() { try { return outer2.getScreenCTM().f; } catch (e) { return e; } })(), -8, "outer2.getScreenCTM().f"); is((function() { try { return outer2.getScreenCTM().f; } catch (e) { return e; } })(), -8, "outer2.getScreenCTM().f");
// g2.farthestViewportElement == outer (but actually == root) // g2.farthestViewportElement == outer (but actually == root)
is((function() { try { return g2.getScreenCTM().e; } catch (e) { return e; } })(), 1044, "g2.getScreenCTM().e"); is((function() { try { return g2.getScreenCTM().e; } catch (e) { return e; } })(), 646, "g2.getScreenCTM().e");
is((function() { try { return g2.getScreenCTM().f; } catch (e) { return e; } })(), 1153.5, "g2.getScreenCTM().f"); is((function() { try { return g2.getScreenCTM().f; } catch (e) { return e; } })(), 769, "g2.getScreenCTM().f");
// g3.farthestViewportElement == null (but actually == null) // g3.farthestViewportElement == null (but actually == null)
is((function() { try { return g3.getScreenCTM(); } catch (e) { return e; } })(), null, "g3.getScreenCTM()"); is((function() { try { return g3.getScreenCTM(); } catch (e) { return e; } })(), null, "g3.getScreenCTM()");
// symbolRect.farthestViewportElement == root // symbolRect.farthestViewportElement == root
is((function() { try { return symbolRect.getScreenCTM().e; } catch (e) { return e; } })(), 202.5, "symbolRect.getScreenCTM().e"); is((function() { try { return symbolRect.getScreenCTM().e; } catch (e) { return e; } })(), 85, "symbolRect.getScreenCTM().e");
is((function() { try { return symbolRect.getScreenCTM().f; } catch (e) { return e; } })(), 162, "symbolRect.getScreenCTM().f"); is((function() { try { return symbolRect.getScreenCTM().f; } catch (e) { return e; } })(), 108, "symbolRect.getScreenCTM().f");
// fO.farthestViewportElement == root // fO.farthestViewportElement == root
is((function() { try { return fO.getScreenCTM().e; } catch (e) { return e; } })(), 99, "symbolRect.getScreenCTM().e"); is((function() { try { return fO.getScreenCTM().e; } catch (e) { return e; } })(), 16, "symbolRect.getScreenCTM().e");
is((function() { try { return fO.getScreenCTM().f; } catch (e) { return e; } })(), 43.5, "symbolRect.getScreenCTM().f"); is((function() { try { return fO.getScreenCTM().f; } catch (e) { return e; } })(), 29, "symbolRect.getScreenCTM().f");
// g5.farthestViewportElement == root // g5.farthestViewportElement == root
is((function() { try { return g5.getScreenCTM(); } catch (e) { return e; } })(), null, "g5.getScreenCTM()"); is((function() { try { return g5.getScreenCTM(); } catch (e) { return e; } })(), null, "g5.getScreenCTM()");

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

@ -308,8 +308,11 @@ LogicalSize nsSVGOuterSVGFrame::ComputeSize(
NS_ASSERTION(aCBSize.ISize(aWM) != NS_AUTOHEIGHT && NS_ASSERTION(aCBSize.ISize(aWM) != NS_AUTOHEIGHT &&
aCBSize.BSize(aWM) != NS_AUTOHEIGHT, aCBSize.BSize(aWM) != NS_AUTOHEIGHT,
"root should not have auto-width/height containing block"); "root should not have auto-width/height containing block");
cbSize.ISize(aWM) *= PresContext()->GetFullZoom();
cbSize.BSize(aWM) *= PresContext()->GetFullZoom(); if (!IsContainingWindowElementOfType(nullptr, nsGkAtoms::iframe)) {
cbSize.ISize(aWM) *= PresContext()->GetFullZoom();
cbSize.BSize(aWM) *= PresContext()->GetFullZoom();
}
// We also need to honour the width and height attributes' default values // We also need to honour the width and height attributes' default values
// of 100% when we're the root of a browsing context. (GetIntrinsicSize() // of 100% when we're the root of a browsing context. (GetIntrinsicSize()
@ -427,7 +430,8 @@ void nsSVGOuterSVGFrame::Reflow(nsPresContext* aPresContext,
changeBits |= COORD_CONTEXT_CHANGED; changeBits |= COORD_CONTEXT_CHANGED;
svgElem->SetViewportSize(newViewportSize); svgElem->SetViewportSize(newViewportSize);
} }
if (mFullZoom != PresContext()->GetFullZoom()) { if (mFullZoom != PresContext()->GetFullZoom() &&
!IsContainingWindowElementOfType(nullptr, nsGkAtoms::iframe)) {
changeBits |= FULL_ZOOM_CHANGED; changeBits |= FULL_ZOOM_CHANGED;
mFullZoom = PresContext()->GetFullZoom(); mFullZoom = PresContext()->GetFullZoom();
} }
@ -873,8 +877,9 @@ gfxMatrix nsSVGOuterSVGFrame::GetCanvasTM() {
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Implementation helpers // Implementation helpers
bool nsSVGOuterSVGFrame::IsRootOfReplacedElementSubDoc( template <typename... Args>
nsIFrame** aEmbeddingFrame) { bool nsSVGOuterSVGFrame::IsContainingWindowElementOfType(
nsIFrame** aContainingWindowFrame, Args... aArgs) const {
if (!mContent->GetParent()) { if (!mContent->GetParent()) {
// Our content is the document element // Our content is the document element
nsCOMPtr<nsIDocShell> docShell = PresContext()->GetDocShell(); nsCOMPtr<nsIDocShell> docShell = PresContext()->GetDocShell();
@ -885,24 +890,27 @@ bool nsSVGOuterSVGFrame::IsRootOfReplacedElementSubDoc(
if (window) { if (window) {
RefPtr<Element> frameElement = window->GetFrameElement(); RefPtr<Element> frameElement = window->GetFrameElement();
if (frameElement && if (frameElement && frameElement->IsAnyOfHTMLElements(aArgs...)) {
frameElement->IsAnyOfHTMLElements(nsGkAtoms::object, nsGkAtoms::embed, if (aContainingWindowFrame) {
nsGkAtoms::iframe)) { *aContainingWindowFrame = frameElement->GetPrimaryFrame();
// Our document is inside an HTML 'object', 'embed' or 'iframe' element NS_ASSERTION(*aContainingWindowFrame, "Yikes, no frame!");
if (aEmbeddingFrame) {
*aEmbeddingFrame = frameElement->GetPrimaryFrame();
NS_ASSERTION(*aEmbeddingFrame, "Yikes, no embedding frame!");
} }
return true; return true;
} }
} }
} }
if (aEmbeddingFrame) { if (aContainingWindowFrame) {
*aEmbeddingFrame = nullptr; *aContainingWindowFrame = nullptr;
} }
return false; return false;
} }
bool nsSVGOuterSVGFrame::IsRootOfReplacedElementSubDoc(
nsIFrame** aEmbeddingFrame) {
return IsContainingWindowElementOfType(aEmbeddingFrame, nsGkAtoms::object,
nsGkAtoms::embed);
}
bool nsSVGOuterSVGFrame::IsRootOfImage() { bool nsSVGOuterSVGFrame::IsRootOfImage() {
if (!mContent->GetParent()) { if (!mContent->GetParent()) {
// Our content is the document element // Our content is the document element

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

@ -191,6 +191,11 @@ class nsSVGOuterSVGFrame final : public nsSVGDisplayContainerFrame,
bool mViewportInitialized; bool mViewportInitialized;
bool mIsRootContent; bool mIsRootContent;
private:
template <typename... Args>
bool IsContainingWindowElementOfType(nsIFrame** aContainingWindowFrame,
Args... aArgs) const;
}; };
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////