../WebCore: [Windows] Refactor RuntimeEnabledFeatures as a Singleton
[WebKit-https.git] / Source / WebCore / testing / InternalSettings.cpp
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 "InternalSettings.h"
29
30 #include "CaptionUserPreferences.h"
31 #include "Document.h"
32 #include "ExceptionCode.h"
33 #include "Frame.h"
34 #include "FrameView.h"
35 #include "Language.h"
36 #include "LocaleToScriptMapping.h"
37 #include "Page.h"
38 #include "PageGroup.h"
39 #include "RuntimeEnabledFeatures.h"
40 #include "Settings.h"
41 #include "Supplementable.h"
42 #include "TextRun.h"
43
44 #if ENABLE(INPUT_TYPE_COLOR)
45 #include "ColorChooser.h"
46 #endif
47
48 #define InternalSettingsGuardForSettingsReturn(returnValue) \
49     if (!settings()) { \
50         ec = INVALID_ACCESS_ERR; \
51         return returnValue; \
52     }
53
54 #define InternalSettingsGuardForSettings()  \
55     if (!settings()) { \
56         ec = INVALID_ACCESS_ERR; \
57         return; \
58     }
59
60 #define InternalSettingsGuardForPage() \
61     if (!page()) { \
62         ec = INVALID_ACCESS_ERR; \
63         return; \
64     }
65
66 namespace WebCore {
67
68 InternalSettings::Backup::Backup(Settings& settings)
69     : m_originalCSSExclusionsEnabled(RuntimeEnabledFeatures::sharedFeatures().cssExclusionsEnabled())
70     , m_originalCSSShapesEnabled(RuntimeEnabledFeatures::sharedFeatures().cssShapesEnabled())
71     , m_originalCSSVariablesEnabled(settings.cssVariablesEnabled())
72 #if ENABLE(SHADOW_DOM)
73     , m_originalShadowDOMEnabled(RuntimeEnabledFeatures::sharedFeatures().shadowDOMEnabled())
74     , m_originalAuthorShadowDOMForAnyElementEnabled(RuntimeEnabledFeatures::sharedFeatures().authorShadowDOMForAnyElementEnabled())
75 #endif
76 #if ENABLE(STYLE_SCOPED)
77     , m_originalStyleScoped(RuntimeEnabledFeatures::sharedFeatures().styleScopedEnabled())
78 #endif
79     , m_originalEditingBehavior(settings.editingBehaviorType())
80 #if ENABLE(TEXT_AUTOSIZING)
81     , m_originalTextAutosizingEnabled(settings.textAutosizingEnabled())
82     , m_originalTextAutosizingWindowSizeOverride(settings.textAutosizingWindowSizeOverride())
83     , m_originalTextAutosizingFontScaleFactor(settings.textAutosizingFontScaleFactor())
84 #endif
85     , m_originalMediaTypeOverride(settings.mediaTypeOverride())
86     , m_originalCanvasUsesAcceleratedDrawing(settings.canvasUsesAcceleratedDrawing())
87     , m_originalMockScrollbarsEnabled(settings.mockScrollbarsEnabled())
88     , m_langAttributeAwareFormControlUIEnabled(RuntimeEnabledFeatures::sharedFeatures().langAttributeAwareFormControlUIEnabled())
89     , m_imagesEnabled(settings.areImagesEnabled())
90     , m_minimumTimerInterval(settings.minDOMTimerInterval())
91 #if ENABLE(VIDEO_TRACK)
92     , m_shouldDisplaySubtitles(settings.shouldDisplaySubtitles())
93     , m_shouldDisplayCaptions(settings.shouldDisplayCaptions())
94     , m_shouldDisplayTextDescriptions(settings.shouldDisplayTextDescriptions())
95 #endif
96     , m_defaultVideoPosterURL(settings.defaultVideoPosterURL())
97     , m_originalTimeWithoutMouseMovementBeforeHidingControls(settings.timeWithoutMouseMovementBeforeHidingControls())
98     , m_useLegacyBackgroundSizeShorthandBehavior(settings.useLegacyBackgroundSizeShorthandBehavior())
99     , m_autoscrollForDragAndDropEnabled(settings.autoscrollForDragAndDropEnabled())
100 {
101 }
102
103 void InternalSettings::Backup::restoreTo(Settings& settings)
104 {
105     RuntimeEnabledFeatures::sharedFeatures().setCSSExclusionsEnabled(m_originalCSSExclusionsEnabled);
106     RuntimeEnabledFeatures::sharedFeatures().setCSSShapesEnabled(m_originalCSSShapesEnabled);
107     settings.setCSSVariablesEnabled(m_originalCSSVariablesEnabled);
108 #if ENABLE(SHADOW_DOM)
109     RuntimeEnabledFeatures::sharedFeatures().setShadowDOMEnabled(m_originalShadowDOMEnabled);
110     RuntimeEnabledFeatures::sharedFeatures().setAuthorShadowDOMForAnyElementEnabled(m_originalAuthorShadowDOMForAnyElementEnabled);
111 #endif
112 #if ENABLE(STYLE_SCOPED)
113     RuntimeEnabledFeatures::sharedFeatures().setStyleScopedEnabled(m_originalStyleScoped);
114 #endif
115     settings.setEditingBehaviorType(m_originalEditingBehavior);
116 #if ENABLE(TEXT_AUTOSIZING)
117     settings.setTextAutosizingEnabled(m_originalTextAutosizingEnabled);
118     settings.setTextAutosizingWindowSizeOverride(m_originalTextAutosizingWindowSizeOverride);
119     settings.setTextAutosizingFontScaleFactor(m_originalTextAutosizingFontScaleFactor);
120 #endif
121     settings.setMediaTypeOverride(m_originalMediaTypeOverride);
122     settings.setCanvasUsesAcceleratedDrawing(m_originalCanvasUsesAcceleratedDrawing);
123     settings.setMockScrollbarsEnabled(m_originalMockScrollbarsEnabled);
124     RuntimeEnabledFeatures::sharedFeatures().setLangAttributeAwareFormControlUIEnabled(m_langAttributeAwareFormControlUIEnabled);
125     settings.setImagesEnabled(m_imagesEnabled);
126     settings.setMinDOMTimerInterval(m_minimumTimerInterval);
127 #if ENABLE(VIDEO_TRACK)
128     settings.setShouldDisplaySubtitles(m_shouldDisplaySubtitles);
129     settings.setShouldDisplayCaptions(m_shouldDisplayCaptions);
130     settings.setShouldDisplayTextDescriptions(m_shouldDisplayTextDescriptions);
131 #endif
132     settings.setDefaultVideoPosterURL(m_defaultVideoPosterURL);
133     settings.setTimeWithoutMouseMovementBeforeHidingControls(m_originalTimeWithoutMouseMovementBeforeHidingControls);
134     settings.setUseLegacyBackgroundSizeShorthandBehavior(m_useLegacyBackgroundSizeShorthandBehavior);
135     settings.setAutoscrollForDragAndDropEnabled(m_autoscrollForDragAndDropEnabled);
136 }
137
138 // We can't use RefCountedSupplement because that would try to make InternalSettings RefCounted
139 // and InternalSettings is already RefCounted via its base class, InternalSettingsGenerated.
140 // Instead, we manually make InternalSettings supplement Page.
141 class InternalSettingsWrapper : public Supplement<Page> {
142 public:
143     explicit InternalSettingsWrapper(Page* page)
144         : m_internalSettings(InternalSettings::create(page)) { }
145     virtual ~InternalSettingsWrapper() { m_internalSettings->hostDestroyed(); }
146 #if !ASSERT_DISABLED
147     virtual bool isRefCountedWrapper() const OVERRIDE { return true; }
148 #endif
149     InternalSettings* internalSettings() const { return m_internalSettings.get(); }
150
151 private:
152     RefPtr<InternalSettings> m_internalSettings;
153 };
154
155 const char* InternalSettings::supplementName()
156 {
157     return "InternalSettings";
158 }
159
160 InternalSettings* InternalSettings::from(Page* page)
161 {
162     if (!Supplement<Page>::from(page, supplementName()))
163         Supplement<Page>::provideTo(page, supplementName(), adoptPtr(new InternalSettingsWrapper(page)));
164     return static_cast<InternalSettingsWrapper*>(Supplement<Page>::from(page, supplementName()))->internalSettings();
165 }
166
167 InternalSettings::~InternalSettings()
168 {
169 }
170
171 InternalSettings::InternalSettings(Page* page)
172     : InternalSettingsGenerated(page)
173     , m_page(page)
174     , m_backup(page->settings())
175 {
176 }
177
178 void InternalSettings::resetToConsistentState()
179 {
180     page()->setPageScaleFactor(1, IntPoint(0, 0));
181     page()->setCanStartMedia(true);
182
183     m_backup.restoreTo(*settings());
184     m_backup = Backup(*settings());
185
186     InternalSettingsGenerated::resetToConsistentState();
187 }
188
189 Settings* InternalSettings::settings() const
190 {
191     if (!page())
192         return 0;
193     return &page()->settings();
194 }
195
196 void InternalSettings::setMockScrollbarsEnabled(bool enabled, ExceptionCode& ec)
197 {
198     InternalSettingsGuardForSettings();
199     settings()->setMockScrollbarsEnabled(enabled);
200 }
201
202 static bool urlIsWhitelistedForSetShadowDOMEnabled(const String& url)
203 {
204     // This check is just for preventing fuzzers from crashing because of unintended API calls.
205     // You can list your test if needed.
206     return notFound != url.find("fast/dom/shadow/content-shadow-unknown.html")
207         || notFound != url.find("fast/dom/shadow/insertion-points-with-shadow-disabled.html");
208 }
209
210 void InternalSettings::setShadowDOMEnabled(bool enabled, ExceptionCode& ec)
211 {
212     if (!urlIsWhitelistedForSetShadowDOMEnabled(page()->mainFrame().document()->url().string())) {
213         ec = INVALID_ACCESS_ERR;
214         return;
215     }
216
217 #if ENABLE(SHADOW_DOM)
218     RuntimeEnabledFeatures::sharedFeatures().setShadowDOMEnabled(enabled);
219 #else
220     // Even SHADOW_DOM is off, InternalSettings allows setShadowDOMEnabled(false) to
221     // have broader test coverage. But it cannot be setShadowDOMEnabled(true).
222     if (enabled)
223         ec = INVALID_ACCESS_ERR;
224 #endif
225 }
226
227 void InternalSettings::setAuthorShadowDOMForAnyElementEnabled(bool isEnabled)
228 {
229 #if ENABLE(SHADOW_DOM)
230     RuntimeEnabledFeatures::sharedFeatures().setAuthorShadowDOMForAnyElementEnabled(isEnabled);
231 #else
232     UNUSED_PARAM(isEnabled);
233 #endif
234 }
235
236 void InternalSettings::setStyleScopedEnabled(bool enabled)
237 {
238 #if ENABLE(STYLE_SCOPED)
239     RuntimeEnabledFeatures::sharedFeatures().setStyleScopedEnabled(enabled);
240 #else
241     UNUSED_PARAM(enabled);
242 #endif
243 }
244
245 void InternalSettings::setTouchEventEmulationEnabled(bool enabled, ExceptionCode& ec)
246 {
247 #if ENABLE(TOUCH_EVENTS)
248     InternalSettingsGuardForSettings();
249     settings()->setTouchEventEmulationEnabled(enabled);
250 #else
251     UNUSED_PARAM(enabled);
252     UNUSED_PARAM(ec);
253 #endif
254 }
255
256 typedef void (Settings::*SetFontFamilyFunction)(const AtomicString&, UScriptCode);
257 static void setFontFamily(Settings* settings, const String& family, const String& script, SetFontFamilyFunction setter)
258 {
259     UScriptCode code = scriptNameToCode(script);
260     if (code != USCRIPT_INVALID_CODE)
261         (settings->*setter)(family, code);
262 }
263
264 void InternalSettings::setStandardFontFamily(const String& family, const String& script, ExceptionCode& ec)
265 {
266     InternalSettingsGuardForSettings();
267     setFontFamily(settings(), family, script, &Settings::setStandardFontFamily);
268 }
269
270 void InternalSettings::setSerifFontFamily(const String& family, const String& script, ExceptionCode& ec)
271 {
272     InternalSettingsGuardForSettings();
273     setFontFamily(settings(), family, script, &Settings::setSerifFontFamily);
274 }
275
276 void InternalSettings::setSansSerifFontFamily(const String& family, const String& script, ExceptionCode& ec)
277 {
278     InternalSettingsGuardForSettings();
279     setFontFamily(settings(), family, script, &Settings::setSansSerifFontFamily);
280 }
281
282 void InternalSettings::setFixedFontFamily(const String& family, const String& script, ExceptionCode& ec)
283 {
284     InternalSettingsGuardForSettings();
285     setFontFamily(settings(), family, script, &Settings::setFixedFontFamily);
286 }
287
288 void InternalSettings::setCursiveFontFamily(const String& family, const String& script, ExceptionCode& ec)
289 {
290     InternalSettingsGuardForSettings();
291     setFontFamily(settings(), family, script, &Settings::setCursiveFontFamily);
292 }
293
294 void InternalSettings::setFantasyFontFamily(const String& family, const String& script, ExceptionCode& ec)
295 {
296     InternalSettingsGuardForSettings();
297     setFontFamily(settings(), family, script, &Settings::setFantasyFontFamily);
298 }
299
300 void InternalSettings::setPictographFontFamily(const String& family, const String& script, ExceptionCode& ec)
301 {
302     InternalSettingsGuardForSettings();
303     setFontFamily(settings(), family, script, &Settings::setPictographFontFamily);
304 }
305
306 void InternalSettings::setTextAutosizingEnabled(bool enabled, ExceptionCode& ec)
307 {
308 #if ENABLE(TEXT_AUTOSIZING)
309     InternalSettingsGuardForSettings();
310     settings()->setTextAutosizingEnabled(enabled);
311 #else
312     UNUSED_PARAM(enabled);
313     UNUSED_PARAM(ec);
314 #endif
315 }
316
317 void InternalSettings::setTextAutosizingWindowSizeOverride(int width, int height, ExceptionCode& ec)
318 {
319 #if ENABLE(TEXT_AUTOSIZING)
320     InternalSettingsGuardForSettings();
321     settings()->setTextAutosizingWindowSizeOverride(IntSize(width, height));
322 #else
323     UNUSED_PARAM(width);
324     UNUSED_PARAM(height);
325     UNUSED_PARAM(ec);
326 #endif
327 }
328
329 void InternalSettings::setMediaTypeOverride(const String& mediaType, ExceptionCode& ec)
330 {
331     InternalSettingsGuardForSettings();
332     settings()->setMediaTypeOverride(mediaType);
333 }
334
335 void InternalSettings::setTextAutosizingFontScaleFactor(float fontScaleFactor, ExceptionCode& ec)
336 {
337 #if ENABLE(TEXT_AUTOSIZING)
338     InternalSettingsGuardForSettings();
339     settings()->setTextAutosizingFontScaleFactor(fontScaleFactor);
340 #else
341     UNUSED_PARAM(fontScaleFactor);
342     UNUSED_PARAM(ec);
343 #endif
344 }
345
346 void InternalSettings::setCSSExclusionsEnabled(bool enabled, ExceptionCode& ec)
347 {
348     UNUSED_PARAM(ec);
349     RuntimeEnabledFeatures::sharedFeatures().setCSSExclusionsEnabled(enabled);
350 }
351
352 void InternalSettings::setCSSShapesEnabled(bool enabled, ExceptionCode& ec)
353 {
354     UNUSED_PARAM(ec);
355     RuntimeEnabledFeatures::sharedFeatures().setCSSShapesEnabled(enabled);
356 }
357
358 void InternalSettings::setCSSVariablesEnabled(bool enabled, ExceptionCode& ec)
359 {
360     InternalSettingsGuardForSettings();
361     settings()->setCSSVariablesEnabled(enabled);
362 }
363
364 bool InternalSettings::cssVariablesEnabled(ExceptionCode& ec)
365 {
366     InternalSettingsGuardForSettingsReturn(false);
367     return settings()->cssVariablesEnabled();
368 }
369
370 void InternalSettings::setCanStartMedia(bool enabled, ExceptionCode& ec)
371 {
372     InternalSettingsGuardForSettings();
373     m_page->setCanStartMedia(enabled);
374 }
375
376 void InternalSettings::setEditingBehavior(const String& editingBehavior, ExceptionCode& ec)
377 {
378     InternalSettingsGuardForSettings();
379     if (equalIgnoringCase(editingBehavior, "win"))
380         settings()->setEditingBehaviorType(EditingWindowsBehavior);
381     else if (equalIgnoringCase(editingBehavior, "mac"))
382         settings()->setEditingBehaviorType(EditingMacBehavior);
383     else if (equalIgnoringCase(editingBehavior, "unix"))
384         settings()->setEditingBehaviorType(EditingUnixBehavior);
385     else
386         ec = SYNTAX_ERR;
387 }
388
389 void InternalSettings::setShouldDisplayTrackKind(const String& kind, bool enabled, ExceptionCode& ec)
390 {
391     InternalSettingsGuardForSettings();
392
393 #if ENABLE(VIDEO_TRACK)
394     if (!page())
395         return;
396     CaptionUserPreferences* captionPreferences = page()->group().captionPreferences();
397
398     if (equalIgnoringCase(kind, "Subtitles"))
399         captionPreferences->setUserPrefersSubtitles(enabled);
400     else if (equalIgnoringCase(kind, "Captions"))
401         captionPreferences->setUserPrefersCaptions(enabled);
402     else if (equalIgnoringCase(kind, "TextDescriptions"))
403         captionPreferences->setUserPrefersTextDescriptions(enabled);
404     else
405         ec = SYNTAX_ERR;
406 #else
407     UNUSED_PARAM(kind);
408     UNUSED_PARAM(enabled);
409 #endif
410 }
411
412 bool InternalSettings::shouldDisplayTrackKind(const String& kind, ExceptionCode& ec)
413 {
414     InternalSettingsGuardForSettingsReturn(false);
415
416 #if ENABLE(VIDEO_TRACK)
417     if (!page())
418         return false;
419     CaptionUserPreferences* captionPreferences = page()->group().captionPreferences();
420
421     if (equalIgnoringCase(kind, "Subtitles"))
422         return captionPreferences->userPrefersSubtitles();
423     if (equalIgnoringCase(kind, "Captions"))
424         return captionPreferences->userPrefersCaptions();
425     if (equalIgnoringCase(kind, "TextDescriptions"))
426         return captionPreferences->userPrefersTextDescriptions();
427
428     ec = SYNTAX_ERR;
429     return false;
430 #else
431     UNUSED_PARAM(kind);
432     return false;
433 #endif
434 }
435
436 void InternalSettings::setStorageBlockingPolicy(const String& mode, ExceptionCode& ec)
437 {
438     InternalSettingsGuardForSettings();
439
440     if (mode == "AllowAll")
441         settings()->setStorageBlockingPolicy(SecurityOrigin::AllowAllStorage);
442     else if (mode == "BlockThirdParty")
443         settings()->setStorageBlockingPolicy(SecurityOrigin::BlockThirdPartyStorage);
444     else if (mode == "BlockAll")
445         settings()->setStorageBlockingPolicy(SecurityOrigin::BlockAllStorage);
446     else
447         ec = SYNTAX_ERR;
448 }
449
450 void InternalSettings::setLangAttributeAwareFormControlUIEnabled(bool enabled)
451 {
452     RuntimeEnabledFeatures::sharedFeatures().setLangAttributeAwareFormControlUIEnabled(enabled);
453 }
454
455 void InternalSettings::setImagesEnabled(bool enabled, ExceptionCode& ec)
456 {
457     InternalSettingsGuardForSettings();
458     settings()->setImagesEnabled(enabled);
459 }
460
461 void InternalSettings::setMinimumTimerInterval(double intervalInSeconds, ExceptionCode& ec)
462 {
463     InternalSettingsGuardForSettings();
464     settings()->setMinDOMTimerInterval(intervalInSeconds);
465 }
466
467 void InternalSettings::setDefaultVideoPosterURL(const String& url, ExceptionCode& ec)
468 {
469     InternalSettingsGuardForSettings();
470     settings()->setDefaultVideoPosterURL(url);
471 }
472
473 void InternalSettings::setTimeWithoutMouseMovementBeforeHidingControls(double time, ExceptionCode& ec)
474 {
475     InternalSettingsGuardForSettings();
476     settings()->setTimeWithoutMouseMovementBeforeHidingControls(time);
477 }
478
479 void InternalSettings::setUseLegacyBackgroundSizeShorthandBehavior(bool enabled, ExceptionCode& ec)
480 {
481     InternalSettingsGuardForSettings();
482     settings()->setUseLegacyBackgroundSizeShorthandBehavior(enabled);
483 }
484
485 void InternalSettings::setAutoscrollForDragAndDropEnabled(bool enabled, ExceptionCode& ec)
486 {
487     InternalSettingsGuardForSettings();
488     settings()->setAutoscrollForDragAndDropEnabled(enabled);
489 }
490
491 }