Bug 1168208 - Refactor the existing logic for syncing the security info between Response and channel objects into a new helper class; r=nsm,jdm,bkelly
☠☠ backed out by 7431168bfa3b ☠ ☠
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 25 May 2015 14:21:05 -0400
changeset 268040 ae9c77fa58d18a2129e6552a49c389a37e6b31c4
parent 268039 020ac30e270a4791af1bfbc8a25dfe60616c26d9
child 268041 67efcb1efc4383180e645b9ee4de6bcbfc774b6a
push id2294
push userbsmedberg@mozilla.com
push dateWed, 27 May 2015 15:05:10 +0000
reviewersnsm, jdm, bkelly
bugs1168208
milestone41.0a1
Bug 1168208 - Refactor the existing logic for syncing the security info between Response and channel objects into a new helper class; r=nsm,jdm,bkelly
dom/cache/CacheTypes.ipdlh
dom/cache/DBSchema.cpp
dom/cache/TypeUtils.cpp
dom/fetch/ChannelInfo.cpp
dom/fetch/ChannelInfo.h
dom/fetch/ChannelInfo.ipdlh
dom/fetch/FetchDriver.cpp
dom/fetch/InternalResponse.cpp
dom/fetch/InternalResponse.h
dom/fetch/Response.h
dom/fetch/moz.build
dom/workers/ScriptLoader.cpp
dom/workers/ServiceWorkerEvents.cpp
dom/workers/ServiceWorkerScriptCache.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
dom/workers/Workers.h
netwerk/base/nsINetworkInterceptController.idl
netwerk/protocol/http/InterceptedChannel.cpp
netwerk/protocol/http/InterceptedChannel.h
netwerk/protocol/http/TunnelUtils.h
netwerk/protocol/http/nsHttpConnectionInfo.h
--- a/dom/cache/CacheTypes.ipdlh
+++ b/dom/cache/CacheTypes.ipdlh
@@ -1,16 +1,17 @@
 /* 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 protocol PCache;
 include protocol PCachePushStream;
 include protocol PCacheStreamControl;
 include InputStreamParams;
+include ChannelInfo;
 
 using HeadersGuardEnum from "mozilla/dom/cache/IPCUtils.h";
 using RequestCredentials from "mozilla/dom/cache/IPCUtils.h";
 using RequestMode from "mozilla/dom/cache/IPCUtils.h";
 using RequestCache from "mozilla/dom/cache/IPCUtils.h";
 using RequestContext from "mozilla/dom/cache/IPCUtils.h";
 using ResponseType from "mozilla/dom/cache/IPCUtils.h";
 using mozilla::void_t from "ipc/IPCMessageUtils.h";
@@ -76,17 +77,17 @@ struct CacheResponse
 {
   ResponseType type;
   nsString url;
   uint32_t status;
   nsCString statusText;
   HeadersEntry[] headers;
   HeadersGuardEnum headersGuard;
   CacheReadStreamOrVoid body;
-  nsCString securityInfo;
+  IPCChannelInfo channelInfo;
 };
 
 union CacheResponseOrVoid
 {
   void_t;
   CacheResponse;
 };
 
--- a/dom/cache/DBSchema.cpp
+++ b/dom/cache/DBSchema.cpp
@@ -170,18 +170,18 @@ static nsresult QueryCache(mozIStorageCo
 static nsresult MatchByVaryHeader(mozIStorageConnection* aConn,
                                   const CacheRequest& aRequest,
                                   EntryId entryId, bool* aSuccessOut);
 static nsresult DeleteEntries(mozIStorageConnection* aConn,
                               const nsTArray<EntryId>& aEntryIdList,
                               nsTArray<nsID>& aDeletedBodyIdListOut,
                               nsTArray<IdCount>& aDeletedSecurityIdListOut,
                               uint32_t aPos=0, int32_t aLen=-1);
-static nsresult InsertSecurity(mozIStorageConnection* aConn,
-                               const nsACString& aData, int32_t *aIdOut);
+static nsresult InsertSecurityInfo(mozIStorageConnection* aConn,
+                                   const nsACString& aData, int32_t *aIdOut);
 static nsresult DeleteSecurityInfo(mozIStorageConnection* aConn, int32_t aId,
                                    int32_t aCount);
 static nsresult DeleteSecurityInfoList(mozIStorageConnection* aConn,
                                        const nsTArray<IdCount>& aDeletedStorageIdList);
 static nsresult InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
                             const CacheRequest& aRequest,
                             const nsID* aRequestBodyId,
                             const CacheResponse& aResponse,
@@ -1189,18 +1189,18 @@ DeleteEntries(mozIStorageConnection* aCo
 
   rv = state->Execute();
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   return rv;
 }
 
 nsresult
-InsertSecurity(mozIStorageConnection* aConn, const nsACString& aData,
-               int32_t *aIdOut)
+InsertSecurityInfo(mozIStorageConnection* aConn, const nsACString& aData,
+                   int32_t *aIdOut)
 {
   MOZ_ASSERT(aConn);
   MOZ_ASSERT(aIdOut);
   MOZ_ASSERT(!aData.IsEmpty());
 
   // We want to use an index to find existing security blobs, but indexing
   // the full blob would be quite expensive.  Instead, we index a small
   // hash value.  Calculate this hash as the first 8 bytes of the SHA1 of
@@ -1389,18 +1389,20 @@ InsertEntry(mozIStorageConnection* aConn
             const nsID* aResponseBodyId)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aConn);
 
   nsresult rv = NS_OK;
   int32_t securityId = -1;
 
-  if (!aResponse.securityInfo().IsEmpty()) {
-    rv = InsertSecurity(aConn, aResponse.securityInfo(), &securityId);
+  if (!aResponse.channelInfo().securityInfo().IsEmpty()) {
+    rv = InsertSecurityInfo(aConn,
+                            aResponse.channelInfo().securityInfo(),
+                            &securityId);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
   }
 
   nsCOMPtr<mozIStorageStatement> state;
   rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
     "INSERT INTO entries ("
       "request_method, "
       "request_url, "
@@ -1506,17 +1508,17 @@ InsertEntry(mozIStorageConnection* aConn
 
   rv = state->BindInt32ByName(NS_LITERAL_CSTRING("response_headers_guard"),
     static_cast<int32_t>(aResponse.headersGuard()));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   rv = BindId(state, NS_LITERAL_CSTRING("response_body_id"), aResponseBodyId);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-  if (aResponse.securityInfo().IsEmpty()) {
+  if (aResponse.channelInfo().securityInfo().IsEmpty()) {
     rv = state->BindNullByName(NS_LITERAL_CSTRING("response_security_info_id"));
   } else {
     rv = state->BindInt32ByName(NS_LITERAL_CSTRING("response_security_info_id"),
                                 securityId);
   }
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   rv = state->BindInt64ByName(NS_LITERAL_CSTRING("cache_id"), aCacheId);
@@ -1652,17 +1654,17 @@ ReadResponse(mozIStorageConnection* aCon
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
   aSavedResponseOut->mHasBodyId = !nullBody;
 
   if (aSavedResponseOut->mHasBodyId) {
     rv = ExtractId(state, 5, &aSavedResponseOut->mBodyId);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
   }
 
-  rv = state->GetBlobAsUTF8String(6, aSavedResponseOut->mValue.securityInfo());
+  rv = state->GetBlobAsUTF8String(6, aSavedResponseOut->mValue.channelInfo().securityInfo());
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
     "SELECT "
       "name, "
       "value "
     "FROM response_headers "
     "WHERE entry_id=:entry_id;"
--- a/dom/cache/TypeUtils.cpp
+++ b/dom/cache/TypeUtils.cpp
@@ -219,17 +219,17 @@ TypeUtils::ToCacheResponseWithoutBody(Ca
   nsRefPtr<InternalHeaders> headers = aIn.UnfilteredHeaders();
   MOZ_ASSERT(headers);
   if (HasVaryStar(headers)) {
     aRv.ThrowTypeError(MSG_RESPONSE_HAS_VARY_STAR);
     return;
   }
   ToHeadersEntryList(aOut.headers(), headers);
   aOut.headersGuard() = headers->Guard();
-  aOut.securityInfo() = aIn.GetSecurityInfo();
+  aOut.channelInfo() = aIn.GetChannelInfo().AsIPCChannelInfo();
 }
 
 void
 TypeUtils::ToCacheResponse(CacheResponse& aOut, Response& aIn, ErrorResult& aRv)
 {
   if (aIn.BodyUsed()) {
     aRv.ThrowTypeError(MSG_FETCH_BODY_CONSUMED_ERROR);
     return;
@@ -285,17 +285,17 @@ TypeUtils::ToResponse(const CacheRespons
   nsRefPtr<InternalHeaders> internalHeaders =
     ToInternalHeaders(aIn.headers(), aIn.headersGuard());
   ErrorResult result;
   ir->Headers()->SetGuard(aIn.headersGuard(), result);
   MOZ_ASSERT(!result.Failed());
   ir->Headers()->Fill(*internalHeaders, result);
   MOZ_ASSERT(!result.Failed());
 
-  ir->SetSecurityInfo(aIn.securityInfo());
+  ir->InitChannelInfo(aIn.channelInfo());
 
   nsCOMPtr<nsIInputStream> stream = ReadStream::Create(aIn.body());
   ir->SetBody(stream);
 
   switch (aIn.type())
   {
     case ResponseType::Default:
       break;
copy from dom/fetch/InternalResponse.cpp
copy to dom/fetch/ChannelInfo.cpp
--- a/dom/fetch/InternalResponse.cpp
+++ b/dom/fetch/ChannelInfo.cpp
@@ -1,98 +1,94 @@
 /* -*- 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 "InternalResponse.h"
-
-#include "mozilla/dom/InternalHeaders.h"
-#include "nsStreamUtils.h"
+#include "mozilla/dom/ChannelInfo.h"
+#include "nsCOMPtr.h"
+#include "nsIChannel.h"
+#include "nsIHttpChannel.h"
 #include "nsSerializationHelper.h"
+#include "mozilla/net/HttpBaseChannel.h"
+#include "mozilla/ipc/ChannelInfo.h"
 
-namespace mozilla {
-namespace dom {
+using namespace mozilla;
+using namespace mozilla::dom;
 
-InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText)
-  : mType(ResponseType::Default)
-  , mFinalURL(false)
-  , mStatus(aStatus)
-  , mStatusText(aStatusText)
-  , mHeaders(new InternalHeaders(HeadersGuardEnum::Response))
+void
+ChannelInfo::InitFromChannel(nsIChannel* aChannel)
 {
-}
-
-already_AddRefed<InternalResponse>
-InternalResponse::Clone()
-{
-  nsRefPtr<InternalResponse> clone = CreateIncompleteCopy();
+  MOZ_ASSERT(!mInited, "Cannot initialize the object twice");
 
-  clone->mHeaders = new InternalHeaders(*mHeaders);
-  if (mWrappedResponse) {
-    clone->mWrappedResponse = mWrappedResponse->Clone();
-    MOZ_ASSERT(!mBody);
-    return clone.forget();
-  }
-
-  if (!mBody) {
-    return clone.forget();
+  nsCOMPtr<nsISupports> securityInfo;
+  aChannel->GetSecurityInfo(getter_AddRefs(securityInfo));
+  if (securityInfo) {
+    SetSecurityInfo(securityInfo);
   }
 
-  nsCOMPtr<nsIInputStream> clonedBody;
-  nsCOMPtr<nsIInputStream> replacementBody;
-
-  nsresult rv = NS_CloneInputStream(mBody, getter_AddRefs(clonedBody),
-                                    getter_AddRefs(replacementBody));
-  if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; }
-
-  clone->mBody.swap(clonedBody);
-  if (replacementBody) {
-    mBody.swap(replacementBody);
-  }
-
-  return clone.forget();
-}
-
-already_AddRefed<InternalResponse>
-InternalResponse::BasicResponse()
-{
-  MOZ_ASSERT(!mWrappedResponse, "Can't BasicResponse a already wrapped response");
-  nsRefPtr<InternalResponse> basic = CreateIncompleteCopy();
-  basic->mType = ResponseType::Basic;
-  basic->mHeaders = InternalHeaders::BasicHeaders(Headers());
-  basic->mWrappedResponse = this;
-  return basic.forget();
-}
-
-already_AddRefed<InternalResponse>
-InternalResponse::CORSResponse()
-{
-  MOZ_ASSERT(!mWrappedResponse, "Can't CORSResponse a already wrapped response");
-  nsRefPtr<InternalResponse> cors = CreateIncompleteCopy();
-  cors->mType = ResponseType::Cors;
-  cors->mHeaders = InternalHeaders::CORSHeaders(Headers());
-  cors->mWrappedResponse = this;
-  return cors.forget();
+  mInited = true;
 }
 
 void
-InternalResponse::SetSecurityInfo(nsISupports* aSecurityInfo)
+ChannelInfo::InitFromIPCChannelInfo(const ipc::IPCChannelInfo& aChannelInfo)
+{
+  MOZ_ASSERT(!mInited, "Cannot initialize the object twice");
+
+  mSecurityInfo = aChannelInfo.securityInfo();
+
+  mInited = true;
+}
+
+void
+ChannelInfo::SetSecurityInfo(nsISupports* aSecurityInfo)
 {
   MOZ_ASSERT(mSecurityInfo.IsEmpty(), "security info should only be set once");
   nsCOMPtr<nsISerializable> serializable = do_QueryInterface(aSecurityInfo);
   if (!serializable) {
     NS_WARNING("A non-serializable object was passed to InternalResponse::SetSecurityInfo");
     return;
   }
   NS_SerializeToString(serializable, mSecurityInfo);
 }
 
-void
-InternalResponse::SetSecurityInfo(const nsCString& aSecurityInfo)
+nsresult
+ChannelInfo::ResurrectInfoOnChannel(nsIChannel* aChannel)
 {
-  MOZ_ASSERT(mSecurityInfo.IsEmpty(), "security info should only be set once");
-  mSecurityInfo = aSecurityInfo;
+  MOZ_ASSERT(mInited);
+
+  if (!mSecurityInfo.IsEmpty()) {
+    nsCOMPtr<nsISupports> infoObj;
+    nsresult rv = NS_DeserializeObject(mSecurityInfo, getter_AddRefs(infoObj));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    nsCOMPtr<nsIHttpChannel> httpChannel =
+      do_QueryInterface(aChannel);
+    if (NS_WARN_IF(!httpChannel)) {
+      return NS_ERROR_FAILURE;
+    }
+    net::HttpBaseChannel* httpBaseChannel =
+      static_cast<net::HttpBaseChannel*>(httpChannel.get());
+    rv = httpBaseChannel->OverrideSecurityInfo(infoObj);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
+  return NS_OK;
 }
 
-} // namespace dom
-} // namespace mozilla
+ipc::IPCChannelInfo
+ChannelInfo::AsIPCChannelInfo() const
+{
+  // This may be called when mInited is false, for example if we try to store
+  // a synthesized Response object into the Cache.  Uninitialized and empty
+  // ChannelInfo objects are indistinguishable at the IPC level, so this is
+  // fine.
+
+  IPCChannelInfo ipcInfo;
+
+  ipcInfo.securityInfo() = mSecurityInfo;
+
+  return ipcInfo;
+}
copy from dom/fetch/Response.h
copy to dom/fetch/ChannelInfo.h
--- a/dom/fetch/Response.h
+++ b/dom/fetch/ChannelInfo.h
@@ -1,129 +1,87 @@
 /* -*- 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_Response_h
-#define mozilla_dom_Response_h
-
-#include "nsWrapperCache.h"
-#include "nsISupportsImpl.h"
+#ifndef mozilla_dom_ChannelInfo_h
+#define mozilla_dom_ChannelInfo_h
 
-#include "mozilla/dom/Fetch.h"
-#include "mozilla/dom/ResponseBinding.h"
+#include "nsString.h"
 
-#include "InternalHeaders.h"
-#include "InternalResponse.h"
+class nsIChannel;
 
 namespace mozilla {
+namespace ipc {
+class IPCChannelInfo;
+} // namespace ipc
+
 namespace dom {
 
-class Headers;
-
-class Response final : public nsISupports
-                     , public FetchBody<Response>
-                     , public nsWrapperCache
+// This class represents the information related to a Response that we
+// retrieve from the corresponding channel that is used to perform the fetch.
+//
+// When adding new members to this object, the following code needs to be
+// updated:
+// * IPCChannelInfo
+// * InitFromChannel and InitFromIPCChannelInfo members
+// * ResurrectInfoOnChannel member
+// * AsIPCChannelInfo member
+// * constructors and assignment operators for this class.
+// * DOM Cache schema code (in dom/cache/DBSchema.cpp) to ensure that the newly
+//   added member is saved into the DB and loaded from it properly.
+//
+// Care must be taken when initializing this object, or when calling
+// ResurrectInfoOnChannel().  This object cannot be initialized twice, and
+// ResurrectInfoOnChannel() cannot be called on it before it has been
+// initialized.  There are assertions ensuring these invariants.
+class ChannelInfo final
 {
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Response)
+public:
+  typedef mozilla::ipc::IPCChannelInfo IPCChannelInfo;
 
-public:
-  Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse);
-
-  Response(const Response& aOther) = delete;
-
-  JSObject*
-  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
+  ChannelInfo()
+    : mInited(false)
   {
-    return ResponseBinding::Wrap(aCx, this, aGivenProto);
-  }
-
-  ResponseType
-  Type() const
-  {
-    return mInternalResponse->Type();
-  }
-
-  void
-  GetUrl(DOMString& aUrl) const
-  {
-    nsCString url;
-    mInternalResponse->GetUrl(url);
-    aUrl.AsAString() = NS_ConvertUTF8toUTF16(url);
-  }
-
-  uint16_t
-  Status() const
-  {
-    return mInternalResponse->GetStatus();
   }
 
-  bool
-  Ok() const
+  ChannelInfo(const ChannelInfo& aRHS)
+    : mSecurityInfo(aRHS.mSecurityInfo)
+    , mInited(aRHS.mInited)
   {
-    return mInternalResponse->GetStatus() >= 200 &&
-           mInternalResponse->GetStatus() <= 299;
   }
 
-  void
-  GetStatusText(nsCString& aStatusText) const
+  ChannelInfo&
+  operator=(const ChannelInfo& aRHS)
   {
-    aStatusText = mInternalResponse->GetStatusText();
-  }
-
-  InternalHeaders*
-  GetInternalHeaders() const
-  {
-    return mInternalResponse->Headers();
-  }
-
-  const nsCString&
-  GetSecurityInfo() const
-  {
-    return mInternalResponse->GetSecurityInfo();
+    mSecurityInfo = aRHS.mSecurityInfo;
+    mInited = aRHS.mInited;
+    return *this;
   }
 
-  Headers* Headers_();
-
-  void
-  GetBody(nsIInputStream** aStream) { return mInternalResponse->GetBody(aStream); }
-
-  static already_AddRefed<Response>
-  Error(const GlobalObject& aGlobal);
+  void InitFromChannel(nsIChannel* aChannel);
+  void InitFromIPCChannelInfo(const IPCChannelInfo& aChannelInfo);
 
-  static already_AddRefed<Response>
-  Redirect(const GlobalObject& aGlobal, const nsAString& aUrl, uint16_t aStatus, ErrorResult& aRv);
+  // This restores every possible information stored from a previous channel
+  // object on a new one.
+  nsresult ResurrectInfoOnChannel(nsIChannel* aChannel);
 
-  static already_AddRefed<Response>
-  Constructor(const GlobalObject& aGlobal,
-              const Optional<ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>& aBody,
-              const ResponseInit& aInit, ErrorResult& rv);
-
-  nsIGlobalObject* GetParentObject() const
+  bool IsInitialized() const
   {
-    return mOwner;
+    return mInited;
   }
 
-  already_AddRefed<Response>
-  Clone(ErrorResult& aRv) const;
-
-  void
-  SetBody(nsIInputStream* aBody);
-
-  already_AddRefed<InternalResponse>
-  GetInternalResponse() const;
+  IPCChannelInfo AsIPCChannelInfo() const;
 
 private:
-  ~Response();
+  void SetSecurityInfo(nsISupports* aSecurityInfo);
 
-  nsCOMPtr<nsIGlobalObject> mOwner;
-  nsRefPtr<InternalResponse> mInternalResponse;
-  // Lazily created
-  nsRefPtr<Headers> mHeaders;
+private:
+  nsCString mSecurityInfo;
+  bool mInited;
 };
 
 } // namespace dom
 } // namespace mozilla
 
-#endif // mozilla_dom_Response_h
+#endif // mozilla_dom_ChannelInfo_h
new file mode 100644
--- /dev/null
+++ b/dom/fetch/ChannelInfo.ipdlh
@@ -0,0 +1,14 @@
+/* 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/. */
+
+namespace mozilla {
+namespace ipc {
+
+struct IPCChannelInfo
+{
+  nsCString securityInfo;
+};
+
+} // namespace ipc
+} // namespace mozilla
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -701,22 +701,18 @@ FetchDriver::OnStartRequest(nsIRequest* 
                   false /* blocking output, since the pipe is 'in'finite */ );
   if (NS_WARN_IF(NS_FAILED(rv))) {
     FailWithNetworkError();
     // Cancel request.
     return rv;
   }
   response->SetBody(pipeInputStream);
 
-  nsCOMPtr<nsISupports> securityInfo;
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
-  rv = channel->GetSecurityInfo(getter_AddRefs(securityInfo));
-  if (securityInfo) {
-    response->SetSecurityInfo(securityInfo);
-  }
+  response->InitChannelInfo(channel);
 
   // Resolves fetch() promise which may trigger code running in a worker.  Make
   // sure the Response is fully initialized before calling this.
   mResponse = BeginAndGetFilteredResponse(response);
 
   nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     FailWithNetworkError();
--- a/dom/fetch/InternalResponse.cpp
+++ b/dom/fetch/InternalResponse.cpp
@@ -3,17 +3,16 @@
 /* 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 "InternalResponse.h"
 
 #include "mozilla/dom/InternalHeaders.h"
 #include "nsStreamUtils.h"
-#include "nsSerializationHelper.h"
 
 namespace mozilla {
 namespace dom {
 
 InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText)
   : mType(ResponseType::Default)
   , mFinalURL(false)
   , mStatus(aStatus)
@@ -70,29 +69,10 @@ InternalResponse::CORSResponse()
   MOZ_ASSERT(!mWrappedResponse, "Can't CORSResponse a already wrapped response");
   nsRefPtr<InternalResponse> cors = CreateIncompleteCopy();
   cors->mType = ResponseType::Cors;
   cors->mHeaders = InternalHeaders::CORSHeaders(Headers());
   cors->mWrappedResponse = this;
   return cors.forget();
 }
 
-void
-InternalResponse::SetSecurityInfo(nsISupports* aSecurityInfo)
-{
-  MOZ_ASSERT(mSecurityInfo.IsEmpty(), "security info should only be set once");
-  nsCOMPtr<nsISerializable> serializable = do_QueryInterface(aSecurityInfo);
-  if (!serializable) {
-    NS_WARNING("A non-serializable object was passed to InternalResponse::SetSecurityInfo");
-    return;
-  }
-  NS_SerializeToString(serializable, mSecurityInfo);
-}
-
-void
-InternalResponse::SetSecurityInfo(const nsCString& aSecurityInfo)
-{
-  MOZ_ASSERT(mSecurityInfo.IsEmpty(), "security info should only be set once");
-  mSecurityInfo = aSecurityInfo;
-}
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/fetch/InternalResponse.h
+++ b/dom/fetch/InternalResponse.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_dom_InternalResponse_h
 #define mozilla_dom_InternalResponse_h
 
 #include "nsIInputStream.h"
 #include "nsISupportsImpl.h"
 
 #include "mozilla/dom/ResponseBinding.h"
+#include "mozilla/dom/ChannelInfo.h"
 
 namespace mozilla {
 namespace dom {
 
 class InternalHeaders;
 
 class InternalResponse final
 {
@@ -43,17 +44,17 @@ public:
   OpaqueResponse()
   {
     MOZ_ASSERT(!mWrappedResponse, "Can't OpaqueResponse a already wrapped response");
     nsRefPtr<InternalResponse> response = new InternalResponse(0, EmptyCString());
     response->mType = ResponseType::Opaque;
     response->mTerminationReason = mTerminationReason;
     response->mURL = mURL;
     response->mFinalURL = mFinalURL;
-    response->mSecurityInfo = mSecurityInfo;
+    response->mChannelInfo = mChannelInfo;
     response->mWrappedResponse = this;
     return response.forget();
   }
 
   already_AddRefed<InternalResponse>
   BasicResponse();
 
   already_AddRefed<InternalResponse>
@@ -151,27 +152,39 @@ public:
     if (mWrappedResponse) {
       return mWrappedResponse->SetBody(aBody);
     }
     // A request's body may not be reset once set.
     MOZ_ASSERT(!mBody);
     mBody = aBody;
   }
 
-  const nsCString&
-  GetSecurityInfo() const
+  void
+  InitChannelInfo(nsIChannel* aChannel)
   {
-    return mSecurityInfo;
+    mChannelInfo.InitFromChannel(aChannel);
   }
 
   void
-  SetSecurityInfo(nsISupports* aSecurityInfo);
+  InitChannelInfo(const mozilla::ipc::IPCChannelInfo& aChannelInfo)
+  {
+    mChannelInfo.InitFromIPCChannelInfo(aChannelInfo);
+  }
 
   void
-  SetSecurityInfo(const nsCString& aSecurityInfo);
+  InitChannelInfo(const ChannelInfo& aChannelInfo)
+  {
+    mChannelInfo = aChannelInfo;
+  }
+
+  const ChannelInfo&
+  GetChannelInfo() const
+  {
+    return mChannelInfo;
+  }
 
 private:
   ~InternalResponse()
   { }
 
   explicit InternalResponse(const InternalResponse& aOther) = delete;
   InternalResponse& operator=(const InternalResponse&) = delete;
 
@@ -180,29 +193,29 @@ private:
   // are left uninitialized. Used for cloning and filtering.
   already_AddRefed<InternalResponse> CreateIncompleteCopy()
   {
     nsRefPtr<InternalResponse> copy = new InternalResponse(mStatus, mStatusText);
     copy->mType = mType;
     copy->mTerminationReason = mTerminationReason;
     copy->mURL = mURL;
     copy->mFinalURL = mFinalURL;
-    copy->mSecurityInfo = mSecurityInfo;
+    copy->mChannelInfo = mChannelInfo;
     return copy.forget();
   }
 
   ResponseType mType;
   nsCString mTerminationReason;
   nsCString mURL;
   bool mFinalURL;
   const uint16_t mStatus;
   const nsCString mStatusText;
   nsRefPtr<InternalHeaders> mHeaders;
   nsCOMPtr<nsIInputStream> mBody;
-  nsCString mSecurityInfo;
+  ChannelInfo mChannelInfo;
 
   // For filtered responses.
   // Cache, and SW interception should always serialize/access the underlying
   // unfiltered headers and when deserializing, create an InternalResponse
   // with the unfiltered headers followed by wrapping it.
   nsRefPtr<InternalResponse> mWrappedResponse;
 };
 
--- a/dom/fetch/Response.h
+++ b/dom/fetch/Response.h
@@ -73,20 +73,26 @@ public:
   }
 
   InternalHeaders*
   GetInternalHeaders() const
   {
     return mInternalResponse->Headers();
   }
 
-  const nsCString&
-  GetSecurityInfo() const
+  void
+  InitChannelInfo(nsIChannel* aChannel)
   {
-    return mInternalResponse->GetSecurityInfo();
+    mInternalResponse->InitChannelInfo(aChannel);
+  }
+
+  const ChannelInfo&
+  GetChannelInfo() const
+  {
+    return mInternalResponse->GetChannelInfo();
   }
 
   Headers* Headers_();
 
   void
   GetBody(nsIInputStream** aStream) { return mInternalResponse->GetBody(aStream); }
 
   static already_AddRefed<Response>
--- a/dom/fetch/moz.build
+++ b/dom/fetch/moz.build
@@ -1,36 +1,48 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 EXPORTS.mozilla.dom += [
+    'ChannelInfo.h',
     'Fetch.h',
     'FetchDriver.h',
     'Headers.h',
     'InternalHeaders.h',
     'InternalRequest.h',
     'InternalResponse.h',
     'Request.h',
     'Response.h',
 ]
 
 UNIFIED_SOURCES += [
+    'ChannelInfo.cpp',
     'Fetch.cpp',
     'FetchDriver.cpp',
     'Headers.cpp',
     'InternalHeaders.cpp',
     'InternalRequest.cpp',
     'InternalResponse.cpp',
     'Request.cpp',
     'Response.cpp',
 ]
 
+IPDL_SOURCES += [
+    'ChannelInfo.ipdlh',
+]
+
 LOCAL_INCLUDES += [
     '../workers',
+    # For HttpBaseChannel.h dependencies
+    '/netwerk/base',
     # For nsDataHandler.h
     '/netwerk/protocol/data',
+    # For HttpBaseChannel.h
+    '/netwerk/protocol/http',
 ]
 
 FAIL_ON_WARNINGS = True
 FINAL_LIBRARY = 'xul'
+
+include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -9,17 +9,16 @@
 #include "nsIChannel.h"
 #include "nsIContentPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIHttpChannel.h"
 #include "nsIInputStreamPump.h"
 #include "nsIIOService.h"
 #include "nsIProtocolHandler.h"
 #include "nsIScriptSecurityManager.h"
-#include "nsISerializable.h"
 #include "nsIStreamLoader.h"
 #include "nsIStreamListenerTee.h"
 #include "nsIThreadRetargetableRequest.h"
 #include "nsIURI.h"
 
 #include "jsapi.h"
 #include "nsError.h"
 #include "nsContentPolicyUtils.h"
@@ -417,17 +416,17 @@ private:
 
   ScriptLoadInfo& mLoadInfo;
   uint32_t mIndex;
   nsRefPtr<ScriptLoaderRunnable> mRunnable;
   bool mIsWorkerScript;
   bool mFailed;
   nsCOMPtr<nsIInputStreamPump> mPump;
   nsCOMPtr<nsIURI> mBaseURI;
-  nsCString mSecurityInfo;
+  ChannelInfo mChannelInfo;
 };
 
 NS_IMPL_ISUPPORTS(CacheScriptLoader, nsIStreamLoaderObserver)
 
 class CachePromiseHandler final : public PromiseNativeHandler
 {
 public:
   CachePromiseHandler(ScriptLoaderRunnable* aRunnable,
@@ -584,29 +583,19 @@ private:
     nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
     MOZ_ASSERT(channel == loadInfo.mChannel);
 
     // We synthesize the result code, but its never exposed to content.
     nsRefPtr<InternalResponse> ir =
       new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
     ir->SetBody(mReader);
 
-    // Set the security info of the channel on the response so that it's
+    // Set the channel info of the channel on the response so that it's
     // saved in the cache.
-    nsCOMPtr<nsISupports> infoObj;
-    channel->GetSecurityInfo(getter_AddRefs(infoObj));
-    if (infoObj) {
-      nsCOMPtr<nsISerializable> serializable = do_QueryInterface(infoObj);
-      if (serializable) {
-        ir->SetSecurityInfo(serializable);
-        MOZ_ASSERT(!ir->GetSecurityInfo().IsEmpty());
-      } else {
-        NS_WARNING("A non-serializable object was obtained from nsIChannel::GetSecurityInfo()!");
-      }
-    }
+    ir->InitChannelInfo(channel);
 
     nsRefPtr<Response> response = new Response(mCacheCreator->Global(), ir);
 
     RequestOrUSVString request;
 
     MOZ_ASSERT(!loadInfo.mFullURL.IsEmpty());
     request.SetAsUSVString().Rebind(loadInfo.mFullURL.Data(),
                                     loadInfo.mFullURL.Length());
@@ -960,28 +949,19 @@ private:
     }
 
     // Update the principal of the worker and its base URI if we just loaded the
     // worker's primary script.
     if (IsMainWorkerScript()) {
       // Take care of the base URI first.
       mWorkerPrivate->SetBaseURI(finalURI);
 
-      // Store the security info if needed.
+      // Store the channel info if needed.
       if (mWorkerPrivate->IsServiceWorker()) {
-        nsCOMPtr<nsISupports> infoObj;
-        channel->GetSecurityInfo(getter_AddRefs(infoObj));
-        if (infoObj) {
-          nsCOMPtr<nsISerializable> serializable = do_QueryInterface(infoObj);
-          if (serializable) {
-            mWorkerPrivate->SetSecurityInfo(serializable);
-          } else {
-            NS_WARNING("A non-serializable object was obtained from nsIChannel::GetSecurityInfo()!");
-          }
-        }
+        mWorkerPrivate->InitChannelInfo(channel);
       }
 
       // Now to figure out which principal to give this worker.
       WorkerPrivate* parent = mWorkerPrivate->GetParent();
 
       NS_ASSERTION(mWorkerPrivate->GetPrincipal() || parent,
                    "Must have one of these!");
 
@@ -1042,17 +1022,18 @@ private:
     }
 
     DataReceived();
     return NS_OK;
   }
 
   void
   DataReceivedFromCache(uint32_t aIndex, const uint8_t* aString,
-                        uint32_t aStringLen, const nsCString& aSecurityInfo)
+                        uint32_t aStringLen,
+                        const ChannelInfo& aChannelInfo)
   {
     AssertIsOnMainThread();
     MOZ_ASSERT(aIndex < mLoadInfos.Length());
     ScriptLoadInfo& loadInfo = mLoadInfos[aIndex];
     MOZ_ASSERT(loadInfo.mCacheStatus == ScriptLoadInfo::Cached);
 
     // May be null.
     nsIDocument* parentDoc = mWorkerPrivate->GetDocument();
@@ -1070,17 +1051,17 @@ private:
       if (NS_SUCCEEDED(rv)) {
         mWorkerPrivate->SetBaseURI(finalURI);
       }
 
       nsIPrincipal* principal = mWorkerPrivate->GetPrincipal();
       MOZ_ASSERT(principal);
       nsILoadGroup* loadGroup = mWorkerPrivate->GetLoadGroup();
       MOZ_ASSERT(loadGroup);
-      mWorkerPrivate->SetSecurityInfo(aSecurityInfo);
+      mWorkerPrivate->InitChannelInfo(aChannelInfo);
       // Needed to initialize the principal info. This is fine because
       // the cache principal cannot change, unlike the channel principal.
       mWorkerPrivate->SetPrincipal(principal, loadGroup);
     }
 
     if (NS_SUCCEEDED(rv)) {
       DataReceived();
     }
@@ -1424,21 +1405,21 @@ CacheScriptLoader::ResolvedCallback(JSCo
   nsresult rv = UNWRAP_OBJECT(Response, obj, response);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     Fail(rv);
     return;
   }
 
   nsCOMPtr<nsIInputStream> inputStream;
   response->GetBody(getter_AddRefs(inputStream));
-  mSecurityInfo = response->GetSecurityInfo();
+  mChannelInfo = response->GetChannelInfo();
 
   if (!inputStream) {
     mLoadInfo.mCacheStatus = ScriptLoadInfo::Cached;
-    mRunnable->DataReceivedFromCache(mIndex, (uint8_t*)"", 0, mSecurityInfo);
+    mRunnable->DataReceivedFromCache(mIndex, (uint8_t*)"", 0, mChannelInfo);
     return;
   }
 
   MOZ_ASSERT(!mPump);
   rv = NS_NewInputStreamPump(getter_AddRefs(mPump), inputStream);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     Fail(rv);
     return;
@@ -1484,17 +1465,17 @@ CacheScriptLoader::OnStreamComplete(nsIS
 
   if (NS_FAILED(aStatus)) {
     Fail(aStatus);
     return NS_OK;
   }
 
   mLoadInfo.mCacheStatus = ScriptLoadInfo::Cached;
 
-  mRunnable->DataReceivedFromCache(mIndex, aString, aStringLen, mSecurityInfo);
+  mRunnable->DataReceivedFromCache(mIndex, aString, aStringLen, mChannelInfo);
   return NS_OK;
 }
 
  class ChannelGetterRunnable final : public nsRunnable
 {
   WorkerPrivate* mParentWorker;
   nsCOMPtr<nsIEventTarget> mSyncLoopTarget;
   const nsAString& mScriptURL;
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -93,45 +93,43 @@ public:
     return NS_OK;
   }
 };
 
 class FinishResponse final : public nsRunnable
 {
   nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel;
   nsRefPtr<InternalResponse> mInternalResponse;
-  nsCString mWorkerSecurityInfo;
+  ChannelInfo mWorkerChannelInfo;
 public:
   FinishResponse(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
                  InternalResponse* aInternalResponse,
-                 const nsCString& aWorkerSecurityInfo)
+                 const ChannelInfo& aWorkerChannelInfo)
     : mChannel(aChannel)
     , mInternalResponse(aInternalResponse)
-    , mWorkerSecurityInfo(aWorkerSecurityInfo)
+    , mWorkerChannelInfo(aWorkerChannelInfo)
   {
   }
 
   NS_IMETHOD
   Run()
   {
     AssertIsOnMainThread();
 
-    nsCOMPtr<nsISupports> infoObj;
-    nsAutoCString securityInfo(mInternalResponse->GetSecurityInfo());
-    if (securityInfo.IsEmpty()) {
+    ChannelInfo channelInfo;
+    if (mInternalResponse->GetChannelInfo().IsInitialized()) {
+      channelInfo = mInternalResponse->GetChannelInfo();
+    } else {
       // We are dealing with a synthesized response here, so fall back to the
-      // security info for the worker script.
-      securityInfo = mWorkerSecurityInfo;
+      // channel info for the worker script.
+      channelInfo = mWorkerChannelInfo;
     }
-    nsresult rv = NS_DeserializeObject(securityInfo, getter_AddRefs(infoObj));
-    if (NS_SUCCEEDED(rv)) {
-      rv = mChannel->SetSecurityInfo(infoObj);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
-      }
+    nsresult rv = mChannel->SetChannelInfo(&channelInfo);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
     }
 
     mChannel->SynthesizeStatus(mInternalResponse->GetStatus(), mInternalResponse->GetStatusText());
 
     nsAutoTArray<InternalHeaders::Entry, 5> entries;
     mInternalResponse->UnfilteredHeaders()->GetEntries(entries);
     for (uint32_t i = 0; i < entries.Length(); ++i) {
        mChannel->SynthesizeHeader(entries[i].mName, entries[i].mValue);
@@ -164,36 +162,36 @@ public:
 
   void CancelRequest();
 };
 
 struct RespondWithClosure
 {
   nsMainThreadPtrHandle<nsIInterceptedChannel> mInterceptedChannel;
   nsRefPtr<InternalResponse> mInternalResponse;
-  nsCString mWorkerSecurityInfo;
+  ChannelInfo mWorkerChannelInfo;
 
   RespondWithClosure(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
                      InternalResponse* aInternalResponse,
-                     const nsCString& aWorkerSecurityInfo)
+                     const ChannelInfo& aWorkerChannelInfo)
     : mInterceptedChannel(aChannel)
     , mInternalResponse(aInternalResponse)
-    , mWorkerSecurityInfo(aWorkerSecurityInfo)
+    , mWorkerChannelInfo(aWorkerChannelInfo)
   {
   }
 };
 
 void RespondWithCopyComplete(void* aClosure, nsresult aStatus)
 {
   nsAutoPtr<RespondWithClosure> data(static_cast<RespondWithClosure*>(aClosure));
   nsCOMPtr<nsIRunnable> event;
   if (NS_SUCCEEDED(aStatus)) {
     event = new FinishResponse(data->mInterceptedChannel,
                                data->mInternalResponse,
-                               data->mWorkerSecurityInfo);
+                               data->mWorkerChannelInfo);
   } else {
     event = new CancelChannelRunnable(data->mInterceptedChannel);
   }
   MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(event)));
 }
 
 class MOZ_STACK_CLASS AutoCancel
 {
@@ -250,17 +248,17 @@ RespondWithHandler::ResolvedCallback(JSC
     return;
   }
 
   WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
   MOZ_ASSERT(worker);
   worker->AssertIsOnWorkerThread();
 
   nsAutoPtr<RespondWithClosure> closure(
-      new RespondWithClosure(mInterceptedChannel, ir, worker->GetSecurityInfo()));
+      new RespondWithClosure(mInterceptedChannel, ir, worker->GetChannelInfo()));
   nsCOMPtr<nsIInputStream> body;
   response->GetBody(getter_AddRefs(body));
   // Errors and redirects may not have a body.
   if (body) {
     response->SetBodyUsed();
 
     nsCOMPtr<nsIOutputStream> responseBody;
     rv = mInterceptedChannel->GetResponseBody(getter_AddRefs(responseBody));
--- a/dom/workers/ServiceWorkerScriptCache.cpp
+++ b/dom/workers/ServiceWorkerScriptCache.cpp
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ServiceWorkerScriptCache.h"
 #include "mozilla/unused.h"
 #include "mozilla/dom/CacheBinding.h"
 #include "mozilla/dom/cache/CacheStorage.h"
 #include "mozilla/dom/cache/Cache.h"
 #include "nsIThreadRetargetableRequest.h"
-#include "nsSerializationHelper.h"
 
 #include "nsIPrincipal.h"
 #include "Workers.h"
 
 using mozilla::dom::cache::Cache;
 using mozilla::dom::cache::CacheStorage;
 
 BEGIN_WORKERS_NAMESPACE
@@ -441,19 +440,19 @@ public:
   CacheStorage_()
   {
     AssertIsOnMainThread();
     MOZ_ASSERT(mCacheStorage);
     return mCacheStorage;
   }
 
   void
-  SetSecurityInfo(nsISerializable* aSecurityInfo)
+  InitChannelInfo(nsIChannel* aChannel)
   {
-    NS_SerializeToString(aSecurityInfo, mSecurityInfo);
+    mChannelInfo.InitFromChannel(aChannel);
   }
 
 private:
   ~CompareManager()
   {
     AssertIsOnMainThread();
     MOZ_ASSERT(!mCC);
     MOZ_ASSERT(!mCN);
@@ -540,17 +539,17 @@ private:
       Fail(result.StealNSResult());
       return;
     }
 
     nsRefPtr<InternalResponse> ir =
       new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
     ir->SetBody(body);
 
-    ir->SetSecurityInfo(mSecurityInfo);
+    ir->InitChannelInfo(mChannelInfo);
 
     nsRefPtr<Response> response = new Response(aCache->GetGlobalObject(), ir);
 
     RequestOrUSVString request;
     request.SetAsUSVString().Rebind(URL().Data(), URL().Length());
 
     // For now we have to wait until the Put Promise is fulfilled before we can
     // continue since Cache does not yet support starting a read that is being
@@ -572,17 +571,17 @@ private:
 
   nsRefPtr<CompareNetwork> mCN;
   nsRefPtr<CompareCache> mCC;
 
   nsString mURL;
   // Only used if the network script has changed and needs to be cached.
   nsString mNewCacheName;
 
-  nsCString mSecurityInfo;
+  ChannelInfo mChannelInfo;
 
   nsCString mMaxScope;
 
   enum {
     WaitingForOpen,
     WaitingForPut
   } mState;
 
@@ -601,26 +600,17 @@ CompareNetwork::OnStartRequest(nsIReques
     return NS_OK;
   }
 
 #ifdef DEBUG
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
   MOZ_ASSERT(channel == mChannel);
 #endif
 
-  nsCOMPtr<nsISupports> infoObj;
-  mChannel->GetSecurityInfo(getter_AddRefs(infoObj));
-  if (infoObj) {
-    nsCOMPtr<nsISerializable> serializable = do_QueryInterface(infoObj);
-    if (serializable) {
-      mManager->SetSecurityInfo(serializable);
-    } else {
-      NS_WARNING("A non-serializable object was obtained from nsIChannel::GetSecurityInfo()!");
-    }
-  }
+  mManager->InitChannelInfo(mChannel);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 CompareNetwork::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
                               nsresult aStatusCode)
 {
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -27,17 +27,16 @@
 #include "nsITimer.h"
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsIWorkerDebugger.h"
 #include "nsIXPConnect.h"
 #include "nsPerformance.h"
 #include "nsPIDOMWindow.h"
-#include "nsSerializationHelper.h"
 
 #include <algorithm>
 #include "jsfriendapi.h"
 #include "js/MemoryMetrics.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/EventDispatcher.h"
@@ -4071,27 +4070,16 @@ WorkerPrivateParent<Derived>::SetPrincip
 
   mLoadInfo.mPrincipalInfo = new PrincipalInfo();
 
   MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
     PrincipalToPrincipalInfo(aPrincipal, mLoadInfo.mPrincipalInfo)));
 }
 
 template <class Derived>
-void
-WorkerPrivateParent<Derived>::SetSecurityInfo(nsISerializable* aSerializable)
-{
-  MOZ_ASSERT(IsServiceWorker());
-  AssertIsOnMainThread();
-  nsAutoCString securityInfo;
-  NS_SerializeToString(aSerializable, securityInfo);
-  SetSecurityInfo(securityInfo);
-}
-
-template <class Derived>
 JSContext*
 WorkerPrivateParent<Derived>::ParentJSContext() const
 {
   AssertIsOnParentThread();
 
   if (mParent) {
     return mParent->GetJSContext();
   }
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -493,34 +493,44 @@ public:
   const nsString&
   ServiceWorkerCacheName() const
   {
     MOZ_ASSERT(IsServiceWorker());
     AssertIsOnMainThread();
     return mLoadInfo.mServiceWorkerCacheName;
   }
 
-  const nsCString&
-  GetSecurityInfo() const
+  const ChannelInfo&
+  GetChannelInfo() const
   {
     MOZ_ASSERT(IsServiceWorker());
-    return mLoadInfo.mSecurityInfo;
+    return mLoadInfo.mChannelInfo;
   }
 
   void
-  SetSecurityInfo(const nsCString& aSecurityInfo)
+  SetChannelInfo(const ChannelInfo& aChannelInfo)
   {
     MOZ_ASSERT(IsServiceWorker());
     AssertIsOnMainThread();
-    MOZ_ASSERT(mLoadInfo.mSecurityInfo.IsEmpty());
-    mLoadInfo.mSecurityInfo = aSecurityInfo;
+    MOZ_ASSERT(!mLoadInfo.mChannelInfo.IsInitialized());
+    MOZ_ASSERT(aChannelInfo.IsInitialized());
+    mLoadInfo.mChannelInfo = aChannelInfo;
   }
 
   void
-  SetSecurityInfo(nsISerializable* aSerializable);
+  InitChannelInfo(nsIChannel* aChannel)
+  {
+    mLoadInfo.mChannelInfo.InitFromChannel(aChannel);
+  }
+
+  void
+  InitChannelInfo(const ChannelInfo& aChannelInfo)
+  {
+    mLoadInfo.mChannelInfo = aChannelInfo;
+  }
 
   // This is used to handle importScripts(). When the worker is first loaded
   // and executed, it happens in a sync loop. At this point it sets
   // mLoadingWorkerScript to true. importScripts() calls that occur during the
   // execution run in nested sync loops and so this continues to return true,
   // leading to these scripts being cached offline.
   // mLoadingWorkerScript is set to false when the top level loop ends.
   // importScripts() in function calls or event handlers are always fetched
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -15,16 +15,17 @@
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 #include "nsILoadContext.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsIInterfaceRequestor.h"
+#include "mozilla/dom/ChannelInfo.h"
 
 #define BEGIN_WORKERS_NAMESPACE \
   namespace mozilla { namespace dom { namespace workers {
 #define END_WORKERS_NAMESPACE \
   } /* namespace workers */ } /* namespace dom */ } /* namespace mozilla */
 #define USING_WORKERS_NAMESPACE \
   using namespace mozilla::dom::workers;
 
@@ -239,17 +240,17 @@ struct WorkerLoadInfo
   // Only set if we have a custom overriden load group
   nsRefPtr<InterfaceRequestor> mInterfaceRequestor;
 
   nsAutoPtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
   nsCString mDomain;
 
   nsString mServiceWorkerCacheName;
 
-  nsCString mSecurityInfo;
+  ChannelInfo mChannelInfo;
 
   uint64_t mWindowID;
   uint64_t mServiceWorkerID;
 
   bool mFromWindow;
   bool mEvalAllowed;
   bool mReportCSPViolations;
   bool mXHRParamsAllowed;
--- a/netwerk/base/nsINetworkInterceptController.idl
+++ b/netwerk/base/nsINetworkInterceptController.idl
@@ -4,24 +4,34 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIChannel;
 interface nsIOutputStream;
 interface nsIURI;
 
+%{C++
+namespace mozilla {
+namespace dom {
+class ChannelInfo;
+}
+}
+%}
+
+[ptr] native ChannelInfo(mozilla::dom::ChannelInfo);
+
 /**
  * Interface to allow implementors of nsINetworkInterceptController to control the behaviour
  * of intercepted channels without tying implementation details of the interception to
  * the actual channel. nsIInterceptedChannel is expected to be implemented by objects
  * which do not implement nsIChannel.
  */
 
-[scriptable, uuid(2fc1170c-4f9d-4c9e-8e5d-2d351dbe03f2)]
+[scriptable, uuid(f2c07a6b-366d-4ef4-85ab-a77f4bcb1646)]
 interface nsIInterceptedChannel : nsISupports
 {
     /**
      * Instruct a channel that has been intercepted to continue with the original
      * network request.
      */
     void resetInterception();
 
@@ -62,19 +72,20 @@ interface nsIInterceptedChannel : nsISup
     readonly attribute nsIChannel channel;
 
     /**
      * True if the underlying request was caused by a navigation attempt.
      */
     readonly attribute bool isNavigation;
 
     /**
-     * This method allows to override the security info for the channel.
+     * This method allows to override the channel info for the channel.
      */
-    void setSecurityInfo(in nsISupports securityInfo);
+    [noscript]
+    void setChannelInfo(in ChannelInfo channelInfo);
 };
 
 /**
  * Interface to allow consumers to attach themselves to a channel's
  * notification callbacks/loadgroup and determine if a given channel
  * request should be intercepted before any network request is initiated.
  */
 
--- a/netwerk/protocol/http/InterceptedChannel.cpp
+++ b/netwerk/protocol/http/InterceptedChannel.cpp
@@ -8,16 +8,17 @@
 
 #include "InterceptedChannel.h"
 #include "nsInputStreamPump.h"
 #include "nsIPipe.h"
 #include "nsIStreamListener.h"
 #include "nsHttpChannel.h"
 #include "HttpChannelChild.h"
 #include "nsHttpResponseHead.h"
+#include "mozilla/dom/ChannelInfo.h"
 
 namespace mozilla {
 namespace net {
 
 extern nsresult
 DoAddCacheEntryHeaders(nsHttpChannel *self,
                        nsICacheEntry *entry,
                        nsHttpRequestHead *requestHead,
@@ -228,23 +229,23 @@ InterceptedChannelChrome::Cancel()
   // we need to use AsyncAbort instead of Cancel since there's no active pump
   // to cancel which will provide OnStart/OnStopRequest to the channel.
   nsresult rv = mChannel->AsyncAbort(NS_BINDING_ABORTED);
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-InterceptedChannelChrome::SetSecurityInfo(nsISupports* aSecurityInfo)
+InterceptedChannelChrome::SetChannelInfo(dom::ChannelInfo* aChannelInfo)
 {
   if (!mChannel) {
     return NS_ERROR_FAILURE;
   }
 
-  return mChannel->OverrideSecurityInfo(aSecurityInfo);
+  return aChannelInfo->ResurrectInfoOnChannel(mChannel);
 }
 
 InterceptedChannelContent::InterceptedChannelContent(HttpChannelChild* aChannel,
                                                      nsINetworkInterceptController* aController,
                                                      nsIStreamListener* aListener)
 : InterceptedChannelBase(aController, aChannel->IsNavigation())
 , mChannel(aChannel)
 , mStreamListener(aListener)
@@ -335,19 +336,19 @@ InterceptedChannelContent::Cancel()
   nsresult rv = mChannel->AsyncAbort(NS_BINDING_ABORTED);
   NS_ENSURE_SUCCESS(rv, rv);
   mChannel = nullptr;
   mStreamListener = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-InterceptedChannelContent::SetSecurityInfo(nsISupports* aSecurityInfo)
+InterceptedChannelContent::SetChannelInfo(dom::ChannelInfo* aChannelInfo)
 {
   if (!mChannel) {
     return NS_ERROR_FAILURE;
   }
 
-  return mChannel->OverrideSecurityInfo(aSecurityInfo);
+  return aChannelInfo->ResurrectInfoOnChannel(mChannel);
 }
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/InterceptedChannel.h
+++ b/netwerk/protocol/http/InterceptedChannel.h
@@ -77,17 +77,17 @@ public:
                            nsICacheEntry* aEntry);
 
   NS_IMETHOD ResetInterception() override;
   NS_IMETHOD FinishSynthesizedResponse() override;
   NS_IMETHOD GetChannel(nsIChannel** aChannel) override;
   NS_IMETHOD SynthesizeStatus(uint16_t aStatus, const nsACString& aReason) override;
   NS_IMETHOD SynthesizeHeader(const nsACString& aName, const nsACString& aValue) override;
   NS_IMETHOD Cancel() override;
-  NS_IMETHOD SetSecurityInfo(nsISupports* aSecurityInfo) override;
+  NS_IMETHOD SetChannelInfo(mozilla::dom::ChannelInfo* aChannelInfo) override;
 
   virtual void NotifyController() override;
 };
 
 class InterceptedChannelContent : public InterceptedChannelBase
 {
   // The actual channel being intercepted.
   nsRefPtr<HttpChannelChild> mChannel;
@@ -104,17 +104,17 @@ public:
                             nsIStreamListener* aListener);
 
   NS_IMETHOD ResetInterception() override;
   NS_IMETHOD FinishSynthesizedResponse() override;
   NS_IMETHOD GetChannel(nsIChannel** aChannel) override;
   NS_IMETHOD SynthesizeStatus(uint16_t aStatus, const nsACString& aReason) override;
   NS_IMETHOD SynthesizeHeader(const nsACString& aName, const nsACString& aValue) override;
   NS_IMETHOD Cancel() override;
-  NS_IMETHOD SetSecurityInfo(nsISupports* aSecurityInfo) override;
+  NS_IMETHOD SetChannelInfo(mozilla::dom::ChannelInfo* aChannelInfo) override;
 
   virtual void NotifyController() override;
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // InterceptedChannel_h
--- a/netwerk/protocol/http/TunnelUtils.h
+++ b/netwerk/protocol/http/TunnelUtils.h
@@ -10,16 +10,17 @@
 #include "mozilla/Attributes.h"
 #include "nsAHttpTransaction.h"
 #include "nsIAsyncInputStream.h"
 #include "nsIAsyncOutputStream.h"
 #include "nsISocketTransport.h"
 #include "nsITimer.h"
 #include "NullHttpTransaction.h"
 #include "mozilla/TimeStamp.h"
+#include "prio.h"
 
 // a TLSFilterTransaction wraps another nsAHttpTransaction but
 // applies a encode/decode filter of TLS onto the ReadSegments
 // and WriteSegments data. It is not used for basic https://
 // but it is used for supplemental TLS tunnels - such as those
 // needed by CONNECT tunnels in HTTP/2 or even CONNECT tunnels when
 // the underlying proxy connection is already running TLS
 //
--- a/netwerk/protocol/http/nsHttpConnectionInfo.h
+++ b/netwerk/protocol/http/nsHttpConnectionInfo.h
@@ -6,16 +6,17 @@
 
 #ifndef nsHttpConnectionInfo_h__
 #define nsHttpConnectionInfo_h__
 
 #include "nsHttp.h"
 #include "nsProxyInfo.h"
 #include "nsCOMPtr.h"
 #include "nsStringFwd.h"
+#include "mozilla/Logging.h"
 
 extern PRLogModuleInfo *gHttpLog;
 
 //-----------------------------------------------------------------------------
 // nsHttpConnectionInfo - holds the properties of a connection
 //-----------------------------------------------------------------------------
 
 // http:// uris through a proxy will all share the same CI, because they can