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

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: Rebased 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;
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());
haraken 2016/09/12 00:46:32 This looks a bit too weird to me. Maybe can we jus
294 context = &observerInit.root()->document();
295 } else {
296 context = toLocalFrame(mainFrame)->document();
297 }
298
299 IntersectionObserverCallback* callback = new IntersectionObserverCallback(th is, context);
300 m_intersectionObserver = IntersectionObserver::create(observerInit, *callbac k, ASSERT_NO_EXCEPTION);
301 m_intersectionObserver->setLowLatency(true);
302 m_intersectionObserver->observe(frame().document()->documentElement());
303
304 // Initially the intersection observer assumes the target is hidden. If it
305 // actually is, no notification about this will be delivered. To work around
306 // this, we set the observer into an undefined state so the first
307 // notification will always get delivered.
308 for (auto& observation : m_intersectionObserver->observations())
309 observation->setLastThresholdIndex(std::numeric_limits<unsigned>::max()) ;
310 }
311
283 void FrameView::dispose() 312 void FrameView::dispose()
284 { 313 {
285 RELEASE_ASSERT(!isInPerformLayout()); 314 RELEASE_ASSERT(!isInPerformLayout());
286 315
287 if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) 316 if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator())
288 scrollAnimator->cancelAnimation(); 317 scrollAnimator->cancelAnimation();
289 cancelProgrammaticScrollAnimation(); 318 cancelProgrammaticScrollAnimation();
290 319
291 detachScrollbars(); 320 detachScrollbars();
292 321
(...skipping 10 matching lines...) Expand all
303 332
304 // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing 333 // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing
305 // partially destroyed |this| via |m_autoSizeInfo->m_frameView|. 334 // partially destroyed |this| via |m_autoSizeInfo->m_frameView|.
306 m_autoSizeInfo.clear(); 335 m_autoSizeInfo.clear();
307 336
308 if (m_postLayoutTasksTimer.isActive()) 337 if (m_postLayoutTasksTimer.isActive())
309 m_postLayoutTasksTimer.stop(); 338 m_postLayoutTasksTimer.stop();
310 339
311 if (m_didScrollTimer.isActive()) 340 if (m_didScrollTimer.isActive())
312 m_didScrollTimer.stop(); 341 m_didScrollTimer.stop();
313 m_renderThrottlingObserverNotificationFactory->cancel();
314 342
315 // FIXME: Do we need to do something here for OOPI? 343 // FIXME: Do we need to do something here for OOPI?
316 HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner(); 344 HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner();
317 // TODO(dcheng): It seems buggy that we can have an owner element that 345 // TODO(dcheng): It seems buggy that we can have an owner element that
318 // points to another Widget. 346 // points to another Widget.
319 if (ownerElement && ownerElement->ownedWidget() == this) 347 if (ownerElement && ownerElement->ownedWidget() == this)
320 ownerElement->setWidget(nullptr); 348 ownerElement->setWidget(nullptr);
321 349
322 #if ENABLE(ASSERT) 350 #if ENABLE(ASSERT)
323 m_hasBeenDisposed = true; 351 m_hasBeenDisposed = true;
(...skipping 2878 matching lines...) Expand 10 before | Expand all | Expand 10 after
3202 if (m_scrollbarsAvoidingResizer && parent()) 3230 if (m_scrollbarsAvoidingResizer && parent())
3203 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(-m_scrollbar sAvoidingResizer); 3231 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(-m_scrollbar sAvoidingResizer);
3204 3232
3205 Widget::setParent(parentView); 3233 Widget::setParent(parentView);
3206 3234
3207 if (m_scrollbarsAvoidingResizer && parent()) 3235 if (m_scrollbarsAvoidingResizer && parent())
3208 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(m_scrollbars AvoidingResizer); 3236 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(m_scrollbars AvoidingResizer);
3209 3237
3210 updateScrollableAreaSet(); 3238 updateScrollableAreaSet();
3211 setNeedsUpdateViewportIntersection(); 3239 setNeedsUpdateViewportIntersection();
3240
3241 setupRenderThrottling();
3212 } 3242 }
3213 3243
3214 void FrameView::removeChild(Widget* child) 3244 void FrameView::removeChild(Widget* child)
3215 { 3245 {
3216 ASSERT(child->parent() == this); 3246 ASSERT(child->parent() == this);
3217 3247
3218 if (child->isFrameView()) 3248 if (child->isFrameView())
3219 removeScrollableArea(toFrameView(child)); 3249 removeScrollableArea(toFrameView(child));
3220 3250
3221 child->setParent(0); 3251 child->setParent(0);
(...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after
4180 if (layoutObject.isText()) 4210 if (layoutObject.isText())
4181 return; 4211 return;
4182 4212
4183 layoutObject.addAnnotatedRegions(regions); 4213 layoutObject.addAnnotatedRegions(regions);
4184 for (LayoutObject* curr = layoutObject.slowFirstChild(); curr; curr = curr-> nextSibling()) 4214 for (LayoutObject* curr = layoutObject.slowFirstChild(); curr; curr = curr-> nextSibling())
4185 collectAnnotatedRegions(*curr, regions); 4215 collectAnnotatedRegions(*curr, regions);
4186 } 4216 }
4187 4217
4188 void FrameView::setNeedsUpdateViewportIntersection() 4218 void FrameView::setNeedsUpdateViewportIntersection()
4189 { 4219 {
4190 m_needsUpdateViewportIntersection = true;
4191 for (FrameView* parent = parentFrameView(); parent; parent = parent->parentF rameView()) 4220 for (FrameView* parent = parentFrameView(); parent; parent = parent->parentF rameView())
4192 parent->m_needsUpdateViewportIntersectionInSubtree = true; 4221 parent->m_needsUpdateViewportIntersectionInSubtree = true;
4193 } 4222 }
4194 4223
4195 void FrameView::updateViewportIntersectionIfNeeded()
4196 {
4197 if (!m_needsUpdateViewportIntersection)
4198 return;
4199 m_needsUpdateViewportIntersection = false;
4200 m_viewportIntersectionValid = true;
4201 FrameView* parent = parentFrameView();
4202 if (!parent) {
4203 m_viewportIntersection = frameRect();
4204 return;
4205 }
4206 ASSERT(!parent->m_needsUpdateViewportIntersection);
4207
4208 // If our parent is hidden, then we are too.
4209 if (parent->m_viewportIntersection.isEmpty()) {
4210 m_viewportIntersection = parent->m_viewportIntersection;
4211 return;
4212 }
4213
4214 // Transform our bounds into the root frame's content coordinate space,
4215 // making sure we have valid layout data in our parent document. If our
4216 // parent is throttled, we'll use possible stale layout information and
4217 // rely on the fact that another lifecycle update will be scheduled once
4218 // our parent becomes unthrottled.
4219 ASSERT(parent->lifecycle().state() >= DocumentLifecycle::LayoutClean || pare nt->shouldThrottleRendering());
4220 m_viewportIntersection = parent->contentsToRootFrame(frameRect());
4221
4222 // TODO(skyostil): Expand the viewport to make it less likely to see stale c ontent while scrolling.
4223 IntRect viewport = parent->m_viewportIntersection;
4224 m_viewportIntersection.intersect(viewport);
4225 }
4226
4227 void FrameView::updateViewportIntersectionsForSubtree(DocumentLifecycle::Lifecyc leState targetState) 4224 void FrameView::updateViewportIntersectionsForSubtree(DocumentLifecycle::Lifecyc leState targetState)
4228 { 4225 {
4229 bool hadValidIntersection = m_viewportIntersectionValid;
4230 bool hadEmptyIntersection = m_viewportIntersection.isEmpty();
4231 updateViewportIntersectionIfNeeded();
4232
4233 // Notify javascript IntersectionObservers 4226 // Notify javascript IntersectionObservers
4234 if (targetState == DocumentLifecycle::PaintClean && frame().document()->inte rsectionObserverController()) 4227 if (targetState == DocumentLifecycle::PaintClean && frame().document()->inte rsectionObserverController())
4235 frame().document()->intersectionObserverController()->computeTrackedInte rsectionObservations(); 4228 frame().document()->intersectionObserverController()->computeTrackedInte rsectionObservations();
4236 4229
4237 // Adjust render throttling for iframes based on visibility
4238 bool shouldNotify = !hadValidIntersection || hadEmptyIntersection != m_viewp ortIntersection.isEmpty();
4239 if (shouldNotify && !m_renderThrottlingObserverNotificationFactory->isPendin g())
4240 m_frame->frameScheduler()->unthrottledTaskRunner()->postTask(BLINK_FROM_ HERE, m_renderThrottlingObserverNotificationFactory->cancelAndCreate());
4241
4242 if (!m_needsUpdateViewportIntersectionInSubtree) 4230 if (!m_needsUpdateViewportIntersectionInSubtree)
4243 return; 4231 return;
4244 m_needsUpdateViewportIntersectionInSubtree = false; 4232 m_needsUpdateViewportIntersectionInSubtree = false;
4245 4233
4246 for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree ().nextSibling()) { 4234 for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree ().nextSibling()) {
4247 if (!child->isLocalFrame()) 4235 if (!child->isLocalFrame())
4248 continue; 4236 continue;
4249 if (FrameView* view = toLocalFrame(child)->view()) 4237 if (FrameView* view = toLocalFrame(child)->view())
4250 view->updateViewportIntersectionsForSubtree(targetState); 4238 view->updateViewportIntersectionsForSubtree(targetState);
4251 } 4239 }
4252 } 4240 }
4253 4241
4254 void FrameView::updateThrottlingStatus() 4242 void FrameView::updateRenderThrottlingStatusForTesting()
4255 { 4243 {
4256 // Only offscreen frames can be throttled. 4244 m_intersectionObserver->deliver();
4257 DCHECK(m_viewportIntersectionValid);
4258 m_hiddenForThrottling = m_viewportIntersection.isEmpty();
4259
4260 // We only throttle the rendering pipeline in cross-origin frames. This is
4261 // to avoid a situation where an ancestor frame directly depends on the
4262 // pipeline timing of a descendant and breaks as a result of throttling.
4263 // The rationale is that cross-origin frames must already communicate with
4264 // asynchronous messages, so they should be able to tolerate some delay in
4265 // receiving replies from a throttled peer.
4266 //
4267 // Check if we can access our parent's security origin.
4268 m_crossOriginForThrottling = false;
4269 // If any of our parents are throttled, we must be too.
4270 m_subtreeThrottled = false;
4271 const SecurityOrigin* origin = frame().securityContext()->getSecurityOrigin( );
4272 for (Frame* parentFrame = m_frame->tree().parent(); parentFrame; parentFrame = parentFrame->tree().parent()) {
4273 const SecurityOrigin* parentOrigin = parentFrame->securityContext()->get SecurityOrigin();
4274 if (!origin->canAccess(parentOrigin))
4275 m_crossOriginForThrottling = true;
4276 if (parentFrame->isLocalFrame() && toLocalFrame(parentFrame)->view() && toLocalFrame(parentFrame)->view()->canThrottleRendering())
4277 m_subtreeThrottled = true;
4278 }
4279 m_frame->frameScheduler()->setFrameVisible(!m_hiddenForThrottling);
4280 m_frame->frameScheduler()->setCrossOrigin(m_crossOriginForThrottling);
4281 } 4245 }
4282 4246
4283 void FrameView::notifyRenderThrottlingObserversForTesting() 4247 void FrameView::updateRenderThrottlingStatus(bool hidden, bool subtreeThrottled)
4284 {
4285 DCHECK(m_renderThrottlingObserverNotificationFactory->isPending());
4286 notifyRenderThrottlingObservers();
4287 }
4288
4289 void FrameView::notifyRenderThrottlingObservers()
4290 { 4248 {
4291 TRACE_EVENT0("blink", "FrameView::notifyRenderThrottlingObservers"); 4249 TRACE_EVENT0("blink", "FrameView::notifyRenderThrottlingObservers");
4292 DCHECK(!isInPerformLayout()); 4250 DCHECK(!isInPerformLayout());
4293 DCHECK(frame().document()); 4251 DCHECK(!m_frame->document() || !m_frame->document()->inStyleRecalc());
4294 DCHECK(!frame().document()->inStyleRecalc());
4295 bool wasThrottled = canThrottleRendering(); 4252 bool wasThrottled = canThrottleRendering();
4296 4253
4297 updateThrottlingStatus(); 4254 m_hiddenForThrottling = hidden;
4255 m_subtreeThrottled = subtreeThrottled;
4298 4256
4299 frame().document()->onVisibilityMaybeChanged(!m_hiddenForThrottling); 4257 bool isThrottled = canThrottleRendering();
dgrogan 2016/09/15 23:47:07 If this was unintentionally dropped in the new cod
4258 bool becameUnthrottled = wasThrottled && !isThrottled;
4300 4259
4301 bool becameThrottled = !wasThrottled && canThrottleRendering(); 4260 // If this FrameView became unthrottled or throttled, we must make sure all
4302 bool becameUnthrottled = wasThrottled && !canThrottleRendering(); 4261 // its children are notified synchronously. Otherwise we 1) might attempt to
4262 // paint one of the children with an out-of-date layout before
4263 // |updateRenderThrottlingStatus| has made it throttled or 2) fail to
4264 // unthrottle a child whose parent is unthrottled by a later notification.
4265 if (wasThrottled != isThrottled) {
4266 for (const Member<Widget>& child : *children()) {
4267 if (child->isFrameView()) {
4268 FrameView* childView = toFrameView(child);
4269 childView->updateRenderThrottlingStatus(childView->m_hiddenForTh rottling, isThrottled);
4270 }
4271 }
4272 }
4273
4303 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator(); 4274 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
4304 if (becameThrottled) {
4305 // If this FrameView became throttled, we must make sure all of its
4306 // children become throttled at the same time. Otherwise we might
4307 // attempt to paint one of the children with an out-of-date layout
4308 // before |notifyRenderThrottlingObservers| has made it throttled.
4309 forAllNonThrottledFrameViews([](FrameView& frameView) {
4310 frameView.m_subtreeThrottled = true;
4311 DCHECK(frameView.canThrottleRendering());
4312 });
4313 }
4314 if (becameUnthrottled) { 4275 if (becameUnthrottled) {
4315 // ScrollingCoordinator needs to update according to the new throttling status. 4276 // ScrollingCoordinator needs to update according to the new throttling status.
4316 if (scrollingCoordinator) 4277 if (scrollingCoordinator)
4317 scrollingCoordinator->notifyGeometryChanged(); 4278 scrollingCoordinator->notifyGeometryChanged();
4318 // Start ticking animation frames again if necessary. 4279 // Start ticking animation frames again if necessary.
4319 if (page()) 4280 if (page())
4320 page()->animator().scheduleVisualUpdate(m_frame.get()); 4281 page()->animator().scheduleVisualUpdate(m_frame.get());
4321 // Force a full repaint of this frame to ensure we are not left with a 4282 // Force a full repaint of this frame to ensure we are not left with a
4322 // partially painted version of this frame's contents if we skipped 4283 // partially painted version of this frame's contents if we skipped
4323 // painting them while the frame was throttled. 4284 // painting them while the frame was throttled.
(...skipping 18 matching lines...) Expand all
4342 4303
4343 bool FrameView::shouldThrottleRendering() const 4304 bool FrameView::shouldThrottleRendering() const
4344 { 4305 {
4345 return canThrottleRendering() && lifecycle().throttlingAllowed(); 4306 return canThrottleRendering() && lifecycle().throttlingAllowed();
4346 } 4307 }
4347 4308
4348 bool FrameView::canThrottleRendering() const 4309 bool FrameView::canThrottleRendering() const
4349 { 4310 {
4350 if (!RuntimeEnabledFeatures::renderingPipelineThrottlingEnabled()) 4311 if (!RuntimeEnabledFeatures::renderingPipelineThrottlingEnabled())
4351 return false; 4312 return false;
4352 return m_subtreeThrottled || (m_hiddenForThrottling && m_crossOriginForThrot tling); 4313 // We only throttle the rendering pipeline in cross-origin frames. This is
4314 // to avoid a situation where an ancestor frame directly depends on the
4315 // pipeline timing of a descendant and breaks as a result of throttling.
4316 // The rationale is that cross-origin frames must already communicate with
4317 // asynchronous messages, so they should be able to tolerate some delay in
4318 // receiving replies from a throttled peer.
4319 return m_subtreeThrottled || (m_hiddenForThrottling && m_frame->isCrossOrigi nSubframe());
4320 }
4321
4322 FrameView::IntersectionObserverCallback::IntersectionObserverCallback(FrameView* frameView, ExecutionContext* context)
4323 : m_frameView(frameView)
4324 , m_context(context)
4325 {
4326 }
4327
4328 void FrameView::IntersectionObserverCallback::handleEvent(const HeapVector<Membe r<IntersectionObserverEntry>>& entries, IntersectionObserver&)
4329 {
4330 if (!m_frameView)
4331 return;
4332 bool wasHidden = m_frameView->m_hiddenForThrottling;
4333 bool isHidden = wasHidden;
4334 if (!entries.isEmpty())
4335 isHidden = !entries.last()->intersectionRatio();
4336 if (wasHidden != isHidden)
4337 m_frameView->updateRenderThrottlingStatus(isHidden, m_frameView->m_subtr eeThrottled);
4338 }
4339
4340 ExecutionContext* FrameView::IntersectionObserverCallback::getExecutionContext() const
4341 {
4342 return m_context.get();
4343 }
4344
4345 DEFINE_TRACE(FrameView::IntersectionObserverCallback)
4346 {
4347 blink::IntersectionObserverCallback::trace(visitor);
4348 visitor->trace(m_frameView);
4349 visitor->trace(m_context);
4353 } 4350 }
4354 4351
4355 } // namespace blink 4352 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698