8fc29beaf7129b7cd9c892d10e54f07367873f20
[WebKit-https.git] / Source / WebCore / page / Page.cpp
1 /*
2  * Copyright (C) 2006-2015  Apple Inc. All Rights Reserved.
3  * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "Page.h"
22
23 #include "AlternativeTextClient.h"
24 #include "AnimationController.h"
25 #include "ApplicationCacheStorage.h"
26 #include "BackForwardClient.h"
27 #include "BackForwardController.h"
28 #include "Chrome.h"
29 #include "ChromeClient.h"
30 #include "ClientRectList.h"
31 #include "ContextMenuClient.h"
32 #include "ContextMenuController.h"
33 #include "DatabaseProvider.h"
34 #include "DocumentLoader.h"
35 #include "DocumentMarkerController.h"
36 #include "DocumentStyleSheetCollection.h"
37 #include "DragController.h"
38 #include "Editor.h"
39 #include "EditorClient.h"
40 #include "Event.h"
41 #include "EventNames.h"
42 #include "ExceptionCode.h"
43 #include "ExceptionCodePlaceholder.h"
44 #include "FileSystem.h"
45 #include "FocusController.h"
46 #include "FrameLoader.h"
47 #include "FrameLoaderClient.h"
48 #include "FrameSelection.h"
49 #include "FrameTree.h"
50 #include "FrameView.h"
51 #include "HTMLElement.h"
52 #include "HistoryController.h"
53 #include "HistoryItem.h"
54 #include "InspectorController.h"
55 #include "InspectorInstrumentation.h"
56 #include "Logging.h"
57 #include "MainFrame.h"
58 #include "MediaCanStartListener.h"
59 #include "Navigator.h"
60 #include "NetworkStateNotifier.h"
61 #include "PageCache.h"
62 #include "PageConfiguration.h"
63 #include "PageConsoleClient.h"
64 #include "PageDebuggable.h"
65 #include "PageGroup.h"
66 #include "PageOverlayController.h"
67 #include "PageThrottler.h"
68 #include "PlugInClient.h"
69 #include "PluginData.h"
70 #include "PluginViewBase.h"
71 #include "PointerLockController.h"
72 #include "ProgressTracker.h"
73 #include "RenderLayerCompositor.h"
74 #include "RenderTheme.h"
75 #include "RenderView.h"
76 #include "RenderWidget.h"
77 #include "RuntimeEnabledFeatures.h"
78 #include "SchemeRegistry.h"
79 #include "ScriptController.h"
80 #include "ScrollingCoordinator.h"
81 #include "Settings.h"
82 #include "SharedBuffer.h"
83 #include "StorageArea.h"
84 #include "StorageNamespace.h"
85 #include "StorageNamespaceProvider.h"
86 #include "StyleResolver.h"
87 #include "SubframeLoader.h"
88 #include "TextResourceDecoder.h"
89 #include "UserContentController.h"
90 #include "UserInputBridge.h"
91 #include "ViewStateChangeObserver.h"
92 #include "VisitedLinkState.h"
93 #include "VisitedLinkStore.h"
94 #include "VoidCallback.h"
95 #include "Widget.h"
96 #include <JavaScriptCore/Profile.h>
97 #include <wtf/HashMap.h>
98 #include <wtf/RefCountedLeakCounter.h>
99 #include <wtf/StdLibExtras.h>
100 #include <wtf/text/Base64.h>
101 #include <wtf/text/StringHash.h>
102
103 #if ENABLE(WEB_REPLAY)
104 #include "ReplayController.h"
105 #include <replay/InputCursor.h>
106 #endif
107
108 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
109 #include "HTMLVideoElement.h"
110 #include "MediaPlaybackTarget.h"
111 #endif
112
113 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& page : *allPages) {
125         for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext())
126             frames.append(*frame);
127         InspectorInstrumentation::networkStateChanged(page);
128     }
129
130     AtomicString eventName = isOnLine ? eventNames().onlineEvent : eventNames().offlineEvent;
131     for (auto& frame : frames)
132         frame->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(nullptr)
185     , m_debugger(nullptr)
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_applicationCacheStorage(pageConfiguration.applicationCacheStorage ? *WTF::move(pageConfiguration.applicationCacheStorage) : ApplicationCacheStorage::singleton())
211     , m_databaseProvider(*WTF::move(pageConfiguration.databaseProvider))
212     , m_storageNamespaceProvider(*WTF::move(pageConfiguration.storageNamespaceProvider))
213     , m_userContentController(WTF::move(pageConfiguration.userContentController))
214     , m_visitedLinkStore(*WTF::move(pageConfiguration.visitedLinkStore))
215     , m_sessionID(SessionID::defaultSessionID())
216     , m_isClosing(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(nullptr);
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()
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->absoluteNonFastScrollableRegion().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
385     return ClientRectList::create(quads);
386 }
387
388 #if ENABLE(VIEW_MODE_CSS_MEDIA)
389 struct ViewModeInfo {
390     const char* name;
391     Page::ViewMode type;
392 };
393 static const int viewModeMapSize = 5;
394 static const ViewModeInfo viewModeMap[viewModeMapSize] = {
395     {"windowed", Page::ViewModeWindowed},
396     {"floating", Page::ViewModeFloating},
397     {"fullscreen", Page::ViewModeFullscreen},
398     {"maximized", Page::ViewModeMaximized},
399     {"minimized", Page::ViewModeMinimized}
400 };
401
402 Page::ViewMode Page::stringToViewMode(const String& text)
403 {
404     for (auto& mode : viewModeMap) {
405         if (text == mode.name)
406             return mode.type;
407     }
408     return Page::ViewModeInvalid;
409 }
410
411 void Page::setViewMode(ViewMode viewMode)
412 {
413     if (viewMode == m_viewMode || viewMode == ViewModeInvalid)
414         return;
415
416     m_viewMode = viewMode;
417
418     if (!m_mainFrame)
419         return;
420
421     if (m_mainFrame->view())
422         m_mainFrame->view()->forceLayout();
423
424     if (m_mainFrame->document())
425         m_mainFrame->document()->styleResolverChanged(RecalcStyleImmediately);
426 }
427 #endif // ENABLE(VIEW_MODE_CSS_MEDIA)
428
429 bool Page::openedByDOM() const
430 {
431     return m_openedByDOM;
432 }
433
434 void Page::setOpenedByDOM()
435 {
436     m_openedByDOM = true;
437 }
438
439 void Page::goToItem(HistoryItem& item, FrameLoadType type)
440 {
441     // stopAllLoaders may end up running onload handlers, which could cause further history traversals that may lead to the passed in HistoryItem
442     // being deref()-ed. Make sure we can still use it with HistoryController::goToItem later.
443     Ref<HistoryItem> protector(item);
444
445     if (m_mainFrame->loader().history().shouldStopLoadingForHistoryItem(item))
446         m_mainFrame->loader().stopAllLoaders();
447
448     m_mainFrame->loader().history().goToItem(item, type);
449 }
450
451 void Page::setGroupName(const String& name)
452 {
453     if (m_group && !m_group->name().isEmpty()) {
454         ASSERT(m_group != m_singlePageGroup.get());
455         ASSERT(!m_singlePageGroup);
456         m_group->removePage(*this);
457     }
458
459     if (name.isEmpty())
460         m_group = m_singlePageGroup.get();
461     else {
462         m_singlePageGroup = nullptr;
463         m_group = PageGroup::pageGroup(name);
464         m_group->addPage(*this);
465     }
466 }
467
468 const String& Page::groupName() const
469 {
470     return m_group ? m_group->name() : nullAtom.string();
471 }
472
473 void Page::initGroup()
474 {
475     ASSERT(!m_singlePageGroup);
476     ASSERT(!m_group);
477     m_singlePageGroup = std::make_unique<PageGroup>(*this);
478     m_group = m_singlePageGroup.get();
479 }
480
481 void Page::updateStyleForAllPagesAfterGlobalChangeInEnvironment()
482 {
483     if (!allPages)
484         return;
485     for (auto& page : *allPages) {
486         for (Frame* frame = &page->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
497 void Page::setNeedsRecalcStyleInAllFrames()
498 {
499     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
500         if (Document* document = frame->document())
501             document->styleResolverChanged(DeferRecalcStyle);
502     }
503 }
504
505 void Page::refreshPlugins(bool reload)
506 {
507     if (!allPages)
508         return;
509
510     PluginData::refresh();
511
512     Vector<Ref<Frame>> framesNeedingReload;
513
514     for (auto& page : *allPages) {
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 (auto& frame : framesNeedingReload)
527         frame->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 = nullptr;
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(COORDINATED_GRAPHICS)
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(COORDINATED_GRAPHICS)
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::setViewScaleFactor(float scale)
835 {
836     if (m_viewScaleFactor == scale)
837         return;
838
839     m_viewScaleFactor = scale;
840     PageCache::singleton().markPagesForDeviceOrPageScaleChanged(*this);
841     PageCache::singleton().markPagesForFullStyleRecalc(*this);
842 }
843
844 void Page::setDeviceScaleFactor(float scaleFactor)
845 {
846     ASSERT(scaleFactor > 0);
847     if (scaleFactor <= 0)
848         return;
849     
850     if (m_deviceScaleFactor == scaleFactor)
851         return;
852
853     m_deviceScaleFactor = scaleFactor;
854     setNeedsRecalcStyleInAllFrames();
855
856     mainFrame().deviceOrPageScaleFactorChanged();
857     PageCache::singleton().markPagesForDeviceOrPageScaleChanged(*this);
858
859     PageCache::singleton().markPagesForFullStyleRecalc(*this);
860     GraphicsContext::updateDocumentMarkerResources();
861
862     mainFrame().pageOverlayController().didChangeDeviceScaleFactor();
863 }
864
865 void Page::setTopContentInset(float contentInset)
866 {
867     if (m_topContentInset == contentInset)
868         return;
869     
870     m_topContentInset = contentInset;
871     
872     if (FrameView* view = mainFrame().view())
873         view->topContentInsetDidChange(m_topContentInset);
874 }
875
876 void Page::setShouldSuppressScrollbarAnimations(bool suppressAnimations)
877 {
878     if (suppressAnimations == m_suppressScrollbarAnimations)
879         return;
880
881     lockAllOverlayScrollbarsToHidden(suppressAnimations);
882     m_suppressScrollbarAnimations = suppressAnimations;
883 }
884
885 void Page::lockAllOverlayScrollbarsToHidden(bool lockOverlayScrollbars)
886 {
887     FrameView* view = mainFrame().view();
888     if (!view)
889         return;
890
891     view->lockOverlayScrollbarStateToHidden(lockOverlayScrollbars);
892     
893     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
894         FrameView* frameView = frame->view();
895         if (!frameView)
896             continue;
897
898         const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas();
899         if (!scrollableAreas)
900             continue;
901
902         for (auto& scrollableArea : *scrollableAreas)
903             scrollableArea->lockOverlayScrollbarStateToHidden(lockOverlayScrollbars);
904     }
905 }
906     
907 void Page::setVerticalScrollElasticity(ScrollElasticity elasticity)
908 {
909     if (m_verticalScrollElasticity == elasticity)
910         return;
911     
912     m_verticalScrollElasticity = elasticity;
913     
914     if (FrameView* view = mainFrame().view())
915         view->setVerticalScrollElasticity(elasticity);
916 }
917     
918 void Page::setHorizontalScrollElasticity(ScrollElasticity elasticity)
919 {
920     if (m_horizontalScrollElasticity == elasticity)
921         return;
922     
923     m_horizontalScrollElasticity = elasticity;
924     
925     if (FrameView* view = mainFrame().view())
926         view->setHorizontalScrollElasticity(elasticity);
927 }
928
929 void Page::setPagination(const Pagination& pagination)
930 {
931     if (m_pagination == pagination)
932         return;
933
934     m_pagination = pagination;
935
936     setNeedsRecalcStyleInAllFrames();
937     PageCache::singleton().markPagesForFullStyleRecalc(*this);
938 }
939
940 unsigned Page::pageCount() const
941 {
942     if (m_pagination.mode == Pagination::Unpaginated)
943         return 0;
944
945     if (Document* document = mainFrame().document())
946         document->updateLayoutIgnorePendingStylesheets();
947
948     RenderView* contentRenderer = mainFrame().contentRenderer();
949     return contentRenderer ? contentRenderer->pageCount() : 0;
950 }
951
952 void Page::setIsInWindow(bool isInWindow)
953 {
954     setViewState(isInWindow ? m_viewState | ViewState::IsInWindow : m_viewState & ~ViewState::IsInWindow);
955 }
956
957 void Page::setIsInWindowInternal(bool isInWindow)
958 {
959     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
960         if (FrameView* frameView = frame->view())
961             frameView->setIsInWindow(isInWindow);
962     }
963
964     if (isInWindow)
965         resumeAnimatingImages();
966 }
967
968 void Page::addViewStateChangeObserver(ViewStateChangeObserver& observer)
969 {
970     m_viewStateChangeObservers.add(&observer);
971 }
972
973 void Page::removeViewStateChangeObserver(ViewStateChangeObserver& observer)
974 {
975     m_viewStateChangeObservers.remove(&observer);
976 }
977
978 void Page::suspendScriptedAnimations()
979 {
980     m_scriptedAnimationsSuspended = true;
981     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
982         if (frame->document())
983             frame->document()->suspendScriptedAnimationControllerCallbacks();
984     }
985 }
986
987 void Page::resumeScriptedAnimations()
988 {
989     m_scriptedAnimationsSuspended = false;
990     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
991         if (frame->document())
992             frame->document()->resumeScriptedAnimationControllerCallbacks();
993     }
994 }
995
996 void Page::setIsVisuallyIdleInternal(bool isVisuallyIdle)
997 {
998     setTimerThrottlingEnabled(isVisuallyIdle);
999     
1000     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1001         if (frame->document())
1002             frame->document()->scriptedAnimationControllerSetThrottled(isVisuallyIdle);
1003     }
1004 }
1005
1006 void Page::userStyleSheetLocationChanged()
1007 {
1008     // FIXME: Eventually we will move to a model of just being handed the sheet
1009     // text instead of loading the URL ourselves.
1010     URL url = m_settings->userStyleSheetLocation();
1011     
1012     // Allow any local file URL scheme to be loaded.
1013     if (SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol()))
1014         m_userStyleSheetPath = url.fileSystemPath();
1015     else
1016         m_userStyleSheetPath = String();
1017
1018     m_didLoadUserStyleSheet = false;
1019     m_userStyleSheet = String();
1020     m_userStyleSheetModificationTime = 0;
1021
1022     // Data URLs with base64-encoded UTF-8 style sheets are common. We can process them
1023     // synchronously and avoid using a loader. 
1024     if (url.protocolIsData() && url.string().startsWith("data:text/css;charset=utf-8;base64,")) {
1025         m_didLoadUserStyleSheet = true;
1026
1027         Vector<char> styleSheetAsUTF8;
1028         if (base64Decode(decodeURLEscapeSequences(url.string().substring(35)), styleSheetAsUTF8, Base64IgnoreWhitespace))
1029             m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size());
1030     }
1031
1032     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1033         if (frame->document())
1034             frame->document()->styleSheetCollection().updatePageUserSheet();
1035     }
1036 }
1037
1038 const String& Page::userStyleSheet() const
1039 {
1040     if (m_userStyleSheetPath.isEmpty())
1041         return m_userStyleSheet;
1042
1043     time_t modTime;
1044     if (!getFileModificationTime(m_userStyleSheetPath, modTime)) {
1045         // The stylesheet either doesn't exist, was just deleted, or is
1046         // otherwise unreadable. If we've read the stylesheet before, we should
1047         // throw away that data now as it no longer represents what's on disk.
1048         m_userStyleSheet = String();
1049         return m_userStyleSheet;
1050     }
1051
1052     // If the stylesheet hasn't changed since the last time we read it, we can
1053     // just return the old data.
1054     if (m_didLoadUserStyleSheet && modTime <= m_userStyleSheetModificationTime)
1055         return m_userStyleSheet;
1056
1057     m_didLoadUserStyleSheet = true;
1058     m_userStyleSheet = String();
1059     m_userStyleSheetModificationTime = modTime;
1060
1061     // FIXME: It would be better to load this asynchronously to avoid blocking
1062     // the process, but we will first need to create an asynchronous loading
1063     // mechanism that is not tied to a particular Frame. We will also have to
1064     // determine what our behavior should be before the stylesheet is loaded
1065     // and what should happen when it finishes loading, especially with respect
1066     // to when the load event fires, when Document::close is called, and when
1067     // layout/paint are allowed to happen.
1068     RefPtr<SharedBuffer> data = SharedBuffer::createWithContentsOfFile(m_userStyleSheetPath);
1069     if (!data)
1070         return m_userStyleSheet;
1071
1072     m_userStyleSheet = TextResourceDecoder::create("text/css")->decodeAndFlush(data->data(), data->size());
1073
1074     return m_userStyleSheet;
1075 }
1076
1077 void Page::invalidateStylesForAllLinks()
1078 {
1079     for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
1080         frame->document()->visitedLinkState().invalidateStyleForAllLinks();
1081 }
1082
1083 void Page::invalidateStylesForLink(LinkHash linkHash)
1084 {
1085     for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
1086         frame->document()->visitedLinkState().invalidateStyleForLink(linkHash);
1087 }
1088
1089 void Page::setDebugger(JSC::Debugger* debugger)
1090 {
1091     if (m_debugger == debugger)
1092         return;
1093
1094     m_debugger = debugger;
1095
1096     for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
1097         frame->script().attachDebugger(m_debugger);
1098 }
1099
1100 StorageNamespace* Page::sessionStorage(bool optionalCreate)
1101 {
1102     if (!m_sessionStorage && optionalCreate)
1103         m_sessionStorage = m_storageNamespaceProvider->createSessionStorageNamespace(*this, m_settings->sessionStorageQuota());
1104
1105     return m_sessionStorage.get();
1106 }
1107
1108 void Page::setSessionStorage(RefPtr<StorageNamespace>&& newStorage)
1109 {
1110     m_sessionStorage = WTF::move(newStorage);
1111 }
1112
1113 bool Page::hasCustomHTMLTokenizerTimeDelay() const
1114 {
1115     return m_settings->maxParseDuration() != -1;
1116 }
1117
1118 double Page::customHTMLTokenizerTimeDelay() const
1119 {
1120     ASSERT(m_settings->maxParseDuration() != -1);
1121     return m_settings->maxParseDuration();
1122 }
1123
1124 void Page::setMemoryCacheClientCallsEnabled(bool enabled)
1125 {
1126     if (m_areMemoryCacheClientCallsEnabled == enabled)
1127         return;
1128
1129     m_areMemoryCacheClientCallsEnabled = enabled;
1130     if (!enabled)
1131         return;
1132
1133     for (RefPtr<Frame> frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1134         frame->loader().tellClientAboutPastMemoryCacheLoads();
1135 }
1136
1137 void Page::hiddenPageDOMTimerThrottlingStateChanged()
1138 {
1139     setTimerThrottlingEnabled(m_viewState & ViewState::IsVisuallyIdle);
1140 }
1141
1142 void Page::setTimerThrottlingEnabled(bool enabled)
1143 {
1144 #if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
1145     if (!m_settings->hiddenPageDOMTimerThrottlingEnabled())
1146         enabled = false;
1147 #endif
1148
1149     if (enabled == m_timerThrottlingEnabled)
1150         return;
1151
1152     m_timerThrottlingEnabled = enabled;
1153     m_settings->setDOMTimerAlignmentInterval(enabled ? DOMTimer::hiddenPageAlignmentInterval() : DOMTimer::defaultAlignmentInterval());
1154     
1155     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1156         if (frame->document())
1157             frame->document()->didChangeTimerAlignmentInterval();
1158     }
1159 }
1160
1161 void Page::dnsPrefetchingStateChanged()
1162 {
1163     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1164         frame->document()->initDNSPrefetch();
1165 }
1166
1167 Vector<Ref<PluginViewBase>> Page::pluginViews()
1168 {
1169     Vector<Ref<PluginViewBase>> views;
1170
1171     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1172         FrameView* view = frame->view();
1173         if (!view)
1174             break;
1175
1176         for (auto& widget : view->children()) {
1177             if (is<PluginViewBase>(*widget))
1178                 views.append(downcast<PluginViewBase>(*widget));
1179         }
1180     }
1181
1182     return views;
1183 }
1184
1185 void Page::storageBlockingStateChanged()
1186 {
1187     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1188         frame->document()->storageBlockingStateDidChange();
1189
1190     // Collect the PluginViews in to a vector to ensure that action the plug-in takes
1191     // from below storageBlockingStateChanged does not affect their lifetime.
1192     for (auto& view : pluginViews())
1193         view->storageBlockingStateChanged();
1194 }
1195
1196 void Page::enableLegacyPrivateBrowsing(bool privateBrowsingEnabled)
1197 {
1198     // Don't allow changing the legacy private browsing state if we have set a session ID.
1199     ASSERT(m_sessionID == SessionID::defaultSessionID() || m_sessionID == SessionID::legacyPrivateSessionID());
1200
1201     setSessionID(privateBrowsingEnabled ? SessionID::legacyPrivateSessionID() : SessionID::defaultSessionID());
1202 }
1203
1204 void Page::updateIsPlayingMedia()
1205 {
1206     MediaProducer::MediaStateFlags state = MediaProducer::IsNotPlaying;
1207     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1208         state |= frame->document()->mediaState();
1209     }
1210
1211     if (state == m_mediaState)
1212         return;
1213
1214     m_mediaState = state;
1215
1216     chrome().client().isPlayingMediaDidChange(state);
1217 }
1218
1219 void Page::setMuted(bool muted)
1220 {
1221     if (m_muted == muted)
1222         return;
1223
1224     m_muted = muted;
1225
1226     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1227         frame->document()->pageMutedStateDidChange();
1228 }
1229
1230 #if !ASSERT_DISABLED
1231 void Page::checkSubframeCountConsistency() const
1232 {
1233     ASSERT(m_subframeCount >= 0);
1234
1235     int subframeCount = 0;
1236     for (const Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1237         ++subframeCount;
1238
1239     ASSERT(m_subframeCount + 1 == subframeCount);
1240 }
1241 #endif
1242
1243 void Page::resumeAnimatingImages()
1244 {
1245     // Drawing models which cache painted content while out-of-window (WebKit2's composited drawing areas, etc.)
1246     // require that we repaint animated images to kickstart the animation loop.
1247     if (FrameView* view = mainFrame().view())
1248         view->resumeVisibleImageAnimationsIncludingSubframes();
1249 }
1250
1251 void Page::setViewState(ViewState::Flags viewState)
1252 {
1253     ViewState::Flags changed = m_viewState ^ viewState;
1254     if (!changed)
1255         return;
1256
1257     ViewState::Flags oldViewState = m_viewState;
1258
1259     m_viewState = viewState;
1260     m_focusController->setViewState(viewState);
1261
1262     if (changed & ViewState::IsVisible)
1263         setIsVisibleInternal(viewState & ViewState::IsVisible);
1264     if (changed & ViewState::IsInWindow)
1265         setIsInWindowInternal(viewState & ViewState::IsInWindow);
1266     if (changed & ViewState::IsVisuallyIdle)
1267         setIsVisuallyIdleInternal(viewState & ViewState::IsVisuallyIdle);
1268
1269     for (auto* observer : m_viewStateChangeObservers)
1270         observer->viewStateDidChange(oldViewState, m_viewState);
1271 }
1272
1273 void Page::setPageActivityState(PageActivityState::Flags activityState)
1274 {
1275     chrome().client().setPageActivityState(activityState);
1276 }
1277
1278 void Page::setIsVisible(bool isVisible)
1279 {
1280     if (isVisible)
1281         setViewState((m_viewState & ~ViewState::IsVisuallyIdle) | ViewState::IsVisible | ViewState::IsVisibleOrOccluded);
1282     else
1283         setViewState((m_viewState & ~(ViewState::IsVisible | ViewState::IsVisibleOrOccluded)) | ViewState::IsVisuallyIdle);
1284 }
1285
1286 void Page::setIsVisibleInternal(bool isVisible)
1287 {
1288     // FIXME: The visibility state should be stored on the top-level document.
1289     // https://bugs.webkit.org/show_bug.cgi?id=116769
1290
1291     if (isVisible) {
1292         m_isPrerender = false;
1293
1294         resumeScriptedAnimations();
1295
1296         if (FrameView* view = mainFrame().view())
1297             view->show();
1298
1299         if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
1300             mainFrame().animation().resumeAnimations();
1301
1302         resumeAnimatingImages();
1303     }
1304
1305     Vector<Ref<Document>> documents;
1306     for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
1307         documents.append(*frame->document());
1308
1309     for (auto& document : documents)
1310         document->visibilityStateChanged();
1311
1312     if (!isVisible) {
1313         if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
1314             mainFrame().animation().suspendAnimations();
1315
1316         suspendScriptedAnimations();
1317
1318         if (FrameView* view = mainFrame().view())
1319             view->hide();
1320     }
1321 }
1322
1323 void Page::setIsPrerender()
1324 {
1325     m_isPrerender = true;
1326 }
1327
1328 PageVisibilityState Page::visibilityState() const
1329 {
1330     if (isVisible())
1331         return PageVisibilityStateVisible;
1332     if (m_isPrerender)
1333         return PageVisibilityStatePrerender;
1334     return PageVisibilityStateHidden;
1335 }
1336
1337 #if ENABLE(RUBBER_BANDING)
1338 void Page::addHeaderWithHeight(int headerHeight)
1339 {
1340     m_headerHeight = headerHeight;
1341
1342     FrameView* frameView = mainFrame().view();
1343     if (!frameView)
1344         return;
1345
1346     RenderView* renderView = frameView->renderView();
1347     if (!renderView)
1348         return;
1349
1350     frameView->setHeaderHeight(m_headerHeight);
1351     renderView->compositor().updateLayerForHeader(m_headerHeight);
1352 }
1353
1354 void Page::addFooterWithHeight(int footerHeight)
1355 {
1356     m_footerHeight = footerHeight;
1357
1358     FrameView* frameView = mainFrame().view();
1359     if (!frameView)
1360         return;
1361
1362     RenderView* renderView = frameView->renderView();
1363     if (!renderView)
1364         return;
1365
1366     frameView->setFooterHeight(m_footerHeight);
1367     renderView->compositor().updateLayerForFooter(m_footerHeight);
1368 }
1369 #endif
1370
1371 #if ENABLE(REMOTE_INSPECTOR)
1372 bool Page::remoteInspectionAllowed() const
1373 {
1374     return m_inspectorDebuggable->remoteDebuggingAllowed();
1375 }
1376
1377 void Page::setRemoteInspectionAllowed(bool allowed)
1378 {
1379     m_inspectorDebuggable->setRemoteDebuggingAllowed(allowed);
1380 }
1381
1382 void Page::remoteInspectorInformationDidChange() const
1383 {
1384     m_inspectorDebuggable->update();
1385 }
1386 #endif
1387
1388 void Page::addLayoutMilestones(LayoutMilestones milestones)
1389 {
1390     // In the future, we may want a function that replaces m_layoutMilestones instead of just adding to it.
1391     m_requestedLayoutMilestones |= milestones;
1392 }
1393
1394 void Page::removeLayoutMilestones(LayoutMilestones milestones)
1395 {
1396     m_requestedLayoutMilestones &= ~milestones;
1397 }
1398
1399 Color Page::pageExtendedBackgroundColor() const
1400 {
1401     FrameView* frameView = mainFrame().view();
1402     if (!frameView)
1403         return Color();
1404
1405     RenderView* renderView = frameView->renderView();
1406     if (!renderView)
1407         return Color();
1408
1409     return renderView->compositor().rootExtendedBackgroundColor();
1410 }
1411
1412 // These are magical constants that might be tweaked over time.
1413 static const double gMinimumPaintedAreaRatio = 0.1;
1414 static const double gMaximumUnpaintedAreaRatio = 0.04;
1415
1416 bool Page::isCountingRelevantRepaintedObjects() const
1417 {
1418     return m_isCountingRelevantRepaintedObjects && (m_requestedLayoutMilestones & DidHitRelevantRepaintedObjectsAreaThreshold);
1419 }
1420
1421 void Page::startCountingRelevantRepaintedObjects()
1422 {
1423     // Reset everything in case we didn't hit the threshold last time.
1424     resetRelevantPaintedObjectCounter();
1425
1426     m_isCountingRelevantRepaintedObjects = true;
1427 }
1428
1429 void Page::resetRelevantPaintedObjectCounter()
1430 {
1431     m_isCountingRelevantRepaintedObjects = false;
1432     m_relevantUnpaintedRenderObjects.clear();
1433     m_topRelevantPaintedRegion = Region();
1434     m_bottomRelevantPaintedRegion = Region();
1435     m_relevantUnpaintedRegion = Region();
1436 }
1437
1438 static LayoutRect relevantViewRect(RenderView* view)
1439 {
1440     // DidHitRelevantRepaintedObjectsAreaThreshold is a LayoutMilestone intended to indicate that
1441     // a certain relevant amount of content has been drawn to the screen. This is the rect that
1442     // has been determined to be relevant in the context of this goal. We may choose to tweak
1443     // the rect over time, much like we may choose to tweak gMinimumPaintedAreaRatio and
1444     // gMaximumUnpaintedAreaRatio. But this seems to work well right now.
1445     LayoutRect relevantViewRect = LayoutRect(0, 0, 980, 1300);
1446
1447     LayoutRect viewRect = view->viewRect();
1448     // If the viewRect is wider than the relevantViewRect, center the relevantViewRect.
1449     if (viewRect.width() > relevantViewRect.width())
1450         relevantViewRect.setX((viewRect.width() - relevantViewRect.width()) / 2);
1451
1452     return relevantViewRect;
1453 }
1454
1455 void Page::addRelevantRepaintedObject(RenderObject* object, const LayoutRect& objectPaintRect)
1456 {
1457     if (!isCountingRelevantRepaintedObjects())
1458         return;
1459
1460     // Objects inside sub-frames are not considered to be relevant.
1461     if (&object->frame() != &mainFrame())
1462         return;
1463
1464     LayoutRect relevantRect = relevantViewRect(&object->view());
1465
1466     // The objects are only relevant if they are being painted within the viewRect().
1467     if (!objectPaintRect.intersects(snappedIntRect(relevantRect)))
1468         return;
1469
1470     IntRect snappedPaintRect = snappedIntRect(objectPaintRect);
1471
1472     // If this object was previously counted as an unpainted object, remove it from that HashSet
1473     // and corresponding Region. FIXME: This doesn't do the right thing if the objects overlap.
1474     if (m_relevantUnpaintedRenderObjects.remove(object))
1475         m_relevantUnpaintedRegion.subtract(snappedPaintRect);
1476
1477     // Split the relevantRect into a top half and a bottom half. Making sure we have coverage in
1478     // both halves helps to prevent cases where we have a fully loaded menu bar or masthead with
1479     // no content beneath that.
1480     LayoutRect topRelevantRect = relevantRect;
1481     topRelevantRect.contract(LayoutSize(0, relevantRect.height() / 2));
1482     LayoutRect bottomRelevantRect = topRelevantRect;
1483     bottomRelevantRect.setY(relevantRect.height() / 2);
1484
1485     // If the rect straddles both Regions, split it appropriately.
1486     if (topRelevantRect.intersects(snappedPaintRect) && bottomRelevantRect.intersects(snappedPaintRect)) {
1487         IntRect topIntersection = snappedPaintRect;
1488         topIntersection.intersect(snappedIntRect(topRelevantRect));
1489         m_topRelevantPaintedRegion.unite(topIntersection);
1490
1491         IntRect bottomIntersection = snappedPaintRect;
1492         bottomIntersection.intersect(snappedIntRect(bottomRelevantRect));
1493         m_bottomRelevantPaintedRegion.unite(bottomIntersection);
1494     } else if (topRelevantRect.intersects(snappedPaintRect))
1495         m_topRelevantPaintedRegion.unite(snappedPaintRect);
1496     else
1497         m_bottomRelevantPaintedRegion.unite(snappedPaintRect);
1498
1499     float topPaintedArea = m_topRelevantPaintedRegion.totalArea();
1500     float bottomPaintedArea = m_bottomRelevantPaintedRegion.totalArea();
1501     float viewArea = relevantRect.width() * relevantRect.height();
1502
1503     float ratioThatIsPaintedOnTop = topPaintedArea / viewArea;
1504     float ratioThatIsPaintedOnBottom = bottomPaintedArea / viewArea;
1505     float ratioOfViewThatIsUnpainted = m_relevantUnpaintedRegion.totalArea() / viewArea;
1506
1507     if (ratioThatIsPaintedOnTop > (gMinimumPaintedAreaRatio / 2) && ratioThatIsPaintedOnBottom > (gMinimumPaintedAreaRatio / 2)
1508         && ratioOfViewThatIsUnpainted < gMaximumUnpaintedAreaRatio) {
1509         m_isCountingRelevantRepaintedObjects = false;
1510         resetRelevantPaintedObjectCounter();
1511         if (Frame* frame = &mainFrame())
1512             frame->loader().didLayout(DidHitRelevantRepaintedObjectsAreaThreshold);
1513     }
1514 }
1515
1516 void Page::addRelevantUnpaintedObject(RenderObject* object, const LayoutRect& objectPaintRect)
1517 {
1518     if (!isCountingRelevantRepaintedObjects())
1519         return;
1520
1521     // The objects are only relevant if they are being painted within the relevantViewRect().
1522     if (!objectPaintRect.intersects(snappedIntRect(relevantViewRect(&object->view()))))
1523         return;
1524
1525     m_relevantUnpaintedRenderObjects.add(object);
1526     m_relevantUnpaintedRegion.unite(snappedIntRect(objectPaintRect));
1527 }
1528
1529 void Page::suspendActiveDOMObjectsAndAnimations()
1530 {
1531     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1532         frame->suspendActiveDOMObjectsAndAnimations();
1533 }
1534
1535 void Page::resumeActiveDOMObjectsAndAnimations()
1536 {
1537     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1538         frame->resumeActiveDOMObjectsAndAnimations();
1539
1540     resumeAnimatingImages();
1541 }
1542
1543 bool Page::hasSeenAnyPlugin() const
1544 {
1545     return !m_seenPlugins.isEmpty();
1546 }
1547
1548 bool Page::hasSeenPlugin(const String& serviceType) const
1549 {
1550     return m_seenPlugins.contains(serviceType);
1551 }
1552
1553 void Page::sawPlugin(const String& serviceType)
1554 {
1555     m_seenPlugins.add(serviceType);
1556 }
1557
1558 void Page::resetSeenPlugins()
1559 {
1560     m_seenPlugins.clear();
1561 }
1562
1563 bool Page::hasSeenAnyMediaEngine() const
1564 {
1565     return !m_seenMediaEngines.isEmpty();
1566 }
1567
1568 bool Page::hasSeenMediaEngine(const String& engineDescription) const
1569 {
1570     return m_seenMediaEngines.contains(engineDescription);
1571 }
1572
1573 void Page::sawMediaEngine(const String& engineDescription)
1574 {
1575     m_seenMediaEngines.add(engineDescription);
1576 }
1577
1578 void Page::resetSeenMediaEngines()
1579 {
1580     m_seenMediaEngines.clear();
1581 }
1582
1583 void Page::hiddenPageCSSAnimationSuspensionStateChanged()
1584 {
1585     if (!isVisible()) {
1586         if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
1587             mainFrame().animation().suspendAnimations();
1588         else
1589             mainFrame().animation().resumeAnimations();
1590     }
1591 }
1592
1593 #if ENABLE(VIDEO_TRACK)
1594 void Page::captionPreferencesChanged()
1595 {
1596     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1597         frame->document()->captionPreferencesChanged();
1598 }
1599 #endif
1600
1601 void Page::incrementFrameHandlingBeforeUnloadEventCount()
1602 {
1603     ++m_framesHandlingBeforeUnloadEvent;
1604 }
1605
1606 void Page::decrementFrameHandlingBeforeUnloadEventCount()
1607 {
1608     ASSERT(m_framesHandlingBeforeUnloadEvent);
1609     --m_framesHandlingBeforeUnloadEvent;
1610 }
1611
1612 bool Page::isAnyFrameHandlingBeforeUnloadEvent()
1613 {
1614     return m_framesHandlingBeforeUnloadEvent;
1615 }
1616
1617 void Page::setUserContentController(UserContentController* userContentController)
1618 {
1619     if (m_userContentController)
1620         m_userContentController->removePage(*this);
1621
1622     m_userContentController = userContentController;
1623
1624     if (m_userContentController)
1625         m_userContentController->addPage(*this);
1626
1627     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1628         if (Document *document = frame->document()) {
1629             document->styleSheetCollection().invalidateInjectedStyleSheetCache();
1630             document->styleResolverChanged(DeferRecalcStyle);
1631         }
1632     }
1633 }
1634
1635 void Page::setStorageNamespaceProvider(Ref<StorageNamespaceProvider>&& storageNamespaceProvider)
1636 {
1637     m_storageNamespaceProvider->removePage(*this);
1638     m_storageNamespaceProvider = WTF::move(storageNamespaceProvider);
1639     m_storageNamespaceProvider->addPage(*this);
1640
1641     // This needs to reset all the local storage namespaces of all the pages.
1642 }
1643
1644 VisitedLinkStore& Page::visitedLinkStore()
1645 {
1646     return m_visitedLinkStore;
1647 }
1648
1649 void Page::setVisitedLinkStore(Ref<VisitedLinkStore>&& visitedLinkStore)
1650 {
1651     m_visitedLinkStore->removePage(*this);
1652     m_visitedLinkStore = WTF::move(visitedLinkStore);
1653     m_visitedLinkStore->addPage(*this);
1654
1655     invalidateStylesForAllLinks();
1656     PageCache::singleton().markPagesForFullStyleRecalc(*this);
1657 }
1658
1659 SessionID Page::sessionID() const
1660 {
1661     return m_sessionID;
1662 }
1663
1664 void Page::setSessionID(SessionID sessionID)
1665 {
1666     ASSERT(sessionID.isValid());
1667
1668     bool privateBrowsingStateChanged = (sessionID.isEphemeral() != m_sessionID.isEphemeral());
1669
1670     m_sessionID = sessionID;
1671
1672     if (!privateBrowsingStateChanged)
1673         return;
1674
1675     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1676         frame->document()->privateBrowsingStateDidChange();
1677
1678     // Collect the PluginViews in to a vector to ensure that action the plug-in takes
1679     // from below privateBrowsingStateChanged does not affect their lifetime.
1680
1681     for (auto& view : pluginViews())
1682         view->privateBrowsingStateChanged(sessionID.isEphemeral());
1683 }
1684
1685 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
1686 void Page::addPlaybackTargetPickerClient(uint64_t contextId)
1687 {
1688     chrome().client().addPlaybackTargetPickerClient(contextId);
1689 }
1690
1691 void Page::removePlaybackTargetPickerClient(uint64_t contextId)
1692 {
1693     chrome().client().removePlaybackTargetPickerClient(contextId);
1694 }
1695
1696 void Page::showPlaybackTargetPicker(uint64_t contextId, const WebCore::IntPoint& location, bool isVideo)
1697 {
1698 #if PLATFORM(IOS)
1699     // FIXME: refactor iOS implementation.
1700     UNUSED_PARAM(contextId);
1701     UNUSED_PARAM(location);
1702     chrome().client().showPlaybackTargetPicker(isVideo);
1703 #else
1704     chrome().client().showPlaybackTargetPicker(contextId, location, isVideo);
1705 #endif
1706 }
1707
1708 void Page::playbackTargetPickerClientStateDidChange(uint64_t contextId, MediaProducer::MediaStateFlags state)
1709 {
1710     chrome().client().playbackTargetPickerClientStateDidChange(contextId, state);
1711 }
1712
1713 void Page::setPlaybackTarget(uint64_t contextId, Ref<MediaPlaybackTarget>&& target)
1714 {
1715     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1716         frame->document()->setPlaybackTarget(contextId, target.copyRef());
1717 }
1718
1719 void Page::playbackTargetAvailabilityDidChange(uint64_t contextId, bool available)
1720 {
1721     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1722         frame->document()->playbackTargetAvailabilityDidChange(contextId, available);
1723 }
1724
1725 void Page::setShouldPlayToPlaybackTarget(uint64_t clientId, bool shouldPlay)
1726 {
1727     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1728         frame->document()->setShouldPlayToPlaybackTarget(clientId, shouldPlay);
1729 }
1730 #endif
1731
1732 WheelEventTestTrigger& Page::ensureTestTrigger()
1733 {
1734     if (!m_testTrigger)
1735         m_testTrigger = adoptRef(new WheelEventTestTrigger());
1736
1737     return *m_testTrigger;
1738 }
1739
1740 } // namespace WebCore