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 { | 53 { |
53 ScriptWrappable::init(this); | 54 ScriptWrappable::init(this); |
54 } | 55 } |
55 | 56 |
56 HTMLStyleElement::~HTMLStyleElement() | 57 HTMLStyleElement::~HTMLStyleElement() |
57 { | 58 { |
| 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
). |
58 #if !ENABLE(OILPAN) | 61 #if !ENABLE(OILPAN) |
59 StyleElement::clearDocumentData(document(), this); | 62 StyleElement::clearDocumentData(document(), this); |
60 #endif | 63 #endif |
61 | 64 |
62 styleLoadEventSender().cancelEvent(this); | 65 styleLoadEventSender().cancelEvent(this); |
63 } | 66 } |
64 | 67 |
65 PassRefPtrWillBeRawPtr<HTMLStyleElement> HTMLStyleElement::create(Document& docu
ment, bool createdByParser) | 68 PassRefPtrWillBeRawPtr<HTMLStyleElement> HTMLStyleElement::create(Document& docu
ment, bool createdByParser) |
66 { | 69 { |
67 return adoptRefWillBeRefCountedGarbageCollected(new HTMLStyleElement(documen
t, createdByParser)); | 70 return adoptRefWillBeRefCountedGarbageCollected(new HTMLStyleElement(documen
t, createdByParser)); |
68 } | 71 } |
69 | 72 |
70 void HTMLStyleElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) | 73 void HTMLStyleElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) |
71 { | 74 { |
72 if (name == titleAttr && m_sheet) { | 75 if (name == titleAttr && m_sheet) { |
73 m_sheet->setTitle(value); | 76 m_sheet->setTitle(value); |
| 77 } else if (name == scopedAttr && ContextFeatures::styleScopedEnabled(&docume
nt())) { |
| 78 scopedAttributeChanged(!value.isNull()); |
74 } else if (name == mediaAttr && inDocument() && document().isActive() && m_s
heet) { | 79 } else if (name == mediaAttr && inDocument() && document().isActive() && m_s
heet) { |
75 m_sheet->setMediaQueries(MediaQuerySet::create(value)); | 80 m_sheet->setMediaQueries(MediaQuerySet::create(value)); |
76 document().modifiedStyleSheet(m_sheet.get()); | 81 document().modifiedStyleSheet(m_sheet.get()); |
77 } else { | 82 } else { |
78 HTMLElement::parseAttribute(name, value); | 83 HTMLElement::parseAttribute(name, value); |
79 } | 84 } |
80 } | 85 } |
81 | 86 |
| 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 |
82 void HTMLStyleElement::finishParsingChildren() | 133 void HTMLStyleElement::finishParsingChildren() |
83 { | 134 { |
84 StyleElement::finishParsingChildren(this); | 135 StyleElement::finishParsingChildren(this); |
85 HTMLElement::finishParsingChildren(); | 136 HTMLElement::finishParsingChildren(); |
86 } | 137 } |
87 | 138 |
| 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 |
88 Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode*
insertionPoint) | 176 Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode*
insertionPoint) |
89 { | 177 { |
90 HTMLElement::insertedInto(insertionPoint); | 178 HTMLElement::insertedInto(insertionPoint); |
91 if (insertionPoint->inDocument() && isInShadowTree()) { | 179 if (insertionPoint->inDocument()) { |
92 if (ShadowRoot* scope = containingShadowRoot()) | 180 if (m_scopedStyleRegistrationState == NotRegistered && (scoped() || isIn
ShadowTree())) |
93 scope->registerScopedHTMLStyleChild(); | 181 registerWithScopingNode(scoped()); |
94 } | 182 } |
95 return InsertionShouldCallDidNotifySubtreeInsertions; | 183 return InsertionShouldCallDidNotifySubtreeInsertions; |
96 } | 184 } |
97 | 185 |
98 void HTMLStyleElement::removedFrom(ContainerNode* insertionPoint) | 186 void HTMLStyleElement::removedFrom(ContainerNode* insertionPoint) |
99 { | 187 { |
100 HTMLElement::removedFrom(insertionPoint); | 188 HTMLElement::removedFrom(insertionPoint); |
101 | 189 |
102 ShadowRoot* scopingNode = containingShadowRoot(); | 190 // In the current implementation, <style scoped> is only registered if the n
ode is in the document. |
103 if (!scopingNode) | 191 // That is, because willRemove() is also called if an ancestor is removed fr
om the document. |
104 scopingNode = insertionPoint->containingShadowRoot(); | 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 } |
105 | 203 |
106 if (scopingNode) | 204 unregisterWithScopingNode(scopingNode); |
107 scopingNode->unregisterScopedHTMLStyleChild(); | 205 } |
108 | 206 |
109 if (!insertionPoint->inDocument()) | 207 if (insertionPoint->inDocument()) { |
110 return; | 208 TreeScope* containingScope = containingShadowRoot(); |
111 | 209 StyleElement::removedFromDocument(document(), this, scopingNode, contain
ingScope ? *containingScope : insertionPoint->treeScope()); |
112 TreeScope* containingScope = containingShadowRoot(); | 210 } |
113 StyleElement::removedFromDocument(document(), this, scopingNode, containingS
cope ? *containingScope : insertionPoint->treeScope()); | |
114 } | 211 } |
115 | 212 |
116 void HTMLStyleElement::didNotifySubtreeInsertionsToDocument() | 213 void HTMLStyleElement::didNotifySubtreeInsertionsToDocument() |
117 { | 214 { |
118 StyleElement::processStyleSheet(document(), this); | 215 StyleElement::processStyleSheet(document(), this); |
119 } | 216 } |
120 | 217 |
121 void HTMLStyleElement::childrenChanged(bool changedByParser, Node* beforeChange,
Node* afterChange, int childCountDelta) | 218 void HTMLStyleElement::childrenChanged(bool changedByParser, Node* beforeChange,
Node* afterChange, int childCountDelta) |
122 { | 219 { |
123 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi
ldCountDelta); | 220 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi
ldCountDelta); |
124 StyleElement::childrenChanged(this); | 221 StyleElement::childrenChanged(this); |
125 } | 222 } |
126 | 223 |
127 const AtomicString& HTMLStyleElement::media() const | 224 const AtomicString& HTMLStyleElement::media() const |
128 { | 225 { |
129 return getAttribute(mediaAttr); | 226 return getAttribute(mediaAttr); |
130 } | 227 } |
131 | 228 |
132 const AtomicString& HTMLStyleElement::type() const | 229 const AtomicString& HTMLStyleElement::type() const |
133 { | 230 { |
134 return getAttribute(typeAttr); | 231 return getAttribute(typeAttr); |
135 } | 232 } |
136 | 233 |
| 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 |
137 ContainerNode* HTMLStyleElement::scopingNode() | 244 ContainerNode* HTMLStyleElement::scopingNode() |
138 { | 245 { |
139 if (!inDocument()) | 246 if (!inDocument()) |
140 return 0; | 247 return 0; |
141 | 248 |
142 if (isInShadowTree()) | 249 if (!isRegisteredAsScoped()) |
| 250 return &document(); |
| 251 |
| 252 if (isRegisteredInShadowRoot()) |
143 return containingShadowRoot(); | 253 return containingShadowRoot(); |
144 | 254 |
145 return &document(); | 255 return parentNode(); |
146 } | 256 } |
147 | 257 |
148 void HTMLStyleElement::dispatchPendingLoadEvents() | 258 void HTMLStyleElement::dispatchPendingLoadEvents() |
149 { | 259 { |
150 styleLoadEventSender().dispatchPendingEvents(); | 260 styleLoadEventSender().dispatchPendingEvents(); |
151 } | 261 } |
152 | 262 |
153 void HTMLStyleElement::dispatchPendingEvent(StyleEventSender* eventSender) | 263 void HTMLStyleElement::dispatchPendingEvent(StyleEventSender* eventSender) |
154 { | 264 { |
155 ASSERT_UNUSED(eventSender, eventSender == &styleLoadEventSender()); | 265 ASSERT_UNUSED(eventSender, eventSender == &styleLoadEventSender()); |
(...skipping 23 matching lines...) Expand all Loading... |
179 styleSheet->setDisabled(setDisabled); | 289 styleSheet->setDisabled(setDisabled); |
180 } | 290 } |
181 | 291 |
182 void HTMLStyleElement::trace(Visitor* visitor) | 292 void HTMLStyleElement::trace(Visitor* visitor) |
183 { | 293 { |
184 StyleElement::trace(visitor); | 294 StyleElement::trace(visitor); |
185 HTMLElement::trace(visitor); | 295 HTMLElement::trace(visitor); |
186 } | 296 } |
187 | 297 |
188 } | 298 } |
OLD | NEW |