Backed out 12 changesets (bug 806127, bug 802366, bug 806168) for Windows build bustage.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 09 Nov 2012 20:14:40 -0500
changeset 112905 5dc1c0530b009ac3f893daa77d70bc9ce482074f
parent 112904 5eb2472d835d834df4a3965a96a898494e56cf9e
child 112906 e9c6c3ac7a762d18e3b0947021915b2d5859e928
push id17824
push userryanvm@gmail.com
push dateSat, 10 Nov 2012 01:14:44 +0000
treeherdermozilla-inbound@5dc1c0530b00 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs806127, 802366, 806168
milestone19.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
Backed out 12 changesets (bug 806127, bug 802366, bug 806168) for Windows build bustage.
caps/idl/nsIPrincipal.idl
caps/src/nsScriptSecurityManager.cpp
content/base/src/ThirdPartyUtil.cpp
content/base/src/nsDocument.cpp
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
content/base/src/nsInProcessTabChildGlobal.cpp
content/base/src/nsInProcessTabChildGlobal.h
content/events/src/nsEventStateManager.cpp
content/html/content/src/nsGenericHTMLFrameElement.cpp
docshell/base/nsDSURIContentListener.cpp
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
docshell/base/nsIDocShellTreeItem.idl
docshell/base/nsILoadContext.idl
dom/apps/src/Webapps.jsm
dom/base/nsGlobalWindow.cpp
dom/browser-element/BrowserElementParent.js
dom/browser-element/mochitest/Makefile.in
dom/browser-element/mochitest/browserElement_CookiesNotThirdParty.js
dom/browser-element/mochitest/file_browserElement_CookiesNotThirdParty.html
dom/browser-element/mochitest/test_browserElement_inproc_CookiesNotThirdParty.html
dom/browser-element/mochitest/test_browserElement_oop_CookiesNotThirdParty.html
dom/indexedDB/IndexedDatabaseManager.cpp
dom/indexedDB/IndexedDatabaseManager.h
dom/indexedDB/test/Makefile.in
dom/indexedDB/test/test_webapp_clearBrowserData.html
dom/indexedDB/test/test_webapp_clearBrowserData_inproc_inproc.html
dom/indexedDB/test/test_webapp_clearBrowserData_inproc_oop.html
dom/indexedDB/test/test_webapp_clearBrowserData_oop_inproc.html
dom/indexedDB/test/webapp_clearBrowserData.js
dom/indexedDB/test/webapp_clearBrowserData_appFrame.html
dom/indexedDB/test/webapp_clearBrowserData_browserFrame.html
dom/interfaces/html/nsIMozBrowserFrame.idl
dom/ipc/AppProcessPermissions.cpp
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/Makefile.in
dom/ipc/PContent.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabContext.cpp
dom/ipc/TabContext.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
embedding/components/windowwatcher/src/nsWindowWatcher.cpp
gfx/thebes/gfxAndroidPlatform.cpp
testing/mochitest/android.json
xpfe/appshell/src/nsContentTreeOwner.cpp
--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -16,17 +16,17 @@ struct JSPrincipals;
 
 interface nsIURI;
 interface nsIContentSecurityPolicy;
 
 [ptr] native JSContext(JSContext);
 [ptr] native JSPrincipals(JSPrincipals);
 [ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
 
-[scriptable, builtinclass, uuid(011966C0-8564-438D-B37A-08D7E1195E5A)]
+[scriptable, uuid(3a283dc9-f733-4618-a36f-e2b68c280ab7)]
 interface nsIPrincipal : nsISerializable
 {
     /**
      * Returns whether the other principal is equivalent to this principal.
      * Principals are considered equal if they are the same principal, or
      * they have the same origin.
      */
     boolean equals(in nsIPrincipal other);
@@ -154,76 +154,88 @@ interface nsIPrincipal : nsISerializable
     readonly attribute AUTF8String extendedOrigin;
 
     const short APP_STATUS_NOT_INSTALLED = 0;
     const short APP_STATUS_INSTALLED     = 1;
     const short APP_STATUS_PRIVILEGED    = 2;
     const short APP_STATUS_CERTIFIED     = 3;
 
     /**
-     * Gets the principal's app status, which indicates whether the principal
-     * corresponds to "app code", and if it does, how privileged that code is.
-     * This method returns one of the APP_STATUS constants above.
-     *
-     * Note that a principal may have
-     *
-     *   appId != nsIScriptSecurityManager::NO_APP_ID &&
-     *   appId != nsIScriptSecurityManager::UNKNOWN_APP_ID
-     *
-     * and still have appStatus == APP_STATUS_NOT_INSTALLED.  That's because
-     * appId identifies the app that contains this principal, but a window
-     * might be contained in an app and not be running code that the app has
-     * vouched for.  For example, the window might be inside an <iframe
-     * mozbrowser>, or the window's origin might not match the app's origin.
-     *
-     * If you're doing a check to determine "does this principal correspond to
-     * app code?", you must check appStatus; checking appId != NO_APP_ID is not
-     * sufficient.
+     * Shows the status of the app.
+     * Can be: APP_STATUS_NOT_INSTALLED, APP_STATUS_INSTALLED,
+     *         APP_STATUS_PRIVILEGED or APP_STATUS_CERTIFIED.
      */
-    [infallible] readonly attribute unsigned short appStatus;
+    readonly attribute unsigned short appStatus;
+
+    %{C++
+    uint16_t GetAppStatus()
+    {
+      uint16_t appStatus;
+      nsresult rv = GetAppStatus(&appStatus);
+      if (NS_FAILED(rv)) {
+        return APP_STATUS_NOT_INSTALLED;
+      }
+      return appStatus;
+    }
+    %}
 
     /**
-     * Gets the id of the app this principal is inside.  If this principal is
-     * not inside an app, returns nsIScriptSecurityManager::NO_APP_ID.
-     *
-     * Note that this principal does not necessarily have the permissions of
-     * the app identified by appId.  For example, this principal might
-     * correspond to an iframe whose origin differs from that of the app frame
-     * containing it.  In this case, the iframe will have the appId of its
-     * containing app frame, but the iframe must not run with the app's
-     * permissions.
-     *
-     * Similarly, this principal might correspond to an <iframe mozbrowser>
-     * inside an app frame; in this case, the content inside the iframe should
-     * not have any of the app's permissions, even if the iframe is at the same
-     * origin as the app.
-     *
-     * If you're doing a security check based on appId, you must check
-     * appStatus as well.
+     * Returns the app id the principal is in, or returns
+     * nsIScriptSecurityManager::NO_APP_ID if this principal isn't part of an
+     * app.
      */
-    [infallible] readonly attribute unsigned long appId;
+    readonly attribute unsigned long appId;
+
+    %{C++
+    uint32_t GetAppId()
+    {
+      uint32_t appId;
+      mozilla::DebugOnly<nsresult> rv = GetAppId(&appId);
+      MOZ_ASSERT(NS_SUCCEEDED(rv));
+      return appId;
+    }
+    %}
 
     /**
-     * Returns true iff the principal is inside a browser element.  (<iframe
-     * mozbrowser mozapp> does not count as a browser element.)
+     * Returns true iif the principal is inside a browser element.
      */
-    [infallible] readonly attribute boolean isInBrowserElement;
+    readonly attribute boolean isInBrowserElement;
+
+    %{C++
+    bool GetIsInBrowserElement()
+    {
+      bool isInBrowserElement;
+      mozilla::DebugOnly<nsresult> rv = GetIsInBrowserElement(&isInBrowserElement);
+      MOZ_ASSERT(NS_SUCCEEDED(rv));
+      return isInBrowserElement;
+    }
+    %}
 
     /**
      * Returns true if this principal has an unknown appId. This shouldn't
      * generally be used. We only expose it due to not providing the correct
      * appId everywhere where we construct principals.
      */
-    [infallible] readonly attribute boolean unknownAppId;
+    readonly attribute boolean unknownAppId;
+
+    %{C++
+    bool GetUnknownAppId()
+    {
+      bool unkwnownAppId;
+      mozilla::DebugOnly<nsresult> rv = GetUnknownAppId(&unkwnownAppId);
+      MOZ_ASSERT(NS_SUCCEEDED(rv));
+      return unkwnownAppId;
+    }
+    %}
 
     /**
      * Returns true iff this principal is a null principal (corresponding to an
      * unknown, hence assumed minimally privileged, security context).
      */
-    [infallible] readonly attribute boolean isNullPrincipal;
+    readonly attribute boolean isNullPrincipal;
 };
 
 /**
  * If nsSystemPrincipal is too risky to use, but we want a principal to access 
  * more than one origin, nsExpandedPrincipals letting us define an array of 
  * principals it subsumes. So script with an nsExpandedPrincipals will gain
  * same origin access when at least one of its principals it contains gained 
  * sameorigin acccess. An nsExpandedPrincipal will be subsumed by the system
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -330,25 +330,29 @@ nsScriptSecurityManager::GetChannelPrinc
     }
 
     // OK, get the principal from the URI.  Make sure this does the same thing
     // as nsDocument::Reset and nsXULDocument::StartDocumentLoad.
     nsCOMPtr<nsIURI> uri;
     nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
     NS_ENSURE_SUCCESS(rv, rv);
 
+    uint32_t appId = UNKNOWN_APP_ID;
+    bool isInBrowserElement = false;
+
     nsCOMPtr<nsIDocShell> docShell;
     NS_QueryNotificationCallbacks(aChannel, docShell);
 
     if (docShell) {
-        return GetDocShellCodebasePrincipal(uri, docShell, aPrincipal);
+        docShell->GetAppId(&appId);
+        docShell->GetIsInBrowserElement(&isInBrowserElement);
     }
 
-    return GetCodebasePrincipalInternal(uri, UNKNOWN_APP_ID,
-        /* isInBrowserElement */ false, aPrincipal);
+    return GetCodebasePrincipalInternal(uri, appId, isInBrowserElement,
+                                        aPrincipal);
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::IsSystemPrincipal(nsIPrincipal* aPrincipal,
                                            bool* aIsSystem)
 {
     *aIsSystem = (aPrincipal == mSystemPrincipal);
     return NS_OK;
@@ -1894,19 +1898,24 @@ nsScriptSecurityManager::GetAppCodebaseP
   return GetCodebasePrincipalInternal(aURI, aAppId, aInMozBrowser, aPrincipal);
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI* aURI,
                                                       nsIDocShell* aDocShell,
                                                       nsIPrincipal** aPrincipal)
 {
-  return GetCodebasePrincipalInternal(aURI,
-                                      aDocShell->GetAppId(),
-                                      aDocShell->GetIsInBrowserElement(),
+  MOZ_ASSERT(aDocShell);
+
+  uint32_t appId;
+  bool isInBrowserElement;
+  aDocShell->GetAppId(&appId);
+  aDocShell->GetIsInBrowserElement(&isInBrowserElement);
+
+  return GetCodebasePrincipalInternal(aURI, appId, isInBrowserElement,
                                       aPrincipal);
 }
 
 nsresult
 nsScriptSecurityManager::GetCodebasePrincipalInternal(nsIURI *aURI,
                                                       uint32_t aAppId,
                                                       bool aInMozBrowser,
                                                       nsIPrincipal **result)
--- a/content/base/src/ThirdPartyUtil.cpp
+++ b/content/base/src/ThirdPartyUtil.cpp
@@ -110,19 +110,17 @@ ThirdPartyUtil::IsThirdPartyWindow(nsIDO
       *aResult = true;
       return NS_OK;
     }
   }
 
   nsCOMPtr<nsIDOMWindow> current = aWindow, parent;
   nsCOMPtr<nsIURI> parentURI;
   do {
-    // We use GetScriptableParent rather than GetParent because we consider
-    // <iframe mozbrowser/mozapp> to be a top-level frame.
-    rv = current->GetScriptableParent(getter_AddRefs(parent));
+    rv = current->GetParent(getter_AddRefs(parent));
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (SameCOMIdentity(parent, current)) {
       // We're at the topmost content window. We already know the answer.
       *aResult = false;
       return NS_OK;
     }
 
@@ -207,19 +205,17 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIC
   // If there is no window, the consumer kicking off the load didn't provide one
   // to the channel. This is limited to loads of certain types of resources. If
   // those loads require cookies, the forceAllowThirdPartyCookie property should
   // be set on the channel.
   nsCOMPtr<nsIDOMWindow> ourWin, parentWin;
   ctx->GetAssociatedWindow(getter_AddRefs(ourWin));
   if (!ourWin) return NS_ERROR_INVALID_ARG;
 
-  // We use GetScriptableParent rather than GetParent because we consider
-  // <iframe mozbrowser/mozapp> to be a top-level frame.
-  ourWin->GetScriptableParent(getter_AddRefs(parentWin));
+  ourWin->GetParent(getter_AddRefs(parentWin));
   NS_ENSURE_TRUE(parentWin, NS_ERROR_INVALID_ARG);
 
   // Check whether this is the document channel for this window (representing a
   // load of a new page). In that situation we want to avoid comparing
   // channelURI to ourWin, since what's in ourWin right now will be replaced as
   // the channel loads.  This covers the case of a freshly kicked-off load
   // (e.g. the user typing something in the location bar, or clicking on a
   // bookmark), where the window's URI hasn't yet been set, and will be bogus.
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -8354,17 +8354,17 @@ HasCrossProcessParent(nsIDocument* aDocu
   nsPIDOMWindow* win = aDocument->GetWindow();
   if (!win) {
     return false;
   }
   nsCOMPtr<nsIDocShell> docShell = win->GetDocShell();
   if (!docShell) {
     return false;
   }
-  return docShell->GetIsBrowserOrApp();
+  return docShell->GetIsContentBoundary();
 }
 
 static bool
 ResetFullScreen(nsIDocument* aDocument, void* aData)
 {
   if (aDocument->IsFullScreenDoc()) {
     static_cast<nsDocument*>(aDocument)->CleanupFullscreenState();
     NS_ASSERTION(!aDocument->IsFullScreenDoc(), "Should reset full-screen");
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -939,17 +939,17 @@ nsFrameLoader::ShowRemoteFrame(const nsI
     }
 
     mRemoteBrowser->Show(size);
     mRemoteBrowserShown = true;
 
     EnsureMessageManager();
 
     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
-    if (OwnerIsBrowserOrAppFrame() && os && !mRemoteBrowserInitialized) {
+    if (OwnerIsBrowserFrame() && os && !mRemoteBrowserInitialized) {
       os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
                           "remote-browser-frame-shown", NULL);
       mRemoteBrowserInitialized = true;
     }
   } else {
     nsRect dimensions;
     NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), false);
     mRemoteBrowser->UpdateDimensions(dimensions, size);
@@ -1388,114 +1388,72 @@ nsFrameLoader::SetOwnerContent(Element* 
   }
   mOwnerContent = aContent;
   if (RenderFrameParent* rfp = GetCurrentRemoteFrame()) {
     rfp->OwnerContentChanged(aContent);
   }
 }
 
 bool
-nsFrameLoader::OwnerIsBrowserOrAppFrame()
+nsFrameLoader::OwnerIsBrowserFrame()
 {
   nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
-  return browserFrame ? browserFrame->GetReallyIsBrowserOrApp() : false;
+  bool isBrowser = false;
+  if (browserFrame) {
+    browserFrame->GetReallyIsBrowser(&isBrowser);
+  }
+  return isBrowser;
 }
 
 bool
 nsFrameLoader::OwnerIsAppFrame()
 {
   nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
-  return browserFrame ? browserFrame->GetReallyIsApp() : false;
-}
-
-bool
-nsFrameLoader::OwnerIsBrowserFrame()
-{
-  return OwnerIsBrowserOrAppFrame() && !OwnerIsAppFrame();
+  bool isApp = false;
+  if (browserFrame) {
+    browserFrame->GetReallyIsApp(&isApp);
+  }
+  return isApp;
 }
 
 void
 nsFrameLoader::GetOwnerAppManifestURL(nsAString& aOut)
 {
   aOut.Truncate();
   nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
   if (browserFrame) {
     browserFrame->GetAppManifestURL(aOut);
   }
 }
 
-already_AddRefed<mozIApplication>
-nsFrameLoader::GetOwnApp()
-{
-  nsAutoString manifest;
-  GetOwnerAppManifestURL(manifest);
-  if (manifest.IsEmpty()) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(appsService, nullptr);
-
-  nsCOMPtr<mozIDOMApplication> domApp;
-  appsService->GetAppByManifestURL(manifest, getter_AddRefs(domApp));
-
-  nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp);
-  MOZ_ASSERT_IF(domApp, app);
-  return app.forget();
-}
-
-already_AddRefed<mozIApplication>
-nsFrameLoader::GetContainingApp()
-{
-  // See if our owner content's principal has an associated app.
-  uint32_t appId = mOwnerContent->NodePrincipal()->GetAppId();
-  MOZ_ASSERT(appId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
-
-  if (appId == nsIScriptSecurityManager::NO_APP_ID ||
-      appId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(appsService, nullptr);
-
-  nsCOMPtr<mozIDOMApplication> domApp;
-  appsService->GetAppByLocalId(appId, getter_AddRefs(domApp));
-  MOZ_ASSERT(domApp);
-
-  nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp);
-  MOZ_ASSERT_IF(domApp, app);
-  return app.forget();
-}
-
 bool
 nsFrameLoader::ShouldUseRemoteProcess()
 {
   if (PR_GetEnv("MOZ_DISABLE_OOP_TABS") ||
       Preferences::GetBool("dom.ipc.tabs.disabled", false)) {
     return false;
   }
 
   // If we're inside a content process, don't use a remote process for this
   // frame; it won't work properly until bug 761935 is fixed.
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     return false;
   }
 
   // If we're an <iframe mozbrowser> and we don't have a "remote" attribute,
   // fall back to the default.
-  if (OwnerIsBrowserOrAppFrame() &&
+  if (OwnerIsBrowserFrame() &&
       !mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::Remote)) {
 
     return Preferences::GetBool("dom.ipc.browser_frames.oop_by_default", false);
   }
 
   // Otherwise, we're remote if we have "remote=true" and we're either a
   // browser frame or a XUL element.
-  return (OwnerIsBrowserOrAppFrame() ||
+  return (OwnerIsBrowserFrame() ||
           mOwnerContent->GetNameSpaceID() == kNameSpaceID_XUL) &&
          mOwnerContent->AttrValueIs(kNameSpaceID_None,
                                     nsGkAtoms::Remote,
                                     nsGkAtoms::_true,
                                     eCaseMatters);
 }
 
 nsresult
@@ -1532,16 +1490,34 @@ nsFrameLoader::MaybeCreateDocShell()
     doc->GetContainer();
   nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(container);
   NS_ENSURE_STATE(parentAsWebNav);
 
   // Create the docshell...
   mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
+  if (OwnerIsBrowserFrame()) {
+    nsAutoString manifest;
+    GetOwnerAppManifestURL(manifest);
+    if (!manifest.IsEmpty()) {
+      nsCOMPtr<nsIAppsService> appsService =
+        do_GetService(APPS_SERVICE_CONTRACTID);
+      if (!appsService) {
+        NS_ERROR("Apps Service is not available!");
+        return NS_ERROR_FAILURE;
+      }
+
+      uint32_t appId;
+      appsService->GetAppLocalIdByManifestURL(manifest, &appId);
+
+      mDocShell->SetAppId(appId);
+    }
+  }
+
   if (!mNetworkCreated) {
     nsCOMPtr<nsIDocShellHistory> history = do_QueryInterface(mDocShell);
     if (history) {
       history->SetCreatedDynamically(true);
     }
   }
 
   // Get the frame name and tell the docshell about it.
@@ -1633,48 +1609,23 @@ nsFrameLoader::MaybeCreateDocShell()
   if (NS_FAILED(base_win->Create()) || !win_private) {
     // Do not call Destroy() here. See bug 472312.
     NS_WARNING("Something wrong when creating the docshell for a frameloader!");
     return NS_ERROR_FAILURE;
   }
 
   EnsureMessageManager();
 
-  if (OwnerIsAppFrame()) {
-    // You can't be both an app and a browser frame.
-    MOZ_ASSERT(!OwnerIsBrowserFrame());
-
-    nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
-    MOZ_ASSERT(ownApp);
-    uint32_t ownAppId = nsIScriptSecurityManager::NO_APP_ID;
-    if (ownApp) {
-      NS_ENSURE_SUCCESS(ownApp->GetLocalId(&ownAppId), NS_ERROR_FAILURE);
-    }
-
-    mDocShell->SetIsApp(ownAppId);
-  }
+  if (OwnerIsBrowserFrame()) {
+    mDocShell->SetIsBrowserElement();
 
-  if (OwnerIsBrowserFrame()) {
-    // You can't be both a browser and an app frame.
-    MOZ_ASSERT(!OwnerIsAppFrame());
-
-    nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
-    uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID;
-    if (containingApp) {
-      NS_ENSURE_SUCCESS(containingApp->GetLocalId(&containingAppId),
-                        NS_ERROR_FAILURE);
-    }
-    mDocShell->SetIsBrowserInsideApp(containingAppId);
-  }
-
-  if (OwnerIsBrowserOrAppFrame()) {
     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
     if (os) {
       os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
-                          "in-process-browser-or-app-frame-shown", NULL);
+                          "in-process-browser-frame-shown", NULL);
     }
 
     if (mMessageManager) {
       mMessageManager->LoadFrameScript(
         NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js"),
         /* allowDelayedLoad = */ true);
     }
   }
@@ -1992,17 +1943,17 @@ nsFrameLoader::TryRemoteBrowser()
 
   if (!parentAsWebNav) {
     return false;
   }
 
   nsCOMPtr<nsIDocShellTreeItem> parentAsItem(do_QueryInterface(parentAsWebNav));
 
   // <iframe mozbrowser> gets to skip these checks.
-  if (!OwnerIsBrowserOrAppFrame()) {
+  if (!OwnerIsBrowserFrame()) {
     int32_t parentType;
     parentAsItem->GetItemType(&parentType);
 
     if (parentType != nsIDocShellTreeItem::typeChrome) {
       return false;
     }
 
     if (!mOwnerContent->IsXUL()) {
@@ -2028,28 +1979,45 @@ nsFrameLoader::TryRemoteBrowser()
   nsCOMPtr<nsIXULWindow> window(do_GetInterface(parentOwner));
   if (!window) {
     return false;
   }
   if (NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
     return false;
   }
 
-  MutableTabContext context;
-  nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
-  nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
-  if (ownApp) {
-    context.SetTabContextForAppFrame(ownApp, containingApp);
-  } else if (OwnerIsBrowserFrame()) {
-    // The |else| above is unnecessary; OwnerIsBrowserFrame() implies !ownApp.
-    context.SetTabContextForBrowserFrame(containingApp);
+  bool isBrowserElement = false;
+  nsCOMPtr<mozIApplication> app;
+  if (OwnerIsBrowserFrame()) {
+    isBrowserElement = true;
+
+    nsAutoString manifest;
+    GetOwnerAppManifestURL(manifest);
+    if (!manifest.IsEmpty()) {
+      nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
+      if (!appsService) {
+        NS_ERROR("Apps Service is not available!");
+        return false;
+      }
+
+      nsCOMPtr<mozIDOMApplication> domApp;
+      appsService->GetAppByManifestURL(manifest, getter_AddRefs(domApp));
+      // If the frame is actually an app, we should not mark it as a
+      // browser.  This is to identify the data store: since <app>s
+      // and <browser>s-within-<app>s have different stores, we want
+      // to ensure the <app> uses its store, not the one for its
+      // <browser>s.
+      app = do_QueryInterface(domApp);
+      if (app) {
+        isBrowserElement = false;
+      }
+    }
   }
 
-  mRemoteBrowser = ContentParent::CreateBrowserOrApp(context);
-  if (mRemoteBrowser) {
+  if ((mRemoteBrowser = ContentParent::CreateBrowser(app, isBrowserElement))) {
     nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mOwnerContent);
     mRemoteBrowser->SetOwnerElement(element);
 
     nsCOMPtr<nsIDocShellTreeItem> rootItem;
     parentAsItem->GetRootTreeItem(getter_AddRefs(rootItem));
     nsCOMPtr<nsIDOMWindow> rootWin = do_GetInterface(rootItem);
     nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(rootWin);
     NS_ABORT_IF_FALSE(rootChromeWin, "How did we not get a chrome window here?");
@@ -2349,17 +2317,17 @@ nsFrameLoader::EnsureMessageManager()
 {
   NS_ENSURE_STATE(mOwnerContent);
 
   nsresult rv = MaybeCreateDocShell();
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  if (!mIsTopLevelContent && !OwnerIsBrowserOrAppFrame() && !mRemoteFrame) {
+  if (!mIsTopLevelContent && !OwnerIsBrowserFrame() && !mRemoteFrame) {
     return NS_OK;
   }
 
   if (mMessageManager) {
     if (ShouldUseRemoteProcess()) {
       mMessageManager->SetCallback(mRemoteBrowserShown ? this : nullptr);
     }
     return NS_OK;
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -28,17 +28,16 @@ class nsIURI;
 class nsSubDocumentFrame;
 class nsIView;
 class nsIInProcessContentFrameMessageManager;
 class AutoResetInShow;
 class nsITabParent;
 class nsIDocShellTreeItem;
 class nsIDocShellTreeOwner;
 class nsIDocShellTreeNode;
-class mozIApplication;
 
 namespace mozilla {
 namespace dom {
 class PBrowserParent;
 class TabParent;
 struct StructuredCloneData;
 }
 
@@ -309,50 +308,33 @@ private:
 
   void SetOwnerContent(mozilla::dom::Element* aContent);
 
   bool ShouldUseRemoteProcess();
 
   /**
    * Is this a frameloader for a bona fide <iframe mozbrowser> or
    * <iframe mozapp>?  (I.e., does the frame return true for
-   * nsIMozBrowserFrame::GetReallyIsBrowserOrApp()?)
+   * nsIMozBrowserFrame::GetReallyIsBrowser()?)
    */
-  bool OwnerIsBrowserOrAppFrame();
+  bool OwnerIsBrowserFrame();
 
   /**
    * Is this a frameloader for a bona fide <iframe mozapp>?  (I.e., does the
    * frame return true for nsIMozBrowserFrame::GetReallyIsApp()?)
    */
   bool OwnerIsAppFrame();
 
   /**
-   * Is this a frame loader for a bona fide <iframe mozbrowser>?
-   */
-  bool OwnerIsBrowserFrame();
-
-  /**
    * Get our owning element's app manifest URL, or return the empty string if
    * our owning element doesn't have an app manifest URL.
    */
   void GetOwnerAppManifestURL(nsAString& aOut);
 
   /**
-   * Get the app for our frame.  This is the app whose manifest is returned by
-   * GetOwnerAppManifestURL.
-   */
-  already_AddRefed<mozIApplication> GetOwnApp();
-
-  /**
-   * Get the app which contains this frame.  This is the app associated with
-   * the frame element's principal.
-   */
-  already_AddRefed<mozIApplication> GetContainingApp();
-
-  /**
    * If we are an IPC frame, set mRemoteFrame. Otherwise, create and
    * initialize mDocShell.
    */
   nsresult MaybeCreateDocShell();
   nsresult EnsureMessageManager();
   NS_HIDDEN_(void) GetURL(nsString& aURL);
 
   // Properly retrieves documentSize of any subdocument type.
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -92,25 +92,24 @@ nsInProcessTabChildGlobal::DoSendAsyncMe
 
 nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
                                                      nsIContent* aOwner,
                                                      nsFrameMessageManager* aChrome)
 : mDocShell(aShell), mInitialized(false), mLoadingScript(false),
   mDelayedDisconnect(false), mOwner(aOwner), mChromeMessageManager(aChrome)
 {
 
-  // If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll
-  // have to tweak our PreHandleEvent implementation.
+  // If owner corresponds to an <iframe mozbrowser>, we'll have to tweak our
+  // PreHandleEvent implementation.
   nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner);
+  bool isBrowser = false;
   if (browserFrame) {
-    mIsBrowserOrAppFrame = browserFrame->GetReallyIsBrowserOrApp();
+    browserFrame->GetReallyIsBrowser(&isBrowser);
   }
-  else {
-    mIsBrowserOrAppFrame = false;
-  }
+  mIsBrowserFrame = isBrowser;
 }
 
 nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
 {
   NS_ASSERTION(!mCx, "Couldn't release JSContext?!?");
 }
 
 /* [notxpcom] boolean markForCC (); */
@@ -264,17 +263,17 @@ nsInProcessTabChildGlobal::GetOwnerConte
   return mOwner;
 }
 
 nsresult
 nsInProcessTabChildGlobal::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   aVisitor.mCanHandle = true;
 
-  if (mIsBrowserOrAppFrame &&
+  if (mIsBrowserFrame &&
       (!mOwner || !nsContentUtils::IsInChromeDocshell(mOwner->OwnerDoc()))) {
     if (mOwner) {
       nsPIDOMWindow* innerWindow = mOwner->OwnerDoc()->GetInnerWindow();
       if (innerWindow) {
         aVisitor.mParentTarget = innerWindow->GetParentTarget();
       }
     }
   } else {
--- a/content/base/src/nsInProcessTabChildGlobal.h
+++ b/content/base/src/nsInProcessTabChildGlobal.h
@@ -117,19 +117,18 @@ protected:
   nsresult Init();
   nsresult InitTabChildGlobal();
   nsCOMPtr<nsIContentFrameMessageManager> mMessageManager;
   nsCOMPtr<nsIDocShell> mDocShell;
   bool mInitialized;
   bool mLoadingScript;
   bool mDelayedDisconnect;
 
-  // Is this the message manager for an in-process <iframe mozbrowser> or
-  // <iframe mozapp>?  This affects where events get sent, so it affects
-  // PreHandleEvent.
-  bool mIsBrowserOrAppFrame;
+  // Is this the message manager for an in-process <iframe mozbrowser>?  This
+  // affects where events get sent, so it affects PreHandleEvent.
+  bool mIsBrowserFrame;
 public:
   nsIContent* mOwner;
   nsFrameMessageManager* mChromeMessageManager;
   nsTArray<nsCOMPtr<nsIRunnable> > mASyncMessages;
 };
 
 #endif
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -1565,20 +1565,24 @@ nsEventStateManager::IsRemoteTarget(nsIC
   if ((target->Tag() == nsGkAtoms::browser ||
        target->Tag() == nsGkAtoms::iframe) &&
       target->IsXUL() &&
       target->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
                           nsGkAtoms::_true, eIgnoreCase)) {
     return true;
   }
 
-  // <frame/iframe mozbrowser/mozapp>
+  // <frame/iframe mozbrowser>
   nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(target);
-  if (browserFrame && browserFrame->GetReallyIsBrowserOrApp()) {
-    return !!TabParent::GetFrom(target);
+  if (browserFrame) {
+    bool isBrowser = false;
+    browserFrame->GetReallyIsBrowser(&isBrowser);
+    if (isBrowser) {
+      return !!TabParent::GetFrom(target);
+    }
   }
 
   return false;
 }
 
 /*static*/ void
 nsEventStateManager::MapEventCoordinatesForChildProcess(nsFrameLoader* aFrameLoader,
                                                         nsEvent* aEvent)
--- a/content/html/content/src/nsGenericHTMLFrameElement.cpp
+++ b/content/html/content/src/nsGenericHTMLFrameElement.cpp
@@ -273,71 +273,73 @@ nsGenericHTMLFrameElement::IsHTMLFocusab
   return false;
 }
 
 /**
  * Return true if this frame element really is a mozbrowser or mozapp.  (It
  * needs to have the right attributes, and its creator must have the right
  * permissions.)
  */
-/* [infallible] */ nsresult
-nsGenericHTMLFrameElement::GetReallyIsBrowserOrApp(bool *aOut)
+nsresult
+nsGenericHTMLFrameElement::GetReallyIsBrowser(bool *aOut)
 {
   *aOut = false;
 
   // Fail if browser frames are globally disabled.
   if (!Preferences::GetBool("dom.mozBrowserFramesEnabled")) {
     return NS_OK;
   }
 
   // Fail if this frame doesn't have the mozbrowser attribute.
-  bool hasMozbrowser = false;
-  GetMozbrowser(&hasMozbrowser);
-  if (!hasMozbrowser) {
+  bool isBrowser = false;
+  GetMozbrowser(&isBrowser);
+  if (!isBrowser) {
     return NS_OK;
   }
 
   // Fail if the node principal isn't trusted.
   nsIPrincipal *principal = NodePrincipal();
   nsCOMPtr<nsIPermissionManager> permMgr =
     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
-  NS_ENSURE_TRUE(permMgr, NS_OK);
+  NS_ENSURE_STATE(permMgr);
 
   uint32_t permission = nsIPermissionManager::DENY_ACTION;
   nsresult rv = permMgr->TestPermissionFromPrincipal(principal, "browser", &permission);
   NS_ENSURE_SUCCESS(rv, NS_OK);
   *aOut = permission == nsIPermissionManager::ALLOW_ACTION;
   return NS_OK;
 }
 
-/* [infallible] */ NS_IMETHODIMP
+NS_IMETHODIMP
 nsGenericHTMLFrameElement::GetReallyIsApp(bool *aOut)
 {
   nsAutoString manifestURL;
   GetAppManifestURL(manifestURL);
 
   *aOut = !manifestURL.IsEmpty();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGenericHTMLFrameElement::GetAppManifestURL(nsAString& aOut)
 {
   aOut.Truncate();
 
   // At the moment, you can't be an app without being a browser.
-  if (!nsIMozBrowserFrame::GetReallyIsBrowserOrApp()) {
+  bool isBrowser = false;
+  GetReallyIsBrowser(&isBrowser);
+  if (!isBrowser) {
     return NS_OK;
   }
 
   // Check permission.
   nsIPrincipal *principal = NodePrincipal();
   nsCOMPtr<nsIPermissionManager> permMgr =
     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
-  NS_ENSURE_TRUE(permMgr, NS_OK);
+  NS_ENSURE_STATE(permMgr);
 
   uint32_t permission = nsIPermissionManager::DENY_ACTION;
   nsresult rv = permMgr->TestPermissionFromPrincipal(principal,
                                                      "embed-apps",
                                                      &permission);
   NS_ENSURE_SUCCESS(rv, NS_OK);
   if (permission != nsIPermissionManager::ALLOW_ACTION) {
     return NS_OK;
@@ -345,20 +347,21 @@ nsGenericHTMLFrameElement::GetAppManifes
 
   nsAutoString manifestURL;
   GetAttr(kNameSpaceID_None, nsGkAtoms::mozapp, manifestURL);
   if (manifestURL.IsEmpty()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(appsService, NS_OK);
+  NS_ENSURE_STATE(appsService);
 
   nsCOMPtr<mozIDOMApplication> app;
   appsService->GetAppByManifestURL(manifestURL, getter_AddRefs(app));
+
   if (app) {
     aOut.Assign(manifestURL);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/docshell/base/nsDSURIContentListener.cpp
+++ b/docshell/base/nsDSURIContentListener.cpp
@@ -321,17 +321,17 @@ bool nsDSURIContentListener::CheckOneFra
 
     // Traverse up the parent chain and stop when we see a docshell whose
     // parent has a system principal, or a docshell corresponding to
     // <iframe mozbrowser>.
     while (NS_SUCCEEDED(curDocShellItem->GetParent(getter_AddRefs(parentDocShellItem))) &&
            parentDocShellItem) {
 
         nsCOMPtr<nsIDocShell> curDocShell = do_QueryInterface(curDocShellItem);
-        if (curDocShell && curDocShell->GetIsBrowserOrApp()) {
+        if (curDocShell && curDocShell->GetIsContentBoundary()) {
           break;
         }
 
         bool system = false;
         topDoc = do_GetInterface(parentDocShellItem);
         if (topDoc) {
             if (NS_SUCCEEDED(ssm->IsSystemPrincipal(topDoc->NodePrincipal(),
                                                     &system)) && system) {
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -725,17 +725,16 @@ static uint64_t gDocshellIDCounter = 0;
 nsDocShell::nsDocShell():
     nsDocLoader(),
     mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto),
     mTreeOwner(nullptr),
     mChromeEventHandler(nullptr),
     mCharsetReloadState(eCharsetReloadInit),
     mChildOffset(0),
     mBusyFlags(BUSY_FLAGS_NONE),
-    mFrameType(eFrameTypeRegular),
     mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
     mLoadType(0),
     mMarginWidth(-1),
     mMarginHeight(-1),
     mItemType(typeContent),
     mPreviousTransIndex(-1),
     mLoadedTransIndex(-1),
     mSandboxFlags(0),
@@ -763,17 +762,17 @@ nsDocShell::nsDocShell():
     mURIResultedInDocument(false),
     mIsBeingDestroyed(false),
     mIsExecutingOnLoadHandler(false),
     mIsPrintingOrPP(false),
     mSavingOldViewer(false),
 #ifdef DEBUG
     mInEnsureScriptEnv(false),
 #endif
-    mOwnOrContainingAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID),
+    mAppId(nsIScriptSecurityManager::NO_APP_ID),
     mParentCharsetSource(0)
 {
     mHistoryID = ++gDocshellIDCounter;
     if (gDocShellCount++ == 0) {
         NS_ASSERTION(sURIFixup == nullptr,
                      "Huh, sURIFixup not null in first nsDocShell ctor!");
 
         CallGetService(NS_URIFIXUP_CONTRACTID, &sURIFixup);
@@ -2146,29 +2145,29 @@ NS_IMETHODIMP nsDocShell::SetAllowWindow
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
 {
     NS_ENSURE_ARG_POINTER(aFullscreenAllowed);
 
-    // Browsers and apps have their mFullscreenAllowed retrieved from their
+    // Content boundaries have their mFullscreenAllowed retrieved from their
     // corresponding iframe in their parent upon creation.
     if (mFullscreenAllowed != CHECK_ATTRIBUTES) {
         *aFullscreenAllowed = (mFullscreenAllowed == PARENT_ALLOWS);
         return NS_OK;
     }
 
     // Assume false until we determine otherwise...
     *aFullscreenAllowed = false;
 
-    // For non-browsers/apps, check that the enclosing iframe element
+    // For non-content boundaries, check that the enclosing iframe element
     // has the allowfullscreen attribute set to true. If any ancestor
-    // iframe does not have mozallowfullscreen=true, then fullscreen is
+    // iframe does not have allowfullscreen=true, then fullscreen is
     // prohibited.
     nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(GetAsSupports(this));
     if (!win) {
         return NS_OK;
     }
     nsCOMPtr<nsIContent> frameElement = do_QueryInterface(win->GetFrameElementInternal());
     if (frameElement &&
         frameElement->IsHTML(nsGkAtoms::iframe) &&
@@ -2195,17 +2194,17 @@ nsDocShell::GetFullscreenAllowed(bool* a
     NS_ENSURE_TRUE(parent, NS_OK);
     
     return parent->GetFullscreenAllowed(aFullscreenAllowed);
 }
 
 NS_IMETHODIMP
 nsDocShell::SetFullscreenAllowed(bool aFullscreenAllowed)
 {
-    if (!nsIDocShell::GetIsBrowserOrApp()) {
+    if (!nsIDocShell::GetIsContentBoundary()) {
         // Only allow setting of fullscreenAllowed on content/process boundaries.
         // At non-boundaries the fullscreenAllowed attribute is calculated based on
         // whether all enclosing frames have the "mozFullscreenAllowed" attribute
         // set to "true". fullscreenAllowed is set at the process boundaries to
         // propagate the value of the parent's "mozFullscreenAllowed" attribute
         // across process boundaries.
         return NS_ERROR_UNEXPECTED;
     }
@@ -2807,17 +2806,17 @@ nsDocShell::SetDocLoaderParent(nsDocLoad
 }
 
 NS_IMETHODIMP
 nsDocShell::GetSameTypeParent(nsIDocShellTreeItem ** aParent)
 {
     NS_ENSURE_ARG_POINTER(aParent);
     *aParent = nullptr;
 
-    if (nsIDocShell::GetIsBrowserOrApp()) {
+    if (mIsBrowserFrame) {
         return NS_OK;
     }
 
     nsCOMPtr<nsIDocShellTreeItem> parent =
         do_QueryInterface(GetAsSupports(mParent));
     if (!parent)
         return NS_OK;
 
@@ -2826,17 +2825,17 @@ nsDocShell::GetSameTypeParent(nsIDocShel
 
     if (parentType == mItemType) {
         parent.swap(*aParent);
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDocShell::GetSameTypeParentIgnoreBrowserAndAppBoundaries(nsIDocShell** aParent)
+nsDocShell::GetParentIgnoreBrowserFrame(nsIDocShell** aParent)
 {
     NS_ENSURE_ARG_POINTER(aParent);
     *aParent = nullptr;
 
     nsCOMPtr<nsIDocShellTreeItem> parent =
         do_QueryInterface(GetAsSupports(mParent));
     if (!parent)
         return NS_OK;
@@ -2929,21 +2928,29 @@ nsDocShell::CanAccessItem(nsIDocShellTre
 
     nsCOMPtr<nsIDocShell> targetDS = do_QueryInterface(aTargetItem);
     nsCOMPtr<nsIDocShell> accessingDS = do_QueryInterface(aAccessingItem);
     if (!!targetDS != !!accessingDS) {
         // We must be able to convert both or neither to nsIDocShell.
         return false;
     }
 
-    if (targetDS && accessingDS &&
-        (targetDS->GetIsInBrowserElement() !=
-           accessingDS->GetIsInBrowserElement() ||
-         targetDS->GetAppId() != accessingDS->GetAppId())) {
-        return false;
+    if (targetDS && accessingDS) {
+        bool targetInBrowser = false, accessingInBrowser = false;
+        targetDS->GetIsInBrowserElement(&targetInBrowser);
+        accessingDS->GetIsInBrowserElement(&accessingInBrowser);
+
+        uint32_t targetAppId = 0, accessingAppId = 0;
+        targetDS->GetAppId(&targetAppId);
+        accessingDS->GetAppId(&accessingAppId);
+
+        if (targetInBrowser != accessingInBrowser ||
+            targetAppId != accessingAppId) {
+            return false;
+        }
     }
 
     nsCOMPtr<nsIDocShellTreeItem> accessingRoot;
     aAccessingItem->GetSameTypeRootTreeItem(getter_AddRefs(accessingRoot));
 
     if (aTargetItem == accessingRoot) {
         // A frame can navigate its root.
         return true;
@@ -5217,17 +5224,17 @@ nsDocShell::SetIsActive(bool aIsActive)
   // children; they handle their state separately.
   int32_t n = mChildList.Count();
   for (int32_t i = 0; i < n; ++i) {
       nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(ChildAt(i));
       if (!docshell) {
           continue;
       }
 
-      if (!docshell->GetIsBrowserOrApp()) {
+      if (!docshell->GetIsContentBoundary()) {
           docshell->SetIsActive(aIsActive);
       }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -12299,118 +12306,148 @@ nsDocShell::GetCanExecuteScripts(bool *a
 #endif // DEBUG
       } while (treeItem && docshell);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDocShell::SetIsApp(uint32_t aOwnAppId)
-{
-    mOwnOrContainingAppId = aOwnAppId;
-    if (aOwnAppId != nsIScriptSecurityManager::NO_APP_ID &&
-        aOwnAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
-        mFrameType = eFrameTypeApp;
-    } else {
-        mFrameType = eFrameTypeRegular;
-    }
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDocShell::SetIsBrowserInsideApp(uint32_t aContainingAppId)
-{
-    mOwnOrContainingAppId = aContainingAppId;
-    mFrameType = eFrameTypeBrowser;
-    return NS_OK;
-}
-
-/* [infallible] */ NS_IMETHODIMP
-nsDocShell::GetIsBrowserElement(bool* aIsBrowser)
-{
-    *aIsBrowser = (mFrameType == eFrameTypeBrowser);
-    return NS_OK;
-}
-
-/* [infallible] */ NS_IMETHODIMP
-nsDocShell::GetIsApp(bool* aIsApp)
-{
-    *aIsApp = (mFrameType == eFrameTypeApp);
-    return NS_OK;
-}
-
-/* [infallible] */ NS_IMETHODIMP
-nsDocShell::GetIsBrowserOrApp(bool* aIsBrowserOrApp)
-{
-    switch (mFrameType) {
-        case eFrameTypeRegular:
-            *aIsBrowserOrApp = false;
-            break;
-        case eFrameTypeBrowser:
-        case eFrameTypeApp:
-            *aIsBrowserOrApp = true;
-            break;
+nsDocShell::SetIsBrowserElement()
+{
+    if (mIsBrowserFrame) {
+        NS_ERROR("You should not call SetIsBrowserElement() more than once.");
+        return NS_OK;
+    }
+
+    mIsBrowserFrame = true;
+
+    nsCOMPtr<nsIObserverService> os = services::GetObserverService();
+    if (os) {
+        os->NotifyObservers(GetAsSupports(this),
+                            "docshell-marked-as-browser-frame", NULL);
     }
 
     return NS_OK;
 }
 
 nsDocShell::FrameType
 nsDocShell::GetInheritedFrameType()
 {
-    if (mFrameType != eFrameTypeRegular) {
-        return mFrameType;
+    FrameType type = GetFrameType();
+
+    if (type != eFrameTypeRegular) {
+        return type;
     }
 
     nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
     GetSameTypeParent(getter_AddRefs(parentAsItem));
 
     nsCOMPtr<nsIDocShell> parent = do_QueryInterface(parentAsItem);
     if (!parent) {
         return eFrameTypeRegular;
     }
 
     return static_cast<nsDocShell*>(parent.get())->GetInheritedFrameType();
 }
 
+nsDocShell::FrameType
+nsDocShell::GetFrameType()
+{
+    if (mAppId != nsIScriptSecurityManager::NO_APP_ID) {
+        return eFrameTypeApp;
+    }
+
+    return mIsBrowserFrame ? eFrameTypeBrowser : eFrameTypeRegular;
+}
+
+/* [infallible] */ NS_IMETHODIMP
+nsDocShell::GetIsBrowserElement(bool* aIsBrowser)
+{
+    *aIsBrowser = (GetFrameType() == eFrameTypeBrowser);
+    return NS_OK;
+}
+
+/* [infallible] */ NS_IMETHODIMP
+nsDocShell::GetIsApp(bool* aIsApp)
+{
+    *aIsApp = (GetFrameType() == eFrameTypeApp);
+    return NS_OK;
+}
+
+/* [infallible] */ NS_IMETHODIMP
+nsDocShell::GetIsContentBoundary(bool* aIsContentBoundary)
+{
+    switch (GetFrameType()) {
+        case eFrameTypeRegular:
+            *aIsContentBoundary = false;
+            break;
+        case eFrameTypeBrowser:
+        case eFrameTypeApp:
+            *aIsContentBoundary = true;
+            break;
+    }
+
+    return NS_OK;
+}
+
 /* [infallible] */ NS_IMETHODIMP
 nsDocShell::GetIsInBrowserElement(bool* aIsInBrowserElement)
 {
     *aIsInBrowserElement = (GetInheritedFrameType() == eFrameTypeBrowser);
     return NS_OK;
 }
 
 /* [infallible] */ NS_IMETHODIMP
-nsDocShell::GetIsInBrowserOrApp(bool* aIsInBrowserOrApp)
+nsDocShell::GetIsInApp(bool* aIsInApp)
+{
+    *aIsInApp = (GetInheritedFrameType() == eFrameTypeApp);
+    return NS_OK;
+}
+
+/* [infallible] */ NS_IMETHODIMP
+nsDocShell::GetIsBelowContentBoundary(bool* aIsInContentBoundary)
 {
     switch (GetInheritedFrameType()) {
         case eFrameTypeRegular:
-            *aIsInBrowserOrApp = false;
+            *aIsInContentBoundary = false;
             break;
         case eFrameTypeBrowser:
         case eFrameTypeApp:
-            *aIsInBrowserOrApp = true;
+            *aIsInContentBoundary = true;
             break;
     }
 
     return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDocShell::SetAppId(uint32_t aAppId)
+{
+    MOZ_ASSERT(mAppId == nsIScriptSecurityManager::NO_APP_ID);
+    MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
+
+    mAppId = aAppId;
+    return NS_OK;
+}
+
 /* [infallible] */ NS_IMETHODIMP
 nsDocShell::GetAppId(uint32_t* aAppId)
 {
-    if (mOwnOrContainingAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
-        *aAppId = mOwnOrContainingAppId;
+    if (mAppId != nsIScriptSecurityManager::NO_APP_ID) {
+        MOZ_ASSERT(GetFrameType() == eFrameTypeApp);
+
+        *aAppId = mAppId;
         return NS_OK;
     }
 
+    MOZ_ASSERT(GetFrameType() != eFrameTypeApp);
+
     nsCOMPtr<nsIDocShell> parent;
-    GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent));
+    GetParentIgnoreBrowserFrame(getter_AddRefs(parent));
 
     if (!parent) {
         *aAppId = nsIScriptSecurityManager::NO_APP_ID;
         return NS_OK;
     }
 
     return parent->GetAppId(aAppId);
 }
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -660,22 +660,23 @@ protected:
         void Revoke() { mDocShell = nullptr; }
     private:
         nsRefPtr<nsDocShell> mDocShell;
     };
 
     bool JustStartedNetworkLoad();
 
     enum FrameType {
-        eFrameTypeRegular,
-        eFrameTypeBrowser,
-        eFrameTypeApp
+        eFrameTypeRegular  = 0x0, // 0000
+        eFrameTypeBrowser  = 0x1, // 0001
+        eFrameTypeApp      = 0x2  // 0010
     };
 
     FrameType GetInheritedFrameType();
+    FrameType GetFrameType();
 
     // hash of session storages, keyed by domain
     nsInterfaceHashtable<nsCStringHashKey, nsIDOMStorage> mStorages;
 
     // Dimensions of the docshell
     nsIntRect                  mBounds;
     nsString                   mName;
     nsString                   mTitle;
@@ -802,16 +803,17 @@ protected:
     bool                       mObserveErrorPages;
     bool                       mAllowAuth;
     bool                       mAllowKeywordFixup;
     bool                       mIsOffScreenBrowser;
     bool                       mIsActive;
     bool                       mIsAppTab;
     bool                       mUseGlobalHistory;
     bool                       mInPrivateBrowsing;
+    bool                       mIsBrowserFrame;
 
     // This boolean is set to true right before we fire pagehide and generally
     // unset when we embed a new content viewer.  While it's true no navigation
     // is allowed in this docshell.
     bool                       mFiredUnloadEvent;
 
     // this flag is for bug #21358. a docshell may load many urls
     // which don't result in new documents being created (i.e. a new
@@ -838,28 +840,17 @@ protected:
     bool                       mInEnsureScriptEnv;
 #endif
     uint64_t                   mHistoryID;
 
     static nsIURIFixup *sURIFixup;
 
     nsRefPtr<nsDOMNavigationTiming> mTiming;
 
-    // Are we a regular frame, a browser frame, or an app frame?
-    FrameType mFrameType;
-
-    // We only expect mOwnOrContainingAppId to be something other than
-    // UNKNOWN_APP_ID if mFrameType != eFrameTypeRegular.  For vanilla iframes
-    // inside an app, we'll retrieve the containing app-id by walking up the
-    // docshell hierarchy.
-    //
-    // (This needs to be the docshell's own /or containing/ app id because the
-    // containing app frame might be in another process, in which case we won't
-    // find it by walking up the docshell hierarchy.)
-    uint32_t mOwnOrContainingAppId;
+    uint32_t mAppId;
 
 private:
     nsCOMPtr<nsIAtom> mForcedCharset;
     nsCOMPtr<nsIAtom> mParentCharset;
     nsTObserverArray<nsWeakPtr> mPrivacyObservers;
     int32_t           mParentCharsetSource;
     nsCString         mOriginalUriString;
 
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -34,17 +34,17 @@ interface nsISHEntry;
 interface nsILayoutHistoryState;
 interface nsISecureBrowserUI;
 interface nsIDOMStorage;
 interface nsIPrincipal;
 interface nsIWebBrowserPrint;
 interface nsIVariant;
 interface nsIPrivacyTransitionObserver;
 
-[scriptable, builtinclass, uuid(318CE516-3F7A-41F6-8F3D-3661650F7A46)]
+[scriptable, builtinclass, uuid(e93b2f6a-c543-448b-9239-55c96e31672e)]
 interface nsIDocShell : nsISupports
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
@@ -574,112 +574,102 @@ interface nsIDocShell : nsISupports
 
   /**
    * Add an observer to the list of parties to be notified when this docshell's
    * private browsing status is changed. |obs| must support weak references.
    */
   void addWeakPrivacyTransitionObserver(in nsIPrivacyTransitionObserver obs);
 
   /**
-   * Returns true if this docshell corresponds to an <iframe mozbrowser>.
-   * (<iframe mozapp mozbrowser> is not considered a browser.)
+   * Mark the docshell as a browser frame.
+   * This should be used for <iframe mozbrowser> but not for <iframe mozapp>.
+   *
+   * This method should not be called more than once.
+   */
+  void setIsBrowserElement();
+
+  /**
+   * Returns true iff the docshell is marked as a browser frame.
    */
   [infallible] readonly attribute boolean isBrowserElement;
 
   /**
-   * Returns true iff the docshell corresponds to an <iframe mozapp>.
+   * Returns true iif the docshell is marked as an app frame.
    */
   [infallible] readonly attribute boolean isApp;
 
   /**
-   * Returns isBrowserElement || isApp.
+   * Returns true iif the docshell is marked as a type that behaves like a
+   * content boundary.
    */
-  [infallible] readonly attribute boolean isBrowserOrApp;
+  [infallible] readonly attribute boolean isContentBoundary;
 
   /**
-   * Returns true if this docshell corresponds to an <iframe mozbrowser> or if
-   * the docshell is contained in an <iframe mozbrowser>.  (<iframe mozapp
-   * mozbrowser> does not count as a browser.)
-   *
-   * Our notion here of "contained in" means: Walk up the docshell hierarchy in
-   * this process until we hit an <iframe mozapp> or <iframe mozbrowser> (or
-   * until the hierarchy ends).  Return true iff the docshell we stopped on has
-   * isBrowserElement == true.
+   * Returns true iif the docshell is inside a browser element.
    */
   [infallible] readonly attribute boolean isInBrowserElement;
 
   /**
-   * Returns true if this docshell corresponds to an <iframe mozbrowser> or
-   * <iframe mozap>, or if this docshell is contained in an <iframe mozbrowser>
-   * or <iframe mozapp>.
+   * Returns true iif the docshell is inside an application.  However, it will
+   * return false if the docshell is inside a browser element that is inside
+   * an application.
    *
-   * To compute this value, we walk up the docshell hierarchy.  If we encounter
-   * a docshell with isBrowserElement or isApp before we hit the end of the
-   * hierarchy, we return true.  Otherwise, we return false.
+   * Note: Do not use this method for permissions checks!  An app may contain
+   * an <iframe> pointing at arbitrary web code.  This iframe's docshell will
+   * have isInApp() == true, but the iframe's content is not "app code", and
+   * so should not be granted more trust than vanilla web content.
+   *
+   * (For example, suppose when web content calls API method X, we show a
+   * permission prompt, but when "app code" calls method X, we don't.  In this
+   * case, it would be /incorrect/ to show the permission prompt if
+   * !isInApp().)
+   *
+   * If you're doing a security check, use the content's principal instead of
+   * this method.
    */
-  [infallible] readonly attribute boolean isInBrowserOrApp;
-
-   /**
-    * Indicate that this docshell corresponds to an app with the given app id.
-    *
-    * You may pass NO_APP_ID or UNKNOWN_APP_ID for containingAppId.  If you
-    * pass NO_APP_ID, then this docshell will return NO_APP_ID for appId.  If
-    * you pass UNKNOWN_APP_ID, then this docshell will search its hiearchy for
-    * an app frame and use that frame's appId.
-    *
-    * You can call this method more than once, but there's no guarantee that
-    * other components will update their view of the world if you change a
-    * docshell's app id, so tread lightly.
-    *
-    * If you call this method after calling setIsBrowserInsideApp, this
-    * docshell will forget the fact that it was a browser.
-    */
-   void setIsApp(in unsigned long ownAppId);
-
-   /**
-    * Indicate that this docshell corresponds to a browser inside an app with
-    * the given ID.  As with setIsApp, you may pass NO_APP_ID or
-    * UNKNOWN_APP_ID.
-    *
-    * As with setIsApp, you may call this more than once, but it's kind of a
-    * hack, so be careful.
-    */
-   void setIsBrowserInsideApp(in unsigned long containingAppId);
+  [infallible] readonly attribute boolean isInApp;
 
   /**
-   * Returns the id of the app associated with this docshell.  If this docshell
-   * is an <iframe mozbrowser> inside an <iframe mozapp>, we return the app's
-   * appId.
+   * Returns if the docshell has a docshell that behaves as a content boundary
+   * in his parent hierarchy.
+   */
+  [infallible] readonly attribute boolean isBelowContentBoundary;
+
+  /**
+   * Set the app id this docshell is associated with. The id has to be a valid
+   * app id. If the docshell isn't associated with any app, the value should be
+   * nsIScriptSecurityManager::NO_APP_ID. However, this is the default value if
+   * nothing is et.
    *
-   * We compute this value by walking up the docshell hierarchy until we find a
-   * docshell on which setIsApp(x) or setIsBrowserInsideApp(x) was called
-   * (ignoring those docshells where x == UNKNOWN_APP_ID).  We return the app
-   * id x.
+   * This method is [noscript] to reduce the scope. It should be used at very
+   * specific moments.
    *
-   * If we don't find a docshell with an associated app id in our hierarchy, we
-   * return NO_APP_ID.  We never return UNKNOWN_APP_ID.
-   *
-   * Notice that a docshell may have an associated app even if it returns true
-   * for isBrowserElement!
+   * Calling setAppId() will mark the frame as an app frame.
+   */
+  [noscript] void setAppId(in unsigned long appId);
+
+  /**
+   * Returns the app id of the app the docshell is in. Returns
+   * nsIScriptSecurityManager::NO_APP_ID if the docshell is not in an app.
    */
   [infallible] readonly attribute unsigned long appId;
 
-  /**
-   * Like nsIDocShellTreeItem::GetSameTypeParent, except this ignores <iframe
-   * mozbrowser> and <iframe mozapp> boundaries.
-   */
-  nsIDocShell getSameTypeParentIgnoreBrowserAndAppBoundaries();
-
   /** 
    * True iff asynchronous panning and zooming is enabled for this
    * docshell.
    */
   readonly attribute bool asyncPanZoomEnabled;
 
   /**
+   * Like GetSameTypeParent, except this ignores <iframe mozbrowser>
+   * boundaries.
+   */
+  nsIDocShell getParentIgnoreBrowserFrame();
+
+  /**
    * The sandbox flags on the docshell. These reflect the value of the sandbox
    * attribute of the associated IFRAME or CSP-protectable content, if
    * existent. See the HTML5 spec for more details.
    * These flags on the docshell reflect the current state of the sandbox
    * attribute, which is modifiable. They are only used when loading new
    * content, sandbox flags are also immutably set on the document when it is
    * loaded.
    * The sandbox flags of a document depend on the sandbox flags on its
--- a/docshell/base/nsIDocShellTreeItem.idl
+++ b/docshell/base/nsIDocShellTreeItem.idl
@@ -48,21 +48,20 @@ interface nsIDocShellTreeItem : nsIDocSh
 	attribute long itemType;
 
 	/*
 	Parent DocShell.
 	*/
 	readonly attribute nsIDocShellTreeItem parent;
 
 	/*
-	This getter returns the same thing parent does however if the parent
-	is of a different itemType, or if the parent is an <iframe mozbrowser>
-	or <iframe mozapp>, it will instead return nullptr.  This call is a
-	convience function for those wishing to not cross the boundaries at
-	which item types change.
+	This is call returns the same thing parent does however if the parent is
+	of a different itemType, it will instead return nullptr.  This call is a
+	convience function for those wishing to not cross the boundaries at which
+	item types change.
 	*/
 	readonly attribute nsIDocShellTreeItem sameTypeParent;
 
 	/*
 	Returns the root DocShellTreeItem.  This is a convience equivalent to 
 	getting the parent and its parent until there isn't a parent.
 	*/
 	readonly attribute nsIDocShellTreeItem rootTreeItem;
--- a/docshell/base/nsILoadContext.idl
+++ b/docshell/base/nsILoadContext.idl
@@ -78,17 +78,17 @@ interface nsILoadContext : nsISupports
 %}
 
   /**
    * Set the private browsing state of the load context, meant to be used internally.
    */
   [noscript] void SetPrivateBrowsing(in boolean aInPrivateBrowsing);
 
   /**
-   * Returns true iff the load is occurring inside a browser element.
+   * Returns true iif the load is occurring inside a browser element.
    */
   readonly attribute boolean isInBrowserElement;
 
   /**
    * Returns the app id of the app the load is occurring is in. Returns
    * nsIScriptSecurityManager::NO_APP_ID if the load is not part of an app.
    */
   readonly attribute unsigned long appId;
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -1829,16 +1829,20 @@ this.DOMApplicationRegistry = {
       mm.addMessageListener(msgName, listener);
     });
   },
 
   receiveAppMessage: function(appId, message) {
     switch (message.name) {
       case "Webapps:ClearBrowserData":
         this._clearPrivateData(appId, true);
+        // XXXbent This is a hack until bug 802366 is fixed. Currently all data
+        //         loaded in mozbrowser frames within an app believe that their
+        //         appId is 0.
+        this._clearPrivateData(0, true);
         break;
     }
   },
 
   _clearPrivateData: function(appId, browserOnly) {
     let subject = {
       appId: appId,
       browserOnly: browserOnly,
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2919,17 +2919,17 @@ nsGlobalWindow::GetScriptableParent(nsID
 {
   FORWARD_TO_OUTER(GetScriptableParent, (aParent), NS_ERROR_NOT_INITIALIZED);
 
   *aParent = NULL;
   if (!mDocShell) {
     return NS_OK;
   }
 
-  if (mDocShell->GetIsBrowserOrApp()) {
+  if (mDocShell->GetIsContentBoundary()) {
     nsCOMPtr<nsIDOMWindow> parent = static_cast<nsIDOMWindow*>(this);
     parent.swap(*aParent);
     return NS_OK;
   }
 
   return GetRealParent(aParent);
 }
 
@@ -2943,17 +2943,17 @@ nsGlobalWindow::GetRealParent(nsIDOMWind
   FORWARD_TO_OUTER(GetRealParent, (aParent), NS_ERROR_NOT_INITIALIZED);
 
   *aParent = nullptr;
   if (!mDocShell) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDocShell> parent;
-  mDocShell->GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent));
+  mDocShell->GetParentIgnoreBrowserFrame(getter_AddRefs(parent));
 
   if (parent) {
     nsCOMPtr<nsIScriptGlobalObject> globalObject(do_GetInterface(parent));
     NS_ENSURE_SUCCESS(CallQueryInterface(globalObject.get(), aParent),
                       NS_ERROR_FAILURE);
   }
   else {
     *aParent = static_cast<nsIDOMWindow*>(this);
@@ -3024,19 +3024,19 @@ nsGlobalWindow::GetTopImpl(nsIDOMWindow*
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetContent(nsIDOMWindow** aContent)
 {
   FORWARD_TO_OUTER(GetContent, (aContent), NS_ERROR_NOT_INITIALIZED);
   *aContent = nullptr;
 
-  // If we're contained in <iframe mozbrowser> or <iframe mozapp>, then
-  // GetContent is the same as window.top.
-  if (mDocShell && mDocShell->GetIsInBrowserOrApp()) {
+  // If we're contained in <iframe mozbrowser>, then GetContent is the same as
+  // window.top.
+  if (mDocShell && mDocShell->GetIsBelowContentBoundary()) {
     return GetScriptableTop(aContent);
   }
 
   nsCOMPtr<nsIDocShellTreeItem> primaryContent;
   if (!nsContentUtils::IsCallerChrome()) {
     // If we're called by non-chrome code, make sure we don't return
     // the primary content window if the calling tab is hidden. In
     // such a case we return the same-type root in the hidden tab,
@@ -6483,17 +6483,17 @@ nsGlobalWindow::CanClose()
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Close()
 {
   FORWARD_TO_OUTER(Close, (), NS_ERROR_NOT_INITIALIZED);
 
   if (!mDocShell || IsInModalState() ||
-      (IsFrame() && !mDocShell->GetIsBrowserOrApp())) {
+      (IsFrame() && !mDocShell->GetIsContentBoundary())) {
     // window.close() is called on a frame in a frameset, on a window
     // that's already closed, or on a window for which there's
     // currently a modal dialog open. Ignore such calls.
 
     return NS_OK;
   }
 
   if (mHavePendingClose) {
@@ -7002,27 +7002,26 @@ nsGlobalWindow::CacheXBLPrototypeHandler
   mCachedXBLPrototypeHandlers.Put(aKey, aHandler.get());
 }
 
 /**
  * GetScriptableFrameElement is called when script reads
  * nsIGlobalWindow::frameElement.
  *
  * In contrast to GetRealFrameElement, GetScriptableFrameElement says that the
- * window contained by an <iframe mozbrowser> or <iframe mozapp> has no frame
- * element (effectively treating a mozbrowser the same as a content/chrome
- * boundary).
+ * window contained by an <iframe mozbrowser> has no frame element
+ * (effectively treating a mozbrowser the same as a content/chrome boundary).
  */
 NS_IMETHODIMP
 nsGlobalWindow::GetScriptableFrameElement(nsIDOMElement** aFrameElement)
 {
   FORWARD_TO_OUTER(GetScriptableFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
   *aFrameElement = NULL;
 
-  if (!mDocShell || mDocShell->GetIsBrowserOrApp()) {
+  if (!mDocShell || mDocShell->GetIsContentBoundary()) {
     return NS_OK;
   }
 
   return GetFrameElement(aFrameElement);
 }
 
 /**
  * nsIGlobalWindow::GetFrameElement (when called from C++) is just a wrapper
@@ -7035,17 +7034,17 @@ nsGlobalWindow::GetRealFrameElement(nsID
 
   *aFrameElement = NULL;
 
   if (!mDocShell) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDocShell> parent;
-  mDocShell->GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent));
+  mDocShell->GetParentIgnoreBrowserFrame(getter_AddRefs(parent));
 
   if (!parent || parent == mDocShell) {
     // We're at a chrome boundary, don't expose the chrome iframe
     // element to content code.
     return NS_OK;
   }
 
   *aFrameElement = mFrameElement;
--- a/dom/browser-element/BrowserElementParent.js
+++ b/dom/browser-element/BrowserElementParent.js
@@ -115,17 +115,17 @@ BrowserElementParentFactory.prototype = 
 
     // Maps frame elements to BrowserElementParent objects.  We never look up
     // anything in this map; the purpose is to keep the BrowserElementParent
     // alive for as long as its frame element lives.
     this._bepMap = new WeakMap();
 
     var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
     os.addObserver(this, 'remote-browser-frame-shown', /* ownsWeak = */ true);
-    os.addObserver(this, 'in-process-browser-or-app-frame-shown', /* ownsWeak = */ true);
+    os.addObserver(this, 'in-process-browser-frame-shown', /* ownsWeak = */ true);
   },
 
   _browserFramesPrefEnabled: function() {
     var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
     try {
       return prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF);
     }
     catch(e) {
@@ -156,17 +156,17 @@ BrowserElementParentFactory.prototype = 
     case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
       if (data == BROWSER_FRAMES_ENABLED_PREF) {
         this._init();
       }
       break;
     case 'remote-browser-frame-shown':
       this._observeRemoteBrowserFrameShown(subject);
       break;
-    case 'in-process-browser-or-app-frame-shown':
+    case 'in-process-browser-frame-shown':
       this._observeInProcessBrowserFrameShown(subject);
       break;
     case 'content-document-global-created':
       this._observeContentGlobalCreated(subject);
       break;
     }
   },
 };
--- a/dom/browser-element/mochitest/Makefile.in
+++ b/dom/browser-element/mochitest/Makefile.in
@@ -85,19 +85,16 @@ MOCHITEST_FILES = \
 		file_browserElement_ForwardName.html \
 		browserElement_TargetBlank.js \
 		test_browserElement_inproc_TargetBlank.html \
 		file_browserElement_TargetBlank.html \
 		browserElement_PromptCheck.js \
 		test_browserElement_inproc_PromptCheck.html \
 		browserElement_PromptConfirm.js \
 		test_browserElement_inproc_PromptConfirm.html \
-		browserElement_CookiesNotThirdParty.js \
-		file_browserElement_CookiesNotThirdParty.html \
-		test_browserElement_inproc_CookiesNotThirdParty.html \
 		browserElement_Close.js \
 		test_browserElement_inproc_Close.html \
 		browserElement_CloseFromOpener.js \
 		test_browserElement_inproc_CloseFromOpener.html \
 		file_browserElement_CloseFromOpener.html \
 		browserElement_CloseApp.js \
 		test_browserElement_inproc_CloseApp.html \
 		file_browserElement_CloseApp.html \
@@ -194,17 +191,16 @@ MOCHITEST_FILES += \
 		test_browserElement_oop_FirstPaint.html \
 		test_browserElement_oop_Alert.html \
 		test_browserElement_oop_AlertInFrame.html \
 		test_browserElement_oop_TargetTop.html \
 		test_browserElement_oop_ForwardName.html \
 		test_browserElement_oop_TargetBlank.html \
 		test_browserElement_oop_PromptCheck.html \
 		test_browserElement_oop_PromptConfirm.html \
-		test_browserElement_oop_CookiesNotThirdParty.html \
 		test_browserElement_oop_Close.html \
 		test_browserElement_oop_CloseFromOpener.html \
 		test_browserElement_oop_CloseApp.html \
 		test_browserElement_oop_OpenWindow.html \
 		test_browserElement_oop_OpenWindowInFrame.html \
 		test_browserElement_oop_OpenWindowRejected.html \
 		test_browserElement_oop_OpenWindowDifferentOrigin.html \
 		test_browserElement_oop_OpenNamed.html \
deleted file mode 100644
--- a/dom/browser-element/mochitest/browserElement_CookiesNotThirdParty.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Any copyright is dedicated to the public domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Bug 806127 - Test that cookies set by <iframe mozbrowser> are not considered
-// third-party.
-"use strict";
-
-SimpleTest.waitForExplicitFinish();
-
-function runTest() {
-  browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addPermission();
-
-  const innerPage = 'http://example.com/tests/dom/browser-element/mochitest/file_browserElement_CookiesNotThirdParty.html';
-
-  var iframe = document.createElement('iframe');
-  iframe.mozbrowser = true;
-
-  iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
-    if (e.detail.message == 'next') {
-      iframe.src = innerPage + '?step=2';
-      return;
-    }
-
-    if (e.detail.message.startsWith('success:')) {
-      ok(true, e.detail.message);
-      return;
-    }
-
-    if (e.detail.message.startsWith('failure:')) {
-      ok(false, e.detail.message);
-      return;
-    }
-
-    if (e.detail.message == 'finish') {
-      SimpleTest.finish();
-    }
-  });
-
-  // innerPage will set a cookie and then alert('next').  We'll load
-  // innerPage?step=2.  That page will check that the cooke exists (despite the
-  // fact that we've disabled third-party cookies) and alert('success:') or
-  // alert('failure:'), as appropriate.  Finally, the page will
-  // alert('finish');
-  iframe.src = innerPage;
-  document.body.appendChild(iframe);
-}
-
-// Disable third-party cookies for this test.
-SpecialPowers.pushPrefEnv({'set': [['network.cookie.cookieBehavior', 1]]}, runTest);
deleted file mode 100644
--- a/dom/browser-element/mochitest/file_browserElement_CookiesNotThirdParty.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<html>
-<body>
-file_browserElement_CookiesNotThirdParty.html
-
-<script type='text/javascript;version=1.7'>
-if (location.search != '?step=2') {
-  // Step 1: Set a cookie.
-  document.cookie = 'file_browserElement_CookiesNotThirdParty';
-  alert('next');
-}
-else {
-  // Step 2: Read the cookie.
-  if (document.cookie == 'file_browserElement_CookiesNotThirdParty') {
-    alert('success: got the correct cookie');
-  }
-  else {
-    alert('failure: got unexpected cookie: "' + document.cookie + '"');
-  }
-
-  alert('finish');
-}
-</script>
-
-</body>
-</html>
deleted file mode 100644
--- a/dom/browser-element/mochitest/test_browserElement_inproc_CookiesNotThirdParty.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for Bug 806127</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<script type="application/javascript;version=1.7" src="browserElement_CookiesNotThirdParty.js">
-</script>
-</body>
-</html>
\ No newline at end of file
deleted file mode 100644
--- a/dom/browser-element/mochitest/test_browserElement_oop_CookiesNotThirdParty.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for Bug 806127</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<script type="application/javascript;version=1.7" src="browserElement_CookiesNotThirdParty.js">
-</script>
-</body>
-</html>
\ No newline at end of file
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -17,17 +17,16 @@
 #include "nsIScriptError.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISHEntry.h"
 #include "nsISimpleEnumerator.h"
 #include "nsITimer.h"
 
 #include "mozilla/dom/file/FileService.h"
-#include "mozilla/dom/TabContext.h"
 #include "mozilla/LazyIdleThread.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/storage.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsContentUtils.h"
 #include "nsCRTGlue.h"
 #include "nsDirectoryServiceUtils.h"
@@ -193,16 +192,23 @@ GetOriginPatternString(uint32_t aAppId, 
                  "Origin doesn't match parameters!");
   }
 #endif
 
   _retval = aOrigin;
 }
 
 void
+GetOriginPatternString(uint32_t aAppId, nsAutoCString& _retval)
+{
+  return GetOriginPatternString(aAppId, IgnoreMozBrowser, EmptyCString(),
+                                _retval);
+}
+
+void
 GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly,
                        nsAutoCString& _retval)
 {
   return GetOriginPatternString(aAppId,
                                 aBrowserOnly ? MozBrowser : NotMozBrowser,
                                 EmptyCString(), _retval);
 }
 
@@ -613,39 +619,43 @@ IndexedDatabaseManager::FireWindowOnErro
     do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return consoleService->LogMessage(scriptError);
 }
 
 // static
 bool
-IndexedDatabaseManager::TabContextMayAccessOrigin(const TabContext& aContext,
-                                                  const nsACString& aOrigin)
+IndexedDatabaseManager::OriginMatchesApp(const nsACString& aOrigin,
+                                         uint32_t aAppId)
 {
   NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
+  NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
+               "Bad appId!");
 
   nsAutoCString pattern;
-  GetOriginPatternString(aContext.OwnOrContainingAppId(),
-                         aContext.IsBrowserElement(),
-                         pattern);
-  if (PatternMatchesOrigin(pattern, aOrigin)) {
-    return true;
-  }
-
-  // If aContext is not for a browser element, then it's allowed to access
-  // is-browser-element origins.
-  if (!aContext.IsBrowserElement()) {
-    GetOriginPatternString(aContext.OwnOrContainingAppId(),
-                           /* isBrowser */ true,
-                           pattern);
-    return PatternMatchesOrigin(pattern, aOrigin);
-  }
-
-  return false;
+  GetOriginPatternString(aAppId, pattern);
+
+  return PatternMatchesOrigin(pattern, aOrigin);
+}
+
+// static
+bool
+IndexedDatabaseManager::OriginMatchesApp(const nsACString& aOrigin,
+                                         uint32_t aAppId,
+                                         bool aInMozBrowser)
+{
+  NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
+  NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
+               "Bad appId!");
+
+  nsAutoCString pattern;
+  GetOriginPatternString(aAppId, aInMozBrowser, pattern);
+
+  return PatternMatchesOrigin(pattern, aOrigin);
 }
 
 bool
 IndexedDatabaseManager::RegisterDatabase(IDBDatabase* aDatabase)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aDatabase, "Null pointer!");
 
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -25,23 +25,16 @@
 
 class mozIStorageQuotaCallback;
 class nsIAtom;
 class nsIFile;
 class nsITimer;
 class nsPIDOMWindow;
 class nsEventChainPostVisitor;
 
-namespace mozilla {
-namespace dom {
-class TabContext;
-}
-}
-
-
 BEGIN_INDEXEDDB_NAMESPACE
 
 class AsyncConnectionHelper;
 class CheckQuotaHelper;
 class FileManager;
 class IDBDatabase;
 
 class IndexedDatabaseManager MOZ_FINAL : public nsIIndexedDatabaseManager,
@@ -206,18 +199,23 @@ public:
   GetDatabaseId(const nsACString& aOrigin,
                 const nsAString& aName);
 
   static nsresult
   FireWindowOnError(nsPIDOMWindow* aOwner,
                     nsEventChainPostVisitor& aVisitor);
 
   static bool
-  TabContextMayAccessOrigin(const TabContext& aContext,
-                            const nsACString& aOrigin);
+  OriginMatchesApp(const nsACString& aOrigin,
+                   uint32_t aAppId);
+
+  static bool
+  OriginMatchesApp(const nsACString& aOrigin,
+                   uint32_t aAppId,
+                   bool aInMozBrowser);
 
 private:
   IndexedDatabaseManager();
   ~IndexedDatabaseManager();
 
   nsresult AcquireExclusiveAccess(const nsACString& aOrigin,
                                   IDBDatabase* aDatabase,
                                   AsyncConnectionHelper* aHelper,
--- a/dom/indexedDB/test/Makefile.in
+++ b/dom/indexedDB/test/Makefile.in
@@ -99,24 +99,21 @@ MOCHITEST_FILES = \
   test_transaction_lifetimes.html \
   test_transaction_lifetimes_nested.html \
   test_transaction_ordering.html \
   test_setVersion.html \
   test_setVersion_abort.html \
   test_setVersion_events.html \
   test_setVersion_exclusion.html \
   test_unique_index_update.html \
-  test_webapp_clearBrowserData_inproc_oop.html \
-  test_webapp_clearBrowserData_oop_inproc.html \
-  test_webapp_clearBrowserData_inproc_inproc.html \
+  test_webapp_clearBrowserData.html \
   third_party_iframe1.html \
   third_party_iframe2.html \
   test_app_isolation_inproc.html \
   test_app_isolation_oop.html \
-  webapp_clearBrowserData.js \
   webapp_clearBrowserData_appFrame.html \
   webapp_clearBrowserData_browserFrame.html \
   $(NULL)
 
 #   test_writer_starvation.html  disabled for infinite loops, bug 595368
 
 ifeq (browser,$(MOZ_BUILD_APP))
 MOCHITEST_BROWSER_FILES = \
rename from dom/indexedDB/test/webapp_clearBrowserData.js
rename to dom/indexedDB/test/test_webapp_clearBrowserData.html
--- a/dom/indexedDB/test/webapp_clearBrowserData.js
+++ b/dom/indexedDB/test/test_webapp_clearBrowserData.html
@@ -1,147 +1,137 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Indexed Database Clear Browser Data Test</title>
 
-"use strict";
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script type="text/javascript;version=1.7">
+    "use strict";
 
-const appDomain = "example.org";
-const manifestURL =
-  location.protocol + "//" + appDomain + "/manifest.webapp";
+    const appDomain = "example.org";
+    const manifestURL =
+      location.protocol + "//" + appDomain + "/manifest.webapp";
 
-function testSteps()
-{
-  const objectStoreName = "foo";
-  const testKey = 1;
-  const testValue = objectStoreName;
+    function testSteps()
+    {
+      const objectStoreName = "foo";
+      const testKey = 1;
+      const testValue = objectStoreName;
+
+      let request = indexedDB.open(window.location.pathname, 1);
+      request.onerror = errorHandler;
+      request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = unexpectedSuccessHandler;
+      let event = yield;
 
-  // Determine whether the app and browser frames should be in or
-  // out-of-process.
-  let remote_app, remote_browser;
-  if (window.location.href.indexOf("inproc_oop") != -1) {
-    remote_app = false;
-    remote_browser = true;
-  }
-  else if (window.location.href.indexOf("oop_inproc") != -1) {
-    remote_app = true;
-    remote_browser = false;
-  }
-  else if (window.location.href.indexOf("inproc_inproc") != -1) {
-    remote_app = false;
-    remote_browser = false;
-  }
-  else {
-    ok(false, "Bad test filename!");
-    return;
-  }
+      let db = event.target.result;
+      db.onerror = errorHandler;
+      db.onversionchange = function(event) {
+        event.target.close();
+      }
+
+      let objectStore = db.createObjectStore(objectStoreName);
+      objectStore.add(testValue, testKey);
+
+      request.onsuccess = grabEventAndContinueHandler;
+      event = yield;
+
+      let srcURL =
+        location.protocol + "//" + appDomain +
+        location.pathname.replace("test_webapp_clearBrowserData.html",
+                                  "webapp_clearBrowserData_appFrame.html");
 
-  let request = indexedDB.open(window.location.pathname, 1);
-  request.onerror = errorHandler;
-  request.onupgradeneeded = grabEventAndContinueHandler;
-  request.onsuccess = unexpectedSuccessHandler;
-  let event = yield;
-
-  let db = event.target.result;
-  db.onerror = errorHandler;
-  db.onversionchange = function(event) {
-    event.target.close();
-  }
-
-  let objectStore = db.createObjectStore(objectStoreName);
-  objectStore.add(testValue, testKey);
+      let iframe = document.createElement("iframe");
+      iframe.setAttribute("mozbrowser", "");
+      iframe.setAttribute("mozapp", manifestURL);
+      iframe.setAttribute("src", srcURL);
+      iframe.setAttribute("remote", "true");
+      iframe.addEventListener("mozbrowsershowmodalprompt", function(event) {
+        let message = JSON.parse(event.detail.message);
+        switch (message.type) {
+          case "info":
+          case "ok":
+            window[message.type].apply(window, message.args);
+            break;
+          case "done":
+            continueToNextStepSync();
+            break;
+          default:
+            throw "unknown message";
+        }
+      });
 
-  request.onsuccess = grabEventAndContinueHandler;
-  event = yield;
-
-  // We need to send both remote_browser and remote_app in the querystring
-  // because webapp_clearBrowserData_appFrame uses the path + querystring to
-  // create and open a database which it checks no other test has touched.  If
-  // we sent only remote_browser, then we wouldn't be able to test both
-  // (remote_app==false, remote_browser==false) and (remote_app==true,
-  // remote_browser==false).
-  let srcURL = location.protocol + "//" + appDomain +
-    location.pathname.substring(0, location.pathname.lastIndexOf('/')) +
-    "/webapp_clearBrowserData_appFrame.html?" +
-    "remote_browser=" + remote_browser + "&" +
-    "remote_app=" + remote_app;
+      info("loading app frame");
 
-  let iframe = document.createElement("iframe");
-  iframe.setAttribute("mozbrowser", "");
-  iframe.setAttribute("mozapp", manifestURL);
-  iframe.setAttribute("src", srcURL);
-  iframe.setAttribute("remote", remote_app);
-  iframe.addEventListener("mozbrowsershowmodalprompt", function(event) {
-    let message = JSON.parse(event.detail.message);
-    switch (message.type) {
-      case "info":
-      case "ok":
-        window[message.type].apply(window, message.args);
-        break;
-      case "done":
-        continueToNextStepSync();
-        break;
-      default:
-        throw "unknown message";
-    }
-  });
+      document.body.appendChild(iframe);
+      yield;
+
+      request = indexedDB.open(window.location.pathname, 1);
+      request.onerror = errorHandler;
+      request.onupgradeneeded = unexpectedSuccessHandler;
+      request.onsuccess = grabEventAndContinueHandler;
+      event = yield;
+
+      db = event.target.result;
+      db.onerror = errorHandler;
 
-  info("loading app frame");
+      objectStore =
+        db.transaction(objectStoreName).objectStore(objectStoreName);
+      objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
+      event = yield;
 
-  document.body.appendChild(iframe);
-  yield;
+      ok(testValue == event.target.result, "data still exists");
 
-  request = indexedDB.open(window.location.pathname, 1);
-  request.onerror = errorHandler;
-  request.onupgradeneeded = unexpectedSuccessHandler;
-  request.onsuccess = grabEventAndContinueHandler;
-  event = yield;
+      finishTest();
+      yield;
+    }
 
-  db = event.target.result;
-  db.onerror = errorHandler;
-
-  objectStore =
-    db.transaction(objectStoreName).objectStore(objectStoreName);
-  objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
-  event = yield;
-
-  ok(testValue == event.target.result, "data still exists");
+    function start()
+    {
+      if (!SpecialPowers.isMainProcess()) {
+        todo(false, "Test disabled in child processes, for now");
+        SimpleTest.finish();
+        return;
+      }
 
-  finishTest();
-  yield;
-}
+      SpecialPowers.addPermission("browser", true, document);
+      SpecialPowers.addPermission("browser", true, { manifestURL: manifestURL,
+                                                     isInBrowserElement: false });
+      SpecialPowers.addPermission("embed-apps", true, document);
 
-function start()
-{
-  if (!SpecialPowers.isMainProcess()) {
-    todo(false, "Test disabled in child processes, for now");
-    SimpleTest.finish();
-    return;
-  }
+      let Webapps = {};
+      SpecialPowers.wrap(Components)
+                   .utils.import("resource://gre/modules/Webapps.jsm", Webapps);
+      let appRegistry = SpecialPowers.wrap(Webapps.DOMApplicationRegistry);
 
-  SpecialPowers.addPermission("browser", true, document);
-  SpecialPowers.addPermission("browser", true, { manifestURL: manifestURL,
-                                                 isInBrowserElement: false });
-  SpecialPowers.addPermission("embed-apps", true, document);
+      let originalAllAppsLaunchable = appRegistry.allAppsLaunchable;
+      appRegistry.allAppsLaunchable = true;
+
+      window.addEventListener("unload", function cleanup(event) {
+        if (event.target == document) {
+          window.removeEventListener("unload", cleanup, false);
 
-  let Webapps = {};
-  SpecialPowers.wrap(Components)
-               .utils.import("resource://gre/modules/Webapps.jsm", Webapps);
-  let appRegistry = SpecialPowers.wrap(Webapps.DOMApplicationRegistry);
-
-  let originalAllAppsLaunchable = appRegistry.allAppsLaunchable;
-  appRegistry.allAppsLaunchable = true;
-
-  window.addEventListener("unload", function cleanup(event) {
-    if (event.target == document) {
-      window.removeEventListener("unload", cleanup, false);
+          SpecialPowers.removePermission("browser", location.href);
+          SpecialPowers.removePermission("browser",
+                                         location.protocol + "//" + appDomain);
+          SpecialPowers.removePermission("embed-apps", location.href);
+          appRegistry.allAppsLaunchable = originalAllAppsLaunchable;
+        }
+      }, false);
 
-      SpecialPowers.removePermission("browser", location.href);
-      SpecialPowers.removePermission("browser",
-                                     location.protocol + "//" + appDomain);
-      SpecialPowers.removePermission("embed-apps", location.href);
-      appRegistry.allAppsLaunchable = originalAllAppsLaunchable;
+      SpecialPowers.pushPrefEnv({
+        "set": [["dom.mozBrowserFramesEnabled", true]]
+      }, runTest);
     }
-  }, false);
+  </script>
 
-  SpecialPowers.pushPrefEnv({
-    "set": [["dom.mozBrowserFramesEnabled", true]]
-  }, runTest);
-}
+  <script type="text/javascript;version=1.7" src="helpers.js"></script>
+</head>
+
+<body onload="start();"></body>
+
+</html>
deleted file mode 100644
--- a/dom/indexedDB/test/test_webapp_clearBrowserData_inproc_inproc.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!--
-  Any copyright is dedicated to the Public Domain.
-  http://creativecommons.org/publicdomain/zero/1.0/
--->
-
-<!--
-  We have three similar tests here which each check that indexedDB data for a
-  browser inside an app is cleared upon request:
-
-    1) test_webapp_clearBrowserData_inproc_oop.html,
-    2) test_webapp_clearBrowserData_oop_inproc.html, and
-    3) test_webapp_clearBrowserData_inproc_inproc.html.
-
-  The only difference between these is that the first constructs an in-process
-  app frame which contains an out-of-process browser frame, the second
-  constructs an out-of-process app frame which contains an in-process browser
-  frame, and the third has both frames in process.
-
-  The tests share all their JS code.  webapp_clearBrowserData.js determines
-  which frames are in- and out-of-process by looking at the test's filename.
--->
-
-<html>
-<head>
-  <title>Indexed Database Clear Browser Data Test inproc/inproc</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-  <script type="text/javascript;version=1.7" src="webapp_clearBrowserData.js"></script>
-  <script type="text/javascript;version=1.7" src="helpers.js"></script>
-</head>
-<body onload="start();">
-</body>
-</html>
deleted file mode 100644
--- a/dom/indexedDB/test/test_webapp_clearBrowserData_inproc_oop.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!--
-  Any copyright is dedicated to the Public Domain.
-  http://creativecommons.org/publicdomain/zero/1.0/
--->
-
-<!--
-  See comment in test_webapp_clearBrowserData_inproc_inproc.html for an
-  explanation of what's going on here.
--->
-
-<html>
-<head>
-  <title>Indexed Database Clear Browser Data Test inproc/oop</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript;version=1.7" src="webapp_clearBrowserData.js"></script>
-  <script type="text/javascript;version=1.7" src="helpers.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body onload="start();">
-</body>
-</html>
deleted file mode 100644
--- a/dom/indexedDB/test/test_webapp_clearBrowserData_oop_inproc.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!--
-  Any copyright is dedicated to the Public Domain.
-  http://creativecommons.org/publicdomain/zero/1.0/
--->
-
-<!--
-  See comment in test_webapp_clearBrowserData_inproc_inproc.html for an
-  explanation of what's going on here.
--->
-
-<html>
-<head>
-  <title>Indexed Database Clear Browser Data Test oop/inproc</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript;version=1.7" src="webapp_clearBrowserData.js"></script>
-  <script type="text/javascript;version=1.7" src="helpers.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body onload="start();">
-</body>
-</html>
--- a/dom/indexedDB/test/webapp_clearBrowserData_appFrame.html
+++ b/dom/indexedDB/test/webapp_clearBrowserData_appFrame.html
@@ -28,33 +28,18 @@
 
     window.onerror = ok.bind(window, false);
 
     function testSteps()
     {
       const objectStoreName = "foo";
       const testKey = 1;
       const testValue = objectStoreName;
-      const dbName = location.pathname + location.search;
 
-      // Determine whether our parent iframe asked us to create a remote
-      // browser frame here.
-      let remote_browser;
-      if (location.search.indexOf("remote_browser=true") != -1) {
-        remote_browser = true;
-      }
-      else if (location.search.indexOf("remote_browser=false") != -1) {
-        remote_browser = false;
-      }
-      else {
-        ok(false, "Expected remote_browser={true,false} in query string.");
-        return;
-      }
-
-      let request = indexedDB.open(dbName, 1);
+      let request = indexedDB.open(window.location.pathname, 1);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       request.onsuccess = unexpectedSuccessHandler;
       let event = yield;
 
       let db = event.target.result;
       db.onerror = errorHandler;
       db.onversionchange = function(event) {
@@ -73,21 +58,17 @@
         db.transaction(objectStoreName).objectStore(objectStoreName);
       objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       ok(testValue == event.target.result, "data exists");
 
       let iframe = document.createElement("iframe");
       iframe.setAttribute("mozbrowser", "");
-      // Send our querystring to the subframe because
-      // webapp_clearBrowserData_browserFrame uses its pathname + querystring to
-      // open a database which it assumes hasn't been touched by another test.
-      iframe.setAttribute("src", "webapp_clearBrowserData_browserFrame.html" + location.search);
-      iframe.setAttribute("remote", remote_browser);
+      iframe.setAttribute("src", "webapp_clearBrowserData_browserFrame.html");
       iframe.addEventListener("mozbrowsershowmodalprompt", function(event) {
         let message = JSON.parse(event.detail.message);
         switch (message.type) {
           case "block":
             info("blocking browserFrame");
             event.preventDefault();
 
             let request = navigator.mozApps.getSelf();
@@ -110,17 +91,17 @@
         }
       });
 
       info("loading browser frame");
 
       document.body.appendChild(iframe);
       yield;
 
-      request = indexedDB.open(dbName, 1);
+      request = indexedDB.open(window.location.pathname, 1);
       request.onerror = errorHandler;
       request.onupgradeneeded = unexpectedSuccessHandler;
       request.onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       db = event.target.result;
       db.onerror = errorHandler;
 
--- a/dom/indexedDB/test/webapp_clearBrowserData_browserFrame.html
+++ b/dom/indexedDB/test/webapp_clearBrowserData_browserFrame.html
@@ -38,19 +38,18 @@
 
     window.onerror = ok.bind(window, false);
 
     function testSteps()
     {
       const objectStoreName = "foo";
       const testKey = 1;
       const testValue = objectStoreName;
-      const dbName = window.location.pathname + window.location.search;
 
-      let request = indexedDB.open(dbName, 1);
+      let request = indexedDB.open(window.location.pathname, 1);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       request.onsuccess = unexpectedSuccessHandler;
       let event = yield;
 
       let db = event.target.result;
       db.onerror = errorHandler;
       db.onversionchange = function(event) {
@@ -69,17 +68,17 @@
         db.transaction(objectStoreName).objectStore(objectStoreName);
       objectStore.get(testKey).onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       ok(testValue == event.target.result, "data exists");
 
       block();
 
-      request = indexedDB.open(dbName, 1);
+      request = indexedDB.open(window.location.pathname, 1);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       request.onsuccess = unexpectedSuccessHandler;
       event = yield;
 
       ok(event.type == "upgradeneeded", "db doesn't exist");
 
       request.onsuccess = grabEventAndContinueHandler;
--- a/dom/interfaces/html/nsIMozBrowserFrame.idl
+++ b/dom/interfaces/html/nsIMozBrowserFrame.idl
@@ -4,42 +4,40 @@
 /* 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 "nsIDOMMozBrowserFrame.idl"
 
 interface nsITabParent;
 
-[scriptable, builtinclass, uuid(929AED00-3E15-49B7-8CA2-75003715B7E7)]
+[scriptable, uuid(6f043e42-02c9-4e8f-8f8d-1b83c6102827)]
 interface nsIMozBrowserFrame : nsIDOMMozBrowserFrame
 {
   /**
    * Gets whether this frame really is a browser or app frame.
    *
    * In order to really be a browser frame, this frame's
    * nsIDOMMozBrowserFrame::mozbrowser attribute must be true, and the frame
    * may have to pass various security checks.
    */
-  [infallible] readonly attribute boolean reallyIsBrowserOrApp;
+  readonly attribute boolean reallyIsBrowser;
 
   /**
    * Gets whether this frame really is an app frame.
    *
    * In order to really be an app frame, this frame must really be a browser
    * frame (this requirement will go away eventually), and the frame's mozapp
    * attribute must point to the manifest of a valid app.
    */
-  [infallible] readonly attribute boolean reallyIsApp;
+  readonly attribute boolean reallyIsApp;
 
   /**
    * Gets this frame's app manifest URL, if the frame really is an app frame.
    * Otherwise, returns the empty string.
-   *
-   * This method is guaranteed not to fail.
    */
   readonly attribute AString appManifestURL;
 
   /**
    * Normally, a frame tries to create its frame loader when its src is
    * modified, or its contentWindow is accessed.
    *
    * disallowCreateFrameLoader prevents the frame element from creating its
--- a/dom/ipc/AppProcessPermissions.cpp
+++ b/dom/ipc/AppProcessPermissions.cpp
@@ -22,17 +22,17 @@ bool
 AssertAppProcessPermission(PBrowserParent* aActor, const char* aPermission)
 {
   if (!aActor) {
     NS_WARNING("Testing permissions for null actor");
     return false;
   }
 
   TabParent* tab = static_cast<TabParent*>(aActor);
-  nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
+  nsCOMPtr<mozIApplication> app = tab->GetApp();
   bool hasPermission = false;
 
   // isBrowser frames inherit their app descriptor to identify their
   // data storage, but they don't inherit the permissions associated
   // with that descriptor.
   if (app && !tab->IsBrowserElement()) {
     if (!NS_SUCCEEDED(app->HasPermission(aPermission, &hasPermission))) {
       hasPermission = false;
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -226,21 +226,23 @@ ConsoleListener::Observe(nsIConsoleMessa
     NS_ENSURE_SUCCESS(rv, rv);
     mChild->SendConsoleMessage(msg);
     return NS_OK;
 }
 
 ContentChild* ContentChild::sSingleton;
 
 ContentChild::ContentChild()
- : TabContext()
- , mID(uint64_t(-1))
+ :
+   mID(uint64_t(-1))
 #ifdef ANDROID
    ,mScreenSize(0, 0)
 #endif
+   , mIsForApp(false)
+   , mIsForBrowser(false)
 {
     // This process is a content process, so it's clearly running in
     // multiprocess mode!
     nsDebugImpl::SetMultiprocessMode("Child");
 }
 
 ContentChild::~ContentChild()
 {
@@ -294,17 +296,17 @@ ContentChild::Init(MessageLoop* aIOLoop,
     bool startBackground = true;
     SendGetProcessAttributes(&mID, &startBackground,
                              &mIsForApp, &mIsForBrowser);
     hal::SetProcessPriority(
         GetCurrentProcId(),
         startBackground ? hal::PROCESS_PRIORITY_BACKGROUND:
                           hal::PROCESS_PRIORITY_FOREGROUND);
     if (mIsForApp && !mIsForBrowser) {
-        SetProcessName(NS_LITERAL_STRING("(Preallocated app)"));
+        SetProcessName(NS_LITERAL_STRING("(App)"));
     } else {
         SetProcessName(NS_LITERAL_STRING("Browser"));
     }
 
     return true;
 }
 
 void
@@ -482,31 +484,27 @@ ContentChild::AllocPImageBridge(mozilla:
 }
 
 static void FirstIdle(void)
 {
     ContentChild::GetSingleton()->SendFirstIdle();
 }
 
 PBrowserChild*
-ContentChild::AllocPBrowser(const IPCTabContext& aContext,
-                            const uint32_t& aChromeFlags)
+ContentChild::AllocPBrowser(const uint32_t& aChromeFlags,
+                            const bool& aIsBrowserElement, const AppId& aApp)
 {
     static bool firstIdleTaskPosted = false;
     if (!firstIdleTaskPosted) {
         MessageLoop::current()->PostIdleTask(FROM_HERE, NewRunnableFunction(FirstIdle));
         firstIdleTaskPosted = true;
     }
 
-    // We'll happily accept any kind of IPCTabContext here; we don't need to
-    // check that it's of a certain type for security purposes, because we
-    // believe whatever the parent process tells us.
-
-    nsRefPtr<TabChild> child = TabChild::Create(TabContext(aContext), aChromeFlags);
-
+    nsRefPtr<TabChild> child =
+        TabChild::Create(aChromeFlags, aIsBrowserElement, aApp.get_uint32_t());
     // The ref here is released below.
     return child.forget().get();
 }
 
 bool
 ContentChild::DeallocPBrowser(PBrowserChild* iframe)
 {
     TabChild* child = static_cast<TabChild*>(iframe);
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -4,17 +4,16 @@
  * 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_ContentChild_h
 #define mozilla_dom_ContentChild_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/PContentChild.h"
-#include "mozilla/dom/TabContext.h"
 #include "mozilla/dom/ipc/Blob.h"
 
 #include "nsTArray.h"
 #include "nsIConsoleListener.h"
 
 struct ChromePackage;
 class nsIDOMBlob;
 class nsIObserver;
@@ -36,17 +35,16 @@ namespace dom {
 
 class AlertObserver;
 class PrefObserver;
 class ConsoleListener;
 class PStorageChild;
 class ClonedMessageData;
 
 class ContentChild : public PContentChild
-                   , public TabContext
 {
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
     typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
     typedef mozilla::ipc::URIParams URIParams;
 
 public:
     ContentChild();
     virtual ~ContentChild();
@@ -75,18 +73,19 @@ public:
 
     PCompositorChild*
     AllocPCompositor(mozilla::ipc::Transport* aTransport,
                      base::ProcessId aOtherProcess) MOZ_OVERRIDE;
     PImageBridgeChild*
     AllocPImageBridge(mozilla::ipc::Transport* aTransport,
                       base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
-    virtual PBrowserChild* AllocPBrowser(const IPCTabContext &aContext,
-                                         const uint32_t &chromeFlags);
+    virtual PBrowserChild* AllocPBrowser(const uint32_t& aChromeFlags,
+                                         const bool& aIsBrowserElement,
+                                         const AppId& aAppId);
     virtual bool DeallocPBrowser(PBrowserChild*);
 
     virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequest(const DeviceStorageParams&);
     virtual bool DeallocPDeviceStorageRequest(PDeviceStorageRequestChild*);
 
     virtual PBlobChild* AllocPBlob(const BlobConstructorParams& aParams);
     virtual bool DeallocPBlob(PBlobChild*);
 
@@ -191,16 +190,19 @@ public:
 #endif
 
     // Get the directory for IndexedDB files. We query the parent for this and
     // cache the value
     nsString &GetIndexedDBPath();
 
     uint64_t GetID() { return mID; }
 
+    bool IsForApp() { return mIsForApp; }
+    bool IsForBrowser() { return mIsForBrowser; }
+
     BlobChild* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
 
 private:
     virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
     virtual void ProcessingError(Result what) MOZ_OVERRIDE;
 
     /**
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -50,16 +50,17 @@
 #include "nsConsoleService.h"
 #include "nsDebugImpl.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsDOMFile.h"
 #include "nsExternalHelperAppService.h"
 #include "nsFrameMessageManager.h"
 #include "nsHashPropertyBag.h"
 #include "nsIAlertsService.h"
+#include "nsIAppsService.h"
 #include "nsIClipboard.h"
 #include "nsIDOMApplicationRegistry.h"
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIDOMWindow.h"
 #include "nsIFilePicker.h"
 #include "nsIMemoryReporter.h"
 #include "nsIObserverService.h"
 #include "nsIPresShell.h"
@@ -311,74 +312,90 @@ AppNeedsInheritedOSPrivileges(mozIApplic
         } else if (needsInherit) {
             return true;
         }
     }
     return false;
 }
 
 /*static*/ TabParent*
-ContentParent::CreateBrowserOrApp(const TabContext& aContext)
+ContentParent::CreateBrowser(mozIApplication* aApp, bool aIsBrowserElement)
 {
-    if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) {
-        if (ContentParent* cp = GetNewOrUsed(aContext.IsBrowserElement())) {
-            nsRefPtr<TabParent> tp(new TabParent(aContext));
-            PBrowserParent* browser = cp->SendPBrowserConstructor(
-                tp.forget().get(), // DeallocPBrowserParent() releases this ref.
-                aContext.AsIPCTabContext(),
-                /* chromeFlags */ 0);
-            return static_cast<TabParent*>(browser);
+    // We currently don't set the <app> ancestor for <browser> content
+    // correctly.  This assertion is to notify the person who fixes
+    // this code that they need to reevaluate places here where we may
+    // make bad assumptions based on that bug.
+    MOZ_ASSERT(!aApp || !aIsBrowserElement);
+
+    if (!aApp) {
+        if (ContentParent* cp = GetNewOrUsed(aIsBrowserElement)) {
+            nsRefPtr<TabParent> tp(new TabParent(aApp, aIsBrowserElement));
+            return static_cast<TabParent*>(
+                cp->SendPBrowserConstructor(
+                    // DeallocPBrowserParent() releases the ref we take here
+                    tp.forget().get(),
+                    /*chromeFlags*/0,
+                    aIsBrowserElement, nsIScriptSecurityManager::NO_APP_ID));
         }
         return nullptr;
     }
 
-    // If we got here, we have an app and we're not a browser element.  ownApp
-    // shouldn't be null, because we otherwise would have gone into the
-    // !HasOwnApp() branch above.
-    nsCOMPtr<mozIApplication> ownApp = aContext.GetOwnApp();
-
     if (!gAppContentParents) {
         gAppContentParents =
             new nsDataHashtable<nsStringHashKey, ContentParent*>();
         gAppContentParents->Init();
     }
 
     // Each app gets its own ContentParent instance.
     nsAutoString manifestURL;
-    if (NS_FAILED(ownApp->GetManifestURL(manifestURL))) {
+    if (NS_FAILED(aApp->GetManifestURL(manifestURL))) {
         NS_ERROR("Failed to get manifest URL");
         return nullptr;
     }
 
+    nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
+    if (!appsService) {
+        NS_ERROR("Failed to get apps service");
+        return nullptr;
+    }
+
+    // Send the local app ID to the new TabChild so it knows what app
+    // it is.
+    uint32_t appId;
+    if (NS_FAILED(appsService->GetAppLocalIdByManifestURL(manifestURL, &appId))) {
+        NS_ERROR("Failed to get local app ID");
+        return nullptr;
+    }
+
     nsRefPtr<ContentParent> p = gAppContentParents->Get(manifestURL);
     if (!p) {
-        if (AppNeedsInheritedOSPrivileges(ownApp)) {
-            p = new ContentParent(manifestURL, /* isBrowserElement = */ false,
+        if (AppNeedsInheritedOSPrivileges(aApp)) {
+            p = new ContentParent(manifestURL, aIsBrowserElement,
                                   base::PRIVILEGES_INHERIT);
             p->Init();
         } else {
             p = MaybeTakePreallocatedAppProcess();
             if (p) {
                 p->SetManifestFromPreallocated(manifestURL);
             } else {
                 NS_WARNING("Unable to use pre-allocated app process");
-                p = new ContentParent(manifestURL, /* isBrowserElement = */ false,
+                p = new ContentParent(manifestURL, aIsBrowserElement,
                                       base::PRIVILEGES_DEFAULT);
                 p->Init();
             }
         }
         gAppContentParents->Put(manifestURL, p);
     }
 
-    nsRefPtr<TabParent> tp = new TabParent(aContext);
-    PBrowserParent* browser = p->SendPBrowserConstructor(
-        tp.forget().get(), // DeallocPBrowserParent() releases this ref.
-        aContext.AsIPCTabContext(),
-        /* chromeFlags */ 0);
-    return static_cast<TabParent*>(browser);
+    nsRefPtr<TabParent> tp(new TabParent(aApp, aIsBrowserElement));
+    return static_cast<TabParent*>(
+        // DeallocPBrowserParent() releases the ref we take here
+        p->SendPBrowserConstructor(tp.forget().get(),
+                                   /*chromeFlags*/0,
+                                   aIsBrowserElement, appId));
 }
 
 static PLDHashOperator
 AppendToTArray(const nsAString& aKey, ContentParent* aValue, void* aArray)
 {
     nsTArray<ContentParent*> *array =
         static_cast<nsTArray<ContentParent*>*>(aArray);
     array->AppendElement(aValue);
@@ -1141,47 +1158,40 @@ ContentParent::RecvGetXPCOMProcessAttrib
     NS_ASSERTION(io, "No IO service?");
     DebugOnly<nsresult> rv = io->GetOffline(aIsOffline);
     NS_ASSERTION(NS_SUCCEEDED(rv), "Failed getting offline?");
 
     return true;
 }
 
 PBrowserParent*
-ContentParent::AllocPBrowser(const IPCTabContext& aContext,
-                             const uint32_t &aChromeFlags)
+ContentParent::AllocPBrowser(const uint32_t& aChromeFlags,
+                             const bool& aIsBrowserElement, const AppId& aApp)
 {
-    unused << aChromeFlags;
+    // We only use this Alloc() method when the content processes asks
+    // us to open a window.  In that case, we're expecting to see the
+    // opening PBrowser as its app descriptor, and we can trust the data
+    // associated with that PBrowser since it's fully owned by this
+    // process.
+    if (AppId::TPBrowserParent != aApp.type()) {
+        NS_ERROR("Content process attempting to forge app ID");
+        return nullptr;
+    }
+    TabParent* opener = static_cast<TabParent*>(aApp.get_PBrowserParent());
 
-    // 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 (aContext.type() != IPCTabContext::TPopupIPCTabContext) {
-        NS_ERROR("Unexpected IPCTabContext type.  Aborting AllocPBrowser.");
+    // Popup windows of isBrowser frames are isBrowser if the parent
+    // isBrowser.  Allocating a !isBrowser frame with same app ID
+    // would allow the content to access data it's not supposed to.
+    if (opener && opener->IsBrowserElement() && !aIsBrowserElement) {
+        NS_ERROR("Content process attempting to escalate data access privileges");
         return nullptr;
     }
 
-    const PopupIPCTabContext& popupContext = aContext.get_PopupIPCTabContext();
-    TabParent* opener = static_cast<TabParent*>(popupContext.openerParent());
-    if (!opener) {
-        NS_ERROR("Got null opener from child; aborting AllocPBrowser.");
-        return nullptr;
-    }
-
-    // Popup windows of isBrowser frames must be isBrowser if the parent
-    // isBrowser.  Allocating a !isBrowser frame with same app ID would allow
-    // the content to access data it's not supposed to.
-    if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) {
-        NS_ERROR("Child trying to escalate privileges!  Aborting AllocPBrowser.");
-        return nullptr;
-    }
-
-    TabParent* parent = new TabParent(TabContext(aContext));
-
+    TabParent* parent = new TabParent(opener ? opener->GetApp() : nullptr,
+                                      aIsBrowserElement);
     // We release this ref in DeallocPBrowser()
     NS_ADDREF(parent);
     return parent;
 }
 
 bool
 ContentParent::DeallocPBrowser(PBrowserParent* frame)
 {
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -6,17 +6,16 @@
 
 #ifndef mozilla_dom_ContentParent_h
 #define mozilla_dom_ContentParent_h
 
 #include "base/waitable_event_watcher.h"
 
 #include "mozilla/dom/PContentParent.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
-#include "mozilla/dom/TabContext.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/dom/ipc/Blob.h"
 #include "mozilla/Attributes.h"
 
 #include "nsFrameMessageManager.h"
 #include "nsIObserver.h"
 #include "nsIThreadInternal.h"
 #include "nsNetUtil.h"
@@ -70,19 +69,25 @@ public:
      */
     static void StartUp();
     /** Shut down the content-process machinery. */
     static void ShutDown();
 
     static ContentParent* GetNewOrUsed(bool aForBrowserElement = false);
 
     /**
-     * Get or create a content process for the given TabContext.
+     * Get or create a content process for the given app descriptor,
+     * which may be null.  This function will assign processes to app
+     * or non-app browsers by internal heuristics.
+     *
+     * Currently apps are given their own process, and browser tabs
+     * share processes.
      */
-    static TabParent* CreateBrowserOrApp(const TabContext& aContext);
+    static TabParent* CreateBrowser(mozIApplication* aApp,
+                                    bool aIsBrowserFrame);
 
     static void GetAll(nsTArray<ContentParent*>& aArray);
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIOBSERVER
     NS_DECL_NSITHREADOBSERVER
     NS_DECL_NSIDOMGEOPOSITIONCALLBACK
 
@@ -179,18 +184,19 @@ private:
                       base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
     virtual bool RecvGetProcessAttributes(uint64_t* aId,
                                           bool* aStartBackground,
                                           bool* aIsForApp,
                                           bool* aIsForBrowser) MOZ_OVERRIDE;
     virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline) MOZ_OVERRIDE;
 
-    virtual PBrowserParent* AllocPBrowser(const IPCTabContext& aContext,
-                                          const uint32_t& aChromeFlags);
+    virtual PBrowserParent* AllocPBrowser(const uint32_t& aChromeFlags,
+                                          const bool& aIsBrowserElement,
+                                          const AppId& aApp);
     virtual bool DeallocPBrowser(PBrowserParent* frame);
 
     virtual PDeviceStorageRequestParent* AllocPDeviceStorageRequest(const DeviceStorageParams&);
     virtual bool DeallocPDeviceStorageRequest(PDeviceStorageRequestParent*);
 
     virtual PBlobParent* AllocPBlob(const BlobConstructorParams& aParams);
     virtual bool DeallocPBlob(PBlobParent*);
 
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -37,17 +37,16 @@ EXPORTS_mozilla/dom = \
   ContentParent.h \
   ContentProcess.h \
   CrashReporterChild.h \
   CrashReporterParent.h \
   PermissionMessageUtils.h \
   StructuredCloneUtils.h \
   TabParent.h \
   TabChild.h \
-  TabContext.h \
   TabMessageUtils.h \
   $(NULL)
 
 EXPORTS_mozilla/dom/ipc = \
   Blob.h \
   ProcessPriorityManager.h \
   nsIRemoteBlob.h \
   $(NULL)
@@ -60,17 +59,16 @@ CPPSRCS = \
   ContentChild.cpp \
   CrashReporterParent.cpp \
   CrashReporterChild.cpp \
   PermissionMessageUtils.cpp \
   ProcessPriorityManager.cpp \
   StructuredCloneUtils.cpp \
   TabParent.cpp \
   TabChild.cpp \
-  TabContext.cpp \
   TabMessageUtils.cpp \
   $(NULL)
 
 ifdef MOZ_SYDNEYAUDIO
 EXPORTS_mozilla/dom += \
   AudioChild.h \
   AudioParent.h \
   $(NULL)
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -130,70 +130,19 @@ struct MysteryBlobConstructorParams
 union BlobConstructorParams
 {
   NormalBlobConstructorParams;
   FileBlobConstructorParams;
   SlicedBlobConstructorParams;
   MysteryBlobConstructorParams;
 };
 
-// An IPCTabContext which corresponds to a PBrowser opened by a child when it
-// receives window.open().
-//
-// If isBrowserElement is false, this PopupIPCTabContext corresponds to an app
-// frame, and the frame's app-id and app-frame-owner-app-id will be equal to the
-// opener's values.
-//
-// If isBrowserElement is true, the frame's browserFrameOwnerAppId will be equal
-// to the opener's app-id.
-//
-// It's an error to set isBrowserElement == false if opener is a browser
-// element.  Such a PopupIPCTabContext should be rejected by code which receives
-// it.
-struct PopupIPCTabContext
-{
-  PBrowser opener;
-  bool isBrowserElement;
-};
-
-// An IPCTabContext which corresponds to an app frame.
-struct AppFrameIPCTabContext
-{
-  // 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;
-};
-
-// 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;
-};
-
-// 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 IPCTabContext
-{
-  PopupIPCTabContext;
-  AppFrameIPCTabContext;
-  BrowserFrameIPCTabContext;
-  VanillaFrameIPCTabContext;
+union AppId {
+  uint32_t;
+  nullable PBrowser;
 };
 
 union PrefValue {
   nsCString;
   int32_t;
   bool;
 };
 
@@ -228,36 +177,26 @@ rpc protocol PContent
     manages PStorage;
     manages PTestShell;
 
 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::CreateTab.
-    //
-    // 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.
+    // TabChild::BrowserFrameProvideWindow, and the parent creates the
+    // PBrowser as part of ContentParent::CreateTab.
     //
-    // 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.
-    //
-    // This allows the parent to prevent a malicious child from escalating its
-    // privileges by requesting a PBrowser corresponding to a highly-privileged
-    // app; the child can only request privileges for an app which the child has
-    // access to (in the form of a TabChild).
-    async PBrowser(IPCTabContext context, uint32_t chromeFlags);
+    // When the parent constructs a PBrowser, the app ID handed to the
+    // child side is trusted.  In that case, |appId| is uint32_t.
+    // However, when the child side constructs a PBrowser, for
+    // window.open(), the parent must validate the app ID used on the
+    // parent side.  To do so, the child process must pass a valid
+    // PBrowser as its |AppId|.
+    async PBrowser(uint32_t chromeFlags, bool isBrowserElement, AppId appId);
 
     async PBlob(BlobConstructorParams params);
 
 child:
     PMemoryReportRequest();
 
     /**
      * Dump the contents of about:memory to a file in our temp directory.
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -115,59 +115,64 @@ public:
 
 StaticRefPtr<TabChild> sPreallocatedTab;
 
 /*static*/ void
 TabChild::PreloadSlowThings()
 {
     MOZ_ASSERT(!sPreallocatedTab);
 
-    nsRefPtr<TabChild> tab(new TabChild(TabContext(), /* chromeFlags */ 0));
+    nsRefPtr<TabChild> tab(new TabChild(0, false,
+                                        nsIScriptSecurityManager::NO_APP_ID));
     if (!NS_SUCCEEDED(tab->Init()) ||
         !tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) {
         return;
     }
     tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT);
 
     sPreallocatedTab = tab;
     ClearOnShutdown(&sPreallocatedTab);
 }
 
 /*static*/ already_AddRefed<TabChild>
-TabChild::Create(const TabContext &aContext, uint32_t aChromeFlags)
+TabChild::Create(uint32_t aChromeFlags,
+                 bool aIsBrowserElement, uint32_t aAppId)
 {
     if (sPreallocatedTab &&
         sPreallocatedTab->mChromeFlags == aChromeFlags &&
-        aContext.IsBrowserOrApp()) {
-
+        (aIsBrowserElement || 
+         aAppId != nsIScriptSecurityManager::NO_APP_ID)) {
         nsRefPtr<TabChild> child = sPreallocatedTab.get();
         sPreallocatedTab = nullptr;
 
         MOZ_ASSERT(!child->mTriedBrowserInit);
 
-        child->SetTabContext(aContext);
-        child->NotifyTabContextUpdated();
+        child->SetAppBrowserConfig(aIsBrowserElement, aAppId);
+
         return child.forget();
     }
 
-    nsRefPtr<TabChild> iframe = new TabChild(aContext, aChromeFlags);
+    nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags, aIsBrowserElement,
+                                             aAppId);
     return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr;
 }
 
 
-TabChild::TabChild(const TabContext& aContext, uint32_t aChromeFlags)
-  : TabContext(aContext)
-  , mRemoteFrame(nullptr)
+TabChild::TabChild(uint32_t aChromeFlags, bool aIsBrowserElement,
+                   uint32_t aAppId)
+  : mRemoteFrame(nullptr)
   , mTabChildGlobal(nullptr)
   , mChromeFlags(aChromeFlags)
   , mOuterRect(0, 0, 0, 0)
   , mInnerSize(0, 0)
   , mOldViewportWidth(0.0f)
   , mLastBackgroundColor(NS_RGB(255, 255, 255))
+  , mAppId(aAppId)
   , mDidFakeShow(false)
+  , mIsBrowserElement(aIsBrowserElement)
   , mNotified(false)
   , mContentDocumentIsDisplayed(false)
   , mTriedBrowserInit(false)
 {
     printf("creating %d!\n", NS_IsMainThread());
 }
 
 NS_IMETHODIMP
@@ -520,17 +525,17 @@ TabChild::Init()
     nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)),
     nullptr,                 // HandleWidgetEvent
     nullptr                  // nsDeviceContext
   );
 
   baseWindow->InitWindow(0, mWidget, 0, 0, 0, 0);
   baseWindow->Create();
 
-  NotifyTabContextUpdated();
+  SetAppBrowserConfig(mIsBrowserElement, mAppId);
 
   // IPC uses a WebBrowser object for which DNS prefetching is turned off
   // by default. But here we really want it, so enable it explicitly
   nsCOMPtr<nsIWebBrowserSetup> webBrowserSetup =
     do_QueryInterface(baseWindow);
   if (webBrowserSetup) {
     webBrowserSetup->SetProperty(nsIWebBrowserSetup::SETUP_ALLOW_DNS_PREFETCH,
                                  true);
@@ -544,28 +549,28 @@ TabChild::Init()
   nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
   NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE);
   webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION);
 
   return NS_OK;
 }
 
 void
-TabChild::NotifyTabContextUpdated()
+TabChild::SetAppBrowserConfig(bool aIsBrowserElement, uint32_t aAppId)
 {
+    mIsBrowserElement = aIsBrowserElement;
+    mAppId = aAppId;
+
     nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mWebNav);
     MOZ_ASSERT(docShell);
 
     if (docShell) {
-        // nsDocShell will do the right thing if we pass NO_APP_ID or
-        // UNKNOWN_APP_ID for aOwnOrContainingAppId.
-        if (IsBrowserElement()) {
-          docShell->SetIsBrowserInsideApp(BrowserOwnerAppId());
-        } else {
-          docShell->SetIsApp(OwnAppId());
+        docShell->SetAppId(mAppId);
+        if (mIsBrowserElement) {
+            docShell->SetIsBrowserElement();
         }
     }
 }
 
 NS_INTERFACE_MAP_BEGIN(TabChild)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
   NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
   NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
@@ -779,21 +784,21 @@ TabChild::ProvideWindow(nsIDOMWindow* aP
                         bool aCalledFromJS,
                         bool aPositionSpecified, bool aSizeSpecified,
                         nsIURI* aURI, const nsAString& aName,
                         const nsACString& aFeatures, bool* aWindowIsNew,
                         nsIDOMWindow** aReturn)
 {
     *aReturn = nullptr;
 
-    // If aParent is inside an <iframe mozbrowser> or <iframe mozapp> and this
-    // isn't a request to open a modal-type window, we're going to create a new
-    // <iframe mozbrowser/mozapp> and return its window here.
+    // If aParent is inside an <iframe mozbrowser> and this isn't a request to
+    // open a modal-type window, we're going to create a new <iframe mozbrowser>
+    // and return its window here.
     nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
-    if (docshell && docshell->GetIsInBrowserOrApp() &&
+    if (docshell && docshell->GetIsBelowContentBoundary() &&
         !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
                           nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
                           nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
 
       // Note that BrowserFrameProvideWindow may return NS_ERROR_ABORT if the
       // open window call was canceled.  It's important that we pass this error
       // code back to our caller.
       return BrowserFrameProvideWindow(aParent, aURI, aName, aFeatures,
@@ -818,35 +823,26 @@ TabChild::BrowserFrameProvideWindow(nsID
                                     nsIURI* aURI,
                                     const nsAString& aName,
                                     const nsACString& aFeatures,
                                     bool* aWindowIsNew,
                                     nsIDOMWindow** aReturn)
 {
   *aReturn = nullptr;
 
-  nsRefPtr<TabChild> newChild =
-      new TabChild(/* TabContext */ *this, /* chromeFlags */ 0);
+  uint32_t chromeFlags = 0;
+  nsRefPtr<TabChild> newChild = new TabChild(chromeFlags,
+                                             mIsBrowserElement, mAppId);
   if (!NS_SUCCEEDED(newChild->Init())) {
       return NS_ERROR_ABORT;
   }
-
-  // We must use PopupIPCTabContext here; ContentParent will not accept the
-  // result of this->AsIPCTabContext() (which will be a
-  // BrowserFrameIPCTabContext or an AppFrameIPCTabContext), for security
-  // reasons.
-  PopupIPCTabContext context;
-  context.openerChild() = this;
-  context.isBrowserElement() = IsBrowserElement();
-
   unused << Manager()->SendPBrowserConstructor(
       // We release this ref in DeallocPBrowserChild
       nsRefPtr<TabChild>(newChild).forget().get(),
-      context, /* chromeFlags */ 0);
-
+      chromeFlags, mIsBrowserElement, this);
   nsAutoCString spec;
   if (aURI) {
     aURI->GetSpec(spec);
   }
 
   NS_ConvertUTF8toUTF16 url(spec);
   nsString name(aName);
   NS_ConvertUTF8toUTF16 features(aFeatures);
@@ -997,53 +993,63 @@ TabChild::~TabChild()
       }
       mTabChildGlobal->mTabChild = nullptr;
     }
 }
 
 void
 TabChild::SetProcessNameToAppName()
 {
-  nsCOMPtr<mozIApplication> app = GetOwnApp();
-  if (!app) {
+  if (mIsBrowserElement || (mAppId == nsIScriptSecurityManager::NO_APP_ID)) {
+    return;
+  }
+  nsCOMPtr<nsIAppsService> appsService =
+    do_GetService(APPS_SERVICE_CONTRACTID);
+  if (!appsService) {
+    NS_WARNING("No AppsService");
     return;
   }
-
+  nsresult rv;
+  nsCOMPtr<mozIDOMApplication> domApp;
+  rv = appsService->GetAppByLocalId(mAppId, getter_AddRefs(domApp));
+  if (NS_FAILED(rv) || !domApp) {
+    NS_WARNING("GetAppByLocalId failed");
+    return;
+  }
+  nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp);
+  if (!app) {
+    NS_WARNING("app isn't a mozIApplication");
+    return;
+  }
   nsAutoString appName;
-  nsresult rv = app->GetName(appName);
+  rv = app->GetName(appName);
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to retrieve app name");
     return;
   }
 
   ContentChild::GetSingleton()->SetProcessName(appName);
 }
 
 bool
 TabChild::IsRootContentDocument()
 {
-    // A TabChild is a "root content document" if it's
-    //
-    //  - <iframe mozapp> not inside another <iframe mozapp>,
-    //  - <iframe mozbrowser> (not mozapp), or
-    //  - a vanilla remote frame (<html:iframe remote=true> or <xul:browser
-    //    remote=true>).
-    //
-    // Put another way, an iframe is /not/ a "root content document" iff it's a
-    // mozapp inside a mozapp.  (This corresponds exactly to !HasAppOwnerApp.)
-    //
-    // Note that we're lying through our teeth here (thus the scare quotes).
-    // <html:iframe remote=true> or <xul:browser remote=true> inside another
-    // content iframe is not actually a root content document, but we say it is.
-    //
-    // We do this because we make a remote frame opaque iff
-    // IsRootContentDocument(), and making vanilla remote frames transparent
-    // breaks our remote reftests.
+    if (mIsBrowserElement || mAppId == nsIScriptSecurityManager::NO_APP_ID) {
+        // We're the child side of a browser element.  This always
+        // behaves like a root content document.
+        return true;
+    }
 
-    return !HasAppOwnerApp();
+    // Otherwise, we're the child side of an <html:app remote=true>
+    // embedded in an outer <html:app>.  These don't behave like root
+    // content documents in nested contexts.  Because of bug 761935,
+    // <html:browser remote> and <html:app remote> can't nest, so we
+    // assume this isn't the root.  When that bug is fixed, we need to
+    // revisit that assumption.
+    return false;
 }
 
 bool
 TabChild::RecvLoadURL(const nsCString& uri)
 {
     printf("loading %s, %d\n", uri.get(), NS_IsMainThread());
     SetProcessNameToAppName();
 
@@ -1691,17 +1697,17 @@ TabChild::InitTabChildGlobal(FrameScript
 
     chromeHandler->AddEventListener(NS_LITERAL_STRING("DOMMetaAdded"), this, false);
   }
 
   if (aScriptLoading != DONT_LOAD_SCRIPTS && !mTriedBrowserInit) {
     mTriedBrowserInit = true;
     // Initialize the child side of the browser element machinery,
     // if appropriate.
-    if (IsBrowserOrApp()) {
+    if (mIsBrowserElement || mAppId != nsIScriptSecurityManager::NO_APP_ID) {
       RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT);
     }
   }
 
   return true;
 }
 
 bool
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -46,17 +46,16 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsPIDOMWindow.h"
 #include "nsWeakReference.h"
 #include "nsITabChild.h"
 #include "mozilla/Attributes.h"
 #include "FrameMetrics.h"
 #include "ProcessUtils.h"
-#include "mozilla/dom/TabContext.h"
 
 struct gfxMatrix;
 
 namespace mozilla {
 namespace layout {
 class RenderFrameChild;
 }
 
@@ -145,36 +144,37 @@ class TabChild : public PBrowserChild,
                  public nsIInterfaceRequestor,
                  public nsIWindowProvider,
                  public nsIDOMEventListener,
                  public nsIWebProgressListener,
                  public nsSupportsWeakReference,
                  public nsIDialogCreator,
                  public nsITabChild,
                  public nsIObserver,
-                 public ipc::MessageManagerCallback,
-                 public TabContext
+                 public mozilla::dom::ipc::MessageManagerCallback
 {
     typedef mozilla::layout::RenderFrameChild RenderFrameChild;
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
 
 public:
     /** 
      * This is expected to be called off the critical path to content
      * startup.  This is an opportunity to load things that are slow
      * on the critical path.
      */
     static void PreloadSlowThings();
 
     /** Return a TabChild with the given attributes. */
     static already_AddRefed<TabChild> 
-    Create(const TabContext& aContext, uint32_t aChromeFlags);
+    Create(uint32_t aChromeFlags, bool aIsBrowserElement, uint32_t aAppId);
 
     virtual ~TabChild();
 
+    uint32_t GetAppId() { return mAppId; }
+
     bool IsRootContentDocument();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBBROWSERCHROME
     NS_DECL_NSIWEBBROWSERCHROME2
     NS_DECL_NSIEMBEDDINGSITEWINDOW
     NS_DECL_NSIWEBBROWSERCHROMEFOCUS
     NS_DECL_NSIINTERFACEREQUESTOR
@@ -315,31 +315,25 @@ protected:
                                              bool* /* aAllowed */);
 
     virtual bool DeallocPIndexedDB(PIndexedDBChild* aActor);
 
 private:
     /**
      * Create a new TabChild object.
      *
-     * |aOwnOrContainingAppId| is the app-id of our frame or of the closest app
-     * frame in the hierarchy which contains us.
-     *
-     * |aIsBrowserElement| indicates whether we're a browser (but not an app).
+     * |aIsBrowserElement| indicates whether the tab is inside an <iframe mozbrowser>.
+     * |aAppId| is the app id of the app containing this tab. If the tab isn't
+     * contained in an app, aAppId will be nsIScriptSecurityManager::NO_APP_ID.
      */
-    TabChild(const TabContext& aContext, uint32_t aChromeFlags);
+    TabChild(uint32_t aChromeFlags, bool aIsBrowserElement, uint32_t aAppId);
 
     nsresult Init();
 
-    // Notify others that our TabContext has been updated.  (At the moment, this
-    // sets the appropriate app-id and is-browser flags on our docshell.)
-    //
-    // You should call this after calling TabContext::SetTabContext().  We also
-    // call this during Init().
-    void NotifyTabContextUpdated();
+    void SetAppBrowserConfig(bool aIsBrowserElement, uint32_t aAppId);
 
     bool UseDirectCompositor();
 
     void ActorDestroy(ActorDestroyReason why);
 
     enum FrameScriptLoading { DONT_LOAD_SCRIPTS, DEFAULT_LOAD_SCRIPTS };
     bool InitTabChildGlobal(FrameScriptLoading aScriptLoading = DEFAULT_LOAD_SCRIPTS);
     bool InitRenderingState();
@@ -393,17 +387,19 @@ private:
     RenderFrameChild* mRemoteFrame;
     nsRefPtr<TabChildGlobal> mTabChildGlobal;
     uint32_t mChromeFlags;
     nsIntRect mOuterRect;
     nsIntSize mInnerSize;
     float mOldViewportWidth;
     nscolor mLastBackgroundColor;
     ScrollingBehavior mScrolling;
+    uint32_t mAppId;
     bool mDidFakeShow;
+    bool mIsBrowserElement;
     bool mNotified;
     bool mContentDocumentIsDisplayed;
     bool mTriedBrowserInit;
 
     DISALLOW_EVIL_CONSTRUCTORS(TabChild);
 };
 
 inline TabChild*
deleted file mode 100644
--- a/dom/ipc/TabContext.cpp
+++ /dev/null
@@ -1,292 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=2 ts=8 et tw=80 : */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/TabContext.h"
-#include "mozilla/dom/TabParent.h"
-#include "mozilla/dom/TabChild.h"
-#include "nsIAppsService.h"
-
-using namespace mozilla::dom::ipc;
-
-namespace mozilla {
-namespace dom {
-
-TabContext::TabContext()
-  : mInitialized(false)
-  , mOwnAppId(nsIScriptSecurityManager::NO_APP_ID)
-  , mContainingAppId(nsIScriptSecurityManager::NO_APP_ID)
-  , mIsBrowser(false)
-{
-}
-
-TabContext::TabContext(const IPCTabContext& aParams)
-  : mInitialized(true)
-{
-  switch(aParams.type()) {
-    case IPCTabContext::TPopupIPCTabContext: {
-      const PopupIPCTabContext &ipcContext = aParams.get_PopupIPCTabContext();
-
-      TabContext *context;
-      if (ipcContext.openerParent()) {
-        context = static_cast<TabParent*>(ipcContext.openerParent());
-        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
-          // a fatal error.
-          MOZ_CRASH();
-        }
-      }
-      else if (ipcContext.openerChild()) {
-        context = static_cast<TabChild*>(ipcContext.openerChild());
-      }
-      else {
-        // This should be unreachable because PopupIPCTabContext::opener is not a
-        // nullable field.
-        MOZ_CRASH();
-      }
-
-      // If ipcContext is a browser element, then the opener's app-id becomes
-      // our containing app-id.  Otherwise, our own and containing app-ids are
-      // directly inherited from our opener.
-      if (ipcContext.isBrowserElement()) {
-        mIsBrowser = true;
-        mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
-        mContainingAppId = context->OwnAppId();
-      }
-      else {
-        mIsBrowser = false;
-        mOwnAppId = context->mOwnAppId;
-        mContainingAppId = context->mContainingAppId;
-      }
-      break;
-    }
-    case IPCTabContext::TAppFrameIPCTabContext: {
-      const AppFrameIPCTabContext &ipcContext =
-        aParams.get_AppFrameIPCTabContext();
-
-      mIsBrowser = false;
-      mOwnAppId = ipcContext.ownAppId();
-      mContainingAppId = ipcContext.appFrameOwnerAppId();
-      break;
-    }
-    case IPCTabContext::TBrowserFrameIPCTabContext: {
-      const BrowserFrameIPCTabContext &ipcContext =
-        aParams.get_BrowserFrameIPCTabContext();
-
-      mIsBrowser = true;
-      mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
-      mContainingAppId = ipcContext.browserFrameOwnerAppId();
-      break;
-    }
-    case IPCTabContext::TVanillaFrameIPCTabContext: {
-      mIsBrowser = false;
-      mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
-      mContainingAppId = nsIScriptSecurityManager::NO_APP_ID;
-      break;
-    }
-    default: {
-      MOZ_CRASH();
-    }
-  }
-}
-
-bool
-TabContext::IsBrowserElement() const
-{
-  return mIsBrowser;
-}
-
-bool
-TabContext::IsBrowserOrApp() const
-{
-  return HasOwnApp() || IsBrowserElement();
-}
-
-uint32_t
-TabContext::OwnAppId() const
-{
-  return mOwnAppId;
-}
-
-already_AddRefed<mozIApplication>
-TabContext::GetOwnApp() const
-{
-  return GetAppForId(OwnAppId());
-}
-
-bool
-TabContext::HasOwnApp() const
-{
-  return mOwnAppId != nsIScriptSecurityManager::NO_APP_ID;
-}
-
-uint32_t
-TabContext::BrowserOwnerAppId() const
-{
-  if (mIsBrowser) {
-    return mContainingAppId;
-  }
-  return nsIScriptSecurityManager::NO_APP_ID;
-}
-
-already_AddRefed<mozIApplication>
-TabContext::GetBrowserOwnerApp() const
-{
-  return GetAppForId(BrowserOwnerAppId());
-}
-
-bool
-TabContext::HasBrowserOwnerApp() const
-{
-  return BrowserOwnerAppId() != nsIScriptSecurityManager::NO_APP_ID;
-}
-
-uint32_t
-TabContext::AppOwnerAppId() const
-{
-  if (mOwnAppId != nsIScriptSecurityManager::NO_APP_ID) {
-    return mContainingAppId;
-  }
-  return nsIScriptSecurityManager::NO_APP_ID;
-}
-
-already_AddRefed<mozIApplication>
-TabContext::GetAppOwnerApp() const
-{
-  return GetAppForId(AppOwnerAppId());
-}
-
-bool
-TabContext::HasAppOwnerApp() const
-{
-  return AppOwnerAppId() != nsIScriptSecurityManager::NO_APP_ID;
-}
-
-uint32_t
-TabContext::OwnOrContainingAppId() const
-{
-  if (mIsBrowser) {
-    MOZ_ASSERT(mOwnAppId == nsIScriptSecurityManager::NO_APP_ID);
-    return mContainingAppId;
-  }
-
-  if (mOwnAppId) {
-    return mOwnAppId;
-  }
-
-  return mContainingAppId;
-}
-
-already_AddRefed<mozIApplication>
-TabContext::GetOwnOrContainingApp() const
-{
-  return GetAppForId(OwnOrContainingAppId());
-}
-
-bool
-TabContext::HasOwnOrContainingApp() const
-{
-  return OwnOrContainingAppId() != nsIScriptSecurityManager::NO_APP_ID;
-}
-
-bool
-TabContext::SetTabContext(const TabContext& aContext)
-{
-  NS_ENSURE_FALSE(mInitialized, false);
-
-  // Verify that we can actually get apps for the given ids.  This step gives us
-  // confidence that HasX() returns true iff GetX() returns true.
-  if (aContext.mOwnAppId != nsIScriptSecurityManager::NO_APP_ID) {
-    nsCOMPtr<mozIApplication> app = GetAppForId(aContext.mOwnAppId);
-    NS_ENSURE_TRUE(app, false);
-  }
-
-  if (aContext.mContainingAppId != nsIScriptSecurityManager::NO_APP_ID) {
-    nsCOMPtr<mozIApplication> app = GetAppForId(aContext.mContainingAppId);
-    NS_ENSURE_TRUE(app, false);
-  }
-
-  mInitialized = true;
-  mIsBrowser = aContext.mIsBrowser;
-  mOwnAppId = aContext.mOwnAppId;
-  mContainingAppId = aContext.mContainingAppId;
-  return true;
-}
-
-bool
-TabContext::SetTabContextForAppFrame(mozIApplication* aOwnApp, mozIApplication* aAppFrameOwnerApp)
-{
-  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 = nsIScriptSecurityManager::NO_APP_ID;
-  if (aOwnApp) {
-    nsresult rv = aOwnApp->GetLocalId(&ownAppId);
-    NS_ENSURE_SUCCESS(rv, false);
-  }
-
-  uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID;
-  if (aAppFrameOwnerApp) {
-    nsresult rv = aOwnApp->GetLocalId(&containingAppId);
-    NS_ENSURE_SUCCESS(rv, false);
-  }
-
-  mInitialized = true;
-  mIsBrowser = false;
-  mOwnAppId = ownAppId;
-  mContainingAppId = containingAppId;
-  return true;
-}
-
-bool
-TabContext::SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp)
-{
-  NS_ENSURE_FALSE(mInitialized, false);
-
-  uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID;
-  if (aBrowserFrameOwnerApp) {
-    nsresult rv = aBrowserFrameOwnerApp->GetLocalId(&containingAppId);
-    NS_ENSURE_SUCCESS(rv, false);
-  }
-
-  mInitialized = true;
-  mIsBrowser = true;
-  mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
-  mContainingAppId = containingAppId;
-  return true;
-}
-
-IPCTabContext
-TabContext::AsIPCTabContext() const
-{
-  if (mIsBrowser) {
-    return BrowserFrameIPCTabContext(mContainingAppId);
-  }
-
-  return AppFrameIPCTabContext(mOwnAppId, mContainingAppId);
-}
-
-already_AddRefed<mozIApplication>
-TabContext::GetAppForId(uint32_t aAppId) const
-{
-  if (aAppId == nsIScriptSecurityManager::NO_APP_ID) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(appsService, nullptr);
-
-  nsCOMPtr<mozIDOMApplication> domApp;
-  appsService->GetAppByLocalId(aAppId, getter_AddRefs(domApp));
-
-  nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp);
-  return app.forget();
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/ipc/TabContext.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=2 ts=8 et tw=80 : */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_TabContext_h
-#define mozilla_dom_TabContext_h
-
-#include "mozilla/Assertions.h"
-#include "mozilla/dom/PContent.h"
-#include "mozilla/dom/PBrowser.h"
-#include "nsIScriptSecurityManager.h"
-#include "mozIApplication.h"
-
-namespace mozilla {
-namespace dom {
-
-/**
- * TabContext encapsulates information about an iframe that may be a mozbrowser
- * or mozapp.  You can ask whether a TabContext correspodns to a mozbrowser or
- * mozapp, get the app that contains the browser, and so on.
- *
- * TabParent and TabChild both inherit from TabContext, and you can also have
- * standalone TabContext objects.
- *
- * This class is immutable except by calling one of the protected
- * SetTabContext*() methods (and those methods can only be called once).  See
- * also MutableTabContext.
- */
-class TabContext
-{
-public:
-  /**
-   * This constructor sets is-browser to false, and sets all relevant apps to
-   * NO_APP_ID.  If you inherit from TabContext, you can mutate this object
-   * exactly once by calling one of the protected SetTabContext*() methods.
-   */
-  TabContext();
-
-  /**
-   * This constructor copies the information in aContext.  The TabContext is
-   * immutable after calling this method; you won't be able call any of the
-   * protected SetTabContext*() methods on an object constructed using this
-   * constructor.
-   *
-   * If aContext is a PopupIPCTabContext with isBrowserElement false and whose
-   * openerParent is a browser element, this constructor will crash (even in
-   * release builds).  So please check that case before calling this method.
-   */
-  TabContext(const IPCTabContext& aContext);
-
-  /**
-   * Generates IPCTabContext of type BrowserFrameIPCTabContext or
-   * AppFrameIPCTabContext from this TabContext's information.
-   */
-  IPCTabContext AsIPCTabContext() const;
-
-  /**
-   * Does this TabContext correspond to a mozbrowser?  (<iframe mozbrowser
-   * mozapp> is not a browser.)
-   *
-   * If IsBrowserElement() is true, HasOwnApp() and HasAppOwnerApp() are
-   * guaranteed to be false.
-   *
-   * If IsBrowserElement() is false, HasBrowserOwnerApp() is guaranteed to be
-   * false.
-   */
-  bool IsBrowserElement() const;
-
-  /**
-   * Does this TabContext correspond to a mozbrowser or mozapp?  This is
-   * equivalent to IsBrowserElement() || HasOwnApp().
-   */
-  bool IsBrowserOrApp() const;
-
-  /**
-   * OwnAppId() returns the id of the app which directly corresponds to this
-   * context's frame.  GetOwnApp() returns the corresponding app object, and
-   * HasOwnApp() returns true iff GetOwnApp() would return a non-null value.
-   *
-   * If HasOwnApp() is true, IsBrowserElement() is guaranteed to be false.
-   */
-  uint32_t OwnAppId() const;
-  already_AddRefed<mozIApplication> GetOwnApp() const;
-  bool HasOwnApp() const;
-
-  /**
-   * BrowserOwnerAppId() gets the ID of the app which contains this browser
-   * frame.  If this is not a browser frame (i.e., if !IsBrowserElement()), then
-   * BrowserOwnerAppId() is guaranteed to return NO_APP_ID.
-   *
-   * Even if we are a browser frame, BrowserOwnerAppId() may still return
-   * NO_APP_ID, if this browser frame is not contained inside an app.
-   */
-  uint32_t BrowserOwnerAppId() const;
-  already_AddRefed<mozIApplication> GetBrowserOwnerApp() const;
-  bool HasBrowserOwnerApp() const;
-
-  /**
-   * AppOwnerAppId() gets the ID of the app which contains this app frame.  If
-   * this is not an app frame (i.e., if !HasOwnApp()), then AppOwnerAppId() is
-   * guaranteed to return NO_APP_ID.
-   *
-   * Even if we are an app frame, AppOwnerAppId() may still return NO_APP_ID, if
-   * this app frame is not contained inside an app.
-   */
-  uint32_t AppOwnerAppId() const;
-  already_AddRefed<mozIApplication> GetAppOwnerApp() const;
-  bool HasAppOwnerApp() const;
-
-  /**
-   * 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;
-
-protected:
-  /**
-   * These protected mutator methods let you modify a TabContext once.  Further
-   * attempts to modify a given TabContext will fail (the method will return
-   * false).
-   *
-   * These mutators will also fail if the TabContext was created with anything
-   * other than the no-args constructor.
-   */
-
-  /**
-   * 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.
-   */
-  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);
-
-private:
-  /**
-   * Translate an appId into a mozIApplication.
-   */
-  already_AddRefed<mozIApplication> GetAppForId(uint32_t aAppId) const;
-
-  /**
-   * Has this TabContext been initialized?  If so, mutator methods will fail.
-   */
-  bool mInitialized;
-
-  /**
-   * This TabContext's own app id.  If this is something other than NO_APP_ID,
-   * then this TabContext corresponds to an app, and mIsBrowser must be false.
-   */
-  uint32_t mOwnAppId;
-
-  /**
-   * The id of the app which contains this TabContext's frame.  If mIsBrowser,
-   * this corresponds to the ID of the app which contains the browser frame;
-   * otherwise, this correspodns to the ID of the app which contains the app
-   * frame.
-   */
-  uint32_t mContainingAppId;
-
-  /**
-   * Does this TabContext correspond to a browser element?
-   *
-   * If this is true, mOwnAppId must be NO_APP_ID.
-   */
-  bool mIsBrowser;
-};
-
-/**
- * MutableTabContext is the same as TabContext, 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)
-  {
-    return TabContext::SetTabContextForAppFrame(aOwnApp, aAppFrameOwnerApp);
-  }
-
-  bool SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp)
-  {
-    return TabContext::SetTabContextForBrowserFrame(aBrowserFrameOwnerApp);
-  }
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -68,28 +68,29 @@ namespace mozilla {
 namespace dom {
 
 TabParent* sEventCapturer;
 
 TabParent *TabParent::mIMETabParent = nullptr;
 
 NS_IMPL_ISUPPORTS3(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI)
 
-TabParent::TabParent(const TabContext& aContext)
-  : TabContext(aContext)
-  , mFrameElement(NULL)
+TabParent::TabParent(mozIApplication* aApp, bool aIsBrowserElement)
+  : mFrameElement(NULL)
+  , mApp(aApp)
   , mIMESelectionAnchor(0)
   , mIMESelectionFocus(0)
   , mIMEComposing(false)
   , mIMECompositionEnding(false)
   , mIMECompositionStart(0)
   , mIMESeqno(0)
   , mEventCaptureDepth(0)
   , mDimensions(0, 0)
   , mDPI(0)
+  , mIsBrowserElement(aIsBrowserElement)
   , mShown(false)
 {
 }
 
 TabParent::~TabParent()
 {
 }
 
@@ -182,17 +183,17 @@ TabParent::RecvEvent(const RemoteDOMEven
 bool
 TabParent::AnswerCreateWindow(PBrowserParent** retval)
 {
     if (!mBrowserDOMWindow) {
         return false;
     }
 
     // Only non-app, non-browser processes may call CreateWindow.
-    if (IsBrowserOrApp()) {
+    if (GetApp() || IsBrowserElement()) {
         return false;
     }
 
     // Get a new rendering area from the browserDOMWin.  We don't want
     // to be starting any loads here, so get it with a null URI.
     nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
     mBrowserDOMWindow->OpenURIInFrame(nullptr, nullptr,
                                       nsIBrowserDOMWindow::OPEN_NEWTAB,
@@ -890,25 +891,27 @@ TabParent::RecvPIndexedDBConstructor(PIn
   if (!IndexedDatabaseManager::IsMainProcess()) {
     NS_RUNTIMEABORT("Not supported yet!");
   }
 
   nsresult rv;
 
   // XXXbent Need to make sure we have a whitelist for chrome databases!
 
-  // Verify that the child is requesting to access a database it's allowed to
-  // see.  (aASCIIOrigin here specifies a TabContext + a website origin, and
-  // we're checking that the TabContext may access it.)
-  if (!aASCIIOrigin.EqualsLiteral("chrome") &&
-      !IndexedDatabaseManager::TabContextMayAccessOrigin(*this, aASCIIOrigin)) {
+  // Verify the appID in the origin first.
+  if (mApp && !aASCIIOrigin.EqualsLiteral("chrome")) {
+    uint32_t appId;
+    rv = mApp->GetLocalId(&appId);
+    NS_ENSURE_SUCCESS(rv, false);
 
-    NS_WARNING("App attempted to open databases that it does not have "
-               "permission to access!");
-    return false;
+    if (!IndexedDatabaseManager::OriginMatchesApp(aASCIIOrigin, appId)) {
+      NS_WARNING("App attempted to open databases that it does not have "
+                 "permission to access!");
+      return false;
+    }
   }
 
   nsCOMPtr<nsINode> node = do_QueryInterface(GetOwnerElement());
   NS_ENSURE_TRUE(node, false);
 
   nsIDocument* doc = node->GetOwnerDocument();
   NS_ENSURE_TRUE(doc, false);
 
@@ -1156,23 +1159,38 @@ TabParent::GetWidget() const
   if (!frame)
     return nullptr;
 
   nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget();
   return widget.forget();
 }
 
 bool
+TabParent::IsForMozBrowser()
+{
+  nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
+  nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(content);
+  if (browserFrame) {
+    bool isBrowser = false;
+    browserFrame->GetReallyIsBrowser(&isBrowser);
+    return isBrowser;
+  }
+  return false;
+}
+
+bool
 TabParent::UseAsyncPanZoom()
 {
   bool usingOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
   bool asyncPanZoomEnabled =
     Preferences::GetBool("layers.async-pan-zoom.enabled", false);
+  ContentParent* cp = static_cast<ContentParent*>(Manager());
   return (usingOffMainThreadCompositing &&
-          IsBrowserElement() && asyncPanZoomEnabled);
+          !cp->IsForApp() && IsForMozBrowser() &&
+          asyncPanZoomEnabled);
 }
 
 void
 TabParent::MaybeForwardEventToRenderFrame(const nsInputEvent& aEvent,
                                           nsInputEvent* aOutEvent)
 {
   if (RenderFrameParent* rfp = GetRenderFrame()) {
     rfp->NotifyInputEvent(aEvent, aOutEvent);
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -7,17 +7,16 @@
 #ifndef mozilla_tabs_TabParent_h
 #define mozilla_tabs_TabParent_h
 
 #include "base/basictypes.h"
 
 #include "jsapi.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/dom/PContentDialogParent.h"
-#include "mozilla/dom/TabContext.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "nsCOMPtr.h"
 #include "nsIAuthPromptProvider.h"
 #include "nsIBrowserDOMWindow.h"
 #include "nsIDialogParamBlock.h"
 #include "nsISecureBrowserUI.h"
 #include "nsITabParent.h"
 #include "nsWeakReference.h"
@@ -46,29 +45,31 @@ class ClonedMessageData;
 struct StructuredCloneData;
 
 class ContentDialogParent : public PContentDialogParent {};
 
 class TabParent : public PBrowserParent 
                 , public nsITabParent 
                 , public nsIAuthPromptProvider
                 , public nsISecureBrowserUI
-                , public TabContext
 {
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
 
 public:
-    TabParent(const TabContext& aContext);
+    TabParent(mozIApplication* aApp, bool aIsBrowserElement);
     virtual ~TabParent();
     nsIDOMElement* GetOwnerElement() { return mFrameElement; }
     void SetOwnerElement(nsIDOMElement* aElement);
     nsIBrowserDOMWindow *GetBrowserDOMWindow() { return mBrowserDOMWindow; }
     void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserDOMWindow) {
         mBrowserDOMWindow = aBrowserDOMWindow;
     }
+ 
+    mozIApplication* GetApp() { return mApp; }
+    bool IsBrowserElement() { return mIsBrowserElement; }
 
     /**
      * Return the TabParent that has decided it wants to capture an
      * event series for fast-path dispatch to its subprocess, if one
      * has.
      *
      * DOM event dispatch and widget are free to ignore capture
      * requests from TabParents; the end result wrt remote content is
@@ -256,16 +257,17 @@ protected:
     bool AllowContentIME();
 
     virtual PRenderFrameParent* AllocPRenderFrame(ScrollingBehavior* aScrolling,
                                                   LayersBackend* aBackend,
                                                   int32_t* aMaxTextureSize,
                                                   uint64_t* aLayersId) MOZ_OVERRIDE;
     virtual bool DeallocPRenderFrame(PRenderFrameParent* aFrame) MOZ_OVERRIDE;
 
+    nsCOMPtr<mozIApplication> mApp;
     // IME
     static TabParent *mIMETabParent;
     nsString mIMECacheText;
     uint32_t mIMESelectionAnchor;
     uint32_t mIMESelectionFocus;
     bool mIMEComposing;
     bool mIMECompositionEnding;
     // Buffer to store composition text during ResetInputState
@@ -274,24 +276,27 @@ protected:
     uint32_t mIMECompositionStart;
     uint32_t mIMESeqno;
 
     // The number of event series we're currently capturing.
     int32_t mEventCaptureDepth;
 
     nsIntSize mDimensions;
     float mDPI;
+    bool mIsBrowserElement;
     bool mShown;
 
 private:
     already_AddRefed<nsFrameLoader> GetFrameLoader() const;
     already_AddRefed<nsIWidget> GetWidget() const;
     layout::RenderFrameParent* GetRenderFrame();
     void TryCacheDPI();
-
+    // Return true iff this TabParent was created for a mozbrowser
+    // frame.
+    bool IsForMozBrowser();
     // When true, we create a pan/zoom controller for our frame and
     // notify it of input events targeting us.
     bool UseAsyncPanZoom();
     // If we have a render frame currently, notify it that we're about
     // to dispatch |aEvent| to our child.  If there's a relevant
     // transform in place, |aOutEvent| is the transformed |aEvent| to
     // dispatch to content.
     void MaybeForwardEventToRenderFrame(const nsInputEvent& aEvent,
--- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
@@ -1628,18 +1628,22 @@ uint32_t nsWindowWatcher::CalculateChrom
   if (!(chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) {
     // Remove the dependent flag if we're not opening as chrome
     chromeFlags &= ~nsIWebBrowserChrome::CHROME_DEPENDENT;
   }
 
   // Disable CHROME_OPENAS_DIALOG if the window is inside <iframe mozbrowser>.
   // It's up to the embedder to interpret what dialog=1 means.
   nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
-  if (docshell && docshell->GetIsInBrowserOrApp()) {
-    chromeFlags &= ~nsIWebBrowserChrome::CHROME_OPENAS_DIALOG;
+  if (docshell) {
+    bool belowContentBoundary = false;
+    docshell->GetIsBelowContentBoundary(&belowContentBoundary);
+    if (belowContentBoundary) {
+      chromeFlags &= ~nsIWebBrowserChrome::CHROME_OPENAS_DIALOG;
+    }
   }
 
   return chromeFlags;
 }
 
 // static
 int32_t
 nsWindowWatcher::WinHasOption(const char *aOptions, const char *aName,
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -191,18 +191,19 @@ gfxAndroidPlatform::FontHintingEnabled()
     // hinting.
     // 
     // XXX when gecko-android-java is used as an "app runtime", we'll
     // want to re-enable hinting.
     return false;
 #else
     // Otherwise, enable hinting unless we're in a content process
     // that might be used for non-reflowing zoom.
-    return XRE_GetProcessType() != GeckoProcessType_Content ||
-           ContentChild::GetSingleton()->HasOwnApp();
+    return (XRE_GetProcessType() != GeckoProcessType_Content ||
+            (ContentChild::GetSingleton()->IsForApp() &&
+             !ContentChild::GetSingleton()->IsForBrowser()));
 #endif //  MOZ_USING_ANDROID_JAVA_WIDGETS
 }
 
 int
 gfxAndroidPlatform::GetScreenDepth() const
 {
     return mScreenDepth;
 }
--- a/testing/mochitest/android.json
+++ b/testing/mochitest/android.json
@@ -147,19 +147,17 @@
  "dom/imptests/webapps/DOMCore/tests/approved/test_Range-set.html": "bug 775227",
  "dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html": "bug 775227",
  "dom/imptests/webapps/WebStorage/tests/submissions/Infraware/test_storage_local_key.html": "bug 775227",
  "dom/indexedDB/ipc/test_ipc.html": "bug 783513",
  "dom/indexedDB/test/test_third_party.html": "TIMED_OUT",
  "dom/indexedDB/test/test_event_propagation.html": "TIMED_OUT, bug 780855",
  "dom/indexedDB/test/test_app_isolation_inproc.html": "TIMED_OUT",
  "dom/indexedDB/test/test_app_isolation_oop.html": "TIMED_OUT",
- "dom/indexedDB/test/test_webapp_clearBrowserData_inproc_inproc.html": "No test app installed",
- "dom/indexedDB/test/test_webapp_clearBrowserData_inproc_oop.html": "No test app installed",
- "dom/indexedDB/test/test_webapp_clearBrowserData_oop_inproc.html": "No test app installed",
+ "dom/indexedDB/test/test_webapp_clearBrowserData.html": "No test app installed",
  "dom/network/tests/test_network_basics.html": "",
  "dom/permission/tests/test_permission_basics.html": "",
  "dom/sms/tests/test_sms_basics.html": "",
  "dom/tests/mochitest/ajax/jquery/test_jQuery.html": "bug 775227",
  "dom/tests/mochitest/ajax/offline/test_simpleManifest.html": "TIMED_OUT",
  "dom/tests/mochitest/ajax/offline/test_updatingManifest.html": "TIMED_OUT",
  "dom/tests/mochitest/ajax/offline/test_xhtmlManifest.xhtml": "TIMED_OUT",
  "dom/tests/mochitest/ajax/prototype/test_Prototype.html": "",
--- a/xpfe/appshell/src/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/src/nsContentTreeOwner.cpp
@@ -846,17 +846,17 @@ nsContentTreeOwner::ProvideWindow(nsIDOM
                                static_cast<nsIDocShellTreeOwner*>(this)),
                "Parent from wrong docshell tree?");
 #endif
 
   // If aParent is inside an <iframe mozbrowser> and this isn't a request to
   // open a modal-type window, we're going to create a new <iframe mozbrowser>
   // and return its window here.
   nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
-  if (docshell && docshell->GetIsInBrowserOrApp() &&
+  if (docshell && docshell->GetIsBelowContentBoundary() &&
       !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
                         nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
                         nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
     *aWindowIsNew =
       BrowserElementParent::OpenWindowInProcess(aParent, aURI, aName,
                                                 aFeatures, aReturn);
 
     // If OpenWindowInProcess failed (perhaps because the embedder blocked the