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