/platform/external/webkit/WebCore/css/CSSStyleSheet.cpp

https://github.com/aharish/totoro-gb-opensource-update2 · C++ · 251 lines · 181 code · 36 blank · 34 comment · 29 complexity · 12563d36b0807089aea29d58fd65313d MD5 · raw file

  1. /*
  2. * (C) 1999-2003 Lars Knoll (knoll@kde.org)
  3. * Copyright (C) 2004, 2006, 2007 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. #include "config.h"
  21. #include "CSSStyleSheet.h"
  22. #include "CSSImportRule.h"
  23. #include "CSSNamespace.h"
  24. #include "CSSParser.h"
  25. #include "CSSRuleList.h"
  26. #include "Document.h"
  27. #include "ExceptionCode.h"
  28. #include "Node.h"
  29. #include "SecurityOrigin.h"
  30. #include "TextEncoding.h"
  31. #include <wtf/Deque.h>
  32. namespace WebCore {
  33. CSSStyleSheet::CSSStyleSheet(CSSStyleSheet* parentSheet, const String& href, const KURL& baseURL, const String& charset)
  34. : StyleSheet(parentSheet, href, baseURL)
  35. , m_doc(parentSheet ? parentSheet->doc() : 0)
  36. , m_namespaces(0)
  37. , m_charset(charset)
  38. , m_loadCompleted(false)
  39. , m_strictParsing(!parentSheet || parentSheet->useStrictParsing())
  40. , m_isUserStyleSheet(parentSheet ? parentSheet->isUserStyleSheet() : false)
  41. , m_hasSyntacticallyValidCSSHeader(true)
  42. {
  43. }
  44. CSSStyleSheet::CSSStyleSheet(Node* parentNode, const String& href, const KURL& baseURL, const String& charset)
  45. : StyleSheet(parentNode, href, baseURL)
  46. , m_doc(parentNode->document())
  47. , m_namespaces(0)
  48. , m_charset(charset)
  49. , m_loadCompleted(false)
  50. , m_strictParsing(false)
  51. , m_isUserStyleSheet(false)
  52. , m_hasSyntacticallyValidCSSHeader(true)
  53. {
  54. }
  55. CSSStyleSheet::CSSStyleSheet(CSSRule* ownerRule, const String& href, const KURL& baseURL, const String& charset)
  56. : StyleSheet(ownerRule, href, baseURL)
  57. , m_namespaces(0)
  58. , m_charset(charset)
  59. , m_loadCompleted(false)
  60. , m_strictParsing(!ownerRule || ownerRule->useStrictParsing())
  61. , m_hasSyntacticallyValidCSSHeader(true)
  62. {
  63. CSSStyleSheet* parentSheet = ownerRule ? ownerRule->parentStyleSheet() : 0;
  64. m_doc = parentSheet ? parentSheet->doc() : 0;
  65. m_isUserStyleSheet = parentSheet ? parentSheet->isUserStyleSheet() : false;
  66. }
  67. CSSStyleSheet::~CSSStyleSheet()
  68. {
  69. delete m_namespaces;
  70. }
  71. CSSRule *CSSStyleSheet::ownerRule() const
  72. {
  73. return (parent() && parent()->isRule()) ? static_cast<CSSRule*>(parent()) : 0;
  74. }
  75. unsigned CSSStyleSheet::insertRule(const String& rule, unsigned index, ExceptionCode& ec)
  76. {
  77. ec = 0;
  78. if (index > length()) {
  79. ec = INDEX_SIZE_ERR;
  80. return 0;
  81. }
  82. CSSParser p(useStrictParsing());
  83. RefPtr<CSSRule> r = p.parseRule(this, rule);
  84. if (!r) {
  85. ec = SYNTAX_ERR;
  86. return 0;
  87. }
  88. // ###
  89. // HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at the specified index e.g. if an
  90. //@import rule is inserted after a standard rule set or other at-rule.
  91. insert(index, r.release());
  92. styleSheetChanged();
  93. return index;
  94. }
  95. int CSSStyleSheet::addRule(const String& selector, const String& style, int index, ExceptionCode& ec)
  96. {
  97. insertRule(selector + " { " + style + " }", index, ec);
  98. // As per Microsoft documentation, always return -1.
  99. return -1;
  100. }
  101. int CSSStyleSheet::addRule(const String& selector, const String& style, ExceptionCode& ec)
  102. {
  103. return addRule(selector, style, length(), ec);
  104. }
  105. PassRefPtr<CSSRuleList> CSSStyleSheet::cssRules(bool omitCharsetRules)
  106. {
  107. if (doc() && !doc()->securityOrigin()->canRequest(baseURL()))
  108. return 0;
  109. return CSSRuleList::create(this, omitCharsetRules);
  110. }
  111. void CSSStyleSheet::deleteRule(unsigned index, ExceptionCode& ec)
  112. {
  113. if (index >= length()) {
  114. ec = INDEX_SIZE_ERR;
  115. return;
  116. }
  117. ec = 0;
  118. remove(index);
  119. styleSheetChanged();
  120. }
  121. void CSSStyleSheet::addNamespace(CSSParser* p, const AtomicString& prefix, const AtomicString& uri)
  122. {
  123. if (uri.isNull())
  124. return;
  125. m_namespaces = new CSSNamespace(prefix, uri, m_namespaces);
  126. if (prefix.isEmpty())
  127. // Set the default namespace on the parser so that selectors that omit namespace info will
  128. // be able to pick it up easily.
  129. p->m_defaultNamespace = uri;
  130. }
  131. const AtomicString& CSSStyleSheet::determineNamespace(const AtomicString& prefix)
  132. {
  133. if (prefix.isNull())
  134. return nullAtom; // No namespace. If an element/attribute has a namespace, we won't match it.
  135. if (prefix == starAtom)
  136. return starAtom; // We'll match any namespace.
  137. if (m_namespaces) {
  138. CSSNamespace* ns = m_namespaces->namespaceForPrefix(prefix);
  139. if (ns)
  140. return ns->uri();
  141. }
  142. return nullAtom; // Assume we wont match any namespaces.
  143. }
  144. bool CSSStyleSheet::parseString(const String &string, bool strict)
  145. {
  146. setStrictParsing(strict);
  147. CSSParser p(strict);
  148. p.parseSheet(this, string);
  149. return true;
  150. }
  151. bool CSSStyleSheet::isLoading()
  152. {
  153. unsigned len = length();
  154. for (unsigned i = 0; i < len; ++i) {
  155. StyleBase* rule = item(i);
  156. if (rule->isImportRule() && static_cast<CSSImportRule*>(rule)->isLoading())
  157. return true;
  158. }
  159. return false;
  160. }
  161. void CSSStyleSheet::checkLoaded()
  162. {
  163. if (isLoading())
  164. return;
  165. if (parent())
  166. parent()->checkLoaded();
  167. // Avoid |this| being deleted by scripts that run via HTMLTokenizer::executeScriptsWaitingForStylesheets().
  168. // See <rdar://problem/6622300>.
  169. RefPtr<CSSStyleSheet> protector(this);
  170. m_loadCompleted = ownerNode() ? ownerNode()->sheetLoaded() : true;
  171. }
  172. void CSSStyleSheet::styleSheetChanged()
  173. {
  174. StyleBase* root = this;
  175. while (StyleBase* parent = root->parent())
  176. root = parent;
  177. Document* documentToUpdate = root->isCSSStyleSheet() ? static_cast<CSSStyleSheet*>(root)->doc() : 0;
  178. /* FIXME: We don't need to do everything updateStyleSelector does,
  179. * basically we just need to recreate the document's selector with the
  180. * already existing style sheets.
  181. */
  182. if (documentToUpdate)
  183. documentToUpdate->updateStyleSelector();
  184. }
  185. KURL CSSStyleSheet::completeURL(const String& url) const
  186. {
  187. // Always return a null URL when passed a null string.
  188. // FIXME: Should we change the KURL constructor to have this behavior?
  189. // See also Document::completeURL(const String&)
  190. if (url.isNull() || m_charset.isEmpty())
  191. return StyleSheet::completeURL(url);
  192. const TextEncoding encoding = TextEncoding(m_charset);
  193. return KURL(baseURL(), url, encoding);
  194. }
  195. void CSSStyleSheet::addSubresourceStyleURLs(ListHashSet<KURL>& urls)
  196. {
  197. Deque<CSSStyleSheet*> styleSheetQueue;
  198. styleSheetQueue.append(this);
  199. while (!styleSheetQueue.isEmpty()) {
  200. CSSStyleSheet* styleSheet = styleSheetQueue.first();
  201. styleSheetQueue.removeFirst();
  202. for (unsigned i = 0; i < styleSheet->length(); ++i) {
  203. StyleBase* styleBase = styleSheet->item(i);
  204. if (!styleBase->isRule())
  205. continue;
  206. CSSRule* rule = static_cast<CSSRule*>(styleBase);
  207. if (rule->isImportRule()) {
  208. if (CSSStyleSheet* ruleStyleSheet = static_cast<CSSImportRule*>(rule)->styleSheet())
  209. styleSheetQueue.append(ruleStyleSheet);
  210. }
  211. rule->addSubresourceStyleURLs(urls);
  212. }
  213. }
  214. }
  215. }