1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4 *           (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2003, 2010 Apple Inc. All rights reserved.
6 *           (C) 2007 Rob Buis (buis@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/dom/Document.h"
30#include "core/events/Event.h"
31#include "core/events/EventSender.h"
32#include "core/dom/shadow/ShadowRoot.h"
33
34namespace blink {
35
36using namespace HTMLNames;
37
38static StyleEventSender& styleLoadEventSender()
39{
40    DEFINE_STATIC_LOCAL(StyleEventSender, sharedLoadEventSender, (EventTypeNames::load));
41    return sharedLoadEventSender;
42}
43
44inline HTMLStyleElement::HTMLStyleElement(Document& document, bool createdByParser)
45    : HTMLElement(styleTag, document)
46    , StyleElement(&document, createdByParser)
47    , m_firedLoad(false)
48    , m_loadedSheet(false)
49{
50}
51
52HTMLStyleElement::~HTMLStyleElement()
53{
54#if !ENABLE(OILPAN)
55    StyleElement::clearDocumentData(document(), this);
56#endif
57
58    styleLoadEventSender().cancelEvent(this);
59}
60
61PassRefPtrWillBeRawPtr<HTMLStyleElement> HTMLStyleElement::create(Document& document, bool createdByParser)
62{
63    return adoptRefWillBeNoop(new HTMLStyleElement(document, createdByParser));
64}
65
66void HTMLStyleElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
67{
68    if (name == titleAttr && m_sheet) {
69        m_sheet->setTitle(value);
70    } else if (name == mediaAttr && inDocument() && document().isActive() && m_sheet) {
71        m_sheet->setMediaQueries(MediaQuerySet::create(value));
72        document().modifiedStyleSheet(m_sheet.get());
73    } else {
74        HTMLElement::parseAttribute(name, value);
75    }
76}
77
78void HTMLStyleElement::finishParsingChildren()
79{
80    StyleElement::finishParsingChildren(this);
81    HTMLElement::finishParsingChildren();
82}
83
84Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode* insertionPoint)
85{
86    HTMLElement::insertedInto(insertionPoint);
87    if (insertionPoint->inDocument() && isInShadowTree()) {
88        if (ShadowRoot* scope = containingShadowRoot())
89            scope->registerScopedHTMLStyleChild();
90    }
91    return InsertionShouldCallDidNotifySubtreeInsertions;
92}
93
94void HTMLStyleElement::removedFrom(ContainerNode* insertionPoint)
95{
96    HTMLElement::removedFrom(insertionPoint);
97
98    if (!insertionPoint->inDocument())
99        return;
100
101    ShadowRoot* scopingNode = containingShadowRoot();
102    if (!scopingNode)
103        scopingNode = insertionPoint->containingShadowRoot();
104
105    if (scopingNode)
106        scopingNode->unregisterScopedHTMLStyleChild();
107
108    TreeScope* containingScope = containingShadowRoot();
109    StyleElement::removedFromDocument(document(), this, scopingNode, containingScope ? *containingScope : insertionPoint->treeScope());
110}
111
112void HTMLStyleElement::didNotifySubtreeInsertionsToDocument()
113{
114    StyleElement::processStyleSheet(document(), this);
115}
116
117void HTMLStyleElement::childrenChanged(const ChildrenChange& change)
118{
119    HTMLElement::childrenChanged(change);
120    StyleElement::childrenChanged(this);
121}
122
123const AtomicString& HTMLStyleElement::media() const
124{
125    return getAttribute(mediaAttr);
126}
127
128const AtomicString& HTMLStyleElement::type() const
129{
130    return getAttribute(typeAttr);
131}
132
133ContainerNode* HTMLStyleElement::scopingNode()
134{
135    if (!inDocument())
136        return 0;
137
138    if (isInShadowTree())
139        return containingShadowRoot();
140
141    return &document();
142}
143
144void HTMLStyleElement::dispatchPendingLoadEvents()
145{
146    styleLoadEventSender().dispatchPendingEvents();
147}
148
149void HTMLStyleElement::dispatchPendingEvent(StyleEventSender* eventSender)
150{
151    ASSERT_UNUSED(eventSender, eventSender == &styleLoadEventSender());
152    dispatchEvent(Event::create(m_loadedSheet ? EventTypeNames::load : EventTypeNames::error));
153}
154
155void HTMLStyleElement::notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred)
156{
157    if (m_firedLoad)
158        return;
159    m_loadedSheet = !errorOccurred;
160    styleLoadEventSender().dispatchEventSoon(this);
161    m_firedLoad = true;
162}
163
164bool HTMLStyleElement::disabled() const
165{
166    if (!m_sheet)
167        return false;
168
169    return m_sheet->disabled();
170}
171
172void HTMLStyleElement::setDisabled(bool setDisabled)
173{
174    if (CSSStyleSheet* styleSheet = sheet())
175        styleSheet->setDisabled(setDisabled);
176}
177
178void HTMLStyleElement::trace(Visitor* visitor)
179{
180    StyleElement::trace(visitor);
181    HTMLElement::trace(visitor);
182}
183
184}
185