Backed out 3 changesets (bug 1234128) for Android crashtest failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 19 May 2016 10:32:02 -0400
changeset 298168 e42d3d42dafa739d8a99f89d72300e9e74fd37be
parent 298167 b72055695f3d2f3d59dd43b6b6d86eeb00bd6fd8
child 298169 c6d91a79d23b7704fd222c7c29e985d4fafb1660
push id30273
push userkwierso@gmail.com
push dateFri, 20 May 2016 21:08:12 +0000
treeherdermozilla-central@c403ac05b8f4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1234128
milestone49.0a1
backs out11db59507360d0d72aa72301d064c8fd2b0e926e
8a0848fb59acc1e9fcf4a5ad7e0b0dfc0c385f73
7cf300dda85ae7435db346b46c109a4ba6c5edae
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
Backed out 3 changesets (bug 1234128) for Android crashtest failures. Backed out changeset 11db59507360 (bug 1234128) Backed out changeset 8a0848fb59ac (bug 1234128) Backed out changeset 7cf300dda85a (bug 1234128) CLOSED TREE
dom/base/Navigator.cpp
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsFrameLoader.cpp
dom/base/nsGkAtomList.h
dom/ipc/PTabContext.ipdlh
dom/ipc/TabContext.cpp
dom/ipc/TabContext.h
dom/presentation/Presentation.cpp
dom/presentation/Presentation.h
dom/presentation/PresentationReceiver.cpp
dom/presentation/PresentationReceiver.h
dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html
dom/presentation/tests/mochitest/file_presentation_1ua_receiver_oop.html
dom/presentation/tests/mochitest/file_presentation_non_receiver.html
dom/presentation/tests/mochitest/file_presentation_non_receiver_inner_iframe.html
dom/presentation/tests/mochitest/file_presentation_non_receiver_inner_iframe_oop.html
dom/presentation/tests/mochitest/file_presentation_non_receiver_oop.html
dom/presentation/tests/mochitest/file_presentation_receiver.html
dom/presentation/tests/mochitest/file_presentation_receiver_establish_connection_error.html
dom/presentation/tests/mochitest/file_presentation_receiver_inner_iframe.html
dom/presentation/tests/mochitest/file_presentation_receiver_inner_iframe_oop.html
dom/presentation/tests/mochitest/file_presentation_receiver_oop.html
dom/presentation/tests/mochitest/mochitest.ini
dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.html
dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver_oop.html
dom/presentation/tests/mochitest/test_presentation_dc_receiver.html
dom/presentation/tests/mochitest/test_presentation_tcp_receiver.html
dom/presentation/tests/mochitest/test_presentation_tcp_receiver_establish_connection_error.html
dom/presentation/tests/mochitest/test_presentation_tcp_receiver_oop.html
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -2398,46 +2398,50 @@ Navigator::HasPresentationSupport(JSCont
 
   // Grant access if it has the permission.
   if (CheckPermission(inner, "presentation")) {
     return true;
   }
 
   // Grant access to browser receiving pages and their same-origin iframes. (App
   // pages should be controlled by "presentation" permission in app manifests.)
-  nsCOMPtr<nsIDocShell> docshell = inner->GetDocShell();
-  MOZ_ASSERT(docshell);
-
-  if (!docshell->GetIsInMozBrowserOrApp()) {
+  mozilla::dom::ContentChild* cc =
+    mozilla::dom::ContentChild::GetSingleton();
+  if (!cc || !cc->IsForBrowser()) {
     return false;
   }
 
-  nsAutoString presentationURL;
-  nsContentUtils::GetPresentationURL(docshell, presentationURL);
-
-  if (presentationURL.IsEmpty()) {
+  nsCOMPtr<nsPIDOMWindowOuter> win = inner->GetOuterWindow();
+  nsCOMPtr<nsPIDOMWindowOuter> top = win->GetTop();
+  nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(win);
+  nsCOMPtr<nsIScriptObjectPrincipal> topSop = do_QueryInterface(top);
+  if (!sop || !topSop) {
     return false;
   }
 
-  nsCOMPtr<nsIScriptSecurityManager> securityManager =
-    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
-  if (!securityManager) {
+  nsIPrincipal* principal = sop->GetPrincipal();
+  nsIPrincipal* topPrincipal = topSop->GetPrincipal();
+  if (!principal || !topPrincipal || !principal->Subsumes(topPrincipal)) {
+    return false;
+  }
+
+  nsCOMPtr<nsPIDOMWindowInner> topInner;
+  if (!(topInner = top->GetCurrentInnerWindow())) {
     return false;
   }
 
-  nsCOMPtr<nsIURI> presentationURI;
-  nsresult rv = NS_NewURI(getter_AddRefs(presentationURI), presentationURL);
-  if (NS_FAILED(rv)) {
+  nsCOMPtr<nsIPresentationService> presentationService =
+    do_GetService(PRESENTATION_SERVICE_CONTRACTID);
+  if (NS_WARN_IF(!presentationService)) {
     return false;
   }
 
-  nsCOMPtr<nsIURI> docURI = inner->GetDocumentURI();
-  return NS_SUCCEEDED(securityManager->CheckSameOriginURI(presentationURI,
-                                                          docURI,
-                                                          false));
+  nsAutoString sessionId;
+  presentationService->GetExistentSessionIdAtLaunch(topInner->WindowID(), sessionId);
+  return !sessionId.IsEmpty();
 }
 
 /* static */
 bool
 Navigator::IsE10sEnabled(JSContext* aCx, JSObject* aGlobal)
 {
   return XRE_IsContentProcess();
 }
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -110,17 +110,16 @@
 #include "nsIContentViewer.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentType.h"
 #include "nsIDOMEvent.h"
-#include "nsIDOMElement.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsIDOMXULCommandEvent.h"
 #include "nsIDragService.h"
@@ -199,17 +198,16 @@
 #include "xpcprivate.h" // nsXPConnect
 #include "HTMLSplitOnSpacesTokenizer.h"
 #include "nsContentTypeParser.h"
 #include "nsICookiePermission.h"
 #include "mozIThirdPartyUtil.h"
 #include "nsICookieService.h"
 #include "mozilla/EnumSet.h"
 #include "mozilla/BloomFilter.h"
-#include "TabChild.h"
 
 #include "nsIBidiKeyboard.h"
 
 #if defined(XP_WIN)
 // Undefine LoadImage to prevent naming conflict with Windows.
 #undef LoadImage
 #endif
 
@@ -8836,36 +8834,8 @@ nsContentUtils::SetScrollbarsVisibility(
     }
 
     scroller->SetDefaultScrollbarPreferences(
                 nsIScrollable::ScrollOrientation_Y, prefValue);
     scroller->SetDefaultScrollbarPreferences(
                 nsIScrollable::ScrollOrientation_X, prefValue);
   }
 }
-
-/* static */ void
-nsContentUtils::GetPresentationURL(nsIDocShell* aDocShell, nsAString& aPresentationUrl)
-{
-  MOZ_ASSERT(aDocShell);
-
-  if (XRE_IsContentProcess()) {
-    nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
-    aDocShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
-    nsCOMPtr<nsIDocShellTreeItem> root;
-    aDocShell->GetRootTreeItem(getter_AddRefs(root));
-    if (sameTypeRoot.get() == root.get()) {
-      // presentation URL is stored in TabChild for the top most
-      // <iframe mozbrowser> in content process.
-      TabChild* tabChild = TabChild::GetFrom(aDocShell);
-      if (tabChild) {
-        aPresentationUrl = tabChild->PresentationURL();
-      }
-      return;
-    }
-  }
-
-  nsCOMPtr<nsILoadContext> loadContext(do_QueryInterface(aDocShell));
-  nsCOMPtr<nsIDOMElement> topFrameElement;
-  loadContext->GetTopFrameElement(getter_AddRefs(topFrameElement));
-
-  topFrameElement->GetAttribute(NS_LITERAL_STRING("mozpresentation"), aPresentationUrl);
-}
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2548,22 +2548,16 @@ public:
    * the provided about: URI.
    * @param aGlobal the JSObject whose URI to check, if it is a global.
    * @param aUri the URI to match, e.g. "about:feeds"
    */
   static bool IsSpecificAboutPage(JSObject* aGlobal, const char* aUri);
 
   static void SetScrollbarsVisibility(nsIDocShell* aDocShell, bool aVisible);
 
-  /*
-   * Return the associated presentation URL of the presented content.
-   * Will return empty string if the docshell is not in a presented content.
-   */
-  static void GetPresentationURL(nsIDocShell* aDocShell, nsAString& aPresentationUrl);
-
 private:
   static bool InitializeEventTable();
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static bool CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
                                 nsIPrincipal* aPrincipal);
 
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -3335,28 +3335,22 @@ nsFrameLoader::GetNewTabContext(MutableT
   }
   if (!userContextIdStr.IsEmpty()) {
     nsresult err;
     uint32_t userContextId = userContextIdStr.ToInteger(&err);
     NS_ENSURE_SUCCESS(err, err);
     attrs.mUserContextId = userContextId;
   }
 
-  nsAutoString presentationURLStr;
-  mOwnerContent->GetAttr(kNameSpaceID_None,
-                         nsGkAtoms::mozpresentation,
-                         presentationURLStr);
-
   bool tabContextUpdated =
     aTabContext->SetTabContext(OwnerIsMozBrowserFrame(),
                                ownApp,
                                containingApp,
                                attrs,
-                               signedPkgOrigin,
-                               presentationURLStr);
+                               signedPkgOrigin);
   NS_ENSURE_STATE(tabContextUpdated);
 
   return NS_OK;
 }
 
 nsresult
 nsFrameLoader::PopulateUserContextIdFromAttribute(DocShellOriginAttributes& aAttr)
 {
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -1009,17 +1009,16 @@ GK_ATOM(position, "position")
 GK_ATOM(poster, "poster")
 GK_ATOM(pre, "pre")
 GK_ATOM(preceding, "preceding")
 GK_ATOM(precedingSibling, "preceding-sibling")
 GK_ATOM(predicate, "predicate")
 GK_ATOM(prefix, "prefix")
 GK_ATOM(preload, "preload")
 GK_ATOM(prerendered, "prerendered")
-GK_ATOM(mozpresentation, "mozpresentation")
 GK_ATOM(preserve, "preserve")
 GK_ATOM(preserveSpace, "preserve-space")
 GK_ATOM(preventdefault, "preventdefault")
 GK_ATOM(primary, "primary")
 GK_ATOM(print, "print")
 GK_ATOM(priority, "priority")
 GK_ATOM(processingInstruction, "processing-instruction")
 GK_ATOM(profile, "profile")
--- a/dom/ipc/PTabContext.ipdlh
+++ b/dom/ipc/PTabContext.ipdlh
@@ -42,21 +42,16 @@ struct FrameIPCTabContext
   // The origin without originAttribute suffix for a signed package.
   // This value would be empty if the TabContext doesn't own a signed
   // package.
   nsCString signedPkgOriginNoSuffix;
 
   // Whether this is a mozbrowser frame.  <iframe mozbrowser mozapp> and
   // <xul:browser> are not considered to be mozbrowser frames.
   bool isMozBrowserElement;
-
-  // The requested presentation URL.
-  // This value would be empty if the TabContext isn't created for
-  // presented content.
-  nsString presentationURL;
 };
 
 // XXXcatalinb: This is only used by ServiceWorkerClients::OpenWindow.
 // Because service workers don't have an associated TabChild
 // we can't satisfy the security constraints on b2g. As such, the parent
 // process will accept this tab context only on desktop.
 struct UnsafeIPCTabContext
 { };
--- a/dom/ipc/TabContext.cpp
+++ b/dom/ipc/TabContext.cpp
@@ -185,29 +185,22 @@ TabContext::OriginAttributesRef() const
 }
 
 const nsACString&
 TabContext::SignedPkgOriginNoSuffix() const
 {
   return mSignedPkgOriginNoSuffix;
 }
 
-const nsAString&
-TabContext::PresentationURL() const
-{
-  return mPresentationURL;
-}
-
 bool
 TabContext::SetTabContext(bool aIsMozBrowserElement,
                           mozIApplication* aOwnApp,
                           mozIApplication* aAppFrameOwnerApp,
                           const DocShellOriginAttributes& aOriginAttributes,
-                          const nsACString& aSignedPkgOriginNoSuffix,
-                          const nsAString& aPresentationURL)
+                          const nsACString& aSignedPkgOriginNoSuffix)
 {
   NS_ENSURE_FALSE(mInitialized, false);
 
   // Get ids for both apps and only write to our member variables after we've
   // verified that this worked.
   uint32_t ownAppId = NO_APP_ID;
   if (aOwnApp) {
     nsresult rv = aOwnApp->GetLocalId(&ownAppId);
@@ -229,30 +222,28 @@ TabContext::SetTabContext(bool aIsMozBro
 
   mInitialized = true;
   mIsMozBrowserElement = aIsMozBrowserElement;
   mOriginAttributes = aOriginAttributes;
   mContainingAppId = containingAppId;
   mOwnApp = aOwnApp;
   mContainingApp = aAppFrameOwnerApp;
   mSignedPkgOriginNoSuffix = aSignedPkgOriginNoSuffix;
-  mPresentationURL = aPresentationURL;
   return true;
 }
 
 IPCTabContext
 TabContext::AsIPCTabContext() const
 {
   nsAutoCString originSuffix;
   mOriginAttributes.CreateSuffix(originSuffix);
   return IPCTabContext(FrameIPCTabContext(originSuffix,
                                           mContainingAppId,
                                           mSignedPkgOriginNoSuffix,
-                                          mIsMozBrowserElement,
-                                          mPresentationURL));
+                                          mIsMozBrowserElement));
 }
 
 static already_AddRefed<mozIApplication>
 GetAppForId(uint32_t aAppId)
 {
   nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(appsService, nullptr);
 
@@ -265,17 +256,16 @@ GetAppForId(uint32_t aAppId)
 MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
   : mInvalidReason(nullptr)
 {
   bool isMozBrowserElement = false;
   uint32_t containingAppId = NO_APP_ID;
   DocShellOriginAttributes originAttributes;
   nsAutoCString originSuffix;
   nsAutoCString signedPkgOriginNoSuffix;
-  nsAutoString presentationURL;
 
   switch(aParams.type()) {
     case IPCTabContext::TPopupIPCTabContext: {
       const PopupIPCTabContext &ipcContext = aParams.get_PopupIPCTabContext();
 
       TabContext *context;
       if (ipcContext.opener().type() == PBrowserOrId::TPBrowserParent) {
         context = TabParent::GetFrom(ipcContext.opener().get_PBrowserParent());
@@ -326,17 +316,16 @@ MaybeInvalidTabContext::MaybeInvalidTabC
     }
     case IPCTabContext::TFrameIPCTabContext: {
       const FrameIPCTabContext &ipcContext =
         aParams.get_FrameIPCTabContext();
 
       isMozBrowserElement = ipcContext.isMozBrowserElement();
       containingAppId = ipcContext.frameOwnerAppId();
       signedPkgOriginNoSuffix = ipcContext.signedPkgOriginNoSuffix();
-      presentationURL = ipcContext.presentationURL();
       originSuffix = ipcContext.originSuffix();
       originAttributes.PopulateFromSuffix(originSuffix);
       break;
     }
     case IPCTabContext::TUnsafeIPCTabContext: {
       // XXXcatalinb: This used *only* by ServiceWorkerClients::OpenWindow.
       // It is meant as a temporary solution until service workers can
       // provide a TabChild equivalent. Don't allow this on b2g since
@@ -375,18 +364,17 @@ MaybeInvalidTabContext::MaybeInvalidTabC
     return;
   }
 
   bool rv;
   rv = mTabContext.SetTabContext(isMozBrowserElement,
                                  ownApp,
                                  containingApp,
                                  originAttributes,
-                                 signedPkgOriginNoSuffix,
-                                 presentationURL);
+                                 signedPkgOriginNoSuffix);
   if (!rv) {
     mInvalidReason = "Couldn't initialize TabContext.";
   }
 }
 
 bool
 MaybeInvalidTabContext::IsValid()
 {
--- a/dom/ipc/TabContext.h
+++ b/dom/ipc/TabContext.h
@@ -125,22 +125,16 @@ public:
   const DocShellOriginAttributes& OriginAttributesRef() const;
 
   /**
    * Returns the origin associated with the tab (w/o suffix) if this tab owns
    * a signed packaged content.
    */
   const nsACString& SignedPkgOriginNoSuffix() const;
 
-  /**
-   * Returns the presentation URL associated with the tab if this tab is
-   * created for presented content
-   */
-  const nsAString& PresentationURL() const;
-
 protected:
   friend class MaybeInvalidTabContext;
 
   /**
    * These protected mutator methods let you modify a TabContext once.  Further
    * attempts to modify a given TabContext will fail (the method will return
    * false).
    *
@@ -159,18 +153,17 @@ protected:
    *    apps can be null.
    *  - a browser frame inside the given owner app (which may be null).
    *  - a non-browser, non-app frame. Both own app and owner app should be null.
    */
   bool SetTabContext(bool aIsMozBrowserElement,
                      mozIApplication* aOwnApp,
                      mozIApplication* aAppFrameOwnerApp,
                      const DocShellOriginAttributes& aOriginAttributes,
-                     const nsACString& aSignedPkgOriginNoSuffix,
-                     const nsAString& aPresentationURL);
+                     const nsACString& aSignedPkgOriginNoSuffix);
 
   /**
    * Modify this TabContext to match the given TabContext.  This is a special
    * case triggered by nsFrameLoader::SwapWithOtherRemoteLoader which may have
    * caused the owner content to change.
    *
    * This special case only allows the field `mIsMozBrowserElement` to be
    * changed.  If any other fields have changed, the update is ignored and
@@ -217,21 +210,16 @@ private:
 
   /**
    * The signed package origin without suffix. Since the signed packaged
    * web content is always loaded in a separate process, it makes sense
    * that we store this immutable value in TabContext. If the TabContext
    * doesn't own a signed package, this value would be empty.
    */
   nsCString mSignedPkgOriginNoSuffix;
-
-  /**
-   * The requested presentation URL.
-   */
-  nsString mPresentationURL;
 };
 
 /**
  * MutableTabContext is the same as MaybeInvalidTabContext, except the mutation
  * methods are public instead of protected.  You can still only call these
  * mutation methods once on a given object.
  */
 class MutableTabContext : public TabContext
@@ -242,25 +230,23 @@ public:
     return TabContext::SetTabContext(aContext);
   }
 
   bool
   SetTabContext(bool aIsMozBrowserElement,
                 mozIApplication* aOwnApp,
                 mozIApplication* aAppFrameOwnerApp,
                 const DocShellOriginAttributes& aOriginAttributes,
-                const nsACString& aSignedPkgOriginNoSuffix = EmptyCString(),
-                const nsAString& aPresentationURL = EmptyString())
+                const nsACString& aSignedPkgOriginNoSuffix = EmptyCString())
   {
     return TabContext::SetTabContext(aIsMozBrowserElement,
                                      aOwnApp,
                                      aAppFrameOwnerApp,
                                      aOriginAttributes,
-                                     aSignedPkgOriginNoSuffix,
-                                     aPresentationURL);
+                                     aSignedPkgOriginNoSuffix);
   }
 };
 
 /**
  * MaybeInvalidTabContext is a simple class that lets you transform an
  * IPCTabContext into a TabContext.
  *
  * The issue is that an IPCTabContext is not necessarily valid; for example, it
--- a/dom/presentation/Presentation.cpp
+++ b/dom/presentation/Presentation.cpp
@@ -1,19 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/PresentationBinding.h"
 #include "mozilla/dom/Promise.h"
-#include "nsContentUtils.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsIDocShell.h"
 #include "nsIPresentationService.h"
 #include "nsServiceManagerUtils.h"
 #include "Presentation.h"
 #include "PresentationReceiver.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
@@ -25,28 +23,59 @@ NS_IMPL_RELEASE_INHERITED(Presentation, 
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Presentation)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 /* static */ already_AddRefed<Presentation>
 Presentation::Create(nsPIDOMWindowInner* aWindow)
 {
   RefPtr<Presentation> presentation = new Presentation(aWindow);
-  return presentation.forget();
+  return NS_WARN_IF(!presentation->Init()) ? nullptr : presentation.forget();
 }
 
 Presentation::Presentation(nsPIDOMWindowInner* aWindow)
   : DOMEventTargetHelper(aWindow)
 {
 }
 
 Presentation::~Presentation()
 {
 }
 
+bool
+Presentation::Init()
+{
+  nsCOMPtr<nsIPresentationService> service =
+    do_GetService(PRESENTATION_SERVICE_CONTRACTID);
+  if (NS_WARN_IF(!service)) {
+    return false;
+  }
+
+  if (NS_WARN_IF(!GetOwner())) {
+    return false;
+  }
+
+  // Check if a receiver instance is required now. A session may already be
+  // connecting before the web content gets loaded in a receiving browsing
+  // context.
+  nsAutoString sessionId;
+  nsresult rv = service->GetExistentSessionIdAtLaunch(GetOwner()->WindowID(), sessionId);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+  if (!sessionId.IsEmpty()) {
+    mReceiver = PresentationReceiver::Create(GetOwner(), sessionId);
+    if (NS_WARN_IF(!mReceiver)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 /* virtual */ JSObject*
 Presentation::WrapObject(JSContext* aCx,
                          JS::Handle<JSObject*> aGivenProto)
 {
   return PresentationBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
@@ -58,41 +87,13 @@ Presentation::SetDefaultRequest(Presenta
 already_AddRefed<PresentationRequest>
 Presentation::GetDefaultRequest() const
 {
   RefPtr<PresentationRequest> request = mDefaultRequest;
   return request.forget();
 }
 
 already_AddRefed<PresentationReceiver>
-Presentation::GetReceiver()
+Presentation::GetReceiver() const
 {
-  // return the same receiver if already created
-  if (mReceiver) {
-    RefPtr<PresentationReceiver> receiver = mReceiver;
-    return receiver.forget();
-  }
-
-  if (!IsInPresentedContent()) {
-    return nullptr;
-  }
-
-  mReceiver = PresentationReceiver::Create(GetOwner());
-  if (NS_WARN_IF(!mReceiver)) {
-    MOZ_ASSERT(mReceiver);
-    return nullptr;
-  }
-
   RefPtr<PresentationReceiver> receiver = mReceiver;
   return receiver.forget();
 }
-
-bool
-Presentation::IsInPresentedContent() const
-{
-  nsCOMPtr<nsIDocShell> docShell = GetOwner()->GetDocShell();
-  MOZ_ASSERT(docShell);
-
-  nsAutoString presentationURL;
-  nsContentUtils::GetPresentationURL(docShell, presentationURL);
-
-  return !presentationURL.IsEmpty();
-}
--- a/dom/presentation/Presentation.h
+++ b/dom/presentation/Presentation.h
@@ -28,24 +28,24 @@ public:
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
   // WebIDL (public APIs)
   void SetDefaultRequest(PresentationRequest* aRequest);
 
   already_AddRefed<PresentationRequest> GetDefaultRequest() const;
 
-  already_AddRefed<PresentationReceiver> GetReceiver();
+  already_AddRefed<PresentationReceiver> GetReceiver() const;
 
 private:
   explicit Presentation(nsPIDOMWindowInner* aWindow);
 
   ~Presentation();
 
-  bool IsInPresentedContent() const;
+  bool Init();
 
   RefPtr<PresentationRequest> mDefaultRequest;
   RefPtr<PresentationReceiver> mReceiver;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/presentation/PresentationReceiver.cpp
+++ b/dom/presentation/PresentationReceiver.cpp
@@ -32,63 +32,56 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_ADDREF_INHERITED(PresentationReceiver, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(PresentationReceiver, DOMEventTargetHelper)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationReceiver)
   NS_INTERFACE_MAP_ENTRY(nsIPresentationRespondingListener)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 /* static */ already_AddRefed<PresentationReceiver>
-PresentationReceiver::Create(nsPIDOMWindowInner* aWindow)
+PresentationReceiver::Create(nsPIDOMWindowInner* aWindow,
+                             const nsAString& aSessionId)
 {
   RefPtr<PresentationReceiver> receiver = new PresentationReceiver(aWindow);
-  return NS_WARN_IF(!receiver->Init()) ? nullptr : receiver.forget();
+  return NS_WARN_IF(!receiver->Init(aSessionId)) ? nullptr : receiver.forget();
 }
 
 PresentationReceiver::PresentationReceiver(nsPIDOMWindowInner* aWindow)
   : DOMEventTargetHelper(aWindow)
 {
 }
 
 PresentationReceiver::~PresentationReceiver()
 {
   Shutdown();
 }
 
 bool
-PresentationReceiver::Init()
+PresentationReceiver::Init(const nsAString& aSessionId)
 {
   if (NS_WARN_IF(!GetOwner())) {
     return false;
   }
   mWindowId = GetOwner()->WindowID();
 
+  if (!aSessionId.IsEmpty()) {
+    nsresult rv = NotifySessionConnect(mWindowId, aSessionId);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return false;
+    }
+  }
+
+  // Register listener for incoming sessions.
   nsCOMPtr<nsIPresentationService> service =
     do_GetService(PRESENTATION_SERVICE_CONTRACTID);
   if (NS_WARN_IF(!service)) {
     return false;
   }
 
-  // A session may already be connecting before the web content
-  // request for access in a receiving browsing context.
-  nsAutoString sessionId;
-  nsresult rv = service->GetExistentSessionIdAtLaunch(mWindowId, sessionId);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return false;
-  }
-
-  if (!sessionId.IsEmpty()) {
-    rv = NotifySessionConnect(mWindowId, sessionId);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return false;
-    }
-  }
-
-  // Register listener for incoming sessions.
-  rv = service->RegisterRespondingListener(mWindowId, this);
+  nsresult rv = service->RegisterRespondingListener(mWindowId, this);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return false;
   }
 
   return true;
 }
 
 void PresentationReceiver::Shutdown()
--- a/dom/presentation/PresentationReceiver.h
+++ b/dom/presentation/PresentationReceiver.h
@@ -20,17 +20,18 @@ class PresentationReceiver final : publi
                                  , public nsIPresentationRespondingListener
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationReceiver,
                                            DOMEventTargetHelper)
   NS_DECL_NSIPRESENTATIONRESPONDINGLISTENER
 
-  static already_AddRefed<PresentationReceiver> Create(nsPIDOMWindowInner* aWindow);
+  static already_AddRefed<PresentationReceiver> Create(nsPIDOMWindowInner* aWindow,
+                                                       const nsAString& aSessionId);
 
   virtual void DisconnectFromOwner() override;
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
   // WebIDL (public APIs)
   already_AddRefed<Promise> GetConnection(ErrorResult& aRv);
@@ -39,17 +40,17 @@ public:
 
   IMPL_EVENT_HANDLER(connectionavailable);
 
 private:
   explicit PresentationReceiver(nsPIDOMWindowInner* aWindow);
 
   ~PresentationReceiver();
 
-  bool Init();
+  bool Init(const nsAString& aSessionId);
 
   void Shutdown();
 
   nsresult DispatchConnectionAvailableEvent();
 
   // Store the inner window ID for |UnregisterRespondingListener| call in
   // |Shutdown| since the inner window may not exist at that moment.
   uint64_t mWindowId;
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
@@ -252,16 +252,17 @@ const mockedSessionTransport = {
 
     setTimeout(()=>{
       this._listener.onSessionTransport(this);
       this._listener = null;
     }, 0);
   },
   // in-process case
   buildDataChannelTransport: function(role, window, controlChannel, listener) {
+    dump("build data channel transport\n");
     this._listener = listener;
     this._role = role;
 
     var hasNavigator = window ? (typeof window.navigator != "undefined") : false;
     sendAsyncMessage('check-navigator', hasNavigator);
 
     setTimeout(()=>{
       this._listener.onSessionTransport(this);
--- a/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html
+++ b/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html
@@ -8,44 +8,50 @@
   <body>
     <div id="content"></div>
 <script type="application/javascript;version=1.7">
 
 "use strict";
 
 function is(a, b, msg) {
   if (a === b) {
-    alert('OK ' + msg);
+    window.parent.postMessage('OK ' + msg, '*');
   } else {
-    alert('KO ' + msg + ' | reason: ' + a + ' != ' + b);
+    window.parent.postMessage('KO ' + msg + ' | reason: ' + a + ' != ' + b, '*');
   }
 }
 
 function ok(a, msg) {
-  alert((a ? 'OK ' : 'KO ') + msg);
+  window.parent.postMessage((a ? 'OK ' : 'KO ') + msg, '*');
 }
 
 function info(msg) {
-  alert('INFO ' + msg);
+  window.parent.postMessage('INFO ' + msg, '*');
 }
 
 function command(name, data) {
-  alert('COMMAND ' + JSON.stringify({name: name, data: data}));
+  window.parent.postMessage('COMMAND ' + JSON.stringify({name: name, data: data}), '*');
 }
 
 function finish() {
-  alert('DONE');
+  window.parent.postMessage('DONE', '*');
 }
 
 var connection;
 
 function testConnectionAvailable() {
   return new Promise(function(aResolve, aReject) {
     info('Receiver: --- testConnectionAvailable ---');
     ok(navigator.presentation, "Receiver: navigator.presentation should be available.");
+    // FIXME Sometimes navigator.presentation.receiver is initialized lately.
+    // See bug 1234128 - navigator.presentation.receiver is null in 1-UA use case.
+    // https://bugzilla.mozilla.org/show_bug.cgi?id=1234128
+    while (!navigator.presentation.receiver) {
+      info('Receiver: navigator.presentation.receiver is null, see Bug 1234128');
+    }
     ok(navigator.presentation.receiver, "Receiver: navigator.presentation.receiver should be available.");
     navigator.presentation.receiver.getConnection()
     .then((aConnection) => {
       connection = aConnection;
       ok(connection.id, "Receiver: Connection ID should be set: " + connection.id);
       is(connection.state, "closed", "Connection state at receiver side should be closed by default.");
       aResolve();
     })
@@ -84,24 +90,24 @@ function testIncomingMessage() {
       aResolve();
     });
     command('forward-command', JSON.stringify({ name: 'trigger-message-from-sender' }));
   });
 }
 
 function testSendMessage() {
   return new Promise(function(aResolve, aReject) {
-    window.addEventListener('hashchange', function hashchangeHandler(evt) {
-      var message = JSON.parse(decodeURIComponent(window.location.hash.substring(1)));
+    window.addEventListener('message', function messageHandler(evt) {
+      var message = evt.data;
       if (message.type === 'trigger-message-from-receiver') {
         info('Receiver: --- testSendMessage ---');
         connection.send('msg-receiver-to-sender');
       }
       if (message.type === 'message-from-receiver-received') {
-        window.removeEventListener('hashchange', hashchangeHandler);
+        window.removeEventListener('message', messageHandler);
         aResolve();
       }
     });
   });
 }
 
 function testTerminateConnection() {
   return new Promise(function(aResolve, aReject) {
new file mode 100644
--- /dev/null
+++ b/dom/presentation/tests/mochitest/file_presentation_1ua_receiver_oop.html
@@ -0,0 +1,137 @@
+<!DOCTYPE HTML>
+<!-- vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: -->
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Test for B2G PresentationReceiver at receiver side</title>
+  </head>
+  <body>
+    <div id="content"></div>
+<script type="application/javascript;version=1.7">
+
+"use strict";
+
+function is(a, b, msg) {
+  if (a === b) {
+    alert('OK ' + msg);
+  } else {
+    alert('KO ' + msg + ' | reason: ' + a + ' != ' + b);
+  }
+}
+
+function ok(a, msg) {
+  alert((a ? 'OK ' : 'KO ') + msg);
+}
+
+function info(msg) {
+  alert('INFO ' + msg);
+}
+
+function command(name, data) {
+  alert('COMMAND ' + JSON.stringify({name: name, data: data}));
+}
+
+function finish() {
+  alert('DONE');
+}
+
+var connection;
+
+function testConnectionAvailable() {
+  return new Promise(function(aResolve, aReject) {
+    info('Receiver: --- testConnectionAvailable ---');
+    ok(navigator.presentation, "Receiver: navigator.presentation should be available.");
+    // FIXME Sometimes navigator.presentation.receiver is initialized lately.
+    // See bug 1234128 - navigator.presentation.receiver is null in 1-UA use case.
+    // https://bugzilla.mozilla.org/show_bug.cgi?id=1234128
+    while (!navigator.presentation.receiver) {
+      info('Receiver: navigator.presentation.receiver is null, see Bug 1234128');
+    }
+    ok(navigator.presentation.receiver, "Receiver: navigator.presentation.receiver should be available.");
+    navigator.presentation.receiver.getConnection()
+    .then((aConnection) => {
+      connection = aConnection;
+      ok(connection.id, "Receiver: Connection ID should be set: " + connection.id);
+      is(connection.state, "closed", "Connection state at receiver side should be closed by default.");
+      aResolve();
+    })
+    .catch((aError) => {
+      ok(false, "Receiver: Error occurred when getting the connection: " + aError);
+      finish();
+      aReject();
+    });
+  });
+}
+
+function testConnectionReady() {
+  return new Promise(function(aResolve, aReject) {
+    info('Receiver: --- testConnectionReady ---');
+    connection.onstatechange = function() {
+      connection.onstatechange = null;
+      is(connection.state, "connected", "Receiver: Connection state should become connected.");
+      aResolve();
+    };
+    if (connection.state === "connected") {
+      connection.onstatechange = null;
+      is(connection.state, "connected", "Receiver: Connection state should become connected.");
+      aResolve();
+    }
+  });
+}
+
+function testIncomingMessage() {
+  return new Promise(function(aResolve, aReject) {
+    info('Receiver: --- testIncomingMessage ---');
+    connection.addEventListener('message', function messageHandler(evt) {
+      connection.removeEventListener('message', messageHandler);
+      let msg = evt.data;
+      is(msg, 'msg-sender-to-receiver', 'Receiver: Receiver should receive message from sender.');
+      command('forward-command', JSON.stringify({ name: 'message-from-sender-received' }));
+      aResolve();
+    });
+    command('forward-command', JSON.stringify({ name: 'trigger-message-from-sender' }));
+  });
+}
+
+function testSendMessage() {
+  return new Promise(function(aResolve, aReject) {
+    window.addEventListener('hashchange', function hashchangeHandler(evt) {
+      var message = JSON.parse(decodeURIComponent(window.location.hash.substring(1)));
+      if (message.type === 'trigger-message-from-receiver') {
+        info('Receiver: --- testSendMessage ---');
+        connection.send('msg-receiver-to-sender');
+      }
+      if (message.type === 'message-from-receiver-received') {
+        window.removeEventListener('hashchange', hashchangeHandler);
+        aResolve();
+      }
+    });
+  });
+}
+
+function testTerminateConnection() {
+  return new Promise(function(aResolve, aReject) {
+    info('Receiver: --- testTerminateConnection ---');
+    connection.onstatechange = function() {
+      connection.onstatechange = null;
+      is(connection.state, "terminated", "Receiver: Connection should be terminated.");
+      aResolve();
+    };
+    connection.terminate();
+  });
+}
+
+function runTests() {
+  testConnectionAvailable()
+  .then(testConnectionReady)
+  .then(testIncomingMessage)
+  .then(testSendMessage)
+  .then(testTerminateConnection)
+  .then(finish);
+}
+
+runTests();
+
+</script>
+  </body>
+</html>
rename from dom/presentation/tests/mochitest/file_presentation_non_receiver_inner_iframe.html
rename to dom/presentation/tests/mochitest/file_presentation_non_receiver_inner_iframe_oop.html
rename from dom/presentation/tests/mochitest/file_presentation_non_receiver.html
rename to dom/presentation/tests/mochitest/file_presentation_non_receiver_oop.html
--- a/dom/presentation/tests/mochitest/file_presentation_receiver.html
+++ b/dom/presentation/tests/mochitest/file_presentation_receiver.html
@@ -1,46 +1,46 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>Test for B2G PresentationReceiver at receiver side (OOP)</title>
+  <title>Test for B2G PresentationReceiver at receiver side</title>
 </head>
 <body>
 <div id="content"></div>
 <script type="application/javascript;version=1.7">
 
 "use strict";
 
 function is(a, b, msg) {
-  alert((a === b ? 'OK ' : 'KO ') + msg);
+  window.parent.postMessage((a === b ? 'OK ' : 'KO ') + msg, '*');
 }
 
 function ok(a, msg) {
-  alert((a ? 'OK ' : 'KO ') + msg);
+  window.parent.postMessage((a ? 'OK ' : 'KO ') + msg, '*');
 }
 
 function info(msg) {
-  alert('INFO ' + msg);
+  window.parent.postMessage('INFO ' + msg, '*');
 }
 
 function command(msg) {
-  alert('COMMAND ' + JSON.stringify(msg));
+  window.parent.postMessage('COMMAND ' + JSON.stringify(msg), '*');
 }
 
 function finish() {
-  alert('DONE');
+  window.parent.postMessage('DONE', '*');
 }
 
 var connection;
 
 function testConnectionAvailable() {
   return new Promise(function(aResolve, aReject) {
-    ok(navigator.presentation, "navigator.presentation should be available in OOP receiving pages.");
-    ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available in OOP receiving pages.");
+    ok(navigator.presentation, "navigator.presentation should be available.");
+    ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available.");
 
     navigator.presentation.receiver.getConnection().then(
       function(aConnection) {
         connection = aConnection;
 
         ok(connection.id, "Connection ID should be set: " + connection.id);
         is(connection.state, "closed", "Connection state at receiver side should be closed by default.");
         aResolve();
@@ -49,36 +49,16 @@ function testConnectionAvailable() {
         ok(false, "Error occurred when getting the connection: " + aError);
         finish();
         aReject();
       }
     );
   });
 }
 
-function testConnectionAvailableSameOriginInnerIframe() {
-  return new Promise(function(aResolve, aReject) {
-    var iframe = document.createElement('iframe');
-    iframe.setAttribute('src', './file_presentation_receiver_inner_iframe.html');
-    document.body.appendChild(iframe);
-
-    aResolve();
-  });
-}
-
-function testConnectionUnavailableDiffOriginInnerIframe() {
-  return new Promise(function(aResolve, aReject) {
-    var iframe = document.createElement('iframe');
-    iframe.setAttribute('src', 'http://example.com/tests/dom/presentation/tests/mochitest/file_presentation_non_receiver_inner_iframe.html');
-    document.body.appendChild(iframe);
-
-    aResolve();
-  });
-}
-
 function testConnectionReady() {
   return new Promise(function(aResolve, aReject) {
     connection.onstatechange = function() {
       connection.onstatechange = null;
       is(connection.state, "connected", "Connection state should become connected.");
       aResolve();
     };
 
@@ -92,35 +72,33 @@ function testIncomingMessage() {
 
     connection.addEventListener('message', function messageHandler(aEvent) {
       connection.removeEventListener('message', messageHandler);
       is(aEvent.data, incomingMessage, "An incoming message should be received.");
       aResolve();
     });
 
     command({ name: 'trigger-incoming-message',
-    	      data: incomingMessage });
+    	        data: incomingMessage });
   });
 }
 
 function testTerminateConnection() {
   return new Promise(function(aResolve, aReject) {
     connection.onstatechange = function() {
       connection.onstatechange = null;
       is(connection.state, "terminated", "Connection should be terminated.");
       aResolve();
     };
 
     connection.terminate();
   });
 }
 
 testConnectionAvailable().
-then(testConnectionAvailableSameOriginInnerIframe).
-then(testConnectionUnavailableDiffOriginInnerIframe).
 then(testConnectionReady).
 then(testIncomingMessage).
 then(testTerminateConnection).
 then(finish);
 
 </script>
 </body>
 </html>
--- a/dom/presentation/tests/mochitest/file_presentation_receiver_establish_connection_error.html
+++ b/dom/presentation/tests/mochitest/file_presentation_receiver_establish_connection_error.html
@@ -6,37 +6,33 @@
 </head>
 <body>
 <div id="content"></div>
 <script type="application/javascript;version=1.7">
 
 "use strict";
 
 function is(a, b, msg) {
-  if (a === b) {
-    alert('OK ' + msg);
-  } else {
-    alert('KO ' + msg + ' | reason: ' + a + ' != ' + b);
-  }
+  window.parent.postMessage((a === b ? 'OK ' : 'KO ') + msg, '*');
 }
 
 function ok(a, msg) {
-  alert((a ? 'OK ' : 'KO ') + msg);
+  window.parent.postMessage((a ? 'OK ' : 'KO ') + msg, '*');
 }
 
 function info(msg) {
-  alert('INFO ' + msg);
+  window.parent.postMessage('INFO ' + msg, '*');
 }
 
-function command(name, data) {
-  alert('COMMAND ' + JSON.stringify({name: name, data: data}));
+function command(msg) {
+  window.parent.postMessage('COMMAND ' + JSON.stringify(msg), '*');
 }
 
 function finish() {
-  alert('DONE');
+  window.parent.postMessage('DONE', '*');
 }
 
 var connection;
 
 function testConnectionAvailable() {
   return new Promise(function(aResolve, aReject) {
     ok(navigator.presentation, "navigator.presentation should be available.");
     ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available.");
@@ -62,17 +58,17 @@ function testUnexpectedControlChannelClo
   return new Promise(function(aResolve, aReject) {
     connection.onstatechange = function() {
       connection.onstatechange = null;
       is(connection.state, "terminated", "Connection state should become terminated.");
       aResolve();
     };
 
     // Trigger the control channel to be closed with error code.
-    command('trigger-control-channel-close', 0x80004004 /* NS_ERROR_ABORT */);
+    command({ name: 'trigger-control-channel-close', data: 0x80004004 /* NS_ERROR_ABORT */ });
   });
 }
 
 testConnectionAvailable().
 then(testUnexpectedControlChannelClose).
 then(finish);
 
 </script>
rename from dom/presentation/tests/mochitest/file_presentation_receiver_inner_iframe.html
rename to dom/presentation/tests/mochitest/file_presentation_receiver_inner_iframe_oop.html
new file mode 100644
--- /dev/null
+++ b/dom/presentation/tests/mochitest/file_presentation_receiver_oop.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test for B2G PresentationReceiver at receiver side (OOP)</title>
+</head>
+<body>
+<div id="content"></div>
+<script type="application/javascript;version=1.7">
+
+"use strict";
+
+function is(a, b, msg) {
+  alert((a === b ? 'OK ' : 'KO ') + msg);
+}
+
+function ok(a, msg) {
+  alert((a ? 'OK ' : 'KO ') + msg);
+}
+
+function info(msg) {
+  alert('INFO ' + msg);
+}
+
+function command(msg) {
+  alert('COMMAND ' + JSON.stringify(msg));
+}
+
+function finish() {
+  alert('DONE');
+}
+
+var connection;
+
+function testConnectionAvailable() {
+  return new Promise(function(aResolve, aReject) {
+    ok(navigator.presentation, "navigator.presentation should be available in OOP receiving pages.");
+    ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available in OOP receiving pages.");
+
+    navigator.presentation.receiver.getConnection().then(
+      function(aConnection) {
+        connection = aConnection;
+
+        ok(connection.id, "Connection ID should be set: " + connection.id);
+        is(connection.state, "closed", "Connection state at receiver side should be closed by default.");
+        aResolve();
+      },
+      function(aError) {
+        ok(false, "Error occurred when getting the connection: " + aError);
+        finish();
+        aReject();
+      }
+    );
+  });
+}
+
+function testConnectionAvailableSameOriginInnerIframe() {
+  return new Promise(function(aResolve, aReject) {
+    var iframe = document.createElement('iframe');
+    iframe.setAttribute('src', './file_presentation_receiver_inner_iframe_oop.html');
+    document.body.appendChild(iframe);
+
+    aResolve();
+  });
+}
+
+function testConnectionUnavailableDiffOriginInnerIframe() {
+  return new Promise(function(aResolve, aReject) {
+    var iframe = document.createElement('iframe');
+    iframe.setAttribute('src', 'http://example.com/tests/dom/presentation/tests/mochitest/file_presentation_non_receiver_inner_iframe_oop.html');
+    document.body.appendChild(iframe);
+
+    aResolve();
+  });
+}
+
+function testConnectionReady() {
+  return new Promise(function(aResolve, aReject) {
+    connection.onstatechange = function() {
+      connection.onstatechange = null;
+      is(connection.state, "connected", "Connection state should become connected.");
+      aResolve();
+    };
+
+    command({ name: 'trigger-incoming-offer' });
+  });
+}
+
+function testIncomingMessage() {
+  return new Promise(function(aResolve, aReject) {
+    const incomingMessage = "test incoming message";
+
+    connection.addEventListener('message', function messageHandler(aEvent) {
+      connection.removeEventListener('message', messageHandler);
+      is(aEvent.data, incomingMessage, "An incoming message should be received.");
+      aResolve();
+    });
+
+    command({ name: 'trigger-incoming-message',
+    	      data: incomingMessage });
+  });
+}
+
+function testTerminateConnection() {
+  return new Promise(function(aResolve, aReject) {
+    connection.onstatechange = function() {
+      connection.onstatechange = null;
+      is(connection.state, "terminated", "Connection should be terminated.");
+      aResolve();
+    };
+
+    connection.terminate();
+  });
+}
+
+testConnectionAvailable().
+// TODO Bug 1234128 - Fix the timing issue for navigator.presentation.receiver.
+// This test fails intermittently under some edge cases. Disable it for now until
+// the issue gets fixed.
+// then(testConnectionAvailableSameOriginInnerIframe).
+then(testConnectionUnavailableDiffOriginInnerIframe).
+then(testConnectionReady).
+then(testIncomingMessage).
+then(testTerminateConnection).
+then(finish);
+
+</script>
+</body>
+</html>
--- a/dom/presentation/tests/mochitest/mochitest.ini
+++ b/dom/presentation/tests/mochitest/mochitest.ini
@@ -1,19 +1,21 @@
 [DEFAULT]
 support-files =
   PresentationDeviceInfoChromeScript.js
   PresentationSessionChromeScript.js
   PresentationSessionChromeScript1UA.js
   file_presentation_1ua_receiver.html
-  file_presentation_non_receiver_inner_iframe.html
-  file_presentation_non_receiver.html
+  file_presentation_1ua_receiver_oop.html
+  file_presentation_non_receiver_inner_iframe_oop.html
+  file_presentation_non_receiver_oop.html
   file_presentation_receiver.html
   file_presentation_receiver_establish_connection_error.html
-  file_presentation_receiver_inner_iframe.html
+  file_presentation_receiver_inner_iframe_oop.html
+  file_presentation_receiver_oop.html
 
 [test_presentation_dc_sender.html]
 skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
 [test_presentation_dc_receiver.html]
 skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
 [test_presentation_1ua_sender_and_receiver.html]
 skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
 [test_presentation_1ua_sender_and_receiver_oop.html]
--- a/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.html
+++ b/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.html
@@ -21,61 +21,56 @@ function debug(str) {
 }
 
 var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript1UA.js'));
 var receiverUrl = SimpleTest.getTestFileURL('file_presentation_1ua_receiver.html');
 var request;
 var connection;
 var receiverIframe;
 
+// This event is triggered when the iframe calls "postMessage".
+window.addEventListener('message', function messageHandler(evt) {
+  var message = evt.data;
+  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)) {
+    window.removeEventListener('message', messageHandler);
+    teardown();
+  }
+}, false);
+
 function postMessageToIframe(aType) {
-  receiverIframe.src = receiverUrl + "#" +
-                       encodeURIComponent(JSON.stringify({ type: aType }));
+  receiverIframe.contentWindow.postMessage({ 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() {
     debug('Got message: control-channel-established');
     gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
     receiverIframe = document.createElement('iframe');
     receiverIframe.setAttribute('src', receiverUrl);
-    receiverIframe.setAttribute("mozbrowser", "true");
-    receiverIframe.setAttribute("mozpresentation", receiverUrl);
     receiverIframe.onload = function() {
       info('Receiver loaded.');
       gScript.sendAsyncMessage('trigger-control-channel-open');
     };
 
-    // 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);
-        teardown();
-      }
-    }, 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);
@@ -200,20 +195,18 @@ function runTests() {
          .then(testIncomingMessage)
          .then(testTerminateConnection);
 }
 
 SimpleTest.waitForExplicitFinish();
 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],
                                       ["dom.presentation.test.enabled", true],
-                                      ["dom.presentation.test.stage", 0],
-                                      ["dom.mozBrowserFramesEnabled", true]]},
+                                      ["dom.presentation.test.stage", 0]]},
                             runTests);
 });
 
     </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
@@ -12,17 +12,17 @@
   <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 receiverUrl = SimpleTest.getTestFileURL('file_presentation_1ua_receiver_oop.html');
 var request;
 var connection;
 var receiverIframe;
 
 function debug(str) {
   // info(str);
 }
 
@@ -41,17 +41,16 @@ function setup() {
 
   gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
     debug('Got message: control-channel-established');
     gScript.removeMessageListener('control-channel-established',
                                   controlChannelEstablishedHandler);
     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.");
       gScript.sendAsyncMessage("trigger-control-channel-open");
     });
 
     // This event is triggered when the iframe calls "alert".
--- a/dom/presentation/tests/mochitest/test_presentation_dc_receiver.html
+++ b/dom/presentation/tests/mochitest/test_presentation_dc_receiver.html
@@ -24,34 +24,33 @@ var obs = SpecialPowers.Cc["@mozilla.org
           .getService(SpecialPowers.Ci.nsIObserverService);
 
 function setup() {
   return new Promise(function(aResolve, aReject) {
     gScript.sendAsyncMessage('trigger-device-add');
 
     var iframe = document.createElement('iframe');
     iframe.setAttribute('src', receiverUrl);
-    iframe.setAttribute("mozbrowser", "true");
-    iframe.setAttribute("mozpresentation", receiverUrl);
 
-    // This event is triggered when the iframe calls "alert".
-    iframe.addEventListener("mozbrowsershowmodalprompt", function receiverListener(evt) {
-      var message = evt.detail.message;
+    // This event is triggered when the iframe calls "postMessage".
+    window.addEventListener('message', function listener(aEvent) {
+      var message = aEvent.data;
       if (/^OK /.exec(message)) {
-        ok(true, message.replace(/^OK /, ""));
+        ok(true, "Message from iframe: " + message);
       } else if (/^KO /.exec(message)) {
-        ok(false, message.replace(/^KO /, ""));
+        ok(false, "Message from iframe: " + message);
       } else if (/^INFO /.exec(message)) {
-        info(message.replace(/^INFO /, ""));
+        info("Message from iframe: " + message);
       } else if (/^COMMAND /.exec(message)) {
-        var command = JSON.parse(message.replace(/^COMMAND /, ""));
+        var command = JSON.parse(message.replace(/^COMMAND /, ''));
         gScript.sendAsyncMessage(command.name, command.data);
       } else if (/^DONE$/.exec(message)) {
-        iframe.removeEventListener("mozbrowsershowmodalprompt",
-                                   receiverListener);
+        ok(true, "Messaging from iframe complete.");
+        window.removeEventListener('message', listener);
+
         teardown();
       }
     }, false);
 
     var promise = new Promise(function(aResolve, aReject) {
       document.body.appendChild(iframe);
 
       aResolve(iframe);
@@ -121,19 +120,17 @@ function runTests() {
   setup().
   then(testIncomingSessionRequest);
 }
 
 SimpleTest.waitForExplicitFinish();
 SpecialPowers.pushPermissions([
   {type: 'presentation-device-manage', allow: false, context: document},
   {type: 'presentation', allow: true, context: document},
-  {type: "browser", allow: true, context: document},
 ], function() {
   SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
-                                      ["dom.presentation.session_transport.data_channel.enable", true],
-                                      ["dom.mozBrowserFramesEnabled", true]]},
+                                      ["dom.presentation.session_transport.data_channel.enable", true]]},
                             runTests);
 });
 
 </script>
 </body>
 </html>
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_receiver.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_receiver.html
@@ -23,35 +23,33 @@ var receiverUrl = SimpleTest.getTestFile
 var obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
           .getService(SpecialPowers.Ci.nsIObserverService);
 
 function setup() {
   return new Promise(function(aResolve, aReject) {
     gScript.sendAsyncMessage('trigger-device-add');
 
     var iframe = document.createElement('iframe');
-    iframe.setAttribute('mozbrowser', 'true');
-    iframe.setAttribute('mozpresentation', receiverUrl);
     iframe.setAttribute('src', receiverUrl);
 
     // This event is triggered when the iframe calls "postMessage".
-    iframe.addEventListener('mozbrowsershowmodalprompt', function listener(aEvent) {
-      var message = aEvent.detail.message;
+    window.addEventListener('message', function listener(aEvent) {
+      var message = aEvent.data;
       if (/^OK /.exec(message)) {
         ok(true, "Message from iframe: " + message);
       } else if (/^KO /.exec(message)) {
         ok(false, "Message from iframe: " + message);
       } else if (/^INFO /.exec(message)) {
         info("Message from iframe: " + message);
       } else if (/^COMMAND /.exec(message)) {
         var command = JSON.parse(message.replace(/^COMMAND /, ''));
         gScript.sendAsyncMessage(command.name, command.data);
       } else if (/^DONE$/.exec(message)) {
         ok(true, "Messaging from iframe complete.");
-        iframe.removeEventListener('mozbrowsershowmodalprompt', listener);
+        window.removeEventListener('message', listener);
 
         teardown();
       }
     }, false);
 
     var promise = new Promise(function(aResolve, aReject) {
       document.body.appendChild(iframe);
 
@@ -117,19 +115,17 @@ function runTests() {
   setup().
   then(testIncomingSessionRequest);
 }
 
 SimpleTest.waitForExplicitFinish();
 SpecialPowers.pushPermissions([
   {type: 'presentation-device-manage', allow: false, context: document},
   {type: 'presentation', allow: true, context: document},
-  {type: 'browser', allow: true, context: document},
 ], function() {
   SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
-                                      ["dom.mozBrowserFramesEnabled", true],
                                       ["dom.presentation.session_transport.data_channel.enable", false]]},
                             runTests);
 });
 
 </script>
 </body>
 </html>
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_receiver_establish_connection_error.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_receiver_establish_connection_error.html
@@ -21,34 +21,33 @@ var obs = SpecialPowers.Cc["@mozilla.org
           .getService(SpecialPowers.Ci.nsIObserverService);
 
 function setup() {
   return new Promise(function(aResolve, aReject) {
     gScript.sendAsyncMessage('trigger-device-add');
 
     var iframe = document.createElement('iframe');
     iframe.setAttribute('src', receiverUrl);
-    iframe.setAttribute("mozbrowser", "true");
-    iframe.setAttribute("mozpresentation", receiverUrl);
 
-    // This event is triggered when the iframe calls "alert".
-    iframe.addEventListener("mozbrowsershowmodalprompt", function receiverListener(evt) {
-      var message = evt.detail.message;
+    // This event is triggered when the iframe calls "postMessage".
+    window.addEventListener('message', function listener(aEvent) {
+      var message = aEvent.data;
       if (/^OK /.exec(message)) {
-        ok(true, message.replace(/^OK /, ""));
+        ok(true, "Message from iframe: " + message);
       } else if (/^KO /.exec(message)) {
-        ok(false, message.replace(/^KO /, ""));
+        ok(false, "Message from iframe: " + message);
       } else if (/^INFO /.exec(message)) {
-        info(message.replace(/^INFO /, ""));
+        info("Message from iframe: " + message);
       } else if (/^COMMAND /.exec(message)) {
-        var command = JSON.parse(message.replace(/^COMMAND /, ""));
+        var command = JSON.parse(message.replace(/^COMMAND /, ''));
         gScript.sendAsyncMessage(command.name, command.data);
       } else if (/^DONE$/.exec(message)) {
-        iframe.removeEventListener("mozbrowsershowmodalprompt",
-                                   receiverListener);
+        ok(true, "Messaging from iframe complete.");
+        window.removeEventListener('message', listener);
+
         teardown();
       }
     }, false);
 
     var promise = new Promise(function(aResolve, aReject) {
       document.body.appendChild(iframe);
 
       aResolve(iframe);
@@ -91,19 +90,17 @@ function runTests() {
   setup().
   then(testIncomingSessionRequest);
 }
 
 SimpleTest.waitForExplicitFinish();
 SpecialPowers.pushPermissions([
   {type: 'presentation-device-manage', allow: false, context: document},
   {type: 'presentation', allow: true, context: document},
-  {type: "browser", allow: true, context: document},
 ], function() {
   SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
-                                      ["dom.presentation.session_transport.data_channel.enable", false],
-                                      ["dom.mozBrowserFramesEnabled", true]]},
+                                      ["dom.presentation.session_transport.data_channel.enable", false]]},
                             runTests);
 });
 
 </script>
 </body>
 </html>
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_receiver_oop.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_receiver_oop.html
@@ -13,34 +13,33 @@
 <p id="display"></p>
 <div id="content" style="display: none"></div>
 <pre id="test"></pre>
 <script type="application/javascript">
 
 'use strict';
 
 var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript.js'));
-var receiverUrl = SimpleTest.getTestFileURL('file_presentation_receiver.html');
-var nonReceiverUrl = SimpleTest.getTestFileURL('file_presentation_non_receiver.html');
+var receiverUrl = SimpleTest.getTestFileURL('file_presentation_receiver_oop.html');
+var nonReceiverUrl = SimpleTest.getTestFileURL('file_presentation_non_receiver_oop.html');
 
 var isReceiverFinished = false;
 var isNonReceiverFinished = false;
 
 var obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
           .getService(SpecialPowers.Ci.nsIObserverService);
 
 function setup() {
   return new Promise(function(aResolve, aReject) {
     gScript.sendAsyncMessage('trigger-device-add');
 
     // Create a receiver OOP iframe.
     var receiverIframe = document.createElement('iframe');
     receiverIframe.setAttribute('remote', 'true');
     receiverIframe.setAttribute('mozbrowser', 'true');
-    receiverIframe.setAttribute('mozpresentation', receiverUrl);
     receiverIframe.setAttribute('src', receiverUrl);
 
     // This event is triggered when the iframe calls "alert".
     receiverIframe.addEventListener('mozbrowsershowmodalprompt', function receiverListener(aEvent) {
       var message = aEvent.detail.message;
       if (/^OK /.exec(message)) {
         ok(true, "Message from iframe: " + message);
       } else if (/^KO /.exec(message)) {