| /* |
| * Copyright (C) 2012 Google Inc. All rights reserved. |
| * Copyright (C) 2013 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "core/testing/InternalSettings.h" |
| |
| #include "bindings/core/v8/ExceptionState.h" |
| #include "core/dom/ExceptionCode.h" |
| #include "core/frame/Settings.h" |
| #include "core/page/Page.h" |
| #include "platform/RuntimeEnabledFeatures.h" |
| #include "platform/Supplementable.h" |
| #include "platform/text/LocaleToScriptMapping.h" |
| |
| #define InternalSettingsGuardForSettingsReturn(returnValue) \ |
| if (!settings()) { \ |
| exceptionState.throwDOMException(InvalidAccessError, "The settings object cannot be obtained."); \ |
| return returnValue; \ |
| } |
| |
| #define InternalSettingsGuardForSettings() \ |
| if (!settings()) { \ |
| exceptionState.throwDOMException(InvalidAccessError, "The settings object cannot be obtained."); \ |
| return; \ |
| } |
| |
| #define InternalSettingsGuardForPage() \ |
| if (!page()) { \ |
| exceptionState.throwDOMException(InvalidAccessError, "The page object cannot be obtained."); \ |
| return; \ |
| } |
| |
| namespace blink { |
| |
| InternalSettings::Backup::Backup(Settings* settings) |
| : m_originalCSP(RuntimeEnabledFeatures::experimentalContentSecurityPolicyFeaturesEnabled()) |
| , m_originalCSSStickyPositionEnabled(RuntimeEnabledFeatures::cssStickyPositionEnabled()) |
| , m_originalOverlayScrollbarsEnabled(RuntimeEnabledFeatures::overlayScrollbarsEnabled()) |
| , m_originalEditingBehavior(settings->editingBehaviorType()) |
| , m_originalTextAutosizingEnabled(settings->textAutosizingEnabled()) |
| , m_originalTextAutosizingWindowSizeOverride(settings->textAutosizingWindowSizeOverride()) |
| , m_originalAccessibilityFontScaleFactor(settings->accessibilityFontScaleFactor()) |
| , m_originalMediaTypeOverride(settings->mediaTypeOverride()) |
| , m_originalDisplayModeOverride(settings->displayModeOverride()) |
| , m_originalMockScrollbarsEnabled(settings->mockScrollbarsEnabled()) |
| , m_originalMockGestureTapHighlightsEnabled(settings->mockGestureTapHighlightsEnabled()) |
| , m_langAttributeAwareFormControlUIEnabled(RuntimeEnabledFeatures::langAttributeAwareFormControlUIEnabled()) |
| , m_imagesEnabled(settings->imagesEnabled()) |
| , m_defaultVideoPosterURL(settings->defaultVideoPosterURL()) |
| , m_originalLayerSquashingEnabled(settings->layerSquashingEnabled()) |
| , m_originalImageAnimationPolicy(settings->imageAnimationPolicy()) |
| , m_originalScrollTopLeftInteropEnabled(RuntimeEnabledFeatures::scrollTopLeftInteropEnabled()) |
| , m_originalCompositorWorkerEnabled(RuntimeEnabledFeatures::compositorWorkerEnabled()) |
| { |
| } |
| |
| void InternalSettings::Backup::restoreTo(Settings* settings) |
| { |
| RuntimeEnabledFeatures::setExperimentalContentSecurityPolicyFeaturesEnabled(m_originalCSP); |
| RuntimeEnabledFeatures::setCSSStickyPositionEnabled(m_originalCSSStickyPositionEnabled); |
| RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(m_originalOverlayScrollbarsEnabled); |
| settings->setEditingBehaviorType(m_originalEditingBehavior); |
| settings->setTextAutosizingEnabled(m_originalTextAutosizingEnabled); |
| settings->setTextAutosizingWindowSizeOverride(m_originalTextAutosizingWindowSizeOverride); |
| settings->setAccessibilityFontScaleFactor(m_originalAccessibilityFontScaleFactor); |
| settings->setMediaTypeOverride(m_originalMediaTypeOverride); |
| settings->setDisplayModeOverride(m_originalDisplayModeOverride); |
| settings->setMockScrollbarsEnabled(m_originalMockScrollbarsEnabled); |
| settings->setMockGestureTapHighlightsEnabled(m_originalMockGestureTapHighlightsEnabled); |
| RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(m_langAttributeAwareFormControlUIEnabled); |
| settings->setImagesEnabled(m_imagesEnabled); |
| settings->setDefaultVideoPosterURL(m_defaultVideoPosterURL); |
| settings->genericFontFamilySettings().reset(); |
| settings->setImageAnimationPolicy(m_originalImageAnimationPolicy); |
| RuntimeEnabledFeatures::setScrollTopLeftInteropEnabled(m_originalScrollTopLeftInteropEnabled); |
| RuntimeEnabledFeatures::setCompositorWorkerEnabled(m_originalCompositorWorkerEnabled); |
| } |
| |
| InternalSettings* InternalSettings::from(Page& page) |
| { |
| if (!Supplement<Page>::from(page, supplementName())) |
| Supplement<Page>::provideTo(page, supplementName(), new InternalSettings(page)); |
| return static_cast<InternalSettings*>(Supplement<Page>::from(page, supplementName())); |
| } |
| const char* InternalSettings::supplementName() |
| { |
| return "InternalSettings"; |
| } |
| |
| InternalSettings::~InternalSettings() |
| { |
| } |
| |
| InternalSettings::InternalSettings(Page& page) |
| : InternalSettingsGenerated(&page) |
| , m_page(&page) |
| , m_backup(&page.settings()) |
| { |
| } |
| |
| void InternalSettings::resetToConsistentState() |
| { |
| m_backup.restoreTo(settings()); |
| m_backup = Backup(settings()); |
| m_backup.m_originalTextAutosizingEnabled = settings()->textAutosizingEnabled(); |
| |
| InternalSettingsGenerated::resetToConsistentState(); |
| } |
| |
| Settings* InternalSettings::settings() const |
| { |
| if (!page()) |
| return 0; |
| return &page()->settings(); |
| } |
| |
| void InternalSettings::setMockScrollbarsEnabled(bool enabled, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setMockScrollbarsEnabled(enabled); |
| } |
| |
| void InternalSettings::setMockGestureTapHighlightsEnabled(bool enabled, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setMockGestureTapHighlightsEnabled(enabled); |
| } |
| |
| void InternalSettings::setCSSStickyPositionEnabled(bool enabled) |
| { |
| RuntimeEnabledFeatures::setCSSStickyPositionEnabled(enabled); |
| } |
| |
| void InternalSettings::setExperimentalContentSecurityPolicyFeaturesEnabled(bool enabled) |
| { |
| RuntimeEnabledFeatures::setExperimentalContentSecurityPolicyFeaturesEnabled(enabled); |
| } |
| |
| void InternalSettings::setOverlayScrollbarsEnabled(bool enabled) |
| { |
| RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(enabled); |
| } |
| |
| void InternalSettings::setViewportEnabled(bool enabled, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setViewportEnabled(enabled); |
| } |
| |
| void InternalSettings::setViewportMetaEnabled(bool enabled, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setViewportMetaEnabled(enabled); |
| } |
| |
| void InternalSettings::setViewportStyle(const String& style, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| if (equalIgnoringCase(style, "default")) |
| settings()->setViewportStyle(WebViewportStyle::Default); |
| else if (equalIgnoringCase(style, "mobile")) |
| settings()->setViewportStyle(WebViewportStyle::Mobile); |
| else if (equalIgnoringCase(style, "television")) |
| settings()->setViewportStyle(WebViewportStyle::Television); |
| else |
| exceptionState.throwDOMException(SyntaxError, "The viewport style type provided ('" + style + "') is invalid."); |
| } |
| |
| void InternalSettings::setStandardFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| UScriptCode code = scriptNameToCode(script); |
| if (code == USCRIPT_INVALID_CODE) |
| return; |
| if (settings()->genericFontFamilySettings().updateStandard(family, code)) |
| settings()->notifyGenericFontFamilyChange(); |
| } |
| |
| void InternalSettings::setSerifFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| UScriptCode code = scriptNameToCode(script); |
| if (code == USCRIPT_INVALID_CODE) |
| return; |
| if (settings()->genericFontFamilySettings().updateSerif(family, code)) |
| settings()->notifyGenericFontFamilyChange(); |
| } |
| |
| void InternalSettings::setSansSerifFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| UScriptCode code = scriptNameToCode(script); |
| if (code == USCRIPT_INVALID_CODE) |
| return; |
| if (settings()->genericFontFamilySettings().updateSansSerif(family, code)) |
| settings()->notifyGenericFontFamilyChange(); |
| } |
| |
| void InternalSettings::setFixedFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| UScriptCode code = scriptNameToCode(script); |
| if (code == USCRIPT_INVALID_CODE) |
| return; |
| if (settings()->genericFontFamilySettings().updateFixed(family, code)) |
| settings()->notifyGenericFontFamilyChange(); |
| } |
| |
| void InternalSettings::setCursiveFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| UScriptCode code = scriptNameToCode(script); |
| if (code == USCRIPT_INVALID_CODE) |
| return; |
| if (settings()->genericFontFamilySettings().updateCursive(family, code)) |
| settings()->notifyGenericFontFamilyChange(); |
| } |
| |
| void InternalSettings::setFantasyFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| UScriptCode code = scriptNameToCode(script); |
| if (code == USCRIPT_INVALID_CODE) |
| return; |
| if (settings()->genericFontFamilySettings().updateFantasy(family, code)) |
| settings()->notifyGenericFontFamilyChange(); |
| } |
| |
| void InternalSettings::setPictographFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| UScriptCode code = scriptNameToCode(script); |
| if (code == USCRIPT_INVALID_CODE) |
| return; |
| if (settings()->genericFontFamilySettings().updatePictograph(family, code)) |
| settings()->notifyGenericFontFamilyChange(); |
| } |
| |
| void InternalSettings::setTextAutosizingEnabled(bool enabled, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setTextAutosizingEnabled(enabled); |
| } |
| |
| void InternalSettings::setTextAutosizingWindowSizeOverride(int width, int height, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setTextAutosizingWindowSizeOverride(IntSize(width, height)); |
| } |
| |
| void InternalSettings::setTextTrackKindUserPreference(const String& preference, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| String token = preference.stripWhiteSpace(); |
| TextTrackKindUserPreference userPreference = TextTrackKindUserPreference::Default; |
| if (token == "default") |
| userPreference = TextTrackKindUserPreference::Default; |
| else if (token == "captions") |
| userPreference = TextTrackKindUserPreference::Captions; |
| else if (token == "subtitles") |
| userPreference = TextTrackKindUserPreference::Subtitles; |
| else |
| exceptionState.throwDOMException(SyntaxError, "The user preference for text track kind " + preference + ")' is invalid."); |
| |
| settings()->setTextTrackKindUserPreference(userPreference); |
| } |
| |
| void InternalSettings::setMediaTypeOverride(const String& mediaType, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setMediaTypeOverride(mediaType); |
| } |
| |
| void InternalSettings::setAccessibilityFontScaleFactor(float fontScaleFactor, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setAccessibilityFontScaleFactor(fontScaleFactor); |
| } |
| |
| void InternalSettings::setEditingBehavior(const String& editingBehavior, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| if (equalIgnoringCase(editingBehavior, "win")) |
| settings()->setEditingBehaviorType(EditingWindowsBehavior); |
| else if (equalIgnoringCase(editingBehavior, "mac")) |
| settings()->setEditingBehaviorType(EditingMacBehavior); |
| else if (equalIgnoringCase(editingBehavior, "unix")) |
| settings()->setEditingBehaviorType(EditingUnixBehavior); |
| else if (equalIgnoringCase(editingBehavior, "android")) |
| settings()->setEditingBehaviorType(EditingAndroidBehavior); |
| else |
| exceptionState.throwDOMException(SyntaxError, "The editing behavior type provided ('" + editingBehavior + "') is invalid."); |
| } |
| |
| void InternalSettings::setLangAttributeAwareFormControlUIEnabled(bool enabled) |
| { |
| RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(enabled); |
| } |
| |
| void InternalSettings::setImagesEnabled(bool enabled, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setImagesEnabled(enabled); |
| } |
| |
| void InternalSettings::setDefaultVideoPosterURL(const String& url, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setDefaultVideoPosterURL(url); |
| } |
| |
| DEFINE_TRACE(InternalSettings) |
| { |
| visitor->trace(m_page); |
| InternalSettingsGenerated::trace(visitor); |
| Supplement<Page>::trace(visitor); |
| } |
| |
| void InternalSettings::setAvailablePointerTypes(const String& pointers, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| |
| // Allow setting multiple pointer types by passing comma seperated list |
| // ("coarse,fine"). |
| Vector<String> tokens; |
| pointers.split(",", false, tokens); |
| |
| int pointerTypes = 0; |
| for (size_t i = 0; i < tokens.size(); ++i) { |
| String token = tokens[i].stripWhiteSpace(); |
| |
| if (token == "coarse") |
| pointerTypes |= PointerTypeCoarse; |
| else if (token == "fine") |
| pointerTypes |= PointerTypeFine; |
| else if (token == "none") |
| pointerTypes |= PointerTypeNone; |
| else |
| exceptionState.throwDOMException(SyntaxError, "The pointer type token ('" + token + ")' is invalid."); |
| } |
| |
| settings()->setAvailablePointerTypes(pointerTypes); |
| } |
| |
| void InternalSettings::setDisplayModeOverride(const String& displayMode, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| String token = displayMode.stripWhiteSpace(); |
| |
| WebDisplayMode mode = WebDisplayModeBrowser; |
| if (token == "browser") |
| mode = WebDisplayModeBrowser; |
| else if (token == "minimal-ui") |
| mode = WebDisplayModeMinimalUi; |
| else if (token == "standalone") |
| mode = WebDisplayModeStandalone; |
| else if (token == "fullscreen") |
| mode = WebDisplayModeFullscreen; |
| else |
| exceptionState.throwDOMException(SyntaxError, "The display-mode token ('" + token + ")' is invalid."); |
| |
| settings()->setDisplayModeOverride(mode); |
| } |
| |
| void InternalSettings::setPrimaryPointerType(const String& pointer, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| String token = pointer.stripWhiteSpace(); |
| |
| PointerType type = PointerTypeNone; |
| if (token == "coarse") |
| type = PointerTypeCoarse; |
| else if (token == "fine") |
| type = PointerTypeFine; |
| else if (token == "none") |
| type = PointerTypeNone; |
| else |
| exceptionState.throwDOMException(SyntaxError, "The pointer type token ('" + token + ")' is invalid."); |
| |
| settings()->setPrimaryPointerType(type); |
| } |
| |
| void InternalSettings::setAvailableHoverTypes(const String& types, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| |
| // Allow setting multiple hover types by passing comma seperated list |
| // ("on-demand,none"). |
| Vector<String> tokens; |
| types.split(",", false, tokens); |
| |
| int hoverTypes = 0; |
| for (size_t i = 0; i < tokens.size(); ++i) { |
| String token = tokens[i].stripWhiteSpace(); |
| |
| if (token == "none") |
| hoverTypes |= HoverTypeNone; |
| else if (token == "on-demand") |
| hoverTypes |= HoverTypeOnDemand; |
| else if (token == "hover") |
| hoverTypes |= HoverTypeHover; |
| else |
| exceptionState.throwDOMException(SyntaxError, "The hover type token ('" + token + ")' is invalid."); |
| } |
| |
| settings()->setAvailableHoverTypes(hoverTypes); |
| } |
| |
| void InternalSettings::setPrimaryHoverType(const String& type, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| String token = type.stripWhiteSpace(); |
| |
| HoverType hoverType = HoverTypeNone; |
| if (token == "none") |
| hoverType = HoverTypeNone; |
| else if (token == "on-demand") |
| hoverType = HoverTypeOnDemand; |
| else if (token == "hover") |
| hoverType = HoverTypeHover; |
| else |
| exceptionState.throwDOMException(SyntaxError, "The hover type token ('" + token + ")' is invalid."); |
| |
| settings()->setPrimaryHoverType(hoverType); |
| } |
| |
| void InternalSettings::setImageAnimationPolicy(const String& policy, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| if (equalIgnoringCase(policy, "allowed")) |
| settings()->setImageAnimationPolicy(ImageAnimationPolicyAllowed); |
| else if (equalIgnoringCase(policy, "once")) |
| settings()->setImageAnimationPolicy(ImageAnimationPolicyAnimateOnce); |
| else if (equalIgnoringCase(policy, "none")) |
| settings()->setImageAnimationPolicy(ImageAnimationPolicyNoAnimation); |
| else |
| exceptionState.throwDOMException(SyntaxError, "The image animation policy provided ('" + policy + "') is invalid."); |
| } |
| |
| void InternalSettings::setScrollTopLeftInteropEnabled(bool enabled) |
| { |
| RuntimeEnabledFeatures::setScrollTopLeftInteropEnabled(enabled); |
| } |
| |
| void InternalSettings::setDnsPrefetchLogging(bool enabled, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setLogDnsPrefetchAndPreconnect(enabled); |
| } |
| |
| void InternalSettings::setPreloadLogging(bool enabled, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| settings()->setLogPreload(enabled); |
| } |
| |
| void InternalSettings::setCompositorWorkerEnabled(bool enabled, ExceptionState& exceptionState) |
| { |
| InternalSettingsGuardForSettings(); |
| RuntimeEnabledFeatures::setCompositorWorkerEnabled(enabled); |
| } |
| |
| } // namespace blink |