Bug 1231213 - Implement IPCInternal{Request,Response}. r=asuth
authorPerry Jiang <perry@mozilla.com>
Thu, 15 Aug 2019 17:26:15 +0000
changeset 488298 1f77d3afe29010be484c2974ee040fd99d776d30
parent 488297 ea69dc3c1056093410ac387f4cdb126637cce953
child 488299 d9caf27cef95d38e96ccbb4b1930da6b084d7dcc
push id113906
push userncsoregi@mozilla.com
push dateFri, 16 Aug 2019 04:07:24 +0000
treeherdermozilla-inbound@d887276421d3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1231213
milestone70.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 1231213 - Implement IPCInternal{Request,Response}. r=asuth Differential Revision: https://phabricator.services.mozilla.com/D26163
dom/fetch/FetchTypes.ipdlh
dom/fetch/InternalRequest.cpp
dom/fetch/InternalRequest.h
dom/fetch/InternalResponse.cpp
dom/fetch/InternalResponse.h
--- a/dom/fetch/FetchTypes.ipdlh
+++ b/dom/fetch/FetchTypes.ipdlh
@@ -2,20 +2,62 @@
  * 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 IPCStream;
 include ChannelInfo;
 include PBackgroundSharedTypes;
 
 using HeadersGuardEnum from "mozilla/dom/FetchIPCTypes.h";
+using ReferrerPolicy from "mozilla/dom/FetchIPCTypes.h";
+using RequestCache from "mozilla/dom/FetchIPCTypes.h";
+using RequestCredentials from "mozilla/dom/FetchIPCTypes.h";
+using RequestMode from "mozilla/dom/FetchIPCTypes.h";
+using RequestRedirect from "mozilla/dom/FetchIPCTypes.h";
+using ResponseType from "mozilla/dom/FetchIPCTypes.h";
 
 namespace mozilla {
 namespace dom {
 
-struct HeadersEntry
-{
+struct HeadersEntry {
   nsCString name;
   nsCString value;
 };
 
+struct IPCInternalRequest {
+  nsCString method;
+  nsCString[] urlList;
+  HeadersGuardEnum headersGuard;
+  HeadersEntry[] headers;
+  IPCStream? body;
+  int64_t bodySize;
+  nsCString preferredAlternativeDataType;
+  uint32_t contentPolicyType;
+  nsString referrer;
+  ReferrerPolicy referrerPolicy;
+  RequestMode requestMode;
+  RequestCredentials requestCredentials;
+  RequestCache cacheMode;
+  RequestRedirect requestRedirect;
+  nsString integrity;
+  nsCString fragment;
+  bool createdByFetchEvent;
+  PrincipalInfo? principalInfo;
+};
+
+struct IPCInternalResponse {
+  ResponseType type;
+  nsCString[] urlList;
+  uint16_t status;
+  nsCString statusText;
+  HeadersGuardEnum headersGuard;
+  HeadersEntry[] headers;
+  IPCStream? body;
+  int64_t bodySize;
+  nsresult errorCode;
+  nsCString alternativeDataType;
+  IPCStream? alternativeBody;
+  IPCChannelInfo channelInfo;
+  PrincipalInfo? principalInfo;
+};
+
 } // namespace ipc
 } // namespace mozilla
--- a/dom/fetch/InternalRequest.cpp
+++ b/dom/fetch/InternalRequest.cpp
@@ -11,16 +11,18 @@
 #include "nsStreamUtils.h"
 
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/FetchTypes.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 #include "mozilla/dom/WorkerCommon.h"
 #include "mozilla/dom/WorkerPrivate.h"
+#include "mozilla/ipc/IPCStreamUtils.h"
+#include "mozilla/ipc/PBackgroundChild.h"
 
 namespace mozilla {
 namespace dom {
 // The global is used to extract the principal.
 already_AddRefed<InternalRequest> InternalRequest::GetRequestConstructorCopy(
     nsIGlobalObject* aGlobal, ErrorResult& aRv) const {
   MOZ_RELEASE_ASSERT(!mURLList.IsEmpty(),
                      "Internal Request's urlList should not be empty when "
@@ -166,18 +168,83 @@ InternalRequest::InternalRequest(const I
       mSynchronous(aOther.mSynchronous),
       mUnsafeRequest(aOther.mUnsafeRequest),
       mUseURLCredentials(aOther.mUseURLCredentials),
       mCreatedByFetchEvent(aOther.mCreatedByFetchEvent),
       mContentPolicyTypeOverridden(aOther.mContentPolicyTypeOverridden) {
   // NOTE: does not copy body stream... use the fallible Clone() for that
 }
 
+InternalRequest::InternalRequest(const IPCInternalRequest& aIPCRequest)
+    : mMethod(aIPCRequest.method()),
+      mURLList(aIPCRequest.urlList()),
+      mHeaders(new InternalHeaders(aIPCRequest.headers(),
+                                   aIPCRequest.headersGuard())),
+      mBodyStream(mozilla::ipc::DeserializeIPCStream(aIPCRequest.body())),
+      mBodyLength(aIPCRequest.bodySize()),
+      mPreferredAlternativeDataType(aIPCRequest.preferredAlternativeDataType()),
+      mContentPolicyType(
+          static_cast<nsContentPolicyType>(aIPCRequest.contentPolicyType())),
+      mReferrer(aIPCRequest.referrer()),
+      mReferrerPolicy(aIPCRequest.referrerPolicy()),
+      mMode(aIPCRequest.requestMode()),
+      mCredentialsMode(aIPCRequest.requestCredentials()),
+      mCacheMode(aIPCRequest.cacheMode()),
+      mRedirectMode(aIPCRequest.requestRedirect()),
+      mIntegrity(aIPCRequest.integrity()),
+      mFragment(aIPCRequest.fragment()),
+      mCreatedByFetchEvent(aIPCRequest.createdByFetchEvent()) {
+  if (aIPCRequest.principalInfo()) {
+    mPrincipalInfo = MakeUnique<mozilla::ipc::PrincipalInfo>(
+        aIPCRequest.principalInfo().ref());
+  }
+}
+
 InternalRequest::~InternalRequest() {}
 
+template void InternalRequest::ToIPC<mozilla::ipc::PBackgroundChild>(
+    IPCInternalRequest* aIPCRequest, mozilla::ipc::PBackgroundChild* aManager,
+    UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
+
+template <typename M>
+void InternalRequest::ToIPC(
+    IPCInternalRequest* aIPCRequest, M* aManager,
+    UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream) {
+  MOZ_ASSERT(aIPCRequest);
+  MOZ_ASSERT(aManager);
+  MOZ_ASSERT(!mURLList.IsEmpty());
+
+  aIPCRequest->method() = mMethod;
+  aIPCRequest->urlList() = mURLList;
+  mHeaders->ToIPC(aIPCRequest->headers(), aIPCRequest->headersGuard());
+
+  if (mBodyStream) {
+    aAutoStream.reset(new mozilla::ipc::AutoIPCStream(aIPCRequest->body()));
+    DebugOnly<bool> ok = aAutoStream->Serialize(mBodyStream, aManager);
+    MOZ_ASSERT(ok);
+  }
+
+  aIPCRequest->bodySize() = mBodyLength;
+  aIPCRequest->preferredAlternativeDataType() = mPreferredAlternativeDataType;
+  aIPCRequest->contentPolicyType() = static_cast<uint32_t>(mContentPolicyType);
+  aIPCRequest->referrer() = mReferrer;
+  aIPCRequest->referrerPolicy() = mReferrerPolicy;
+  aIPCRequest->requestMode() = mMode;
+  aIPCRequest->requestCredentials() = mCredentialsMode;
+  aIPCRequest->cacheMode() = mCacheMode;
+  aIPCRequest->requestRedirect() = mRedirectMode;
+  aIPCRequest->integrity() = mIntegrity;
+  aIPCRequest->fragment() = mFragment;
+  aIPCRequest->createdByFetchEvent() = mCreatedByFetchEvent;
+
+  if (mPrincipalInfo) {
+    aIPCRequest->principalInfo().emplace(*mPrincipalInfo);
+  }
+}
+
 void InternalRequest::SetContentPolicyType(
     nsContentPolicyType aContentPolicyType) {
   mContentPolicyType = aContentPolicyType;
 }
 
 void InternalRequest::OverrideContentPolicyType(
     nsContentPolicyType aContentPolicyType) {
   SetContentPolicyType(aContentPolicyType);
--- a/dom/fetch/InternalRequest.h
+++ b/dom/fetch/InternalRequest.h
@@ -7,30 +7,32 @@
 #ifndef mozilla_dom_InternalRequest_h
 #define mozilla_dom_InternalRequest_h
 
 #include "mozilla/dom/HeadersBinding.h"
 #include "mozilla/dom/InternalHeaders.h"
 #include "mozilla/dom/RequestBinding.h"
 #include "mozilla/LoadTainting.h"
 #include "mozilla/net/ReferrerPolicy.h"
+#include "mozilla/UniquePtr.h"
 
 #include "nsIContentPolicy.h"
 #include "nsIInputStream.h"
 #include "nsISupportsImpl.h"
 #ifdef DEBUG
 #  include "nsIURLParser.h"
 #  include "nsNetCID.h"
 #  include "nsServiceManagerUtils.h"
 #endif
 
 namespace mozilla {
 
 namespace ipc {
 class PrincipalInfo;
+class AutoIPCStream;
 }  // namespace ipc
 
 namespace dom {
 
 /*
  * The mapping of RequestDestination and nsContentPolicyType is currently as the
  * following.  Note that this mapping is not perfect yet (see the TODO comments
  * below for examples).
@@ -63,16 +65,17 @@ namespace dom {
  * track             | TYPE_INTERNAL_TRACK
  * video             | TYPE_INTERNAL_VIDEO
  * worker            | TYPE_INTERNAL_WORKER
  * xslt              | TYPE_XSLT
  * _empty            | Default for everything else.
  *
  */
 
+class IPCInternalRequest;
 class Request;
 
 #define kFETCH_CLIENT_REFERRER_STR "about:client"
 class InternalRequest final {
   friend class Request;
 
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalRequest)
@@ -82,16 +85,22 @@ class InternalRequest final {
                   already_AddRefed<InternalHeaders> aHeaders,
                   RequestCache aCacheMode, RequestMode aMode,
                   RequestRedirect aRequestRedirect,
                   RequestCredentials aRequestCredentials,
                   const nsAString& aReferrer, ReferrerPolicy aReferrerPolicy,
                   nsContentPolicyType aContentPolicyType,
                   const nsAString& aIntegrity);
 
+  explicit InternalRequest(const IPCInternalRequest& aIPCRequest);
+
+  template <typename M>
+  void ToIPC(IPCInternalRequest* aIPCRequest, M* aManager,
+             UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoStream);
+
   already_AddRefed<InternalRequest> Clone();
 
   void GetMethod(nsCString& aMethod) const { aMethod.Assign(mMethod); }
 
   void SetMethod(const nsACString& aMethod) { mMethod.Assign(aMethod); }
 
   bool HasSimpleMethod() const {
     return mMethod.LowerCaseEqualsASCII("get") ||
--- a/dom/fetch/InternalResponse.cpp
+++ b/dom/fetch/InternalResponse.cpp
@@ -2,16 +2,18 @@
 /* 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/Assertions.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/dom/FetchTypes.h"
 #include "mozilla/dom/InternalHeaders.h"
 #include "mozilla/dom/cache/CacheTypes.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "mozilla/ipc/IPCStreamUtils.h"
 #include "mozilla/RandomNum.h"
 #include "nsIRandomGenerator.h"
 #include "nsIURI.h"
 #include "nsStreamUtils.h"
@@ -34,18 +36,122 @@ InternalResponse::InternalResponse(uint1
       mStatus(aStatus),
       mStatusText(aStatusText),
       mHeaders(new InternalHeaders(HeadersGuardEnum::Response)),
       mBodySize(UNKNOWN_BODY_SIZE),
       mPaddingSize(UNKNOWN_PADDING_SIZE),
       mErrorCode(NS_OK),
       mCredentialsMode(aCredentialsMode) {}
 
+/* static */ RefPtr<InternalResponse> InternalResponse::FromIPC(
+    const IPCInternalResponse& aIPCResponse) {
+  if (aIPCResponse.type() == ResponseType::Error) {
+    return InternalResponse::NetworkError(aIPCResponse.errorCode());
+  }
+
+  RefPtr<InternalResponse> response =
+      new InternalResponse(aIPCResponse.status(), aIPCResponse.statusText());
+
+  response->SetURLList(aIPCResponse.urlList());
+  response->mHeaders =
+      new InternalHeaders(aIPCResponse.headers(), aIPCResponse.headersGuard());
+
+  nsCOMPtr<nsIInputStream> body =
+      mozilla::ipc::DeserializeIPCStream(aIPCResponse.body());
+  response->SetBody(body, aIPCResponse.bodySize());
+
+  response->SetAlternativeDataType(aIPCResponse.alternativeDataType());
+
+  nsCOMPtr<nsIInputStream> alternativeBody =
+      mozilla::ipc::DeserializeIPCStream(aIPCResponse.alternativeBody());
+  response->SetAlternativeBody(alternativeBody);
+
+  response->InitChannelInfo(aIPCResponse.channelInfo());
+
+  if (aIPCResponse.principalInfo()) {
+    response->SetPrincipalInfo(MakeUnique<mozilla::ipc::PrincipalInfo>(
+        aIPCResponse.principalInfo().ref()));
+  }
+
+  switch (aIPCResponse.type()) {
+    case ResponseType::Basic:
+      response = response->BasicResponse();
+      break;
+    case ResponseType::Cors:
+      response = response->CORSResponse();
+      break;
+    case ResponseType::Default:
+      break;
+    case ResponseType::Opaque:
+      response = response->OpaqueResponse();
+      break;
+    case ResponseType::Opaqueredirect:
+      response = response->OpaqueRedirectResponse();
+      break;
+    default:
+      MOZ_CRASH("Unexpected ResponseType!");
+  }
+
+  MOZ_ASSERT(response);
+
+  return response;
+}
+
 InternalResponse::~InternalResponse() {}
 
+template void InternalResponse::ToIPC<mozilla::ipc::PBackgroundChild>(
+    IPCInternalResponse* aIPCResponse, mozilla::ipc::PBackgroundChild* aManager,
+    UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoBodyStream,
+    UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoAlternativeBodyStream);
+
+template <typename M>
+void InternalResponse::ToIPC(
+    IPCInternalResponse* aIPCResponse, M* aManager,
+    UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoBodyStream,
+    UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoAlternativeBodyStream) {
+  MOZ_ASSERT(aIPCResponse);
+
+  aIPCResponse->type() = mType;
+  GetUnfilteredURLList(aIPCResponse->urlList());
+  aIPCResponse->status() = GetUnfilteredStatus();
+  aIPCResponse->statusText() = GetUnfilteredStatusText();
+  UnfilteredHeaders()->ToIPC(aIPCResponse->headers(),
+                             aIPCResponse->headersGuard());
+
+  nsCOMPtr<nsIInputStream> body;
+  int64_t bodySize;
+  GetUnfilteredBody(getter_AddRefs(body), &bodySize);
+
+  if (body) {
+    aAutoBodyStream.reset(
+        new mozilla::ipc::AutoIPCStream(aIPCResponse->body()));
+    DebugOnly<bool> ok = aAutoBodyStream->Serialize(body, aManager);
+    MOZ_ASSERT(ok);
+  }
+
+  aIPCResponse->bodySize() = bodySize;
+  aIPCResponse->errorCode() = mErrorCode;
+  aIPCResponse->alternativeDataType() = GetAlternativeDataType();
+
+  nsCOMPtr<nsIInputStream> alternativeBody = TakeAlternativeBody();
+  if (alternativeBody) {
+    aAutoAlternativeBodyStream.reset(
+        new mozilla::ipc::AutoIPCStream(aIPCResponse->alternativeBody()));
+    DebugOnly<bool> ok =
+        aAutoAlternativeBodyStream->Serialize(alternativeBody, aManager);
+    MOZ_ASSERT(ok);
+  }
+
+  aIPCResponse->channelInfo() = mChannelInfo.AsIPCChannelInfo();
+
+  if (mPrincipalInfo) {
+    aIPCResponse->principalInfo().emplace(*mPrincipalInfo);
+  }
+}
+
 already_AddRefed<InternalResponse> InternalResponse::Clone(
     CloneType aCloneType) {
   RefPtr<InternalResponse> clone = CreateIncompleteCopy();
 
   clone->mHeaders = new InternalHeaders(*mHeaders);
 
   // Make sure the clone response will have the same padding size.
   clone->mPaddingInfo = mPaddingInfo;
--- a/dom/fetch/InternalResponse.h
+++ b/dom/fetch/InternalResponse.h
@@ -21,28 +21,38 @@
 namespace mozilla {
 namespace ipc {
 class PrincipalInfo;
 class AutoIPCStream;
 }  // namespace ipc
 
 namespace dom {
 
+class IPCInternalResponse;
 class InternalHeaders;
 
 class InternalResponse final {
   friend class FetchDriver;
 
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalResponse)
 
   InternalResponse(
       uint16_t aStatus, const nsACString& aStatusText,
       RequestCredentials aCredentialsMode = RequestCredentials::Omit);
 
+  static RefPtr<InternalResponse> FromIPC(
+      const IPCInternalResponse& aIPCResponse);
+
+  template <typename M>
+  void ToIPC(
+      IPCInternalResponse* aIPCResponse, M* aManager,
+      UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoBodyStream,
+      UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoAlternativeBodyStream);
+
   enum CloneType {
     eCloneInputStream,
     eDontCloneInputStream,
   };
 
   already_AddRefed<InternalResponse> Clone(CloneType eCloneType);
 
   static already_AddRefed<InternalResponse> NetworkError(nsresult aRv) {
@@ -206,16 +216,34 @@ class InternalResponse final {
   uint32_t GetPaddingInfo();
 
   nsresult GeneratePaddingInfo();
 
   int64_t GetPaddingSize();
 
   void SetPaddingSize(int64_t aPaddingSize);
 
+  void SetAlternativeDataType(const nsACString& aAltDataType) {
+    if (mWrappedResponse) {
+      return mWrappedResponse->SetAlternativeDataType(aAltDataType);
+    }
+
+    MOZ_DIAGNOSTIC_ASSERT(mAlternativeDataType.IsEmpty());
+
+    mAlternativeDataType.Assign(aAltDataType);
+  }
+
+  const nsCString& GetAlternativeDataType() {
+    if (mWrappedResponse) {
+      return mWrappedResponse->GetAlternativeDataType();
+    }
+
+    return mAlternativeDataType;
+  }
+
   void SetAlternativeBody(nsIInputStream* aAlternativeBody) {
     if (mWrappedResponse) {
       return mWrappedResponse->SetAlternativeBody(aAlternativeBody);
     }
     // A request's body may not be reset once set.
     MOZ_DIAGNOSTIC_ASSERT(!mAlternativeBody);
 
     mAlternativeBody = aAlternativeBody;
@@ -318,16 +346,17 @@ class InternalResponse final {
   // It's used to passed to the CacheResponse to generate padding size. Once, we
   // generate the padding size for resposne, we don't need it anymore.
   Maybe<uint32_t> mPaddingInfo;
   int64_t mPaddingSize;
   nsresult mErrorCode;
   RequestCredentials mCredentialsMode;
 
   // For alternative data such as JS Bytecode cached in the HTTP cache.
+  nsCString mAlternativeDataType;
   nsCOMPtr<nsIInputStream> mAlternativeBody;
   nsMainThreadPtrHandle<nsICacheInfoChannel> mCacheInfoChannel;
 
  public:
   static const int64_t UNKNOWN_BODY_SIZE = -1;
   static const int64_t UNKNOWN_PADDING_SIZE = -1;
 
  private: