/* * 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 #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(standardFont.key)); m_standardFontFamilies.clear(); for (const auto& fixedFont : m_fixedFontFamilies) settings.setFixedFontFamily(fixedFont.value, static_cast(fixedFont.key)); m_fixedFontFamilies.clear(); for (const auto& serifFont : m_serifFontFamilies) settings.setSerifFontFamily(serifFont.value, static_cast(serifFont.key)); m_serifFontFamilies.clear(); for (const auto& sansSerifFont : m_sansSerifFontFamilies) settings.setSansSerifFontFamily(sansSerifFont.value, static_cast(sansSerifFont.key)); m_sansSerifFontFamilies.clear(); for (const auto& cursiveFont : m_cursiveFontFamilies) settings.setCursiveFontFamily(cursiveFont.value, static_cast(cursiveFont.key)); m_cursiveFontFamilies.clear(); for (const auto& fantasyFont : m_fantasyFontFamilies) settings.setFantasyFontFamily(fantasyFont.value, static_cast(fantasyFont.key)); m_fantasyFontFamilies.clear(); for (const auto& pictographFont : m_pictographFontFamilies) settings.setPictographFontFamily(pictographFont.value, static_cast(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 { 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 m_internalSettings; }; const char* InternalSettings::supplementName() { return "InternalSettings"; } InternalSettings* InternalSettings::from(Page* page) { if (!Supplement::from(page, supplementName())) Supplement::provideTo(page, supplementName(), makeUnique(page)); return static_cast(Supplement::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::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 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 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 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 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 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 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 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 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 InternalSettings::setEditingBehavior(EditingBehaviorType editingBehaviorType) { if (!m_page) return Exception { InvalidAccessError }; settings().setEditingBehaviorType(editingBehaviorType); return { }; } ExceptionOr InternalSettings::setStorageBlockingPolicy(StorageBlockingPolicy policy) { if (!m_page) return Exception { InvalidAccessError }; settings().setStorageBlockingPolicy(policy); return { }; } ExceptionOr InternalSettings::setPDFImageCachingPolicy(PDFImageCachingPolicy policy) { if (!m_page) return Exception { InvalidAccessError }; settings().setPdfImageCachingPolicy(policy); return { }; } ExceptionOr InternalSettings::setMinimumTimerInterval(double intervalInSeconds) { if (!m_page) return Exception { InvalidAccessError }; settings().setMinimumDOMTimerInterval(Seconds { intervalInSeconds }); return { }; } ExceptionOr InternalSettings::setTimeWithoutMouseMovementBeforeHidingControls(double time) { if (!m_page) return Exception { InvalidAccessError }; settings().setTimeWithoutMouseMovementBeforeHidingControls(Seconds { time }); return { }; } ExceptionOr InternalSettings::setFontLoadTimingOverride(FontLoadTimingOverride fontLoadTimingOverride) { if (!m_page) return Exception { InvalidAccessError }; settings().setFontLoadTimingOverride(fontLoadTimingOverride); return { }; } ExceptionOr InternalSettings::setUserInterfaceDirectionPolicy(UserInterfaceDirectionPolicy policy) { if (!m_page) return Exception { InvalidAccessError }; settings().setUserInterfaceDirectionPolicy(policy); return { }; } ExceptionOr InternalSettings::setSystemLayoutDirection(SystemLayoutDirection direction) { if (!m_page) return Exception { InvalidAccessError }; settings().setSystemLayoutDirection(direction); return { }; } ExceptionOr 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 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 InternalSettings::setCustomPasteboardDataEnabled(bool enabled) { if (!m_page) return Exception { InvalidAccessError }; RuntimeEnabledFeatures::sharedFeatures().setCustomPasteboardDataEnabled(enabled); return { }; } ExceptionOr InternalSettings::setShouldManageAudioSessionCategory(bool should) { #if USE(AUDIO_SESSION) DeprecatedGlobalSettings::setShouldManageAudioSessionCategory(should); return { }; #else UNUSED_PARAM(should); return Exception { InvalidAccessError }; #endif } ExceptionOr 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 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 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 InternalSettings::setCanStartMedia(bool enabled) { if (!m_page) return Exception { InvalidAccessError }; m_page->setCanStartMedia(enabled); return { }; } ExceptionOr InternalSettings::setUseDarkAppearance(bool useDarkAppearance) { if (!m_page) return Exception { InvalidAccessError }; m_page->effectiveAppearanceDidChange(useDarkAppearance, m_page->useElevatedUserInterfaceLevel()); return { }; } ExceptionOr InternalSettings::setUseElevatedUserInterfaceLevel(bool useElevatedUserInterfaceLevel) { if (!m_page) return Exception { InvalidAccessError }; m_page->effectiveAppearanceDidChange(m_page->useDarkAppearance(), useElevatedUserInterfaceLevel); return { }; } ExceptionOr InternalSettings::setAllowUnclampedScrollPosition(bool allowUnclamped) { if (!m_page || !m_page->mainFrame().view()) return Exception { InvalidAccessError }; m_page->mainFrame().view()->setAllowsUnclampedScrollPositionForTesting(allowUnclamped); return { }; } ExceptionOr InternalSettings::setShouldDeactivateAudioSession(bool should) { if (!m_page) return Exception { InvalidAccessError }; #if ENABLE(VIDEO) || ENABLE(WEB_AUDIO) PlatformMediaSessionManager::setShouldDeactivateAudioSession(should); #endif return { }; } ExceptionOr InternalSettings::setShouldMockBoldSystemFontForAccessibility(bool requires) { if (!m_page) return Exception { InvalidAccessError }; RenderTheme::singleton().setShouldMockBoldSystemFontForAccessibility(requires); FontCache::singleton().setShouldMockBoldSystemFontForAccessibility(requires); return { }; } ExceptionOr 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. }