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