2 * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
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.
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.
23 #include "ActivityStateChangeObserver.h"
24 #include "AlternativeTextClient.h"
25 #include "ApplicationCacheStorage.h"
26 #include "ApplicationStateChangeListener.h"
27 #include "AuthenticatorCoordinator.h"
28 #include "BackForwardCache.h"
29 #include "BackForwardClient.h"
30 #include "BackForwardController.h"
31 #include "CSSAnimationController.h"
32 #include "CacheStorageProvider.h"
34 #include "ChromeClient.h"
35 #include "ConstantPropertyMap.h"
36 #include "ContextMenuClient.h"
37 #include "ContextMenuController.h"
38 #include "CookieJar.h"
39 #include "CustomHeaderFields.h"
41 #include "DOMRectList.h"
42 #include "DatabaseProvider.h"
43 #include "DiagnosticLoggingClient.h"
44 #include "DiagnosticLoggingKeys.h"
45 #include "DocumentLoader.h"
46 #include "DocumentMarkerController.h"
47 #include "DocumentTimeline.h"
48 #include "DragController.h"
51 #include "EditorClient.h"
52 #include "EmptyClients.h"
54 #include "EventNames.h"
55 #include "ExtensionStyleSheets.h"
56 #include "FocusController.h"
57 #include "FrameLoader.h"
58 #include "FrameLoaderClient.h"
59 #include "FrameSelection.h"
60 #include "FrameTree.h"
61 #include "FrameView.h"
62 #include "FullscreenManager.h"
63 #include "HTMLElement.h"
64 #include "HTMLMediaElement.h"
65 #include "HistoryController.h"
66 #include "HistoryItem.h"
67 #include "InspectorClient.h"
68 #include "InspectorController.h"
69 #include "InspectorInstrumentation.h"
70 #include "LegacySchemeRegistry.h"
71 #include "LibWebRTCProvider.h"
72 #include "LoaderStrategy.h"
74 #include "LowPowerModeNotifier.h"
75 #include "MediaCanStartListener.h"
76 #include "Navigator.h"
77 #include "PageConfiguration.h"
78 #include "PageConsoleClient.h"
79 #include "PageDebuggable.h"
80 #include "PageGroup.h"
81 #include "PageOverlayController.h"
82 #include "PaymentCoordinator.h"
83 #include "PerformanceLogging.h"
84 #include "PerformanceLoggingClient.h"
85 #include "PerformanceMonitor.h"
86 #include "PlatformMediaSessionManager.h"
87 #include "PlatformStrategies.h"
88 #include "PlugInClient.h"
89 #include "PluginData.h"
90 #include "PluginInfoProvider.h"
91 #include "PluginViewBase.h"
92 #include "PointerCaptureController.h"
93 #include "PointerLockController.h"
94 #include "ProgressTracker.h"
95 #include "RenderDescendantIterator.h"
96 #include "RenderLayerCompositor.h"
97 #include "RenderTheme.h"
98 #include "RenderView.h"
99 #include "RenderWidget.h"
100 #include "ResizeObserver.h"
101 #include "ResourceUsageOverlay.h"
102 #include "RuntimeEnabledFeatures.h"
103 #include "SVGDocumentExtensions.h"
104 #include "ScriptController.h"
105 #include "ScriptedAnimationController.h"
106 #include "ScrollLatchingState.h"
107 #include "ScrollingCoordinator.h"
108 #include "Settings.h"
109 #include "SharedBuffer.h"
110 #include "SocketProvider.h"
111 #include "StorageArea.h"
112 #include "StorageNamespace.h"
113 #include "StorageNamespaceProvider.h"
114 #include "StyleResolver.h"
115 #include "StyleScope.h"
116 #include "SubframeLoader.h"
117 #include "TextIterator.h"
118 #include "TextResourceDecoder.h"
119 #include "UserContentProvider.h"
120 #include "UserInputBridge.h"
121 #include "ValidationMessageClient.h"
122 #include "VisitedLinkState.h"
123 #include "VisitedLinkStore.h"
124 #include "VoidCallback.h"
125 #include "WheelEventDeltaFilter.h"
127 #include <wtf/FileSystem.h>
128 #include <wtf/RefCountedLeakCounter.h>
129 #include <wtf/StdLibExtras.h>
130 #include <wtf/SystemTracing.h>
131 #include <wtf/text/Base64.h>
132 #include <wtf/text/StringHash.h>
134 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
135 #include "HTMLVideoElement.h"
136 #include "MediaPlaybackTarget.h"
140 #include "ServicesOverlayController.h"
143 #if ENABLE(MEDIA_SESSION)
144 #include "MediaSessionManager.h"
147 #if ENABLE(INDEXED_DATABASE)
148 #include "IDBConnectionToServer.h"
149 #include "InProcessIDBServer.h"
152 #if ENABLE(DATA_INTERACTION)
153 #include "SelectionRect.h"
157 #include "WebGLStateTracker.h"
162 static HashSet<Page*>& allPages()
164 static NeverDestroyed<HashSet<Page*>> set;
168 static unsigned nonUtilityPageCount { 0 };
170 static inline bool isUtilityPageChromeClient(ChromeClient& chromeClient)
172 return chromeClient.isEmptyChromeClient() || chromeClient.isSVGImageChromeClient();
175 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, pageCounter, ("Page"));
177 void Page::forEachPage(const WTF::Function<void(Page&)>& function)
179 for (auto* page : allPages())
183 void Page::updateValidationBubbleStateIfNeeded()
185 if (auto* client = validationMessageClient())
186 client->updateValidationBubbleStateIfNeeded();
189 static void networkStateChanged(bool isOnLine)
191 Vector<Ref<Frame>> frames;
193 // Get all the frames of all the pages in all the page groups
194 for (auto* page : allPages()) {
195 for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext())
196 frames.append(*frame);
197 InspectorInstrumentation::networkStateChanged(*page);
200 auto& eventName = isOnLine ? eventNames().onlineEvent : eventNames().offlineEvent;
201 for (auto& frame : frames) {
202 if (!frame->document())
204 frame->document()->dispatchWindowEvent(Event::create(eventName, Event::CanBubble::No, Event::IsCancelable::No));
208 static constexpr OptionSet<ActivityState::Flag> pageInitialActivityState()
210 return { ActivityState::IsVisible, ActivityState::IsInWindow };
213 Page::Page(PageConfiguration&& pageConfiguration)
214 : m_chrome(makeUnique<Chrome>(*this, *pageConfiguration.chromeClient))
215 , m_dragCaretController(makeUnique<DragCaretController>())
216 #if ENABLE(DRAG_SUPPORT)
217 , m_dragController(makeUnique<DragController>(*this, *pageConfiguration.dragClient))
219 , m_focusController(makeUnique<FocusController>(*this, pageInitialActivityState()))
220 #if ENABLE(CONTEXT_MENUS)
221 , m_contextMenuController(makeUnique<ContextMenuController>(*this, *pageConfiguration.contextMenuClient))
223 , m_userInputBridge(makeUnique<UserInputBridge>(*this))
224 , m_inspectorController(makeUnique<InspectorController>(*this, pageConfiguration.inspectorClient))
225 #if ENABLE(POINTER_EVENTS)
226 , m_pointerCaptureController(makeUnique<PointerCaptureController>(*this))
228 #if ENABLE(POINTER_LOCK)
229 , m_pointerLockController(makeUnique<PointerLockController>(*this))
231 , m_settings(Settings::create(this))
232 , m_progress(makeUnique<ProgressTracker>(*pageConfiguration.progressTrackerClient))
233 , m_backForwardController(makeUnique<BackForwardController>(*this, WTFMove(pageConfiguration.backForwardClient)))
234 , m_mainFrame(Frame::create(this, nullptr, pageConfiguration.loaderClientForMainFrame))
235 , m_editorClient(WTFMove(pageConfiguration.editorClient))
236 , m_plugInClient(pageConfiguration.plugInClient)
237 , m_validationMessageClient(WTFMove(pageConfiguration.validationMessageClient))
238 , m_diagnosticLoggingClient(WTFMove(pageConfiguration.diagnosticLoggingClient))
239 , m_performanceLoggingClient(WTFMove(pageConfiguration.performanceLoggingClient))
241 , m_webGLStateTracker(WTFMove(pageConfiguration.webGLStateTracker))
243 #if ENABLE(SPEECH_SYNTHESIS)
244 , m_speechSynthesisClient(WTFMove(pageConfiguration.speechSynthesisClient))
246 , m_libWebRTCProvider(WTFMove(pageConfiguration.libWebRTCProvider))
247 , m_verticalScrollElasticity(ScrollElasticityAllowed)
248 , m_horizontalScrollElasticity(ScrollElasticityAllowed)
249 , m_domTimerAlignmentInterval(DOMTimer::defaultAlignmentInterval())
250 , m_domTimerAlignmentIntervalIncreaseTimer(*this, &Page::domTimerAlignmentIntervalIncreaseTimerFired)
251 , m_activityState(pageInitialActivityState())
252 , m_alternativeTextClient(pageConfiguration.alternativeTextClient)
253 , m_consoleClient(makeUnique<PageConsoleClient>(*this))
254 #if ENABLE(REMOTE_INSPECTOR)
255 , m_inspectorDebuggable(makeUnique<PageDebuggable>(*this))
257 , m_socketProvider(WTFMove(pageConfiguration.socketProvider))
258 , m_cookieJar(WTFMove(pageConfiguration.cookieJar))
259 , m_applicationCacheStorage(*WTFMove(pageConfiguration.applicationCacheStorage))
260 , m_cacheStorageProvider(WTFMove(pageConfiguration.cacheStorageProvider))
261 , m_databaseProvider(*WTFMove(pageConfiguration.databaseProvider))
262 , m_pluginInfoProvider(*WTFMove(pageConfiguration.pluginInfoProvider))
263 , m_storageNamespaceProvider(*WTFMove(pageConfiguration.storageNamespaceProvider))
264 , m_userContentProvider(*WTFMove(pageConfiguration.userContentProvider))
265 , m_visitedLinkStore(*WTFMove(pageConfiguration.visitedLinkStore))
266 , m_sessionID(pageConfiguration.sessionID)
268 , m_playbackControlsManagerUpdateTimer(*this, &Page::playbackControlsManagerUpdateTimerFired)
270 , m_isUtilityPage(isUtilityPageChromeClient(chrome().client()))
271 , m_performanceMonitor(isUtilityPage() ? nullptr : makeUnique<PerformanceMonitor>(*this))
272 , m_lowPowerModeNotifier(makeUnique<LowPowerModeNotifier>([this](bool isLowPowerModeEnabled) { handleLowModePowerChange(isLowPowerModeEnabled); }))
273 , m_performanceLogging(makeUnique<PerformanceLogging>(*this))
274 #if PLATFORM(MAC) && (ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION))
275 , m_servicesOverlayController(makeUnique<ServicesOverlayController>(*this))
277 , m_recentWheelEventDeltaFilter(WheelEventDeltaFilter::create())
278 , m_pageOverlayController(makeUnique<PageOverlayController>(*this))
279 #if ENABLE(APPLE_PAY)
280 , m_paymentCoordinator(makeUnique<PaymentCoordinator>(*pageConfiguration.paymentCoordinatorClient))
282 #if ENABLE(WEB_AUTHN)
283 , m_authenticatorCoordinator(makeUniqueRef<AuthenticatorCoordinator>(WTFMove(pageConfiguration.authenticatorCoordinatorClient)))
285 #if ENABLE(APPLICATION_MANIFEST)
286 , m_applicationManifest(pageConfiguration.applicationManifest)
289 updateTimerThrottlingState();
291 m_pluginInfoProvider->addPage(*this);
292 m_userContentProvider->addPage(*this);
293 m_visitedLinkStore->addPage(*this);
295 static bool addedListener;
296 if (!addedListener) {
297 platformStrategies()->loaderStrategy()->addOnlineStateChangeListener(&networkStateChanged);
298 addedListener = true;
301 ASSERT(!allPages().contains(this));
302 allPages().add(this);
304 if (!isUtilityPage()) {
305 ++nonUtilityPageCount;
306 MemoryPressureHandler::setPageCount(nonUtilityPageCount);
310 pageCounter.increment();
313 #if ENABLE(REMOTE_INSPECTOR)
314 if (m_inspectorController->inspectorClient() && m_inspectorController->inspectorClient()->allowRemoteInspectionToPageDirectly())
315 m_inspectorDebuggable->init();
319 platformInitialize();
323 m_libWebRTCProvider->supportsVP8(RuntimeEnabledFeatures::sharedFeatures().webRTCVP8CodecEnabled());
329 ASSERT(!m_nestedRunLoopCount);
330 ASSERT(!m_unnestCallback);
332 m_validationMessageClient = nullptr;
333 m_diagnosticLoggingClient = nullptr;
334 m_performanceLoggingClient = nullptr;
335 m_mainFrame->setView(nullptr);
336 setGroupName(String());
337 allPages().remove(this);
338 if (!isUtilityPage()) {
339 --nonUtilityPageCount;
340 MemoryPressureHandler::setPageCount(nonUtilityPageCount);
343 m_settings->pageDestroyed();
345 m_inspectorController->inspectedPageDestroyed();
347 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
348 frame->willDetachPage();
349 frame->detachFromPage();
353 m_plugInClient->pageDestroyed();
354 if (m_alternativeTextClient)
355 m_alternativeTextClient->pageDestroyed();
357 if (m_scrollingCoordinator)
358 m_scrollingCoordinator->pageDestroyed();
360 backForward().close();
361 if (!isUtilityPage())
362 BackForwardCache::singleton().removeAllItemsForPage(*this);
365 pageCounter.decrement();
368 m_pluginInfoProvider->removePage(*this);
369 m_userContentProvider->removePage(*this);
370 m_visitedLinkStore->removePage(*this);
373 void Page::clearPreviousItemFromAllPages(HistoryItem* item)
375 for (auto* page : allPages()) {
376 auto& controller = page->mainFrame().loader().history();
377 if (item == controller.previousItem()) {
378 controller.clearPreviousItem();
384 uint64_t Page::renderTreeSize() const
387 for (const Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
388 if (!frame->document() || !frame->document()->renderView())
390 total += frame->document()->renderView()->rendererCount();
395 OptionSet<DisabledAdaptations> Page::disabledAdaptations() const
397 if (mainFrame().document())
398 return mainFrame().document()->disabledAdaptations();
403 ViewportArguments Page::viewportArguments() const
405 return mainFrame().document() ? mainFrame().document()->viewportArguments() : ViewportArguments();
408 void Page::setOverrideViewportArguments(const Optional<ViewportArguments>& viewportArguments)
410 if (viewportArguments == m_overrideViewportArguments)
413 m_overrideViewportArguments = viewportArguments;
414 if (auto* document = mainFrame().document())
415 document->updateViewportArguments();
418 ScrollingCoordinator* Page::scrollingCoordinator()
420 if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled()) {
421 m_scrollingCoordinator = chrome().client().createScrollingCoordinator(*this);
422 if (!m_scrollingCoordinator)
423 m_scrollingCoordinator = ScrollingCoordinator::create(this);
426 return m_scrollingCoordinator.get();
429 String Page::scrollingStateTreeAsText()
431 if (Document* document = m_mainFrame->document())
432 document->updateLayout();
434 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
435 return scrollingCoordinator->scrollingStateTreeAsText();
440 String Page::synchronousScrollingReasonsAsText()
442 if (Document* document = m_mainFrame->document())
443 document->updateLayout();
445 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
446 return scrollingCoordinator->synchronousScrollingReasonsAsText();
451 Ref<DOMRectList> Page::nonFastScrollableRects()
453 if (Document* document = m_mainFrame->document())
454 document->updateLayout();
456 Vector<IntRect> rects;
457 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
458 const EventTrackingRegions& eventTrackingRegions = scrollingCoordinator->absoluteEventTrackingRegions();
459 for (const auto& synchronousEventRegion : eventTrackingRegions.eventSpecificSynchronousDispatchRegions)
460 rects.appendVector(synchronousEventRegion.value.rects());
463 Vector<FloatQuad> quads(rects.size());
464 for (size_t i = 0; i < rects.size(); ++i)
465 quads[i] = FloatRect(rects[i]);
467 return DOMRectList::create(quads);
470 Ref<DOMRectList> Page::touchEventRectsForEvent(const String& eventName)
472 if (Document* document = m_mainFrame->document()) {
473 document->updateLayout();
474 #if ENABLE(IOS_TOUCH_EVENTS)
475 document->updateTouchEventRegions();
479 Vector<IntRect> rects;
480 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
481 const EventTrackingRegions& eventTrackingRegions = scrollingCoordinator->absoluteEventTrackingRegions();
482 const auto& region = eventTrackingRegions.eventSpecificSynchronousDispatchRegions.get(eventName);
483 rects.appendVector(region.rects());
486 Vector<FloatQuad> quads(rects.size());
487 for (size_t i = 0; i < rects.size(); ++i)
488 quads[i] = FloatRect(rects[i]);
490 return DOMRectList::create(quads);
493 Ref<DOMRectList> Page::passiveTouchEventListenerRects()
495 if (Document* document = m_mainFrame->document()) {
496 document->updateLayout();
497 #if ENABLE(IOS_TOUCH_EVENTS)
498 document->updateTouchEventRegions();
502 Vector<IntRect> rects;
503 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
504 rects.appendVector(scrollingCoordinator->absoluteEventTrackingRegions().asynchronousDispatchRegion.rects());
506 Vector<FloatQuad> quads(rects.size());
507 for (size_t i = 0; i < rects.size(); ++i)
508 quads[i] = FloatRect(rects[i]);
510 return DOMRectList::create(quads);
513 bool Page::openedByDOM() const
515 return m_openedByDOM;
518 void Page::setOpenedByDOM()
520 m_openedByDOM = true;
523 void Page::goToItem(HistoryItem& item, FrameLoadType type, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad)
525 // stopAllLoaders may end up running onload handlers, which could cause further history traversals that may lead to the passed in HistoryItem
526 // being deref()-ed. Make sure we can still use it with HistoryController::goToItem later.
527 Ref<HistoryItem> protector(item);
529 auto& frameLoader = m_mainFrame->loader();
530 if (frameLoader.history().shouldStopLoadingForHistoryItem(item))
531 m_mainFrame->loader().stopAllLoadersAndCheckCompleteness();
533 m_mainFrame->loader().history().goToItem(item, type, shouldTreatAsContinuingLoad);
536 void Page::setGroupName(const String& name)
538 if (m_group && !m_group->name().isEmpty()) {
539 ASSERT(m_group != m_singlePageGroup.get());
540 ASSERT(!m_singlePageGroup);
541 m_group->removePage(*this);
545 m_group = m_singlePageGroup.get();
547 m_singlePageGroup = nullptr;
548 m_group = PageGroup::pageGroup(name);
549 m_group->addPage(*this);
553 const String& Page::groupName() const
555 return m_group ? m_group->name() : nullAtom().string();
558 void Page::initGroup()
560 ASSERT(!m_singlePageGroup);
562 m_singlePageGroup = makeUnique<PageGroup>(*this);
563 m_group = m_singlePageGroup.get();
566 void Page::updateStyleAfterChangeInEnvironment()
568 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
569 // If a change in the global environment has occurred, we need to
570 // make sure all the properties a recomputed, therefore we invalidate
571 // the properties cache.
572 auto* document = frame->document();
576 if (StyleResolver* styleResolver = document->styleScope().resolverIfExists())
577 styleResolver->invalidateMatchedPropertiesCache();
578 document->scheduleFullStyleRebuild();
579 document->styleScope().didChangeStyleSheetEnvironment();
583 void Page::updateStyleForAllPagesAfterGlobalChangeInEnvironment()
585 for (auto* page : allPages())
586 page->updateStyleAfterChangeInEnvironment();
589 void Page::setNeedsRecalcStyleInAllFrames()
591 // FIXME: Figure out what this function is actually trying to add in different call sites.
592 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
593 if (Document* document = frame->document())
594 document->styleScope().didChangeStyleSheetEnvironment();
598 void Page::refreshPlugins(bool reload)
600 HashSet<PluginInfoProvider*> pluginInfoProviders;
602 for (auto* page : allPages())
603 pluginInfoProviders.add(&page->pluginInfoProvider());
605 for (auto& pluginInfoProvider : pluginInfoProviders)
606 pluginInfoProvider->refresh(reload);
609 PluginData& Page::pluginData()
612 m_pluginData = PluginData::create(*this);
613 return *m_pluginData;
616 void Page::clearPluginData()
618 m_pluginData = nullptr;
621 bool Page::showAllPlugins() const
623 if (m_showAllPlugins)
626 if (Document* document = mainFrame().document())
627 return document->securityOrigin().isLocal();
632 inline Optional<std::pair<MediaCanStartListener&, Document&>> Page::takeAnyMediaCanStartListener()
634 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
635 if (!frame->document())
637 if (MediaCanStartListener* listener = frame->document()->takeAnyMediaCanStartListener())
638 return { { *listener, *frame->document() } };
643 void Page::setCanStartMedia(bool canStartMedia)
645 if (m_canStartMedia == canStartMedia)
648 m_canStartMedia = canStartMedia;
650 while (m_canStartMedia) {
651 auto listener = takeAnyMediaCanStartListener();
654 listener->first.mediaCanStart(listener->second);
658 static Frame* incrementFrame(Frame* curr, bool forward, CanWrap canWrap, DidWrap* didWrap = nullptr)
661 ? curr->tree().traverseNext(canWrap, didWrap)
662 : curr->tree().traversePrevious(canWrap, didWrap);
665 bool Page::findString(const String& target, FindOptions options, DidWrap* didWrap)
667 if (target.isEmpty())
670 CanWrap canWrap = options.contains(WrapAround) ? CanWrap::Yes : CanWrap::No;
671 Frame* frame = &focusController().focusedOrMainFrame();
672 Frame* startFrame = frame;
674 if (frame->editor().findString(target, (options - WrapAround) | StartInSelection)) {
675 if (frame != startFrame)
676 startFrame->selection().clear();
677 focusController().setFocusedFrame(frame);
680 frame = incrementFrame(frame, !options.contains(Backwards), canWrap, didWrap);
681 } while (frame && frame != startFrame);
683 // Search contents of startFrame, on the other side of the selection that we did earlier.
684 // We cheat a bit and just research with wrap on
685 if (canWrap == CanWrap::Yes && !startFrame->selection().isNone()) {
687 *didWrap = DidWrap::Yes;
688 bool found = startFrame->editor().findString(target, options | WrapAround | StartInSelection);
689 focusController().setFocusedFrame(frame);
696 void Page::findStringMatchingRanges(const String& target, FindOptions options, int limit, Vector<RefPtr<Range>>& matchRanges, int& indexForSelection)
698 indexForSelection = 0;
700 Frame* frame = &mainFrame();
701 Frame* frameWithSelection = nullptr;
703 frame->editor().countMatchesForText(target, 0, options, limit ? (limit - matchRanges.size()) : 0, true, &matchRanges);
704 if (frame->selection().isRange())
705 frameWithSelection = frame;
706 frame = incrementFrame(frame, true, CanWrap::No);
709 if (matchRanges.isEmpty())
712 if (frameWithSelection) {
713 indexForSelection = NoMatchAfterUserSelection;
714 RefPtr<Range> selectedRange = frameWithSelection->selection().selection().firstRange();
715 if (options.contains(Backwards)) {
716 for (size_t i = matchRanges.size(); i > 0; --i) {
717 auto result = selectedRange->compareBoundaryPoints(Range::END_TO_START, *matchRanges[i - 1]);
718 if (!result.hasException() && result.releaseReturnValue() > 0) {
719 indexForSelection = i - 1;
724 for (size_t i = 0, size = matchRanges.size(); i < size; ++i) {
725 auto result = selectedRange->compareBoundaryPoints(Range::START_TO_END, *matchRanges[i]);
726 if (!result.hasException() && result.releaseReturnValue() < 0) {
727 indexForSelection = i;
733 if (options.contains(Backwards))
734 indexForSelection = matchRanges.size() - 1;
736 indexForSelection = 0;
740 RefPtr<Range> Page::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
742 if (target.isEmpty())
745 if (referenceRange && referenceRange->ownerDocument().page() != this)
748 CanWrap canWrap = options.contains(WrapAround) ? CanWrap::Yes : CanWrap::No;
749 Frame* frame = referenceRange ? referenceRange->ownerDocument().frame() : &mainFrame();
750 Frame* startFrame = frame;
752 if (RefPtr<Range> resultRange = frame->editor().rangeOfString(target, frame == startFrame ? referenceRange : 0, options - WrapAround))
755 frame = incrementFrame(frame, !options.contains(Backwards), canWrap);
756 } while (frame && frame != startFrame);
758 // Search contents of startFrame, on the other side of the reference range that we did earlier.
759 // We cheat a bit and just search again with wrap on.
760 if (canWrap == CanWrap::Yes && referenceRange) {
761 if (RefPtr<Range> resultRange = startFrame->editor().rangeOfString(target, referenceRange, options | WrapAround | StartInSelection))
768 unsigned Page::findMatchesForText(const String& target, FindOptions options, unsigned maxMatchCount, ShouldHighlightMatches shouldHighlightMatches, ShouldMarkMatches shouldMarkMatches)
770 if (target.isEmpty())
773 unsigned matchCount = 0;
775 Frame* frame = &mainFrame();
777 if (shouldMarkMatches == MarkMatches)
778 frame->editor().setMarkedTextMatchesAreHighlighted(shouldHighlightMatches == HighlightMatches);
779 matchCount += frame->editor().countMatchesForText(target, 0, options, maxMatchCount ? (maxMatchCount - matchCount) : 0, shouldMarkMatches == MarkMatches, 0);
780 frame = incrementFrame(frame, true, CanWrap::No);
786 unsigned Page::markAllMatchesForText(const String& target, FindOptions options, bool shouldHighlight, unsigned maxMatchCount)
788 return findMatchesForText(target, options, maxMatchCount, shouldHighlight ? HighlightMatches : DoNotHighlightMatches, MarkMatches);
791 unsigned Page::countFindMatches(const String& target, FindOptions options, unsigned maxMatchCount)
793 return findMatchesForText(target, options, maxMatchCount, DoNotHighlightMatches, DoNotMarkMatches);
796 struct FindReplacementRange {
797 RefPtr<ContainerNode> root;
798 size_t location { notFound };
802 static void replaceRanges(Page& page, const Vector<FindReplacementRange>& ranges, const String& replacementText)
804 HashMap<RefPtr<ContainerNode>, Vector<FindReplacementRange>> rangesByContainerNode;
805 for (auto& range : ranges) {
806 auto& rangeList = rangesByContainerNode.ensure(range.root, [] {
807 return Vector<FindReplacementRange> { };
810 // Ensure that ranges are sorted by their end offsets, per editing container.
811 auto endOffsetForRange = range.location + range.length;
812 auto insertionIndex = rangeList.size();
813 for (auto iterator = rangeList.rbegin(); iterator != rangeList.rend(); ++iterator) {
814 auto endOffsetBeforeInsertionIndex = iterator->location + iterator->length;
815 if (endOffsetForRange >= endOffsetBeforeInsertionIndex)
819 rangeList.insert(insertionIndex, range);
822 HashMap<RefPtr<Frame>, unsigned> frameToTraversalIndexMap;
823 unsigned currentFrameTraversalIndex = 0;
824 for (Frame* frame = &page.mainFrame(); frame; frame = frame->tree().traverseNext())
825 frameToTraversalIndexMap.set(frame, currentFrameTraversalIndex++);
827 // Likewise, iterate backwards (in document and frame order) through editing containers that contain text matches,
828 // so that we're consistent with our backwards iteration behavior per editing container when replacing text.
829 auto containerNodesInOrderOfReplacement = copyToVector(rangesByContainerNode.keys());
830 std::sort(containerNodesInOrderOfReplacement.begin(), containerNodesInOrderOfReplacement.end(), [frameToTraversalIndexMap] (auto& firstNode, auto& secondNode) {
831 if (firstNode == secondNode)
834 auto firstFrame = makeRefPtr(firstNode->document().frame());
838 auto secondFrame = makeRefPtr(secondNode->document().frame());
842 if (firstFrame == secondFrame) {
843 // comparePositions is used here instead of Node::compareDocumentPosition because some editing roots may exist inside shadow roots.
844 return comparePositions({ firstNode.get(), Position::PositionIsBeforeChildren }, { secondNode.get(), Position::PositionIsBeforeChildren }) > 0;
846 return frameToTraversalIndexMap.get(firstFrame) > frameToTraversalIndexMap.get(secondFrame);
849 for (auto& container : containerNodesInOrderOfReplacement) {
850 auto frame = makeRefPtr(container->document().frame());
854 // Iterate backwards through ranges when replacing text, such that earlier text replacements don't clobber replacement ranges later on.
855 auto& ranges = rangesByContainerNode.find(container)->value;
856 for (auto iterator = ranges.rbegin(); iterator != ranges.rend(); ++iterator) {
857 auto range = TextIterator::rangeFromLocationAndLength(container.get(), iterator->location, iterator->length);
858 if (!range || range->collapsed())
861 frame->selection().setSelectedRange(range.get(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::Yes);
862 frame->editor().replaceSelectionWithText(replacementText, Editor::SelectReplacement::Yes, Editor::SmartReplace::No, EditAction::InsertReplacement);
867 uint32_t Page::replaceRangesWithText(const Vector<Ref<Range>>& rangesToReplace, const String& replacementText, bool selectionOnly)
869 // FIXME: In the future, we should respect the `selectionOnly` flag by checking whether each range being replaced is
870 // contained within its frame's selection.
871 UNUSED_PARAM(selectionOnly);
873 Vector<FindReplacementRange> replacementRanges;
874 replacementRanges.reserveInitialCapacity(rangesToReplace.size());
876 for (auto& range : rangesToReplace) {
877 auto highestRoot = makeRefPtr(highestEditableRoot(range->startPosition()));
878 if (!highestRoot || highestRoot != highestEditableRoot(range->endPosition()))
881 auto frame = makeRefPtr(highestRoot->document().frame());
885 size_t replacementLocation = notFound;
886 size_t replacementLength = 0;
887 if (!TextIterator::getLocationAndLengthFromRange(highestRoot.get(), range.ptr(), replacementLocation, replacementLength))
890 if (replacementLocation == notFound || !replacementLength)
893 replacementRanges.append({ WTFMove(highestRoot), replacementLocation, replacementLength });
896 replaceRanges(*this, replacementRanges, replacementText);
897 return rangesToReplace.size();
900 uint32_t Page::replaceSelectionWithText(const String& replacementText)
902 auto frame = makeRef(focusController().focusedOrMainFrame());
903 auto selection = frame->selection().selection();
904 if (!selection.isContentEditable())
907 auto editAction = selection.isRange() ? EditAction::InsertReplacement : EditAction::Insert;
908 frame->editor().replaceSelectionWithText(replacementText, Editor::SelectReplacement::Yes, Editor::SmartReplace::No, editAction);
912 void Page::unmarkAllTextMatches()
914 Frame* frame = &mainFrame();
916 frame->document()->markers().removeMarkers(DocumentMarker::TextMatch);
917 frame = incrementFrame(frame, true, CanWrap::No);
921 const VisibleSelection& Page::selection() const
923 return focusController().focusedOrMainFrame().selection().selection();
926 void Page::setDefersLoading(bool defers)
928 if (!m_settings->loadDeferringEnabled())
931 if (m_settings->wantsBalancedSetDefersLoadingBehavior()) {
932 ASSERT(defers || m_defersLoadingCallCount);
933 if (defers && ++m_defersLoadingCallCount > 1)
935 if (!defers && --m_defersLoadingCallCount)
938 ASSERT(!m_defersLoadingCallCount);
939 if (defers == m_defersLoading)
943 m_defersLoading = defers;
944 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
945 frame->loader().setDefersLoading(defers);
948 void Page::clearUndoRedoOperations()
950 m_editorClient->clearUndoRedoOperations();
953 bool Page::inLowQualityImageInterpolationMode() const
955 return m_inLowQualityInterpolationMode;
958 void Page::setInLowQualityImageInterpolationMode(bool mode)
960 m_inLowQualityInterpolationMode = mode;
963 DiagnosticLoggingClient& Page::diagnosticLoggingClient() const
965 if (!settings().diagnosticLoggingEnabled() || !m_diagnosticLoggingClient)
966 return emptyDiagnosticLoggingClient();
967 return *m_diagnosticLoggingClient;
970 void Page::setMediaVolume(float volume)
972 if (volume < 0 || volume > 1)
975 if (m_mediaVolume == volume)
978 m_mediaVolume = volume;
979 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
980 if (!frame->document())
982 frame->document()->mediaVolumeDidChange();
986 void Page::setZoomedOutPageScaleFactor(float scale)
988 if (m_zoomedOutPageScaleFactor == scale)
990 m_zoomedOutPageScaleFactor = scale;
992 mainFrame().deviceOrPageScaleFactorChanged();
995 void Page::setPageScaleFactor(float scale, const IntPoint& origin, bool inStableState)
997 LOG(Viewports, "Page::setPageScaleFactor %.2f - inStableState %d", scale, inStableState);
999 Document* document = mainFrame().document();
1000 FrameView* view = document->view();
1002 if (scale == m_pageScaleFactor) {
1003 if (view && view->scrollPosition() != origin) {
1004 if (!m_settings->delegatesPageScaling())
1005 document->updateLayoutIgnorePendingStylesheets();
1007 if (!view->delegatesScrolling())
1008 view->setScrollPosition(origin);
1009 #if USE(COORDINATED_GRAPHICS)
1011 view->requestScrollPositionUpdate(origin);
1014 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
1015 if (inStableState) {
1016 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1017 if (!frame->document())
1019 frame->document()->pageScaleFactorChangedAndStable();
1026 m_pageScaleFactor = scale;
1028 if (!m_settings->delegatesPageScaling()) {
1029 view->setNeedsLayoutAfterViewConfigurationChange();
1030 view->setNeedsCompositingGeometryUpdate();
1032 document->resolveStyle(Document::ResolveStyleType::Rebuild);
1034 // Transform change on RenderView doesn't trigger repaint on non-composited contents.
1035 mainFrame().view()->invalidateRect(IntRect(LayoutRect::infiniteRect()));
1038 mainFrame().deviceOrPageScaleFactorChanged();
1040 if (view && view->fixedElementsLayoutRelativeToFrame())
1041 view->setViewportConstrainedObjectsNeedLayout();
1043 if (view && view->scrollPosition() != origin) {
1044 if (!m_settings->delegatesPageScaling() && document->renderView() && document->renderView()->needsLayout() && view->didFirstLayout())
1045 view->layoutContext().layout();
1047 if (!view->delegatesScrolling())
1048 view->setScrollPosition(origin);
1049 #if USE(COORDINATED_GRAPHICS)
1051 view->requestScrollPositionUpdate(origin);
1055 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
1056 if (inStableState) {
1057 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1058 if (!frame->document())
1060 frame->document()->pageScaleFactorChangedAndStable();
1064 UNUSED_PARAM(inStableState);
1068 void Page::setViewScaleFactor(float scale)
1070 if (m_viewScaleFactor == scale)
1073 m_viewScaleFactor = scale;
1074 BackForwardCache::singleton().markPagesForDeviceOrPageScaleChanged(*this);
1077 void Page::setDeviceScaleFactor(float scaleFactor)
1079 ASSERT(scaleFactor > 0);
1080 if (scaleFactor <= 0)
1083 if (m_deviceScaleFactor == scaleFactor)
1086 m_deviceScaleFactor = scaleFactor;
1087 setNeedsRecalcStyleInAllFrames();
1089 mainFrame().deviceOrPageScaleFactorChanged();
1090 BackForwardCache::singleton().markPagesForDeviceOrPageScaleChanged(*this);
1092 pageOverlayController().didChangeDeviceScaleFactor();
1095 void Page::setInitialScale(float initialScale)
1097 m_initialScale = initialScale;
1100 void Page::setUserInterfaceLayoutDirection(UserInterfaceLayoutDirection userInterfaceLayoutDirection)
1102 if (m_userInterfaceLayoutDirection == userInterfaceLayoutDirection)
1105 m_userInterfaceLayoutDirection = userInterfaceLayoutDirection;
1106 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
1107 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1108 if (!frame->document())
1110 frame->document()->userInterfaceLayoutDirectionChanged();
1116 void Page::updateMediaElementRateChangeRestrictions()
1118 for (auto* mediaElement : HTMLMediaElement::allMediaElements())
1119 mediaElement->updateRateChangeRestrictions();
1123 void Page::didStartProvisionalLoad()
1125 if (m_performanceMonitor)
1126 m_performanceMonitor->didStartProvisionalLoad();
1129 void Page::didFinishLoad()
1131 resetRelevantPaintedObjectCounter();
1133 if (m_performanceMonitor)
1134 m_performanceMonitor->didFinishLoad();
1137 bool Page::isOnlyNonUtilityPage() const
1139 return !isUtilityPage() && nonUtilityPageCount == 1;
1142 bool Page::isLowPowerModeEnabled() const
1144 if (m_lowPowerModeEnabledOverrideForTesting)
1145 return m_lowPowerModeEnabledOverrideForTesting.value();
1147 return m_lowPowerModeNotifier->isLowPowerModeEnabled();
1150 void Page::setLowPowerModeEnabledOverrideForTesting(Optional<bool> isEnabled)
1152 m_lowPowerModeEnabledOverrideForTesting = isEnabled;
1153 handleLowModePowerChange(m_lowPowerModeEnabledOverrideForTesting.valueOr(false));
1156 void Page::setTopContentInset(float contentInset)
1158 if (m_topContentInset == contentInset)
1161 m_topContentInset = contentInset;
1163 if (FrameView* view = mainFrame().view())
1164 view->topContentInsetDidChange(m_topContentInset);
1167 void Page::setShouldSuppressScrollbarAnimations(bool suppressAnimations)
1169 if (suppressAnimations == m_suppressScrollbarAnimations)
1172 lockAllOverlayScrollbarsToHidden(suppressAnimations);
1173 m_suppressScrollbarAnimations = suppressAnimations;
1176 void Page::lockAllOverlayScrollbarsToHidden(bool lockOverlayScrollbars)
1178 FrameView* view = mainFrame().view();
1182 view->lockOverlayScrollbarStateToHidden(lockOverlayScrollbars);
1184 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1185 FrameView* frameView = frame->view();
1189 const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas();
1190 if (!scrollableAreas)
1193 for (auto& scrollableArea : *scrollableAreas)
1194 scrollableArea->lockOverlayScrollbarStateToHidden(lockOverlayScrollbars);
1198 void Page::setVerticalScrollElasticity(ScrollElasticity elasticity)
1200 if (m_verticalScrollElasticity == elasticity)
1203 m_verticalScrollElasticity = elasticity;
1205 if (FrameView* view = mainFrame().view())
1206 view->setVerticalScrollElasticity(elasticity);
1209 void Page::setHorizontalScrollElasticity(ScrollElasticity elasticity)
1211 if (m_horizontalScrollElasticity == elasticity)
1214 m_horizontalScrollElasticity = elasticity;
1216 if (FrameView* view = mainFrame().view())
1217 view->setHorizontalScrollElasticity(elasticity);
1220 void Page::setPagination(const Pagination& pagination)
1222 if (m_pagination == pagination)
1225 m_pagination = pagination;
1227 setNeedsRecalcStyleInAllFrames();
1230 void Page::setPaginationLineGridEnabled(bool enabled)
1232 if (m_paginationLineGridEnabled == enabled)
1235 m_paginationLineGridEnabled = enabled;
1237 setNeedsRecalcStyleInAllFrames();
1240 unsigned Page::pageCount() const
1242 if (m_pagination.mode == Pagination::Unpaginated)
1245 if (Document* document = mainFrame().document())
1246 document->updateLayoutIgnorePendingStylesheets();
1248 RenderView* contentRenderer = mainFrame().contentRenderer();
1249 return contentRenderer ? contentRenderer->pageCount() : 0;
1252 void Page::setIsInWindow(bool isInWindow)
1254 setActivityState(isInWindow ? m_activityState | ActivityState::IsInWindow : m_activityState - ActivityState::IsInWindow);
1257 void Page::setIsInWindowInternal(bool isInWindow)
1259 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1260 if (FrameView* frameView = frame->view())
1261 frameView->setIsInWindow(isInWindow);
1265 resumeAnimatingImages();
1268 void Page::addActivityStateChangeObserver(ActivityStateChangeObserver& observer)
1270 m_activityStateChangeObservers.add(&observer);
1273 void Page::removeActivityStateChangeObserver(ActivityStateChangeObserver& observer)
1275 m_activityStateChangeObservers.remove(&observer);
1278 void Page::layoutIfNeeded()
1280 if (FrameView* view = m_mainFrame->view())
1281 view->updateLayoutAndStyleIfNeededRecursive();
1284 // https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering
1285 void Page::updateRendering()
1287 // This function is not reentrant, e.g. a rAF callback may force repaint.
1288 if (m_inUpdateRendering) {
1293 TraceScope traceScope(RenderingUpdateStart, RenderingUpdateEnd);
1295 SetForScope<bool> change(m_inUpdateRendering, true);
1297 Vector<RefPtr<Document>> documents;
1299 // The requestAnimationFrame callbacks may change the frame hierarchy of the page
1300 forEachDocument([&documents] (Document& document) {
1301 documents.append(&document);
1304 // FIXME: Run the resize steps
1306 // FIXME: Run the scroll steps
1308 // FIXME: Evaluate media queries and report changes.
1310 for (auto& document : documents) {
1311 DOMHighResTimeStamp timestamp = document->domWindow()->nowTimestamp();
1312 document->updateAnimationsAndSendEvents(timestamp);
1313 // FIXME: Run the fullscreen steps.
1314 document->serviceRequestAnimationFrameCallbacks(timestamp);
1319 #if ENABLE(INTERSECTION_OBSERVER)
1320 for (auto& document : documents)
1321 document->updateIntersectionObservations();
1323 #if ENABLE(RESIZE_OBSERVER)
1324 for (auto& document : documents)
1325 document->updateResizeObservations(*this);
1328 // FIXME: Flush autofocus candidates
1329 // https://github.com/whatwg/html/issues/4992
1334 void Page::suspendScriptedAnimations()
1336 m_scriptedAnimationsSuspended = true;
1337 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1338 if (frame->document())
1339 frame->document()->suspendScriptedAnimationControllerCallbacks();
1343 void Page::resumeScriptedAnimations()
1345 m_scriptedAnimationsSuspended = false;
1346 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1347 if (frame->document())
1348 frame->document()->resumeScriptedAnimationControllerCallbacks();
1352 enum class ThrottlingReasonOperation { Add, Remove };
1353 static void updateScriptedAnimationsThrottlingReason(Page& page, ThrottlingReasonOperation operation, ScriptedAnimationController::ThrottlingReason reason)
1355 for (Frame* frame = &page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
1356 auto* document = frame->document();
1359 auto* scriptedAnimationController = document->scriptedAnimationController();
1360 if (!scriptedAnimationController)
1363 if (operation == ThrottlingReasonOperation::Add)
1364 scriptedAnimationController->addThrottlingReason(reason);
1366 scriptedAnimationController->removeThrottlingReason(reason);
1370 void Page::setIsVisuallyIdleInternal(bool isVisuallyIdle)
1372 updateScriptedAnimationsThrottlingReason(*this, isVisuallyIdle ? ThrottlingReasonOperation::Add : ThrottlingReasonOperation::Remove, ScriptedAnimationController::ThrottlingReason::VisuallyIdle);
1375 void Page::handleLowModePowerChange(bool isLowPowerModeEnabled)
1377 updateScriptedAnimationsThrottlingReason(*this, isLowPowerModeEnabled ? ThrottlingReasonOperation::Add : ThrottlingReasonOperation::Remove, ScriptedAnimationController::ThrottlingReason::LowPowerMode);
1378 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
1379 forEachDocument([&] (Document& document) {
1380 if (auto timeline = document.existingTimeline())
1381 timeline->updateThrottlingState();
1384 mainFrame().animation().updateThrottlingState();
1385 updateDOMTimerAlignmentInterval();
1388 void Page::userStyleSheetLocationChanged()
1390 // FIXME: Eventually we will move to a model of just being handed the sheet
1391 // text instead of loading the URL ourselves.
1392 URL url = m_settings->userStyleSheetLocation();
1394 // Allow any local file URL scheme to be loaded.
1395 if (LegacySchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol().toStringWithoutCopying()))
1396 m_userStyleSheetPath = url.fileSystemPath();
1398 m_userStyleSheetPath = String();
1400 m_didLoadUserStyleSheet = false;
1401 m_userStyleSheet = String();
1402 m_userStyleSheetModificationTime = WTF::nullopt;
1404 // Data URLs with base64-encoded UTF-8 style sheets are common. We can process them
1405 // synchronously and avoid using a loader.
1406 if (url.protocolIsData() && url.string().startsWith("data:text/css;charset=utf-8;base64,")) {
1407 m_didLoadUserStyleSheet = true;
1409 Vector<char> styleSheetAsUTF8;
1410 if (base64Decode(decodeURLEscapeSequences(url.string().substring(35)), styleSheetAsUTF8, Base64IgnoreSpacesAndNewLines))
1411 m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size());
1414 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1415 if (frame->document())
1416 frame->document()->extensionStyleSheets().updatePageUserSheet();
1420 const String& Page::userStyleSheet() const
1422 if (m_userStyleSheetPath.isEmpty())
1423 return m_userStyleSheet;
1425 auto modificationTime = FileSystem::getFileModificationTime(m_userStyleSheetPath);
1426 if (!modificationTime) {
1427 // The stylesheet either doesn't exist, was just deleted, or is
1428 // otherwise unreadable. If we've read the stylesheet before, we should
1429 // throw away that data now as it no longer represents what's on disk.
1430 m_userStyleSheet = String();
1431 return m_userStyleSheet;
1434 // If the stylesheet hasn't changed since the last time we read it, we can
1435 // just return the old data.
1436 if (m_didLoadUserStyleSheet && (m_userStyleSheetModificationTime && modificationTime.value() <= m_userStyleSheetModificationTime.value()))
1437 return m_userStyleSheet;
1439 m_didLoadUserStyleSheet = true;
1440 m_userStyleSheet = String();
1441 m_userStyleSheetModificationTime = modificationTime;
1443 // FIXME: It would be better to load this asynchronously to avoid blocking
1444 // the process, but we will first need to create an asynchronous loading
1445 // mechanism that is not tied to a particular Frame. We will also have to
1446 // determine what our behavior should be before the stylesheet is loaded
1447 // and what should happen when it finishes loading, especially with respect
1448 // to when the load event fires, when Document::close is called, and when
1449 // layout/paint are allowed to happen.
1450 auto data = SharedBuffer::createWithContentsOfFile(m_userStyleSheetPath);
1452 return m_userStyleSheet;
1454 m_userStyleSheet = TextResourceDecoder::create("text/css")->decodeAndFlush(data->data(), data->size());
1456 return m_userStyleSheet;
1459 void Page::userAgentChanged()
1461 for (auto* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
1462 auto* window = frame->window();
1465 if (auto* navigator = window->optionalNavigator())
1466 navigator->userAgentChanged();
1470 void Page::invalidateStylesForAllLinks()
1472 for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
1473 if (!frame->document())
1475 frame->document()->visitedLinkState().invalidateStyleForAllLinks();
1479 void Page::invalidateStylesForLink(SharedStringHash linkHash)
1481 for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
1482 if (!frame->document())
1484 frame->document()->visitedLinkState().invalidateStyleForLink(linkHash);
1488 void Page::invalidateInjectedStyleSheetCacheInAllFrames()
1490 for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
1491 Document* document = frame->document();
1494 document->extensionStyleSheets().invalidateInjectedStyleSheetCache();
1498 void Page::setDebugger(JSC::Debugger* debugger)
1500 if (m_debugger == debugger)
1503 m_debugger = debugger;
1505 for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
1506 frame->windowProxy().attachDebugger(m_debugger);
1509 StorageNamespace* Page::sessionStorage(bool optionalCreate)
1511 if (!m_sessionStorage && optionalCreate)
1512 m_sessionStorage = m_storageNamespaceProvider->createSessionStorageNamespace(*this, m_settings->sessionStorageQuota());
1514 return m_sessionStorage.get();
1517 void Page::setSessionStorage(RefPtr<StorageNamespace>&& newStorage)
1519 m_sessionStorage = WTFMove(newStorage);
1522 bool Page::hasCustomHTMLTokenizerTimeDelay() const
1524 return m_settings->maxParseDuration() != -1;
1527 double Page::customHTMLTokenizerTimeDelay() const
1529 ASSERT(m_settings->maxParseDuration() != -1);
1530 return m_settings->maxParseDuration();
1533 void Page::setMemoryCacheClientCallsEnabled(bool enabled)
1535 if (m_areMemoryCacheClientCallsEnabled == enabled)
1538 m_areMemoryCacheClientCallsEnabled = enabled;
1542 for (RefPtr<Frame> frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1543 frame->loader().tellClientAboutPastMemoryCacheLoads();
1546 void Page::hiddenPageDOMTimerThrottlingStateChanged()
1548 // Disable & reengage to ensure state is updated.
1549 setTimerThrottlingState(TimerThrottlingState::Disabled);
1550 updateTimerThrottlingState();
1553 void Page::updateTimerThrottlingState()
1555 // Timer throttling disabled if page is visually active, or disabled by setting.
1556 if (!m_settings->hiddenPageDOMTimerThrottlingEnabled() || !(m_activityState & ActivityState::IsVisuallyIdle)) {
1557 setTimerThrottlingState(TimerThrottlingState::Disabled);
1561 // If the page is visible (but idle), there is any activity (loading, media playing, etc), or per setting,
1562 // we allow timer throttling, but not increasing timer throttling.
1563 if (!m_settings->hiddenPageDOMTimerThrottlingAutoIncreases()
1564 || m_activityState.containsAny({ActivityState::IsVisible, ActivityState::IsAudible, ActivityState::IsLoading, ActivityState::IsCapturingMedia })) {
1565 setTimerThrottlingState(TimerThrottlingState::Enabled);
1569 // If we get here increasing timer throttling is enabled.
1570 setTimerThrottlingState(TimerThrottlingState::EnabledIncreasing);
1573 void Page::setTimerThrottlingState(TimerThrottlingState state)
1575 if (state == m_timerThrottlingState)
1578 m_timerThrottlingState = state;
1579 m_timerThrottlingStateLastChangedTime = MonotonicTime::now();
1581 updateDOMTimerAlignmentInterval();
1583 // When throttling is disabled, release all throttled timers.
1584 if (state == TimerThrottlingState::Disabled) {
1585 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1586 if (auto* document = frame->document())
1587 document->didChangeTimerAlignmentInterval();
1592 void Page::setDOMTimerAlignmentIntervalIncreaseLimit(Seconds limit)
1594 m_domTimerAlignmentIntervalIncreaseLimit = limit;
1596 // If (m_domTimerAlignmentIntervalIncreaseLimit < m_domTimerAlignmentInterval) then we need
1597 // to update m_domTimerAlignmentInterval, if greater then need to restart the increase timer.
1598 if (m_timerThrottlingState == TimerThrottlingState::EnabledIncreasing)
1599 updateDOMTimerAlignmentInterval();
1602 void Page::updateDOMTimerAlignmentInterval()
1604 bool needsIncreaseTimer = false;
1606 switch (m_timerThrottlingState) {
1607 case TimerThrottlingState::Disabled:
1608 m_domTimerAlignmentInterval = isLowPowerModeEnabled() ? DOMTimer::defaultAlignmentIntervalInLowPowerMode() : DOMTimer::defaultAlignmentInterval();
1611 case TimerThrottlingState::Enabled:
1612 m_domTimerAlignmentInterval = DOMTimer::hiddenPageAlignmentInterval();
1615 case TimerThrottlingState::EnabledIncreasing:
1616 // For pages in prerender state maximum throttling kicks in immediately.
1618 m_domTimerAlignmentInterval = m_domTimerAlignmentIntervalIncreaseLimit;
1620 ASSERT(!!m_timerThrottlingStateLastChangedTime);
1621 m_domTimerAlignmentInterval = MonotonicTime::now() - m_timerThrottlingStateLastChangedTime;
1622 // If we're below the limit, set the timer. If above, clamp to limit.
1623 if (m_domTimerAlignmentInterval < m_domTimerAlignmentIntervalIncreaseLimit)
1624 needsIncreaseTimer = true;
1626 m_domTimerAlignmentInterval = m_domTimerAlignmentIntervalIncreaseLimit;
1628 // Alignment interval should not be less than DOMTimer::hiddenPageAlignmentInterval().
1629 m_domTimerAlignmentInterval = std::max(m_domTimerAlignmentInterval, DOMTimer::hiddenPageAlignmentInterval());
1632 // If throttling is enabled, auto-increasing of throttling is enabled, and the auto-increase
1633 // limit has not yet been reached, and then arm the timer to consider an increase. Time to wait
1634 // between increases is equal to the current throttle time. Since alinment interval increases
1635 // exponentially, time between steps is exponential too.
1636 if (!needsIncreaseTimer)
1637 m_domTimerAlignmentIntervalIncreaseTimer.stop();
1638 else if (!m_domTimerAlignmentIntervalIncreaseTimer.isActive())
1639 m_domTimerAlignmentIntervalIncreaseTimer.startOneShot(m_domTimerAlignmentInterval);
1642 void Page::domTimerAlignmentIntervalIncreaseTimerFired()
1644 ASSERT(m_settings->hiddenPageDOMTimerThrottlingAutoIncreases());
1645 ASSERT(m_timerThrottlingState == TimerThrottlingState::EnabledIncreasing);
1646 ASSERT(m_domTimerAlignmentInterval < m_domTimerAlignmentIntervalIncreaseLimit);
1648 // Alignment interval is increased to equal the time the page has been throttled, to a limit.
1649 updateDOMTimerAlignmentInterval();
1652 void Page::dnsPrefetchingStateChanged()
1654 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1655 if (!frame->document())
1657 frame->document()->initDNSPrefetch();
1661 Vector<Ref<PluginViewBase>> Page::pluginViews()
1663 Vector<Ref<PluginViewBase>> views;
1664 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1665 auto* view = frame->view();
1668 for (auto& widget : view->children()) {
1669 if (is<PluginViewBase>(widget))
1670 views.append(downcast<PluginViewBase>(widget.get()));
1676 void Page::storageBlockingStateChanged()
1678 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1679 if (!frame->document())
1681 frame->document()->storageBlockingStateDidChange();
1684 // Collect the PluginViews in to a vector to ensure that action the plug-in takes
1685 // from below storageBlockingStateChanged does not affect their lifetime.
1686 for (auto& view : pluginViews())
1687 view->storageBlockingStateChanged();
1690 void Page::updateIsPlayingMedia(uint64_t sourceElementID)
1692 MediaProducer::MediaStateFlags state = MediaProducer::IsNotPlaying;
1693 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1694 if (Document* document = frame->document())
1695 state |= document->mediaState();
1698 if (state == m_mediaState)
1701 m_mediaState = state;
1703 chrome().client().isPlayingMediaDidChange(state, sourceElementID);
1706 void Page::schedulePlaybackControlsManagerUpdate()
1709 if (!m_playbackControlsManagerUpdateTimer.isActive())
1710 m_playbackControlsManagerUpdateTimer.startOneShot(0_s);
1715 void Page::playbackControlsManagerUpdateTimerFired()
1717 if (auto bestMediaElement = HTMLMediaElement::bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose::ControlsManager))
1718 chrome().client().setUpPlaybackControlsManager(*bestMediaElement);
1720 chrome().client().clearPlaybackControlsManager();
1724 void Page::setMuted(MediaProducer::MutedStateFlags muted)
1726 if (m_mutedState == muted)
1729 m_mutedState = muted;
1731 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1732 if (!frame->document())
1734 frame->document()->pageMutedStateDidChange();
1738 void Page::stopMediaCapture()
1740 #if ENABLE(MEDIA_STREAM)
1741 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1742 if (!frame->document())
1745 frame->document()->stopMediaCapture();
1750 void Page::stopAllMediaPlayback()
1753 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1754 if (auto* document = frame->document())
1755 document->stopAllMediaPlayback();
1760 void Page::suspendAllMediaPlayback()
1763 ASSERT(!m_mediaPlaybackIsSuspended);
1764 if (m_mediaPlaybackIsSuspended)
1767 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1768 if (auto* document = frame->document())
1769 document->suspendAllMediaPlayback();
1772 m_mediaPlaybackIsSuspended = true;
1776 void Page::resumeAllMediaPlayback()
1779 ASSERT(m_mediaPlaybackIsSuspended);
1780 if (!m_mediaPlaybackIsSuspended)
1782 m_mediaPlaybackIsSuspended = false;
1784 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1785 if (auto* document = frame->document())
1786 document->resumeAllMediaPlayback();
1791 void Page::suspendAllMediaBuffering()
1794 ASSERT(!m_mediaBufferingIsSuspended);
1795 if (m_mediaBufferingIsSuspended)
1797 m_mediaBufferingIsSuspended = true;
1799 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1800 if (auto* document = frame->document())
1801 document->suspendAllMediaBuffering();
1806 void Page::resumeAllMediaBuffering()
1809 if (!m_mediaBufferingIsSuspended)
1811 m_mediaBufferingIsSuspended = false;
1813 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
1814 if (auto* document = frame->document())
1815 document->resumeAllMediaBuffering();
1820 #if ENABLE(MEDIA_SESSION)
1821 void Page::handleMediaEvent(MediaEventType eventType)
1823 switch (eventType) {
1824 case MediaEventType::PlayPause:
1825 MediaSessionManager::singleton().togglePlayback();
1827 case MediaEventType::TrackNext:
1828 MediaSessionManager::singleton().skipToNextTrack();
1830 case MediaEventType::TrackPrevious:
1831 MediaSessionManager::singleton().skipToPreviousTrack();
1836 void Page::setVolumeOfMediaElement(double volume, uint64_t elementID)
1838 if (HTMLMediaElement* element = HTMLMediaElement::elementWithID(elementID))
1839 element->setVolume(volume, ASSERT_NO_EXCEPTION);
1843 #if !ASSERT_DISABLED
1844 void Page::checkSubframeCountConsistency() const
1846 ASSERT(m_subframeCount >= 0);
1848 int subframeCount = 0;
1849 for (const Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
1852 ASSERT(m_subframeCount + 1 == subframeCount);
1856 void Page::resumeAnimatingImages()
1858 // Drawing models which cache painted content while out-of-window (WebKit2's composited drawing areas, etc.)
1859 // require that we repaint animated images to kickstart the animation loop.
1860 if (FrameView* view = mainFrame().view())
1861 view->resumeVisibleImageAnimationsIncludingSubframes();
1864 void Page::setActivityState(OptionSet<ActivityState::Flag> activityState)
1866 auto changed = m_activityState ^ activityState;
1870 auto oldActivityState = m_activityState;
1872 bool wasVisibleAndActive = isVisibleAndActive();
1873 m_activityState = activityState;
1875 m_focusController->setActivityState(activityState);
1877 if (changed & ActivityState::IsVisible)
1878 setIsVisibleInternal(activityState.contains(ActivityState::IsVisible));
1879 if (changed & ActivityState::IsInWindow)
1880 setIsInWindowInternal(activityState.contains(ActivityState::IsInWindow));
1881 if (changed & ActivityState::IsVisuallyIdle)
1882 setIsVisuallyIdleInternal(activityState.contains(ActivityState::IsVisuallyIdle));
1883 if (changed & ActivityState::WindowIsActive) {
1884 if (auto* view = m_mainFrame->view())
1885 view->updateTiledBackingAdaptiveSizing();
1888 if (changed.containsAny({ActivityState::IsVisible, ActivityState::IsVisuallyIdle, ActivityState::IsAudible, ActivityState::IsLoading, ActivityState::IsCapturingMedia }))
1889 updateTimerThrottlingState();
1891 for (auto* observer : m_activityStateChangeObservers)
1892 observer->activityStateDidChange(oldActivityState, m_activityState);
1894 if (wasVisibleAndActive != isVisibleAndActive())
1895 PlatformMediaSessionManager::updateNowPlayingInfoIfNecessary();
1897 if (m_performanceMonitor)
1898 m_performanceMonitor->activityStateChanged(oldActivityState, activityState);
1901 bool Page::isVisibleAndActive() const
1903 return m_activityState.contains(ActivityState::IsVisible) && m_activityState.contains(ActivityState::WindowIsActive);
1906 bool Page::isWindowActive() const
1908 return m_activityState.contains(ActivityState::WindowIsActive);
1911 void Page::setIsVisible(bool isVisible)
1913 auto state = m_activityState;
1916 state.remove(ActivityState::IsVisuallyIdle);
1917 state.add({ ActivityState::IsVisible, ActivityState::IsVisibleOrOccluded });
1919 state.add(ActivityState::IsVisuallyIdle);
1920 state.remove({ ActivityState::IsVisible, ActivityState::IsVisibleOrOccluded });
1922 setActivityState(state);
1925 enum class SVGAnimationsState { Paused, Resumed };
1926 static inline void setSVGAnimationsState(Page& page, SVGAnimationsState state)
1928 for (Frame* frame = &page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
1929 auto* document = frame->document();
1933 if (!document->svgExtensions())
1936 if (state == SVGAnimationsState::Paused)
1937 document->accessSVGExtensions().pauseAnimations();
1939 document->accessSVGExtensions().unpauseAnimations();
1943 void Page::setIsVisibleInternal(bool isVisible)
1945 // FIXME: The visibility state should be stored on the top-level document.
1946 // https://bugs.webkit.org/show_bug.cgi?id=116769
1949 m_isPrerender = false;
1951 resumeScriptedAnimations();
1952 #if PLATFORM(IOS_FAMILY)
1953 resumeDeviceMotionAndOrientationUpdates();
1956 if (FrameView* view = mainFrame().view())
1959 if (m_settings->hiddenPageCSSAnimationSuspensionEnabled()) {
1960 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
1961 forEachDocument([&] (Document& document) {
1962 if (auto* timeline = document.existingTimeline())
1963 timeline->resumeAnimations();
1966 mainFrame().animation().resumeAnimations();
1969 setSVGAnimationsState(*this, SVGAnimationsState::Resumed);
1971 resumeAnimatingImages();
1973 if (m_navigationToLogWhenVisible) {
1974 logNavigation(m_navigationToLogWhenVisible.value());
1975 m_navigationToLogWhenVisible = WTF::nullopt;
1980 if (m_settings->hiddenPageCSSAnimationSuspensionEnabled()) {
1981 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
1982 forEachDocument([&] (Document& document) {
1983 if (auto* timeline = document.existingTimeline())
1984 timeline->suspendAnimations();
1987 mainFrame().animation().suspendAnimations();
1990 setSVGAnimationsState(*this, SVGAnimationsState::Paused);
1992 #if PLATFORM(IOS_FAMILY)
1993 suspendDeviceMotionAndOrientationUpdates();
1996 suspendScriptedAnimations();
1998 if (FrameView* view = mainFrame().view())
2002 Vector<Ref<Document>> documents;
2003 for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
2004 documents.append(*frame->document());
2006 for (auto& document : documents)
2007 document->visibilityStateChanged();
2010 void Page::setIsPrerender()
2012 m_isPrerender = true;
2013 updateDOMTimerAlignmentInterval();
2016 VisibilityState Page::visibilityState() const
2019 return VisibilityState::Visible;
2021 return VisibilityState::Prerender;
2022 return VisibilityState::Hidden;
2025 void Page::setHeaderHeight(int headerHeight)
2027 if (headerHeight == m_headerHeight)
2030 m_headerHeight = headerHeight;
2032 FrameView* frameView = mainFrame().view();
2036 RenderView* renderView = frameView->renderView();
2040 frameView->setNeedsLayoutAfterViewConfigurationChange();
2041 frameView->setNeedsCompositingGeometryUpdate();
2044 void Page::setFooterHeight(int footerHeight)
2046 if (footerHeight == m_footerHeight)
2049 m_footerHeight = footerHeight;
2051 FrameView* frameView = mainFrame().view();
2055 RenderView* renderView = frameView->renderView();
2059 frameView->setNeedsLayoutAfterViewConfigurationChange();
2060 frameView->setNeedsCompositingGeometryUpdate();
2063 void Page::incrementNestedRunLoopCount()
2065 m_nestedRunLoopCount++;
2068 void Page::decrementNestedRunLoopCount()
2070 ASSERT(m_nestedRunLoopCount);
2071 if (m_nestedRunLoopCount <= 0)
2074 m_nestedRunLoopCount--;
2076 if (!m_nestedRunLoopCount && m_unnestCallback) {
2077 callOnMainThread([this] {
2078 if (insideNestedRunLoop())
2081 // This callback may destruct the Page.
2082 if (m_unnestCallback) {
2083 auto callback = WTFMove(m_unnestCallback);
2090 void Page::whenUnnested(WTF::Function<void()>&& callback)
2092 ASSERT(!m_unnestCallback);
2094 m_unnestCallback = WTFMove(callback);
2097 #if ENABLE(REMOTE_INSPECTOR)
2098 bool Page::remoteInspectionAllowed() const
2100 return m_inspectorDebuggable->remoteDebuggingAllowed();
2103 void Page::setRemoteInspectionAllowed(bool allowed)
2105 m_inspectorDebuggable->setRemoteDebuggingAllowed(allowed);
2108 String Page::remoteInspectionNameOverride() const
2110 return m_inspectorDebuggable->nameOverride();
2113 void Page::setRemoteInspectionNameOverride(const String& name)
2115 m_inspectorDebuggable->setNameOverride(name);
2118 void Page::remoteInspectorInformationDidChange() const
2120 m_inspectorDebuggable->update();
2124 void Page::addLayoutMilestones(OptionSet<LayoutMilestone> milestones)
2126 // In the future, we may want a function that replaces m_layoutMilestones instead of just adding to it.
2127 m_requestedLayoutMilestones.add(milestones);
2130 void Page::removeLayoutMilestones(OptionSet<LayoutMilestone> milestones)
2132 m_requestedLayoutMilestones.remove(milestones);
2135 Color Page::pageExtendedBackgroundColor() const
2137 FrameView* frameView = mainFrame().view();
2141 RenderView* renderView = frameView->renderView();
2145 return renderView->compositor().rootExtendedBackgroundColor();
2148 // These are magical constants that might be tweaked over time.
2149 static const double gMinimumPaintedAreaRatio = 0.1;
2150 static const double gMaximumUnpaintedAreaRatio = 0.04;
2152 bool Page::isCountingRelevantRepaintedObjects() const
2154 return m_isCountingRelevantRepaintedObjects && m_requestedLayoutMilestones.contains(DidHitRelevantRepaintedObjectsAreaThreshold);
2157 void Page::startCountingRelevantRepaintedObjects()
2159 // Reset everything in case we didn't hit the threshold last time.
2160 resetRelevantPaintedObjectCounter();
2162 m_isCountingRelevantRepaintedObjects = true;
2165 void Page::resetRelevantPaintedObjectCounter()
2167 m_isCountingRelevantRepaintedObjects = false;
2168 m_relevantUnpaintedRenderObjects.clear();
2169 m_topRelevantPaintedRegion = Region();
2170 m_bottomRelevantPaintedRegion = Region();
2171 m_relevantUnpaintedRegion = Region();
2174 static LayoutRect relevantViewRect(RenderView* view)
2176 LayoutRect viewRect = view->viewRect();
2178 float relevantViewRectWidth = 980;
2179 #if PLATFORM(WATCHOS)
2180 // FIXME(186051): Consider limiting the relevant rect width to the view width everywhere.
2181 relevantViewRectWidth = std::min<float>(viewRect.width().toFloat(), relevantViewRectWidth);
2184 // DidHitRelevantRepaintedObjectsAreaThreshold is a LayoutMilestone intended to indicate that
2185 // a certain relevant amount of content has been drawn to the screen. This is the rect that
2186 // has been determined to be relevant in the context of this goal. We may choose to tweak
2187 // the rect over time, much like we may choose to tweak gMinimumPaintedAreaRatio and
2188 // gMaximumUnpaintedAreaRatio. But this seems to work well right now.
2189 LayoutRect relevantViewRect { 0, 0, LayoutUnit(relevantViewRectWidth), 1300 };
2190 // If the viewRect is wider than the relevantViewRect, center the relevantViewRect.
2191 if (viewRect.width() > relevantViewRect.width())
2192 relevantViewRect.setX((viewRect.width() - relevantViewRect.width()) / 2);
2194 return relevantViewRect;
2197 void Page::addRelevantRepaintedObject(RenderObject* object, const LayoutRect& objectPaintRect)
2199 if (!isCountingRelevantRepaintedObjects())
2202 // Objects inside sub-frames are not considered to be relevant.
2203 if (&object->frame() != &mainFrame())
2206 LayoutRect relevantRect = relevantViewRect(&object->view());
2208 // The objects are only relevant if they are being painted within the viewRect().
2209 if (!objectPaintRect.intersects(snappedIntRect(relevantRect)))
2212 IntRect snappedPaintRect = snappedIntRect(objectPaintRect);
2214 // If this object was previously counted as an unpainted object, remove it from that HashSet
2215 // and corresponding Region. FIXME: This doesn't do the right thing if the objects overlap.
2216 if (m_relevantUnpaintedRenderObjects.remove(object))
2217 m_relevantUnpaintedRegion.subtract(snappedPaintRect);
2219 // Split the relevantRect into a top half and a bottom half. Making sure we have coverage in
2220 // both halves helps to prevent cases where we have a fully loaded menu bar or masthead with
2221 // no content beneath that.
2222 LayoutRect topRelevantRect = relevantRect;
2223 topRelevantRect.contract(LayoutSize(0_lu, relevantRect.height() / 2));
2224 LayoutRect bottomRelevantRect = topRelevantRect;
2225 bottomRelevantRect.setY(relevantRect.height() / 2);
2227 // If the rect straddles both Regions, split it appropriately.
2228 if (topRelevantRect.intersects(snappedPaintRect) && bottomRelevantRect.intersects(snappedPaintRect)) {
2229 IntRect topIntersection = snappedPaintRect;
2230 topIntersection.intersect(snappedIntRect(topRelevantRect));
2231 m_topRelevantPaintedRegion.unite(topIntersection);
2233 IntRect bottomIntersection = snappedPaintRect;
2234 bottomIntersection.intersect(snappedIntRect(bottomRelevantRect));
2235 m_bottomRelevantPaintedRegion.unite(bottomIntersection);
2236 } else if (topRelevantRect.intersects(snappedPaintRect))
2237 m_topRelevantPaintedRegion.unite(snappedPaintRect);
2239 m_bottomRelevantPaintedRegion.unite(snappedPaintRect);
2241 float topPaintedArea = m_topRelevantPaintedRegion.totalArea();
2242 float bottomPaintedArea = m_bottomRelevantPaintedRegion.totalArea();
2243 float viewArea = relevantRect.width() * relevantRect.height();
2245 float ratioThatIsPaintedOnTop = topPaintedArea / viewArea;
2246 float ratioThatIsPaintedOnBottom = bottomPaintedArea / viewArea;
2247 float ratioOfViewThatIsUnpainted = m_relevantUnpaintedRegion.totalArea() / viewArea;
2249 if (ratioThatIsPaintedOnTop > (gMinimumPaintedAreaRatio / 2) && ratioThatIsPaintedOnBottom > (gMinimumPaintedAreaRatio / 2)
2250 && ratioOfViewThatIsUnpainted < gMaximumUnpaintedAreaRatio) {
2251 m_isCountingRelevantRepaintedObjects = false;
2252 resetRelevantPaintedObjectCounter();
2253 if (Frame* frame = &mainFrame())
2254 frame->loader().didReachLayoutMilestone(DidHitRelevantRepaintedObjectsAreaThreshold);
2258 void Page::addRelevantUnpaintedObject(RenderObject* object, const LayoutRect& objectPaintRect)
2260 if (!isCountingRelevantRepaintedObjects())
2263 // The objects are only relevant if they are being painted within the relevantViewRect().
2264 if (!objectPaintRect.intersects(snappedIntRect(relevantViewRect(&object->view()))))
2267 m_relevantUnpaintedRenderObjects.add(object);
2268 m_relevantUnpaintedRegion.unite(snappedIntRect(objectPaintRect));
2271 void Page::suspendDeviceMotionAndOrientationUpdates()
2273 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2274 if (Document* document = frame->document())
2275 document->suspendDeviceMotionAndOrientationUpdates();
2279 void Page::resumeDeviceMotionAndOrientationUpdates()
2281 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2282 if (Document* document = frame->document())
2283 document->resumeDeviceMotionAndOrientationUpdates();
2287 void Page::suspendActiveDOMObjectsAndAnimations()
2289 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
2290 frame->suspendActiveDOMObjectsAndAnimations();
2293 void Page::resumeActiveDOMObjectsAndAnimations()
2295 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
2296 frame->resumeActiveDOMObjectsAndAnimations();
2298 resumeAnimatingImages();
2301 bool Page::hasSeenAnyPlugin() const
2303 return !m_seenPlugins.isEmpty();
2306 bool Page::hasSeenPlugin(const String& serviceType) const
2308 return m_seenPlugins.contains(serviceType);
2311 void Page::sawPlugin(const String& serviceType)
2313 m_seenPlugins.add(serviceType);
2316 void Page::resetSeenPlugins()
2318 m_seenPlugins.clear();
2321 bool Page::hasSeenAnyMediaEngine() const
2323 return !m_seenMediaEngines.isEmpty();
2326 bool Page::hasSeenMediaEngine(const String& engineDescription) const
2328 return m_seenMediaEngines.contains(engineDescription);
2331 void Page::sawMediaEngine(const String& engineDescription)
2333 m_seenMediaEngines.add(engineDescription);
2336 void Page::resetSeenMediaEngines()
2338 m_seenMediaEngines.clear();
2341 void Page::hiddenPageCSSAnimationSuspensionStateChanged()
2344 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
2345 forEachDocument([&] (Document& document) {
2346 if (auto* timeline = document.existingTimeline()) {
2347 if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
2348 timeline->suspendAnimations();
2350 timeline->resumeAnimations();
2354 if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
2355 mainFrame().animation().suspendAnimations();
2357 mainFrame().animation().resumeAnimations();
2362 #if ENABLE(VIDEO_TRACK)
2363 void Page::captionPreferencesChanged()
2365 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2366 if (!frame->document())
2368 frame->document()->captionPreferencesChanged();
2373 void Page::forbidPrompts()
2375 ++m_forbidPromptsDepth;
2378 void Page::allowPrompts()
2380 ASSERT(m_forbidPromptsDepth);
2381 --m_forbidPromptsDepth;
2384 bool Page::arePromptsAllowed()
2386 return !m_forbidPromptsDepth;
2389 void Page::logNavigation(const Navigation& navigation)
2391 String navigationDescription;
2392 switch (navigation.type) {
2393 case FrameLoadType::Standard:
2394 navigationDescription = "standard"_s;
2396 case FrameLoadType::Back:
2397 navigationDescription = "back"_s;
2399 case FrameLoadType::Forward:
2400 navigationDescription = "forward"_s;
2402 case FrameLoadType::IndexedBackForward:
2403 navigationDescription = "indexedBackForward"_s;
2405 case FrameLoadType::Reload:
2406 navigationDescription = "reload"_s;
2408 case FrameLoadType::Same:
2409 navigationDescription = "same"_s;
2411 case FrameLoadType::ReloadFromOrigin:
2412 navigationDescription = "reloadFromOrigin"_s;
2414 case FrameLoadType::ReloadExpiredOnly:
2415 navigationDescription = "reloadRevalidatingExpired"_s;
2417 case FrameLoadType::Replace:
2418 case FrameLoadType::RedirectWithLockedBackForwardList:
2419 // Not logging those for now.
2422 diagnosticLoggingClient().logDiagnosticMessage(DiagnosticLoggingKeys::navigationKey(), navigationDescription, ShouldSample::No);
2424 if (!navigation.domain.isEmpty())
2425 diagnosticLoggingClient().logDiagnosticMessageWithEnhancedPrivacy(DiagnosticLoggingKeys::domainVisitedKey(), navigation.domain.string(), ShouldSample::Yes);
2428 void Page::mainFrameLoadStarted(const URL& destinationURL, FrameLoadType type)
2430 Navigation navigation = { RegistrableDomain { destinationURL }, type };
2432 // To avoid being too verbose, we only log navigations if the page is or becomes visible. This avoids logging non-user observable loads.
2434 m_navigationToLogWhenVisible = navigation;
2438 m_navigationToLogWhenVisible = WTF::nullopt;
2439 logNavigation(navigation);
2442 PluginInfoProvider& Page::pluginInfoProvider()
2444 return m_pluginInfoProvider;
2447 UserContentProvider& Page::userContentProvider()
2449 return m_userContentProvider;
2452 void Page::setUserContentProvider(Ref<UserContentProvider>&& userContentProvider)
2454 m_userContentProvider->removePage(*this);
2455 m_userContentProvider = WTFMove(userContentProvider);
2456 m_userContentProvider->addPage(*this);
2458 invalidateInjectedStyleSheetCacheInAllFrames();
2461 VisitedLinkStore& Page::visitedLinkStore()
2463 return m_visitedLinkStore;
2466 void Page::setVisitedLinkStore(Ref<VisitedLinkStore>&& visitedLinkStore)
2468 m_visitedLinkStore->removePage(*this);
2469 m_visitedLinkStore = WTFMove(visitedLinkStore);
2470 m_visitedLinkStore->addPage(*this);
2472 invalidateStylesForAllLinks();
2475 PAL::SessionID Page::sessionID() const
2480 // This is only called by WebKitLegacy.
2481 void Page::setSessionID(PAL::SessionID sessionID)
2483 ASSERT(sessionID.isValid());
2484 ASSERT(m_sessionID == PAL::SessionID::legacyPrivateSessionID() || m_sessionID == PAL::SessionID::defaultSessionID());
2485 ASSERT(sessionID == PAL::SessionID::legacyPrivateSessionID() || sessionID == PAL::SessionID::defaultSessionID());
2487 #if ENABLE(INDEXED_DATABASE)
2488 if (sessionID != m_sessionID)
2489 m_idbConnectionToServer = nullptr;
2492 if (sessionID != m_sessionID && m_sessionStorage)
2493 m_sessionStorage->setSessionIDForTesting(sessionID);
2495 bool privateBrowsingStateChanged = (sessionID.isEphemeral() != m_sessionID.isEphemeral());
2497 m_sessionID = sessionID;
2499 if (!privateBrowsingStateChanged)
2502 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2503 if (!frame->document())
2505 frame->document()->privateBrowsingStateDidChange(m_sessionID);
2508 // Collect the PluginViews in to a vector to ensure that action the plug-in takes
2509 // from below privateBrowsingStateChanged does not affect their lifetime.
2511 for (auto& view : pluginViews())
2512 view->privateBrowsingStateChanged(sessionID.isEphemeral());
2515 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
2516 void Page::addPlaybackTargetPickerClient(uint64_t contextId)
2518 chrome().client().addPlaybackTargetPickerClient(contextId);
2521 void Page::removePlaybackTargetPickerClient(uint64_t contextId)
2523 chrome().client().removePlaybackTargetPickerClient(contextId);
2526 void Page::showPlaybackTargetPicker(uint64_t contextId, const WebCore::IntPoint& location, bool isVideo, RouteSharingPolicy routeSharingPolicy, const String& routingContextUID)
2528 #if PLATFORM(IOS_FAMILY)
2529 // FIXME: refactor iOS implementation.
2530 UNUSED_PARAM(contextId);
2531 UNUSED_PARAM(location);
2532 chrome().client().showPlaybackTargetPicker(isVideo, routeSharingPolicy, routingContextUID);
2534 UNUSED_PARAM(routeSharingPolicy);
2535 UNUSED_PARAM(routingContextUID);
2536 chrome().client().showPlaybackTargetPicker(contextId, location, isVideo);
2540 void Page::playbackTargetPickerClientStateDidChange(uint64_t contextId, MediaProducer::MediaStateFlags state)
2542 chrome().client().playbackTargetPickerClientStateDidChange(contextId, state);
2545 void Page::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
2547 chrome().client().setMockMediaPlaybackTargetPickerEnabled(enabled);
2550 void Page::setMockMediaPlaybackTargetPickerState(const String& name, MediaPlaybackTargetContext::State state)
2552 chrome().client().setMockMediaPlaybackTargetPickerState(name, state);
2555 void Page::setPlaybackTarget(uint64_t contextId, Ref<MediaPlaybackTarget>&& target)
2557 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2558 if (!frame->document())
2560 frame->document()->setPlaybackTarget(contextId, target.copyRef());
2564 void Page::playbackTargetAvailabilityDidChange(uint64_t contextId, bool available)
2566 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2567 if (!frame->document())
2569 frame->document()->playbackTargetAvailabilityDidChange(contextId, available);
2573 void Page::setShouldPlayToPlaybackTarget(uint64_t clientId, bool shouldPlay)
2575 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2576 if (!frame->document())
2578 frame->document()->setShouldPlayToPlaybackTarget(clientId, shouldPlay);
2583 WheelEventTestMonitor& Page::ensureWheelEventTestMonitor()
2585 if (!m_wheelEventTestMonitor) {
2586 m_wheelEventTestMonitor = adoptRef(new WheelEventTestMonitor());
2587 // We need to update the scrolling coordinator so that the mainframe scrolling node can expect wheel event test triggers.
2588 if (auto* frameView = mainFrame().view()) {
2589 if (m_scrollingCoordinator)
2590 m_scrollingCoordinator->updateIsMonitoringWheelEventsForFrameView(*frameView);
2594 return *m_wheelEventTestMonitor;
2598 void Page::setAllowsMediaDocumentInlinePlayback(bool flag)
2600 if (m_allowsMediaDocumentInlinePlayback == flag)
2602 m_allowsMediaDocumentInlinePlayback = flag;
2604 Vector<Ref<Document>> documents;
2605 for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
2606 documents.append(*frame->document());
2608 for (auto& document : documents)
2609 document->allowsMediaDocumentInlinePlaybackChanged();
2613 #if ENABLE(INDEXED_DATABASE)
2614 IDBClient::IDBConnectionToServer& Page::idbConnection()
2616 if (!m_idbConnectionToServer)
2617 m_idbConnectionToServer = &databaseProvider().idbConnectionToServerForSession(m_sessionID);
2619 return *m_idbConnectionToServer;
2622 IDBClient::IDBConnectionToServer* Page::optionalIDBConnection()
2624 return m_idbConnectionToServer.get();
2627 void Page::clearIDBConnection()
2629 m_idbConnectionToServer = nullptr;
2633 #if ENABLE(RESOURCE_USAGE)
2634 void Page::setResourceUsageOverlayVisible(bool visible)
2637 m_resourceUsageOverlay = nullptr;
2641 if (!m_resourceUsageOverlay && m_settings->acceleratedCompositingEnabled())
2642 m_resourceUsageOverlay = makeUnique<ResourceUsageOverlay>(*this);
2646 bool Page::isAlwaysOnLoggingAllowed() const
2648 return m_sessionID.isAlwaysOnLoggingAllowed();
2651 String Page::captionUserPreferencesStyleSheet()
2653 return m_captionUserPreferencesStyleSheet;
2656 void Page::setCaptionUserPreferencesStyleSheet(const String& styleSheet)
2658 if (m_captionUserPreferencesStyleSheet == styleSheet)
2661 m_captionUserPreferencesStyleSheet = styleSheet;
2664 void Page::accessibilitySettingsDidChange()
2666 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2667 if (auto* document = frame->document()) {
2668 document->styleScope().evaluateMediaQueriesForAccessibilitySettingsChange();
2669 document->evaluateMediaQueryList();
2674 void Page::appearanceDidChange()
2676 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2677 auto* document = frame->document();
2681 document->styleScope().didChangeStyleSheetEnvironment();
2682 document->styleScope().evaluateMediaQueriesForAppearanceChange();
2683 document->evaluateMediaQueryList();
2687 void Page::setUnobscuredSafeAreaInsets(const FloatBoxExtent& insets)
2689 if (m_unobscuredSafeAreaInsets == insets)
2692 m_unobscuredSafeAreaInsets = insets;
2694 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2695 if (!frame->document())
2697 frame->document()->constantProperties().didChangeSafeAreaInsets();
2701 void Page::setUseSystemAppearance(bool value)
2703 if (m_useSystemAppearance == value)
2706 m_useSystemAppearance = value;
2708 appearanceDidChange();
2710 for (auto* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2711 auto* document = frame->document();
2715 // System apperance change may affect stylesheet parsing. We need to reparse.
2716 document->extensionStyleSheets().clearPageUserSheet();
2717 document->extensionStyleSheets().invalidateInjectedStyleSheetCache();
2721 void Page::effectiveAppearanceDidChange(bool useDarkAppearance, bool useElevatedUserInterfaceLevel)
2723 #if HAVE(OS_DARK_MODE_SUPPORT)
2724 if (m_useDarkAppearance == useDarkAppearance && m_useElevatedUserInterfaceLevel == useElevatedUserInterfaceLevel)
2727 m_useDarkAppearance = useDarkAppearance;
2728 m_useElevatedUserInterfaceLevel = useElevatedUserInterfaceLevel;
2730 InspectorInstrumentation::defaultAppearanceDidChange(*this, useDarkAppearance);
2732 appearanceDidChange();
2734 UNUSED_PARAM(useDarkAppearance);
2736 if (m_useElevatedUserInterfaceLevel == useElevatedUserInterfaceLevel)
2739 m_useElevatedUserInterfaceLevel = useElevatedUserInterfaceLevel;
2741 appearanceDidChange();
2745 bool Page::useDarkAppearance() const
2747 #if HAVE(OS_DARK_MODE_SUPPORT)
2748 FrameView* view = mainFrame().view();
2749 if (!view || !equalLettersIgnoringASCIICase(view->mediaType(), "screen"))
2751 if (m_useDarkAppearanceOverride)
2752 return m_useDarkAppearanceOverride.value();
2753 return m_useDarkAppearance;
2759 void Page::setUseDarkAppearanceOverride(Optional<bool> valueOverride)
2761 #if HAVE(OS_DARK_MODE_SUPPORT)
2762 if (valueOverride == m_useDarkAppearanceOverride)
2765 m_useDarkAppearanceOverride = valueOverride;
2767 appearanceDidChange();
2769 UNUSED_PARAM(valueOverride);
2773 void Page::setFullscreenInsets(const FloatBoxExtent& insets)
2775 if (insets == m_fullscreenInsets)
2777 m_fullscreenInsets = insets;
2779 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2780 if (!frame->document())
2782 frame->document()->constantProperties().didChangeFullscreenInsets();
2786 void Page::setFullscreenAutoHideDuration(Seconds duration)
2788 if (duration == m_fullscreenAutoHideDuration)
2790 m_fullscreenAutoHideDuration = duration;
2791 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2792 if (!frame->document())
2794 frame->document()->constantProperties().setFullscreenAutoHideDuration(duration);
2798 void Page::setFullscreenControlsHidden(bool hidden)
2800 #if ENABLE(FULLSCREEN_API)
2801 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2802 if (!frame->document())
2804 frame->document()->fullscreenManager().setFullscreenControlsHidden(hidden);
2807 UNUSED_PARAM(hidden);
2811 #if ENABLE(DATA_INTERACTION)
2813 bool Page::hasSelectionAtPosition(const FloatPoint& position) const
2815 auto currentSelection = m_mainFrame->selection().selection();
2816 if (!currentSelection.isRange())
2819 if (auto selectedRange = currentSelection.toNormalizedRange()) {
2820 Vector<SelectionRect> selectionRects;
2821 selectedRange->collectSelectionRects(selectionRects);
2822 for (auto selectionRect : selectionRects) {
2823 if (FloatRect(selectionRect.rect()).contains(position))
2833 void Page::disableICECandidateFiltering()
2835 m_shouldEnableICECandidateFilteringByDefault = false;
2837 m_rtcController.disableICECandidateFilteringForAllOrigins();
2841 void Page::enableICECandidateFiltering()
2843 m_shouldEnableICECandidateFilteringByDefault = true;
2845 m_rtcController.enableICECandidateFiltering();
2849 void Page::didChangeMainDocument()
2852 m_rtcController.reset(m_shouldEnableICECandidateFilteringByDefault);
2854 #if ENABLE(POINTER_EVENTS)
2855 m_pointerCaptureController->reset();
2859 RenderingUpdateScheduler& Page::renderingUpdateScheduler()
2861 if (!m_renderingUpdateScheduler)
2862 m_renderingUpdateScheduler = RenderingUpdateScheduler::create(*this);
2863 return *m_renderingUpdateScheduler;
2866 void Page::forEachDocument(const Function<void(Document&)>& functor)
2868 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2869 if (!frame->document())
2872 functor(*frame->document());
2876 Vector<Ref<Document>> Page::collectDocuments()
2878 Vector<Ref<Document>> documents;
2879 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
2880 auto* document = frame->document();
2883 documents.append(*document);
2888 void Page::applicationWillResignActive()
2890 forEachDocument([&] (Document& document) {
2891 document.forEachApplicationStateChangeListener([&] (ApplicationStateChangeListener& listener) {
2892 listener.applicationWillResignActive();
2897 void Page::applicationDidEnterBackground()
2899 m_libWebRTCProvider->setActive(false);
2902 void Page::applicationWillEnterForeground()
2904 m_libWebRTCProvider->setActive(true);
2907 void Page::applicationDidBecomeActive()
2909 forEachDocument([&] (Document& document) {
2910 document.forEachApplicationStateChangeListener([&] (ApplicationStateChangeListener& listener) {
2911 listener.applicationDidBecomeActive();
2917 ScrollLatchingState* Page::latchingState()
2919 if (m_latchingState.isEmpty())
2922 return &m_latchingState.last();
2925 void Page::pushNewLatchingState()
2927 m_latchingState.append(ScrollLatchingState());
2930 void Page::resetLatchingState()
2932 m_latchingState.clear();
2935 void Page::popLatchingState()
2937 m_latchingState.removeLast();
2940 void Page::removeLatchingStateForTarget(Element& targetNode)
2942 if (m_latchingState.isEmpty())
2945 m_latchingState.removeAllMatching([&targetNode] (ScrollLatchingState& state) {
2946 auto* wheelElement = state.wheelEventElement();
2950 return targetNode.isEqualNode(wheelElement);
2953 #endif // PLATFORM(MAC)
2955 static void dispatchPrintEvent(Frame& mainFrame, const AtomString& eventType)
2957 Vector<Ref<Frame>> frames;
2958 for (auto* frame = &mainFrame; frame; frame = frame->tree().traverseNext())
2959 frames.append(*frame);
2961 for (auto& frame : frames) {
2962 if (auto* window = frame->window())
2963 window->dispatchEvent(Event::create(eventType, Event::CanBubble::No, Event::IsCancelable::No), window->document());
2967 void Page::dispatchBeforePrintEvent()
2969 dispatchPrintEvent(m_mainFrame, eventNames().beforeprintEvent);
2972 void Page::dispatchAfterPrintEvent()
2974 dispatchPrintEvent(m_mainFrame, eventNames().afterprintEvent);
2977 #if ENABLE(APPLE_PAY)
2978 void Page::setPaymentCoordinator(std::unique_ptr<PaymentCoordinator>&& paymentCoordinator)
2980 m_paymentCoordinator = WTFMove(paymentCoordinator);
2984 void Page::configureLoggingChannel(const String& channelName, WTFLogChannelState state, WTFLogLevel level)
2986 #if !RELEASE_LOG_DISABLED
2987 if (auto* channel = getLogChannel(channelName)) {
2988 channel->state = state;
2989 channel->level = level;
2992 if (channel == &LogWebRTC && m_mainFrame->document())
2993 libWebRTCProvider().setEnableLogging(!sessionID().isEphemeral());
2997 chrome().client().configureLoggingChannel(channelName, state, level);
2999 UNUSED_PARAM(channelName);
3000 UNUSED_PARAM(state);
3001 UNUSED_PARAM(level);
3005 void Page::didFinishLoadingImageForElement(HTMLImageElement& element)
3007 auto protectedElement = makeRef(element);
3008 if (auto frame = makeRefPtr(element.document().frame()))
3009 frame->editor().revealSelectionIfNeededAfterLoadingImageForElement(element);
3010 chrome().client().didFinishLoadingImageForElement(element);
3013 #if ENABLE(TEXT_AUTOSIZING)
3014 void Page::recomputeTextAutoSizingInAllFrames()
3016 ASSERT(settings().textAutosizingEnabled() && settings().textAutosizingUsesIdempotentMode());
3017 for (auto* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
3018 if (!frame->document())
3020 auto& document = *frame->document();
3021 if (!document.renderView() || !document.styleScope().resolverIfExists())
3024 auto& styleResolver = document.styleScope().resolver();
3025 for (auto& renderer : descendantsOfType<RenderElement>(*document.renderView())) {
3026 if (auto* element = renderer.element()) {
3027 auto needsLayout = styleResolver.adjustRenderStyleForTextAutosizing(renderer.mutableStyle(), *element);
3029 renderer.setNeedsLayout();
3036 } // namespace WebCore