moebius#161: The Performance Resource Timing (make timestamps be relative to startTime)

https://github.com/MoonchildProductions/moebius/pull/161
This commit is contained in:
janekptacijarabaci 2018-04-29 14:15:18 +02:00 committed by Roy Tam
commit e8dbb561f6
20 changed files with 520 additions and 154 deletions

View file

@ -281,6 +281,7 @@ bool nsContentUtils::sIsCutCopyAllowed = true;
bool nsContentUtils::sIsFrameTimingPrefEnabled = false;
bool nsContentUtils::sIsPerformanceTimingEnabled = false;
bool nsContentUtils::sIsResourceTimingEnabled = false;
bool nsContentUtils::sIsPerformanceNavigationTimingEnabled = false;
bool nsContentUtils::sIsUserTimingLoggingEnabled = false;
bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false;
bool nsContentUtils::sEncodeDecodeURLHash = false;
@ -571,6 +572,9 @@ nsContentUtils::Init()
Preferences::AddBoolVarCache(&sIsResourceTimingEnabled,
"dom.enable_resource_timing", true);
Preferences::AddBoolVarCache(&sIsPerformanceNavigationTimingEnabled,
"dom.enable_performance_navigation_timing", true);
Preferences::AddBoolVarCache(&sIsUserTimingLoggingEnabled,
"dom.performance.enable_user_timing_logging", false);

View file

@ -2032,6 +2032,14 @@ public:
return sIsResourceTimingEnabled;
}
/*
* Returns true if the performance timing APIs are enabled.
*/
static bool IsPerformanceNavigationTimingEnabled()
{
return sIsPerformanceNavigationTimingEnabled;
}
/*
* Returns true if notification should be sent for peformance timing events.
*/
@ -2825,6 +2833,7 @@ private:
static uint32_t sHandlingInputTimeout;
static bool sIsPerformanceTimingEnabled;
static bool sIsResourceTimingEnabled;
static bool sIsPerformanceNavigationTimingEnabled;
static bool sIsUserTimingLoggingEnabled;
static bool sIsFrameTimingPrefEnabled;
static bool sIsExperimentalAutocompleteEnabled;

View file

@ -15,6 +15,7 @@
#include "nsPrintfCString.h"
#include "mozilla/dom/PerformanceNavigation.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Telemetry.h"
using namespace mozilla;
@ -32,24 +33,17 @@ nsDOMNavigationTiming::Clear()
{
mNavigationType = TYPE_RESERVED;
mNavigationStartHighRes = 0;
mBeforeUnloadStart = 0;
mUnloadStart = 0;
mUnloadEnd = 0;
mLoadEventStart = 0;
mLoadEventEnd = 0;
mDOMLoading = 0;
mDOMInteractive = 0;
mDOMContentLoadedEventStart = 0;
mDOMContentLoadedEventEnd = 0;
mDOMComplete = 0;
mBeforeUnloadStart = TimeStamp();
mUnloadStart = TimeStamp();
mUnloadEnd = TimeStamp();
mLoadEventStart = TimeStamp();
mLoadEventEnd = TimeStamp();
mDOMLoading = TimeStamp();
mDOMInteractive = TimeStamp();
mDOMContentLoadedEventStart = TimeStamp();
mDOMContentLoadedEventEnd = TimeStamp();
mDOMComplete = TimeStamp();
mLoadEventStartSet = false;
mLoadEventEndSet = false;
mDOMLoadingSet = false;
mDOMInteractiveSet = false;
mDOMContentLoadedEventStartSet = false;
mDOMContentLoadedEventEndSet = false;
mDOMCompleteSet = false;
mDocShellHasBeenActiveSinceNavigationStart = false;
}
@ -60,20 +54,15 @@ nsDOMNavigationTiming::TimeStampToDOM(TimeStamp aStamp) const
return 0;
}
TimeDuration duration = aStamp - mNavigationStartTimeStamp;
TimeDuration duration = aStamp - mNavigationStart;
return GetNavigationStart() + static_cast<int64_t>(duration.ToMilliseconds());
}
DOMTimeMilliSec nsDOMNavigationTiming::DurationFromStart()
{
return TimeStampToDOM(TimeStamp::Now());
}
void
nsDOMNavigationTiming::NotifyNavigationStart(DocShellState aDocShellState)
{
mNavigationStartHighRes = (double)PR_Now() / PR_USEC_PER_MSEC;
mNavigationStartTimeStamp = TimeStamp::Now();
mNavigationStart = TimeStamp::Now();
mDocShellHasBeenActiveSinceNavigationStart = (aDocShellState == DocShellState::eActive);
}
@ -89,7 +78,7 @@ nsDOMNavigationTiming::NotifyFetchStart(nsIURI* aURI, Type aNavigationType)
void
nsDOMNavigationTiming::NotifyBeforeUnload()
{
mBeforeUnloadStart = DurationFromStart();
mBeforeUnloadStart = TimeStamp::Now();
}
void
@ -102,105 +91,107 @@ nsDOMNavigationTiming::NotifyUnloadAccepted(nsIURI* aOldURI)
void
nsDOMNavigationTiming::NotifyUnloadEventStart()
{
mUnloadStart = DurationFromStart();
mUnloadStart = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyUnloadEventEnd()
{
mUnloadEnd = DurationFromStart();
mUnloadEnd = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyLoadEventStart()
{
if (!mLoadEventStartSet) {
mLoadEventStart = DurationFromStart();
mLoadEventStartSet = true;
if (!mLoadEventStart.IsNull()) {
return;
}
mLoadEventStart = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyLoadEventEnd()
{
if (!mLoadEventEndSet) {
mLoadEventEnd = DurationFromStart();
mLoadEventEndSet = true;
if (!mLoadEventEnd.IsNull()) {
return;
}
mLoadEventEnd = TimeStamp::Now();
}
void
nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, TimeStamp aValue)
{
if (!mDOMLoadingSet) {
mLoadedURI = aURI;
mDOMLoading = TimeStampToDOM(aValue);
mDOMLoadingSet = true;
if (!mDOMLoading.IsNull()) {
return;
}
mLoadedURI = aURI;
mDOMLoading = aValue;
}
void
nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI)
{
if (!mDOMLoadingSet) {
mLoadedURI = aURI;
mDOMLoading = DurationFromStart();
mDOMLoadingSet = true;
if (!mDOMLoading.IsNull()) {
return;
}
mLoadedURI = aURI;
mDOMLoading = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI* aURI)
{
if (!mDOMInteractiveSet) {
mLoadedURI = aURI;
mDOMInteractive = DurationFromStart();
mDOMInteractiveSet = true;
if (!mDOMInteractive.IsNull()) {
return;
}
mLoadedURI = aURI;
mDOMInteractive = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyDOMComplete(nsIURI* aURI)
{
if (!mDOMCompleteSet) {
mLoadedURI = aURI;
mDOMComplete = DurationFromStart();
mDOMCompleteSet = true;
if (!mDOMComplete.IsNull()) {
return;
}
mLoadedURI = aURI;
mDOMComplete = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI)
{
if (!mDOMContentLoadedEventStartSet) {
mLoadedURI = aURI;
mDOMContentLoadedEventStart = DurationFromStart();
mDOMContentLoadedEventStartSet = true;
if (!mDOMContentLoadedEventStart.IsNull()) {
return;
}
mLoadedURI = aURI;
mDOMContentLoadedEventStart = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI)
{
if (!mDOMContentLoadedEventEndSet) {
mLoadedURI = aURI;
mDOMContentLoadedEventEnd = DurationFromStart();
mDOMContentLoadedEventEndSet = true;
if (!mDOMContentLoadedEventEnd.IsNull()) {
return;
}
mLoadedURI = aURI;
mDOMContentLoadedEventEnd = TimeStamp::Now();
}
void
nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mNavigationStartTimeStamp.IsNull());
MOZ_ASSERT(!mNavigationStart.IsNull());
if (!mNonBlankPaintTimeStamp.IsNull()) {
if (!mNonBlankPaint.IsNull()) {
return;
}
mNonBlankPaintTimeStamp = TimeStamp::Now();
TimeDuration elapsed = mNonBlankPaintTimeStamp - mNavigationStartTimeStamp;
mNonBlankPaint = TimeStamp::Now();
TimeDuration elapsed = mNonBlankPaint - mNavigationStart;
if (profiler_is_active()) {
nsAutoCString spec;
@ -215,8 +206,8 @@ nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument()
if (mDocShellHasBeenActiveSinceNavigationStart) {
Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_NON_BLANK_PAINT_MS,
mNavigationStartTimeStamp,
mNonBlankPaintTimeStamp);
mNavigationStart,
mNonBlankPaint);
}
}
@ -227,24 +218,24 @@ nsDOMNavigationTiming::NotifyDocShellStateChanged(DocShellState aDocShellState)
(aDocShellState == DocShellState::eActive);
}
DOMTimeMilliSec
nsDOMNavigationTiming::GetUnloadEventStart()
mozilla::TimeStamp
nsDOMNavigationTiming::GetUnloadEventStartTimeStamp() const
{
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
if (NS_SUCCEEDED(rv)) {
return mUnloadStart;
}
return 0;
return mozilla::TimeStamp();
}
DOMTimeMilliSec
nsDOMNavigationTiming::GetUnloadEventEnd()
mozilla::TimeStamp
nsDOMNavigationTiming::GetUnloadEventEndTimeStamp() const
{
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
if (NS_SUCCEEDED(rv)) {
return mUnloadEnd;
}
return 0;
return mozilla::TimeStamp();
}

View file

@ -47,38 +47,91 @@ public:
mozilla::TimeStamp GetNavigationStartTimeStamp() const
{
return mNavigationStartTimeStamp;
return mNavigationStart;
}
DOMTimeMilliSec GetUnloadEventStart()
{
return TimeStampToDOM(GetUnloadEventStartTimeStamp());
}
DOMTimeMilliSec GetUnloadEventEnd()
{
return TimeStampToDOM(GetUnloadEventEndTimeStamp());
}
DOMTimeMilliSec GetUnloadEventStart();
DOMTimeMilliSec GetUnloadEventEnd();
DOMTimeMilliSec GetDomLoading() const
{
return mDOMLoading;
return TimeStampToDOM(mDOMLoading);
}
DOMTimeMilliSec GetDomInteractive() const
{
return mDOMInteractive;
return TimeStampToDOM(mDOMInteractive);
}
DOMTimeMilliSec GetDomContentLoadedEventStart() const
{
return mDOMContentLoadedEventStart;
return TimeStampToDOM(mDOMContentLoadedEventStart);
}
DOMTimeMilliSec GetDomContentLoadedEventEnd() const
{
return mDOMContentLoadedEventEnd;
return TimeStampToDOM(mDOMContentLoadedEventEnd);
}
DOMTimeMilliSec GetDomComplete() const
{
return mDOMComplete;
return TimeStampToDOM(mDOMComplete);
}
DOMTimeMilliSec GetLoadEventStart() const
{
return mLoadEventStart;
return TimeStampToDOM(mLoadEventStart);
}
DOMTimeMilliSec GetLoadEventEnd() const
{
return mLoadEventEnd;
return TimeStampToDOM(mLoadEventEnd);
}
DOMTimeMilliSec GetTimeToNonBlankPaint() const
{
return TimeStampToDOM(mNonBlankPaint);
}
DOMHighResTimeStamp GetUnloadEventStartHighRes()
{
mozilla::TimeStamp stamp = GetUnloadEventStartTimeStamp();
if (stamp.IsNull()) {
return 0;
}
return TimeStampToDOMHighRes(stamp);
}
DOMHighResTimeStamp GetUnloadEventEndHighRes()
{
mozilla::TimeStamp stamp = GetUnloadEventEndTimeStamp();
if (stamp.IsNull()) {
return 0;
}
return TimeStampToDOMHighRes(stamp);
}
DOMHighResTimeStamp GetDomInteractiveHighRes() const
{
return TimeStampToDOMHighRes(mDOMInteractive);
}
DOMHighResTimeStamp GetDomContentLoadedEventStartHighRes() const
{
return TimeStampToDOMHighRes(mDOMContentLoadedEventStart);
}
DOMHighResTimeStamp GetDomContentLoadedEventEndHighRes() const
{
return TimeStampToDOMHighRes(mDOMContentLoadedEventEnd);
}
DOMHighResTimeStamp GetDomCompleteHighRes() const
{
return TimeStampToDOMHighRes(mDOMComplete);
}
DOMHighResTimeStamp GetLoadEventStartHighRes() const
{
return TimeStampToDOMHighRes(mLoadEventStart);
}
DOMHighResTimeStamp GetLoadEventEndHighRes() const
{
return TimeStampToDOMHighRes(mLoadEventEnd);
}
enum class DocShellState : uint8_t {
@ -108,9 +161,13 @@ public:
DOMTimeMilliSec TimeStampToDOM(mozilla::TimeStamp aStamp) const;
inline DOMHighResTimeStamp TimeStampToDOMHighRes(mozilla::TimeStamp aStamp)
inline DOMHighResTimeStamp TimeStampToDOMHighRes(mozilla::TimeStamp aStamp) const
{
mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp;
MOZ_ASSERT(!aStamp.IsNull(), "The timestamp should not be null");
if (aStamp.IsNull()) {
return 0;
}
mozilla::TimeDuration duration = aStamp - mNavigationStart;
return duration.ToMilliseconds();
}
@ -120,37 +177,29 @@ private:
void Clear();
mozilla::TimeStamp GetUnloadEventStartTimeStamp() const;
mozilla::TimeStamp GetUnloadEventEndTimeStamp() const;
nsCOMPtr<nsIURI> mUnloadedURI;
nsCOMPtr<nsIURI> mLoadedURI;
Type mNavigationType;
DOMHighResTimeStamp mNavigationStartHighRes;
mozilla::TimeStamp mNavigationStartTimeStamp;
mozilla::TimeStamp mNonBlankPaintTimeStamp;
DOMTimeMilliSec DurationFromStart();
mozilla::TimeStamp mNavigationStart;
mozilla::TimeStamp mNonBlankPaint;
DOMTimeMilliSec mBeforeUnloadStart;
DOMTimeMilliSec mUnloadStart;
DOMTimeMilliSec mUnloadEnd;
DOMTimeMilliSec mLoadEventStart;
DOMTimeMilliSec mLoadEventEnd;
mozilla::TimeStamp mBeforeUnloadStart;
mozilla::TimeStamp mUnloadStart;
mozilla::TimeStamp mUnloadEnd;
mozilla::TimeStamp mLoadEventStart;
mozilla::TimeStamp mLoadEventEnd;
DOMTimeMilliSec mDOMLoading;
DOMTimeMilliSec mDOMInteractive;
DOMTimeMilliSec mDOMContentLoadedEventStart;
DOMTimeMilliSec mDOMContentLoadedEventEnd;
DOMTimeMilliSec mDOMComplete;
mozilla::TimeStamp mDOMLoading;
mozilla::TimeStamp mDOMInteractive;
mozilla::TimeStamp mDOMContentLoadedEventStart;
mozilla::TimeStamp mDOMContentLoadedEventEnd;
mozilla::TimeStamp mDOMComplete;
// Booleans to keep track of what things we've already been notified
// about. We don't update those once we've been notified about them
// once.
bool mLoadEventStartSet : 1;
bool mLoadEventEndSet : 1;
bool mDOMLoadingSet : 1;
bool mDOMInteractiveSet : 1;
bool mDOMContentLoadedEventStartSet : 1;
bool mDOMContentLoadedEventEndSet : 1;
bool mDOMCompleteSet : 1;
bool mDocShellHasBeenActiveSinceNavigationStart : 1;
};

View file

@ -1069,6 +1069,20 @@ class CGHeaders(CGWrapper):
if parent:
ancestors.append(parent)
interfaceDeps.extend(ancestors)
# Include parent interface headers needed for jsonifier code.
jsonInterfaceParents = []
for desc in descriptors:
if not desc.operations['Jsonifier']:
continue
parent = desc.interface.parent
while parent:
parentDesc = desc.getDescriptor(parent.identifier.name)
if parentDesc.operations['Jsonifier']:
jsonInterfaceParents.append(parentDesc.interface)
parent = parent.parent
interfaceDeps.extend(jsonInterfaceParents)
bindingIncludes = set(self.getDeclarationFilename(d) for d in interfaceDeps)
# Grab all the implementation declaration files we need.

View file

@ -20,6 +20,7 @@
#include "mozilla/dom/PerformanceEntryEvent.h"
#include "mozilla/dom/PerformanceNavigationBinding.h"
#include "mozilla/dom/PerformanceObserverBinding.h"
#include "mozilla/dom/PerformanceNavigationTiming.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Preferences.h"
#include "mozilla/TimerClamping.h"

View file

@ -54,14 +54,14 @@ public:
JSObject* WrapObject(JSContext *cx,
JS::Handle<JSObject*> aGivenProto) override;
void GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval);
virtual void GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval);
void GetEntriesByType(const nsAString& aEntryType,
nsTArray<RefPtr<PerformanceEntry>>& aRetval);
virtual void GetEntriesByType(const nsAString& aEntryType,
nsTArray<RefPtr<PerformanceEntry>>& aRetval);
void GetEntriesByName(const nsAString& aName,
const Optional<nsAString>& aEntryType,
nsTArray<RefPtr<PerformanceEntry>>& aRetval);
virtual void GetEntriesByName(const nsAString& aName,
const Optional<nsAString>& aEntryType,
nsTArray<RefPtr<PerformanceEntry>>& aRetval);
virtual void AddEntry(nsIHttpChannel* channel,
nsITimedChannel* timedChannel) = 0;
@ -153,7 +153,7 @@ protected:
nsTObserverArray<PerformanceObserver*> mObservers;
private:
protected:
nsTArray<RefPtr<PerformanceEntry>> mUserEntries;
nsTArray<RefPtr<PerformanceEntry>> mResourceEntries;

View file

@ -16,7 +16,8 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceMainThread)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PerformanceMainThread,
Performance)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTiming,
mNavigation)
mNavigation,
mDocEntry)
tmp->mMozMemory = nullptr;
mozilla::DropJSObjects(this);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -24,7 +25,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PerformanceMainThread,
Performance)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTiming,
mNavigation)
mNavigation,
mDocEntry)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -152,38 +154,7 @@ PerformanceMainThread::AddEntry(nsIHttpChannel* channel,
// The PerformanceResourceTiming object will use the PerformanceTiming
// object to get all the required timings.
RefPtr<PerformanceResourceTiming> performanceEntry =
new PerformanceResourceTiming(performanceTiming, this, entryName);
nsAutoCString protocol;
channel->GetProtocolVersion(protocol);
// If this is a local fetch, nextHopProtocol should be set to empty string.
nsCOMPtr<nsICacheInfoChannel> cachedChannel = do_QueryInterface(channel);
if (cachedChannel) {
bool isFromCache;
if (NS_SUCCEEDED(cachedChannel->IsFromCache(&isFromCache))
&& isFromCache) {
protocol.Truncate();
}
}
performanceEntry->SetNextHopProtocol(NS_ConvertUTF8toUTF16(protocol));
uint64_t encodedBodySize = 0;
channel->GetEncodedBodySize(&encodedBodySize);
performanceEntry->SetEncodedBodySize(encodedBodySize);
uint64_t transferSize = 0;
channel->GetTransferSize(&transferSize);
performanceEntry->SetTransferSize(transferSize);
uint64_t decodedBodySize = 0;
channel->GetDecodedBodySize(&decodedBodySize);
if (decodedBodySize == 0) {
decodedBodySize = encodedBodySize;
}
performanceEntry->SetDecodedBodySize(decodedBodySize);
new PerformanceResourceTiming(performanceTiming, this, entryName, channel);
// If the initiator type had no valid value, then set it to the default
// ("other") value.
if (initiatorType.IsEmpty()) {
@ -337,5 +308,65 @@ PerformanceMainThread::CreationTime() const
return GetDOMTiming()->GetNavigationStart();
}
void
PerformanceMainThread::EnsureDocEntry()
{
if (!mDocEntry && nsContentUtils::IsPerformanceNavigationTimingEnabled()) {
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
RefPtr<PerformanceTiming> timing =
new PerformanceTiming(this, mChannel, nullptr, 0);
mDocEntry = new PerformanceNavigationTiming(timing, this,
httpChannel);
}
}
void
PerformanceMainThread::GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval)
{
aRetval = mResourceEntries;
aRetval.AppendElements(mUserEntries);
EnsureDocEntry();
if (mDocEntry) {
aRetval.AppendElement(mDocEntry);
}
aRetval.Sort(PerformanceEntryComparator());
}
void
PerformanceMainThread::GetEntriesByType(const nsAString& aEntryType,
nsTArray<RefPtr<PerformanceEntry>>& aRetval)
{
if (aEntryType.EqualsLiteral("navigation")) {
aRetval.Clear();
EnsureDocEntry();
if (mDocEntry) {
aRetval.AppendElement(mDocEntry);
}
return;
}
Performance::GetEntriesByType(aEntryType, aRetval);
}
void
PerformanceMainThread::GetEntriesByName(const nsAString& aName,
const Optional<nsAString>& aEntryType,
nsTArray<RefPtr<PerformanceEntry>>& aRetval)
{
if (aName.EqualsLiteral("document")) {
aRetval.Clear();
EnsureDocEntry();
if (mDocEntry) {
aRetval.AppendElement(mDocEntry);
}
return;
}
Performance::GetEntriesByName(aName, aEntryType, aRetval);
}
} // dom namespace
} // mozilla namespace

View file

@ -47,6 +47,15 @@ public:
return mChannel;
}
// The GetEntries* methods need to be overriden in order to add the
// the document entry of type navigation.
virtual void GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval) override;
virtual void GetEntriesByType(const nsAString& aEntryType,
nsTArray<RefPtr<PerformanceEntry>>& aRetval) override;
virtual void GetEntriesByName(const nsAString& aName,
const Optional<nsAString>& aEntryType,
nsTArray<RefPtr<PerformanceEntry>>& aRetval) override;
protected:
~PerformanceMainThread();
@ -63,7 +72,9 @@ protected:
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
void DispatchBufferFullEvent() override;
void EnsureDocEntry();
RefPtr<PerformanceEntry> mDocEntry;
RefPtr<nsDOMNavigationTiming> mDOMTiming;
nsCOMPtr<nsITimedChannel> mChannel;
RefPtr<PerformanceTiming> mTiming;

View file

@ -0,0 +1,96 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/PerformanceNavigationTiming.h"
#include "mozilla/dom/PerformanceNavigationTimingBinding.h"
using namespace mozilla::dom;
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceNavigationTiming)
NS_INTERFACE_MAP_END_INHERITING(PerformanceResourceTiming)
NS_IMPL_ADDREF_INHERITED(PerformanceNavigationTiming, PerformanceResourceTiming)
NS_IMPL_RELEASE_INHERITED(PerformanceNavigationTiming, PerformanceResourceTiming)
JSObject*
PerformanceNavigationTiming::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return PerformanceNavigationTimingBinding::Wrap(aCx, this, aGivenProto);
}
DOMHighResTimeStamp
PerformanceNavigationTiming::UnloadEventStart() const
{
return mTiming->GetDOMTiming()->GetUnloadEventStartHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::UnloadEventEnd() const
{
return mTiming->GetDOMTiming()->GetUnloadEventEndHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::DomInteractive() const
{
return mTiming->GetDOMTiming()->GetDomInteractiveHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::DomContentLoadedEventStart() const
{
return mTiming->GetDOMTiming()->GetDomContentLoadedEventStartHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::DomContentLoadedEventEnd() const
{
return mTiming->GetDOMTiming()->GetDomContentLoadedEventEndHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::DomComplete() const
{
return mTiming->GetDOMTiming()->GetDomCompleteHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::LoadEventStart() const
{
return mTiming->GetDOMTiming()->GetLoadEventStartHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::LoadEventEnd() const
{
return mTiming->GetDOMTiming()->GetLoadEventEndHighRes();
}
NavigationType
PerformanceNavigationTiming::Type() const
{
switch(mTiming->GetDOMTiming()->GetType()) {
case nsDOMNavigationTiming::TYPE_NAVIGATE:
return NavigationType::Navigate;
break;
case nsDOMNavigationTiming::TYPE_RELOAD:
return NavigationType::Reload;
break;
case nsDOMNavigationTiming::TYPE_BACK_FORWARD:
return NavigationType::Back_forward;
break;
default:
// The type is TYPE_RESERVED or some other value that was later added.
// We fallback to the default of Navigate.
return NavigationType::Navigate;
}
}
uint16_t
PerformanceNavigationTiming::RedirectCount() const
{
return mTiming->GetRedirectCount();
}

View file

@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_PerformanceNavigationTiming_h___
#define mozilla_dom_PerformanceNavigationTiming_h___
#include "nsCOMPtr.h"
#include "nsIChannel.h"
#include "nsITimedChannel.h"
#include "mozilla/dom/PerformanceResourceTiming.h"
#include "mozilla/dom/PerformanceNavigationTimingBinding.h"
#include "nsIHttpChannel.h"
namespace mozilla {
namespace dom {
// https://www.w3.org/TR/navigation-timing-2/#sec-PerformanceNavigationTiming
class PerformanceNavigationTiming final
: public PerformanceResourceTiming
{
public:
NS_DECL_ISUPPORTS_INHERITED
// Note that aPerformanceTiming must be initalized with zeroTime = 0
// so that timestamps are relative to startTime, as opposed to the
// performance.timing object for which timestamps are absolute and has a
// zeroTime initialized to navigationStart
explicit PerformanceNavigationTiming(PerformanceTiming* aPerformanceTiming,
Performance* aPerformance,
nsIHttpChannel* aChannel)
: PerformanceResourceTiming(aPerformanceTiming, aPerformance,
NS_LITERAL_STRING("document"), aChannel) {
SetEntryType(NS_LITERAL_STRING("navigation"));
SetInitiatorType(NS_LITERAL_STRING("navigation"));
}
DOMHighResTimeStamp Duration() const override
{
return LoadEventEnd() - StartTime();
}
DOMHighResTimeStamp StartTime() const override
{
return 0;
}
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
DOMHighResTimeStamp UnloadEventStart() const;
DOMHighResTimeStamp UnloadEventEnd() const;
DOMHighResTimeStamp DomInteractive() const;
DOMHighResTimeStamp DomContentLoadedEventStart() const;
DOMHighResTimeStamp DomContentLoadedEventEnd() const;
DOMHighResTimeStamp DomComplete() const;
DOMHighResTimeStamp LoadEventStart() const;
DOMHighResTimeStamp LoadEventEnd() const;
NavigationType Type() const;
uint16_t RedirectCount() const;
private:
~PerformanceNavigationTiming() {}
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PerformanceNavigationTiming_h___

View file

@ -25,7 +25,8 @@ NS_IMPL_RELEASE_INHERITED(PerformanceResourceTiming, PerformanceEntry)
PerformanceResourceTiming::PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming,
Performance* aPerformance,
const nsAString& aName)
const nsAString& aName,
nsIHttpChannel* aChannel)
: PerformanceEntry(aPerformance, aName, NS_LITERAL_STRING("resource")),
mTiming(aPerformanceTiming),
mEncodedBodySize(0),
@ -33,6 +34,34 @@ PerformanceResourceTiming::PerformanceResourceTiming(PerformanceTiming* aPerform
mDecodedBodySize(0)
{
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
SetPropertiesFromChannel(aChannel);
}
void
PerformanceResourceTiming::SetPropertiesFromChannel(nsIHttpChannel* aChannel)
{
if (!aChannel) {
return;
}
nsAutoCString protocol;
Unused << aChannel->GetProtocolVersion(protocol);
SetNextHopProtocol(NS_ConvertUTF8toUTF16(protocol));
uint64_t encodedBodySize = 0;
Unused << aChannel->GetEncodedBodySize(&encodedBodySize);
SetEncodedBodySize(encodedBodySize);
uint64_t transferSize = 0;
Unused << aChannel->GetTransferSize(&transferSize);
SetTransferSize(transferSize);
uint64_t decodedBodySize = 0;
Unused << aChannel->GetDecodedBodySize(&decodedBodySize);
if (decodedBodySize == 0) {
decodedBodySize = encodedBodySize;
}
SetDecodedBodySize(decodedBodySize);
}
PerformanceResourceTiming::~PerformanceResourceTiming()

View file

@ -18,7 +18,7 @@ namespace mozilla {
namespace dom {
// http://www.w3.org/TR/resource-timing/#performanceresourcetiming
class PerformanceResourceTiming final : public PerformanceEntry
class PerformanceResourceTiming : public PerformanceEntry
{
public:
typedef mozilla::TimeStamp TimeStamp;
@ -30,7 +30,8 @@ public:
PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming,
Performance* aPerformance,
const nsAString& aName);
const nsAString& aName,
nsIHttpChannel* aChannel = nullptr);
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
@ -176,6 +177,7 @@ public:
protected:
virtual ~PerformanceResourceTiming();
void SetPropertiesFromChannel(nsIHttpChannel* aChannel);
nsString mInitiatorType;
nsString mNextHopProtocol;

View file

@ -242,6 +242,14 @@ public:
return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetLoadEventEnd());
}
DOMTimeMilliSec TimeToNonBlankPaint() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
return 0;
}
return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetTimeToNonBlankPaint());
}
private:
~PerformanceTiming();

View file

@ -10,6 +10,7 @@ EXPORTS.mozilla.dom += [
'PerformanceMark.h',
'PerformanceMeasure.h',
'PerformanceNavigation.h',
'PerformanceNavigationTiming.h',
'PerformanceObserver.h',
'PerformanceObserverEntryList.h',
'PerformanceResourceTiming.h',
@ -24,6 +25,7 @@ UNIFIED_SOURCES += [
'PerformanceMark.cpp',
'PerformanceMeasure.cpp',
'PerformanceNavigation.cpp',
'PerformanceNavigationTiming.cpp',
'PerformanceObserver.cpp',
'PerformanceObserverEntryList.cpp',
'PerformanceResourceTiming.cpp',

View file

@ -751,9 +751,11 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceNavigation",
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceObserver",
"PerformanceNavigationTiming",
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceObserverEntryList",
"PerformanceObserver"
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceObserverEntryList"
// IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceResourceTiming",
// IMPORTANT: Do not change this list without review from a DOM peer!

View file

@ -0,0 +1,33 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* https://www.w3.org/TR/navigation-timing-2/#sec-PerformanceNavigationTiming
*
* Copyright © 2016 W3C® (MIT, ERCIM, Keio, Beihang).
* W3C liability, trademark and document use rules apply.
*/
enum NavigationType {
"navigate",
"reload",
"back_forward",
"prerender"
};
interface PerformanceNavigationTiming : PerformanceResourceTiming {
readonly attribute DOMHighResTimeStamp unloadEventStart;
readonly attribute DOMHighResTimeStamp unloadEventEnd;
readonly attribute DOMHighResTimeStamp domInteractive;
readonly attribute DOMHighResTimeStamp domContentLoadedEventStart;
readonly attribute DOMHighResTimeStamp domContentLoadedEventEnd;
readonly attribute DOMHighResTimeStamp domComplete;
readonly attribute DOMHighResTimeStamp loadEventStart;
readonly attribute DOMHighResTimeStamp loadEventEnd;
readonly attribute NavigationType type;
readonly attribute unsigned short redirectCount;
jsonifier;
};

View file

@ -33,5 +33,11 @@ interface PerformanceTiming {
readonly attribute unsigned long long loadEventStart;
readonly attribute unsigned long long loadEventEnd;
// This is a Chrome proprietary extension and not part of the
// performance/navigation timing specification.
// Returns 0 if a non-blank paint has not happened.
[Pref="dom.performance.time_to_non_blank_paint.enabled"]
readonly attribute unsigned long long timeToNonBlankPaint;
jsonifier;
};

View file

@ -347,6 +347,7 @@ WEBIDL_FILES = [
'PerformanceMark.webidl',
'PerformanceMeasure.webidl',
'PerformanceNavigation.webidl',
'PerformanceNavigationTiming.webidl',
'PerformanceObserver.webidl',
'PerformanceObserverEntryList.webidl',
'PerformanceResourceTiming.webidl',

View file

@ -183,6 +183,9 @@ pref("dom.enable_resource_timing", true);
// Enable high-resolution timing markers for users
pref("dom.enable_user_timing", true);
// Whether performance.GetEntries* will contain an entry for the active document
pref("dom.enable_performance_navigation_timing", true);
// Enable printing performance marks/measures to log
pref("dom.performance.enable_user_timing_logging", false);
@ -192,6 +195,9 @@ pref("dom.performance.enable_notify_performance_timing", false);
// Enable Permission API's .revoke() method
pref("dom.permissions.revoke.enable", false);
// Enable exposing timeToNonBlankPaint
pref("dom.performance.time_to_non_blank_paint.enabled", false);
// Enable Performance Observer API
#ifdef NIGHTLY_BUILD
pref("dom.enable_performance_observer", true);