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