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