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