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