18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006, 2007 Rob Buis
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Apple, Inc. All rights reserved.
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details.
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB.  If not, write to
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA.
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "StyleElement.h"
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
24e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "Attribute.h"
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h"
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Element.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MediaList.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MediaQueryEvaluator.h"
29db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block#include "ScriptableDocumentParser.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic bool isValidStyleChild(Node* node)
3465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
3565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(node);
3665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    Node::NodeType nodeType = node->nodeType();
3765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return nodeType == Node::TEXT_NODE || nodeType == Node::CDATA_SECTION_NODE;
3865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
3965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
40db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve BlockStyleElement::StyleElement(Document* document, bool createdByParser)
41db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    : m_createdByParser(createdByParser)
42db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    , m_loading(false)
43db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    , m_startLineNumber(0)
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
45db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    if (createdByParser && document && document->scriptableDocumentParser())
46db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        m_startLineNumber = document->scriptableDocumentParser()->lineNumber();
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
49a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochStyleElement::~StyleElement()
50a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
51a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
53db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid StyleElement::insertedIntoDocument(Document* document, Element* element)
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
55db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    ASSERT(document);
56db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    ASSERT(element);
57db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    document->addStyleSheetCandidateNode(element, m_createdByParser);
58db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    if (m_createdByParser)
59db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        return;
60db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
61db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    process(element);
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
64db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid StyleElement::removedFromDocument(Document* document, Element* element)
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
66db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    ASSERT(document);
67db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    ASSERT(element);
68db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    document->removeStyleSheetCandidateNode(element);
69db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (m_sheet) {
716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        ASSERT(m_sheet->ownerNode() == element);
726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_sheet->clearOwnerNode();
736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_sheet = 0;
746b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // If we're in document teardown, then we don't need to do any notification of our sheet's removal.
776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (document->renderer())
785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        document->styleSelectorChanged(DeferRecalcStyle);
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
81db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid StyleElement::childrenChanged(Element* element)
82db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block{
83db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    ASSERT(element);
84db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    if (m_createdByParser)
85db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        return;
86db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
87db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    process(element);
88db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block}
89db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
90db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid StyleElement::finishParsingChildren(Element* element)
91db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block{
92db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    ASSERT(element);
93db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    process(element);
94db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    m_createdByParser = false;
95db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block}
96db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
97db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid StyleElement::process(Element* e)
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!e || !e->inDocument())
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    unsigned resultLength = 0;
1035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    for (Node* c = e->firstChild(); c; c = c->nextSibling()) {
104e7913fbdd6f145fe1644c90c22aa73cb733c9e17Ben Murdoch        if (isValidStyleChild(c)) {
105bcc077531734eca7eb8663a76ab8d4c15721672cBart Sears            unsigned length = c->nodeValue().length();
1062bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (length > std::numeric_limits<unsigned>::max() - resultLength) {
1072bde8e466a4451c7319e3a072d118917957d6554Steve Block                createSheet(e, m_startLineNumber, "");
1082bde8e466a4451c7319e3a072d118917957d6554Steve Block                return;
1092bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
110bcc077531734eca7eb8663a76ab8d4c15721672cBart Sears            resultLength += length;
111bcc077531734eca7eb8663a76ab8d4c15721672cBart Sears        }
1125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
1135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    UChar* text;
1145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    String sheetText = String::createUninitialized(resultLength, text);
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    UChar* p = text;
1175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    for (Node* c = e->firstChild(); c; c = c->nextSibling()) {
11865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (isValidStyleChild(c)) {
1195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            String nodeValue = c->nodeValue();
1205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned nodeLength = nodeValue.length();
1215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            memcpy(p, nodeValue.characters(), nodeLength * sizeof(UChar));
1225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            p += nodeLength;
1235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
1245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
1255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT(p == text + resultLength);
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
127db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    createSheet(e, m_startLineNumber, sheetText);
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
130e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkevoid StyleElement::createSheet(Element* e, int startLineNumber, const String& text)
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
132db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    ASSERT(e);
1336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(e->inDocument());
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Document* document = e->document();
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_sheet) {
136db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        if (m_sheet->isLoading())
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            document->removePendingSheet();
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_sheet = 0;
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If type is empty or CSS, this is a CSS style sheet.
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const AtomicString& type = this->type();
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (type.isEmpty() || (e->isHTMLElement() ? equalIgnoringCase(type, "text/css") : (type == "text/css"))) {
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RefPtr<MediaList> mediaList = MediaList::create(media(), e->isHTMLElement());
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        MediaQueryEvaluator screenEval("screen", true);
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        MediaQueryEvaluator printEval("print", true);
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (screenEval.eval(mediaList.get()) || printEval.eval(mediaList.get())) {
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            document->addPendingSheet();
149db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            m_loading = true;
150d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_sheet = CSSStyleSheet::create(e, String(), KURL(), document->inputEncoding());
1515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            m_sheet->parseStringAtLine(text, !document->inQuirksMode(), startLineNumber);
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_sheet->setMedia(mediaList.get());
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_sheet->setTitle(e->title());
154db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            m_loading = false;
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_sheet)
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_sheet->checkLoaded();
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
162db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockbool StyleElement::isLoading() const
163db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block{
164db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    if (m_loading)
165db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        return true;
166db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    return m_sheet ? m_sheet->isLoading() : false;
167db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block}
168db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
169db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockbool StyleElement::sheetLoaded(Document* document)
170db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block{
171db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    ASSERT(document);
172db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    if (isLoading())
173db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        return false;
174db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
175db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    document->removePendingSheet();
176db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    return true;
177db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block}
178db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
180