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 AtomicString
77 // hash before trying to use it.
78 AtomicString::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
100bool SettingsBase::defaultTextAutosizingUsesIdempotentMode()
101{
102 return false;
103}
104#endif
105
106bool SettingsBase::defaultDownloadableBinaryFontsEnabled()
107{
108#if PLATFORM(WATCHOS)
109 return false;
110#else
111 return true;
112#endif
113}
114
115bool SettingsBase::defaultContentChangeObserverEnabled()
116{
117#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOSMAC)
118 return true;
119#else
120 return false;
121#endif
122}
123
124#if !PLATFORM(COCOA)
125const String& SettingsBase::defaultMediaContentTypesRequiringHardwareSupport()
126{
127 return emptyString();
128}
129#endif
130
131#if !PLATFORM(COCOA)
132void SettingsBase::initializeDefaultFontFamilies()
133{
134 // Other platforms can set up fonts from a client, but on Mac, we want it in WebCore to share code between WebKit1 and WebKit2.
135}
136#endif
137
138#if ENABLE(MEDIA_SOURCE) && !PLATFORM(COCOA)
139bool SettingsBase::platformDefaultMediaSourceEnabled()
140{
141 return true;
142}
143#endif
144
145const AtomicString& SettingsBase::standardFontFamily(UScriptCode script) const
146{
147 return m_fontGenericFamilies->standardFontFamily(script);
148}
149
150void SettingsBase::setStandardFontFamily(const AtomicString& family, UScriptCode script)
151{
152 bool changes = m_fontGenericFamilies->setStandardFontFamily(family, script);
153 if (changes)
154 invalidateAfterGenericFamilyChange(m_page);
155}
156
157const AtomicString& SettingsBase::fixedFontFamily(UScriptCode script) const
158{
159 return m_fontGenericFamilies->fixedFontFamily(script);
160}
161
162void SettingsBase::setFixedFontFamily(const AtomicString& family, UScriptCode script)
163{
164 bool changes = m_fontGenericFamilies->setFixedFontFamily(family, script);
165 if (changes)
166 invalidateAfterGenericFamilyChange(m_page);
167}
168
169const AtomicString& SettingsBase::serifFontFamily(UScriptCode script) const
170{
171 return m_fontGenericFamilies->serifFontFamily(script);
172}
173
174void SettingsBase::setSerifFontFamily(const AtomicString& family, UScriptCode script)
175{
176 bool changes = m_fontGenericFamilies->setSerifFontFamily(family, script);
177 if (changes)
178 invalidateAfterGenericFamilyChange(m_page);
179}
180
181const AtomicString& SettingsBase::sansSerifFontFamily(UScriptCode script) const
182{
183 return m_fontGenericFamilies->sansSerifFontFamily(script);
184}
185
186void SettingsBase::setSansSerifFontFamily(const AtomicString& family, UScriptCode script)
187{
188 bool changes = m_fontGenericFamilies->setSansSerifFontFamily(family, script);
189 if (changes)
190 invalidateAfterGenericFamilyChange(m_page);
191}
192
193const AtomicString& SettingsBase::cursiveFontFamily(UScriptCode script) const
194{
195 return m_fontGenericFamilies->cursiveFontFamily(script);
196}
197
198void SettingsBase::setCursiveFontFamily(const AtomicString& family, UScriptCode script)
199{
200 bool changes = m_fontGenericFamilies->setCursiveFontFamily(family, script);
201 if (changes)
202 invalidateAfterGenericFamilyChange(m_page);
203}
204
205const AtomicString& SettingsBase::fantasyFontFamily(UScriptCode script) const
206{
207 return m_fontGenericFamilies->fantasyFontFamily(script);
208}
209
210void SettingsBase::setFantasyFontFamily(const AtomicString& family, UScriptCode script)
211{
212 bool changes = m_fontGenericFamilies->setFantasyFontFamily(family, script);
213 if (changes)
214 invalidateAfterGenericFamilyChange(m_page);
215}
216
217const AtomicString& SettingsBase::pictographFontFamily(UScriptCode script) const
218{
219 return m_fontGenericFamilies->pictographFontFamily(script);
220}
221
222void SettingsBase::setPictographFontFamily(const AtomicString& family, UScriptCode script)
223{
224 bool changes = m_fontGenericFamilies->setPictographFontFamily(family, script);
225 if (changes)
226 invalidateAfterGenericFamilyChange(m_page);
227}
228
229void SettingsBase::setMinimumDOMTimerInterval(Seconds interval)
230{
231 auto oldTimerInterval = std::exchange(m_minimumDOMTimerInterval, interval);
232
233 if (!m_page)
234 return;
235
236 for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
237 if (frame->document())
238 frame->document()->adjustMinimumDOMTimerInterval(oldTimerInterval);
239 }
240}
241
242void SettingsBase::setLayoutInterval(Seconds layoutInterval)
243{
244 // FIXME: It seems weird that this function may disregard the specified layout interval.
245 // We should either expose layoutScheduleThreshold or better communicate this invariant.
246 m_layoutInterval = std::max(layoutInterval, layoutScheduleThreshold);
247}
248
249void SettingsBase::setMediaContentTypesRequiringHardwareSupport(const String& contentTypes)
250{
251 m_mediaContentTypesRequiringHardwareSupport.shrink(0);
252 for (auto type : StringView(contentTypes).split(':'))
253 m_mediaContentTypesRequiringHardwareSupport.append(ContentType { type.toString() });
254}
255
256void SettingsBase::setMediaContentTypesRequiringHardwareSupport(const Vector<ContentType>& contentTypes)
257{
258 m_mediaContentTypesRequiringHardwareSupport = contentTypes;
259}
260
261
262
263// MARK - onChange handlers
264
265void SettingsBase::setNeedsRecalcStyleInAllFrames()
266{
267 if (m_page)
268 m_page->setNeedsRecalcStyleInAllFrames();
269}
270
271void SettingsBase::setNeedsRelayoutAllFrames()
272{
273 if (!m_page)
274 return;
275
276 for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
277 if (!frame->ownerRenderer())
278 continue;
279 frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
280 }
281}
282
283void SettingsBase::mediaTypeOverrideChanged()
284{
285 if (!m_page)
286 return;
287
288 FrameView* view = m_page->mainFrame().view();
289 if (view)
290 view->setMediaType(m_page->settings().mediaTypeOverride());
291
292 m_page->setNeedsRecalcStyleInAllFrames();
293}
294
295void SettingsBase::imagesEnabledChanged()
296{
297 // Changing this setting to true might immediately start new loads for images that had previously had loading disabled.
298 // If this happens while a WebView is being dealloc'ed, and we don't know the WebView is being dealloc'ed, these new loads
299 // can cause crashes downstream when the WebView memory has actually been free'd.
300 // One example where this can happen is in Mac apps that subclass WebView then do work in their overridden dealloc methods.
301 // Starting these loads synchronously is not important. By putting it on a 0-delay, properly closing the Page cancels them
302 // before they have a chance to really start.
303 // See http://webkit.org/b/60572 for more discussion.
304 m_setImageLoadingSettingsTimer.startOneShot(0_s);
305}
306
307void SettingsBase::imageLoadingSettingsTimerFired()
308{
309 if (!m_page)
310 return;
311
312 for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
313 if (!frame->document())
314 continue;
315 frame->document()->cachedResourceLoader().setImagesEnabled(m_page->settings().areImagesEnabled());
316 frame->document()->cachedResourceLoader().setAutoLoadImages(m_page->settings().loadsImagesAutomatically());
317 }
318}
319
320void SettingsBase::pluginsEnabledChanged()
321{
322 Page::refreshPlugins(false);
323}
324
325void SettingsBase::iceCandidateFilteringEnabledChanged()
326{
327 if (!m_page)
328 return;
329
330 if (m_page->settings().iceCandidateFilteringEnabled())
331 m_page->enableICECandidateFiltering();
332 else
333 m_page->disableICECandidateFiltering();
334}
335
336#if ENABLE(TEXT_AUTOSIZING)
337
338void SettingsBase::shouldEnableTextAutosizingBoostChanged()
339{
340 if (!m_page)
341 return;
342
343 bool boostAutosizing = m_page->settings().shouldEnableTextAutosizingBoost();
344 m_oneLineTextMultiplierCoefficient = boostAutosizing ? boostedOneLineTextMultiplierCoefficient : defaultOneLineTextMultiplierCoefficient;
345 m_multiLineTextMultiplierCoefficient = boostAutosizing ? boostedMultiLineTextMultiplierCoefficient : defaultMultiLineTextMultiplierCoefficient;
346 m_maxTextAutosizingScaleIncrease = boostAutosizing ? boostedMaxTextAutosizingScaleIncrease : defaultMaxTextAutosizingScaleIncrease;
347
348 setNeedsRecalcStyleInAllFrames();
349}
350
351#endif
352
353#if ENABLE(MEDIA_STREAM)
354void SettingsBase::mockCaptureDevicesEnabledChanged()
355{
356 bool enabled = false;
357 if (m_page)
358 enabled = m_page->settings().mockCaptureDevicesEnabled();
359
360 MockRealtimeMediaSourceCenter::setMockRealtimeMediaSourceCenterEnabled(enabled);
361}
362#endif
363
364void SettingsBase::userStyleSheetLocationChanged()
365{
366 if (m_page)
367 m_page->userStyleSheetLocationChanged();
368}
369
370void SettingsBase::usesPageCacheChanged()
371{
372 if (!m_page)
373 return;
374
375 if (!m_page->settings().usesPageCache())
376 PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
377}
378
379void SettingsBase::dnsPrefetchingEnabledChanged()
380{
381 if (m_page)
382 m_page->dnsPrefetchingStateChanged();
383}
384
385void SettingsBase::storageBlockingPolicyChanged()
386{
387 if (m_page)
388 m_page->storageBlockingStateChanged();
389}
390
391void SettingsBase::backgroundShouldExtendBeyondPageChanged()
392{
393 if (m_page)
394 m_page->mainFrame().view()->updateExtendBackgroundIfNecessary();
395}
396
397void SettingsBase::scrollingPerformanceLoggingEnabledChanged()
398{
399 if (m_page && m_page->mainFrame().view())
400 m_page->mainFrame().view()->setScrollingPerformanceLoggingEnabled(m_page->settings().scrollingPerformanceLoggingEnabled());
401}
402
403void SettingsBase::hiddenPageDOMTimerThrottlingStateChanged()
404{
405 if (m_page)
406 m_page->hiddenPageDOMTimerThrottlingStateChanged();
407}
408
409void SettingsBase::hiddenPageCSSAnimationSuspensionEnabledChanged()
410{
411 if (m_page)
412 m_page->hiddenPageCSSAnimationSuspensionStateChanged();
413}
414
415void SettingsBase::resourceUsageOverlayVisibleChanged()
416{
417#if ENABLE(RESOURCE_USAGE)
418 if (m_page)
419 m_page->setResourceUsageOverlayVisible(m_page->settings().resourceUsageOverlayVisible());
420#endif
421}
422
423} // namespace WebCore
424