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