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