[SVG Masking] Enable the use of <mask> elements for -webkit-mask-image
[WebKit-https.git] / Source / WebCore / css / CSSDefaultStyleSheets.cpp
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 "HTMLBRElement.h"
37 #include "MathMLElement.h"
38 #include "MediaQueryEvaluator.h"
39 #include "Page.h"
40 #include "RenderTheme.h"
41 #include "RuleSet.h"
42 #include "SVGElement.h"
43 #include "StyleSheetContents.h"
44 #include "UserAgentStyleSheets.h"
45 #include <wtf/NeverDestroyed.h>
46
47 namespace WebCore {
48
49 using namespace HTMLNames;
50
51 RuleSet* CSSDefaultStyleSheets::defaultStyle;
52 RuleSet* CSSDefaultStyleSheets::defaultQuirksStyle;
53 RuleSet* CSSDefaultStyleSheets::defaultPrintStyle;
54
55 StyleSheetContents* CSSDefaultStyleSheets::simpleDefaultStyleSheet;
56 StyleSheetContents* CSSDefaultStyleSheets::defaultStyleSheet;
57 StyleSheetContents* CSSDefaultStyleSheets::quirksStyleSheet;
58 StyleSheetContents* CSSDefaultStyleSheets::svgStyleSheet;
59 StyleSheetContents* CSSDefaultStyleSheets::mathMLStyleSheet;
60 StyleSheetContents* CSSDefaultStyleSheets::mediaControlsStyleSheet;
61 StyleSheetContents* CSSDefaultStyleSheets::fullscreenStyleSheet;
62 StyleSheetContents* CSSDefaultStyleSheets::plugInsStyleSheet;
63 StyleSheetContents* CSSDefaultStyleSheets::imageControlsStyleSheet;
64
65 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
66 static 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}";
67
68 static inline bool elementCanUseSimpleDefaultStyle(Element& element)
69 {
70     return is<HTMLHtmlElement>(element) || is<HTMLHeadElement>(element)
71         || is<HTMLBodyElement>(element) || is<HTMLDivElement>(element)
72         || is<HTMLSpanElement>(element) || is<HTMLBRElement>(element)
73         || is<HTMLAnchorElement>(element);
74 }
75
76 static const MediaQueryEvaluator& screenEval()
77 {
78     static NeverDestroyed<const MediaQueryEvaluator> staticScreenEval("screen");
79     return staticScreenEval;
80 }
81
82 static const MediaQueryEvaluator& printEval()
83 {
84     static NeverDestroyed<const MediaQueryEvaluator> staticPrintEval("print");
85     return staticPrintEval;
86 }
87
88 static StyleSheetContents* parseUASheet(const String& str)
89 {
90     StyleSheetContents& sheet = StyleSheetContents::create().leakRef(); // leak the sheet on purpose
91     sheet.parseString(str);
92     return &sheet;
93 }
94
95 static StyleSheetContents* parseUASheet(const char* characters, unsigned size)
96 {
97     return parseUASheet(String(characters, size));
98 }
99
100 void CSSDefaultStyleSheets::initDefaultStyle(Element* root)
101 {
102     if (!defaultStyle) {
103         if (!root || elementCanUseSimpleDefaultStyle(*root))
104             loadSimpleDefaultStyle();
105         else
106             loadFullDefaultStyle();
107     }
108 }
109
110 void CSSDefaultStyleSheets::loadFullDefaultStyle()
111 {
112     if (simpleDefaultStyleSheet) {
113         ASSERT(defaultStyle);
114         ASSERT(defaultPrintStyle == defaultStyle);
115         delete defaultStyle;
116         simpleDefaultStyleSheet->deref();
117         defaultStyle = std::make_unique<RuleSet>().release();
118         defaultPrintStyle = std::make_unique<RuleSet>().release();
119         simpleDefaultStyleSheet = 0;
120     } else {
121         ASSERT(!defaultStyle);
122         defaultStyle = std::make_unique<RuleSet>().release();
123         defaultPrintStyle = std::make_unique<RuleSet>().release();
124         defaultQuirksStyle = std::make_unique<RuleSet>().release();
125     }
126
127     // Strict-mode rules.
128     String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
129     defaultStyleSheet = parseUASheet(defaultRules);
130     defaultStyle->addRulesFromSheet(defaultStyleSheet, screenEval());
131     defaultPrintStyle->addRulesFromSheet(defaultStyleSheet, printEval());
132
133     // Quirks-mode rules.
134     String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
135     quirksStyleSheet = parseUASheet(quirksRules);
136     defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet, screenEval());
137 }
138
139 void CSSDefaultStyleSheets::loadSimpleDefaultStyle()
140 {
141     ASSERT(!defaultStyle);
142     ASSERT(!simpleDefaultStyleSheet);
143
144     defaultStyle = std::make_unique<RuleSet>().release();
145     // There are no media-specific rules in the simple default style.
146     defaultPrintStyle = defaultStyle;
147     defaultQuirksStyle = std::make_unique<RuleSet>().release();
148
149     simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
150     defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
151
152     // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
153 }
154
155 void CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(Element& element, bool& changedDefaultStyle)
156 {
157     if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(element)) {
158         loadFullDefaultStyle();
159         changedDefaultStyle = true;
160     }
161
162     if (is<HTMLElement>(element)) {
163         if (is<HTMLObjectElement>(element) || is<HTMLEmbedElement>(element)) {
164             if (!plugInsStyleSheet) {
165                 String plugInsRules = RenderTheme::themeForPage(element.document().page())->extraPlugInsStyleSheet() + element.document().page()->chrome().client().plugInExtraStyleSheet();
166                 if (plugInsRules.isEmpty())
167                     plugInsRules = String(plugInsUserAgentStyleSheet, sizeof(plugInsUserAgentStyleSheet));
168                 plugInsStyleSheet = parseUASheet(plugInsRules);
169                 defaultStyle->addRulesFromSheet(plugInsStyleSheet, screenEval());
170                 changedDefaultStyle = true;
171             }
172         }
173 #if ENABLE(VIDEO)
174         else if (is<HTMLMediaElement>(element)) {
175             if (!mediaControlsStyleSheet) {
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         }
185 #endif // ENABLE(VIDEO)
186 #if ENABLE(SERVICE_CONTROLS)
187         else if (is<HTMLDivElement>(element) && element.isImageControlsRootElement()) {
188             if (!imageControlsStyleSheet) {
189                 String imageControlsRules = RenderTheme::themeForPage(element.document().page())->imageControlsStyleSheet();
190                 imageControlsStyleSheet = parseUASheet(imageControlsRules);
191                 defaultStyle->addRulesFromSheet(imageControlsStyleSheet, screenEval());
192                 defaultPrintStyle->addRulesFromSheet(imageControlsStyleSheet, printEval());
193                 changedDefaultStyle = true;
194             }
195         }
196 #endif // ENABLE(SERVICE_CONTROLS)
197     } else if (is<SVGElement>(element)) {
198         if (!svgStyleSheet) {
199             // SVG rules.
200             svgStyleSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
201             defaultStyle->addRulesFromSheet(svgStyleSheet, screenEval());
202             defaultPrintStyle->addRulesFromSheet(svgStyleSheet, printEval());
203             changedDefaultStyle = true;
204         }
205     }
206 #if ENABLE(MATHML)
207     else if (is<MathMLElement>(element)) {
208         if (!mathMLStyleSheet) {
209             // MathML rules.
210             mathMLStyleSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
211             defaultStyle->addRulesFromSheet(mathMLStyleSheet, screenEval());
212             defaultPrintStyle->addRulesFromSheet(mathMLStyleSheet, printEval());
213             changedDefaultStyle = true;
214         }
215     }
216 #endif // ENABLE(MATHML)
217
218 #if ENABLE(FULLSCREEN_API)
219     if (!fullscreenStyleSheet && element.document().webkitIsFullScreen()) {
220         String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet();
221         fullscreenStyleSheet = parseUASheet(fullscreenRules);
222         defaultStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval());
223         defaultQuirksStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval());
224         changedDefaultStyle = true;
225     }
226 #endif // ENABLE(FULLSCREEN_API)
227
228     ASSERT(defaultStyle->features().idsInRules.isEmpty());
229     ASSERT(mathMLStyleSheet || defaultStyle->features().siblingRules.isEmpty());
230 }
231
232 } // namespace WebCore