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

Unified Diff: third_party/WebKit/Source/core/frame/FrameView.cpp

Issue 2516473002: Cross-origin iframes: collect data under hypothetical loading strategies (Closed)
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 side-by-side diff with in-line comments
Download patch
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;
}
}
}

Powered by Google App Engine
This is Rietveld 408576698