Bug 1263991 parts 2 and 2.5: Enable launching a server in the parent process. r=baku,ehsan
authorJonas Sicking <jonas@sicking.cc>
Tue, 07 Jun 2016 02:46:03 -0700
changeset 300992 c9cc418f871dba0a3cca29c6e4afbce7dba4670d
parent 300991 e26bfa28a8826bac045ce8f6c7bb99f4da1bccf8
child 300993 411ea82341038f2a4fbac62bb8ff1ce03e0628e2
push id19599
push usercbook@mozilla.com
push dateWed, 08 Jun 2016 10:16:21 +0000
treeherderfx-team@81f4cc3f6f4c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku, ehsan
bugs1263991
milestone50.0a1
Bug 1263991 parts 2 and 2.5: Enable launching a server in the parent process. r=baku,ehsan
dom/base/Navigator.cpp
dom/flyweb/FlyWebPublishOptionsIPCSerializer.h
dom/flyweb/FlyWebPublishedServer.cpp
dom/flyweb/FlyWebPublishedServer.h
dom/flyweb/FlyWebPublishedServerIPC.h
dom/flyweb/FlyWebService.cpp
dom/flyweb/FlyWebService.h
dom/flyweb/HttpServer.cpp
dom/flyweb/PFlyWebPublishedServer.ipdl
dom/flyweb/moz.build
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -32,16 +32,17 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "BatteryManager.h"
 #include "mozilla/dom/DeviceStorageAreaListener.h"
 #include "mozilla/dom/PowerManager.h"
 #include "mozilla/dom/WakeLock.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/CellBroadcast.h"
+#include "mozilla/dom/FlyWebPublishedServer.h"
 #include "mozilla/dom/FlyWebService.h"
 #include "mozilla/dom/IccManager.h"
 #include "mozilla/dom/InputPortManager.h"
 #include "mozilla/dom/MobileMessageManager.h"
 #include "mozilla/dom/Permissions.h"
 #include "mozilla/dom/Presentation.h"
 #include "mozilla/dom/ServiceWorkerContainer.h"
 #include "mozilla/dom/TCPSocket.h"
@@ -1609,17 +1610,38 @@ Navigator::PublishServer(const nsAString
                          ErrorResult& aRv)
 {
   RefPtr<FlyWebService> service = FlyWebService::GetOrCreate();
   if (!service) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
-  return service->PublishServer(aName, aOptions, mWindow, aRv);
+  RefPtr<FlyWebPublishPromise> mozPromise =
+    service->PublishServer(aName, aOptions, mWindow);
+  MOZ_ASSERT(mozPromise);
+
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
+  ErrorResult result;
+  RefPtr<Promise> domPromise = Promise::Create(global, result);
+  if (result.Failed()) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  mozPromise->Then(AbstractThread::MainThread(),
+                   __func__,
+                   [domPromise] (FlyWebPublishedServer* aServer) {
+                     domPromise->MaybeResolve(aServer);
+                   },
+                   [domPromise] (nsresult aStatus) {
+                     domPromise->MaybeReject(aStatus);
+                   });
+
+  return domPromise.forget();
 }
 
 already_AddRefed<Promise>
 Navigator::GetFeature(const nsAString& aName, ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
   RefPtr<Promise> p = Promise::Create(go, aRv);
   if (aRv.Failed()) {
new file mode 100644
--- /dev/null
+++ b/dom/flyweb/FlyWebPublishOptionsIPCSerializer.h
@@ -0,0 +1,33 @@
+/* -*- 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_FlyWebPublishOptionsIPCSerialiser_h
+#define mozilla_dom_FlyWebPublishOptionsIPCSerialiser_h
+
+#include "mozilla/dom/FlyWebPublishBinding.h"
+
+namespace IPC {
+
+template <>
+struct ParamTraits<mozilla::dom::FlyWebPublishOptions>
+{
+  typedef mozilla::dom::FlyWebPublishOptions paramType;
+
+  // Function to serialize a FlyWebPublishOptions
+  static void Write(Message *aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mUiUrl);
+  }
+  // Function to de-serialize a FlyWebPublishOptions
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+  {
+    return ReadParam(aMsg, aIter, &(aResult->mUiUrl));
+  }
+};
+
+}
+
+#endif // mozilla_dom_FlyWebPublishOptionsIPCSerialiser_h
--- a/dom/flyweb/FlyWebPublishedServer.cpp
+++ b/dom/flyweb/FlyWebPublishedServer.cpp
@@ -1,143 +1,177 @@
 /* -*- 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/FlyWebPublishedServer.h"
+#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/ErrorResult.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/unused.h"
 #include "nsGlobalWindow.h"
 
 namespace mozilla {
 namespace dom {
 
 static LazyLogModule gFlyWebPublishedServerLog("FlyWebPublishedServer");
 #undef LOG_I
 #define LOG_I(...) MOZ_LOG(mozilla::dom::gFlyWebPublishedServerLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
 #undef LOG_E
 #define LOG_E(...) MOZ_LOG(mozilla::dom::gFlyWebPublishedServerLog, mozilla::LogLevel::Error, (__VA_ARGS__))
 
-NS_IMPL_ISUPPORTS_INHERITED0(FlyWebPublishedServer, mozilla::DOMEventTargetHelper)
+/******** FlyWebPublishedServer ********/
 
 FlyWebPublishedServer::FlyWebPublishedServer(nsPIDOMWindowInner* aOwner,
                                              const nsAString& aName,
-                                             const FlyWebPublishOptions& aOptions,
-                                             Promise* aPublishPromise)
+                                             const FlyWebPublishOptions& aOptions)
   : mozilla::DOMEventTargetHelper(aOwner)
   , mOwnerWindowID(aOwner ? aOwner->WindowID() : 0)
-  , mPublishPromise(aPublishPromise)
   , mName(aName)
   , mUiUrl(aOptions.mUiUrl)
   , mIsRegistered(true) // Registered by the FlyWebService
 {
-  mHttpServer = new HttpServer();
-  mHttpServer->Init(-1, Preferences::GetBool("flyweb.use-tls", false), this);
 }
 
-FlyWebPublishedServer::~FlyWebPublishedServer()
+void
+FlyWebPublishedServer::LastRelease()
 {
-  // Make sure to unregister to avoid dangling pointers
+  // Make sure to unregister to avoid dangling pointers. Use the LastRelease
+  // hook rather than dtor since calling virtual functions during dtor
+  // wouldn't do what we want. Also, LastRelease is called earlier than dtor
+  // for CC objects.
   Close();
 }
 
 JSObject*
 FlyWebPublishedServer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return FlyWebPublishedServerBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 FlyWebPublishedServer::Close()
 {
+  LOG_I("FlyWebPublishedServer::Close(%p)", this);
+
   // Unregister from server.
   if (mIsRegistered) {
-    FlyWebService::GetOrCreate()->UnregisterServer(this);
+    MOZ_ASSERT(FlyWebService::GetExisting());
+    FlyWebService::GetExisting()->UnregisterServer(this);
     mIsRegistered = false;
+
+    DispatchTrustedEvent(NS_LITERAL_STRING("close"));
   }
+}
+
+void
+FlyWebPublishedServer::FireFetchEvent(InternalRequest* aRequest)
+{
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
+  RefPtr<FlyWebFetchEvent> e = new FlyWebFetchEvent(this,
+                                                    new Request(global, aRequest),
+                                                    aRequest);
+  e->Init(this);
+  e->InitEvent(NS_LITERAL_STRING("fetch"), false, false);
+
+  DispatchTrustedEvent(e);
+}
+
+void
+FlyWebPublishedServer::FireWebsocketEvent(InternalRequest* aConnectRequest)
+{
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
+  RefPtr<FlyWebFetchEvent> e = new FlyWebWebSocketEvent(this,
+                                                        new Request(global, aConnectRequest),
+                                                        aConnectRequest);
+  e->Init(this);
+  e->InitEvent(NS_LITERAL_STRING("websocket"), false, false);
+
+  DispatchTrustedEvent(e);
+}
+
+void
+FlyWebPublishedServer::PublishedServerStarted(nsresult aStatus)
+{
+  LOG_I("FlyWebPublishedServer::PublishedServerStarted(%p)", this);
+
+  RefPtr<FlyWebPublishPromise> promise = mPublishPromise.Ensure(__func__);
+  if (NS_SUCCEEDED(aStatus)) {
+    mPublishPromise.Resolve(this, __func__);
+  } else {
+    Close();
+    mPublishPromise.Reject(aStatus, __func__);
+  }
+}
+
+/******** FlyWebPublishedServerImpl ********/
+
+NS_IMPL_ISUPPORTS_INHERITED0(FlyWebPublishedServerImpl, mozilla::DOMEventTargetHelper)
+
+FlyWebPublishedServerImpl::FlyWebPublishedServerImpl(nsPIDOMWindowInner* aOwner,
+                                                     const nsAString& aName,
+                                                     const FlyWebPublishOptions& aOptions)
+  : FlyWebPublishedServer(aOwner, aName, aOptions)
+  , mHttpServer(new HttpServer())
+{
+  LOG_I("FlyWebPublishedServerImpl::FlyWebPublishedServerImpl(%p)", this);
+
+  mHttpServer->Init(-1, Preferences::GetBool("flyweb.use-tls", false), this);
+}
+
+void
+FlyWebPublishedServerImpl::Close()
+{
+  FlyWebPublishedServer::Close();
 
   if (mMDNSCancelRegister) {
     mMDNSCancelRegister->Cancel(NS_BINDING_ABORTED);
     mMDNSCancelRegister = nullptr;
   }
 
   if (mHttpServer) {
     RefPtr<HttpServer> server = mHttpServer.forget();
     server->Close();
   }
 }
 
 void
-FlyWebPublishedServer::OnServerStarted(nsresult aStatus)
+FlyWebPublishedServerImpl::OnServerStarted(nsresult aStatus)
 {
   if (NS_SUCCEEDED(aStatus)) {
     FlyWebService::GetOrCreate()->StartDiscoveryOf(this);
   } else {
-    DiscoveryStarted(aStatus);
+    PublishedServerStarted(aStatus);
   }
 }
 
 void
-FlyWebPublishedServer::OnServerClose()
-{
-  mHttpServer = nullptr;
-  Close();
-
-  DispatchTrustedEvent(NS_LITERAL_STRING("close"));
-}
-
-void
-FlyWebPublishedServer::OnRequest(InternalRequest* aRequest)
-{
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
-  RefPtr<FlyWebFetchEvent> e = new FlyWebFetchEvent(this,
-                                                    new Request(global, aRequest),
-                                                    aRequest);
-  e->Init(this);
-  e->InitEvent(NS_LITERAL_STRING("fetch"), false, false);
-
-  DispatchTrustedEvent(e);
-}
-
-void
-FlyWebPublishedServer::OnWebSocket(InternalRequest* aConnectRequest)
-{
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
-  RefPtr<FlyWebFetchEvent> e = new FlyWebWebSocketEvent(this,
-                                                        new Request(global, aConnectRequest),
-                                                        aConnectRequest);
-  e->Init(this);
-  e->InitEvent(NS_LITERAL_STRING("websocket"), false, false);
-
-  DispatchTrustedEvent(e);
-}
-
-void
-FlyWebPublishedServer::OnFetchResponse(InternalRequest* aRequest,
-                                       InternalResponse* aResponse)
+FlyWebPublishedServerImpl::OnFetchResponse(InternalRequest* aRequest,
+                                           InternalResponse* aResponse)
 {
   MOZ_ASSERT(aRequest);
   MOZ_ASSERT(aResponse);
 
-  LOG_I("FlyWebPublishedMDNSServer::OnFetchResponse(%p)", this);
+  LOG_I("FlyWebPublishedServerImpl::OnFetchResponse(%p)", this);
 
   if (mHttpServer) {
     mHttpServer->SendResponse(aRequest, aResponse);
   }
 }
 
 already_AddRefed<WebSocket>
-FlyWebPublishedServer::OnWebSocketAccept(InternalRequest* aConnectRequest,
-                                         const Optional<nsAString>& aProtocol,
-                                         ErrorResult& aRv)
+FlyWebPublishedServerImpl::OnWebSocketAccept(InternalRequest* aConnectRequest,
+                                             const Optional<nsAString>& aProtocol,
+                                             ErrorResult& aRv)
 {
   MOZ_ASSERT(aConnectRequest);
 
   LOG_I("FlyWebPublishedMDNSServer::OnWebSocketAccept(%p)", this);
 
   if (!mHttpServer) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
@@ -171,35 +205,167 @@ FlyWebPublishedServer::OnWebSocketAccept
                                       NS_ConvertUTF8toUTF16(url),
                                       protocols,
                                       provider,
                                       negotiatedExtensions,
                                       aRv);
 }
 
 void
-FlyWebPublishedServer::OnWebSocketResponse(InternalRequest* aConnectRequest,
-                                           InternalResponse* aResponse)
+FlyWebPublishedServerImpl::OnWebSocketResponse(InternalRequest* aConnectRequest,
+                                               InternalResponse* aResponse)
 {
   MOZ_ASSERT(aConnectRequest);
   MOZ_ASSERT(aResponse);
 
   LOG_I("FlyWebPublishedMDNSServer::OnWebSocketResponse(%p)", this);
 
   if (mHttpServer) {
     mHttpServer->SendWebSocketResponse(aConnectRequest, aResponse);
   }
 }
 
-void FlyWebPublishedServer::DiscoveryStarted(nsresult aStatus)
+/******** FlyWebPublishedServerChild ********/
+
+FlyWebPublishedServerChild::FlyWebPublishedServerChild(nsPIDOMWindowInner* aOwner,
+                                                       const nsAString& aName,
+                                                       const FlyWebPublishOptions& aOptions)
+  : FlyWebPublishedServer(aOwner, aName, aOptions)
+  , mActorDestroyed(false)
+{
+  LOG_I("FlyWebPublishedServerChild::FlyWebPublishedServerChild(%p)", this);
+
+  ContentChild::GetSingleton()->
+    SendPFlyWebPublishedServerConstructor(this,
+                                          PromiseFlatString(aName),
+                                          aOptions);
+
+  // The matching release happens when the actor is destroyed, in
+  // ContentChild::DeallocPFlyWebPublishedServerChild
+  NS_ADDREF_THIS();
+}
+
+bool
+FlyWebPublishedServerChild::RecvServerReady(const nsresult& aStatus)
+{
+  LOG_I("FlyWebPublishedServerChild::RecvServerReady(%p)", this);
+
+  PublishedServerStarted(aStatus);
+  return true;
+}
+
+bool
+FlyWebPublishedServerChild::RecvServerClose()
+{
+  LOG_I("FlyWebPublishedServerChild::RecvServerClose(%p)", this);
+
+  Close();
+
+  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
+}
+
+already_AddRefed<WebSocket>
+FlyWebPublishedServerChild::OnWebSocketAccept(InternalRequest* aConnectRequest,
+                                              const Optional<nsAString>& aProtocol,
+                                              ErrorResult& aRv)
+{
+  // Send ipdl message to parent
+  return nullptr;
+}
+
+void
+FlyWebPublishedServerChild::OnWebSocketResponse(InternalRequest* aConnectRequest,
+                                                InternalResponse* aResponse)
 {
-  if (NS_SUCCEEDED(aStatus)) {
-    mPublishPromise->MaybeResolve(this);
-  } else {
-    Close();
-    mPublishPromise->MaybeReject(aStatus);
+  // Send ipdl message to parent
+}
+
+void
+FlyWebPublishedServerChild::Close()
+{
+  LOG_I("FlyWebPublishedServerChild::Close(%p)", this);
+
+  FlyWebPublishedServer::Close();
+
+  if (!mActorDestroyed) {
+    LOG_I("FlyWebPublishedServerChild::Close - sending __delete__ (%p)", this);
+
+    Send__delete__(this);
+  }
+}
+
+/******** FlyWebPublishedServerParent ********/
+
+FlyWebPublishedServerParent::FlyWebPublishedServerParent(const nsAString& aName,
+                                                         const FlyWebPublishOptions& aOptions)
+  : mActorDestroyed(false)
+{
+  LOG_I("FlyWebPublishedServerParent::FlyWebPublishedServerParent(%p)", this);
+
+  RefPtr<FlyWebService> service = FlyWebService::GetOrCreate();
+  if (!service) {
+    Unused << SendServerReady(NS_ERROR_FAILURE);
+    return;
+  }
+
+  RefPtr<FlyWebPublishPromise> mozPromise =
+    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);
+                     }
+                   });
+}
+
+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->Close();
+    mPublishedServer = nullptr;
+  }
+  return true;
 }
 
 } // namespace dom
 } // namespace mozilla
 
 
--- a/dom/flyweb/FlyWebPublishedServer.h
+++ b/dom/flyweb/FlyWebPublishedServer.h
@@ -2,112 +2,99 @@
 /* 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_FlyWebPublishedServer_h
 #define mozilla_dom_FlyWebPublishedServer_h
 
-#include "nsISupportsImpl.h"
-#include "nsICancelable.h"
 #include "mozilla/DOMEventTargetHelper.h"
-#include "mozilla/ErrorResult.h"
-#include "HttpServer.h"
-#include "mozilla/dom/WebSocket.h"
+#include "mozilla/MozPromise.h"
 
 class nsPIDOMWindowInner;
 
 namespace mozilla {
+
+class ErrorResult;
+
 namespace dom {
 
-class Promise;
 class InternalResponse;
 class InternalRequest;
+class WebSocket;
 struct FlyWebPublishOptions;
 class FlyWebPublishedServer;
 
-class FlyWebPublishedServer final : public mozilla::DOMEventTargetHelper
-                                  , public HttpServerListener
+typedef MozPromise<RefPtr<FlyWebPublishedServer>, nsresult, false>
+  FlyWebPublishPromise;
+
+class FlyWebPublishedServer : public mozilla::DOMEventTargetHelper
 {
 public:
   FlyWebPublishedServer(nsPIDOMWindowInner* aOwner,
                         const nsAString& aName,
-                        const FlyWebPublishOptions& aOptions,
-                        Promise* aPublishPromise);
+                        const FlyWebPublishOptions& aOptions);
+
+  virtual void LastRelease() override;
 
   virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
 
-  NS_DECL_ISUPPORTS_INHERITED
-
   uint64_t OwnerWindowID() const {
     return mOwnerWindowID;
   }
 
-  int32_t Port()
-  {
-    return mHttpServer ? mHttpServer->GetPort() : 0;
-  }
-  void GetCertKey(nsACString& aKey) {
-    if (mHttpServer) {
-      mHttpServer->GetCertKey(aKey);
-    } else {
-      aKey.Truncate();
-    }
-  }
-
   void GetName(nsAString& aName)
   {
     aName = mName;
   }
   nsAString& Name()
   {
     return mName;
   }
 
   void GetUiUrl(nsAString& aUiUrl)
   {
     aUiUrl = mUiUrl;
   }
 
-  void OnFetchResponse(InternalRequest* aRequest,
-                       InternalResponse* aResponse);
-  already_AddRefed<WebSocket>
+  virtual void OnFetchResponse(InternalRequest* aRequest,
+                               InternalResponse* aResponse) = 0;
+  virtual already_AddRefed<WebSocket>
     OnWebSocketAccept(InternalRequest* aConnectRequest,
                       const Optional<nsAString>& aProtocol,
-                      ErrorResult& aRv);
-  void OnWebSocketResponse(InternalRequest* aConnectRequest,
-                           InternalResponse* aResponse);
+                      ErrorResult& aRv) = 0;
+  virtual void OnWebSocketResponse(InternalRequest* aConnectRequest,
+                                   InternalResponse* aResponse) = 0;
 
-  void SetCancelRegister(nsICancelable* aCancelRegister)
-  {
-    mMDNSCancelRegister = aCancelRegister;
-  }
+  virtual void Close();
 
-  void Close();
-
-  // HttpServerListener
-  virtual void OnServerStarted(nsresult aStatus) override;
-  virtual void OnRequest(InternalRequest* aRequest) override;
-  virtual void OnWebSocket(InternalRequest* aConnectRequest) override;
-  virtual void OnServerClose() override;
+  void FireFetchEvent(InternalRequest* aRequest);
+  void FireWebsocketEvent(InternalRequest* aConnectRequest);
+  void PublishedServerStarted(nsresult aStatus);
 
   IMPL_EVENT_HANDLER(fetch)
   IMPL_EVENT_HANDLER(websocket)
   IMPL_EVENT_HANDLER(close)
 
-  void DiscoveryStarted(nsresult aStatus);
+  already_AddRefed<FlyWebPublishPromise>
+  GetPublishPromise()
+  {
+    return mPublishPromise.Ensure(__func__);
+  }
 
-private:
-  ~FlyWebPublishedServer();
+protected:
+
+  virtual ~FlyWebPublishedServer()
+  {
+    MOZ_ASSERT(!mIsRegistered, "Subclass dtor forgot to call Close()");
+  }
 
   uint64_t mOwnerWindowID;
-  RefPtr<HttpServer> mHttpServer;
-  RefPtr<Promise> mPublishPromise;
-  nsCOMPtr<nsICancelable> mMDNSCancelRegister;
+  MozPromiseHolder<FlyWebPublishPromise> mPublishPromise;
 
   nsString mName;
   nsString mUiUrl;
 
   bool mIsRegistered;
 };
 
 } // namespace dom
new file mode 100644
--- /dev/null
+++ b/dom/flyweb/FlyWebPublishedServerIPC.h
@@ -0,0 +1,141 @@
+/* -*- 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_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 "nsISupportsImpl.h"
+#include "nsICancelable.h"
+
+class nsPIDOMWindowInner;
+
+namespace mozilla {
+namespace dom {
+
+class FlyWebPublishedServerParent;
+
+class FlyWebPublishedServerImpl final : public FlyWebPublishedServer
+                                      , public HttpServerListener
+{
+public:
+  FlyWebPublishedServerImpl(nsPIDOMWindowInner* aOwner,
+                            const nsAString& aName,
+                            const FlyWebPublishOptions& aOptions);
+
+  NS_DECL_ISUPPORTS_INHERITED
+
+  int32_t Port()
+  {
+    return mHttpServer ? mHttpServer->GetPort() : 0;
+  }
+  void GetCertKey(nsACString& aKey) {
+    if (mHttpServer) {
+      mHttpServer->GetCertKey(aKey);
+    } else {
+      aKey.Truncate();
+    }
+  }
+
+  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,
+                                   InternalResponse* aResponse) override;
+
+  void SetCancelRegister(nsICancelable* aCancelRegister)
+  {
+    mMDNSCancelRegister = aCancelRegister;
+  }
+
+  virtual void Close() override;
+
+  // HttpServerListener
+  virtual void OnServerStarted(nsresult aStatus) override;
+  virtual void OnRequest(InternalRequest* aRequest) override
+  {
+    FireFetchEvent(aRequest);
+  }
+  virtual void OnWebSocket(InternalRequest* aConnectRequest) override
+  {
+    FireWebsocketEvent(aConnectRequest);
+  }
+  virtual void OnServerClose() override
+  {
+    mHttpServer = nullptr;
+    Close();
+  }
+
+private:
+  ~FlyWebPublishedServerImpl() {}
+
+  RefPtr<HttpServer> mHttpServer;
+  nsCOMPtr<nsICancelable> mMDNSCancelRegister;
+  RefPtr<FlyWebPublishedServerParent> mServerParent;
+};
+
+class FlyWebPublishedServerChild final : public FlyWebPublishedServer
+                                       , public PFlyWebPublishedServerChild
+{
+public:
+  FlyWebPublishedServerChild(nsPIDOMWindowInner* aOwner,
+                             const nsAString& aName,
+                             const FlyWebPublishOptions& aOptions);
+
+  virtual bool RecvServerReady(const nsresult& aStatus) override;
+  virtual bool RecvServerClose() 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,
+                                   InternalResponse* aResponse) override;
+
+  virtual void Close() override;
+
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+
+private:
+  ~FlyWebPublishedServerChild() {}
+
+  bool mActorDestroyed;
+};
+
+class FlyWebPublishedServerParent final : public PFlyWebPublishedServerParent
+{
+public:
+  FlyWebPublishedServerParent(const nsAString& aName,
+                              const FlyWebPublishOptions& aOptions);
+
+  NS_INLINE_DECL_REFCOUNTING(FlyWebPublishedServerParent)
+
+private:
+  virtual void
+  ActorDestroy(ActorDestroyReason aWhy) override;
+
+  virtual bool
+  Recv__delete__() override;
+
+  ~FlyWebPublishedServerParent() {}
+
+  bool mActorDestroyed;
+  RefPtr<FlyWebPublishedServerImpl> mPublishedServer;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_FlyWebPublishedServerIPC_h
--- a/dom/flyweb/FlyWebService.cpp
+++ b/dom/flyweb/FlyWebService.cpp
@@ -3,17 +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/. */
 
 #include "mozilla/dom/FlyWebService.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/dom/Promise.h"
-#include "mozilla/dom/FlyWebPublishedServer.h"
+#include "mozilla/dom/FlyWebPublishedServerIPC.h"
 #include "nsISocketTransportService.h"
 #include "mdns/libmdns/nsDNSServiceInfo.h"
 #include "nsIUUIDGenerator.h"
 #include "nsStandardURL.h"
 #include "mozilla/Services.h"
 #include "nsISupportsPrimitives.h"
 #include "mozilla/dom/FlyWebDiscoveryManagerBinding.h"
 #include "prnetdb.h"
@@ -72,17 +72,17 @@ private:
   nsresult StartDiscovery();
   nsresult StopDiscovery();
 
   void ListDiscoveredServices(nsTArray<FlyWebDiscoveredService>& aServices);
   bool HasService(const nsAString& aServiceId);
   nsresult PairWithService(const nsAString& aServiceId,
                            UniquePtr<FlyWebService::PairedInfo>& aInfo);
 
-  nsresult StartDiscoveryOf(FlyWebPublishedServer* aServer);
+  nsresult StartDiscoveryOf(FlyWebPublishedServerImpl* aServer);
 
   void EnsureDiscoveryStarted();
   void EnsureDiscoveryStopped();
 
   // Cycle-breaking link to manager.
   FlyWebService* mService;
   nsCString mServiceType;
 
@@ -437,17 +437,17 @@ FlyWebMDNSService::OnServiceRegistered(n
 
   nsString name = NS_ConvertUTF8toUTF16(cName);
   RefPtr<FlyWebPublishedServer> existingServer =
     FlyWebService::GetOrCreate()->FindPublishedServerByName(name);
   if (!existingServer) {
     return NS_ERROR_FAILURE;
   }
 
-  existingServer->DiscoveryStarted(NS_OK);
+  existingServer->PublishedServerStarted(NS_OK);
 
   return NS_OK;
 }
 
 nsresult
 FlyWebMDNSService::OnServiceUnregistered(nsIDNSServiceInfo* aServiceInfo)
 {
   LogDNSInfo(aServiceInfo, "FlyWebMDNSService::OnServiceUnregistered");
@@ -484,17 +484,17 @@ FlyWebMDNSService::OnRegistrationFailed(
     FlyWebService::GetOrCreate()->FindPublishedServerByName(name);
   if (!existingServer) {
     return NS_ERROR_FAILURE;
   }
 
   LOG_I("OnServiceRegistered(MDNS): Registration of server with name %s failed.", cName.get());
 
   // Remove the nsICancelable from the published server.
-  existingServer->DiscoveryStarted(NS_ERROR_FAILURE);
+  existingServer->PublishedServerStarted(NS_ERROR_FAILURE);
   return NS_OK;
 }
 
 nsresult
 FlyWebMDNSService::OnUnregistrationFailed(nsIDNSServiceInfo* aServiceInfo, int32_t errorCode)
 {
   LogDNSInfo(aServiceInfo, "FlyWebMDNSService::OnUnregistrationFailed");
 
@@ -691,17 +691,17 @@ FlyWebMDNSService::PairWithService(const
 
   aInfo->mService.mDiscoveredService = discInfo->mService;
   aInfo->mDNSServiceInfo = discInfo->mDNSServiceInfo;
 
   return NS_OK;
 }
 
 nsresult
-FlyWebMDNSService::StartDiscoveryOf(FlyWebPublishedServer* aServer)
+FlyWebMDNSService::StartDiscoveryOf(FlyWebPublishedServerImpl* aServer)
 {
 
   RefPtr<FlyWebPublishedServer> existingServer =
     FlyWebService::GetOrCreate()->FindPublishedServerByName(aServer->Name());
   MOZ_ASSERT(existingServer);
 
   // Advertise the service via mdns.
   RefPtr<net::nsDNSServiceInfo> serviceInfo(new net::nsDNSServiceInfo());
@@ -800,16 +800,24 @@ FlyWebService::GetOrCreate()
     }
   }
   return gFlyWebService;
 }
 
 ErrorResult
 FlyWebService::Init()
 {
+  // Most functions of FlyWebService should not be started in the child.
+  // Instead FlyWebService in the child is mainly responsible for tracking
+  // publishedServer lifetimes. Other functions are handled by the
+  // FlyWebService running in the parent.
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    return ErrorResult(NS_OK);
+  }
+
   MOZ_ASSERT(NS_IsMainThread());
   if (!mMDNSHttpService) {
     mMDNSHttpService = new FlyWebMDNSService(this, NS_LITERAL_CSTRING("_http._tcp."));
     ErrorResult rv;
 
     rv = mMDNSHttpService->Init();
     if (rv.Failed()) {
       LOG_E("FlyWebService failed to initialize MDNS _http._tcp.");
@@ -828,46 +836,44 @@ FlyWebService::Init()
       mMDNSFlywebService = nullptr;
       rv.SuppressException();
     }
   }
 
   return ErrorResult(NS_OK);
 }
 
-already_AddRefed<Promise>
+already_AddRefed<FlyWebPublishPromise>
 FlyWebService::PublishServer(const nsAString& aName,
                              const FlyWebPublishOptions& aOptions,
-                             nsPIDOMWindowInner* aWindow,
-                             ErrorResult& aRv)
+                             nsPIDOMWindowInner* aWindow)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aWindow);
-  RefPtr<Promise> promise = Promise::Create(global, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
   // Scan uiUrl for illegal characters
 
   RefPtr<FlyWebPublishedServer> existingServer =
     FlyWebService::GetOrCreate()->FindPublishedServerByName(aName);
   if (existingServer) {
     LOG_I("PublishServer: Trying to publish server with already-existing name %s.",
           NS_ConvertUTF16toUTF8(aName).get());
-    promise->MaybeReject(NS_ERROR_FAILURE);
+    MozPromiseHolder<FlyWebPublishPromise> holder;
+    RefPtr<FlyWebPublishPromise> promise = holder.Ensure(__func__);
+    holder.Reject(NS_ERROR_FAILURE, __func__);
     return promise.forget();
   }
 
-  RefPtr<FlyWebPublishedServer> server =
-    new FlyWebPublishedServer(aWindow, aName, aOptions, promise);
+  RefPtr<FlyWebPublishedServer> server;
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    server = new FlyWebPublishedServerChild(aWindow, aName, aOptions);
+  } else {
+    server = new FlyWebPublishedServerImpl(aWindow, aName, aOptions);
+  }
 
   mServers.AppendElement(server);
 
-  return promise.forget();
+  return server->GetPublishPromise();
 }
 
 already_AddRefed<FlyWebPublishedServer>
 FlyWebService::FindPublishedServerByName(
         const nsAString& aName)
 {
   MOZ_ASSERT(NS_IsMainThread());
   for (FlyWebPublishedServer* publishedServer : mServers) {
@@ -1106,22 +1112,22 @@ FlyWebService::CreateTransportForHost(co
     types, typeCount, host, port, hostRoute, portRoute, proxyInfo, &netAddr);
   NS_ENSURE_SUCCESS(rv, rv);
 
   trans.forget(result);
   return NS_OK;
 }
 
 void
-FlyWebService::StartDiscoveryOf(FlyWebPublishedServer* aServer)
+FlyWebService::StartDiscoveryOf(FlyWebPublishedServerImpl* aServer)
 {
   MOZ_ASSERT(NS_IsMainThread());
   nsresult rv = mMDNSFlywebService ?
     mMDNSFlywebService->StartDiscoveryOf(aServer) :
     NS_ERROR_FAILURE;
 
   if (NS_FAILED(rv)) {
-    aServer->DiscoveryStarted(rv);
+    aServer->PublishedServerStarted(rv);
   }
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/flyweb/FlyWebService.h
+++ b/dom/flyweb/FlyWebService.h
@@ -8,55 +8,59 @@
 #define mozilla_dom_FlyWebService_h
 
 #include "nsISupportsImpl.h"
 #include "mozilla/ErrorResult.h"
 #include "nsIProtocolHandler.h"
 #include "nsDataHashtable.h"
 #include "nsClassHashtable.h"
 #include "nsIObserver.h"
+#include "mozilla/MozPromise.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/dom/FlyWebDiscoveryManagerBinding.h"
 #include "nsITimer.h"
 #include "nsICancelable.h"
 #include "nsIDNSServiceDiscovery.h"
 
 class nsPIDOMWindowInner;
 class nsIProxyInfo;
 class nsISocketTransport;
 
 namespace mozilla {
 namespace dom {
 
-class Promise;
 struct FlyWebPublishOptions;
 struct FlyWebFilter;
 class FlyWebPublishedServer;
+class FlyWebPublishedServerImpl;
 class FlyWebPairingCallback;
 class FlyWebDiscoveryManager;
 class FlyWebMDNSService;
 
+typedef MozPromise<RefPtr<FlyWebPublishedServer>, nsresult, false>
+  FlyWebPublishPromise;
+
 class FlyWebService final : public nsIObserver
 {
   friend class FlyWebMDNSService;
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   static FlyWebService* GetExisting();
   static FlyWebService* GetOrCreate();
   static already_AddRefed<FlyWebService> GetOrCreateAddRefed()
   {
     return do_AddRef(GetOrCreate());
   }
 
-  already_AddRefed<Promise> PublishServer(const nsAString& aName,
-                                          const FlyWebPublishOptions& aOptions,
-                                          nsPIDOMWindowInner* aWindow,
-                                          ErrorResult& aRv);
+  already_AddRefed<FlyWebPublishPromise>
+    PublishServer(const nsAString& aName,
+                  const FlyWebPublishOptions& aOptions,
+                  nsPIDOMWindowInner* aWindow);
 
   void UnregisterServer(FlyWebPublishedServer* aServer);
 
   bool HasConnectionOrServer(uint64_t aWindowID);
 
   void ListDiscoveredServices(nsTArray<FlyWebDiscoveredService>& aServices);
   void PairWithService(const nsAString& aServiceId, FlyWebPairingCallback& aCallback);
   nsresult CreateTransportForHost(const char **types,
@@ -69,18 +73,18 @@ public:
                                   nsISocketTransport **result);
 
   already_AddRefed<FlyWebPublishedServer> FindPublishedServerByName(
             const nsAString& aName);
 
   void RegisterDiscoveryManager(FlyWebDiscoveryManager* aDiscoveryManager);
   void UnregisterDiscoveryManager(FlyWebDiscoveryManager* aDiscoveryManager);
 
-  // Should only be called by FlyWebPublishedServer
-  void StartDiscoveryOf(FlyWebPublishedServer* aServer);
+  // Should only be called by FlyWebPublishedServerImpl
+  void StartDiscoveryOf(FlyWebPublishedServerImpl* aServer);
 
 private:
   FlyWebService();
   ~FlyWebService();
 
   ErrorResult Init();
 
   void NotifyDiscoveredServicesChanged();
--- a/dom/flyweb/HttpServer.cpp
+++ b/dom/flyweb/HttpServer.cpp
@@ -216,18 +216,18 @@ void
 HttpServer::Close()
 {
   if (mServerSocket) {
     mServerSocket->Close();
     mServerSocket = nullptr;
   }
 
   if (mListener) {
-    mListener->OnServerClose();
-    mListener = nullptr;
+    RefPtr<HttpServerListener> listener = mListener.forget();
+    listener->OnServerClose();
   }
 
   for (Connection* conn : mConnections) {
     conn->Close();
   }
   mConnections.Clear();
 }
 
new file mode 100644
--- /dev/null
+++ b/dom/flyweb/PFlyWebPublishedServer.ipdl
@@ -0,0 +1,25 @@
+/* -*- 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;
+
+namespace mozilla {
+namespace dom {
+
+async protocol PFlyWebPublishedServer
+{
+  manager PContent;
+
+child:
+  async ServerReady(nsresult aStatus);
+  async ServerClose();
+
+parent:
+  async __delete__();
+};
+
+} // namespace dom
+} // namespace mozilla
--- a/dom/flyweb/moz.build
+++ b/dom/flyweb/moz.build
@@ -2,35 +2,41 @@
 # 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 += [
     'FlyWebDiscoveryManager.h',
     'FlyWebPublishedServer.h',
+    'FlyWebPublishedServerIPC.h',
+    'FlyWebPublishOptionsIPCSerializer.h',
     'FlyWebServerEvents.h',
     'FlyWebService.h',
     'HttpServer.h',
 ]
 
 UNIFIED_SOURCES += [
     'FlyWebDiscoveryManager.cpp',
     'FlyWebPublishedServer.cpp',
     'FlyWebServerEvents.cpp',
     'FlyWebService.cpp',
     'HttpServer.cpp'
 ]
 
-#include('/ipc/chromium/chromium-config.mozbuild')
+IPDL_SOURCES += [
+    'PFlyWebPublishedServer.ipdl',
+]
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/netwerk/base',
     '/netwerk/dns',
     '/netwerk/protocol/websocket',
     '/xpcom/io'
 ]
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -27,16 +27,17 @@
 #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
 #include "mozilla/docshell/OfflineCacheUpdateChild.h"
 #include "mozilla/dom/ContentBridgeChild.h"
 #include "mozilla/dom/ContentBridgeParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DOMStorageIPC.h"
 #include "mozilla/dom/ExternalHelperAppChild.h"
+#include "mozilla/dom/FlyWebPublishedServerIPC.h"
 #include "mozilla/dom/PCrashReporterChild.h"
 #include "mozilla/dom/ProcessGlobal.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/nsIContentChild.h"
 #include "mozilla/psm/PSMContentListener.h"
 #include "mozilla/hal_sandbox/PHalChild.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/FileDescriptorSetChild.h"
@@ -1684,16 +1685,32 @@ ContentChild::AllocPPresentationChild()
 
 bool
 ContentChild::DeallocPPresentationChild(PPresentationChild* aActor)
 {
   delete aActor;
   return true;
 }
 
+PFlyWebPublishedServerChild*
+ContentChild::AllocPFlyWebPublishedServerChild(const nsString& name,
+                                               const FlyWebPublishOptions& params)
+{
+  MOZ_CRASH("We should never be manually allocating PFlyWebPublishedServerChild actors");
+  return nullptr;
+}
+
+bool
+ContentChild::DeallocPFlyWebPublishedServerChild(PFlyWebPublishedServerChild* aActor)
+{
+  RefPtr<FlyWebPublishedServerChild> actor =
+    dont_AddRef(static_cast<FlyWebPublishedServerChild*>(aActor));
+  return true;
+}
+
 bool
 ContentChild::RecvNotifyPresentationReceiverLaunched(PBrowserChild* aIframe,
                                                      const nsString& aSessionId)
 {
   nsCOMPtr<nsIDocShell> docShell =
     do_GetInterface(static_cast<TabChild*>(aIframe)->WebNavigation());
   NS_WARN_IF(!docShell);
 
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -356,16 +356,22 @@ public:
   virtual PFMRadioChild* AllocPFMRadioChild() override;
 
   virtual bool DeallocPFMRadioChild(PFMRadioChild* aActor) override;
 
   virtual PPresentationChild* AllocPPresentationChild() override;
 
   virtual bool DeallocPPresentationChild(PPresentationChild* aActor) override;
 
+  virtual PFlyWebPublishedServerChild*
+    AllocPFlyWebPublishedServerChild(const nsString& name,
+                                     const FlyWebPublishOptions& params) override;
+
+  virtual bool DeallocPFlyWebPublishedServerChild(PFlyWebPublishedServerChild* aActor) override;
+
   virtual bool
   RecvNotifyPresentationReceiverLaunched(PBrowserChild* aIframe,
                                          const nsString& aSessionId) override;
 
   virtual bool
   RecvNotifyPresentationReceiverCleanUp(const nsString& aSessionId) override;
 
   virtual bool RecvNotifyGMPsChanged() override;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -63,16 +63,17 @@
 #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
 #include "mozilla/dom/icc/IccParent.h"
 #include "mozilla/dom/mobileconnection/MobileConnectionParent.h"
 #include "mozilla/dom/mobilemessage/SmsParent.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/Permissions.h"
 #include "mozilla/dom/PresentationParent.h"
 #include "mozilla/dom/PPresentationParent.h"
+#include "mozilla/dom/FlyWebPublishedServerIPC.h"
 #include "mozilla/dom/quota/QuotaManagerService.h"
 #include "mozilla/dom/telephony/TelephonyParent.h"
 #include "mozilla/dom/time/DateCacheCleaner.h"
 #include "mozilla/dom/voicemail/VoicemailParent.h"
 #include "mozilla/embedding/printingui/PrintingParent.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/hal_sandbox/PHalParent.h"
 #include "mozilla/ipc/BackgroundChild.h"
@@ -4143,16 +4144,33 @@ ContentParent::DeallocPPresentationParen
 }
 
 bool
 ContentParent::RecvPPresentationConstructor(PPresentationParent* aActor)
 {
   return static_cast<PresentationParent*>(aActor)->Init();
 }
 
+PFlyWebPublishedServerParent*
+ContentParent::AllocPFlyWebPublishedServerParent(const nsString& name,
+                                                 const FlyWebPublishOptions& params)
+{
+  RefPtr<FlyWebPublishedServerParent> actor =
+    new FlyWebPublishedServerParent(name, params);
+  return actor.forget().take();
+}
+
+bool
+ContentParent::DeallocPFlyWebPublishedServerParent(PFlyWebPublishedServerParent* aActor)
+{
+  RefPtr<FlyWebPublishedServerParent> actor =
+    dont_AddRef(static_cast<FlyWebPublishedServerParent*>(aActor));
+  return true;
+}
+
 PSpeechSynthesisParent*
 ContentParent::AllocPSpeechSynthesisParent()
 {
 #ifdef MOZ_WEBSPEECH
   return new mozilla::dom::SpeechSynthesisParent();
 #else
   return nullptr;
 #endif
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -863,16 +863,22 @@ private:
   virtual bool DeallocPFMRadioParent(PFMRadioParent* aActor) override;
 
   virtual PPresentationParent* AllocPPresentationParent() override;
 
   virtual bool DeallocPPresentationParent(PPresentationParent* aActor) override;
 
   virtual bool RecvPPresentationConstructor(PPresentationParent* aActor) override;
 
+  virtual PFlyWebPublishedServerParent*
+    AllocPFlyWebPublishedServerParent(const nsString& name,
+                                      const FlyWebPublishOptions& params) override;
+
+  virtual bool DeallocPFlyWebPublishedServerParent(PFlyWebPublishedServerParent* aActor) override;
+
   virtual PSpeechSynthesisParent* AllocPSpeechSynthesisParent() override;
 
   virtual bool
   DeallocPSpeechSynthesisParent(PSpeechSynthesisParent* aActor) override;
 
   virtual bool
   RecvPSpeechSynthesisConstructor(PSpeechSynthesisParent* aActor) override;
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -52,16 +52,17 @@ include protocol PTelephony;
 include protocol PTestShell;
 include protocol PVoicemail;
 include protocol PJavaScript;
 include protocol PRemoteSpellcheckEngine;
 include protocol PWebBrowserPersistDocument;
 include protocol PWebrtcGlobal;
 include protocol PPresentation;
 include protocol PVRManager;
+include protocol PFlyWebPublishedServer;
 include DOMTypes;
 include JavaScriptTypes;
 include InputStreamParams;
 include PTabContext;
 include URIParams;
 include PluginTypes;
 include ProtocolTypes;
 include PBackgroundSharedTypes;
@@ -93,16 +94,17 @@ using mozilla::gfx::IntSize from "mozill
 using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
 using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
 using mozilla::LayoutDeviceIntPoint from "Units.h";
 using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
 using class mozilla::dom::ipc::StructuredCloneData from "ipc/IPCMessageUtils.h";
 using mozilla::DataStorageType from "ipc/DataStorageIPCUtils.h";
 using mozilla::DocShellOriginAttributes from "mozilla/ipc/BackgroundUtils.h";
 using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
+using struct mozilla::dom::FlyWebPublishOptions from "mozilla/dom/FlyWebPublishOptionsIPCSerializer.h";
 
 union ChromeRegistryItem
 {
     ChromePackage;
     OverrideMapping;
     SubstitutionMapping;
 };
 
@@ -428,16 +430,17 @@ prio(normal upto urgent) sync protocol P
     manages PTelephony;
     manages PTestShell;
     manages PVoicemail;
     manages PJavaScript;
     manages PRemoteSpellcheckEngine;
     manages PWebBrowserPersistDocument;
     manages PWebrtcGlobal;
     manages PPresentation;
+    manages PFlyWebPublishedServer;
 
 both:
     // Depending on exactly how the new browser is being created, it might be
     // created from either the child or parent process!
     //
     // The child creates the PBrowser as part of
     // TabChild::BrowserFrameProvideWindow (which happens when the child's
     // content calls window.open()), and the parent creates the PBrowser as part
@@ -848,16 +851,18 @@ parent:
     async PBluetooth();
 
     async PFMRadio();
 
     async PWebrtcGlobal();
 
     async PPresentation();
 
+    async PFlyWebPublishedServer(nsString name, FlyWebPublishOptions params);
+
     // Services remoting
 
     async StartVisitedQuery(URIParams uri);
     async VisitURI(URIParams uri, OptionalURIParams referrer, uint32_t flags);
     async SetURITitle(URIParams uri, nsString title);
 
     async LoadURIExternal(URIParams uri, PBrowser windowContext);