1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 5 * Copyright (C) 2003, 2010 Apple Inc. All rights reserved. 6 * (C) 2007 Rob Buis (buis (at) kde.org) 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 */ 23 24 #include "config.h" 25 #include "core/html/HTMLStyleElement.h" 26 27 #include "core/HTMLNames.h" 28 #include "core/css/MediaList.h" 29 #include "core/css/StyleSheetContents.h" 30 #include "core/dom/ContextFeatures.h" 31 #include "core/dom/Document.h" 32 #include "core/events/Event.h" 33 #include "core/events/EventSender.h" 34 #include "core/dom/StyleEngine.h" 35 #include "core/dom/shadow/ShadowRoot.h" 36 37 namespace WebCore { 38 39 using namespace HTMLNames; 40 41 static StyleEventSender& styleLoadEventSender() 42 { 43 DEFINE_STATIC_LOCAL(StyleEventSender, sharedLoadEventSender, (EventTypeNames::load)); 44 return sharedLoadEventSender; 45 } 46 47 inline HTMLStyleElement::HTMLStyleElement(Document& document, bool createdByParser) 48 : HTMLElement(styleTag, document) 49 , StyleElement(&document, createdByParser) 50 , m_firedLoad(false) 51 , m_loadedSheet(false) 52 { 53 ScriptWrappable::init(this); 54 } 55 56 HTMLStyleElement::~HTMLStyleElement() 57 { 58 #if !ENABLE(OILPAN) 59 StyleElement::clearDocumentData(document(), this); 60 #endif 61 62 styleLoadEventSender().cancelEvent(this); 63 } 64 65 PassRefPtrWillBeRawPtr<HTMLStyleElement> HTMLStyleElement::create(Document& document, bool createdByParser) 66 { 67 return adoptRefWillBeNoop(new HTMLStyleElement(document, createdByParser)); 68 } 69 70 void HTMLStyleElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 71 { 72 if (name == titleAttr && m_sheet) { 73 m_sheet->setTitle(value); 74 } else if (name == mediaAttr && inDocument() && document().isActive() && m_sheet) { 75 m_sheet->setMediaQueries(MediaQuerySet::create(value)); 76 document().modifiedStyleSheet(m_sheet.get()); 77 } else { 78 HTMLElement::parseAttribute(name, value); 79 } 80 } 81 82 void HTMLStyleElement::finishParsingChildren() 83 { 84 StyleElement::finishParsingChildren(this); 85 HTMLElement::finishParsingChildren(); 86 } 87 88 Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode* insertionPoint) 89 { 90 HTMLElement::insertedInto(insertionPoint); 91 if (insertionPoint->inDocument() && isInShadowTree()) { 92 if (ShadowRoot* scope = containingShadowRoot()) 93 scope->registerScopedHTMLStyleChild(); 94 } 95 return InsertionShouldCallDidNotifySubtreeInsertions; 96 } 97 98 void HTMLStyleElement::removedFrom(ContainerNode* insertionPoint) 99 { 100 HTMLElement::removedFrom(insertionPoint); 101 102 if (!insertionPoint->inDocument()) 103 return; 104 105 ShadowRoot* scopingNode = containingShadowRoot(); 106 if (!scopingNode) 107 scopingNode = insertionPoint->containingShadowRoot(); 108 109 if (scopingNode) 110 scopingNode->unregisterScopedHTMLStyleChild(); 111 112 TreeScope* containingScope = containingShadowRoot(); 113 StyleElement::removedFromDocument(document(), this, scopingNode, containingScope ? *containingScope : insertionPoint->treeScope()); 114 } 115 116 void HTMLStyleElement::didNotifySubtreeInsertionsToDocument() 117 { 118 StyleElement::processStyleSheet(document(), this); 119 } 120 121 void HTMLStyleElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 122 { 123 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 124 StyleElement::childrenChanged(this); 125 } 126 127 const AtomicString& HTMLStyleElement::media() const 128 { 129 return getAttribute(mediaAttr); 130 } 131 132 const AtomicString& HTMLStyleElement::type() const 133 { 134 return getAttribute(typeAttr); 135 } 136 137 ContainerNode* HTMLStyleElement::scopingNode() 138 { 139 if (!inDocument()) 140 return 0; 141 142 if (isInShadowTree()) 143 return containingShadowRoot(); 144 145 return &document(); 146 } 147 148 void HTMLStyleElement::dispatchPendingLoadEvents() 149 { 150 styleLoadEventSender().dispatchPendingEvents(); 151 } 152 153 void HTMLStyleElement::dispatchPendingEvent(StyleEventSender* eventSender) 154 { 155 ASSERT_UNUSED(eventSender, eventSender == &styleLoadEventSender()); 156 dispatchEvent(Event::create(m_loadedSheet ? EventTypeNames::load : EventTypeNames::error)); 157 } 158 159 void HTMLStyleElement::notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred) 160 { 161 if (m_firedLoad) 162 return; 163 m_loadedSheet = !errorOccurred; 164 styleLoadEventSender().dispatchEventSoon(this); 165 m_firedLoad = true; 166 } 167 168 bool HTMLStyleElement::disabled() const 169 { 170 if (!m_sheet) 171 return false; 172 173 return m_sheet->disabled(); 174 } 175 176 void HTMLStyleElement::setDisabled(bool setDisabled) 177 { 178 if (CSSStyleSheet* styleSheet = sheet()) 179 styleSheet->setDisabled(setDisabled); 180 } 181 182 void HTMLStyleElement::trace(Visitor* visitor) 183 { 184 StyleElement::trace(visitor); 185 HTMLElement::trace(visitor); 186 } 187 188 } 189