blob: 0320d1670ee3e610773c32dfa52cd58bcafdef7b [file] [log] [blame]
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +01001/*
2 * Copyright (C) 2006, 2007 Rob Buis
3 * Copyright (C) 2008 Apple, Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include "config.h"
22#include "core/dom/StyleElement.h"
23
24#include "core/css/MediaList.h"
25#include "core/css/MediaQueryEvaluator.h"
26#include "core/css/StyleSheetContents.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010027#include "core/dom/Document.h"
28#include "core/dom/DocumentStyleSheetCollection.h"
29#include "core/dom/Element.h"
30#include "core/dom/ScriptableDocumentParser.h"
Ben Murdoch02772c62013-07-26 10:21:05 +010031#include "core/html/HTMLStyleElement.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010032#include "core/page/ContentSecurityPolicy.h"
Ben Murdoche69819b2013-07-17 14:56:49 +010033#include "wtf/text/StringBuilder.h"
34#include "wtf/text/TextPosition.h"
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010035
36namespace WebCore {
37
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010038static bool isCSS(Element* element, const AtomicString& type)
39{
40 return type.isEmpty() || (element->isHTMLElement() ? equalIgnoringCase(type, "text/css") : (type == "text/css"));
41}
42
43StyleElement::StyleElement(Document* document, bool createdByParser)
44 : m_createdByParser(createdByParser)
45 , m_loading(false)
Torne (Richard Coles)93ac45c2013-05-29 14:40:20 +010046 , m_startPosition(TextPosition::belowRangePosition())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010047{
48 if (createdByParser && document && document->scriptableDocumentParser() && !document->isInDocumentWrite())
Torne (Richard Coles)93ac45c2013-05-29 14:40:20 +010049 m_startPosition = document->scriptableDocumentParser()->textPosition();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010050}
51
52StyleElement::~StyleElement()
53{
Torne (Richard Coles)5267f702013-06-11 10:57:24 +010054 if (m_sheet)
55 clearSheet();
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010056}
57
Torne (Richard Coles)5267f702013-06-11 10:57:24 +010058void StyleElement::processStyleSheet(Document* document, Element* element)
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010059{
60 ASSERT(document);
61 ASSERT(element);
62 document->styleSheetCollection()->addStyleSheetCandidateNode(element, m_createdByParser);
63 if (m_createdByParser)
64 return;
65
66 process(element);
67}
68
Ben Murdoch02772c62013-07-26 10:21:05 +010069void StyleElement::removedFromDocument(Document* document, Element* element, ContainerNode* scopingNode)
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010070{
71 ASSERT(document);
72 ASSERT(element);
Ben Murdoch02772c62013-07-26 10:21:05 +010073 document->styleSheetCollection()->removeStyleSheetCandidateNode(element, scopingNode);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010074
Ben Murdoche69819b2013-07-17 14:56:49 +010075 RefPtr<StyleSheet> removedSheet = m_sheet;
76
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010077 if (m_sheet)
78 clearSheet();
79
80 // If we're in document teardown, then we don't need to do any notification of our sheet's removal.
81 if (document->renderer())
Ben Murdoche69819b2013-07-17 14:56:49 +010082 document->removedStyleSheet(removedSheet.get());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010083}
84
85void StyleElement::clearDocumentData(Document* document, Element* element)
86{
87 if (m_sheet)
88 m_sheet->clearOwnerNode();
89
90 if (element->inDocument())
Ben Murdoch02772c62013-07-26 10:21:05 +010091 document->styleSheetCollection()->removeStyleSheetCandidateNode(element, isHTMLStyleElement(element) ? toHTMLStyleElement(element)->scopingNode() : 0);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +010092}
93
94void StyleElement::childrenChanged(Element* element)
95{
96 ASSERT(element);
97 if (m_createdByParser)
98 return;
99
100 process(element);
101}
102
103void StyleElement::finishParsingChildren(Element* element)
104{
105 ASSERT(element);
106 process(element);
107 m_createdByParser = false;
108}
109
Ben Murdoch591b9582013-07-10 11:41:44 +0100110void StyleElement::process(Element* element)
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100111{
Ben Murdoch591b9582013-07-10 11:41:44 +0100112 if (!element || !element->inDocument())
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100113 return;
Ben Murdoch591b9582013-07-10 11:41:44 +0100114 createSheet(element, element->textFromChildren());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100115}
116
117void StyleElement::clearSheet()
118{
119 ASSERT(m_sheet);
120 m_sheet.release()->clearOwnerNode();
121}
122
Torne (Richard Coles)93ac45c2013-05-29 14:40:20 +0100123void StyleElement::createSheet(Element* e, const String& text)
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100124{
125 ASSERT(e);
126 ASSERT(e->inDocument());
127 Document* document = e->document();
128 if (m_sheet) {
129 if (m_sheet->isLoading())
130 document->styleSheetCollection()->removePendingSheet();
131 clearSheet();
132 }
133
134 // If type is empty or CSS, this is a CSS style sheet.
135 const AtomicString& type = this->type();
Torne (Richard Coles)93ac45c2013-05-29 14:40:20 +0100136 if (document->contentSecurityPolicy()->allowInlineStyle(e->document()->url(), m_startPosition.m_line) && isCSS(e, type)) {
Torne (Richard Coles)5267f702013-06-11 10:57:24 +0100137 RefPtr<MediaQuerySet> mediaQueries = MediaQuerySet::create(media());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100138
139 MediaQueryEvaluator screenEval("screen", true);
140 MediaQueryEvaluator printEval("print", true);
141 if (screenEval.eval(mediaQueries.get()) || printEval.eval(mediaQueries.get())) {
142 document->styleSheetCollection()->addPendingSheet();
143 m_loading = true;
144
Torne (Richard Coles)93ac45c2013-05-29 14:40:20 +0100145 TextPosition startPosition = m_startPosition == TextPosition::belowRangePosition() ? TextPosition::minimumPosition() : m_startPosition;
146 m_sheet = CSSStyleSheet::createInline(e, KURL(), startPosition, document->inputEncoding());
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100147 m_sheet->setMediaQueries(mediaQueries.release());
148 m_sheet->setTitle(e->title());
Ben Murdoche69819b2013-07-17 14:56:49 +0100149 m_sheet->contents()->parseStringAtPosition(text, startPosition, m_createdByParser);
Torne (Richard Coles)53e740f2013-05-09 18:38:43 +0100150
151 m_loading = false;
152 }
153 }
154
155 if (m_sheet)
156 m_sheet->contents()->checkLoaded();
157}
158
159bool StyleElement::isLoading() const
160{
161 if (m_loading)
162 return true;
163 return m_sheet ? m_sheet->isLoading() : false;
164}
165
166bool StyleElement::sheetLoaded(Document* document)
167{
168 ASSERT(document);
169 if (isLoading())
170 return false;
171
172 document->styleSheetCollection()->removePendingSheet();
173 return true;
174}
175
176void StyleElement::startLoadingDynamicSheet(Document* document)
177{
178 ASSERT(document);
179 document->styleSheetCollection()->addPendingSheet();
180}
181
182}