blob: 4ba67253f875cd49e3b08121bdd71a839965362e [file] [log] [blame]
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
* Copyright (C) 2013-2020 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 "config.h"
#include "InternalSettings.h"
#include "CaptionUserPreferences.h"
#include "DeprecatedGlobalSettings.h"
#include "Document.h"
#include "FontCache.h"
#include "Frame.h"
#include "FrameView.h"
#include "LocaleToScriptMapping.h"
#include "Page.h"
#include "PageGroup.h"
#include "PlatformMediaSessionManager.h"
#include "RenderTheme.h"
#include "RuntimeEnabledFeatures.h"
#include "Supplementable.h"
#include <wtf/Language.h>
#if ENABLE(WEB_AUDIO)
#include "AudioContext.h"
#endif
namespace WebCore {
InternalSettings::Backup::Backup(Settings& settings)
: m_minimumDOMTimerInterval(settings.minimumDOMTimerInterval())
, m_originalTimeWithoutMouseMovementBeforeHidingControls(settings.timeWithoutMouseMovementBeforeHidingControls())
, m_originalEditingBehavior(settings.editingBehaviorType())
, m_storageBlockingPolicy(settings.storageBlockingPolicy())
, m_userInterfaceDirectionPolicy(settings.userInterfaceDirectionPolicy())
, m_systemLayoutDirection(settings.systemLayoutDirection())
, m_pdfImageCachingPolicy(settings.pdfImageCachingPolicy())
, m_forcedColorsAreInvertedAccessibilityValue(settings.forcedColorsAreInvertedAccessibilityValue())
, m_forcedDisplayIsMonochromeAccessibilityValue(settings.forcedDisplayIsMonochromeAccessibilityValue())
, m_forcedPrefersContrastAccessibilityValue(settings.forcedPrefersContrastAccessibilityValue())
, m_forcedPrefersReducedMotionAccessibilityValue(settings.forcedPrefersReducedMotionAccessibilityValue())
, m_fontLoadTimingOverride(settings.fontLoadTimingOverride())
, m_frameFlattening(settings.frameFlattening())
, m_fetchAPIKeepAliveAPIEnabled(RuntimeEnabledFeatures::sharedFeatures().fetchAPIKeepAliveEnabled())
, m_customPasteboardDataEnabled(RuntimeEnabledFeatures::sharedFeatures().customPasteboardDataEnabled())
, m_originalMockScrollbarsEnabled(DeprecatedGlobalSettings::mockScrollbarsEnabled())
#if USE(AUDIO_SESSION)
, m_shouldManageAudioSessionCategory(DeprecatedGlobalSettings::shouldManageAudioSessionCategory())
#endif
#if ENABLE(VIDEO) || ENABLE(WEB_AUDIO)
, m_shouldDeactivateAudioSession(PlatformMediaSessionManager::shouldDeactivateAudioSession())
#endif
, m_shouldMockBoldSystemFontForAccessibility(RenderTheme::singleton().shouldMockBoldSystemFontForAccessibility())
{
}
void InternalSettings::Backup::restoreTo(Settings& settings)
{
for (const auto& standardFont : m_standardFontFamilies)
settings.setStandardFontFamily(standardFont.value, static_cast<UScriptCode>(standardFont.key));
m_standardFontFamilies.clear();
for (const auto& fixedFont : m_fixedFontFamilies)
settings.setFixedFontFamily(fixedFont.value, static_cast<UScriptCode>(fixedFont.key));
m_fixedFontFamilies.clear();
for (const auto& serifFont : m_serifFontFamilies)
settings.setSerifFontFamily(serifFont.value, static_cast<UScriptCode>(serifFont.key));
m_serifFontFamilies.clear();
for (const auto& sansSerifFont : m_sansSerifFontFamilies)
settings.setSansSerifFontFamily(sansSerifFont.value, static_cast<UScriptCode>(sansSerifFont.key));
m_sansSerifFontFamilies.clear();
for (const auto& cursiveFont : m_cursiveFontFamilies)
settings.setCursiveFontFamily(cursiveFont.value, static_cast<UScriptCode>(cursiveFont.key));
m_cursiveFontFamilies.clear();
for (const auto& fantasyFont : m_fantasyFontFamilies)
settings.setFantasyFontFamily(fantasyFont.value, static_cast<UScriptCode>(fantasyFont.key));
m_fantasyFontFamilies.clear();
for (const auto& pictographFont : m_pictographFontFamilies)
settings.setPictographFontFamily(pictographFont.value, static_cast<UScriptCode>(pictographFont.key));
m_pictographFontFamilies.clear();
settings.setMinimumDOMTimerInterval(m_minimumDOMTimerInterval);
settings.setTimeWithoutMouseMovementBeforeHidingControls(m_originalTimeWithoutMouseMovementBeforeHidingControls);
settings.setEditingBehaviorType(m_originalEditingBehavior);
settings.setStorageBlockingPolicy(m_storageBlockingPolicy);
settings.setUserInterfaceDirectionPolicy(m_userInterfaceDirectionPolicy);
settings.setSystemLayoutDirection(m_systemLayoutDirection);
settings.setPdfImageCachingPolicy(m_pdfImageCachingPolicy);
settings.setForcedColorsAreInvertedAccessibilityValue(m_forcedColorsAreInvertedAccessibilityValue);
settings.setForcedDisplayIsMonochromeAccessibilityValue(m_forcedDisplayIsMonochromeAccessibilityValue);
settings.setForcedPrefersContrastAccessibilityValue(m_forcedPrefersContrastAccessibilityValue);
settings.setForcedPrefersReducedMotionAccessibilityValue(m_forcedPrefersReducedMotionAccessibilityValue);
settings.setFontLoadTimingOverride(m_fontLoadTimingOverride);
settings.setFrameFlattening(m_frameFlattening);
RuntimeEnabledFeatures::sharedFeatures().setFetchAPIKeepAliveEnabled(m_fetchAPIKeepAliveAPIEnabled);
RuntimeEnabledFeatures::sharedFeatures().setCustomPasteboardDataEnabled(m_customPasteboardDataEnabled);
#if USE(AUDIO_SESSION)
DeprecatedGlobalSettings::setShouldManageAudioSessionCategory(m_shouldManageAudioSessionCategory);
#endif
#if ENABLE(VIDEO) || ENABLE(WEB_AUDIO)
PlatformMediaSessionManager::setShouldDeactivateAudioSession(m_shouldDeactivateAudioSession);
#endif
RenderTheme::singleton().setShouldMockBoldSystemFontForAccessibility(m_shouldMockBoldSystemFontForAccessibility);
FontCache::singleton().setShouldMockBoldSystemFontForAccessibility(m_shouldMockBoldSystemFontForAccessibility);
#if ENABLE(WEB_AUDIO)
AudioContext::setDefaultSampleRateForTesting(std::nullopt);
#endif
}
class InternalSettingsWrapper : public Supplement<Page> {
WTF_MAKE_FAST_ALLOCATED;
public:
explicit InternalSettingsWrapper(Page* page)
: m_internalSettings(InternalSettings::create(page)) { }
virtual ~InternalSettingsWrapper() { m_internalSettings->hostDestroyed(); }
#if ASSERT_ENABLED
bool isRefCountedWrapper() const override { return true; }
#endif
InternalSettings* internalSettings() const { return m_internalSettings.get(); }
private:
RefPtr<InternalSettings> m_internalSettings;
};
const char* InternalSettings::supplementName()
{
return "InternalSettings";
}
InternalSettings* InternalSettings::from(Page* page)
{
if (!Supplement<Page>::from(page, supplementName()))
Supplement<Page>::provideTo(page, supplementName(), makeUnique<InternalSettingsWrapper>(page));
return static_cast<InternalSettingsWrapper*>(Supplement<Page>::from(page, supplementName()))->internalSettings();
}
void InternalSettings::hostDestroyed()
{
m_page = nullptr;
}
InternalSettings::InternalSettings(Page* page)
: InternalSettingsGenerated(page)
, m_page(page)
, m_backup(page->settings())
{
}
Ref<InternalSettings> InternalSettings::create(Page* page)
{
return adoptRef(*new InternalSettings(page));
}
void InternalSettings::resetToConsistentState()
{
m_page->setPageScaleFactor(1, { 0, 0 });
m_page->mainFrame().setPageAndTextZoomFactors(1, 1);
m_page->setCanStartMedia(true);
m_page->effectiveAppearanceDidChange(false, false);
m_backup.restoreTo(settings());
m_backup = Backup { settings() };
InternalSettingsGenerated::resetToConsistentState();
}
Settings& InternalSettings::settings() const
{
ASSERT(m_page);
return m_page->settings();
}
ExceptionOr<void> InternalSettings::setStandardFontFamily(const String& family, const String& script)
{
if (!m_page)
return Exception { InvalidAccessError };
UScriptCode code = scriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return { };
m_backup.m_standardFontFamilies.add(code, settings().standardFontFamily(code));
settings().setStandardFontFamily(family, code);
return { };
}
ExceptionOr<void> InternalSettings::setSerifFontFamily(const String& family, const String& script)
{
if (!m_page)
return Exception { InvalidAccessError };
UScriptCode code = scriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return { };
m_backup.m_serifFontFamilies.add(code, settings().serifFontFamily(code));
settings().setSerifFontFamily(family, code);
return { };
}
ExceptionOr<void> InternalSettings::setSansSerifFontFamily(const String& family, const String& script)
{
if (!m_page)
return Exception { InvalidAccessError };
UScriptCode code = scriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return { };
m_backup.m_sansSerifFontFamilies.add(code, settings().sansSerifFontFamily(code));
settings().setSansSerifFontFamily(family, code);
return { };
}
ExceptionOr<void> InternalSettings::setFixedFontFamily(const String& family, const String& script)
{
if (!m_page)
return Exception { InvalidAccessError };
UScriptCode code = scriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return { };
m_backup.m_fixedFontFamilies.add(code, settings().fixedFontFamily(code));
settings().setFixedFontFamily(family, code);
return { };
}
ExceptionOr<void> InternalSettings::setCursiveFontFamily(const String& family, const String& script)
{
if (!m_page)
return Exception { InvalidAccessError };
UScriptCode code = scriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return { };
m_backup.m_cursiveFontFamilies.add(code, settings().cursiveFontFamily(code));
settings().setCursiveFontFamily(family, code);
return { };
}
ExceptionOr<void> InternalSettings::setFantasyFontFamily(const String& family, const String& script)
{
if (!m_page)
return Exception { InvalidAccessError };
UScriptCode code = scriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return { };
m_backup.m_fantasyFontFamilies.add(code, settings().fantasyFontFamily(code));
settings().setFantasyFontFamily(family, code);
return { };
}
ExceptionOr<void> InternalSettings::setPictographFontFamily(const String& family, const String& script)
{
if (!m_page)
return Exception { InvalidAccessError };
UScriptCode code = scriptNameToCode(script);
if (code == USCRIPT_INVALID_CODE)
return { };
m_backup.m_pictographFontFamilies.add(code, settings().pictographFontFamily(code));
settings().setPictographFontFamily(family, code);
return { };
}
ExceptionOr<void> InternalSettings::setTextAutosizingWindowSizeOverride(int width, int height)
{
if (!m_page)
return Exception { InvalidAccessError };
#if ENABLE(TEXT_AUTOSIZING)
settings().setTextAutosizingWindowSizeOverrideWidth(width);
settings().setTextAutosizingWindowSizeOverrideHeight(height);
#else
UNUSED_PARAM(width);
UNUSED_PARAM(height);
#endif
return { };
}
ExceptionOr<void> InternalSettings::setEditingBehavior(EditingBehaviorType editingBehaviorType)
{
if (!m_page)
return Exception { InvalidAccessError };
settings().setEditingBehaviorType(editingBehaviorType);
return { };
}
ExceptionOr<void> InternalSettings::setStorageBlockingPolicy(StorageBlockingPolicy policy)
{
if (!m_page)
return Exception { InvalidAccessError };
settings().setStorageBlockingPolicy(policy);
return { };
}
ExceptionOr<void> InternalSettings::setPDFImageCachingPolicy(PDFImageCachingPolicy policy)
{
if (!m_page)
return Exception { InvalidAccessError };
settings().setPdfImageCachingPolicy(policy);
return { };
}
ExceptionOr<void> InternalSettings::setMinimumTimerInterval(double intervalInSeconds)
{
if (!m_page)
return Exception { InvalidAccessError };
settings().setMinimumDOMTimerInterval(Seconds { intervalInSeconds });
return { };
}
ExceptionOr<void> InternalSettings::setTimeWithoutMouseMovementBeforeHidingControls(double time)
{
if (!m_page)
return Exception { InvalidAccessError };
settings().setTimeWithoutMouseMovementBeforeHidingControls(Seconds { time });
return { };
}
ExceptionOr<void> InternalSettings::setFontLoadTimingOverride(FontLoadTimingOverride fontLoadTimingOverride)
{
if (!m_page)
return Exception { InvalidAccessError };
settings().setFontLoadTimingOverride(fontLoadTimingOverride);
return { };
}
ExceptionOr<void> InternalSettings::setUserInterfaceDirectionPolicy(UserInterfaceDirectionPolicy policy)
{
if (!m_page)
return Exception { InvalidAccessError };
settings().setUserInterfaceDirectionPolicy(policy);
return { };
}
ExceptionOr<void> InternalSettings::setSystemLayoutDirection(SystemLayoutDirection direction)
{
if (!m_page)
return Exception { InvalidAccessError };
settings().setSystemLayoutDirection(direction);
return { };
}
ExceptionOr<void> InternalSettings::setFrameFlattening(FrameFlatteningValue frameFlattening)
{
if (!m_page)
return Exception { InvalidAccessError };
settings().setFrameFlattening(frameFlattening);
return { };
}
InternalSettings::ForcedAccessibilityValue InternalSettings::forcedColorsAreInvertedAccessibilityValue() const
{
return settings().forcedColorsAreInvertedAccessibilityValue();
}
void InternalSettings::setForcedColorsAreInvertedAccessibilityValue(InternalSettings::ForcedAccessibilityValue value)
{
settings().setForcedColorsAreInvertedAccessibilityValue(value);
}
InternalSettings::ForcedAccessibilityValue InternalSettings::forcedDisplayIsMonochromeAccessibilityValue() const
{
return settings().forcedDisplayIsMonochromeAccessibilityValue();
}
void InternalSettings::setForcedDisplayIsMonochromeAccessibilityValue(InternalSettings::ForcedAccessibilityValue value)
{
settings().setForcedDisplayIsMonochromeAccessibilityValue(value);
}
InternalSettings::ForcedAccessibilityValue InternalSettings::forcedPrefersContrastAccessibilityValue() const
{
return settings().forcedPrefersContrastAccessibilityValue();
}
void InternalSettings::setForcedPrefersContrastAccessibilityValue(InternalSettings::ForcedAccessibilityValue value)
{
settings().setForcedPrefersContrastAccessibilityValue(value);
}
InternalSettings::ForcedAccessibilityValue InternalSettings::forcedPrefersReducedMotionAccessibilityValue() const
{
return settings().forcedPrefersReducedMotionAccessibilityValue();
}
void InternalSettings::setForcedPrefersReducedMotionAccessibilityValue(InternalSettings::ForcedAccessibilityValue value)
{
settings().setForcedPrefersReducedMotionAccessibilityValue(value);
}
InternalSettings::ForcedAccessibilityValue InternalSettings::forcedSupportsHighDynamicRangeValue() const
{
return settings().forcedSupportsHighDynamicRangeValue();
}
void InternalSettings::setForcedSupportsHighDynamicRangeValue(InternalSettings::ForcedAccessibilityValue value)
{
settings().setForcedSupportsHighDynamicRangeValue(value);
}
ExceptionOr<void> InternalSettings::setFetchAPIKeepAliveEnabled(bool enabled)
{
if (!m_page)
return Exception { InvalidAccessError };
RuntimeEnabledFeatures::sharedFeatures().setFetchAPIKeepAliveEnabled(enabled);
return { };
}
bool InternalSettings::vp9DecoderEnabled() const
{
#if ENABLE(VP9)
return m_page ? m_page->settings().vp9DecoderEnabled() : false;
#else
return false;
#endif
}
ExceptionOr<void> InternalSettings::setCustomPasteboardDataEnabled(bool enabled)
{
if (!m_page)
return Exception { InvalidAccessError };
RuntimeEnabledFeatures::sharedFeatures().setCustomPasteboardDataEnabled(enabled);
return { };
}
ExceptionOr<void> InternalSettings::setShouldManageAudioSessionCategory(bool should)
{
#if USE(AUDIO_SESSION)
DeprecatedGlobalSettings::setShouldManageAudioSessionCategory(should);
return { };
#else
UNUSED_PARAM(should);
return Exception { InvalidAccessError };
#endif
}
ExceptionOr<void> InternalSettings::setShouldDisplayTrackKind(TrackKind kind, bool enabled)
{
if (!m_page)
return Exception { InvalidAccessError };
#if ENABLE(VIDEO)
auto& captionPreferences = m_page->group().ensureCaptionPreferences();
switch (kind) {
case TrackKind::Subtitles:
captionPreferences.setUserPrefersSubtitles(enabled);
break;
case TrackKind::Captions:
captionPreferences.setUserPrefersCaptions(enabled);
break;
case TrackKind::TextDescriptions:
captionPreferences.setUserPrefersTextDescriptions(enabled);
break;
}
#else
UNUSED_PARAM(kind);
UNUSED_PARAM(enabled);
#endif
return { };
}
ExceptionOr<bool> InternalSettings::shouldDisplayTrackKind(TrackKind kind)
{
if (!m_page)
return Exception { InvalidAccessError };
#if ENABLE(VIDEO)
auto& captionPreferences = m_page->group().ensureCaptionPreferences();
switch (kind) {
case TrackKind::Subtitles:
return captionPreferences.userPrefersSubtitles();
case TrackKind::Captions:
return captionPreferences.userPrefersCaptions();
case TrackKind::TextDescriptions:
return captionPreferences.userPrefersTextDescriptions();
}
#else
UNUSED_PARAM(kind);
#endif
return false;
}
ExceptionOr<void> InternalSettings::setEditableRegionEnabled(bool enabled)
{
if (!m_page)
return Exception { InvalidAccessError };
#if ENABLE(EDITABLE_REGION)
m_page->setEditableRegionEnabled(enabled);
#else
UNUSED_PARAM(enabled);
#endif
return { };
}
ExceptionOr<void> InternalSettings::setCanStartMedia(bool enabled)
{
if (!m_page)
return Exception { InvalidAccessError };
m_page->setCanStartMedia(enabled);
return { };
}
ExceptionOr<void> InternalSettings::setUseDarkAppearance(bool useDarkAppearance)
{
if (!m_page)
return Exception { InvalidAccessError };
m_page->effectiveAppearanceDidChange(useDarkAppearance, m_page->useElevatedUserInterfaceLevel());
return { };
}
ExceptionOr<void> InternalSettings::setUseElevatedUserInterfaceLevel(bool useElevatedUserInterfaceLevel)
{
if (!m_page)
return Exception { InvalidAccessError };
m_page->effectiveAppearanceDidChange(m_page->useDarkAppearance(), useElevatedUserInterfaceLevel);
return { };
}
ExceptionOr<void> InternalSettings::setAllowUnclampedScrollPosition(bool allowUnclamped)
{
if (!m_page || !m_page->mainFrame().view())
return Exception { InvalidAccessError };
m_page->mainFrame().view()->setAllowsUnclampedScrollPositionForTesting(allowUnclamped);
return { };
}
ExceptionOr<void> InternalSettings::setShouldDeactivateAudioSession(bool should)
{
if (!m_page)
return Exception { InvalidAccessError };
#if ENABLE(VIDEO) || ENABLE(WEB_AUDIO)
PlatformMediaSessionManager::setShouldDeactivateAudioSession(should);
#endif
return { };
}
ExceptionOr<void> InternalSettings::setShouldMockBoldSystemFontForAccessibility(bool requires)
{
if (!m_page)
return Exception { InvalidAccessError };
RenderTheme::singleton().setShouldMockBoldSystemFontForAccessibility(requires);
FontCache::singleton().setShouldMockBoldSystemFontForAccessibility(requires);
return { };
}
ExceptionOr<void> InternalSettings::setDefaultAudioContextSampleRate(float sampleRate)
{
if (!m_page)
return Exception { InvalidAccessError };
#if ENABLE(WEB_AUDIO)
AudioContext::setDefaultSampleRateForTesting(sampleRate);
#else
UNUSED_PARAM(sampleRate);
#endif
return { };
}
// If you add to this class, make sure you are not duplicating functionality in the generated
// base class InternalSettingsGenerated and that you update the Backup class for test reproducability.
}