1 /*
2  * Copyright (C) 2004 Zack Rusin <zack@kde.org>
3  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc.
4  * All rights reserved.
5  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
6  * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
7  * Copyright (C) 2011 Sencha, Inc. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301  USA
23  */
24 
25 #include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
26 
27 #include "base/stl_util.h"
28 #include "third_party/blink/renderer/core/css/computed_style_css_value_mapping.h"
29 #include "third_party/blink/renderer/core/css/css_identifier_value.h"
30 #include "third_party/blink/renderer/core/css/css_primitive_value.h"
31 #include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h"
32 #include "third_party/blink/renderer/core/css/css_property_id_templates.h"
33 #include "third_party/blink/renderer/core/css/css_property_names.h"
34 #include "third_party/blink/renderer/core/css/css_selector.h"
35 #include "third_party/blink/renderer/core/css/css_variable_data.h"
36 #include "third_party/blink/renderer/core/css/parser/css_parser.h"
37 #include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
38 #include "third_party/blink/renderer/core/css/style_engine.h"
39 #include "third_party/blink/renderer/core/css/zoom_adjusted_pixel_value.h"
40 #include "third_party/blink/renderer/core/dom/document.h"
41 #include "third_party/blink/renderer/core/dom/pseudo_element.h"
42 #include "third_party/blink/renderer/core/frame/web_feature.h"
43 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
44 #include "third_party/blink/renderer/core/layout/layout_object.h"
45 #include "third_party/blink/renderer/core/style/computed_style.h"
46 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
47 #include "third_party/blink/renderer/platform/heap/heap.h"
48 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
49 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
50 
51 namespace blink {
52 
53 namespace {
54 
55 // List of all properties we know how to compute, omitting shorthands.
56 // NOTE: Do not use this list, use computableProperties() instead
57 // to respect runtime enabling of CSS properties.
58 const CSSPropertyID kComputedPropertyArray[] = {
59     CSSPropertyID::kAnimationDelay, CSSPropertyID::kAnimationDirection,
60     CSSPropertyID::kAnimationDuration, CSSPropertyID::kAnimationFillMode,
61     CSSPropertyID::kAnimationIterationCount, CSSPropertyID::kAnimationName,
62     CSSPropertyID::kAnimationPlayState, CSSPropertyID::kAnimationTimingFunction,
63     CSSPropertyID::kBackgroundAttachment, CSSPropertyID::kBackgroundBlendMode,
64     CSSPropertyID::kBackgroundClip, CSSPropertyID::kBackgroundColor,
65     CSSPropertyID::kBackgroundImage, CSSPropertyID::kBackgroundOrigin,
66     // more-specific background-position-x/y are non-standard
67     CSSPropertyID::kBackgroundPosition, CSSPropertyID::kBackgroundRepeat,
68     CSSPropertyID::kBackgroundSize, CSSPropertyID::kBorderBottomColor,
69     CSSPropertyID::kBorderBottomLeftRadius,
70     CSSPropertyID::kBorderBottomRightRadius, CSSPropertyID::kBorderBottomStyle,
71     CSSPropertyID::kBorderBottomWidth, CSSPropertyID::kBorderCollapse,
72     CSSPropertyID::kBorderImageOutset, CSSPropertyID::kBorderImageRepeat,
73     CSSPropertyID::kBorderImageSlice, CSSPropertyID::kBorderImageSource,
74     CSSPropertyID::kBorderImageWidth, CSSPropertyID::kBorderLeftColor,
75     CSSPropertyID::kBorderLeftStyle, CSSPropertyID::kBorderLeftWidth,
76     CSSPropertyID::kBorderRightColor, CSSPropertyID::kBorderRightStyle,
77     CSSPropertyID::kBorderRightWidth, CSSPropertyID::kBorderTopColor,
78     CSSPropertyID::kBorderTopLeftRadius, CSSPropertyID::kBorderTopRightRadius,
79     CSSPropertyID::kBorderTopStyle, CSSPropertyID::kBorderTopWidth,
80     CSSPropertyID::kBottom, CSSPropertyID::kBoxShadow,
81     CSSPropertyID::kBoxSizing, CSSPropertyID::kBreakAfter,
82     CSSPropertyID::kBreakBefore, CSSPropertyID::kBreakInside,
83     CSSPropertyID::kCaptionSide, CSSPropertyID::kClear, CSSPropertyID::kClip,
84     CSSPropertyID::kColor, CSSPropertyID::kContent, CSSPropertyID::kCursor,
85     CSSPropertyID::kDirection, CSSPropertyID::kDisplay,
86     CSSPropertyID::kEmptyCells, CSSPropertyID::kFloat,
87     CSSPropertyID::kFontFamily, CSSPropertyID::kFontKerning,
88     CSSPropertyID::kFontOpticalSizing, CSSPropertyID::kFontSize,
89     CSSPropertyID::kFontSizeAdjust, CSSPropertyID::kFontStretch,
90     CSSPropertyID::kFontStyle, CSSPropertyID::kFontVariant,
91     CSSPropertyID::kFontVariantLigatures, CSSPropertyID::kFontVariantCaps,
92     CSSPropertyID::kFontVariantNumeric, CSSPropertyID::kFontVariantEastAsian,
93     CSSPropertyID::kFontWeight, CSSPropertyID::kHeight,
94     CSSPropertyID::kImageOrientation, CSSPropertyID::kImageRendering,
95     CSSPropertyID::kIsolation, CSSPropertyID::kJustifyItems,
96     CSSPropertyID::kJustifySelf, CSSPropertyID::kLeft,
97     CSSPropertyID::kLetterSpacing, CSSPropertyID::kLineHeight,
98     CSSPropertyID::kLineHeightStep, CSSPropertyID::kListStyleImage,
99     CSSPropertyID::kListStylePosition, CSSPropertyID::kListStyleType,
100     CSSPropertyID::kMarginBottom, CSSPropertyID::kMarginLeft,
101     CSSPropertyID::kMarginRight, CSSPropertyID::kMarginTop,
102     CSSPropertyID::kMaxHeight, CSSPropertyID::kMaxWidth,
103     CSSPropertyID::kMinHeight, CSSPropertyID::kMinWidth,
104     CSSPropertyID::kMixBlendMode, CSSPropertyID::kObjectFit,
105     CSSPropertyID::kObjectPosition, CSSPropertyID::kOffsetAnchor,
106     CSSPropertyID::kOffsetDistance, CSSPropertyID::kOffsetPath,
107     CSSPropertyID::kOffsetPosition, CSSPropertyID::kOffsetRotate,
108     CSSPropertyID::kOpacity, CSSPropertyID::kOrphans,
109     CSSPropertyID::kOutlineColor, CSSPropertyID::kOutlineOffset,
110     CSSPropertyID::kOutlineStyle, CSSPropertyID::kOutlineWidth,
111     CSSPropertyID::kOverflowAnchor, CSSPropertyID::kOverflowWrap,
112     CSSPropertyID::kOverflowX, CSSPropertyID::kOverflowY,
113     CSSPropertyID::kPaddingBottom, CSSPropertyID::kPaddingLeft,
114     CSSPropertyID::kPaddingRight, CSSPropertyID::kPaddingTop,
115     CSSPropertyID::kPointerEvents, CSSPropertyID::kPosition,
116     CSSPropertyID::kResize, CSSPropertyID::kRight,
117     CSSPropertyID::kScrollBehavior, CSSPropertyID::kScrollCustomization,
118     CSSPropertyID::kSpeak, CSSPropertyID::kTableLayout, CSSPropertyID::kTabSize,
119     CSSPropertyID::kTextAlign, CSSPropertyID::kTextAlignLast,
120     CSSPropertyID::kTextDecoration, CSSPropertyID::kTextDecorationLine,
121     CSSPropertyID::kTextDecorationStyle, CSSPropertyID::kTextDecorationColor,
122     CSSPropertyID::kTextDecorationSkipInk, CSSPropertyID::kTextJustify,
123     CSSPropertyID::kTextUnderlinePosition, CSSPropertyID::kTextIndent,
124     CSSPropertyID::kTextRendering, CSSPropertyID::kTextShadow,
125     CSSPropertyID::kTextSizeAdjust, CSSPropertyID::kTextOverflow,
126     CSSPropertyID::kTextTransform, CSSPropertyID::kTop,
127     CSSPropertyID::kTouchAction, CSSPropertyID::kTransitionDelay,
128     CSSPropertyID::kTransitionDuration, CSSPropertyID::kTransitionProperty,
129     CSSPropertyID::kTransitionTimingFunction, CSSPropertyID::kUnicodeBidi,
130     CSSPropertyID::kVerticalAlign, CSSPropertyID::kVisibility,
131     CSSPropertyID::kWhiteSpace, CSSPropertyID::kWidows, CSSPropertyID::kWidth,
132     CSSPropertyID::kWillChange, CSSPropertyID::kWordBreak,
133     CSSPropertyID::kWordSpacing, CSSPropertyID::kZIndex, CSSPropertyID::kZoom,
134 
135     CSSPropertyID::kWebkitAppearance, CSSPropertyID::kBackfaceVisibility,
136     CSSPropertyID::kWebkitBorderHorizontalSpacing,
137     CSSPropertyID::kWebkitBorderImage,
138     CSSPropertyID::kWebkitBorderVerticalSpacing, CSSPropertyID::kWebkitBoxAlign,
139     CSSPropertyID::kWebkitBoxDecorationBreak,
140     CSSPropertyID::kWebkitBoxDirection, CSSPropertyID::kWebkitBoxFlex,
141     CSSPropertyID::kWebkitBoxOrdinalGroup, CSSPropertyID::kWebkitBoxOrient,
142     CSSPropertyID::kWebkitBoxPack, CSSPropertyID::kWebkitBoxReflect,
143     CSSPropertyID::kColumnCount, CSSPropertyID::kColumnGap,
144     CSSPropertyID::kColumnRuleColor, CSSPropertyID::kColumnRuleStyle,
145     CSSPropertyID::kColumnRuleWidth, CSSPropertyID::kColumnSpan,
146     CSSPropertyID::kColumnWidth, CSSPropertyID::kBackdropFilter,
147     CSSPropertyID::kAlignContent, CSSPropertyID::kAlignItems,
148     CSSPropertyID::kAlignSelf, CSSPropertyID::kFlexBasis,
149     CSSPropertyID::kFlexGrow, CSSPropertyID::kFlexShrink,
150     CSSPropertyID::kFlexDirection, CSSPropertyID::kFlexWrap,
151     CSSPropertyID::kJustifyContent, CSSPropertyID::kWebkitFontSmoothing,
152     CSSPropertyID::kGridAutoColumns, CSSPropertyID::kGridAutoFlow,
153     CSSPropertyID::kGridAutoRows, CSSPropertyID::kGridColumnEnd,
154     CSSPropertyID::kGridColumnStart, CSSPropertyID::kGridTemplateAreas,
155     CSSPropertyID::kGridTemplateColumns, CSSPropertyID::kGridTemplateRows,
156     CSSPropertyID::kGridRowEnd, CSSPropertyID::kGridRowStart,
157     CSSPropertyID::kRowGap, CSSPropertyID::kWebkitHighlight,
158     CSSPropertyID::kHyphens, CSSPropertyID::kWebkitHyphenateCharacter,
159     CSSPropertyID::kWebkitLineBreak, CSSPropertyID::kWebkitLineClamp,
160     CSSPropertyID::kWebkitLocale, CSSPropertyID::kWebkitMaskBoxImage,
161     CSSPropertyID::kWebkitMaskBoxImageOutset,
162     CSSPropertyID::kWebkitMaskBoxImageRepeat,
163     CSSPropertyID::kWebkitMaskBoxImageSlice,
164     CSSPropertyID::kWebkitMaskBoxImageSource,
165     CSSPropertyID::kWebkitMaskBoxImageWidth, CSSPropertyID::kWebkitMaskClip,
166     CSSPropertyID::kWebkitMaskComposite, CSSPropertyID::kWebkitMaskImage,
167     CSSPropertyID::kWebkitMaskOrigin, CSSPropertyID::kWebkitMaskPosition,
168     CSSPropertyID::kWebkitMaskRepeat, CSSPropertyID::kWebkitMaskSize,
169     CSSPropertyID::kOrder, CSSPropertyID::kPerspective,
170     CSSPropertyID::kPerspectiveOrigin, CSSPropertyID::kWebkitPrintColorAdjust,
171     CSSPropertyID::kWebkitRtlOrdering, CSSPropertyID::kShapeOutside,
172     CSSPropertyID::kShapeImageThreshold, CSSPropertyID::kShapeMargin,
173     CSSPropertyID::kWebkitTapHighlightColor, CSSPropertyID::kWebkitTextCombine,
174     CSSPropertyID::kWebkitTextDecorationsInEffect,
175     CSSPropertyID::kWebkitTextEmphasisColor,
176     CSSPropertyID::kWebkitTextEmphasisPosition,
177     CSSPropertyID::kWebkitTextEmphasisStyle,
178     CSSPropertyID::kWebkitTextFillColor, CSSPropertyID::kWebkitTextOrientation,
179     CSSPropertyID::kWebkitTextSecurity, CSSPropertyID::kWebkitTextStrokeColor,
180     CSSPropertyID::kWebkitTextStrokeWidth, CSSPropertyID::kTransform,
181     CSSPropertyID::kTransformOrigin, CSSPropertyID::kTransformStyle,
182     CSSPropertyID::kWebkitUserDrag, CSSPropertyID::kWebkitUserModify,
183     CSSPropertyID::kUserSelect, CSSPropertyID::kWebkitWritingMode,
184     CSSPropertyID::kWebkitAppRegion, CSSPropertyID::kBufferedRendering,
185     CSSPropertyID::kClipPath, CSSPropertyID::kClipRule, CSSPropertyID::kMask,
186     CSSPropertyID::kFilter, CSSPropertyID::kFloodColor,
187     CSSPropertyID::kFloodOpacity, CSSPropertyID::kLightingColor,
188     CSSPropertyID::kStopColor, CSSPropertyID::kStopOpacity,
189     CSSPropertyID::kColorInterpolation,
190     CSSPropertyID::kColorInterpolationFilters, CSSPropertyID::kColorRendering,
191     CSSPropertyID::kFill, CSSPropertyID::kFillOpacity, CSSPropertyID::kFillRule,
192     CSSPropertyID::kMarkerEnd, CSSPropertyID::kMarkerMid,
193     CSSPropertyID::kMarkerStart, CSSPropertyID::kMaskType,
194     CSSPropertyID::kMaskSourceType, CSSPropertyID::kShapeRendering,
195     CSSPropertyID::kStroke, CSSPropertyID::kStrokeDasharray,
196     CSSPropertyID::kStrokeDashoffset, CSSPropertyID::kStrokeLinecap,
197     CSSPropertyID::kStrokeLinejoin, CSSPropertyID::kStrokeMiterlimit,
198     CSSPropertyID::kStrokeOpacity, CSSPropertyID::kStrokeWidth,
199     CSSPropertyID::kAlignmentBaseline, CSSPropertyID::kBaselineShift,
200     CSSPropertyID::kDominantBaseline, CSSPropertyID::kTextAnchor,
201     CSSPropertyID::kWritingMode, CSSPropertyID::kVectorEffect,
202     CSSPropertyID::kPaintOrder, CSSPropertyID::kD, CSSPropertyID::kCx,
203     CSSPropertyID::kCy, CSSPropertyID::kX, CSSPropertyID::kY, CSSPropertyID::kR,
204     CSSPropertyID::kRx, CSSPropertyID::kRy, CSSPropertyID::kTranslate,
205     CSSPropertyID::kRotate, CSSPropertyID::kScale, CSSPropertyID::kCaretColor,
206     CSSPropertyID::kLineBreak, CSSPropertyID::kMathStyle};
207 
CssIdentifierForFontSizeKeyword(int keyword_size)208 CSSValueID CssIdentifierForFontSizeKeyword(int keyword_size) {
209   DCHECK_NE(keyword_size, 0);
210   DCHECK_LE(keyword_size, 8);
211   return static_cast<CSSValueID>(static_cast<int>(CSSValueID::kXxSmall) +
212                                  keyword_size - 1);
213 }
214 
LogUnimplementedPropertyID(const CSSProperty & property)215 void LogUnimplementedPropertyID(const CSSProperty& property) {
216   DEFINE_STATIC_LOCAL(HashSet<CSSPropertyID>, property_id_set, ());
217   if (property.PropertyID() == CSSPropertyID::kVariable)
218     return;
219   if (!property_id_set.insert(property.PropertyID()).is_new_entry)
220     return;
221 
222   DLOG(ERROR) << "Blink does not yet implement getComputedStyle for '"
223               << property.GetPropertyName() << "'.";
224 }
225 
226 }  // namespace
227 
228 const Vector<const CSSProperty*>&
ComputableProperties(const ExecutionContext * execution_context)229 CSSComputedStyleDeclaration::ComputableProperties(
230     const ExecutionContext* execution_context) {
231   DEFINE_STATIC_LOCAL(Vector<const CSSProperty*>, properties, ());
232   if (properties.IsEmpty()) {
233     CSSProperty::FilterWebExposedCSSPropertiesIntoVector(
234         execution_context, kComputedPropertyArray,
235         base::size(kComputedPropertyArray), properties);
236   }
237   return properties;
238 }
239 
CSSComputedStyleDeclaration(Node * n,bool allow_visited_style,const String & pseudo_element_name)240 CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(
241     Node* n,
242     bool allow_visited_style,
243     const String& pseudo_element_name)
244     : CSSStyleDeclaration(n ? n->GetExecutionContext() : nullptr),
245       node_(n),
246       pseudo_element_specifier_(
247           CSSSelector::ParsePseudoId(pseudo_element_name)),
248       allow_visited_style_(allow_visited_style) {}
249 
250 CSSComputedStyleDeclaration::~CSSComputedStyleDeclaration() = default;
251 
cssText() const252 String CSSComputedStyleDeclaration::cssText() const {
253   StringBuilder result;
254   static const Vector<const CSSProperty*>& properties =
255       ComputableProperties(GetExecutionContext());
256 
257   for (unsigned i = 0; i < properties.size(); i++) {
258     if (i)
259       result.Append(' ');
260     result.Append(properties[i]->GetPropertyName());
261     result.Append(": ");
262     result.Append(GetPropertyValue(properties[i]->PropertyID()));
263     result.Append(';');
264   }
265 
266   return result.ToString();
267 }
268 
setCSSText(const ExecutionContext *,const String &,ExceptionState & exception_state)269 void CSSComputedStyleDeclaration::setCSSText(const ExecutionContext*,
270                                              const String&,
271                                              ExceptionState& exception_state) {
272   exception_state.ThrowDOMException(
273       DOMExceptionCode::kNoModificationAllowedError,
274       "These styles are computed, and therefore read-only.");
275 }
276 
277 const CSSValue*
GetFontSizeCSSValuePreferringKeyword() const278 CSSComputedStyleDeclaration::GetFontSizeCSSValuePreferringKeyword() const {
279   if (!node_)
280     return nullptr;
281 
282   node_->GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
283 
284   const ComputedStyle* style =
285       node_->EnsureComputedStyle(pseudo_element_specifier_);
286   if (!style)
287     return nullptr;
288 
289   if (int keyword_size = style->GetFontDescription().KeywordSize()) {
290     return CSSIdentifierValue::Create(
291         CssIdentifierForFontSizeKeyword(keyword_size));
292   }
293 
294   return ZoomAdjustedPixelValue(style->GetFontDescription().ComputedPixelSize(),
295                                 *style);
296 }
297 
IsMonospaceFont() const298 bool CSSComputedStyleDeclaration::IsMonospaceFont() const {
299   if (!node_)
300     return false;
301 
302   const ComputedStyle* style =
303       node_->EnsureComputedStyle(pseudo_element_specifier_);
304   if (!style)
305     return false;
306 
307   return style->GetFontDescription().IsMonospace();
308 }
ComputeComputedStyle() const309 const ComputedStyle* CSSComputedStyleDeclaration::ComputeComputedStyle() const {
310   Node* styled_node = this->StyledNode();
311   DCHECK(styled_node);
312   const ComputedStyle* style = styled_node->EnsureComputedStyle(
313       styled_node->IsPseudoElement() ? kPseudoIdNone
314                                      : pseudo_element_specifier_);
315   if (style && style->IsEnsuredOutsideFlatTree()) {
316     UseCounter::Count(node_->GetDocument(),
317                       WebFeature::kGetComputedStyleOutsideFlatTree);
318   }
319   return style;
320 }
321 
StyledNode() const322 Node* CSSComputedStyleDeclaration::StyledNode() const {
323   if (!node_)
324     return nullptr;
325 
326   if (auto* node_element = DynamicTo<Element>(node_.Get())) {
327     if (PseudoElement* element =
328             node_element->GetPseudoElement(pseudo_element_specifier_))
329       return element;
330   }
331   return node_.Get();
332 }
333 
StyledLayoutObject() const334 LayoutObject* CSSComputedStyleDeclaration::StyledLayoutObject() const {
335   auto* node = StyledNode();
336   if (!node)
337     return nullptr;
338 
339   if (pseudo_element_specifier_ != kPseudoIdNone && node == node_.Get())
340     return nullptr;
341 
342   return node->GetLayoutObject();
343 }
344 
GetPropertyCSSValue(CSSPropertyID property_id) const345 const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValue(
346     CSSPropertyID property_id) const {
347   if (property_id == CSSPropertyID::kVariable) {
348     // TODO(https://crbug.com/980160): Disallow calling this function with
349     // kVariable.
350     return nullptr;
351   }
352   return GetPropertyCSSValue(CSSPropertyName(property_id));
353 }
354 
GetPropertyCSSValue(AtomicString custom_property_name) const355 const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValue(
356     AtomicString custom_property_name) const {
357   return GetPropertyCSSValue(CSSPropertyName(custom_property_name));
358 }
359 
360 HeapHashMap<AtomicString, Member<const CSSValue>>
GetVariables() const361 CSSComputedStyleDeclaration::GetVariables() const {
362   const ComputedStyle* style = ComputeComputedStyle();
363   if (!style)
364     return {};
365   DCHECK(StyledNode());
366   return ComputedStyleCSSValueMapping::GetVariables(
367       *style, StyledNode()->GetDocument().GetPropertyRegistry());
368 }
369 
GetPropertyCSSValue(const CSSPropertyName & property_name) const370 const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValue(
371     const CSSPropertyName& property_name) const {
372   Node* styled_node = StyledNode();
373   if (!styled_node)
374     return nullptr;
375 
376   Document& document = styled_node->GetDocument();
377 
378   if (HTMLFrameOwnerElement* owner = document.LocalOwner()) {
379     // We are inside an iframe. If any of our ancestor iframes needs a style
380     // and/or layout update, we need to make that up-to-date to resolve viewport
381     // media queries and generate boxes as we might be moving to/from
382     // display:none in some element in the chain of ancestors.
383     //
384     // TODO(futhark@chromium.org): There is an open question what the computed
385     // style should be in a display:none iframe. If the property we are querying
386     // is not layout dependent, we will not update the iframe layout box here.
387     bool is_layout_dependent_property =
388         !property_name.IsCustomProperty() &&
389         CSSProperty::Get(property_name.Id()).IsLayoutDependentProperty();
390     if (is_layout_dependent_property ||
391         document.GetStyleEngine().HasViewportDependentMediaQueries()) {
392       owner->GetDocument().UpdateStyleAndLayout(
393           DocumentUpdateReason::kJavaScript);
394       // The style recalc could have caused the styled node to be discarded or
395       // replaced if it was a PseudoElement so we need to update it.
396       styled_node = StyledNode();
397     }
398   }
399 
400   document.UpdateStyleAndLayoutTreeForNode(styled_node);
401 
402   CSSPropertyRef ref(property_name, document);
403   if (!ref.IsValid())
404     return nullptr;
405   const CSSProperty& property_class = ref.GetProperty();
406 
407   // The style recalc could have caused the styled node to be discarded or
408   // replaced if it was a PseudoElement so we need to update it.
409   styled_node = StyledNode();
410   LayoutObject* layout_object = StyledLayoutObject();
411   const ComputedStyle* style = ComputeComputedStyle();
412 
413   if (property_class.IsLayoutDependent(style, layout_object)) {
414     document.UpdateStyleAndLayoutForNode(styled_node,
415                                          DocumentUpdateReason::kJavaScript);
416     styled_node = StyledNode();
417     style = ComputeComputedStyle();
418     layout_object = StyledLayoutObject();
419   }
420 
421   if (!style)
422     return nullptr;
423 
424   const CSSValue* value = property_class.CSSValueFromComputedStyle(
425       *style, layout_object, allow_visited_style_);
426   if (value)
427     return value;
428 
429   LogUnimplementedPropertyID(property_class);
430   return nullptr;
431 }
432 
GetPropertyValue(CSSPropertyID property_id) const433 String CSSComputedStyleDeclaration::GetPropertyValue(
434     CSSPropertyID property_id) const {
435   // allow_visited_style_ is true only for access from DevTools.
436   if (!allow_visited_style_ &&
437       property_id == CSSPropertyID::kWebkitAppearance) {
438     UseCounter::Count(
439         node_->GetDocument(),
440         WebFeature::kGetComputedStyleForWebkitAppearanceExcludeDevTools);
441   }
442   const CSSValue* value = GetPropertyCSSValue(property_id);
443   if (value)
444     return value->CssText();
445   return "";
446 }
447 
length() const448 unsigned CSSComputedStyleDeclaration::length() const {
449   if (!node_ || !node_->InActiveDocument())
450     return 0;
451   return ComputableProperties(GetExecutionContext()).size();
452 }
453 
item(unsigned i) const454 String CSSComputedStyleDeclaration::item(unsigned i) const {
455   if (i >= length())
456     return "";
457 
458   return ComputableProperties(GetExecutionContext())[i]
459       ->GetPropertyNameString();
460 }
461 
CssPropertyMatches(CSSPropertyID property_id,const CSSValue & property_value) const462 bool CSSComputedStyleDeclaration::CssPropertyMatches(
463     CSSPropertyID property_id,
464     const CSSValue& property_value) const {
465   if (property_id == CSSPropertyID::kFontSize &&
466       (property_value.IsPrimitiveValue() ||
467        property_value.IsIdentifierValue()) &&
468       node_) {
469     // This is only used by editing code.
470     node_->GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
471     const ComputedStyle* style =
472         node_->EnsureComputedStyle(pseudo_element_specifier_);
473     if (style && style->GetFontDescription().KeywordSize()) {
474       CSSValueID size_value = CssIdentifierForFontSizeKeyword(
475           style->GetFontDescription().KeywordSize());
476       auto* identifier_value = DynamicTo<CSSIdentifierValue>(property_value);
477       if (identifier_value && identifier_value->GetValueID() == size_value)
478         return true;
479     }
480   }
481   const CSSValue* value = GetPropertyCSSValue(property_id);
482   return DataEquivalent(value, &property_value);
483 }
484 
CopyProperties() const485 MutableCSSPropertyValueSet* CSSComputedStyleDeclaration::CopyProperties()
486     const {
487   return CopyPropertiesInSet(ComputableProperties(GetExecutionContext()));
488 }
489 
CopyPropertiesInSet(const Vector<const CSSProperty * > & properties) const490 MutableCSSPropertyValueSet* CSSComputedStyleDeclaration::CopyPropertiesInSet(
491     const Vector<const CSSProperty*>& properties) const {
492   HeapVector<CSSPropertyValue, 256> list;
493   list.ReserveInitialCapacity(properties.size());
494   for (unsigned i = 0; i < properties.size(); ++i) {
495     const CSSProperty& property = *properties[i];
496     const CSSValue* value = GetPropertyCSSValue(property.GetCSSPropertyName());
497     if (value)
498       list.push_back(CSSPropertyValue(property, *value, false));
499   }
500   return MakeGarbageCollected<MutableCSSPropertyValueSet>(list.data(),
501                                                           list.size());
502 }
503 
parentRule() const504 CSSRule* CSSComputedStyleDeclaration::parentRule() const {
505   return nullptr;
506 }
507 
getPropertyValue(const String & property_name)508 String CSSComputedStyleDeclaration::getPropertyValue(
509     const String& property_name) {
510   CSSPropertyID property_id =
511       cssPropertyID(GetExecutionContext(), property_name);
512   if (!isValidCSSPropertyID(property_id))
513     return String();
514   if (property_id == CSSPropertyID::kVariable) {
515     const CSSValue* value = GetPropertyCSSValue(AtomicString(property_name));
516     if (value)
517       return value->CssText();
518     return String();
519   }
520 #if DCHECK_IS_ON
521   DCHECK(CSSProperty::Get(property_id).IsEnabled());
522 #endif
523   return GetPropertyValue(property_id);
524 }
525 
getPropertyPriority(const String &)526 String CSSComputedStyleDeclaration::getPropertyPriority(const String&) {
527   // All computed styles have a priority of not "important".
528   return "";
529 }
530 
GetPropertyShorthand(const String &)531 String CSSComputedStyleDeclaration::GetPropertyShorthand(const String&) {
532   return "";
533 }
534 
IsPropertyImplicit(const String &)535 bool CSSComputedStyleDeclaration::IsPropertyImplicit(const String&) {
536   return false;
537 }
538 
setProperty(const ExecutionContext *,const String & name,const String &,const String &,ExceptionState & exception_state)539 void CSSComputedStyleDeclaration::setProperty(const ExecutionContext*,
540                                               const String& name,
541                                               const String&,
542                                               const String&,
543                                               ExceptionState& exception_state) {
544   exception_state.ThrowDOMException(
545       DOMExceptionCode::kNoModificationAllowedError,
546       "These styles are computed, and therefore the '" + name +
547           "' property is read-only.");
548 }
549 
removeProperty(const String & name,ExceptionState & exception_state)550 String CSSComputedStyleDeclaration::removeProperty(
551     const String& name,
552     ExceptionState& exception_state) {
553   exception_state.ThrowDOMException(
554       DOMExceptionCode::kNoModificationAllowedError,
555       "These styles are computed, and therefore the '" + name +
556           "' property is read-only.");
557   return String();
558 }
559 
GetPropertyCSSValueInternal(CSSPropertyID property_id)560 const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValueInternal(
561     CSSPropertyID property_id) {
562   if (property_id == CSSPropertyID::kWebkitAppearance && node_) {
563     UseCounter::Count(node_->GetDocument(),
564                       WebFeature::kGetComputedStyleWebkitAppearance);
565   }
566   return GetPropertyCSSValue(property_id);
567 }
568 
GetPropertyCSSValueInternal(AtomicString custom_property_name)569 const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValueInternal(
570     AtomicString custom_property_name) {
571   DCHECK_EQ(CSSPropertyID::kVariable,
572             cssPropertyID(GetExecutionContext(), custom_property_name));
573   return GetPropertyCSSValue(custom_property_name);
574 }
575 
GetPropertyValueInternal(CSSPropertyID property_id)576 String CSSComputedStyleDeclaration::GetPropertyValueInternal(
577     CSSPropertyID property_id) {
578   return GetPropertyValue(property_id);
579 }
580 
SetPropertyInternal(CSSPropertyID id,const String &,const String &,bool,SecureContextMode,ExceptionState & exception_state)581 void CSSComputedStyleDeclaration::SetPropertyInternal(
582     CSSPropertyID id,
583     const String&,
584     const String&,
585     bool,
586     SecureContextMode,
587     ExceptionState& exception_state) {
588   exception_state.ThrowDOMException(
589       DOMExceptionCode::kNoModificationAllowedError,
590       "These styles are computed, and therefore the '" +
591           CSSUnresolvedProperty::Get(id).GetPropertyNameString() +
592           "' property is read-only.");
593 }
594 
Trace(Visitor * visitor)595 void CSSComputedStyleDeclaration::Trace(Visitor* visitor) {
596   visitor->Trace(node_);
597   CSSStyleDeclaration::Trace(visitor);
598 }
599 
600 }  // namespace blink
601