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 "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/Fullscreen.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 blink {
44
45 using namespace HTMLNames;
46
instance()47 CSSDefaultStyleSheets& CSSDefaultStyleSheets::instance()
48 {
49 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<CSSDefaultStyleSheets>, cssDefaultStyleSheets, (adoptPtrWillBeNoop(new CSSDefaultStyleSheets())));
50 return *cssDefaultStyleSheets;
51 }
52
screenEval()53 static const MediaQueryEvaluator& screenEval()
54 {
55 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
56 return staticScreenEval;
57 }
58
printEval()59 static const MediaQueryEvaluator& printEval()
60 {
61 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
62 return staticPrintEval;
63 }
64
parseUASheet(const String & str)65 static PassRefPtrWillBeRawPtr<StyleSheetContents> parseUASheet(const String& str)
66 {
67 RefPtrWillBeRawPtr<StyleSheetContents> sheet = StyleSheetContents::create(CSSParserContext(UASheetMode, 0));
68 sheet->parseString(str);
69 // User Agent stylesheets are parsed once for the lifetime of the renderer
70 // and are intentionally leaked.
71 WTF_ANNOTATE_LEAKING_OBJECT_PTR(sheet.get());
72 return sheet.release();
73 }
74
parseUASheet(const char * characters,unsigned size)75 static PassRefPtrWillBeRawPtr<StyleSheetContents> parseUASheet(const char* characters, unsigned size)
76 {
77 return parseUASheet(String(characters, size));
78 }
79
CSSDefaultStyleSheets()80 CSSDefaultStyleSheets::CSSDefaultStyleSheets()
81 : m_defaultStyle(nullptr)
82 , m_defaultViewportStyle(nullptr)
83 , m_defaultQuirksStyle(nullptr)
84 , m_defaultPrintStyle(nullptr)
85 , m_defaultViewSourceStyle(nullptr)
86 , m_defaultXHTMLMobileProfileStyle(nullptr)
87 , m_defaultTransitionStyle(nullptr)
88 , m_defaultStyleSheet(nullptr)
89 , m_viewportStyleSheet(nullptr)
90 , m_quirksStyleSheet(nullptr)
91 , m_svgStyleSheet(nullptr)
92 , m_mathmlStyleSheet(nullptr)
93 , m_mediaControlsStyleSheet(nullptr)
94 , m_fullscreenStyleSheet(nullptr)
95 {
96 m_defaultStyle = RuleSet::create();
97 m_defaultViewportStyle = RuleSet::create();
98 m_defaultPrintStyle = RuleSet::create();
99 m_defaultQuirksStyle = RuleSet::create();
100
101 // Strict-mode rules.
102 String defaultRules = String(htmlCss, sizeof(htmlCss)) + RenderTheme::theme().extraDefaultStyleSheet();
103 m_defaultStyleSheet = parseUASheet(defaultRules);
104 m_defaultStyle->addRulesFromSheet(defaultStyleSheet(), screenEval());
105 #if OS(ANDROID)
106 String viewportRules(viewportAndroidCss, sizeof(viewportAndroidCss));
107 #else
108 String viewportRules;
109 #endif
110 m_viewportStyleSheet = parseUASheet(viewportRules);
111 m_defaultViewportStyle->addRulesFromSheet(viewportStyleSheet(), screenEval());
112 m_defaultPrintStyle->addRulesFromSheet(defaultStyleSheet(), printEval());
113
114 // Quirks-mode rules.
115 String quirksRules = String(quirksCss, sizeof(quirksCss)) + RenderTheme::theme().extraQuirksStyleSheet();
116 m_quirksStyleSheet = parseUASheet(quirksRules);
117 m_defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet(), screenEval());
118 }
119
defaultViewSourceStyle()120 RuleSet* CSSDefaultStyleSheets::defaultViewSourceStyle()
121 {
122 if (!m_defaultViewSourceStyle) {
123 m_defaultViewSourceStyle = RuleSet::create();
124 // Loaded stylesheet is leaked on purpose.
125 RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(viewSourceCss, sizeof(viewSourceCss));
126 m_defaultViewSourceStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval());
127 }
128 return m_defaultViewSourceStyle.get();
129 }
130
defaultTransitionStyle()131 RuleSet* CSSDefaultStyleSheets::defaultTransitionStyle()
132 {
133 if (!m_defaultTransitionStyle) {
134 m_defaultTransitionStyle = RuleSet::create();
135 // Loaded stylesheet is leaked on purpose.
136 RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(navigationTransitionsCss, sizeof(navigationTransitionsCss));
137 m_defaultTransitionStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval());
138 }
139 return m_defaultTransitionStyle.get();
140 }
141
defaultXHTMLMobileProfileStyle()142 RuleSet* CSSDefaultStyleSheets::defaultXHTMLMobileProfileStyle()
143 {
144 if (!m_defaultXHTMLMobileProfileStyle) {
145 m_defaultXHTMLMobileProfileStyle = RuleSet::create();
146 // Loaded stylesheet is leaked on purpose.
147 RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(xhtmlmpCss, sizeof(xhtmlmpCss));
148 m_defaultXHTMLMobileProfileStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval());
149 }
150 return m_defaultXHTMLMobileProfileStyle.get();
151 }
152
ensureDefaultStyleSheetsForElement(Element * element,bool & changedDefaultStyle)153 void CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(Element* element, bool& changedDefaultStyle)
154 {
155 // FIXME: We should assert that the sheet only styles SVG elements.
156 if (element->isSVGElement() && !m_svgStyleSheet) {
157 m_svgStyleSheet = parseUASheet(svgCss, sizeof(svgCss));
158 m_defaultStyle->addRulesFromSheet(svgStyleSheet(), screenEval());
159 m_defaultPrintStyle->addRulesFromSheet(svgStyleSheet(), printEval());
160 changedDefaultStyle = true;
161 }
162
163 // FIXME: We should assert that the sheet only styles MathML elements.
164 if (element->namespaceURI() == MathMLNames::mathmlNamespaceURI
165 && !m_mathmlStyleSheet) {
166 m_mathmlStyleSheet = parseUASheet(mathmlCss, sizeof(mathmlCss));
167 m_defaultStyle->addRulesFromSheet(mathmlStyleSheet(), screenEval());
168 m_defaultPrintStyle->addRulesFromSheet(mathmlStyleSheet(), printEval());
169 changedDefaultStyle = true;
170 }
171
172 // FIXME: We should assert that this sheet only contains rules for <video> and <audio>.
173 if (!m_mediaControlsStyleSheet && (isHTMLVideoElement(*element) || isHTMLAudioElement(*element))) {
174 String mediaRules = String(mediaControlsCss, sizeof(mediaControlsCss)) + RenderTheme::theme().extraMediaControlsStyleSheet();
175 m_mediaControlsStyleSheet = parseUASheet(mediaRules);
176 m_defaultStyle->addRulesFromSheet(mediaControlsStyleSheet(), screenEval());
177 m_defaultPrintStyle->addRulesFromSheet(mediaControlsStyleSheet(), printEval());
178 changedDefaultStyle = true;
179 }
180
181 // FIXME: This only works because we Force recalc the entire document so the new sheet
182 // is loaded for <html> and the correct styles apply to everyone.
183 if (!m_fullscreenStyleSheet && Fullscreen::isFullScreen(element->document())) {
184 String fullscreenRules = String(fullscreenCss, sizeof(fullscreenCss)) + RenderTheme::theme().extraFullScreenStyleSheet();
185 m_fullscreenStyleSheet = parseUASheet(fullscreenRules);
186 m_defaultStyle->addRulesFromSheet(fullscreenStyleSheet(), screenEval());
187 m_defaultQuirksStyle->addRulesFromSheet(fullscreenStyleSheet(), screenEval());
188 changedDefaultStyle = true;
189 }
190
191 ASSERT(!m_defaultStyle->features().hasIdsInSelectors());
192 ASSERT(m_defaultStyle->features().siblingRules.isEmpty());
193 }
194
trace(Visitor * visitor)195 void CSSDefaultStyleSheets::trace(Visitor* visitor)
196 {
197 visitor->trace(m_defaultStyle);
198 visitor->trace(m_defaultViewportStyle);
199 visitor->trace(m_defaultQuirksStyle);
200 visitor->trace(m_defaultPrintStyle);
201 visitor->trace(m_defaultViewSourceStyle);
202 visitor->trace(m_defaultXHTMLMobileProfileStyle);
203 visitor->trace(m_defaultTransitionStyle);
204 visitor->trace(m_defaultStyleSheet);
205 visitor->trace(m_viewportStyleSheet);
206 visitor->trace(m_quirksStyleSheet);
207 visitor->trace(m_svgStyleSheet);
208 visitor->trace(m_mathmlStyleSheet);
209 visitor->trace(m_mediaControlsStyleSheet);
210 visitor->trace(m_fullscreenStyleSheet);
211 }
212
213 } // namespace blink
214