1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com) 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. 6 * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org> 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 11 * Copyright (C) 2012 Google Inc. All rights reserved. 12 * 13 * This library is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU Library General Public 15 * License as published by the Free Software Foundation; either 16 * version 2 of the License, or (at your option) any later version. 17 * 18 * This library is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * Library General Public License for more details. 22 * 23 * You should have received a copy of the GNU Library General Public License 24 * along with this library; see the file COPYING.LIB. If not, write to 25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 26 * Boston, MA 02110-1301, USA. 27 */ 28 29 #include "config.h" 30 #include "core/css/CSSDefaultStyleSheets.h" 31 32 #include "core/MathMLNames.h" 33 #include "core/UserAgentStyleSheets.h" 34 #include "core/css/MediaQueryEvaluator.h" 35 #include "core/css/RuleSet.h" 36 #include "core/css/StyleSheetContents.h" 37 #include "core/dom/FullscreenElementStack.h" 38 #include "core/html/HTMLAnchorElement.h" 39 #include "core/html/HTMLHtmlElement.h" 40 #include "core/rendering/RenderTheme.h" 41 #include "wtf/LeakAnnotations.h" 42 43 namespace WebCore { 44 45 using namespace HTMLNames; 46 47 CSSDefaultStyleSheets& CSSDefaultStyleSheets::instance() 48 { 49 #if ENABLE(OILPAN) 50 DEFINE_STATIC_LOCAL(Persistent<CSSDefaultStyleSheets>, cssDefaultStyleSheets, (new CSSDefaultStyleSheets())); 51 return *cssDefaultStyleSheets; 52 #else 53 DEFINE_STATIC_LOCAL(CSSDefaultStyleSheets, cssDefaultStyleSheets, ()); 54 return cssDefaultStyleSheets; 55 #endif 56 } 57 58 static const MediaQueryEvaluator& screenEval() 59 { 60 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen")); 61 return staticScreenEval; 62 } 63 64 static const MediaQueryEvaluator& printEval() 65 { 66 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print")); 67 return staticPrintEval; 68 } 69 70 static PassRefPtrWillBeRawPtr<StyleSheetContents> parseUASheet(const String& str) 71 { 72 RefPtrWillBeRawPtr<StyleSheetContents> sheet = StyleSheetContents::create(CSSParserContext(UASheetMode, 0)); 73 sheet->parseString(str); 74 // User Agent stylesheets are parsed once for the lifetime of the renderer 75 // and are intentionally leaked. 76 WTF_ANNOTATE_LEAKING_OBJECT_PTR(sheet.get()); 77 return sheet.release(); 78 } 79 80 static PassRefPtrWillBeRawPtr<StyleSheetContents> parseUASheet(const char* characters, unsigned size) 81 { 82 return parseUASheet(String(characters, size)); 83 } 84 85 CSSDefaultStyleSheets::CSSDefaultStyleSheets() 86 : m_defaultStyle(nullptr) 87 , m_defaultViewportStyle(nullptr) 88 , m_defaultQuirksStyle(nullptr) 89 , m_defaultPrintStyle(nullptr) 90 , m_defaultViewSourceStyle(nullptr) 91 , m_defaultXHTMLMobileProfileStyle(nullptr) 92 , m_defaultTransitionStyle(nullptr) 93 , m_defaultStyleSheet(nullptr) 94 , m_viewportStyleSheet(nullptr) 95 , m_quirksStyleSheet(nullptr) 96 , m_svgStyleSheet(nullptr) 97 , m_mathmlStyleSheet(nullptr) 98 , m_mediaControlsStyleSheet(nullptr) 99 , m_fullscreenStyleSheet(nullptr) 100 { 101 m_defaultStyle = RuleSet::create(); 102 m_defaultViewportStyle = RuleSet::create(); 103 m_defaultPrintStyle = RuleSet::create(); 104 m_defaultQuirksStyle = RuleSet::create(); 105 106 // Strict-mode rules. 107 String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::theme().extraDefaultStyleSheet(); 108 m_defaultStyleSheet = parseUASheet(defaultRules); 109 m_defaultStyle->addRulesFromSheet(defaultStyleSheet(), screenEval()); 110 #if OS(ANDROID) 111 String viewportRules(viewportAndroidUserAgentStyleSheet, sizeof(viewportAndroidUserAgentStyleSheet)); 112 #else 113 String viewportRules; 114 #endif 115 m_viewportStyleSheet = parseUASheet(viewportRules); 116 m_defaultViewportStyle->addRulesFromSheet(viewportStyleSheet(), screenEval()); 117 m_defaultPrintStyle->addRulesFromSheet(defaultStyleSheet(), printEval()); 118 119 // Quirks-mode rules. 120 String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::theme().extraQuirksStyleSheet(); 121 m_quirksStyleSheet = parseUASheet(quirksRules); 122 m_defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet(), screenEval()); 123 } 124 125 RuleSet* CSSDefaultStyleSheets::defaultViewSourceStyle() 126 { 127 if (!m_defaultViewSourceStyle) { 128 m_defaultViewSourceStyle = RuleSet::create(); 129 // Loaded stylesheet is leaked on purpose. 130 RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)); 131 m_defaultViewSourceStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval()); 132 } 133 return m_defaultViewSourceStyle.get(); 134 } 135 136 RuleSet* CSSDefaultStyleSheets::defaultTransitionStyle() 137 { 138 if (!m_defaultTransitionStyle) { 139 m_defaultTransitionStyle = RuleSet::create(); 140 // Loaded stylesheet is leaked on purpose. 141 RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(navigationTransitionsUserAgentStyleSheet, sizeof(navigationTransitionsUserAgentStyleSheet)); 142 m_defaultTransitionStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval()); 143 } 144 return m_defaultTransitionStyle.get(); 145 } 146 147 RuleSet* CSSDefaultStyleSheets::defaultXHTMLMobileProfileStyle() 148 { 149 if (!m_defaultXHTMLMobileProfileStyle) { 150 m_defaultXHTMLMobileProfileStyle = RuleSet::create(); 151 // Loaded stylesheet is leaked on purpose. 152 RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(xhtmlmpUserAgentStyleSheet, sizeof(xhtmlmpUserAgentStyleSheet)); 153 m_defaultXHTMLMobileProfileStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval()); 154 } 155 return m_defaultXHTMLMobileProfileStyle.get(); 156 } 157 158 void CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(Element* element, bool& changedDefaultStyle) 159 { 160 // FIXME: We should assert that the sheet only styles SVG elements. 161 if (element->isSVGElement() && !m_svgStyleSheet) { 162 m_svgStyleSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet)); 163 m_defaultStyle->addRulesFromSheet(svgStyleSheet(), screenEval()); 164 m_defaultPrintStyle->addRulesFromSheet(svgStyleSheet(), printEval()); 165 changedDefaultStyle = true; 166 } 167 168 // FIXME: We should assert that the sheet only styles MathML elements. 169 if (element->namespaceURI() == MathMLNames::mathmlNamespaceURI 170 && !m_mathmlStyleSheet) { 171 m_mathmlStyleSheet = parseUASheet(mathmlUserAgentStyleSheet, 172 sizeof(mathmlUserAgentStyleSheet)); 173 m_defaultStyle->addRulesFromSheet(mathmlStyleSheet(), screenEval()); 174 m_defaultPrintStyle->addRulesFromSheet(mathmlStyleSheet(), printEval()); 175 changedDefaultStyle = true; 176 } 177 178 // FIXME: We should assert that this sheet only contains rules for <video> and <audio>. 179 if (!m_mediaControlsStyleSheet && (isHTMLVideoElement(*element) || isHTMLAudioElement(*element))) { 180 String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::theme().extraMediaControlsStyleSheet(); 181 m_mediaControlsStyleSheet = parseUASheet(mediaRules); 182 m_defaultStyle->addRulesFromSheet(mediaControlsStyleSheet(), screenEval()); 183 m_defaultPrintStyle->addRulesFromSheet(mediaControlsStyleSheet(), printEval()); 184 changedDefaultStyle = true; 185 } 186 187 // FIXME: This only works because we Force recalc the entire document so the new sheet 188 // is loaded for <html> and the correct styles apply to everyone. 189 if (!m_fullscreenStyleSheet && FullscreenElementStack::isFullScreen(element->document())) { 190 String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::theme().extraFullScreenStyleSheet(); 191 m_fullscreenStyleSheet = parseUASheet(fullscreenRules); 192 m_defaultStyle->addRulesFromSheet(fullscreenStyleSheet(), screenEval()); 193 m_defaultQuirksStyle->addRulesFromSheet(fullscreenStyleSheet(), screenEval()); 194 changedDefaultStyle = true; 195 } 196 197 ASSERT(!m_defaultStyle->features().hasIdsInSelectors()); 198 ASSERT(m_defaultStyle->features().siblingRules.isEmpty()); 199 } 200 201 void CSSDefaultStyleSheets::trace(Visitor* visitor) 202 { 203 visitor->trace(m_defaultStyle); 204 visitor->trace(m_defaultViewportStyle); 205 visitor->trace(m_defaultQuirksStyle); 206 visitor->trace(m_defaultPrintStyle); 207 visitor->trace(m_defaultViewSourceStyle); 208 visitor->trace(m_defaultXHTMLMobileProfileStyle); 209 visitor->trace(m_defaultTransitionStyle); 210 visitor->trace(m_defaultStyleSheet); 211 visitor->trace(m_viewportStyleSheet); 212 visitor->trace(m_quirksStyleSheet); 213 visitor->trace(m_svgStyleSheet); 214 visitor->trace(m_mathmlStyleSheet); 215 visitor->trace(m_mediaControlsStyleSheet); 216 visitor->trace(m_fullscreenStyleSheet); 217 } 218 219 } // namespace WebCore 220