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 "RuntimeEnabledFeatures.h"
31#include "bindings/v8/ExceptionState.h"
32#include "core/dom/ExceptionCode.h"
33#include "core/page/Page.h"
34#include "core/page/Settings.h"
35#include "core/platform/ColorChooser.h"
36#include "core/platform/Supplementable.h"
37#include "core/platform/text/LocaleToScriptMapping.h"
38
39#define InternalSettingsGuardForSettingsReturn(returnValue) \
40    if (!settings()) { \
41        es.throwDOMException(InvalidAccessError); \
42        return returnValue; \
43    }
44
45#define InternalSettingsGuardForSettings()  \
46    if (!settings()) { \
47        es.throwDOMException(InvalidAccessError); \
48        return; \
49    }
50
51#define InternalSettingsGuardForPage() \
52    if (!page()) { \
53        es.throwDOMException(InvalidAccessError); \
54        return; \
55    }
56
57namespace WebCore {
58
59InternalSettings::Backup::Backup(Settings* settings)
60    : m_originalCSSExclusionsEnabled(RuntimeEnabledFeatures::cssExclusionsEnabled())
61    , m_originalAuthorShadowDOMForAnyElementEnabled(RuntimeEnabledFeatures::authorShadowDOMForAnyElementEnabled())
62    , m_originalExperimentalWebSocketEnabled(settings->experimentalWebSocketEnabled())
63    , m_originalStyleScoped(RuntimeEnabledFeatures::styleScopedEnabled())
64    , m_originalEditingBehavior(settings->editingBehaviorType())
65    , m_originalTextAutosizingEnabled(settings->textAutosizingEnabled())
66    , m_originalTextAutosizingWindowSizeOverride(settings->textAutosizingWindowSizeOverride())
67    , m_originalTextAutosizingFontScaleFactor(settings->textAutosizingFontScaleFactor())
68    , m_originalMediaTypeOverride(settings->mediaTypeOverride())
69    , m_originalLazyLayoutEnabled(RuntimeEnabledFeatures::lazyLayoutEnabled())
70    , m_originalMockScrollbarsEnabled(settings->mockScrollbarsEnabled())
71    , m_langAttributeAwareFormControlUIEnabled(RuntimeEnabledFeatures::langAttributeAwareFormControlUIEnabled())
72    , m_imagesEnabled(settings->areImagesEnabled())
73    , m_shouldDisplaySubtitles(settings->shouldDisplaySubtitles())
74    , m_shouldDisplayCaptions(settings->shouldDisplayCaptions())
75    , m_shouldDisplayTextDescriptions(settings->shouldDisplayTextDescriptions())
76    , m_defaultVideoPosterURL(settings->defaultVideoPosterURL())
77{
78}
79
80void InternalSettings::Backup::restoreTo(Settings* settings)
81{
82    RuntimeEnabledFeatures::setCSSExclusionsEnabled(m_originalCSSExclusionsEnabled);
83    RuntimeEnabledFeatures::setAuthorShadowDOMForAnyElementEnabled(m_originalAuthorShadowDOMForAnyElementEnabled);
84    settings->setExperimentalWebSocketEnabled(m_originalExperimentalWebSocketEnabled);
85    RuntimeEnabledFeatures::setStyleScopedEnabled(m_originalStyleScoped);
86    settings->setEditingBehaviorType(m_originalEditingBehavior);
87    settings->setTextAutosizingEnabled(m_originalTextAutosizingEnabled);
88    settings->setTextAutosizingWindowSizeOverride(m_originalTextAutosizingWindowSizeOverride);
89    settings->setTextAutosizingFontScaleFactor(m_originalTextAutosizingFontScaleFactor);
90    settings->setMediaTypeOverride(m_originalMediaTypeOverride);
91    RuntimeEnabledFeatures::setLazyLayoutEnabled(m_originalLazyLayoutEnabled);
92    settings->setMockScrollbarsEnabled(m_originalMockScrollbarsEnabled);
93    RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(m_langAttributeAwareFormControlUIEnabled);
94    settings->setImagesEnabled(m_imagesEnabled);
95    settings->setShouldDisplaySubtitles(m_shouldDisplaySubtitles);
96    settings->setShouldDisplayCaptions(m_shouldDisplayCaptions);
97    settings->setShouldDisplayTextDescriptions(m_shouldDisplayTextDescriptions);
98    settings->setDefaultVideoPosterURL(m_defaultVideoPosterURL);
99}
100
101// We can't use RefCountedSupplement because that would try to make InternalSettings RefCounted
102// and InternalSettings is already RefCounted via its base class, InternalSettingsGenerated.
103// Instead, we manually make InternalSettings supplement Page.
104class InternalSettingsWrapper : public Supplement<Page> {
105public:
106    explicit InternalSettingsWrapper(Page* page)
107        : m_internalSettings(InternalSettings::create(page)) { }
108    virtual ~InternalSettingsWrapper() { m_internalSettings->hostDestroyed(); }
109#if !ASSERT_DISABLED
110    virtual bool isRefCountedWrapper() const OVERRIDE { return true; }
111#endif
112    InternalSettings* internalSettings() const { return m_internalSettings.get(); }
113
114private:
115    RefPtr<InternalSettings> m_internalSettings;
116};
117
118const char* InternalSettings::supplementName()
119{
120    return "InternalSettings";
121}
122
123InternalSettings* 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
130InternalSettings::~InternalSettings()
131{
132}
133
134InternalSettings::InternalSettings(Page* page)
135    : InternalSettingsGenerated(page)
136    , m_page(page)
137    , m_backup(page->settings())
138{
139}
140
141void InternalSettings::resetToConsistentState()
142{
143    page()->setPageScaleFactor(1, IntPoint(0, 0));
144
145    m_backup.restoreTo(settings());
146    m_backup = Backup(settings());
147
148    InternalSettingsGenerated::resetToConsistentState();
149}
150
151Settings* InternalSettings::settings() const
152{
153    if (!page())
154        return 0;
155    return page()->settings();
156}
157
158void InternalSettings::setMockScrollbarsEnabled(bool enabled, ExceptionState& es)
159{
160    InternalSettingsGuardForSettings();
161    settings()->setMockScrollbarsEnabled(enabled);
162}
163
164void InternalSettings::setAuthorShadowDOMForAnyElementEnabled(bool isEnabled)
165{
166    RuntimeEnabledFeatures::setAuthorShadowDOMForAnyElementEnabled(isEnabled);
167}
168
169void InternalSettings::setExperimentalWebSocketEnabled(bool isEnabled)
170{
171    settings()->setExperimentalWebSocketEnabled(isEnabled);
172}
173
174void InternalSettings::setStyleScopedEnabled(bool enabled)
175{
176    RuntimeEnabledFeatures::setStyleScopedEnabled(enabled);
177}
178
179void InternalSettings::setTouchEventEmulationEnabled(bool enabled, ExceptionState& es)
180{
181    InternalSettingsGuardForSettings();
182    settings()->setTouchEventEmulationEnabled(enabled);
183}
184
185// FIXME: This is a temporary flag and should be removed once accelerated
186// overflow scroll is ready (crbug.com/254111).
187void InternalSettings::setCompositorDrivenAcceleratedScrollingEnabled(bool enabled, ExceptionState& es)
188{
189    InternalSettingsGuardForSettings();
190    settings()->setCompositorDrivenAcceleratedScrollingEnabled(enabled);
191}
192
193typedef void (Settings::*SetFontFamilyFunction)(const AtomicString&, UScriptCode);
194static void setFontFamily(Settings* settings, const String& family, const String& script, SetFontFamilyFunction setter)
195{
196    UScriptCode code = scriptNameToCode(script);
197    if (code != USCRIPT_INVALID_CODE)
198        (settings->*setter)(family, code);
199}
200
201void InternalSettings::setStandardFontFamily(const String& family, const String& script, ExceptionState& es)
202{
203    InternalSettingsGuardForSettings();
204    setFontFamily(settings(), family, script, &Settings::setStandardFontFamily);
205}
206
207void InternalSettings::setSerifFontFamily(const String& family, const String& script, ExceptionState& es)
208{
209    InternalSettingsGuardForSettings();
210    setFontFamily(settings(), family, script, &Settings::setSerifFontFamily);
211}
212
213void InternalSettings::setSansSerifFontFamily(const String& family, const String& script, ExceptionState& es)
214{
215    InternalSettingsGuardForSettings();
216    setFontFamily(settings(), family, script, &Settings::setSansSerifFontFamily);
217}
218
219void InternalSettings::setFixedFontFamily(const String& family, const String& script, ExceptionState& es)
220{
221    InternalSettingsGuardForSettings();
222    setFontFamily(settings(), family, script, &Settings::setFixedFontFamily);
223}
224
225void InternalSettings::setCursiveFontFamily(const String& family, const String& script, ExceptionState& es)
226{
227    InternalSettingsGuardForSettings();
228    setFontFamily(settings(), family, script, &Settings::setCursiveFontFamily);
229}
230
231void InternalSettings::setFantasyFontFamily(const String& family, const String& script, ExceptionState& es)
232{
233    InternalSettingsGuardForSettings();
234    setFontFamily(settings(), family, script, &Settings::setFantasyFontFamily);
235}
236
237void InternalSettings::setPictographFontFamily(const String& family, const String& script, ExceptionState& es)
238{
239    InternalSettingsGuardForSettings();
240    setFontFamily(settings(), family, script, &Settings::setPictographFontFamily);
241}
242
243void InternalSettings::setTextAutosizingEnabled(bool enabled, ExceptionState& es)
244{
245    InternalSettingsGuardForSettings();
246    settings()->setTextAutosizingEnabled(enabled);
247}
248
249void InternalSettings::setTextAutosizingWindowSizeOverride(int width, int height, ExceptionState& es)
250{
251    InternalSettingsGuardForSettings();
252    settings()->setTextAutosizingWindowSizeOverride(IntSize(width, height));
253}
254
255void InternalSettings::setMediaTypeOverride(const String& mediaType, ExceptionState& es)
256{
257    InternalSettingsGuardForSettings();
258    settings()->setMediaTypeOverride(mediaType);
259}
260
261void InternalSettings::setTextAutosizingFontScaleFactor(float fontScaleFactor, ExceptionState& es)
262{
263    InternalSettingsGuardForSettings();
264    settings()->setTextAutosizingFontScaleFactor(fontScaleFactor);
265}
266
267void InternalSettings::setCSSExclusionsEnabled(bool enabled)
268{
269    RuntimeEnabledFeatures::setCSSExclusionsEnabled(enabled);
270}
271
272void InternalSettings::setEditingBehavior(const String& editingBehavior, ExceptionState& es)
273{
274    InternalSettingsGuardForSettings();
275    if (equalIgnoringCase(editingBehavior, "win"))
276        settings()->setEditingBehaviorType(EditingWindowsBehavior);
277    else if (equalIgnoringCase(editingBehavior, "mac"))
278        settings()->setEditingBehaviorType(EditingMacBehavior);
279    else if (equalIgnoringCase(editingBehavior, "unix"))
280        settings()->setEditingBehaviorType(EditingUnixBehavior);
281    else if (equalIgnoringCase(editingBehavior, "android"))
282        settings()->setEditingBehaviorType(EditingAndroidBehavior);
283    else
284        es.throwDOMException(SyntaxError);
285}
286
287void InternalSettings::setLazyLayoutEnabled(bool enabled)
288{
289    RuntimeEnabledFeatures::setLazyLayoutEnabled(enabled);
290}
291
292void InternalSettings::setLangAttributeAwareFormControlUIEnabled(bool enabled)
293{
294    RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(enabled);
295}
296
297void InternalSettings::setImagesEnabled(bool enabled, ExceptionState& es)
298{
299    InternalSettingsGuardForSettings();
300    settings()->setImagesEnabled(enabled);
301}
302
303void InternalSettings::setDefaultVideoPosterURL(const String& url, ExceptionState& es)
304{
305    InternalSettingsGuardForSettings();
306    settings()->setDefaultVideoPosterURL(url);
307}
308
309}
310