source: webkit/trunk/Source/WebCore/css/PropertySetCSSStyleDeclaration.cpp

Last change on this file was 294138, checked in by Matt Woodrow, 3 years ago

Quirk Flightaware.com to use the older number serialization path.
https://bugs.webkit.org/show_bug.cgi?id=240320

Reviewed by Simon Fraser.

Ensures that serialization of matrix() CSS properties uses the older serialization (which
matches ECMA script serialization) since this site expects these to be comparable as strings.

No new tests, since this is a site-specific quirk.

  • css/CSSFunctionValue.cpp:

(WebCore::CSSFunctionValue::customCSSText const):

  • css/CSSFunctionValue.h:
  • css/CSSPrimitiveValue.cpp:

(WebCore::CSSPrimitiveValue::formatNumberValue const):
(WebCore::CSSPrimitiveValue::customCSSText const):

  • css/CSSPrimitiveValue.h:
  • css/CSSValue.cpp:

(WebCore::CSSValue::cssText const):

  • css/CSSValue.h:

(WebCore::CSSValue::CSSValue):

  • css/CSSValueList.cpp:

(WebCore::CSSValueList::customCSSText const):

  • css/CSSValueList.h:
  • css/PropertySetCSSStyleDeclaration.cpp:

(WebCore::PropertySetCSSStyleDeclaration::getPropertyValueInternal):

  • css/StyleProperties.cpp:

(WebCore::StyleProperties::getPropertyValue const):

  • css/StyleProperties.h:
  • page/Quirks.cpp:

(WebCore::Quirks::needsFlightAwareSerializationQuirk const):

  • page/Quirks.h:
  • Property svn:eol-style set to native
File size: 14.5 KB
Line 
1/*
2 * (C) 1999-2003 Lars Knoll ([email protected])
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All rights reserved.
4 * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22#include "config.h"
23#include "PropertySetCSSStyleDeclaration.h"
24
25#include "CSSPropertyParser.h"
26#include "CSSRule.h"
27#include "CSSStyleSheet.h"
28#include "CustomElementReactionQueue.h"
29#include "DOMWindow.h"
30#include "HTMLNames.h"
31#include "InspectorInstrumentation.h"
32#include "JSDOMGlobalObject.h"
33#include "JSDOMWindowBase.h"
34#include "MutationObserverInterestGroup.h"
35#include "MutationRecord.h"
36#include "StyleProperties.h"
37#include "StyleSheetContents.h"
38#include "StyledElement.h"
39#include <wtf/IsoMallocInlines.h>
40
41namespace WebCore {
42
43WTF_MAKE_ISO_ALLOCATED_IMPL(PropertySetCSSStyleDeclaration);
44WTF_MAKE_ISO_ALLOCATED_IMPL(StyleRuleCSSStyleDeclaration);
45WTF_MAKE_ISO_ALLOCATED_IMPL(InlineCSSStyleDeclaration);
46
47class StyleAttributeMutationScope {
48 WTF_MAKE_NONCOPYABLE(StyleAttributeMutationScope);
49public:
50 StyleAttributeMutationScope(PropertySetCSSStyleDeclaration* decl)
51 {
52 ++s_scopeCount;
53
54 if (s_scopeCount != 1) {
55 ASSERT(s_currentDecl == decl);
56 return;
57 }
58
59 ASSERT(!s_currentDecl);
60 s_currentDecl = decl;
61
62 auto* element = s_currentDecl->parentElement();
63 if (!element)
64 return;
65
66 bool shouldReadOldValue = false;
67
68 m_mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(*s_currentDecl->parentElement(), HTMLNames::styleAttr);
69 if (m_mutationRecipients && m_mutationRecipients->isOldValueRequested())
70 shouldReadOldValue = true;
71
72 if (UNLIKELY(element->isDefinedCustomElement())) {
73 auto* reactionQueue = element->reactionQueue();
74 if (reactionQueue && reactionQueue->observesStyleAttribute()) {
75 m_customElement = element;
76 shouldReadOldValue = true;
77 }
78 }
79
80 if (shouldReadOldValue)
81 m_oldValue = s_currentDecl->parentElement()->getAttribute(HTMLNames::styleAttr);
82 }
83
84 ~StyleAttributeMutationScope()
85 {
86 --s_scopeCount;
87 if (s_scopeCount)
88 return;
89
90 if (s_shouldDeliver) {
91 if (m_mutationRecipients) {
92 auto mutation = MutationRecord::createAttributes(*s_currentDecl->parentElement(), HTMLNames::styleAttr, m_oldValue);
93 m_mutationRecipients->enqueueMutationRecord(WTFMove(mutation));
94 }
95 if (m_customElement) {
96 auto& newValue = m_customElement->getAttribute(HTMLNames::styleAttr);
97 CustomElementReactionQueue::enqueueAttributeChangedCallbackIfNeeded(*m_customElement, HTMLNames::styleAttr, m_oldValue, newValue);
98 }
99 }
100
101 s_shouldDeliver = false;
102 if (!s_shouldNotifyInspector) {
103 s_currentDecl = nullptr;
104 return;
105 }
106 // We have to clear internal state before calling Inspector's code.
107 PropertySetCSSStyleDeclaration* localCopyStyleDecl = s_currentDecl;
108 s_currentDecl = nullptr;
109 s_shouldNotifyInspector = false;
110
111 if (auto* parentElement = localCopyStyleDecl->parentElement())
112 InspectorInstrumentation::didInvalidateStyleAttr(*parentElement);
113 }
114
115 void enqueueMutationRecord()
116 {
117 s_shouldDeliver = true;
118 }
119
120 void didInvalidateStyleAttr()
121 {
122 s_shouldNotifyInspector = true;
123 }
124
125private:
126 static unsigned s_scopeCount;
127 static PropertySetCSSStyleDeclaration* s_currentDecl;
128 static bool s_shouldNotifyInspector;
129 static bool s_shouldDeliver;
130
131 std::unique_ptr<MutationObserverInterestGroup> m_mutationRecipients;
132 AtomString m_oldValue;
133 RefPtr<Element> m_customElement;
134};
135
136unsigned StyleAttributeMutationScope::s_scopeCount = 0;
137PropertySetCSSStyleDeclaration* StyleAttributeMutationScope::s_currentDecl = nullptr;
138bool StyleAttributeMutationScope::s_shouldNotifyInspector = false;
139bool StyleAttributeMutationScope::s_shouldDeliver = false;
140
141void PropertySetCSSStyleDeclaration::ref()
142{
143 m_propertySet->ref();
144}
145
146void PropertySetCSSStyleDeclaration::deref()
147{
148 m_propertySet->deref();
149}
150
151unsigned PropertySetCSSStyleDeclaration::length() const
152{
153 return m_propertySet->propertyCount();
154}
155
156String PropertySetCSSStyleDeclaration::item(unsigned i) const
157{
158 if (i >= m_propertySet->propertyCount())
159 return String();
160 return m_propertySet->propertyAt(i).cssName();
161}
162
163String PropertySetCSSStyleDeclaration::cssText() const
164{
165 return m_propertySet->asText();
166}
167
168ExceptionOr<void> PropertySetCSSStyleDeclaration::setCssText(const String& text)
169{
170 StyleAttributeMutationScope mutationScope(this);
171 if (!willMutate())
172 return { };
173
174 bool changed = m_propertySet->parseDeclaration(text, cssParserContext());
175
176 didMutate(changed ? PropertyChanged : NoChanges);
177
178 mutationScope.enqueueMutationRecord();
179 return { };
180}
181
182RefPtr<DeprecatedCSSOMValue> PropertySetCSSStyleDeclaration::getPropertyCSSValue(const String& propertyName)
183{
184 if (isCustomPropertyName(propertyName)) {
185 RefPtr<CSSValue> value = m_propertySet->getCustomPropertyCSSValue(propertyName);
186 if (!value)
187 return nullptr;
188 return wrapForDeprecatedCSSOM(value.get());
189 }
190
191 CSSPropertyID propertyID = cssPropertyID(propertyName);
192 if (!propertyID)
193 return nullptr;
194 return wrapForDeprecatedCSSOM(getPropertyCSSValueInternal(propertyID).get());
195}
196
197String PropertySetCSSStyleDeclaration::getPropertyValue(const String& propertyName)
198{
199 if (isCustomPropertyName(propertyName))
200 return m_propertySet->getCustomPropertyValue(propertyName);
201
202 CSSPropertyID propertyID = cssPropertyID(propertyName);
203 if (!propertyID)
204 return String();
205 return getPropertyValueInternal(propertyID);
206}
207
208String PropertySetCSSStyleDeclaration::getPropertyPriority(const String& propertyName)
209{
210 if (isCustomPropertyName(propertyName))
211 return m_propertySet->customPropertyIsImportant(propertyName) ? "important"_s : emptyString();
212
213 CSSPropertyID propertyID = cssPropertyID(propertyName);
214 if (!propertyID)
215 return emptyString();
216 return m_propertySet->propertyIsImportant(propertyID) ? "important"_s : emptyString();
217}
218
219String PropertySetCSSStyleDeclaration::getPropertyShorthand(const String& propertyName)
220{
221 CSSPropertyID propertyID = cssPropertyID(propertyName);
222 if (!propertyID)
223 return String();
224 return m_propertySet->getPropertyShorthand(propertyID);
225}
226
227bool PropertySetCSSStyleDeclaration::isPropertyImplicit(const String& propertyName)
228{
229 CSSPropertyID propertyID = cssPropertyID(propertyName);
230 if (!propertyID)
231 return false;
232 return m_propertySet->isPropertyImplicit(propertyID);
233}
234
235ExceptionOr<void> PropertySetCSSStyleDeclaration::setProperty(const String& propertyName, const String& value, const String& priority)
236{
237 StyleAttributeMutationScope mutationScope(this);
238
239 CSSPropertyID propertyID = cssPropertyID(propertyName);
240 if (isCustomPropertyName(propertyName))
241 propertyID = CSSPropertyCustom;
242 if (!propertyID)
243 return { };
244
245 if (!willMutate())
246 return { };
247
248 bool important = equalLettersIgnoringASCIICase(priority, "important"_s);
249 if (!important && !priority.isEmpty())
250 return { };
251
252 bool changed;
253 if (UNLIKELY(propertyID == CSSPropertyCustom)) {
254 Document* document = nullptr;
255
256 if (parentElement())
257 document = &parentElement()->document();
258 else if (parentStyleSheet())
259 document = parentStyleSheet()->ownerDocument();
260
261 changed = m_propertySet->setCustomProperty(document, propertyName, value, important, cssParserContext());
262 } else
263 changed = m_propertySet->setProperty(propertyID, value, important, cssParserContext());
264
265 didMutate(changed ? PropertyChanged : NoChanges);
266
267 if (changed) {
268 // CSS DOM requires raising SyntaxError of parsing failed, but this is too dangerous for compatibility,
269 // see <http://bugs.webkit.org/show_bug.cgi?id=7296>.
270 mutationScope.enqueueMutationRecord();
271 }
272
273 return { };
274}
275
276ExceptionOr<String> PropertySetCSSStyleDeclaration::removeProperty(const String& propertyName)
277{
278 StyleAttributeMutationScope mutationScope(this);
279 CSSPropertyID propertyID = cssPropertyID(propertyName);
280 if (isCustomPropertyName(propertyName))
281 propertyID = CSSPropertyCustom;
282 if (!propertyID)
283 return String();
284
285 if (!willMutate())
286 return String();
287
288 String result;
289 bool changed = propertyID != CSSPropertyCustom ? m_propertySet->removeProperty(propertyID, &result) : m_propertySet->removeCustomProperty(propertyName, &result);
290
291 didMutate(changed ? PropertyChanged : NoChanges);
292
293 if (changed)
294 mutationScope.enqueueMutationRecord();
295 return result;
296}
297
298RefPtr<CSSValue> PropertySetCSSStyleDeclaration::getPropertyCSSValueInternal(CSSPropertyID propertyID)
299{
300 return m_propertySet->getPropertyCSSValue(propertyID);
301}
302
303String PropertySetCSSStyleDeclaration::getPropertyValueInternal(CSSPropertyID propertyID)
304{
305 Document* doc = nullptr;
306 JSDOMObject* wrap = wrapper();
307 if (wrap) {
308 JSDOMGlobalObject* global = wrap->globalObject();
309 if (global) {
310 DOMWindow& window = activeDOMWindow(*global);
311 doc = window.document();
312 }
313 }
314 String value = m_propertySet->getPropertyValue(propertyID, doc);
315
316 if (!value.isEmpty())
317 return value;
318
319 return { };
320}
321
322ExceptionOr<void> PropertySetCSSStyleDeclaration::setPropertyInternal(CSSPropertyID propertyID, const String& value, bool important)
323{
324 StyleAttributeMutationScope mutationScope { this };
325 if (!willMutate())
326 return { };
327
328 if (m_propertySet->setProperty(propertyID, value, important, cssParserContext())) {
329 didMutate(PropertyChanged);
330 mutationScope.enqueueMutationRecord();
331 } else
332 didMutate(NoChanges);
333
334 return { };
335}
336
337RefPtr<DeprecatedCSSOMValue> PropertySetCSSStyleDeclaration::wrapForDeprecatedCSSOM(CSSValue* internalValue)
338{
339 if (!internalValue)
340 return nullptr;
341
342 // The map is here to maintain the object identity of the CSSValues over multiple invocations.
343 // FIXME: It is likely that the identity is not important for web compatibility and this code should be removed.
344 auto& clonedValue = m_cssomValueWrappers.add(internalValue, WeakPtr<DeprecatedCSSOMValue>()).iterator->value;
345 if (clonedValue)
346 return clonedValue.get();
347
348 auto wrapper = internalValue->createDeprecatedCSSOMWrapper(*this);
349 clonedValue = wrapper;
350 return wrapper;
351}
352
353StyleSheetContents* PropertySetCSSStyleDeclaration::contextStyleSheet() const
354{
355 CSSStyleSheet* cssStyleSheet = parentStyleSheet();
356 return cssStyleSheet ? &cssStyleSheet->contents() : nullptr;
357}
358
359CSSParserContext PropertySetCSSStyleDeclaration::cssParserContext() const
360{
361 return CSSParserContext(m_propertySet->cssParserMode());
362}
363
364Ref<MutableStyleProperties> PropertySetCSSStyleDeclaration::copyProperties() const
365{
366 return m_propertySet->mutableCopy();
367}
368
369StyleRuleCSSStyleDeclaration::StyleRuleCSSStyleDeclaration(MutableStyleProperties& propertySet, CSSRule& parentRule)
370 : PropertySetCSSStyleDeclaration(propertySet)
371 , m_refCount(1)
372 , m_parentRuleType(static_cast<StyleRuleType>(parentRule.type()))
373 , m_parentRule(&parentRule)
374{
375 m_propertySet->ref();
376}
377
378StyleRuleCSSStyleDeclaration::~StyleRuleCSSStyleDeclaration()
379{
380 m_propertySet->deref();
381}
382
383void StyleRuleCSSStyleDeclaration::ref()
384{
385 ++m_refCount;
386}
387
388void StyleRuleCSSStyleDeclaration::deref()
389{
390 ASSERT(m_refCount);
391 if (!--m_refCount)
392 delete this;
393}
394
395bool StyleRuleCSSStyleDeclaration::willMutate()
396{
397 if (!m_parentRule || !m_parentRule->parentStyleSheet())
398 return false;
399 m_parentRule->parentStyleSheet()->willMutateRules();
400 return true;
401}
402
403void StyleRuleCSSStyleDeclaration::didMutate(MutationType type)
404{
405 ASSERT(m_parentRule);
406 ASSERT(m_parentRule->parentStyleSheet());
407
408 if (type == PropertyChanged)
409 m_cssomValueWrappers.clear();
410
411 // Style sheet mutation needs to be signaled even if the change failed. willMutate*/didMutate* must pair.
412 m_parentRule->parentStyleSheet()->didMutateRuleFromCSSStyleDeclaration();
413}
414
415CSSStyleSheet* StyleRuleCSSStyleDeclaration::parentStyleSheet() const
416{
417 return m_parentRule ? m_parentRule->parentStyleSheet() : nullptr;
418}
419
420CSSParserContext StyleRuleCSSStyleDeclaration::cssParserContext() const
421{
422 auto* styleSheet = contextStyleSheet();
423 if (!styleSheet)
424 return PropertySetCSSStyleDeclaration::cssParserContext();
425
426 auto context = styleSheet->parserContext();
427 context.enclosingRuleType = m_parentRuleType;
428
429 return context;
430}
431
432void StyleRuleCSSStyleDeclaration::reattach(MutableStyleProperties& propertySet)
433{
434 m_propertySet->deref();
435 m_propertySet = &propertySet;
436 m_propertySet->ref();
437}
438
439bool InlineCSSStyleDeclaration::willMutate()
440{
441 if (m_parentElement)
442 InspectorInstrumentation::willInvalidateStyleAttr(*m_parentElement);
443 return true;
444}
445
446void InlineCSSStyleDeclaration::didMutate(MutationType type)
447{
448 if (type == NoChanges)
449 return;
450
451 m_cssomValueWrappers.clear();
452
453 if (!m_parentElement)
454 return;
455
456 m_parentElement->invalidateStyleAttribute();
457 StyleAttributeMutationScope(this).didInvalidateStyleAttr();
458}
459
460CSSStyleSheet* InlineCSSStyleDeclaration::parentStyleSheet() const
461{
462 return nullptr;
463}
464
465CSSParserContext InlineCSSStyleDeclaration::cssParserContext() const
466{
467 if (!m_parentElement)
468 return PropertySetCSSStyleDeclaration::cssParserContext();
469
470 CSSParserContext context(m_parentElement->document());
471 context.mode = m_propertySet->cssParserMode();
472 return context;
473}
474
475} // namespace WebCore
Note: See TracBrowser for help on using the repository browser.