author | Andrea Marchesini <amarchesini@mozilla.com> |
Thu, 09 Jun 2016 12:43:56 +0200 | |
changeset 301256 | 2401b6b118b399ad8c44f70b8ce0423f1f4b67b3 |
parent 301255 | 7ec00141f0a253efb4307f8105483ab0895775b1 |
child 301257 | 0c2668c814d02fb58967bb7fee6967e6df4dd6b6 |
push id | 78267 |
push user | amarchesini@mozilla.com |
push date | Thu, 09 Jun 2016 10:45:17 +0000 |
treeherder | mozilla-inbound@0c2668c814d0 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | smaug |
bugs | 1278843 |
milestone | 50.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -889,20 +889,16 @@ DOMInterfaces = { 'nativeType': 'nsPerformance', }, { 'nativeType': 'mozilla::dom::workers::Performance', 'headerFile': 'mozilla/dom/workers/bindings/Performance.h', 'workers': True, }], -'PerformanceTiming': { - 'headerFile': 'nsPerformance.h' -}, - 'PerformanceNavigation': { 'headerFile': 'nsPerformance.h' }, 'Plugin': { 'headerFile' : 'nsPluginArray.h', 'nativeType': 'nsPluginElement', },
--- a/dom/performance/PerformanceResourceTiming.h +++ b/dom/performance/PerformanceResourceTiming.h @@ -8,16 +8,17 @@ #define mozilla_dom_PerformanceResourceTiming_h___ #include "nsCOMPtr.h" #include "nsPerformance.h" #include "nsIChannel.h" #include "nsITimedChannel.h" #include "nsDOMNavigationTiming.h" #include "PerformanceEntry.h" +#include "PerformanceTiming.h" namespace mozilla { namespace dom { // http://www.w3.org/TR/resource-timing/#performanceresourcetiming class PerformanceResourceTiming final : public PerformanceEntry { public:
new file mode 100644 --- /dev/null +++ b/dom/performance/PerformanceTiming.cpp @@ -0,0 +1,361 @@ +/* -*- 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 "PerformanceTiming.h" +#include "mozilla/dom/PerformanceTimingBinding.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PerformanceTiming, mPerformance) + +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PerformanceTiming, AddRef) +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PerformanceTiming, Release) + +PerformanceTiming::PerformanceTiming(nsPerformance* aPerformance, + nsITimedChannel* aChannel, + nsIHttpChannel* aHttpChannel, + DOMHighResTimeStamp aZeroTime) + : mPerformance(aPerformance), + mFetchStart(0.0), + mZeroTime(aZeroTime), + mRedirectCount(0), + mTimingAllowed(true), + mAllRedirectsSameOrigin(true), + mInitialized(!!aChannel), + mReportCrossOriginRedirect(true) +{ + MOZ_ASSERT(aPerformance, "Parent performance object should be provided"); + + 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; + } + + 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->GetAllRedirectsSameOrigin(&mAllRedirectsSameOrigin); + aChannel->GetRedirectCount(&mRedirectCount); + aChannel->GetRedirectStart(&mRedirectStart); + aChannel->GetRedirectEnd(&mRedirectEnd); + aChannel->GetDomainLookupStart(&mDomainLookupStart); + aChannel->GetDomainLookupEnd(&mDomainLookupEnd); + aChannel->GetConnectStart(&mConnectStart); + aChannel->GetConnectEnd(&mConnectEnd); + aChannel->GetRequestStart(&mRequestStart); + aChannel->GetResponseStart(&mResponseStart); + aChannel->GetCacheReadStart(&mCacheReadStart); + aChannel->GetResponseEnd(&mResponseEnd); + aChannel->GetCacheReadEnd(&mCacheReadEnd); + } +} + +PerformanceTiming::~PerformanceTiming() +{ +} + +DOMHighResTimeStamp +PerformanceTiming::FetchStartHighRes() +{ + if (!mFetchStart) { + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return mZeroTime; + } + MOZ_ASSERT(!mAsyncOpen.IsNull(), "The fetch start time stamp should always be " + "valid if the performance timing is enabled"); + mFetchStart = (!mAsyncOpen.IsNull()) + ? TimeStampToDOMHighRes(mAsyncOpen) + : 0.0; + } + return mFetchStart; +} + +DOMTimeMilliSec +PerformanceTiming::FetchStart() +{ + return static_cast<int64_t>(FetchStartHighRes()); +} + +bool +PerformanceTiming::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, + nsITimedChannel* aChannel) +{ + if (!IsInitialized()) { + return false; + } + + // Check that the current document passes the ckeck. + nsCOMPtr<nsILoadInfo> loadInfo; + aResourceChannel->GetLoadInfo(getter_AddRefs(loadInfo)); + if (!loadInfo) { + return false; + } + + // TYPE_DOCUMENT loads have no loadingPrincipal. And that's OK, because we + // never actually need to have a performance timing entry for TYPE_DOCUMENT + // loads. + if (loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT) { + return false; + } + + nsCOMPtr<nsIPrincipal> principal = loadInfo->LoadingPrincipal(); + + // Check if the resource is either same origin as the page that started + // the load, or if the response contains the proper Timing-Allow-Origin + // header with the domain of the page that started the load. + return aChannel->TimingAllowCheck(principal); +} + +bool +PerformanceTiming::TimingAllowed() const +{ + return mTimingAllowed; +} + +uint16_t +PerformanceTiming::GetRedirectCount() const +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return 0; + } + if (!mAllRedirectsSameOrigin) { + return 0; + } + return mRedirectCount; +} + +bool +PerformanceTiming::ShouldReportCrossOriginRedirect() const +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return false; + } + + // If the redirect count is 0, or if one of the cross-origin + // redirects doesn't have the proper Timing-Allow-Origin header, + // then RedirectStart and RedirectEnd will be set to zero + return (mRedirectCount != 0) && mReportCrossOriginRedirect; +} + +/** + * RedirectStartHighRes() is used by both the navigation timing and the + * resource timing. Since, navigation timing and resource timing check and + * interpret cross-domain redirects in a different manner, + * RedirectStartHighRes() will make no checks for cross-domain redirect. + * It's up to the consumers of this method (PerformanceTiming::RedirectStart() + * and PerformanceResourceTiming::RedirectStart() to make such verifications. + * + * @return a valid timing if the Performance Timing is enabled + */ +DOMHighResTimeStamp +PerformanceTiming::RedirectStartHighRes() +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return mZeroTime; + } + return TimeStampToDOMHighResOrFetchStart(mRedirectStart); +} + +DOMTimeMilliSec +PerformanceTiming::RedirectStart() +{ + if (!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()); + } + return 0; +} + +/** + * RedirectEndHighRes() is used by both the navigation timing and the resource + * timing. Since, navigation timing and resource timing check and interpret + * cross-domain redirects in a different manner, RedirectEndHighRes() will make + * no checks for cross-domain redirect. It's up to the consumers of this method + * (PerformanceTiming::RedirectEnd() and + * PerformanceResourceTiming::RedirectEnd() to make such verifications. + * + * @return a valid timing if the Performance Timing is enabled + */ +DOMHighResTimeStamp +PerformanceTiming::RedirectEndHighRes() +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return mZeroTime; + } + return TimeStampToDOMHighResOrFetchStart(mRedirectEnd); +} + +DOMTimeMilliSec +PerformanceTiming::RedirectEnd() +{ + if (!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()); + } + return 0; +} + +DOMHighResTimeStamp +PerformanceTiming::DomainLookupStartHighRes() +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return mZeroTime; + } + return TimeStampToDOMHighResOrFetchStart(mDomainLookupStart); +} + +DOMTimeMilliSec +PerformanceTiming::DomainLookupStart() +{ + return static_cast<int64_t>(DomainLookupStartHighRes()); +} + +DOMHighResTimeStamp +PerformanceTiming::DomainLookupEndHighRes() +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return mZeroTime; + } + // Bug 1155008 - nsHttpTransaction is racy. Return DomainLookupStart when null + return mDomainLookupEnd.IsNull() ? DomainLookupStartHighRes() + : TimeStampToDOMHighRes(mDomainLookupEnd); +} + +DOMTimeMilliSec +PerformanceTiming::DomainLookupEnd() +{ + return static_cast<int64_t>(DomainLookupEndHighRes()); +} + +DOMHighResTimeStamp +PerformanceTiming::ConnectStartHighRes() +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return mZeroTime; + } + return mConnectStart.IsNull() ? DomainLookupEndHighRes() + : TimeStampToDOMHighRes(mConnectStart); +} + +DOMTimeMilliSec +PerformanceTiming::ConnectStart() +{ + return static_cast<int64_t>(ConnectStartHighRes()); +} + +DOMHighResTimeStamp +PerformanceTiming::ConnectEndHighRes() +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return mZeroTime; + } + // Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null + return mConnectEnd.IsNull() ? ConnectStartHighRes() + : TimeStampToDOMHighRes(mConnectEnd); +} + +DOMTimeMilliSec +PerformanceTiming::ConnectEnd() +{ + return static_cast<int64_t>(ConnectEndHighRes()); +} + +DOMHighResTimeStamp +PerformanceTiming::RequestStartHighRes() +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return mZeroTime; + } + return TimeStampToDOMHighResOrFetchStart(mRequestStart); +} + +DOMTimeMilliSec +PerformanceTiming::RequestStart() +{ + return static_cast<int64_t>(RequestStartHighRes()); +} + +DOMHighResTimeStamp +PerformanceTiming::ResponseStartHighRes() +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return mZeroTime; + } + if (mResponseStart.IsNull() || + (!mCacheReadStart.IsNull() && mCacheReadStart < mResponseStart)) { + mResponseStart = mCacheReadStart; + } + return TimeStampToDOMHighResOrFetchStart(mResponseStart); +} + +DOMTimeMilliSec +PerformanceTiming::ResponseStart() +{ + return static_cast<int64_t>(ResponseStartHighRes()); +} + +DOMHighResTimeStamp +PerformanceTiming::ResponseEndHighRes() +{ + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { + return mZeroTime; + } + if (mResponseEnd.IsNull() || + (!mCacheReadEnd.IsNull() && mCacheReadEnd < mResponseEnd)) { + mResponseEnd = mCacheReadEnd; + } + // Bug 1155008 - nsHttpTransaction is racy. Return ResponseStart when null + return mResponseEnd.IsNull() ? ResponseStartHighRes() + : TimeStampToDOMHighRes(mResponseEnd); +} + +DOMTimeMilliSec +PerformanceTiming::ResponseEnd() +{ + return static_cast<int64_t>(ResponseEndHighRes()); +} + +bool +PerformanceTiming::IsInitialized() const +{ + return mInitialized; +} + +JSObject* +PerformanceTiming::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) +{ + return PerformanceTimingBinding::Wrap(cx, this, aGivenProto); +} + +} // dom namespace +} // mozilla namespace
new file mode 100644 --- /dev/null +++ b/dom/performance/PerformanceTiming.h @@ -0,0 +1,278 @@ +/* -*- 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_PerformanceTiming_h +#define mozilla_dom_PerformanceTiming_h + +#include "mozilla/Attributes.h" +#include "nsContentUtils.h" +#include "nsDOMNavigationTiming.h" +#include "nsPerformance.h" +#include "nsWrapperCache.h" + +class nsIHttpChannel; +class nsITimedChannel; + +namespace mozilla { +namespace dom { + +// 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(nsPerformance* 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(); + } + + nsPerformance* GetParentObject() const + { + return mPerformance; + } + + /** + * @param aStamp + * The TimeStamp recorded for a specific event. This TimeStamp can + * be null. + * @return the duration of an event with a given TimeStamp, relative to the + * navigationStart TimeStamp (the moment the user landed on the + * page), if the given TimeStamp is valid. Otherwise, it will return + * the FetchStart timing value. + */ + inline DOMHighResTimeStamp TimeStampToDOMHighResOrFetchStart(TimeStamp aStamp) + { + return (!aStamp.IsNull()) + ? TimeStampToDOMHighRes(aStamp) + : FetchStartHighRes(); + } + + /** + * The nsITimedChannel records an absolute timestamp for each event. + * The nsDOMNavigationTiming will record the moment when the user landed on + * the page. This is a window.performance unique timestamp, so it can be used + * for all the events (navigation timing and resource timing events). + * + * 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 + * 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, + * this offset value is either 0 (for the resource timing), or equal to + * "performance.navigationStart" (for navigation timing). + * For the resource timing, mZeroTime is set to 0, causing the result to be a + * relative time. + * For the navigation timing, mZeroTime is set to "performance.navigationStart" + * causing the result be an absolute time. + * + * @param aStamp + * The TimeStamp recorded for a specific event. This TimeStamp can't + * be null. + * @return number of milliseconds value as one of: + * - relative to the navigation start time, time the user has landed on the + * page + * - an absolute wall clock time since the unix epoch + */ + inline DOMHighResTimeStamp TimeStampToDOMHighRes(TimeStamp aStamp) const + { + MOZ_ASSERT(!aStamp.IsNull()); + TimeDuration duration = + aStamp - GetDOMTiming()->GetNavigationStartTimeStamp(); + return duration.ToMilliseconds() + mZeroTime; + } + + virtual JSObject* WrapObject(JSContext *cx, + JS::Handle<JSObject*> aGivenProto) override; + + // PerformanceNavigation WebIDL methods + DOMTimeMilliSec NavigationStart() const + { + if (!nsContentUtils::IsPerformanceTimingEnabled()) { + return 0; + } + return GetDOMTiming()->GetNavigationStart(); + } + + DOMTimeMilliSec UnloadEventStart() + { + if (!nsContentUtils::IsPerformanceTimingEnabled()) { + return 0; + } + return GetDOMTiming()->GetUnloadEventStart(); + } + + DOMTimeMilliSec UnloadEventEnd() + { + if (!nsContentUtils::IsPerformanceTimingEnabled()) { + return 0; + } + return GetDOMTiming()->GetUnloadEventEnd(); + } + + uint16_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; + + // High resolution (used by resource timing) + DOMHighResTimeStamp FetchStartHighRes(); + DOMHighResTimeStamp RedirectStartHighRes(); + DOMHighResTimeStamp RedirectEndHighRes(); + DOMHighResTimeStamp DomainLookupStartHighRes(); + DOMHighResTimeStamp DomainLookupEndHighRes(); + DOMHighResTimeStamp ConnectStartHighRes(); + DOMHighResTimeStamp ConnectEndHighRes(); + DOMHighResTimeStamp RequestStartHighRes(); + DOMHighResTimeStamp ResponseStartHighRes(); + DOMHighResTimeStamp ResponseEndHighRes(); + + // Low resolution (used by navigation timing) + DOMTimeMilliSec FetchStart(); + DOMTimeMilliSec RedirectStart(); + DOMTimeMilliSec RedirectEnd(); + DOMTimeMilliSec DomainLookupStart(); + DOMTimeMilliSec DomainLookupEnd(); + DOMTimeMilliSec ConnectStart(); + DOMTimeMilliSec ConnectEnd(); + DOMTimeMilliSec RequestStart(); + DOMTimeMilliSec ResponseStart(); + DOMTimeMilliSec ResponseEnd(); + + DOMTimeMilliSec DomLoading() + { + if (!nsContentUtils::IsPerformanceTimingEnabled()) { + return 0; + } + return GetDOMTiming()->GetDomLoading(); + } + + DOMTimeMilliSec DomInteractive() const + { + if (!nsContentUtils::IsPerformanceTimingEnabled()) { + return 0; + } + return GetDOMTiming()->GetDomInteractive(); + } + + DOMTimeMilliSec DomContentLoadedEventStart() const + { + if (!nsContentUtils::IsPerformanceTimingEnabled()) { + return 0; + } + return GetDOMTiming()->GetDomContentLoadedEventStart(); + } + + DOMTimeMilliSec DomContentLoadedEventEnd() const + { + if (!nsContentUtils::IsPerformanceTimingEnabled()) { + return 0; + } + return GetDOMTiming()->GetDomContentLoadedEventEnd(); + } + + DOMTimeMilliSec DomComplete() const + { + if (!nsContentUtils::IsPerformanceTimingEnabled()) { + return 0; + } + return GetDOMTiming()->GetDomComplete(); + } + + DOMTimeMilliSec LoadEventStart() const + { + if (!nsContentUtils::IsPerformanceTimingEnabled()) { + return 0; + } + return GetDOMTiming()->GetLoadEventStart(); + } + + DOMTimeMilliSec LoadEventEnd() const + { + if (!nsContentUtils::IsPerformanceTimingEnabled()) { + return 0; + } + return GetDOMTiming()->GetLoadEventEnd(); + } + +private: + ~PerformanceTiming(); + + bool IsInitialized() const; + void InitializeTimingInfo(nsITimedChannel* aChannel); + + RefPtr<nsPerformance> 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 mRedirectStart; + TimeStamp mRedirectEnd; + TimeStamp mDomainLookupStart; + TimeStamp mDomainLookupEnd; + TimeStamp mConnectStart; + TimeStamp mConnectEnd; + TimeStamp mRequestStart; + TimeStamp mResponseStart; + TimeStamp mCacheReadStart; + TimeStamp mResponseEnd; + TimeStamp mCacheReadEnd; + uint16_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; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_PerformanceTiming_h
--- a/dom/performance/moz.build +++ b/dom/performance/moz.build @@ -10,26 +10,28 @@ EXPORTS += [ EXPORTS.mozilla.dom += [ 'PerformanceEntry.h', 'PerformanceMark.h', 'PerformanceMeasure.h', 'PerformanceObserver.h', 'PerformanceObserverEntryList.h', 'PerformanceResourceTiming.h', + 'PerformanceTiming.h', ] UNIFIED_SOURCES += [ 'nsPerformance.cpp', 'PerformanceEntry.cpp', 'PerformanceMark.cpp', 'PerformanceMeasure.cpp', 'PerformanceObserver.cpp', 'PerformanceObserverEntryList.cpp', 'PerformanceResourceTiming.cpp', + 'PerformanceTiming.cpp', ] LOCAL_INCLUDES += [ '/dom/workers', ] MOCHITEST_MANIFESTS += [ 'tests/mochitest.ini' ]
--- a/dom/performance/nsPerformance.cpp +++ b/dom/performance/nsPerformance.cpp @@ -18,17 +18,16 @@ #include "PerformanceEntry.h" #include "PerformanceMark.h" #include "PerformanceMeasure.h" #include "PerformanceObserver.h" #include "PerformanceResourceTiming.h" #include "mozilla/ErrorResult.h" #include "mozilla/dom/PerformanceBinding.h" #include "mozilla/dom/PerformanceEntryEvent.h" -#include "mozilla/dom/PerformanceTimingBinding.h" #include "mozilla/dom/PerformanceNavigationBinding.h" #include "mozilla/dom/PerformanceObserverBinding.h" #include "mozilla/Preferences.h" #include "mozilla/IntegerPrintfMacros.h" #include "mozilla/TimeStamp.h" #include "js/HeapAPI.h" #include "GeckoProfiler.h" #include "WorkerPrivate.h" @@ -39,364 +38,16 @@ #else #define PERFLOG(msg, ...) printf_stderr(msg, ##__VA_ARGS__) #endif using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::dom::workers; -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PerformanceTiming, mPerformance) - -NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PerformanceTiming, AddRef) -NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PerformanceTiming, Release) - -PerformanceTiming::PerformanceTiming(nsPerformance* aPerformance, - nsITimedChannel* aChannel, - nsIHttpChannel* aHttpChannel, - DOMHighResTimeStamp aZeroTime) - : mPerformance(aPerformance), - mFetchStart(0.0), - mZeroTime(aZeroTime), - mRedirectCount(0), - mTimingAllowed(true), - mAllRedirectsSameOrigin(true), - mInitialized(!!aChannel), - mReportCrossOriginRedirect(true) -{ - MOZ_ASSERT(aPerformance, "Parent performance object should be provided"); - - 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; - } - - 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->GetAllRedirectsSameOrigin(&mAllRedirectsSameOrigin); - aChannel->GetRedirectCount(&mRedirectCount); - aChannel->GetRedirectStart(&mRedirectStart); - aChannel->GetRedirectEnd(&mRedirectEnd); - aChannel->GetDomainLookupStart(&mDomainLookupStart); - aChannel->GetDomainLookupEnd(&mDomainLookupEnd); - aChannel->GetConnectStart(&mConnectStart); - aChannel->GetConnectEnd(&mConnectEnd); - aChannel->GetRequestStart(&mRequestStart); - aChannel->GetResponseStart(&mResponseStart); - aChannel->GetCacheReadStart(&mCacheReadStart); - aChannel->GetResponseEnd(&mResponseEnd); - aChannel->GetCacheReadEnd(&mCacheReadEnd); - } -} - -PerformanceTiming::~PerformanceTiming() -{ -} - -DOMHighResTimeStamp -PerformanceTiming::FetchStartHighRes() -{ - if (!mFetchStart) { - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return mZeroTime; - } - MOZ_ASSERT(!mAsyncOpen.IsNull(), "The fetch start time stamp should always be " - "valid if the performance timing is enabled"); - mFetchStart = (!mAsyncOpen.IsNull()) - ? TimeStampToDOMHighRes(mAsyncOpen) - : 0.0; - } - return mFetchStart; -} - -DOMTimeMilliSec -PerformanceTiming::FetchStart() -{ - return static_cast<int64_t>(FetchStartHighRes()); -} - -bool -PerformanceTiming::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, - nsITimedChannel* aChannel) -{ - if (!IsInitialized()) { - return false; - } - - // Check that the current document passes the ckeck. - nsCOMPtr<nsILoadInfo> loadInfo; - aResourceChannel->GetLoadInfo(getter_AddRefs(loadInfo)); - if (!loadInfo) { - return false; - } - - // TYPE_DOCUMENT loads have no loadingPrincipal. And that's OK, because we - // never actually need to have a performance timing entry for TYPE_DOCUMENT - // loads. - if (loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT) { - return false; - } - - nsCOMPtr<nsIPrincipal> principal = loadInfo->LoadingPrincipal(); - - // Check if the resource is either same origin as the page that started - // the load, or if the response contains the proper Timing-Allow-Origin - // header with the domain of the page that started the load. - return aChannel->TimingAllowCheck(principal); -} - -bool -PerformanceTiming::TimingAllowed() const -{ - return mTimingAllowed; -} - -uint16_t -PerformanceTiming::GetRedirectCount() const -{ - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return 0; - } - if (!mAllRedirectsSameOrigin) { - return 0; - } - return mRedirectCount; -} - -bool -PerformanceTiming::ShouldReportCrossOriginRedirect() const -{ - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return false; - } - - // If the redirect count is 0, or if one of the cross-origin - // redirects doesn't have the proper Timing-Allow-Origin header, - // then RedirectStart and RedirectEnd will be set to zero - return (mRedirectCount != 0) && mReportCrossOriginRedirect; -} - -/** - * RedirectStartHighRes() is used by both the navigation timing and the - * resource timing. Since, navigation timing and resource timing check and - * interpret cross-domain redirects in a different manner, - * RedirectStartHighRes() will make no checks for cross-domain redirect. - * It's up to the consumers of this method (PerformanceTiming::RedirectStart() - * and PerformanceResourceTiming::RedirectStart() to make such verifications. - * - * @return a valid timing if the Performance Timing is enabled - */ -DOMHighResTimeStamp -PerformanceTiming::RedirectStartHighRes() -{ - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return mZeroTime; - } - return TimeStampToDOMHighResOrFetchStart(mRedirectStart); -} - -DOMTimeMilliSec -PerformanceTiming::RedirectStart() -{ - if (!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()); - } - return 0; -} - -/** - * RedirectEndHighRes() is used by both the navigation timing and the resource - * timing. Since, navigation timing and resource timing check and interpret - * cross-domain redirects in a different manner, RedirectEndHighRes() will make - * no checks for cross-domain redirect. It's up to the consumers of this method - * (PerformanceTiming::RedirectEnd() and - * PerformanceResourceTiming::RedirectEnd() to make such verifications. - * - * @return a valid timing if the Performance Timing is enabled - */ -DOMHighResTimeStamp -PerformanceTiming::RedirectEndHighRes() -{ - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return mZeroTime; - } - return TimeStampToDOMHighResOrFetchStart(mRedirectEnd); -} - -DOMTimeMilliSec -PerformanceTiming::RedirectEnd() -{ - if (!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()); - } - return 0; -} - -DOMHighResTimeStamp -PerformanceTiming::DomainLookupStartHighRes() -{ - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return mZeroTime; - } - return TimeStampToDOMHighResOrFetchStart(mDomainLookupStart); -} - -DOMTimeMilliSec -PerformanceTiming::DomainLookupStart() -{ - return static_cast<int64_t>(DomainLookupStartHighRes()); -} - -DOMHighResTimeStamp -PerformanceTiming::DomainLookupEndHighRes() -{ - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return mZeroTime; - } - // Bug 1155008 - nsHttpTransaction is racy. Return DomainLookupStart when null - return mDomainLookupEnd.IsNull() ? DomainLookupStartHighRes() - : TimeStampToDOMHighRes(mDomainLookupEnd); -} - -DOMTimeMilliSec -PerformanceTiming::DomainLookupEnd() -{ - return static_cast<int64_t>(DomainLookupEndHighRes()); -} - -DOMHighResTimeStamp -PerformanceTiming::ConnectStartHighRes() -{ - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return mZeroTime; - } - return mConnectStart.IsNull() ? DomainLookupEndHighRes() - : TimeStampToDOMHighRes(mConnectStart); -} - -DOMTimeMilliSec -PerformanceTiming::ConnectStart() -{ - return static_cast<int64_t>(ConnectStartHighRes()); -} - -DOMHighResTimeStamp -PerformanceTiming::ConnectEndHighRes() -{ - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return mZeroTime; - } - // Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null - return mConnectEnd.IsNull() ? ConnectStartHighRes() - : TimeStampToDOMHighRes(mConnectEnd); -} - -DOMTimeMilliSec -PerformanceTiming::ConnectEnd() -{ - return static_cast<int64_t>(ConnectEndHighRes()); -} - -DOMHighResTimeStamp -PerformanceTiming::RequestStartHighRes() -{ - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return mZeroTime; - } - return TimeStampToDOMHighResOrFetchStart(mRequestStart); -} - -DOMTimeMilliSec -PerformanceTiming::RequestStart() -{ - return static_cast<int64_t>(RequestStartHighRes()); -} - -DOMHighResTimeStamp -PerformanceTiming::ResponseStartHighRes() -{ - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return mZeroTime; - } - if (mResponseStart.IsNull() || - (!mCacheReadStart.IsNull() && mCacheReadStart < mResponseStart)) { - mResponseStart = mCacheReadStart; - } - return TimeStampToDOMHighResOrFetchStart(mResponseStart); -} - -DOMTimeMilliSec -PerformanceTiming::ResponseStart() -{ - return static_cast<int64_t>(ResponseStartHighRes()); -} - -DOMHighResTimeStamp -PerformanceTiming::ResponseEndHighRes() -{ - if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { - return mZeroTime; - } - if (mResponseEnd.IsNull() || - (!mCacheReadEnd.IsNull() && mCacheReadEnd < mResponseEnd)) { - mResponseEnd = mCacheReadEnd; - } - // Bug 1155008 - nsHttpTransaction is racy. Return ResponseStart when null - return mResponseEnd.IsNull() ? ResponseStartHighRes() - : TimeStampToDOMHighRes(mResponseEnd); -} - -DOMTimeMilliSec -PerformanceTiming::ResponseEnd() -{ - return static_cast<int64_t>(ResponseEndHighRes()); -} - -bool -PerformanceTiming::IsInitialized() const -{ - return mInitialized; -} - -JSObject* -PerformanceTiming::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) -{ - return PerformanceTimingBinding::Wrap(cx, this, aGivenProto); -} - - NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PerformanceNavigation, mPerformance) NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PerformanceNavigation, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PerformanceNavigation, Release) PerformanceNavigation::PerformanceNavigation(nsPerformance* aPerformance) : mPerformance(aPerformance) { @@ -408,16 +59,21 @@ PerformanceNavigation::~PerformanceNavig } JSObject* PerformanceNavigation::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) { return PerformanceNavigationBinding::Wrap(cx, this, aGivenProto); } +uint16_t +PerformanceNavigation::RedirectCount() const +{ + return GetPerformanceTiming()->GetRedirectCount(); +} NS_IMPL_CYCLE_COLLECTION_CLASS(nsPerformance) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsPerformance, PerformanceBase) NS_IMPL_CYCLE_COLLECTION_UNLINK(mTiming, mNavigation, mParentPerformance) tmp->mMozMemory = nullptr;
--- a/dom/performance/nsPerformance.h +++ b/dom/performance/nsPerformance.h @@ -25,242 +25,17 @@ class nsIHttpChannel; namespace mozilla { class ErrorResult; namespace dom { class PerformanceEntry; class PerformanceObserver; - -// 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(nsPerformance* 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; - - nsPerformance* GetParentObject() const - { - return mPerformance; - } - - /** - * @param aStamp - * The TimeStamp recorded for a specific event. This TimeStamp can - * be null. - * @return the duration of an event with a given TimeStamp, relative to the - * navigationStart TimeStamp (the moment the user landed on the - * page), if the given TimeStamp is valid. Otherwise, it will return - * the FetchStart timing value. - */ - inline DOMHighResTimeStamp TimeStampToDOMHighResOrFetchStart(TimeStamp aStamp) - { - return (!aStamp.IsNull()) - ? TimeStampToDOMHighRes(aStamp) - : FetchStartHighRes(); - } - - /** - * The nsITimedChannel records an absolute timestamp for each event. - * The nsDOMNavigationTiming will record the moment when the user landed on - * the page. This is a window.performance unique timestamp, so it can be used - * for all the events (navigation timing and resource timing events). - * - * 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 - * 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, - * this offset value is either 0 (for the resource timing), or equal to - * "performance.navigationStart" (for navigation timing). - * For the resource timing, mZeroTime is set to 0, causing the result to be a - * relative time. - * For the navigation timing, mZeroTime is set to "performance.navigationStart" - * causing the result be an absolute time. - * - * @param aStamp - * The TimeStamp recorded for a specific event. This TimeStamp can't - * be null. - * @return number of milliseconds value as one of: - * - relative to the navigation start time, time the user has landed on the - * page - * - an absolute wall clock time since the unix epoch - */ - inline DOMHighResTimeStamp TimeStampToDOMHighRes(TimeStamp aStamp) const - { - MOZ_ASSERT(!aStamp.IsNull()); - TimeDuration duration = - aStamp - GetDOMTiming()->GetNavigationStartTimeStamp(); - return duration.ToMilliseconds() + mZeroTime; - } - - virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override; - - // PerformanceNavigation WebIDL methods - DOMTimeMilliSec NavigationStart() const { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { - return 0; - } - return GetDOMTiming()->GetNavigationStart(); - } - DOMTimeMilliSec UnloadEventStart() { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { - return 0; - } - return GetDOMTiming()->GetUnloadEventStart(); - } - DOMTimeMilliSec UnloadEventEnd() { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { - return 0; - } - return GetDOMTiming()->GetUnloadEventEnd(); - } - - uint16_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; - - // High resolution (used by resource timing) - DOMHighResTimeStamp FetchStartHighRes(); - DOMHighResTimeStamp RedirectStartHighRes(); - DOMHighResTimeStamp RedirectEndHighRes(); - DOMHighResTimeStamp DomainLookupStartHighRes(); - DOMHighResTimeStamp DomainLookupEndHighRes(); - DOMHighResTimeStamp ConnectStartHighRes(); - DOMHighResTimeStamp ConnectEndHighRes(); - DOMHighResTimeStamp RequestStartHighRes(); - DOMHighResTimeStamp ResponseStartHighRes(); - DOMHighResTimeStamp ResponseEndHighRes(); - - // Low resolution (used by navigation timing) - DOMTimeMilliSec FetchStart(); - DOMTimeMilliSec RedirectStart(); - DOMTimeMilliSec RedirectEnd(); - DOMTimeMilliSec DomainLookupStart(); - DOMTimeMilliSec DomainLookupEnd(); - DOMTimeMilliSec ConnectStart(); - DOMTimeMilliSec ConnectEnd(); - DOMTimeMilliSec RequestStart(); - DOMTimeMilliSec ResponseStart(); - DOMTimeMilliSec ResponseEnd(); - - DOMTimeMilliSec DomLoading() { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { - return 0; - } - return GetDOMTiming()->GetDomLoading(); - } - DOMTimeMilliSec DomInteractive() const { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { - return 0; - } - return GetDOMTiming()->GetDomInteractive(); - } - DOMTimeMilliSec DomContentLoadedEventStart() const { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { - return 0; - } - return GetDOMTiming()->GetDomContentLoadedEventStart(); - } - DOMTimeMilliSec DomContentLoadedEventEnd() const { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { - return 0; - } - return GetDOMTiming()->GetDomContentLoadedEventEnd(); - } - DOMTimeMilliSec DomComplete() const { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { - return 0; - } - return GetDOMTiming()->GetDomComplete(); - } - DOMTimeMilliSec LoadEventStart() const { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { - return 0; - } - return GetDOMTiming()->GetLoadEventStart(); - } - DOMTimeMilliSec LoadEventEnd() const { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { - return 0; - } - return GetDOMTiming()->GetLoadEventEnd(); - } - -private: - ~PerformanceTiming(); - bool IsInitialized() const; - void InitializeTimingInfo(nsITimedChannel* aChannel); - RefPtr<nsPerformance> 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 mRedirectStart; - TimeStamp mRedirectEnd; - TimeStamp mDomainLookupStart; - TimeStamp mDomainLookupEnd; - TimeStamp mConnectStart; - TimeStamp mConnectEnd; - TimeStamp mRequestStart; - TimeStamp mResponseStart; - TimeStamp mCacheReadStart; - TimeStamp mResponseEnd; - TimeStamp mCacheReadEnd; - uint16_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; -}; +class PerformanceTiming; // Script "performance.navigation" object class PerformanceNavigation final : public nsWrapperCache { public: enum PerformanceNavigationType { TYPE_NAVIGATE = 0, TYPE_RELOAD = 1, @@ -282,19 +57,18 @@ public: } virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override; // PerformanceNavigation WebIDL methods uint16_t Type() const { return GetDOMTiming()->GetType(); } - uint16_t RedirectCount() const { - return GetPerformanceTiming()->GetRedirectCount(); - } + + uint16_t RedirectCount() const; private: ~PerformanceNavigation(); RefPtr<nsPerformance> mPerformance; }; } // namespace dom } // namespace mozilla @@ -482,16 +256,9 @@ mozilla::dom::PerformanceNavigation::Get } inline mozilla::dom::PerformanceTiming* mozilla::dom::PerformanceNavigation::GetPerformanceTiming() const { return mPerformance->Timing(); } -inline nsDOMNavigationTiming* -mozilla::dom::PerformanceTiming::GetDOMTiming() const -{ - return mPerformance->GetDOMTiming(); -} - #endif /* nsPerformance_h___ */ -
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp @@ -76,16 +76,17 @@ #include "mozilla/PeerIdentity.h" #include "mozilla/dom/RTCCertificate.h" #include "mozilla/dom/RTCConfigurationBinding.h" #include "mozilla/dom/RTCRtpSenderBinding.h" #include "mozilla/dom/RTCStatsReportBinding.h" #include "mozilla/dom/RTCPeerConnectionBinding.h" #include "mozilla/dom/PeerConnectionImplBinding.h" #include "mozilla/dom/DataChannelBinding.h" +#include "mozilla/dom/PerformanceTiming.h" #include "mozilla/dom/PluginCrashedEvent.h" #include "MediaStreamList.h" #include "MediaStreamTrack.h" #include "AudioStreamTrack.h" #include "VideoStreamTrack.h" #include "nsIScriptGlobalObject.h" #include "MediaStreamGraph.h" #include "DOMMediaStream.h"