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