1 | /*
|
---|
2 | * Copyright (C) 2018-2021 Apple Inc. All rights reserved.
|
---|
3 | *
|
---|
4 | * Redistribution and use in source and binary forms, with or without
|
---|
5 | * modification, are permitted provided that the following conditions
|
---|
6 | * are met:
|
---|
7 | * 1. Redistributions of source code must retain the above copyright
|
---|
8 | * notice, this list of conditions and the following disclaimer.
|
---|
9 | * 2. Redistributions in binary form must reproduce the above copyright
|
---|
10 | * notice, this list of conditions and the following disclaimer in the
|
---|
11 | * documentation and/or other materials provided with the distribution.
|
---|
12 | *
|
---|
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
---|
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
---|
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
---|
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
---|
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
---|
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
---|
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
---|
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
---|
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
---|
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
---|
23 | * THE POSSIBILITY OF SUCH DAMAGE.
|
---|
24 | */
|
---|
25 |
|
---|
26 | #include "config.h"
|
---|
27 | #include "CSSParserContext.h"
|
---|
28 |
|
---|
29 | #include "CSSImageValue.h"
|
---|
30 | #include "Document.h"
|
---|
31 | #include "DocumentLoader.h"
|
---|
32 | #include "Page.h"
|
---|
33 | #include "RuntimeEnabledFeatures.h"
|
---|
34 | #include "Settings.h"
|
---|
35 | #include <wtf/NeverDestroyed.h>
|
---|
36 |
|
---|
37 | namespace WebCore {
|
---|
38 |
|
---|
39 | const CSSParserContext& strictCSSParserContext()
|
---|
40 | {
|
---|
41 | static MainThreadNeverDestroyed<CSSParserContext> strictContext(HTMLStandardMode);
|
---|
42 | return strictContext;
|
---|
43 | }
|
---|
44 |
|
---|
45 | CSSParserContext::CSSParserContext(CSSParserMode mode, const URL& baseURL)
|
---|
46 | : baseURL(baseURL)
|
---|
47 | , mode(mode)
|
---|
48 | {
|
---|
49 | // FIXME: We should turn all of the features on from their WebCore Settings defaults.
|
---|
50 | if (mode == UASheetMode) {
|
---|
51 | individualTransformPropertiesEnabled = true;
|
---|
52 | focusVisibleEnabled = true;
|
---|
53 | inputSecurityEnabled = true;
|
---|
54 | containmentEnabled = true;
|
---|
55 | #if ENABLE(CSS_TRANSFORM_STYLE_OPTIMIZED_3D)
|
---|
56 | transformStyleOptimized3DEnabled = true;
|
---|
57 | #endif
|
---|
58 | }
|
---|
59 | }
|
---|
60 |
|
---|
61 | #if ENABLE(OVERFLOW_SCROLLING_TOUCH)
|
---|
62 | static bool shouldEnableLegacyOverflowScrollingTouch(const Document& document)
|
---|
63 | {
|
---|
64 | // The legacy -webkit-overflow-scrolling: touch behavior may have been disabled through the website policy,
|
---|
65 | // in that case we want to disable the legacy behavior regardless of what the setting says.
|
---|
66 | if (auto* loader = document.loader()) {
|
---|
67 | if (loader->legacyOverflowScrollingTouchPolicy() == LegacyOverflowScrollingTouchPolicy::Disable)
|
---|
68 | return false;
|
---|
69 | }
|
---|
70 | return document.settings().legacyOverflowScrollingTouchEnabled();
|
---|
71 | }
|
---|
72 | #endif
|
---|
73 |
|
---|
74 | CSSParserContext::CSSParserContext(const Document& document, const URL& sheetBaseURL, const String& charset)
|
---|
75 | : baseURL { sheetBaseURL.isNull() ? document.baseURL() : sheetBaseURL }
|
---|
76 | , charset { charset }
|
---|
77 | , mode { document.inQuirksMode() ? HTMLQuirksMode : HTMLStandardMode }
|
---|
78 | , isHTMLDocument { document.isHTMLDocument() }
|
---|
79 | , hasDocumentSecurityOrigin { sheetBaseURL.isNull() || document.securityOrigin().canRequest(baseURL) }
|
---|
80 | , useSystemAppearance { document.page() ? document.page()->useSystemAppearance() : false }
|
---|
81 | , accentColorEnabled { document.settings().accentColorEnabled() }
|
---|
82 | , aspectRatioEnabled { document.settings().aspectRatioEnabled() }
|
---|
83 | , colorContrastEnabled { document.settings().cssColorContrastEnabled() }
|
---|
84 | , colorFilterEnabled { document.settings().colorFilterEnabled() }
|
---|
85 | , colorMixEnabled { document.settings().cssColorMixEnabled() }
|
---|
86 | , constantPropertiesEnabled { document.settings().constantPropertiesEnabled() }
|
---|
87 | , containmentEnabled { document.settings().cssContainmentEnabled() }
|
---|
88 | , counterStyleAtRulesEnabled { document.settings().cssCounterStyleAtRulesEnabled() }
|
---|
89 | , counterStyleAtRuleImageSymbolsEnabled { document.settings().cssCounterStyleAtRuleImageSymbolsEnabled() }
|
---|
90 | , cssColor4 { document.settings().cssColor4() }
|
---|
91 | , individualTransformPropertiesEnabled { document.settings().cssIndividualTransformPropertiesEnabled() }
|
---|
92 | #if ENABLE(OVERFLOW_SCROLLING_TOUCH)
|
---|
93 | , legacyOverflowScrollingTouchEnabled { shouldEnableLegacyOverflowScrollingTouch(document) }
|
---|
94 | #endif
|
---|
95 | , overscrollBehaviorEnabled { document.settings().overscrollBehaviorEnabled() }
|
---|
96 | , relativeColorSyntaxEnabled { document.settings().cssRelativeColorSyntaxEnabled() }
|
---|
97 | , scrollBehaviorEnabled { document.settings().CSSOMViewSmoothScrollingEnabled() }
|
---|
98 | , springTimingFunctionEnabled { document.settings().springTimingFunctionEnabled() }
|
---|
99 | #if ENABLE(TEXT_AUTOSIZING)
|
---|
100 | , textAutosizingEnabled { document.settings().textAutosizingEnabled() }
|
---|
101 | #endif
|
---|
102 | #if ENABLE(CSS_TRANSFORM_STYLE_OPTIMIZED_3D)
|
---|
103 | , transformStyleOptimized3DEnabled { document.settings().cssTransformStyleOptimized3DEnabled() }
|
---|
104 | #endif
|
---|
105 | , useLegacyBackgroundSizeShorthandBehavior { document.settings().useLegacyBackgroundSizeShorthandBehavior() }
|
---|
106 | , focusVisibleEnabled { document.settings().focusVisibleEnabled() }
|
---|
107 | , hasPseudoClassEnabled { document.settings().hasPseudoClassEnabled() }
|
---|
108 | , cascadeLayersEnabled { document.settings().cssCascadeLayersEnabled() }
|
---|
109 | , containerQueriesEnabled { document.settings().cssContainerQueriesEnabled() }
|
---|
110 | , overflowClipEnabled { document.settings().overflowClipEnabled() }
|
---|
111 | , gradientPremultipliedAlphaInterpolationEnabled { document.settings().cssGradientPremultipliedAlphaInterpolationEnabled() }
|
---|
112 | , gradientInterpolationColorSpacesEnabled { document.settings().cssGradientInterpolationColorSpacesEnabled() }
|
---|
113 | , inputSecurityEnabled { document.settings().cssInputSecurityEnabled() }
|
---|
114 | , subgridEnabled { document.settings().subgridEnabled() }
|
---|
115 | , containIntrinsicSizeEnabled { document.settings().cssContainIntrinsicSizeEnabled() }
|
---|
116 | , motionPathEnabled { document.settings().cssMotionPathEnabled() }
|
---|
117 | , cssTextAlignLastEnabled { document.settings().cssTextAlignLastEnabled() }
|
---|
118 | , cssTextJustifyEnabled { document.settings().cssTextJustifyEnabled() }
|
---|
119 | #if ENABLE(ATTACHMENT_ELEMENT)
|
---|
120 | , attachmentEnabled { RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled() }
|
---|
121 | #endif
|
---|
122 | {
|
---|
123 | }
|
---|
124 |
|
---|
125 | bool operator==(const CSSParserContext& a, const CSSParserContext& b)
|
---|
126 | {
|
---|
127 | return a.baseURL == b.baseURL
|
---|
128 | && a.charset == b.charset
|
---|
129 | && a.mode == b.mode
|
---|
130 | && a.enclosingRuleType == b.enclosingRuleType
|
---|
131 | && a.isHTMLDocument == b.isHTMLDocument
|
---|
132 | && a.hasDocumentSecurityOrigin == b.hasDocumentSecurityOrigin
|
---|
133 | && a.isContentOpaque == b.isContentOpaque
|
---|
134 | && a.useSystemAppearance == b.useSystemAppearance
|
---|
135 | && a.accentColorEnabled == b.accentColorEnabled
|
---|
136 | && a.aspectRatioEnabled == b.aspectRatioEnabled
|
---|
137 | && a.colorContrastEnabled == b.colorContrastEnabled
|
---|
138 | && a.colorFilterEnabled == b.colorFilterEnabled
|
---|
139 | && a.colorMixEnabled == b.colorMixEnabled
|
---|
140 | && a.constantPropertiesEnabled == b.constantPropertiesEnabled
|
---|
141 | && a.containmentEnabled == b.containmentEnabled
|
---|
142 | && a.counterStyleAtRulesEnabled == b.counterStyleAtRulesEnabled
|
---|
143 | && a.counterStyleAtRuleImageSymbolsEnabled == b.counterStyleAtRuleImageSymbolsEnabled
|
---|
144 | && a.cssColor4 == b.cssColor4
|
---|
145 | && a.individualTransformPropertiesEnabled == b.individualTransformPropertiesEnabled
|
---|
146 | #if ENABLE(OVERFLOW_SCROLLING_TOUCH)
|
---|
147 | && a.legacyOverflowScrollingTouchEnabled == b.legacyOverflowScrollingTouchEnabled
|
---|
148 | #endif
|
---|
149 | && a.overscrollBehaviorEnabled == b.overscrollBehaviorEnabled
|
---|
150 | && a.relativeColorSyntaxEnabled == b.relativeColorSyntaxEnabled
|
---|
151 | && a.scrollBehaviorEnabled == b.scrollBehaviorEnabled
|
---|
152 | && a.springTimingFunctionEnabled == b.springTimingFunctionEnabled
|
---|
153 | #if ENABLE(TEXT_AUTOSIZING)
|
---|
154 | && a.textAutosizingEnabled == b.textAutosizingEnabled
|
---|
155 | #endif
|
---|
156 | #if ENABLE(CSS_TRANSFORM_STYLE_OPTIMIZED_3D)
|
---|
157 | && a.transformStyleOptimized3DEnabled == b.transformStyleOptimized3DEnabled
|
---|
158 | #endif
|
---|
159 | && a.useLegacyBackgroundSizeShorthandBehavior == b.useLegacyBackgroundSizeShorthandBehavior
|
---|
160 | && a.focusVisibleEnabled == b.focusVisibleEnabled
|
---|
161 | && a.hasPseudoClassEnabled == b.hasPseudoClassEnabled
|
---|
162 | && a.cascadeLayersEnabled == b.cascadeLayersEnabled
|
---|
163 | && a.containerQueriesEnabled == b.containerQueriesEnabled
|
---|
164 | && a.overflowClipEnabled == b.overflowClipEnabled
|
---|
165 | && a.gradientPremultipliedAlphaInterpolationEnabled == b.gradientPremultipliedAlphaInterpolationEnabled
|
---|
166 | && a.gradientInterpolationColorSpacesEnabled == b.gradientInterpolationColorSpacesEnabled
|
---|
167 | && a.inputSecurityEnabled == b.inputSecurityEnabled
|
---|
168 | #if ENABLE(ATTACHMENT_ELEMENT)
|
---|
169 | && a.attachmentEnabled == b.attachmentEnabled
|
---|
170 | #endif
|
---|
171 | && a.subgridEnabled == b.subgridEnabled
|
---|
172 | && a.containIntrinsicSizeEnabled == b.containIntrinsicSizeEnabled
|
---|
173 | && a.motionPathEnabled == b.motionPathEnabled
|
---|
174 | && a.cssTextAlignLastEnabled == b.cssTextAlignLastEnabled
|
---|
175 | && a.cssTextJustifyEnabled == b.cssTextJustifyEnabled
|
---|
176 | ;
|
---|
177 | }
|
---|
178 |
|
---|
179 | void add(Hasher& hasher, const CSSParserContext& context)
|
---|
180 | {
|
---|
181 | uint64_t bits = context.isHTMLDocument << 0
|
---|
182 | | context.hasDocumentSecurityOrigin << 1
|
---|
183 | | context.isContentOpaque << 2
|
---|
184 | | context.useSystemAppearance << 3
|
---|
185 | | context.aspectRatioEnabled << 4
|
---|
186 | | context.colorContrastEnabled << 5
|
---|
187 | | context.colorFilterEnabled << 6
|
---|
188 | | context.colorMixEnabled << 7
|
---|
189 | | context.constantPropertiesEnabled << 8
|
---|
190 | | context.containmentEnabled << 9
|
---|
191 | | context.cssColor4 << 10
|
---|
192 | | context.individualTransformPropertiesEnabled << 11
|
---|
193 | #if ENABLE(OVERFLOW_SCROLLING_TOUCH)
|
---|
194 | | context.legacyOverflowScrollingTouchEnabled << 12
|
---|
195 | #endif
|
---|
196 | | context.overscrollBehaviorEnabled << 13
|
---|
197 | | context.relativeColorSyntaxEnabled << 14
|
---|
198 | | context.scrollBehaviorEnabled << 15
|
---|
199 | | context.springTimingFunctionEnabled << 16
|
---|
200 | #if ENABLE(TEXT_AUTOSIZING)
|
---|
201 | | context.textAutosizingEnabled << 17
|
---|
202 | #endif
|
---|
203 | #if ENABLE(CSS_TRANSFORM_STYLE_OPTIMIZED_3D)
|
---|
204 | | context.transformStyleOptimized3DEnabled << 18
|
---|
205 | #endif
|
---|
206 | | context.useLegacyBackgroundSizeShorthandBehavior << 19
|
---|
207 | | context.focusVisibleEnabled << 20
|
---|
208 | | context.hasPseudoClassEnabled << 21
|
---|
209 | | context.cascadeLayersEnabled << 22
|
---|
210 | | context.containerQueriesEnabled << 23
|
---|
211 | | context.overflowClipEnabled << 24
|
---|
212 | | context.gradientPremultipliedAlphaInterpolationEnabled << 25
|
---|
213 | | context.gradientInterpolationColorSpacesEnabled << 27
|
---|
214 | #if ENABLE(ATTACHMENT_ELEMENT)
|
---|
215 | | context.attachmentEnabled << 28
|
---|
216 | #endif
|
---|
217 | | context.accentColorEnabled << 29
|
---|
218 | | context.inputSecurityEnabled << 30
|
---|
219 | | context.subgridEnabled << 31
|
---|
220 | | (uint64_t)context.containIntrinsicSizeEnabled << 32
|
---|
221 | | (uint64_t)context.motionPathEnabled << 33
|
---|
222 | | (uint64_t)context.cssTextAlignLastEnabled << 34
|
---|
223 | | (uint64_t)context.cssTextJustifyEnabled << 35
|
---|
224 | | (uint64_t)context.mode << 36; // This is multiple bits, so keep it last.
|
---|
225 |
|
---|
226 | add(hasher, context.baseURL, context.charset, bits);
|
---|
227 | }
|
---|
228 |
|
---|
229 | bool CSSParserContext::isPropertyRuntimeDisabled(CSSPropertyID property) const
|
---|
230 | {
|
---|
231 | switch (property) {
|
---|
232 | case CSSPropertyAdditiveSymbols:
|
---|
233 | case CSSPropertyFallback:
|
---|
234 | case CSSPropertyPad:
|
---|
235 | case CSSPropertySymbols:
|
---|
236 | case CSSPropertyNegative:
|
---|
237 | case CSSPropertyPrefix:
|
---|
238 | case CSSPropertyRange:
|
---|
239 | case CSSPropertySuffix:
|
---|
240 | case CSSPropertySystem:
|
---|
241 | return !counterStyleAtRulesEnabled;
|
---|
242 | case CSSPropertyAccentColor:
|
---|
243 | return !accentColorEnabled;
|
---|
244 | case CSSPropertyAspectRatio:
|
---|
245 | return !aspectRatioEnabled;
|
---|
246 | case CSSPropertyContain:
|
---|
247 | return !containmentEnabled;
|
---|
248 | case CSSPropertyAppleColorFilter:
|
---|
249 | return !colorFilterEnabled;
|
---|
250 | case CSSPropertyInputSecurity:
|
---|
251 | return !inputSecurityEnabled;
|
---|
252 | case CSSPropertyTranslate:
|
---|
253 | case CSSPropertyRotate:
|
---|
254 | case CSSPropertyScale:
|
---|
255 | return !individualTransformPropertiesEnabled;
|
---|
256 | case CSSPropertyOverscrollBehavior:
|
---|
257 | case CSSPropertyOverscrollBehaviorBlock:
|
---|
258 | case CSSPropertyOverscrollBehaviorInline:
|
---|
259 | case CSSPropertyOverscrollBehaviorX:
|
---|
260 | case CSSPropertyOverscrollBehaviorY:
|
---|
261 | return !overscrollBehaviorEnabled;
|
---|
262 | case CSSPropertyScrollBehavior:
|
---|
263 | return !scrollBehaviorEnabled;
|
---|
264 | #if ENABLE(TEXT_AUTOSIZING) && !PLATFORM(IOS_FAMILY)
|
---|
265 | case CSSPropertyWebkitTextSizeAdjust:
|
---|
266 | return !textAutosizingEnabled;
|
---|
267 | #endif
|
---|
268 | #if ENABLE(OVERFLOW_SCROLLING_TOUCH)
|
---|
269 | case CSSPropertyWebkitOverflowScrolling:
|
---|
270 | return !legacyOverflowScrollingTouchEnabled;
|
---|
271 | #endif
|
---|
272 | case CSSPropertyContainIntrinsicSize:
|
---|
273 | case CSSPropertyContainIntrinsicHeight:
|
---|
274 | case CSSPropertyContainIntrinsicWidth:
|
---|
275 | case CSSPropertyContainIntrinsicBlockSize:
|
---|
276 | case CSSPropertyContainIntrinsicInlineSize:
|
---|
277 | return !containIntrinsicSizeEnabled;
|
---|
278 | case CSSPropertyOffset:
|
---|
279 | case CSSPropertyOffsetPath:
|
---|
280 | case CSSPropertyOffsetDistance:
|
---|
281 | case CSSPropertyOffsetPosition:
|
---|
282 | case CSSPropertyOffsetAnchor:
|
---|
283 | case CSSPropertyOffsetRotate:
|
---|
284 | return !motionPathEnabled;
|
---|
285 | case CSSPropertyTextAlignLast:
|
---|
286 | return !cssTextAlignLastEnabled;
|
---|
287 | case CSSPropertyTextJustify:
|
---|
288 | return !cssTextJustifyEnabled;
|
---|
289 | default:
|
---|
290 | return false;
|
---|
291 | }
|
---|
292 | }
|
---|
293 |
|
---|
294 | ResolvedURL CSSParserContext::completeURL(const String& string) const
|
---|
295 | {
|
---|
296 | auto result = [&] () -> ResolvedURL {
|
---|
297 | // See also Document::completeURL(const String&)
|
---|
298 | if (string.isNull())
|
---|
299 | return { };
|
---|
300 |
|
---|
301 | if (CSSValue::isCSSLocalURL(string))
|
---|
302 | return { string, URL { string } };
|
---|
303 |
|
---|
304 | if (charset.isEmpty())
|
---|
305 | return { string, { baseURL, string } };
|
---|
306 | auto encodingForURLParsing = PAL::TextEncoding { charset }.encodingForFormSubmissionOrURLParsing();
|
---|
307 | return { string, { baseURL, string, encodingForURLParsing == PAL::UTF8Encoding() ? nullptr : &encodingForURLParsing } };
|
---|
308 | }();
|
---|
309 |
|
---|
310 | if (mode == WebVTTMode && !result.resolvedURL.protocolIsData())
|
---|
311 | return { };
|
---|
312 |
|
---|
313 | return result;
|
---|
314 | }
|
---|
315 |
|
---|
316 | }
|
---|