• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
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 #include "config.h"
27 #include "JSCSSStyleDeclarationCustom.h"
28 
29 #include "AtomicString.h"
30 #include "CSSPrimitiveValue.h"
31 #include "CSSStyleDeclaration.h"
32 #include "CSSValue.h"
33 #include "PlatformString.h"
34 #include <runtime/StringObjectThatMasqueradesAsUndefined.h>
35 #include <runtime/StringPrototype.h>
36 #include <wtf/ASCIICType.h>
37 
38 using namespace JSC;
39 using namespace WTF;
40 
41 namespace WebCore {
42 
43 // Check for a CSS prefix.
44 // Passed prefix is all lowercase.
45 // First character of the prefix within the property name may be upper or lowercase.
46 // Other characters in the prefix within the property name must be lowercase.
47 // The prefix within the property name must be followed by a capital letter.
hasCSSPropertyNamePrefix(const Identifier & propertyName,const char * prefix)48 static bool hasCSSPropertyNamePrefix(const Identifier& propertyName, const char* prefix)
49 {
50 #ifndef NDEBUG
51     ASSERT(*prefix);
52     for (const char* p = prefix; *p; ++p)
53         ASSERT(isASCIILower(*p));
54     ASSERT(propertyName.size());
55 #endif
56 
57     if (toASCIILower(propertyName.data()[0]) != prefix[0])
58         return false;
59 
60     unsigned length = propertyName.size();
61     for (unsigned i = 1; i < length; ++i) {
62         if (!prefix[i])
63             return isASCIIUpper(propertyName.data()[i]);
64         if (propertyName.data()[i] != prefix[i])
65             return false;
66     }
67     return false;
68 }
69 
cssPropertyName(const Identifier & propertyName,bool * hadPixelOrPosPrefix=0)70 static String cssPropertyName(const Identifier& propertyName, bool* hadPixelOrPosPrefix = 0)
71 {
72     if (hadPixelOrPosPrefix)
73         *hadPixelOrPosPrefix = false;
74 
75     unsigned length = propertyName.size();
76     if (!length)
77         return String();
78 
79     Vector<UChar> name;
80     name.reserveInitialCapacity(length);
81 
82     unsigned i = 0;
83 
84     if (hasCSSPropertyNamePrefix(propertyName, "css"))
85         i += 3;
86     else if (hasCSSPropertyNamePrefix(propertyName, "pixel")) {
87         i += 5;
88         if (hadPixelOrPosPrefix)
89             *hadPixelOrPosPrefix = true;
90     } else if (hasCSSPropertyNamePrefix(propertyName, "pos")) {
91         i += 3;
92         if (hadPixelOrPosPrefix)
93             *hadPixelOrPosPrefix = true;
94     } else if (hasCSSPropertyNamePrefix(propertyName, "webkit")
95             || hasCSSPropertyNamePrefix(propertyName, "khtml")
96             || hasCSSPropertyNamePrefix(propertyName, "apple"))
97         name.append('-');
98     else {
99         if (isASCIIUpper(propertyName.data()[0]))
100             return String();
101     }
102 
103     name.append(toASCIILower(propertyName.data()[i++]));
104 
105     for (; i < length; ++i) {
106         UChar c = propertyName.data()[i];
107         if (!isASCIIUpper(c))
108             name.append(c);
109         else {
110             name.append('-');
111             name.append(toASCIILower(c));
112         }
113     }
114 
115     return String::adopt(name);
116 }
117 
isCSSPropertyName(const Identifier & propertyName)118 static bool isCSSPropertyName(const Identifier& propertyName)
119 {
120     return CSSStyleDeclaration::isPropertyName(cssPropertyName(propertyName));
121 }
122 
canGetItemsForName(ExecState *,CSSStyleDeclaration *,const Identifier & propertyName)123 bool JSCSSStyleDeclaration::canGetItemsForName(ExecState*, CSSStyleDeclaration*, const Identifier& propertyName)
124 {
125     return isCSSPropertyName(propertyName);
126 }
127 
128 // FIXME: You can get these properties, and set them (see putDelegate below),
129 // but you should also be able to enumerate them.
nameGetter(ExecState * exec,const Identifier & propertyName,const PropertySlot & slot)130 JSValue JSCSSStyleDeclaration::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
131 {
132     JSCSSStyleDeclaration* thisObj = static_cast<JSCSSStyleDeclaration*>(asObject(slot.slotBase()));
133 
134     // Set up pixelOrPos boolean to handle the fact that
135     // pixelTop returns "CSS Top" as number value in unit pixels
136     // posTop returns "CSS top" as number value in unit pixels _if_ its a
137     // positioned element. if it is not a positioned element, return 0
138     // from MSIE documentation FIXME: IMPLEMENT THAT (Dirk)
139     bool pixelOrPos;
140     String prop = cssPropertyName(propertyName, &pixelOrPos);
141     RefPtr<CSSValue> v = thisObj->impl()->getPropertyCSSValue(prop);
142     if (v) {
143         if (pixelOrPos && v->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE)
144             return jsNumber(exec, static_pointer_cast<CSSPrimitiveValue>(v)->getFloatValue(CSSPrimitiveValue::CSS_PX));
145         return jsStringOrNull(exec, v->cssText());
146     }
147 
148     // If the property is a shorthand property (such as "padding"),
149     // it can only be accessed using getPropertyValue.
150 
151     // Make the SVG 'filter' attribute undetectable, to avoid confusion with the IE 'filter' attribute.
152     if (propertyName == "filter")
153         return StringObjectThatMasqueradesAsUndefined::create(exec, thisObj->impl()->getPropertyValue(prop));
154 
155     return jsString(exec, thisObj->impl()->getPropertyValue(prop));
156 }
157 
158 
putDelegate(ExecState * exec,const Identifier & propertyName,JSValue value,PutPropertySlot &)159 bool JSCSSStyleDeclaration::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&)
160 {
161     if (!isCSSPropertyName(propertyName))
162         return false;
163 
164     bool pixelOrPos;
165     String prop = cssPropertyName(propertyName, &pixelOrPos);
166     String propValue = valueToStringWithNullCheck(exec, value);
167     if (pixelOrPos)
168         propValue += "px";
169     ExceptionCode ec = 0;
170     impl()->setProperty(prop, propValue, ec);
171     setDOMException(exec, ec);
172     return true;
173 }
174 
175 } // namespace WebCore
176