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 | |
55 | namespace WebCore { |
56 | |
57 | static 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. :) |
67 | static const Seconds layoutScheduleThreshold = 250_ms; |
68 | |
69 | SettingsBase::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 | |
83 | SettingsBase::~SettingsBase() = default; |
84 | |
85 | float SettingsBase::defaultMinimumZoomFontSize() |
86 | { |
87 | #if PLATFORM(WATCHOS) |
88 | return 30; |
89 | #else |
90 | return 15; |
91 | #endif |
92 | } |
93 | |
94 | #if !PLATFORM(IOS_FAMILY) |
95 | bool SettingsBase::defaultTextAutosizingEnabled() |
96 | { |
97 | return false; |
98 | } |
99 | #endif |
100 | |
101 | bool SettingsBase::defaultDownloadableBinaryFontsEnabled() |
102 | { |
103 | #if PLATFORM(WATCHOS) |
104 | return false; |
105 | #else |
106 | return true; |
107 | #endif |
108 | } |
109 | |
110 | bool 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) |
120 | const String& SettingsBase::defaultMediaContentTypesRequiringHardwareSupport() |
121 | { |
122 | return emptyString(); |
123 | } |
124 | #endif |
125 | |
126 | #if !PLATFORM(COCOA) |
127 | void 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) |
134 | bool SettingsBase::platformDefaultMediaSourceEnabled() |
135 | { |
136 | return true; |
137 | } |
138 | #endif |
139 | |
140 | const AtomString& SettingsBase::standardFontFamily(UScriptCode script) const |
141 | { |
142 | return m_fontGenericFamilies->standardFontFamily(script); |
143 | } |
144 | |
145 | void 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 | |
152 | const AtomString& SettingsBase::fixedFontFamily(UScriptCode script) const |
153 | { |
154 | return m_fontGenericFamilies->fixedFontFamily(script); |
155 | } |
156 | |
157 | void 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 | |
164 | const AtomString& SettingsBase::serifFontFamily(UScriptCode script) const |
165 | { |
166 | return m_fontGenericFamilies->serifFontFamily(script); |
167 | } |
168 | |
169 | void 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 | |
176 | const AtomString& SettingsBase::sansSerifFontFamily(UScriptCode script) const |
177 | { |
178 | return m_fontGenericFamilies->sansSerifFontFamily(script); |
179 | } |
180 | |
181 | void 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 | |
188 | const AtomString& SettingsBase::cursiveFontFamily(UScriptCode script) const |
189 | { |
190 | return m_fontGenericFamilies->cursiveFontFamily(script); |
191 | } |
192 | |
193 | void 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 | |
200 | const AtomString& SettingsBase::fantasyFontFamily(UScriptCode script) const |
201 | { |
202 | return m_fontGenericFamilies->fantasyFontFamily(script); |
203 | } |
204 | |
205 | void 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 | |
212 | const AtomString& SettingsBase::pictographFontFamily(UScriptCode script) const |
213 | { |
214 | return m_fontGenericFamilies->pictographFontFamily(script); |
215 | } |
216 | |
217 | void 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 | |
224 | void 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 | |
237 | void 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 | |
244 | void 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 | |
251 | void SettingsBase::setMediaContentTypesRequiringHardwareSupport(const Vector<ContentType>& contentTypes) |
252 | { |
253 | m_mediaContentTypesRequiringHardwareSupport = contentTypes; |
254 | } |
255 | |
256 | |
257 | |
258 | // MARK - onChange handlers |
259 | |
260 | void SettingsBase::setNeedsRecalcStyleInAllFrames() |
261 | { |
262 | if (m_page) |
263 | m_page->setNeedsRecalcStyleInAllFrames(); |
264 | } |
265 | |
266 | void 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 | |
278 | void 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 | |
290 | void 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 | |
302 | void 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 | |
315 | void SettingsBase::pluginsEnabledChanged() |
316 | { |
317 | Page::refreshPlugins(false); |
318 | } |
319 | |
320 | void 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 | |
333 | void 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) |
349 | void 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 | |
359 | void SettingsBase::userStyleSheetLocationChanged() |
360 | { |
361 | if (m_page) |
362 | m_page->userStyleSheetLocationChanged(); |
363 | } |
364 | |
365 | void 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 | |
374 | void SettingsBase::dnsPrefetchingEnabledChanged() |
375 | { |
376 | if (m_page) |
377 | m_page->dnsPrefetchingStateChanged(); |
378 | } |
379 | |
380 | void SettingsBase::storageBlockingPolicyChanged() |
381 | { |
382 | if (m_page) |
383 | m_page->storageBlockingStateChanged(); |
384 | } |
385 | |
386 | void SettingsBase::backgroundShouldExtendBeyondPageChanged() |
387 | { |
388 | if (m_page) |
389 | m_page->mainFrame().view()->updateExtendBackgroundIfNecessary(); |
390 | } |
391 | |
392 | void SettingsBase::scrollingPerformanceLoggingEnabledChanged() |
393 | { |
394 | if (m_page && m_page->mainFrame().view()) |
395 | m_page->mainFrame().view()->setScrollingPerformanceLoggingEnabled(m_page->settings().scrollingPerformanceLoggingEnabled()); |
396 | } |
397 | |
398 | void SettingsBase::hiddenPageDOMTimerThrottlingStateChanged() |
399 | { |
400 | if (m_page) |
401 | m_page->hiddenPageDOMTimerThrottlingStateChanged(); |
402 | } |
403 | |
404 | void SettingsBase::hiddenPageCSSAnimationSuspensionEnabledChanged() |
405 | { |
406 | if (m_page) |
407 | m_page->hiddenPageCSSAnimationSuspensionStateChanged(); |
408 | } |
409 | |
410 | void 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 | |