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

@ -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',