OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2003, 2010 Apple Inc. All rights reserved. | 5 * Copyright (C) 2003, 2010 Apple Inc. All rights reserved. |
6 * (C) 2007 Rob Buis (buis@kde.org) | 6 * (C) 2007 Rob Buis (buis@kde.org) |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 { | 42 { |
43 DEFINE_STATIC_LOCAL(StyleEventSender, sharedLoadEventSender, (EventTypeNames
::load)); | 43 DEFINE_STATIC_LOCAL(StyleEventSender, sharedLoadEventSender, (EventTypeNames
::load)); |
44 return sharedLoadEventSender; | 44 return sharedLoadEventSender; |
45 } | 45 } |
46 | 46 |
47 inline HTMLStyleElement::HTMLStyleElement(Document& document, bool createdByPars
er) | 47 inline HTMLStyleElement::HTMLStyleElement(Document& document, bool createdByPars
er) |
48 : HTMLElement(styleTag, document) | 48 : HTMLElement(styleTag, document) |
49 , StyleElement(&document, createdByParser) | 49 , StyleElement(&document, createdByParser) |
50 , m_firedLoad(false) | 50 , m_firedLoad(false) |
51 , m_loadedSheet(false) | 51 , m_loadedSheet(false) |
52 , m_scopedStyleRegistrationState(NotRegistered) | |
53 { | 52 { |
54 ScriptWrappable::init(this); | 53 ScriptWrappable::init(this); |
55 } | 54 } |
56 | 55 |
57 HTMLStyleElement::~HTMLStyleElement() | 56 HTMLStyleElement::~HTMLStyleElement() |
58 { | 57 { |
59 // During tear-down, willRemove isn't called, so m_scopedStyleRegistrationSt
ate may still be RegisteredAsScoped or RegisteredInShadowRoot here. | |
60 // Therefore we can't ASSERT(m_scopedStyleRegistrationState == NotRegistered
). | |
61 #if !ENABLE(OILPAN) | 58 #if !ENABLE(OILPAN) |
62 StyleElement::clearDocumentData(document(), this); | 59 StyleElement::clearDocumentData(document(), this); |
63 #endif | 60 #endif |
64 | 61 |
65 styleLoadEventSender().cancelEvent(this); | 62 styleLoadEventSender().cancelEvent(this); |
66 } | 63 } |
67 | 64 |
68 PassRefPtrWillBeRawPtr<HTMLStyleElement> HTMLStyleElement::create(Document& docu
ment, bool createdByParser) | 65 PassRefPtrWillBeRawPtr<HTMLStyleElement> HTMLStyleElement::create(Document& docu
ment, bool createdByParser) |
69 { | 66 { |
70 return adoptRefWillBeRefCountedGarbageCollected(new HTMLStyleElement(documen
t, createdByParser)); | 67 return adoptRefWillBeRefCountedGarbageCollected(new HTMLStyleElement(documen
t, createdByParser)); |
71 } | 68 } |
72 | 69 |
73 void HTMLStyleElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) | 70 void HTMLStyleElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) |
74 { | 71 { |
75 if (name == titleAttr && m_sheet) { | 72 if (name == titleAttr && m_sheet) { |
76 m_sheet->setTitle(value); | 73 m_sheet->setTitle(value); |
77 } else if (name == scopedAttr && ContextFeatures::styleScopedEnabled(&docume
nt())) { | |
78 scopedAttributeChanged(!value.isNull()); | |
79 } else if (name == mediaAttr && inDocument() && document().isActive() && m_s
heet) { | 74 } else if (name == mediaAttr && inDocument() && document().isActive() && m_s
heet) { |
80 m_sheet->setMediaQueries(MediaQuerySet::create(value)); | 75 m_sheet->setMediaQueries(MediaQuerySet::create(value)); |
81 document().modifiedStyleSheet(m_sheet.get()); | 76 document().modifiedStyleSheet(m_sheet.get()); |
82 } else { | 77 } else { |
83 HTMLElement::parseAttribute(name, value); | 78 HTMLElement::parseAttribute(name, value); |
84 } | 79 } |
85 } | 80 } |
86 | 81 |
87 void HTMLStyleElement::scopedAttributeChanged(bool scoped) | |
88 { | |
89 ASSERT(ContextFeatures::styleScopedEnabled(&document())); | |
90 | |
91 if (!inDocument()) | |
92 return; | |
93 | |
94 if (scoped) { | |
95 if (m_scopedStyleRegistrationState == RegisteredAsScoped) | |
96 return; | |
97 | |
98 // As any <style> in a shadow tree is treated as "scoped", | |
99 // need to remove the <style> from its shadow root. | |
100 ContainerNode* scopingNode = 0; | |
101 if (m_scopedStyleRegistrationState == RegisteredInShadowRoot) { | |
102 scopingNode = containingShadowRoot(); | |
103 unregisterWithScopingNode(scopingNode); | |
104 } | |
105 document().styleEngine()->removeStyleSheetCandidateNode(this, scopingNod
e, treeScope()); | |
106 registerWithScopingNode(true); | |
107 | |
108 document().styleEngine()->addStyleSheetCandidateNode(this, false); | |
109 document().modifiedStyleSheet(sheet()); | |
110 return; | |
111 } | |
112 | |
113 // If the <style> was scoped, need to remove the <style> from the scoping | |
114 // element, i.e. the parent node. | |
115 if (m_scopedStyleRegistrationState != RegisteredAsScoped) | |
116 return; | |
117 | |
118 unregisterWithScopingNode(parentNode()); | |
119 document().styleEngine()->removeStyleSheetCandidateNode(this, parentNode(),
treeScope()); | |
120 | |
121 // As any <style> in a shadow tree is treated as "scoped", | |
122 // need to add the <style> to its shadow root. | |
123 if (isInShadowTree()) | |
124 registerWithScopingNode(false); | |
125 | |
126 document().styleEngine()->addStyleSheetCandidateNode(this, false); | |
127 // FIXME: currently need to use FullStyleUpdate here. | |
128 // Because ShadowTreeStyleSheetCollection doesn't know old scoping node. | |
129 // So setNeedsStyleRecalc for old scoping node is not invoked. | |
130 document().modifiedStyleSheet(sheet()); | |
131 } | |
132 | |
133 void HTMLStyleElement::finishParsingChildren() | 82 void HTMLStyleElement::finishParsingChildren() |
134 { | 83 { |
135 StyleElement::finishParsingChildren(this); | 84 StyleElement::finishParsingChildren(this); |
136 HTMLElement::finishParsingChildren(); | 85 HTMLElement::finishParsingChildren(); |
137 } | 86 } |
138 | 87 |
139 void HTMLStyleElement::registerWithScopingNode(bool scoped) | |
140 { | |
141 // Note: We cannot rely on the 'scoped' element already being present when t
his method is invoked. | |
142 // Therefore we cannot rely on scoped()! | |
143 ASSERT(m_scopedStyleRegistrationState == NotRegistered); | |
144 ASSERT(inDocument()); | |
145 if (m_scopedStyleRegistrationState != NotRegistered) | |
146 return; | |
147 | |
148 ContainerNode* scope = scoped ? parentNode() : containingShadowRoot(); | |
149 if (!scope) | |
150 return; | |
151 if (!scope->isElementNode() && !scope->isShadowRoot()) { | |
152 // DocumentFragment nodes should never be inDocument, | |
153 // <style> should not be a child of Document, PI or some such. | |
154 ASSERT_NOT_REACHED(); | |
155 return; | |
156 } | |
157 scope->registerScopedHTMLStyleChild(); | |
158 m_scopedStyleRegistrationState = scoped ? RegisteredAsScoped : RegisteredInS
hadowRoot; | |
159 } | |
160 | |
161 void HTMLStyleElement::unregisterWithScopingNode(ContainerNode* scope) | |
162 { | |
163 ASSERT(m_scopedStyleRegistrationState != NotRegistered || !ContextFeatures::
styleScopedEnabled(&document())); | |
164 if (!isRegisteredAsScoped()) | |
165 return; | |
166 | |
167 ASSERT(scope); | |
168 if (scope) { | |
169 ASSERT(scope->hasScopedHTMLStyleChild()); | |
170 scope->unregisterScopedHTMLStyleChild(); | |
171 } | |
172 | |
173 m_scopedStyleRegistrationState = NotRegistered; | |
174 } | |
175 | |
176 Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode*
insertionPoint) | 88 Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode*
insertionPoint) |
177 { | 89 { |
178 HTMLElement::insertedInto(insertionPoint); | 90 HTMLElement::insertedInto(insertionPoint); |
179 if (insertionPoint->inDocument()) { | 91 if (insertionPoint->inDocument() && isInShadowTree()) { |
180 if (m_scopedStyleRegistrationState == NotRegistered && (scoped() || isIn
ShadowTree())) | 92 if (ShadowRoot* scope = containingShadowRoot()) |
181 registerWithScopingNode(scoped()); | 93 scope->registerScopedHTMLStyleChild(); |
182 } | 94 } |
183 return InsertionShouldCallDidNotifySubtreeInsertions; | 95 return InsertionShouldCallDidNotifySubtreeInsertions; |
184 } | 96 } |
185 | 97 |
186 void HTMLStyleElement::removedFrom(ContainerNode* insertionPoint) | 98 void HTMLStyleElement::removedFrom(ContainerNode* insertionPoint) |
187 { | 99 { |
188 HTMLElement::removedFrom(insertionPoint); | 100 HTMLElement::removedFrom(insertionPoint); |
189 | 101 |
190 // In the current implementation, <style scoped> is only registered if the n
ode is in the document. | 102 if (!insertionPoint->inDocument()) |
191 // That is, because willRemove() is also called if an ancestor is removed fr
om the document. | 103 return; |
192 // Now, if we want to register <style scoped> even if it's not inDocument, | |
193 // we'd need to find a way to discern whether that is the case, or whether <
style scoped> itself is about to be removed. | |
194 ContainerNode* scopingNode = 0; | |
195 if (m_scopedStyleRegistrationState != NotRegistered) { | |
196 if (m_scopedStyleRegistrationState == RegisteredInShadowRoot) { | |
197 scopingNode = containingShadowRoot(); | |
198 if (!scopingNode) | |
199 scopingNode = insertionPoint->containingShadowRoot(); | |
200 } else { | |
201 scopingNode = parentNode() ? parentNode() : insertionPoint; | |
202 } | |
203 | 104 |
204 unregisterWithScopingNode(scopingNode); | 105 ShadowRoot* scopingNode = containingShadowRoot(); |
205 } | 106 if (!scopingNode) |
| 107 scopingNode = insertionPoint->containingShadowRoot(); |
206 | 108 |
207 if (insertionPoint->inDocument()) { | 109 if (scopingNode) |
208 TreeScope* containingScope = containingShadowRoot(); | 110 scopingNode->unregisterScopedHTMLStyleChild(); |
209 StyleElement::removedFromDocument(document(), this, scopingNode, contain
ingScope ? *containingScope : insertionPoint->treeScope()); | 111 |
210 } | 112 TreeScope* containingScope = containingShadowRoot(); |
| 113 StyleElement::removedFromDocument(document(), this, scopingNode, containingS
cope ? *containingScope : insertionPoint->treeScope()); |
211 } | 114 } |
212 | 115 |
213 void HTMLStyleElement::didNotifySubtreeInsertionsToDocument() | 116 void HTMLStyleElement::didNotifySubtreeInsertionsToDocument() |
214 { | 117 { |
215 StyleElement::processStyleSheet(document(), this); | 118 StyleElement::processStyleSheet(document(), this); |
216 } | 119 } |
217 | 120 |
218 void HTMLStyleElement::childrenChanged(bool changedByParser, Node* beforeChange,
Node* afterChange, int childCountDelta) | 121 void HTMLStyleElement::childrenChanged(bool changedByParser, Node* beforeChange,
Node* afterChange, int childCountDelta) |
219 { | 122 { |
220 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi
ldCountDelta); | 123 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi
ldCountDelta); |
221 StyleElement::childrenChanged(this); | 124 StyleElement::childrenChanged(this); |
222 } | 125 } |
223 | 126 |
224 const AtomicString& HTMLStyleElement::media() const | 127 const AtomicString& HTMLStyleElement::media() const |
225 { | 128 { |
226 return getAttribute(mediaAttr); | 129 return getAttribute(mediaAttr); |
227 } | 130 } |
228 | 131 |
229 const AtomicString& HTMLStyleElement::type() const | 132 const AtomicString& HTMLStyleElement::type() const |
230 { | 133 { |
231 return getAttribute(typeAttr); | 134 return getAttribute(typeAttr); |
232 } | 135 } |
233 | 136 |
234 bool HTMLStyleElement::scoped() const | |
235 { | |
236 return fastHasAttribute(scopedAttr) && ContextFeatures::styleScopedEnabled(&
document()); | |
237 } | |
238 | |
239 void HTMLStyleElement::setScoped(bool scopedValue) | |
240 { | |
241 setBooleanAttribute(scopedAttr, scopedValue); | |
242 } | |
243 | |
244 ContainerNode* HTMLStyleElement::scopingNode() | 137 ContainerNode* HTMLStyleElement::scopingNode() |
245 { | 138 { |
246 if (!inDocument()) | 139 if (!inDocument()) |
247 return 0; | 140 return 0; |
248 | 141 |
249 if (!isRegisteredAsScoped()) | 142 if (isInShadowTree()) |
250 return &document(); | |
251 | |
252 if (isRegisteredInShadowRoot()) | |
253 return containingShadowRoot(); | 143 return containingShadowRoot(); |
254 | 144 |
255 return parentNode(); | 145 return &document(); |
256 } | 146 } |
257 | 147 |
258 void HTMLStyleElement::dispatchPendingLoadEvents() | 148 void HTMLStyleElement::dispatchPendingLoadEvents() |
259 { | 149 { |
260 styleLoadEventSender().dispatchPendingEvents(); | 150 styleLoadEventSender().dispatchPendingEvents(); |
261 } | 151 } |
262 | 152 |
263 void HTMLStyleElement::dispatchPendingEvent(StyleEventSender* eventSender) | 153 void HTMLStyleElement::dispatchPendingEvent(StyleEventSender* eventSender) |
264 { | 154 { |
265 ASSERT_UNUSED(eventSender, eventSender == &styleLoadEventSender()); | 155 ASSERT_UNUSED(eventSender, eventSender == &styleLoadEventSender()); |
(...skipping 23 matching lines...) Expand all Loading... |
289 styleSheet->setDisabled(setDisabled); | 179 styleSheet->setDisabled(setDisabled); |
290 } | 180 } |
291 | 181 |
292 void HTMLStyleElement::trace(Visitor* visitor) | 182 void HTMLStyleElement::trace(Visitor* visitor) |
293 { | 183 { |
294 StyleElement::trace(visitor); | 184 StyleElement::trace(visitor); |
295 HTMLElement::trace(visitor); | 185 HTMLElement::trace(visitor); |
296 } | 186 } |
297 | 187 |
298 } | 188 } |
OLD | NEW |