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

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: Fix rebase typo Created 4 years, 2 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 16 matching lines...) Expand all
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/animation/DocumentAnimations.h" 31 #include "core/animation/DocumentAnimations.h"
32 #include "core/css/FontFaceSet.h" 32 #include "core/css/FontFaceSet.h"
33 #include "core/css/resolver/StyleResolver.h" 33 #include "core/css/resolver/StyleResolver.h"
34 #include "core/dom/AXObjectCache.h" 34 #include "core/dom/AXObjectCache.h"
35 #include "core/dom/DOMNodeIds.h" 35 #include "core/dom/DOMNodeIds.h"
36 #include "core/dom/Fullscreen.h" 36 #include "core/dom/Fullscreen.h"
37 #include "core/dom/IntersectionObserverCallback.h"
37 #include "core/dom/IntersectionObserverController.h" 38 #include "core/dom/IntersectionObserverController.h"
39 #include "core/dom/IntersectionObserverInit.h"
38 #include "core/editing/EditingUtilities.h" 40 #include "core/editing/EditingUtilities.h"
39 #include "core/editing/FrameSelection.h" 41 #include "core/editing/FrameSelection.h"
40 #include "core/editing/RenderedPosition.h" 42 #include "core/editing/RenderedPosition.h"
41 #include "core/editing/markers/DocumentMarkerController.h" 43 #include "core/editing/markers/DocumentMarkerController.h"
42 #include "core/events/ErrorEvent.h" 44 #include "core/events/ErrorEvent.h"
43 #include "core/fetch/ResourceFetcher.h" 45 #include "core/fetch/ResourceFetcher.h"
44 #include "core/frame/EventHandlerRegistry.h" 46 #include "core/frame/EventHandlerRegistry.h"
45 #include "core/frame/FrameHost.h" 47 #include "core/frame/FrameHost.h"
46 #include "core/frame/LocalFrame.h" 48 #include "core/frame/LocalFrame.h"
47 #include "core/frame/Location.h" 49 #include "core/frame/Location.h"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 static bool s_initialTrackAllPaintInvalidations = false; 148 static bool s_initialTrackAllPaintInvalidations = false;
147 149
148 FrameView::FrameView(LocalFrame* frame) 150 FrameView::FrameView(LocalFrame* frame)
149 : m_frame(frame), 151 : m_frame(frame),
150 m_displayMode(WebDisplayModeBrowser), 152 m_displayMode(WebDisplayModeBrowser),
151 m_canHaveScrollbars(true), 153 m_canHaveScrollbars(true),
152 m_hasPendingLayout(false), 154 m_hasPendingLayout(false),
153 m_inSynchronousPostLayout(false), 155 m_inSynchronousPostLayout(false),
154 m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired), 156 m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired),
155 m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired), 157 m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired),
156 m_renderThrottlingObserverNotificationFactory(
157 CancellableTaskFactory::create(
158 this,
159 &FrameView::notifyRenderThrottlingObservers)),
160 m_isTransparent(false), 158 m_isTransparent(false),
161 m_baseBackgroundColor(Color::white), 159 m_baseBackgroundColor(Color::white),
162 m_mediaType(MediaTypeNames::screen), 160 m_mediaType(MediaTypeNames::screen),
163 m_safeToPropagateScrollToParent(true), 161 m_safeToPropagateScrollToParent(true),
164 m_scrollCorner(nullptr), 162 m_scrollCorner(nullptr),
165 m_stickyPositionObjectCount(0), 163 m_stickyPositionObjectCount(0),
166 m_inputEventsScaleFactorForEmulation(1), 164 m_inputEventsScaleFactorForEmulation(1),
167 m_layoutSizeFixedToFrameSize(true), 165 m_layoutSizeFixedToFrameSize(true),
168 m_didScrollTimer(this, &FrameView::didScrollTimerFired), 166 m_didScrollTimer(this, &FrameView::didScrollTimerFired),
169 m_topControlsViewportAdjustment(0), 167 m_topControlsViewportAdjustment(0),
170 m_needsUpdateWidgetGeometries(false), 168 m_needsUpdateWidgetGeometries(false),
171 m_needsUpdateViewportIntersection(true), 169 m_needsUpdateViewportIntersection(true),
172 m_needsUpdateViewportIntersectionInSubtree(true),
173 #if ENABLE(ASSERT) 170 #if ENABLE(ASSERT)
174 m_hasBeenDisposed(false), 171 m_hasBeenDisposed(false),
175 #endif 172 #endif
176 m_horizontalScrollbarMode(ScrollbarAuto), 173 m_horizontalScrollbarMode(ScrollbarAuto),
177 m_verticalScrollbarMode(ScrollbarAuto), 174 m_verticalScrollbarMode(ScrollbarAuto),
178 m_horizontalScrollbarLock(false), 175 m_horizontalScrollbarLock(false),
179 m_verticalScrollbarLock(false), 176 m_verticalScrollbarLock(false),
180 m_scrollbarsSuppressed(false), 177 m_scrollbarsSuppressed(false),
181 m_inUpdateScrollbars(false), 178 m_inUpdateScrollbars(false),
182 m_frameTimingRequestsDirty(true), 179 m_frameTimingRequestsDirty(true),
183 m_viewportIntersectionValid(false),
184 m_hiddenForThrottling(false), 180 m_hiddenForThrottling(false),
185 m_crossOriginForThrottling(false),
186 m_subtreeThrottled(false), 181 m_subtreeThrottled(false),
187 m_currentUpdateLifecyclePhasesTargetState( 182 m_currentUpdateLifecyclePhasesTargetState(
188 DocumentLifecycle::Uninitialized), 183 DocumentLifecycle::Uninitialized),
189 m_scrollAnchor(this), 184 m_scrollAnchor(this),
190 m_needsScrollbarsUpdate(false), 185 m_needsScrollbarsUpdate(false),
191 m_suppressAdjustViewSize(false), 186 m_suppressAdjustViewSize(false),
192 m_allowsLayoutInvalidationAfterLayoutClean(true) { 187 m_allowsLayoutInvalidationAfterLayoutClean(true) {
193 ASSERT(m_frame); 188 ASSERT(m_frame);
194 init(); 189 init();
195 } 190 }
(...skipping 20 matching lines...) Expand all
216 DEFINE_TRACE(FrameView) { 211 DEFINE_TRACE(FrameView) {
217 visitor->trace(m_frame); 212 visitor->trace(m_frame);
218 visitor->trace(m_fragmentAnchor); 213 visitor->trace(m_fragmentAnchor);
219 visitor->trace(m_scrollableAreas); 214 visitor->trace(m_scrollableAreas);
220 visitor->trace(m_animatingScrollableAreas); 215 visitor->trace(m_animatingScrollableAreas);
221 visitor->trace(m_autoSizeInfo); 216 visitor->trace(m_autoSizeInfo);
222 visitor->trace(m_horizontalScrollbar); 217 visitor->trace(m_horizontalScrollbar);
223 visitor->trace(m_verticalScrollbar); 218 visitor->trace(m_verticalScrollbar);
224 visitor->trace(m_children); 219 visitor->trace(m_children);
225 visitor->trace(m_viewportScrollableArea); 220 visitor->trace(m_viewportScrollableArea);
221 visitor->trace(m_intersectionObserver);
226 visitor->trace(m_scrollAnchor); 222 visitor->trace(m_scrollAnchor);
227 Widget::trace(visitor); 223 Widget::trace(visitor);
228 ScrollableArea::trace(visitor); 224 ScrollableArea::trace(visitor);
229 } 225 }
230 226
231 void FrameView::reset() { 227 void FrameView::reset() {
232 m_hasPendingLayout = false; 228 m_hasPendingLayout = false;
233 m_layoutSchedulingEnabled = true; 229 m_layoutSchedulingEnabled = true;
234 m_inSynchronousPostLayout = false; 230 m_inSynchronousPostLayout = false;
235 m_layoutCount = 0; 231 m_layoutCount = 0;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 reset(); 272 reset();
277 273
278 m_size = LayoutSize(); 274 m_size = LayoutSize();
279 275
280 // Propagate the marginwidth/height and scrolling modes to the view. 276 // Propagate the marginwidth/height and scrolling modes to the view.
281 if (m_frame->owner() && 277 if (m_frame->owner() &&
282 m_frame->owner()->scrollingMode() == ScrollbarAlwaysOff) 278 m_frame->owner()->scrollingMode() == ScrollbarAlwaysOff)
283 setCanHaveScrollbars(false); 279 setCanHaveScrollbars(false);
284 } 280 }
285 281
282 void FrameView::setupRenderThrottling() {
283 if (m_intersectionObserver || !frame().document() ||
284 !frame().document()->frame() || !frame().document()->documentElement() ||
285 !frame().document()->documentElement()->isConnected()) {
286 return;
287 }
288
289 ExecutionContext* context;
290 IntersectionObserverInit observerInit;
291 // Intersection observer does not currently support remote frames. As a
292 // workaround we monitor visibility up to the local root (crbug.com/615156).
293 Frame* mainFrame = frame().tree().top();
294 if (!mainFrame || !mainFrame->isLocalFrame()) {
295 observerInit.setRoot(
296 frame().localFrameRoot()->document()->documentElement());
297 context = &observerInit.root()->document();
298 } else {
299 context = toLocalFrame(mainFrame)->document();
300 }
301
302 IntersectionObserverCallback* callback =
303 new IntersectionObserverCallback(this, context);
304 m_intersectionObserver = IntersectionObserver::create(observerInit, *callback,
305 ASSERT_NO_EXCEPTION);
306 m_intersectionObserver->observe(frame().document()->documentElement());
307
308 // Initially the intersection observer assumes the target is hidden. If it
309 // actually is, no notification about this will be delivered. To work around
310 // this, we set the observer into an undefined state so the first
311 // notification will always get delivered.
312 for (auto& observation : m_intersectionObserver->observations())
313 observation->setLastThresholdIndex(std::numeric_limits<unsigned>::max());
ojan 2016/10/14 02:25:47 This is digging into the guts of IntersectionObser
Sami 2016/10/25 17:47:12 Yeah, sounds good. I've added an explicit method f
314 }
315
286 void FrameView::dispose() { 316 void FrameView::dispose() {
287 RELEASE_ASSERT(!isInPerformLayout()); 317 RELEASE_ASSERT(!isInPerformLayout());
288 318
289 if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) 319 if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator())
290 scrollAnimator->cancelAnimation(); 320 scrollAnimator->cancelAnimation();
291 cancelProgrammaticScrollAnimation(); 321 cancelProgrammaticScrollAnimation();
292 322
293 detachScrollbars(); 323 detachScrollbars();
294 324
295 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 325 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
296 scrollingCoordinator->willDestroyScrollableArea(this); 326 scrollingCoordinator->willDestroyScrollableArea(this);
297 327
298 // We need to clear the RootFrameViewport's animator since it gets called 328 // We need to clear the RootFrameViewport's animator since it gets called
299 // from non-GC'd objects and RootFrameViewport will still have a pointer to 329 // from non-GC'd objects and RootFrameViewport will still have a pointer to
300 // this class. 330 // this class.
301 if (m_viewportScrollableArea) 331 if (m_viewportScrollableArea)
302 m_viewportScrollableArea->clearScrollAnimators(); 332 m_viewportScrollableArea->clearScrollAnimators();
303 333
304 clearScrollAnimators(); 334 clearScrollAnimators();
305 335
306 // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing 336 // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing
307 // partially destroyed |this| via |m_autoSizeInfo->m_frameView|. 337 // partially destroyed |this| via |m_autoSizeInfo->m_frameView|.
308 m_autoSizeInfo.clear(); 338 m_autoSizeInfo.clear();
309 339
310 m_postLayoutTasksTimer.stop(); 340 m_postLayoutTasksTimer.stop();
311 m_didScrollTimer.stop(); 341 m_didScrollTimer.stop();
312 342
313 m_renderThrottlingObserverNotificationFactory->cancel();
314
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;
324 #endif 352 #endif
(...skipping 3010 matching lines...) Expand 10 before | Expand all | Expand 10 after
3335 } 3363 }
3336 3364
3337 void FrameView::setParent(Widget* parentView) { 3365 void FrameView::setParent(Widget* parentView) {
3338 if (parentView == parent()) 3366 if (parentView == parent())
3339 return; 3367 return;
3340 3368
3341 Widget::setParent(parentView); 3369 Widget::setParent(parentView);
3342 3370
3343 updateScrollableAreaSet(); 3371 updateScrollableAreaSet();
3344 setNeedsUpdateViewportIntersection(); 3372 setNeedsUpdateViewportIntersection();
3373 setupRenderThrottling();
3374
3375 if (parentFrameView())
3376 m_subtreeThrottled = parentFrameView()->canThrottleRendering();
3345 } 3377 }
3346 3378
3347 void FrameView::removeChild(Widget* child) { 3379 void FrameView::removeChild(Widget* child) {
3348 ASSERT(child->parent() == this); 3380 ASSERT(child->parent() == this);
3349 3381
3350 if (child->isFrameView()) 3382 if (child->isFrameView())
3351 removeScrollableArea(toFrameView(child)); 3383 removeScrollableArea(toFrameView(child));
3352 3384
3353 child->setParent(0); 3385 child->setParent(0);
3354 m_children.remove(child); 3386 m_children.remove(child);
(...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after
4291 if (layoutObject.isText()) 4323 if (layoutObject.isText())
4292 return; 4324 return;
4293 4325
4294 layoutObject.addAnnotatedRegions(regions); 4326 layoutObject.addAnnotatedRegions(regions);
4295 for (LayoutObject* curr = layoutObject.slowFirstChild(); curr; 4327 for (LayoutObject* curr = layoutObject.slowFirstChild(); curr;
4296 curr = curr->nextSibling()) 4328 curr = curr->nextSibling())
4297 collectAnnotatedRegions(*curr, regions); 4329 collectAnnotatedRegions(*curr, regions);
4298 } 4330 }
4299 4331
4300 void FrameView::setNeedsUpdateViewportIntersection() { 4332 void FrameView::setNeedsUpdateViewportIntersection() {
4301 m_needsUpdateViewportIntersection = true;
4302 for (FrameView* parent = parentFrameView(); parent; 4333 for (FrameView* parent = parentFrameView(); parent;
4303 parent = parent->parentFrameView()) 4334 parent = parent->parentFrameView())
4304 parent->m_needsUpdateViewportIntersectionInSubtree = true; 4335 parent->m_needsUpdateViewportIntersectionInSubtree = true;
4305 } 4336 }
4306 4337
4307 void FrameView::updateViewportIntersectionIfNeeded() {
4308 if (!m_needsUpdateViewportIntersection)
4309 return;
4310 m_needsUpdateViewportIntersection = false;
4311 m_viewportIntersectionValid = true;
4312 FrameView* parent = parentFrameView();
4313 if (!parent) {
4314 m_viewportIntersection = frameRect();
4315 return;
4316 }
4317 ASSERT(!parent->m_needsUpdateViewportIntersection);
4318
4319 // If our parent is hidden, then we are too.
4320 if (parent->m_viewportIntersection.isEmpty()) {
4321 m_viewportIntersection = parent->m_viewportIntersection;
4322 return;
4323 }
4324
4325 // Transform our bounds into the root frame's content coordinate space,
4326 // making sure we have valid layout data in our parent document. If our
4327 // parent is throttled, we'll use possible stale layout information and
4328 // rely on the fact that another lifecycle update will be scheduled once
4329 // our parent becomes unthrottled.
4330 ASSERT(parent->lifecycle().state() >= DocumentLifecycle::LayoutClean ||
4331 parent->shouldThrottleRendering());
4332 m_viewportIntersection = parent->contentsToRootFrame(frameRect());
4333
4334 // TODO(skyostil): Expand the viewport to make it less likely to see stale
4335 // content while scrolling.
4336 IntRect viewport = parent->m_viewportIntersection;
4337 m_viewportIntersection.intersect(viewport);
4338 }
4339
4340 void FrameView::updateViewportIntersectionsForSubtree( 4338 void FrameView::updateViewportIntersectionsForSubtree(
4341 DocumentLifecycle::LifecycleState targetState) { 4339 DocumentLifecycle::LifecycleState targetState) {
4342 bool hadValidIntersection = m_viewportIntersectionValid;
4343 bool hadEmptyIntersection = m_viewportIntersection.isEmpty();
4344 updateViewportIntersectionIfNeeded();
4345
4346 // Notify javascript IntersectionObservers 4340 // Notify javascript IntersectionObservers
4347 if (targetState == DocumentLifecycle::PaintClean && 4341 if (targetState == DocumentLifecycle::PaintClean &&
4348 frame().document()->intersectionObserverController()) 4342 frame().document()->intersectionObserverController())
4349 frame() 4343 frame()
4350 .document() 4344 .document()
4351 ->intersectionObserverController() 4345 ->intersectionObserverController()
4352 ->computeTrackedIntersectionObservations(); 4346 ->computeTrackedIntersectionObservations();
4353 4347
4354 // Adjust render throttling for iframes based on visibility
4355 bool shouldNotify = !hadValidIntersection ||
4356 hadEmptyIntersection != m_viewportIntersection.isEmpty();
4357 if (shouldNotify &&
4358 !m_renderThrottlingObserverNotificationFactory->isPending())
4359 m_frame->frameScheduler()->unthrottledTaskRunner()->postTask(
4360 BLINK_FROM_HERE,
4361 m_renderThrottlingObserverNotificationFactory->cancelAndCreate());
4362
4363 if (!m_needsUpdateViewportIntersectionInSubtree) 4348 if (!m_needsUpdateViewportIntersectionInSubtree)
4364 return; 4349 return;
4365 m_needsUpdateViewportIntersectionInSubtree = false; 4350 m_needsUpdateViewportIntersectionInSubtree = false;
4366 4351
4367 for (Frame* child = m_frame->tree().firstChild(); child; 4352 for (Frame* child = m_frame->tree().firstChild(); child;
4368 child = child->tree().nextSibling()) { 4353 child = child->tree().nextSibling()) {
4369 if (!child->isLocalFrame()) 4354 if (!child->isLocalFrame())
4370 continue; 4355 continue;
4371 if (FrameView* view = toLocalFrame(child)->view()) 4356 if (FrameView* view = toLocalFrame(child)->view())
4372 view->updateViewportIntersectionsForSubtree(targetState); 4357 view->updateViewportIntersectionsForSubtree(targetState);
4373 } 4358 }
4374 } 4359 }
4375 4360
4376 void FrameView::updateThrottlingStatus() { 4361 void FrameView::updateRenderThrottlingStatusForTesting() {
4377 // Only offscreen frames can be throttled. Note that we disallow throttling 4362 m_intersectionObserver->deliver();
4378 // of 0x0 frames because some sites use them to drive UI logic.
4379 DCHECK(m_viewportIntersectionValid);
4380 m_hiddenForThrottling =
4381 m_viewportIntersection.isEmpty() && !frameRect().isEmpty();
4382
4383 // We only throttle the rendering pipeline in cross-origin frames. This is
4384 // to avoid a situation where an ancestor frame directly depends on the
4385 // pipeline timing of a descendant and breaks as a result of throttling.
4386 // The rationale is that cross-origin frames must already communicate with
4387 // asynchronous messages, so they should be able to tolerate some delay in
4388 // receiving replies from a throttled peer.
4389 //
4390 // Check if we can access our parent's security origin.
4391 m_crossOriginForThrottling = false;
4392 // If any of our parents are throttled, we must be too.
4393 m_subtreeThrottled = false;
4394 const SecurityOrigin* origin = frame().securityContext()->getSecurityOrigin();
4395 for (Frame* parentFrame = m_frame->tree().parent(); parentFrame;
4396 parentFrame = parentFrame->tree().parent()) {
4397 const SecurityOrigin* parentOrigin =
4398 parentFrame->securityContext()->getSecurityOrigin();
4399 if (!origin->canAccess(parentOrigin))
4400 m_crossOriginForThrottling = true;
4401 if (parentFrame->isLocalFrame() && toLocalFrame(parentFrame)->view() &&
4402 toLocalFrame(parentFrame)->view()->canThrottleRendering())
4403 m_subtreeThrottled = true;
4404 }
4405 m_frame->frameScheduler()->setFrameVisible(!m_hiddenForThrottling);
4406 m_frame->frameScheduler()->setCrossOrigin(m_crossOriginForThrottling);
4407 } 4363 }
4408 4364
4409 void FrameView::notifyRenderThrottlingObserversForTesting() { 4365 void FrameView::updateRenderThrottlingStatus(bool hidden,
4410 DCHECK(m_renderThrottlingObserverNotificationFactory->isPending()); 4366 bool subtreeThrottled) {
4411 notifyRenderThrottlingObservers(); 4367 TRACE_EVENT0("blink", "FrameView::updateRenderThrottlingStatus");
4412 }
4413
4414 void FrameView::notifyRenderThrottlingObservers() {
4415 TRACE_EVENT0("blink", "FrameView::notifyRenderThrottlingObservers");
4416 DCHECK(!isInPerformLayout()); 4368 DCHECK(!isInPerformLayout());
4417 DCHECK(frame().document()); 4369 DCHECK(!m_frame->document() || !m_frame->document()->inStyleRecalc());
4418 DCHECK(!frame().document()->inStyleRecalc());
4419 bool wasThrottled = canThrottleRendering(); 4370 bool wasThrottled = canThrottleRendering();
4420 4371
4421 updateThrottlingStatus(); 4372 // Note that we disallow throttling of 0x0 frames because some sites use
4373 // them to drive UI logic.
4374 m_hiddenForThrottling = hidden && !frameRect().isEmpty();
4375 m_subtreeThrottled = subtreeThrottled;
4422 4376
4423 frame().document()->onVisibilityMaybeChanged(!m_hiddenForThrottling); 4377 bool isThrottled = canThrottleRendering();
4378 bool becameUnthrottled = wasThrottled && !isThrottled;
4424 4379
4425 bool becameThrottled = !wasThrottled && canThrottleRendering(); 4380 // If this FrameView became unthrottled or throttled, we must make sure all
4426 bool becameUnthrottled = wasThrottled && !canThrottleRendering(); 4381 // its children are notified synchronously. Otherwise we 1) might attempt to
4382 // paint one of the children with an out-of-date layout before
4383 // |updateRenderThrottlingStatus| has made it throttled or 2) fail to
4384 // unthrottle a child whose parent is unthrottled by a later notification.
4385 if (wasThrottled != isThrottled) {
4386 for (const Member<Widget>& child : *children()) {
4387 if (child->isFrameView()) {
4388 FrameView* childView = toFrameView(child);
4389 childView->updateRenderThrottlingStatus(
4390 childView->m_hiddenForThrottling, isThrottled);
4391 }
4392 }
4393 }
4394
4427 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator(); 4395 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
4428 if (becameThrottled) {
4429 // If this FrameView became throttled, we must make sure all of its
4430 // children become throttled at the same time. Otherwise we might
4431 // attempt to paint one of the children with an out-of-date layout
4432 // before |notifyRenderThrottlingObservers| has made it throttled.
4433 forAllNonThrottledFrameViews([](FrameView& frameView) {
4434 frameView.m_subtreeThrottled = true;
4435 DCHECK(frameView.canThrottleRendering());
4436 });
4437 }
4438 if (becameUnthrottled) { 4396 if (becameUnthrottled) {
4439 // ScrollingCoordinator needs to update according to the new throttling 4397 // ScrollingCoordinator needs to update according to the new throttling
4440 // status. 4398 // status.
4441 if (scrollingCoordinator) 4399 if (scrollingCoordinator)
4442 scrollingCoordinator->notifyGeometryChanged(); 4400 scrollingCoordinator->notifyGeometryChanged();
4443 // Start ticking animation frames again if necessary. 4401 // Start ticking animation frames again if necessary.
4444 if (page()) 4402 if (page())
4445 page()->animator().scheduleVisualUpdate(m_frame.get()); 4403 page()->animator().scheduleVisualUpdate(m_frame.get());
4446 // Force a full repaint of this frame to ensure we are not left with a 4404 // Force a full repaint of this frame to ensure we are not left with a
4447 // partially painted version of this frame's contents if we skipped 4405 // partially painted version of this frame's contents if we skipped
(...skipping 11 matching lines...) Expand all
4459 scrollingCoordinator->touchEventTargetRectsDidChange(); 4417 scrollingCoordinator->touchEventTargetRectsDidChange();
4460 4418
4461 #if DCHECK_IS_ON() 4419 #if DCHECK_IS_ON()
4462 // Make sure we never have an unthrottled frame inside a throttled one. 4420 // Make sure we never have an unthrottled frame inside a throttled one.
4463 FrameView* parent = parentFrameView(); 4421 FrameView* parent = parentFrameView();
4464 while (parent) { 4422 while (parent) {
4465 DCHECK(canThrottleRendering() || !parent->canThrottleRendering()); 4423 DCHECK(canThrottleRendering() || !parent->canThrottleRendering());
4466 parent = parent->parentFrameView(); 4424 parent = parent->parentFrameView();
4467 } 4425 }
4468 #endif 4426 #endif
4427
4428 if (frame().document()->frame())
4429 frame().document()->onVisibilityMaybeChanged(!hidden);
4469 } 4430 }
4470 4431
4471 bool FrameView::shouldThrottleRendering() const { 4432 bool FrameView::shouldThrottleRendering() const {
4472 return canThrottleRendering() && lifecycle().throttlingAllowed(); 4433 return canThrottleRendering() && lifecycle().throttlingAllowed();
4473 } 4434 }
4474 4435
4475 bool FrameView::canThrottleRendering() const { 4436 bool FrameView::canThrottleRendering() const {
4476 if (!RuntimeEnabledFeatures::renderingPipelineThrottlingEnabled()) 4437 if (!RuntimeEnabledFeatures::renderingPipelineThrottlingEnabled())
4477 return false; 4438 return false;
4439 // We only throttle the rendering pipeline in cross-origin frames. This is
4440 // to avoid a situation where an ancestor frame directly depends on the
4441 // pipeline timing of a descendant and breaks as a result of throttling.
4442 // The rationale is that cross-origin frames must already communicate with
4443 // asynchronous messages, so they should be able to tolerate some delay in
4444 // receiving replies from a throttled peer.
4478 return m_subtreeThrottled || 4445 return m_subtreeThrottled ||
4479 (m_hiddenForThrottling && m_crossOriginForThrottling); 4446 (m_hiddenForThrottling && m_frame->isCrossOriginSubframe());
4447 }
4448
4449 FrameView::IntersectionObserverCallback::IntersectionObserverCallback(
4450 FrameView* frameView,
4451 ExecutionContext* context)
4452 : m_frameView(frameView), m_context(context) {}
4453
4454 void FrameView::IntersectionObserverCallback::handleEvent(
4455 const HeapVector<Member<IntersectionObserverEntry>>& entries,
4456 IntersectionObserver&) {
4457 if (!m_frameView)
4458 return;
4459 bool wasHidden = m_frameView->m_hiddenForThrottling;
4460 bool isHidden = wasHidden;
4461 if (!entries.isEmpty())
4462 isHidden = !entries.last()->intersectionRatio();
4463 if (wasHidden != isHidden) {
4464 m_frameView->updateRenderThrottlingStatus(isHidden,
4465 m_frameView->m_subtreeThrottled);
4466 }
4467 }
4468
4469 ExecutionContext* FrameView::IntersectionObserverCallback::getExecutionContext()
4470 const {
4471 return m_context.get();
4472 }
4473
4474 DEFINE_TRACE(FrameView::IntersectionObserverCallback) {
4475 blink::IntersectionObserverCallback::trace(visitor);
4476 visitor->trace(m_frameView);
4477 visitor->trace(m_context);
4480 } 4478 }
4481 4479
4482 } // namespace blink 4480 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/frame/FrameView.h ('k') | third_party/WebKit/Source/core/layout/svg/LayoutSVGBlock.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698