1/*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "SettingsBase.h"
28
29#include "AudioSession.h"
30#include "BackForwardController.h"
31#include "CachedResourceLoader.h"
32#include "CookieStorage.h"
33#include "DOMTimer.h"
34#include "Database.h"
35#include "Document.h"
36#include "FontCascade.h"
37#include "FontGenericFamilies.h"
38#include "Frame.h"
39#include "FrameTree.h"
40#include "FrameView.h"
41#include "HistoryItem.h"
42#include "Page.h"
43#include "PageCache.h"
44#include "RenderWidget.h"
45#include "RuntimeApplicationChecks.h"
46#include "Settings.h"
47#include "StorageMap.h"
48#include <limits>
49#include <wtf/StdLibExtras.h>
50
51#if ENABLE(MEDIA_STREAM)
52#include "MockRealtimeMediaSourceCenter.h"
53#endif
54
55namespace WebCore {
56
57static void invalidateAfterGenericFamilyChange(Page* page)
58{
59 invalidateFontCascadeCache();
60 if (page)
61 page->setNeedsRecalcStyleInAllFrames();
62}
63
64// This amount of time must have elapsed before we will even consider scheduling a layout without a delay.
65// FIXME: For faster machines this value can really be lowered to 200. 250 is adequate, but a little high
66// for dual G5s. :)
67static const Seconds layoutScheduleThreshold = 250_ms;
68
69SettingsBase::SettingsBase(Page* page)
70 : m_page(nullptr)
71 , m_fontGenericFamilies(std::make_unique<FontGenericFamilies>())
72 , m_layoutInterval(layoutScheduleThreshold)
73 , m_minimumDOMTimerInterval(DOMTimer::defaultMinimumInterval())
74 , m_setImageLoadingSettingsTimer(*this, &SettingsBase::imageLoadingSettingsTimerFired)
75{
76 // A Frame may not have been created yet, so we initialize the AtomString
77 // hash before trying to use it.
78 AtomString::init();
79 initializeDefaultFontFamilies();
80 m_page = page; // Page is not yet fully initialized when constructing Settings, so keeping m_page null over initializeDefaultFontFamilies() call.
81}
82
83SettingsBase::~SettingsBase() = default;
84
85float SettingsBase::defaultMinimumZoomFontSize()
86{
87#if PLATFORM(WATCHOS)
88 return 30;
89#else
90 return 15;
91#endif
92}
93
94#if !PLATFORM(IOS_FAMILY)
95bool SettingsBase::defaultTextAutosizingEnabled()
96{
97 return false;
98}
99#endif
100
101bool SettingsBase::defaultDownloadableBinaryFontsEnabled()
102{
103#if PLATFORM(WATCHOS)
104 return false;
105#else
106 return true;
107#endif
108}
109
110bool SettingsBase::defaultContentChangeObserverEnabled()
111{
112#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOSMAC)
113 return true;
114#else
115 return false;
116#endif
117}
118
119#if !PLATFORM(COCOA)
120const String& SettingsBase::defaultMediaContentTypesRequiringHardwareSupport()
121{
122 return emptyString();
123}
124#endif
125
126#if !PLATFORM(COCOA)
127void SettingsBase::initializeDefaultFontFamilies()
128{
129 // Other platforms can set up fonts from a client, but on Mac, we want it in WebCore to share code between WebKit1 and WebKit2.
130}
131#endif
132
133#if ENABLE(MEDIA_SOURCE) && !PLATFORM(COCOA)
134bool SettingsBase::platformDefaultMediaSourceEnabled()
135{
136 return true;
137}
138#endif
139
140const AtomString& SettingsBase::standardFontFamily(UScriptCode script) const
141{
142 return m_fontGenericFamilies->standardFontFamily(script);
143}
144
145void SettingsBase::setStandardFontFamily(const AtomString& family, UScriptCode script)
146{
147 bool changes = m_fontGenericFamilies->setStandardFontFamily(family, script);
148 if (changes)
149 invalidateAfterGenericFamilyChange(m_page);
150}
151
152const AtomString& SettingsBase::fixedFontFamily(UScriptCode script) const
153{
154 return m_fontGenericFamilies->fixedFontFamily(script);
155}
156
157void SettingsBase::setFixedFontFamily(const AtomString& family, UScriptCode script)
158{
159 bool changes = m_fontGenericFamilies->setFixedFontFamily(family, script);
160 if (changes)
161 invalidateAfterGenericFamilyChange(m_page);
162}
163
164const AtomString& SettingsBase::serifFontFamily(UScriptCode script) const
165{
166 return m_fontGenericFamilies->serifFontFamily(script);
167}
168
169void SettingsBase::setSerifFontFamily(const AtomString& family, UScriptCode script)
170{
171 bool changes = m_fontGenericFamilies->setSerifFontFamily(family, script);
172 if (changes)
173 invalidateAfterGenericFamilyChange(m_page);
174}
175
176const AtomString& SettingsBase::sansSerifFontFamily(UScriptCode script) const
177{
178 return m_fontGenericFamilies->sansSerifFontFamily(script);
179}
180
181void SettingsBase::setSansSerifFontFamily(const AtomString& family, UScriptCode script)
182{
183 bool changes = m_fontGenericFamilies->setSansSerifFontFamily(family, script);
184 if (changes)
185 invalidateAfterGenericFamilyChange(m_page);
186}
187
188const AtomString& SettingsBase::cursiveFontFamily(UScriptCode script) const
189{
190 return m_fontGenericFamilies->cursiveFontFamily(script);
191}
192
193void SettingsBase::setCursiveFontFamily(const AtomString& family, UScriptCode script)
194{
195 bool changes = m_fontGenericFamilies->setCursiveFontFamily(family, script);
196 if (changes)
197 invalidateAfterGenericFamilyChange(m_page);
198}
199
200const AtomString& SettingsBase::fantasyFontFamily(UScriptCode script) const
201{
202 return m_fontGenericFamilies->fantasyFontFamily(script);
203}
204
205void SettingsBase::setFantasyFontFamily(const AtomString& family, UScriptCode script)
206{
207 bool changes = m_fontGenericFamilies->setFantasyFontFamily(family, script);
208 if (changes)
209 invalidateAfterGenericFamilyChange(m_page);
210}
211
212const AtomString& SettingsBase::pictographFontFamily(UScriptCode script) const
213{
214 return m_fontGenericFamilies->pictographFontFamily(script);
215}
216
217void SettingsBase::setPictographFontFamily(const AtomString& family, UScriptCode script)
218{
219 bool changes = m_fontGenericFamilies->setPictographFontFamily(family, script);
220 if (changes)
221 invalidateAfterGenericFamilyChange(m_page);
222}
223
224void SettingsBase::setMinimumDOMTimerInterval(Seconds interval)
225{
226 auto oldTimerInterval = std::exchange(m_minimumDOMTimerInterval, interval);
227
228 if (!m_page)
229 return;
230
231 for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
232 if (frame->document())
233 frame->document()->adjustMinimumDOMTimerInterval(oldTimerInterval);
234 }
235}
236
237void SettingsBase::setLayoutInterval(Seconds layoutInterval)
238{
239 // FIXME: It seems weird that this function may disregard the specified layout interval.
240 // We should either expose layoutScheduleThreshold or better communicate this invariant.
241 m_layoutInterval = std::max(layoutInterval, layoutScheduleThreshold);
242}
243
244void SettingsBase::setMediaContentTypesRequiringHardwareSupport(const String& contentTypes)
245{
246 m_mediaContentTypesRequiringHardwareSupport.shrink(0);
247 for (auto type : StringView(contentTypes).split(':'))
248 m_mediaContentTypesRequiringHardwareSupport.append(ContentType { type.toString() });
249}
250
251void SettingsBase::setMediaContentTypesRequiringHardwareSupport(const Vector<ContentType>& contentTypes)
252{
253 m_mediaContentTypesRequiringHardwareSupport = contentTypes;
254}
255
256
257
258// MARK - onChange handlers
259
260void SettingsBase::setNeedsRecalcStyleInAllFrames()
261{
262 if (m_page)
263 m_page->setNeedsRecalcStyleInAllFrames();
264}
265
266void SettingsBase::setNeedsRelayoutAllFrames()
267{
268 if (!m_page)
269 return;
270
271 for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
272 if (!frame->ownerRenderer())
273 continue;
274 frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
275 }
276}
277
278void SettingsBase::mediaTypeOverrideChanged()
279{
280 if (!m_page)
281 return;
282
283 FrameView* view = m_page->mainFrame().view();
284 if (view)
285 view->setMediaType(m_page->settings().mediaTypeOverride());
286
287 m_page->setNeedsRecalcStyleInAllFrames();
288}
289
290void SettingsBase::imagesEnabledChanged()
291{
292 // Changing this setting to true might immediately start new loads for images that had previously had loading disabled.
293 // If this happens while a WebView is being dealloc'ed, and we don't know the WebView is being dealloc'ed, these new loads
294 // can cause crashes downstream when the WebView memory has actually been free'd.
295 // One example where this can happen is in Mac apps that subclass WebView then do work in their overridden dealloc methods.
296 // Starting these loads synchronously is not important. By putting it on a 0-delay, properly closing the Page cancels them
297 // before they have a chance to really start.
298 // See http://webkit.org/b/60572 for more discussion.
299 m_setImageLoadingSettingsTimer.startOneShot(0_s);
300}
301
302void SettingsBase::imageLoadingSettingsTimerFired()
303{
304 if (!m_page)
305 return;
306
307 for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
308 if (!frame->document())
309 continue;
310 frame->document()->cachedResourceLoader().setImagesEnabled(m_page->settings().areImagesEnabled());
311 frame->document()->cachedResourceLoader().setAutoLoadImages(m_page->settings().loadsImagesAutomatically());
312 }
313}
314
315void SettingsBase::pluginsEnabledChanged()
316{
317 Page::refreshPlugins(false);
318}
319
320void SettingsBase::iceCandidateFilteringEnabledChanged()
321{
322 if (!m_page)
323 return;
324
325 if (m_page->settings().iceCandidateFilteringEnabled())
326 m_page->enableICECandidateFiltering();
327 else
328 m_page->disableICECandidateFiltering();
329}
330
331#if ENABLE(TEXT_AUTOSIZING)
332
333void SettingsBase::shouldEnableTextAutosizingBoostChanged()
334{
335 if (!m_page)
336 return;
337
338 bool boostAutosizing = m_page->settings().shouldEnableTextAutosizingBoost();
339 m_oneLineTextMultiplierCoefficient = boostAutosizing ? boostedOneLineTextMultiplierCoefficient : defaultOneLineTextMultiplierCoefficient;
340 m_multiLineTextMultiplierCoefficient = boostAutosizing ? boostedMultiLineTextMultiplierCoefficient : defaultMultiLineTextMultiplierCoefficient;
341 m_maxTextAutosizingScaleIncrease = boostAutosizing ? boostedMaxTextAutosizingScaleIncrease : defaultMaxTextAutosizingScaleIncrease;
342
343 setNeedsRecalcStyleInAllFrames();
344}
345
346#endif
347
348#if ENABLE(MEDIA_STREAM)
349void SettingsBase::mockCaptureDevicesEnabledChanged()
350{
351 bool enabled = false;
352 if (m_page)
353 enabled = m_page->settings().mockCaptureDevicesEnabled();
354
355 MockRealtimeMediaSourceCenter::setMockRealtimeMediaSourceCenterEnabled(enabled);
356}
357#endif
358
359void SettingsBase::userStyleSheetLocationChanged()
360{
361 if (m_page)
362 m_page->userStyleSheetLocationChanged();
363}
364
365void SettingsBase::usesPageCacheChanged()
366{
367 if (!m_page)
368 return;
369
370 if (!m_page->settings().usesPageCache())
371 PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
372}
373
374void SettingsBase::dnsPrefetchingEnabledChanged()
375{
376 if (m_page)
377 m_page->dnsPrefetchingStateChanged();
378}
379
380void SettingsBase::storageBlockingPolicyChanged()
381{
382 if (m_page)
383 m_page->storageBlockingStateChanged();
384}
385
386void SettingsBase::backgroundShouldExtendBeyondPageChanged()
387{
388 if (m_page)
389 m_page->mainFrame().view()->updateExtendBackgroundIfNecessary();
390}
391
392void SettingsBase::scrollingPerformanceLoggingEnabledChanged()
393{
394 if (m_page && m_page->mainFrame().view())
395 m_page->mainFrame().view()->setScrollingPerformanceLoggingEnabled(m_page->settings().scrollingPerformanceLoggingEnabled());
396}
397
398void SettingsBase::hiddenPageDOMTimerThrottlingStateChanged()
399{
400 if (m_page)
401 m_page->hiddenPageDOMTimerThrottlingStateChanged();
402}
403
404void SettingsBase::hiddenPageCSSAnimationSuspensionEnabledChanged()
405{
406 if (m_page)
407 m_page->hiddenPageCSSAnimationSuspensionStateChanged();
408}
409
410void SettingsBase::resourceUsageOverlayVisibleChanged()
411{
412#if ENABLE(RESOURCE_USAGE)
413 if (m_page)
414 m_page->setResourceUsageOverlayVisible(m_page->settings().resourceUsageOverlayVisible());
415#endif
416}
417
418} // namespace WebCore
419