Chromium Code Reviews| Index: third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp |
| diff --git a/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b2c1072439bb2213c8a7482f81449a9fd5b821af |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp |
| @@ -0,0 +1,100 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "core/paint/FirstMeaningfulPaintDetector.h" |
| + |
| +#include "core/css/FontFaceSet.h" |
| +#include "core/fetch/ResourceFetcher.h" |
| +#include "core/paint/PaintTiming.h" |
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| +// Web fonts that laid out more than this number of characters block First |
| +// Meaningful Paint. |
| +const int kBlankCharactersThreshold = 200; |
| + |
| +// FirstMeaningfulPaintDetector stops observing layouts and reports First |
| +// Meaningful Paint when this duration passed from last network activity. |
| +const double kTimeWithoutNetworkActivity = 2.0; |
| + |
| +} // namespace |
| + |
| +FirstMeaningfulPaintDetector& FirstMeaningfulPaintDetector::from(Document& document) |
| +{ |
| + return PaintTiming::from(document).firstMeaningfulPaintDetector(); |
| +} |
| + |
| +FirstMeaningfulPaintDetector::FirstMeaningfulPaintDetector(PaintTiming* paintTiming) |
| + : m_paintTiming(paintTiming) |
| + , m_networkStableTimer(this, &FirstMeaningfulPaintDetector::networkStableTimerFired) |
| +{ |
| +} |
| + |
| +Document* FirstMeaningfulPaintDetector::document() |
| +{ |
| + return m_paintTiming->document(); |
| +} |
| + |
| +void FirstMeaningfulPaintDetector::computeLayoutSignificance( |
| + const LayoutObjectCounter& counter, int contentsHeightBeforeLayout, |
| + int contentsHeightAfterLayout, int visibleHeight) |
| +{ |
| + if (m_state == Reported) |
| + return; |
| + |
| + unsigned delta = counter.count() - m_prevLayoutObjectCount; |
| + m_prevLayoutObjectCount = counter.count(); |
| + |
| + double ratioBefore = std::max(1.0, static_cast<double>(contentsHeightBeforeLayout) / visibleHeight); |
| + double ratioAfter = std::max(1.0, static_cast<double>(contentsHeightAfterLayout) / visibleHeight); |
| + double significance = delta / ((ratioBefore + ratioAfter) / 2); |
| + |
| + int approximateBlankCharacterCount = FontFaceSet::approximateBlankCharacterCount(*document()); |
| + if (approximateBlankCharacterCount > kBlankCharactersThreshold) { |
| + m_accumulatedSignificanceWhileHavingBlankText += significance; |
| + } else { |
| + significance += m_accumulatedSignificanceWhileHavingBlankText; |
| + m_accumulatedSignificanceWhileHavingBlankText = 0; |
| + if (significance > m_maxSignificanceSoFar) { |
| + m_state = NextPaintIsMeaningful; |
| + m_maxSignificanceSoFar = significance; |
| + } |
| + } |
| +} |
| + |
| +void FirstMeaningfulPaintDetector::notifyPaint() |
| +{ |
| + if (m_state == NextPaintIsMeaningful) { |
| + m_provisionalFirstMeaningfulPaint = monotonicallyIncreasingTime(); |
| + m_state = NextPaintIsNotMeaningful; |
| + } |
| +} |
| + |
| +void FirstMeaningfulPaintDetector::checkNetworkStable() |
| +{ |
| + if (m_state == Reported || !document() || document()->fetcher()->hasPendingRequest()) |
|
kouhei (in TOK)
2016/07/28 03:45:04
s/hasPendingRequest/!document()->frame()->isLoadin
Kunihiko Sakamoto
2016/08/01 08:52:07
IIUC frame()->isLoading() never returns true after
|
| + return; |
| + |
| + if (m_networkStableTimer.isActive()) |
| + m_networkStableTimer.stop(); |
| + m_networkStableTimer.startOneShot(kTimeWithoutNetworkActivity, BLINK_FROM_HERE); |
| +} |
| + |
| +void FirstMeaningfulPaintDetector::networkStableTimerFired(Timer<FirstMeaningfulPaintDetector>*) |
| +{ |
| + if (m_state == Reported || !document() || document()->fetcher()->hasPendingRequest()) |
| + return; |
| + |
| + m_paintTiming->setFirstMeaningfulPaint(m_provisionalFirstMeaningfulPaint); |
| + m_state = Reported; |
| +} |
| + |
| +DEFINE_TRACE(FirstMeaningfulPaintDetector) |
| +{ |
| + visitor->trace(m_paintTiming); |
| +} |
| + |
| +} // namespace blink |