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