Bug 1148307 - Part1, separate object bruilder from nsIPresentationSessionTransport, r=smaug
authorJunior Hsu <juhsu@mozilla.com>
Thu, 24 Sep 2015 16:16:47 +0800
changeset 330653 9c014e78167266b6a1abc726d22d938eb61b3fda
parent 330651 52fd577f808f21db74f8ad98c3cc82a20bae486e
child 330654 ee4c84bfbf69d1cb709e84a25c3a92e62889d288
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1148307
milestone48.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 1148307 - Part1, separate object bruilder from nsIPresentationSessionTransport, r=smaug
dom/presentation/PresentationSessionInfo.cpp
dom/presentation/PresentationSessionInfo.h
dom/presentation/PresentationSessionTransport.cpp
dom/presentation/PresentationSessionTransport.h
dom/presentation/PresentationTCPSessionTransport.cpp
dom/presentation/PresentationTCPSessionTransport.h
dom/presentation/interfaces/moz.build
dom/presentation/interfaces/nsIPresentationSessionTransport.idl
dom/presentation/interfaces/nsIPresentationSessionTransportBuilder.idl
dom/presentation/moz.build
dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
dom/presentation/tests/xpcshell/test_presentation_session_transport.js
layout/build/nsLayoutModule.cpp
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -116,56 +116,56 @@ PresentationNetworkHelper::OnGetWifiIPAd
                                            aIPAddress));
   return NS_OK;
 }
 
 } // anonymous namespace
 
 #endif // MOZ_WIDGET_ANDROID
 
-class PresentationChannelDescription final : public nsIPresentationChannelDescription
+class TCPPresentationChannelDescription final : public nsIPresentationChannelDescription
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPRESENTATIONCHANNELDESCRIPTION
 
-  PresentationChannelDescription(const nsACString& aAddress,
-                                 uint16_t aPort)
+  TCPPresentationChannelDescription(const nsACString& aAddress,
+                                    uint16_t aPort)
     : mAddress(aAddress)
     , mPort(aPort)
   {
   }
 
 private:
-  ~PresentationChannelDescription() {}
+  ~TCPPresentationChannelDescription() {}
 
   nsCString mAddress;
   uint16_t mPort;
 };
 
 } // namespace dom
 } // namespace mozilla
 
-NS_IMPL_ISUPPORTS(PresentationChannelDescription, nsIPresentationChannelDescription)
+NS_IMPL_ISUPPORTS(TCPPresentationChannelDescription, nsIPresentationChannelDescription)
 
 NS_IMETHODIMP
-PresentationChannelDescription::GetType(uint8_t* aRetVal)
+TCPPresentationChannelDescription::GetType(uint8_t* aRetVal)
 {
   if (NS_WARN_IF(!aRetVal)) {
     return NS_ERROR_INVALID_POINTER;
   }
 
   // TODO bug 1148307 Implement PresentationSessionTransport with DataChannel.
   // Only support TCP socket for now.
   *aRetVal = nsIPresentationChannelDescription::TYPE_TCP;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PresentationChannelDescription::GetTcpAddress(nsIArray** aRetVal)
+TCPPresentationChannelDescription::GetTcpAddress(nsIArray** aRetVal)
 {
   if (NS_WARN_IF(!aRetVal)) {
     return NS_ERROR_INVALID_POINTER;
   }
 
   nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
   if (NS_WARN_IF(!array)) {
     return NS_ERROR_OUT_OF_MEMORY;
@@ -184,42 +184,43 @@ PresentationChannelDescription::GetTcpAd
 
   array->AppendElement(address, false);
   array.forget(aRetVal);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PresentationChannelDescription::GetTcpPort(uint16_t* aRetVal)
+TCPPresentationChannelDescription::GetTcpPort(uint16_t* aRetVal)
 {
   if (NS_WARN_IF(!aRetVal)) {
     return NS_ERROR_INVALID_POINTER;
   }
 
   *aRetVal = mPort;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PresentationChannelDescription::GetDataChannelSDP(nsAString& aDataChannelSDP)
+TCPPresentationChannelDescription::GetDataChannelSDP(nsAString& aDataChannelSDP)
 {
   // TODO bug 1148307 Implement PresentationSessionTransport with DataChannel.
   // Only support TCP socket for now.
   aDataChannelSDP.Truncate();
   return NS_OK;
 }
 
 /*
  * Implementation of PresentationSessionInfo
  */
 
 NS_IMPL_ISUPPORTS(PresentationSessionInfo,
                   nsIPresentationSessionTransportCallback,
-                  nsIPresentationControlChannelListener);
+                  nsIPresentationControlChannelListener,
+                  nsIPresentationSessionTransportBuilderListener);
 
 /* virtual */ nsresult
 PresentationSessionInfo::Init(nsIPresentationControlChannel* aControlChannel)
 {
   SetControlChannel(aControlChannel);
   return NS_OK;
 }
 
@@ -401,16 +402,41 @@ PresentationSessionInfo::NotifyData(cons
 
   if (NS_WARN_IF(!mListener)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   return mListener->NotifyMessage(mSessionId, aData);
 }
 
+// nsIPresentationSessionTransportBuilderListener
+NS_IMETHODIMP
+PresentationSessionInfo::OnSessionTransport(nsIPresentationSessionTransport* transport)
+{
+  mTransport = transport;
+
+  nsresult rv = mTransport->SetCallback(this);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (mListener) {
+    mTransport->EnableDataNotification();
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PresentationSessionInfo::OnError(nsresult reason)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
 /*
  * Implementation of PresentationControllingInfo
  *
  * During presentation session establishment, the sender expects the following
  * after trying to establish the control channel: (The order between step 3 and
  * 4 is not guaranteed.)
  * 1. |Init| is called to open a socket |mServerSocket| for data transport
  *    channel.
@@ -565,18 +591,18 @@ PresentationControllingInfo::OnGetAddres
 
   // Prepare and send the offer.
   int32_t port;
   nsresult rv = mServerSocket->GetPort(&port);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  RefPtr<PresentationChannelDescription> description =
-    new PresentationChannelDescription(aAddress, static_cast<uint16_t>(port));
+  RefPtr<TCPPresentationChannelDescription> description =
+    new TCPPresentationChannelDescription(aAddress, static_cast<uint16_t>(port));
   return mControlChannel->SendOffer(description);
 }
 
 // nsIPresentationControlChannelListener
 NS_IMETHODIMP
 PresentationControllingInfo::OnOffer(nsIPresentationChannelDescription* aDescription)
 {
   MOZ_ASSERT(false, "Sender side should not receive offer.");
@@ -639,33 +665,24 @@ PresentationControllingInfo::OnSocketAcc
   int32_t port;
   nsresult rv = aTransport->GetPort(&port);
   if (!NS_WARN_IF(NS_FAILED(rv))) {
     PRES_DEBUG("%s:receive from port[%d]\n",__func__, port);
   }
 
   MOZ_ASSERT(NS_IsMainThread());
 
-  // Initialize |mTransport| and use |this| as the callback.
-  mTransport = do_CreateInstance(PRESENTATION_SESSION_TRANSPORT_CONTRACTID);
-  if (NS_WARN_IF(!mTransport)) {
+  // Initialize session transport builder and use |this| as the callback.
+  nsCOMPtr<nsIPresentationTCPSessionTransportBuilder> builder =
+    do_CreateInstance(PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID);
+  if (NS_WARN_IF(!builder)) {
     return ReplyError(NS_ERROR_DOM_OPERATION_ERR);
   }
 
-  rv = mTransport->InitWithSocketTransport(aTransport, this);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  // Enable data notification if the listener has been registered.
-  if (mListener) {
-    return mTransport->EnableDataNotification();
-  }
-
-  return NS_OK;
+  return builder->BuildTCPSenderTransport(aTransport, this);
 }
 
 NS_IMETHODIMP
 PresentationControllingInfo::OnStopListening(nsIServerSocket* aServerSocket,
                                            nsresult aStatus)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -740,61 +757,64 @@ PresentationPresentingInfo::Shutdown(nsr
     mTimer->Cancel();
   }
 
   mLoadingCallback = nullptr;
   mRequesterDescription = nullptr;
   mPromise = nullptr;
 }
 
-nsresult
-PresentationPresentingInfo::InitTransportAndSendAnswer()
+// nsIPresentationSessionTransportBuilderListener
+NS_IMETHODIMP
+PresentationPresentingInfo::OnSessionTransport(nsIPresentationSessionTransport* transport)
 {
-  // Establish a data transport channel |mTransport| to the sender and use
-  // |this| as the callback.
-  mTransport = do_CreateInstance(PRESENTATION_SESSION_TRANSPORT_CONTRACTID);
-  if (NS_WARN_IF(!mTransport)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  nsresult rv = mTransport->InitWithChannelDescription(mRequesterDescription, this);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  // Enable data notification if the listener has been registered.
-  if (mListener) {
-    rv = mTransport->EnableDataNotification();
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-  }
+  PresentationSessionInfo::OnSessionTransport(transport);
 
   // Prepare and send the answer.
   // TODO bug 1148307 Implement PresentationSessionTransport with DataChannel.
   // In the current implementation of |PresentationSessionTransport|,
   // |GetSelfAddress| cannot return the real info when it's initialized via
   // |InitWithChannelDescription|. Yet this deficiency only affects the channel
   // description for the answer, which is not actually checked at requester side.
   nsCOMPtr<nsINetAddr> selfAddr;
-  rv = mTransport->GetSelfAddress(getter_AddRefs(selfAddr));
+  nsresult rv = mTransport->GetSelfAddress(getter_AddRefs(selfAddr));
   NS_WARN_IF(NS_FAILED(rv));
 
   nsCString address;
   uint16_t port = 0;
   if (NS_SUCCEEDED(rv)) {
     selfAddr->GetAddress(address);
     selfAddr->GetPort(&port);
   }
   nsCOMPtr<nsIPresentationChannelDescription> description =
-    new PresentationChannelDescription(address, port);
+    new TCPPresentationChannelDescription(address, port);
 
   return mControlChannel->SendAnswer(description);
 }
 
+NS_IMETHODIMP
+PresentationPresentingInfo::OnError(nsresult reason)
+{
+  return PresentationSessionInfo::OnError(reason);
+}
+
+nsresult
+PresentationPresentingInfo::InitTransportAndSendAnswer()
+{
+  // Establish a data transport channel |mTransport| to the sender and use
+  // |this| as the callback.
+  nsCOMPtr<nsIPresentationTCPSessionTransportBuilder> builder =
+    do_CreateInstance(PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID);
+  if (NS_WARN_IF(!builder)) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  return builder->BuildTCPReceiverTransport(mRequesterDescription, this);
+}
+
 nsresult
 PresentationPresentingInfo::UntrackFromService()
 {
   // Remove the OOP responding info (if it has never been used).
   if (mContentParent) {
     NS_WARN_IF(!static_cast<ContentParent*>(mContentParent.get())->SendNotifyPresentationReceiverCleanUp(mSessionId));
   }
 
--- a/dom/presentation/PresentationSessionInfo.h
+++ b/dom/presentation/PresentationSessionInfo.h
@@ -13,30 +13,33 @@
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/RefPtr.h"
 #include "nsCOMPtr.h"
 #include "nsIPresentationControlChannel.h"
 #include "nsIPresentationDevice.h"
 #include "nsIPresentationListener.h"
 #include "nsIPresentationService.h"
 #include "nsIPresentationSessionTransport.h"
+#include "nsIPresentationSessionTransportBuilder.h"
 #include "nsIServerSocket.h"
 #include "nsITimer.h"
 #include "nsString.h"
 #include "PresentationCallbacks.h"
 
 namespace mozilla {
 namespace dom {
 
 class PresentationSessionInfo : public nsIPresentationSessionTransportCallback
                               , public nsIPresentationControlChannelListener
+                              , public nsIPresentationSessionTransportBuilderListener
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTCALLBACK
+  NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTBUILDERLISTENER
 
   PresentationSessionInfo(const nsAString& aUrl,
                           const nsAString& aSessionId,
                           nsIPresentationServiceCallback* aCallback)
     : mUrl(aUrl)
     , mSessionId(aSessionId)
     , mIsResponderReady(false)
     , mIsTransportReady(false)
@@ -179,16 +182,17 @@ private:
 // Session info with presenting browsing context (receiver side) behaviors.
 class PresentationPresentingInfo final : public PresentationSessionInfo
                                        , public PromiseNativeHandler
                                        , public nsITimerCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIPRESENTATIONCONTROLCHANNELLISTENER
+  NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTBUILDERLISTENER
   NS_DECL_NSITIMERCALLBACK
 
   PresentationPresentingInfo(const nsAString& aUrl,
                              const nsAString& aSessionId,
                              nsIPresentationDevice* aDevice)
     : PresentationSessionInfo(aUrl, aSessionId, nullptr)
   {
     MOZ_ASSERT(aDevice);
rename from dom/presentation/PresentationSessionTransport.cpp
rename to dom/presentation/PresentationTCPSessionTransport.cpp
--- a/dom/presentation/PresentationSessionTransport.cpp
+++ b/dom/presentation/PresentationTCPSessionTransport.cpp
@@ -11,40 +11,41 @@
 #include "nsIMutableArray.h"
 #include "nsIOutputStream.h"
 #include "nsIPresentationControlChannel.h"
 #include "nsIScriptableInputStream.h"
 #include "nsISocketTransport.h"
 #include "nsISocketTransportService.h"
 #include "nsISupportsPrimitives.h"
 #include "nsNetUtil.h"
+#include "nsQueryObject.h"
 #include "nsServiceManagerUtils.h"
 #include "nsStreamUtils.h"
 #include "nsThreadUtils.h"
 #include "PresentationLog.h"
-#include "PresentationSessionTransport.h"
+#include "PresentationTCPSessionTransport.h"
 
 #define BUFFER_SIZE 65536
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 class CopierCallbacks final : public nsIRequestObserver
 {
 public:
-  explicit CopierCallbacks(PresentationSessionTransport* aTransport)
+  explicit CopierCallbacks(PresentationTCPSessionTransport* aTransport)
     : mOwner(aTransport)
   {}
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
 private:
   ~CopierCallbacks() {}
 
-  RefPtr<PresentationSessionTransport> mOwner;
+  RefPtr<PresentationTCPSessionTransport> mOwner;
 };
 
 NS_IMPL_ISUPPORTS(CopierCallbacks, nsIRequestObserver)
 
 NS_IMETHODIMP
 CopierCallbacks::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
 {
   return NS_OK;
@@ -52,86 +53,95 @@ CopierCallbacks::OnStartRequest(nsIReque
 
 NS_IMETHODIMP
 CopierCallbacks::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatus)
 {
   mOwner->NotifyCopyComplete(aStatus);
   return NS_OK;
 }
 
-NS_IMPL_CYCLE_COLLECTION(PresentationSessionTransport, mTransport,
+NS_IMPL_CYCLE_COLLECTION(PresentationTCPSessionTransport, mTransport,
                          mSocketInputStream, mSocketOutputStream,
                          mInputStreamPump, mInputStreamScriptable,
                          mMultiplexStream, mMultiplexStreamCopier, mCallback)
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(PresentationSessionTransport)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationSessionTransport)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(PresentationTCPSessionTransport)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationTCPSessionTransport)
 
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PresentationSessionTransport)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PresentationTCPSessionTransport)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPresentationSessionTransport)
   NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionTransport)
   NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
+  NS_INTERFACE_MAP_ENTRY(nsIPresentationTCPSessionTransportBuilder)
   NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
   NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
   NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
 NS_INTERFACE_MAP_END
 
-PresentationSessionTransport::PresentationSessionTransport()
-  : mReadyState(CLOSED)
+PresentationTCPSessionTransport::PresentationTCPSessionTransport()
+  : mReadyState(ReadyState::CLOSED)
   , mAsyncCopierActive(false)
   , mCloseStatus(NS_OK)
   , mDataNotificationEnabled(false)
 {
 }
 
-PresentationSessionTransport::~PresentationSessionTransport()
+PresentationTCPSessionTransport::~PresentationTCPSessionTransport()
 {
 }
 
 NS_IMETHODIMP
-PresentationSessionTransport::InitWithSocketTransport(nsISocketTransport* aTransport,
-                                                      nsIPresentationSessionTransportCallback* aCallback)
+PresentationTCPSessionTransport::BuildTCPSenderTransport(nsISocketTransport* aTransport,
+                                                         nsIPresentationSessionTransportBuilderListener* aListener)
 {
-  if (NS_WARN_IF(!aCallback)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-  mCallback = aCallback;
-
   if (NS_WARN_IF(!aTransport)) {
     return NS_ERROR_INVALID_ARG;
   }
   mTransport = aTransport;
 
+  if (NS_WARN_IF(!aListener)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+  mListener = aListener;
+
   nsresult rv = CreateStream();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  SetReadyState(OPEN);
+  SetReadyState(ReadyState::OPEN);
 
   if (IsReadyToNotifyData()) {
     return CreateInputStreamPump();
   }
 
-  return NS_OK;
+  mType = nsIPresentationSessionTransportBuilder::TYPE_SENDER;
+
+  nsCOMPtr<nsIPresentationSessionTransport> sessionTransport = do_QueryObject(this);
+  nsCOMPtr<nsIRunnable> runnable =
+    NS_NewRunnableMethodWithArgs
+      <nsIPresentationSessionTransport*>(mListener,
+                                         &nsIPresentationSessionTransportBuilderListener::OnSessionTransport,
+                                         sessionTransport);
+  return NS_DispatchToCurrentThread(runnable);
 }
 
 NS_IMETHODIMP
-PresentationSessionTransport::InitWithChannelDescription(nsIPresentationChannelDescription* aDescription,
-                                                         nsIPresentationSessionTransportCallback* aCallback)
+PresentationTCPSessionTransport::BuildTCPReceiverTransport(nsIPresentationChannelDescription* aDescription,
+                                                           nsIPresentationSessionTransportBuilderListener* aListener)
 {
-  if (NS_WARN_IF(!aCallback)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-  mCallback = aCallback;
-
   if (NS_WARN_IF(!aDescription)) {
     return NS_ERROR_INVALID_ARG;
   }
 
+  if (NS_WARN_IF(!aListener)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+  mListener = aListener;
+
   uint16_t serverPort;
   nsresult rv = aDescription->GetTcpPort(&serverPort);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsCOMPtr<nsIArray> serverHosts;
   rv = aDescription->GetTcpAddress(getter_AddRefs(serverHosts));
@@ -152,17 +162,17 @@ PresentationSessionTransport::InitWithCh
   nsAutoCString serverHost;
   supportStr->GetData(serverHost);
   if (serverHost.IsEmpty()) {
     return NS_ERROR_INVALID_ARG;
   }
 
   PRES_DEBUG("%s:ServerHost[%s],ServerPort[%d]\n", __func__, serverHost.get(), serverPort);
 
-  SetReadyState(CONNECTING);
+  SetReadyState(ReadyState::CONNECTING);
 
   nsCOMPtr<nsISocketTransportService> sts =
     do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
   if (NS_WARN_IF(!sts)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   rv = sts->CreateTransport(nullptr, 0, serverHost, serverPort, nullptr,
                             getter_AddRefs(mTransport));
@@ -175,21 +185,29 @@ PresentationSessionTransport::InitWithCh
 
   mTransport->SetEventSink(this, mainThread);
 
   rv = CreateStream();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  return NS_OK;
+  mType = nsIPresentationSessionTransportBuilder::TYPE_RECEIVER;
+
+  nsCOMPtr<nsIPresentationSessionTransport> sessionTransport = do_QueryObject(this);
+  nsCOMPtr<nsIRunnable> runnable =
+    NS_NewRunnableMethodWithArgs
+      <nsIPresentationSessionTransport*>(mListener,
+                                         &nsIPresentationSessionTransportBuilderListener::OnSessionTransport,
+                                         sessionTransport);
+  return NS_DispatchToCurrentThread(runnable);
 }
 
 nsresult
-PresentationSessionTransport::CreateStream()
+PresentationTCPSessionTransport::CreateStream()
 {
   nsresult rv = mTransport->OpenInputStream(0, 0, 0, getter_AddRefs(mSocketInputStream));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   rv = mTransport->OpenOutputStream(nsITransport::OPEN_UNBUFFERED, 0, 0, getter_AddRefs(mSocketOutputStream));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -247,17 +265,17 @@ PresentationSessionTransport::CreateStre
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
 
 nsresult
-PresentationSessionTransport::CreateInputStreamPump()
+PresentationTCPSessionTransport::CreateInputStreamPump()
 {
   nsresult rv;
   mInputStreamPump = do_CreateInstance(NS_INPUTSTREAMPUMP_CONTRACTID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = mInputStreamPump->Init(mSocketInputStream, -1, -1, 0, 0, false);
@@ -269,17 +287,17 @@ PresentationSessionTransport::CreateInpu
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PresentationSessionTransport::EnableDataNotification()
+PresentationTCPSessionTransport::EnableDataNotification()
 {
   if (NS_WARN_IF(!mCallback)) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   if (mDataNotificationEnabled) {
     return NS_OK;
   }
@@ -288,178 +306,196 @@ PresentationSessionTransport::EnableData
 
   if (IsReadyToNotifyData()) {
     return CreateInputStreamPump();
   }
 
   return NS_OK;
 }
 
+// nsIPresentationSessionTransportBuilderListener
 NS_IMETHODIMP
-PresentationSessionTransport::GetSelfAddress(nsINetAddr** aSelfAddress)
+PresentationTCPSessionTransport::GetCallback(nsIPresentationSessionTransportCallback** aCallback)
+{
+  nsCOMPtr<nsIPresentationSessionTransportCallback> callback = mCallback;
+  callback.forget(aCallback);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PresentationTCPSessionTransport::SetCallback(nsIPresentationSessionTransportCallback* aCallback)
+{
+  mCallback = aCallback;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PresentationTCPSessionTransport::GetSelfAddress(nsINetAddr** aSelfAddress)
 {
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   return mTransport->GetScriptableSelfAddr(aSelfAddress);
 }
 
 void
-PresentationSessionTransport::EnsureCopying()
+PresentationTCPSessionTransport::EnsureCopying()
 {
   if (mAsyncCopierActive) {
     return;
   }
 
   mAsyncCopierActive = true;
   RefPtr<CopierCallbacks> callbacks = new CopierCallbacks(this);
   NS_WARN_IF(NS_FAILED(mMultiplexStreamCopier->AsyncCopy(callbacks, nullptr)));
 }
 
 void
-PresentationSessionTransport::NotifyCopyComplete(nsresult aStatus)
+PresentationTCPSessionTransport::NotifyCopyComplete(nsresult aStatus)
 {
   mAsyncCopierActive = false;
   mMultiplexStream->RemoveStream(0);
   if (NS_WARN_IF(NS_FAILED(aStatus))) {
-    if (mReadyState != CLOSED) {
+    if (mReadyState != ReadyState::CLOSED) {
       mCloseStatus = aStatus;
-      SetReadyState(CLOSED);
+      SetReadyState(ReadyState::CLOSED);
     }
     return;
   }
 
   uint32_t count;
   nsresult rv = mMultiplexStream->GetCount(&count);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   if (count) {
     EnsureCopying();
     return;
   }
 
-  if (mReadyState == CLOSING) {
+  if (mReadyState == ReadyState::CLOSING) {
     mSocketOutputStream->Close();
     mCloseStatus = NS_OK;
-    SetReadyState(CLOSED);
+    SetReadyState(ReadyState::CLOSED);
   }
 }
 
 NS_IMETHODIMP
-PresentationSessionTransport::Send(nsIInputStream* aData)
+PresentationTCPSessionTransport::Send(nsIInputStream* aData)
 {
-  if (NS_WARN_IF(mReadyState != OPEN)) {
+  if (NS_WARN_IF(mReadyState != ReadyState::OPEN)) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   mMultiplexStream->AppendStream(aData);
 
   EnsureCopying();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PresentationSessionTransport::Close(nsresult aReason)
+PresentationTCPSessionTransport::Close(nsresult aReason)
 {
   PRES_DEBUG("%s:reason[%x]\n", __func__, aReason);
 
-  if (mReadyState == CLOSED || mReadyState == CLOSING) {
+  if (mReadyState == ReadyState::CLOSED || mReadyState == ReadyState::CLOSING) {
     return NS_OK;
   }
 
   mCloseStatus = aReason;
-  SetReadyState(CLOSING);
+  SetReadyState(ReadyState::CLOSING);
 
   uint32_t count = 0;
   mMultiplexStream->GetCount(&count);
   if (!count) {
     mSocketOutputStream->Close();
   }
 
   mSocketInputStream->Close();
   mDataNotificationEnabled = false;
 
+  mListener = nullptr;
+
   return NS_OK;
 }
 
 void
-PresentationSessionTransport::SetReadyState(ReadyState aReadyState)
+PresentationTCPSessionTransport::SetReadyState(ReadyState aReadyState)
 {
   mReadyState = aReadyState;
 
-  if (mReadyState == OPEN && mCallback) {
+  if (mReadyState == ReadyState::OPEN && mCallback) {
     // Notify the transport channel is ready.
     NS_WARN_IF(NS_FAILED(mCallback->NotifyTransportReady()));
-  } else if (mReadyState == CLOSED && mCallback) {
+  } else if (mReadyState == ReadyState::CLOSED && mCallback) {
     // Notify the transport channel has been shut down.
     NS_WARN_IF(NS_FAILED(mCallback->NotifyTransportClosed(mCloseStatus)));
     mCallback = nullptr;
   }
 }
 
 // nsITransportEventSink
 NS_IMETHODIMP
-PresentationSessionTransport::OnTransportStatus(nsITransport* aTransport,
-                                                nsresult aStatus,
-                                                int64_t aProgress,
-                                                int64_t aProgressMax)
+PresentationTCPSessionTransport::OnTransportStatus(nsITransport* aTransport,
+                                                   nsresult aStatus,
+                                                   int64_t aProgress,
+                                                   int64_t aProgressMax)
 {
   PRES_DEBUG("%s:aStatus[%x]\n", __func__, aStatus);
 
   MOZ_ASSERT(NS_IsMainThread());
 
   if (aStatus != NS_NET_STATUS_CONNECTED_TO) {
     return NS_OK;
   }
 
-  SetReadyState(OPEN);
+  SetReadyState(ReadyState::OPEN);
 
   if (IsReadyToNotifyData()) {
     return CreateInputStreamPump();
   }
 
   return NS_OK;
 }
 
 // nsIInputStreamCallback
 NS_IMETHODIMP
-PresentationSessionTransport::OnInputStreamReady(nsIAsyncInputStream* aStream)
+PresentationTCPSessionTransport::OnInputStreamReady(nsIAsyncInputStream* aStream)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Only used for detecting if the connection was refused.
   uint64_t dummy;
   nsresult rv = aStream->Available(&dummy);
   if (NS_WARN_IF(NS_FAILED(rv))) {
-    if (mReadyState != CLOSED) {
+    if (mReadyState != ReadyState::CLOSED) {
       mCloseStatus = NS_ERROR_CONNECTION_REFUSED;
-      SetReadyState(CLOSED);
+      SetReadyState(ReadyState::CLOSED);
     }
   }
 
   return NS_OK;
 }
 
 // nsIRequestObserver
 NS_IMETHODIMP
-PresentationSessionTransport::OnStartRequest(nsIRequest* aRequest,
-                                             nsISupports* aContext)
+PresentationTCPSessionTransport::OnStartRequest(nsIRequest* aRequest,
+                                                nsISupports* aContext)
 {
   // Do nothing.
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PresentationSessionTransport::OnStopRequest(nsIRequest* aRequest,
-                                            nsISupports* aContext,
-                                            nsresult aStatusCode)
+PresentationTCPSessionTransport::OnStopRequest(nsIRequest* aRequest,
+                                               nsISupports* aContext,
+                                               nsresult aStatusCode)
 {
   PRES_DEBUG("%s:aStatusCode[%x]\n", __func__, aStatusCode);
 
   MOZ_ASSERT(NS_IsMainThread());
 
   uint32_t count;
   nsresult rv = mMultiplexStream->GetCount(&count);
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -472,30 +508,30 @@ PresentationSessionTransport::OnStopRequ
     // If we have some buffered output still, and status is not an error, the
     // other side has done a half-close, but we don't want to be in the close
     // state until we are done sending everything that was buffered. We also
     // don't want to call |NotifyTransportClosed| yet.
     return NS_OK;
   }
 
   // We call this even if there is no error.
-  if (mReadyState != CLOSED) {
+  if (mReadyState != ReadyState::CLOSED) {
     mCloseStatus = aStatusCode;
-    SetReadyState(CLOSED);
+    SetReadyState(ReadyState::CLOSED);
   }
   return NS_OK;
 }
 
 // nsIStreamListener
 NS_IMETHODIMP
-PresentationSessionTransport::OnDataAvailable(nsIRequest* aRequest,
-                                              nsISupports* aContext,
-                                              nsIInputStream* aStream,
-                                              uint64_t aOffset,
-                                              uint32_t aCount)
+PresentationTCPSessionTransport::OnDataAvailable(nsIRequest* aRequest,
+                                                 nsISupports* aContext,
+                                                 nsIInputStream* aStream,
+                                                 uint64_t aOffset,
+                                                 uint32_t aCount)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (NS_WARN_IF(!mCallback)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsCString data;
rename from dom/presentation/PresentationSessionTransport.h
rename to dom/presentation/PresentationTCPSessionTransport.h
--- a/dom/presentation/PresentationSessionTransport.h
+++ b/dom/presentation/PresentationTCPSessionTransport.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_dom_PresentationSessionTransport_h
 #define mozilla_dom_PresentationSessionTransport_h
 
 #include "mozilla/RefPtr.h"
 #include "nsCOMPtr.h"
 #include "nsIAsyncInputStream.h"
 #include "nsIPresentationSessionTransport.h"
+#include "nsIPresentationSessionTransportBuilder.h"
 #include "nsIStreamListener.h"
 #include "nsISupportsImpl.h"
 #include "nsITransport.h"
 
 class nsISocketTransport;
 class nsIInputStreamPump;
 class nsIScriptableInputStream;
 class nsIMultiplexInputStream;
@@ -33,76 +34,82 @@ namespace dom {
  * |PresentationControllingInfo| (sender side) or |PresentationPresentingInfo|
  * (receiver side) in PresentationSessionInfo.cpp.
  *
  * TODO bug 1148307 Implement PresentationSessionTransport with DataChannel.
  * The implementation over the TCP channel is primarily used for the early stage
  * of Presentation API (without SSL) and should be migrated to DataChannel with
  * full support soon.
  */
-class PresentationSessionTransport final : public nsIPresentationSessionTransport
-                                         , public nsITransportEventSink
-                                         , public nsIInputStreamCallback
-                                         , public nsIStreamListener
+class PresentationTCPSessionTransport final : public nsIPresentationSessionTransport
+                                            , public nsIPresentationTCPSessionTransportBuilder
+                                            , public nsITransportEventSink
+                                            , public nsIInputStreamCallback
+                                            , public nsIStreamListener
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PresentationSessionTransport,
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PresentationTCPSessionTransport,
                                            nsIPresentationSessionTransport)
 
   NS_DECL_NSIPRESENTATIONSESSIONTRANSPORT
+  NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTBUILDER
+  NS_DECL_NSIPRESENTATIONTCPSESSIONTRANSPORTBUILDER
   NS_DECL_NSITRANSPORTEVENTSINK
   NS_DECL_NSIINPUTSTREAMCALLBACK
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
 
-  PresentationSessionTransport();
+  PresentationTCPSessionTransport();
 
   void NotifyCopyComplete(nsresult aStatus);
 
 private:
-  ~PresentationSessionTransport();
+  ~PresentationTCPSessionTransport();
 
   nsresult CreateStream();
 
   nsresult CreateInputStreamPump();
 
   void EnsureCopying();
 
-  enum ReadyState {
+  enum class ReadyState {
     CONNECTING,
     OPEN,
     CLOSING,
     CLOSED
   };
 
   void SetReadyState(ReadyState aReadyState);
 
   bool IsReadyToNotifyData()
   {
-    return mDataNotificationEnabled && mReadyState == OPEN;
+    return mDataNotificationEnabled && mReadyState == ReadyState::OPEN;
   }
 
   ReadyState mReadyState;
   bool mAsyncCopierActive;
   nsresult mCloseStatus;
   bool mDataNotificationEnabled;
 
+  uint8_t mType = 0;
+
   // Raw socket streams
   nsCOMPtr<nsISocketTransport> mTransport;
   nsCOMPtr<nsIInputStream> mSocketInputStream;
   nsCOMPtr<nsIOutputStream> mSocketOutputStream;
 
   // Input stream machinery
   nsCOMPtr<nsIInputStreamPump> mInputStreamPump;
   nsCOMPtr<nsIScriptableInputStream> mInputStreamScriptable;
 
   // Output stream machinery
   nsCOMPtr<nsIMultiplexInputStream> mMultiplexStream;
   nsCOMPtr<nsIAsyncStreamCopier> mMultiplexStreamCopier;
 
   nsCOMPtr<nsIPresentationSessionTransportCallback> mCallback;
+  nsCOMPtr<nsIPresentationSessionTransportBuilderListener> mListener;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_PresentationSessionTransport_h
--- a/dom/presentation/interfaces/moz.build
+++ b/dom/presentation/interfaces/moz.build
@@ -10,16 +10,17 @@ XPIDL_SOURCES += [
     'nsIPresentationDeviceManager.idl',
     'nsIPresentationDevicePrompt.idl',
     'nsIPresentationDeviceProvider.idl',
     'nsIPresentationListener.idl',
     'nsIPresentationRequestUIGlue.idl',
     'nsIPresentationService.idl',
     'nsIPresentationSessionRequest.idl',
     'nsIPresentationSessionTransport.idl',
+    'nsIPresentationSessionTransportBuilder.idl',
     'nsITCPPresentationServer.idl',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     XPIDL_SOURCES += [
         'nsIPresentationNetworkHelper.idl',
     ]
 
--- a/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
+++ b/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
@@ -1,64 +1,49 @@
 /* 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 "nsISupports.idl"
 
 interface nsIInputStream;
 interface nsINetAddr;
-interface nsIPresentationChannelDescription;
-interface nsISocketTransport;
 
 %{C++
-#define PRESENTATION_SESSION_TRANSPORT_CONTRACTID \
-  "@mozilla.org/presentation/presentationsessiontransport;1"
+#define PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID \
+  "@mozilla.org/presentation/presentationtcpsessiontransport;1"
 %}
 
 /*
  * The callback for session transport events.
  */
 [scriptable, uuid(9f158786-41a6-4a10-b29b-9497f25d4b67)]
 interface nsIPresentationSessionTransportCallback : nsISupports
 {
   void notifyTransportReady();
   void notifyTransportClosed(in nsresult reason);
   void notifyData(in ACString data);
 };
 
 /*
  * App-to-App transport channel for the presentation session.
  */
-[scriptable, uuid(b6a416cf-03ae-4e74-9cda-88828e8ff418)]
+[scriptable, uuid(7af8556e-e37b-4ca1-a5dd-029567172863)]
 interface nsIPresentationSessionTransport : nsISupports
 {
-  readonly attribute nsINetAddr selfAddress;
+  // Should be set once the underlying session transport is built
+  attribute nsIPresentationSessionTransportCallback callback;
 
-  /*
-   * Initialize the transport channel with an existent socket transport. (This
-   * is primarily used at the sender side.)
-   * @param transport The socket transport.
-   * @param callback The callback for followup notifications.
-   */
-  void initWithSocketTransport(in nsISocketTransport transport,
-                               in nsIPresentationSessionTransportCallback callback);
-
-  /*
-   * Initialize the transport channel with the channel description. (This is
-   * primarily used at the receiver side.)
-   * @param description The channel description.
-   * @param callback The callback for followup notifications.
-   */
-  void initWithChannelDescription(in nsIPresentationChannelDescription description,
-                                  in nsIPresentationSessionTransportCallback callback);
+  // valid for TCP session transport
+  readonly attribute nsINetAddr selfAddress;
 
   /*
    * Enable the notification for incoming data. |notifyData| of
    * |nsIPresentationSessionTransportCallback| can start getting invoked.
+   * Should set callback before |enableDataNotification| is called.
    */
   void enableDataNotification();
 
   /*
    * Send message to the remote endpoint.
    * @param data The message to send.
    */
   void send(in nsIInputStream data);
new file mode 100644
--- /dev/null
+++ b/dom/presentation/interfaces/nsIPresentationSessionTransportBuilder.idl
@@ -0,0 +1,62 @@
+/* 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 "nsISupports.idl"
+
+interface nsIPresentationChannelDescription;
+interface nsISocketTransport;
+interface nsIDOMWindow;
+interface nsIPresentationControlChannel;
+interface nsIPresentationSessionTransport;
+
+[scriptable, uuid(673f6de1-e253-41b8-9be8-b7ff161fa8dc)]
+interface nsIPresentationSessionTransportBuilderListener : nsISupports
+{
+  // Should set |transport.callback| in |onSessionTransport|.
+  void onSessionTransport(in nsIPresentationSessionTransport transport);
+
+  void onError(in nsresult reason);
+};
+
+[scriptable, uuid(2fdbe67d-80f9-48dc-8237-5bef8fa19801)]
+interface nsIPresentationSessionTransportBuilder : nsISupports
+{
+  const unsigned short TYPE_SENDER = 1;
+  const unsigned short TYPE_RECEIVER = 2;
+};
+
+/**
+ * Builder for TCP session transport
+ */
+[scriptable, uuid(cde36d6e-f471-4262-a70d-f932a26b21d9)]
+interface nsIPresentationTCPSessionTransportBuilder : nsIPresentationSessionTransportBuilder
+{
+  /**
+   * The following creation functions will trigger |listener.onSessionTransport|
+   * if the session transport is successfully built, |listener.onError| if some
+   * error occurs during building session transport.
+   */
+  void buildTCPSenderTransport(in nsISocketTransport aTransport,
+                               in nsIPresentationSessionTransportBuilderListener aListener);
+
+  void buildTCPReceiverTransport(in nsIPresentationChannelDescription aDescription,
+                                 in nsIPresentationSessionTransportBuilderListener aListener);
+};
+
+/**
+ * Builder for WebRTC data channel session transport
+ */
+[scriptable, uuid(8131c4e0-3a8c-4bc1-a92a-8431473d2fe8)]
+interface nsIPresentationDataChannelSessionTransportBuilder : nsIPresentationSessionTransportBuilder
+{
+  /**
+   * The following creation function will trigger |listener.onSessionTransport|
+   * if the session transport is successfully built, |listener.onError| if some
+   * error occurs during creating session transport.
+   */
+  void buildDataChannelTransport(in uint8_t aType,
+                                 in nsIDOMWindow aWindow,
+                                 in nsIPresentationControlChannel aControlChannel,
+                                 in nsIPresentationSessionTransportBuilderListener aListener);
+};
--- a/dom/presentation/moz.build
+++ b/dom/presentation/moz.build
@@ -17,34 +17,34 @@ EXPORTS.mozilla.dom += [
     'PresentationAvailability.h',
     'PresentationCallbacks.h',
     'PresentationConnection.h',
     'PresentationDeviceManager.h',
     'PresentationReceiver.h',
     'PresentationRequest.h',
     'PresentationService.h',
     'PresentationSessionInfo.h',
-    'PresentationSessionTransport.h',
+    'PresentationTCPSessionTransport.h',
 ]
 
 UNIFIED_SOURCES += [
     'ipc/PresentationChild.cpp',
     'ipc/PresentationIPCService.cpp',
     'ipc/PresentationParent.cpp',
     'Presentation.cpp',
     'PresentationAvailability.cpp',
     'PresentationCallbacks.cpp',
     'PresentationConnection.cpp',
     'PresentationDeviceManager.cpp',
     'PresentationReceiver.cpp',
     'PresentationRequest.cpp',
     'PresentationService.cpp',
     'PresentationSessionInfo.cpp',
     'PresentationSessionRequest.cpp',
-    'PresentationSessionTransport.cpp',
+    'PresentationTCPSessionTransport.cpp',
 ]
 
 EXTRA_COMPONENTS += [
     'PresentationDeviceInfoManager.js',
     'PresentationDeviceInfoManager.manifest',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
@@ -193,47 +193,57 @@ const mockedDevicePrompt = {
   },
   simulateCancel: function() {
     this._request.cancel();
   }
 };
 
 const mockedSessionTransport = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationSessionTransport,
+                                         Ci.nsIPresentationTCPSessionTransportBuilder,
                                          Ci.nsIFactory]),
   createInstance: function(aOuter, aIID) {
     if (aOuter) {
       throw Components.results.NS_ERROR_NO_AGGREGATION;
     }
     return this.QueryInterface(aIID);
   },
   set callback(callback) {
     this._callback = callback;
   },
   get callback() {
     return this._callback;
   },
   get selfAddress() {
     return this._selfAddress;
   },
-  initWithSocketTransport: function(transport, callback) {
+  buildTCPSenderTransport: function(transport, listener) {
     sendAsyncMessage('data-transport-initialized');
-    this._callback = callback;
+    this._listener = listener;
+    this._type = Ci.nsIPresentationSessionTransportBuilder.TYPE_SENDER;
+
+    this._listener.onSessionTransport(this);
+    this._listener = null;
+
     this.simulateTransportReady();
   },
-  initWithChannelDescription: function(description, callback) {
-    this._callback = callback;
+  buildTCPReceiverTransport: function(description, listener) {
+    this._listener = listener;
+    this._type = Ci.nsIPresentationSessionTransportBuilder.TYPE_RECEIVER;
 
     var addresses = description.QueryInterface(Ci.nsIPresentationChannelDescription).tcpAddress;
     this._selfAddress = {
       QueryInterface: XPCOMUtils.generateQI([Ci.nsINetAddr]),
       address: (addresses.length > 0) ?
                 addresses.queryElementAt(0, Ci.nsISupportsCString).data : "",
       port: description.QueryInterface(Ci.nsIPresentationChannelDescription).tcpPort,
     };
+
+    this._listener.onSessionTransport(this);
+    this._listener = null;
   },
   enableDataNotification: function() {
     sendAsyncMessage('data-transport-notification-enabled');
   },
   send: function(data) {
     var binaryStream = Cc["@mozilla.org/binaryinputstream;1"].
                        createInstance(Ci.nsIBinaryInputStream);
     binaryStream.setInputStream(data);
@@ -297,17 +307,17 @@ const uuidGenerator = Cc["@mozilla.org/u
                       .getService(Ci.nsIUUIDGenerator);
 const originalFactoryData = [];
 originalFactoryData.push(registerMockedFactory("@mozilla.org/presentation-device/prompt;1",
                                                uuidGenerator.generateUUID(),
                                                mockedDevicePrompt));
 originalFactoryData.push(registerMockedFactory("@mozilla.org/network/server-socket;1",
                                                uuidGenerator.generateUUID(),
                                                mockedServerSocket));
-originalFactoryData.push(registerMockedFactory("@mozilla.org/presentation/presentationsessiontransport;1",
+originalFactoryData.push(registerMockedFactory("@mozilla.org/presentation/presentationtcpsessiontransport;1",
                                                uuidGenerator.generateUUID(),
                                                mockedSessionTransport));
 originalFactoryData.push(registerMockedFactory("@mozilla.org/network/manager;1",
                                                uuidGenerator.generateUUID(),
                                                mockedNetworkManager));
 originalFactoryData.push(registerMockedFactory("@mozilla.org/presentation/requestuiglue;1",
                                                uuidGenerator.generateUUID(),
                                                mockedRequestUIGlue));
--- a/dom/presentation/tests/xpcshell/test_presentation_session_transport.js
+++ b/dom/presentation/tests/xpcshell/test_presentation_session_transport.js
@@ -11,16 +11,19 @@ const ServerSocket = CC("@mozilla.org/ne
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 
 var testServer = null;
 var clientTransport = null;
 var serverTransport = null;
 
+var clientBuilder = null;
+var serverBuilder = null;
+
 const clientMessage = "Client Message";
 const serverMessage = "Server Message";
 
 const address = Cc["@mozilla.org/supports-cstring;1"]
                   .createInstance(Ci.nsISupportsCString);
 address.data = "127.0.0.1";
 const addresses = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
 addresses.appendElement(address, false);
@@ -79,46 +82,72 @@ const serverCallback = {
     }
   },
   notifyData: function(aData) {
     Assert.equal(aData, clientMessage, "Server transport receives data.");
     run_next_test();
   },
 };
 
+const clientListener = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationSessionTransportBuilderListener]),
+  onSessionTransport(aTransport) {
+    Assert.ok(true, "Client Transport is built.");
+    clientTransport = aTransport;
+    clientTransport.callback = clientCallback;
+
+    if (serverTransport) {
+      run_next_test();
+    }
+  }
+}
+
+const serverListener = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationSessionTransportBuilderListener]),
+  onSessionTransport(aTransport) {
+    Assert.ok(true, "Server Transport is built.");
+    serverTransport = aTransport;
+    serverTransport.callback = serverCallback;
+    serverTransport.enableDataNotification();
+
+    if (clientTransport) {
+      run_next_test();
+    }
+  }
+}
+
 function TestServer() {
   this.serverSocket = ServerSocket(-1, true, -1);
   this.serverSocket.asyncListen(this)
 }
 
 TestServer.prototype = {
   onSocketAccepted: function(aSocket, aTransport) {
     print("Test server gets a client connection.");
-    serverTransport = Cc["@mozilla.org/presentation/presentationsessiontransport;1"]
-                        .createInstance(Ci.nsIPresentationSessionTransport);
-    serverTransport.initWithSocketTransport(aTransport, serverCallback);
-    serverTransport.enableDataNotification();
+    serverBuilder = Cc["@mozilla.org/presentation/presentationtcpsessiontransport;1"]
+                      .createInstance(Ci.nsIPresentationTCPSessionTransportBuilder);
+    serverBuilder.buildTCPSenderTransport(aTransport, serverListener);
   },
   onStopListening: function(aSocket) {
     print("Test server stops listening.");
   },
   close: function() {
     if (this.serverSocket) {
       this.serverSocket.close();
       this.serverSocket = null;
     }
   }
 };
 
 // Set up the transport connection and ensure |notifyTransportReady| triggered
 // at both sides.
 function setup() {
-  clientTransport = Cc["@mozilla.org/presentation/presentationsessiontransport;1"]
-                      .createInstance(Ci.nsIPresentationSessionTransport);
-  clientTransport.initWithChannelDescription(serverChannelDescription, clientCallback);
+  clientBuilder = Cc["@mozilla.org/presentation/presentationtcpsessiontransport;1"]
+                    .createInstance(Ci.nsIPresentationTCPSessionTransportBuilder);
+  clientBuilder.buildTCPReceiverTransport(serverChannelDescription, clientListener);
 }
 
 // Test |selfAddress| attribute of |nsIPresentationSessionTransport|.
 function selfAddress() {
   var serverSelfAddress = serverTransport.selfAddress;
   Assert.equal(serverSelfAddress.address, address.data, "The self address of server transport should be set.");
   Assert.equal(serverSelfAddress.port, testServer.serverSocket.port, "The port of server transport should be set.");
 
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -258,17 +258,17 @@ static void Shutdown();
 #ifdef MOZ_WIDGET_GONK
 #include "GonkGPSGeolocationProvider.h"
 #endif
 #include "MediaManager.h"
 
 #include "GMPService.h"
 
 #include "mozilla/dom/PresentationDeviceManager.h"
-#include "mozilla/dom/PresentationSessionTransport.h"
+#include "mozilla/dom/PresentationTCPSessionTransport.h"
 
 #include "mozilla/TextInputProcessor.h"
 
 #ifdef MOZ_B2G
 #include "nsIHardwareKeyHandler.h"
 #include "mozilla/HardwareKeyHandler.h"
 #endif
 
@@ -293,17 +293,17 @@ using mozilla::dom::NotificationTelemetr
 #define TRANSFORMIIX_NODESET_CONTRACTID \
 "@mozilla.org/transformiix-nodeset;1"
 
 // PresentationDeviceManager
 /* e1e79dec-4085-4994-ac5b-744b016697e6 */
 #define PRESENTATION_DEVICE_MANAGER_CID \
 { 0xe1e79dec, 0x4085, 0x4994, { 0xac, 0x5b, 0x74, 0x4b, 0x01, 0x66, 0x97, 0xe6 } }
 
-#define PRESENTATION_SESSION_TRANSPORT_CID \
+#define PRESENTATION_TCP_SESSION_TRANSPORT_CID \
 { 0xc9d023f4, 0x6228, 0x4c07, { 0x8b, 0x1d, 0x9c, 0x19, 0x57, 0x3f, 0xaa, 0x27 } }
 
 already_AddRefed<nsIPresentationService> NS_CreatePresentationService();
 
 // Factory Constructor
 NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor)
 NS_GENERIC_FACTORY_CONSTRUCTOR(XPathEvaluator)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init)
@@ -400,17 +400,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(TVChannel
 NS_GENERIC_FACTORY_CONSTRUCTOR(TVProgramData)
 NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationDeviceManager)
 NS_GENERIC_FACTORY_CONSTRUCTOR(TextInputProcessor)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(FakeInputPortService,
                                          InputPortServiceFactory::CreateFakeInputPortService)
 NS_GENERIC_FACTORY_CONSTRUCTOR(InputPortData)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPresentationService,
                                          NS_CreatePresentationService)
-NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationSessionTransport)
+NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationTCPSessionTransport)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NotificationTelemetryService, Init)
 
 #ifndef MOZ_SIMPLEPUSH
 NS_GENERIC_FACTORY_CONSTRUCTOR(PushNotifier)
 #endif
 //-----------------------------------------------------------------------------
 
 static bool gInitialized = false;
@@ -867,17 +867,17 @@ NS_DEFINE_NAMED_CID(TV_PROGRAM_DATA_CID)
 
 NS_DEFINE_NAMED_CID(FAKE_INPUTPORT_SERVICE_CID);
 NS_DEFINE_NAMED_CID(INPUTPORT_DATA_CID);
 
 NS_DEFINE_NAMED_CID(GECKO_MEDIA_PLUGIN_SERVICE_CID);
 
 NS_DEFINE_NAMED_CID(PRESENTATION_SERVICE_CID);
 NS_DEFINE_NAMED_CID(PRESENTATION_DEVICE_MANAGER_CID);
-NS_DEFINE_NAMED_CID(PRESENTATION_SESSION_TRANSPORT_CID);
+NS_DEFINE_NAMED_CID(PRESENTATION_TCP_SESSION_TRANSPORT_CID);
 
 NS_DEFINE_NAMED_CID(TEXT_INPUT_PROCESSOR_CID);
 
 #ifdef MOZ_B2G
 NS_DEFINE_NAMED_CID(NS_HARDWARE_KEY_HANDLER_CID);
 #endif
 
 static nsresult
@@ -1166,17 +1166,17 @@ static const mozilla::Module::CIDEntry k
   { &kTELEPHONY_SERVICE_CID, false, nullptr, nsITelephonyServiceConstructor },
   { &kNS_MOBILE_CONNECTION_SERVICE_CID, false, NULL, nsIMobileConnectionServiceConstructor },
   { &kNS_VOICEMAIL_SERVICE_CID, false, nullptr, nsIVoicemailServiceConstructor },
   { &kTV_TUNER_DATA_CID, false, nullptr, TVTunerDataConstructor },
   { &kTV_CHANNEL_DATA_CID, false, nullptr, TVChannelDataConstructor },
   { &kTV_PROGRAM_DATA_CID, false, nullptr, TVProgramDataConstructor },
   { &kPRESENTATION_SERVICE_CID, false, nullptr, nsIPresentationServiceConstructor },
   { &kPRESENTATION_DEVICE_MANAGER_CID, false, nullptr, PresentationDeviceManagerConstructor },
-  { &kPRESENTATION_SESSION_TRANSPORT_CID, false, nullptr, PresentationSessionTransportConstructor },
+  { &kPRESENTATION_TCP_SESSION_TRANSPORT_CID, false, nullptr, PresentationTCPSessionTransportConstructor },
   { &kTEXT_INPUT_PROCESSOR_CID, false, nullptr, TextInputProcessorConstructor },
   { &kFAKE_INPUTPORT_SERVICE_CID, false, nullptr, FakeInputPortServiceConstructor },
   { &kINPUTPORT_DATA_CID, false, nullptr, InputPortDataConstructor },
 #ifdef MOZ_B2G
   { &kNS_HARDWARE_KEY_HANDLER_CID, false, nullptr, nsIHardwareKeyHandlerConstructor },
 #endif
   { nullptr }
 };
@@ -1335,17 +1335,17 @@ static const mozilla::Module::ContractID
   { TV_TUNER_DATA_CONTRACTID, &kTV_TUNER_DATA_CID },
   { TV_CHANNEL_DATA_CONTRACTID, &kTV_CHANNEL_DATA_CID },
   { TV_PROGRAM_DATA_CONTRACTID, &kTV_PROGRAM_DATA_CID },
   { "@mozilla.org/gecko-media-plugin-service;1",  &kGECKO_MEDIA_PLUGIN_SERVICE_CID },
   { NS_MOBILE_CONNECTION_SERVICE_CONTRACTID, &kNS_MOBILE_CONNECTION_SERVICE_CID },
   { NS_VOICEMAIL_SERVICE_CONTRACTID, &kNS_VOICEMAIL_SERVICE_CID },
   { PRESENTATION_SERVICE_CONTRACTID, &kPRESENTATION_SERVICE_CID },
   { PRESENTATION_DEVICE_MANAGER_CONTRACTID, &kPRESENTATION_DEVICE_MANAGER_CID },
-  { PRESENTATION_SESSION_TRANSPORT_CONTRACTID, &kPRESENTATION_SESSION_TRANSPORT_CID },
+  { PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID, &kPRESENTATION_TCP_SESSION_TRANSPORT_CID },
   { "@mozilla.org/text-input-processor;1", &kTEXT_INPUT_PROCESSOR_CID },
   { FAKE_INPUTPORT_SERVICE_CONTRACTID, &kFAKE_INPUTPORT_SERVICE_CID },
   { INPUTPORT_DATA_CONTRACTID, &kINPUTPORT_DATA_CID },
 #ifdef MOZ_B2G
   { NS_HARDWARE_KEY_HANDLER_CONTRACTID, &kNS_HARDWARE_KEY_HANDLER_CID },
 #endif
   { nullptr }
 };