blob: d0846c2a5346e766d4f6fcc6be0e64a357f91a9f [file] [log] [blame]
/*
* 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 "third_party/blink/renderer/core/testing/internal_settings.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/supplementable.h"
#include "third_party/blink/renderer/platform/text/locale_to_script_mapping.h"
#define InternalSettingsGuardForSettingsReturn(returnValue) \
if (!settings()) { \
exceptionState.throwDOMException( \
InvalidAccessError, "The settings object cannot be obtained."); \
return returnValue; \
}
#define InternalSettingsGuardForSettings() \
if (!GetSettings()) { \
exception_state.ThrowDOMException( \
DOMExceptionCode::kInvalidAccessError, \
"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)
: original_csp_(RuntimeEnabledFeatures::
ExperimentalContentSecurityPolicyFeaturesEnabled()),
original_overlay_scrollbars_enabled_(
RuntimeEnabledFeatures::OverlayScrollbarsEnabled()),
original_editing_behavior_(settings->GetEditingBehaviorType()),
original_text_autosizing_enabled_(settings->TextAutosizingEnabled()),
original_text_autosizing_window_size_override_(
settings->TextAutosizingWindowSizeOverride()),
original_accessibility_font_scale_factor_(
settings->GetAccessibilityFontScaleFactor()),
original_media_type_override_(settings->GetMediaTypeOverride()),
original_display_mode_override_(settings->GetDisplayModeOverride()),
original_mock_scrollbars_enabled_(settings->MockScrollbarsEnabled()),
original_mock_gesture_tap_highlights_enabled_(
settings->GetMockGestureTapHighlightsEnabled()),
lang_attribute_aware_form_control_ui_enabled_(
RuntimeEnabledFeatures::LangAttributeAwareFormControlUIEnabled()),
images_enabled_(settings->GetImagesEnabled()),
default_video_poster_url_(settings->GetDefaultVideoPosterURL()),
original_image_animation_policy_(settings->GetImageAnimationPolicy()),
original_scroll_top_left_interop_enabled_(
RuntimeEnabledFeatures::ScrollTopLeftInteropEnabled()) {}
void InternalSettings::Backup::RestoreTo(Settings* settings) {
RuntimeEnabledFeatures::SetExperimentalContentSecurityPolicyFeaturesEnabled(
original_csp_);
RuntimeEnabledFeatures::SetOverlayScrollbarsEnabled(
original_overlay_scrollbars_enabled_);
settings->SetEditingBehaviorType(original_editing_behavior_);
settings->SetTextAutosizingEnabled(original_text_autosizing_enabled_);
settings->SetTextAutosizingWindowSizeOverride(
original_text_autosizing_window_size_override_);
settings->SetAccessibilityFontScaleFactor(
original_accessibility_font_scale_factor_);
settings->SetMediaTypeOverride(original_media_type_override_);
settings->SetDisplayModeOverride(original_display_mode_override_);
settings->SetMockScrollbarsEnabled(original_mock_scrollbars_enabled_);
settings->SetMockGestureTapHighlightsEnabled(
original_mock_gesture_tap_highlights_enabled_);
RuntimeEnabledFeatures::SetLangAttributeAwareFormControlUIEnabled(
lang_attribute_aware_form_control_ui_enabled_);
settings->SetImagesEnabled(images_enabled_);
settings->SetDefaultVideoPosterURL(default_video_poster_url_);
settings->GetGenericFontFamilySettings().Reset();
settings->SetImageAnimationPolicy(original_image_animation_policy_);
RuntimeEnabledFeatures::SetScrollTopLeftInteropEnabled(
original_scroll_top_left_interop_enabled_);
}
InternalSettings* InternalSettings::From(Page& page) {
InternalSettings* supplement = Supplement<Page>::From<InternalSettings>(page);
if (!supplement) {
supplement = MakeGarbageCollected<InternalSettings>(page);
ProvideTo(page, supplement);
}
return supplement;
}
const char InternalSettings::kSupplementName[] = "InternalSettings";
InternalSettings::~InternalSettings() = default;
InternalSettings::InternalSettings(Page& page)
: InternalSettingsGenerated(&page),
Supplement<Page>(page),
backup_(&page.GetSettings()) {}
void InternalSettings::ResetToConsistentState() {
backup_.RestoreTo(GetSettings());
backup_ = Backup(GetSettings());
backup_.original_text_autosizing_enabled_ =
GetSettings()->TextAutosizingEnabled();
InternalSettingsGenerated::resetToConsistentState();
}
Settings* InternalSettings::GetSettings() const {
if (!GetPage())
return nullptr;
return &GetPage()->GetSettings();
}
void InternalSettings::setMockScrollbarsEnabled(
bool enabled,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetMockScrollbarsEnabled(enabled);
}
void InternalSettings::setHideScrollbars(bool enabled,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetHideScrollbars(enabled);
}
void InternalSettings::setMockGestureTapHighlightsEnabled(
bool enabled,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetMockGestureTapHighlightsEnabled(enabled);
}
void InternalSettings::setExperimentalContentSecurityPolicyFeaturesEnabled(
bool enabled) {
RuntimeEnabledFeatures::SetExperimentalContentSecurityPolicyFeaturesEnabled(
enabled);
}
void InternalSettings::setViewportEnabled(bool enabled,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetViewportEnabled(enabled);
}
void InternalSettings::setViewportMetaEnabled(bool enabled,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetViewportMetaEnabled(enabled);
}
void InternalSettings::setViewportStyle(const String& style,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
if (DeprecatedEqualIgnoringCase(style, "default"))
GetSettings()->SetViewportStyle(WebViewportStyle::kDefault);
else if (DeprecatedEqualIgnoringCase(style, "mobile"))
GetSettings()->SetViewportStyle(WebViewportStyle::kMobile);
else if (DeprecatedEqualIgnoringCase(style, "television"))
GetSettings()->SetViewportStyle(WebViewportStyle::kTelevision);
else
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"The viewport style type provided ('" + style + "') is invalid.");
}
void InternalSettings::setStandardFontFamily(const AtomicString& family,
const String& script,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
UScriptCode code = ScriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return;
if (GetSettings()->GetGenericFontFamilySettings().UpdateStandard(family,
code))
GetSettings()->NotifyGenericFontFamilyChange();
}
void InternalSettings::setSerifFontFamily(const AtomicString& family,
const String& script,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
UScriptCode code = ScriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return;
if (GetSettings()->GetGenericFontFamilySettings().UpdateSerif(family, code))
GetSettings()->NotifyGenericFontFamilyChange();
}
void InternalSettings::setSansSerifFontFamily(const AtomicString& family,
const String& script,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
UScriptCode code = ScriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return;
if (GetSettings()->GetGenericFontFamilySettings().UpdateSansSerif(family,
code))
GetSettings()->NotifyGenericFontFamilyChange();
}
void InternalSettings::setFixedFontFamily(const AtomicString& family,
const String& script,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
UScriptCode code = ScriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return;
if (GetSettings()->GetGenericFontFamilySettings().UpdateFixed(family, code))
GetSettings()->NotifyGenericFontFamilyChange();
}
void InternalSettings::setCursiveFontFamily(const AtomicString& family,
const String& script,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
UScriptCode code = ScriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return;
if (GetSettings()->GetGenericFontFamilySettings().UpdateCursive(family, code))
GetSettings()->NotifyGenericFontFamilyChange();
}
void InternalSettings::setFantasyFontFamily(const AtomicString& family,
const String& script,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
UScriptCode code = ScriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return;
if (GetSettings()->GetGenericFontFamilySettings().UpdateFantasy(family, code))
GetSettings()->NotifyGenericFontFamilyChange();
}
void InternalSettings::setPictographFontFamily(
const AtomicString& family,
const String& script,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
UScriptCode code = ScriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return;
if (GetSettings()->GetGenericFontFamilySettings().UpdatePictograph(family,
code))
GetSettings()->NotifyGenericFontFamilyChange();
}
void InternalSettings::setTextAutosizingEnabled(
bool enabled,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetTextAutosizingEnabled(enabled);
}
void InternalSettings::setTextAutosizingWindowSizeOverride(
int width,
int height,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetTextAutosizingWindowSizeOverride(IntSize(width, height));
}
void InternalSettings::setTextTrackKindUserPreference(
const String& preference,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
String token = preference.StripWhiteSpace();
TextTrackKindUserPreference user_preference =
TextTrackKindUserPreference::kDefault;
if (token == "default") {
user_preference = TextTrackKindUserPreference::kDefault;
} else if (token == "captions") {
user_preference = TextTrackKindUserPreference::kCaptions;
} else if (token == "subtitles") {
user_preference = TextTrackKindUserPreference::kSubtitles;
} else {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"The user preference for text track kind " + preference +
")' is invalid.");
return;
}
GetSettings()->SetTextTrackKindUserPreference(user_preference);
}
void InternalSettings::setMediaTypeOverride(const String& media_type,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetMediaTypeOverride(media_type);
}
void InternalSettings::setAccessibilityFontScaleFactor(
float font_scale_factor,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetAccessibilityFontScaleFactor(font_scale_factor);
}
void InternalSettings::setEditingBehavior(const String& editing_behavior,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
if (DeprecatedEqualIgnoringCase(editing_behavior, "win"))
GetSettings()->SetEditingBehaviorType(kEditingWindowsBehavior);
else if (DeprecatedEqualIgnoringCase(editing_behavior, "mac"))
GetSettings()->SetEditingBehaviorType(kEditingMacBehavior);
else if (DeprecatedEqualIgnoringCase(editing_behavior, "unix"))
GetSettings()->SetEditingBehaviorType(kEditingUnixBehavior);
else if (DeprecatedEqualIgnoringCase(editing_behavior, "android"))
GetSettings()->SetEditingBehaviorType(kEditingAndroidBehavior);
else
exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"The editing behavior type provided ('" +
editing_behavior + "') is invalid.");
}
void InternalSettings::setLangAttributeAwareFormControlUIEnabled(bool enabled) {
RuntimeEnabledFeatures::SetLangAttributeAwareFormControlUIEnabled(enabled);
}
void InternalSettings::setImagesEnabled(bool enabled,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetImagesEnabled(enabled);
}
void InternalSettings::setDefaultVideoPosterURL(
const String& url,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetDefaultVideoPosterURL(url);
}
void InternalSettings::Trace(blink::Visitor* visitor) {
InternalSettingsGenerated::Trace(visitor);
Supplement<Page>::Trace(visitor);
}
void InternalSettings::setAvailablePointerTypes(
const String& pointers,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
// Allow setting multiple pointer types by passing comma seperated list
// ("coarse,fine").
Vector<String> tokens;
pointers.Split(",", false, tokens);
int pointer_types = 0;
for (const String& split_token : tokens) {
String token = split_token.StripWhiteSpace();
if (token == "coarse") {
pointer_types |= kPointerTypeCoarse;
} else if (token == "fine") {
pointer_types |= kPointerTypeFine;
} else if (token == "none") {
pointer_types |= kPointerTypeNone;
} else {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"The pointer type token ('" + token + ")' is invalid.");
return;
}
}
GetSettings()->SetAvailablePointerTypes(pointer_types);
}
void InternalSettings::setDisplayModeOverride(const String& display_mode,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
String token = display_mode.StripWhiteSpace();
WebDisplayMode mode = kWebDisplayModeBrowser;
if (token == "browser") {
mode = kWebDisplayModeBrowser;
} else if (token == "minimal-ui") {
mode = kWebDisplayModeMinimalUi;
} else if (token == "standalone") {
mode = kWebDisplayModeStandalone;
} else if (token == "fullscreen") {
mode = kWebDisplayModeFullscreen;
} else {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"The display-mode token ('" + token + ")' is invalid.");
return;
}
GetSettings()->SetDisplayModeOverride(mode);
}
void InternalSettings::setPrimaryPointerType(const String& pointer,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
String token = pointer.StripWhiteSpace();
PointerType type = kPointerTypeNone;
if (token == "coarse") {
type = kPointerTypeCoarse;
} else if (token == "fine") {
type = kPointerTypeFine;
} else if (token == "none") {
type = kPointerTypeNone;
} else {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"The pointer type token ('" + token + ")' is invalid.");
return;
}
GetSettings()->SetPrimaryPointerType(type);
}
void InternalSettings::setAvailableHoverTypes(const String& types,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
// Allow setting multiple hover types by passing comma seperated list
// ("on-demand,none").
Vector<String> tokens;
types.Split(",", false, tokens);
int hover_types = 0;
for (const String& split_token : tokens) {
String token = split_token.StripWhiteSpace();
if (token == "none") {
hover_types |= kHoverTypeNone;
} else if (token == "hover") {
hover_types |= kHoverTypeHover;
} else {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"The hover type token ('" + token + ")' is invalid.");
return;
}
}
GetSettings()->SetAvailableHoverTypes(hover_types);
}
void InternalSettings::setPrimaryHoverType(const String& type,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
String token = type.StripWhiteSpace();
HoverType hover_type = kHoverTypeNone;
if (token == "none") {
hover_type = kHoverTypeNone;
} else if (token == "hover") {
hover_type = kHoverTypeHover;
} else {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"The hover type token ('" + token + ")' is invalid.");
return;
}
GetSettings()->SetPrimaryHoverType(hover_type);
}
void InternalSettings::setImageAnimationPolicy(
const String& policy,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
if (DeprecatedEqualIgnoringCase(policy, "allowed")) {
GetSettings()->SetImageAnimationPolicy(kImageAnimationPolicyAllowed);
} else if (DeprecatedEqualIgnoringCase(policy, "once")) {
GetSettings()->SetImageAnimationPolicy(kImageAnimationPolicyAnimateOnce);
} else if (DeprecatedEqualIgnoringCase(policy, "none")) {
GetSettings()->SetImageAnimationPolicy(kImageAnimationPolicyNoAnimation);
} else {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"The image animation policy provided ('" + policy + "') is invalid.");
return;
}
}
void InternalSettings::setScrollTopLeftInteropEnabled(bool enabled) {
RuntimeEnabledFeatures::SetScrollTopLeftInteropEnabled(enabled);
}
void InternalSettings::SetDnsPrefetchLogging(bool enabled,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetLogDnsPrefetchAndPreconnect(enabled);
}
void InternalSettings::SetPreloadLogging(bool enabled,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetLogPreload(enabled);
}
void InternalSettings::setPresentationReceiver(
bool enabled,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
GetSettings()->SetPresentationReceiver(enabled);
}
void InternalSettings::setAutoplayPolicy(const String& policy_str,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
AutoplayPolicy::Type policy = AutoplayPolicy::Type::kNoUserGestureRequired;
if (policy_str == "no-user-gesture-required") {
policy = AutoplayPolicy::Type::kNoUserGestureRequired;
} else if (policy_str == "user-gesture-required") {
policy = AutoplayPolicy::Type::kUserGestureRequired;
} else if (policy_str == "document-user-activation-required") {
policy = AutoplayPolicy::Type::kDocumentUserActivationRequired;
} else {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
"The autoplay policy ('" + policy_str + ")' is invalid.");
}
GetSettings()->SetAutoplayPolicy(policy);
}
} // namespace blink