Bug 1263991 part 3: Support incoming and outgoing requests/responses. r=baku f=bkelly, a=lizzard
authorJonas Sicking <jonas@sicking.cc>
Tue, 07 Jun 2016 02:46:03 -0700
changeset 339623 b408dc5c1ab86fa13c9a0880a92e3d808b19d000
parent 339622 147ddb5ce6f068f307f34f7d0004e06f18aaa0f4
child 339624 e9f5c7eb1b284786c66c674b9af7fbbf5b570f51
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)
reviewersbaku, lizzard
bugs1263991
milestone49.0a2
Bug 1263991 part 3: Support incoming and outgoing requests/responses. r=baku f=bkelly, a=lizzard
dom/cache/CacheTypes.ipdlh
dom/cache/IPCUtils.h
dom/fetch/FetchIPCTypes.h
dom/fetch/FetchTypes.ipdlh
dom/fetch/InternalHeaders.cpp
dom/fetch/InternalHeaders.h
dom/fetch/InternalRequest.cpp
dom/fetch/InternalRequest.h
dom/fetch/InternalResponse.cpp
dom/fetch/InternalResponse.h
dom/fetch/moz.build
dom/flyweb/FlyWebPublishedServer.cpp
dom/flyweb/FlyWebPublishedServerIPC.h
dom/flyweb/HttpServer.cpp
dom/flyweb/PFlyWebPublishedServer.ipdl
--- a/dom/cache/CacheTypes.ipdlh
+++ b/dom/cache/CacheTypes.ipdlh
@@ -4,23 +4,23 @@
 
 include protocol PCache;
 include protocol PCacheStreamControl;
 include protocol PSendStream;
 include IPCStream;
 include ChannelInfo;
 include PBackgroundSharedTypes;
 
-using HeadersGuardEnum from "mozilla/dom/cache/IPCUtils.h";
-using ReferrerPolicy 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 RequestRedirect from "mozilla/dom/cache/IPCUtils.h";
-using ResponseType from "mozilla/dom/cache/IPCUtils.h";
+using HeadersGuardEnum from "mozilla/dom/FetchIPCTypes.h";
+using ReferrerPolicy from "mozilla/dom/FetchIPCTypes.h";
+using RequestCredentials from "mozilla/dom/FetchIPCTypes.h";
+using RequestMode from "mozilla/dom/FetchIPCTypes.h";
+using RequestCache from "mozilla/dom/FetchIPCTypes.h";
+using RequestRedirect from "mozilla/dom/FetchIPCTypes.h";
+using ResponseType from "mozilla/dom/FetchIPCTypes.h";
 using mozilla::void_t from "ipc/IPCMessageUtils.h";
 using struct nsID from "nsID.h";
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 struct CacheQueryParams
--- a/dom/cache/IPCUtils.h
+++ b/dom/cache/IPCUtils.h
@@ -4,61 +4,20 @@
  * 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_cache_IPCUtils_h
 #define mozilla_dom_cache_IPCUtils_h
 
 #include "ipc/IPCMessageUtils.h"
 
-// Fix X11 header brain damage that conflicts with HeadersGuardEnum::None
-#undef None
-
-#include "mozilla/dom/HeadersBinding.h"
-#include "mozilla/dom/RequestBinding.h"
-#include "mozilla/dom/ResponseBinding.h"
 #include "mozilla/dom/cache/Types.h"
 
 namespace IPC {
   template<>
-  struct ParamTraits<mozilla::dom::HeadersGuardEnum> :
-    public ContiguousEnumSerializer<mozilla::dom::HeadersGuardEnum,
-                                    mozilla::dom::HeadersGuardEnum::None,
-                                    mozilla::dom::HeadersGuardEnum::EndGuard_> {};
-  template<>
-  struct ParamTraits<mozilla::dom::ReferrerPolicy> :
-    public ContiguousEnumSerializer<mozilla::dom::ReferrerPolicy,
-                                    mozilla::dom::ReferrerPolicy::_empty,
-                                    mozilla::dom::ReferrerPolicy::EndGuard_> {};
-  template<>
-  struct ParamTraits<mozilla::dom::RequestMode> :
-    public ContiguousEnumSerializer<mozilla::dom::RequestMode,
-                                    mozilla::dom::RequestMode::Same_origin,
-                                    mozilla::dom::RequestMode::EndGuard_> {};
-  template<>
-  struct ParamTraits<mozilla::dom::RequestCredentials> :
-    public ContiguousEnumSerializer<mozilla::dom::RequestCredentials,
-                                    mozilla::dom::RequestCredentials::Omit,
-                                    mozilla::dom::RequestCredentials::EndGuard_> {};
-  template<>
-  struct ParamTraits<mozilla::dom::RequestCache> :
-    public ContiguousEnumSerializer<mozilla::dom::RequestCache,
-                                    mozilla::dom::RequestCache::Default,
-                                    mozilla::dom::RequestCache::EndGuard_> {};
-  template<>
-  struct ParamTraits<mozilla::dom::RequestRedirect> :
-    public ContiguousEnumSerializer<mozilla::dom::RequestRedirect,
-                                    mozilla::dom::RequestRedirect::Follow,
-                                    mozilla::dom::RequestRedirect::EndGuard_> {};
-  template<>
-  struct ParamTraits<mozilla::dom::ResponseType> :
-    public ContiguousEnumSerializer<mozilla::dom::ResponseType,
-                                    mozilla::dom::ResponseType::Basic,
-                                    mozilla::dom::ResponseType::EndGuard_> {};
-  template<>
   struct ParamTraits<mozilla::dom::cache::Namespace> :
     public ContiguousEnumSerializer<mozilla::dom::cache::Namespace,
                                     mozilla::dom::cache::DEFAULT_NAMESPACE,
                                     mozilla::dom::cache::NUMBER_OF_NAMESPACES>
   {};
 } // namespace IPC
 
 #endif // mozilla_dom_cache_IPCUtils_h
new file mode 100644
--- /dev/null
+++ b/dom/fetch/FetchIPCTypes.h
@@ -0,0 +1,57 @@
+/* -*- 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_fetch_IPCUtils_h
+#define mozilla_dom_fetch_IPCUtils_h
+
+#include "ipc/IPCMessageUtils.h"
+
+// Fix X11 header brain damage that conflicts with HeadersGuardEnum::None
+#undef None
+
+#include "mozilla/dom/HeadersBinding.h"
+#include "mozilla/dom/RequestBinding.h"
+#include "mozilla/dom/ResponseBinding.h"
+
+namespace IPC {
+  template<>
+  struct ParamTraits<mozilla::dom::HeadersGuardEnum> :
+    public ContiguousEnumSerializer<mozilla::dom::HeadersGuardEnum,
+                                    mozilla::dom::HeadersGuardEnum::None,
+                                    mozilla::dom::HeadersGuardEnum::EndGuard_> {};
+  template<>
+  struct ParamTraits<mozilla::dom::ReferrerPolicy> :
+    public ContiguousEnumSerializer<mozilla::dom::ReferrerPolicy,
+                                    mozilla::dom::ReferrerPolicy::_empty,
+                                    mozilla::dom::ReferrerPolicy::EndGuard_> {};
+  template<>
+  struct ParamTraits<mozilla::dom::RequestMode> :
+    public ContiguousEnumSerializer<mozilla::dom::RequestMode,
+                                    mozilla::dom::RequestMode::Same_origin,
+                                    mozilla::dom::RequestMode::EndGuard_> {};
+  template<>
+  struct ParamTraits<mozilla::dom::RequestCredentials> :
+    public ContiguousEnumSerializer<mozilla::dom::RequestCredentials,
+                                    mozilla::dom::RequestCredentials::Omit,
+                                    mozilla::dom::RequestCredentials::EndGuard_> {};
+  template<>
+  struct ParamTraits<mozilla::dom::RequestCache> :
+    public ContiguousEnumSerializer<mozilla::dom::RequestCache,
+                                    mozilla::dom::RequestCache::Default,
+                                    mozilla::dom::RequestCache::EndGuard_> {};
+  template<>
+  struct ParamTraits<mozilla::dom::RequestRedirect> :
+    public ContiguousEnumSerializer<mozilla::dom::RequestRedirect,
+                                    mozilla::dom::RequestRedirect::Follow,
+                                    mozilla::dom::RequestRedirect::EndGuard_> {};
+  template<>
+  struct ParamTraits<mozilla::dom::ResponseType> :
+    public ContiguousEnumSerializer<mozilla::dom::ResponseType,
+                                    mozilla::dom::ResponseType::Basic,
+                                    mozilla::dom::ResponseType::EndGuard_> {};
+} // namespace IPC
+
+#endif // mozilla_dom_fetch_IPCUtils_h
new file mode 100644
--- /dev/null
+++ b/dom/fetch/FetchTypes.ipdlh
@@ -0,0 +1,59 @@
+/* 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 IPCStream;
+include ChannelInfo;
+include PBackgroundSharedTypes;
+
+using HeadersGuardEnum from "mozilla/dom/FetchIPCTypes.h";
+using ReferrerPolicy from "mozilla/dom/FetchIPCTypes.h";
+using RequestCredentials from "mozilla/dom/FetchIPCTypes.h";
+using RequestMode from "mozilla/dom/FetchIPCTypes.h";
+using ResponseType from "mozilla/dom/FetchIPCTypes.h";
+using RequestRedirect from "mozilla/dom/FetchIPCTypes.h";
+using RequestCache from "mozilla/dom/FetchIPCTypes.h";
+
+namespace mozilla {
+namespace dom {
+
+struct HeadersEntry
+{
+  nsCString name;
+  nsCString value;
+};
+
+// Note, this does not yet serialize *all* of InternalRequest
+// Make sure that it contains the fields that you care about
+struct IPCInternalRequest
+{
+  nsCString[] urls;
+  nsCString method;
+  HeadersEntry[] headers;
+  HeadersGuardEnum headersGuard;
+  nsString referrer;
+  ReferrerPolicy referrerPolicy;
+  RequestMode mode;
+  RequestCredentials credentials;
+  uint32_t contentPolicyType;
+  RequestCache requestCache;
+  RequestRedirect requestRedirect;
+};
+
+// Note, this does not yet serialize *all* of InternalResponse
+// Make sure that it contains the fields that you care about
+struct IPCInternalResponse
+{
+  ResponseType type;
+  nsCString[] urlList;
+  uint32_t status;
+  nsCString statusText;
+  HeadersEntry[] headers;
+  HeadersGuardEnum headersGuard;
+  IPCChannelInfo channelInfo;
+  OptionalPrincipalInfo principalInfo;
+};
+
+
+} // namespace ipc
+} // namespace mozilla
--- a/dom/fetch/InternalHeaders.cpp
+++ b/dom/fetch/InternalHeaders.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "mozilla/dom/InternalHeaders.h"
 
+#include "mozilla/dom/FetchTypes.h"
 #include "mozilla/ErrorResult.h"
 
 #include "nsCharSeparatedTokenizer.h"
 #include "nsContentUtils.h"
 #include "nsNetUtil.h"
 #include "nsReadableUtils.h"
 
 namespace mozilla {
@@ -18,16 +19,37 @@ namespace dom {
 
 InternalHeaders::InternalHeaders(const nsTArray<Entry>&& aHeaders,
                                  HeadersGuardEnum aGuard)
   : mGuard(aGuard)
   , mList(aHeaders)
 {
 }
 
+InternalHeaders::InternalHeaders(const nsTArray<HeadersEntry>& aHeadersEntryList,
+                                 HeadersGuardEnum aGuard)
+  : mGuard(aGuard)
+{
+  for (const HeadersEntry& headersEntry : aHeadersEntryList) {
+    mList.AppendElement(Entry(headersEntry.name(), headersEntry.value()));
+  }
+}
+
+void
+InternalHeaders::ToIPC(nsTArray<HeadersEntry>& aIPCHeaders,
+                       HeadersGuardEnum& aGuard)
+{
+  aGuard = mGuard;
+
+  aIPCHeaders.Clear();
+  for (Entry& entry : mList) {
+    aIPCHeaders.AppendElement(HeadersEntry(entry.mName, entry.mValue));
+  }
+}
+
 void
 InternalHeaders::Append(const nsACString& aName, const nsACString& aValue,
                         ErrorResult& aRv)
 {
   nsAutoCString lowerName;
   ToLowerCase(aName, lowerName);
 
   if (IsInvalidMutableHeader(lowerName, aValue, aRv)) {
--- a/dom/fetch/InternalHeaders.h
+++ b/dom/fetch/InternalHeaders.h
@@ -16,16 +16,17 @@
 
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 
 template<typename T> class MozMap;
+class HeadersEntry;
 
 class InternalHeaders final
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalHeaders)
 
 public:
   struct Entry
   {
@@ -59,16 +60,22 @@ public:
     // Note that it's important to set the guard after Fill(), to make sure
     // that Fill() doesn't fail if aOther is immutable.
     mGuard = aOther.mGuard;
   }
 
   explicit InternalHeaders(const nsTArray<Entry>&& aHeaders,
                            HeadersGuardEnum aGuard = HeadersGuardEnum::None);
 
+  InternalHeaders(const nsTArray<HeadersEntry>& aHeadersEntryList,
+                  HeadersGuardEnum aGuard);
+
+  void ToIPC(nsTArray<HeadersEntry>& aIPCHeaders,
+             HeadersGuardEnum& aGuard);
+
   void Append(const nsACString& aName, const nsACString& aValue,
               ErrorResult& aRv);
   void Delete(const nsACString& aName, ErrorResult& aRv);
   void Get(const nsACString& aName, nsCString& aValue, ErrorResult& aRv) const;
   void GetAll(const nsACString& aName, nsTArray<nsCString>& aResults,
               ErrorResult& aRv) const;
   bool Has(const nsACString& aName, ErrorResult& aRv) const;
   void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv);
--- a/dom/fetch/InternalRequest.cpp
+++ b/dom/fetch/InternalRequest.cpp
@@ -6,16 +6,17 @@
 
 #include "InternalRequest.h"
 
 #include "nsIContentPolicy.h"
 #include "nsIDocument.h"
 #include "nsStreamUtils.h"
 
 #include "mozilla/ErrorResult.h"
+#include "mozilla/dom/FetchTypes.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/workers/Workers.h"
 
 #include "WorkerPrivate.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -97,21 +98,56 @@ InternalRequest::InternalRequest(const I
   , 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.urls())
+  , mHeaders(new InternalHeaders(aIPCRequest.headers(),
+                                 aIPCRequest.headersGuard()))
+  , mContentPolicyType(aIPCRequest.contentPolicyType())
+  , mReferrer(aIPCRequest.referrer())
+  , mReferrerPolicy(aIPCRequest.referrerPolicy())
+  , mMode(aIPCRequest.mode())
+  , mCredentialsMode(aIPCRequest.credentials())
+  , mCacheMode(aIPCRequest.requestCache())
+  , mRedirectMode(aIPCRequest.requestRedirect())
+{
+  MOZ_ASSERT(!mURLList.IsEmpty());
+}
+
 InternalRequest::~InternalRequest()
 {
 }
 
 void
+InternalRequest::ToIPC(IPCInternalRequest* aIPCRequest)
+{
+  MOZ_ASSERT(aIPCRequest);
+  MOZ_ASSERT(!mURLList.IsEmpty());
+  aIPCRequest->urls() = mURLList;
+  aIPCRequest->method() = mMethod;
+
+  mHeaders->ToIPC(aIPCRequest->headers(), aIPCRequest->headersGuard());
+
+  aIPCRequest->referrer() = mReferrer;
+  aIPCRequest->referrerPolicy() = mReferrerPolicy;
+  aIPCRequest->mode() = mMode;
+  aIPCRequest->credentials() = mCredentialsMode;
+  aIPCRequest->contentPolicyType() = mContentPolicyType;
+  aIPCRequest->requestCache() = mCacheMode;
+  aIPCRequest->requestRedirect() = mRedirectMode;
+}
+
+void
 InternalRequest::SetContentPolicyType(nsContentPolicyType aContentPolicyType)
 {
   mContentPolicyType = aContentPolicyType;
 }
 
 void
 InternalRequest::OverrideContentPolicyType(nsContentPolicyType aContentPolicyType)
 {
--- a/dom/fetch/InternalRequest.h
+++ b/dom/fetch/InternalRequest.h
@@ -73,16 +73,17 @@ namespace dom {
  * TODO: Add a content type for location
  * TODO: Add a content type for hyperlink
  * TODO: Add a content type for form
  * TODO: Add a content type for favicon
  * TODO: Add a content type for download
  */
 
 class Request;
+class IPCInternalRequest;
 
 #define kFETCH_CLIENT_REFERRER_STR "about:client"
 
 class InternalRequest final
 {
   friend class Request;
 
 public:
@@ -145,16 +146,20 @@ public:
     , mSynchronous(false)
     , mUnsafeRequest(false)
     , mUseURLCredentials(false)
   {
     MOZ_ASSERT(!aURL.IsEmpty());
     AddURL(aURL);
   }
 
+  explicit InternalRequest(const IPCInternalRequest& aIPCRequest);
+
+  void ToIPC(IPCInternalRequest* aIPCRequest);
+
   already_AddRefed<InternalRequest> Clone();
 
   void
   GetMethod(nsCString& aMethod) const
   {
     aMethod.Assign(mMethod);
   }
 
--- a/dom/fetch/InternalResponse.cpp
+++ b/dom/fetch/InternalResponse.cpp
@@ -7,33 +7,102 @@
 #include "InternalResponse.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/InternalHeaders.h"
 #include "mozilla/dom/cache/CacheTypes.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "nsIURI.h"
 #include "nsStreamUtils.h"
+#include "mozilla/dom/FetchTypes.h"
 
 namespace mozilla {
 namespace dom {
 
 InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText)
   : mType(ResponseType::Default)
   , mStatus(aStatus)
   , mStatusText(aStatusText)
   , mHeaders(new InternalHeaders(HeadersGuardEnum::Response))
   , mBodySize(UNKNOWN_BODY_SIZE)
 {
 }
 
+already_AddRefed<InternalResponse>
+InternalResponse::FromIPC(const IPCInternalResponse& aIPCResponse)
+{
+  MOZ_ASSERT(!aIPCResponse.urlList().IsEmpty());
+
+  if (aIPCResponse.type() == ResponseType::Error) {
+    return InternalResponse::NetworkError();
+  }
+
+  RefPtr<InternalResponse> response =
+    new InternalResponse(aIPCResponse.status(),
+                         aIPCResponse.statusText());
+
+  response->SetURLList(aIPCResponse.urlList());
+
+  response->mHeaders = new InternalHeaders(aIPCResponse.headers(),
+                                           aIPCResponse.headersGuard());
+
+  response->InitChannelInfo(aIPCResponse.channelInfo());
+  if (aIPCResponse.principalInfo().type() == mozilla::ipc::OptionalPrincipalInfo::TPrincipalInfo) {
+    UniquePtr<mozilla::ipc::PrincipalInfo> info(new mozilla::ipc::PrincipalInfo(aIPCResponse.principalInfo().get_PrincipalInfo()));
+    response->SetPrincipalInfo(Move(info));
+  }
+
+  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.forget();
+}
+
 InternalResponse::~InternalResponse()
 {
 }
 
+void
+InternalResponse::ToIPC(IPCInternalResponse* aIPCResponse)
+{
+  MOZ_ASSERT(aIPCResponse);
+  MOZ_ASSERT(!mURLList.IsEmpty());
+  aIPCResponse->type() = mType;
+  aIPCResponse->urlList() = mURLList;
+  aIPCResponse->status() = GetUnfilteredStatus();
+  aIPCResponse->statusText() = GetUnfilteredStatusText();
+
+  mHeaders->ToIPC(aIPCResponse->headers(), aIPCResponse->headersGuard());
+
+  aIPCResponse->channelInfo() = mChannelInfo.AsIPCChannelInfo();
+  if (mPrincipalInfo) {
+    aIPCResponse->principalInfo() = *mPrincipalInfo;
+  } else {
+    aIPCResponse->principalInfo() = void_t();
+  }
+}
+
 already_AddRefed<InternalResponse>
 InternalResponse::Clone()
 {
   RefPtr<InternalResponse> clone = CreateIncompleteCopy();
 
   clone->mHeaders = new InternalHeaders(*mHeaders);
   if (mWrappedResponse) {
     clone->mWrappedResponse = mWrappedResponse->Clone();
--- a/dom/fetch/InternalResponse.h
+++ b/dom/fetch/InternalResponse.h
@@ -17,26 +17,32 @@
 namespace mozilla {
 namespace ipc {
 class PrincipalInfo;
 } // namespace ipc
 
 namespace dom {
 
 class InternalHeaders;
+class IPCInternalResponse;
 
 class InternalResponse final
 {
   friend class FetchDriver;
 
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalResponse)
 
   InternalResponse(uint16_t aStatus, const nsACString& aStatusText);
 
+  static already_AddRefed<InternalResponse>
+  FromIPC(const IPCInternalResponse& aIPCResponse);
+
+  void ToIPC(IPCInternalResponse* aIPCResponse);
+
   already_AddRefed<InternalResponse> Clone();
 
   static already_AddRefed<InternalResponse>
   NetworkError()
   {
     RefPtr<InternalResponse> response = new InternalResponse(0, EmptyCString());
     ErrorResult result;
     response->Headers()->SetGuard(HeadersGuardEnum::Immutable, result);
--- a/dom/fetch/moz.build
+++ b/dom/fetch/moz.build
@@ -3,16 +3,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/.
 
 EXPORTS.mozilla.dom += [
     'ChannelInfo.h',
     'Fetch.h',
     'FetchDriver.h',
+    'FetchIPCTypes.h',
     'FetchUtil.h',
     'Headers.h',
     'InternalHeaders.h',
     'InternalRequest.h',
     'InternalResponse.h',
     'Request.h',
     'Response.h',
 ]
@@ -27,16 +28,17 @@ UNIFIED_SOURCES += [
     'InternalRequest.cpp',
     'InternalResponse.cpp',
     'Request.cpp',
     'Response.cpp',
 ]
 
 IPDL_SOURCES += [
     'ChannelInfo.ipdlh',
+    'FetchTypes.ipdlh',
 ]
 
 LOCAL_INCLUDES += [
     '../workers',
     # For HttpBaseChannel.h dependencies
     '/netwerk/base',
     # For nsDataHandler.h
     '/netwerk/protocol/data',
--- a/dom/flyweb/FlyWebPublishedServer.cpp
+++ b/dom/flyweb/FlyWebPublishedServer.cpp
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/FlyWebPublishedServerIPC.h"
 #include "mozilla/dom/FlyWebPublishBinding.h"
 #include "mozilla/dom/FlyWebService.h"
 #include "mozilla/dom/Request.h"
 #include "mozilla/dom/FlyWebServerEvents.h"
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/InternalResponse.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/unused.h"
 #include "nsGlobalWindow.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -257,29 +259,55 @@ FlyWebPublishedServerChild::RecvServerCl
 {
   LOG_I("FlyWebPublishedServerChild::RecvServerClose(%p)", this);
 
   Close();
 
   return true;
 }
 
+bool
+FlyWebPublishedServerChild::RecvFetchRequest(const IPCInternalRequest& aRequest,
+                                             const uint64_t& aRequestId)
+{
+  LOG_I("FlyWebPublishedServerChild::RecvFetchRequest(%p)", this);
+
+  RefPtr<InternalRequest> request = new InternalRequest(aRequest);
+  mPendingRequests.Put(request, aRequestId);
+  FireFetchEvent(request);
+
+  return true;
+}
+
 void
 FlyWebPublishedServerChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   LOG_I("FlyWebPublishedServerChild::ActorDestroy(%p)", this);
 
   mActorDestroyed = true;
 }
 
 void
 FlyWebPublishedServerChild::OnFetchResponse(InternalRequest* aRequest,
                                             InternalResponse* aResponse)
 {
-  // Send ipdl message to parent
+  LOG_I("FlyWebPublishedServerChild::OnFetchResponse(%p)", this);
+
+  if (mActorDestroyed) {
+    LOG_I("FlyWebPublishedServerChild::OnFetchResponse(%p) - No actor!", this);
+    return;
+  }
+
+  uint64_t id = mPendingRequests.Get(aRequest);
+  MOZ_ASSERT(id);
+  mPendingRequests.Remove(aRequest);
+
+  IPCInternalResponse ipcResp;
+  aResponse->ToIPC(&ipcResp);
+  Unused << SendFetchResponse(ipcResp, id);
 }
 
 already_AddRefed<WebSocket>
 FlyWebPublishedServerChild::OnWebSocketAccept(InternalRequest* aConnectRequest,
                                               const Optional<nsAString>& aProtocol,
                                               ErrorResult& aRv)
 {
   // Send ipdl message to parent
@@ -304,19 +332,22 @@ FlyWebPublishedServerChild::Close()
     LOG_I("FlyWebPublishedServerChild::Close - sending __delete__ (%p)", this);
 
     Send__delete__(this);
   }
 }
 
 /******** FlyWebPublishedServerParent ********/
 
+NS_IMPL_ISUPPORTS(FlyWebPublishedServerParent, nsIDOMEventListener)
+
 FlyWebPublishedServerParent::FlyWebPublishedServerParent(const nsAString& aName,
                                                          const FlyWebPublishOptions& aOptions)
   : mActorDestroyed(false)
+  , mNextRequestId(1)
 {
   LOG_I("FlyWebPublishedServerParent::FlyWebPublishedServerParent(%p)", this);
 
   RefPtr<FlyWebService> service = FlyWebService::GetOrCreate();
   if (!service) {
     Unused << SendServerReady(NS_ERROR_FAILURE);
     return;
   }
@@ -325,45 +356,107 @@ FlyWebPublishedServerParent::FlyWebPubli
     service->PublishServer(aName, aOptions, nullptr);
   if (!mozPromise) {
     Unused << SendServerReady(NS_ERROR_FAILURE);
     return;
   }
 
   RefPtr<FlyWebPublishedServerParent> self = this;
 
-  mozPromise->Then(AbstractThread::MainThread(),
-                   __func__,
-                   [this, self] (FlyWebPublishedServer* aServer) {
-                     mPublishedServer = static_cast<FlyWebPublishedServerImpl*>(aServer);
-                     if (!mActorDestroyed) {
-                       Unused << SendServerReady(NS_OK);
-                     }
-                   },
-                   [this, self] (nsresult aStatus) {
-                     if (!mActorDestroyed) {
-                       Unused << SendServerReady(aStatus);
-                     }
-                   });
+  mozPromise->Then(
+    AbstractThread::MainThread(),
+    __func__,
+    [this, self] (FlyWebPublishedServer* aServer) {
+      mPublishedServer = static_cast<FlyWebPublishedServerImpl*>(aServer);
+      if (mActorDestroyed) {
+        mPublishedServer->Close();
+        return;
+      }
+
+      mPublishedServer->AddEventListener(NS_LITERAL_STRING("fetch"),
+                                         this, false, false, 2);
+      mPublishedServer->AddEventListener(NS_LITERAL_STRING("close"),
+                                         this, false, false, 2);
+      Unused << SendServerReady(NS_OK);
+    },
+    [this, self] (nsresult aStatus) {
+      MOZ_ASSERT(NS_FAILED(aStatus));
+      if (!mActorDestroyed) {
+        Unused << SendServerReady(aStatus);
+      }
+    });
+}
+
+NS_IMETHODIMP
+FlyWebPublishedServerParent::HandleEvent(nsIDOMEvent* aEvent)
+{
+  if (mActorDestroyed) {
+    return NS_OK;
+  }
+
+  nsAutoString type;
+  aEvent->GetType(type);
+  if (type.EqualsLiteral("close")) {
+    Unused << SendServerClose();
+    return NS_OK;
+  }
+
+  if (type.EqualsLiteral("fetch")) {
+    RefPtr<InternalRequest> request =
+      static_cast<FlyWebFetchEvent*>(aEvent)->Request()->GetInternalRequest();
+    uint64_t id = mNextRequestId++;
+    mPendingRequests.Put(id, request);
+
+    IPCInternalRequest ipcReq;
+    request->ToIPC(&ipcReq);
+    Unused << SendFetchRequest(ipcReq, id);
+    return NS_OK;
+  }
+
+  MOZ_CRASH("Unknown event type");
+
+  return NS_OK;
+}
+
+bool
+FlyWebPublishedServerParent::RecvFetchResponse(const IPCInternalResponse& aResponse,
+                                               const uint64_t& aRequestId)
+{
+  RefPtr<InternalRequest> request = mPendingRequests.GetWeak(aRequestId);
+  mPendingRequests.Remove(aRequestId);
+  if (!request) {
+     static_cast<ContentParent*>(Manager())->KillHard("unknown request id");
+     return false;
+  }
+
+  RefPtr<InternalResponse> response = InternalResponse::FromIPC(aResponse);
+
+  mPublishedServer->OnFetchResponse(request, response);
+
+  return true;
 }
 
 void
 FlyWebPublishedServerParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   LOG_I("FlyWebPublishedServerParent::ActorDestroy(%p)", this);
 
   mActorDestroyed = true;
 }
 
 bool
 FlyWebPublishedServerParent::Recv__delete__()
 {
   LOG_I("FlyWebPublishedServerParent::Recv__delete__(%p)", this);
 
   if (mPublishedServer) {
+    mPublishedServer->RemoveEventListener(NS_LITERAL_STRING("fetch"),
+                                          this, false);
+    mPublishedServer->RemoveEventListener(NS_LITERAL_STRING("close"),
+                                          this, false);
     mPublishedServer->Close();
     mPublishedServer = nullptr;
   }
   return true;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/flyweb/FlyWebPublishedServerIPC.h
+++ b/dom/flyweb/FlyWebPublishedServerIPC.h
@@ -7,18 +7,19 @@
 #ifndef mozilla_dom_FlyWebPublishedServerIPC_h
 #define mozilla_dom_FlyWebPublishedServerIPC_h
 
 #include "HttpServer.h"
 #include "mozilla/dom/FlyWebPublishedServer.h"
 #include "mozilla/dom/PFlyWebPublishedServerParent.h"
 #include "mozilla/dom/PFlyWebPublishedServerChild.h"
 #include "mozilla/MozPromise.h"
+#include "nsICancelable.h"
+#include "nsIDOMEventListener.h"
 #include "nsISupportsImpl.h"
-#include "nsICancelable.h"
 
 class nsPIDOMWindowInner;
 
 namespace mozilla {
 namespace dom {
 
 class FlyWebPublishedServerParent;
 
@@ -89,16 +90,18 @@ class FlyWebPublishedServerChild final :
 {
 public:
   FlyWebPublishedServerChild(nsPIDOMWindowInner* aOwner,
                              const nsAString& aName,
                              const FlyWebPublishOptions& aOptions);
 
   virtual bool RecvServerReady(const nsresult& aStatus) override;
   virtual bool RecvServerClose() override;
+  virtual bool RecvFetchRequest(const IPCInternalRequest& aRequest,
+                                const uint64_t& aRequestId) override;
 
   virtual void OnFetchResponse(InternalRequest* aRequest,
                                InternalResponse* aResponse) override;
   virtual already_AddRefed<WebSocket>
     OnWebSocketAccept(InternalRequest* aConnectRequest,
                       const Optional<nsAString>& aProtocol,
                       ErrorResult& aRv) override;
   virtual void OnWebSocketResponse(InternalRequest* aConnectRequest,
@@ -106,36 +109,44 @@ public:
 
   virtual void Close() override;
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   ~FlyWebPublishedServerChild() {}
 
+  nsDataHashtable<nsRefPtrHashKey<InternalRequest>, uint64_t> mPendingRequests;
   bool mActorDestroyed;
 };
 
 class FlyWebPublishedServerParent final : public PFlyWebPublishedServerParent
+                                        , public nsIDOMEventListener
 {
 public:
   FlyWebPublishedServerParent(const nsAString& aName,
                               const FlyWebPublishOptions& aOptions);
 
-  NS_INLINE_DECL_REFCOUNTING(FlyWebPublishedServerParent)
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOMEVENTLISTENER
 
 private:
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) override;
 
   virtual bool
   Recv__delete__() override;
+  virtual bool
+  RecvFetchResponse(const IPCInternalResponse& aResponse,
+                    const uint64_t& aRequestId) override;
 
   ~FlyWebPublishedServerParent() {}
 
   bool mActorDestroyed;
+  uint64_t mNextRequestId;
+  nsRefPtrHashtable<nsUint64HashKey, InternalRequest> mPendingRequests;
   RefPtr<FlyWebPublishedServerImpl> mPublishedServer;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_FlyWebPublishedServerIPC_h
--- a/dom/flyweb/HttpServer.cpp
+++ b/dom/flyweb/HttpServer.cpp
@@ -907,17 +907,17 @@ HttpServer::Connection::QueueResponse(In
 
   nsCString head(NS_LITERAL_CSTRING("HTTP/1.1 "));
   head.AppendInt(aResponse->GetStatus());
   // XXX is the statustext security checked?
   head.Append(NS_LITERAL_CSTRING(" ") +
               aResponse->GetStatusText() +
               NS_LITERAL_CSTRING("\r\n"));
 
-  nsTArray<InternalHeaders::Entry> entries;
+  AutoTArray<InternalHeaders::Entry, 16> entries;
   headers->GetEntries(entries);
 
   for (auto header : entries) {
     head.Append(header.mName +
                 NS_LITERAL_CSTRING(": ") +
                 header.mValue +
                 NS_LITERAL_CSTRING("\r\n"));
   }
--- a/dom/flyweb/PFlyWebPublishedServer.ipdl
+++ b/dom/flyweb/PFlyWebPublishedServer.ipdl
@@ -1,25 +1,29 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et ft=cpp : */
 /* 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 PContent;
+include FetchTypes;
 
 namespace mozilla {
 namespace dom {
 
 async protocol PFlyWebPublishedServer
 {
   manager PContent;
 
 child:
   async ServerReady(nsresult aStatus);
+  async FetchRequest(IPCInternalRequest aRequest, uint64_t aRequestId);
   async ServerClose();
 
 parent:
   async __delete__();
+
+  async FetchResponse(IPCInternalResponse aResponse, uint64_t aRequestId);
 };
 
 } // namespace dom
 } // namespace mozilla