Bug 1278843 - Move PerformanceTiming code in separate files, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 09 Jun 2016 12:43:56 +0200
changeset 301256 2401b6b118b399ad8c44f70b8ce0423f1f4b67b3
parent 301255 7ec00141f0a253efb4307f8105483ab0895775b1
child 301257 0c2668c814d02fb58967bb7fee6967e6df4dd6b6
push id78267
push useramarchesini@mozilla.com
push dateThu, 09 Jun 2016 10:45:17 +0000
treeherdermozilla-inbound@0c2668c814d0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1278843
milestone50.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
Bug 1278843 - Move PerformanceTiming code in separate files, r=smaug
dom/bindings/Bindings.conf
dom/performance/PerformanceResourceTiming.h
dom/performance/PerformanceTiming.cpp
dom/performance/PerformanceTiming.h
dom/performance/moz.build
dom/performance/nsPerformance.cpp
dom/performance/nsPerformance.h
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
--- 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"