Bug 1274556 - Add a channelId attribute to nsIHttpChannel r=hurley
authorJarda Snajdr <jsnajdr@gmail.com>
Wed, 01 Jun 2016 12:29:21 -0700
changeset 339001 dc171b5fafc0742057f24d66dd76818f95c86656
parent 339000 f9c82b044f90bf8a1e141c290b0e206ed99a8b53
child 339002 16042a3a145c271f6937cb25ca53f65614a61543
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershurley
bugs1274556
milestone49.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 1274556 - Add a channelId attribute to nsIHttpChannel r=hurley
netwerk/base/nsIChildChannel.idl
netwerk/ipc/NeckoChannelParams.ipdlh
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/HttpChannelParent.h
netwerk/protocol/http/NullHttpChannel.cpp
netwerk/protocol/http/PHttpChannel.ipdl
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
netwerk/protocol/http/nsIHttpChannel.idl
netwerk/protocol/viewsource/nsViewSourceChannel.cpp
--- a/netwerk/base/nsIChildChannel.idl
+++ b/netwerk/base/nsIChildChannel.idl
@@ -18,17 +18,17 @@ interface nsIChildChannel : nsISupports
    * channel on the parent process.  The id is provided by
    * nsIRedirectChannelRegistrar on the chrome process and pushed to the child
    * protocol as an argument to event starting a redirect.
    *
    * Primarilly used in HttpChannelChild::Redirect1Begin on a newly created
    * child channel, where the new channel is intended to be created on the
    * child process.
    */
-  void connectParent(in uint32_t id);
+  void connectParent(in uint32_t registrarId);
 
   /**
    * As AsyncOpen is called on the chrome process for redirect target channels,
    * we have to inform the child side of the protocol of that fact by a special
    * method.
    */
   void completeRedirectSetup(in nsIStreamListener aListener,
                              in nsISupports aContext);
--- a/netwerk/ipc/NeckoChannelParams.ipdlh
+++ b/netwerk/ipc/NeckoChannelParams.ipdlh
@@ -116,21 +116,22 @@ struct HttpChannelOpenArgs
   uint32_t                    cacheKey;
   nsCString                   requestContextID;
   OptionalCorsPreflightArgs   preflightArgs;
   uint32_t                    initialRwin;
   bool                        blockAuthPrompt;
   bool                        suspendAfterSynthesizeResponse;
   bool                        allowStaleCacheContent;
   nsCString                   contentTypeHint;
+  nsCString                   channelId;
 };
 
 struct HttpChannelConnectArgs
 {
-  uint32_t channelId;
+  uint32_t registrarId;
   bool shouldIntercept;
 };
 
 union HttpChannelCreationArgs
 {
   HttpChannelOpenArgs;      // For AsyncOpen: the common case.
   HttpChannelConnectArgs;   // Used for redirected-to channels
 };
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -138,28 +138,30 @@ HttpBaseChannel::~HttpBaseChannel()
   CleanRedirectCacheChainIfNecessary();
 }
 
 nsresult
 HttpBaseChannel::Init(nsIURI *aURI,
                       uint32_t aCaps,
                       nsProxyInfo *aProxyInfo,
                       uint32_t aProxyResolveFlags,
-                      nsIURI *aProxyURI)
+                      nsIURI *aProxyURI,
+                      const nsID& aChannelId)
 {
   LOG(("HttpBaseChannel::Init [this=%p]\n", this));
 
   NS_PRECONDITION(aURI, "null uri");
 
   mURI = aURI;
   mOriginalURI = aURI;
   mDocumentURI = nullptr;
   mCaps = aCaps;
   mProxyResolveFlags = aProxyResolveFlags;
   mProxyURI = aProxyURI;
+  mChannelId = aChannelId;
 
   // Construct connection info object
   nsAutoCString host;
   int32_t port = -1;
   bool isHTTPS = false;
 
   nsresult rv = mURI->SchemeIs("https", &isHTTPS);
   if (NS_FAILED(rv)) return rv;
@@ -1153,16 +1155,38 @@ HttpBaseChannel::nsContentEncodings::Pre
 }
 
 
 //-----------------------------------------------------------------------------
 // HttpBaseChannel::nsIHttpChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
+HttpBaseChannel::GetChannelId(nsACString& aChannelId)
+{
+  char id[NSID_LENGTH];
+  mChannelId.ToProvidedString(id);
+  aChannelId.AssignASCII(id);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpBaseChannel::SetChannelId(const nsACString& aChannelId)
+{
+  nsID newId;
+  nsAutoCString idStr(aChannelId);
+  if (newId.Parse(idStr.get())) {
+    mChannelId = newId;
+    return NS_OK;
+  }
+
+  return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
 HttpBaseChannel::GetTransferSize(uint64_t *aTransferSize)
 {
   *aTransferSize = mTransferSize;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::GetDecodedBodySize(uint64_t *aDecodedBodySize)
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -87,17 +87,18 @@ public:
   NS_DECL_NSIUPLOADCHANNEL2
   NS_DECL_NSITRACEABLECHANNEL
   NS_DECL_NSITIMEDCHANNEL
 
   HttpBaseChannel();
 
   virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo,
                         uint32_t aProxyResolveFlags,
-                        nsIURI *aProxyURI);
+                        nsIURI *aProxyURI,
+                        const nsID& aChannelId);
 
   // nsIRequest
   NS_IMETHOD GetName(nsACString& aName) override;
   NS_IMETHOD IsPending(bool *aIsPending) override;
   NS_IMETHOD GetStatus(nsresult *aStatus) override;
   NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup) override;
   NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup) override;
   NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags) override;
@@ -174,16 +175,18 @@ public:
   NS_IMETHOD GetRequestContextID(nsID *aRCID) override;
   NS_IMETHOD GetTransferSize(uint64_t *aTransferSize) override;
   NS_IMETHOD GetDecodedBodySize(uint64_t *aDecodedBodySize) override;
   NS_IMETHOD GetEncodedBodySize(uint64_t *aEncodedBodySize) override;
   NS_IMETHOD SetRequestContextID(const nsID aRCID) override;
   NS_IMETHOD GetIsMainDocumentChannel(bool* aValue) override;
   NS_IMETHOD SetIsMainDocumentChannel(bool aValue) override;
   NS_IMETHOD GetProtocolVersion(nsACString & aProtocolVersion) override;
+  NS_IMETHOD GetChannelId(nsACString& aChannelId) override;
+  NS_IMETHOD SetChannelId(const nsACString& aChannelId) override;
 
   // nsIHttpChannelInternal
   NS_IMETHOD GetDocumentURI(nsIURI **aDocumentURI) override;
   NS_IMETHOD SetDocumentURI(nsIURI *aDocumentURI) override;
   NS_IMETHOD GetRequestVersion(uint32_t *major, uint32_t *minor) override;
   NS_IMETHOD GetResponseVersion(uint32_t *major, uint32_t *minor) override;
   NS_IMETHOD SetCookie(const char *aCookieHeader) override;
   NS_IMETHOD GetThirdPartyFlags(uint32_t *aForce) override;
@@ -510,16 +513,18 @@ protected:
   bool EnsureRequestContextID();
 
   bool                              mRequireCORSPreflight;
   nsTArray<nsCString>               mUnsafeHeaders;
 
   nsCOMPtr<nsIConsoleReportCollector> mReportCollector;
 
   bool mForceMainDocumentChannel;
+
+  nsID mChannelId;
 };
 
 // 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
@@ -1143,54 +1143,60 @@ HttpChannelChild::RecvReportSecurityMess
   AddSecurityMessage(messageTag, messageCategory);
   return true;
 }
 
 class Redirect1Event : public ChannelEvent
 {
  public:
   Redirect1Event(HttpChannelChild* child,
-                 const uint32_t& newChannelId,
+                 const uint32_t& registrarId,
                  const URIParams& newURI,
                  const uint32_t& redirectFlags,
                  const nsHttpResponseHead& responseHead,
-                 const nsACString& securityInfoSerialization)
+                 const nsACString& securityInfoSerialization,
+                 const nsACString& channelId)
   : mChild(child)
-  , mNewChannelId(newChannelId)
+  , mRegistrarId(registrarId)
   , mNewURI(newURI)
   , mRedirectFlags(redirectFlags)
   , mResponseHead(responseHead)
-  , mSecurityInfoSerialization(securityInfoSerialization) {}
+  , mSecurityInfoSerialization(securityInfoSerialization)
+  , mChannelId(channelId) {}
 
   void Run()
   {
-    mChild->Redirect1Begin(mNewChannelId, mNewURI, mRedirectFlags,
-                           mResponseHead, mSecurityInfoSerialization);
+    mChild->Redirect1Begin(mRegistrarId, mNewURI, mRedirectFlags,
+                           mResponseHead, mSecurityInfoSerialization,
+                           mChannelId);
   }
  private:
   HttpChannelChild*   mChild;
-  uint32_t            mNewChannelId;
+  uint32_t            mRegistrarId;
   URIParams           mNewURI;
   uint32_t            mRedirectFlags;
   nsHttpResponseHead  mResponseHead;
   nsCString           mSecurityInfoSerialization;
+  nsCString           mChannelId;
 };
 
 bool
-HttpChannelChild::RecvRedirect1Begin(const uint32_t& newChannelId,
+HttpChannelChild::RecvRedirect1Begin(const uint32_t& registrarId,
                                      const URIParams& newUri,
                                      const uint32_t& redirectFlags,
                                      const nsHttpResponseHead& responseHead,
-                                     const nsCString& securityInfoSerialization)
+                                     const nsCString& securityInfoSerialization,
+                                     const nsCString& channelId)
 {
   // TODO: handle security info
   LOG(("HttpChannelChild::RecvRedirect1Begin [this=%p]\n", this));
-  mEventQ->RunOrEnqueue(new Redirect1Event(this, newChannelId, newUri,
+  mEventQ->RunOrEnqueue(new Redirect1Event(this, registrarId, newUri,
                                            redirectFlags, responseHead,
-                                           securityInfoSerialization));
+                                           securityInfoSerialization,
+                                           channelId));
   return true;
 }
 
 nsresult
 HttpChannelChild::SetupRedirect(nsIURI* uri,
                                 const nsHttpResponseHead* responseHead,
                                 const uint32_t& redirectFlags,
                                 nsIChannel** outChannel)
@@ -1245,21 +1251,22 @@ HttpChannelChild::SetupRedirect(nsIURI* 
 
   mRedirectChannelChild = do_QueryInterface(newChannel);
   newChannel.forget(outChannel);
 
   return NS_OK;
 }
 
 void
-HttpChannelChild::Redirect1Begin(const uint32_t& newChannelId,
+HttpChannelChild::Redirect1Begin(const uint32_t& registrarId,
                                  const URIParams& newUri,
                                  const uint32_t& redirectFlags,
                                  const nsHttpResponseHead& responseHead,
-                                 const nsACString& securityInfoSerialization)
+                                 const nsACString& securityInfoSerialization,
+                                 const nsACString& channelId)
 {
   LOG(("HttpChannelChild::Redirect1Begin [this=%p]\n", this));
 
   nsCOMPtr<nsIURI> uri = DeserializeURI(newUri);
 
   if (!securityInfoSerialization.IsEmpty()) {
     NS_DeserializeObject(securityInfoSerialization,
                          getter_AddRefs(mSecurityInfo));
@@ -1268,17 +1275,22 @@ HttpChannelChild::Redirect1Begin(const u
   nsCOMPtr<nsIChannel> newChannel;
   nsresult rv = SetupRedirect(uri,
                               &responseHead,
                               redirectFlags,
                               getter_AddRefs(newChannel));
 
   if (NS_SUCCEEDED(rv)) {
     if (mRedirectChannelChild) {
-      mRedirectChannelChild->ConnectParent(newChannelId);
+      // Set the channelId allocated in parent to the child instance
+      nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mRedirectChannelChild);
+      if (httpChannel) {
+        httpChannel->SetChannelId(channelId);
+      }
+      mRedirectChannelChild->ConnectParent(registrarId);
     }
     rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, redirectFlags);
   }
 
   if (NS_FAILED(rv))
     OnRedirectVerifyCallback(rv);
 }
 
@@ -1417,34 +1429,34 @@ HttpChannelChild::Redirect3Complete()
   }
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelChild::nsIChildChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-HttpChannelChild::ConnectParent(uint32_t id)
+HttpChannelChild::ConnectParent(uint32_t registrarId)
 {
   LOG(("HttpChannelChild::ConnectParent [this=%p]\n", this));
   mozilla::dom::TabChild* tabChild = nullptr;
   nsCOMPtr<nsITabChild> iTabChild;
   GetCallback(iTabChild);
   if (iTabChild) {
     tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
   }
   if (MissingRequiredTabChild(tabChild, "http")) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
   // The socket transport in the chrome process now holds a logical ref to us
   // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
   AddIPDLReference();
 
-  HttpChannelConnectArgs connectArgs(id, mShouldParentIntercept);
+  HttpChannelConnectArgs connectArgs(registrarId, mShouldParentIntercept);
   PBrowserOrId browser = static_cast<ContentChild*>(gNeckoChild->Manager())
                          ->GetBrowserOrId(tabChild);
   if (!gNeckoChild->
         SendPHttpChannelConstructor(this, browser,
                                     IPC::SerializedLoadContext(this),
                                     connectArgs)) {
     return NS_ERROR_FAILURE;
   }
@@ -1944,16 +1956,20 @@ HttpChannelChild::ContinueAsyncOpen()
   nsresult rv = mozilla::ipc::LoadInfoToLoadInfoArgs(mLoadInfo, &openArgs.loadInfo());
   NS_ENSURE_SUCCESS(rv, rv);
 
   EnsureRequestContextID();
   char rcid[NSID_LENGTH];
   mRequestContextID.ToProvidedString(rcid);
   openArgs.requestContextID().AssignASCII(rcid);
 
+  char chid[NSID_LENGTH];
+  mChannelId.ToProvidedString(chid);
+  openArgs.channelId().AssignASCII(chid);
+
   // The socket transport in the chrome process now holds a logical ref to us
   // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
   AddIPDLReference();
 
   PBrowserOrId browser = static_cast<ContentChild*>(gNeckoChild->Manager())
                          ->GetBrowserOrId(tabChild);
   gNeckoChild->SendPHttpChannelConstructor(this, browser,
                                            IPC::SerializedLoadContext(this),
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -128,21 +128,22 @@ protected:
                               const uint64_t& progressMax,
                               const uint64_t& offset,
                               const uint32_t& count,
                               const nsCString& data) override;
   bool RecvOnStopRequest(const nsresult& statusCode, const ResourceTimingStruct& timing) override;
   bool RecvOnProgress(const int64_t& progress, const int64_t& progressMax) override;
   bool RecvOnStatus(const nsresult& status) override;
   bool RecvFailedAsyncOpen(const nsresult& status) override;
-  bool RecvRedirect1Begin(const uint32_t& newChannel,
+  bool RecvRedirect1Begin(const uint32_t& registrarId,
                           const URIParams& newURI,
                           const uint32_t& redirectFlags,
                           const nsHttpResponseHead& responseHead,
-                          const nsCString& securityInfoSerialization) override;
+                          const nsCString& securityInfoSerialization,
+                          const nsCString& channelId) override;
   bool RecvRedirect3Complete() override;
   bool RecvAssociateApplicationCache(const nsCString& groupID,
                                      const nsCString& clientID) override;
   bool RecvFlushedForDiversion() override;
   bool RecvDivertMessages() override;
   bool RecvDeleteSelf() override;
 
   bool RecvReportSecurityMessage(const nsString& messageTag,
@@ -272,21 +273,22 @@ private:
                           const uint32_t& count,
                           const nsCString& data);
   void OnStopRequest(const nsresult& channelStatus, const ResourceTimingStruct& timing);
   void MaybeDivertOnStop(const nsresult& aChannelStatus);
   void OnProgress(const int64_t& progress, const int64_t& progressMax);
   void OnStatus(const nsresult& status);
   void FailedAsyncOpen(const nsresult& status);
   void HandleAsyncAbort();
-  void Redirect1Begin(const uint32_t& newChannelId,
+  void Redirect1Begin(const uint32_t& registrarId,
                       const URIParams& newUri,
                       const uint32_t& redirectFlags,
                       const nsHttpResponseHead& responseHead,
-                      const nsACString& securityInfoSerialization);
+                      const nsACString& securityInfoSerialization,
+                      const nsACString& channelId);
   void Redirect3Complete();
   void DeleteSelf();
 
   // Create a a new channel to be used in a redirection, based on the provided
   // response headers.
   nsresult SetupRedirect(nsIURI* uri,
                          const nsHttpResponseHead* responseHead,
                          const uint32_t& redirectFlags,
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -128,22 +128,23 @@ HttpChannelParent::Init(const HttpChanne
                        a.thirdPartyFlags(), a.resumeAt(), a.startPos(),
                        a.entityID(), a.chooseApplicationCache(),
                        a.appCacheClientID(), a.allowSpdy(), a.allowAltSvc(), a.fds(),
                        a.loadInfo(), a.synthesizedResponseHead(),
                        a.synthesizedSecurityInfoSerialization(),
                        a.cacheKey(), a.requestContextID(), a.preflightArgs(),
                        a.initialRwin(), a.blockAuthPrompt(),
                        a.suspendAfterSynthesizeResponse(),
-                       a.allowStaleCacheContent(), a.contentTypeHint());
+                       a.allowStaleCacheContent(), a.contentTypeHint(),
+                       a.channelId());
   }
   case HttpChannelCreationArgs::THttpChannelConnectArgs:
   {
     const HttpChannelConnectArgs& cArgs = aArgs.get_HttpChannelConnectArgs();
-    return ConnectChannel(cArgs.channelId(), cArgs.shouldIntercept());
+    return ConnectChannel(cArgs.registrarId(), cArgs.shouldIntercept());
   }
   default:
     NS_NOTREACHED("unknown open type");
     return false;
   }
 }
 
 //-----------------------------------------------------------------------------
@@ -259,17 +260,18 @@ HttpChannelParent::DoAsyncOpen(  const U
                                  const nsCString&           aSecurityInfoSerialization,
                                  const uint32_t&            aCacheKey,
                                  const nsCString&           aRequestContextID,
                                  const OptionalCorsPreflightArgs& aCorsPreflightArgs,
                                  const uint32_t&            aInitialRwin,
                                  const bool&                aBlockAuthPrompt,
                                  const bool&                aSuspendAfterSynthesizeResponse,
                                  const bool&                aAllowStaleCacheContent,
-                                 const nsCString&           aContentTypeHint)
+                                 const nsCString&           aContentTypeHint,
+                                 const nsCString&           aChannelId)
 {
   nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
   if (!uri) {
     // URIParams does MOZ_ASSERT if null, but we need to protect opt builds from
     // null deref here.
     return false;
   }
   nsCOMPtr<nsIURI> originalUri = DeserializeURI(aOriginalURI);
@@ -313,16 +315,20 @@ HttpChannelParent::DoAsyncOpen(  const U
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewChannelInternal(getter_AddRefs(channel), uri, loadInfo,
                              nullptr, nullptr, loadFlags, ios);
 
   if (NS_FAILED(rv))
     return SendFailedAsyncOpen(rv);
 
   mChannel = static_cast<nsHttpChannel *>(channel.get());
+
+  // Set the channelId allocated in child to the parent instance
+  mChannel->SetChannelId(aChannelId);
+
   mChannel->SetWarningReporter(this);
   mChannel->SetTimingEnabled(true);
   if (mPBOverride != kPBOverride_Unset) {
     mChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
   }
 
   if (doResumeAt)
     mChannel->ResumeAt(startPos, entityID);
@@ -491,24 +497,24 @@ HttpChannelParent::DoAsyncOpen(  const U
   }
   if (NS_FAILED(rv))
     return SendFailedAsyncOpen(rv);
 
   return true;
 }
 
 bool
-HttpChannelParent::ConnectChannel(const uint32_t& channelId, const bool& shouldIntercept)
+HttpChannelParent::ConnectChannel(const uint32_t& registrarId, const bool& shouldIntercept)
 {
   nsresult rv;
 
   LOG(("HttpChannelParent::ConnectChannel: Looking for a registered channel "
-       "[this=%p, id=%lu]\n", this, channelId));
+       "[this=%p, id=%lu]\n", this, registrarId));
   nsCOMPtr<nsIChannel> channel;
-  rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel));
+  rv = NS_LinkRedirectChannels(registrarId, this, getter_AddRefs(channel));
   mChannel = static_cast<nsHttpChannel*>(channel.get());
   LOG(("  found channel %p, rv=%08x", mChannel.get(), rv));
 
   nsCOMPtr<nsINetworkInterceptController> controller;
   NS_QueryNotificationCallbacks(channel, controller);
   RefPtr<HttpChannelParentListener> parentListener = do_QueryObject(controller);
   MOZ_ASSERT(parentListener);
   parentListener->SetupInterceptionAfterRedirect(shouldIntercept);
@@ -1246,42 +1252,53 @@ HttpChannelParent::Delete()
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsIParentRedirectingChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-HttpChannelParent::StartRedirect(uint32_t newChannelId,
+HttpChannelParent::StartRedirect(uint32_t registrarId,
                                  nsIChannel* newChannel,
                                  uint32_t redirectFlags,
                                  nsIAsyncVerifyRedirectCallback* callback)
 {
-  LOG(("HttpChannelParent::StartRedirect [this=%p, newChannelId=%lu "
-       "newChannel=%p callback=%p]\n", this, newChannelId, newChannel,
+  LOG(("HttpChannelParent::StartRedirect [this=%p, registrarId=%lu "
+       "newChannel=%p callback=%p]\n", this, registrarId, newChannel,
        callback));
 
   if (mIPCClosed)
     return NS_BINDING_ABORTED;
 
   nsCOMPtr<nsIURI> newURI;
   newChannel->GetURI(getter_AddRefs(newURI));
 
   URIParams uriParams;
   SerializeURI(newURI, uriParams);
 
   nsCString secInfoSerialization;
   UpdateAndSerializeSecurityInfo(secInfoSerialization);
 
+  // If the channel is a HTTP channel, we also want to inform the child
+  // about the parent's channelId attribute, so that both parent and child
+  // share the same ID. Useful for monitoring channel activity in devtools.
+  nsAutoCString channelId;
+  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
+  if (httpChannel) {
+    nsresult rv = httpChannel->GetChannelId(channelId);
+    NS_ENSURE_SUCCESS(rv, NS_BINDING_ABORTED);
+  }
+
   nsHttpResponseHead *responseHead = mChannel->GetResponseHead();
-  bool result = SendRedirect1Begin(newChannelId, uriParams, redirectFlags,
+  bool result = SendRedirect1Begin(registrarId, uriParams, redirectFlags,
                                    responseHead ? *responseHead
                                                 : nsHttpResponseHead(),
-                                   secInfoSerialization);
+                                   secInfoSerialization,
+                                   channelId);
   if (!result) {
     // Bug 621446 investigation
     mSentRedirect1BeginFailed = true;
     return NS_BINDING_ABORTED;
   }
 
   // Bug 621446 investigation
   mSentRedirect1Begin = true;
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -134,17 +134,18 @@ protected:
                    const nsCString&           aSecurityInfoSerialization,
                    const uint32_t&            aCacheKey,
                    const nsCString&           aRequestContextID,
                    const OptionalCorsPreflightArgs& aCorsPreflightArgs,
                    const uint32_t&            aInitialRwin,
                    const bool&                aBlockAuthPrompt,
                    const bool&                aSuspendAfterSynthesizeResponse,
                    const bool&                aAllowStaleCacheContent,
-                   const nsCString&           aContentTypeHint);
+                   const nsCString&           aContentTypeHint,
+                   const nsCString&           aChannelId);
 
   virtual bool RecvSetPriority(const uint16_t& priority) override;
   virtual bool RecvSetClassOfService(const uint32_t& cos) override;
   virtual bool RecvSetCacheTokenCachedCharset(const nsCString& charset) override;
   virtual bool RecvSuspend() override;
   virtual bool RecvResume() override;
   virtual bool RecvCancel(const nsresult& status) override;
   virtual bool RecvRedirect2Verify(const nsresult& result,
--- a/netwerk/protocol/http/NullHttpChannel.cpp
+++ b/netwerk/protocol/http/NullHttpChannel.cpp
@@ -53,16 +53,28 @@ NullHttpChannel::Init(nsIURI *aURI,
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // NullHttpChannel::nsIHttpChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
+NullHttpChannel::GetChannelId(nsACString& aChannelId)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+NullHttpChannel::SetChannelId(const nsACString& aChannelId)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 NullHttpChannel::GetTransferSize(uint64_t *aTransferSize)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 NullHttpChannel::GetDecodedBodySize(uint64_t *aDecodedBodySize)
 {
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -118,21 +118,22 @@ child:
   async OnStatus(nsresult status);
 
   // Used to cancel child channel if we hit errors during creating and
   // AsyncOpen of nsHttpChannel on the parent.
   async FailedAsyncOpen(nsresult status);
 
   // Called to initiate content channel redirect, starts talking to sinks
   // on the content process and reports result via Redirect2Verify above
-  async Redirect1Begin(uint32_t           newChannelId,
+  async Redirect1Begin(uint32_t           registrarId,
                        URIParams          newUri,
                        uint32_t           redirectFlags,
                        nsHttpResponseHead responseHead,
-                       nsCString          securityInfoSerialization);
+                       nsCString          securityInfoSerialization,
+                       nsCString          channelId);
 
   // Called if redirect successful so that child can complete setup.
   async Redirect3Complete();
 
   // Associate the child with an application ids
   async AssociateApplicationCache(nsCString groupID,
                                   nsCString clientID);
 
@@ -156,9 +157,8 @@ child:
 
   // Tell the child to issue a deprecation warning.
   async IssueDeprecationWarning(uint32_t warning, bool asError);
 };
 
 
 } // namespace net
 } // namespace mozilla
-
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -280,20 +280,21 @@ nsHttpChannel::~nsHttpChannel()
         mAuthProvider->Disconnect(NS_ERROR_ABORT);
 }
 
 nsresult
 nsHttpChannel::Init(nsIURI *uri,
                     uint32_t caps,
                     nsProxyInfo *proxyInfo,
                     uint32_t proxyResolveFlags,
-                    nsIURI *proxyURI)
+                    nsIURI *proxyURI,
+                    const nsID& channelId)
 {
     nsresult rv = HttpBaseChannel::Init(uri, caps, proxyInfo,
-                                        proxyResolveFlags, proxyURI);
+                                        proxyResolveFlags, proxyURI, channelId);
     if (NS_FAILED(rv))
         return rv;
 
     LOG(("nsHttpChannel::Init [this=%p]\n", this));
 
     return rv;
 }
 
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -114,17 +114,18 @@ public:
     NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks) override;
     NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup) override;
     NS_IMETHOD GetRequestMethod(nsACString& aMethod) override;
 
     nsHttpChannel();
 
     virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo,
                           uint32_t aProxyResolveFlags,
-                          nsIURI *aProxyURI) override;
+                          nsIURI *aProxyURI,
+                          const nsID& aChannelId) override;
 
     nsresult OnPush(const nsACString &uri, Http2PushedStream *pushedStream);
 
     static bool IsRedirectStatus(uint32_t status);
 
 
     // Methods HttpBaseChannel didn't implement for us or that we override.
     //
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -49,16 +49,17 @@
 #include "nsIParentalControlsService.h"
 #include "nsPIDOMWindow.h"
 #include "nsINetworkLinkService.h"
 #include "nsHttpChannelAuthProvider.h"
 #include "nsServiceManagerUtils.h"
 #include "nsComponentManagerUtils.h"
 #include "nsSocketTransportService2.h"
 #include "nsIOService.h"
+#include "nsIUUIDGenerator.h"
 
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/net/NeckoParent.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/unused.h"
 
 #if defined(XP_UNIX)
@@ -1890,17 +1891,17 @@ nsHttpHandler::SetAcceptEncodings(const 
         mHttpsAcceptEncodings = aAcceptEncodings;
     } else {
         // use legacy list if a secure override is not specified
         mHttpAcceptEncodings = aAcceptEncodings;
         if (mHttpsAcceptEncodings.IsEmpty()) {
             mHttpsAcceptEncodings = aAcceptEncodings;
         }
     }
-      
+
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpHandler::nsISupports
 //-----------------------------------------------------------------------------
 
 NS_IMPL_ISUPPORTS(nsHttpHandler,
@@ -2028,17 +2029,21 @@ nsHttpHandler::NewProxiedChannel2(nsIURI
             caps |= NS_HTTP_ALLOW_PIPELINING;
     }
 
     if (!IsNeckoChild()) {
         // HACK: make sure PSM gets initialized on the main thread.
         net_EnsurePSMInit();
     }
 
-    rv = httpChannel->Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI);
+    nsID channelId;
+    rv = NewChannelId(&channelId);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = httpChannel->Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI, channelId);
     if (NS_FAILED(rv))
         return rv;
 
     // set the loadInfo on the new channel
     rv = httpChannel->SetLoadInfo(aLoadInfo);
     if (NS_FAILED(rv)) {
         return rv;
     }
@@ -2434,10 +2439,23 @@ void
 nsHttpHandler::ShutdownConnectionManager()
 {
     // ensure connection manager is shutdown
     if (mConnMgr) {
         mConnMgr->Shutdown();
     }
 }
 
+nsresult
+nsHttpHandler::NewChannelId(nsID *channelId)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  if (!mUUIDGen) {
+    nsresult rv;
+    mUUIDGen = do_GetService("@mozilla.org/uuid-generator;1", &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return mUUIDGen->GenerateUUIDInPlace(channelId);
+}
+
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -23,16 +23,17 @@ class nsIHttpChannel;
 class nsIPrefBranch;
 class nsICancelable;
 class nsICookieService;
 class nsIIOService;
 class nsIRequestContextService;
 class nsISiteSecurityService;
 class nsIStreamConverterService;
 class nsITimer;
+class nsIUUIDGenerator;
 
 
 namespace mozilla {
 namespace net {
 
 extern Atomic<PRThread*, Relaxed> gSocketThread;
 
 class ATokenBucketEvent;
@@ -623,16 +624,21 @@ public:
 private:
     RefPtr<Tickler> mWifiTickler;
     void TickleWifi(nsIInterfaceRequestor *cb);
 
 private:
     nsresult SpeculativeConnectInternal(nsIURI *aURI,
                                         nsIInterfaceRequestor *aCallbacks,
                                         bool anonymous);
+
+    // UUID generator for channelIds
+    nsCOMPtr<nsIUUIDGenerator> mUUIDGen;
+
+    nsresult NewChannelId(nsID *channelId);
 };
 
 extern nsHttpHandler *gHttpHandler;
 
 //-----------------------------------------------------------------------------
 // nsHttpsHandler - thin wrapper to distinguish the HTTP handler from the
 //                  HTTPS handler (even though they share the same impl).
 //-----------------------------------------------------------------------------
--- a/netwerk/protocol/http/nsIHttpChannel.idl
+++ b/netwerk/protocol/http/nsIHttpChannel.idl
@@ -442,9 +442,16 @@ interface nsIHttpChannel : nsIChannel
      *         started to deliver the content to its listener.
      */
     void redirectTo(in nsIURI aTargetURI);
 
     /**
      * Identifies the request context for this load.
      */
     [noscript] attribute nsID requestContextID;
+
+    /**
+     * Unique ID of the channel, shared between parent and child. Needed if
+     * the channel activity needs to be monitored across process boundaries,
+     * like in devtools net monitor. See bug 1274556.
+     */
+    attribute ACString channelId;
 };
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
@@ -711,16 +711,30 @@ nsViewSourceChannel::OnDataAvailable(nsI
 
 
 // nsIHttpChannel methods
 
 // We want to forward most of nsIHttpChannel over to mHttpChannel, but we want
 // to override GetRequestHeader and VisitHeaders. The reason is that we don't
 // want various headers like Link: and Refresh: applying to view-source.
 NS_IMETHODIMP
+nsViewSourceChannel::GetChannelId(nsACString& aChannelId)
+{
+  return !mHttpChannel ? NS_ERROR_NULL_POINTER :
+      mHttpChannel->GetChannelId(aChannelId);
+}
+
+NS_IMETHODIMP
+nsViewSourceChannel::SetChannelId(const nsACString& aChannelId)
+{
+  return !mHttpChannel ? NS_ERROR_NULL_POINTER :
+      mHttpChannel->SetChannelId(aChannelId);
+}
+
+NS_IMETHODIMP
 nsViewSourceChannel::GetRequestMethod(nsACString & aRequestMethod)
 {
     return !mHttpChannel ? NS_ERROR_NULL_POINTER :
         mHttpChannel->GetRequestMethod(aRequestMethod);
 }
 
 NS_IMETHODIMP
 nsViewSourceChannel::SetRequestMethod(const nsACString & aRequestMethod)