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