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

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: Adjust OOPIF expectations 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
szager1 2016/08/30 23:57:12 if (frame().isLocalRoot()) return;
Sami 2016/08/31 11:08:56 Any particular reason why? That would mean we don'
szager1 2016/08/31 20:54:26 OK; that's a weird scenario, but if that's the beh
287 IntersectionObserverInit observerInit;
288 // Intersection observer does not currently support remote frames. As a
szager1 2016/08/30 23:57:12 Is there a nice way to combine this with the stati
Sami 2016/08/31 11:08:55 I gave this a try but couldn't find a good way to
289 // workaround we monitor visibility up to the local root (crbug.com/615156).
290 Frame* mainFrame = frame().tree().top();
291 if (!mainFrame || !mainFrame->isLocalFrame())
292 observerInit.setRoot(frame().localFrameRoot()->document()->documentEleme nt());
293
294 IntersectionObserverCallback* callback = new IntersectionObserverCallback(th is);
295 m_intersectionObserver = IntersectionObserver::create(observerInit, *callbac k, ASSERT_NO_EXCEPTION);
296 m_intersectionObserver->setLowLatency(true);
297 m_intersectionObserver->observe(frame().document()->documentElement());
298
299 // Initially the intersection observer assumes the target is hidden. If it
300 // actually is, no notification about this will be delivered. To work around
301 // this, we set the observer into an undefined state so the first
302 // notification will always get delivered.
303 for (auto& observation : m_intersectionObserver->observations())
304 observation->setLastThresholdIndex(std::numeric_limits<unsigned>::max()) ;
305 }
306
283 void FrameView::dispose() 307 void FrameView::dispose()
284 { 308 {
285 RELEASE_ASSERT(!isInPerformLayout()); 309 RELEASE_ASSERT(!isInPerformLayout());
286 310
287 if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) 311 if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator())
288 scrollAnimator->cancelAnimation(); 312 scrollAnimator->cancelAnimation();
289 cancelProgrammaticScrollAnimation(); 313 cancelProgrammaticScrollAnimation();
290 314
291 detachScrollbars(); 315 detachScrollbars();
292 316
(...skipping 10 matching lines...) Expand all
303 327
304 // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing 328 // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing
305 // partially destroyed |this| via |m_autoSizeInfo->m_frameView|. 329 // partially destroyed |this| via |m_autoSizeInfo->m_frameView|.
306 m_autoSizeInfo.clear(); 330 m_autoSizeInfo.clear();
307 331
308 if (m_postLayoutTasksTimer.isActive()) 332 if (m_postLayoutTasksTimer.isActive())
309 m_postLayoutTasksTimer.stop(); 333 m_postLayoutTasksTimer.stop();
310 334
311 if (m_didScrollTimer.isActive()) 335 if (m_didScrollTimer.isActive())
312 m_didScrollTimer.stop(); 336 m_didScrollTimer.stop();
313 m_renderThrottlingObserverNotificationFactory->cancel();
314 337
315 // FIXME: Do we need to do something here for OOPI? 338 // FIXME: Do we need to do something here for OOPI?
316 HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner(); 339 HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner();
317 // TODO(dcheng): It seems buggy that we can have an owner element that 340 // TODO(dcheng): It seems buggy that we can have an owner element that
318 // points to another Widget. 341 // points to another Widget.
319 if (ownerElement && ownerElement->ownedWidget() == this) 342 if (ownerElement && ownerElement->ownedWidget() == this)
320 ownerElement->setWidget(nullptr); 343 ownerElement->setWidget(nullptr);
321 344
322 #if ENABLE(ASSERT) 345 #if ENABLE(ASSERT)
323 m_hasBeenDisposed = true; 346 m_hasBeenDisposed = true;
(...skipping 2859 matching lines...) Expand 10 before | Expand all | Expand 10 after
3183 if (m_scrollbarsAvoidingResizer && parent()) 3206 if (m_scrollbarsAvoidingResizer && parent())
3184 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(-m_scrollbar sAvoidingResizer); 3207 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(-m_scrollbar sAvoidingResizer);
3185 3208
3186 Widget::setParent(parentView); 3209 Widget::setParent(parentView);
3187 3210
3188 if (m_scrollbarsAvoidingResizer && parent()) 3211 if (m_scrollbarsAvoidingResizer && parent())
3189 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(m_scrollbars AvoidingResizer); 3212 toFrameView(parent())->adjustScrollbarsAvoidingResizerCount(m_scrollbars AvoidingResizer);
3190 3213
3191 updateScrollableAreaSet(); 3214 updateScrollableAreaSet();
3192 setNeedsUpdateViewportIntersection(); 3215 setNeedsUpdateViewportIntersection();
3216
3217 setupRenderThrottling();
3193 } 3218 }
3194 3219
3195 void FrameView::removeChild(Widget* child) 3220 void FrameView::removeChild(Widget* child)
3196 { 3221 {
3197 ASSERT(child->parent() == this); 3222 ASSERT(child->parent() == this);
3198 3223
3199 if (child->isFrameView()) 3224 if (child->isFrameView())
3200 removeScrollableArea(toFrameView(child)); 3225 removeScrollableArea(toFrameView(child));
3201 3226
3202 child->setParent(0); 3227 child->setParent(0);
(...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after
4161 if (layoutObject.isText()) 4186 if (layoutObject.isText())
4162 return; 4187 return;
4163 4188
4164 layoutObject.addAnnotatedRegions(regions); 4189 layoutObject.addAnnotatedRegions(regions);
4165 for (LayoutObject* curr = layoutObject.slowFirstChild(); curr; curr = curr-> nextSibling()) 4190 for (LayoutObject* curr = layoutObject.slowFirstChild(); curr; curr = curr-> nextSibling())
4166 collectAnnotatedRegions(*curr, regions); 4191 collectAnnotatedRegions(*curr, regions);
4167 } 4192 }
4168 4193
4169 void FrameView::setNeedsUpdateViewportIntersection() 4194 void FrameView::setNeedsUpdateViewportIntersection()
4170 { 4195 {
4171 m_needsUpdateViewportIntersection = true;
4172 for (FrameView* parent = parentFrameView(); parent; parent = parent->parentF rameView()) 4196 for (FrameView* parent = parentFrameView(); parent; parent = parent->parentF rameView())
4173 parent->m_needsUpdateViewportIntersectionInSubtree = true; 4197 parent->m_needsUpdateViewportIntersectionInSubtree = true;
4174 } 4198 }
4175 4199
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) 4200 void FrameView::updateViewportIntersectionsForSubtree(DocumentLifecycle::Lifecyc leState targetState)
4209 { 4201 {
4210 bool hadValidIntersection = m_viewportIntersectionValid;
4211 bool hadEmptyIntersection = m_viewportIntersection.isEmpty();
4212 updateViewportIntersectionIfNeeded();
4213
4214 // Notify javascript IntersectionObservers 4202 // Notify javascript IntersectionObservers
4215 if (targetState == DocumentLifecycle::PaintClean && frame().document()->inte rsectionObserverController()) 4203 if (targetState == DocumentLifecycle::PaintClean && frame().document()->inte rsectionObserverController())
4216 frame().document()->intersectionObserverController()->computeTrackedInte rsectionObservations(); 4204 frame().document()->intersectionObserverController()->computeTrackedInte rsectionObservations();
4217 4205
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) 4206 if (!m_needsUpdateViewportIntersectionInSubtree)
4224 return; 4207 return;
4225 m_needsUpdateViewportIntersectionInSubtree = false; 4208 m_needsUpdateViewportIntersectionInSubtree = false;
4226 4209
4227 for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree ().nextSibling()) { 4210 for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree ().nextSibling()) {
4228 if (!child->isLocalFrame()) 4211 if (!child->isLocalFrame())
4229 continue; 4212 continue;
4230 if (FrameView* view = toLocalFrame(child)->view()) 4213 if (FrameView* view = toLocalFrame(child)->view())
4231 view->updateViewportIntersectionsForSubtree(targetState); 4214 view->updateViewportIntersectionsForSubtree(targetState);
4232 } 4215 }
4233 } 4216 }
4234 4217
4235 void FrameView::updateThrottlingStatus() 4218 void FrameView::updateRenderThrottlingStatusForTesting()
4236 { 4219 {
4237 // Only offscreen frames can be throttled. 4220 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 } 4221 }
4263 4222
4264 void FrameView::notifyRenderThrottlingObserversForTesting() 4223 void FrameView::updateRenderThrottlingStatus(bool hidden, bool subtreeThrottled)
4265 {
4266 DCHECK(m_renderThrottlingObserverNotificationFactory->isPending());
4267 notifyRenderThrottlingObservers();
4268 }
4269
4270 void FrameView::notifyRenderThrottlingObservers()
4271 { 4224 {
4272 TRACE_EVENT0("blink", "FrameView::notifyRenderThrottlingObservers"); 4225 TRACE_EVENT0("blink", "FrameView::notifyRenderThrottlingObservers");
4273 DCHECK(!isInPerformLayout()); 4226 DCHECK(!isInPerformLayout());
4274 DCHECK(!m_frame->document() || !m_frame->document()->inStyleRecalc()); 4227 DCHECK(!m_frame->document() || !m_frame->document()->inStyleRecalc());
4275 bool wasThrottled = canThrottleRendering(); 4228 bool wasThrottled = canThrottleRendering();
4276 4229
4277 updateThrottlingStatus(); 4230 m_hiddenForThrottling = hidden;
4231 m_subtreeThrottled = subtreeThrottled;
4278 4232
4279 bool becameThrottled = !wasThrottled && canThrottleRendering(); 4233 bool isThrottled = canThrottleRendering();
4280 bool becameUnthrottled = wasThrottled && !canThrottleRendering(); 4234 bool becameUnthrottled = wasThrottled && !isThrottled;
4235
4236 // If this FrameView became unthrottled or throttled, we must make sure all
4237 // its children are notified synchronously. Otherwise we 1) might attempt to
4238 // paint one of the children with an out-of-date layout before
4239 // |updateRenderThrottlingStatus| has made it throttled or 2) fail to
4240 // unthrottle a child whose parent is unthrottled by a later notification.
4241 if (wasThrottled != isThrottled) {
4242 for (const Member<Widget>& child : *children()) {
4243 if (child->isFrameView()) {
4244 FrameView* childView = toFrameView(child);
4245 childView->updateRenderThrottlingStatus(childView->m_hiddenForTh rottling, isThrottled);
4246 }
4247 }
4248 }
4249
4281 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator(); 4250 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) { 4251 if (becameUnthrottled) {
4293 // ScrollingCoordinator needs to update according to the new throttling status. 4252 // ScrollingCoordinator needs to update according to the new throttling status.
4294 if (scrollingCoordinator) 4253 if (scrollingCoordinator)
4295 scrollingCoordinator->notifyGeometryChanged(); 4254 scrollingCoordinator->notifyGeometryChanged();
4296 // Start ticking animation frames again if necessary. 4255 // Start ticking animation frames again if necessary.
4297 if (page()) 4256 if (page())
4298 page()->animator().scheduleVisualUpdate(m_frame.get()); 4257 page()->animator().scheduleVisualUpdate(m_frame.get());
4299 // Force a full repaint of this frame to ensure we are not left with a 4258 // 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 4259 // partially painted version of this frame's contents if we skipped
4301 // painting them while the frame was throttled. 4260 // painting them while the frame was throttled.
(...skipping 18 matching lines...) Expand all
4320 4279
4321 bool FrameView::shouldThrottleRendering() const 4280 bool FrameView::shouldThrottleRendering() const
4322 { 4281 {
4323 return canThrottleRendering() && lifecycle().throttlingAllowed(); 4282 return canThrottleRendering() && lifecycle().throttlingAllowed();
4324 } 4283 }
4325 4284
4326 bool FrameView::canThrottleRendering() const 4285 bool FrameView::canThrottleRendering() const
4327 { 4286 {
4328 if (!RuntimeEnabledFeatures::renderingPipelineThrottlingEnabled()) 4287 if (!RuntimeEnabledFeatures::renderingPipelineThrottlingEnabled())
4329 return false; 4288 return false;
4330 return m_subtreeThrottled || (m_hiddenForThrottling && m_crossOriginForThrot tling); 4289 // We only throttle the rendering pipeline in cross-origin frames. This is
4290 // to avoid a situation where an ancestor frame directly depends on the
4291 // pipeline timing of a descendant and breaks as a result of throttling.
4292 // The rationale is that cross-origin frames must already communicate with
4293 // asynchronous messages, so they should be able to tolerate some delay in
4294 // receiving replies from a throttled peer.
4295 return m_subtreeThrottled || (m_hiddenForThrottling && m_frame->isCrossOrigi nSubframe());
4296 }
4297
4298 FrameView::IntersectionObserverCallback::IntersectionObserverCallback(FrameView* frameView)
4299 : m_frameView(std::move(frameView))
szager1 2016/08/30 23:57:12 Why std::move?
Sami 2016/08/31 11:08:55 Oops, looks like I'm typing it out of habit alread
4300 {
4301 }
4302
4303 void FrameView::IntersectionObserverCallback::handleEvent(const HeapVector<Membe r<IntersectionObserverEntry>>& entries, IntersectionObserver&)
4304 {
4305 bool wasHidden = m_frameView->m_hiddenForThrottling;
4306 bool isHidden = wasHidden;
4307 for (const auto& entry : entries)
szager1 2016/08/30 23:57:11 if (entries.length()) isHidden = !entries.last()
Sami 2016/08/31 11:08:56 Neat, thanks!
4308 isHidden = !entry->intersectionRatio();
4309 if (wasHidden != isHidden)
4310 m_frameView->updateRenderThrottlingStatus(isHidden, m_frameView->m_subtr eeThrottled);
szager1 2016/08/30 23:57:12 I would expect that you need a friend declaration
Sami 2016/08/31 11:08:55 This is an inner class and since C++11 it's automa
4311 }
4312
4313 ExecutionContext* FrameView::IntersectionObserverCallback::getExecutionContext() const
4314 {
4315 return m_frameView->frame().document();
szager1 2016/08/30 23:57:12 I'm not sure it matters, which ExecutionContext is
Sami 2016/08/31 11:08:56 I wasn't sure about that either. I've now made it
4316 }
4317
4318 DEFINE_TRACE(FrameView::IntersectionObserverCallback)
4319 {
4320 blink::IntersectionObserverCallback::trace(visitor);
4321 visitor->trace(m_frameView);
4331 } 4322 }
4332 4323
4333 } // namespace blink 4324 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698