summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dom/base/nsGlobalWindow.cpp9
-rw-r--r--dom/base/nsPIDOMWindow.h2
-rw-r--r--dom/performance/Performance.h2
-rw-r--r--dom/performance/PerformanceMainThread.cpp70
-rw-r--r--dom/performance/PerformanceMainThread.h5
-rw-r--r--dom/performance/PerformanceNavigation.cpp2
-rw-r--r--dom/performance/PerformanceNavigationTiming.cpp20
-rw-r--r--dom/performance/PerformanceNavigationTiming.h16
-rw-r--r--dom/performance/PerformanceResourceTiming.cpp49
-rw-r--r--dom/performance/PerformanceResourceTiming.h99
-rwxr-xr-xdom/performance/PerformanceTiming.cpp255
-rwxr-xr-xdom/performance/PerformanceTiming.h288
-rw-r--r--dom/performance/PerformanceWorker.h5
-rw-r--r--layout/base/nsDocumentViewer.cpp5
14 files changed, 484 insertions, 343 deletions
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index ae84de3a19..a69b5e177a 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4223,6 +4223,15 @@ nsGlobalWindow::GetPerformance()
}
void
+nsPIDOMWindowInner::QueuePerformanceNavigationTiming()
+{
+ CreatePerformanceObjectIfNeeded();
+ if (mPerformance) {
+ mPerformance->QueueNavigationTimingEntry();
+ }
+}
+
+void
nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded()
{
MOZ_ASSERT(IsInnerWindow());
diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h
index ffebf6570d..110da38604 100644
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -727,6 +727,8 @@ public:
mozilla::dom::Performance* GetPerformance();
+ void QueuePerformanceNavigationTiming();
+
bool HasMutationListeners(uint32_t aMutationEventType) const
{
if (!mOuterWindow) {
diff --git a/dom/performance/Performance.h b/dom/performance/Performance.h
index 7a60eb85a9..2e1b63c45b 100644
--- a/dom/performance/Performance.h
+++ b/dom/performance/Performance.h
@@ -124,6 +124,8 @@ public:
return false;
}
+ virtual void QueueNavigationTimingEntry() = 0;
+
protected:
Performance();
explicit Performance(nsPIDOMWindowInner* aWindow);
diff --git a/dom/performance/PerformanceMainThread.cpp b/dom/performance/PerformanceMainThread.cpp
index a4dbf88799..b5ca6ca1be 100644
--- a/dom/performance/PerformanceMainThread.cpp
+++ b/dom/performance/PerformanceMainThread.cpp
@@ -15,6 +15,34 @@
namespace mozilla {
namespace dom {
+namespace {
+
+void
+GetURLSpecFromChannel(nsITimedChannel* aChannel, nsAString& aSpec)
+{
+ aSpec.AssignLiteral("document");
+
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(aChannel);
+ if (!channel) {
+ return;
+ }
+
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = channel->GetURI(getter_AddRefs(uri));
+ if (NS_WARN_IF(NS_FAILED(rv)) || !uri) {
+ return;
+ }
+
+ nsAutoCString spec;
+ rv = uri->GetSpec(spec);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return;
+ }
+
+ aSpec = NS_ConvertUTF8toUTF16(spec);
+}
+
+} // anonymous
NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceMainThread)
@@ -60,6 +88,7 @@ PerformanceMainThread::PerformanceMainThread(nsPIDOMWindowInner* aWindow,
, mChannel(aChannel)
{
MOZ_ASSERT(aWindow, "Parent window object should be provided");
+ CreateNavigationTimingEntry();
}
PerformanceMainThread::~PerformanceMainThread()
@@ -159,14 +188,14 @@ PerformanceMainThread::AddEntry(nsIHttpChannel* channel,
// The last argument is the "zero time" (offset). Since we don't want
// any offset for the resource timing, this will be set to "0" - the
// resource timing returns a relative timing (no offset).
- RefPtr<PerformanceTiming> performanceTiming =
- new PerformanceTiming(this, timedChannel, channel,
- 0);
+ UniquePtr<PerformanceTimingData> performanceTimingData(
+ new PerformanceTimingData(timedChannel, channel, 0));
// The PerformanceResourceTiming object will use the PerformanceTiming
// object to get all the required timings.
RefPtr<PerformanceResourceTiming> performanceEntry =
- new PerformanceResourceTiming(performanceTiming, this, entryName, channel);
+ new PerformanceResourceTiming(std::move(performanceTimingData), this, entryName);
+
// If the initiator type had no valid value, then set it to the default
// ("other") value.
if (initiatorType.IsEmpty()) {
@@ -299,17 +328,31 @@ PerformanceMainThread::CreationTime() const
}
void
-PerformanceMainThread::EnsureDocEntry()
+PerformanceMainThread::CreateNavigationTimingEntry()
{
- 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);
+ MOZ_ASSERT(!mDocEntry, "mDocEntry should be null.");
+
+ nsAutoString name;
+ GetURLSpecFromChannel(mChannel, name);
+
+ UniquePtr<PerformanceTimingData> timing(
+ new PerformanceTimingData(mChannel, nullptr, 0));
+
+ nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
+ if (httpChannel) {
+ timing->SetPropertiesFromHttpChannel(httpChannel, mChannel);
}
+
+ mDocEntry = new PerformanceNavigationTiming(std::move(timing), this, name);
}
+void
+PerformanceMainThread::QueueNavigationTimingEntry()
+{
+ if (mDocEntry) {
+ QueueEntry(mDocEntry);
+ }
+}
void
PerformanceMainThread::GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval)
@@ -317,7 +360,6 @@ PerformanceMainThread::GetEntries(nsTArray<RefPtr<PerformanceEntry>>& aRetval)
aRetval = mResourceEntries;
aRetval.AppendElements(mUserEntries);
- EnsureDocEntry();
if (mDocEntry) {
aRetval.AppendElement(mDocEntry);
}
@@ -331,7 +373,7 @@ PerformanceMainThread::GetEntriesByType(const nsAString& aEntryType,
{
if (aEntryType.EqualsLiteral("navigation")) {
aRetval.Clear();
- EnsureDocEntry();
+
if (mDocEntry) {
aRetval.AppendElement(mDocEntry);
}
@@ -348,7 +390,7 @@ PerformanceMainThread::GetEntriesByName(const nsAString& aName,
{
if (aName.EqualsLiteral("document")) {
aRetval.Clear();
- EnsureDocEntry();
+
if (mDocEntry) {
aRetval.AppendElement(mDocEntry);
}
diff --git a/dom/performance/PerformanceMainThread.h b/dom/performance/PerformanceMainThread.h
index 702483e9de..fc81c94e2a 100644
--- a/dom/performance/PerformanceMainThread.h
+++ b/dom/performance/PerformanceMainThread.h
@@ -62,9 +62,13 @@ public:
return true;
}
+ void QueueNavigationTimingEntry() override;
+
protected:
~PerformanceMainThread();
+ void CreateNavigationTimingEntry();
+
nsISupports* GetAsISupports() override
{
return this;
@@ -76,7 +80,6 @@ protected:
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
void DispatchBufferFullEvent() override;
- void EnsureDocEntry();
RefPtr<PerformanceEntry> mDocEntry;
RefPtr<nsDOMNavigationTiming> mDOMTiming;
diff --git a/dom/performance/PerformanceNavigation.cpp b/dom/performance/PerformanceNavigation.cpp
index 24b3af11f8..1b96de1cf4 100644
--- a/dom/performance/PerformanceNavigation.cpp
+++ b/dom/performance/PerformanceNavigation.cpp
@@ -35,7 +35,7 @@ PerformanceNavigation::WrapObject(JSContext *cx,
uint16_t
PerformanceNavigation::RedirectCount() const
{
- return GetPerformanceTiming()->GetRedirectCount();
+ return GetPerformanceTiming()->Data()->GetRedirectCount();
}
} // dom namespace
diff --git a/dom/performance/PerformanceNavigationTiming.cpp b/dom/performance/PerformanceNavigationTiming.cpp
index 37d54366c6..1c4a30b569 100644
--- a/dom/performance/PerformanceNavigationTiming.cpp
+++ b/dom/performance/PerformanceNavigationTiming.cpp
@@ -24,55 +24,55 @@ PerformanceNavigationTiming::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aG
DOMHighResTimeStamp
PerformanceNavigationTiming::UnloadEventStart() const
{
- return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetUnloadEventStartHighRes());
+ return mPerformance->GetDOMTiming()->GetUnloadEventStartHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::UnloadEventEnd() const
{
- return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetUnloadEventEndHighRes());
+ return mPerformance->GetDOMTiming()->GetUnloadEventEndHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::DomInteractive() const
{
- return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomInteractiveHighRes());
+ return mPerformance->GetDOMTiming()->GetDomInteractiveHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::DomContentLoadedEventStart() const
{
- return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomContentLoadedEventStartHighRes());
+ return mPerformance->GetDOMTiming()->GetDomContentLoadedEventStartHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::DomContentLoadedEventEnd() const
{
- return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomContentLoadedEventEndHighRes());
+ return mPerformance->GetDOMTiming()->GetDomContentLoadedEventEndHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::DomComplete() const
{
- return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomCompleteHighRes());
+ return mPerformance->GetDOMTiming()->GetDomCompleteHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::LoadEventStart() const
{
- return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetLoadEventStartHighRes());
+ return mPerformance->GetDOMTiming()->GetLoadEventStartHighRes();
}
DOMHighResTimeStamp
PerformanceNavigationTiming::LoadEventEnd() const
{
- return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetLoadEventEndHighRes());
+ return mPerformance->GetDOMTiming()->GetLoadEventEndHighRes();
}
NavigationType
PerformanceNavigationTiming::Type() const
{
- switch(mTiming->GetDOMTiming()->GetType()) {
+ switch(mPerformance->GetDOMTiming()->GetType()) {
case nsDOMNavigationTiming::TYPE_NAVIGATE:
return NavigationType::Navigate;
break;
@@ -92,5 +92,5 @@ PerformanceNavigationTiming::Type() const
uint16_t
PerformanceNavigationTiming::RedirectCount() const
{
- return mTiming->GetRedirectCount();
+ return mTimingData->GetRedirectCount();
}
diff --git a/dom/performance/PerformanceNavigationTiming.h b/dom/performance/PerformanceNavigationTiming.h
index f528c5337e..93471e17de 100644
--- a/dom/performance/PerformanceNavigationTiming.h
+++ b/dom/performance/PerformanceNavigationTiming.h
@@ -27,14 +27,14 @@ public:
// 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"));
- }
+ PerformanceNavigationTiming(UniquePtr<PerformanceTimingData>&& aPerformanceTiming,
+ Performance* aPerformance,
+ const nsAString& aName)
+ : PerformanceResourceTiming(Move(aPerformanceTiming), aPerformance, aName)
+ {
+ SetEntryType(NS_LITERAL_STRING("navigation"));
+ SetInitiatorType(NS_LITERAL_STRING("navigation"));
+ }
DOMHighResTimeStamp Duration() const override
{
diff --git a/dom/performance/PerformanceResourceTiming.cpp b/dom/performance/PerformanceResourceTiming.cpp
index 6f84896af1..cb08b39b65 100644
--- a/dom/performance/PerformanceResourceTiming.cpp
+++ b/dom/performance/PerformanceResourceTiming.cpp
@@ -11,7 +11,7 @@ using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformanceResourceTiming,
PerformanceEntry,
- mTiming)
+ mPerformance)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceResourceTiming,
PerformanceEntry)
@@ -23,45 +23,14 @@ NS_INTERFACE_MAP_END_INHERITING(PerformanceEntry)
NS_IMPL_ADDREF_INHERITED(PerformanceResourceTiming, PerformanceEntry)
NS_IMPL_RELEASE_INHERITED(PerformanceResourceTiming, PerformanceEntry)
-PerformanceResourceTiming::PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming,
+PerformanceResourceTiming::PerformanceResourceTiming(UniquePtr<PerformanceTimingData>&& aPerformanceTiming,
Performance* aPerformance,
- const nsAString& aName,
- nsIHttpChannel* aChannel)
-: PerformanceEntry(aPerformance, aName, NS_LITERAL_STRING("resource")),
- mTiming(aPerformanceTiming),
- mEncodedBodySize(0),
- mTransferSize(0),
- mDecodedBodySize(0)
+ const nsAString& aName)
+ : PerformanceEntry(aPerformance->GetParentObject(), aName, NS_LITERAL_STRING("resource"))
+ , mTimingData(Move(aPerformanceTiming))
+ , mPerformance(aPerformance)
{
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()
@@ -78,13 +47,13 @@ PerformanceResourceTiming::StartTime() const
// Ignore zero values. The RedirectStart and WorkerStart values
// can come from earlier redirected channels prior to the AsyncOpen
// time being recorded.
- DOMHighResTimeStamp redirect = mTiming->RedirectStartHighRes();
+ DOMHighResTimeStamp redirect = mTimingData->RedirectStartHighRes(mPerformance);
redirect = redirect ? redirect : DBL_MAX;
- DOMHighResTimeStamp worker = mTiming->WorkerStartHighRes();
+ DOMHighResTimeStamp worker = mTimingData->WorkerStartHighRes(mPerformance);
worker = worker ? worker : DBL_MAX;
- DOMHighResTimeStamp asyncOpen = mTiming->AsyncOpenHighRes();
+ DOMHighResTimeStamp asyncOpen = mTimingData->AsyncOpenHighRes(mPerformance);
return std::min(asyncOpen, std::min(redirect, worker));
}
diff --git a/dom/performance/PerformanceResourceTiming.h b/dom/performance/PerformanceResourceTiming.h
index 63a8c24149..fd085b120a 100644
--- a/dom/performance/PerformanceResourceTiming.h
+++ b/dom/performance/PerformanceResourceTiming.h
@@ -6,9 +6,8 @@
#ifndef mozilla_dom_PerformanceResourceTiming_h___
#define mozilla_dom_PerformanceResourceTiming_h___
+#include "mozilla/UniquePtr.h"
#include "nsCOMPtr.h"
-#include "nsIChannel.h"
-#include "nsITimedChannel.h"
#include "Performance.h"
#include "PerformanceEntry.h"
#include "PerformanceTiming.h"
@@ -27,10 +26,9 @@ public:
PerformanceResourceTiming,
PerformanceEntry)
- PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming,
+ PerformanceResourceTiming(UniquePtr<PerformanceTimingData>&& aPerformanceTimingData,
Performance* aPerformance,
- const nsAString& aName,
- nsIHttpChannel* aChannel = nullptr);
+ const nsAString& aName);
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
@@ -54,93 +52,85 @@ public:
void GetNextHopProtocol(nsAString& aNextHopProtocol) const
{
- if (mTiming && mTiming->TimingAllowed()) {
- aNextHopProtocol = mNextHopProtocol;
+ if (mTimingData) {
+ aNextHopProtocol = mTimingData->NextHopProtocol();
}
}
- void SetNextHopProtocol(const nsAString& aNextHopProtocol)
- {
- mNextHopProtocol = aNextHopProtocol;
- }
-
DOMHighResTimeStamp WorkerStart() const {
- return mTiming && mTiming->TimingAllowed()
- ? mTiming->WorkerStartHighRes()
+ return mTimingData
+ ? mTimingData->WorkerStartHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp FetchStart() const {
- if (mTiming) {
- return mTiming->TimingAllowed()
- ? mTiming->FetchStartHighRes()
- : StartTime();
- }
- return 0;
+ return mTimingData
+ ? mTimingData->FetchStartHighRes(mPerformance)
+ : 0;
}
DOMHighResTimeStamp RedirectStart() const {
// We have to check if all the redirect URIs had the same origin (since
// there is no check in RedirectEndHighRes())
- return mTiming && mTiming->ShouldReportCrossOriginRedirect()
- ? mTiming->RedirectStartHighRes()
+ return mTimingData && mTimingData->ShouldReportCrossOriginRedirect()
+ ? mTimingData->RedirectStartHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp RedirectEnd() const {
// We have to check if all the redirect URIs had the same origin (since
// there is no check in RedirectEndHighRes())
- return mTiming && mTiming->ShouldReportCrossOriginRedirect()
- ? mTiming->RedirectEndHighRes()
+ return mTimingData && mTimingData->ShouldReportCrossOriginRedirect()
+ ? mTimingData->RedirectEndHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp DomainLookupStart() const {
- return mTiming && mTiming->TimingAllowed()
- ? mTiming->DomainLookupStartHighRes()
+ return mTimingData && mTimingData->TimingAllowed()
+ ? mTimingData->DomainLookupStartHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp DomainLookupEnd() const {
- return mTiming && mTiming->TimingAllowed()
- ? mTiming->DomainLookupEndHighRes()
+ return mTimingData && mTimingData->TimingAllowed()
+ ? mTimingData->DomainLookupEndHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp ConnectStart() const {
- return mTiming && mTiming->TimingAllowed()
- ? mTiming->ConnectStartHighRes()
+ return mTimingData && mTimingData->TimingAllowed()
+ ? mTimingData->ConnectStartHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp ConnectEnd() const {
- return mTiming && mTiming->TimingAllowed()
- ? mTiming->ConnectEndHighRes()
+ return mTimingData && mTimingData->TimingAllowed()
+ ? mTimingData->ConnectEndHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp RequestStart() const {
- return mTiming && mTiming->TimingAllowed()
- ? mTiming->RequestStartHighRes()
+ return mTimingData && mTimingData->TimingAllowed()
+ ? mTimingData->RequestStartHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp ResponseStart() const {
- return mTiming && mTiming->TimingAllowed()
- ? mTiming->ResponseStartHighRes()
+ return mTimingData && mTimingData->TimingAllowed()
+ ? mTimingData->ResponseStartHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp ResponseEnd() const {
- return mTiming
- ? mTiming->ResponseEndHighRes()
+ return mTimingData
+ ? mTimingData->ResponseEndHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp SecureConnectionStart() const
{
- return mTiming && mTiming->TimingAllowed()
- ? mTiming->SecureConnectionStartHighRes()
+ return mTimingData && mTimingData->TimingAllowed()
+ ? mTimingData->SecureConnectionStartHighRes(mPerformance)
: 0;
}
@@ -151,44 +141,25 @@ public:
uint64_t TransferSize() const
{
- return mTiming && mTiming->TimingAllowed() ? mTransferSize : 0;
+ return mTimingData ? mTimingData->TransferSize() : 0;
}
uint64_t EncodedBodySize() const
{
- return mTiming && mTiming->TimingAllowed() ? mEncodedBodySize : 0;
+ return mTimingData ? mTimingData->EncodedBodySize() : 0;
}
uint64_t DecodedBodySize() const
{
- return mTiming && mTiming->TimingAllowed() ? mDecodedBodySize : 0;
- }
-
- void SetEncodedBodySize(uint64_t aEncodedBodySize)
- {
- mEncodedBodySize = aEncodedBodySize;
- }
-
- void SetTransferSize(uint64_t aTransferSize)
- {
- mTransferSize = aTransferSize;
- }
-
- void SetDecodedBodySize(uint64_t aDecodedBodySize)
- {
- mDecodedBodySize = aDecodedBodySize;
+ return mTimingData ? mTimingData->DecodedBodySize() : 0;
}
protected:
virtual ~PerformanceResourceTiming();
- void SetPropertiesFromChannel(nsIHttpChannel* aChannel);
nsString mInitiatorType;
- nsString mNextHopProtocol;
- RefPtr<PerformanceTiming> mTiming;
- uint64_t mEncodedBodySize;
- uint64_t mTransferSize;
- uint64_t mDecodedBodySize;
+ UniquePtr<PerformanceTimingData> mTimingData;
+ RefPtr<Performance> mPerformance;
};
} // namespace dom
diff --git a/dom/performance/PerformanceTiming.cpp b/dom/performance/PerformanceTiming.cpp
index 5c33457d0c..7e10a7edda 100755
--- a/dom/performance/PerformanceTiming.cpp
+++ b/dom/performance/PerformanceTiming.cpp
@@ -19,34 +19,39 @@ PerformanceTiming::PerformanceTiming(Performance* aPerformance,
nsITimedChannel* aChannel,
nsIHttpChannel* aHttpChannel,
DOMHighResTimeStamp aZeroTime)
- : mPerformance(aPerformance),
- mFetchStart(0.0),
- mZeroTime(TimerClamping::ReduceMsTimeValue(aZeroTime)),
- mRedirectCount(0),
- mTimingAllowed(true),
- mAllRedirectsSameOrigin(true),
- mInitialized(!!aChannel),
- mReportCrossOriginRedirect(true)
+ : mPerformance(aPerformance)
{
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
+ mTimingData.reset(new PerformanceTimingData(aChannel, aHttpChannel,
+ aZeroTime));
+}
+
+// Copy the timing info from the channel so we don't need to keep the channel
+// alive just to get the timestamps.
+PerformanceTimingData::PerformanceTimingData(nsITimedChannel* aChannel,
+ nsIHttpChannel* aHttpChannel,
+ DOMHighResTimeStamp aZeroTime)
+ : mZeroTime(0.0)
+ , mFetchStart(0.0)
+ , mEncodedBodySize(0)
+ , mTransferSize(0)
+ , mDecodedBodySize(0)
+ , mRedirectCount(0)
+ , mAllRedirectsSameOrigin(true)
+ , mReportCrossOriginRedirect(true)
+ , mSecureConnection(false)
+ , mTimingAllowed(true)
+ , mInitialized(false)
+{
+ mInitialized = !!aChannel;
+
+ mZeroTime = TimerClamping::ReduceMsTimeValue(aZeroTime);
+
if (!nsContentUtils::IsPerformanceTimingEnabled()) {
mZeroTime = 0;
}
- // The aHttpChannel argument is null if this PerformanceTiming object is
- // being used for navigation timing (which is only relevant for documents).
- // It has a non-null value if this PerformanceTiming object is being used
- // for resource timing, which can include document loads, both toplevel and
- // in subframes, and resources linked from a document.
- if (aHttpChannel) {
- mTimingAllowed = CheckAllowedOrigin(aHttpChannel, aChannel);
- bool redirectsPassCheck = false;
- aChannel->GetAllRedirectsPassTimingAllowCheck(&redirectsPassCheck);
- mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck;
- }
-
- mSecureConnection = false;
nsCOMPtr<nsIURI> uri;
if (aHttpChannel) {
aHttpChannel->GetURI(getter_AddRefs(uri));
@@ -63,14 +68,7 @@ PerformanceTiming::PerformanceTiming(Performance* aPerformance,
mSecureConnection = false;
}
}
- InitializeTimingInfo(aChannel);
-}
-// Copy the timing info from the channel so we don't need to keep the channel
-// alive just to get the timestamps.
-void
-PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel)
-{
if (aChannel) {
aChannel->GetAsyncOpen(&mAsyncOpen);
aChannel->GetDispatchFetchEventStart(&mWorkerStart);
@@ -90,11 +88,11 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel)
aChannel->GetCacheReadEnd(&mCacheReadEnd);
// The performance timing api essentially requires that the event timestamps
- // have a strict relation with each other. The truth, however, is the browser
- // engages in a number of speculative activities that sometimes mean connections
- // and lookups begin at different times. Workaround that here by clamping
- // these values to what we expect FetchStart to be. This means the later of
- // AsyncOpen or WorkerStart times.
+ // have a strict relation with each other. The truth, however, is the
+ // browser engages in a number of speculative activities that sometimes mean
+ // connections and lookups begin at different times. Workaround that here by
+ // clamping these values to what we expect FetchStart to be. This means the
+ // later of AsyncOpen or WorkerStart times.
if (!mAsyncOpen.IsNull()) {
// We want to clamp to the expected FetchStart value. This is later of
// the AsyncOpen and WorkerStart values.
@@ -125,6 +123,43 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel)
}
}
}
+
+ // The aHttpChannel argument is null if this PerformanceTiming object is
+ // being used for navigation timing (which is only relevant for documents).
+ // It has a non-null value if this PerformanceTiming object is being used
+ // for resource timing, which can include document loads, both toplevel and
+ // in subframes, and resources linked from a document.
+ if (aHttpChannel) {
+ mTimingAllowed = CheckAllowedOrigin(aHttpChannel, aChannel);
+ bool redirectsPassCheck = false;
+ aChannel->GetAllRedirectsPassTimingAllowCheck(&redirectsPassCheck);
+ mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck;
+
+ SetPropertiesFromHttpChannel(aHttpChannel, aChannel);
+ }
+}
+
+void
+PerformanceTimingData::SetPropertiesFromHttpChannel(nsIHttpChannel* aHttpChannel,
+ nsITimedChannel* aChannel)
+{
+ MOZ_ASSERT(aHttpChannel);
+
+ nsAutoCString protocol;
+ Unused << aHttpChannel->GetProtocolVersion(protocol);
+ mNextHopProtocol = NS_ConvertUTF8toUTF16(protocol);
+
+ Unused << aHttpChannel->GetEncodedBodySize(&mEncodedBodySize);
+ Unused << aHttpChannel->GetTransferSize(&mTransferSize);
+ Unused << aHttpChannel->GetDecodedBodySize(&mDecodedBodySize);
+ if (mDecodedBodySize == 0) {
+ mDecodedBodySize = mEncodedBodySize;
+ }
+
+ mTimingAllowed = CheckAllowedOrigin(aHttpChannel, aChannel);
+ bool redirectsPassCheck = false;
+ aChannel->GetAllRedirectsPassTimingAllowCheck(&redirectsPassCheck);
+ mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck;
}
PerformanceTiming::~PerformanceTiming()
@@ -132,8 +167,10 @@ PerformanceTiming::~PerformanceTiming()
}
DOMHighResTimeStamp
-PerformanceTiming::FetchStartHighRes()
+PerformanceTimingData::FetchStartHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!mFetchStart) {
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
@@ -142,9 +179,9 @@ PerformanceTiming::FetchStartHighRes()
"valid if the performance timing is enabled");
if (!mAsyncOpen.IsNull()) {
if (!mWorkerStart.IsNull() && mWorkerStart > mAsyncOpen) {
- mFetchStart = TimeStampToDOMHighRes(mWorkerStart);
+ mFetchStart = TimeStampToDOMHighRes(aPerformance, mWorkerRequestStart);
} else {
- mFetchStart = TimeStampToDOMHighRes(mAsyncOpen);
+ mFetchStart = TimeStampToDOMHighRes(aPerformance, mAsyncOpen);
}
}
}
@@ -154,12 +191,12 @@ PerformanceTiming::FetchStartHighRes()
DOMTimeMilliSec
PerformanceTiming::FetchStart()
{
- return static_cast<int64_t>(FetchStartHighRes());
+ return static_cast<int64_t>(mTimingData->FetchStartHighRes(mPerformance));
}
bool
-PerformanceTiming::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
- nsITimedChannel* aChannel)
+PerformanceTimingData::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
+ nsITimedChannel* aChannel)
{
if (!IsInitialized()) {
return false;
@@ -187,14 +224,8 @@ PerformanceTiming::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
return aChannel->TimingAllowCheck(principal);
}
-bool
-PerformanceTiming::TimingAllowed() const
-{
- return mTimingAllowed;
-}
-
uint8_t
-PerformanceTiming::GetRedirectCount() const
+PerformanceTimingData::GetRedirectCount() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return 0;
@@ -206,7 +237,7 @@ PerformanceTiming::GetRedirectCount() const
}
bool
-PerformanceTiming::ShouldReportCrossOriginRedirect() const
+PerformanceTimingData::ShouldReportCrossOriginRedirect() const
{
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return false;
@@ -219,23 +250,27 @@ PerformanceTiming::ShouldReportCrossOriginRedirect() const
}
DOMHighResTimeStamp
-PerformanceTiming::AsyncOpenHighRes()
+PerformanceTimingData::AsyncOpenHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
mAsyncOpen.IsNull()) {
return mZeroTime;
}
- return TimeStampToReducedDOMHighResOrFetchStart(mAsyncOpen);
+ return TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(aPerformance, mAsyncOpen));
}
DOMHighResTimeStamp
-PerformanceTiming::WorkerStartHighRes()
+PerformanceTimingData::WorkerStartHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() ||
mWorkerStart.IsNull()) {
return mZeroTime;
}
- return TimeStampToReducedDOMHighResOrFetchStart(mWorkerStart);
+ return TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(aPerformance, mWorkerStart));
}
/**
@@ -249,24 +284,27 @@ PerformanceTiming::WorkerStartHighRes()
* @return a valid timing if the Performance Timing is enabled
*/
DOMHighResTimeStamp
-PerformanceTiming::RedirectStartHighRes()
+PerformanceTimingData::RedirectStartHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
- return TimeStampToReducedDOMHighResOrFetchStart(mRedirectStart);
+ return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mRedirectStart);
}
DOMTimeMilliSec
PerformanceTiming::RedirectStart()
{
- if (!IsInitialized()) {
+ if (!mTimingData->IsInitialized()) {
return 0;
}
// We have to check if all the redirect URIs had the same origin (since there
// is no check in RedirectStartHighRes())
- if (mAllRedirectsSameOrigin && mRedirectCount) {
- return static_cast<int64_t>(RedirectStartHighRes());
+ if (mTimingData->AllRedirectsSameOrigin() &&
+ mTimingData->RedirectCountReal()) {
+ return static_cast<int64_t>(mTimingData->RedirectStartHighRes(mPerformance));
}
return 0;
}
@@ -282,130 +320,155 @@ PerformanceTiming::RedirectStart()
* @return a valid timing if the Performance Timing is enabled
*/
DOMHighResTimeStamp
-PerformanceTiming::RedirectEndHighRes()
+PerformanceTimingData::RedirectEndHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
- return TimeStampToReducedDOMHighResOrFetchStart(mRedirectEnd);
+ return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mRedirectEnd);
}
DOMTimeMilliSec
PerformanceTiming::RedirectEnd()
{
- if (!IsInitialized()) {
+ if (!mTimingData->IsInitialized()) {
return 0;
}
// We have to check if all the redirect URIs had the same origin (since there
// is no check in RedirectEndHighRes())
- if (mAllRedirectsSameOrigin && mRedirectCount) {
- return static_cast<int64_t>(RedirectEndHighRes());
+ if (mTimingData->AllRedirectsSameOrigin() &&
+ mTimingData->RedirectCountReal()) {
+ return static_cast<int64_t>(mTimingData->RedirectEndHighRes(mPerformance));
}
return 0;
}
DOMHighResTimeStamp
-PerformanceTiming::DomainLookupStartHighRes()
+PerformanceTimingData::DomainLookupStartHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
- return TimeStampToReducedDOMHighResOrFetchStart(mDomainLookupStart);
+ return TimeStampToReducedDOMHighResOrFetchStart(aPerformance,
+ mDomainLookupStart);
}
DOMTimeMilliSec
PerformanceTiming::DomainLookupStart()
{
- return static_cast<int64_t>(DomainLookupStartHighRes());
+ return static_cast<int64_t>(mTimingData->DomainLookupStartHighRes(mPerformance));
}
DOMHighResTimeStamp
-PerformanceTiming::DomainLookupEndHighRes()
+PerformanceTimingData::DomainLookupEndHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
- // Bug 1155008 - nsHttpTransaction is racy. Return DomainLookupStart when null
- return mDomainLookupEnd.IsNull() ? DomainLookupStartHighRes()
- : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mDomainLookupEnd));
+ return mDomainLookupEnd.IsNull()
+ ? DomainLookupStartHighRes(aPerformance)
+ : TimerClamping::ReduceMsTimeValue(
+ TimeStampToDOMHighRes(aPerformance, mDomainLookupEnd));
}
DOMTimeMilliSec
PerformanceTiming::DomainLookupEnd()
{
- return static_cast<int64_t>(DomainLookupEndHighRes());
+ return static_cast<int64_t>(mTimingData->DomainLookupEndHighRes(mPerformance));
}
DOMHighResTimeStamp
-PerformanceTiming::ConnectStartHighRes()
+PerformanceTimingData::ConnectStartHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
- return mConnectStart.IsNull() ? DomainLookupEndHighRes()
- : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mConnectStart));
+ return mConnectStart.IsNull()
+ ? DomainLookupEndHighRes(aPerformance)
+ : TimerClamping::ReduceMsTimeValue(
+ TimeStampToDOMHighRes(aPerformance, mConnectStart));
}
DOMTimeMilliSec
PerformanceTiming::ConnectStart()
{
- return static_cast<int64_t>(ConnectStartHighRes());
+ return static_cast<int64_t>(mTimingData->ConnectStartHighRes(mPerformance));
}
DOMHighResTimeStamp
-PerformanceTiming::SecureConnectionStartHighRes()
+PerformanceTimingData::SecureConnectionStartHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
return !mSecureConnection
? 0 // We use 0 here, because mZeroTime is sometimes set to the navigation
// start time.
- : (mSecureConnectionStart.IsNull() ? mZeroTime
- : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mSecureConnectionStart)));
+ : (mSecureConnectionStart.IsNull()
+ ? mZeroTime
+ : TimerClamping::ReduceMsTimeValue(
+ TimeStampToDOMHighRes(aPerformance, mSecureConnectionStart)));
}
DOMTimeMilliSec
PerformanceTiming::SecureConnectionStart()
{
- return static_cast<int64_t>(SecureConnectionStartHighRes());
+ return static_cast<int64_t>(mTimingData->SecureConnectionStartHighRes(mPerformance));
}
DOMHighResTimeStamp
-PerformanceTiming::ConnectEndHighRes()
+PerformanceTimingData::ConnectEndHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
// Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null
- return mConnectEnd.IsNull() ? ConnectStartHighRes()
- : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mConnectEnd));
+ return mConnectEnd.IsNull()
+ ? ConnectStartHighRes(aPerformance)
+ : TimerClamping::ReduceMsTimeValue(
+ TimeStampToDOMHighRes(aPerformance, mConnectEnd));
}
DOMTimeMilliSec
PerformanceTiming::ConnectEnd()
{
- return static_cast<int64_t>(ConnectEndHighRes());
+ return static_cast<int64_t>(mTimingData->ConnectEndHighRes(mPerformance));
}
DOMHighResTimeStamp
-PerformanceTiming::RequestStartHighRes()
+PerformanceTimingData::RequestStartHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
- return TimeStampToReducedDOMHighResOrFetchStart(mRequestStart);
+ return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mRequestStart);
}
DOMTimeMilliSec
PerformanceTiming::RequestStart()
{
- return static_cast<int64_t>(RequestStartHighRes());
+ return static_cast<int64_t>(mTimingData->RequestStartHighRes(mPerformance));
}
DOMHighResTimeStamp
-PerformanceTiming::ResponseStartHighRes()
+PerformanceTimingData::ResponseStartHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
@@ -413,18 +476,20 @@ PerformanceTiming::ResponseStartHighRes()
(!mCacheReadStart.IsNull() && mCacheReadStart < mResponseStart)) {
mResponseStart = mCacheReadStart;
}
- return TimeStampToReducedDOMHighResOrFetchStart(mResponseStart);
+ return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mResponseStart);
}
DOMTimeMilliSec
PerformanceTiming::ResponseStart()
{
- return static_cast<int64_t>(ResponseStartHighRes());
+ return static_cast<int64_t>(mTimingData->ResponseStartHighRes(mPerformance));
}
DOMHighResTimeStamp
-PerformanceTiming::ResponseEndHighRes()
+PerformanceTimingData::ResponseEndHighRes(Performance* aPerformance)
{
+ MOZ_ASSERT(aPerformance);
+
if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
return mZeroTime;
}
@@ -433,20 +498,16 @@ PerformanceTiming::ResponseEndHighRes()
mResponseEnd = mCacheReadEnd;
}
// Bug 1155008 - nsHttpTransaction is racy. Return ResponseStart when null
- return mResponseEnd.IsNull() ? ResponseStartHighRes()
- : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mResponseEnd));
+ return mResponseEnd.IsNull()
+ ? ResponseStartHighRes(aPerformance)
+ : TimerClamping::ReduceMsTimeValue(
+ TimeStampToDOMHighRes(aPerformance, mResponseEnd));
}
DOMTimeMilliSec
PerformanceTiming::ResponseEnd()
{
- return static_cast<int64_t>(ResponseEndHighRes());
-}
-
-bool
-PerformanceTiming::IsInitialized() const
-{
- return mInitialized;
+ return static_cast<int64_t>(mTimingData->ResponseEndHighRes(mPerformance));
}
JSObject*
diff --git a/dom/performance/PerformanceTiming.h b/dom/performance/PerformanceTiming.h
index c0d4b6237b..91bd14f0d7 100755
--- a/dom/performance/PerformanceTiming.h
+++ b/dom/performance/PerformanceTiming.h
@@ -19,44 +19,38 @@ class nsITimedChannel;
namespace mozilla {
namespace dom {
-// Script "performance.timing" object
-class PerformanceTiming final : public nsWrapperCache
+class PerformanceTimingData final
{
public:
-/**
- * @param aPerformance
- * The performance object (the JS parent).
- * This will allow access to "window.performance.timing" attribute for
- * the navigation timing (can't be null).
- * @param aChannel
- * An nsITimedChannel used to gather all the networking timings by both
- * the navigation timing and the resource timing (can't be null).
- * @param aHttpChannel
- * An nsIHttpChannel (the resource's http channel).
- * This will be used by the resource timing cross-domain check
- * algorithm.
- * Argument is null for the navigation timing (navigation timing uses
- * another algorithm for the cross-domain redirects).
- * @param aZeroTime
- * The offset that will be added to the timestamp of each event. This
- * argument should be equal to performance.navigationStart for
- * navigation timing and "0" for the resource timing.
- */
- PerformanceTiming(Performance* aPerformance,
- nsITimedChannel* aChannel,
- nsIHttpChannel* aHttpChannel,
- DOMHighResTimeStamp aZeroTime);
- NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PerformanceTiming)
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(PerformanceTiming)
+ PerformanceTimingData(nsITimedChannel* aChannel,
+ nsIHttpChannel* aHttpChannel,
+ DOMHighResTimeStamp aZeroTime);
- nsDOMNavigationTiming* GetDOMTiming() const
+ void SetPropertiesFromHttpChannel(nsIHttpChannel* aHttpChannel, nsITimedChannel* aChannel);
+
+ bool IsInitialized() const
{
- return mPerformance->GetDOMTiming();
+ return mInitialized;
}
- Performance* GetParentObject() const
+ const nsString& NextHopProtocol() const
{
- return mPerformance;
+ return mNextHopProtocol;
+ }
+
+ uint64_t TransferSize() const
+ {
+ return mTimingAllowed ? mTransferSize : 0;
+ }
+
+ uint64_t EncodedBodySize() const
+ {
+ return mTimingAllowed ? mEncodedBodySize : 0;
+ }
+
+ uint64_t DecodedBodySize() const
+ {
+ return mTimingAllowed ? mDecodedBodySize : 0;
}
/**
@@ -68,11 +62,16 @@ public:
* page), if the given TimeStamp is valid. Otherwise, it will return
* the FetchStart timing value.
*/
- inline DOMHighResTimeStamp TimeStampToReducedDOMHighResOrFetchStart(TimeStamp aStamp)
+ inline DOMHighResTimeStamp
+ TimeStampToReducedDOMHighResOrFetchStart(Performance* aPerformance,
+ TimeStamp aStamp)
{
+ MOZ_ASSERT(aPerformance);
+
return (!aStamp.IsNull())
- ? TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(aStamp))
- : FetchStartHighRes();
+ ? TimerClamping::ReduceMsTimeValue(
+ TimeStampToDOMHighRes(aPerformance, aStamp))
+ : FetchStartHighRes(aPerformance);
}
/**
@@ -83,7 +82,7 @@ public:
*
* The algorithm operates in 2 steps:
* 1. The first step is to subtract the two timestamps: the argument (the
- * envet's timesramp) and the navigation start timestamp. This will result in
+ * event's timestamp) and the navigation start timestamp. This will result in
* a relative timestamp of the event (relative to the navigation start -
* window.performance.timing.navigationStart).
* 2. The second step is to add any required offset (the mZeroTime). For now,
@@ -99,17 +98,154 @@ public:
* be null.
* @return number of milliseconds value as one of:
* - relative to the navigation start time, time the user has landed on the
- * page
+ * page
* - an absolute wall clock time since the unix epoch
*/
- inline DOMHighResTimeStamp TimeStampToDOMHighRes(TimeStamp aStamp) const
+ inline DOMHighResTimeStamp
+ TimeStampToDOMHighRes(Performance* aPerformance, TimeStamp aStamp) const
{
+ MOZ_ASSERT(aPerformance);
MOZ_ASSERT(!aStamp.IsNull());
+
TimeDuration duration =
- aStamp - GetDOMTiming()->GetNavigationStartTimeStamp();
+ aStamp - aPerformance->GetDOMTiming()->GetNavigationStartTimeStamp();
return duration.ToMilliseconds() + mZeroTime;
}
+ // The last channel's AsyncOpen time. This may occur before the FetchStart
+ // in some cases.
+ DOMHighResTimeStamp AsyncOpenHighRes(Performance* aPerformance);
+
+ // High resolution (used by resource timing)
+ DOMHighResTimeStamp WorkerStartHighRes(Performance* aPerformance);
+ DOMHighResTimeStamp FetchStartHighRes(Performance* aPerformance);
+ DOMHighResTimeStamp RedirectStartHighRes(Performance* aPerformance);
+ DOMHighResTimeStamp RedirectEndHighRes(Performance* aPerformance);
+ DOMHighResTimeStamp DomainLookupStartHighRes(Performance* aPerformance);
+ DOMHighResTimeStamp DomainLookupEndHighRes(Performance* aPerformance);
+ DOMHighResTimeStamp ConnectStartHighRes(Performance* aPerformance);
+ DOMHighResTimeStamp SecureConnectionStartHighRes(Performance* aPerformance);
+ DOMHighResTimeStamp ConnectEndHighRes(Performance* aPerformance);
+ DOMHighResTimeStamp RequestStartHighRes(Performance* aPerformance);
+ DOMHighResTimeStamp ResponseStartHighRes(Performance* aPerformance);
+ DOMHighResTimeStamp ResponseEndHighRes(Performance* aPerformance);
+
+ DOMHighResTimeStamp ZeroTime() const { return mZeroTime; }
+
+ uint8_t RedirectCountReal() const { return mRedirectCount; }
+ uint8_t GetRedirectCount() const;
+
+ bool AllRedirectsSameOrigin() const { return mAllRedirectsSameOrigin; }
+
+ // If this is false the values of redirectStart/End will be 0 This is false if
+ // no redirects occured, or if any of the responses failed the
+ // timing-allow-origin check in HttpBaseChannel::TimingAllowCheck
+ bool ShouldReportCrossOriginRedirect() const;
+
+ // Cached result of CheckAllowedOrigin. If false, security sensitive
+ // attributes of the resourceTiming object will be set to 0
+ bool TimingAllowed() const
+ {
+ return mTimingAllowed;
+ }
+
+private:
+ // Checks if the resource is either same origin as the page that started
+ // the load, or if the response contains the Timing-Allow-Origin header
+ // with a value of * or matching the domain of the loading Principal
+ bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
+ nsITimedChannel* aChannel);
+
+ nsString mNextHopProtocol;
+
+ TimeStamp mAsyncOpen;
+ TimeStamp mRedirectStart;
+ TimeStamp mRedirectEnd;
+ TimeStamp mDomainLookupStart;
+ TimeStamp mDomainLookupEnd;
+ TimeStamp mConnectStart;
+ TimeStamp mSecureConnectionStart;
+ TimeStamp mConnectEnd;
+ TimeStamp mRequestStart;
+ TimeStamp mResponseStart;
+ TimeStamp mCacheReadStart;
+ TimeStamp mResponseEnd;
+ TimeStamp mCacheReadEnd;
+
+ // ServiceWorker interception timing information
+ TimeStamp mWorkerStart;
+ TimeStamp mWorkerRequestStart;
+ TimeStamp mWorkerResponseEnd;
+
+ // This is an offset that will be added to each timing ([ms] resolution).
+ // There are only 2 possible values: (1) logicaly equal to navigationStart
+ // TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results
+ // are relative to the navigation start).
+ DOMHighResTimeStamp mZeroTime;
+
+ DOMHighResTimeStamp mFetchStart;
+
+ uint64_t mEncodedBodySize;
+ uint64_t mTransferSize;
+ uint64_t mDecodedBodySize;
+
+ uint8_t mRedirectCount;
+
+ bool mAllRedirectsSameOrigin;
+
+ // If the resourceTiming object should have non-zero redirectStart and
+ // redirectEnd attributes. It is false if there were no redirects, or if any
+ // of the responses didn't pass the timing-allow-check
+ bool mReportCrossOriginRedirect;
+
+ bool mSecureConnection;
+
+ bool mTimingAllowed;
+
+ bool mInitialized;
+
+};
+
+// Script "performance.timing" object
+class PerformanceTiming final : public nsWrapperCache
+{
+public:
+/**
+ * @param aPerformance
+ * The performance object (the JS parent).
+ * This will allow access to "window.performance.timing" attribute for
+ * the navigation timing (can't be null).
+ * @param aChannel
+ * An nsITimedChannel used to gather all the networking timings by both
+ * the navigation timing and the resource timing (can't be null).
+ * @param aHttpChannel
+ * An nsIHttpChannel (the resource's http channel).
+ * This will be used by the resource timing cross-domain check
+ * algorithm.
+ * Argument is null for the navigation timing (navigation timing uses
+ * another algorithm for the cross-domain redirects).
+ * @param aZeroTime
+ * The offset that will be added to the timestamp of each event. This
+ * argument should be equal to performance.navigationStart for
+ * navigation timing and "0" for the resource timing.
+ */
+ PerformanceTiming(Performance* aPerformance,
+ nsITimedChannel* aChannel,
+ nsIHttpChannel* aHttpChannel,
+ DOMHighResTimeStamp aZeroTime);
+ NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PerformanceTiming)
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(PerformanceTiming)
+
+ nsDOMNavigationTiming* GetDOMTiming() const
+ {
+ return mPerformance->GetDOMTiming();
+ }
+
+ Performance* GetParentObject() const
+ {
+ return mPerformance;
+ }
+
virtual JSObject* WrapObject(JSContext *cx,
JS::Handle<JSObject*> aGivenProto) override;
@@ -138,40 +274,6 @@ public:
return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetUnloadEventEnd());
}
- uint8_t GetRedirectCount() const;
-
- // Checks if the resource is either same origin as the page that started
- // the load, or if the response contains the Timing-Allow-Origin header
- // with a value of * or matching the domain of the loading Principal
- bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, nsITimedChannel* aChannel);
-
- // Cached result of CheckAllowedOrigin. If false, security sensitive
- // attributes of the resourceTiming object will be set to 0
- bool TimingAllowed() const;
-
- // If this is false the values of redirectStart/End will be 0
- // This is false if no redirects occured, or if any of the responses failed
- // the timing-allow-origin check in HttpBaseChannel::TimingAllowCheck
- bool ShouldReportCrossOriginRedirect() const;
-
- // The last channel's AsyncOpen time. This may occur before the FetchStart
- // in some cases.
- DOMHighResTimeStamp AsyncOpenHighRes();
-
- // High resolution (used by resource timing)
- DOMHighResTimeStamp WorkerStartHighRes();
- DOMHighResTimeStamp FetchStartHighRes();
- DOMHighResTimeStamp RedirectStartHighRes();
- DOMHighResTimeStamp RedirectEndHighRes();
- DOMHighResTimeStamp DomainLookupStartHighRes();
- DOMHighResTimeStamp DomainLookupEndHighRes();
- DOMHighResTimeStamp ConnectStartHighRes();
- DOMHighResTimeStamp SecureConnectionStartHighRes();
- DOMHighResTimeStamp ConnectEndHighRes();
- DOMHighResTimeStamp RequestStartHighRes();
- DOMHighResTimeStamp ResponseStartHighRes();
- DOMHighResTimeStamp ResponseEndHighRes();
-
// Low resolution (used by navigation timing)
DOMTimeMilliSec FetchStart();
DOMTimeMilliSec RedirectStart();
@@ -249,46 +351,16 @@ public:
return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetTimeToNonBlankPaint());
}
+ PerformanceTimingData* Data() const
+ {
+ return mTimingData.get();
+ }
+
private:
~PerformanceTiming();
- bool IsInitialized() const;
- void InitializeTimingInfo(nsITimedChannel* aChannel);
-
RefPtr<Performance> mPerformance;
- DOMHighResTimeStamp mFetchStart;
-
- // This is an offset that will be added to each timing ([ms] resolution).
- // There are only 2 possible values: (1) logicaly equal to navigationStart
- // TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results
- // are relative to the navigation start).
- DOMHighResTimeStamp mZeroTime;
-
- TimeStamp mAsyncOpen;
- TimeStamp mWorkerStart;
- TimeStamp mRedirectStart;
- TimeStamp mRedirectEnd;
- TimeStamp mDomainLookupStart;
- TimeStamp mDomainLookupEnd;
- TimeStamp mConnectStart;
- TimeStamp mSecureConnectionStart;
- TimeStamp mConnectEnd;
- TimeStamp mRequestStart;
- TimeStamp mResponseStart;
- TimeStamp mCacheReadStart;
- TimeStamp mResponseEnd;
- TimeStamp mCacheReadEnd;
- uint8_t mRedirectCount;
- bool mTimingAllowed;
- bool mAllRedirectsSameOrigin;
- bool mInitialized;
-
- // If the resourceTiming object should have non-zero redirectStart and
- // redirectEnd attributes. It is false if there were no redirects, or if
- // any of the responses didn't pass the timing-allow-check
- bool mReportCrossOriginRedirect;
-
- bool mSecureConnection;
+ UniquePtr<PerformanceTimingData> mTimingData;
};
} // namespace dom
diff --git a/dom/performance/PerformanceWorker.h b/dom/performance/PerformanceWorker.h
index 3604e6874f..cdd3a521dd 100644
--- a/dom/performance/PerformanceWorker.h
+++ b/dom/performance/PerformanceWorker.h
@@ -62,6 +62,11 @@ public:
return nullptr;
}
+ void QueueNavigationTimingEntry() override
+ {
+ MOZ_CRASH("This should not be called on workers.");
+ }
+
protected:
~PerformanceWorker();
diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp
index 879f47b206..a3577fdd12 100644
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -1070,6 +1070,11 @@ nsDocumentViewer::LoadComplete(nsresult aStatus)
if (timing) {
timing->NotifyLoadEventEnd();
}
+
+ nsPIDOMWindowInner* innerWindow = window->GetCurrentInnerWindow();
+ if (innerWindow) {
+ innerWindow->QueuePerformanceNavigationTiming();
+ }
}
} else {
// XXX: Should fire error event to the document...