Home | History | Annotate | Download | only in testing
      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/core/v8/ExceptionState.h"
     31 #include "core/css/PointerProperties.h"
     32 #include "core/dom/ExceptionCode.h"
     33 #include "core/frame/Settings.h"
     34 #include "core/inspector/InspectorController.h"
     35 #include "core/page/Page.h"
     36 #include "platform/RuntimeEnabledFeatures.h"
     37 #include "platform/Supplementable.h"
     38 #include "platform/text/LocaleToScriptMapping.h"
     39 
     40 #define InternalSettingsGuardForSettingsReturn(returnValue) \
     41     if (!settings()) { \
     42         exceptionState.throwDOMException(InvalidAccessError, "The settings object cannot be obtained."); \
     43         return returnValue; \
     44     }
     45 
     46 #define InternalSettingsGuardForSettings()  \
     47     if (!settings()) { \
     48         exceptionState.throwDOMException(InvalidAccessError, "The settings object cannot be obtained."); \
     49         return; \
     50     }
     51 
     52 #define InternalSettingsGuardForPage() \
     53     if (!page()) { \
     54         exceptionState.throwDOMException(InvalidAccessError, "The page object cannot be obtained."); \
     55         return; \
     56     }
     57 
     58 namespace blink {
     59 
     60 InternalSettings::Backup::Backup(Settings* settings)
     61     : m_originalAuthorShadowDOMForAnyElementEnabled(RuntimeEnabledFeatures::authorShadowDOMForAnyElementEnabled())
     62     , m_originalCSP(RuntimeEnabledFeatures::experimentalContentSecurityPolicyFeaturesEnabled())
     63     , m_originalLaxMixedContentCheckingEnabled(RuntimeEnabledFeatures::laxMixedContentCheckingEnabled())
     64     , m_originalOverlayScrollbarsEnabled(RuntimeEnabledFeatures::overlayScrollbarsEnabled())
     65     , m_originalEditingBehavior(settings->editingBehaviorType())
     66     , m_originalTextAutosizingEnabled(settings->textAutosizingEnabled())
     67     , m_originalTextAutosizingWindowSizeOverride(settings->textAutosizingWindowSizeOverride())
     68     , m_originalAccessibilityFontScaleFactor(settings->accessibilityFontScaleFactor())
     69     , m_originalMediaTypeOverride(settings->mediaTypeOverride())
     70     , m_originalMockScrollbarsEnabled(settings->mockScrollbarsEnabled())
     71     , m_originalMockGestureTapHighlightsEnabled(settings->mockGestureTapHighlightsEnabled())
     72     , m_langAttributeAwareFormControlUIEnabled(RuntimeEnabledFeatures::langAttributeAwareFormControlUIEnabled())
     73     , m_imagesEnabled(settings->imagesEnabled())
     74     , m_defaultVideoPosterURL(settings->defaultVideoPosterURL())
     75     , m_originalLayerSquashingEnabled(settings->layerSquashingEnabled())
     76     , m_originalPseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled(RuntimeEnabledFeatures::pseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled())
     77 {
     78 }
     79 
     80 void InternalSettings::Backup::restoreTo(Settings* settings)
     81 {
     82     RuntimeEnabledFeatures::setAuthorShadowDOMForAnyElementEnabled(m_originalAuthorShadowDOMForAnyElementEnabled);
     83     RuntimeEnabledFeatures::setExperimentalContentSecurityPolicyFeaturesEnabled(m_originalCSP);
     84     RuntimeEnabledFeatures::setLaxMixedContentCheckingEnabled(m_originalLaxMixedContentCheckingEnabled);
     85     RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(m_originalOverlayScrollbarsEnabled);
     86     settings->setEditingBehaviorType(m_originalEditingBehavior);
     87     settings->setTextAutosizingEnabled(m_originalTextAutosizingEnabled);
     88     settings->setTextAutosizingWindowSizeOverride(m_originalTextAutosizingWindowSizeOverride);
     89     settings->setAccessibilityFontScaleFactor(m_originalAccessibilityFontScaleFactor);
     90     settings->setMediaTypeOverride(m_originalMediaTypeOverride);
     91     settings->setMockScrollbarsEnabled(m_originalMockScrollbarsEnabled);
     92     settings->setMockGestureTapHighlightsEnabled(m_originalMockGestureTapHighlightsEnabled);
     93     RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(m_langAttributeAwareFormControlUIEnabled);
     94     settings->setImagesEnabled(m_imagesEnabled);
     95     settings->setDefaultVideoPosterURL(m_defaultVideoPosterURL);
     96     settings->setLayerSquashingEnabled(m_originalLayerSquashingEnabled);
     97     settings->genericFontFamilySettings().reset();
     98     RuntimeEnabledFeatures::setPseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled(m_originalPseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled);
     99 }
    100 
    101 #if ENABLE(OILPAN)
    102 InternalSettings* InternalSettings::from(Page& page)
    103 {
    104     if (!HeapSupplement<Page>::from(page, supplementName()))
    105         HeapSupplement<Page>::provideTo(page, supplementName(), new InternalSettings(page));
    106     return static_cast<InternalSettings*>(HeapSupplement<Page>::from(page, supplementName()));
    107 }
    108 #else
    109 // We can't use RefCountedSupplement because that would try to make InternalSettings RefCounted
    110 // and InternalSettings is already RefCounted via its base class, InternalSettingsGenerated.
    111 // Instead, we manually make InternalSettings supplement Page.
    112 class InternalSettingsWrapper : public Supplement<Page> {
    113 public:
    114     explicit InternalSettingsWrapper(Page& page)
    115         : m_internalSettings(InternalSettings::create(page)) { }
    116     virtual ~InternalSettingsWrapper() { m_internalSettings->hostDestroyed(); }
    117 #if ENABLE(ASSERT)
    118     virtual bool isRefCountedWrapper() const OVERRIDE { return true; }
    119 #endif
    120     InternalSettings* internalSettings() const { return m_internalSettings.get(); }
    121 
    122 private:
    123     RefPtr<InternalSettings> m_internalSettings;
    124 };
    125 
    126 InternalSettings* InternalSettings::from(Page& page)
    127 {
    128     if (!Supplement<Page>::from(page, supplementName()))
    129         Supplement<Page>::provideTo(page, supplementName(), adoptPtr(new InternalSettingsWrapper(page)));
    130     return static_cast<InternalSettingsWrapper*>(Supplement<Page>::from(page, supplementName()))->internalSettings();
    131 }
    132 #endif
    133 
    134 const char* InternalSettings::supplementName()
    135 {
    136     return "InternalSettings";
    137 }
    138 
    139 InternalSettings::~InternalSettings()
    140 {
    141 }
    142 
    143 InternalSettings::InternalSettings(Page& page)
    144     : InternalSettingsGenerated(&page)
    145     , m_page(&page)
    146     , m_backup(&page.settings())
    147 {
    148 }
    149 
    150 void InternalSettings::resetToConsistentState()
    151 {
    152     page()->setPageScaleFactor(1, IntPoint(0, 0));
    153 
    154     m_backup.restoreTo(settings());
    155     m_backup = Backup(settings());
    156     m_backup.m_originalTextAutosizingEnabled = settings()->textAutosizingEnabled();
    157 
    158     InternalSettingsGenerated::resetToConsistentState();
    159 }
    160 
    161 Settings* InternalSettings::settings() const
    162 {
    163     if (!page())
    164         return 0;
    165     return &page()->settings();
    166 }
    167 
    168 void InternalSettings::setMockScrollbarsEnabled(bool enabled, ExceptionState& exceptionState)
    169 {
    170     InternalSettingsGuardForSettings();
    171     settings()->setMockScrollbarsEnabled(enabled);
    172 }
    173 
    174 void InternalSettings::setMockGestureTapHighlightsEnabled(bool enabled, ExceptionState& exceptionState)
    175 {
    176     InternalSettingsGuardForSettings();
    177     settings()->setMockGestureTapHighlightsEnabled(enabled);
    178 }
    179 
    180 void InternalSettings::setAuthorShadowDOMForAnyElementEnabled(bool isEnabled)
    181 {
    182     RuntimeEnabledFeatures::setAuthorShadowDOMForAnyElementEnabled(isEnabled);
    183 }
    184 
    185 void InternalSettings::setExperimentalContentSecurityPolicyFeaturesEnabled(bool enabled)
    186 {
    187     RuntimeEnabledFeatures::setExperimentalContentSecurityPolicyFeaturesEnabled(enabled);
    188 }
    189 
    190 void InternalSettings::setLaxMixedContentCheckingEnabled(bool enabled)
    191 {
    192     RuntimeEnabledFeatures::setLaxMixedContentCheckingEnabled(enabled);
    193 }
    194 
    195 void InternalSettings::setPseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled(bool enabled)
    196 {
    197     RuntimeEnabledFeatures::setPseudoClassesInMatchingCriteriaInAuthorShadowTreesEnabled(enabled);
    198 }
    199 
    200 void InternalSettings::setOverlayScrollbarsEnabled(bool enabled)
    201 {
    202     RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(enabled);
    203 }
    204 
    205 void InternalSettings::setViewportEnabled(bool enabled, ExceptionState& exceptionState)
    206 {
    207     InternalSettingsGuardForSettings();
    208     settings()->setViewportEnabled(enabled);
    209 }
    210 
    211 // FIXME: This is a temporary flag and should be removed once squashing is
    212 // ready (crbug.com/261605).
    213 void InternalSettings::setLayerSquashingEnabled(bool enabled, ExceptionState& exceptionState)
    214 {
    215     InternalSettingsGuardForSettings();
    216     settings()->setLayerSquashingEnabled(enabled);
    217 }
    218 
    219 void InternalSettings::setStandardFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
    220 {
    221     InternalSettingsGuardForSettings();
    222     UScriptCode code = scriptNameToCode(script);
    223     if (code == USCRIPT_INVALID_CODE)
    224         return;
    225     if (settings()->genericFontFamilySettings().updateStandard(family, code))
    226         settings()->notifyGenericFontFamilyChange();
    227 }
    228 
    229 void InternalSettings::setSerifFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
    230 {
    231     InternalSettingsGuardForSettings();
    232     UScriptCode code = scriptNameToCode(script);
    233     if (code == USCRIPT_INVALID_CODE)
    234         return;
    235     if (settings()->genericFontFamilySettings().updateSerif(family, code))
    236         settings()->notifyGenericFontFamilyChange();
    237 }
    238 
    239 void InternalSettings::setSansSerifFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
    240 {
    241     InternalSettingsGuardForSettings();
    242     UScriptCode code = scriptNameToCode(script);
    243     if (code == USCRIPT_INVALID_CODE)
    244         return;
    245     if (settings()->genericFontFamilySettings().updateSansSerif(family, code))
    246         settings()->notifyGenericFontFamilyChange();
    247 }
    248 
    249 void InternalSettings::setFixedFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
    250 {
    251     InternalSettingsGuardForSettings();
    252     UScriptCode code = scriptNameToCode(script);
    253     if (code == USCRIPT_INVALID_CODE)
    254         return;
    255     if (settings()->genericFontFamilySettings().updateFixed(family, code))
    256         settings()->notifyGenericFontFamilyChange();
    257 }
    258 
    259 void InternalSettings::setCursiveFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
    260 {
    261     InternalSettingsGuardForSettings();
    262     UScriptCode code = scriptNameToCode(script);
    263     if (code == USCRIPT_INVALID_CODE)
    264         return;
    265     if (settings()->genericFontFamilySettings().updateCursive(family, code))
    266         settings()->notifyGenericFontFamilyChange();
    267 }
    268 
    269 void InternalSettings::setFantasyFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
    270 {
    271     InternalSettingsGuardForSettings();
    272     UScriptCode code = scriptNameToCode(script);
    273     if (code == USCRIPT_INVALID_CODE)
    274         return;
    275     if (settings()->genericFontFamilySettings().updateFantasy(family, code))
    276         settings()->notifyGenericFontFamilyChange();
    277 }
    278 
    279 void InternalSettings::setPictographFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
    280 {
    281     InternalSettingsGuardForSettings();
    282     UScriptCode code = scriptNameToCode(script);
    283     if (code == USCRIPT_INVALID_CODE)
    284         return;
    285     if (settings()->genericFontFamilySettings().updatePictograph(family, code))
    286         settings()->notifyGenericFontFamilyChange();
    287 }
    288 
    289 void InternalSettings::setTextAutosizingEnabled(bool enabled, ExceptionState& exceptionState)
    290 {
    291     InternalSettingsGuardForSettings();
    292     settings()->setTextAutosizingEnabled(enabled);
    293     m_page->inspectorController().setTextAutosizingEnabled(enabled);
    294 }
    295 
    296 void InternalSettings::setTextAutosizingWindowSizeOverride(int width, int height, ExceptionState& exceptionState)
    297 {
    298     InternalSettingsGuardForSettings();
    299     settings()->setTextAutosizingWindowSizeOverride(IntSize(width, height));
    300 }
    301 
    302 void InternalSettings::setMediaTypeOverride(const String& mediaType, ExceptionState& exceptionState)
    303 {
    304     InternalSettingsGuardForSettings();
    305     settings()->setMediaTypeOverride(mediaType);
    306 }
    307 
    308 void InternalSettings::setAccessibilityFontScaleFactor(float fontScaleFactor, ExceptionState& exceptionState)
    309 {
    310     InternalSettingsGuardForSettings();
    311     settings()->setAccessibilityFontScaleFactor(fontScaleFactor);
    312 }
    313 
    314 void InternalSettings::setEditingBehavior(const String& editingBehavior, ExceptionState& exceptionState)
    315 {
    316     InternalSettingsGuardForSettings();
    317     if (equalIgnoringCase(editingBehavior, "win"))
    318         settings()->setEditingBehaviorType(EditingWindowsBehavior);
    319     else if (equalIgnoringCase(editingBehavior, "mac"))
    320         settings()->setEditingBehaviorType(EditingMacBehavior);
    321     else if (equalIgnoringCase(editingBehavior, "unix"))
    322         settings()->setEditingBehaviorType(EditingUnixBehavior);
    323     else if (equalIgnoringCase(editingBehavior, "android"))
    324         settings()->setEditingBehaviorType(EditingAndroidBehavior);
    325     else
    326         exceptionState.throwDOMException(SyntaxError, "The editing behavior type provided ('" + editingBehavior + "') is invalid.");
    327 }
    328 
    329 void InternalSettings::setLangAttributeAwareFormControlUIEnabled(bool enabled)
    330 {
    331     RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(enabled);
    332 }
    333 
    334 void InternalSettings::setImagesEnabled(bool enabled, ExceptionState& exceptionState)
    335 {
    336     InternalSettingsGuardForSettings();
    337     settings()->setImagesEnabled(enabled);
    338 }
    339 
    340 void InternalSettings::setDefaultVideoPosterURL(const String& url, ExceptionState& exceptionState)
    341 {
    342     InternalSettingsGuardForSettings();
    343     settings()->setDefaultVideoPosterURL(url);
    344 }
    345 
    346 void InternalSettings::trace(Visitor* visitor)
    347 {
    348     visitor->trace(m_page);
    349     InternalSettingsGenerated::trace(visitor);
    350 #if ENABLE(OILPAN)
    351     HeapSupplement<Page>::trace(visitor);
    352 #endif
    353 }
    354 
    355 void InternalSettings::setAvailablePointerTypes(const String& pointers, ExceptionState& exceptionState)
    356 {
    357     InternalSettingsGuardForSettings();
    358 
    359     // Allow setting multiple pointer types by passing comma seperated list
    360     // ("coarse,fine").
    361     Vector<String> tokens;
    362     pointers.split(",", false, tokens);
    363 
    364     int pointerTypes = 0;
    365     for (size_t i = 0; i < tokens.size(); ++i) {
    366         String token = tokens[i].stripWhiteSpace();
    367 
    368         if (token == "coarse")
    369             pointerTypes |= PointerTypeCoarse;
    370         else if (token == "fine")
    371             pointerTypes |= PointerTypeFine;
    372         else if (token == "none")
    373             pointerTypes |= PointerTypeNone;
    374         else
    375             exceptionState.throwDOMException(SyntaxError, "The pointer type token ('" + token + ")' is invalid.");
    376     }
    377 
    378     settings()->setAvailablePointerTypes(pointerTypes);
    379 }
    380 
    381 void InternalSettings::setPrimaryPointerType(const String& pointer, ExceptionState& exceptionState)
    382 {
    383     InternalSettingsGuardForSettings();
    384     String token = pointer.stripWhiteSpace();
    385 
    386     PointerType type = PointerTypeNone;
    387     if (token == "coarse")
    388         type = PointerTypeCoarse;
    389     else if (token == "fine")
    390         type = PointerTypeFine;
    391     else if (token == "none")
    392         type = PointerTypeNone;
    393     else
    394         exceptionState.throwDOMException(SyntaxError, "The pointer type token ('" + token + ")' is invalid.");
    395 
    396     settings()->setPrimaryPointerType(type);
    397 }
    398 
    399 void InternalSettings::setAvailableHoverTypes(const String& types, ExceptionState& exceptionState)
    400 {
    401     InternalSettingsGuardForSettings();
    402 
    403     // Allow setting multiple hover types by passing comma seperated list
    404     // ("on-demand,none").
    405     Vector<String> tokens;
    406     types.split(",", false, tokens);
    407 
    408     int hoverTypes = 0;
    409     for (size_t i = 0; i < tokens.size(); ++i) {
    410         String token = tokens[i].stripWhiteSpace();
    411 
    412         if (token == "none")
    413             hoverTypes |= HoverTypeNone;
    414         else if (token == "on-demand")
    415             hoverTypes |= HoverTypeOnDemand;
    416         else if (token == "hover")
    417             hoverTypes |= HoverTypeHover;
    418         else
    419             exceptionState.throwDOMException(SyntaxError, "The hover type token ('" + token + ")' is invalid.");
    420     }
    421 
    422     settings()->setAvailableHoverTypes(hoverTypes);
    423 }
    424 
    425 void InternalSettings::setPrimaryHoverType(const String& type, ExceptionState& exceptionState)
    426 {
    427     InternalSettingsGuardForSettings();
    428     String token = type.stripWhiteSpace();
    429 
    430     HoverType hoverType = HoverTypeNone;
    431     if (token == "none")
    432         hoverType = HoverTypeNone;
    433     else if (token == "on-demand")
    434         hoverType = HoverTypeOnDemand;
    435     else if (token == "hover")
    436         hoverType = HoverTypeHover;
    437     else
    438         exceptionState.throwDOMException(SyntaxError, "The hover type token ('" + token + ")' is invalid.");
    439 
    440     settings()->setPrimaryHoverType(hoverType);
    441 }
    442 
    443 }
    444