1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "config.h"
28 #include "core/testing/InternalSettings.h"
29
30 #include "bindings/v8/ExceptionState.h"
31 #include "core/dom/ExceptionCode.h"
32 #include "core/frame/Settings.h"
33 #include "core/inspector/InspectorController.h"
34 #include "core/page/Page.h"
35 #include "platform/RuntimeEnabledFeatures.h"
36 #include "platform/Supplementable.h"
37 #include "platform/text/LocaleToScriptMapping.h"
38
39 #define InternalSettingsGuardForSettingsReturn(returnValue) \
40 if (!settings()) { \
41 exceptionState.throwDOMException(InvalidAccessError, "The settings object cannot be obtained."); \
42 return returnValue; \
43 }
44
45 #define InternalSettingsGuardForSettings() \
46 if (!settings()) { \
47 exceptionState.throwDOMException(InvalidAccessError, "The settings object cannot be obtained."); \
48 return; \
49 }
50
51 #define InternalSettingsGuardForPage() \
52 if (!page()) { \
53 exceptionState.throwDOMException(InvalidAccessError, "The page object cannot be obtained."); \
54 return; \
55 }
56
57 namespace WebCore {
58
Backup(Settings * settings)59 InternalSettings::Backup::Backup(Settings* settings)
60 : m_originalCSSExclusionsEnabled(RuntimeEnabledFeatures::cssExclusionsEnabled())
61 , m_originalAuthorShadowDOMForAnyElementEnabled(RuntimeEnabledFeatures::authorShadowDOMForAnyElementEnabled())
62 , m_originalCSP(RuntimeEnabledFeatures::experimentalContentSecurityPolicyFeaturesEnabled())
63 , m_originalOverlayScrollbarsEnabled(RuntimeEnabledFeatures::overlayScrollbarsEnabled())
64 , m_originalEditingBehavior(settings->editingBehaviorType())
65 , m_originalTextAutosizingEnabled(settings->textAutosizingEnabled())
66 , m_originalTextAutosizingWindowSizeOverride(settings->textAutosizingWindowSizeOverride())
67 , m_originalAccessibilityFontScaleFactor(settings->accessibilityFontScaleFactor())
68 , m_originalMediaTypeOverride(settings->mediaTypeOverride())
69 , m_originalMockScrollbarsEnabled(settings->mockScrollbarsEnabled())
70 , m_langAttributeAwareFormControlUIEnabled(RuntimeEnabledFeatures::langAttributeAwareFormControlUIEnabled())
71 , m_imagesEnabled(settings->imagesEnabled())
72 , m_defaultVideoPosterURL(settings->defaultVideoPosterURL())
73 , m_originalLayerSquashingEnabled(settings->layerSquashingEnabled())
74 , m_originalPseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled(RuntimeEnabledFeatures::pseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled())
75 {
76 }
77
restoreTo(Settings * settings)78 void InternalSettings::Backup::restoreTo(Settings* settings)
79 {
80 RuntimeEnabledFeatures::setCSSExclusionsEnabled(m_originalCSSExclusionsEnabled);
81 RuntimeEnabledFeatures::setAuthorShadowDOMForAnyElementEnabled(m_originalAuthorShadowDOMForAnyElementEnabled);
82 RuntimeEnabledFeatures::setExperimentalContentSecurityPolicyFeaturesEnabled(m_originalCSP);
83 RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(m_originalOverlayScrollbarsEnabled);
84 settings->setEditingBehaviorType(m_originalEditingBehavior);
85 settings->setTextAutosizingEnabled(m_originalTextAutosizingEnabled);
86 settings->setTextAutosizingWindowSizeOverride(m_originalTextAutosizingWindowSizeOverride);
87 settings->setAccessibilityFontScaleFactor(m_originalAccessibilityFontScaleFactor);
88 settings->setMediaTypeOverride(m_originalMediaTypeOverride);
89 settings->setMockScrollbarsEnabled(m_originalMockScrollbarsEnabled);
90 RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(m_langAttributeAwareFormControlUIEnabled);
91 settings->setImagesEnabled(m_imagesEnabled);
92 settings->setDefaultVideoPosterURL(m_defaultVideoPosterURL);
93 settings->setLayerSquashingEnabled(m_originalLayerSquashingEnabled);
94 settings->genericFontFamilySettings().reset();
95 RuntimeEnabledFeatures::setPseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled(m_originalPseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled);
96 }
97
98 #if ENABLE(OILPAN)
from(Page & page)99 InternalSettings* InternalSettings::from(Page& page)
100 {
101 if (!HeapSupplement<Page>::from(page, supplementName()))
102 HeapSupplement<Page>::provideTo(page, supplementName(), new InternalSettings(page));
103 return static_cast<InternalSettings*>(HeapSupplement<Page>::from(page, supplementName()));
104 }
105 #else
106 // We can't use RefCountedSupplement because that would try to make InternalSettings RefCounted
107 // and InternalSettings is already RefCounted via its base class, InternalSettingsGenerated.
108 // Instead, we manually make InternalSettings supplement Page.
109 class InternalSettingsWrapper : public Supplement<Page> {
110 public:
InternalSettingsWrapper(Page & page)111 explicit InternalSettingsWrapper(Page& page)
112 : m_internalSettings(InternalSettings::create(page)) { }
~InternalSettingsWrapper()113 virtual ~InternalSettingsWrapper() { m_internalSettings->hostDestroyed(); }
114 #if ASSERT_ENABLED
isRefCountedWrapper() const115 virtual bool isRefCountedWrapper() const OVERRIDE { return true; }
116 #endif
internalSettings() const117 InternalSettings* internalSettings() const { return m_internalSettings.get(); }
118
119 private:
120 RefPtr<InternalSettings> m_internalSettings;
121 };
122
from(Page & page)123 InternalSettings* InternalSettings::from(Page& page)
124 {
125 if (!Supplement<Page>::from(page, supplementName()))
126 Supplement<Page>::provideTo(page, supplementName(), adoptPtr(new InternalSettingsWrapper(page)));
127 return static_cast<InternalSettingsWrapper*>(Supplement<Page>::from(page, supplementName()))->internalSettings();
128 }
129 #endif
130
supplementName()131 const char* InternalSettings::supplementName()
132 {
133 return "InternalSettings";
134 }
135
~InternalSettings()136 InternalSettings::~InternalSettings()
137 {
138 }
139
InternalSettings(Page & page)140 InternalSettings::InternalSettings(Page& page)
141 : InternalSettingsGenerated(&page)
142 , m_page(&page)
143 , m_backup(&page.settings())
144 {
145 }
146
resetToConsistentState()147 void InternalSettings::resetToConsistentState()
148 {
149 page()->setPageScaleFactor(1, IntPoint(0, 0));
150
151 m_backup.restoreTo(settings());
152 m_backup = Backup(settings());
153 m_backup.m_originalTextAutosizingEnabled = settings()->textAutosizingEnabled();
154
155 InternalSettingsGenerated::resetToConsistentState();
156 }
157
settings() const158 Settings* InternalSettings::settings() const
159 {
160 if (!page())
161 return 0;
162 return &page()->settings();
163 }
164
setMockScrollbarsEnabled(bool enabled,ExceptionState & exceptionState)165 void InternalSettings::setMockScrollbarsEnabled(bool enabled, ExceptionState& exceptionState)
166 {
167 InternalSettingsGuardForSettings();
168 settings()->setMockScrollbarsEnabled(enabled);
169 }
170
setAuthorShadowDOMForAnyElementEnabled(bool isEnabled)171 void InternalSettings::setAuthorShadowDOMForAnyElementEnabled(bool isEnabled)
172 {
173 RuntimeEnabledFeatures::setAuthorShadowDOMForAnyElementEnabled(isEnabled);
174 }
175
setExperimentalContentSecurityPolicyFeaturesEnabled(bool enabled)176 void InternalSettings::setExperimentalContentSecurityPolicyFeaturesEnabled(bool enabled)
177 {
178 RuntimeEnabledFeatures::setExperimentalContentSecurityPolicyFeaturesEnabled(enabled);
179 }
180
setPseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled(bool enabled)181 void InternalSettings::setPseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled(bool enabled)
182 {
183 RuntimeEnabledFeatures::setPseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled(enabled);
184 }
185
setOverlayScrollbarsEnabled(bool enabled)186 void InternalSettings::setOverlayScrollbarsEnabled(bool enabled)
187 {
188 RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(enabled);
189 }
190
setViewportEnabled(bool enabled,ExceptionState & exceptionState)191 void InternalSettings::setViewportEnabled(bool enabled, ExceptionState& exceptionState)
192 {
193 InternalSettingsGuardForSettings();
194 settings()->setViewportEnabled(enabled);
195 }
196
197 // FIXME: This is a temporary flag and should be removed once squashing is
198 // ready (crbug.com/261605).
setLayerSquashingEnabled(bool enabled,ExceptionState & exceptionState)199 void InternalSettings::setLayerSquashingEnabled(bool enabled, ExceptionState& exceptionState)
200 {
201 InternalSettingsGuardForSettings();
202 settings()->setLayerSquashingEnabled(enabled);
203 }
204
setStandardFontFamily(const AtomicString & family,const String & script,ExceptionState & exceptionState)205 void InternalSettings::setStandardFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
206 {
207 InternalSettingsGuardForSettings();
208 UScriptCode code = scriptNameToCode(script);
209 if (code == USCRIPT_INVALID_CODE)
210 return;
211 settings()->genericFontFamilySettings().setStandard(family, code);
212 settings()->notifyGenericFontFamilyChange();
213 }
214
setSerifFontFamily(const AtomicString & family,const String & script,ExceptionState & exceptionState)215 void InternalSettings::setSerifFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
216 {
217 InternalSettingsGuardForSettings();
218 UScriptCode code = scriptNameToCode(script);
219 if (code == USCRIPT_INVALID_CODE)
220 return;
221 settings()->genericFontFamilySettings().setSerif(family, code);
222 settings()->notifyGenericFontFamilyChange();
223 }
224
setSansSerifFontFamily(const AtomicString & family,const String & script,ExceptionState & exceptionState)225 void InternalSettings::setSansSerifFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
226 {
227 InternalSettingsGuardForSettings();
228 UScriptCode code = scriptNameToCode(script);
229 if (code == USCRIPT_INVALID_CODE)
230 return;
231 settings()->genericFontFamilySettings().setSansSerif(family, code);
232 settings()->notifyGenericFontFamilyChange();
233 }
234
setFixedFontFamily(const AtomicString & family,const String & script,ExceptionState & exceptionState)235 void InternalSettings::setFixedFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
236 {
237 InternalSettingsGuardForSettings();
238 UScriptCode code = scriptNameToCode(script);
239 if (code == USCRIPT_INVALID_CODE)
240 return;
241 settings()->genericFontFamilySettings().setFixed(family, code);
242 settings()->notifyGenericFontFamilyChange();
243 }
244
setCursiveFontFamily(const AtomicString & family,const String & script,ExceptionState & exceptionState)245 void InternalSettings::setCursiveFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
246 {
247 InternalSettingsGuardForSettings();
248 UScriptCode code = scriptNameToCode(script);
249 if (code == USCRIPT_INVALID_CODE)
250 return;
251 settings()->genericFontFamilySettings().setCursive(family, code);
252 settings()->notifyGenericFontFamilyChange();
253 }
254
setFantasyFontFamily(const AtomicString & family,const String & script,ExceptionState & exceptionState)255 void InternalSettings::setFantasyFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
256 {
257 InternalSettingsGuardForSettings();
258 UScriptCode code = scriptNameToCode(script);
259 if (code == USCRIPT_INVALID_CODE)
260 return;
261 settings()->genericFontFamilySettings().setFantasy(family, code);
262 settings()->notifyGenericFontFamilyChange();
263 }
264
setPictographFontFamily(const AtomicString & family,const String & script,ExceptionState & exceptionState)265 void InternalSettings::setPictographFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
266 {
267 InternalSettingsGuardForSettings();
268 UScriptCode code = scriptNameToCode(script);
269 if (code == USCRIPT_INVALID_CODE)
270 return;
271 settings()->genericFontFamilySettings().setPictograph(family, code);
272 settings()->notifyGenericFontFamilyChange();
273 }
274
setTextAutosizingEnabled(bool enabled,ExceptionState & exceptionState)275 void InternalSettings::setTextAutosizingEnabled(bool enabled, ExceptionState& exceptionState)
276 {
277 InternalSettingsGuardForSettings();
278 settings()->setTextAutosizingEnabled(enabled);
279 m_page->inspectorController().setTextAutosizingEnabled(enabled);
280 }
281
setTextAutosizingWindowSizeOverride(int width,int height,ExceptionState & exceptionState)282 void InternalSettings::setTextAutosizingWindowSizeOverride(int width, int height, ExceptionState& exceptionState)
283 {
284 InternalSettingsGuardForSettings();
285 settings()->setTextAutosizingWindowSizeOverride(IntSize(width, height));
286 }
287
setMediaTypeOverride(const String & mediaType,ExceptionState & exceptionState)288 void InternalSettings::setMediaTypeOverride(const String& mediaType, ExceptionState& exceptionState)
289 {
290 InternalSettingsGuardForSettings();
291 settings()->setMediaTypeOverride(mediaType);
292 }
293
setAccessibilityFontScaleFactor(float fontScaleFactor,ExceptionState & exceptionState)294 void InternalSettings::setAccessibilityFontScaleFactor(float fontScaleFactor, ExceptionState& exceptionState)
295 {
296 InternalSettingsGuardForSettings();
297 settings()->setAccessibilityFontScaleFactor(fontScaleFactor);
298 }
299
setCSSExclusionsEnabled(bool enabled)300 void InternalSettings::setCSSExclusionsEnabled(bool enabled)
301 {
302 RuntimeEnabledFeatures::setCSSExclusionsEnabled(enabled);
303 }
304
setEditingBehavior(const String & editingBehavior,ExceptionState & exceptionState)305 void InternalSettings::setEditingBehavior(const String& editingBehavior, ExceptionState& exceptionState)
306 {
307 InternalSettingsGuardForSettings();
308 if (equalIgnoringCase(editingBehavior, "win"))
309 settings()->setEditingBehaviorType(EditingWindowsBehavior);
310 else if (equalIgnoringCase(editingBehavior, "mac"))
311 settings()->setEditingBehaviorType(EditingMacBehavior);
312 else if (equalIgnoringCase(editingBehavior, "unix"))
313 settings()->setEditingBehaviorType(EditingUnixBehavior);
314 else if (equalIgnoringCase(editingBehavior, "android"))
315 settings()->setEditingBehaviorType(EditingAndroidBehavior);
316 else
317 exceptionState.throwDOMException(SyntaxError, "The editing behavior type provided ('" + editingBehavior + "') is invalid.");
318 }
319
setLangAttributeAwareFormControlUIEnabled(bool enabled)320 void InternalSettings::setLangAttributeAwareFormControlUIEnabled(bool enabled)
321 {
322 RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(enabled);
323 }
324
setImagesEnabled(bool enabled,ExceptionState & exceptionState)325 void InternalSettings::setImagesEnabled(bool enabled, ExceptionState& exceptionState)
326 {
327 InternalSettingsGuardForSettings();
328 settings()->setImagesEnabled(enabled);
329 }
330
setDefaultVideoPosterURL(const String & url,ExceptionState & exceptionState)331 void InternalSettings::setDefaultVideoPosterURL(const String& url, ExceptionState& exceptionState)
332 {
333 InternalSettingsGuardForSettings();
334 settings()->setDefaultVideoPosterURL(url);
335 }
336
trace(Visitor * visitor)337 void InternalSettings::trace(Visitor* visitor)
338 {
339 visitor->trace(m_page);
340 InternalSettingsGenerated::trace(visitor);
341 #if ENABLE(OILPAN)
342 HeapSupplement<Page>::trace(visitor);
343 #endif
344 }
345
346 }
347