Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(547)

Side by Side Diff: third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp

Issue 2323633002: Implement animation tainted custom property values (Closed)
Patch Set: Rebased Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/css/resolver/CSSVariableResolver.h" 5 #include "core/css/resolver/CSSVariableResolver.h"
6 6
7 #include "core/CSSPropertyNames.h" 7 #include "core/CSSPropertyNames.h"
8 #include "core/CSSValueKeywords.h" 8 #include "core/CSSValueKeywords.h"
9 #include "core/StyleBuilderFunctions.h" 9 #include "core/StyleBuilderFunctions.h"
10 #include "core/StylePropertyShorthand.h" 10 #include "core/StylePropertyShorthand.h"
11 #include "core/css/CSSPendingSubstitutionValue.h" 11 #include "core/css/CSSPendingSubstitutionValue.h"
12 #include "core/css/CSSUnsetValue.h" 12 #include "core/css/CSSUnsetValue.h"
13 #include "core/css/CSSVariableData.h" 13 #include "core/css/CSSVariableData.h"
14 #include "core/css/CSSVariableReferenceValue.h" 14 #include "core/css/CSSVariableReferenceValue.h"
15 #include "core/css/PropertyRegistry.h" 15 #include "core/css/PropertyRegistry.h"
16 #include "core/css/parser/CSSParserToken.h" 16 #include "core/css/parser/CSSParserToken.h"
17 #include "core/css/parser/CSSParserTokenRange.h" 17 #include "core/css/parser/CSSParserTokenRange.h"
18 #include "core/css/parser/CSSPropertyParser.h" 18 #include "core/css/parser/CSSPropertyParser.h"
19 #include "core/css/resolver/StyleBuilder.h" 19 #include "core/css/resolver/StyleBuilder.h"
20 #include "core/css/resolver/StyleBuilderConverter.h" 20 #include "core/css/resolver/StyleBuilderConverter.h"
21 #include "core/css/resolver/StyleResolverState.h" 21 #include "core/css/resolver/StyleResolverState.h"
22 #include "core/style/StyleInheritedVariables.h" 22 #include "core/style/StyleInheritedVariables.h"
23 #include "core/style/StyleNonInheritedVariables.h" 23 #include "core/style/StyleNonInheritedVariables.h"
24 #include "wtf/Vector.h" 24 #include "wtf/Vector.h"
25 25
26 namespace blink { 26 namespace blink {
27 27
28 bool CSSVariableResolver::resolveFallback(CSSParserTokenRange range, 28 bool CSSVariableResolver::resolveFallback(CSSParserTokenRange range,
29 Vector<CSSParserToken>& result) { 29 bool disallowAnimationTainted,
30 Vector<CSSParserToken>& result,
31 bool& resultIsAnimationTainted) {
30 if (range.atEnd()) 32 if (range.atEnd())
31 return false; 33 return false;
32 ASSERT(range.peek().type() == CommaToken); 34 ASSERT(range.peek().type() == CommaToken);
33 range.consume(); 35 range.consume();
34 return resolveTokenRange(range, result); 36 return resolveTokenRange(range, disallowAnimationTainted, result,
37 resultIsAnimationTainted);
35 } 38 }
36 39
37 CSSVariableData* CSSVariableResolver::valueForCustomProperty( 40 CSSVariableData* CSSVariableResolver::valueForCustomProperty(
38 AtomicString name) { 41 AtomicString name) {
39 if (m_variablesSeen.contains(name)) { 42 if (m_variablesSeen.contains(name)) {
40 m_cycleStartPoints.add(name); 43 m_cycleStartPoints.add(name);
41 return nullptr; 44 return nullptr;
42 } 45 }
43 46
44 DCHECK(m_registry || !RuntimeEnabledFeatures::cssVariables2Enabled()); 47 DCHECK(m_registry || !RuntimeEnabledFeatures::cssVariables2Enabled());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 if (!newVariableData) 86 if (!newVariableData)
84 return registration->initialVariableData(); 87 return registration->initialVariableData();
85 return newVariableData.get(); 88 return newVariableData.get();
86 } 89 }
87 90
88 PassRefPtr<CSSVariableData> CSSVariableResolver::resolveCustomProperty( 91 PassRefPtr<CSSVariableData> CSSVariableResolver::resolveCustomProperty(
89 AtomicString name, 92 AtomicString name,
90 const CSSVariableData& variableData) { 93 const CSSVariableData& variableData) {
91 ASSERT(variableData.needsVariableResolution()); 94 ASSERT(variableData.needsVariableResolution());
92 95
96 bool disallowAnimationTainted = false;
97 bool isAnimationTainted = variableData.isAnimationTainted();
93 Vector<CSSParserToken> tokens; 98 Vector<CSSParserToken> tokens;
94 m_variablesSeen.add(name); 99 m_variablesSeen.add(name);
95 bool success = resolveTokenRange(variableData.tokens(), tokens); 100 bool success =
101 resolveTokenRange(variableData.tokens(), disallowAnimationTainted, tokens,
102 isAnimationTainted);
96 m_variablesSeen.remove(name); 103 m_variablesSeen.remove(name);
97 104
98 // The old variable data holds onto the backing string the new resolved 105 // The old variable data holds onto the backing string the new resolved
99 // CSSVariableData relies on. Ensure it will live beyond us overwriting the 106 // CSSVariableData relies on. Ensure it will live beyond us overwriting the
100 // RefPtr in StyleInheritedVariables. 107 // RefPtr in StyleInheritedVariables.
101 ASSERT(variableData.refCount() > 1); 108 ASSERT(variableData.refCount() > 1);
102 109
103 if (!success || !m_cycleStartPoints.isEmpty()) { 110 if (!success || !m_cycleStartPoints.isEmpty()) {
104 m_cycleStartPoints.remove(name); 111 m_cycleStartPoints.remove(name);
105 return nullptr; 112 return nullptr;
106 } 113 }
107 return CSSVariableData::createResolved(tokens, variableData); 114 return CSSVariableData::createResolved(tokens, variableData,
115 isAnimationTainted);
108 } 116 }
109 117
110 bool CSSVariableResolver::resolveVariableReference( 118 bool CSSVariableResolver::resolveVariableReference(
111 CSSParserTokenRange range, 119 CSSParserTokenRange range,
112 Vector<CSSParserToken>& result) { 120 bool disallowAnimationTainted,
121 Vector<CSSParserToken>& result,
122 bool& resultIsAnimationTainted) {
113 range.consumeWhitespace(); 123 range.consumeWhitespace();
114 ASSERT(range.peek().type() == IdentToken); 124 ASSERT(range.peek().type() == IdentToken);
115 AtomicString variableName = 125 AtomicString variableName =
116 range.consumeIncludingWhitespace().value().toAtomicString(); 126 range.consumeIncludingWhitespace().value().toAtomicString();
117 ASSERT(range.atEnd() || (range.peek().type() == CommaToken)); 127 ASSERT(range.atEnd() || (range.peek().type() == CommaToken));
118 128
119 CSSVariableData* variableData = valueForCustomProperty(variableName); 129 CSSVariableData* variableData = valueForCustomProperty(variableName);
120 if (!variableData) 130 if (!variableData ||
121 return resolveFallback(range, result); 131 (disallowAnimationTainted && variableData->isAnimationTainted())) {
132 // TODO(alancutter): Append the registered initial custom property value if
133 // we are disallowing an animation tainted value.
134 return resolveFallback(range, disallowAnimationTainted, result,
135 resultIsAnimationTainted);
136 }
122 137
123 result.appendVector(variableData->tokens()); 138 result.appendVector(variableData->tokens());
139 resultIsAnimationTainted |= variableData->isAnimationTainted();
140
124 Vector<CSSParserToken> trash; 141 Vector<CSSParserToken> trash;
125 resolveFallback(range, trash); 142 bool trashIsAnimationTainted;
143 resolveFallback(range, disallowAnimationTainted, trash,
144 trashIsAnimationTainted);
126 return true; 145 return true;
127 } 146 }
128 147
129 void CSSVariableResolver::resolveApplyAtRule(CSSParserTokenRange& range, 148 void CSSVariableResolver::resolveApplyAtRule(CSSParserTokenRange& range,
130 Vector<CSSParserToken>& result) { 149 Vector<CSSParserToken>& result) {
131 DCHECK(range.peek().type() == AtKeywordToken && 150 DCHECK(range.peek().type() == AtKeywordToken &&
132 equalIgnoringASCIICase(range.peek().value(), "apply")); 151 equalIgnoringASCIICase(range.peek().value(), "apply"));
133 range.consumeIncludingWhitespace(); 152 range.consumeIncludingWhitespace();
134 const CSSParserToken& variableName = range.consumeIncludingWhitespace(); 153 const CSSParserToken& variableName = range.consumeIncludingWhitespace();
135 // TODO(timloh): Should we actually be consuming this? 154 // TODO(timloh): Should we actually be consuming this?
(...skipping 11 matching lines...) Expand all
147 return; 166 return;
148 CSSParserTokenRange ruleContents = rule.consumeBlock(); 167 CSSParserTokenRange ruleContents = rule.consumeBlock();
149 rule.consumeWhitespace(); 168 rule.consumeWhitespace();
150 if (!rule.atEnd()) 169 if (!rule.atEnd())
151 return; 170 return;
152 171
153 result.appendRange(ruleContents.begin(), ruleContents.end()); 172 result.appendRange(ruleContents.begin(), ruleContents.end());
154 } 173 }
155 174
156 bool CSSVariableResolver::resolveTokenRange(CSSParserTokenRange range, 175 bool CSSVariableResolver::resolveTokenRange(CSSParserTokenRange range,
157 Vector<CSSParserToken>& result) { 176 bool disallowAnimationTainted,
177 Vector<CSSParserToken>& result,
178 bool& resultIsAnimationTainted) {
158 bool success = true; 179 bool success = true;
159 while (!range.atEnd()) { 180 while (!range.atEnd()) {
160 if (range.peek().functionId() == CSSValueVar) { 181 if (range.peek().functionId() == CSSValueVar) {
161 success &= resolveVariableReference(range.consumeBlock(), result); 182 success &= resolveVariableReference(range.consumeBlock(),
183 disallowAnimationTainted, result,
184 resultIsAnimationTainted);
162 } else if (range.peek().type() == AtKeywordToken && 185 } else if (range.peek().type() == AtKeywordToken &&
163 equalIgnoringASCIICase(range.peek().value(), "apply") && 186 equalIgnoringASCIICase(range.peek().value(), "apply") &&
164 RuntimeEnabledFeatures::cssApplyAtRulesEnabled()) { 187 RuntimeEnabledFeatures::cssApplyAtRulesEnabled()) {
165 resolveApplyAtRule(range, result); 188 resolveApplyAtRule(range, result);
166 } else { 189 } else {
167 result.append(range.consume()); 190 result.append(range.consume());
168 } 191 }
169 } 192 }
170 return success; 193 return success;
171 } 194 }
172 195
173 const CSSValue* CSSVariableResolver::resolveVariableReferences( 196 const CSSValue* CSSVariableResolver::resolveVariableReferences(
174 const StyleResolverState& state, 197 const StyleResolverState& state,
175 CSSPropertyID id, 198 CSSPropertyID id,
176 const CSSValue& value) { 199 const CSSValue& value,
200 bool disallowAnimationTainted) {
177 ASSERT(!isShorthandProperty(id)); 201 ASSERT(!isShorthandProperty(id));
178 202
179 if (value.isPendingSubstitutionValue()) 203 if (value.isPendingSubstitutionValue()) {
180 return resolvePendingSubstitutions(state, id, 204 return resolvePendingSubstitutions(state, id,
181 toCSSPendingSubstitutionValue(value)); 205 toCSSPendingSubstitutionValue(value),
206 disallowAnimationTainted);
207 }
182 208
183 if (value.isVariableReferenceValue()) 209 if (value.isVariableReferenceValue()) {
184 return resolveVariableReferences(state, id, 210 return resolveVariableReferences(state, id,
185 toCSSVariableReferenceValue(value)); 211 toCSSVariableReferenceValue(value),
212 disallowAnimationTainted);
213 }
186 214
187 NOTREACHED(); 215 NOTREACHED();
188 return nullptr; 216 return nullptr;
189 } 217 }
190 218
191 const CSSValue* CSSVariableResolver::resolveVariableReferences( 219 const CSSValue* CSSVariableResolver::resolveVariableReferences(
192 const StyleResolverState& state, 220 const StyleResolverState& state,
193 CSSPropertyID id, 221 CSSPropertyID id,
194 const CSSVariableReferenceValue& value) { 222 const CSSVariableReferenceValue& value,
223 bool disallowAnimationTainted) {
195 CSSVariableResolver resolver(state); 224 CSSVariableResolver resolver(state);
196 Vector<CSSParserToken> tokens; 225 Vector<CSSParserToken> tokens;
197 if (!resolver.resolveTokenRange(value.variableDataValue()->tokens(), tokens)) 226 bool isAnimationTainted = false;
227 if (!resolver.resolveTokenRange(value.variableDataValue()->tokens(),
228 disallowAnimationTainted, tokens,
229 isAnimationTainted))
198 return CSSUnsetValue::create(); 230 return CSSUnsetValue::create();
199 const CSSValue* result = 231 const CSSValue* result =
200 CSSPropertyParser::parseSingleValue(id, tokens, strictCSSParserContext()); 232 CSSPropertyParser::parseSingleValue(id, tokens, strictCSSParserContext());
201 if (!result) 233 if (!result)
202 return CSSUnsetValue::create(); 234 return CSSUnsetValue::create();
203 return result; 235 return result;
204 } 236 }
205 237
206 const CSSValue* CSSVariableResolver::resolvePendingSubstitutions( 238 const CSSValue* CSSVariableResolver::resolvePendingSubstitutions(
207 const StyleResolverState& state, 239 const StyleResolverState& state,
208 CSSPropertyID id, 240 CSSPropertyID id,
209 const CSSPendingSubstitutionValue& pendingValue) { 241 const CSSPendingSubstitutionValue& pendingValue,
242 bool disallowAnimationTainted) {
210 // Longhands from shorthand references follow this path. 243 // Longhands from shorthand references follow this path.
211 HeapHashMap<CSSPropertyID, Member<const CSSValue>>& propertyCache = 244 HeapHashMap<CSSPropertyID, Member<const CSSValue>>& propertyCache =
212 state.parsedPropertiesForPendingSubstitutionCache(pendingValue); 245 state.parsedPropertiesForPendingSubstitutionCache(pendingValue);
213 246
214 const CSSValue* value = propertyCache.get(id); 247 const CSSValue* value = propertyCache.get(id);
215 if (!value) { 248 if (!value) {
216 // TODO(timloh): We shouldn't retry this for all longhands if the shorthand 249 // TODO(timloh): We shouldn't retry this for all longhands if the shorthand
217 // ends up invalid. 250 // ends up invalid.
218 CSSVariableReferenceValue* shorthandValue = pendingValue.shorthandValue(); 251 CSSVariableReferenceValue* shorthandValue = pendingValue.shorthandValue();
219 CSSPropertyID shorthandPropertyId = pendingValue.shorthandPropertyId(); 252 CSSPropertyID shorthandPropertyId = pendingValue.shorthandPropertyId();
220 253
221 CSSVariableResolver resolver(state); 254 CSSVariableResolver resolver(state);
222 255
223 Vector<CSSParserToken> tokens; 256 Vector<CSSParserToken> tokens;
257 bool isAnimationTainted = false;
224 if (resolver.resolveTokenRange( 258 if (resolver.resolveTokenRange(
225 shorthandValue->variableDataValue()->tokens(), tokens)) { 259 shorthandValue->variableDataValue()->tokens(),
260 disallowAnimationTainted, tokens, isAnimationTainted)) {
226 CSSParserContext context(HTMLStandardMode, 0); 261 CSSParserContext context(HTMLStandardMode, 0);
227 262
228 HeapVector<CSSProperty, 256> parsedProperties; 263 HeapVector<CSSProperty, 256> parsedProperties;
229 264
230 if (CSSPropertyParser::parseValue( 265 if (CSSPropertyParser::parseValue(
231 shorthandPropertyId, false, CSSParserTokenRange(tokens), context, 266 shorthandPropertyId, false, CSSParserTokenRange(tokens), context,
232 parsedProperties, StyleRule::RuleType::Style)) { 267 parsedProperties, StyleRule::RuleType::Style)) {
233 unsigned parsedPropertiesCount = parsedProperties.size(); 268 unsigned parsedPropertiesCount = parsedProperties.size();
234 for (unsigned i = 0; i < parsedPropertiesCount; ++i) { 269 for (unsigned i = 0; i < parsedPropertiesCount; ++i) {
235 propertyCache.set(parsedProperties[i].id(), 270 propertyCache.set(parsedProperties[i].id(),
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 : m_styleResolverState(state), 305 : m_styleResolverState(state),
271 m_inheritedVariables(state.style()->inheritedVariables()), 306 m_inheritedVariables(state.style()->inheritedVariables()),
272 m_nonInheritedVariables(state.style()->nonInheritedVariables()), 307 m_nonInheritedVariables(state.style()->nonInheritedVariables()),
273 m_registry(state.document().propertyRegistry()) {} 308 m_registry(state.document().propertyRegistry()) {}
274 309
275 DEFINE_TRACE(CSSVariableResolver) { 310 DEFINE_TRACE(CSSVariableResolver) {
276 visitor->trace(m_registry); 311 visitor->trace(m_registry);
277 } 312 }
278 313
279 } // namespace blink 314 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698