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

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

Issue 2470793002: Revert of Use intersection observer to control frame throttling (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 1 month 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/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/ElementVisibilityObserver.h"
37 #include "core/dom/Fullscreen.h" 36 #include "core/dom/Fullscreen.h"
38 #include "core/dom/IntersectionObserverCallback.h"
39 #include "core/dom/IntersectionObserverController.h" 37 #include "core/dom/IntersectionObserverController.h"
40 #include "core/dom/IntersectionObserverInit.h"
41 #include "core/editing/EditingUtilities.h" 38 #include "core/editing/EditingUtilities.h"
42 #include "core/editing/FrameSelection.h" 39 #include "core/editing/FrameSelection.h"
43 #include "core/editing/RenderedPosition.h" 40 #include "core/editing/RenderedPosition.h"
44 #include "core/editing/markers/DocumentMarkerController.h" 41 #include "core/editing/markers/DocumentMarkerController.h"
45 #include "core/events/ErrorEvent.h" 42 #include "core/events/ErrorEvent.h"
46 #include "core/fetch/ResourceFetcher.h" 43 #include "core/fetch/ResourceFetcher.h"
47 #include "core/frame/BrowserControls.h" 44 #include "core/frame/BrowserControls.h"
48 #include "core/frame/EventHandlerRegistry.h" 45 #include "core/frame/EventHandlerRegistry.h"
49 #include "core/frame/FrameHost.h" 46 #include "core/frame/FrameHost.h"
50 #include "core/frame/LocalFrame.h" 47 #include "core/frame/LocalFrame.h"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 static bool s_initialTrackAllPaintInvalidations = false; 146 static bool s_initialTrackAllPaintInvalidations = false;
150 147
151 FrameView::FrameView(LocalFrame* frame) 148 FrameView::FrameView(LocalFrame* frame)
152 : m_frame(frame), 149 : m_frame(frame),
153 m_displayMode(WebDisplayModeBrowser), 150 m_displayMode(WebDisplayModeBrowser),
154 m_canHaveScrollbars(true), 151 m_canHaveScrollbars(true),
155 m_hasPendingLayout(false), 152 m_hasPendingLayout(false),
156 m_inSynchronousPostLayout(false), 153 m_inSynchronousPostLayout(false),
157 m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired), 154 m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired),
158 m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired), 155 m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired),
156 m_renderThrottlingObserverNotificationFactory(
157 CancellableTaskFactory::create(
158 this,
159 &FrameView::notifyRenderThrottlingObservers)),
159 m_isTransparent(false), 160 m_isTransparent(false),
160 m_baseBackgroundColor(Color::white), 161 m_baseBackgroundColor(Color::white),
161 m_mediaType(MediaTypeNames::screen), 162 m_mediaType(MediaTypeNames::screen),
162 m_safeToPropagateScrollToParent(true), 163 m_safeToPropagateScrollToParent(true),
163 m_scrollCorner(nullptr), 164 m_scrollCorner(nullptr),
164 m_stickyPositionObjectCount(0), 165 m_stickyPositionObjectCount(0),
165 m_inputEventsScaleFactorForEmulation(1), 166 m_inputEventsScaleFactorForEmulation(1),
166 m_layoutSizeFixedToFrameSize(true), 167 m_layoutSizeFixedToFrameSize(true),
167 m_didScrollTimer(this, &FrameView::didScrollTimerFired), 168 m_didScrollTimer(this, &FrameView::didScrollTimerFired),
168 m_browserControlsViewportAdjustment(0), 169 m_browserControlsViewportAdjustment(0),
169 m_needsUpdateWidgetGeometries(false), 170 m_needsUpdateWidgetGeometries(false),
170 m_needsUpdateViewportIntersection(true), 171 m_needsUpdateViewportIntersection(true),
172 m_needsUpdateViewportIntersectionInSubtree(true),
171 #if ENABLE(ASSERT) 173 #if ENABLE(ASSERT)
172 m_hasBeenDisposed(false), 174 m_hasBeenDisposed(false),
173 #endif 175 #endif
174 m_horizontalScrollbarMode(ScrollbarAuto), 176 m_horizontalScrollbarMode(ScrollbarAuto),
175 m_verticalScrollbarMode(ScrollbarAuto), 177 m_verticalScrollbarMode(ScrollbarAuto),
176 m_horizontalScrollbarLock(false), 178 m_horizontalScrollbarLock(false),
177 m_verticalScrollbarLock(false), 179 m_verticalScrollbarLock(false),
178 m_scrollbarsSuppressed(false), 180 m_scrollbarsSuppressed(false),
179 m_inUpdateScrollbars(false), 181 m_inUpdateScrollbars(false),
180 m_frameTimingRequestsDirty(true), 182 m_frameTimingRequestsDirty(true),
183 m_viewportIntersectionValid(false),
181 m_hiddenForThrottling(false), 184 m_hiddenForThrottling(false),
185 m_crossOriginForThrottling(false),
182 m_subtreeThrottled(false), 186 m_subtreeThrottled(false),
183 m_currentUpdateLifecyclePhasesTargetState( 187 m_currentUpdateLifecyclePhasesTargetState(
184 DocumentLifecycle::Uninitialized), 188 DocumentLifecycle::Uninitialized),
185 m_scrollAnchor(this), 189 m_scrollAnchor(this),
186 m_scrollbarManager(*this), 190 m_scrollbarManager(*this),
187 m_needsScrollbarsUpdate(false), 191 m_needsScrollbarsUpdate(false),
188 m_suppressAdjustViewSize(false), 192 m_suppressAdjustViewSize(false),
189 m_allowsLayoutInvalidationAfterLayoutClean(true) { 193 m_allowsLayoutInvalidationAfterLayoutClean(true) {
190 ASSERT(m_frame); 194 ASSERT(m_frame);
191 init(); 195 init();
(...skipping 19 matching lines...) Expand all
211 } 215 }
212 216
213 DEFINE_TRACE(FrameView) { 217 DEFINE_TRACE(FrameView) {
214 visitor->trace(m_frame); 218 visitor->trace(m_frame);
215 visitor->trace(m_fragmentAnchor); 219 visitor->trace(m_fragmentAnchor);
216 visitor->trace(m_scrollableAreas); 220 visitor->trace(m_scrollableAreas);
217 visitor->trace(m_animatingScrollableAreas); 221 visitor->trace(m_animatingScrollableAreas);
218 visitor->trace(m_autoSizeInfo); 222 visitor->trace(m_autoSizeInfo);
219 visitor->trace(m_children); 223 visitor->trace(m_children);
220 visitor->trace(m_viewportScrollableArea); 224 visitor->trace(m_viewportScrollableArea);
221 visitor->trace(m_visibilityObserver);
222 visitor->trace(m_scrollAnchor); 225 visitor->trace(m_scrollAnchor);
223 visitor->trace(m_anchoringAdjustmentQueue); 226 visitor->trace(m_anchoringAdjustmentQueue);
224 visitor->trace(m_scrollbarManager); 227 visitor->trace(m_scrollbarManager);
225 Widget::trace(visitor); 228 Widget::trace(visitor);
226 ScrollableArea::trace(visitor); 229 ScrollableArea::trace(visitor);
227 } 230 }
228 231
229 void FrameView::reset() { 232 void FrameView::reset() {
230 m_hasPendingLayout = false; 233 m_hasPendingLayout = false;
231 m_layoutSchedulingEnabled = true; 234 m_layoutSchedulingEnabled = true;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 reset(); 277 reset();
275 278
276 m_size = LayoutSize(); 279 m_size = LayoutSize();
277 280
278 // Propagate the marginwidth/height and scrolling modes to the view. 281 // Propagate the marginwidth/height and scrolling modes to the view.
279 if (m_frame->owner() && 282 if (m_frame->owner() &&
280 m_frame->owner()->scrollingMode() == ScrollbarAlwaysOff) 283 m_frame->owner()->scrollingMode() == ScrollbarAlwaysOff)
281 setCanHaveScrollbars(false); 284 setCanHaveScrollbars(false);
282 } 285 }
283 286
284 void FrameView::setupRenderThrottling() {
285 if (m_visibilityObserver)
286 return;
287
288 // We observe the frame owner element instead of the document element, because
289 // if the document has no content we can falsely think the frame is invisible.
290 // Note that this means we cannot throttle top-level frames or (currently)
291 // frames whose owner element is remote.
292 Element* targetElement = frame().deprecatedLocalOwner();
293 if (!targetElement)
294 return;
295
296 m_visibilityObserver = new ElementVisibilityObserver(
297 targetElement, WTF::bind(
298 [](FrameView* frameView, bool isVisible) {
299 frameView->updateRenderThrottlingStatus(
300 !isVisible, frameView->m_subtreeThrottled);
301 },
302 wrapWeakPersistent(this)));
303 m_visibilityObserver->start();
304 }
305
306 void FrameView::dispose() { 287 void FrameView::dispose() {
307 RELEASE_ASSERT(!isInPerformLayout()); 288 RELEASE_ASSERT(!isInPerformLayout());
308 289
309 if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) 290 if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator())
310 scrollAnimator->cancelAnimation(); 291 scrollAnimator->cancelAnimation();
311 cancelProgrammaticScrollAnimation(); 292 cancelProgrammaticScrollAnimation();
312 293
313 detachScrollbars(); 294 detachScrollbars();
314 295
315 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 296 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
316 scrollingCoordinator->willDestroyScrollableArea(this); 297 scrollingCoordinator->willDestroyScrollableArea(this);
317 298
318 // We need to clear the RootFrameViewport's animator since it gets called 299 // We need to clear the RootFrameViewport's animator since it gets called
319 // from non-GC'd objects and RootFrameViewport will still have a pointer to 300 // from non-GC'd objects and RootFrameViewport will still have a pointer to
320 // this class. 301 // this class.
321 if (m_viewportScrollableArea) 302 if (m_viewportScrollableArea)
322 m_viewportScrollableArea->clearScrollAnimators(); 303 m_viewportScrollableArea->clearScrollAnimators();
323 304
324 clearScrollAnimators(); 305 clearScrollAnimators();
325 306
326 // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing 307 // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing
327 // partially destroyed |this| via |m_autoSizeInfo->m_frameView|. 308 // partially destroyed |this| via |m_autoSizeInfo->m_frameView|.
328 m_autoSizeInfo.clear(); 309 m_autoSizeInfo.clear();
329 310
330 m_postLayoutTasksTimer.stop(); 311 m_postLayoutTasksTimer.stop();
331 m_didScrollTimer.stop(); 312 m_didScrollTimer.stop();
332 313
314 m_renderThrottlingObserverNotificationFactory->cancel();
315
333 // FIXME: Do we need to do something here for OOPI? 316 // FIXME: Do we need to do something here for OOPI?
334 HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner(); 317 HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner();
335 // TODO(dcheng): It seems buggy that we can have an owner element that 318 // TODO(dcheng): It seems buggy that we can have an owner element that
336 // points to another Widget. 319 // points to another Widget.
337 if (ownerElement && ownerElement->ownedWidget() == this) 320 if (ownerElement && ownerElement->ownedWidget() == this)
338 ownerElement->setWidget(nullptr); 321 ownerElement->setWidget(nullptr);
339 322
340 #if ENABLE(ASSERT) 323 #if ENABLE(ASSERT)
341 m_hasBeenDisposed = true; 324 m_hasBeenDisposed = true;
342 #endif 325 #endif
(...skipping 3084 matching lines...) Expand 10 before | Expand all | Expand 10 after
3427 } 3410 }
3428 3411
3429 void FrameView::setParent(Widget* parentView) { 3412 void FrameView::setParent(Widget* parentView) {
3430 if (parentView == parent()) 3413 if (parentView == parent())
3431 return; 3414 return;
3432 3415
3433 Widget::setParent(parentView); 3416 Widget::setParent(parentView);
3434 3417
3435 updateScrollableAreaSet(); 3418 updateScrollableAreaSet();
3436 setNeedsUpdateViewportIntersection(); 3419 setNeedsUpdateViewportIntersection();
3437 setupRenderThrottling();
3438
3439 if (parentFrameView())
3440 m_subtreeThrottled = parentFrameView()->canThrottleRendering();
3441 } 3420 }
3442 3421
3443 void FrameView::removeChild(Widget* child) { 3422 void FrameView::removeChild(Widget* child) {
3444 ASSERT(child->parent() == this); 3423 ASSERT(child->parent() == this);
3445 3424
3446 if (child->isFrameView()) 3425 if (child->isFrameView())
3447 removeScrollableArea(toFrameView(child)); 3426 removeScrollableArea(toFrameView(child));
3448 3427
3449 child->setParent(0); 3428 child->setParent(0);
3450 m_children.remove(child); 3429 m_children.remove(child);
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after
4347 if (layoutObject.isText()) 4326 if (layoutObject.isText())
4348 return; 4327 return;
4349 4328
4350 layoutObject.addAnnotatedRegions(regions); 4329 layoutObject.addAnnotatedRegions(regions);
4351 for (LayoutObject* curr = layoutObject.slowFirstChild(); curr; 4330 for (LayoutObject* curr = layoutObject.slowFirstChild(); curr;
4352 curr = curr->nextSibling()) 4331 curr = curr->nextSibling())
4353 collectAnnotatedRegions(*curr, regions); 4332 collectAnnotatedRegions(*curr, regions);
4354 } 4333 }
4355 4334
4356 void FrameView::setNeedsUpdateViewportIntersection() { 4335 void FrameView::setNeedsUpdateViewportIntersection() {
4336 m_needsUpdateViewportIntersection = true;
4357 for (FrameView* parent = parentFrameView(); parent; 4337 for (FrameView* parent = parentFrameView(); parent;
4358 parent = parent->parentFrameView()) 4338 parent = parent->parentFrameView())
4359 parent->m_needsUpdateViewportIntersectionInSubtree = true; 4339 parent->m_needsUpdateViewportIntersectionInSubtree = true;
4360 } 4340 }
4361 4341
4342 void FrameView::updateViewportIntersectionIfNeeded() {
4343 if (!m_needsUpdateViewportIntersection)
4344 return;
4345 m_needsUpdateViewportIntersection = false;
4346 m_viewportIntersectionValid = true;
4347 FrameView* parent = parentFrameView();
4348 if (!parent) {
4349 HTMLFrameOwnerElement* element = frame().deprecatedLocalOwner();
4350 if (!element)
4351 frame().document()->maybeRecordLoadReason(WouldLoadOutOfProcess);
4352 // Having no layout object means the frame is not drawn.
4353 else if (!element->layoutObject())
4354 frame().document()->maybeRecordLoadReason(WouldLoadDisplayNone);
4355 m_viewportIntersection = frameRect();
4356 return;
4357 }
4358 ASSERT(!parent->m_needsUpdateViewportIntersection);
4359
4360 bool parentLoaded = parent->frame().document()->wouldLoadReason() > Created;
4361 // If the parent wasn't loaded, the children won't be either.
4362 if (parentLoaded) {
4363 if (frameRect().isEmpty())
4364 frame().document()->maybeRecordLoadReason(WouldLoadZeroByZero);
4365 else if (frameRect().maxY() < 0 && frameRect().maxX() < 0)
4366 frame().document()->maybeRecordLoadReason(WouldLoadAboveAndLeft);
4367 else if (frameRect().maxY() < 0)
4368 frame().document()->maybeRecordLoadReason(WouldLoadAbove);
4369 else if (frameRect().maxX() < 0)
4370 frame().document()->maybeRecordLoadReason(WouldLoadLeft);
4371 }
4372
4373 // If our parent is hidden, then we are too.
4374 if (parent->m_viewportIntersection.isEmpty()) {
4375 m_viewportIntersection = parent->m_viewportIntersection;
4376 return;
4377 }
4378
4379 // Transform our bounds into the root frame's content coordinate space,
4380 // making sure we have valid layout data in our parent document. If our
4381 // parent is throttled, we'll use possible stale layout information and
4382 // rely on the fact that another lifecycle update will be scheduled once
4383 // our parent becomes unthrottled.
4384 ASSERT(parent->lifecycle().state() >= DocumentLifecycle::LayoutClean ||
4385 parent->shouldThrottleRendering());
4386 m_viewportIntersection = parent->contentsToRootFrame(frameRect());
4387
4388 // TODO(skyostil): Expand the viewport to make it less likely to see stale
4389 // content while scrolling.
4390 IntRect viewport = parent->m_viewportIntersection;
4391 m_viewportIntersection.intersect(viewport);
4392
4393 if (parentLoaded && !m_viewportIntersection.isEmpty())
4394 frame().document()->maybeRecordLoadReason(WouldLoadVisible);
4395 }
4396
4362 void FrameView::updateViewportIntersectionsForSubtree( 4397 void FrameView::updateViewportIntersectionsForSubtree(
4363 DocumentLifecycle::LifecycleState targetState) { 4398 DocumentLifecycle::LifecycleState targetState) {
4399 bool hadValidIntersection = m_viewportIntersectionValid;
4400 bool hadEmptyIntersection = m_viewportIntersection.isEmpty();
4401 updateViewportIntersectionIfNeeded();
4402
4364 // Notify javascript IntersectionObservers 4403 // Notify javascript IntersectionObservers
4365 if (targetState == DocumentLifecycle::PaintClean && 4404 if (targetState == DocumentLifecycle::PaintClean &&
4366 frame().document()->intersectionObserverController()) 4405 frame().document()->intersectionObserverController())
4367 frame() 4406 frame()
4368 .document() 4407 .document()
4369 ->intersectionObserverController() 4408 ->intersectionObserverController()
4370 ->computeTrackedIntersectionObservations(); 4409 ->computeTrackedIntersectionObservations();
4371 4410
4411 // Adjust render throttling for iframes based on visibility
4412 bool shouldNotify = !hadValidIntersection ||
4413 hadEmptyIntersection != m_viewportIntersection.isEmpty();
4414 if (shouldNotify &&
4415 !m_renderThrottlingObserverNotificationFactory->isPending())
4416 m_frame->frameScheduler()->unthrottledTaskRunner()->postTask(
4417 BLINK_FROM_HERE,
4418 m_renderThrottlingObserverNotificationFactory->cancelAndCreate());
4419
4372 if (!m_needsUpdateViewportIntersectionInSubtree) 4420 if (!m_needsUpdateViewportIntersectionInSubtree)
4373 return; 4421 return;
4374 m_needsUpdateViewportIntersectionInSubtree = false; 4422 m_needsUpdateViewportIntersectionInSubtree = false;
4375 4423
4376 for (Frame* child = m_frame->tree().firstChild(); child; 4424 for (Frame* child = m_frame->tree().firstChild(); child;
4377 child = child->tree().nextSibling()) { 4425 child = child->tree().nextSibling()) {
4378 if (!child->isLocalFrame()) 4426 if (!child->isLocalFrame())
4379 continue; 4427 continue;
4380 if (FrameView* view = toLocalFrame(child)->view()) 4428 if (FrameView* view = toLocalFrame(child)->view())
4381 view->updateViewportIntersectionsForSubtree(targetState); 4429 view->updateViewportIntersectionsForSubtree(targetState);
4382 } 4430 }
4383 } 4431 }
4384 4432
4385 void FrameView::updateRenderThrottlingStatusForTesting() { 4433 void FrameView::updateThrottlingStatus() {
4386 m_visibilityObserver->deliverObservationsForTesting(); 4434 // Only offscreen frames can be throttled. Note that we disallow throttling
4435 // of 0x0 frames because some sites use them to drive UI logic.
4436 DCHECK(m_viewportIntersectionValid);
4437 m_hiddenForThrottling =
4438 m_viewportIntersection.isEmpty() && !frameRect().isEmpty();
4439
4440 // We only throttle the rendering pipeline in cross-origin frames. This is
4441 // to avoid a situation where an ancestor frame directly depends on the
4442 // pipeline timing of a descendant and breaks as a result of throttling.
4443 // The rationale is that cross-origin frames must already communicate with
4444 // asynchronous messages, so they should be able to tolerate some delay in
4445 // receiving replies from a throttled peer.
4446 //
4447 // Check if we can access our parent's security origin.
4448 m_crossOriginForThrottling = false;
4449 // If any of our parents are throttled, we must be too.
4450 m_subtreeThrottled = false;
4451 const SecurityOrigin* origin = frame().securityContext()->getSecurityOrigin();
4452 for (Frame* parentFrame = m_frame->tree().parent(); parentFrame;
4453 parentFrame = parentFrame->tree().parent()) {
4454 const SecurityOrigin* parentOrigin =
4455 parentFrame->securityContext()->getSecurityOrigin();
4456 if (!origin->canAccess(parentOrigin))
4457 m_crossOriginForThrottling = true;
4458 if (parentFrame->isLocalFrame() && toLocalFrame(parentFrame)->view() &&
4459 toLocalFrame(parentFrame)->view()->canThrottleRendering())
4460 m_subtreeThrottled = true;
4461 }
4462 m_frame->frameScheduler()->setFrameVisible(!m_hiddenForThrottling);
4463 m_frame->frameScheduler()->setCrossOrigin(m_crossOriginForThrottling);
4387 } 4464 }
4388 4465
4389 void FrameView::updateRenderThrottlingStatus(bool hidden, 4466 void FrameView::notifyRenderThrottlingObserversForTesting() {
4390 bool subtreeThrottled) { 4467 DCHECK(m_renderThrottlingObserverNotificationFactory->isPending());
4391 TRACE_EVENT0("blink", "FrameView::updateRenderThrottlingStatus"); 4468 notifyRenderThrottlingObservers();
4469 }
4470
4471 void FrameView::notifyRenderThrottlingObservers() {
4472 TRACE_EVENT0("blink", "FrameView::notifyRenderThrottlingObservers");
4392 DCHECK(!isInPerformLayout()); 4473 DCHECK(!isInPerformLayout());
4393 DCHECK(!m_frame->document() || !m_frame->document()->inStyleRecalc()); 4474 DCHECK(frame().document());
4475 DCHECK(!frame().document()->inStyleRecalc());
4394 bool wasThrottled = canThrottleRendering(); 4476 bool wasThrottled = canThrottleRendering();
4395 4477
4396 // Note that we disallow throttling of 0x0 frames because some sites use 4478 updateThrottlingStatus();
4397 // them to drive UI logic.
4398 m_hiddenForThrottling = hidden && !frameRect().isEmpty();
4399 m_subtreeThrottled = subtreeThrottled;
4400 4479
4401 bool isThrottled = canThrottleRendering(); 4480 bool becameThrottled = !wasThrottled && canThrottleRendering();
4402 bool becameUnthrottled = wasThrottled && !isThrottled; 4481 bool becameUnthrottled = wasThrottled && !canThrottleRendering();
4403 4482 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
4404 // If this FrameView became unthrottled or throttled, we must make sure all 4483 if (becameThrottled) {
4405 // its children are notified synchronously. Otherwise we 1) might attempt to 4484 // If this FrameView became throttled, we must make sure all of its
4406 // paint one of the children with an out-of-date layout before 4485 // children become throttled at the same time. Otherwise we might
4407 // |updateRenderThrottlingStatus| has made it throttled or 2) fail to 4486 // attempt to paint one of the children with an out-of-date layout
4408 // unthrottle a child whose parent is unthrottled by a later notification. 4487 // before |notifyRenderThrottlingObservers| has made it throttled.
4409 if (wasThrottled != isThrottled) { 4488 forAllNonThrottledFrameViews([](FrameView& frameView) {
4410 for (const Member<Widget>& child : *children()) { 4489 frameView.m_subtreeThrottled = true;
4411 if (child->isFrameView()) { 4490 DCHECK(frameView.canThrottleRendering());
4412 FrameView* childView = toFrameView(child); 4491 });
4413 childView->updateRenderThrottlingStatus(
4414 childView->m_hiddenForThrottling, isThrottled);
4415 }
4416 }
4417 } 4492 }
4418
4419 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
4420 if (becameUnthrottled) { 4493 if (becameUnthrottled) {
4421 // ScrollingCoordinator needs to update according to the new throttling 4494 // ScrollingCoordinator needs to update according to the new throttling
4422 // status. 4495 // status.
4423 if (scrollingCoordinator) 4496 if (scrollingCoordinator)
4424 scrollingCoordinator->notifyGeometryChanged(); 4497 scrollingCoordinator->notifyGeometryChanged();
4425 // Start ticking animation frames again if necessary. 4498 // Start ticking animation frames again if necessary.
4426 if (page()) 4499 if (page())
4427 page()->animator().scheduleVisualUpdate(m_frame.get()); 4500 page()->animator().scheduleVisualUpdate(m_frame.get());
4428 // Force a full repaint of this frame to ensure we are not left with a 4501 // Force a full repaint of this frame to ensure we are not left with a
4429 // partially painted version of this frame's contents if we skipped 4502 // partially painted version of this frame's contents if we skipped
4430 // painting them while the frame was throttled. 4503 // painting them while the frame was throttled.
4431 LayoutViewItem layoutViewItem = this->layoutViewItem(); 4504 LayoutViewItem layoutViewItem = this->layoutViewItem();
4432 if (!layoutViewItem.isNull()) 4505 if (!layoutViewItem.isNull())
4433 layoutViewItem.invalidatePaintForViewAndCompositedLayers(); 4506 layoutViewItem.invalidatePaintForViewAndCompositedLayers();
4434 } 4507 }
4435 4508
4436 bool hasHandlers = m_frame->host() && 4509 bool hasHandlers = m_frame->host() &&
4437 m_frame->host()->eventHandlerRegistry().hasEventHandlers( 4510 m_frame->host()->eventHandlerRegistry().hasEventHandlers(
4438 EventHandlerRegistry::TouchStartOrMoveEventBlocking); 4511 EventHandlerRegistry::TouchStartOrMoveEventBlocking);
4439 if (wasThrottled != canThrottleRendering() && scrollingCoordinator && 4512 if (wasThrottled != canThrottleRendering() && scrollingCoordinator &&
4440 hasHandlers) 4513 hasHandlers)
4441 scrollingCoordinator->touchEventTargetRectsDidChange(); 4514 scrollingCoordinator->touchEventTargetRectsDidChange();
4442 4515
4443 FrameView* parent = parentFrameView();
4444 if (frame().document()->frame()) {
4445 if (!parent) {
4446 HTMLFrameOwnerElement* element = frame().deprecatedLocalOwner();
4447 if (!element)
4448 frame().document()->maybeRecordLoadReason(WouldLoadOutOfProcess);
4449 // Having no layout object means the frame is not drawn.
4450 else if (!element->layoutObject())
4451 frame().document()->maybeRecordLoadReason(WouldLoadDisplayNone);
4452 } else {
4453 // Assume the main frame has always loaded since we don't track its
4454 // visibility.
4455 bool parentLoaded =
4456 !parent->parentFrameView() ||
4457 parent->frame().document()->wouldLoadReason() > Created;
4458 // If the parent wasn't loaded, the children won't be either.
4459 if (parentLoaded) {
4460 if (frameRect().isEmpty())
4461 frame().document()->maybeRecordLoadReason(WouldLoadZeroByZero);
4462 else if (frameRect().maxY() < 0 && frameRect().maxX() < 0)
4463 frame().document()->maybeRecordLoadReason(WouldLoadAboveAndLeft);
4464 else if (frameRect().maxY() < 0)
4465 frame().document()->maybeRecordLoadReason(WouldLoadAbove);
4466 else if (frameRect().maxX() < 0)
4467 frame().document()->maybeRecordLoadReason(WouldLoadLeft);
4468 else if (!m_hiddenForThrottling)
4469 frame().document()->maybeRecordLoadReason(WouldLoadVisible);
4470 }
4471 }
4472 }
4473
4474 #if DCHECK_IS_ON() 4516 #if DCHECK_IS_ON()
4475 // Make sure we never have an unthrottled frame inside a throttled one. 4517 // Make sure we never have an unthrottled frame inside a throttled one.
4518 FrameView* parent = parentFrameView();
4476 while (parent) { 4519 while (parent) {
4477 DCHECK(canThrottleRendering() || !parent->canThrottleRendering()); 4520 DCHECK(canThrottleRendering() || !parent->canThrottleRendering());
4478 parent = parent->parentFrameView(); 4521 parent = parent->parentFrameView();
4479 } 4522 }
4480 #endif 4523 #endif
4481 } 4524 }
4482 4525
4483 bool FrameView::shouldThrottleRendering() const { 4526 bool FrameView::shouldThrottleRendering() const {
4484 return canThrottleRendering() && lifecycle().throttlingAllowed(); 4527 return canThrottleRendering() && lifecycle().throttlingAllowed();
4485 } 4528 }
4486 4529
4487 bool FrameView::canThrottleRendering() const { 4530 bool FrameView::canThrottleRendering() const {
4488 if (!RuntimeEnabledFeatures::renderingPipelineThrottlingEnabled()) 4531 if (!RuntimeEnabledFeatures::renderingPipelineThrottlingEnabled())
4489 return false; 4532 return false;
4490 // We only throttle the rendering pipeline in cross-origin frames. This is
4491 // to avoid a situation where an ancestor frame directly depends on the
4492 // pipeline timing of a descendant and breaks as a result of throttling.
4493 // The rationale is that cross-origin frames must already communicate with
4494 // asynchronous messages, so they should be able to tolerate some delay in
4495 // receiving replies from a throttled peer.
4496 return m_subtreeThrottled || 4533 return m_subtreeThrottled ||
4497 (m_hiddenForThrottling && m_frame->isCrossOriginSubframe()); 4534 (m_hiddenForThrottling && m_crossOriginForThrottling);
4498 } 4535 }
4499 4536
4500 void FrameView::setInitialViewportSize(const IntSize& viewportSize) { 4537 void FrameView::setInitialViewportSize(const IntSize& viewportSize) {
4501 if (viewportSize == m_initialViewportSize) 4538 if (viewportSize == m_initialViewportSize)
4502 return; 4539 return;
4503 4540
4504 m_initialViewportSize = viewportSize; 4541 m_initialViewportSize = viewportSize;
4505 if (Document* document = m_frame->document()) 4542 if (Document* document = m_frame->document())
4506 document->styleEngine().initialViewportChanged(); 4543 document->styleEngine().initialViewportChanged();
4507 } 4544 }
4508 4545
4509 int FrameView::initialViewportWidth() const { 4546 int FrameView::initialViewportWidth() const {
4510 DCHECK(m_frame->isMainFrame()); 4547 DCHECK(m_frame->isMainFrame());
4511 return m_initialViewportSize.width(); 4548 return m_initialViewportSize.width();
4512 } 4549 }
4513 4550
4514 int FrameView::initialViewportHeight() const { 4551 int FrameView::initialViewportHeight() const {
4515 DCHECK(m_frame->isMainFrame()); 4552 DCHECK(m_frame->isMainFrame());
4516 return m_initialViewportSize.height(); 4553 return m_initialViewportSize.height();
4517 } 4554 }
4518 4555
4519 } // namespace blink 4556 } // 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