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