Bug 1191740 - Add originAttributes in TabContext. r=bholley
authorSteven Englehardt <senglehardt@mozilla.com>
Wed, 07 Oct 2015 11:47:46 +0800
changeset 267459 9c406698782b764201bf3357d8797e3239c022a6
parent 267458 ac9f96ca40cb0d4cfe4e79bbc126ba9309a87516
child 267460 cde243d573472684a21b3a38d2b2dff620a50307
push id29519
push usercbook@mozilla.com
push dateWed, 14 Oct 2015 10:29:57 +0000
treeherdermozilla-central@6307530f9f1e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1191740
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1191740 - Add originAttributes in TabContext. r=bholley
dom/base/nsFrameLoader.cpp
dom/ipc/ContentProcessManager.cpp
dom/ipc/PContent.ipdl
dom/ipc/PTabContext.ipdlh
dom/ipc/TabContext.cpp
dom/ipc/TabContext.h
dom/ipc/nsIContentParent.cpp
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -74,16 +74,17 @@
 #include "ClientLayerManager.h"
 
 #include "AppProcessChecker.h"
 #include "ContentParent.h"
 #include "TabParent.h"
 #include "mozilla/plugins/PPluginWidgetParent.h"
 #include "../plugins/ipc/PluginWidgetParent.h"
 #include "mozilla/AsyncEventDispatcher.h"
+#include "mozilla/BasePrincipal.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/unused.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/layout/RenderFrameParent.h"
 #include "nsIAppsService.h"
 #include "GeckoProfiler.h"
@@ -280,26 +281,33 @@ NS_IMETHODIMP
 nsFrameLoader::SwitchProcessAndLoadURI(nsIURI* aURI)
 {
   nsCOMPtr<nsIURI> URIToLoad = aURI;
   nsRefPtr<TabParent> tp = nullptr;
 
   MutableTabContext context;
   nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
   nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
-
-  bool tabContextUpdated = true;
+  OriginAttributes attrs = OriginAttributes();
+  attrs.mInBrowser = OwnerIsBrowserFrame();
+
+  // Get the AppId from ownApp
+  uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
   if (ownApp) {
-    tabContextUpdated = context.SetTabContextForAppFrame(ownApp, containingApp);
-  } else if (OwnerIsBrowserFrame()) {
-    // The |else| above is unnecessary; OwnerIsBrowserFrame() implies !ownApp.
-    tabContextUpdated = context.SetTabContextForBrowserFrame(containingApp);
-  } else {
-    tabContextUpdated = context.SetTabContextForNormalFrame();
+    nsresult rv = ownApp->GetLocalId(&appId);
+    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_STATE(appId != nsIScriptSecurityManager::NO_APP_ID);
+  } else if (containingApp) {
+    nsresult rv = containingApp->GetLocalId(&appId);
+    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_STATE(appId != nsIScriptSecurityManager::NO_APP_ID);
   }
+  attrs.mAppId = appId;
+
+  bool tabContextUpdated = context.SetTabContext(ownApp, containingApp, attrs);
   NS_ENSURE_STATE(tabContextUpdated);
 
   nsCOMPtr<Element> ownerElement = mOwnerContent;
   tp = ContentParent::CreateBrowserOrApp(context, ownerElement, nullptr);
   if (!tp) {
     return NS_ERROR_FAILURE;
   }
   mRemoteBrowserShown = false;
@@ -2266,26 +2274,34 @@ nsFrameLoader::TryRemoteBrowser()
   }
 
   PROFILER_LABEL("nsFrameLoader", "CreateRemoteBrowser",
     js::ProfileEntry::Category::OTHER);
 
   MutableTabContext context;
   nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
   nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
+  OriginAttributes attrs = OriginAttributes();
+  attrs.mInBrowser = OwnerIsBrowserFrame();
+
+  // Get the AppId from ownApp
+  uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
+  if (ownApp) {
+    nsresult rv = ownApp->GetLocalId(&appId);
+    NS_ENSURE_SUCCESS(rv, false);
+    NS_ENSURE_TRUE(appId != nsIScriptSecurityManager::NO_APP_ID, false);
+  } else if (containingApp) {
+    nsresult rv = containingApp->GetLocalId(&appId);
+    NS_ENSURE_SUCCESS(rv, false);
+    NS_ENSURE_TRUE(appId != nsIScriptSecurityManager::NO_APP_ID, false);
+  }
+  attrs.mAppId = appId;
 
   bool rv = true;
-  if (ownApp) {
-    rv = context.SetTabContextForAppFrame(ownApp, containingApp);
-  } else if (OwnerIsBrowserFrame()) {
-    // The |else| above is unnecessary; OwnerIsBrowserFrame() implies !ownApp.
-    rv = context.SetTabContextForBrowserFrame(containingApp);
-  } else {
-    rv = context.SetTabContextForNormalFrame();
-  }
+  rv = context.SetTabContext(ownApp, containingApp, attrs);
   NS_ENSURE_TRUE(rv, false);
 
   nsCOMPtr<Element> ownerElement = mOwnerContent;
   mRemoteBrowser = ContentParent::CreateBrowserOrApp(context, ownerElement, openerContentParent);
   if (!mRemoteBrowser) {
     return false;
   }
 
--- a/dom/ipc/ContentProcessManager.cpp
+++ b/dom/ipc/ContentProcessManager.cpp
@@ -145,29 +145,29 @@ ContentProcessManager::AllocateTabId(con
   auto iter = mContentParentMap.find(aChildCpId);
   if (NS_WARN_IF(iter == mContentParentMap.end())) {
     ASSERT_UNLESS_FUZZING();
     return TabId(0);
   }
 
   struct RemoteFrameInfo info;
 
-  const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext();
+  const IPCTabContextUnion& contextUnion = aContext.contextUnion();
   // If it's a PopupIPCTabContext, it's the case that a TabChild want to
   // open a new tab. aOpenerTabId has to be it's parent frame's opener id.
-  if (appBrowser.type() == IPCTabAppBrowserContext::TPopupIPCTabContext) {
+  if (contextUnion.type() == IPCTabContextUnion::TPopupIPCTabContext) {
     auto remoteFrameIter = iter->second.mRemoteFrames.find(aOpenerTabId);
     if (remoteFrameIter == iter->second.mRemoteFrames.end()) {
       ASSERT_UNLESS_FUZZING("Failed to find parent frame's opener id.");
       return TabId(0);
     }
 
     info.mOpenerTabId = remoteFrameIter->second.mOpenerTabId;
 
-    const PopupIPCTabContext &ipcContext = appBrowser.get_PopupIPCTabContext();
+    const PopupIPCTabContext &ipcContext = contextUnion.get_PopupIPCTabContext();
     MOZ_ASSERT(ipcContext.opener().type() == PBrowserOrId::TTabId);
 
     remoteFrameIter = iter->second.mRemoteFrames.find(ipcContext.opener().get_TabId());
     if (remoteFrameIter == iter->second.mRemoteFrames.end()) {
       ASSERT_UNLESS_FUZZING("Failed to find tab id.");
       return TabId(0);
     }
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -460,19 +460,19 @@ both:
     // Depending on exactly how the new browser is being created, it might be
     // created from either the child or parent process!
     //
     // The child creates the PBrowser as part of
     // TabChild::BrowserFrameProvideWindow (which happens when the child's
     // content calls window.open()), and the parent creates the PBrowser as part
     // of ContentParent::CreateBrowserOrApp.
     //
-    // When the parent constructs a PBrowser, the child trusts the app token it
-    // receives from the parent.  In that case, context can be any of the
-    // IPCTabContext subtypes.
+    // When the parent constructs a PBrowser, the child trusts the app token and
+    // other attributes it receives from the parent.  In that case, the
+    // context should be FrameIPCTabContext.
     //
     // When the child constructs a PBrowser, the parent doesn't trust the app
     // token it receives from the child.  In this case, context must have type
     // PopupIPCTabContext.  The browser created using a PopupIPCTabContext has
     // the opener PBrowser's app-id and containing-app-id.  The parent checks
     // that if the opener is a browser element, the context is also for a
     // browser element.
     //
--- a/dom/ipc/PTabContext.ipdlh
+++ b/dom/ipc/PTabContext.ipdlh
@@ -24,51 +24,38 @@ namespace dom {
 // element.  Such a PopupIPCTabContext should be rejected by code which receives
 // it.
 struct PopupIPCTabContext
 {
   PBrowserOrId opener;
   bool isBrowserElement;
 };
 
-// An IPCTabContext which corresponds to an app frame.
-struct AppFrameIPCTabContext
+// An IPCTabContext which corresponds to an app, browser, or normal frame.
+struct FrameIPCTabContext
 {
-  // The ID of the app this frame corresponds to.  May be NO_APP_ID.
-  uint32_t ownAppId;
-
-  // The ID of the app containing this frame.  May be NO_APP_ID.
-  uint32_t appFrameOwnerAppId;
-};
+  // The stringified originAttributes dictionary.
+  nsCString originSuffix;
 
-// An IPCTabContext which corresponds to a browser frame.
-struct BrowserFrameIPCTabContext
-{
-  // The ID of the app which contains this browser frame.  May be NO_APP_ID.
-  uint32_t browserFrameOwnerAppId;
+  // The ID of the app containing this app/browser frame, if applicable.
+  uint32_t frameOwnerAppId;
 };
 
-// This is equivalent to AppFrameIPCTabContext with all fields set to NO_APP_ID.
-struct VanillaFrameIPCTabContext
-{};
-
 // IPCTabContext is an analog to mozilla::dom::TabContext.  Both specify an
 // iframe/PBrowser's own and containing app-ids and tell you whether the
 // iframe/PBrowser is a browser frame.  But only IPCTabContext is allowed to
 // travel over IPC.
 //
 // We need IPCTabContext (specifically, PopupIPCTabContext) to prevent a
 // privilege escalation attack by a compromised child process.  See the comment
 // on AllocPBrowser for details.
-union IPCTabAppBrowserContext
+union IPCTabContextUnion
 {
   PopupIPCTabContext;
-  AppFrameIPCTabContext;
-  BrowserFrameIPCTabContext;
-  VanillaFrameIPCTabContext;
+  FrameIPCTabContext;
 };
 
 struct IPCTabContext {
-  IPCTabAppBrowserContext appBrowserContext;
+  IPCTabContextUnion contextUnion;
 };
 
 }
 }
--- a/dom/ipc/TabContext.cpp
+++ b/dom/ipc/TabContext.cpp
@@ -17,38 +17,37 @@
 using namespace mozilla::dom::ipc;
 using namespace mozilla::layout;
 
 namespace mozilla {
 namespace dom {
 
 TabContext::TabContext()
   : mInitialized(false)
-  , mOwnAppId(NO_APP_ID)
   , mContainingAppId(NO_APP_ID)
-  , mIsBrowser(false)
+  , mOriginAttributes()
 {
 }
 
 bool
 TabContext::IsBrowserElement() const
 {
-  return mIsBrowser;
+  return mOriginAttributes.mInBrowser;
 }
 
 bool
 TabContext::IsBrowserOrApp() const
 {
   return HasOwnApp() || IsBrowserElement();
 }
 
 uint32_t
 TabContext::OwnAppId() const
 {
-  return mOwnAppId;
+  return mOriginAttributes.mAppId;
 }
 
 already_AddRefed<mozIApplication>
 TabContext::GetOwnApp() const
 {
   nsCOMPtr<mozIApplication> ownApp = mOwnApp;
   return ownApp.forget();
 }
@@ -111,17 +110,17 @@ TabContext::HasAppOwnerApp() const
   nsCOMPtr<mozIApplication> ownerApp = GetAppOwnerApp();
   return !!ownerApp;
 }
 
 uint32_t
 TabContext::OwnOrContainingAppId() const
 {
   if (HasOwnApp()) {
-    return mOwnAppId;
+    return mOriginAttributes.mAppId;
   }
 
   return mContainingAppId;
 }
 
 already_AddRefed<mozIApplication>
 TabContext::GetOwnOrContainingApp() const
 {
@@ -148,19 +147,27 @@ TabContext::SetTabContext(const TabConte
   NS_ENSURE_FALSE(mInitialized, false);
 
   *this = aContext;
   mInitialized = true;
 
   return true;
 }
 
+const OriginAttributes&
+TabContext::OriginAttributesRef() const
+{
+  return mOriginAttributes;
+}
+
+
 bool
-TabContext::SetTabContextForAppFrame(mozIApplication* aOwnApp,
-                                     mozIApplication* aAppFrameOwnerApp)
+TabContext::SetTabContext(mozIApplication* aOwnApp,
+                          mozIApplication* aAppFrameOwnerApp,
+                          const OriginAttributes& aOriginAttributes)
 {
   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);
@@ -170,62 +177,35 @@ TabContext::SetTabContextForAppFrame(moz
 
   uint32_t containingAppId = NO_APP_ID;
   if (aAppFrameOwnerApp) {
     nsresult rv = aAppFrameOwnerApp->GetLocalId(&containingAppId);
     NS_ENSURE_SUCCESS(rv, false);
     NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false);
   }
 
+  // Veryify that app id matches mAppId passed in originAttributes
+  MOZ_RELEASE_ASSERT((aOwnApp && aOriginAttributes.mAppId == ownAppId) ||
+                     (aAppFrameOwnerApp && aOriginAttributes.mAppId == containingAppId) ||
+                     aOriginAttributes.mAppId == NO_APP_ID);
+
   mInitialized = true;
-  mIsBrowser = false;
-  mOwnAppId = ownAppId;
+  mOriginAttributes = aOriginAttributes;
   mContainingAppId = containingAppId;
   mOwnApp = aOwnApp;
   mContainingApp = aAppFrameOwnerApp;
   return true;
 }
 
-bool
-TabContext::SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp)
-{
-  NS_ENSURE_FALSE(mInitialized, false);
-
-  uint32_t containingAppId = NO_APP_ID;
-  if (aBrowserFrameOwnerApp) {
-    nsresult rv = aBrowserFrameOwnerApp->GetLocalId(&containingAppId);
-    NS_ENSURE_SUCCESS(rv, false);
-    NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false);
-  }
-
-  mInitialized = true;
-  mIsBrowser = true;
-  mOwnAppId = NO_APP_ID;
-  mContainingAppId = containingAppId;
-  mContainingApp = aBrowserFrameOwnerApp;
-  return true;
-}
-
-bool
-TabContext::SetTabContextForNormalFrame()
-{
-  NS_ENSURE_FALSE(mInitialized, false);
-
-  mInitialized = true;
-  return true;
-}
-
 IPCTabContext
 TabContext::AsIPCTabContext() const
 {
-  if (mIsBrowser) {
-    return IPCTabContext(BrowserFrameIPCTabContext(mContainingAppId));
-  }
-
-  return IPCTabContext(AppFrameIPCTabContext(mOwnAppId, mContainingAppId));
+  nsAutoCString originSuffix;
+  mOriginAttributes.CreateSuffix(originSuffix);
+  return IPCTabContext(FrameIPCTabContext(originSuffix, mContainingAppId));
 }
 
 static already_AddRefed<mozIApplication>
 GetAppForId(uint32_t aAppId)
 {
   nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(appsService, nullptr);
 
@@ -233,24 +213,24 @@ GetAppForId(uint32_t aAppId)
   appsService->GetAppByLocalId(aAppId, getter_AddRefs(app));
 
   return app.forget();
 }
 
 MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
   : mInvalidReason(nullptr)
 {
-  bool isBrowser = false;
-  uint32_t ownAppId = NO_APP_ID;
   uint32_t containingAppId = NO_APP_ID;
+  OriginAttributes originAttributes = OriginAttributes();
+  nsAutoCString originSuffix;
 
-  const IPCTabAppBrowserContext& appBrowser = aParams.appBrowserContext();
-  switch(appBrowser.type()) {
-    case IPCTabAppBrowserContext::TPopupIPCTabContext: {
-      const PopupIPCTabContext &ipcContext = appBrowser.get_PopupIPCTabContext();
+  const IPCTabContextUnion& contextUnion = aParams.contextUnion();
+  switch(contextUnion.type()) {
+    case IPCTabContextUnion::TPopupIPCTabContext: {
+      const PopupIPCTabContext &ipcContext = contextUnion.get_PopupIPCTabContext();
 
       TabContext *context;
       if (ipcContext.opener().type() == PBrowserOrId::TPBrowserParent) {
         context = TabParent::GetFrom(ipcContext.opener().get_PBrowserParent());
         if (context->IsBrowserElement() && !ipcContext.isBrowserElement()) {
           // If the TabParent corresponds to a browser element, then it can only
           // open other browser elements, for security reasons.  We should have
           // checked this before calling the TabContext constructor, so this is
@@ -275,76 +255,57 @@ MaybeInvalidTabContext::MaybeInvalidTabC
 
       // Browser elements can't nest other browser elements.  So if
       // our opener is browser element, we must be a new DOM window
       // opened by it.  In that case we inherit our containing app ID
       // (if any).
       //
       // Otherwise, we're a new app window and we inherit from our
       // opener app.
+
+      // FIXME bug 1212250 - use InheritFromDocToChildDocshell instead
+      // of copying attributes directly.
+      originAttributes = context->mOriginAttributes;
       if (ipcContext.isBrowserElement()) {
-        isBrowser = true;
-        ownAppId = NO_APP_ID;
         containingAppId = context->OwnOrContainingAppId();
       } else {
-        isBrowser = false;
-        ownAppId = context->mOwnAppId;
         containingAppId = context->mContainingAppId;
       }
       break;
     }
-    case IPCTabAppBrowserContext::TAppFrameIPCTabContext: {
-      const AppFrameIPCTabContext &ipcContext =
-        appBrowser.get_AppFrameIPCTabContext();
+    case IPCTabContextUnion::TFrameIPCTabContext: {
+      const FrameIPCTabContext &ipcContext =
+        contextUnion.get_FrameIPCTabContext();
 
-      isBrowser = false;
-      ownAppId = ipcContext.ownAppId();
-      containingAppId = ipcContext.appFrameOwnerAppId();
-      break;
-    }
-    case IPCTabAppBrowserContext::TBrowserFrameIPCTabContext: {
-      const BrowserFrameIPCTabContext &ipcContext =
-        appBrowser.get_BrowserFrameIPCTabContext();
-
-      isBrowser = true;
-      ownAppId = NO_APP_ID;
-      containingAppId = ipcContext.browserFrameOwnerAppId();
-      break;
-    }
-    case IPCTabAppBrowserContext::TVanillaFrameIPCTabContext: {
-      isBrowser = false;
-      ownAppId = NO_APP_ID;
-      containingAppId = NO_APP_ID;
+      containingAppId = ipcContext.frameOwnerAppId();
+      originSuffix = ipcContext.originSuffix();
+      originAttributes.PopulateFromSuffix(originSuffix);
       break;
     }
     default: {
       MOZ_CRASH();
     }
   }
 
-  nsCOMPtr<mozIApplication> ownApp = GetAppForId(ownAppId);
-  if ((ownApp == nullptr) != (ownAppId == NO_APP_ID)) {
+  nsCOMPtr<mozIApplication> ownApp = GetAppForId(originAttributes.mAppId);
+  if ((ownApp == nullptr) != (originAttributes.mAppId == NO_APP_ID)) {
     mInvalidReason = "Got an ownAppId that didn't correspond to an app.";
     return;
   }
 
   nsCOMPtr<mozIApplication> containingApp = GetAppForId(containingAppId);
   if ((containingApp == nullptr) != (containingAppId == NO_APP_ID)) {
     mInvalidReason = "Got a containingAppId that didn't correspond to an app.";
     return;
   }
 
   bool rv;
-  if (isBrowser) {
-    rv = mTabContext.SetTabContextForBrowserFrame(containingApp);
-  } else {
-    rv = mTabContext.SetTabContextForAppFrame(ownApp,
-                                              containingApp);
-  }
-
+  rv = mTabContext.SetTabContext(ownApp,
+                                 containingApp,
+                                 originAttributes);
   if (!rv) {
     mInvalidReason = "Couldn't initialize TabContext.";
   }
 }
 
 bool
 MaybeInvalidTabContext::IsValid()
 {
--- a/dom/ipc/TabContext.h
+++ b/dom/ipc/TabContext.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_TabContext_h
 #define mozilla_dom_TabContext_h
 
 #include "mozIApplication.h"
 #include "nsCOMPtr.h"
+#include "mozilla/BasePrincipal.h"
 
 namespace mozilla {
 namespace dom {
 
 class IPCTabContext;
 
 /**
  * TabContext encapsulates information about an iframe that may be a mozbrowser
@@ -97,16 +98,23 @@ public:
    * OwnOrContainingAppId() gets the ID of this frame, if HasOwnApp().  If this
    * frame does not have its own app, it gets the ID of the app which contains
    * this frame (i.e., the result of {Browser,App}OwnerAppId(), as applicable).
    */
   uint32_t OwnOrContainingAppId() const;
   already_AddRefed<mozIApplication> GetOwnOrContainingApp() const;
   bool HasOwnOrContainingApp() const;
 
+  /**
+   * OriginAttributesRef() returns the OriginAttributes of this frame to the
+   * caller. This is used to store any attribute associated with the frame's
+   * docshell, such as the AppId.
+   */
+  const OriginAttributes& OriginAttributesRef() 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).
    *
@@ -115,98 +123,77 @@ protected:
    */
 
   /**
    * Set this TabContext to match the given TabContext.
    */
   bool SetTabContext(const TabContext& aContext);
 
   /**
-   * Set this TabContext to be an app frame (with the given own app) inside the
-   * given app.  Either or both apps may be null.
+   * Set the TabContext for this frame. This can either be:
+   *  - an app frame (with the given own app) inside the given owner app. Either
+   *    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 SetTabContextForAppFrame(mozIApplication* aOwnApp,
-                                mozIApplication* aAppFrameOwnerApp);
-
-  /**
-   * Set this TabContext to be a browser frame inside the given app (which may
-   * be null).
-   */
-  bool SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp);
-
-  /**
-   * Set this TabContext to be a normal non-browser non-app frame.
-   */
-  bool SetTabContextForNormalFrame();
+  bool SetTabContext(mozIApplication* aOwnApp,
+                     mozIApplication* aAppFrameOwnerApp,
+                     const OriginAttributes& aOriginAttributes);
 
 private:
   /**
    * Has this TabContext been initialized?  If so, mutator methods will fail.
    */
   bool mInitialized;
 
   /**
    * This TabContext's own app.  If this is non-null, then this
    * TabContext corresponds to an app, and mIsBrowser must be false.
    */
   nsCOMPtr<mozIApplication> mOwnApp;
 
   /**
-   * A cache of mOwnApp->GetLocalId().  Speed really does matter here, since we
-   * read this ID often during process startup.
-   */
-  uint32_t mOwnAppId;
-
-  /**
    * This TabContext's containing app.  If mIsBrowser, this corresponds to the
    * app which contains the browser frame; otherwise, this corresponds to the
    * app which contains the app frame.
    */
   nsCOMPtr<mozIApplication> mContainingApp;
 
   /*
    * Cache of mContainingApp->GetLocalId().
    */
   uint32_t mContainingAppId;
 
   /**
-   * Does this TabContext correspond to a browser element?
-   *
-   * If this is true, mOwnApp must be null.
+   * OriginAttributes of the top level tab docShell
    */
-  bool mIsBrowser;
+  OriginAttributes mOriginAttributes;
+
 };
 
 /**
  * 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
 {
 public:
   bool SetTabContext(const TabContext& aContext)
   {
     return TabContext::SetTabContext(aContext);
   }
 
-  bool SetTabContextForAppFrame(mozIApplication* aOwnApp,
-                                mozIApplication* aAppFrameOwnerApp)
+  bool SetTabContext(mozIApplication* aOwnApp,
+                     mozIApplication* aAppFrameOwnerApp,
+                     const OriginAttributes& aOriginAttributes)
   {
-    return TabContext::SetTabContextForAppFrame(aOwnApp, aAppFrameOwnerApp);
-  }
-
-  bool SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp)
-  {
-    return TabContext::SetTabContextForBrowserFrame(aBrowserFrameOwnerApp);
-  }
-
-  bool SetTabContextForNormalFrame()
-  {
-    return TabContext::SetTabContextForNormalFrame();
+    return TabContext::SetTabContext(aOwnApp,
+                                     aAppFrameOwnerApp,
+                                     aOriginAttributes);
   }
 };
 
 /**
  * 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/ipc/nsIContentParent.cpp
+++ b/dom/ipc/nsIContentParent.cpp
@@ -65,28 +65,28 @@ nsIContentParent::DeallocPJavaScriptPare
 {
   ReleaseJavaScriptParent(aParent);
   return true;
 }
 
 bool
 nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
 {
-  const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext();
+  const IPCTabContextUnion& contextUnion = aContext.contextUnion();
 
   // We don't trust the IPCTabContext we receive from the child, so we'll bail
   // if we receive an IPCTabContext that's not a PopupIPCTabContext.
   // (PopupIPCTabContext lets the child process prove that it has access to
   // the app it's trying to open.)
-  if (appBrowser.type() != IPCTabAppBrowserContext::TPopupIPCTabContext) {
+  if (contextUnion.type() != IPCTabContextUnion::TPopupIPCTabContext) {
     ASSERT_UNLESS_FUZZING("Unexpected IPCTabContext type.  Aborting AllocPBrowserParent.");
     return false;
   }
 
-  const PopupIPCTabContext& popupContext = appBrowser.get_PopupIPCTabContext();
+  const PopupIPCTabContext& popupContext = contextUnion.get_PopupIPCTabContext();
   if (popupContext.opener().type() != PBrowserOrId::TPBrowserParent) {
     ASSERT_UNLESS_FUZZING("Unexpected PopupIPCTabContext type.  Aborting AllocPBrowserParent.");
     return false;
   }
 
   auto opener = TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
   if (!opener) {
     ASSERT_UNLESS_FUZZING("Got null opener from child; aborting AllocPBrowserParent.");
@@ -123,18 +123,18 @@ nsIContentParent::AllocPBrowserParent(co
   unused << aCpId;
   unused << aIsForApp;
   unused << aIsForBrowser;
 
   if (!CanOpenBrowser(aContext)) {
     return nullptr;
   }
 
-  const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext();
-  const PopupIPCTabContext& popupContext = appBrowser.get_PopupIPCTabContext();
+  const IPCTabContextUnion& contextUnion = aContext.contextUnion();
+  const PopupIPCTabContext& popupContext = contextUnion.get_PopupIPCTabContext();
 
   uint32_t chromeFlags = aChromeFlags;
 
   // CanOpenBrowser has ensured that the IPCTabContext is of
   // type PopupIPCTabContext, and that the opener TabParent is
   // reachable.
   auto opener = TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
   // We must ensure that the private browsing and remoteness flags