Bug 1064706 - Send timing info to content process r=honzab
authorValentin Gosu <valentin.gosu@gmail.com>
Mon, 06 Oct 2014 14:33:27 +0300
changeset 232219 afecbcdbe6d52dd407300716ca33e7c1a83ac805
parent 232218 19cc89734f2d51bdb01ff5e59f6d19ac33c81708
child 232220 30e935a33442b461430c4a15ef7eee346e359b58
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershonzab
bugs1064706
milestone35.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 1064706 - Send timing info to content process r=honzab
netwerk/ipc/NeckoMessageUtils.h
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/PHttpChannel.ipdl
netwerk/protocol/http/TimingStruct.h
netwerk/protocol/http/moz.build
--- a/netwerk/ipc/NeckoMessageUtils.h
+++ b/netwerk/ipc/NeckoMessageUtils.h
@@ -7,16 +7,17 @@
 #define mozilla_net_NeckoMessageUtils_h
 
 #include "mozilla/DebugOnly.h"
 
 #include "ipc/IPCMessageUtils.h"
 #include "nsStringGlue.h"
 #include "prio.h"
 #include "mozilla/net/DNS.h"
+#include "TimingStruct.h"
 
 namespace IPC {
 
 // nsIPermissionManager utilities
 
 struct Permission
 {
   nsCString host, type;
@@ -141,11 +142,44 @@ struct ParamTraits<mozilla::net::NetAddr
 #endif
     }
 
     /* We've been tricked by some socket family we don't know about! */
     return false;
   }
 };
 
+template<>
+struct ParamTraits<mozilla::net::ResourceTimingStruct>
+{
+  static void Write(Message* aMsg, const mozilla::net::ResourceTimingStruct& aParam)
+  {
+    WriteParam(aMsg, aParam.domainLookupStart);
+    WriteParam(aMsg, aParam.domainLookupEnd);
+    WriteParam(aMsg, aParam.connectStart);
+    WriteParam(aMsg, aParam.connectEnd);
+    WriteParam(aMsg, aParam.requestStart);
+    WriteParam(aMsg, aParam.responseStart);
+    WriteParam(aMsg, aParam.responseEnd);
+
+    WriteParam(aMsg, aParam.fetchStart);
+    WriteParam(aMsg, aParam.redirectStart);
+    WriteParam(aMsg, aParam.redirectEnd);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, mozilla::net::ResourceTimingStruct* aResult)
+  {
+    return ReadParam(aMsg, aIter, &aResult->domainLookupStart) &&
+           ReadParam(aMsg, aIter, &aResult->domainLookupEnd) &&
+           ReadParam(aMsg, aIter, &aResult->connectStart) &&
+           ReadParam(aMsg, aIter, &aResult->connectEnd) &&
+           ReadParam(aMsg, aIter, &aResult->requestStart) &&
+           ReadParam(aMsg, aIter, &aResult->responseStart) &&
+           ReadParam(aMsg, aIter, &aResult->responseEnd) &&
+           ReadParam(aMsg, aIter, &aResult->fetchStart) &&
+           ReadParam(aMsg, aIter, &aResult->redirectStart) &&
+           ReadParam(aMsg, aIter, &aResult->redirectEnd);
+  }
+};
+
 }
 
 #endif // mozilla_net_NeckoMessageUtils_h
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -23,16 +23,17 @@
 #include "nsSerializationHelper.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/net/ChannelDiverterChild.h"
 #include "mozilla/net/DNS.h"
 #include "SerializedLoadContext.h"
+#include "nsPerformance.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
 
 //-----------------------------------------------------------------------------
@@ -500,56 +501,77 @@ HttpChannelChild::OnTransportAndData(con
     Cancel(rv);
   }
 }
 
 class StopRequestEvent : public ChannelEvent
 {
  public:
   StopRequestEvent(HttpChannelChild* child,
-                   const nsresult& channelStatus)
+                   const nsresult& channelStatus,
+                   const ResourceTimingStruct& timing)
   : mChild(child)
-  , mChannelStatus(channelStatus) {}
+  , mChannelStatus(channelStatus)
+  , mTiming(timing) {}
 
-  void Run() { mChild->OnStopRequest(mChannelStatus); }
+  void Run() { mChild->OnStopRequest(mChannelStatus, mTiming); }
  private:
   HttpChannelChild* mChild;
   nsresult mChannelStatus;
+  ResourceTimingStruct mTiming;
 };
 
 bool
-HttpChannelChild::RecvOnStopRequest(const nsresult& channelStatus)
+HttpChannelChild::RecvOnStopRequest(const nsresult& channelStatus,
+                                    const ResourceTimingStruct& timing)
 {
   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     "Should not be receiving any more callbacks from parent!");
 
   if (mEventQ->ShouldEnqueue()) {
-    mEventQ->Enqueue(new StopRequestEvent(this, channelStatus));
+    mEventQ->Enqueue(new StopRequestEvent(this, channelStatus, timing));
   } else {
     MOZ_ASSERT(!mDivertingToParent, "ShouldEnqueue when diverting to parent!");
 
-    OnStopRequest(channelStatus);
+    OnStopRequest(channelStatus, timing);
   }
   return true;
 }
 
 void
-HttpChannelChild::OnStopRequest(const nsresult& channelStatus)
+HttpChannelChild::OnStopRequest(const nsresult& channelStatus,
+                                const ResourceTimingStruct& timing)
 {
   LOG(("HttpChannelChild::OnStopRequest [this=%p status=%x]\n",
            this, channelStatus));
 
   if (mDivertingToParent) {
     MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
       "Should not be processing any more callbacks from parent!");
 
     SendDivertOnStopRequest(channelStatus);
     return;
   }
 
+  mTransactionTimings.domainLookupStart = timing.domainLookupStart;
+  mTransactionTimings.domainLookupEnd = timing.domainLookupEnd;
+  mTransactionTimings.connectStart = timing.connectStart;
+  mTransactionTimings.connectEnd = timing.connectEnd;
+  mTransactionTimings.requestStart = timing.requestStart;
+  mTransactionTimings.responseStart = timing.responseStart;
+  mTransactionTimings.responseEnd = timing.responseEnd;
+  mAsyncOpenTime = timing.fetchStart;
+  mRedirectStartTimeStamp = timing.redirectStart;
+  mRedirectEndTimeStamp = timing.redirectEnd;
+
+  nsPerformance* documentPerformance = GetPerformance();
+  if (documentPerformance) {
+      documentPerformance->AddEntry(this, this);
+  }
+
   mIsPending = false;
 
   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
     mStatus = channelStatus;
   }
 
   { // We must flush the queue before we Send__delete__
     // (although we really shouldn't receive any msgs after OnStop),
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -110,17 +110,17 @@ protected:
                           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);
+  bool RecvOnStopRequest(const nsresult& statusCode, const ResourceTimingStruct& timing);
   bool RecvOnProgress(const uint64_t& progress, const uint64_t& progressMax) MOZ_OVERRIDE;
   bool RecvOnStatus(const nsresult& status) MOZ_OVERRIDE;
   bool RecvFailedAsyncOpen(const nsresult& status) MOZ_OVERRIDE;
   bool RecvRedirect1Begin(const uint32_t& newChannel,
                           const URIParams& newURI,
                           const uint32_t& redirectFlags,
                           const nsHttpResponseHead& responseHead) MOZ_OVERRIDE;
   bool RecvRedirect3Complete() MOZ_OVERRIDE;
@@ -177,17 +177,17 @@ private:
                       const NetAddr& peerAddr);
   void OnTransportAndData(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);
-  void OnStopRequest(const nsresult& channelStatus);
+  void OnStopRequest(const nsresult& channelStatus, const ResourceTimingStruct& timing);
   void OnProgress(const uint64_t& progress, const uint64_t& progressMax);
   void OnStatus(const nsresult& status);
   void FailedAsyncOpen(const nsresult& status);
   void HandleAsyncAbort();
   void Redirect1Begin(const uint32_t& newChannelId,
                       const URIParams& newUri,
                       const uint32_t& redirectFlags,
                       const nsHttpResponseHead& responseHead);
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -224,16 +224,17 @@ HttpChannelParent::DoAsyncOpen(  const U
                      nullptr,   // aCallbacks
                      loadFlags,
                      ios);
 
   if (NS_FAILED(rv))
     return SendFailedAsyncOpen(rv);
 
   mChannel = static_cast<nsHttpChannel *>(channel.get());
+  mChannel->SetTimingEnabled(true);
   if (mPBOverride != kPBOverride_Unset) {
     mChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
   }
 
   if (doResumeAt)
     mChannel->ResumeAt(startPos, entityID);
 
   if (originalUri)
@@ -663,18 +664,29 @@ HttpChannelParent::OnStopRequest(nsIRequ
                                  nsISupports *aContext,
                                  nsresult aStatusCode)
 {
   LOG(("HttpChannelParent::OnStopRequest: [this=%p status=%x]\n",
        this, aStatusCode));
 
   MOZ_RELEASE_ASSERT(!mDivertingFromChild,
     "Cannot call OnStopRequest if diverting is set!");
+  ResourceTimingStruct timing;
+  mChannel->GetDomainLookupStart(&timing.domainLookupStart);
+  mChannel->GetDomainLookupEnd(&timing.domainLookupEnd);
+  mChannel->GetConnectStart(&timing.connectStart);
+  mChannel->GetConnectEnd(&timing.connectEnd);
+  mChannel->GetRequestStart(&timing.requestStart);
+  mChannel->GetResponseStart(&timing.responseStart);
+  mChannel->GetResponseEnd(&timing.responseEnd);
+  mChannel->GetAsyncOpen(&timing.fetchStart);
+  mChannel->GetRedirectStart(&timing.redirectStart);
+  mChannel->GetRedirectEnd(&timing.redirectEnd);
 
-  if (mIPCClosed || !SendOnStopRequest(aStatusCode))
+  if (mIPCClosed || !SendOnStopRequest(aStatusCode, timing))
     return NS_ERROR_UNEXPECTED;
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsIStreamListener
 //-----------------------------------------------------------------------------
 
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -13,16 +13,17 @@ include protocol PBlob; //FIXME: bug #79
 
 include "mozilla/net/NeckoMessageUtils.h";
 
 using RequestHeaderTuples from "mozilla/net/PHttpChannelParams.h";
 using class nsHttpHeaderArray from "nsHttpHeaderArray.h";
 using class nsHttpResponseHead from "nsHttpResponseHead.h";
 using struct nsHttpAtom from "nsHttp.h";
 using mozilla::net::NetAddr from "mozilla/net/DNS.h";
+using struct mozilla::net::ResourceTimingStruct from "mozilla/net/TimingStruct.h";
 
 namespace mozilla {
 namespace net {
 
 //-------------------------------------------------------------------
 protocol PHttpChannel
 {
   manager PNecko;
@@ -98,17 +99,17 @@ child:
   OnTransportAndData(nsresult  channelStatus,
                      nsresult  transportStatus,
                      uint64_t  progress,
                      uint64_t  progressMax,
                      nsCString data,
                      uint64_t  offset,
                      uint32_t  count);
 
-  OnStopRequest(nsresult channelStatus);
+  OnStopRequest(nsresult channelStatus, ResourceTimingStruct timing);
 
   OnProgress(uint64_t progress, uint64_t progressMax);
 
   OnStatus(nsresult status);
 
   // Used to cancel child channel if we hit errors during creating and
   // AsyncOpen of nsHttpChannel on the parent.
   FailedAsyncOpen(nsresult status);
--- a/netwerk/protocol/http/TimingStruct.h
+++ b/netwerk/protocol/http/TimingStruct.h
@@ -15,11 +15,17 @@ struct TimingStruct {
   TimeStamp domainLookupEnd;
   TimeStamp connectStart;
   TimeStamp connectEnd;
   TimeStamp requestStart;
   TimeStamp responseStart;
   TimeStamp responseEnd;
 };
 
+struct ResourceTimingStruct : TimingStruct {
+  TimeStamp fetchStart;
+  TimeStamp redirectStart;
+  TimeStamp redirectEnd;
+};
+
 }} // namespace mozilla::net
 
 #endif
--- a/netwerk/protocol/http/moz.build
+++ b/netwerk/protocol/http/moz.build
@@ -29,16 +29,17 @@ EXPORTS += [
 
 EXPORTS.mozilla.net += [
     'HttpBaseChannel.h',
     'HttpChannelChild.h',
     'HttpChannelParent.h',
     'HttpInfo.h',
     'PHttpChannelParams.h',
     'PSpdyPush.h',
+    'TimingStruct.h',
 ]
 
 # ASpdySession.cpp and nsHttpAuthCache cannot be built in unified mode because
 # they use plarena.h.
 # The rest of these files cannot be built in unified mode because they want to
 # force NSPR logging.
 SOURCES += [
     'ASpdySession.cpp',