1 /*
2 * Copyright (C) 2011 Andreas Kling (kling@webkit.org)
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
27 #include "config.h"
28 #include "core/css/CSSValue.h"
29
30 #include "core/css/CSSArrayFunctionValue.h"
31 #include "core/css/CSSAspectRatioValue.h"
32 #include "core/css/CSSBorderImageSliceValue.h"
33 #include "core/css/CSSCalculationValue.h"
34 #include "core/css/CSSCanvasValue.h"
35 #include "core/css/CSSCrossfadeValue.h"
36 #include "core/css/CSSCursorImageValue.h"
37 #include "core/css/CSSFilterValue.h"
38 #include "core/css/CSSFontFaceSrcValue.h"
39 #include "core/css/CSSFontFeatureValue.h"
40 #include "core/css/CSSFontValue.h"
41 #include "core/css/CSSFunctionValue.h"
42 #include "core/css/CSSGradientValue.h"
43 #include "core/css/CSSGridLineNamesValue.h"
44 #include "core/css/CSSGridTemplateValue.h"
45 #include "core/css/CSSImageSetValue.h"
46 #include "core/css/CSSImageValue.h"
47 #include "core/css/CSSInheritedValue.h"
48 #include "core/css/CSSInitialValue.h"
49 #include "core/css/CSSLineBoxContainValue.h"
50 #include "core/css/CSSMixFunctionValue.h"
51 #include "core/css/CSSPrimitiveValue.h"
52 #include "core/css/CSSReflectValue.h"
53 #include "core/css/CSSSVGDocumentValue.h"
54 #include "core/css/CSSShaderValue.h"
55 #include "core/css/CSSShadowValue.h"
56 #include "core/css/CSSTimingFunctionValue.h"
57 #include "core/css/CSSTransformValue.h"
58 #include "core/css/CSSUnicodeRangeValue.h"
59 #include "core/css/CSSValueList.h"
60 #include "core/css/CSSVariableValue.h"
61 #include "core/svg/SVGColor.h"
62 #include "core/svg/SVGPaint.h"
63
64 namespace WebCore {
65
66 struct SameSizeAsCSSValue : public RefCounted<SameSizeAsCSSValue> {
67 uint32_t bitfields;
68 };
69
70 COMPILE_ASSERT(sizeof(CSSValue) <= sizeof(SameSizeAsCSSValue), CSS_value_should_stay_small);
71
72 class TextCloneCSSValue : public CSSValue {
73 public:
create(ClassType classType,const String & text)74 static PassRefPtr<TextCloneCSSValue> create(ClassType classType, const String& text) { return adoptRef(new TextCloneCSSValue(classType, text)); }
75
cssText() const76 String cssText() const { return m_cssText; }
77
78 private:
TextCloneCSSValue(ClassType classType,const String & text)79 TextCloneCSSValue(ClassType classType, const String& text)
80 : CSSValue(classType, /*isCSSOMSafe*/ true)
81 , m_cssText(text)
82 {
83 m_isTextClone = true;
84 }
85
86 String m_cssText;
87 };
88
89 DEFINE_CSS_VALUE_TYPE_CASTS(TextCloneCSSValue, isTextCloneCSSValue());
90
isImplicitInitialValue() const91 bool CSSValue::isImplicitInitialValue() const
92 {
93 return m_classType == InitialClass && toCSSInitialValue(this)->isImplicit();
94 }
95
cssValueType() const96 CSSValue::Type CSSValue::cssValueType() const
97 {
98 if (isInheritedValue())
99 return CSS_INHERIT;
100 if (isPrimitiveValue())
101 return CSS_PRIMITIVE_VALUE;
102 if (isValueList())
103 return CSS_VALUE_LIST;
104 if (isInitialValue())
105 return CSS_INITIAL;
106 return CSS_CUSTOM;
107 }
108
addSubresourceStyleURLs(ListHashSet<KURL> & urls,const StyleSheetContents * styleSheet) const109 void CSSValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const
110 {
111 // This should get called for internal instances only.
112 ASSERT(!isCSSOMSafe());
113
114 if (isPrimitiveValue())
115 toCSSPrimitiveValue(this)->addSubresourceStyleURLs(urls, styleSheet);
116 else if (isValueList())
117 toCSSValueList(this)->addSubresourceStyleURLs(urls, styleSheet);
118 else if (classType() == FontFaceSrcClass)
119 toCSSFontFaceSrcValue(this)->addSubresourceStyleURLs(urls, styleSheet);
120 else if (classType() == ReflectClass)
121 toCSSReflectValue(this)->addSubresourceStyleURLs(urls, styleSheet);
122 }
123
hasFailedOrCanceledSubresources() const124 bool CSSValue::hasFailedOrCanceledSubresources() const
125 {
126 // This should get called for internal instances only.
127 ASSERT(!isCSSOMSafe());
128
129 if (isValueList())
130 return toCSSValueList(this)->hasFailedOrCanceledSubresources();
131 if (classType() == FontFaceSrcClass)
132 return toCSSFontFaceSrcValue(this)->hasFailedOrCanceledSubresources();
133 if (classType() == ImageClass)
134 return toCSSImageValue(this)->hasFailedOrCanceledSubresources();
135 if (classType() == CrossfadeClass)
136 return toCSSCrossfadeValue(this)->hasFailedOrCanceledSubresources();
137 if (classType() == ImageSetClass)
138 return toCSSImageSetValue(this)->hasFailedOrCanceledSubresources();
139
140 return false;
141 }
142
143 template<class ChildClassType>
compareCSSValues(const CSSValue & first,const CSSValue & second)144 inline static bool compareCSSValues(const CSSValue& first, const CSSValue& second)
145 {
146 return static_cast<const ChildClassType&>(first).equals(static_cast<const ChildClassType&>(second));
147 }
148
equals(const CSSValue & other) const149 bool CSSValue::equals(const CSSValue& other) const
150 {
151 if (m_isTextClone) {
152 ASSERT(isCSSOMSafe());
153 return toTextCloneCSSValue(this)->cssText() == other.cssText();
154 }
155
156 if (m_classType == other.m_classType) {
157 switch (m_classType) {
158 case AspectRatioClass:
159 return compareCSSValues<CSSAspectRatioValue>(*this, other);
160 case BorderImageSliceClass:
161 return compareCSSValues<CSSBorderImageSliceValue>(*this, other);
162 case CanvasClass:
163 return compareCSSValues<CSSCanvasValue>(*this, other);
164 case CursorImageClass:
165 return compareCSSValues<CSSCursorImageValue>(*this, other);
166 case FontClass:
167 return compareCSSValues<CSSFontValue>(*this, other);
168 case FontFaceSrcClass:
169 return compareCSSValues<CSSFontFaceSrcValue>(*this, other);
170 case FontFeatureClass:
171 return compareCSSValues<CSSFontFeatureValue>(*this, other);
172 case FunctionClass:
173 return compareCSSValues<CSSFunctionValue>(*this, other);
174 case LinearGradientClass:
175 return compareCSSValues<CSSLinearGradientValue>(*this, other);
176 case RadialGradientClass:
177 return compareCSSValues<CSSRadialGradientValue>(*this, other);
178 case CrossfadeClass:
179 return compareCSSValues<CSSCrossfadeValue>(*this, other);
180 case ImageClass:
181 return compareCSSValues<CSSImageValue>(*this, other);
182 case InheritedClass:
183 return compareCSSValues<CSSInheritedValue>(*this, other);
184 case InitialClass:
185 return compareCSSValues<CSSInitialValue>(*this, other);
186 case GridLineNamesClass:
187 return compareCSSValues<CSSGridLineNamesValue>(*this, other);
188 case GridTemplateClass:
189 return compareCSSValues<CSSGridTemplateValue>(*this, other);
190 case PrimitiveClass:
191 return compareCSSValues<CSSPrimitiveValue>(*this, other);
192 case ReflectClass:
193 return compareCSSValues<CSSReflectValue>(*this, other);
194 case ShadowClass:
195 return compareCSSValues<CSSShadowValue>(*this, other);
196 case CubicBezierTimingFunctionClass:
197 return compareCSSValues<CSSCubicBezierTimingFunctionValue>(*this, other);
198 case StepsTimingFunctionClass:
199 return compareCSSValues<CSSStepsTimingFunctionValue>(*this, other);
200 case UnicodeRangeClass:
201 return compareCSSValues<CSSUnicodeRangeValue>(*this, other);
202 case ValueListClass:
203 return compareCSSValues<CSSValueList>(*this, other);
204 case CSSTransformClass:
205 return compareCSSValues<CSSTransformValue>(*this, other);
206 case LineBoxContainClass:
207 return compareCSSValues<CSSLineBoxContainValue>(*this, other);
208 case CalculationClass:
209 return compareCSSValues<CSSCalcValue>(*this, other);
210 case ImageSetClass:
211 return compareCSSValues<CSSImageSetValue>(*this, other);
212 case CSSFilterClass:
213 return compareCSSValues<CSSFilterValue>(*this, other);
214 case CSSArrayFunctionValueClass:
215 return compareCSSValues<CSSArrayFunctionValue>(*this, other);
216 case CSSMixFunctionValueClass:
217 return compareCSSValues<CSSMixFunctionValue>(*this, other);
218 case CSSShaderClass:
219 return compareCSSValues<CSSShaderValue>(*this, other);
220 case VariableClass:
221 return compareCSSValues<CSSVariableValue>(*this, other);
222 case SVGColorClass:
223 return compareCSSValues<SVGColor>(*this, other);
224 case SVGPaintClass:
225 return compareCSSValues<SVGPaint>(*this, other);
226 case CSSSVGDocumentClass:
227 return compareCSSValues<CSSSVGDocumentValue>(*this, other);
228 default:
229 ASSERT_NOT_REACHED();
230 return false;
231 }
232 } else if (m_classType == ValueListClass && other.m_classType != ValueListClass)
233 return toCSSValueList(this)->equals(other);
234 else if (m_classType != ValueListClass && other.m_classType == ValueListClass)
235 return static_cast<const CSSValueList&>(other).equals(*this);
236 return false;
237 }
238
cssText() const239 String CSSValue::cssText() const
240 {
241 if (m_isTextClone) {
242 ASSERT(isCSSOMSafe());
243 return toTextCloneCSSValue(this)->cssText();
244 }
245 ASSERT(!isCSSOMSafe() || isSubtypeExposedToCSSOM());
246
247 switch (classType()) {
248 case AspectRatioClass:
249 return toCSSAspectRatioValue(this)->customCSSText();
250 case BorderImageSliceClass:
251 return toCSSBorderImageSliceValue(this)->customCSSText();
252 case CanvasClass:
253 return toCSSCanvasValue(this)->customCSSText();
254 case CursorImageClass:
255 return toCSSCursorImageValue(this)->customCSSText();
256 case FontClass:
257 return toCSSFontValue(this)->customCSSText();
258 case FontFaceSrcClass:
259 return toCSSFontFaceSrcValue(this)->customCSSText();
260 case FontFeatureClass:
261 return toCSSFontFeatureValue(this)->customCSSText();
262 case FunctionClass:
263 return toCSSFunctionValue(this)->customCSSText();
264 case LinearGradientClass:
265 return toCSSLinearGradientValue(this)->customCSSText();
266 case RadialGradientClass:
267 return toCSSRadialGradientValue(this)->customCSSText();
268 case CrossfadeClass:
269 return toCSSCrossfadeValue(this)->customCSSText();
270 case ImageClass:
271 return toCSSImageValue(this)->customCSSText();
272 case InheritedClass:
273 return toCSSInheritedValue(this)->customCSSText();
274 case InitialClass:
275 return toCSSInitialValue(this)->customCSSText();
276 case GridLineNamesClass:
277 return toCSSGridLineNamesValue(this)->customCSSText();
278 case GridTemplateClass:
279 return toCSSGridTemplateValue(this)->customCSSText();
280 case PrimitiveClass:
281 return toCSSPrimitiveValue(this)->customCSSText();
282 case ReflectClass:
283 return toCSSReflectValue(this)->customCSSText();
284 case ShadowClass:
285 return toCSSShadowValue(this)->customCSSText();
286 case CubicBezierTimingFunctionClass:
287 return toCSSCubicBezierTimingFunctionValue(this)->customCSSText();
288 case StepsTimingFunctionClass:
289 return toCSSStepsTimingFunctionValue(this)->customCSSText();
290 case UnicodeRangeClass:
291 return toCSSUnicodeRangeValue(this)->customCSSText();
292 case ValueListClass:
293 return toCSSValueList(this)->customCSSText();
294 case CSSTransformClass:
295 return toCSSTransformValue(this)->customCSSText();
296 case LineBoxContainClass:
297 return toCSSLineBoxContainValue(this)->customCSSText();
298 case CalculationClass:
299 return toCSSCalcValue(this)->customCSSText();
300 case ImageSetClass:
301 return toCSSImageSetValue(this)->customCSSText();
302 case CSSFilterClass:
303 return toCSSFilterValue(this)->customCSSText();
304 case CSSArrayFunctionValueClass:
305 return toCSSArrayFunctionValue(this)->customCSSText();
306 case CSSMixFunctionValueClass:
307 return toCSSMixFunctionValue(this)->customCSSText();
308 case CSSShaderClass:
309 return toCSSShaderValue(this)->customCSSText();
310 case VariableClass:
311 return toCSSVariableValue(this)->value();
312 case SVGColorClass:
313 return toSVGColor(this)->customCSSText();
314 case SVGPaintClass:
315 return toSVGPaint(this)->customCSSText();
316 case CSSSVGDocumentClass:
317 return toCSSSVGDocumentValue(this)->customCSSText();
318 }
319 ASSERT_NOT_REACHED();
320 return String();
321 }
322
serializeResolvingVariables(const HashMap<AtomicString,String> & variables) const323 String CSSValue::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
324 {
325 switch (classType()) {
326 case PrimitiveClass:
327 return toCSSPrimitiveValue(this)->customSerializeResolvingVariables(variables);
328 case ReflectClass:
329 return toCSSReflectValue(this)->customSerializeResolvingVariables(variables);
330 case ValueListClass:
331 return toCSSValueList(this)->customSerializeResolvingVariables(variables);
332 case CSSTransformClass:
333 return toCSSTransformValue(this)->customSerializeResolvingVariables(variables);
334 default:
335 return cssText();
336 }
337 }
338
destroy()339 void CSSValue::destroy()
340 {
341 if (m_isTextClone) {
342 ASSERT(isCSSOMSafe());
343 delete toTextCloneCSSValue(this);
344 return;
345 }
346 ASSERT(!isCSSOMSafe() || isSubtypeExposedToCSSOM());
347
348 switch (classType()) {
349 case AspectRatioClass:
350 delete toCSSAspectRatioValue(this);
351 return;
352 case BorderImageSliceClass:
353 delete toCSSBorderImageSliceValue(this);
354 return;
355 case CanvasClass:
356 delete toCSSCanvasValue(this);
357 return;
358 case CursorImageClass:
359 delete toCSSCursorImageValue(this);
360 return;
361 case FontClass:
362 delete toCSSFontValue(this);
363 return;
364 case FontFaceSrcClass:
365 delete toCSSFontFaceSrcValue(this);
366 return;
367 case FontFeatureClass:
368 delete toCSSFontFeatureValue(this);
369 return;
370 case FunctionClass:
371 delete toCSSFunctionValue(this);
372 return;
373 case LinearGradientClass:
374 delete toCSSLinearGradientValue(this);
375 return;
376 case RadialGradientClass:
377 delete toCSSRadialGradientValue(this);
378 return;
379 case CrossfadeClass:
380 delete toCSSCrossfadeValue(this);
381 return;
382 case ImageClass:
383 delete toCSSImageValue(this);
384 return;
385 case InheritedClass:
386 delete toCSSInheritedValue(this);
387 return;
388 case InitialClass:
389 delete toCSSInitialValue(this);
390 return;
391 case GridLineNamesClass:
392 delete toCSSGridLineNamesValue(this);
393 return;
394 case GridTemplateClass:
395 delete toCSSGridTemplateValue(this);
396 return;
397 case PrimitiveClass:
398 delete toCSSPrimitiveValue(this);
399 return;
400 case ReflectClass:
401 delete toCSSReflectValue(this);
402 return;
403 case ShadowClass:
404 delete toCSSShadowValue(this);
405 return;
406 case CubicBezierTimingFunctionClass:
407 delete toCSSCubicBezierTimingFunctionValue(this);
408 return;
409 case StepsTimingFunctionClass:
410 delete toCSSStepsTimingFunctionValue(this);
411 return;
412 case UnicodeRangeClass:
413 delete toCSSUnicodeRangeValue(this);
414 return;
415 case ValueListClass:
416 delete toCSSValueList(this);
417 return;
418 case CSSTransformClass:
419 delete toCSSTransformValue(this);
420 return;
421 case LineBoxContainClass:
422 delete toCSSLineBoxContainValue(this);
423 return;
424 case CalculationClass:
425 delete toCSSCalcValue(this);
426 return;
427 case ImageSetClass:
428 delete toCSSImageSetValue(this);
429 return;
430 case CSSFilterClass:
431 delete toCSSFilterValue(this);
432 return;
433 case CSSArrayFunctionValueClass:
434 delete toCSSArrayFunctionValue(this);
435 return;
436 case CSSMixFunctionValueClass:
437 delete toCSSMixFunctionValue(this);
438 return;
439 case CSSShaderClass:
440 delete toCSSShaderValue(this);
441 return;
442 case VariableClass:
443 delete toCSSVariableValue(this);
444 return;
445 case SVGColorClass:
446 delete toSVGColor(this);
447 return;
448 case SVGPaintClass:
449 delete toSVGPaint(this);
450 return;
451 case CSSSVGDocumentClass:
452 delete toCSSSVGDocumentValue(this);
453 return;
454 }
455 ASSERT_NOT_REACHED();
456 }
457
cloneForCSSOM() const458 PassRefPtr<CSSValue> CSSValue::cloneForCSSOM() const
459 {
460 switch (classType()) {
461 case PrimitiveClass:
462 return toCSSPrimitiveValue(this)->cloneForCSSOM();
463 case ValueListClass:
464 return toCSSValueList(this)->cloneForCSSOM();
465 case ImageClass:
466 case CursorImageClass:
467 return toCSSImageValue(this)->cloneForCSSOM();
468 case CSSFilterClass:
469 return toCSSFilterValue(this)->cloneForCSSOM();
470 case CSSArrayFunctionValueClass:
471 return toCSSArrayFunctionValue(this)->cloneForCSSOM();
472 case CSSMixFunctionValueClass:
473 return toCSSMixFunctionValue(this)->cloneForCSSOM();
474 case CSSTransformClass:
475 return toCSSTransformValue(this)->cloneForCSSOM();
476 case ImageSetClass:
477 return toCSSImageSetValue(this)->cloneForCSSOM();
478 case SVGColorClass:
479 return toSVGColor(this)->cloneForCSSOM();
480 case SVGPaintClass:
481 return toSVGPaint(this)->cloneForCSSOM();
482 default:
483 ASSERT(!isSubtypeExposedToCSSOM());
484 return TextCloneCSSValue::create(classType(), cssText());
485 }
486 }
487
488 }
489