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