Chromium Code Reviews| Index: third_party/WebKit/Source/core/frame/FrameView.cpp |
| diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp |
| index 92b46e9a1c3850ba0c0b3fbf8bcaefc9d77e9724..58829902ff0815adc4c0e090f00d2e436e22cb75 100644 |
| --- a/third_party/WebKit/Source/core/frame/FrameView.cpp |
| +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp |
| @@ -125,6 +125,7 @@ |
| #include "wtf/CurrentTime.h" |
| #include "wtf/PtrUtil.h" |
| #include "wtf/StdLibExtras.h" |
| +#include <algorithm> |
| #include <memory> |
| // Used to check for dirty layouts violating document lifecycle rules. |
| @@ -175,7 +176,6 @@ FrameView::FrameView(LocalFrame& frame) |
| m_didScrollTimer(this, &FrameView::didScrollTimerFired), |
| m_browserControlsViewportAdjustment(0), |
| m_needsUpdateWidgetGeometries(false), |
| - m_needsUpdateViewportIntersection(true), |
| #if ENABLE(ASSERT) |
| m_hasBeenDisposed(false), |
| #endif |
| @@ -315,7 +315,7 @@ void FrameView::setupRenderThrottling() { |
| [](FrameView* frameView, bool isVisible) { |
| frameView->updateRenderThrottlingStatus( |
| !isVisible, frameView->m_subtreeThrottled); |
| - frameView->maybeRecordLoadReason(); |
| + frameView->recordDeferredLoadingStats(); |
| }, |
| wrapWeakPersistent(this))); |
| m_visibilityObserver->start(); |
| @@ -4524,13 +4524,16 @@ void FrameView::setNeedsUpdateViewportIntersection() { |
| void FrameView::updateViewportIntersectionsForSubtree( |
| DocumentLifecycle::LifecycleState targetState) { |
| - // Notify javascript IntersectionObservers |
| - if (targetState == DocumentLifecycle::PaintClean && |
| - frame().document()->intersectionObserverController()) |
| - frame() |
| - .document() |
| - ->intersectionObserverController() |
| - ->computeTrackedIntersectionObservations(); |
| + if (targetState == DocumentLifecycle::PaintClean) { |
| + recordDeferredLoadingStats(); |
| + // Notify javascript IntersectionObservers |
| + if (frame().document()->intersectionObserverController()) { |
| + frame() |
| + .document() |
| + ->intersectionObserverController() |
| + ->computeTrackedIntersectionObservations(); |
| + } |
| + } |
| if (!m_needsUpdateViewportIntersectionInSubtree) |
| return; |
| @@ -4618,39 +4621,53 @@ void FrameView::updateRenderThrottlingStatus(bool hidden, |
| #endif |
| } |
| -// TODO(esprehn): Rename this and the method on Document to |
| -// recordDeferredLoadReason(). |
| -void FrameView::maybeRecordLoadReason() { |
| +void FrameView::recordDeferredLoadingStats() { |
| + if (!frame().document()->frame() || !frame().isCrossOriginSubframe()) |
| + return; |
| FrameView* parent = parentFrameView(); |
| - if (frame().document()->frame()) { |
| - if (!parent) { |
| - HTMLFrameOwnerElement* element = frame().deprecatedLocalOwner(); |
| - if (!element) |
| - frame().document()->maybeRecordLoadReason(WouldLoadOutOfProcess); |
| - // Having no layout object means the frame is not drawn. |
| - else if (!element->layoutObject()) |
| - frame().document()->maybeRecordLoadReason(WouldLoadDisplayNone); |
| - } else { |
| - // Assume the main frame has always loaded since we don't track its |
| - // visibility. |
| - bool parentLoaded = |
| - !parent->parentFrameView() || |
| - parent->frame().document()->wouldLoadReason() > Created; |
| - // If the parent wasn't loaded, the children won't be either. |
| - if (parentLoaded) { |
| - if (frameRect().isEmpty()) |
| - frame().document()->maybeRecordLoadReason(WouldLoadZeroByZero); |
| - else if (frameRect().maxY() < 0 && frameRect().maxX() < 0) |
| - frame().document()->maybeRecordLoadReason(WouldLoadAboveAndLeft); |
| - else if (frameRect().maxY() < 0) |
| - frame().document()->maybeRecordLoadReason(WouldLoadAbove); |
| - else if (frameRect().maxX() < 0) |
| - frame().document()->maybeRecordLoadReason(WouldLoadLeft); |
| - else if (!m_hiddenForThrottling) |
| - frame().document()->maybeRecordLoadReason(WouldLoadVisible); |
| - } |
| - } |
| + if (!parent) { |
| + HTMLFrameOwnerElement* element = frame().deprecatedLocalOwner(); |
| + // We would fall into an else block on some teardowns and other weird cases. |
| + if (!element || !element->layoutObject()) |
| + frame().document()->recordDeferredLoadReason(WouldLoadNoParent); |
| + return; |
| + } |
| + // Small inaccuracy: frames with origins that match the top level might be |
| + // nested in a cross-origin frame. To keep code simpler, count such frames as |
| + // WouldLoadVisible, even when their parent is offscreen. |
| + WouldLoadReason whyParentLoaded = WouldLoadVisible; |
| + if (parent->parentFrameView() && parent->frame().isCrossOriginSubframe()) |
| + whyParentLoaded = parent->frame().document()->deferredLoadReason(); |
| + |
| + // If the parent wasn't loaded, the children won't be either. |
| + if (whyParentLoaded == Created) |
| + return; |
| + // These frames are never meant to be seen so we will need to load them. |
| + if (frameRect().isEmpty() || frameRect().maxY() < 0 || |
| + frameRect().maxX() < 0) { |
| + frame().document()->recordDeferredLoadReason(whyParentLoaded); |
| + return; |
| } |
| + IntRect parentRect = parent->frameRect(); |
| + // First clause is checking if the child frame misses its parent laterally. |
| + if (frameRect().x() >= parentRect.width() || parentRect.height() <= 0) |
| + return; |
| + |
| + int screensAway = frameRect().y() / parentRect.height(); |
|
ojan
2017/01/18 00:55:01
Does this need to take scroll position into accoun
|
| + |
| + // We're collecting data for frames that are at most 3 screens away. |
| + if (screensAway > 3) |
| + return; |
| + |
| + // This means that the top of the child frame is positioned above the parent. |
| + // But the above check for maxY() < 0 means that maxY() is positive -> the |
| + // child stretches at least into the first screen and possibly lower. |
| + if (screensAway < 0) |
| + screensAway = 0; |
| + |
| + frame().document()->recordDeferredLoadReason( |
| + static_cast<WouldLoadReason>(std::min(static_cast<int>(whyParentLoaded), |
| + WouldLoadVisible - screensAway))); |
| } |
| bool FrameView::shouldThrottleRendering() const { |