Commit 52bbe598 authored by Rune Lillesveen's avatar Rune Lillesveen Committed by Commit Bot

Computed style inside iframe depends on parent layout.

Make sure we layout the parent document when it's dirty.

Bug: 819189
Change-Id: I3835aa913e20abdd4adaab072567191b3ca25c20
Reviewed-on: https://chromium-review.googlesource.com/951248
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
Reviewed-by: default avatarSteve Kobes <skobes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#542372}
parent 32a824ab
<!DOCTYPE html>
<title>CSS Test: getComputedStyle - resolved width in iframe</title>
<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org" />
<link rel="help" href="https://drafts.csswg.org/cssom/#resolved-values" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe id="frm" width="100"></iframe>
<script>
test(() => {
const frmDoc = frm.contentWindow.document;
frmDoc.open();
frmDoc.write('<body style="margin:0"><div style="width:100%"></div>');
frmDoc.close();
assert_equals(frm.contentWindow.getComputedStyle(frmDoc.querySelector("div")).width, "100px");
}, "Check that a percent width in an iframe is resolved against iframe width for getComputedStyle.");
</script>
<!DOCTYPE html>
<title>CSS Test: getComputedStyle - resolved width in iframe dynamic display</title>
<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org" />
<link rel="help" href="https://drafts.csswg.org/cssom/#resolved-values" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe id="frm" width="100" style="display:none"></iframe>
<script>
const frmDoc = frm.contentWindow.document;
frmDoc.open();
frmDoc.write('<body style="margin:0"><div style="width:100%"></div>');
frmDoc.close();
document.body.offsetWidth; // Make sure we layout the top document.
test(() => {
frm.style.display = "inline";
assert_equals(frm.contentWindow.getComputedStyle(frmDoc.querySelector("div")).width, "100px");
}, "Check that a percent width in an iframe is the resolved width when the iframe is displayed.");
</script>
<!DOCTYPE html>
<title>CSS Test: getComputedStyle - resolved width in nested iframes dynamic width</title>
<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org" />
<link rel="help" href="https://drafts.csswg.org/cssom/#resolved-values" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe id="outer" width="100" scrolling="no" frameborder="0"></iframe>
<script>
const outerDoc = outer.contentWindow.document;
outerDoc.open();
outerDoc.write('<body style="margin:0"><iframe id="inner" scrolling="no" frameborder="0" style="width:100%"></iframe>');
outerDoc.close();
const innerWindow = outerDoc.querySelector("#inner").contentWindow;
const innerDoc = innerWindow.document;
innerDoc.open();
innerDoc.write('<body style="margin:0"><div style="width:100%"></div>');
innerDoc.close();
innerDoc.body.offsetWidth; // Make sure we layout the top document.
test(() => {
assert_equals(innerWindow.getComputedStyle(innerDoc.querySelector("div")).width, "100px");
}, "Check that the initial width is 100px.");
test(() => {
outer.setAttribute("width", "200");
assert_equals(innerWindow.getComputedStyle(innerDoc.querySelector("div")).width, "200px");
}, "Check that the resolved width of the inner div is affected by changing the width of outer iframe.");
</script>
...@@ -61,6 +61,7 @@ class CSSProperty : public CSSUnresolvedProperty { ...@@ -61,6 +61,7 @@ class CSSProperty : public CSSUnresolvedProperty {
virtual bool IsProperty() const { return true; } virtual bool IsProperty() const { return true; }
virtual bool IsEnabled() const { return true; } virtual bool IsEnabled() const { return true; }
virtual bool IsAffectedByAll() const { return IsEnabled() && IsProperty(); } virtual bool IsAffectedByAll() const { return IsEnabled() && IsProperty(); }
virtual bool IsLayoutDependentProperty() const { return false; }
virtual bool IsLayoutDependent(const ComputedStyle* style, LayoutObject* layout_object) const { return false; } virtual bool IsLayoutDependent(const ComputedStyle* style, LayoutObject* layout_object) const { return false; }
// Properties that do not override this method: // Properties that do not override this method:
......
...@@ -41,6 +41,10 @@ class {{property_classname}} final : public {{property.namespace_group}} { ...@@ -41,6 +41,10 @@ class {{property_classname}} final : public {{property.namespace_group}} {
return WTF::String("{{property_classname[0].lower() + property_classname[1:]}}\0"); return WTF::String("{{property_classname[0].lower() + property_classname[1:]}}\0");
} }
CSSPropertyID PropertyID() const override { return {{property.property_id}}; } CSSPropertyID PropertyID() const override { return {{property.property_id}}; }
{%if property.layout_dependent %}
bool IsLayoutDependentProperty() const override { return true; }
bool IsLayoutDependent(const ComputedStyle*, LayoutObject*) const override;
{% endif %}
{% for property_method in property.property_methods %} {% for property_method in property.property_methods %}
{{property_method.return_type}} {{property_method.name}}{{property_method.parameters}} const override; {{property_method.return_type}} {{property_method.name}}{{property_method.parameters}} const override;
{% endfor %} {% endfor %}
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "core/dom/ExceptionCode.h" #include "core/dom/ExceptionCode.h"
#include "core/dom/PseudoElement.h" #include "core/dom/PseudoElement.h"
#include "core/frame/UseCounter.h" #include "core/frame/UseCounter.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/layout/LayoutObject.h" #include "core/layout/LayoutObject.h"
#include "core/style/ComputedStyle.h" #include "core/style/ComputedStyle.h"
#include "platform/wtf/text/StringBuilder.h" #include "platform/wtf/text/StringBuilder.h"
...@@ -333,22 +334,37 @@ const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValue( ...@@ -333,22 +334,37 @@ const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValue(
return nullptr; return nullptr;
Document& document = styled_node->GetDocument(); Document& document = styled_node->GetDocument();
if (HTMLFrameOwnerElement* owner = document.LocalOwner()) {
// We are inside an iframe. If any of our ancestor iframes needs a style
// and/or layout update, we need to make that up-to-date to resolve viewport
// media queries and generate boxes as we might be moving to/from
// display:none in some element in the chain of ancestors.
//
// TODO(futhark@chromium.org): There is an open question what the computed
// style should be in a display:none iframe. If the property we are querying
// is not layout dependent, we will not update the iframe layout box here.
if (property_class.IsLayoutDependentProperty() ||
document.GetStyleEngine().HasViewportDependentMediaQueries()) {
owner->GetDocument().UpdateStyleAndLayout();
// The style recalc could have caused the styled node to be discarded or
// replaced if it was a PseudoElement so we need to update it.
styled_node = StyledNode();
}
}
document.UpdateStyleAndLayoutTreeForNode(styled_node); document.UpdateStyleAndLayoutTreeForNode(styled_node);
// The style recalc could have caused the styled node to be discarded or // The style recalc could have caused the styled node to be discarded or
// replaced if it was a PseudoElement so we need to update it. // replaced if it was a PseudoElement so we need to update it.
styled_node = StyledNode(); styled_node = StyledNode();
LayoutObject* layout_object = StyledLayoutObject(); LayoutObject* layout_object = StyledLayoutObject();
const ComputedStyle* style = ComputeComputedStyle(); const ComputedStyle* style = ComputeComputedStyle();
bool force_full_layout = // TODO(futhark@chromium.org): IsInShadowTree() should not be necessary here.
property_class.IsLayoutDependent(style, layout_object) || // See http://crbug.com/704421
styled_node->IsInShadowTree() || if (property_class.IsLayoutDependent(style, layout_object) ||
(document.LocalOwner() && styled_node->IsInShadowTree()) {
document.GetStyleEngine().HasViewportDependentMediaQueries());
if (force_full_layout) {
document.UpdateStyleAndLayoutIgnorePendingStylesheetsForNode(styled_node); document.UpdateStyleAndLayoutIgnorePendingStylesheetsForNode(styled_node);
styled_node = StyledNode(); styled_node = StyledNode();
style = ComputeComputedStyle(); style = ComputeComputedStyle();
......
...@@ -221,9 +221,10 @@ class CORE_EXPORT StyleEngine final ...@@ -221,9 +221,10 @@ class CORE_EXPORT StyleEngine final
StyleInvalidator& GetStyleInvalidator() { return style_invalidator_; } StyleInvalidator& GetStyleInvalidator() { return style_invalidator_; }
bool MediaQueryAffectedByViewportChange(); bool MediaQueryAffectedByViewportChange();
bool MediaQueryAffectedByDeviceChange(); bool MediaQueryAffectedByDeviceChange();
bool HasViewportDependentMediaQueries() const { bool HasViewportDependentMediaQueries() {
DCHECK(IsMaster()); DCHECK(IsMaster());
DCHECK(global_rule_set_); DCHECK(global_rule_set_);
UpdateActiveStyle();
return !global_rule_set_->GetRuleFeatureSet() return !global_rule_set_->GetRuleFeatureSet()
.ViewportDependentMediaQueryResults() .ViewportDependentMediaQueryResults()
.IsEmpty(); .IsEmpty();
......
...@@ -29,11 +29,6 @@ ...@@ -29,11 +29,6 @@
return_type: "bool", return_type: "bool",
parameters: "(bool, CSSParserTokenRange&, const CSSParserContext&, const CSSParserLocalContext&, HeapVector<CSSPropertyValue, 256>&)", parameters: "(bool, CSSParserTokenRange&, const CSSParserContext&, const CSSParserLocalContext&, HeapVector<CSSPropertyValue, 256>&)",
}, },
{
name: "IsLayoutDependent",
return_type: "bool",
parameters: "(const ComputedStyle*, LayoutObject*)",
},
{ {
name: "CSSValueFromComputedStyleInternal", name: "CSSValueFromComputedStyleInternal",
return_type: "const CSSValue*", return_type: "const CSSValue*",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment