Bug 1284188 - use nsINetworkInfoService to obtain self IP address. r=smaug. draft
authorShih-Chiang Chien <schien@mozilla.com>
Fri, 12 Aug 2016 15:27:33 +0800
changeset 399861 2aa7c8620505074aeba012de358d56edf0dc2af5
parent 399408 0502bd9e025edde29777ba1de4280f9b52af4663
child 528085 07a11d732756201bdc8fd927beeeafeec95b4047
push id26019
push userschien@mozilla.com
push dateFri, 12 Aug 2016 07:32:07 +0000
reviewerssmaug
bugs1284188
milestone51.0a1
Bug 1284188 - use nsINetworkInfoService to obtain self IP address. r=smaug. MozReview-Commit-ID: 1QwjrkV9cEk
dom/presentation/PresentationSessionInfo.cpp
dom/presentation/PresentationSessionInfo.h
dom/presentation/PresentationTCPSessionTransport.cpp
dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js
dom/presentation/tests/mochitest/PresentationSessionFrameScript.js
dom/presentation/tests/mochitest/mochitest.ini
dom/presentation/tests/mochitest/test_presentation_1ua_connection_wentaway.js
dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.html
dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js
dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver_inproc.html
dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver_oop.html
dom/presentation/tests/mochitest/test_presentation_terminate.js
dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -643,32 +643,25 @@ PresentationControllingInfo::GetAddress(
   RefPtr<PresentationNetworkHelper> networkHelper =
     new PresentationNetworkHelper(this,
                                   &PresentationControllingInfo::OnGetAddress);
   nsresult rv = networkHelper->GetWifiIPAddress();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-#elif defined(MOZ_MULET)
-  // In simulator,we need to use the "127.0.0.1" as target address.
-  NS_DispatchToMainThread(
-    NewRunnableMethod<nsCString>(
-      this,
-      &PresentationControllingInfo::OnGetAddress,
-      "127.0.0.1"));
+#else
+  nsCOMPtr<nsINetworkInfoService> networkInfo = do_GetService(NETWORKINFOSERVICE_CONTRACT_ID);
+  MOZ_ASSERT(networkInfo);
 
-#else
-  // TODO Get host IP via other platforms.
+  nsresult rv = networkInfo->ListNetworkAddresses(this);
 
-  NS_DispatchToMainThread(
-    NewRunnableMethod<nsCString>(
-      this,
-      &PresentationControllingInfo::OnGetAddress,
-      EmptyCString()));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 #endif
 
   return NS_OK;
 }
 
 nsresult
 PresentationControllingInfo::OnGetAddress(const nsACString& aAddress)
 {
@@ -947,16 +940,60 @@ PresentationControllingInfo::Reconnect(n
   rv = mControlChannel->Reconnect(mSessionId, GetUrl());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return mReconnectCallback->NotifyError(rv);
   }
 
   return NS_OK;
 }
 
+// nsIListNetworkAddressesListener
+NS_IMETHODIMP
+PresentationControllingInfo::OnListedNetworkAddresses(const char** aAddressArray,
+                                                      uint32_t aAddressArraySize)
+{
+  if (!aAddressArraySize) {
+    return OnListNetworkAddressesFailed();
+  }
+
+  // TODO bug 1228504 Take all IP addresses in PresentationChannelDescription
+  // into account. And at the first stage Presentation API is only exposed on
+  // Firefox OS where the first IP appears enough for most scenarios.
+
+  nsAutoCString ip;
+  ip.Assign(aAddressArray[0]);
+
+  // On Firefox desktop, the IP address is retrieved from a callback function.
+  // To make consistent code sequence, following function call is dispatched
+  // into main thread instead of calling it directly.
+  NS_DispatchToMainThread(
+    NewRunnableMethod<nsCString>(
+      this,
+      &PresentationControllingInfo::OnGetAddress,
+      ip));
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PresentationControllingInfo::OnListNetworkAddressesFailed()
+{
+  PRES_ERROR("PresentationControllingInfo:OnListNetworkAddressesFailed");
+
+  // In 1-UA case, transport channel can still be established
+  // on loopback interface even if no network address available.
+  NS_DispatchToMainThread(
+    NewRunnableMethod<nsCString>(
+      this,
+      &PresentationControllingInfo::OnGetAddress,
+      "127.0.0.1"));
+
+  return NS_OK;
+}
+
 /**
  * Implementation of PresentationPresentingInfo
  *
  * During presentation session establishment, the receiver expects the following
  * after trying to launch the app by notifying "presentation-launch-receiver":
  * (The order between step 2 and 3 is not guaranteed.)
  * 1. |Observe| of |nsIObserver| is called with "presentation-receiver-launched".
  *    Then start listen to document |STATE_TRANSFERRING| event.
--- a/dom/presentation/PresentationSessionInfo.h
+++ b/dom/presentation/PresentationSessionInfo.h
@@ -8,16 +8,17 @@
 #define mozilla_dom_PresentationSessionInfo_h
 
 #include "base/process.h"
 #include "mozilla/dom/nsIContentParent.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/RefPtr.h"
 #include "nsCOMPtr.h"
+#include "nsINetworkInfoService.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"
@@ -166,21 +167,23 @@ protected:
   nsCOMPtr<nsIPresentationSessionTransport> mTransport;
   nsCOMPtr<nsIPresentationControlChannel> mControlChannel;
   nsCOMPtr<nsIPresentationSessionTransportBuilder> mBuilder;
 };
 
 // Session info with controlling browsing context (sender side) behaviors.
 class PresentationControllingInfo final : public PresentationSessionInfo
                                         , public nsIServerSocketListener
+                                        , public nsIListNetworkAddressesListener
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIPRESENTATIONCONTROLCHANNELLISTENER
   NS_DECL_NSISERVERSOCKETLISTENER
+  NS_DECL_NSILISTNETWORKADDRESSESLISTENER
 
   PresentationControllingInfo(const nsAString& aUrl,
                               const nsAString& aSessionId)
     : PresentationSessionInfo(aUrl,
                               aSessionId,
                               nsIPresentationService::ROLE_CONTROLLER)
   {}
 
--- a/dom/presentation/PresentationTCPSessionTransport.cpp
+++ b/dom/presentation/PresentationTCPSessionTransport.cpp
@@ -323,16 +323,22 @@ PresentationTCPSessionTransport::GetCall
   callback.forget(aCallback);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationTCPSessionTransport::SetCallback(nsIPresentationSessionTransportCallback* aCallback)
 {
   mCallback = aCallback;
+
+  if (!!mCallback && ReadyState::OPEN == mReadyState) {
+    // Notify the transport channel is ready.
+    NS_WARN_IF(NS_FAILED(mCallback->NotifyTransportReady()));
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationTCPSessionTransport::GetSelfAddress(nsINetAddr** aSelfAddress)
 {
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
@@ -369,17 +369,17 @@ function tearDown() {
   mockedDevicePrompt.request = null;
   mockedSessionTransport.callback = null;
 
   var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
                       .getService(Ci.nsIPresentationDeviceManager);
   deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener).removeDevice(mockedDevice);
 
   // Register original factories.
-  for (var data in originalFactoryData) {
+  for (var data of originalFactoryData) {
     registerOriginalFactory(data.contractId, data.mockedClassId,
                             data.mockedFactory, data.originalClassId,
                             data.originalFactory);
   }
 
   sendAsyncMessage('teardown-complete');
 }
 
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js
@@ -3,163 +3,29 @@
  * 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/. */
 
 'use strict';
 
 const { classes: Cc, interfaces: Ci, manager: Cm, utils: Cu, results: Cr } = Components;
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
 
 const uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
                       .getService(Ci.nsIUUIDGenerator);
 
 function debug(str) {
   // dump('DEBUG -*- PresentationSessionChromeScript1UA -*-: ' + str + '\n');
 }
 
 const originalFactoryData = [];
 var sessionId; // Store the uuid generated by PresentationRequest.
-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);
 var triggerControlChannelError = false; // For simulating error during control channel establishment.
 
-function mockChannelDescription(role) {
-  this.QueryInterface = XPCOMUtils.generateQI([Ci.nsIPresentationChannelDescription]);
-  this.role = role;
-  this.type = Ci.nsIPresentationChannelDescription.TYPE_TCP;
-  this.tcpAddress = addresses;
-  this.tcpPort = (role === 'sender' ? 1234 : 4321); // either sender or receiver
-}
-
-const mockChannelDescriptionOfSender   = new mockChannelDescription('sender');
-const mockChannelDescriptionOfReceiver = new mockChannelDescription('receiver');
-
-const mockServerSocket = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIServerSocket,
-                                         Ci.nsIFactory]),
-  createInstance: function(aOuter, aIID) {
-    if (aOuter) {
-      throw Components.results.NS_ERROR_NO_AGGREGATION;
-    }
-    return this.QueryInterface(aIID);
-  },
-  get port() {
-    return this._port;
-  },
-  set listener(listener) {
-    this._listener = listener;
-  },
-  init: function(port, loopbackOnly, backLog) {
-    this._port = (port == -1 ? 5678 : port);
-  },
-  asyncListen: function(listener) {
-    this._listener = listener;
-  },
-  close: function() {
-    this._listener.onStopListening(this, Cr.NS_BINDING_ABORTED);
-  },
-  onSocketAccepted: function(serverSocket, socketTransport) {
-    this._listener.onSocketAccepted(serverSocket, socketTransport);
-  }
-};
-
-// mockSessionTransport
-var mockSessionTransportOfSender   = undefined;
-var mockSessionTransportOfReceiver = undefined;
-
-function mockSessionTransport() {}
-
-mockSessionTransport.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationSessionTransport,
-                                         Ci.nsIPresentationTCPSessionTransportBuilder]),
-  set callback(callback) {
-    this._callback = callback;
-  },
-  get callback() {
-    return this._callback;
-  },
-  get selfAddress() {
-    return this._selfAddress;
-  },
-  buildTCPSenderTransport: function(transport, listener) {
-    mockSessionTransportOfSender = this;
-    this._listener = listener;
-    this._role = Ci.nsIPresentationService.ROLE_CONTROLLER;
-
-    this._listener.onSessionTransport(this);
-    this._listener = null;
-    this.simulateTransportReady();
-  },
-  buildTCPReceiverTransport: function(description, listener) {
-    mockSessionTransportOfReceiver = this;
-    this._listener = listener;
-    this._role = Ci.nsIPresentationService.ROLE_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() {
-  },
-  send: function(data) {
-    debug('Send message: ' + data);
-    if (this._role === Ci.nsIPresentationService.ROLE_CONTROLLER) {
-      mockSessionTransportOfReceiver._callback.notifyData(data);
-    }
-    if (this._role === Ci.nsIPresentationService.ROLE_RECEIVER) {
-      mockSessionTransportOfSender._callback.notifyData(data);
-    }
-  },
-  close: function(reason) {
-    sendAsyncMessage('data-transport-closed', reason);
-    this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportClosed(reason);
-    if (this._role === Ci.nsIPresentationService.ROLE_CONTROLLER) {
-      if (mockSessionTransportOfReceiver._callback) {
-        mockSessionTransportOfReceiver._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportClosed(reason);
-      }
-    }
-    else if (this._role === Ci.nsIPresentationService.ROLE_RECEIVER) {
-      if (mockSessionTransportOfSender._callback) {
-        mockSessionTransportOfSender._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportClosed(reason);
-      }
-    }
-  },
-  simulateTransportReady: function() {
-    this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportReady();
-  },
-};
-
-const mockSessionTransportFactory = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]),
-  createInstance: function(aOuter, aIID) {
-    if (aOuter) {
-      throw Components.results.NS_ERROR_NO_AGGREGATION;
-    }
-    var result = new mockSessionTransport();
-    return result.QueryInterface(aIID);
-  }
-}
-
-const mockSocketTransport = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISocketTransport]),
-};
-
 // control channel of sender
 const mockControlChannelOfSender = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
   set listener(listener) {
     // PresentationControllingInfo::SetControlChannel
     if (listener) {
       debug('set listener for mockControlChannelOfSender without null');
     } else {
@@ -178,17 +44,19 @@ const mockControlChannelOfSender = {
   },
   notifyReconnected: function() {
     // send offer after notifyOpened immediately
     this._listener
         .QueryInterface(Ci.nsIPresentationControlChannelListener)
         .notifyReconnected();
   },
   sendOffer: function(offer) {
-    sendAsyncMessage('offer-sent');
+    Services.tm.mainThread.dispatch(() => {
+      mockControlChannelOfReceiver.onOffer(offer);
+    }, Ci.nsIThread.DISPATCH_NORMAL);
   },
   onAnswer: function(answer) {
     this._listener
         .QueryInterface(Ci.nsIPresentationControlChannelListener)
         .onAnswer(answer);
   },
   launch: function(presentationId, url) {
     sessionId = presentationId;
@@ -242,20 +110,19 @@ const mockControlChannelOfReceiver = {
         .notifyConnected();
   },
   onOffer: function(offer) {
     this._listener
         .QueryInterface(Ci.nsIPresentationControlChannelListener)
         .onOffer(offer);
   },
   sendAnswer: function(answer) {
-    this._listener
-        .QueryInterface(Ci.nsIPresentationSessionTransportCallback)
-        .notifyTransportReady();
-    sendAsyncMessage('answer-sent');
+    Services.tm.mainThread.dispatch(() => {
+      mockControlChannelOfSender.onAnswer(answer);
+    }, Ci.nsIThread.DISPATCH_NORMAL);
   },
   disconnect: function(reason) {
     if (!this._listener) {
       return;
     }
 
     this._listener
         .QueryInterface(Ci.nsIPresentationControlChannelListener)
@@ -354,22 +221,16 @@ function initMockAndListener() {
              originalFactory: originalFactory };
   }
   // Register mock factories.
   const uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
                         .getService(Ci.nsIUUIDGenerator);
   originalFactoryData.push(registerMockFactory("@mozilla.org/presentation-device/prompt;1",
                                                uuidGenerator.generateUUID(),
                                                mockDevicePrompt));
-  originalFactoryData.push(registerMockFactory("@mozilla.org/network/server-socket;1",
-                                               uuidGenerator.generateUUID(),
-                                               mockServerSocket));
-  originalFactoryData.push(registerMockFactory("@mozilla.org/presentation/presentationtcpsessiontransport;1",
-                                               uuidGenerator.generateUUID(),
-                                               mockSessionTransportFactory));
   originalFactoryData.push(registerMockFactory("@mozilla.org/presentation/requestuiglue;1",
                                                uuidGenerator.generateUUID(),
                                                mockRequestUIGlue));
 
   addMessageListener('trigger-device-add', function() {
     debug('Got message: trigger-device-add');
     var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
                         .getService(Ci.nsIPresentationDeviceManager);
@@ -422,27 +283,16 @@ function initMockAndListener() {
                           .getService(Ci.nsIPresentationDeviceManager);
     deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener)
                  .onReconnectRequest(mockDevice,
                                      url,
                                      sessionId,
                                      mockControlChannelOfReceiver);
   });
 
-  addMessageListener('trigger-on-offer', function() {
-    debug('Got message: trigger-on-offer');
-    mockControlChannelOfReceiver.onOffer(mockChannelDescriptionOfSender);
-    mockServerSocket.onSocketAccepted(mockServerSocket, mockSocketTransport);
-  });
-
-  addMessageListener('trigger-on-answer', function() {
-    debug('Got message: trigger-on-answer');
-    mockControlChannelOfSender.onAnswer(mockChannelDescriptionOfReceiver);
-  });
-
   // Used to call sendAsyncMessage in chrome script from receiver.
   addMessageListener('forward-command', function(command_data) {
     let command = JSON.parse(command_data);
     sendAsyncMessage(command.name, command.data);
   });
 
   addMessageListener('teardown', teardown);
 
@@ -454,35 +304,33 @@ function initMockAndListener() {
     sendAsyncMessage('promise-setup-ready');
   }, 'setup-request-promise', false);
 }
 
 function teardown() {
 
   function registerOriginalFactory(contractId, mockedClassId, mockedFactory, originalClassId, originalFactory) {
     if (originalFactory) {
+      var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
       registrar.unregisterFactory(mockedClassId, mockedFactory);
       registrar.registerFactory(originalClassId, "", contractId, originalFactory);
     }
   }
 
   mockRequestUIGlue.promise               = null;
-  mockServerSocket.listener               = null;
-  mockSessionTransportOfSender.callback   = null;
-  mockSessionTransportOfReceiver.callback = null;
   mockControlChannelOfSender.listener     = null;
   mockControlChannelOfReceiver.listener   = null;
   mockDevicePrompt.request                = null;
 
   var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
                       .getService(Ci.nsIPresentationDeviceManager);
   deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener)
                .removeDevice(mockDevice);
   // Register original factories.
-  for (var data in originalFactoryData) {
+  for (var data of originalFactoryData) {
     registerOriginalFactory(data.contractId, data.mockClassId,
                             data.mockFactory, data.originalClassId,
                             data.originalFactory);
   }
   sendAsyncMessage('teardown-complete');
 }
 
 initMockAndListener();
--- a/dom/presentation/tests/mochitest/PresentationSessionFrameScript.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionFrameScript.js
@@ -152,17 +152,17 @@ function loadPrivilegedScriptTest() {
     }
   };
 
 
   function tearDown() {
     mockedSessionTransport.callback = null;
 
     /* Register original factories. */
-    for (var data in originalFactoryData) {
+    for (var data of originalFactoryData) {
       registerOriginalFactory(data.contractId, data.mockedClassId,
                               data.mockedFactory, data.originalClassId,
                               data.originalFactory);
     }
     sendMessage("teardown-complete");
   }
 
 
--- a/dom/presentation/tests/mochitest/mochitest.ini
+++ b/dom/presentation/tests/mochitest/mochitest.ini
@@ -1,15 +1,16 @@
 [DEFAULT]
 support-files =
   PresentationDeviceInfoChromeScript.js
   PresentationSessionChromeScript.js
   PresentationSessionFrameScript.js
   PresentationSessionChromeScript1UA.js
   file_presentation_1ua_receiver.html
+  test_presentation_1ua_sender_and_receiver.js
   file_presentation_non_receiver_inner_iframe.html
   file_presentation_non_receiver.html
   file_presentation_receiver.html
   file_presentation_receiver_establish_connection_error.html
   file_presentation_receiver_inner_iframe.html
   file_presentation_1ua_wentaway.html
   test_presentation_1ua_connection_wentaway.js
   file_presentation_receiver_auxiliary_navigation.html
@@ -24,17 +25,17 @@ support-files =
   file_presentation_unknown_content_type.test^headers^
   test_presentation_tcp_receiver_establish_connection_unknown_content_type.js
 
 [test_presentation_dc_sender.html]
 [test_presentation_dc_receiver.html]
 skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
 [test_presentation_dc_receiver_oop.html]
 skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
-[test_presentation_1ua_sender_and_receiver.html]
+[test_presentation_1ua_sender_and_receiver_inproc.html]
 skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
 [test_presentation_1ua_sender_and_receiver_oop.html]
 skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
 [test_presentation_1ua_connection_wentaway_inproc.html]
 skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
 [test_presentation_1ua_connection_wentaway_oop.html]
 skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
 [test_presentation_device_info_permission.html]
--- a/dom/presentation/tests/mochitest/test_presentation_1ua_connection_wentaway.js
+++ b/dom/presentation/tests/mochitest/test_presentation_1ua_connection_wentaway.js
@@ -79,28 +79,16 @@ function setup() {
 
   gScript.addMessageListener('promise-setup-ready', function promiseSetupReadyHandler() {
     debug('Got message: promise-setup-ready');
     gScript.removeMessageListener('promise-setup-ready',
                                   promiseSetupReadyHandler);
     gScript.sendAsyncMessage('trigger-on-session-request', receiverUrl);
   });
 
-  gScript.addMessageListener('offer-sent', function offerSentHandler() {
-    debug('Got message: offer-sent');
-    gScript.removeMessageListener('offer-sent', offerSentHandler);
-    gScript.sendAsyncMessage('trigger-on-offer');
-  });
-
-  gScript.addMessageListener('answer-sent', function answerSentHandler() {
-    debug('Got message: answer-sent');
-    gScript.removeMessageListener('answer-sent', answerSentHandler);
-    gScript.sendAsyncMessage('trigger-on-answer');
-  });
-
   return Promise.resolve();
 }
 
 function testCreateRequest() {
   return new Promise(function(aResolve, aReject) {
     info('Sender: --- testCreateRequest ---');
     request = new PresentationRequest(receiverUrl);
     request.getAvailability().then((aAvailability) => {
deleted file mode 100644
--- a/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.html
+++ /dev/null
@@ -1,329 +0,0 @@
-<!DOCTYPE HTML>
-<!-- vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: -->
-<html>
-  <!-- Any copyright is dedicated to the Public Domain.
-    - http://creativecommons.org/publicdomain/zero/1.0/ -->
-  <head>
-    <meta charset="utf-8">
-    <title>Test for B2G Presentation API when sender and receiver at the same side</title>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-    <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  </head>
-  <body>
-    <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1234492">
-      Test for B2G Presentation API when sender and receiver at the same side</a>
-    <script type="application/javascript;version=1.8">
-
-'use strict';
-
-function debug(str) {
-  // info(str);
-}
-
-var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript1UA.js'));
-var receiverUrl = SimpleTest.getTestFileURL('file_presentation_1ua_receiver.html');
-var request;
-var connection;
-var receiverIframe;
-var presentationId;
-
-function postMessageToIframe(aType) {
-  receiverIframe.src = receiverUrl + "#" +
-                       encodeURIComponent(JSON.stringify({ type: aType }));
-}
-
-function setup() {
-
-  gScript.addMessageListener('device-prompt', function devicePromptHandler() {
-    debug('Got message: device-prompt');
-    gScript.removeMessageListener('device-prompt', devicePromptHandler);
-    gScript.sendAsyncMessage('trigger-device-prompt-select');
-  });
-
-  gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
-    gScript.removeMessageListener('control-channel-established',
-                                  controlChannelEstablishedHandler);
-    gScript.sendAsyncMessage("trigger-control-channel-open");
-  });
-
-  gScript.addMessageListener('sender-launch', function senderLaunchHandler(url) {
-    debug('Got message: sender-launch');
-    gScript.removeMessageListener('sender-launch', senderLaunchHandler);
-    is(url, receiverUrl, 'Receiver: should receive the same url');
-    receiverIframe = document.createElement('iframe');
-    receiverIframe.setAttribute('src', receiverUrl);
-    receiverIframe.setAttribute("mozbrowser", "true");
-    receiverIframe.setAttribute("mozpresentation", receiverUrl);
-
-    // This event is triggered when the iframe calls "alert".
-    receiverIframe.addEventListener("mozbrowsershowmodalprompt", function receiverListener(evt) {
-      var message = evt.detail.message;
-      debug('Got iframe message: ' + message);
-      if (/^OK /.exec(message)) {
-        ok(true, message.replace(/^OK /, ""));
-      } else if (/^KO /.exec(message)) {
-        ok(false, message.replace(/^KO /, ""));
-      } else if (/^INFO /.exec(message)) {
-        info(message.replace(/^INFO /, ""));
-      } else if (/^COMMAND /.exec(message)) {
-        var command = JSON.parse(message.replace(/^COMMAND /, ""));
-        gScript.sendAsyncMessage(command.name, command.data);
-      } else if (/^DONE$/.exec(message)) {
-        receiverIframe.removeEventListener("mozbrowsershowmodalprompt",
-                                            receiverListener);
-      }
-    }, false);
-
-    var promise = new Promise(function(aResolve, aReject) {
-      document.body.appendChild(receiverIframe);
-      aResolve(receiverIframe);
-    });
-
-    var obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
-                           .getService(SpecialPowers.Ci.nsIObserverService);
-    obs.notifyObservers(promise, 'setup-request-promise', null);
-  });
-
-  gScript.addMessageListener('promise-setup-ready', function promiseSetupReadyHandler() {
-    debug('Got message: promise-setup-ready');
-    gScript.removeMessageListener('promise-setup-ready', promiseSetupReadyHandler);
-    gScript.sendAsyncMessage('trigger-on-session-request', receiverUrl);
-  });
-
-  gScript.addMessageListener('offer-sent', function offerSentHandler() {
-    debug('Got message: offer-sent');
-    gScript.removeMessageListener('offer-sent', offerSentHandler);
-    gScript.sendAsyncMessage('trigger-on-offer');
-  });
-
-  gScript.addMessageListener('answer-sent', function answerSentHandler() {
-    debug('Got message: answer-sent');
-    gScript.removeMessageListener('answer-sent', answerSentHandler);
-    gScript.sendAsyncMessage('trigger-on-answer');
-  });
-
-  return Promise.resolve();
-}
-
-function testCreateRequest() {
-  return new Promise(function(aResolve, aReject) {
-    info('Sender: --- testCreateRequest ---');
-    request = new PresentationRequest("file_presentation_1ua_receiver.html");
-    request.getAvailability().then((aAvailability) => {
-      aAvailability.onchange = function() {
-        aAvailability.onchange = null;
-        ok(aAvailability.value, "Sender: Device should be available.");
-        aResolve();
-      }
-    }).catch((aError) => {
-      ok(false, "Sender: Error occurred when getting availability: " + aError);
-      teardown();
-      aReject();
-    });
-
-    gScript.sendAsyncMessage('trigger-device-add');
-  });
-}
-
-function testStartConnection() {
-  return new Promise(function(aResolve, aReject) {
-    request.start().then((aConnection) => {
-      connection = aConnection;
-      ok(connection, "Sender: Connection should be available.");
-      ok(connection.id, "Sender: Connection ID should be set.");
-      is(connection.state, "connecting", "The initial state should be connecting.");
-      is(connection.url, receiverUrl, "request URL should be expanded to absolute URL");
-      connection.onconnect = function() {
-        connection.onconnect = null;
-        is(connection.state, "connected", "Connection should be connected.");
-        presentationId = connection.id;
-        aResolve();
-      };
-    }).catch((aError) => {
-      ok(false, "Sender: Error occurred when establishing a connection: " + aError);
-      teardown();
-      aReject();
-    });
-  });
-}
-
-function testSendMessage() {
-  return new Promise(function(aResolve, aReject) {
-    info('Sender: --- testSendMessage ---');
-    gScript.addMessageListener('trigger-message-from-sender', function triggerMessageFromSenderHandler() {
-      debug('Got message: trigger-message-from-sender');
-      gScript.removeMessageListener('trigger-message-from-sender', triggerMessageFromSenderHandler);
-      info('Send message to receiver');
-      connection.send('msg-sender-to-receiver');
-    });
-
-    gScript.addMessageListener('message-from-sender-received', function messageFromSenderReceivedHandler() {
-      debug('Got message: message-from-sender-received');
-      gScript.removeMessageListener('message-from-sender-received', messageFromSenderReceivedHandler);
-      aResolve();
-    });
-  });
-}
-
-function testIncomingMessage() {
-  return new Promise(function(aResolve, aReject) {
-    info('Sender: --- testIncomingMessage ---');
-    connection.addEventListener('message', function messageHandler(evt) {
-      connection.removeEventListener('message', messageHandler);
-      let msg = evt.data;
-      is(msg, "msg-receiver-to-sender", "Sender: Sender should receive message from Receiver");
-      postMessageToIframe('message-from-receiver-received');
-      aResolve();
-    });
-    postMessageToIframe('trigger-message-from-receiver');
-  });
-}
-
-function testCloseConnection() {
-  info('Sender: --- testCloseConnection ---');
-  // Test terminate immediate after close.
-  function controlChannelEstablishedHandler()
-  {
-    gScript.removeMessageListener('control-channel-established',
-                                  controlChannelEstablishedHandler);
-    ok(false, "terminate after close should do nothing");
-  }
-  gScript.addMessageListener('ready-to-close', function onReadyToClose() {
-    gScript.removeMessageListener('ready-to-close', onReadyToClose);
-    connection.close();
-
-    gScript.addMessageListener('control-channel-established', controlChannelEstablishedHandler);
-    connection.terminate();
-  });
-
-  return Promise.all([
-    new Promise(function(aResolve, aReject) {
-      connection.onclose = function() {
-        connection.onclose = null;
-        is(connection.state, 'closed', 'Sender: Connection should be closed.');
-        gScript.removeMessageListener('control-channel-established',
-                                      controlChannelEstablishedHandler);
-        aResolve();
-      };
-    }),
-    new Promise(function(aResolve, aReject) {
-      gScript.addMessageListener('receiver-closed', function onReceiverClosed() {
-        gScript.removeMessageListener('receiver-closed', onReceiverClosed);
-        gScript.removeMessageListener('control-channel-established',
-                                      controlChannelEstablishedHandler);
-        aResolve();
-      });
-    }),
-  ]);
-}
-
-function testTerminateAfterClose() {
-  info('Sender: --- testTerminateAfterClose ---');
-  return Promise.race([
-      new Promise(function(aResolve, aReject) {
-        connection.onterminate = function() {
-          connection.onterminate = null;
-          ok(false, 'terminate after close should do nothing');
-          aResolve();
-        };
-        connection.terminate();
-      }),
-      new Promise(function(aResolve, aReject) {
-        setTimeout(function() {
-          is(connection.state, 'closed', 'Sender: Connection should be closed.');
-          aResolve();
-        }, 3000);
-      }),
-  ]);
-}
-
-function testReconnect() {
-  return new Promise(function(aResolve, aReject) {
-    info('Sender: --- testReconnect ---');
-    gScript.addMessageListener('control-channel-established', function controlChannelEstablished() {
-      gScript.removeMessageListener('control-channel-established', controlChannelEstablished);
-      gScript.sendAsyncMessage("trigger-control-channel-open");
-    });
-
-    gScript.addMessageListener('start-reconnect', function startReconnectHandler(url) {
-      debug('Got message: start-reconnect');
-      gScript.removeMessageListener('start-reconnect', startReconnectHandler);
-      is(url, receiverUrl, "URLs should be the same.")
-      gScript.sendAsyncMessage('trigger-reconnected-acked', url);
-    });
-
-    gScript.addMessageListener('offer-sent', function offerSentHandler() {
-      debug('Got message: offer-sent');
-      gScript.removeMessageListener('offer-sent', offerSentHandler);
-      gScript.sendAsyncMessage('trigger-on-offer');
-    });
-
-    gScript.addMessageListener('answer-sent', function answerSentHandler() {
-      debug('Got message: answer-sent');
-      gScript.removeMessageListener('answer-sent', answerSentHandler);
-      gScript.sendAsyncMessage('trigger-on-answer');
-    });
-
-    gScript.addMessageListener('ready-to-reconnect', function onReadyToReconnect() {
-      gScript.removeMessageListener('ready-to-reconnect', onReadyToReconnect);
-      request.reconnect(presentationId).then((aConnection) => {
-        connection = aConnection;
-        ok(connection, "Sender: Connection should be available.");
-        is(connection.id, presentationId, "The presentationId should be the same.");
-        is(connection.state, "connecting", "The initial state should be connecting.");
-        connection.onconnect = function() {
-          connection.onconnect = null;
-          is(connection.state, "connected", "Connection should be connected.");
-          aResolve();
-        };
-      }).catch((aError) => {
-        ok(false, "Sender: Error occurred when establishing a connection: " + aError);
-        teardown();
-        aReject();
-      });
-    });
-  });
-}
-
-function teardown() {
-  gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
-    debug('Got message: teardown-complete');
-    gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
-    gScript.destroy();
-    SimpleTest.finish();
-  });
-
-  gScript.sendAsyncMessage('teardown');
-}
-
-function runTests() {
-  setup().then(testCreateRequest)
-         .then(testStartConnection)
-         .then(testSendMessage)
-         .then(testIncomingMessage)
-         .then(testCloseConnection)
-         .then(testReconnect)
-         .then(testCloseConnection)
-         .then(testTerminateAfterClose)
-         .then(teardown);
-}
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.requestFlakyTimeout('Test for guarantee not firing async event');
-SpecialPowers.pushPermissions([
-  {type: 'presentation-device-manage', allow: false, context: document},
-  {type: 'presentation', allow: true, context: document},
-  {type: "browser", allow: true, context: document},
-], () => {
-  SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
-                                      /* Mocked TCP session transport builder in the test */
-                                      ["dom.presentation.session_transport.data_channel.enable", false],
-                                      ["dom.presentation.test.enabled", true],
-                                      ["dom.presentation.test.stage", 0],
-                                      ["dom.mozBrowserFramesEnabled", true]]},
-                            runTests);
-});
-
-    </script>
-  </body>
-</html>
new file mode 100644
--- /dev/null
+++ b/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js
@@ -0,0 +1,292 @@
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* 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/. */
+
+'use strict';
+
+function debug(str) {
+  // info(str);
+}
+
+var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript1UA.js'));
+var receiverUrl = SimpleTest.getTestFileURL('file_presentation_1ua_receiver.html');
+var request;
+var connection;
+var receiverIframe;
+var presentationId;
+
+function postMessageToIframe(aType) {
+  receiverIframe.src = receiverUrl + "#" +
+                       encodeURIComponent(JSON.stringify({ type: aType }));
+}
+
+function setup() {
+
+  gScript.addMessageListener('device-prompt', function devicePromptHandler() {
+    debug('Got message: device-prompt');
+    gScript.removeMessageListener('device-prompt', devicePromptHandler);
+    gScript.sendAsyncMessage('trigger-device-prompt-select');
+  });
+
+  gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
+    gScript.removeMessageListener('control-channel-established',
+                                  controlChannelEstablishedHandler);
+    gScript.sendAsyncMessage("trigger-control-channel-open");
+  });
+
+  gScript.addMessageListener('sender-launch', function senderLaunchHandler(url) {
+    debug('Got message: sender-launch');
+    gScript.removeMessageListener('sender-launch', senderLaunchHandler);
+    is(url, receiverUrl, 'Receiver: should receive the same url');
+    receiverIframe = document.createElement('iframe');
+    receiverIframe.setAttribute('src', receiverUrl);
+    receiverIframe.setAttribute("mozbrowser", "true");
+    receiverIframe.setAttribute("mozpresentation", receiverUrl);
+    var oop = location.pathname.indexOf('_inproc') == -1;
+    receiverIframe.setAttribute("remote", oop);
+
+    // This event is triggered when the iframe calls "alert".
+    receiverIframe.addEventListener("mozbrowsershowmodalprompt", function receiverListener(evt) {
+      var message = evt.detail.message;
+      debug('Got iframe message: ' + message);
+      if (/^OK /.exec(message)) {
+        ok(true, message.replace(/^OK /, ""));
+      } else if (/^KO /.exec(message)) {
+        ok(false, message.replace(/^KO /, ""));
+      } else if (/^INFO /.exec(message)) {
+        info(message.replace(/^INFO /, ""));
+      } else if (/^COMMAND /.exec(message)) {
+        var command = JSON.parse(message.replace(/^COMMAND /, ""));
+        gScript.sendAsyncMessage(command.name, command.data);
+      } else if (/^DONE$/.exec(message)) {
+        receiverIframe.removeEventListener("mozbrowsershowmodalprompt",
+                                            receiverListener);
+      }
+    }, false);
+
+    var promise = new Promise(function(aResolve, aReject) {
+      document.body.appendChild(receiverIframe);
+      aResolve(receiverIframe);
+    });
+
+    var obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
+                           .getService(SpecialPowers.Ci.nsIObserverService);
+    obs.notifyObservers(promise, 'setup-request-promise', null);
+  });
+
+  gScript.addMessageListener('promise-setup-ready', function promiseSetupReadyHandler() {
+    debug('Got message: promise-setup-ready');
+    gScript.removeMessageListener('promise-setup-ready', promiseSetupReadyHandler);
+    gScript.sendAsyncMessage('trigger-on-session-request', receiverUrl);
+  });
+
+  return Promise.resolve();
+}
+
+function testCreateRequest() {
+  return new Promise(function(aResolve, aReject) {
+    info('Sender: --- testCreateRequest ---');
+    request = new PresentationRequest("file_presentation_1ua_receiver.html");
+    request.getAvailability().then((aAvailability) => {
+      aAvailability.onchange = function() {
+        aAvailability.onchange = null;
+        ok(aAvailability.value, "Sender: Device should be available.");
+        aResolve();
+      }
+    }).catch((aError) => {
+      ok(false, "Sender: Error occurred when getting availability: " + aError);
+      teardown();
+      aReject();
+    });
+
+    gScript.sendAsyncMessage('trigger-device-add');
+  });
+}
+
+function testStartConnection() {
+  return new Promise(function(aResolve, aReject) {
+    request.start().then((aConnection) => {
+      connection = aConnection;
+      ok(connection, "Sender: Connection should be available.");
+      ok(connection.id, "Sender: Connection ID should be set.");
+      is(connection.state, "connecting", "The initial state should be connecting.");
+      is(connection.url, receiverUrl, "request URL should be expanded to absolute URL");
+      connection.onconnect = function() {
+        connection.onconnect = null;
+        is(connection.state, "connected", "Connection should be connected.");
+        presentationId = connection.id;
+        aResolve();
+      };
+    }).catch((aError) => {
+      ok(false, "Sender: Error occurred when establishing a connection: " + aError);
+      teardown();
+      aReject();
+    });
+  });
+}
+
+function testSendMessage() {
+  return new Promise(function(aResolve, aReject) {
+    info('Sender: --- testSendMessage ---');
+    gScript.addMessageListener('trigger-message-from-sender', function triggerMessageFromSenderHandler() {
+      debug('Got message: trigger-message-from-sender');
+      gScript.removeMessageListener('trigger-message-from-sender', triggerMessageFromSenderHandler);
+      info('Send message to receiver');
+      connection.send('msg-sender-to-receiver');
+    });
+
+    gScript.addMessageListener('message-from-sender-received', function messageFromSenderReceivedHandler() {
+      debug('Got message: message-from-sender-received');
+      gScript.removeMessageListener('message-from-sender-received', messageFromSenderReceivedHandler);
+      aResolve();
+    });
+  });
+}
+
+function testIncomingMessage() {
+  return new Promise(function(aResolve, aReject) {
+    info('Sender: --- testIncomingMessage ---');
+    connection.addEventListener('message', function messageHandler(evt) {
+      connection.removeEventListener('message', messageHandler);
+      let msg = evt.data;
+      is(msg, "msg-receiver-to-sender", "Sender: Sender should receive message from Receiver");
+      postMessageToIframe('message-from-receiver-received');
+      aResolve();
+    });
+    postMessageToIframe('trigger-message-from-receiver');
+  });
+}
+
+function testCloseConnection() {
+  info('Sender: --- testCloseConnection ---');
+  // Test terminate immediate after close.
+  function controlChannelEstablishedHandler()
+  {
+    gScript.removeMessageListener('control-channel-established',
+                                  controlChannelEstablishedHandler);
+    ok(false, "terminate after close should do nothing");
+  }
+  gScript.addMessageListener('ready-to-close', function onReadyToClose() {
+    gScript.removeMessageListener('ready-to-close', onReadyToClose);
+    connection.close();
+
+    gScript.addMessageListener('control-channel-established', controlChannelEstablishedHandler);
+    connection.terminate();
+  });
+
+  return Promise.all([
+    new Promise(function(aResolve, aReject) {
+      connection.onclose = function() {
+        connection.onclose = null;
+        is(connection.state, 'closed', 'Sender: Connection should be closed.');
+        gScript.removeMessageListener('control-channel-established',
+                                      controlChannelEstablishedHandler);
+        aResolve();
+      };
+    }),
+    new Promise(function(aResolve, aReject) {
+      gScript.addMessageListener('receiver-closed', function onReceiverClosed() {
+        gScript.removeMessageListener('receiver-closed', onReceiverClosed);
+        gScript.removeMessageListener('control-channel-established',
+                                      controlChannelEstablishedHandler);
+        aResolve();
+      });
+    }),
+  ]);
+}
+
+function testTerminateAfterClose() {
+  info('Sender: --- testTerminateAfterClose ---');
+  return Promise.race([
+      new Promise(function(aResolve, aReject) {
+        connection.onterminate = function() {
+          connection.onterminate = null;
+          ok(false, 'terminate after close should do nothing');
+          aResolve();
+        };
+        connection.terminate();
+      }),
+      new Promise(function(aResolve, aReject) {
+        setTimeout(function() {
+          is(connection.state, 'closed', 'Sender: Connection should be closed.');
+          aResolve();
+        }, 3000);
+      }),
+  ]);
+}
+
+function testReconnect() {
+  return new Promise(function(aResolve, aReject) {
+    info('Sender: --- testReconnect ---');
+    gScript.addMessageListener('control-channel-established', function controlChannelEstablished() {
+      gScript.removeMessageListener('control-channel-established', controlChannelEstablished);
+      gScript.sendAsyncMessage("trigger-control-channel-open");
+    });
+
+    gScript.addMessageListener('start-reconnect', function startReconnectHandler(url) {
+      debug('Got message: start-reconnect');
+      gScript.removeMessageListener('start-reconnect', startReconnectHandler);
+      is(url, receiverUrl, "URLs should be the same.")
+      gScript.sendAsyncMessage('trigger-reconnected-acked', url);
+    });
+
+    gScript.addMessageListener('ready-to-reconnect', function onReadyToReconnect() {
+      gScript.removeMessageListener('ready-to-reconnect', onReadyToReconnect);
+      request.reconnect(presentationId).then((aConnection) => {
+        connection = aConnection;
+        ok(connection, "Sender: Connection should be available.");
+        is(connection.id, presentationId, "The presentationId should be the same.");
+        is(connection.state, "connecting", "The initial state should be connecting.");
+        connection.onconnect = function() {
+          connection.onconnect = null;
+          is(connection.state, "connected", "Connection should be connected.");
+          aResolve();
+        };
+      }).catch((aError) => {
+        ok(false, "Sender: Error occurred when establishing a connection: " + aError);
+        teardown();
+        aReject();
+      });
+    });
+  });
+}
+
+function teardown() {
+  gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
+    debug('Got message: teardown-complete');
+    gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
+    gScript.destroy();
+    SimpleTest.finish();
+  });
+
+  gScript.sendAsyncMessage('teardown');
+}
+
+function runTests() {
+  setup().then(testCreateRequest)
+         .then(testStartConnection)
+         .then(testSendMessage)
+         .then(testIncomingMessage)
+         .then(testCloseConnection)
+         .then(testReconnect)
+         .then(testCloseConnection)
+         .then(testTerminateAfterClose)
+         .then(teardown);
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout('Test for guarantee not firing async event');
+SpecialPowers.pushPermissions([
+  {type: 'presentation-device-manage', allow: false, context: document},
+  {type: 'presentation', allow: true, context: document},
+  {type: "browser", allow: true, context: document},
+], () => {
+  SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
+                                      /* Mocked TCP session transport builder in the test */
+                                      ["dom.presentation.session_transport.data_channel.enable", false],
+                                      ["dom.presentation.test.enabled", true],
+                                      ["dom.presentation.test.stage", 0],
+                                      ["dom.mozBrowserFramesEnabled", true]]},
+                            runTests);
+});
new file mode 100644
--- /dev/null
+++ b/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver_inproc.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<!-- vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: -->
+<html>
+  <!-- Any copyright is dedicated to the Public Domain.
+    - http://creativecommons.org/publicdomain/zero/1.0/ -->
+  <head>
+    <meta charset="utf-8">
+    <title>Test for B2G Presentation API when sender and receiver at the same side</title>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+    <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  </head>
+  <body>
+    <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1234492">
+      Test for B2G Presentation API when sender and receiver at the same side</a>
+    <script type="application/javascript;version=1.8" src="test_presentation_1ua_sender_and_receiver.js">
+    </script>
+  </body>
+</html>
--- a/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver_oop.html
+++ b/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver_oop.html
@@ -7,272 +7,12 @@
     <meta charset="utf-8">
     <title>Test for B2G Presentation API when sender and receiver at the same side (OOP ver.)</title>
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
     <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   </head>
   <body>
     <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1234492">
     Test for B2G Presentation API when sender and receiver at the same side (OOP ver.)</a>
-<script type="application/javascript;version=1.8">
-
-'use strict';
-
-var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript1UA.js'));
-var receiverUrl = SimpleTest.getTestFileURL('file_presentation_1ua_receiver.html');
-var request;
-var connection;
-var receiverIframe;
-
-function debug(str) {
-  // info(str);
-}
-
-function postMessageToIframe(aType) {
-  receiverIframe.src = receiverUrl + "#" +
-                       encodeURIComponent(JSON.stringify({ type: aType }));
-}
-
-function setup() {
-
-  gScript.addMessageListener('device-prompt', function devicePromptHandler() {
-    debug('Got message: device-prompt');
-    gScript.removeMessageListener('device-prompt', devicePromptHandler);
-    gScript.sendAsyncMessage('trigger-device-prompt-select');
-  });
-
-  gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
-    gScript.removeMessageListener('control-channel-established',
-                                  controlChannelEstablishedHandler);
-    gScript.sendAsyncMessage("trigger-control-channel-open");
-  });
-
-  gScript.addMessageListener('sender-launch', function senderLaunchHandler(url) {
-    debug('Got message: sender-launch');
-    gScript.removeMessageListener('sender-launch', senderLaunchHandler);
-    is(url, receiverUrl, 'Receiver: should receive the same url');
-    receiverIframe = document.createElement('iframe');
-    receiverIframe.setAttribute("remote", "true");
-    receiverIframe.setAttribute("mozbrowser", "true");
-    receiverIframe.setAttribute("mozpresentation", receiverUrl);
-    receiverIframe.setAttribute('src', receiverUrl);
-    receiverIframe.addEventListener("mozbrowserloadend", function mozbrowserloadendHander() {
-      receiverIframe.removeEventListener("mozbrowserloadend", mozbrowserloadendHander);
-      info("Receiver loaded.");
-    });
-
-    // This event is triggered when the iframe calls "alert".
-    receiverIframe.addEventListener("mozbrowsershowmodalprompt", function receiverListener(evt) {
-      var message = evt.detail.message;
-      if (/^OK /.exec(message)) {
-        ok(true, message.replace(/^OK /, ""));
-      } else if (/^KO /.exec(message)) {
-        ok(false, message.replace(/^KO /, ""));
-      } else if (/^INFO /.exec(message)) {
-        info(message.replace(/^INFO /, ""));
-      } else if (/^COMMAND /.exec(message)) {
-        var command = JSON.parse(message.replace(/^COMMAND /, ""));
-        gScript.sendAsyncMessage(command.name, command.data);
-      } else if (/^DONE$/.exec(message)) {
-        receiverIframe.removeEventListener("mozbrowsershowmodalprompt",
-                                            receiverListener);
-      }
-    }, false);
-
-    var promise = new Promise(function(aResolve, aReject) {
-      document.body.appendChild(receiverIframe);
-      aResolve(receiverIframe);
-    });
-
-    var obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
-                           .getService(SpecialPowers.Ci.nsIObserverService);
-    obs.notifyObservers(promise, 'setup-request-promise', null);
-  });
-
-  gScript.addMessageListener('promise-setup-ready', function promiseSetupReadyHandler() {
-    debug('Got message: promise-setup-ready');
-    gScript.removeMessageListener('promise-setup-ready',
-                                  promiseSetupReadyHandler);
-    gScript.sendAsyncMessage('trigger-on-session-request', receiverUrl);
-  });
-
-  gScript.addMessageListener('offer-sent', function offerSentHandler() {
-    debug('Got message: offer-sent');
-    gScript.removeMessageListener('offer-sent', offerSentHandler);
-    gScript.sendAsyncMessage('trigger-on-offer');
-  });
-
-  gScript.addMessageListener('answer-sent', function answerSentHandler() {
-    debug('Got message: answer-sent');
-    gScript.removeMessageListener('answer-sent', answerSentHandler);
-    gScript.sendAsyncMessage('trigger-on-answer');
-  });
-
-  return Promise.resolve();
-}
-
-function testCreateRequest() {
-  return new Promise(function(aResolve, aReject) {
-    info('Sender: --- testCreateRequest ---');
-    request = new PresentationRequest(receiverUrl);
-    request.getAvailability()
-      .then((aAvailability) => {
-        aAvailability.onchange = function() {
-          aAvailability.onchange = null;
-          ok(aAvailability.value, "Sender: Device should be available.");
-          aResolve();
-        }
-      })
-      .catch((aError) => {
-        ok(false, "Sender: Error occurred when getting availability: " + aError);
-        teardown();
-        aReject();
-      });
-
-    gScript.sendAsyncMessage('trigger-device-add');
-  });
-}
-
-function testStartConnection() {
-  return new Promise(function(aResolve, aReject) {
-    request.start()
-    .then((aConnection) => {
-      connection = aConnection;
-      ok(connection, "Sender: Connection should be available.");
-      ok(connection.id, "Sender: Connection ID should be set.");
-      is(connection.state, "connecting", "The initial state should be connecting.");
-      connection.onconnect = function() {
-        connection.onconnect = null;
-        is(connection.state, "connected", "Connection should be connected.");
-        aResolve();
-      };
-    })
-    .catch((aError) => {
-      ok(false, "Sender: Error occurred when establishing a connection: " + aError);
-      teardown();
-      aReject();
-    });
-  });
-}
-
-function testSendMessage() {
-  return new Promise(function(aResolve, aReject) {
-    info('Sender: --- testSendMessage ---');
-    gScript.addMessageListener('trigger-message-from-sender', function triggerMessageFromSenderHandler() {
-      gScript.removeMessageListener('trigger-message-from-sender', triggerMessageFromSenderHandler);
-      info('Send message to receiver');
-      connection.send('msg-sender-to-receiver');
-    });
-
-    gScript.addMessageListener('message-from-sender-received', function messageFromSenderReceivedHandler() {
-      gScript.removeMessageListener('message-from-sender-received', messageFromSenderReceivedHandler);
-      aResolve();
-    });
-  });
-}
-
-function testIncomingMessage() {
-  return new Promise(function(aResolve, aReject) {
-    info('Sender: --- testIncomingMessage ---');
-    connection.addEventListener('message', function messageHandler(evt) {
-      connection.removeEventListener('message', messageHandler);
-      let msg = evt.data;
-      is(msg, "msg-receiver-to-sender", "Sender: Sender should receive message from Receiver");
-      postMessageToIframe('message-from-receiver-received');
-      aResolve();
-    });
-    postMessageToIframe('trigger-message-from-receiver');
-  });
-}
-
-function testCloseConnection() {
-  info('Sender: --- testCloseConnection ---');
-  gScript.addMessageListener('ready-to-close', function onReadyToClose() {
-    gScript.removeMessageListener('ready-to-close', onReadyToClose);
-    connection.close();
-
-    // Test terminate immediate after close.
-    gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
-      gScript.removeMessageListener('control-channel-established',
-                                    controlChannelEstablishedHandler);
-      ok(false, 'terminate after close should do nothing');
-    });
-    connection.terminate();
-  });
-
-  return Promise.all([
-    new Promise(function(aResolve, aReject) {
-      connection.onclose = function() {
-        connection.onclose = null;
-        is(connection.state, 'closed', 'Sender: Connection should be closed.');
-        aResolve();
-      };
-    }),
-    new Promise(function(aResolve, aReject) {
-      gScript.addMessageListener('receiver-closed', function onReceiverClosed() {
-        gScript.removeMessageListener('receiver-closed', onReceiverClosed);
-        aResolve();
-      });
-    }),
-  ]);
-}
-
-function testTerminateAfterClose() {
-  info('Sender: --- testTerminateAfterClose ---');
-  return Promise.race([
-      new Promise(function(aResolve, aReject) {
-        connection.onterminate = function() {
-          connection.onterminate = null;
-          ok(false, 'terminate at closed state should do nothing');
-          aResolve();
-        };
-        connection.terminate();
-      }),
-      new Promise(function(aResolve, aReject) {
-        setTimeout(function() {
-          is(connection.state, 'closed', 'Sender: Connection should be closed.');
-          aResolve();
-        }, 3000);
-      }),
-  ]);
-}
-
-function teardown() {
-  gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
-    gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
-    gScript.destroy();
-    SimpleTest.finish();
-  });
-
-  gScript.sendAsyncMessage('teardown');
-}
-
-function runTests() {
-  setup()
-  .then(testCreateRequest)
-  .then(testStartConnection)
-  .then(testSendMessage)
-  .then(testIncomingMessage)
-  .then(testCloseConnection)
-  .then(testTerminateAfterClose)
-  .then(teardown);
-}
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.requestFlakyTimeout('Test for guarantee not firing async event');
-SpecialPowers.pushPermissions([
-  {type: 'presentation-device-manage', allow: false, context: document},
-  {type: 'presentation', allow: true, context: document},
-  {type: "browser", allow: true, context: document},
-], () => {
-  SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
-                                      /* Mocked TCP session transport builder in the test */
-                                      ["dom.presentation.session_transport.data_channel.enable", false],
-                                      ["dom.presentation.test.enabled", true],
-                                      ["dom.presentation.test.stage", 0],
-                                      ["dom.mozBrowserFramesEnabled", true],
-                                      ["dom.ipc.browser_frames.oop_by_default", true]]},
-    	                      runTests);
-});
-
-</script>
+    <script type="application/javascript;version=1.8" src="test_presentation_1ua_sender_and_receiver.js">
+    </script>
   </body>
 </html>
--- a/dom/presentation/tests/mochitest/test_presentation_terminate.js
+++ b/dom/presentation/tests/mochitest/test_presentation_terminate.js
@@ -73,28 +73,16 @@ function setup() {
 
   gScript.addMessageListener('promise-setup-ready', function promiseSetupReadyHandler() {
     debug('Got message: promise-setup-ready');
     gScript.removeMessageListener('promise-setup-ready',
                                   promiseSetupReadyHandler);
     gScript.sendAsyncMessage('trigger-on-session-request', receiverUrl);
   });
 
-  gScript.addMessageListener('offer-sent', function offerSentHandler() {
-    debug('Got message: offer-sent');
-    gScript.removeMessageListener('offer-sent', offerSentHandler);
-    gScript.sendAsyncMessage('trigger-on-offer');
-  });
-
-  gScript.addMessageListener('answer-sent', function answerSentHandler() {
-    debug('Got message: answer-sent');
-    gScript.removeMessageListener('answer-sent', answerSentHandler);
-    gScript.sendAsyncMessage('trigger-on-answer');
-  });
-
   return Promise.resolve();
 }
 
 function testCreateRequest() {
   return new Promise(function(aResolve, aReject) {
     info('Sender: --- testCreateRequest ---');
     request = new PresentationRequest(receiverUrl);
     request.getAvailability().then((aAvailability) => {
--- a/dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js
+++ b/dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js
@@ -78,28 +78,16 @@ function setup() {
 
   gScript.addMessageListener('promise-setup-ready', function promiseSetupReadyHandler() {
     debug('Got message: promise-setup-ready');
     gScript.removeMessageListener('promise-setup-ready',
                                   promiseSetupReadyHandler);
     gScript.sendAsyncMessage('trigger-on-session-request', receiverUrl);
   });
 
-  gScript.addMessageListener('offer-sent', function offerSentHandler() {
-    debug('Got message: offer-sent');
-    gScript.removeMessageListener('offer-sent', offerSentHandler);
-    gScript.sendAsyncMessage('trigger-on-offer');
-  });
-
-  gScript.addMessageListener('answer-sent', function answerSentHandler() {
-    debug('Got message: answer-sent');
-    gScript.removeMessageListener('answer-sent', answerSentHandler);
-    gScript.sendAsyncMessage('trigger-on-answer');
-  });
-
   return Promise.resolve();
 }
 
 function testCreateRequest() {
   return new Promise(function(aResolve, aReject) {
     info('Sender: --- testCreateRequest ---');
     request = new PresentationRequest(receiverUrl);
     request.getAvailability().then((aAvailability) => {
@@ -134,33 +122,41 @@ function testStartConnection() {
       ok(false, 'Sender: Error occurred when establishing a connection: ' + aError);
       teardown();
       aReject();
     });
   });
 }
 
 function testConnectionTerminate() {
-  return new Promise(function(aResolve, aReject) {
-    info('Sender: --- testConnectionTerminate---');
-    gScript.addMessageListener('prepare-for-terminate', function prepareForTerminateHandler() {
-      debug('Got message: prepare-for-terminate');
-      gScript.removeMessageListener('prepare-for-terminate', prepareForTerminateHandler);
+  info('Sender: --- testConnectionTerminate---');
+  let promise = Promise.all([
+    new Promise(function(aResolve, aReject) {
       connection.onclose = function() {
         connection.onclose = null;
         is(connection.state, 'closed', 'Sender: Connection should be closed.');
+        aResolve();
       };
-      gScript.sendAsyncMessage('trigger-control-channel-error');
+    }),
+    new Promise(function(aResolve, aReject) {
       receiverIframe.addEventListener('mozbrowserclose', function() {
         ok(true, 'observe receiver page closing');
         aResolve();
       });
-      postMessageToIframe('ready-to-terminate');
-    });
+    })
+  ]);
+
+  gScript.addMessageListener('prepare-for-terminate', function prepareForTerminateHandler() {
+    debug('Got message: prepare-for-terminate');
+    gScript.removeMessageListener('prepare-for-terminate', prepareForTerminateHandler);
+    gScript.sendAsyncMessage('trigger-control-channel-error');
+    postMessageToIframe('ready-to-terminate');
   });
+
+  return promise;
 }
 
 function teardown() {
   gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
     debug('Got message: teardown-complete');
     gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
     gScript.destroy();
     SimpleTest.finish();