Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: third_party/WebKit/Source/core/frame/FrameView.cpp

Issue 2272773002: Use intersection observer to control frame throttling (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Review comments Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 * 1999 Lars Knoll <knoll@kde.org> 3 * 1999 Lars Knoll <knoll@kde.org>
4 * 1999 Antti Koivisto <koivisto@kde.org> 4 * 1999 Antti Koivisto <koivisto@kde.org>
5 * 2000 Dirk Mueller <mueller@kde.org> 5 * 2000 Dirk Mueller <mueller@kde.org>
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
7 * (C) 2006 Graham Dennis (graham.dennis@gmail.com) 7 * (C) 2006 Graham Dennis (graham.dennis@gmail.com)
8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9 * Copyright (C) 2009 Google Inc. All rights reserved. 9 * Copyright (C) 2009 Google Inc. All rights reserved.
10 * 10 *
(...skipping 15 matching lines...) Expand all
26 26
27 #include "core/frame/FrameView.h" 27 #include "core/frame/FrameView.h"
28 28
29 #include "core/HTMLNames.h" 29 #include "core/HTMLNames.h"
30 #include "core/MediaTypeNames.h" 30 #include "core/MediaTypeNames.h"
31 #include "core/css/FontFaceSet.h" 31 #include "core/css/FontFaceSet.h"
32 #include "core/css/resolver/StyleResolver.h" 32 #include "core/css/resolver/StyleResolver.h"
33 #include "core/dom/AXObjectCache.h" 33 #include "core/dom/AXObjectCache.h"
34 #include "core/dom/DOMNodeIds.h" 34 #include "core/dom/DOMNodeIds.h"
35 #include "core/dom/Fullscreen.h" 35 #include "core/dom/Fullscreen.h"
36 #include "core/dom/IntersectionObserverCallback.h"
36 #include "core/dom/IntersectionObserverController.h" 37 #include "core/dom/IntersectionObserverController.h"
38 #include "core/dom/IntersectionObserverInit.h"
37 #include "core/editing/EditingUtilities.h" 39 #include "core/editing/EditingUtilities.h"
38 #include "core/editing/FrameSelection.h" 40 #include "core/editing/FrameSelection.h"
39 #include "core/editing/RenderedPosition.h" 41 #include "core/editing/RenderedPosition.h"
40 #include "core/editing/markers/DocumentMarkerController.h" 42 #include "core/editing/markers/DocumentMarkerController.h"
41 #include "core/events/ErrorEvent.h" 43 #include "core/events/ErrorEvent.h"
42 #include "core/fetch/ResourceFetcher.h" 44 #include "core/fetch/ResourceFetcher.h"
43 #include "core/frame/EventHandlerRegistry.h" 45 #include "core/frame/EventHandlerRegistry.h"
44 #include "core/frame/FrameHost.h" 46 #include "core/frame/FrameHost.h"
45 #include "core/frame/LocalFrame.h" 47 #include "core/frame/LocalFrame.h"
46 #include "core/frame/Location.h" 48 #include "core/frame/Location.h"
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 static bool s_initialTrackAllPaintInvalidations = false; 146 static bool s_initialTrackAllPaintInvalidations = false;
145 147
146 FrameView::FrameView(LocalFrame* frame) 148 FrameView::FrameView(LocalFrame* frame)
147 : m_frame(frame) 149 : m_frame(frame)
148 , m_displayMode(WebDisplayModeBrowser) 150 , m_displayMode(WebDisplayModeBrowser)
149 , m_canHaveScrollbars(true) 151 , m_canHaveScrollbars(true)
150 , m_hasPendingLayout(false) 152 , m_hasPendingLayout(false)
151 , m_inSynchronousPostLayout(false) 153 , m_inSynchronousPostLayout(false)
152 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired) 154 , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
153 , m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired) 155 , m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired)
154 , m_renderThrottlingObserverNotificationFactory(CancellableTaskFactory::crea te(this, &FrameView::notifyRenderThrottlingObservers))
155 , m_isTransparent(false) 156 , m_isTransparent(false)
156 , m_baseBackgroundColor(Color::white) 157 , m_baseBackgroundColor(Color::white)
157 , m_mediaType(MediaTypeNames::screen) 158 , m_mediaType(MediaTypeNames::screen)
158 , m_safeToPropagateScrollToParent(true) 159 , m_safeToPropagateScrollToParent(true)
159 , m_scrollCorner(nullptr) 160 , m_scrollCorner(nullptr)
160 , m_stickyPositionObjectCount(0) 161 , m_stickyPositionObjectCount(0)
161 , m_inputEventsScaleFactorForEmulation(1) 162 , m_inputEventsScaleFactorForEmulation(1)
162 , m_layoutSizeFixedToFrameSize(true) 163 , m_layoutSizeFixedToFrameSize(true)
163 , m_didScrollTimer(this, &FrameView::didScrollTimerFired) 164 , m_didScrollTimer(this, &FrameView::didScrollTimerFired)
164 , m_topControlsViewportAdjustment(0) 165 , m_topControlsViewportAdjustment(0)
165 , m_needsUpdateWidgetGeometries(false) 166 , m_needsUpdateWidgetGeometries(false)
166 , m_needsUpdateViewportIntersection(true)
167 , m_needsUpdateViewportIntersectionInSubtree(true) 167 , m_needsUpdateViewportIntersectionInSubtree(true)
168 #if ENABLE(ASSERT) 168 #if ENABLE(ASSERT)
169 , m_hasBeenDisposed(false) 169 , m_hasBeenDisposed(false)
170 #endif 170 #endif
171 , m_horizontalScrollbarMode(ScrollbarAuto) 171 , m_horizontalScrollbarMode(ScrollbarAuto)
172 , m_verticalScrollbarMode(ScrollbarAuto) 172 , m_verticalScrollbarMode(ScrollbarAuto)
173 , m_horizontalScrollbarLock(false) 173 , m_horizontalScrollbarLock(false)
174 , m_verticalScrollbarLock(false) 174 , m_verticalScrollbarLock(false)
175 , m_scrollbarsAvoidingResizer(0) 175 , m_scrollbarsAvoidingResizer(0)
176 , m_scrollbarsSuppressed(false) 176 , m_scrollbarsSuppressed(false)
177 , m_inUpdateScrollbars(false) 177 , m_inUpdateScrollbars(false)
178 , m_frameTimingRequestsDirty(true) 178 , m_frameTimingRequestsDirty(true)
179 , m_viewportIntersectionValid(false)
180 , m_hiddenForThrottling(false) 179 , m_hiddenForThrottling(false)
181 , m_crossOriginForThrottling(false)
182 , m_subtreeThrottled(false) 180 , m_subtreeThrottled(false)
183 , m_currentUpdateLifecyclePhasesTargetState(DocumentLifecycle::Uninitialized ) 181 , m_currentUpdateLifecyclePhasesTargetState(DocumentLifecycle::Uninitialized )
184 , m_needsScrollbarsUpdate(false) 182 , m_needsScrollbarsUpdate(false)
185 , m_suppressAdjustViewSize(false) 183 , m_suppressAdjustViewSize(false)
186 , m_allowsLayoutInvalidationAfterLayoutClean(true) 184 , m_allowsLayoutInvalidationAfterLayoutClean(true)
187 { 185 {
188 ASSERT(m_frame); 186 ASSERT(m_frame);
189 init(); 187 init();
190 } 188 }
191 189
(...skipping 24 matching lines...) Expand all
216 visitor->trace(m_frame); 214 visitor->trace(m_frame);
217 visitor->trace(m_fragmentAnchor); 215 visitor->trace(m_fragmentAnchor);
218 visitor->trace(m_scrollableAreas); 216 visitor->trace(m_scrollableAreas);
219 visitor->trace(m_animatingScrollableAreas); 217 visitor->trace(m_animatingScrollableAreas);
220 visitor->trace(m_autoSizeInfo); 218 visitor->trace(m_autoSizeInfo);
221 visitor->trace(m_horizontalScrollbar); 219 visitor->trace(m_horizontalScrollbar);
222 visitor->trace(m_verticalScrollbar); 220 visitor->trace(m_verticalScrollbar);
223 visitor->trace(m_children); 221 visitor->trace(m_children);
224 visitor->trace(m_viewportScrollableArea); 222 visitor->trace(m_viewportScrollableArea);
225 visitor->trace(m_scrollAnchor); 223 visitor->trace(m_scrollAnchor);
224 visitor->trace(m_intersectionObserver);
226 Widget::trace(visitor); 225 Widget::trace(visitor);
227 ScrollableArea::trace(visitor); 226 ScrollableArea::trace(visitor);
228 } 227 }
229 228
230 void FrameView::reset() 229 void FrameView::reset()
231 { 230 {
232 m_hasPendingLayout = false; 231 m_hasPendingLayout = false;
233 m_layoutSchedulingEnabled = true; 232 m_layoutSchedulingEnabled = true;
234 m_inSynchronousPostLayout = false; 233 m_inSynchronousPostLayout = false;
235 m_layoutCount = 0; 234 m_layoutCount = 0;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 { 272 {
274 reset(); 273 reset();
275 274
276 m_size = LayoutSize(); 275 m_size = LayoutSize();
277 276
278 // Propagate the marginwidth/height and scrolling modes to the view. 277 // Propagate the marginwidth/height and scrolling modes to the view.
279 if (m_frame->owner() && m_frame->owner()->scrollingMode() == ScrollbarAlways Off) 278 if (m_frame->owner() && m_frame->owner()->scrollingMode() == ScrollbarAlways Off)
280 setCanHaveScrollbars(false); 279 setCanHaveScrollbars(false);
281 } 280 }
282 281
282 void FrameView::setupRenderThrottling()
283 {
284 if (m_intersectionObserver || !frame().document() || !frame().document()->fr ame() || !frame().document()->documentElement())
285 return;
286
287 ExecutionContext* context = frame().document();
288 IntersectionObserverInit observerInit;
289 // Intersection observer does not currently support remote frames. As a
290 // workaround we monitor visibility up to the local root (crbug.com/615156).
291 Frame* mainFrame = frame().tree().top();
292 if (!mainFrame || !mainFrame->isLocalFrame()) {
293 observerInit.setRoot(frame().localFrameRoot()->document()->documentEleme nt());
294 context = &observerInit.root()->document();
295 }
szager1 2016/08/31 20:54:27 Shouldn't this be: } else { context = mainFrame
Sami 2016/09/01 11:11:35 Ah, well spotted, thanks.
296
297 IntersectionObserverCallback* callback = new IntersectionObserverCallback(th is, context);
298 m_intersectionObserver = IntersectionObserver::create(observerInit, *callbac k, ASSERT_NO_EXCEPTION);
299 m_intersectionObserver->setLowLatency(true);
300 m_intersectionObserver->observe(frame().document()->documentElement());
301
302 // Initially the intersection observer assumes the target is hidden. If it
303 // actually is, no notification about this will be delivered. To work around
304 // this, we set the observer into an undefined state so the first
305 // notification will always get delivered.
306 for (auto& observation : m_intersectionObserver->observations())
307 observation->setLastThresholdIndex(std::numeric_limits<unsigned>::max()) ;
308 }
309
283 void FrameView::dispose() 310 void FrameView::dispose()
284 { 311 {
285 RELEASE_ASSERT(!isInPerformLayout()); 312 RELEASE_ASSERT(!isInPerformLayout());
286 313
287 if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) 314 if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator())
288 scrollAnimator->cancelAnimation(); 315 scrollAnimator->cancelAnimation();
289 cancelProgrammaticScrollAnimation(); 316 cancelProgrammaticScrollAnimation();
290 317
291 detachScrollbars(); 318 detachScrollbars();
292 319
(...skipping 10 matching lines...) Expand all
303 330
304 // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing 331 // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing
305 // partially destroyed |this| via |m_autoSizeInfo->m_frameView|. 332 // partially destroyed |this| via |m_autoSizeInfo->m_frameView|.
306 m_autoSizeInfo.clear(); 333 m_autoSizeInfo.clear();
307 334
308 if (m_postLayoutTasksTimer.isActive()) 335 if (m_postLayoutTasksTimer.isActive())
309 m_postLayoutTasksTimer.stop(); 336 m_postLayoutTasksTimer.stop();
310 337
311 if (m_didScrollTimer.isActive()) 338 if (m_didScrollTimer.isActive())
312 m_didScrollTimer.stop(); 339 m_didScrollTimer.stop();
313 m_renderThrottlingObserverNotificationFactory->cancel();
314 340
315 // FIXME: Do we need to do something here for OOPI? 341 // FIXME: Do we need to do something here for OOPI?
316 HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner(); 342 HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner();
317 // TODO(dcheng): It seems buggy that we can have an owner element that 343 // TODO(dcheng): It seems buggy that we can have an owner element that
318 // points to another Widget. 344 // points to another Widget.
319 if (ownerElement && ownerElement->ownedWidget() == this) 345 if (ownerElement && ownerElement->ownedWidget() == this)
320 ownerElement->setWidget(nullptr); 346 ownerElement->setWidget(nullptr);
321 347
322 #if ENABLE(ASSERT) 348 #if ENABLE(ASSERT)
323 m_hasBeenDisposed = true; 349 m_hasBeenDisposed = true;
(...skipping 2859 matching lines...) Expand 10 before | Expand all | Expand 10 after
3183 if (m_scrollbarsAvoidingResizer && parent()) 3209 if (m_scrollbarsAvoidingResizer && parent())
3184 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(-m_scrollbar sAvoidingResizer); 3210 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(-m_scrollbar sAvoidingResizer);
3185 3211
3186 Widget::setParent(parentView); 3212 Widget::setParent(parentView);
3187 3213
3188 if (m_scrollbarsAvoidingResizer && parent()) 3214 if (m_scrollbarsAvoidingResizer && parent())
3189 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(m_scrollbars AvoidingResizer); 3215 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(m_scrollbars AvoidingResizer);
3190 3216
3191 updateScrollableAreaSet(); 3217 updateScrollableAreaSet();
3192 setNeedsUpdateViewportIntersection(); 3218 setNeedsUpdateViewportIntersection();
3219
3220 setupRenderThrottling();
3193 } 3221 }
3194 3222
3195 void FrameView::removeChild(Widget* child) 3223 void FrameView::removeChild(Widget* child)
3196 { 3224 {
3197 ASSERT(child->parent() == this); 3225 ASSERT(child->parent() == this);
3198 3226
3199 if (child->isFrameView()) 3227 if (child->isFrameView())
3200 removeScrollableArea(toFrameView(child)); 3228 removeScrollableArea(toFrameView(child));
3201 3229
3202 child->setParent(0); 3230 child->setParent(0);
(...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after
4161 if (layoutObject.isText()) 4189 if (layoutObject.isText())
4162 return; 4190 return;
4163 4191
4164 layoutObject.addAnnotatedRegions(regions); 4192 layoutObject.addAnnotatedRegions(regions);
4165 for (LayoutObject* curr = layoutObject.slowFirstChild(); curr; curr = curr-> nextSibling()) 4193 for (LayoutObject* curr = layoutObject.slowFirstChild(); curr; curr = curr-> nextSibling())
4166 collectAnnotatedRegions(*curr, regions); 4194 collectAnnotatedRegions(*curr, regions);
4167 } 4195 }
4168 4196
4169 void FrameView::setNeedsUpdateViewportIntersection() 4197 void FrameView::setNeedsUpdateViewportIntersection()
4170 { 4198 {
4171 m_needsUpdateViewportIntersection = true;
4172 for (FrameView* parent = parentFrameView(); parent; parent = parent->parentF rameView()) 4199 for (FrameView* parent = parentFrameView(); parent; parent = parent->parentF rameView())
4173 parent->m_needsUpdateViewportIntersectionInSubtree = true; 4200 parent->m_needsUpdateViewportIntersectionInSubtree = true;
4174 } 4201 }
4175 4202
4176 void FrameView::updateViewportIntersectionIfNeeded()
4177 {
4178 if (!m_needsUpdateViewportIntersection)
4179 return;
4180 m_needsUpdateViewportIntersection = false;
4181 m_viewportIntersectionValid = true;
4182 FrameView* parent = parentFrameView();
4183 if (!parent) {
4184 m_viewportIntersection = frameRect();
4185 return;
4186 }
4187 ASSERT(!parent->m_needsUpdateViewportIntersection);
4188
4189 // If our parent is hidden, then we are too.
4190 if (parent->m_viewportIntersection.isEmpty()) {
4191 m_viewportIntersection = parent->m_viewportIntersection;
4192 return;
4193 }
4194
4195 // Transform our bounds into the root frame's content coordinate space,
4196 // making sure we have valid layout data in our parent document. If our
4197 // parent is throttled, we'll use possible stale layout information and
4198 // rely on the fact that another lifecycle update will be scheduled once
4199 // our parent becomes unthrottled.
4200 ASSERT(parent->lifecycle().state() >= DocumentLifecycle::LayoutClean || pare nt->shouldThrottleRendering());
4201 m_viewportIntersection = parent->contentsToRootFrame(frameRect());
4202
4203 // TODO(skyostil): Expand the viewport to make it less likely to see stale c ontent while scrolling.
4204 IntRect viewport = parent->m_viewportIntersection;
4205 m_viewportIntersection.intersect(viewport);
4206 }
4207
4208 void FrameView::updateViewportIntersectionsForSubtree(DocumentLifecycle::Lifecyc leState targetState) 4203 void FrameView::updateViewportIntersectionsForSubtree(DocumentLifecycle::Lifecyc leState targetState)
4209 { 4204 {
4210 bool hadValidIntersection = m_viewportIntersectionValid;
4211 bool hadEmptyIntersection = m_viewportIntersection.isEmpty();
4212 updateViewportIntersectionIfNeeded();
4213
4214 // Notify javascript IntersectionObservers 4205 // Notify javascript IntersectionObservers
4215 if (targetState == DocumentLifecycle::PaintClean && frame().document()->inte rsectionObserverController()) 4206 if (targetState == DocumentLifecycle::PaintClean && frame().document()->inte rsectionObserverController())
4216 frame().document()->intersectionObserverController()->computeTrackedInte rsectionObservations(); 4207 frame().document()->intersectionObserverController()->computeTrackedInte rsectionObservations();
4217 4208
4218 // Adjust render throttling for iframes based on visibility
4219 bool shouldNotify = !hadValidIntersection || hadEmptyIntersection != m_viewp ortIntersection.isEmpty();
4220 if (shouldNotify && !m_renderThrottlingObserverNotificationFactory->isPendin g())
4221 m_frame->frameScheduler()->unthrottledTaskRunner()->postTask(BLINK_FROM_ HERE, m_renderThrottlingObserverNotificationFactory->cancelAndCreate());
4222
4223 if (!m_needsUpdateViewportIntersectionInSubtree) 4209 if (!m_needsUpdateViewportIntersectionInSubtree)
4224 return; 4210 return;
4225 m_needsUpdateViewportIntersectionInSubtree = false; 4211 m_needsUpdateViewportIntersectionInSubtree = false;
4226 4212
4227 for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree ().nextSibling()) { 4213 for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree ().nextSibling()) {
4228 if (!child->isLocalFrame()) 4214 if (!child->isLocalFrame())
4229 continue; 4215 continue;
4230 if (FrameView* view = toLocalFrame(child)->view()) 4216 if (FrameView* view = toLocalFrame(child)->view())
4231 view->updateViewportIntersectionsForSubtree(targetState); 4217 view->updateViewportIntersectionsForSubtree(targetState);
4232 } 4218 }
4233 } 4219 }
4234 4220
4235 void FrameView::updateThrottlingStatus() 4221 void FrameView::updateRenderThrottlingStatusForTesting()
4236 { 4222 {
4237 // Only offscreen frames can be throttled. 4223 m_intersectionObserver->deliver();
4238 DCHECK(m_viewportIntersectionValid);
4239 m_hiddenForThrottling = m_viewportIntersection.isEmpty();
4240
4241 // We only throttle the rendering pipeline in cross-origin frames. This is
4242 // to avoid a situation where an ancestor frame directly depends on the
4243 // pipeline timing of a descendant and breaks as a result of throttling.
4244 // The rationale is that cross-origin frames must already communicate with
4245 // asynchronous messages, so they should be able to tolerate some delay in
4246 // receiving replies from a throttled peer.
4247 //
4248 // Check if we can access our parent's security origin.
4249 m_crossOriginForThrottling = false;
4250 // If any of our parents are throttled, we must be too.
4251 m_subtreeThrottled = false;
4252 const SecurityOrigin* origin = frame().securityContext()->getSecurityOrigin( );
4253 for (Frame* parentFrame = m_frame->tree().parent(); parentFrame; parentFrame = parentFrame->tree().parent()) {
4254 const SecurityOrigin* parentOrigin = parentFrame->securityContext()->get SecurityOrigin();
4255 if (!origin->canAccess(parentOrigin))
4256 m_crossOriginForThrottling = true;
4257 if (parentFrame->isLocalFrame() && toLocalFrame(parentFrame)->view() && toLocalFrame(parentFrame)->view()->canThrottleRendering())
4258 m_subtreeThrottled = true;
4259 }
4260 m_frame->frameScheduler()->setFrameVisible(!m_hiddenForThrottling);
4261 m_frame->frameScheduler()->setCrossOrigin(m_crossOriginForThrottling);
4262 } 4224 }
4263 4225
4264 void FrameView::notifyRenderThrottlingObserversForTesting() 4226 void FrameView::updateRenderThrottlingStatus(bool hidden, bool subtreeThrottled)
4265 {
4266 DCHECK(m_renderThrottlingObserverNotificationFactory->isPending());
4267 notifyRenderThrottlingObservers();
4268 }
4269
4270 void FrameView::notifyRenderThrottlingObservers()
4271 { 4227 {
4272 TRACE_EVENT0("blink", "FrameView::notifyRenderThrottlingObservers"); 4228 TRACE_EVENT0("blink", "FrameView::notifyRenderThrottlingObservers");
4273 DCHECK(!isInPerformLayout()); 4229 DCHECK(!isInPerformLayout());
4274 DCHECK(!m_frame->document() || !m_frame->document()->inStyleRecalc()); 4230 DCHECK(!m_frame->document() || !m_frame->document()->inStyleRecalc());
4275 bool wasThrottled = canThrottleRendering(); 4231 bool wasThrottled = canThrottleRendering();
4276 4232
4277 updateThrottlingStatus(); 4233 m_hiddenForThrottling = hidden;
4234 m_subtreeThrottled = subtreeThrottled;
4278 4235
4279 bool becameThrottled = !wasThrottled && canThrottleRendering(); 4236 bool isThrottled = canThrottleRendering();
4280 bool becameUnthrottled = wasThrottled && !canThrottleRendering(); 4237 bool becameUnthrottled = wasThrottled && !isThrottled;
4238
4239 // If this FrameView became unthrottled or throttled, we must make sure all
4240 // its children are notified synchronously. Otherwise we 1) might attempt to
4241 // paint one of the children with an out-of-date layout before
4242 // |updateRenderThrottlingStatus| has made it throttled or 2) fail to
4243 // unthrottle a child whose parent is unthrottled by a later notification.
4244 if (wasThrottled != isThrottled) {
4245 for (const Member<Widget>& child : *children()) {
4246 if (child->isFrameView()) {
4247 FrameView* childView = toFrameView(child);
4248 childView->updateRenderThrottlingStatus(childView->m_hiddenForTh rottling, isThrottled);
4249 }
4250 }
4251 }
4252
4281 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator(); 4253 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
4282 if (becameThrottled) {
4283 // If this FrameView became throttled, we must make sure all of its
4284 // children become throttled at the same time. Otherwise we might
4285 // attempt to paint one of the children with an out-of-date layout
4286 // before |notifyRenderThrottlingObservers| has made it throttled.
4287 forAllNonThrottledFrameViews([](FrameView& frameView) {
4288 frameView.m_subtreeThrottled = true;
4289 DCHECK(frameView.canThrottleRendering());
4290 });
4291 }
4292 if (becameUnthrottled) { 4254 if (becameUnthrottled) {
4293 // ScrollingCoordinator needs to update according to the new throttling status. 4255 // ScrollingCoordinator needs to update according to the new throttling status.
4294 if (scrollingCoordinator) 4256 if (scrollingCoordinator)
4295 scrollingCoordinator->notifyGeometryChanged(); 4257 scrollingCoordinator->notifyGeometryChanged();
4296 // Start ticking animation frames again if necessary. 4258 // Start ticking animation frames again if necessary.
4297 if (page()) 4259 if (page())
4298 page()->animator().scheduleVisualUpdate(m_frame.get()); 4260 page()->animator().scheduleVisualUpdate(m_frame.get());
4299 // Force a full repaint of this frame to ensure we are not left with a 4261 // Force a full repaint of this frame to ensure we are not left with a
4300 // partially painted version of this frame's contents if we skipped 4262 // partially painted version of this frame's contents if we skipped
4301 // painting them while the frame was throttled. 4263 // painting them while the frame was throttled.
(...skipping 18 matching lines...) Expand all
4320 4282
4321 bool FrameView::shouldThrottleRendering() const 4283 bool FrameView::shouldThrottleRendering() const
4322 { 4284 {
4323 return canThrottleRendering() && lifecycle().throttlingAllowed(); 4285 return canThrottleRendering() && lifecycle().throttlingAllowed();
4324 } 4286 }
4325 4287
4326 bool FrameView::canThrottleRendering() const 4288 bool FrameView::canThrottleRendering() const
4327 { 4289 {
4328 if (!RuntimeEnabledFeatures::renderingPipelineThrottlingEnabled()) 4290 if (!RuntimeEnabledFeatures::renderingPipelineThrottlingEnabled())
4329 return false; 4291 return false;
4330 return m_subtreeThrottled || (m_hiddenForThrottling && m_crossOriginForThrot tling); 4292 // We only throttle the rendering pipeline in cross-origin frames. This is
4293 // to avoid a situation where an ancestor frame directly depends on the
4294 // pipeline timing of a descendant and breaks as a result of throttling.
4295 // The rationale is that cross-origin frames must already communicate with
4296 // asynchronous messages, so they should be able to tolerate some delay in
4297 // receiving replies from a throttled peer.
4298 return m_subtreeThrottled || (m_hiddenForThrottling && m_frame->isCrossOrigi nSubframe());
4299 }
4300
4301 FrameView::IntersectionObserverCallback::IntersectionObserverCallback(FrameView* frameView, ExecutionContext* context)
4302 : m_frameView(frameView)
4303 , m_context(context)
4304 {
4305 }
4306
4307 void FrameView::IntersectionObserverCallback::handleEvent(const HeapVector<Membe r<IntersectionObserverEntry>>& entries, IntersectionObserver&)
4308 {
4309 if (!m_frameView)
4310 return;
4311 bool wasHidden = m_frameView->m_hiddenForThrottling;
4312 bool isHidden = wasHidden;
4313 if (!entries.isEmpty())
4314 isHidden = !entries.last()->intersectionRatio();
4315 if (wasHidden != isHidden)
4316 m_frameView->updateRenderThrottlingStatus(isHidden, m_frameView->m_subtr eeThrottled);
4317 }
4318
4319 ExecutionContext* FrameView::IntersectionObserverCallback::getExecutionContext() const
4320 {
4321 return m_context.get();
4322 }
4323
4324 DEFINE_TRACE(FrameView::IntersectionObserverCallback)
4325 {
4326 blink::IntersectionObserverCallback::trace(visitor);
4327 visitor->trace(m_frameView);
4328 visitor->trace(m_context);
4331 } 4329 }
4332 4330
4333 } // namespace blink 4331 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/frame/FrameView.h ('k') | third_party/WebKit/Source/web/tests/FrameThrottlingTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698