blob: 01d611d48a0d67b51f0287d37df7fd9f278e0083 [file] [log] [blame]
/*
* Copyright (C) 2011 Google, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "core/loader/DocumentLoadTiming.h"
#include "base/memory/scoped_refptr.h"
#include "core/loader/DocumentLoader.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/weborigin/SecurityOrigin.h"
namespace blink {
DocumentLoadTiming::DocumentLoadTiming(DocumentLoader& document_loader)
: reference_monotonic_time_(0.0),
reference_wall_time_(0.0),
navigation_start_(0.0),
unload_event_start_(0.0),
unload_event_end_(0.0),
redirect_start_(0.0),
redirect_end_(0.0),
redirect_count_(0),
fetch_start_(0.0),
response_end_(0.0),
load_event_start_(0.0),
load_event_end_(0.0),
has_cross_origin_redirect_(false),
has_same_origin_as_previous_document_(false),
document_loader_(document_loader) {}
void DocumentLoadTiming::Trace(blink::Visitor* visitor) {
visitor->Trace(document_loader_);
}
// TODO(csharrison): Remove the null checking logic in a later patch.
LocalFrame* DocumentLoadTiming::GetFrame() const {
return document_loader_ ? document_loader_->GetFrame() : nullptr;
}
void DocumentLoadTiming::NotifyDocumentTimingChanged() {
if (document_loader_)
document_loader_->DidChangePerformanceTiming();
}
void DocumentLoadTiming::EnsureReferenceTimesSet() {
if (!reference_wall_time_)
reference_wall_time_ = CurrentTime();
if (!reference_monotonic_time_)
reference_monotonic_time_ = CurrentTimeTicksInSeconds();
}
double DocumentLoadTiming::MonotonicTimeToZeroBasedDocumentTime(
double monotonic_time) const {
if (!monotonic_time || !reference_monotonic_time_)
return 0.0;
return monotonic_time - reference_monotonic_time_;
}
double DocumentLoadTiming::MonotonicTimeToPseudoWallTime(
double monotonic_time) const {
if (!monotonic_time || !reference_monotonic_time_)
return 0.0;
return reference_wall_time_ + monotonic_time - reference_monotonic_time_;
}
double DocumentLoadTiming::PseudoWallTimeToMonotonicTime(
double pseudo_wall_time) const {
if (!pseudo_wall_time)
return 0.0;
return reference_monotonic_time_ + pseudo_wall_time - reference_wall_time_;
}
void DocumentLoadTiming::MarkNavigationStart() {
// Allow the embedder to override navigationStart before we record it if
// they have a more accurate timestamp.
if (navigation_start_) {
DCHECK(reference_monotonic_time_);
DCHECK(reference_wall_time_);
return;
}
DCHECK(!navigation_start_);
DCHECK(!reference_monotonic_time_);
DCHECK(!reference_wall_time_);
EnsureReferenceTimesSet();
navigation_start_ = reference_monotonic_time_;
TRACE_EVENT_MARK_WITH_TIMESTAMP1(
"blink.user_timing", "navigationStart",
TraceEvent::ToTraceTimestamp(navigation_start_), "frame", GetFrame());
NotifyDocumentTimingChanged();
}
void DocumentLoadTiming::SetNavigationStart(double navigation_start) {
// |m_referenceMonotonicTime| and |m_referenceWallTime| represent
// navigationStart. We must set these to the current time if they haven't
// been set yet in order to have a valid reference time in both units.
EnsureReferenceTimesSet();
navigation_start_ = navigation_start;
TRACE_EVENT_MARK_WITH_TIMESTAMP1(
"blink.user_timing", "navigationStart",
TraceEvent::ToTraceTimestamp(navigation_start_), "frame", GetFrame());
// The reference times are adjusted based on the embedder's navigationStart.
DCHECK(reference_monotonic_time_);
DCHECK(reference_wall_time_);
reference_wall_time_ = MonotonicTimeToPseudoWallTime(navigation_start);
reference_monotonic_time_ = navigation_start;
NotifyDocumentTimingChanged();
}
void DocumentLoadTiming::AddRedirect(const KURL& redirecting_url,
const KURL& redirected_url) {
redirect_count_++;
if (!redirect_start_) {
SetRedirectStart(fetch_start_);
}
MarkRedirectEnd();
MarkFetchStart();
// Check if the redirected url is allowed to access the redirecting url's
// timing information.
scoped_refptr<const SecurityOrigin> redirected_security_origin =
SecurityOrigin::Create(redirected_url);
has_cross_origin_redirect_ |=
!redirected_security_origin->CanRequest(redirecting_url);
}
void DocumentLoadTiming::SetRedirectStart(double redirect_start) {
redirect_start_ = redirect_start;
TRACE_EVENT_MARK_WITH_TIMESTAMP1(
"blink.user_timing", "redirectStart",
TraceEvent::ToTraceTimestamp(redirect_start_), "frame", GetFrame());
NotifyDocumentTimingChanged();
}
void DocumentLoadTiming::SetRedirectEnd(double redirect_end) {
redirect_end_ = redirect_end;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "redirectEnd",
TraceEvent::ToTraceTimestamp(redirect_end_),
"frame", GetFrame());
NotifyDocumentTimingChanged();
}
void DocumentLoadTiming::MarkUnloadEventStart(double start_time) {
unload_event_start_ = start_time;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "unloadEventStart",
TraceEvent::ToTraceTimestamp(start_time),
"frame", GetFrame());
NotifyDocumentTimingChanged();
}
void DocumentLoadTiming::MarkUnloadEventEnd(double end_time) {
unload_event_end_ = end_time;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "unloadEventEnd",
TraceEvent::ToTraceTimestamp(end_time),
"frame", GetFrame());
NotifyDocumentTimingChanged();
}
void DocumentLoadTiming::MarkFetchStart() {
SetFetchStart(CurrentTimeTicksInSeconds());
}
void DocumentLoadTiming::SetFetchStart(double fetch_start) {
fetch_start_ = fetch_start;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "fetchStart",
TraceEvent::ToTraceTimestamp(fetch_start_),
"frame", GetFrame());
NotifyDocumentTimingChanged();
}
void DocumentLoadTiming::SetResponseEnd(double response_end) {
response_end_ = response_end;
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "responseEnd",
TraceEvent::ToTraceTimestamp(response_end_),
"frame", GetFrame());
NotifyDocumentTimingChanged();
}
void DocumentLoadTiming::MarkLoadEventStart() {
load_event_start_ = CurrentTimeTicksInSeconds();
TRACE_EVENT_MARK_WITH_TIMESTAMP1(
"blink.user_timing", "loadEventStart",
TraceEvent::ToTraceTimestamp(load_event_start_), "frame", GetFrame());
NotifyDocumentTimingChanged();
}
void DocumentLoadTiming::MarkLoadEventEnd() {
load_event_end_ = CurrentTimeTicksInSeconds();
TRACE_EVENT_MARK_WITH_TIMESTAMP1(
"blink.user_timing", "loadEventEnd",
TraceEvent::ToTraceTimestamp(load_event_end_), "frame", GetFrame());
NotifyDocumentTimingChanged();
}
void DocumentLoadTiming::MarkRedirectEnd() {
redirect_end_ = CurrentTimeTicksInSeconds();
TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "redirectEnd",
TraceEvent::ToTraceTimestamp(redirect_end_),
"frame", GetFrame());
NotifyDocumentTimingChanged();
}
} // namespace blink