Bug 822480 - Fix e10s bits of Resource Timing implementation. r=bz, r=honzab
authorValentin Gosu <valentin.gosu@gmail.com>
Mon, 21 Apr 2014 09:34:33 -0400
changeset 197883 a5679c8bc3fe99eab1f79a6f42915167767bc7f3
parent 197882 f27f91556752114079be188a8ce883052883298d
child 197884 2fcd144a6282b06000bc19b6a5d994f6d21f6342
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, honzab
bugs822480
milestone31.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 822480 - Fix e10s bits of Resource Timing implementation. r=bz, r=honzab * Move nsITimedChannel to HttpBaseChannel which is inherited by HttpChannelChild * Return mZeroTime instead of 0 in nsPerformanceTiming * Pass redirect count from parent to child channel
dom/base/nsPerformance.cpp
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/HttpBaseChannel.h
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/PHttpChannel.ipdl
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
--- a/dom/base/nsPerformance.cpp
+++ b/dom/base/nsPerformance.cpp
@@ -51,17 +51,17 @@ nsPerformanceTiming::~nsPerformanceTimin
 {
 }
 
 DOMHighResTimeStamp
 nsPerformanceTiming::FetchStartHighRes()
 {
   if (!mFetchStart) {
     if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
-      return 0;
+      return mZeroTime;
     }
     TimeStamp stamp;
     mChannel->GetAsyncOpen(&stamp);
     MOZ_ASSERT(!stamp.IsNull(), "The fetch start time stamp should always be "
         "valid if the performance timing is enabled");
     mFetchStart = (!stamp.IsNull())
         ? TimeStampToDOMHighRes(stamp)
         : 0.0;
@@ -76,18 +76,19 @@ nsPerformanceTiming::FetchStart()
 }
 
 // This method will implement the timing allow check algorithm
 // http://w3c-test.org/webperf/specs/ResourceTiming/#timing-allow-check
 // https://bugzilla.mozilla.org/show_bug.cgi?id=936814
 void
 nsPerformanceTiming::CheckRedirectCrossOrigin(nsIHttpChannel* aResourceChannel)
 {
-  MOZ_ASSERT(mChannel, "The resource channel should not be null for any"
-            "valid resource");
+  if (!IsInitialized()) {
+    return;
+  }
   uint16_t redirectCount;
   mChannel->GetRedirectCount(&redirectCount);
   if (redirectCount == 0) {
     return;
   }
   nsCOMPtr<nsIURI> resourceURI, referrerURI;
   aResourceChannel->GetReferrer(getter_AddRefs(referrerURI));
   aResourceChannel->GetURI(getter_AddRefs(resourceURI));
@@ -129,26 +130,29 @@ nsPerformanceTiming::GetRedirectCount() 
  * and PerformanceResourceTiming::RedirectStart() to make such verifications.
  *
  * @return a valid timing if the Performance Timing is enabled
  */
 DOMHighResTimeStamp
 nsPerformanceTiming::RedirectStartHighRes()
 {
   if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
-    return 0;
+    return mZeroTime;
   }
   mozilla::TimeStamp stamp;
   mChannel->GetRedirectStart(&stamp);
   return TimeStampToDOMHighResOrFetchStart(stamp);
 }
 
 DOMTimeMilliSec
 nsPerformanceTiming::RedirectStart()
 {
+  if (!IsInitialized()) {
+    return mZeroTime;
+  }
   // We have to check if all the redirect URIs had the same origin (since there
   // is no check in RedirectStartHighRes())
   bool sameOrigin;
   mChannel->GetAllRedirectsSameOrigin(&sameOrigin);
   if (sameOrigin) {
     return static_cast<int64_t>(RedirectStartHighRes());
   }
   return 0;
@@ -163,126 +167,129 @@ nsPerformanceTiming::RedirectStart()
  * PerformanceResourceTiming::RedirectEnd() to make such verifications.
  *
  * @return a valid timing if the Performance Timing is enabled
  */
 DOMHighResTimeStamp
 nsPerformanceTiming::RedirectEndHighRes()
 {
   if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
-    return 0;
+    return mZeroTime;
   }
   mozilla::TimeStamp stamp;
   mChannel->GetRedirectEnd(&stamp);
   return TimeStampToDOMHighResOrFetchStart(stamp);
 }
 
 DOMTimeMilliSec
 nsPerformanceTiming::RedirectEnd()
 {
+  if (!IsInitialized()) {
+    return mZeroTime;
+  }
   // We have to check if all the redirect URIs had the same origin (since there
   // is no check in RedirectEndHighRes())
   bool sameOrigin;
   mChannel->GetAllRedirectsSameOrigin(&sameOrigin);
   if (sameOrigin) {
     return static_cast<int64_t>(RedirectEndHighRes());
   }
   return 0;
 }
 
 DOMHighResTimeStamp
 nsPerformanceTiming::DomainLookupStartHighRes()
 {
   if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
-    return 0;
+    return mZeroTime;
   }
   mozilla::TimeStamp stamp;
   mChannel->GetDomainLookupStart(&stamp);
   return TimeStampToDOMHighResOrFetchStart(stamp);
 }
 
 DOMTimeMilliSec
 nsPerformanceTiming::DomainLookupStart()
 {
   return static_cast<int64_t>(DomainLookupStartHighRes());
 }
 
 DOMHighResTimeStamp
 nsPerformanceTiming::DomainLookupEndHighRes()
 {
   if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
-    return 0;
+    return mZeroTime;
   }
   mozilla::TimeStamp stamp;
   mChannel->GetDomainLookupEnd(&stamp);
   return TimeStampToDOMHighResOrFetchStart(stamp);
 }
 
 DOMTimeMilliSec
 nsPerformanceTiming::DomainLookupEnd()
 {
   return static_cast<int64_t>(DomainLookupEndHighRes());
 }
 
 DOMHighResTimeStamp
 nsPerformanceTiming::ConnectStartHighRes()
 {
   if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
-    return 0;
+    return mZeroTime;
   }
   mozilla::TimeStamp stamp;
   mChannel->GetConnectStart(&stamp);
   return TimeStampToDOMHighResOrFetchStart(stamp);
 }
 
 DOMTimeMilliSec
 nsPerformanceTiming::ConnectStart()
 {
   return static_cast<int64_t>(ConnectStartHighRes());
 }
 
 DOMHighResTimeStamp
 nsPerformanceTiming::ConnectEndHighRes()
 {
   if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
-    return 0;
+    return mZeroTime;
   }
   mozilla::TimeStamp stamp;
   mChannel->GetConnectEnd(&stamp);
   return TimeStampToDOMHighResOrFetchStart(stamp);
 }
 
 DOMTimeMilliSec
 nsPerformanceTiming::ConnectEnd()
 {
   return static_cast<int64_t>(ConnectEndHighRes());
 }
 
 DOMHighResTimeStamp
 nsPerformanceTiming::RequestStartHighRes()
 {
   if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
-    return 0;
+    return mZeroTime;
   }
   mozilla::TimeStamp stamp;
   mChannel->GetRequestStart(&stamp);
   return TimeStampToDOMHighResOrFetchStart(stamp);
 }
 
 DOMTimeMilliSec
 nsPerformanceTiming::RequestStart()
 {
   return static_cast<int64_t>(RequestStartHighRes());
 }
 
 DOMHighResTimeStamp
 nsPerformanceTiming::ResponseStartHighRes()
 {
   if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
-    return 0;
+    return mZeroTime;
   }
   mozilla::TimeStamp stamp;
   mChannel->GetResponseStart(&stamp);
   mozilla::TimeStamp cacheStamp;
   mChannel->GetCacheReadStart(&cacheStamp);
   if (stamp.IsNull() || (!cacheStamp.IsNull() && cacheStamp < stamp)) {
     stamp = cacheStamp;
   }
@@ -294,17 +301,17 @@ nsPerformanceTiming::ResponseStart()
 {
   return static_cast<int64_t>(ResponseStartHighRes());
 }
 
 DOMHighResTimeStamp
 nsPerformanceTiming::ResponseEndHighRes()
 {
   if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) {
-    return 0;
+    return mZeroTime;
   }
   mozilla::TimeStamp stamp;
   mChannel->GetResponseEnd(&stamp);
   mozilla::TimeStamp cacheStamp;
   mChannel->GetCacheReadEnd(&cacheStamp);
   if (stamp.IsNull() || (!cacheStamp.IsNull() && cacheStamp < stamp)) {
     stamp = cacheStamp;
   }
@@ -315,18 +322,16 @@ DOMTimeMilliSec
 nsPerformanceTiming::ResponseEnd()
 {
   return static_cast<int64_t>(ResponseEndHighRes());
 }
 
 bool
 nsPerformanceTiming::IsInitialized() const
 {
-  MOZ_ASSERT(mChannel, "The timed channel should not be null for any "
-      "valid resource");
   return !!mChannel;
 }
 
 JSObject*
 nsPerformanceTiming::WrapObject(JSContext *cx)
 {
   return dom::PerformanceTimingBinding::Wrap(cx, this);
 }
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -146,28 +146,32 @@ HttpBaseChannel::Init(nsIURI *aURI,
 
   return rv;
 }
 
 //-----------------------------------------------------------------------------
 // HttpBaseChannel::nsISupports
 //-----------------------------------------------------------------------------
 
-NS_IMPL_ISUPPORTS_INHERITED10(HttpBaseChannel,
-                              nsHashPropertyBag,
-                              nsIRequest,
-                              nsIChannel,
-                              nsIEncodedChannel,
-                              nsIHttpChannel,
-                              nsIHttpChannelInternal,
-                              nsIUploadChannel,
-                              nsIUploadChannel2,
-                              nsISupportsPriority,
-                              nsITraceableChannel,
-                              nsIPrivateBrowsingChannel)
+NS_IMPL_ADDREF(HttpBaseChannel)
+NS_IMPL_RELEASE(HttpBaseChannel)
+
+NS_INTERFACE_MAP_BEGIN(HttpBaseChannel)
+  NS_INTERFACE_MAP_ENTRY(nsIRequest)
+  NS_INTERFACE_MAP_ENTRY(nsIChannel)
+  NS_INTERFACE_MAP_ENTRY(nsIEncodedChannel)
+  NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
+  NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
+  NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)
+  NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
+  NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
+  NS_INTERFACE_MAP_ENTRY(nsIPrivateBrowsingChannel)
+  NS_INTERFACE_MAP_ENTRY(nsITimedChannel)
+NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)
 
 //-----------------------------------------------------------------------------
 // HttpBaseChannel::nsIRequest
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpBaseChannel::GetName(nsACString& aName)
 {
@@ -1946,13 +1950,202 @@ HttpBaseChannel::SetupReplacementChannel
 bool
 HttpBaseChannel::SameOriginWithOriginalUri(nsIURI *aURI)
 {
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   nsresult rv = ssm->CheckSameOriginURI(aURI, mOriginalURI, false);
   return (NS_SUCCEEDED(rv));
 }
 
+
+
+//-----------------------------------------------------------------------------
+// HttpBaseChannel::nsITimedChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpBaseChannel::SetTimingEnabled(bool enabled) {
+  mTimingEnabled = enabled;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetTimingEnabled(bool* _retval) {
+  *_retval = mTimingEnabled;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetChannelCreation(TimeStamp* _retval) {
+  *_retval = mChannelCreationTimestamp;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetAsyncOpen(TimeStamp* _retval) {
+  *_retval = mAsyncOpenTime;
+  return NS_OK;
+}
+
+/**
+ * @return the number of redirects. There is no check for cross-domain
+ * redirects. This check must be done by the consumers.
+ */
+NS_IMETHODIMP
+HttpBaseChannel::GetRedirectCount(uint16_t *aRedirectCount)
+{
+  *aRedirectCount = mRedirectCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::SetRedirectCount(uint16_t aRedirectCount)
+{
+  mRedirectCount = aRedirectCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetRedirectStart(TimeStamp* _retval)
+{
+  *_retval = mRedirectStartTimeStamp;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::SetRedirectStart(TimeStamp aRedirectStart)
+{
+  mRedirectStartTimeStamp = aRedirectStart;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetRedirectEnd(TimeStamp* _retval)
+{
+  *_retval = mRedirectEndTimeStamp;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::SetRedirectEnd(TimeStamp aRedirectEnd)
+{
+  mRedirectEndTimeStamp = aRedirectEnd;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetAllRedirectsSameOrigin(bool *aAllRedirectsSameOrigin)
+{
+  *aAllRedirectsSameOrigin = mAllRedirectsSameOrigin;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::SetAllRedirectsSameOrigin(bool aAllRedirectsSameOrigin)
+{
+  mAllRedirectsSameOrigin = aAllRedirectsSameOrigin;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetDomainLookupStart(TimeStamp* _retval) {
+  *_retval = mTransactionTimings.domainLookupStart;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetDomainLookupEnd(TimeStamp* _retval) {
+  *_retval = mTransactionTimings.domainLookupEnd;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetConnectStart(TimeStamp* _retval) {
+  *_retval = mTransactionTimings.connectStart;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetConnectEnd(TimeStamp* _retval) {
+  *_retval = mTransactionTimings.connectEnd;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetRequestStart(TimeStamp* _retval) {
+  *_retval = mTransactionTimings.requestStart;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetResponseStart(TimeStamp* _retval) {
+  *_retval = mTransactionTimings.responseStart;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetResponseEnd(TimeStamp* _retval) {
+  *_retval = mTransactionTimings.responseEnd;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetCacheReadStart(TimeStamp* _retval) {
+  *_retval = mCacheReadStart;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetCacheReadEnd(TimeStamp* _retval) {
+  *_retval = mCacheReadEnd;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::GetInitiatorType(nsAString & aInitiatorType)
+{
+  aInitiatorType = mInitiatorType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::SetInitiatorType(const nsAString & aInitiatorType)
+{
+  mInitiatorType = aInitiatorType;
+  return NS_OK;
+}
+
+#define IMPL_TIMING_ATTR(name)                                 \
+NS_IMETHODIMP                                                  \
+HttpBaseChannel::Get##name##Time(PRTime* _retval) {            \
+    TimeStamp stamp;                                           \
+    Get##name(&stamp);                                         \
+    if (stamp.IsNull()) {                                      \
+        *_retval = 0;                                          \
+        return NS_OK;                                          \
+    }                                                          \
+    *_retval = mChannelCreationTime +                          \
+        (PRTime) ((stamp - mChannelCreationTimestamp).ToSeconds() * 1e6); \
+    return NS_OK;                                              \
+}
+
+IMPL_TIMING_ATTR(ChannelCreation)
+IMPL_TIMING_ATTR(AsyncOpen)
+IMPL_TIMING_ATTR(DomainLookupStart)
+IMPL_TIMING_ATTR(DomainLookupEnd)
+IMPL_TIMING_ATTR(ConnectStart)
+IMPL_TIMING_ATTR(ConnectEnd)
+IMPL_TIMING_ATTR(RequestStart)
+IMPL_TIMING_ATTR(ResponseStart)
+IMPL_TIMING_ATTR(ResponseEnd)
+IMPL_TIMING_ATTR(CacheReadStart)
+IMPL_TIMING_ATTR(CacheReadEnd)
+IMPL_TIMING_ATTR(RedirectStart)
+IMPL_TIMING_ATTR(RedirectEnd)
+
+#undef IMPL_TIMING_ATTR
+
+
 //------------------------------------------------------------------------------
 
 }  // namespace net
 }  // namespace mozilla
 
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -29,16 +29,17 @@
 #include "nsIApplicationCache.h"
 #include "nsIResumableChannel.h"
 #include "nsITraceableChannel.h"
 #include "nsILoadContext.h"
 #include "mozilla/net/NeckoCommon.h"
 #include "nsThreadUtils.h"
 #include "PrivateBrowsingChannel.h"
 #include "mozilla/net/DNS.h"
+#include "nsITimedChannel.h"
 #include "nsISecurityConsoleMessage.h"
 
 extern PRLogModuleInfo *gHttpLog;
 
 namespace mozilla {
 namespace net {
 
 /*
@@ -53,22 +54,24 @@ class HttpBaseChannel : public nsHashPro
                       , public nsIHttpChannel
                       , public nsIHttpChannelInternal
                       , public nsIUploadChannel
                       , public nsIUploadChannel2
                       , public nsISupportsPriority
                       , public nsIResumableChannel
                       , public nsITraceableChannel
                       , public PrivateBrowsingChannel<HttpBaseChannel>
+                      , public nsITimedChannel
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIUPLOADCHANNEL
   NS_DECL_NSIUPLOADCHANNEL2
   NS_DECL_NSITRACEABLECHANNEL
+  NS_DECL_NSITIMEDCHANNEL
 
   HttpBaseChannel();
   virtual ~HttpBaseChannel();
 
   virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo,
                         uint32_t aProxyResolveFlags,
                         nsIURI *aProxyURI);
 
@@ -334,16 +337,25 @@ protected:
   // Number of redirects that has occurred.
   int16_t                           mRedirectCount;
   // A time value equal to the starting time of the fetch that initiates the
   // redirect.
   mozilla::TimeStamp                mRedirectStartTimeStamp;
   // A time value equal to the time immediately after receiving the last byte of
   // the response of the last redirect.
   mozilla::TimeStamp                mRedirectEndTimeStamp;
+
+  PRTime                            mChannelCreationTime;
+  TimeStamp                         mChannelCreationTimestamp;
+  TimeStamp                         mAsyncOpenTime;
+  TimeStamp                         mCacheReadStart;
+  TimeStamp                         mCacheReadEnd;
+  // copied from the transaction before we null out mTransaction
+  // so that the timing can still be queried from OnStopRequest
+  TimingStruct                      mTransactionTimings;
 };
 
 // Share some code while working around C++'s absurd inability to handle casting
 // of member functions between base/derived types.
 // - We want to store member function pointer to call at resume time, but one
 //   such function--HandleAsyncAbort--we want to share between the
 //   nsHttpChannel/HttpChannelChild.  Can't define it in base class, because
 //   then we'd have to cast member function ptr between base/derived class
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -46,16 +46,19 @@ HttpChannelChild::HttpChannelChild()
   , mIPCOpen(false)
   , mKeptAlive(false)
   , mDivertingToParent(false)
   , mFlushedForDiversion(false)
   , mSuspendSent(false)
 {
   LOG(("Creating HttpChannelChild @%x\n", this));
 
+  mChannelCreationTime = PR_Now();
+  mChannelCreationTimestamp = TimeStamp::Now();
+  mAsyncOpenTime = TimeStamp::Now();
   mEventQ = new ChannelEventQueue(static_cast<nsIHttpChannel*>(this));
 }
 
 HttpChannelChild::~HttpChannelChild()
 {
   LOG(("Destroying HttpChannelChild @%x\n", this));
 }
 
@@ -231,25 +234,29 @@ HttpChannelChild::RecvOnStartRequest(con
                                      const bool& useResponseHead,
                                      const nsHttpHeaderArray& requestHeaders,
                                      const bool& isFromCache,
                                      const bool& cacheEntryAvailable,
                                      const uint32_t& cacheExpirationTime,
                                      const nsCString& cachedCharset,
                                      const nsCString& securityInfoSerialization,
                                      const NetAddr& selfAddr,
-                                     const NetAddr& peerAddr)
+                                     const NetAddr& peerAddr,
+                                     const int16_t& redirectCount)
 {
   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
   // stage, as they are set in the listener's OnStartRequest.
   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     "mFlushedForDiversion should be unset before OnStartRequest!");
   MOZ_RELEASE_ASSERT(!mDivertingToParent,
     "mDivertingToParent should be unset before OnStartRequest!");
 
+
+  mRedirectCount = redirectCount;
+
   if (mEventQ->ShouldEnqueue()) {
     mEventQ->Enqueue(new StartRequestEvent(this, channelStatus, responseHead,
                                            useResponseHead, requestHeaders,
                                            isFromCache, cacheEntryAvailable,
                                            cacheExpirationTime, cachedCharset,
                                            securityInfoSerialization, selfAddr,
                                            peerAddr));
   } else {
@@ -1137,16 +1144,18 @@ HttpChannelChild::AsyncOpen(nsIStreamLis
   if (mCanceled)
     return mStatus;
 
   NS_ENSURE_TRUE(gNeckoChild != nullptr, NS_ERROR_FAILURE);
   NS_ENSURE_ARG_POINTER(listener);
   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
 
+  mAsyncOpenTime = TimeStamp::Now();
+
   // Port checked in parent, but duplicate here so we can return with error
   // immediately
   nsresult rv;
   rv = NS_CheckPortSafety(mURI);
   if (NS_FAILED(rv))
     return rv;
 
   const char *cookieHeader = mRequestHead.PeekHeader(nsHttp::Cookie);
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -101,17 +101,18 @@ protected:
                           const bool& useResponseHead,
                           const nsHttpHeaderArray& requestHeaders,
                           const bool& isFromCache,
                           const bool& cacheEntryAvailable,
                           const uint32_t& cacheExpirationTime,
                           const nsCString& cachedCharset,
                           const nsCString& securityInfoSerialization,
                           const NetAddr& selfAddr,
-                          const NetAddr& peerAddr) MOZ_OVERRIDE;
+                          const NetAddr& peerAddr,
+                          const int16_t& redirectCount) MOZ_OVERRIDE;
   bool RecvOnTransportAndData(const nsresult& channelStatus,
                               const nsresult& status,
                               const uint64_t& progress,
                               const uint64_t& progressMax,
                               const nsCString& data,
                               const uint64_t& offset,
                               const uint32_t& count) MOZ_OVERRIDE;
   bool RecvOnStopRequest(const nsresult& statusCode);
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -596,25 +596,28 @@ HttpChannelParent::OnStartRequest(nsIReq
   chan->GetSecurityInfo(getter_AddRefs(secInfoSupp));
   if (secInfoSupp) {
     mAssociatedContentSecurity = do_QueryInterface(secInfoSupp);
     nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(secInfoSupp);
     if (secInfoSer)
       NS_SerializeToString(secInfoSer, secInfoSerialization);
   }
 
+  uint16_t redirectCount = 0;
+  mChannel->GetRedirectCount(&redirectCount);
   if (mIPCClosed ||
       !SendOnStartRequest(channelStatus,
                           responseHead ? *responseHead : nsHttpResponseHead(),
                           !!responseHead,
                           requestHead->Headers(),
                           isFromCache,
                           mCacheEntry ? true : false,
                           expirationTime, cachedCharset, secInfoSerialization,
-                          mChannel->GetSelfAddr(), mChannel->GetPeerAddr()))
+                          mChannel->GetSelfAddr(), mChannel->GetPeerAddr(),
+                          redirectCount))
   {
     return NS_ERROR_UNEXPECTED;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpChannelParent::OnStopRequest(nsIRequest *aRequest,
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -85,17 +85,18 @@ child:
                  bool                useResponseHead,
                  nsHttpHeaderArray   requestHeaders,
                  bool                isFromCache,
                  bool                cacheEntryAvailable,
                  uint32_t            cacheExpirationTime,
                  nsCString           cachedCharset,
                  nsCString           securityInfoSerialization,
                  NetAddr             selfAddr,
-                 NetAddr             peerAddr);
+                 NetAddr             peerAddr,
+                 int16_t             redirectCount);
 
   // Combines a single OnDataAvailable and its associated OnProgress &
   // OnStatus calls into one IPDL message
   OnTransportAndData(nsresult  channelStatus,
                      nsresult  transportStatus,
                      uint64_t  progress,
                      uint64_t  progressMax,
                      nsCString data,
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -4363,17 +4363,16 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
     NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
     NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
     NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)
     NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
     NS_INTERFACE_MAP_ENTRY(nsIHttpAuthenticableChannel)
     NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
     NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
     NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
-    NS_INTERFACE_MAP_ENTRY(nsITimedChannel)
     NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)
     NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)
     NS_INTERFACE_MAP_ENTRY(nsIDNSListener)
     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_INHERITING(HttpBaseChannel)
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsIRequest
@@ -4748,100 +4747,16 @@ nsHttpChannel::GetProxyInfo(nsIProxyInfo
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsITimedChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-nsHttpChannel::SetTimingEnabled(bool enabled) {
-    mTimingEnabled = enabled;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetTimingEnabled(bool* _retval) {
-    *_retval = mTimingEnabled;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetChannelCreation(TimeStamp* _retval) {
-    *_retval = mChannelCreationTimestamp;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetAsyncOpen(TimeStamp* _retval) {
-    *_retval = mAsyncOpenTime;
-    return NS_OK;
-}
-
-/**
- * @return the number of redirects. There is no check for cross-domain
- * redirects. This check must be done by the consumers.
- */
-NS_IMETHODIMP
-nsHttpChannel::GetRedirectCount(uint16_t *aRedirectCount)
-{
-    *aRedirectCount = mRedirectCount;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetRedirectCount(uint16_t aRedirectCount)
-{
-    mRedirectCount = aRedirectCount;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetRedirectStart(TimeStamp* _retval)
-{
-    *_retval = mRedirectStartTimeStamp;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetRedirectStart(TimeStamp aRedirectStart)
-{
-    mRedirectStartTimeStamp = aRedirectStart;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetRedirectEnd(TimeStamp* _retval)
-{
-    *_retval = mRedirectEndTimeStamp;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetRedirectEnd(TimeStamp aRedirectEnd)
-{
-    mRedirectEndTimeStamp = aRedirectEnd;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetAllRedirectsSameOrigin(bool *aAllRedirectsSameOrigin)
-{
-    *aAllRedirectsSameOrigin = mAllRedirectsSameOrigin;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetAllRedirectsSameOrigin(bool aAllRedirectsSameOrigin)
-{
-    mAllRedirectsSameOrigin = aAllRedirectsSameOrigin;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 nsHttpChannel::GetDomainLookupStart(TimeStamp* _retval) {
     if (mDNSPrefetch && mDNSPrefetch->TimingsValid())
         *_retval = mDNSPrefetch->StartTimestamp();
     else if (mTransaction)
         *_retval = mTransaction->Timings().domainLookupStart;
     else
         *_retval = mTransactionTimings.domainLookupStart;
     return NS_OK;
@@ -4898,72 +4813,16 @@ NS_IMETHODIMP
 nsHttpChannel::GetResponseEnd(TimeStamp* _retval) {
     if (mTransaction)
         *_retval = mTransaction->Timings().responseEnd;
     else
         *_retval = mTransactionTimings.responseEnd;
     return NS_OK;
 }
 
-NS_IMETHODIMP
-nsHttpChannel::GetCacheReadStart(TimeStamp* _retval) {
-    *_retval = mCacheReadStart;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetCacheReadEnd(TimeStamp* _retval) {
-    *_retval = mCacheReadEnd;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::GetInitiatorType(nsAString & aInitiatorType)
-{
-    aInitiatorType = mInitiatorType;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHttpChannel::SetInitiatorType(const nsAString & aInitiatorType)
-{
-    mInitiatorType = aInitiatorType;
-    return NS_OK;
-}
-
-#define IMPL_TIMING_ATTR(name)                                 \
-NS_IMETHODIMP                                                  \
-nsHttpChannel::Get##name##Time(PRTime* _retval) {              \
-    TimeStamp stamp;                                  \
-    Get##name(&stamp);                                         \
-    if (stamp.IsNull()) {                                      \
-        *_retval = 0;                                          \
-        return NS_OK;                                          \
-    }                                                          \
-    *_retval = mChannelCreationTime +                          \
-        (PRTime) ((stamp - mChannelCreationTimestamp).ToSeconds() * 1e6); \
-    return NS_OK;                                              \
-}
-
-IMPL_TIMING_ATTR(ChannelCreation)
-IMPL_TIMING_ATTR(AsyncOpen)
-IMPL_TIMING_ATTR(DomainLookupStart)
-IMPL_TIMING_ATTR(DomainLookupEnd)
-IMPL_TIMING_ATTR(ConnectStart)
-IMPL_TIMING_ATTR(ConnectEnd)
-IMPL_TIMING_ATTR(RequestStart)
-IMPL_TIMING_ATTR(ResponseStart)
-IMPL_TIMING_ATTR(ResponseEnd)
-IMPL_TIMING_ATTR(CacheReadStart)
-IMPL_TIMING_ATTR(CacheReadEnd)
-IMPL_TIMING_ATTR(RedirectStart)
-IMPL_TIMING_ATTR(RedirectEnd)
-
-#undef IMPL_TIMING_ATTR
-
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsIHttpAuthenticableChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpChannel::GetIsSSL(bool *aIsSSL)
 {
     *aIsSSL = mConnectionInfo->UsingSSL();
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -12,17 +12,16 @@
 #include "nsICachingChannel.h"
 #include "nsICacheEntry.h"
 #include "nsICacheEntryOpenCallback.h"
 #include "nsIDNSListener.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIProtocolProxyCallback.h"
 #include "nsIHttpAuthenticableChannel.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
-#include "nsITimedChannel.h"
 #include "nsIThreadRetargetableRequest.h"
 #include "nsIThreadRetargetableStreamListener.h"
 #include "nsWeakReference.h"
 #include "TimingStruct.h"
 #include "AutoClose.h"
 
 class nsIPrincipal;
 class nsDNSPrefetch;
@@ -43,17 +42,16 @@ class nsHttpChannel : public HttpBaseCha
                     , public nsIStreamListener
                     , public nsICachingChannel
                     , public nsICacheEntryOpenCallback
                     , public nsITransportEventSink
                     , public nsIProtocolProxyCallback
                     , public nsIHttpAuthenticableChannel
                     , public nsIApplicationCacheChannel
                     , public nsIAsyncVerifyRedirectCallback
-                    , public nsITimedChannel
                     , public nsIThreadRetargetableRequest
                     , public nsIThreadRetargetableStreamListener
                     , public nsIDNSListener
                     , public nsSupportsWeakReference
 {
 public:
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIREQUESTOBSERVER
@@ -63,17 +61,16 @@ public:
     NS_DECL_NSICACHINGCHANNEL
     NS_DECL_NSICACHEENTRYOPENCALLBACK
     NS_DECL_NSITRANSPORTEVENTSINK
     NS_DECL_NSIPROTOCOLPROXYCALLBACK
     NS_DECL_NSIPROXIEDCHANNEL
     NS_DECL_NSIAPPLICATIONCACHECONTAINER
     NS_DECL_NSIAPPLICATIONCACHECHANNEL
     NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
-    NS_DECL_NSITIMEDCHANNEL
     NS_DECL_NSITHREADRETARGETABLEREQUEST
     NS_DECL_NSIDNSLISTENER
 
     // nsIHttpAuthenticableChannel. We can't use
     // NS_DECL_NSIHTTPAUTHENTICABLECHANNEL because it duplicates cancel() and
     // others.
     NS_IMETHOD GetIsSSL(bool *aIsSSL);
     NS_IMETHOD GetProxyMethodIsConnect(bool *aProxyMethodIsConnect);
@@ -114,16 +111,24 @@ public:
     NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey);
     // nsISupportsPriority
     NS_IMETHOD SetPriority(int32_t value);
     // nsIResumableChannel
     NS_IMETHOD ResumeAt(uint64_t startPos, const nsACString& entityID);
 
     NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks);
     NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup);
+    // nsITimedChannel
+    NS_IMETHOD GetDomainLookupStart(mozilla::TimeStamp *aDomainLookupStart);
+    NS_IMETHOD GetDomainLookupEnd(mozilla::TimeStamp *aDomainLookupEnd);
+    NS_IMETHOD GetConnectStart(mozilla::TimeStamp *aConnectStart);
+    NS_IMETHOD GetConnectEnd(mozilla::TimeStamp *aConnectEnd);
+    NS_IMETHOD GetRequestStart(mozilla::TimeStamp *aRequestStart);
+    NS_IMETHOD GetResponseStart(mozilla::TimeStamp *aResponseStart);
+    NS_IMETHOD GetResponseEnd(mozilla::TimeStamp *aResponseEnd);
 
 public: /* internal necko use only */
 
     void InternalSetUploadStream(nsIInputStream *uploadStream)
       { mUploadStream = uploadStream; }
     void SetUploadStreamHasHeaders(bool hasHeaders)
       { mUploadStreamHasHeaders = hasHeaders; }
 
@@ -399,24 +404,16 @@ private:
     uint32_t                          mConcurentCacheAccess : 1;
     // whether the request is setup be byte-range
     uint32_t                          mIsPartialRequest : 1;
     // true iff there is AutoRedirectVetoNotifier on the stack
     uint32_t                          mHasAutoRedirectVetoNotifier : 1;
 
     nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack;
 
-    PRTime                            mChannelCreationTime;
-    TimeStamp                         mChannelCreationTimestamp;
-    TimeStamp                         mAsyncOpenTime;
-    TimeStamp                         mCacheReadStart;
-    TimeStamp                         mCacheReadEnd;
-    // copied from the transaction before we null out mTransaction
-    // so that the timing can still be queried from OnStopRequest
-    TimingStruct                      mTransactionTimings;
     // Needed for accurate DNS timing
     nsRefPtr<nsDNSPrefetch>           mDNSPrefetch;
 
     nsresult WaitForRedirectCallback();
     void PushRedirectAsyncFunc(nsContinueRedirectionFunc func);
     void PopRedirectAsyncFunc(nsContinueRedirectionFunc func);
 
 protected: