| 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 d7af7ba56a5426ac3ae365a376c9ffdab5dac2b4..4add5fc99d4328747464348aa051328137cf31f3 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.
|
| @@ -173,7 +174,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
|
| @@ -311,7 +311,7 @@ void FrameView::setupRenderThrottling() {
|
| [](FrameView* frameView, bool isVisible) {
|
| frameView->updateRenderThrottlingStatus(
|
| !isVisible, frameView->m_subtreeThrottled);
|
| - frameView->maybeRecordLoadReason();
|
| + frameView->recordDeferredLoadingStats();
|
| },
|
| wrapWeakPersistent(this)));
|
| m_visibilityObserver->start();
|
| @@ -4410,13 +4410,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;
|
| @@ -4504,36 +4507,48 @@ 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;
|
| + if (frameRect().isEmpty() || frameRect().maxY() < 0 ||
|
| + frameRect().maxX() < 0) {
|
| + frame().document()->recordDeferredLoadReason(whyParentLoaded);
|
| + return;
|
| + }
|
| + IntRect parentRect = parent->frameRect();
|
| + if (FrameView* grandParent = parent->parentFrameView())
|
| + parentRect = grandParent->contentsToRootFrame(parentRect);
|
| + const IntRect childRect = parent->contentsToRootFrame(frameRect());
|
| + // Optimization opportunity: Do some arithmetic instead of looping over each
|
| + // of the repositioned viewports.
|
| + for (int i = 0; i <= 3; ++i) {
|
| + for (int j = 0; j <= (3 - i); ++j) {
|
| + IntRect expandedParentRect(parentRect);
|
| + expandedParentRect.expand(i * parentRect.width(),
|
| + j * parentRect.height());
|
| + if (expandedParentRect.intersects(childRect)) {
|
| + frame().document()->recordDeferredLoadReason(
|
| + static_cast<WouldLoadReason>(std::min(
|
| + static_cast<int>(whyParentLoaded), WouldLoadVisible - i - j)));
|
| + return;
|
| }
|
| }
|
| }
|
|
|