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) | 52 , m_scoped(false) |
53 { | 53 { |
54 ScriptWrappable::init(this); | 54 ScriptWrappable::init(this); |
55 } | 55 } |
56 | 56 |
57 HTMLStyleElement::~HTMLStyleElement() | 57 HTMLStyleElement::~HTMLStyleElement() |
58 { | 58 { |
59 // During tear-down, willRemove isn't called, so m_scopedStyleRegistrationSt
ate may still be RegisteredAsScoped or RegisteredInShadowRoot here. | 59 // During tear-down, willRemove isn't called, so m_scoped may still be Regis
teredAsScoped or RegisteredInShadowRoot here. |
60 // Therefore we can't ASSERT(m_scopedStyleRegistrationState == NotRegistered
). | 60 // Therefore we can't ASSERT(!m_scoped). |
61 StyleElement::clearDocumentData(document(), this); | 61 StyleElement::clearDocumentData(document(), this); |
62 | 62 |
63 styleLoadEventSender().cancelEvent(this); | 63 styleLoadEventSender().cancelEvent(this); |
64 } | 64 } |
65 | 65 |
66 PassRefPtr<HTMLStyleElement> HTMLStyleElement::create(Document& document, bool c
reatedByParser) | 66 PassRefPtr<HTMLStyleElement> HTMLStyleElement::create(Document& document, bool c
reatedByParser) |
67 { | 67 { |
68 return adoptRef(new HTMLStyleElement(document, createdByParser)); | 68 return adoptRef(new HTMLStyleElement(document, createdByParser)); |
69 } | 69 } |
70 | 70 |
71 void HTMLStyleElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) | 71 void HTMLStyleElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) |
72 { | 72 { |
73 if (name == titleAttr && m_sheet) { | 73 if (name == titleAttr && m_sheet) { |
74 m_sheet->setTitle(value); | 74 m_sheet->setTitle(value); |
75 } else if (name == scopedAttr && ContextFeatures::styleScopedEnabled(&docume
nt())) { | |
76 scopedAttributeChanged(!value.isNull()); | |
77 } else if (name == mediaAttr && inDocument() && document().isActive() && m_s
heet) { | 75 } else if (name == mediaAttr && inDocument() && document().isActive() && m_s
heet) { |
78 m_sheet->setMediaQueries(MediaQuerySet::create(value)); | 76 m_sheet->setMediaQueries(MediaQuerySet::create(value)); |
79 document().modifiedStyleSheet(m_sheet.get(), RecalcStyleDeferred); | 77 document().modifiedStyleSheet(m_sheet.get(), RecalcStyleDeferred); |
80 } else { | 78 } else { |
81 HTMLElement::parseAttribute(name, value); | 79 HTMLElement::parseAttribute(name, value); |
82 } | 80 } |
83 } | 81 } |
84 | 82 |
85 void HTMLStyleElement::scopedAttributeChanged(bool scoped) | |
86 { | |
87 ASSERT(ContextFeatures::styleScopedEnabled(&document())); | |
88 | |
89 if (!inDocument()) | |
90 return; | |
91 | |
92 if (scoped) { | |
93 if (m_scopedStyleRegistrationState == RegisteredAsScoped) | |
94 return; | |
95 | |
96 // As any <style> in a shadow tree is treated as "scoped", | |
97 // need to remove the <style> from its shadow root. | |
98 ContainerNode* scopingNode = 0; | |
99 if (m_scopedStyleRegistrationState == RegisteredInShadowRoot) { | |
100 scopingNode = containingShadowRoot(); | |
101 unregisterWithScopingNode(scopingNode); | |
102 } | |
103 document().styleEngine()->removeStyleSheetCandidateNode(this, scopingNod
e, treeScope()); | |
104 registerWithScopingNode(true); | |
105 | |
106 document().styleEngine()->addStyleSheetCandidateNode(this, false); | |
107 document().modifiedStyleSheet(sheet()); | |
108 return; | |
109 } | |
110 | |
111 // If the <style> was scoped, need to remove the <style> from the scoping | |
112 // element, i.e. the parent node. | |
113 if (m_scopedStyleRegistrationState != RegisteredAsScoped) | |
114 return; | |
115 | |
116 unregisterWithScopingNode(parentNode()); | |
117 document().styleEngine()->removeStyleSheetCandidateNode(this, parentNode(),
treeScope()); | |
118 | |
119 // As any <style> in a shadow tree is treated as "scoped", | |
120 // need to add the <style> to its shadow root. | |
121 if (isInShadowTree()) | |
122 registerWithScopingNode(false); | |
123 | |
124 document().styleEngine()->addStyleSheetCandidateNode(this, false); | |
125 // FIXME: currently need to use FullStyleUpdate here. | |
126 // Because ShadowTreeStyleSheetCollection doesn't know old scoping node. | |
127 // So setNeedsStyleRecalc for old scoping node is not invoked. | |
128 document().modifiedStyleSheet(sheet()); | |
129 } | |
130 | |
131 void HTMLStyleElement::finishParsingChildren() | 83 void HTMLStyleElement::finishParsingChildren() |
132 { | 84 { |
133 StyleElement::finishParsingChildren(this); | 85 StyleElement::finishParsingChildren(this); |
134 HTMLElement::finishParsingChildren(); | 86 HTMLElement::finishParsingChildren(); |
135 } | 87 } |
136 | 88 |
137 void HTMLStyleElement::registerWithScopingNode(bool scoped) | |
138 { | |
139 // Note: We cannot rely on the 'scoped' element already being present when t
his method is invoked. | |
140 // Therefore we cannot rely on scoped()! | |
141 ASSERT(m_scopedStyleRegistrationState == NotRegistered); | |
142 ASSERT(inDocument()); | |
143 if (m_scopedStyleRegistrationState != NotRegistered) | |
144 return; | |
145 | |
146 ContainerNode* scope = scoped ? parentNode() : containingShadowRoot(); | |
147 if (!scope) | |
148 return; | |
149 if (!scope->isElementNode() && !scope->isShadowRoot()) { | |
150 // DocumentFragment nodes should never be inDocument, | |
151 // <style> should not be a child of Document, PI or some such. | |
152 ASSERT_NOT_REACHED(); | |
153 return; | |
154 } | |
155 scope->registerScopedHTMLStyleChild(); | |
156 m_scopedStyleRegistrationState = scoped ? RegisteredAsScoped : RegisteredInS
hadowRoot; | |
157 } | |
158 | |
159 void HTMLStyleElement::unregisterWithScopingNode(ContainerNode* scope) | |
160 { | |
161 ASSERT(m_scopedStyleRegistrationState != NotRegistered || !ContextFeatures::
styleScopedEnabled(&document())); | |
162 if (!isRegisteredAsScoped()) | |
163 return; | |
164 | |
165 ASSERT(scope); | |
166 if (scope) { | |
167 ASSERT(scope->hasScopedHTMLStyleChild()); | |
168 scope->unregisterScopedHTMLStyleChild(); | |
169 } | |
170 | |
171 m_scopedStyleRegistrationState = NotRegistered; | |
172 } | |
173 | |
174 Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode*
insertionPoint) | 89 Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode*
insertionPoint) |
175 { | 90 { |
176 HTMLElement::insertedInto(insertionPoint); | 91 HTMLElement::insertedInto(insertionPoint); |
177 if (insertionPoint->inDocument()) { | 92 if (insertionPoint->inDocument() && isInShadowTree() && !m_scoped) { |
178 if (m_scopedStyleRegistrationState == NotRegistered && (scoped() || isIn
ShadowTree())) | 93 if (ShadowRoot* scope = containingShadowRoot()) { |
179 registerWithScopingNode(scoped()); | 94 scope->registerScopedHTMLStyleChild(); |
| 95 m_scoped = true; |
| 96 } |
180 } | 97 } |
181 return InsertionShouldCallDidNotifySubtreeInsertions; | 98 return InsertionShouldCallDidNotifySubtreeInsertions; |
182 } | 99 } |
183 | 100 |
184 void HTMLStyleElement::removedFrom(ContainerNode* insertionPoint) | 101 void HTMLStyleElement::removedFrom(ContainerNode* insertionPoint) |
185 { | 102 { |
186 HTMLElement::removedFrom(insertionPoint); | 103 HTMLElement::removedFrom(insertionPoint); |
187 | 104 |
188 // In the current implementation, <style scoped> is only registered if the n
ode is in the document. | 105 ShadowRoot* scopingNode = containingShadowRoot(); |
189 // That is, because willRemove() is also called if an ancestor is removed fr
om the document. | 106 if (!scopingNode) |
190 // Now, if we want to register <style scoped> even if it's not inDocument, | 107 scopingNode = insertionPoint->containingShadowRoot(); |
191 // we'd need to find a way to discern whether that is the case, or whether <
style scoped> itself is about to be removed. | |
192 ContainerNode* scopingNode = 0; | |
193 if (m_scopedStyleRegistrationState != NotRegistered) { | |
194 if (m_scopedStyleRegistrationState == RegisteredInShadowRoot) { | |
195 scopingNode = containingShadowRoot(); | |
196 if (!scopingNode) | |
197 scopingNode = insertionPoint->containingShadowRoot(); | |
198 } else { | |
199 scopingNode = parentNode() ? parentNode() : insertionPoint; | |
200 } | |
201 | 108 |
202 unregisterWithScopingNode(scopingNode); | 109 if (scopingNode && m_scoped) { |
| 110 scopingNode->unregisterScopedHTMLStyleChild(); |
| 111 m_scoped = false; |
203 } | 112 } |
204 | 113 |
205 if (insertionPoint->inDocument()) { | 114 if (!insertionPoint->inDocument()) |
206 TreeScope* containingScope = containingShadowRoot(); | 115 return; |
207 StyleElement::removedFromDocument(document(), this, scopingNode, contain
ingScope ? *containingScope : insertionPoint->treeScope()); | 116 |
208 } | 117 TreeScope* containingScope = containingShadowRoot(); |
| 118 StyleElement::removedFromDocument(document(), this, scopingNode, containingS
cope ? *containingScope : insertionPoint->treeScope()); |
209 } | 119 } |
210 | 120 |
211 void HTMLStyleElement::didNotifySubtreeInsertionsToDocument() | 121 void HTMLStyleElement::didNotifySubtreeInsertionsToDocument() |
212 { | 122 { |
213 StyleElement::processStyleSheet(document(), this); | 123 StyleElement::processStyleSheet(document(), this); |
214 } | 124 } |
215 | 125 |
216 void HTMLStyleElement::childrenChanged(bool changedByParser, Node* beforeChange,
Node* afterChange, int childCountDelta) | 126 void HTMLStyleElement::childrenChanged(bool changedByParser, Node* beforeChange,
Node* afterChange, int childCountDelta) |
217 { | 127 { |
218 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi
ldCountDelta); | 128 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi
ldCountDelta); |
219 StyleElement::childrenChanged(this); | 129 StyleElement::childrenChanged(this); |
220 } | 130 } |
221 | 131 |
222 const AtomicString& HTMLStyleElement::media() const | 132 const AtomicString& HTMLStyleElement::media() const |
223 { | 133 { |
224 return getAttribute(mediaAttr); | 134 return getAttribute(mediaAttr); |
225 } | 135 } |
226 | 136 |
227 const AtomicString& HTMLStyleElement::type() const | 137 const AtomicString& HTMLStyleElement::type() const |
228 { | 138 { |
229 return getAttribute(typeAttr); | 139 return getAttribute(typeAttr); |
230 } | 140 } |
231 | 141 |
232 bool HTMLStyleElement::scoped() const | |
233 { | |
234 return fastHasAttribute(scopedAttr) && ContextFeatures::styleScopedEnabled(&
document()); | |
235 } | |
236 | |
237 void HTMLStyleElement::setScoped(bool scopedValue) | |
238 { | |
239 setBooleanAttribute(scopedAttr, scopedValue); | |
240 } | |
241 | |
242 ContainerNode* HTMLStyleElement::scopingNode() | 142 ContainerNode* HTMLStyleElement::scopingNode() |
243 { | 143 { |
244 if (!inDocument()) | 144 if (!inDocument()) |
245 return 0; | 145 return 0; |
246 | 146 |
247 if (!isRegisteredAsScoped()) | 147 if (isScoped()) |
248 return &document(); | |
249 | |
250 if (isRegisteredInShadowRoot()) | |
251 return containingShadowRoot(); | 148 return containingShadowRoot(); |
252 | 149 |
253 return parentNode(); | 150 return &document(); |
254 } | 151 } |
255 | 152 |
256 void HTMLStyleElement::dispatchPendingLoadEvents() | 153 void HTMLStyleElement::dispatchPendingLoadEvents() |
257 { | 154 { |
258 styleLoadEventSender().dispatchPendingEvents(); | 155 styleLoadEventSender().dispatchPendingEvents(); |
259 } | 156 } |
260 | 157 |
261 void HTMLStyleElement::dispatchPendingEvent(StyleEventSender* eventSender) | 158 void HTMLStyleElement::dispatchPendingEvent(StyleEventSender* eventSender) |
262 { | 159 { |
263 ASSERT_UNUSED(eventSender, eventSender == &styleLoadEventSender()); | 160 ASSERT_UNUSED(eventSender, eventSender == &styleLoadEventSender()); |
(...skipping 17 matching lines...) Expand all Loading... |
281 return m_sheet->disabled(); | 178 return m_sheet->disabled(); |
282 } | 179 } |
283 | 180 |
284 void HTMLStyleElement::setDisabled(bool setDisabled) | 181 void HTMLStyleElement::setDisabled(bool setDisabled) |
285 { | 182 { |
286 if (CSSStyleSheet* styleSheet = sheet()) | 183 if (CSSStyleSheet* styleSheet = sheet()) |
287 styleSheet->setDisabled(setDisabled); | 184 styleSheet->setDisabled(setDisabled); |
288 } | 185 } |
289 | 186 |
290 } | 187 } |
OLD | NEW |