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