Improve use of NeverDestroyed
[WebKit-https.git] / Source / WebCore / page / Page.cpp
1 /*
2  * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "Page.h"
22
23 #include "ActivityStateChangeObserver.h"
24 #include "AlternativeTextClient.h"
25 #include "ApplicationCacheStorage.h"
26 #include "BackForwardClient.h"
27 #include "BackForwardController.h"
28 #include "CSSAnimationController.h"
29 #include "Chrome.h"
30 #include "ChromeClient.h"
31 #include "ConstantPropertyMap.h"
32 #include "ContextMenuClient.h"
33 #include "ContextMenuController.h"
34 #include "DOMRect.h"
35 #include "DOMRectList.h"
36 #include "DatabaseProvider.h"
37 #include "DiagnosticLoggingClient.h"
38 #include "DiagnosticLoggingKeys.h"
39 #include "DocumentLoader.h"
40 #include "DocumentMarkerController.h"
41 #include "DragController.h"
42 #include "Editor.h"
43 #include "EditorClient.h"
44 #include "EmptyClients.h"
45 #include "Event.h"
46 #include "EventNames.h"
47 #include "ExtensionStyleSheets.h"
48 #include "FileSystem.h"
49 #include "FocusController.h"
50 #include "FrameLoader.h"
51 #include "FrameLoaderClient.h"
52 #include "FrameSelection.h"
53 #include "FrameTree.h"
54 #include "FrameView.h"
55 #include "HTMLElement.h"
56 #include "HTMLMediaElement.h"
57 #include "HistoryController.h"
58 #include "HistoryItem.h"
59 #include "InspectorController.h"
60 #include "InspectorInstrumentation.h"
61 #include "LibWebRTCProvider.h"
62 #include "Logging.h"
63 #include "LowPowerModeNotifier.h"
64 #include "MainFrame.h"
65 #include "MediaCanStartListener.h"
66 #include "Navigator.h"
67 #include "NetworkStateNotifier.h"
68 #include "PageCache.h"
69 #include "PageConfiguration.h"
70 #include "PageConsoleClient.h"
71 #include "PageDebuggable.h"
72 #include "PageGroup.h"
73 #include "PageOverlayController.h"
74 #include "PerformanceLoggingClient.h"
75 #include "PerformanceMonitor.h"
76 #include "PlatformMediaSessionManager.h"
77 #include "PlugInClient.h"
78 #include "PluginData.h"
79 #include "PluginInfoProvider.h"
80 #include "PluginViewBase.h"
81 #include "PointerLockController.h"
82 #include "ProgressTracker.h"
83 #include "PublicSuffix.h"
84 #include "RenderLayerCompositor.h"
85 #include "RenderTheme.h"
86 #include "RenderView.h"
87 #include "RenderWidget.h"
88 #include "ResourceUsageOverlay.h"
89 #include "RuntimeEnabledFeatures.h"
90 #include "SVGDocumentExtensions.h"
91 #include "SchemeRegistry.h"
92 #include "ScriptController.h"
93 #include "ScriptedAnimationController.h"
94 #include "ScrollingCoordinator.h"
95 #include "Settings.h"
96 #include "SharedBuffer.h"
97 #include "SocketProvider.h"
98 #include "StorageArea.h"
99 #include "StorageNamespace.h"
100 #include "StorageNamespaceProvider.h"
101 #include "StyleResolver.h"
102 #include "StyleScope.h"
103 #include "SubframeLoader.h"
104 #include "TextResourceDecoder.h"
105 #include "UserContentProvider.h"
106 #include "UserInputBridge.h"
107 #include "ValidationMessageClient.h"
108 #include "VisitedLinkState.h"
109 #include "VisitedLinkStore.h"
110 #include "VoidCallback.h"
111 #include "WebGLStateTracker.h"
112 #include "Widget.h"
113 #include <wtf/CurrentTime.h>
114 #include <wtf/RefCountedLeakCounter.h>
115 #include <wtf/StdLibExtras.h>
116 #include <wtf/text/Base64.h>
117 #include <wtf/text/StringHash.h>
118
119 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
120 #include "HTMLVideoElement.h"
121 #include "MediaPlaybackTarget.h"
122 #endif
123
124 #if ENABLE(MEDIA_SESSION)
125 #include "MediaSessionManager.h"
126 #endif
127
128 #if ENABLE(INDEXED_DATABASE)
129 #include "IDBConnectionToServer.h"
130 #include "InProcessIDBServer.h"
131 #endif
132
133 #if ENABLE(DATA_INTERACTION)
134 #include "SelectionRect.h"
135 #endif
136
137 namespace WebCore {
138
139 static HashSet<Page*>& allPages()
140 {
141     static NeverDestroyed<HashSet<Page*>> set;
142     return set;
143 }
144
145 static unsigned nonUtilityPageCount { 0 };
146
147 static inline bool isUtilityPageChromeClient(ChromeClient& chromeClient)
148 {
149     return chromeClient.isEmptyChromeClient() || chromeClient.isSVGImageChromeClient();
150 }
151
152 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, pageCounter, ("Page"));
153
154 void Page::forEachPage(const WTF::Function<void(Page&)>& function)
155 {
156     for (auto* page : allPages())
157         function(*page);
158 }
159
160 void Page::updateValidationBubbleStateIfNeeded()
161 {
162     if (auto* client = validationMessageClient())
163         client->updateValidationBubbleStateIfNeeded();
164 }
165
166 static void networkStateChanged(bool isOnLine)
167 {
168     Vector<Ref<Frame>> frames;
169
170     // Get all the frames of all the pages in all the page groups
171     for (auto* page : allPages()) {
172         for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext())
173             frames.append(*frame);
174         InspectorInstrumentation::networkStateChanged(*page);
175     }
176
177     auto& eventName = isOnLine ? eventNames().onlineEvent : eventNames().offlineEvent;
178     for (auto& frame : frames) {
179         if (!frame->document())
180             continue;
181         frame->document()->dispatchWindowEvent(Event::create(eventName, false, false));
182     }
183 }
184
185 static const ActivityState::Flags PageInitialActivityState = ActivityState::IsVisible | ActivityState::IsInWindow;
186
187 Page::Page(PageConfiguration&& pageConfiguration)
188     : m_chrome(std::make_unique<Chrome>(*this, *pageConfiguration.chromeClient))
189     , m_dragCaretController(std::make_unique<DragCaretController>())
190 #if ENABLE(DRAG_SUPPORT)
191     , m_dragController(std::make_unique<DragController>(*this, *pageConfiguration.dragClient))
192 #endif
193     , m_focusController(std::make_unique<FocusController>(*this, PageInitialActivityState))
194 #if ENABLE(CONTEXT_MENUS)
195     , m_contextMenuController(std::make_unique<ContextMenuController>(*this, *pageConfiguration.contextMenuClient))
196 #endif
197     , m_userInputBridge(std::make_unique<UserInputBridge>(*this))
198     , m_inspectorController(std::make_unique<InspectorController>(*this, pageConfiguration.inspectorClient))
199 #if ENABLE(POINTER_LOCK)
200     , m_pointerLockController(std::make_unique<PointerLockController>(*this))
201 #endif
202     , m_settings(Settings::create(this))
203     , m_progress(std::make_unique<ProgressTracker>(*pageConfiguration.progressTrackerClient))
204     , m_backForwardController(std::make_unique<BackForwardController>(*this, *WTFMove(pageConfiguration.backForwardClient)))
205     , m_mainFrame(MainFrame::create(*this, pageConfiguration))
206     , m_editorClient(WTFMove(pageConfiguration.editorClient))
207     , m_plugInClient(pageConfiguration.plugInClient)
208     , m_validationMessageClient(WTFMove(pageConfiguration.validationMessageClient))
209     , m_diagnosticLoggingClient(WTFMove(pageConfiguration.diagnosticLoggingClient))
210     , m_performanceLoggingClient(WTFMove(pageConfiguration.performanceLoggingClient))
211     , m_webGLStateTracker(WTFMove(pageConfiguration.webGLStateTracker))
212     , m_libWebRTCProvider(WTFMove(pageConfiguration.libWebRTCProvider))
213     , m_verticalScrollElasticity(ScrollElasticityAllowed)
214     , m_horizontalScrollElasticity(ScrollElasticityAllowed)
215     , m_domTimerAlignmentInterval(DOMTimer::defaultAlignmentInterval())
216     , m_domTimerAlignmentIntervalIncreaseTimer(*this, &Page::domTimerAlignmentIntervalIncreaseTimerFired)
217     , m_activityState(PageInitialActivityState)
218     , m_alternativeTextClient(pageConfiguration.alternativeTextClient)
219     , m_consoleClient(std::make_unique<PageConsoleClient>(*this))
220 #if ENABLE(REMOTE_INSPECTOR)
221     , m_inspectorDebuggable(std::make_unique<PageDebuggable>(*this))
222 #endif
223     , m_socketProvider(WTFMove(pageConfiguration.socketProvider))
224     , m_applicationCacheStorage(*WTFMove(pageConfiguration.applicationCacheStorage))
225     , m_databaseProvider(*WTFMove(pageConfiguration.databaseProvider))
226     , m_pluginInfoProvider(*WTFMove(pageConfiguration.pluginInfoProvider))
227     , m_storageNamespaceProvider(*WTFMove(pageConfiguration.storageNamespaceProvider))
228     , m_userContentProvider(*WTFMove(pageConfiguration.userContentProvider))
229     , m_visitedLinkStore(*WTFMove(pageConfiguration.visitedLinkStore))
230     , m_sessionID(SessionID::defaultSessionID())
231     , m_isUtilityPage(isUtilityPageChromeClient(chrome().client()))
232     , m_performanceMonitor(isUtilityPage() ? nullptr : std::make_unique<PerformanceMonitor>(*this))
233     , m_lowPowerModeNotifier(std::make_unique<LowPowerModeNotifier>([this](bool isLowPowerModeEnabled) { handleLowModePowerChange(isLowPowerModeEnabled); }))
234 {
235     updateTimerThrottlingState();
236
237     m_pluginInfoProvider->addPage(*this);
238     m_storageNamespaceProvider->addPage(*this);
239     m_userContentProvider->addPage(*this);
240     m_visitedLinkStore->addPage(*this);
241
242     static bool addedListener;
243     if (!addedListener) {
244         NetworkStateNotifier::singleton().addListener(&networkStateChanged);
245         addedListener = true;
246     }
247
248     ASSERT(!allPages().contains(this));
249     allPages().add(this);
250
251     if (!isUtilityPage()) {
252         ++nonUtilityPageCount;
253         MemoryPressureHandler::setPageCount(nonUtilityPageCount);
254     }
255
256 #ifndef NDEBUG
257     pageCounter.increment();
258 #endif
259
260 #if ENABLE(REMOTE_INSPECTOR)
261     m_inspectorDebuggable->init();
262 #endif
263
264 #if PLATFORM(COCOA)
265     platformInitialize();
266 #endif
267 }
268
269 Page::~Page()
270 {
271     ASSERT(!m_nestedRunLoopCount);
272     ASSERT(!m_unnestCallback);
273
274     m_validationMessageClient = nullptr;
275     m_diagnosticLoggingClient = nullptr;
276     m_performanceLoggingClient = nullptr;
277     m_mainFrame->setView(nullptr);
278     setGroupName(String());
279     allPages().remove(this);
280     if (!isUtilityPage()) {
281         --nonUtilityPageCount;
282         MemoryPressureHandler::setPageCount(nonUtilityPageCount);
283     }
284     
285     m_settings->pageDestroyed();
286
287     m_inspectorController->inspectedPageDestroyed();
288
289     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
290         frame->willDetachPage();
291         frame->detachFromPage();
292     }
293
294     if (m_plugInClient)
295         m_plugInClient->pageDestroyed();
296     if (m_alternativeTextClient)
297         m_alternativeTextClient->pageDestroyed();
298
299     if (m_scrollingCoordinator)
300         m_scrollingCoordinator->pageDestroyed();
301
302     backForward().close();
303     if (!isUtilityPage())
304         PageCache::singleton().removeAllItemsForPage(*this);
305
306 #ifndef NDEBUG
307     pageCounter.decrement();
308 #endif
309
310     m_pluginInfoProvider->removePage(*this);
311     m_storageNamespaceProvider->removePage(*this);
312     m_userContentProvider->removePage(*this);
313     m_visitedLinkStore->removePage(*this);
314 }
315
316 void Page::clearPreviousItemFromAllPages(HistoryItem* item)
317 {
318     for (auto* page : allPages()) {
319         auto& controller = page->mainFrame().loader().history();
320         if (item == controller.previousItem()) {
321             controller.clearPreviousItem();
322             return;
323         }
324     }
325 }
326
327 uint64_t Page::renderTreeSize() const
328 {
329     uint64_t total = 0;
330     for (const Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
331         if (!frame->document() || !frame->document()->renderView())
332             continue;
333         total += frame->document()->renderView()->rendererCount();
334     }
335     return total;
336 }
337
338 ViewportArguments Page::viewportArguments() const
339 {
340     return mainFrame().document() ? mainFrame().document()->viewportArguments() : ViewportArguments();
341 }
342
343 ScrollingCoordinator* Page::scrollingCoordinator()
344 {
345     if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled()) {
346         m_scrollingCoordinator = chrome().client().createScrollingCoordinator(*this);
347         if (!m_scrollingCoordinator)
348             m_scrollingCoordinator = ScrollingCoordinator::create(this);
349     }
350
351     return m_scrollingCoordinator.get();
352 }
353
354 String Page::scrollingStateTreeAsText()
355 {
356     if (Document* document = m_mainFrame->document())
357         document->updateLayout();
358
359     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
360         return scrollingCoordinator->scrollingStateTreeAsText();
361
362     return String();
363 }
364
365 String Page::synchronousScrollingReasonsAsText()
366 {
367     if (Document* document = m_mainFrame->document())
368         document->updateLayout();
369
370     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
371         return scrollingCoordinator->synchronousScrollingReasonsAsText();
372
373     return String();
374 }
375
376 Ref<DOMRectList> Page::nonFastScrollableRects()
377 {
378     if (Document* document = m_mainFrame->document())
379         document->updateLayout();
380
381     Vector<IntRect> rects;
382     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
383         const EventTrackingRegions& eventTrackingRegions = scrollingCoordinator->absoluteEventTrackingRegions();
384         for (const auto& synchronousEventRegion : eventTrackingRegions.eventSpecificSynchronousDispatchRegions)
385             rects.appendVector(synchronousEventRegion.value.rects());
386     }
387
388     Vector<FloatQuad> quads(rects.size());
389     for (size_t i = 0; i < rects.size(); ++i)
390         quads[i] = FloatRect(rects[i]);
391
392     return DOMRectList::create(quads);
393 }
394
395 Ref<DOMRectList> Page::touchEventRectsForEvent(const String& eventName)
396 {
397     if (Document* document = m_mainFrame->document()) {
398         document->updateLayout();
399 #if ENABLE(IOS_TOUCH_EVENTS)
400         document->updateTouchEventRegions();
401 #endif
402     }
403
404     Vector<IntRect> rects;
405     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
406         const EventTrackingRegions& eventTrackingRegions = scrollingCoordinator->absoluteEventTrackingRegions();
407         const auto& region = eventTrackingRegions.eventSpecificSynchronousDispatchRegions.get(eventName);
408         rects.appendVector(region.rects());
409     }
410
411     Vector<FloatQuad> quads(rects.size());
412     for (size_t i = 0; i < rects.size(); ++i)
413         quads[i] = FloatRect(rects[i]);
414
415     return DOMRectList::create(quads);
416 }
417
418 Ref<DOMRectList> Page::passiveTouchEventListenerRects()
419 {
420     if (Document* document = m_mainFrame->document()) {
421         document->updateLayout();
422 #if ENABLE(IOS_TOUCH_EVENTS)
423         document->updateTouchEventRegions();
424 #endif  
425     }
426
427     Vector<IntRect> rects;
428     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
429         rects.appendVector(scrollingCoordinator->absoluteEventTrackingRegions().asynchronousDispatchRegion.rects());
430
431     Vector<FloatQuad> quads(rects.size());
432     for (size_t i = 0; i < rects.size(); ++i)
433         quads[i] = FloatRect(rects[i]);
434
435     return DOMRectList::create(quads);
436 }
437
438 #if ENABLE(VIEW_MODE_CSS_MEDIA)
439 struct ViewModeInfo {
440     const char* name;
441     Page::ViewMode type;
442 };
443 static const int viewModeMapSize = 5;
444 static const ViewModeInfo viewModeMap[viewModeMapSize] = {
445     {"windowed", Page::ViewModeWindowed},
446     {"floating", Page::ViewModeFloating},
447     {"fullscreen", Page::ViewModeFullscreen},
448     {"maximized", Page::ViewModeMaximized},
449     {"minimized", Page::ViewModeMinimized}
450 };
451
452 Page::ViewMode Page::stringToViewMode(const String& text)
453 {
454     for (auto& mode : viewModeMap) {
455         if (text == mode.name)
456             return mode.type;
457     }
458     return Page::ViewModeInvalid;
459 }
460
461 void Page::setViewMode(ViewMode viewMode)
462 {
463     if (viewMode == m_viewMode || viewMode == ViewModeInvalid)
464         return;
465
466     m_viewMode = viewMode;
467
468
469     if (m_mainFrame->view())
470         m_mainFrame->view()->forceLayout();
471
472     if (m_mainFrame->document())
473         m_mainFrame->document()->styleScope().didChangeStyleSheetEnvironment();
474 }
475 #endif // ENABLE(VIEW_MODE_CSS_MEDIA)
476
477 bool Page::openedByDOM() const
478 {
479     return m_openedByDOM;
480 }
481
482 void Page::setOpenedByDOM()
483 {
484     m_openedByDOM = true;
485 }
486
487 void Page::goToItem(HistoryItem& item, FrameLoadType type)
488 {
489     // stopAllLoaders may end up running onload handlers, which could cause further history traversals that may lead to the passed in HistoryItem
490     // being deref()-ed. Make sure we can still use it with HistoryController::goToItem later.
491     Ref<HistoryItem> protector(item);
492
493     if (m_mainFrame->loader().history().shouldStopLoadingForHistoryItem(item))
494         m_mainFrame->loader().stopAllLoaders();
495
496     m_mainFrame->loader().history().goToItem(item, type);
497 }
498
499 void Page::setGroupName(const String& name)
500 {
501     if (m_group && !m_group->name().isEmpty()) {
502         ASSERT(m_group != m_singlePageGroup.get());
503         ASSERT(!m_singlePageGroup);
504         m_group->removePage(*this);
505     }
506
507     if (name.isEmpty())
508         m_group = m_singlePageGroup.get();
509     else {
510         m_singlePageGroup = nullptr;
511         m_group = PageGroup::pageGroup(name);
512         m_group->addPage(*this);
513     }
514 }
515
516 const String& Page::groupName() const
517 {
518     return m_group ? m_group->name() : nullAtom().string();
519 }
520
521 void Page::initGroup()
522 {
523     ASSERT(!m_singlePageGroup);
524     ASSERT(!m_group);
525     m_singlePageGroup = std::make_unique<PageGroup>(*this);
526     m_group = m_singlePageGroup.get();
527 }
528
529 void Page::updateStyleForAllPagesAfterGlobalChangeInEnvironment()
530 {
531     for (auto* page : allPages()) {
532         for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
533             // If a change in the global environment has occurred, we need to
534             // make sure all the properties a recomputed, therefore we invalidate
535             // the properties cache.
536             if (!frame->document())
537                 continue;
538             if (StyleResolver* styleResolver = frame->document()->styleScope().resolverIfExists())
539                 styleResolver->invalidateMatchedPropertiesCache();
540             frame->document()->scheduleForcedStyleRecalc();
541         }
542     }
543 }
544
545 void Page::setNeedsRecalcStyleInAllFrames()
546 {
547     // FIXME: Figure out what this function is actually trying to add in different call sites.
548     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
549         if (Document* document = frame->document())
550             document->styleScope().didChangeStyleSheetEnvironment();
551     }
552 }
553
554 void Page::refreshPlugins(bool reload)
555 {
556     HashSet<PluginInfoProvider*> pluginInfoProviders;
557
558     for (auto* page : allPages())
559         pluginInfoProviders.add(&page->pluginInfoProvider());
560
561     for (auto& pluginInfoProvider : pluginInfoProviders)
562         pluginInfoProvider->refresh(reload);
563 }
564
565 PluginData& Page::pluginData()
566 {
567     if (!m_pluginData)
568         m_pluginData = PluginData::create(*this);
569     return *m_pluginData;
570 }
571
572 void Page::clearPluginData()
573 {
574     m_pluginData = nullptr;
575 }
576
577 bool Page::showAllPlugins() const
578 {
579     if (m_showAllPlugins)
580         return true;
581
582     if (Document* document = mainFrame().document())
583         return document->securityOrigin().isLocal();
584
585     return false;
586 }
587
588 inline std::optional<std::pair<MediaCanStartListener&, Document&>>  Page::takeAnyMediaCanStartListener()
589 {
590     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
591         if (!frame->document())
592             continue;
593         if (MediaCanStartListener* listener = frame->document()->takeAnyMediaCanStartListener())
594             return { { *listener, *frame->document() } };
595     }
596     return std::nullopt;
597 }
598
599 void Page::setCanStartMedia(bool canStartMedia)
600 {
601     if (m_canStartMedia == canStartMedia)
602         return;
603
604     m_canStartMedia = canStartMedia;
605
606     while (m_canStartMedia) {
607         auto listener = takeAnyMediaCanStartListener();
608         if (!listener)
609             break;
610         listener->first.mediaCanStart(listener->second);
611     }
612 }
613
614 static Frame* incrementFrame(Frame* curr, bool forward, CanWrap canWrap, DidWrap* didWrap = nullptr)
615 {
616     return forward
617         ? curr->tree().traverseNext(canWrap, didWrap)
618         : curr->tree().traversePrevious(canWrap, didWrap);
619 }
620
621 bool Page::findString(const String& target, FindOptions options, DidWrap* didWrap)
622 {
623     if (target.isEmpty())
624         return false;
625
626     CanWrap canWrap = options & WrapAround ? CanWrap::Yes : CanWrap::No;
627     Frame* frame = &focusController().focusedOrMainFrame();
628     Frame* startFrame = frame;
629     do {
630         if (frame->editor().findString(target, (options & ~WrapAround) | StartInSelection)) {
631             if (frame != startFrame)
632                 startFrame->selection().clear();
633             focusController().setFocusedFrame(frame);
634             return true;
635         }
636         frame = incrementFrame(frame, !(options & Backwards), canWrap, didWrap);
637     } while (frame && frame != startFrame);
638
639     // Search contents of startFrame, on the other side of the selection that we did earlier.
640     // We cheat a bit and just research with wrap on
641     if (canWrap == CanWrap::Yes && !startFrame->selection().isNone()) {
642         if (didWrap)
643             *didWrap = DidWrap::Yes;
644         bool found = startFrame->editor().findString(target, options | WrapAround | StartInSelection);
645         focusController().setFocusedFrame(frame);
646         return found;
647     }
648
649     return false;
650 }
651
652 void Page::findStringMatchingRanges(const String& target, FindOptions options, int limit, Vector<RefPtr<Range>>& matchRanges, int& indexForSelection)
653 {
654     indexForSelection = 0;
655
656     Frame* frame = &mainFrame();
657     Frame* frameWithSelection = nullptr;
658     do {
659         frame->editor().countMatchesForText(target, 0, options, limit ? (limit - matchRanges.size()) : 0, true, &matchRanges);
660         if (frame->selection().isRange())
661             frameWithSelection = frame;
662         frame = incrementFrame(frame, true, CanWrap::No);
663     } while (frame);
664
665     if (matchRanges.isEmpty())
666         return;
667
668     if (frameWithSelection) {
669         indexForSelection = NoMatchAfterUserSelection;
670         RefPtr<Range> selectedRange = frameWithSelection->selection().selection().firstRange();
671         if (options & Backwards) {
672             for (size_t i = matchRanges.size(); i > 0; --i) {
673                 auto result = selectedRange->compareBoundaryPoints(Range::END_TO_START, *matchRanges[i - 1]);
674                 if (!result.hasException() && result.releaseReturnValue() > 0) {
675                     indexForSelection = i - 1;
676                     break;
677                 }
678             }
679         } else {
680             for (size_t i = 0, size = matchRanges.size(); i < size; ++i) {
681                 auto result = selectedRange->compareBoundaryPoints(Range::START_TO_END, *matchRanges[i]);
682                 if (!result.hasException() && result.releaseReturnValue() < 0) {
683                     indexForSelection = i;
684                     break;
685                 }
686             }
687         }
688     } else {
689         if (options & Backwards)
690             indexForSelection = matchRanges.size() - 1;
691         else
692             indexForSelection = 0;
693     }
694 }
695
696 RefPtr<Range> Page::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
697 {
698     if (target.isEmpty())
699         return nullptr;
700
701     if (referenceRange && referenceRange->ownerDocument().page() != this)
702         return nullptr;
703
704     CanWrap canWrap = options & WrapAround ? CanWrap::Yes : CanWrap::No;
705     Frame* frame = referenceRange ? referenceRange->ownerDocument().frame() : &mainFrame();
706     Frame* startFrame = frame;
707     do {
708         if (RefPtr<Range> resultRange = frame->editor().rangeOfString(target, frame == startFrame ? referenceRange : 0, options & ~WrapAround))
709             return resultRange;
710
711         frame = incrementFrame(frame, !(options & Backwards), canWrap);
712     } while (frame && frame != startFrame);
713
714     // Search contents of startFrame, on the other side of the reference range that we did earlier.
715     // We cheat a bit and just search again with wrap on.
716     if (canWrap == CanWrap::Yes && referenceRange) {
717         if (RefPtr<Range> resultRange = startFrame->editor().rangeOfString(target, referenceRange, options | WrapAround | StartInSelection))
718             return resultRange;
719     }
720
721     return nullptr;
722 }
723
724 unsigned Page::findMatchesForText(const String& target, FindOptions options, unsigned maxMatchCount, ShouldHighlightMatches shouldHighlightMatches, ShouldMarkMatches shouldMarkMatches)
725 {
726     if (target.isEmpty())
727         return 0;
728
729     unsigned matchCount = 0;
730
731     Frame* frame = &mainFrame();
732     do {
733         if (shouldMarkMatches == MarkMatches)
734             frame->editor().setMarkedTextMatchesAreHighlighted(shouldHighlightMatches == HighlightMatches);
735         matchCount += frame->editor().countMatchesForText(target, 0, options, maxMatchCount ? (maxMatchCount - matchCount) : 0, shouldMarkMatches == MarkMatches, 0);
736         frame = incrementFrame(frame, true, CanWrap::No);
737     } while (frame);
738
739     return matchCount;
740 }
741
742 unsigned Page::markAllMatchesForText(const String& target, FindOptions options, bool shouldHighlight, unsigned maxMatchCount)
743 {
744     return findMatchesForText(target, options, maxMatchCount, shouldHighlight ? HighlightMatches : DoNotHighlightMatches, MarkMatches);
745 }
746
747 unsigned Page::countFindMatches(const String& target, FindOptions options, unsigned maxMatchCount)
748 {
749     return findMatchesForText(target, options, maxMatchCount, DoNotHighlightMatches, DoNotMarkMatches);
750 }
751
752 void Page::unmarkAllTextMatches()
753 {
754     Frame* frame = &mainFrame();
755     do {
756         frame->document()->markers().removeMarkers(DocumentMarker::TextMatch);
757         frame = incrementFrame(frame, true, CanWrap::No);
758     } while (frame);
759 }
760
761 const VisibleSelection& Page::selection() const
762 {
763     return focusController().focusedOrMainFrame().selection().selection();
764 }
765
766 void Page::setDefersLoading(bool defers)
767 {
768     if (!m_settings->loadDeferringEnabled())
769         return;
770
771     if (m_settings->wantsBalancedSetDefersLoadingBehavior()) {
772         ASSERT(defers || m_defersLoadingCallCount);
773         if (defers && ++m_defersLoadingCallCount > 1)
774             return;
775         if (!defers && --m_defersLoadingCallCount)
776             return;
777     } else {
778         ASSERT(!m_defersLoadingCallCount);
779         if (defers == m_defersLoading)
780             return;
781     }
782
783     m_defersLoading = defers;
784     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
785         frame->loader().setDefersLoading(defers);
786 }
787
788 void Page::clearUndoRedoOperations()
789 {
790     m_editorClient->clearUndoRedoOperations();
791 }
792
793 bool Page::inLowQualityImageInterpolationMode() const
794 {
795     return m_inLowQualityInterpolationMode;
796 }
797
798 void Page::setInLowQualityImageInterpolationMode(bool mode)
799 {
800     m_inLowQualityInterpolationMode = mode;
801 }
802
803 DiagnosticLoggingClient& Page::diagnosticLoggingClient() const
804 {
805     if (!settings().diagnosticLoggingEnabled() || !m_diagnosticLoggingClient)
806         return emptyDiagnosticLoggingClient();
807     return *m_diagnosticLoggingClient;
808 }
809
810 void Page::setMediaVolume(float volume)
811 {
812     if (volume < 0 || volume > 1)
813         return;
814
815     if (m_mediaVolume == volume)
816         return;
817
818     m_mediaVolume = volume;
819     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
820         if (!frame->document())
821             continue;
822         frame->document()->mediaVolumeDidChange();
823     }
824 }
825
826 void Page::setZoomedOutPageScaleFactor(float scale)
827 {
828     if (m_zoomedOutPageScaleFactor == scale)
829         return;
830     m_zoomedOutPageScaleFactor = scale;
831
832     mainFrame().deviceOrPageScaleFactorChanged();
833 }
834
835 void Page::setPageScaleFactor(float scale, const IntPoint& origin, bool inStableState)
836 {
837     Document* document = mainFrame().document();
838     FrameView* view = document->view();
839
840     if (scale == m_pageScaleFactor) {
841         if (view && view->scrollPosition() != origin) {
842             if (!m_settings->delegatesPageScaling())
843                 document->updateLayoutIgnorePendingStylesheets();
844
845             if (!view->delegatesScrolling())
846                 view->setScrollPosition(origin);
847 #if USE(COORDINATED_GRAPHICS)
848             else
849                 view->requestScrollPositionUpdate(origin);
850 #endif
851         }
852 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
853         if (inStableState) {
854             for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
855                 if (!frame->document())
856                     continue;
857                 frame->document()->pageScaleFactorChangedAndStable();
858             }
859         }
860 #endif
861         return;
862     }
863
864     m_pageScaleFactor = scale;
865
866     if (!m_settings->delegatesPageScaling()) {
867         if (document->renderView())
868             document->renderView()->setNeedsLayout();
869
870         document->resolveStyle(Document::ResolveStyleType::Rebuild);
871
872         // Transform change on RenderView doesn't trigger repaint on non-composited contents.
873         mainFrame().view()->invalidateRect(IntRect(LayoutRect::infiniteRect()));
874     }
875
876     mainFrame().deviceOrPageScaleFactorChanged();
877
878     if (view && view->fixedElementsLayoutRelativeToFrame())
879         view->setViewportConstrainedObjectsNeedLayout();
880
881     if (view && view->scrollPosition() != origin) {
882         if (!m_settings->delegatesPageScaling() && document->renderView() && document->renderView()->needsLayout() && view->didFirstLayout())
883             view->layout();
884
885         if (!view->delegatesScrolling())
886             view->setScrollPosition(origin);
887 #if USE(COORDINATED_GRAPHICS)
888         else
889             view->requestScrollPositionUpdate(origin);
890 #endif
891     }
892
893 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
894     if (inStableState) {
895         for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
896             if (!frame->document())
897                 continue;
898             frame->document()->pageScaleFactorChangedAndStable();
899         }
900     }
901 #else
902     UNUSED_PARAM(inStableState);
903 #endif
904 }
905
906 void Page::setViewScaleFactor(float scale)
907 {
908     if (m_viewScaleFactor == scale)
909         return;
910
911     m_viewScaleFactor = scale;
912     PageCache::singleton().markPagesForDeviceOrPageScaleChanged(*this);
913 }
914
915 void Page::setDeviceScaleFactor(float scaleFactor)
916 {
917     ASSERT(scaleFactor > 0);
918     if (scaleFactor <= 0)
919         return;
920     
921     if (m_deviceScaleFactor == scaleFactor)
922         return;
923
924     m_deviceScaleFactor = scaleFactor;
925     setNeedsRecalcStyleInAllFrames();
926
927     mainFrame().deviceOrPageScaleFactorChanged();
928     PageCache::singleton().markPagesForDeviceOrPageScaleChanged(*this);
929
930     GraphicsContext::updateDocumentMarkerResources();
931
932     mainFrame().pageOverlayController().didChangeDeviceScaleFactor();
933 }
934
935 void Page::setUserInterfaceLayoutDirection(UserInterfaceLayoutDirection userInterfaceLayoutDirection)
936 {
937     if (m_userInterfaceLayoutDirection == userInterfaceLayoutDirection)
938         return;
939
940     m_userInterfaceLayoutDirection = userInterfaceLayoutDirection;
941 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
942     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
943         if (!frame->document())
944             continue;
945         frame->document()->userInterfaceLayoutDirectionChanged();
946     }
947 #endif
948 }
949
950 #if ENABLE(VIDEO)
951 void Page::updateMediaElementRateChangeRestrictions()
952 {
953     for (auto* mediaElement : HTMLMediaElement::allMediaElements())
954         mediaElement->updateRateChangeRestrictions();
955 }
956 #endif
957
958 void Page::didStartProvisionalLoad()
959 {
960     if (m_performanceMonitor)
961         m_performanceMonitor->didStartProvisionalLoad();
962 }
963
964 void Page::didFinishLoad()
965 {
966     resetRelevantPaintedObjectCounter();
967
968     if (m_performanceMonitor)
969         m_performanceMonitor->didFinishLoad();
970 }
971
972 bool Page::isOnlyNonUtilityPage() const
973 {
974     return !isUtilityPage() && nonUtilityPageCount == 1;
975 }
976
977 bool Page::isLowPowerModeEnabled() const
978 {
979     if (m_lowPowerModeEnabledOverrideForTesting)
980         return m_lowPowerModeEnabledOverrideForTesting.value();
981
982     return m_lowPowerModeNotifier->isLowPowerModeEnabled();
983 }
984
985 void Page::setLowPowerModeEnabledOverrideForTesting(std::optional<bool> isEnabled)
986 {
987     m_lowPowerModeEnabledOverrideForTesting = isEnabled;
988     handleLowModePowerChange(m_lowPowerModeEnabledOverrideForTesting.value_or(false));
989 }
990
991 void Page::setTopContentInset(float contentInset)
992 {
993     if (m_topContentInset == contentInset)
994         return;
995     
996     m_topContentInset = contentInset;
997     
998     if (FrameView* view = mainFrame().view())
999         view->topContentInsetDidChange(m_topContentInset);
1000 }
1001
1002 void Page::setShouldSuppressScrollbarAnimations(bool suppressAnimations)
1003 {
1004     if (suppressAnimations == m_suppressScrollbarAnimations)
1005         return;
1006
1007     lockAllOverlayScrollbarsToHidden(suppressAnimations);
1008     m_suppressScrollbarAnimations = suppressAnimations;
1009 }
1010
1011 void Page::lockAllOverlayScrollbarsToHidden(bool lockOverlayScrollbars)
1012 {
1013     FrameView* view = mainFrame().view();
1014     if (!view)
1015         return;
1016
1017     view->lockOverlayScrollbarStateToHidden(lockOverlayScrollbars);
1018     
1019     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1020         FrameView* frameView = frame->view();
1021         if (!frameView)
1022             continue;
1023
1024         const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas();
1025         if (!scrollableAreas)
1026             continue;
1027
1028         for (auto& scrollableArea : *scrollableAreas)
1029             scrollableArea->lockOverlayScrollbarStateToHidden(lockOverlayScrollbars);
1030     }
1031 }
1032     
1033 void Page::setVerticalScrollElasticity(ScrollElasticity elasticity)
1034 {
1035     if (m_verticalScrollElasticity == elasticity)
1036         return;
1037     
1038     m_verticalScrollElasticity = elasticity;
1039     
1040     if (FrameView* view = mainFrame().view())
1041         view->setVerticalScrollElasticity(elasticity);
1042 }
1043     
1044 void Page::setHorizontalScrollElasticity(ScrollElasticity elasticity)
1045 {
1046     if (m_horizontalScrollElasticity == elasticity)
1047         return;
1048     
1049     m_horizontalScrollElasticity = elasticity;
1050     
1051     if (FrameView* view = mainFrame().view())
1052         view->setHorizontalScrollElasticity(elasticity);
1053 }
1054
1055 void Page::setPagination(const Pagination& pagination)
1056 {
1057     if (m_pagination == pagination)
1058         return;
1059
1060     m_pagination = pagination;
1061
1062     setNeedsRecalcStyleInAllFrames();
1063 }
1064
1065 void Page::setPaginationLineGridEnabled(bool enabled)
1066 {
1067     if (m_paginationLineGridEnabled == enabled)
1068         return;
1069     
1070     m_paginationLineGridEnabled = enabled;
1071     
1072     setNeedsRecalcStyleInAllFrames();
1073 }
1074
1075 unsigned Page::pageCount() const
1076 {
1077     if (m_pagination.mode == Pagination::Unpaginated)
1078         return 0;
1079
1080     if (Document* document = mainFrame().document())
1081         document->updateLayoutIgnorePendingStylesheets();
1082
1083     RenderView* contentRenderer = mainFrame().contentRenderer();
1084     return contentRenderer ? contentRenderer->pageCount() : 0;
1085 }
1086
1087 void Page::setIsInWindow(bool isInWindow)
1088 {
1089     setActivityState(isInWindow ? m_activityState | ActivityState::IsInWindow : m_activityState & ~ActivityState::IsInWindow);
1090 }
1091
1092 void Page::setIsInWindowInternal(bool isInWindow)
1093 {
1094     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1095         if (FrameView* frameView = frame->view())
1096             frameView->setIsInWindow(isInWindow);
1097     }
1098
1099     if (isInWindow)
1100         resumeAnimatingImages();
1101 }
1102
1103 void Page::addActivityStateChangeObserver(ActivityStateChangeObserver& observer)
1104 {
1105     m_activityStateChangeObservers.add(&observer);
1106 }
1107
1108 void Page::removeActivityStateChangeObserver(ActivityStateChangeObserver& observer)
1109 {
1110     m_activityStateChangeObservers.remove(&observer);
1111 }
1112
1113 void Page::suspendScriptedAnimations()
1114 {
1115     m_scriptedAnimationsSuspended = true;
1116     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1117         if (frame->document())
1118             frame->document()->suspendScriptedAnimationControllerCallbacks();
1119     }
1120 }
1121
1122 void Page::resumeScriptedAnimations()
1123 {
1124     m_scriptedAnimationsSuspended = false;
1125     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1126         if (frame->document())
1127             frame->document()->resumeScriptedAnimationControllerCallbacks();
1128     }
1129 }
1130
1131 enum class ThrottlingReasonOperation { Add, Remove };
1132 static void updateScriptedAnimationsThrottlingReason(Page& page, ThrottlingReasonOperation operation, ScriptedAnimationController::ThrottlingReason reason)
1133 {
1134     for (Frame* frame = &page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
1135         auto* document = frame->document();
1136         if (!document)
1137             continue;
1138         auto* scriptedAnimationController = document->scriptedAnimationController();
1139         if (!scriptedAnimationController)
1140             continue;
1141
1142         if (operation == ThrottlingReasonOperation::Add)
1143             scriptedAnimationController->addThrottlingReason(reason);
1144         else
1145             scriptedAnimationController->removeThrottlingReason(reason);
1146     }
1147 }
1148
1149 void Page::setIsVisuallyIdleInternal(bool isVisuallyIdle)
1150 {
1151     updateScriptedAnimationsThrottlingReason(*this, isVisuallyIdle ? ThrottlingReasonOperation::Add : ThrottlingReasonOperation::Remove, ScriptedAnimationController::ThrottlingReason::VisuallyIdle);
1152 }
1153
1154 void Page::handleLowModePowerChange(bool isLowPowerModeEnabled)
1155 {
1156     updateScriptedAnimationsThrottlingReason(*this, isLowPowerModeEnabled ? ThrottlingReasonOperation::Add : ThrottlingReasonOperation::Remove, ScriptedAnimationController::ThrottlingReason::LowPowerMode);
1157     mainFrame().animation().updateThrottlingState();
1158     updateDOMTimerAlignmentInterval();
1159 }
1160
1161 void Page::userStyleSheetLocationChanged()
1162 {
1163     // FIXME: Eventually we will move to a model of just being handed the sheet
1164     // text instead of loading the URL ourselves.
1165     URL url = m_settings->userStyleSheetLocation();
1166     
1167     // Allow any local file URL scheme to be loaded.
1168     if (SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol().toStringWithoutCopying()))
1169         m_userStyleSheetPath = url.fileSystemPath();
1170     else
1171         m_userStyleSheetPath = String();
1172
1173     m_didLoadUserStyleSheet = false;
1174     m_userStyleSheet = String();
1175     m_userStyleSheetModificationTime = 0;
1176
1177     // Data URLs with base64-encoded UTF-8 style sheets are common. We can process them
1178     // synchronously and avoid using a loader. 
1179     if (url.protocolIsData() && url.string().startsWith("data:text/css;charset=utf-8;base64,")) {
1180         m_didLoadUserStyleSheet = true;
1181
1182         Vector<char> styleSheetAsUTF8;
1183         if (base64Decode(decodeURLEscapeSequences(url.string().substring(35)), styleSheetAsUTF8, Base64IgnoreSpacesAndNewLines))
1184             m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size());
1185     }
1186
1187     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1188         if (frame->document())
1189             frame->document()->extensionStyleSheets().updatePageUserSheet();
1190     }
1191 }
1192
1193 const String& Page::userStyleSheet() const
1194 {
1195     if (m_userStyleSheetPath.isEmpty())
1196         return m_userStyleSheet;
1197
1198     time_t modTime;
1199     if (!getFileModificationTime(m_userStyleSheetPath, modTime)) {
1200         // The stylesheet either doesn't exist, was just deleted, or is
1201         // otherwise unreadable. If we've read the stylesheet before, we should
1202         // throw away that data now as it no longer represents what's on disk.
1203         m_userStyleSheet = String();
1204         return m_userStyleSheet;
1205     }
1206
1207     // If the stylesheet hasn't changed since the last time we read it, we can
1208     // just return the old data.
1209     if (m_didLoadUserStyleSheet && modTime <= m_userStyleSheetModificationTime)
1210         return m_userStyleSheet;
1211
1212     m_didLoadUserStyleSheet = true;
1213     m_userStyleSheet = String();
1214     m_userStyleSheetModificationTime = modTime;
1215
1216     // FIXME: It would be better to load this asynchronously to avoid blocking
1217     // the process, but we will first need to create an asynchronous loading
1218     // mechanism that is not tied to a particular Frame. We will also have to
1219     // determine what our behavior should be before the stylesheet is loaded
1220     // and what should happen when it finishes loading, especially with respect
1221     // to when the load event fires, when Document::close is called, and when
1222     // layout/paint are allowed to happen.
1223     RefPtr<SharedBuffer> data = SharedBuffer::createWithContentsOfFile(m_userStyleSheetPath);
1224     if (!data)
1225         return m_userStyleSheet;
1226
1227     m_userStyleSheet = TextResourceDecoder::create("text/css")->decodeAndFlush(data->data(), data->size());
1228
1229     return m_userStyleSheet;
1230 }
1231
1232 void Page::invalidateStylesForAllLinks()
1233 {
1234     for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
1235         if (!frame->document())
1236             continue;
1237         frame->document()->visitedLinkState().invalidateStyleForAllLinks();
1238     }
1239 }
1240
1241 void Page::invalidateStylesForLink(LinkHash linkHash)
1242 {
1243     for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
1244         if (!frame->document())
1245             continue;
1246         frame->document()->visitedLinkState().invalidateStyleForLink(linkHash);
1247     }
1248 }
1249
1250 void Page::invalidateInjectedStyleSheetCacheInAllFrames()
1251 {
1252     for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
1253         Document* document = frame->document();
1254         if (!document)
1255             continue;
1256         document->extensionStyleSheets().invalidateInjectedStyleSheetCache();
1257     }
1258 }
1259
1260 void Page::setDebugger(JSC::Debugger* debugger)
1261 {
1262     if (m_debugger == debugger)
1263         return;
1264
1265     m_debugger = debugger;
1266
1267     for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
1268         frame->script().attachDebugger(m_debugger);
1269 }
1270
1271 StorageNamespace* Page::sessionStorage(bool optionalCreate)
1272 {
1273     if (!m_sessionStorage && optionalCreate)
1274         m_sessionStorage = m_storageNamespaceProvider->createSessionStorageNamespace(*this, m_settings->sessionStorageQuota());
1275
1276     return m_sessionStorage.get();
1277 }
1278
1279 void Page::setSessionStorage(RefPtr<StorageNamespace>&& newStorage)
1280 {
1281     m_sessionStorage = WTFMove(newStorage);
1282 }
1283
1284 StorageNamespace* Page::ephemeralLocalStorage(bool optionalCreate)
1285 {
1286     if (!m_ephemeralLocalStorage && optionalCreate)
1287         m_ephemeralLocalStorage = m_storageNamespaceProvider->createEphemeralLocalStorageNamespace(*this, m_settings->sessionStorageQuota());
1288
1289     return m_ephemeralLocalStorage.get();
1290 }
1291
1292 void Page::setEphemeralLocalStorage(RefPtr<StorageNamespace>&& newStorage)
1293 {
1294     m_ephemeralLocalStorage = WTFMove(newStorage);
1295 }
1296
1297 bool Page::hasCustomHTMLTokenizerTimeDelay() const
1298 {
1299     return m_settings->maxParseDuration() != -1;
1300 }
1301
1302 double Page::customHTMLTokenizerTimeDelay() const
1303 {
1304     ASSERT(m_settings->maxParseDuration() != -1);
1305     return m_settings->maxParseDuration();
1306 }
1307
1308 void Page::setMemoryCacheClientCallsEnabled(bool enabled)
1309 {
1310     if (m_areMemoryCacheClientCallsEnabled == enabled)
1311         return;
1312
1313     m_areMemoryCacheClientCallsEnabled = enabled;
1314     if (!enabled)
1315         return;
1316
1317     for (RefPtr<Frame> frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1318         frame->loader().tellClientAboutPastMemoryCacheLoads();
1319 }
1320
1321 void Page::hiddenPageDOMTimerThrottlingStateChanged()
1322 {
1323     // Disable & reengage to ensure state is updated.
1324     setTimerThrottlingState(TimerThrottlingState::Disabled);
1325     updateTimerThrottlingState();
1326 }
1327
1328 void Page::updateTimerThrottlingState()
1329 {
1330     // Timer throttling disabled if page is visually active, or disabled by setting.
1331     if (!m_settings->hiddenPageDOMTimerThrottlingEnabled() || !(m_activityState & ActivityState::IsVisuallyIdle)) {
1332         setTimerThrottlingState(TimerThrottlingState::Disabled);
1333         return;
1334     }
1335
1336     // If the page is visible (but idle), there is any activity (loading, media playing, etc), or per setting,
1337     // we allow timer throttling, but not increasing timer throttling.
1338     if (!m_settings->hiddenPageDOMTimerThrottlingAutoIncreases()
1339         || m_activityState & (ActivityState::IsVisible | ActivityState::IsAudible | ActivityState::IsLoading | ActivityState::IsCapturingMedia)) {
1340         setTimerThrottlingState(TimerThrottlingState::Enabled);
1341         return;
1342     }
1343
1344     // If we get here increasing timer throttling is enabled.
1345     setTimerThrottlingState(TimerThrottlingState::EnabledIncreasing);
1346 }
1347
1348 void Page::setTimerThrottlingState(TimerThrottlingState state)
1349 {
1350     if (state == m_timerThrottlingState)
1351         return;
1352
1353     m_timerThrottlingState = state;
1354     m_timerThrottlingStateLastChangedTime = MonotonicTime::now();
1355
1356     updateDOMTimerAlignmentInterval();
1357
1358     // When throttling is disabled, release all throttled timers.
1359     if (state == TimerThrottlingState::Disabled) {
1360         for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1361             if (auto* document = frame->document())
1362                 document->didChangeTimerAlignmentInterval();
1363         }
1364     }
1365 }
1366
1367 void Page::setDOMTimerAlignmentIntervalIncreaseLimit(Seconds limit)
1368 {
1369     m_domTimerAlignmentIntervalIncreaseLimit = limit;
1370
1371     // If (m_domTimerAlignmentIntervalIncreaseLimit < m_domTimerAlignmentInterval) then we need
1372     // to update m_domTimerAlignmentInterval, if greater then need to restart the increase timer.
1373     if (m_timerThrottlingState == TimerThrottlingState::EnabledIncreasing)
1374         updateDOMTimerAlignmentInterval();
1375 }
1376
1377 void Page::updateDOMTimerAlignmentInterval()
1378 {
1379     bool needsIncreaseTimer = false;
1380
1381     switch (m_timerThrottlingState) {
1382     case TimerThrottlingState::Disabled:
1383         m_domTimerAlignmentInterval = isLowPowerModeEnabled() ? DOMTimer::defaultAlignmentIntervalInLowPowerMode() : DOMTimer::defaultAlignmentInterval();
1384         break;
1385
1386     case TimerThrottlingState::Enabled:
1387         m_domTimerAlignmentInterval = DOMTimer::hiddenPageAlignmentInterval();
1388         break;
1389
1390     case TimerThrottlingState::EnabledIncreasing:
1391         // For pages in prerender state maximum throttling kicks in immediately.
1392         if (m_isPrerender)
1393             m_domTimerAlignmentInterval = m_domTimerAlignmentIntervalIncreaseLimit;
1394         else {
1395             ASSERT(!!m_timerThrottlingStateLastChangedTime);
1396             m_domTimerAlignmentInterval = MonotonicTime::now() - m_timerThrottlingStateLastChangedTime;
1397             // If we're below the limit, set the timer. If above, clamp to limit.
1398             if (m_domTimerAlignmentInterval < m_domTimerAlignmentIntervalIncreaseLimit)
1399                 needsIncreaseTimer = true;
1400             else
1401                 m_domTimerAlignmentInterval = m_domTimerAlignmentIntervalIncreaseLimit;
1402         }
1403         // Alignment interval should not be less than DOMTimer::hiddenPageAlignmentInterval().
1404         m_domTimerAlignmentInterval = std::max(m_domTimerAlignmentInterval, DOMTimer::hiddenPageAlignmentInterval());
1405     }
1406
1407     // If throttling is enabled, auto-increasing of throttling is enabled, and the auto-increase
1408     // limit has not yet been reached, and then arm the timer to consider an increase. Time to wait
1409     // between increases is equal to the current throttle time. Since alinment interval increases
1410     // exponentially, time between steps is exponential too.
1411     if (!needsIncreaseTimer)
1412         m_domTimerAlignmentIntervalIncreaseTimer.stop();
1413     else if (!m_domTimerAlignmentIntervalIncreaseTimer.isActive())
1414         m_domTimerAlignmentIntervalIncreaseTimer.startOneShot(m_domTimerAlignmentInterval);
1415 }
1416
1417 void Page::domTimerAlignmentIntervalIncreaseTimerFired()
1418 {
1419     ASSERT(m_settings->hiddenPageDOMTimerThrottlingAutoIncreases());
1420     ASSERT(m_timerThrottlingState == TimerThrottlingState::EnabledIncreasing);
1421     ASSERT(m_domTimerAlignmentInterval < m_domTimerAlignmentIntervalIncreaseLimit);
1422     
1423     // Alignment interval is increased to equal the time the page has been throttled, to a limit.
1424     updateDOMTimerAlignmentInterval();
1425 }
1426
1427 void Page::dnsPrefetchingStateChanged()
1428 {
1429     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1430         if (!frame->document())
1431             continue;
1432         frame->document()->initDNSPrefetch();
1433     }
1434 }
1435
1436 Vector<Ref<PluginViewBase>> Page::pluginViews()
1437 {
1438     Vector<Ref<PluginViewBase>> views;
1439     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1440         auto* view = frame->view();
1441         if (!view)
1442             break;
1443         for (auto& widget : view->children()) {
1444             if (is<PluginViewBase>(widget.get()))
1445                 views.append(downcast<PluginViewBase>(widget.get()));
1446         }
1447     }
1448     return views;
1449 }
1450
1451 void Page::storageBlockingStateChanged()
1452 {
1453     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1454         if (!frame->document())
1455             continue;
1456         frame->document()->storageBlockingStateDidChange();
1457     }
1458
1459     // Collect the PluginViews in to a vector to ensure that action the plug-in takes
1460     // from below storageBlockingStateChanged does not affect their lifetime.
1461     for (auto& view : pluginViews())
1462         view->storageBlockingStateChanged();
1463 }
1464
1465 void Page::enableLegacyPrivateBrowsing(bool privateBrowsingEnabled)
1466 {
1467     // Don't allow changing the legacy private browsing state if we have set a session ID.
1468     ASSERT(m_sessionID == SessionID::defaultSessionID() || m_sessionID == SessionID::legacyPrivateSessionID());
1469
1470     setSessionID(privateBrowsingEnabled ? SessionID::legacyPrivateSessionID() : SessionID::defaultSessionID());
1471 }
1472
1473 void Page::updateIsPlayingMedia(uint64_t sourceElementID)
1474 {
1475     MediaProducer::MediaStateFlags state = MediaProducer::IsNotPlaying;
1476     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1477         if (Document* document = frame->document())
1478             state |= document->mediaState();
1479     }
1480
1481     if (state == m_mediaState)
1482         return;
1483
1484     m_mediaState = state;
1485
1486     chrome().client().isPlayingMediaDidChange(state, sourceElementID);
1487 }
1488
1489 void Page::setMuted(MediaProducer::MutedStateFlags muted)
1490 {
1491     if (m_mutedState == muted)
1492         return;
1493
1494     m_mutedState = muted;
1495
1496     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1497         if (!frame->document())
1498             continue;
1499         frame->document()->pageMutedStateDidChange();
1500     }
1501 }
1502
1503 void Page::stopMediaCapture()
1504 {
1505 #if ENABLE(MEDIA_STREAM)
1506     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1507         if (!frame->document())
1508             continue;
1509
1510         frame->document()->stopMediaCapture();
1511     }
1512 #endif
1513 }
1514
1515 #if ENABLE(MEDIA_SESSION)
1516 void Page::handleMediaEvent(MediaEventType eventType)
1517 {
1518     switch (eventType) {
1519     case MediaEventType::PlayPause:
1520         MediaSessionManager::singleton().togglePlayback();
1521         break;
1522     case MediaEventType::TrackNext:
1523         MediaSessionManager::singleton().skipToNextTrack();
1524         break;
1525     case MediaEventType::TrackPrevious:
1526         MediaSessionManager::singleton().skipToPreviousTrack();
1527         break;
1528     }
1529 }
1530
1531 void Page::setVolumeOfMediaElement(double volume, uint64_t elementID)
1532 {
1533     if (HTMLMediaElement* element = HTMLMediaElement::elementWithID(elementID))
1534         element->setVolume(volume, ASSERT_NO_EXCEPTION);
1535 }
1536 #endif
1537
1538 #if !ASSERT_DISABLED
1539 void Page::checkSubframeCountConsistency() const
1540 {
1541     ASSERT(m_subframeCount >= 0);
1542
1543     int subframeCount = 0;
1544     for (const Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1545         ++subframeCount;
1546
1547     ASSERT(m_subframeCount + 1 == subframeCount);
1548 }
1549 #endif
1550
1551 void Page::resumeAnimatingImages()
1552 {
1553     // Drawing models which cache painted content while out-of-window (WebKit2's composited drawing areas, etc.)
1554     // require that we repaint animated images to kickstart the animation loop.
1555     if (FrameView* view = mainFrame().view())
1556         view->resumeVisibleImageAnimationsIncludingSubframes();
1557 }
1558
1559 void Page::setActivityState(ActivityState::Flags activityState)
1560 {
1561     ActivityState::Flags changed = m_activityState ^ activityState;
1562     if (!changed)
1563         return;
1564
1565     ActivityState::Flags oldActivityState = m_activityState;
1566
1567     bool wasVisibleAndActive = isVisibleAndActive();
1568     m_activityState = activityState;
1569
1570     m_focusController->setActivityState(activityState);
1571
1572     if (changed & ActivityState::IsVisible)
1573         setIsVisibleInternal(activityState & ActivityState::IsVisible);
1574     if (changed & ActivityState::IsInWindow)
1575         setIsInWindowInternal(activityState & ActivityState::IsInWindow);
1576     if (changed & ActivityState::IsVisuallyIdle)
1577         setIsVisuallyIdleInternal(activityState & ActivityState::IsVisuallyIdle);
1578     if (changed & ActivityState::WindowIsActive) {
1579         if (auto* view = m_mainFrame->view())
1580             view->updateTiledBackingAdaptiveSizing();
1581     }
1582
1583     if (changed & (ActivityState::IsVisible | ActivityState::IsVisuallyIdle | ActivityState::IsAudible | ActivityState::IsLoading | ActivityState::IsCapturingMedia))
1584         updateTimerThrottlingState();
1585
1586     for (auto* observer : m_activityStateChangeObservers)
1587         observer->activityStateDidChange(oldActivityState, m_activityState);
1588
1589     if (wasVisibleAndActive != isVisibleAndActive())
1590         PlatformMediaSessionManager::updateNowPlayingInfoIfNecessary();
1591
1592     if (m_performanceMonitor)
1593         m_performanceMonitor->activityStateChanged(oldActivityState, activityState);
1594 }
1595
1596 bool Page::isVisibleAndActive() const
1597 {
1598     return (m_activityState & ActivityState::IsVisible) && (m_activityState & ActivityState::WindowIsActive);
1599 }
1600
1601 bool Page::isWindowActive() const
1602 {
1603     return m_activityState & ActivityState::WindowIsActive;
1604 }
1605
1606 void Page::setIsVisible(bool isVisible)
1607 {
1608     if (isVisible)
1609         setActivityState((m_activityState & ~ActivityState::IsVisuallyIdle) | ActivityState::IsVisible | ActivityState::IsVisibleOrOccluded);
1610     else
1611         setActivityState((m_activityState & ~(ActivityState::IsVisible | ActivityState::IsVisibleOrOccluded)) | ActivityState::IsVisuallyIdle);
1612 }
1613
1614 enum class SVGAnimationsState { Paused, Resumed };
1615 static inline void setSVGAnimationsState(Page& page, SVGAnimationsState state)
1616 {
1617     for (Frame* frame = &page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
1618         auto* document = frame->document();
1619         if (!document)
1620             continue;
1621
1622         if (!document->svgExtensions())
1623             continue;
1624
1625         if (state == SVGAnimationsState::Paused)
1626             document->accessSVGExtensions().pauseAnimations();
1627         else
1628             document->accessSVGExtensions().unpauseAnimations();
1629     }
1630 }
1631
1632 void Page::setIsVisibleInternal(bool isVisible)
1633 {
1634     // FIXME: The visibility state should be stored on the top-level document.
1635     // https://bugs.webkit.org/show_bug.cgi?id=116769
1636
1637     if (isVisible) {
1638         m_isPrerender = false;
1639
1640         resumeScriptedAnimations();
1641 #if PLATFORM(IOS)
1642         resumeDeviceMotionAndOrientationUpdates();
1643 #endif
1644
1645         if (FrameView* view = mainFrame().view())
1646             view->show();
1647
1648         if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
1649             mainFrame().animation().resumeAnimations();
1650
1651         setSVGAnimationsState(*this, SVGAnimationsState::Resumed);
1652
1653         resumeAnimatingImages();
1654
1655         if (m_navigationToLogWhenVisible) {
1656             logNavigation(m_navigationToLogWhenVisible.value());
1657             m_navigationToLogWhenVisible = std::nullopt;
1658         }
1659     }
1660
1661     if (!isVisible) {
1662         if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
1663             mainFrame().animation().suspendAnimations();
1664
1665         setSVGAnimationsState(*this, SVGAnimationsState::Paused);
1666
1667 #if PLATFORM(IOS)
1668         suspendDeviceMotionAndOrientationUpdates();
1669 #endif
1670
1671         suspendScriptedAnimations();
1672
1673         if (FrameView* view = mainFrame().view())
1674             view->hide();
1675     }
1676
1677     Vector<Ref<Document>> documents;
1678     for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
1679         documents.append(*frame->document());
1680
1681     for (auto& document : documents)
1682         document->visibilityStateChanged();
1683 }
1684
1685 void Page::setIsPrerender()
1686 {
1687     m_isPrerender = true;
1688     updateDOMTimerAlignmentInterval();
1689 }
1690
1691 PageVisibilityState Page::visibilityState() const
1692 {
1693     if (isVisible())
1694         return PageVisibilityState::Visible;
1695     if (m_isPrerender)
1696         return PageVisibilityState::Prerender;
1697     return PageVisibilityState::Hidden;
1698 }
1699
1700 #if ENABLE(RUBBER_BANDING)
1701 void Page::addHeaderWithHeight(int headerHeight)
1702 {
1703     m_headerHeight = headerHeight;
1704
1705     FrameView* frameView = mainFrame().view();
1706     if (!frameView)
1707         return;
1708
1709     RenderView* renderView = frameView->renderView();
1710     if (!renderView)
1711         return;
1712
1713     frameView->setHeaderHeight(m_headerHeight);
1714     renderView->compositor().updateLayerForHeader(m_headerHeight);
1715 }
1716
1717 void Page::addFooterWithHeight(int footerHeight)
1718 {
1719     m_footerHeight = footerHeight;
1720
1721     FrameView* frameView = mainFrame().view();
1722     if (!frameView)
1723         return;
1724
1725     RenderView* renderView = frameView->renderView();
1726     if (!renderView)
1727         return;
1728
1729     frameView->setFooterHeight(m_footerHeight);
1730     renderView->compositor().updateLayerForFooter(m_footerHeight);
1731 }
1732 #endif
1733
1734 void Page::incrementNestedRunLoopCount()
1735 {
1736     m_nestedRunLoopCount++;
1737 }
1738
1739 void Page::decrementNestedRunLoopCount()
1740 {
1741     ASSERT(m_nestedRunLoopCount);
1742     if (m_nestedRunLoopCount <= 0)
1743         return;
1744
1745     m_nestedRunLoopCount--;
1746
1747     if (!m_nestedRunLoopCount && m_unnestCallback) {
1748         callOnMainThread([this] {
1749             if (insideNestedRunLoop())
1750                 return;
1751
1752             // This callback may destruct the Page.
1753             if (m_unnestCallback) {
1754                 auto callback = WTFMove(m_unnestCallback);
1755                 callback();
1756             }
1757         });
1758     }
1759 }
1760
1761 void Page::whenUnnested(WTF::Function<void()>&& callback)
1762 {
1763     ASSERT(!m_unnestCallback);
1764
1765     m_unnestCallback = WTFMove(callback);
1766 }
1767
1768 #if ENABLE(REMOTE_INSPECTOR)
1769 bool Page::remoteInspectionAllowed() const
1770 {
1771     return m_inspectorDebuggable->remoteDebuggingAllowed();
1772 }
1773
1774 void Page::setRemoteInspectionAllowed(bool allowed)
1775 {
1776     m_inspectorDebuggable->setRemoteDebuggingAllowed(allowed);
1777 }
1778
1779 String Page::remoteInspectionNameOverride() const
1780 {
1781     return m_inspectorDebuggable->nameOverride();
1782 }
1783
1784 void Page::setRemoteInspectionNameOverride(const String& name)
1785 {
1786     m_inspectorDebuggable->setNameOverride(name);
1787 }
1788
1789 void Page::remoteInspectorInformationDidChange() const
1790 {
1791     m_inspectorDebuggable->update();
1792 }
1793 #endif
1794
1795 void Page::addLayoutMilestones(LayoutMilestones milestones)
1796 {
1797     // In the future, we may want a function that replaces m_layoutMilestones instead of just adding to it.
1798     m_requestedLayoutMilestones |= milestones;
1799 }
1800
1801 void Page::removeLayoutMilestones(LayoutMilestones milestones)
1802 {
1803     m_requestedLayoutMilestones &= ~milestones;
1804 }
1805
1806 Color Page::pageExtendedBackgroundColor() const
1807 {
1808     FrameView* frameView = mainFrame().view();
1809     if (!frameView)
1810         return Color();
1811
1812     RenderView* renderView = frameView->renderView();
1813     if (!renderView)
1814         return Color();
1815
1816     return renderView->compositor().rootExtendedBackgroundColor();
1817 }
1818
1819 // These are magical constants that might be tweaked over time.
1820 static const double gMinimumPaintedAreaRatio = 0.1;
1821 static const double gMaximumUnpaintedAreaRatio = 0.04;
1822
1823 bool Page::isCountingRelevantRepaintedObjects() const
1824 {
1825     return m_isCountingRelevantRepaintedObjects && (m_requestedLayoutMilestones & DidHitRelevantRepaintedObjectsAreaThreshold);
1826 }
1827
1828 void Page::startCountingRelevantRepaintedObjects()
1829 {
1830     // Reset everything in case we didn't hit the threshold last time.
1831     resetRelevantPaintedObjectCounter();
1832
1833     m_isCountingRelevantRepaintedObjects = true;
1834 }
1835
1836 void Page::resetRelevantPaintedObjectCounter()
1837 {
1838     m_isCountingRelevantRepaintedObjects = false;
1839     m_relevantUnpaintedRenderObjects.clear();
1840     m_topRelevantPaintedRegion = Region();
1841     m_bottomRelevantPaintedRegion = Region();
1842     m_relevantUnpaintedRegion = Region();
1843 }
1844
1845 static LayoutRect relevantViewRect(RenderView* view)
1846 {
1847     // DidHitRelevantRepaintedObjectsAreaThreshold is a LayoutMilestone intended to indicate that
1848     // a certain relevant amount of content has been drawn to the screen. This is the rect that
1849     // has been determined to be relevant in the context of this goal. We may choose to tweak
1850     // the rect over time, much like we may choose to tweak gMinimumPaintedAreaRatio and
1851     // gMaximumUnpaintedAreaRatio. But this seems to work well right now.
1852     LayoutRect relevantViewRect = LayoutRect(0, 0, 980, 1300);
1853
1854     LayoutRect viewRect = view->viewRect();
1855     // If the viewRect is wider than the relevantViewRect, center the relevantViewRect.
1856     if (viewRect.width() > relevantViewRect.width())
1857         relevantViewRect.setX((viewRect.width() - relevantViewRect.width()) / 2);
1858
1859     return relevantViewRect;
1860 }
1861
1862 void Page::addRelevantRepaintedObject(RenderObject* object, const LayoutRect& objectPaintRect)
1863 {
1864     if (!isCountingRelevantRepaintedObjects())
1865         return;
1866
1867     // Objects inside sub-frames are not considered to be relevant.
1868     if (&object->frame() != &mainFrame())
1869         return;
1870
1871     LayoutRect relevantRect = relevantViewRect(&object->view());
1872
1873     // The objects are only relevant if they are being painted within the viewRect().
1874     if (!objectPaintRect.intersects(snappedIntRect(relevantRect)))
1875         return;
1876
1877     IntRect snappedPaintRect = snappedIntRect(objectPaintRect);
1878
1879     // If this object was previously counted as an unpainted object, remove it from that HashSet
1880     // and corresponding Region. FIXME: This doesn't do the right thing if the objects overlap.
1881     if (m_relevantUnpaintedRenderObjects.remove(object))
1882         m_relevantUnpaintedRegion.subtract(snappedPaintRect);
1883
1884     // Split the relevantRect into a top half and a bottom half. Making sure we have coverage in
1885     // both halves helps to prevent cases where we have a fully loaded menu bar or masthead with
1886     // no content beneath that.
1887     LayoutRect topRelevantRect = relevantRect;
1888     topRelevantRect.contract(LayoutSize(0, relevantRect.height() / 2));
1889     LayoutRect bottomRelevantRect = topRelevantRect;
1890     bottomRelevantRect.setY(relevantRect.height() / 2);
1891
1892     // If the rect straddles both Regions, split it appropriately.
1893     if (topRelevantRect.intersects(snappedPaintRect) && bottomRelevantRect.intersects(snappedPaintRect)) {
1894         IntRect topIntersection = snappedPaintRect;
1895         topIntersection.intersect(snappedIntRect(topRelevantRect));
1896         m_topRelevantPaintedRegion.unite(topIntersection);
1897
1898         IntRect bottomIntersection = snappedPaintRect;
1899         bottomIntersection.intersect(snappedIntRect(bottomRelevantRect));
1900         m_bottomRelevantPaintedRegion.unite(bottomIntersection);
1901     } else if (topRelevantRect.intersects(snappedPaintRect))
1902         m_topRelevantPaintedRegion.unite(snappedPaintRect);
1903     else
1904         m_bottomRelevantPaintedRegion.unite(snappedPaintRect);
1905
1906     float topPaintedArea = m_topRelevantPaintedRegion.totalArea();
1907     float bottomPaintedArea = m_bottomRelevantPaintedRegion.totalArea();
1908     float viewArea = relevantRect.width() * relevantRect.height();
1909
1910     float ratioThatIsPaintedOnTop = topPaintedArea / viewArea;
1911     float ratioThatIsPaintedOnBottom = bottomPaintedArea / viewArea;
1912     float ratioOfViewThatIsUnpainted = m_relevantUnpaintedRegion.totalArea() / viewArea;
1913
1914     if (ratioThatIsPaintedOnTop > (gMinimumPaintedAreaRatio / 2) && ratioThatIsPaintedOnBottom > (gMinimumPaintedAreaRatio / 2)
1915         && ratioOfViewThatIsUnpainted < gMaximumUnpaintedAreaRatio) {
1916         m_isCountingRelevantRepaintedObjects = false;
1917         resetRelevantPaintedObjectCounter();
1918         if (Frame* frame = &mainFrame())
1919             frame->loader().didReachLayoutMilestone(DidHitRelevantRepaintedObjectsAreaThreshold);
1920     }
1921 }
1922
1923 void Page::addRelevantUnpaintedObject(RenderObject* object, const LayoutRect& objectPaintRect)
1924 {
1925     if (!isCountingRelevantRepaintedObjects())
1926         return;
1927
1928     // The objects are only relevant if they are being painted within the relevantViewRect().
1929     if (!objectPaintRect.intersects(snappedIntRect(relevantViewRect(&object->view()))))
1930         return;
1931
1932     m_relevantUnpaintedRenderObjects.add(object);
1933     m_relevantUnpaintedRegion.unite(snappedIntRect(objectPaintRect));
1934 }
1935
1936 void Page::suspendDeviceMotionAndOrientationUpdates()
1937 {
1938     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1939         if (Document* document = frame->document())
1940             document->suspendDeviceMotionAndOrientationUpdates();
1941     }
1942 }
1943
1944 void Page::resumeDeviceMotionAndOrientationUpdates()
1945 {
1946     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1947         if (Document* document = frame->document())
1948             document->resumeDeviceMotionAndOrientationUpdates();
1949     }
1950 }
1951
1952 void Page::suspendActiveDOMObjectsAndAnimations()
1953 {
1954     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1955         frame->suspendActiveDOMObjectsAndAnimations();
1956 }
1957
1958 void Page::resumeActiveDOMObjectsAndAnimations()
1959 {
1960     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1961         frame->resumeActiveDOMObjectsAndAnimations();
1962
1963     resumeAnimatingImages();
1964 }
1965
1966 bool Page::hasSeenAnyPlugin() const
1967 {
1968     return !m_seenPlugins.isEmpty();
1969 }
1970
1971 bool Page::hasSeenPlugin(const String& serviceType) const
1972 {
1973     return m_seenPlugins.contains(serviceType);
1974 }
1975
1976 void Page::sawPlugin(const String& serviceType)
1977 {
1978     m_seenPlugins.add(serviceType);
1979 }
1980
1981 void Page::resetSeenPlugins()
1982 {
1983     m_seenPlugins.clear();
1984 }
1985
1986 bool Page::hasSeenAnyMediaEngine() const
1987 {
1988     return !m_seenMediaEngines.isEmpty();
1989 }
1990
1991 bool Page::hasSeenMediaEngine(const String& engineDescription) const
1992 {
1993     return m_seenMediaEngines.contains(engineDescription);
1994 }
1995
1996 void Page::sawMediaEngine(const String& engineDescription)
1997 {
1998     m_seenMediaEngines.add(engineDescription);
1999 }
2000
2001 void Page::resetSeenMediaEngines()
2002 {
2003     m_seenMediaEngines.clear();
2004 }
2005
2006 void Page::hiddenPageCSSAnimationSuspensionStateChanged()
2007 {
2008     if (!isVisible()) {
2009         if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
2010             mainFrame().animation().suspendAnimations();
2011         else
2012             mainFrame().animation().resumeAnimations();
2013     }
2014 }
2015
2016 #if ENABLE(VIDEO_TRACK)
2017 void Page::captionPreferencesChanged()
2018 {
2019     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2020         if (!frame->document())
2021             continue;
2022         frame->document()->captionPreferencesChanged();
2023     }
2024 }
2025 #endif
2026
2027 void Page::forbidPrompts()
2028 {
2029     ++m_forbidPromptsDepth;
2030 }
2031
2032 void Page::allowPrompts()
2033 {
2034     ASSERT(m_forbidPromptsDepth);
2035     --m_forbidPromptsDepth;
2036 }
2037
2038 bool Page::arePromptsAllowed()
2039 {
2040     return !m_forbidPromptsDepth;
2041 }
2042
2043 void Page::logNavigation(const Navigation& navigation)
2044 {
2045     String navigationDescription;
2046     switch (navigation.type) {
2047     case FrameLoadType::Standard:
2048         navigationDescription = ASCIILiteral("standard");
2049         break;
2050     case FrameLoadType::Back:
2051         navigationDescription = ASCIILiteral("back");
2052         break;
2053     case FrameLoadType::Forward:
2054         navigationDescription = ASCIILiteral("forward");
2055         break;
2056     case FrameLoadType::IndexedBackForward:
2057         navigationDescription = ASCIILiteral("indexedBackForward");
2058         break;
2059     case FrameLoadType::Reload:
2060         navigationDescription = ASCIILiteral("reload");
2061         break;
2062     case FrameLoadType::Same:
2063         navigationDescription = ASCIILiteral("same");
2064         break;
2065     case FrameLoadType::ReloadFromOrigin:
2066         navigationDescription = ASCIILiteral("reloadFromOrigin");
2067         break;
2068     case FrameLoadType::ReloadExpiredOnly:
2069         navigationDescription = ASCIILiteral("reloadRevalidatingExpired");
2070         break;
2071     case FrameLoadType::Replace:
2072     case FrameLoadType::RedirectWithLockedBackForwardList:
2073         // Not logging those for now.
2074         return;
2075     }
2076     diagnosticLoggingClient().logDiagnosticMessage(DiagnosticLoggingKeys::navigationKey(), navigationDescription, ShouldSample::No);
2077
2078     if (!navigation.domain.isEmpty())
2079         diagnosticLoggingClient().logDiagnosticMessageWithEnhancedPrivacy(DiagnosticLoggingKeys::domainVisitedKey(), navigation.domain, ShouldSample::No);
2080 }
2081
2082 void Page::mainFrameLoadStarted(const URL& destinationURL, FrameLoadType type)
2083 {
2084     String domain;
2085 #if ENABLE(PUBLIC_SUFFIX_LIST)
2086     domain = topPrivatelyControlledDomain(destinationURL.host());
2087 #else
2088     UNUSED_PARAM(destinationURL);
2089 #endif
2090
2091     Navigation navigation = { domain, type };
2092
2093     // To avoid being too verbose, we only log navigations if the page is or becomes visible. This avoids logging non-user observable loads.
2094     if (!isVisible()) {
2095         m_navigationToLogWhenVisible = navigation;
2096         return;
2097     }
2098
2099     m_navigationToLogWhenVisible = std::nullopt;
2100     logNavigation(navigation);
2101 }
2102
2103 PluginInfoProvider& Page::pluginInfoProvider()
2104 {
2105     return m_pluginInfoProvider;
2106 }
2107
2108 UserContentProvider& Page::userContentProvider()
2109 {
2110     return m_userContentProvider;
2111 }
2112
2113 void Page::setUserContentProvider(Ref<UserContentProvider>&& userContentProvider)
2114 {
2115     m_userContentProvider->removePage(*this);
2116     m_userContentProvider = WTFMove(userContentProvider);
2117     m_userContentProvider->addPage(*this);
2118
2119     invalidateInjectedStyleSheetCacheInAllFrames();
2120 }
2121
2122 void Page::setStorageNamespaceProvider(Ref<StorageNamespaceProvider>&& storageNamespaceProvider)
2123 {
2124     m_storageNamespaceProvider->removePage(*this);
2125     m_storageNamespaceProvider = WTFMove(storageNamespaceProvider);
2126     m_storageNamespaceProvider->addPage(*this);
2127
2128     // This needs to reset all the local storage namespaces of all the pages.
2129 }
2130
2131 VisitedLinkStore& Page::visitedLinkStore()
2132 {
2133     return m_visitedLinkStore;
2134 }
2135
2136 void Page::setVisitedLinkStore(Ref<VisitedLinkStore>&& visitedLinkStore)
2137 {
2138     m_visitedLinkStore->removePage(*this);
2139     m_visitedLinkStore = WTFMove(visitedLinkStore);
2140     m_visitedLinkStore->addPage(*this);
2141
2142     invalidateStylesForAllLinks();
2143 }
2144
2145 SessionID Page::sessionID() const
2146 {
2147     return m_sessionID;
2148 }
2149
2150 void Page::setSessionID(SessionID sessionID)
2151 {
2152     ASSERT(sessionID.isValid());
2153
2154 #if ENABLE(INDEXED_DATABASE)
2155     if (sessionID != m_sessionID)
2156         m_idbIDBConnectionToServer = nullptr;
2157 #endif
2158
2159     bool privateBrowsingStateChanged = (sessionID.isEphemeral() != m_sessionID.isEphemeral());
2160
2161     m_sessionID = sessionID;
2162
2163     if (!privateBrowsingStateChanged)
2164         return;
2165
2166     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2167         if (!frame->document())
2168             continue;
2169         frame->document()->privateBrowsingStateDidChange();
2170     }
2171
2172     // Collect the PluginViews in to a vector to ensure that action the plug-in takes
2173     // from below privateBrowsingStateChanged does not affect their lifetime.
2174
2175     for (auto& view : pluginViews())
2176         view->privateBrowsingStateChanged(sessionID.isEphemeral());
2177 }
2178
2179 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
2180 void Page::addPlaybackTargetPickerClient(uint64_t contextId)
2181 {
2182     chrome().client().addPlaybackTargetPickerClient(contextId);
2183 }
2184
2185 void Page::removePlaybackTargetPickerClient(uint64_t contextId)
2186 {
2187     chrome().client().removePlaybackTargetPickerClient(contextId);
2188 }
2189
2190 void Page::showPlaybackTargetPicker(uint64_t contextId, const WebCore::IntPoint& location, bool isVideo)
2191 {
2192 #if PLATFORM(IOS)
2193     // FIXME: refactor iOS implementation.
2194     UNUSED_PARAM(contextId);
2195     UNUSED_PARAM(location);
2196     chrome().client().showPlaybackTargetPicker(isVideo);
2197 #else
2198     chrome().client().showPlaybackTargetPicker(contextId, location, isVideo);
2199 #endif
2200 }
2201
2202 void Page::playbackTargetPickerClientStateDidChange(uint64_t contextId, MediaProducer::MediaStateFlags state)
2203 {
2204     chrome().client().playbackTargetPickerClientStateDidChange(contextId, state);
2205 }
2206
2207 void Page::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
2208 {
2209     chrome().client().setMockMediaPlaybackTargetPickerEnabled(enabled);
2210 }
2211
2212 void Page::setMockMediaPlaybackTargetPickerState(const String& name, MediaPlaybackTargetContext::State state)
2213 {
2214     chrome().client().setMockMediaPlaybackTargetPickerState(name, state);
2215 }
2216
2217 void Page::setPlaybackTarget(uint64_t contextId, Ref<MediaPlaybackTarget>&& target)
2218 {
2219     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2220         if (!frame->document())
2221             continue;
2222         frame->document()->setPlaybackTarget(contextId, target.copyRef());
2223     }
2224 }
2225
2226 void Page::playbackTargetAvailabilityDidChange(uint64_t contextId, bool available)
2227 {
2228     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2229         if (!frame->document())
2230             continue;
2231         frame->document()->playbackTargetAvailabilityDidChange(contextId, available);
2232     }
2233 }
2234
2235 void Page::setShouldPlayToPlaybackTarget(uint64_t clientId, bool shouldPlay)
2236 {
2237     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2238         if (!frame->document())
2239             continue;
2240         frame->document()->setShouldPlayToPlaybackTarget(clientId, shouldPlay);
2241     }
2242 }
2243 #endif
2244
2245 WheelEventTestTrigger& Page::ensureTestTrigger()
2246 {
2247     if (!m_testTrigger) {
2248         m_testTrigger = adoptRef(new WheelEventTestTrigger());
2249         // We need to update the scrolling coordinator so that the mainframe scrolling node can expect wheel event test triggers.
2250         if (auto* frameView = mainFrame().view()) {
2251             if (m_scrollingCoordinator)
2252                 m_scrollingCoordinator->updateExpectsWheelEventTestTriggerWithFrameView(*frameView);
2253         }
2254     }
2255
2256     return *m_testTrigger;
2257 }
2258
2259 #if ENABLE(VIDEO)
2260 void Page::setAllowsMediaDocumentInlinePlayback(bool flag)
2261 {
2262     if (m_allowsMediaDocumentInlinePlayback == flag)
2263         return;
2264     m_allowsMediaDocumentInlinePlayback = flag;
2265
2266     Vector<Ref<Document>> documents;
2267     for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
2268         documents.append(*frame->document());
2269
2270     for (auto& document : documents)
2271         document->allowsMediaDocumentInlinePlaybackChanged();
2272 }
2273 #endif
2274
2275 #if ENABLE(INDEXED_DATABASE)
2276 IDBClient::IDBConnectionToServer& Page::idbConnection()
2277 {
2278     if (!m_idbIDBConnectionToServer)
2279         m_idbIDBConnectionToServer = &databaseProvider().idbConnectionToServerForSession(m_sessionID);
2280     
2281     return *m_idbIDBConnectionToServer;
2282 }
2283 #endif
2284
2285 #if ENABLE(RESOURCE_USAGE)
2286 void Page::setResourceUsageOverlayVisible(bool visible)
2287 {
2288     if (!visible) {
2289         m_resourceUsageOverlay = nullptr;
2290         return;
2291     }
2292
2293     if (!m_resourceUsageOverlay && m_settings->acceleratedCompositingEnabled())
2294         m_resourceUsageOverlay = std::make_unique<ResourceUsageOverlay>(*this);
2295 }
2296 #endif
2297
2298 bool Page::isAlwaysOnLoggingAllowed() const
2299 {
2300     return m_sessionID.isAlwaysOnLoggingAllowed();
2301 }
2302
2303 String Page::captionUserPreferencesStyleSheet()
2304 {
2305     return m_captionUserPreferencesStyleSheet;
2306 }
2307
2308 void Page::setCaptionUserPreferencesStyleSheet(const String& styleSheet)
2309 {
2310     if (m_captionUserPreferencesStyleSheet == styleSheet)
2311         return;
2312
2313     m_captionUserPreferencesStyleSheet = styleSheet;
2314     
2315     invalidateInjectedStyleSheetCacheInAllFrames();
2316 }
2317
2318 void Page::accessibilitySettingsDidChange()
2319 {
2320     bool neededRecalc = false;
2321
2322     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2323         if (Document* document = frame->document()) {
2324             auto* styleResolver = document->styleScope().resolverIfExists();
2325             if (styleResolver && styleResolver->hasMediaQueriesAffectedByAccessibilitySettingsChange()) {
2326                 document->styleScope().didChangeStyleSheetEnvironment();
2327                 document->evaluateMediaQueryList();
2328                 neededRecalc = true;
2329                 // FIXME: This instrumentation event is not strictly accurate since cached media query results do not persist across StyleResolver rebuilds.
2330                 InspectorInstrumentation::mediaQueryResultChanged(*document);
2331             }
2332         }
2333     }
2334
2335     if (neededRecalc)
2336         LOG(Layout, "hasMediaQueriesAffectedByAccessibilitySettingsChange, enqueueing style recalc");
2337 }
2338
2339 void Page::setUnobscuredSafeAreaInsets(const FloatBoxExtent& insets)
2340 {
2341     if (m_unobscuredSafeAreaInsets == insets)
2342         return;
2343
2344     m_unobscuredSafeAreaInsets = insets;
2345
2346     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2347         if (!frame->document())
2348             continue;
2349         frame->document()->constantProperties().didChangeSafeAreaInsets();
2350     }
2351 }
2352
2353 #if ENABLE(DATA_INTERACTION)
2354
2355 bool Page::hasSelectionAtPosition(const FloatPoint& position) const
2356 {
2357     auto currentSelection = m_mainFrame->selection().selection();
2358     if (!currentSelection.isRange())
2359         return false;
2360
2361     if (auto selectedRange = currentSelection.toNormalizedRange()) {
2362         Vector<SelectionRect> selectionRects;
2363         selectedRange->collectSelectionRects(selectionRects);
2364         for (auto selectionRect : selectionRects) {
2365             if (FloatRect(selectionRect.rect()).contains(position))
2366                 return true;
2367         }
2368     }
2369
2370     return false;
2371 }
2372
2373 #endif
2374
2375 void Page::disableICECandidateFiltering()
2376 {
2377     m_shouldEnableICECandidateFilteringByDefault = false;
2378 #if ENABLE(WEB_RTC)
2379     m_rtcController.disableICECandidateFiltering();
2380 #endif
2381 }
2382
2383 void Page::enableICECandidateFiltering()
2384 {
2385     m_shouldEnableICECandidateFilteringByDefault = true;
2386 #if ENABLE(WEB_RTC)
2387     m_rtcController.enableICECandidateFiltering();
2388 #endif
2389 }
2390
2391 void Page::didChangeMainDocument()
2392 {
2393 #if ENABLE(WEB_RTC)
2394     m_rtcController.reset(m_shouldEnableICECandidateFilteringByDefault);
2395 #endif
2396 }
2397
2398 } // namespace WebCore