summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dom/base/nsContentUtils.cpp4
-rw-r--r--dom/base/nsContentUtils.h9
-rw-r--r--dom/base/nsDOMNavigationTiming.cpp138
-rw-r--r--dom/base/nsDOMNavigationTiming.h125
-rw-r--r--dom/base/nsGlobalWindow.cpp20
-rw-r--r--dom/bindings/Codegen.py14
-rwxr-xr-xdom/console/Console.cpp5
-rw-r--r--dom/console/Console.h10
-rwxr-xr-xdom/events/Event.cpp7
-rw-r--r--dom/events/test/test_eventTimeStamp.html36
-rwxr-xr-xdom/performance/Performance.cpp28
-rw-r--r--dom/performance/Performance.h36
-rw-r--r--dom/performance/PerformanceMainThread.cpp99
-rw-r--r--dom/performance/PerformanceMainThread.h21
-rw-r--r--dom/performance/PerformanceNavigationTiming.cpp96
-rw-r--r--dom/performance/PerformanceNavigationTiming.h71
-rw-r--r--dom/performance/PerformanceResourceTiming.cpp31
-rw-r--r--dom/performance/PerformanceResourceTiming.h6
-rw-r--r--dom/performance/PerformanceService.cpp46
-rw-r--r--dom/performance/PerformanceService.h48
-rwxr-xr-xdom/performance/PerformanceTiming.h8
-rw-r--r--dom/performance/PerformanceWorker.cpp35
-rw-r--r--dom/performance/PerformanceWorker.h14
-rw-r--r--dom/performance/moz.build4
-rw-r--r--dom/performance/tests/mochitest.ini1
-rw-r--r--dom/performance/tests/test_performance_user_timing.js21
-rw-r--r--dom/performance/tests/test_timeOrigin.html68
-rw-r--r--dom/tests/mochitest/general/test_interfaces.html6
-rw-r--r--dom/webidl/Performance.webidl3
-rw-r--r--dom/webidl/PerformanceNavigationTiming.webidl33
-rw-r--r--dom/webidl/PerformanceTiming.webidl6
-rw-r--r--dom/webidl/moz.build1
-rw-r--r--dom/workers/WorkerPrivate.cpp14
-rw-r--r--dom/workers/WorkerPrivate.h13
-rw-r--r--modules/libpref/init/all.js6
-rw-r--r--testing/web-platform/meta/MANIFEST.json4
-rw-r--r--testing/web-platform/tests/user-timing/resources/webperftestharness.js2
-rw-r--r--testing/web-platform/tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.html32
-rw-r--r--testing/web-platform/tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.js14
39 files changed, 825 insertions, 310 deletions
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index ef87a250e..bc8cea35a 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -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);
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
index 0932f451e..9ae6d2155 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2033,6 +2033,14 @@ public:
}
/*
+ * 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.
*/
static bool SendPerformanceTimingNotifications()
@@ -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;
diff --git a/dom/base/nsDOMNavigationTiming.cpp b/dom/base/nsDOMNavigationTiming.cpp
index 31b2932fb..32ce8a8cb 100644
--- a/dom/base/nsDOMNavigationTiming.cpp
+++ b/dom/base/nsDOMNavigationTiming.cpp
@@ -15,6 +15,9 @@
#include "nsPrintfCString.h"
#include "mozilla/dom/PerformanceNavigation.h"
#include "mozilla/TimeStamp.h"
+#include "mozilla/Telemetry.h"
+
+using namespace mozilla;
nsDOMNavigationTiming::nsDOMNavigationTiming()
{
@@ -30,47 +33,36 @@ 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;
-
- mLoadEventStartSet = false;
- mLoadEventEndSet = false;
- mDOMLoadingSet = false;
- mDOMInteractiveSet = false;
- mDOMContentLoadedEventStartSet = false;
- mDOMContentLoadedEventEndSet = false;
- mDOMCompleteSet = false;
+ mBeforeUnloadStart = TimeStamp();
+ mUnloadStart = TimeStamp();
+ mUnloadEnd = TimeStamp();
+ mLoadEventStart = TimeStamp();
+ mLoadEventEnd = TimeStamp();
+ mDOMLoading = TimeStamp();
+ mDOMInteractive = TimeStamp();
+ mDOMContentLoadedEventStart = TimeStamp();
+ mDOMContentLoadedEventEnd = TimeStamp();
+ mDOMComplete = TimeStamp();
+
mDocShellHasBeenActiveSinceNavigationStart = false;
}
DOMTimeMilliSec
-nsDOMNavigationTiming::TimeStampToDOM(mozilla::TimeStamp aStamp) const
+nsDOMNavigationTiming::TimeStampToDOM(TimeStamp aStamp) const
{
if (aStamp.IsNull()) {
return 0;
}
- mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp;
- return GetNavigationStart() + static_cast<int64_t>(duration.ToMilliseconds());
-}
-DOMTimeMilliSec nsDOMNavigationTiming::DurationFromStart()
-{
- return TimeStampToDOM(mozilla::TimeStamp::Now());
+ TimeDuration duration = aStamp - mNavigationStart;
+ return GetNavigationStart() + static_cast<int64_t>(duration.ToMilliseconds());
}
void
nsDOMNavigationTiming::NotifyNavigationStart(DocShellState aDocShellState)
{
mNavigationStartHighRes = (double)PR_Now() / PR_USEC_PER_MSEC;
- mNavigationStartTimeStamp = mozilla::TimeStamp::Now();
+ mNavigationStart = TimeStamp::Now();
mDocShellHasBeenActiveSinceNavigationStart = (aDocShellState == DocShellState::eActive);
}
@@ -86,7 +78,7 @@ nsDOMNavigationTiming::NotifyFetchStart(nsIURI* aURI, Type aNavigationType)
void
nsDOMNavigationTiming::NotifyBeforeUnload()
{
- mBeforeUnloadStart = DurationFromStart();
+ mBeforeUnloadStart = TimeStamp::Now();
}
void
@@ -99,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, mozilla::TimeStamp aValue)
+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;
@@ -212,8 +206,8 @@ nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument()
if (mDocShellHasBeenActiveSinceNavigationStart) {
Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_NON_BLANK_PAINT_MS,
- mNavigationStartTimeStamp,
- mNonBlankPaintTimeStamp);
+ mNavigationStart,
+ mNonBlankPaint);
}
}
@@ -224,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();
}
diff --git a/dom/base/nsDOMNavigationTiming.h b/dom/base/nsDOMNavigationTiming.h
index 9babece96..3be2527ca 100644
--- a/dom/base/nsDOMNavigationTiming.h
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -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();
-
- DOMTimeMilliSec mBeforeUnloadStart;
- DOMTimeMilliSec mUnloadStart;
- DOMTimeMilliSec mUnloadEnd;
- DOMTimeMilliSec mLoadEventStart;
- DOMTimeMilliSec mLoadEventEnd;
-
- DOMTimeMilliSec mDOMLoading;
- DOMTimeMilliSec mDOMInteractive;
- DOMTimeMilliSec mDOMContentLoadedEventStart;
- DOMTimeMilliSec mDOMContentLoadedEventEnd;
- DOMTimeMilliSec 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;
+ mozilla::TimeStamp mNavigationStart;
+ mozilla::TimeStamp mNonBlankPaint;
+
+ mozilla::TimeStamp mBeforeUnloadStart;
+ mozilla::TimeStamp mUnloadStart;
+ mozilla::TimeStamp mUnloadEnd;
+ mozilla::TimeStamp mLoadEventStart;
+ mozilla::TimeStamp mLoadEventEnd;
+
+ mozilla::TimeStamp mDOMLoading;
+ mozilla::TimeStamp mDOMInteractive;
+ mozilla::TimeStamp mDOMContentLoadedEventStart;
+ mozilla::TimeStamp mDOMContentLoadedEventEnd;
+ mozilla::TimeStamp mDOMComplete;
+
bool mDocShellHasBeenActiveSinceNavigationStart : 1;
};
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index 3d5c44a78..738703ef1 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -3124,8 +3124,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
newInnerWindow->mPerformance =
Performance::CreateForMainThread(newInnerWindow->AsInner(),
currentInner->mPerformance->GetDOMTiming(),
- currentInner->mPerformance->GetChannel(),
- currentInner->mPerformance->GetParentPerformance());
+ currentInner->mPerformance->GetChannel());
}
}
@@ -4339,22 +4338,7 @@ nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded()
timedChannel = nullptr;
}
if (timing) {
- // If we are dealing with an iframe, we will need the parent's performance
- // object (so we can add the iframe as a resource of that page).
- Performance* parentPerformance = nullptr;
- nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
- if (parentWindow) {
- nsPIDOMWindowInner* parentInnerWindow = nullptr;
- if (parentWindow) {
- parentInnerWindow = parentWindow->GetCurrentInnerWindow();
- }
- if (parentInnerWindow) {
- parentPerformance = parentInnerWindow->GetPerformance();
- }
- }
- mPerformance =
- Performance::CreateForMainThread(this, timing, timedChannel,
- parentPerformance);
+ mPerformance = Performance::CreateForMainThread(this, timing, timedChannel);
}
}
diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
index 3174c37dd..7a6668687 100644
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -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.
diff --git a/dom/console/Console.cpp b/dom/console/Console.cpp
index 79e3eadc5..ff5a92167 100755
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -1336,10 +1336,7 @@ Console::MethodInternal(JSContext* aCx, MethodName aMethodName,
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
- TimeDuration duration =
- mozilla::TimeStamp::Now() - workerPrivate->NowBaseTimeStamp();
-
- monotonicTimer = TimerClamping::ReduceMsTimeValue(duration.ToMilliseconds());
+ monotonicTimer = workerPrivate->TimeStampToDOMHighRes(TimeStamp::Now());
}
}
diff --git a/dom/console/Console.h b/dom/console/Console.h
index b334d79f9..2f375c8eb 100644
--- a/dom/console/Console.h
+++ b/dom/console/Console.h
@@ -258,9 +258,8 @@ private:
// the max number of timers is reached.
// * aCx - the JSContext rooting aName.
// * aName - this is (should be) the name of the timer as JS::Value.
- // * aTimestamp - the monotonicTimer for this context (taken from
- // window->performance.now() or from Now() -
- // workerPrivate->NowBaseTimeStamp() in workers.
+ // * aTimestamp - the monotonicTimer for this context taken from
+ // performance.now().
// * aTimerLabel - This label will be populated with the aName converted to a
// string.
// * aTimerValue - the StartTimer value stored into (or taken from)
@@ -290,9 +289,8 @@ private:
// the aName timer doesn't exist in the mTimerRegistry.
// * aCx - the JSContext rooting aName.
// * aName - this is (should be) the name of the timer as JS::Value.
- // * aTimestamp - the monotonicTimer for this context (taken from
- // window->performance.now() or from Now() -
- // workerPrivate->NowBaseTimeStamp() in workers.
+ // * aTimestamp - the monotonicTimer for this context taken from
+ // performance.now().
// * aTimerLabel - This label will be populated with the aName converted to a
// string.
// * aTimerDuration - the difference between aTimestamp and when the timer
diff --git a/dom/events/Event.cpp b/dom/events/Event.cpp
index 7e19cd74d..4b9776c0a 100755
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -1146,16 +1146,11 @@ Event::TimeStampImpl() const
return perf->GetDOMTiming()->TimeStampToDOMHighRes(mEvent->mTimeStamp);
}
- // For dedicated workers, we should make times relative to the navigation
- // start of the document that created the worker, which is the same as the
- // timebase for performance.now().
workers::WorkerPrivate* workerPrivate =
workers::GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
- TimeDuration duration =
- mEvent->mTimeStamp - workerPrivate->NowBaseTimeStamp();
- return duration.ToMilliseconds();
+ return workerPrivate->TimeStampToDOMHighRes(mEvent->mTimeStamp);
}
bool
diff --git a/dom/events/test/test_eventTimeStamp.html b/dom/events/test/test_eventTimeStamp.html
index 107a21f87..056203e92 100644
--- a/dom/events/test/test_eventTimeStamp.html
+++ b/dom/events/test/test_eventTimeStamp.html
@@ -17,7 +17,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=77992
<script type="text/js-worker" id="worker-src">
// Simply returns the event timestamp
onmessage = function(evt) {
- postMessage(evt.timeStamp);
+ postMessage(evt.timeStamp + performance.timeOrigin);
}
</script>
<script type="text/js-worker" id="shared-worker-src">
@@ -25,7 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=77992
onconnect = function(evt) {
var port = evt.ports[0];
port.onmessage = function(messageEvt) {
- port.postMessage(messageEvt.timeStamp);
+ port.postMessage(messageEvt.timeStamp + performance.timeOrigin);
};
};
</script>
@@ -57,9 +57,9 @@ function testRegularEvents() {
finishTests();
return;
}
- var timeBeforeEvent = window.performance.now();
- window.addEventListener("load", function(evt) {
- var timeAfterEvent = window.performance.now();
+ var timeBeforeEvent = performance.now();
+ addEventListener("load", function(evt) {
+ var timeAfterEvent = performance.now();
ok(evt.timeStamp >= timeBeforeEvent &&
evt.timeStamp <= timeAfterEvent,
"Event timestamp (" + evt.timeStamp + ") is in expected range: (" +
@@ -71,19 +71,18 @@ function testRegularEvents() {
function testWorkerEvents() {
var blob = new Blob([ document.getElementById("worker-src").textContent ],
{ type: "text/javascript" });
- var worker = new Worker(window.URL.createObjectURL(blob));
+ var worker = new Worker(URL.createObjectURL(blob));
worker.onmessage = function(evt) {
- var timeAfterEvent = window.performance.now();
- // Comparing times across timelines may break now
- // ok(evt.data >= timeBeforeEvent &&
- // evt.data <= timeAfterEvent,
+ var timeAfterEvent = performance.now() + performance.timeOrigin;
+ ok(evt.data >= timeBeforeEvent &&
+ evt.data <= timeAfterEvent,
// "Event timestamp in dedicated worker (" + evt.data +
// ") is in expected range: (" +
// timeBeforeEvent + ", " + timeAfterEvent + ")");
worker.terminate();
testSharedWorkerEvents();
};
- var timeBeforeEvent = window.performance.now();
+ var timeBeforeEvent = performance.now() + performance.timeOrigin;
worker.postMessage("");
}
@@ -93,17 +92,16 @@ function testSharedWorkerEvents() {
{ type: "text/javascript" });
// Delay creation of worker slightly so it is easier to distinguish
// shared worker creation time from this document's navigation start
- window.setTimeout(function() {
- var timeBeforeWorkerCreation = window.performance.now();
- var worker = new SharedWorker(window.URL.createObjectURL(blob));
+ setTimeout(function() {
+ var timeBeforeEvent = performance.now() + performance.timeOrigin;
+ var worker = new SharedWorker(URL.createObjectURL(blob));
worker.port.onmessage = function(evt) {
- var timeAfterEvent = window.performance.now();
- // Comparing times across timelines may break now
- // ok(evt.data >= 0 &&
- // evt.data <= timeAfterEvent - timeBeforeWorkerCreation,
+ var timeAfterEvent = performance.now() + performance.timeOrigin;
+ ok(evt.data >= timeBeforeEvent &&
+ evt.data <= timeAfterEvent,
// "Event timestamp in shared worker (" + evt.data +
// ") is in expected range: (0, " +
- // (timeAfterEvent - timeBeforeWorkerCreation) + ")");
+ // timeBeforeEvent + ", " + timeAfterEvent + ")");
worker.port.close();
finishTests();
};
diff --git a/dom/performance/Performance.cpp b/dom/performance/Performance.cpp
index 497bdea27..93a6b7313 100755
--- a/dom/performance/Performance.cpp
+++ b/dom/performance/Performance.cpp
@@ -13,12 +13,14 @@
#include "PerformanceMeasure.h"
#include "PerformanceObserver.h"
#include "PerformanceResourceTiming.h"
+#include "PerformanceService.h"
#include "PerformanceWorker.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/PerformanceBinding.h"
#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"
@@ -82,14 +84,12 @@ NS_IMPL_RELEASE_INHERITED(Performance, DOMEventTargetHelper)
/* static */ already_AddRefed<Performance>
Performance::CreateForMainThread(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
- nsITimedChannel* aChannel,
- Performance* aParentPerformance)
+ nsITimedChannel* aChannel)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<Performance> performance =
- new PerformanceMainThread(aWindow, aDOMTiming, aChannel,
- aParentPerformance);
+ new PerformanceMainThread(aWindow, aDOMTiming, aChannel);
return performance.forget();
}
@@ -121,6 +121,24 @@ Performance::Performance(nsPIDOMWindowInner* aWindow)
Performance::~Performance()
{}
+DOMHighResTimeStamp
+Performance::Now() const
+{
+ TimeDuration duration = TimeStamp::Now() - CreationTimeStamp();
+ return RoundTime(duration.ToMilliseconds());
+}
+
+DOMHighResTimeStamp
+Performance::TimeOrigin()
+{
+ if (!mPerformanceService) {
+ mPerformanceService = PerformanceService::GetOrCreate();
+ }
+
+ MOZ_ASSERT(mPerformanceService);
+ return mPerformanceService->TimeOrigin(CreationTimeStamp());
+}
+
JSObject*
Performance::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
@@ -245,7 +263,7 @@ Performance::ClearMarks(const Optional<nsAString>& aName)
DOMHighResTimeStamp
Performance::ResolveTimestampFromName(const nsAString& aName,
- ErrorResult& aRv)
+ ErrorResult& aRv)
{
AutoTArray<RefPtr<PerformanceEntry>, 1> arr;
DOMHighResTimeStamp ts;
diff --git a/dom/performance/Performance.h b/dom/performance/Performance.h
index bc70589a5..4debecc90 100644
--- a/dom/performance/Performance.h
+++ b/dom/performance/Performance.h
@@ -24,6 +24,7 @@ namespace dom {
class PerformanceEntry;
class PerformanceNavigation;
class PerformanceObserver;
+class PerformanceService;
class PerformanceTiming;
namespace workers {
@@ -45,8 +46,7 @@ public:
static already_AddRefed<Performance>
CreateForMainThread(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
- nsITimedChannel* aChannel,
- Performance* aParentPerformance);
+ nsITimedChannel* aChannel);
static already_AddRefed<Performance>
CreateForWorker(workers::WorkerPrivate* aWorkerPrivate);
@@ -54,21 +54,23 @@ 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;
void ClearResourceTimings();
- virtual DOMHighResTimeStamp Now() const = 0;
+ DOMHighResTimeStamp Now() const;
+
+ DOMHighResTimeStamp TimeOrigin();
void Mark(const nsAString& aName, ErrorResult& aRv);
@@ -101,8 +103,6 @@ public:
virtual nsITimedChannel* GetChannel() const = 0;
- virtual Performance* GetParentPerformance() const = 0;
-
protected:
Performance();
explicit Performance(nsPIDOMWindowInner* aWindow);
@@ -126,10 +126,16 @@ protected:
virtual DOMHighResTimeStamp CreationTime() const = 0;
- virtual bool IsPerformanceTimingAttribute(const nsAString& aName) = 0;
+ virtual bool IsPerformanceTimingAttribute(const nsAString& aName)
+ {
+ return false;
+ }
virtual DOMHighResTimeStamp
- GetPerformanceTimingFromString(const nsAString& aTimingName) = 0;
+ GetPerformanceTimingFromString(const nsAString& aTimingName)
+ {
+ return 0;
+ }
bool IsResourceEntryLimitReached() const
{
@@ -147,13 +153,15 @@ protected:
nsTObserverArray<PerformanceObserver*> mObservers;
-private:
+protected:
nsTArray<RefPtr<PerformanceEntry>> mUserEntries;
nsTArray<RefPtr<PerformanceEntry>> mResourceEntries;
uint64_t mResourceTimingBufferSize;
static const uint64_t kDefaultResourceTimingBufferSize = 150;
bool mPendingNotificationObserversTask;
+
+ RefPtr<PerformanceService> mPerformanceService;
};
} // namespace dom
diff --git a/dom/performance/PerformanceMainThread.cpp b/dom/performance/PerformanceMainThread.cpp
index 86d42c5f8..64c06d3ea 100644
--- a/dom/performance/PerformanceMainThread.cpp
+++ b/dom/performance/PerformanceMainThread.cpp
@@ -6,6 +6,7 @@
#include "PerformanceMainThread.h"
#include "PerformanceNavigation.h"
+#include "nsICacheInfoChannel.h"
namespace mozilla {
namespace dom {
@@ -16,7 +17,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PerformanceMainThread,
Performance)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTiming,
mNavigation,
- mParentPerformance)
+ mDocEntry)
tmp->mMozMemory = nullptr;
mozilla::DropJSObjects(this);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -25,7 +26,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PerformanceMainThread,
Performance)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTiming,
mNavigation,
- mParentPerformance)
+ mDocEntry)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -45,12 +46,10 @@ NS_INTERFACE_MAP_END_INHERITING(Performance)
PerformanceMainThread::PerformanceMainThread(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
- nsITimedChannel* aChannel,
- Performance* aParentPerformance)
+ nsITimedChannel* aChannel)
: Performance(aWindow)
, mDOMTiming(aDOMTiming)
, mChannel(aChannel)
- , mParentPerformance(aParentPerformance)
{
MOZ_ASSERT(aWindow, "Parent window object should be provided");
}
@@ -78,7 +77,7 @@ PerformanceTiming*
PerformanceMainThread::Timing()
{
if (!mTiming) {
- // For navigation timing, the third argument (an nsIHtttpChannel) is null
+ // For navigation timing, the third argument (an nsIHttpChannel) is null
// since the cross-domain redirect were already checked. The last argument
// (zero time) for performance.timing is the navigation start value.
mTiming = new PerformanceTiming(this, mChannel, nullptr,
@@ -108,12 +107,6 @@ PerformanceMainThread::Navigation()
return mNavigation;
}
-DOMHighResTimeStamp
-PerformanceMainThread::Now() const
-{
- return RoundTime(GetDOMTiming()->TimeStampToDOMHighRes(TimeStamp::Now()));
-}
-
/**
* An entry should be added only after the resource is loaded.
* This method is not thread safe and can only be called on the main thread.
@@ -161,27 +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);
- 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()) {
@@ -335,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
diff --git a/dom/performance/PerformanceMainThread.h b/dom/performance/PerformanceMainThread.h
index 84773f29b..9f0e185fc 100644
--- a/dom/performance/PerformanceMainThread.h
+++ b/dom/performance/PerformanceMainThread.h
@@ -17,16 +17,12 @@ class PerformanceMainThread final : public Performance
public:
PerformanceMainThread(nsPIDOMWindowInner* aWindow,
nsDOMNavigationTiming* aDOMTiming,
- nsITimedChannel* aChannel,
- Performance* aParentPerformance);
+ nsITimedChannel* aChannel);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PerformanceMainThread,
Performance)
- // Performance WebIDL methods
- DOMHighResTimeStamp Now() const override;
-
virtual PerformanceTiming* Timing() override;
virtual PerformanceNavigation* Navigation() override;
@@ -51,10 +47,14 @@ public:
return mChannel;
}
- virtual Performance* GetParentPerformance() const override
- {
- return mParentPerformance;
- }
+ // 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();
@@ -72,12 +72,13 @@ protected:
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
void DispatchBufferFullEvent() override;
+ void EnsureDocEntry();
+ RefPtr<PerformanceEntry> mDocEntry;
RefPtr<nsDOMNavigationTiming> mDOMTiming;
nsCOMPtr<nsITimedChannel> mChannel;
RefPtr<PerformanceTiming> mTiming;
RefPtr<PerformanceNavigation> mNavigation;
- RefPtr<Performance> mParentPerformance;
JS::Heap<JSObject*> mMozMemory;
};
diff --git a/dom/performance/PerformanceNavigationTiming.cpp b/dom/performance/PerformanceNavigationTiming.cpp
new file mode 100644
index 000000000..4e00b2bb2
--- /dev/null
+++ b/dom/performance/PerformanceNavigationTiming.cpp
@@ -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();
+}
diff --git a/dom/performance/PerformanceNavigationTiming.h b/dom/performance/PerformanceNavigationTiming.h
new file mode 100644
index 000000000..8555f1987
--- /dev/null
+++ b/dom/performance/PerformanceNavigationTiming.h
@@ -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___
diff --git a/dom/performance/PerformanceResourceTiming.cpp b/dom/performance/PerformanceResourceTiming.cpp
index 94df27408..2eaa4eb9a 100644
--- a/dom/performance/PerformanceResourceTiming.cpp
+++ b/dom/performance/PerformanceResourceTiming.cpp
@@ -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()
diff --git a/dom/performance/PerformanceResourceTiming.h b/dom/performance/PerformanceResourceTiming.h
index c2e6c0972..98a03327e 100644
--- a/dom/performance/PerformanceResourceTiming.h
+++ b/dom/performance/PerformanceResourceTiming.h
@@ -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;
diff --git a/dom/performance/PerformanceService.cpp b/dom/performance/PerformanceService.cpp
new file mode 100644
index 000000000..cf119af89
--- /dev/null
+++ b/dom/performance/PerformanceService.cpp
@@ -0,0 +1,46 @@
+/* -*- 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 "PerformanceService.h"
+
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/StaticMutex.h"
+#include "mozilla/StaticPtr.h"
+
+namespace mozilla {
+namespace dom {
+
+static StaticRefPtr<PerformanceService> gPerformanceService;
+static StaticMutex gPerformanceServiceMutex;
+
+/* static */ PerformanceService*
+PerformanceService::GetOrCreate()
+{
+ StaticMutexAutoLock al(gPerformanceServiceMutex);
+
+ if (!gPerformanceService) {
+ gPerformanceService = new PerformanceService();
+ ClearOnShutdown(&gPerformanceService);
+ }
+
+ return gPerformanceService;
+}
+
+DOMHighResTimeStamp
+PerformanceService::TimeOrigin(const TimeStamp& aCreationTimeStamp) const
+{
+ return (aCreationTimeStamp - mCreationTimeStamp).ToMilliseconds() +
+ (mCreationEpochTime / PR_USEC_PER_MSEC);
+}
+
+PerformanceService::PerformanceService()
+{
+ mCreationTimeStamp = TimeStamp::Now();
+ mCreationEpochTime = PR_Now();
+}
+
+} // dom namespace
+} // mozilla namespace
diff --git a/dom/performance/PerformanceService.h b/dom/performance/PerformanceService.h
new file mode 100644
index 000000000..9abbd674d
--- /dev/null
+++ b/dom/performance/PerformanceService.h
@@ -0,0 +1,48 @@
+/* -*- 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 dom_performance_PerformanceService_h
+#define dom_performance_PerformanceService_h
+
+#include "mozilla/TimeStamp.h"
+#include "nsCOMPtr.h"
+#include "nsDOMNavigationTiming.h"
+
+namespace mozilla {
+namespace dom {
+
+// This class is thread-safe.
+
+// We use this singleton for having the correct value of performance.timeOrigin.
+// This value must be calculated on top of the pair:
+// - mCreationTimeStamp (monotonic clock)
+// - mCreationEpochTime (unix epoch time)
+// These 2 values must be taken "at the same time" in order to be used
+// correctly.
+
+class PerformanceService
+{
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PerformanceService)
+
+ static PerformanceService*
+ GetOrCreate();
+
+ DOMHighResTimeStamp
+ TimeOrigin(const TimeStamp& aCreationTimeStamp) const;
+
+private:
+ PerformanceService();
+ ~PerformanceService() = default;
+
+ TimeStamp mCreationTimeStamp;
+ PRTime mCreationEpochTime;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // dom_performance_PerformanceService_h
diff --git a/dom/performance/PerformanceTiming.h b/dom/performance/PerformanceTiming.h
index 584ae0816..435e1bca1 100755
--- a/dom/performance/PerformanceTiming.h
+++ b/dom/performance/PerformanceTiming.h
@@ -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();
diff --git a/dom/performance/PerformanceWorker.cpp b/dom/performance/PerformanceWorker.cpp
index 85ca2ccd8..f10c58446 100644
--- a/dom/performance/PerformanceWorker.cpp
+++ b/dom/performance/PerformanceWorker.cpp
@@ -23,37 +23,6 @@ PerformanceWorker::~PerformanceWorker()
mWorkerPrivate->AssertIsOnWorkerThread();
}
-DOMHighResTimeStamp
-PerformanceWorker::Now() const
-{
- TimeDuration duration =
- TimeStamp::Now() - mWorkerPrivate->NowBaseTimeStamp();
- return RoundTime(duration.ToMilliseconds());
-}
-
-// To be removed once bug 1124165 lands
-bool
-PerformanceWorker::IsPerformanceTimingAttribute(const nsAString& aName)
-{
- // In workers we just support navigationStart.
- return aName.EqualsASCII("navigationStart");
-}
-
-DOMHighResTimeStamp
-PerformanceWorker::GetPerformanceTimingFromString(const nsAString& aProperty)
-{
- if (!IsPerformanceTimingAttribute(aProperty)) {
- return 0;
- }
-
- if (aProperty.EqualsLiteral("navigationStart")) {
- return mWorkerPrivate->NowBaseTime();
- }
-
- MOZ_CRASH("IsPerformanceTimingAttribute and GetPerformanceTimingFromString are out of sync");
- return 0;
-}
-
void
PerformanceWorker::InsertUserEntry(PerformanceEntry* aEntry)
{
@@ -72,13 +41,13 @@ PerformanceWorker::InsertUserEntry(PerformanceEntry* aEntry)
TimeStamp
PerformanceWorker::CreationTimeStamp() const
{
- return mWorkerPrivate->NowBaseTimeStamp();
+ return mWorkerPrivate->CreationTimeStamp();
}
DOMHighResTimeStamp
PerformanceWorker::CreationTime() const
{
- return mWorkerPrivate->NowBaseTime();
+ return mWorkerPrivate->CreationTime();
}
} // dom namespace
diff --git a/dom/performance/PerformanceWorker.h b/dom/performance/PerformanceWorker.h
index 7eef0d974..346bdd026 100644
--- a/dom/performance/PerformanceWorker.h
+++ b/dom/performance/PerformanceWorker.h
@@ -21,9 +21,6 @@ class PerformanceWorker final : public Performance
public:
explicit PerformanceWorker(workers::WorkerPrivate* aWorkerPrivate);
- // Performance WebIDL methods
- DOMHighResTimeStamp Now() const override;
-
virtual PerformanceTiming* Timing() override
{
MOZ_CRASH("This should not be called on workers.");
@@ -64,12 +61,6 @@ public:
return nullptr;
}
- virtual Performance* GetParentPerformance() const override
- {
- MOZ_CRASH("This should not be called on workers.");
- return nullptr;
- }
-
protected:
~PerformanceWorker();
@@ -80,11 +71,6 @@ protected:
void InsertUserEntry(PerformanceEntry* aEntry) override;
- bool IsPerformanceTimingAttribute(const nsAString& aName) override;
-
- DOMHighResTimeStamp
- GetPerformanceTimingFromString(const nsAString& aTimingName) override;
-
void DispatchBufferFullEvent() override
{
MOZ_CRASH("This should not be called on workers.");
diff --git a/dom/performance/moz.build b/dom/performance/moz.build
index 3286a0a4c..e1f96fec8 100644
--- a/dom/performance/moz.build
+++ b/dom/performance/moz.build
@@ -10,9 +10,11 @@ EXPORTS.mozilla.dom += [
'PerformanceMark.h',
'PerformanceMeasure.h',
'PerformanceNavigation.h',
+ 'PerformanceNavigationTiming.h',
'PerformanceObserver.h',
'PerformanceObserverEntryList.h',
'PerformanceResourceTiming.h',
+ 'PerformanceService.h',
'PerformanceTiming.h',
]
@@ -23,9 +25,11 @@ UNIFIED_SOURCES += [
'PerformanceMark.cpp',
'PerformanceMeasure.cpp',
'PerformanceNavigation.cpp',
+ 'PerformanceNavigationTiming.cpp',
'PerformanceObserver.cpp',
'PerformanceObserverEntryList.cpp',
'PerformanceResourceTiming.cpp',
+ 'PerformanceService.cpp',
'PerformanceTiming.cpp',
'PerformanceWorker.cpp',
]
diff --git a/dom/performance/tests/mochitest.ini b/dom/performance/tests/mochitest.ini
index 7005637e1..bee0b2e70 100644
--- a/dom/performance/tests/mochitest.ini
+++ b/dom/performance/tests/mochitest.ini
@@ -13,3 +13,4 @@ support-files =
[test_worker_observer.html]
[test_sharedWorker_performance_user_timing.html]
[test_worker_performance_now.html]
+[test_timeOrigin.html]
diff --git a/dom/performance/tests/test_performance_user_timing.js b/dom/performance/tests/test_performance_user_timing.js
index cd8261bbd..a15dbebb6 100644
--- a/dom/performance/tests/test_performance_user_timing.js
+++ b/dom/performance/tests/test_performance_user_timing.js
@@ -126,15 +126,18 @@ var steps = [
},
// Test measure
function () {
- ok(true, "Running measure addition with no start/end time test");
- performance.measure("test");
- var measures = performance.getEntriesByType("measure");
- is(measures.length, 1, "number of measures should be 1");
- var measure = measures[0];
- is(measure.name, "test", "measure name should be 'test'");
- is(measure.entryType, "measure", "measure type should be 'measure'");
- is(measure.startTime, 0, "measure start time should be zero");
- ok(measure.duration >= 0, "measure duration should not be negative");
+ // We don't have navigationStart in workers.
+ if ("window" in self) {
+ ok(true, "Running measure addition with no start/end time test");
+ performance.measure("test", "navigationStart");
+ var measures = performance.getEntriesByType("measure");
+ is(measures.length, 1, "number of measures should be 1");
+ var measure = measures[0];
+ is(measure.name, "test", "measure name should be 'test'");
+ is(measure.entryType, "measure", "measure type should be 'measure'");
+ is(measure.startTime, 0, "measure start time should be zero");
+ ok(measure.duration >= 0, "measure duration should not be negative");
+ }
},
function () {
ok(true, "Running measure addition with only start time test");
diff --git a/dom/performance/tests/test_timeOrigin.html b/dom/performance/tests/test_timeOrigin.html
new file mode 100644
index 000000000..5a8a461f3
--- /dev/null
+++ b/dom/performance/tests/test_timeOrigin.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Test for performance.timeOrigin</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="test_performance_user_timing.js"></script>
+ </head>
+ <body>
+ <script type="text/js-worker" id="worker-src">
+ postMessage({ now: performance.now(), timeOrigin: performance.timeOrigin });
+ </script>
+
+ <script type="text/js-worker" id="shared-worker-src">
+ onconnect = function(evt) {
+ evt.ports[0].postMessage({ now: performance.now(), timeOrigin: performance.timeOrigin });
+ };
+ </script>
+
+ <script class="testbody" type="text/javascript">
+
+function testBasic() {
+ ok("timeOrigin" in performance, "Performance.timeOrigin exists.");
+ ok(performance.timeOrigin > 0, "TimeOrigin must be greater than 0.");
+ next();
+}
+
+function testWorker() {
+ var now = performance.now();
+
+ var blob = new Blob([ document.getElementById("worker-src").textContent ],
+ { type: "text/javascript" });
+ var w = new Worker(URL.createObjectURL(blob));
+ w.onmessage = function(e) {
+ ok (e.now + e.timeOrigin > now + performance.now, "Comparing worker.now and window.now");
+ next();
+ }
+}
+
+function testSharedWorker() {
+ var now = performance.now();
+
+ var blob = new Blob([ document.getElementById("shared-worker-src").textContent ],
+ { type: "text/javascript" });
+ var w = new SharedWorker(URL.createObjectURL(blob));
+ w.port.onmessage = function(e) {
+ ok (e.now + e.timeOrigin > now + performance.now, "Comparing worker.now and window.now");
+ next();
+ }
+}
+
+var tests = [ testBasic, testWorker, testSharedWorker ];
+function next() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ var test = tests.shift();
+ test();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(next);
+ </script>
+ </pre>
+ </body>
+</html>
diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html
index cbd08d8d4..4b47d2b4f 100644
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -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!
diff --git a/dom/webidl/Performance.webidl b/dom/webidl/Performance.webidl
index eaede253c..0bd2677df 100644
--- a/dom/webidl/Performance.webidl
+++ b/dom/webidl/Performance.webidl
@@ -17,6 +17,9 @@ typedef sequence <PerformanceEntry> PerformanceEntryList;
interface Performance {
[DependsOn=DeviceState, Affects=Nothing]
DOMHighResTimeStamp now();
+
+ [Constant]
+ readonly attribute DOMHighResTimeStamp timeOrigin;
};
[Exposed=Window]
diff --git a/dom/webidl/PerformanceNavigationTiming.webidl b/dom/webidl/PerformanceNavigationTiming.webidl
new file mode 100644
index 000000000..fa3ecaec4
--- /dev/null
+++ b/dom/webidl/PerformanceNavigationTiming.webidl
@@ -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;
+};
diff --git a/dom/webidl/PerformanceTiming.webidl b/dom/webidl/PerformanceTiming.webidl
index e14201440..4aa403a50 100644
--- a/dom/webidl/PerformanceTiming.webidl
+++ b/dom/webidl/PerformanceTiming.webidl
@@ -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;
};
diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build
index 8682aee97..8469c9001 100644
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -347,6 +347,7 @@ WEBIDL_FILES = [
'PerformanceMark.webidl',
'PerformanceMeasure.webidl',
'PerformanceNavigation.webidl',
+ 'PerformanceNavigationTiming.webidl',
'PerformanceObserver.webidl',
'PerformanceObserverEntryList.webidl',
'PerformanceResourceTiming.webidl',
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
index bd8a33032..8848e881a 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -2419,8 +2419,6 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
MOZ_ASSERT_IF(mIsChromeWorker, mIsSecureContext);
MOZ_ASSERT(IsDedicatedWorker());
- mNowBaseTimeStamp = aParent->NowBaseTimeStamp();
- mNowBaseTimeHighRes = aParent->NowBaseTime();
if (aParent->mParentFrozen) {
Freeze(nullptr);
@@ -2451,18 +2449,6 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
.creationOptions().setSecureContext(true);
}
- if (IsDedicatedWorker() && mLoadInfo.mWindow &&
- mLoadInfo.mWindow->GetPerformance()) {
- mNowBaseTimeStamp = mLoadInfo.mWindow->GetPerformance()->GetDOMTiming()->
- GetNavigationStartTimeStamp();
- mNowBaseTimeHighRes =
- mLoadInfo.mWindow->GetPerformance()->GetDOMTiming()->
- GetNavigationStartHighRes();
- } else {
- mNowBaseTimeStamp = CreationTimeStamp();
- mNowBaseTimeHighRes = CreationTime();
- }
-
// Our parent can get suspended after it initiates the async creation
// of a new worker thread. In this case suspend the new worker as well.
if (mLoadInfo.mWindow && mLoadInfo.mWindow->IsSuspended()) {
diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
index 465c0f9a3..28283bed7 100644
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -216,8 +216,6 @@ private:
WorkerType mWorkerType;
TimeStamp mCreationTimeStamp;
DOMHighResTimeStamp mCreationTimeHighRes;
- TimeStamp mNowBaseTimeStamp;
- DOMHighResTimeStamp mNowBaseTimeHighRes;
protected:
// The worker is owned by its thread, which is represented here. This is set
@@ -579,14 +577,11 @@ public:
return mCreationTimeHighRes;
}
- TimeStamp NowBaseTimeStamp() const
+ DOMHighResTimeStamp TimeStampToDOMHighRes(const TimeStamp& aTimeStamp) const
{
- return mNowBaseTimeStamp;
- }
-
- DOMHighResTimeStamp NowBaseTime() const
- {
- return mNowBaseTimeHighRes;
+ MOZ_ASSERT(!aTimeStamp.IsNull());
+ TimeDuration duration = aTimeStamp - mCreationTimeStamp;
+ return duration.ToMilliseconds();
}
nsIPrincipal*
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index 903665ff8..4239c83bd 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -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);
diff --git a/testing/web-platform/meta/MANIFEST.json b/testing/web-platform/meta/MANIFEST.json
index 3c7df67fa..496f8e3cb 100644
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -31100,6 +31100,10 @@
"url": "/user-timing/test_user_timing_mark.html"
},
{
+ "path": "user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.html",
+ "url": "/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.html"
+ },
+ {
"path": "user-timing/test_user_timing_mark_and_measure_exception_when_invoke_without_parameter.html",
"url": "/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_without_parameter.html"
},
diff --git a/testing/web-platform/tests/user-timing/resources/webperftestharness.js b/testing/web-platform/tests/user-timing/resources/webperftestharness.js
index 750946dde..f1597bbe7 100644
--- a/testing/web-platform/tests/user-timing/resources/webperftestharness.js
+++ b/testing/web-platform/tests/user-timing/resources/webperftestharness.js
@@ -12,7 +12,7 @@ policies and contribution forms [3].
// Helper Functions for NavigationTiming W3C tests
//
-var performanceNamespace = window.performance;
+var performanceNamespace = self.performance;
var timingAttributes = [
'connectEnd',
'connectStart',
diff --git a/testing/web-platform/tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.html b/testing/web-platform/tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.html
new file mode 100644
index 000000000..aea8cb6e9
--- /dev/null
+++ b/testing/web-platform/tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>exception test of performance.mark and performance.measure</title>
+ <meta rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ </head>
+ <body>
+ <script>
+ setup({explicit_done: true});
+ test_namespace();
+
+ test(function() {
+ for (var i in timingAttributes) {
+ assert_throws("SyntaxError", function() { window.performance.mark(timingAttributes[i]); });
+ assert_throws("SyntaxError", function() { window.performance.measure(timingAttributes[i]); });
+ }
+ }, "performance.mark and performance.measure should throw if used with timing attribute values");
+
+ fetch_tests_from_worker(new Worker("test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.js"));
+
+ done();
+
+ </script>
+ <h1>Description</h1>
+ <p>This test validates exception scenarios of invoking mark() and measure() with timing attributes as value.</p>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.js b/testing/web-platform/tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.js
new file mode 100644
index 000000000..f015402f9
--- /dev/null
+++ b/testing/web-platform/tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.js
@@ -0,0 +1,14 @@
+importScripts("/resources/testharness.js");
+importScripts("resources/webperftestharness.js");
+
+test(function() {
+ for (var i in timingAttributes) {
+ performance.mark(timingAttributes[i]);
+ performance.clearMarks(timingAttributes[i]);
+
+ performance.measure(timingAttributes[i]);
+ performance.clearMeasures(timingAttributes[i]);
+ }
+}, "performance.mark and performance.measure should not throw if used with timing attribute values in workers");
+
+done();