| 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 |