Back out f99521bfd197:38657fcd2d1a (bug 890570) for Linux xpcshell failures
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 10 Aug 2013 17:23:05 -0700
changeset 142186 2c77b620ffe8b482cf2fbb62799023d429f50eed
parent 142185 5fdf867f67d6ac764e44d257aa2b8280e3a20fbe
child 142187 954b005832ac4b4b3528c6a7662b6aee1ed6096d
push id25084
push usercbook@mozilla.com
push dateMon, 12 Aug 2013 09:28:56 +0000
treeherdermozilla-central@f057fca09627 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs890570
milestone26.0a1
backs outf99521bfd19727096e41f0f63d6f7ede7d8f3335
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
Back out f99521bfd197:38657fcd2d1a (bug 890570) for Linux xpcshell failures CLOSED TREE
dom/network/src/PTCPSocket.ipdl
dom/network/src/TCPSocketChild.cpp
dom/network/src/TCPSocketParent.cpp
dom/network/src/TCPSocketParent.h
netwerk/cookie/CookieServiceChild.cpp
netwerk/cookie/CookieServiceParent.cpp
netwerk/cookie/CookieServiceParent.h
netwerk/cookie/PCookieService.ipdl
netwerk/ipc/NeckoChild.cpp
netwerk/ipc/NeckoChild.h
netwerk/ipc/NeckoParent.cpp
netwerk/ipc/NeckoParent.h
netwerk/ipc/PNecko.ipdl
netwerk/ipc/RemoteOpenFileChild.cpp
netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp
--- a/dom/network/src/PTCPSocket.ipdl
+++ b/dom/network/src/PTCPSocket.ipdl
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
 
 /* 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 protocol PNecko;
+include protocol PBrowser;
 
 include "mozilla/net/NeckoMessageUtils.h";
 
 using mozilla::void_t;
 
 struct TCPError {
   nsString name;
 };
@@ -30,17 +31,18 @@ namespace mozilla {
 namespace net {
 
 //-------------------------------------------------------------------
 protocol PTCPSocket
 {
   manager PNecko;
 
 parent:
-  Open(nsString host, uint16_t port, bool useSSL, nsString binaryType);
+  Open(nsString host, uint16_t port, bool useSSL, nsString binaryType,
+       nullable PBrowser browser);
   Data(SendableData data);
   Suspend();
   Resume();
   Close();
 
 child:
   Callback(nsString type, CallbackData data,
            nsString readyState, uint32_t bufferedAmount);
--- a/dom/network/src/TCPSocketChild.cpp
+++ b/dom/network/src/TCPSocketChild.cpp
@@ -86,17 +86,18 @@ TCPSocketChild::Open(nsITCPSocketInterna
 
   MOZ_ASSERT(aWindowObj.isObject());
   mWindowObj = js::CheckedUnwrap(&aWindowObj.toObject());
   if (!mWindowObj) {
     return NS_ERROR_FAILURE;
   }
   AddIPDLReference();
   gNeckoChild->SendPTCPSocketConstructor(this);
-  SendOpen(nsString(aHost), aPort, aUseSSL, nsString(aBinaryType));
+  SendOpen(nsString(aHost), aPort, aUseSSL, nsString(aBinaryType),
+           GetTabChildFrom(aWindow));
   return NS_OK;
 }
 
 void
 TCPSocketChildBase::ReleaseIPDLReference()
 {
   MOZ_ASSERT(mIPCOpen);
   mIPCOpen = false;
--- a/dom/network/src/TCPSocketParent.cpp
+++ b/dom/network/src/TCPSocketParent.cpp
@@ -6,18 +6,16 @@
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "nsJSUtils.h"
 #include "nsIDOMTCPSocket.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 #include "mozilla/unused.h"
 #include "mozilla/AppProcessChecker.h"
-#include "mozilla/net/NeckoCommon.h"
-#include "mozilla/net/PNeckoParent.h"
 
 namespace IPC {
 
 //Defined in TCPSocketChild.cpp
 extern bool
 DeserializeArrayBuffer(JS::Handle<JSObject*> aObj,
                        const InfallibleTArray<uint8_t>& aBuffer,
                        JS::MutableHandle<JS::Value> aVal);
@@ -77,22 +75,21 @@ NS_IMETHODIMP_(nsrefcnt) TCPSocketParent
     mozilla::unused << PTCPSocketParent::SendRequestDelete();
     return 1;
   }
   return refcnt;
 }
 
 bool
 TCPSocketParent::RecvOpen(const nsString& aHost, const uint16_t& aPort, const bool& aUseSSL,
-                          const nsString& aBinaryType)
+                          const nsString& aBinaryType, PBrowserParent* aBrowser)
 {
   // We don't have browser actors in xpcshell, and hence can't run automated
   // tests without this loophole.
-  if (net::UsingNeckoIPCSecurity() &&
-      !AssertAppProcessPermission(Manager()->Manager(), "tcp-socket")) {
+  if (aBrowser && !AssertAppProcessPermission(aBrowser, "tcp-socket")) {
     FireInteralError(this, __LINE__);
     return true;
   }
 
   nsresult rv;
   mIntermediary = do_CreateInstance("@mozilla.org/tcp-socket-intermediary;1", &rv);
   if (NS_FAILED(rv)) {
     FireInteralError(this, __LINE__);
--- a/dom/network/src/TCPSocketParent.h
+++ b/dom/network/src/TCPSocketParent.h
@@ -42,17 +42,18 @@ class TCPSocketParent : public mozilla::
 {
 public:
   NS_DECL_NSITCPSOCKETPARENT
   NS_IMETHOD_(nsrefcnt) Release() MOZ_OVERRIDE;
 
   TCPSocketParent() : mIntermediaryObj(nullptr) {}
 
   virtual bool RecvOpen(const nsString& aHost, const uint16_t& aPort,
-                        const bool& useSSL, const nsString& aBinaryType);
+                        const bool& useSSL, const nsString& aBinaryType,
+                        PBrowserParent* aBrowser);
 
   virtual bool RecvSuspend() MOZ_OVERRIDE;
   virtual bool RecvResume() MOZ_OVERRIDE;
   virtual bool RecvClose() MOZ_OVERRIDE;
   virtual bool RecvData(const SendableData& aData) MOZ_OVERRIDE;
   virtual bool RecvRequestDelete() MOZ_OVERRIDE;
 
 private:
--- a/netwerk/cookie/CookieServiceChild.cpp
+++ b/netwerk/cookie/CookieServiceChild.cpp
@@ -1,19 +1,21 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/net/CookieServiceChild.h"
+#include "mozilla/dom/TabChild.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/net/NeckoChild.h"
 #include "nsIURI.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
+#include "nsITabChild.h"
 #include "nsNetUtil.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
 
 // Behavior pref constants
@@ -111,20 +113,32 @@ CookieServiceChild::GetCookieStringInter
   // Determine whether the request is foreign. Failure is acceptable.
   bool isForeign = true;
   if (RequireThirdPartyCheck())
     mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
 
   URIParams uriParams;
   SerializeURI(aHostURI, uriParams);
 
+  nsCOMPtr<nsITabChild> iTabChild;
+  mozilla::dom::TabChild* tabChild = nullptr;
+  if (aChannel) {
+    NS_QueryNotificationCallbacks(aChannel, iTabChild);
+    if (iTabChild) {
+      tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
+    }
+    if (MissingRequiredTabChild(tabChild, "cookie")) {
+      return NS_ERROR_ILLEGAL_VALUE;
+    }
+  }
+
   // Synchronously call the parent.
   nsAutoCString result;
   SendGetCookieString(uriParams, !!isForeign, aFromHttp,
-                      IPC::SerializedLoadContext(aChannel), &result);
+                      IPC::SerializedLoadContext(aChannel), tabChild, &result);
   if (!result.IsEmpty())
     *aCookieString = ToNewCString(result);
 
   return NS_OK;
 }
 
 nsresult
 CookieServiceChild::SetCookieStringInternal(nsIURI *aHostURI,
@@ -144,19 +158,31 @@ CookieServiceChild::SetCookieStringInter
   nsDependentCString cookieString(aCookieString);
   nsDependentCString serverTime;
   if (aServerTime)
     serverTime.Rebind(aServerTime);
 
   URIParams uriParams;
   SerializeURI(aHostURI, uriParams);
 
+  nsCOMPtr<nsITabChild> iTabChild;
+  mozilla::dom::TabChild* tabChild = nullptr;
+  if (aChannel) {
+    NS_QueryNotificationCallbacks(aChannel, iTabChild);
+    if (iTabChild) {
+      tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
+    }
+    if (MissingRequiredTabChild(tabChild, "cookie")) {
+      return NS_ERROR_ILLEGAL_VALUE;
+    }
+  }
+
   // Synchronously call the parent.
   SendSetCookieString(uriParams, !!isForeign, cookieString, serverTime,
-                      aFromHttp, IPC::SerializedLoadContext(aChannel));
+                      aFromHttp, IPC::SerializedLoadContext(aChannel), tabChild);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 CookieServiceChild::Observe(nsISupports     *aSubject,
                             const char      *aTopic,
                             const PRUnichar *aData)
 {
--- a/netwerk/cookie/CookieServiceParent.cpp
+++ b/netwerk/cookie/CookieServiceParent.cpp
@@ -1,42 +1,42 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/net/CookieServiceParent.h"
-#include "mozilla/dom/PContentParent.h"
+#include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/net/NeckoParent.h"
 
 #include "mozilla/ipc/URIUtils.h"
 #include "nsCookieService.h"
 #include "nsNetUtil.h"
 #include "nsPrintfCString.h"
 
 using namespace mozilla::ipc;
-using mozilla::dom::PContentParent;
+using mozilla::dom::PBrowserParent;
 using mozilla::net::NeckoParent;
 
 namespace mozilla {
 namespace net {
 
 MOZ_WARN_UNUSED_RESULT
-bool
-CookieServiceParent::GetAppInfoFromParams(const IPC::SerializedLoadContext &aLoadContext,
-                                          uint32_t& aAppId,
-                                          bool& aIsInBrowserElement,
-                                          bool& aIsPrivate)
+static bool
+GetAppInfoFromParams(const IPC::SerializedLoadContext &aLoadContext,
+                     PBrowserParent* aBrowser,
+                     uint32_t& aAppId,
+                     bool& aIsInBrowserElement,
+                     bool& aIsPrivate)
 {
   aAppId = NECKO_NO_APP_ID;
   aIsInBrowserElement = false;
   aIsPrivate = false;
 
-  const char* error = NeckoParent::GetValidatedAppInfo(aLoadContext,
-                                                       Manager()->Manager(),
+  const char* error = NeckoParent::GetValidatedAppInfo(aLoadContext, aBrowser,
                                                        &aAppId,
                                                        &aIsInBrowserElement);
   if (error) {
     NS_WARNING(nsPrintfCString("CookieServiceParent: GetAppInfoFromParams: "
                                "FATAL error: %s: KILLING CHILD PROCESS\n",
                                error).get());
     return false;
   }
@@ -64,30 +64,31 @@ CookieServiceParent::~CookieServiceParen
 }
 
 bool
 CookieServiceParent::RecvGetCookieString(const URIParams& aHost,
                                          const bool& aIsForeign,
                                          const bool& aFromHttp,
                                          const IPC::SerializedLoadContext&
                                                aLoadContext,
+                                         PBrowserParent* aBrowser,
                                          nsCString* aResult)
 {
   if (!mCookieService)
     return true;
 
   // Deserialize URI. Having a host URI is mandatory and should always be
   // provided by the child; thus we consider failure fatal.
   nsCOMPtr<nsIURI> hostURI = DeserializeURI(aHost);
   if (!hostURI)
     return false;
 
   uint32_t appId;
   bool isInBrowserElement, isPrivate;
-  bool valid = GetAppInfoFromParams(aLoadContext, appId,
+  bool valid = GetAppInfoFromParams(aLoadContext, aBrowser, appId,
                                     isInBrowserElement, isPrivate);
   if (!valid) {
     return false;
   }
 
   mCookieService->GetCookieStringInternal(hostURI, aIsForeign, aFromHttp, appId,
                                           isInBrowserElement, isPrivate, *aResult);
   return true;
@@ -95,30 +96,31 @@ CookieServiceParent::RecvGetCookieString
 
 bool
 CookieServiceParent::RecvSetCookieString(const URIParams& aHost,
                                          const bool& aIsForeign,
                                          const nsCString& aCookieString,
                                          const nsCString& aServerTime,
                                          const bool& aFromHttp,
                                          const IPC::SerializedLoadContext&
-                                               aLoadContext)
+                                               aLoadContext,
+                                         PBrowserParent* aBrowser)
 {
   if (!mCookieService)
     return true;
 
   // Deserialize URI. Having a host URI is mandatory and should always be
   // provided by the child; thus we consider failure fatal.
   nsCOMPtr<nsIURI> hostURI = DeserializeURI(aHost);
   if (!hostURI)
     return false;
 
   uint32_t appId;
   bool isInBrowserElement, isPrivate;
-  bool valid = GetAppInfoFromParams(aLoadContext, appId,
+  bool valid = GetAppInfoFromParams(aLoadContext, aBrowser, appId,
                                     isInBrowserElement, isPrivate);
   if (!valid) {
     return false;
   }
 
   nsDependentCString cookieString(aCookieString, 0);
   //TODO: bug 812475, pass a real channel object
   mCookieService->SetCookieStringInternal(hostURI, aIsForeign, cookieString,
--- a/netwerk/cookie/CookieServiceParent.h
+++ b/netwerk/cookie/CookieServiceParent.h
@@ -8,45 +8,44 @@
 
 #include "mozilla/net/PCookieServiceParent.h"
 #include "SerializedLoadContext.h"
 
 class nsCookieService;
 class nsIIOService;
 
 namespace mozilla {
+namespace dom {
+  class PBrowserParent;
+}
 namespace net {
 
 class CookieServiceParent : public PCookieServiceParent
 {
 public:
   CookieServiceParent();
   virtual ~CookieServiceParent();
 
 protected:
-  MOZ_WARN_UNUSED_RESULT bool
-  GetAppInfoFromParams(const IPC::SerializedLoadContext &aLoadContext,
-                       uint32_t& aAppId,
-                       bool& aIsInBrowserElement,
-                       bool& aIsPrivate);
-
-   virtual bool RecvGetCookieString(const URIParams& aHost,
+  virtual bool RecvGetCookieString(const URIParams& aHost,
                                    const bool& aIsForeign,
                                    const bool& aFromHttp,
                                    const IPC::SerializedLoadContext&
                                          loadContext,
-                                   nsCString* aResult) MOZ_OVERRIDE;
+                                   mozilla::dom::PBrowserParent* aBrowser,
+                                   nsCString* aResult);
 
   virtual bool RecvSetCookieString(const URIParams& aHost,
                                    const bool& aIsForeign,
                                    const nsCString& aCookieString,
                                    const nsCString& aServerTime,
                                    const bool& aFromHttp,
                                    const IPC::SerializedLoadContext&
-                                         loadContext) MOZ_OVERRIDE;
+                                         loadContext,
+                                   mozilla::dom::PBrowserParent* aBrowser);
 
   nsRefPtr<nsCookieService> mCookieService;
 };
 
 }
 }
 
 #endif // mozilla_net_CookieServiceParent_h
--- a/netwerk/cookie/PCookieService.ipdl
+++ b/netwerk/cookie/PCookieService.ipdl
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
 
 /* 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 protocol PNecko;
+include protocol PBrowser;
 include URIParams;
 
 include "SerializedLoadContext.h";
 
 using IPC::SerializedLoadContext;
 
 namespace mozilla {
 namespace net {
@@ -59,17 +60,18 @@ parent:
    * @see nsICookieService.getCookieStringFromHttp
    * @see mozIThirdPartyUtil.isThirdPartyChannel
    *
    * @return the resulting cookie string.
    */
   sync GetCookieString(URIParams host,
                        bool isForeign,
                        bool fromHttp,
-                       SerializedLoadContext loadContext)
+                       SerializedLoadContext loadContext,
+                       nullable PBrowser browser)
        returns (nsCString result);
 
   /*
    * Set a cookie string.
    *
    * @param host
    *        Same as the 'aURI' argument to nsICookieService.setCookieString.
    * @param isForeign
@@ -96,16 +98,17 @@ parent:
    * @see nsICookieService.setCookieStringFromHttp
    * @see mozIThirdPartyUtil.isThirdPartyChannel
    */
   SetCookieString(URIParams host,
                   bool isForeign,
                   nsCString cookieString,
                   nsCString serverTime,
                   bool fromHttp,
-                  SerializedLoadContext loadContext);
+                  SerializedLoadContext loadContext,
+                  nullable PBrowser browser);
 
   __delete__();
 };
 
 }
 }
 
--- a/netwerk/ipc/NeckoChild.cpp
+++ b/netwerk/ipc/NeckoChild.cpp
@@ -184,17 +184,17 @@ bool
 NeckoChild::DeallocPTCPServerSocketChild(PTCPServerSocketChild* child)
 {
   TCPServerSocketChild* p = static_cast<TCPServerSocketChild*>(child);
   p->ReleaseIPDLReference();
   return true;
 }
 
 PRemoteOpenFileChild*
-NeckoChild::AllocPRemoteOpenFileChild(const URIParams&)
+NeckoChild::AllocPRemoteOpenFileChild(const URIParams&, PBrowserChild*)
 {
   // We don't allocate here: instead we always use IPDL constructor that takes
   // an existing RemoteOpenFileChild
   NS_NOTREACHED("AllocPRemoteOpenFileChild should not be called on child");
   return nullptr;
 }
 
 bool
--- a/netwerk/ipc/NeckoChild.h
+++ b/netwerk/ipc/NeckoChild.h
@@ -42,17 +42,18 @@ protected:
   virtual PWebSocketChild* AllocPWebSocketChild(PBrowserChild*, const SerializedLoadContext&);
   virtual bool DeallocPWebSocketChild(PWebSocketChild*);
   virtual PTCPSocketChild* AllocPTCPSocketChild();
   virtual bool DeallocPTCPSocketChild(PTCPSocketChild*);
   virtual PTCPServerSocketChild* AllocPTCPServerSocketChild(const uint16_t& aLocalPort,
                                                        const uint16_t& aBacklog,
                                                        const nsString& aBinaryType);
   virtual bool DeallocPTCPServerSocketChild(PTCPServerSocketChild*);
-  virtual PRemoteOpenFileChild* AllocPRemoteOpenFileChild(const URIParams&);
+  virtual PRemoteOpenFileChild* AllocPRemoteOpenFileChild(const URIParams&,
+                                                          PBrowserChild*);
   virtual bool DeallocPRemoteOpenFileChild(PRemoteOpenFileChild*);
 };
 
 /**
  * Reference to the PNecko Child protocol.
  * Null if this is not a content process.
  */
 extern PNeckoChild *gNeckoChild;
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -8,30 +8,28 @@
 #include "nsHttp.h"
 #include "mozilla/net/NeckoParent.h"
 #include "mozilla/net/HttpChannelParent.h"
 #include "mozilla/net/CookieServiceParent.h"
 #include "mozilla/net/WyciwygChannelParent.h"
 #include "mozilla/net/FTPChannelParent.h"
 #include "mozilla/net/WebSocketChannelParent.h"
 #include "mozilla/net/RemoteOpenFileParent.h"
-#include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/dom/network/TCPSocketParent.h"
 #include "mozilla/dom/network/TCPServerSocketParent.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/LoadContext.h"
 #include "mozilla/AppProcessChecker.h"
 #include "nsPrintfCString.h"
 #include "nsHTMLDNSPrefetch.h"
 #include "nsIAppsService.h"
 #include "nsEscape.h"
 #include "RemoteOpenFileParent.h"
 
-using mozilla::dom::ContentParent;
 using mozilla::dom::TabParent;
 using mozilla::net::PTCPSocketParent;
 using mozilla::dom::TCPSocketParent;
 using mozilla::net::PTCPServerSocketParent;
 using mozilla::dom::TCPServerSocketParent;
 using IPC::SerializedLoadContext;
 
 namespace mozilla {
@@ -74,90 +72,81 @@ PBOverrideStatusFromLoadContext(const Se
       kPBOverride_Private :
       kPBOverride_NotPrivate;
   }
   return kPBOverride_Unset;
 }
 
 const char*
 NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
-                                 PContentParent* aContent,
+                                 PBrowserParent* aBrowser,
                                  uint32_t* aAppId,
                                  bool* aInBrowserElement)
 {
-  *aAppId = NECKO_UNKNOWN_APP_ID;
-  *aInBrowserElement = false;
-
   if (UsingNeckoIPCSecurity()) {
+    if (!aBrowser) {
+      return "missing required PBrowser argument";
+    }
     if (!aSerialized.IsNotNull()) {
       return "SerializedLoadContext from child is null";
     }
   }
 
-  uint32_t appId;
-  bool inBrowserElement;
+  *aAppId = NECKO_UNKNOWN_APP_ID;
+  *aInBrowserElement = false;
+
+  if (aBrowser) {
+    nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(aBrowser);
 
-  const InfallibleTArray<PBrowserParent*>& browsers = aContent->ManagedPBrowserParent();
-  for (uint32_t i = 0; i < browsers.Length(); i++) {
-    nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(browsers[i]);
-    appId = tabParent->OwnOrContainingAppId();
-    inBrowserElement = aSerialized.IsNotNull() ? aSerialized.mIsInBrowserElement
-                                               : tabParent->IsBrowserElement();
+    *aAppId = tabParent->OwnOrContainingAppId();
+    *aInBrowserElement = aSerialized.IsNotNull() ? aSerialized.mIsInBrowserElement
+                                                 : tabParent->IsBrowserElement();
 
-    if (appId == NECKO_UNKNOWN_APP_ID) {
-      continue;
+    if (*aAppId == NECKO_UNKNOWN_APP_ID) {
+      return "TabParent reports appId=NECKO_UNKNOWN_APP_ID!";
     }
     // We may get appID=NO_APP if child frame is neither a browser nor an app
-    if (appId == NECKO_NO_APP_ID) {
+    if (*aAppId == NECKO_NO_APP_ID) {
       if (tabParent->HasOwnApp()) {
-        continue;
+        return "TabParent reports NECKO_NO_APP_ID but also is an app";
       }
       if (UsingNeckoIPCSecurity() && tabParent->IsBrowserElement()) {
         // <iframe mozbrowser> which doesn't have an <iframe mozapp> above it.
         // This is not supported now, and we'll need to do a code audit to make
         // sure we can handle it (i.e don't short-circuit using separate
         // namespace if just appID==0)
-        continue;
+        return "TabParent reports appId=NECKO_NO_APP_ID but is a mozbrowser";
       }
     }
-    *aAppId = appId;
-    *aInBrowserElement = inBrowserElement;
-    return nullptr;
-  }
-
-  if (browsers.Length() != 0) {
-    return "App does not have permission";
-  }
-
-  if (!UsingNeckoIPCSecurity()) {
-    // We are running xpcshell tests
+  } else {
+    // Only trust appId/inBrowser from child-side loadcontext if we're in
+    // testing mode: allows xpcshell tests to masquerade as apps
+    MOZ_ASSERT(!UsingNeckoIPCSecurity());
+    if (UsingNeckoIPCSecurity()) {
+      return "internal error";
+    }
     if (aSerialized.IsNotNull()) {
-      appId = aSerialized.mAppId;
-      inBrowserElement = aSerialized.mIsInBrowserElement;
+      *aAppId = aSerialized.mAppId;
+      *aInBrowserElement = aSerialized.mIsInBrowserElement;
     } else {
-      appId = NECKO_NO_APP_ID;
+      *aAppId = NECKO_NO_APP_ID;
     }
-    *aAppId = appId;
-    *aInBrowserElement = inBrowserElement;
-    return nullptr;
   }
-
-  return "ContentParent does not have any PBrowsers";
+  return nullptr;
 }
 
 const char *
 NeckoParent::CreateChannelLoadContext(PBrowserParent* aBrowser,
-                                      PContentParent* aContent,
                                       const SerializedLoadContext& aSerialized,
                                       nsCOMPtr<nsILoadContext> &aResult)
 {
   uint32_t appId = NECKO_UNKNOWN_APP_ID;
   bool inBrowser = false;
   dom::Element* topFrameElement = nullptr;
-  const char* error = GetValidatedAppInfo(aSerialized, aContent, &appId, &inBrowser);
+  const char* error = GetValidatedAppInfo(aSerialized, aBrowser, &appId, &inBrowser);
   if (error) {
     return error;
   }
 
   if (aBrowser) {
     nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(aBrowser);
     topFrameElement = tabParent->GetOwnerElement();
   }
@@ -172,18 +161,18 @@ NeckoParent::CreateChannelLoadContext(PB
 }
 
 PHttpChannelParent*
 NeckoParent::AllocPHttpChannelParent(PBrowserParent* aBrowser,
                                      const SerializedLoadContext& aSerialized,
                                      const HttpChannelCreationArgs& aOpenArgs)
 {
   nsCOMPtr<nsILoadContext> loadContext;
-  const char *error = CreateChannelLoadContext(aBrowser, Manager(),
-                                               aSerialized, loadContext);
+  const char *error = CreateChannelLoadContext(aBrowser, aSerialized,
+                                               loadContext);
   if (error) {
     printf_stderr("NeckoParent::AllocPHttpChannelParent: "
                   "FATAL error: %s: KILLING CHILD PROCESS\n",
                   error);
     return nullptr;
   }
   PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(aSerialized);
   HttpChannelParent *p = new HttpChannelParent(aBrowser, loadContext, overrideStatus);
@@ -211,18 +200,18 @@ NeckoParent::RecvPHttpChannelConstructor
 }
 
 PFTPChannelParent*
 NeckoParent::AllocPFTPChannelParent(PBrowserParent* aBrowser,
                                     const SerializedLoadContext& aSerialized,
                                     const FTPChannelCreationArgs& aOpenArgs)
 {
   nsCOMPtr<nsILoadContext> loadContext;
-  const char *error = CreateChannelLoadContext(aBrowser, Manager(),
-                                               aSerialized, loadContext);
+  const char *error = CreateChannelLoadContext(aBrowser, aSerialized,
+                                               loadContext);
   if (error) {
     printf_stderr("NeckoParent::AllocPFTPChannelParent: "
                   "FATAL error: %s: KILLING CHILD PROCESS\n",
                   error);
     return nullptr;
   }
   PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(aSerialized);
   FTPChannelParent *p = new FTPChannelParent(loadContext, overrideStatus);
@@ -278,18 +267,18 @@ NeckoParent::DeallocPWyciwygChannelParen
   return true;
 }
 
 PWebSocketParent*
 NeckoParent::AllocPWebSocketParent(PBrowserParent* browser,
                                    const SerializedLoadContext& serialized)
 {
   nsCOMPtr<nsILoadContext> loadContext;
-  const char *error = CreateChannelLoadContext(browser, Manager(),
-                                               serialized, loadContext);
+  const char *error = CreateChannelLoadContext(browser, serialized,
+                                               loadContext);
   if (error) {
     printf_stderr("NeckoParent::AllocPWebSocketParent: "
                   "FATAL error: %s: KILLING CHILD PROCESS\n",
                   error);
     return nullptr;
   }
 
   TabParent* tabParent = static_cast<TabParent*>(browser);
@@ -348,57 +337,51 @@ bool
 NeckoParent::DeallocPTCPServerSocketParent(PTCPServerSocketParent* actor)
 {
   TCPServerSocketParent* p = static_cast<TCPServerSocketParent*>(actor);
    p->ReleaseIPDLReference();
   return true;
 }
 
 PRemoteOpenFileParent*
-NeckoParent::AllocPRemoteOpenFileParent(const URIParams& aURI)
+NeckoParent::AllocPRemoteOpenFileParent(const URIParams& aURI,
+                                        PBrowserParent* aBrowser)
 {
   nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
   nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(uri);
   if (!fileURL) {
     return nullptr;
   }
 
   // security checks
   if (UsingNeckoIPCSecurity()) {
+    if (!aBrowser) {
+      printf_stderr("NeckoParent::AllocPRemoteOpenFile: "
+                    "FATAL error: missing TabParent: KILLING CHILD PROCESS\n");
+      return nullptr;
+    }
+    nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(aBrowser);
+    uint32_t appId = tabParent->OwnOrContainingAppId();
     nsCOMPtr<nsIAppsService> appsService =
       do_GetService(APPS_SERVICE_CONTRACTID);
     if (!appsService) {
       return nullptr;
     }
-    bool haveValidBrowser = false;
+    nsCOMPtr<mozIDOMApplication> domApp;
+    nsresult rv = appsService->GetAppByLocalId(appId, getter_AddRefs(domApp));
+    if (!domApp) {
+      return nullptr;
+    }
+    nsCOMPtr<mozIApplication> mozApp = do_QueryInterface(domApp);
+    if (!mozApp) {
+      return nullptr;
+    }
     bool hasManage = false;
-    nsCOMPtr<mozIApplication> mozApp;
-    for (uint32_t i = 0; i < Manager()->ManagedPBrowserParent().Length(); i++) {
-      nsRefPtr<TabParent> tabParent =
-        static_cast<TabParent*>(Manager()->ManagedPBrowserParent()[i]);
-      uint32_t appId = tabParent->OwnOrContainingAppId();
-      nsCOMPtr<mozIDOMApplication> domApp;
-      nsresult rv = appsService->GetAppByLocalId(appId, getter_AddRefs(domApp));
-      if (!domApp) {
-        continue;
-      }
-      mozApp = do_QueryInterface(domApp);
-      if (!mozApp) {
-        continue;
-      }
-      hasManage = false;
-      rv = mozApp->HasPermission("webapps-manage", &hasManage);
-      if (NS_FAILED(rv)) {
-        continue;
-      }
-      haveValidBrowser = true;
-      break;
-    }
-
-    if (!haveValidBrowser) {
+    rv = mozApp->HasPermission("webapps-manage", &hasManage);
+    if (NS_FAILED(rv)) {
       return nullptr;
     }
 
     nsAutoCString requestedPath;
     fileURL->GetPath(requestedPath);
     NS_UnescapeURL(requestedPath);
 
     if (hasManage) {
@@ -431,17 +414,17 @@ NeckoParent::AllocPRemoteOpenFileParent(
         printf_stderr("NeckoParent::AllocPRemoteOpenFile: "
                       "FATAL error: requested file URI '%s' contains '/../' "
                       "KILLING CHILD PROCESS\n", requestedPath.get());
         return nullptr;
       }
     } else {
       // regular packaged apps can only access their own application.zip file
       nsAutoString basePath;
-      nsresult rv = mozApp->GetBasePath(basePath);
+      rv = mozApp->GetBasePath(basePath);
       if (NS_FAILED(rv)) {
         return nullptr;
       }
       nsAutoString uuid;
       rv = mozApp->GetId(uuid);
       if (NS_FAILED(rv)) {
         return nullptr;
       }
@@ -460,17 +443,18 @@ NeckoParent::AllocPRemoteOpenFileParent(
   }
 
   RemoteOpenFileParent* parent = new RemoteOpenFileParent(fileURL);
   return parent;
 }
 
 bool
 NeckoParent::RecvPRemoteOpenFileConstructor(PRemoteOpenFileParent* aActor,
-                                            const URIParams& aFileURI)
+                                            const URIParams& aFileURI,
+                                            PBrowserParent* aBrowser)
 {
   return static_cast<RemoteOpenFileParent*>(aActor)->OpenSendCloseDelete();
 }
 
 bool
 NeckoParent::DeallocPRemoteOpenFileParent(PRemoteOpenFileParent* actor)
 {
   delete actor;
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -31,34 +31,27 @@ public:
 
   MOZ_WARN_UNUSED_RESULT
   static const char *
   GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
                       PBrowserParent* aBrowser,
                       uint32_t* aAppId,
                       bool* aInBrowserElement);
 
-  MOZ_WARN_UNUSED_RESULT
-  static const char *
-  GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
-                      PContentParent* aBrowser,
-                      uint32_t* aAppId,
-                      bool* aInBrowserElement);
-
   /*
    * Creates LoadContext for parent-side of an e10s channel.
    *
-   * PContentParent corresponds to the process that is requesting the load.
+   * Values from PBrowserParent are more secure, and override those set in
+   * SerializedLoadContext.
    *
    * Returns null if successful, or an error string if failed.
    */
   MOZ_WARN_UNUSED_RESULT
   static const char*
   CreateChannelLoadContext(PBrowserParent* aBrowser,
-                           PContentParent* aContent,
                            const SerializedLoadContext& aSerialized,
                            nsCOMPtr<nsILoadContext> &aResult);
 
 protected:
   virtual PHttpChannelParent*
     AllocPHttpChannelParent(PBrowserParent*, const SerializedLoadContext&,
                             const HttpChannelCreationArgs& aOpenArgs);
   virtual bool
@@ -81,22 +74,24 @@ protected:
                       PFTPChannelParent* aActor,
                       PBrowserParent* aBrowser,
                       const SerializedLoadContext& aSerialized,
                       const FTPChannelCreationArgs& aOpenArgs);
   virtual bool DeallocPFTPChannelParent(PFTPChannelParent*);
   virtual PWebSocketParent* AllocPWebSocketParent(PBrowserParent* browser,
                                                   const SerializedLoadContext& aSerialized);
   virtual bool DeallocPWebSocketParent(PWebSocketParent*);
-  virtual PTCPSocketParent* AllocPTCPSocketParent();
+virtual PTCPSocketParent* AllocPTCPSocketParent();
 
-  virtual PRemoteOpenFileParent* AllocPRemoteOpenFileParent(const URIParams& aFileURI)
+  virtual PRemoteOpenFileParent* AllocPRemoteOpenFileParent(const URIParams& aFileURI,
+                                                            PBrowserParent* aBrowser)
                                                             MOZ_OVERRIDE;
   virtual bool RecvPRemoteOpenFileConstructor(PRemoteOpenFileParent* aActor,
-                                              const URIParams& aFileURI)
+                                              const URIParams& aFileURI,
+                                              PBrowserParent* aBrowser)
                                               MOZ_OVERRIDE;
   virtual bool DeallocPRemoteOpenFileParent(PRemoteOpenFileParent* aActor)
                                             MOZ_OVERRIDE;
 
   virtual bool DeallocPTCPSocketParent(PTCPSocketParent*);
   virtual PTCPServerSocketParent* AllocPTCPServerSocketParent(const uint16_t& aLocalPort,
                                                         const uint16_t& aBacklog,
                                                         const nsString& aBinaryType);
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -49,17 +49,17 @@ parent:
                SerializedLoadContext loadContext,
                HttpChannelCreationArgs args);
   PWyciwygChannel();
   PFTPChannel(PBrowser browser, SerializedLoadContext loadContext,
               FTPChannelCreationArgs args);
 
   PWebSocket(PBrowser browser, SerializedLoadContext loadContext);
   PTCPServerSocket(uint16_t localPort, uint16_t backlog, nsString binaryType);
-  PRemoteOpenFile(URIParams fileuri);
+  PRemoteOpenFile(URIParams fileuri, nullable PBrowser browser);
 
   HTMLDNSPrefetch(nsString hostname, uint16_t flags);
   CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason);
 
 both:
   PTCPSocket();
 };
 
--- a/netwerk/ipc/RemoteOpenFileChild.cpp
+++ b/netwerk/ipc/RemoteOpenFileChild.cpp
@@ -179,17 +179,17 @@ RemoteOpenFileChild::AsyncRemoteFileOpen
       // will be called with it.
       return NS_OK;
     }
   }
 
   URIParams uri;
   SerializeURI(mURI, uri);
 
-  gNeckoChild->SendPRemoteOpenFileConstructor(this, uri);
+  gNeckoChild->SendPRemoteOpenFileConstructor(this, uri, mTabChild);
 
   // The chrome process now has a logical ref to us until it calls Send__delete.
   AddIPDLReference();
 
   mListener = aListener;
   mAsyncOpenCalled = true;
   return NS_OK;
 #endif
--- a/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp
+++ b/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp
@@ -102,19 +102,17 @@ WyciwygChannelParent::RecvAppData(const 
 
 bool
 WyciwygChannelParent::SetupAppData(const IPC::SerializedLoadContext& loadContext,
                                    PBrowserParent* aParent)
 {
   if (!mChannel)
     return true;
 
-  const char* error = NeckoParent::CreateChannelLoadContext(aParent,
-                                                            Manager()->Manager(),
-                                                            loadContext,
+  const char* error = NeckoParent::CreateChannelLoadContext(aParent, loadContext,
                                                             mLoadContext);
   if (error) {
     printf_stderr(nsPrintfCString("WyciwygChannelParent::SetupAppData: FATAL ERROR: %s\n",
                                   error).get());
     return false;
   }
 
   if (!mLoadContext && loadContext.IsPrivateBitValid()) {