1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@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@webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@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 "CSSDefaultStyleSheets.h" 31 32#include "Chrome.h" 33#include "ChromeClient.h" 34#include "HTMLAnchorElement.h" 35#include "HTMLAudioElement.h" 36#include "MediaQueryEvaluator.h" 37#include "Page.h" 38#include "RenderTheme.h" 39#include "RuleSet.h" 40#include "StyleSheetContents.h" 41#include "UserAgentStyleSheets.h" 42#include <wtf/NeverDestroyed.h> 43 44namespace WebCore { 45 46using namespace HTMLNames; 47 48RuleSet* CSSDefaultStyleSheets::defaultStyle; 49RuleSet* CSSDefaultStyleSheets::defaultQuirksStyle; 50RuleSet* CSSDefaultStyleSheets::defaultPrintStyle; 51 52StyleSheetContents* CSSDefaultStyleSheets::simpleDefaultStyleSheet; 53StyleSheetContents* CSSDefaultStyleSheets::defaultStyleSheet; 54StyleSheetContents* CSSDefaultStyleSheets::quirksStyleSheet; 55StyleSheetContents* CSSDefaultStyleSheets::svgStyleSheet; 56StyleSheetContents* CSSDefaultStyleSheets::mathMLStyleSheet; 57StyleSheetContents* CSSDefaultStyleSheets::mediaControlsStyleSheet; 58StyleSheetContents* CSSDefaultStyleSheets::fullscreenStyleSheet; 59StyleSheetContents* CSSDefaultStyleSheets::plugInsStyleSheet; 60StyleSheetContents* CSSDefaultStyleSheets::imageControlsStyleSheet; 61 62// FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet. 63static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}head{display:none}body{margin:8px}div:focus,span:focus,a:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}"; 64 65static inline bool elementCanUseSimpleDefaultStyle(Element* e) 66{ 67 return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || isHTMLAnchorElement(e); 68} 69 70static const MediaQueryEvaluator& screenEval() 71{ 72 static NeverDestroyed<const MediaQueryEvaluator> staticScreenEval("screen"); 73 return staticScreenEval; 74} 75 76static const MediaQueryEvaluator& printEval() 77{ 78 static NeverDestroyed<const MediaQueryEvaluator> staticPrintEval("print"); 79 return staticPrintEval; 80} 81 82static StyleSheetContents* parseUASheet(const String& str) 83{ 84 StyleSheetContents& sheet = StyleSheetContents::create().leakRef(); // leak the sheet on purpose 85 sheet.parseString(str); 86 return &sheet; 87} 88 89static StyleSheetContents* parseUASheet(const char* characters, unsigned size) 90{ 91 return parseUASheet(String(characters, size)); 92} 93 94void CSSDefaultStyleSheets::initDefaultStyle(Element* root) 95{ 96 if (!defaultStyle) { 97 if (!root || elementCanUseSimpleDefaultStyle(root)) 98 loadSimpleDefaultStyle(); 99 else 100 loadFullDefaultStyle(); 101 } 102} 103 104void CSSDefaultStyleSheets::loadFullDefaultStyle() 105{ 106 if (simpleDefaultStyleSheet) { 107 ASSERT(defaultStyle); 108 ASSERT(defaultPrintStyle == defaultStyle); 109 delete defaultStyle; 110 simpleDefaultStyleSheet->deref(); 111 defaultStyle = std::make_unique<RuleSet>().release(); 112 defaultPrintStyle = std::make_unique<RuleSet>().release(); 113 simpleDefaultStyleSheet = 0; 114 } else { 115 ASSERT(!defaultStyle); 116 defaultStyle = std::make_unique<RuleSet>().release(); 117 defaultPrintStyle = std::make_unique<RuleSet>().release(); 118 defaultQuirksStyle = std::make_unique<RuleSet>().release(); 119 } 120 121 // Strict-mode rules. 122 String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet(); 123 defaultStyleSheet = parseUASheet(defaultRules); 124 defaultStyle->addRulesFromSheet(defaultStyleSheet, screenEval()); 125 defaultPrintStyle->addRulesFromSheet(defaultStyleSheet, printEval()); 126 127 // Quirks-mode rules. 128 String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet(); 129 quirksStyleSheet = parseUASheet(quirksRules); 130 defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet, screenEval()); 131} 132 133void CSSDefaultStyleSheets::loadSimpleDefaultStyle() 134{ 135 ASSERT(!defaultStyle); 136 ASSERT(!simpleDefaultStyleSheet); 137 138 defaultStyle = std::make_unique<RuleSet>().release(); 139 // There are no media-specific rules in the simple default style. 140 defaultPrintStyle = defaultStyle; 141 defaultQuirksStyle = std::make_unique<RuleSet>().release(); 142 143 simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet)); 144 defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval()); 145 146 // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style. 147} 148 149void CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(Element* element, bool& changedDefaultStyle) 150{ 151 if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(element)) { 152 loadFullDefaultStyle(); 153 changedDefaultStyle = true; 154 } 155 156 if (element->isSVGElement() && !svgStyleSheet) { 157 // SVG rules. 158 svgStyleSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet)); 159 defaultStyle->addRulesFromSheet(svgStyleSheet, screenEval()); 160 defaultPrintStyle->addRulesFromSheet(svgStyleSheet, printEval()); 161 changedDefaultStyle = true; 162 } 163 164#if ENABLE(MATHML) 165 if (element->isMathMLElement() && !mathMLStyleSheet) { 166 // MathML rules. 167 mathMLStyleSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet)); 168 defaultStyle->addRulesFromSheet(mathMLStyleSheet, screenEval()); 169 defaultPrintStyle->addRulesFromSheet(mathMLStyleSheet, printEval()); 170 changedDefaultStyle = true; 171 } 172#endif 173 174#if ENABLE(VIDEO) 175 if (!mediaControlsStyleSheet && (element->hasTagName(videoTag) || isHTMLAudioElement(element))) { 176 String mediaRules = RenderTheme::themeForPage(element->document().page())->mediaControlsStyleSheet(); 177 if (mediaRules.isEmpty()) 178 mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(element->document().page())->extraMediaControlsStyleSheet(); 179 mediaControlsStyleSheet = parseUASheet(mediaRules); 180 defaultStyle->addRulesFromSheet(mediaControlsStyleSheet, screenEval()); 181 defaultPrintStyle->addRulesFromSheet(mediaControlsStyleSheet, printEval()); 182 changedDefaultStyle = true; 183 } 184#endif 185 186#if ENABLE(FULLSCREEN_API) 187 if (!fullscreenStyleSheet && element->document().webkitIsFullScreen()) { 188 String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet(); 189 fullscreenStyleSheet = parseUASheet(fullscreenRules); 190 defaultStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval()); 191 defaultQuirksStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval()); 192 changedDefaultStyle = true; 193 } 194#endif 195 196#if ENABLE(SERVICE_CONTROLS) 197 if (!imageControlsStyleSheet && element->isImageControlsRootElement()) { 198 String imageControlsRules = RenderTheme::themeForPage(element->document().page())->imageControlsStyleSheet(); 199 imageControlsStyleSheet = parseUASheet(imageControlsRules); 200 defaultStyle->addRulesFromSheet(imageControlsStyleSheet, screenEval()); 201 defaultPrintStyle->addRulesFromSheet(imageControlsStyleSheet, printEval()); 202 changedDefaultStyle = true; 203 } 204#endif 205 206 if (!plugInsStyleSheet && (element->hasTagName(objectTag) || element->hasTagName(embedTag))) { 207 String plugInsRules = RenderTheme::themeForPage(element->document().page())->extraPlugInsStyleSheet() + element->document().page()->chrome().client().plugInExtraStyleSheet(); 208 if (plugInsRules.isEmpty()) 209 plugInsRules = String(plugInsUserAgentStyleSheet, sizeof(plugInsUserAgentStyleSheet)); 210 plugInsStyleSheet = parseUASheet(plugInsRules); 211 defaultStyle->addRulesFromSheet(plugInsStyleSheet, screenEval()); 212 changedDefaultStyle = true; 213 } 214 215 ASSERT(defaultStyle->features().idsInRules.isEmpty()); 216 ASSERT(mathMLStyleSheet || defaultStyle->features().siblingRules.isEmpty()); 217} 218 219} // namespace WebCore 220