Bug 890570 - Part 006. Fix http auth prompts for nested content processes r=honzab
☠☠ backed out by 1208d93b9428 ☠ ☠
author"Kan-Ru Chen (陳侃如)" <kanru@kanru.info>
Mon, 09 Jun 2014 16:49:12 +0800
changeset 187533 820e34a746471f160e41f393c00f7bc4e1333c0a
parent 187532 a7872dbfa5ce0a91b06c353b1080dc6950c97ef8
child 187534 00c2ba04f8d439ba9bb8624c10f058e287a57948
push id26923
push useremorley@mozilla.com
push dateMon, 09 Jun 2014 14:21:33 +0000
treeherdermozilla-central@43a2f570cea2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershonzab
bugs890570
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 890570 - Part 006. Fix http auth prompts for nested content processes r=honzab Based on original patch by David Zbarsky <dzbarsky@gmail.com>
docshell/base/LoadContext.cpp
docshell/base/LoadContext.h
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsILoadContext.idl
dom/browser-element/BrowserElementPromptService.jsm
dom/ipc/PBrowser.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
netwerk/ipc/NeckoChild.cpp
netwerk/ipc/NeckoChild.h
netwerk/ipc/NeckoParent.cpp
netwerk/ipc/NeckoParent.h
netwerk/ipc/PNecko.ipdl
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/HttpChannelParent.h
uriloader/prefetch/OfflineCacheUpdateParent.cpp
--- a/docshell/base/LoadContext.cpp
+++ b/docshell/base/LoadContext.cpp
@@ -36,16 +36,24 @@ NS_IMETHODIMP
 LoadContext::GetTopFrameElement(nsIDOMElement** aElement)
 {
   nsCOMPtr<nsIDOMElement> element = do_QueryReferent(mTopFrameElement);
   element.forget(aElement);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+LoadContext::GetNestedFrameId(uint64_t* aId)
+{
+  NS_ENSURE_ARG(aId);
+  *aId = mNestedFrameId;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 LoadContext::IsAppOfType(uint32_t, bool*)
 {
   MOZ_ASSERT(mIsNotNull);
 
   // don't expect we need this in parent (Thunderbird/SeaMonkey specific?)
   return NS_ERROR_UNEXPECTED;
 }
 
--- a/docshell/base/LoadContext.h
+++ b/docshell/base/LoadContext.h
@@ -40,16 +40,34 @@ public:
   NS_DECL_NSIINTERFACEREQUESTOR
 
   // AppId/inBrowser arguments override those in SerializedLoadContext provided
   // by child process.
   LoadContext(const IPC::SerializedLoadContext& aToCopy,
               dom::Element* aTopFrameElement,
               uint32_t aAppId, bool aInBrowser)
     : mTopFrameElement(do_GetWeakReference(aTopFrameElement))
+    , mNestedFrameId(0)
+    , mAppId(aAppId)
+    , mIsContent(aToCopy.mIsContent)
+    , mUsePrivateBrowsing(aToCopy.mUsePrivateBrowsing)
+    , mUseRemoteTabs(aToCopy.mUseRemoteTabs)
+    , mIsInBrowserElement(aInBrowser)
+#ifdef DEBUG
+    , mIsNotNull(aToCopy.mIsNotNull)
+#endif
+  {}
+
+  // AppId/inBrowser arguments override those in SerializedLoadContext provided
+  // by child process.
+  LoadContext(const IPC::SerializedLoadContext& aToCopy,
+              uint64_t aNestedFrameId,
+              uint32_t aAppId, bool aInBrowser)
+    : mTopFrameElement(nullptr)
+    , mNestedFrameId(aNestedFrameId)
     , mAppId(aAppId)
     , mIsContent(aToCopy.mIsContent)
     , mUsePrivateBrowsing(aToCopy.mUsePrivateBrowsing)
     , mUseRemoteTabs(aToCopy.mUseRemoteTabs)
     , mIsInBrowserElement(aInBrowser)
 #ifdef DEBUG
     , mIsNotNull(aToCopy.mIsNotNull)
 #endif
@@ -57,41 +75,44 @@ public:
 
   LoadContext(dom::Element* aTopFrameElement,
               uint32_t aAppId,
               bool aIsContent,
               bool aUsePrivateBrowsing,
               bool aUseRemoteTabs,
               bool aIsInBrowserElement)
     : mTopFrameElement(do_GetWeakReference(aTopFrameElement))
+    , mNestedFrameId(0)
     , mAppId(aAppId)
     , mIsContent(aIsContent)
     , mUsePrivateBrowsing(aUsePrivateBrowsing)
     , mUseRemoteTabs(aUseRemoteTabs)
     , mIsInBrowserElement(aIsInBrowserElement)
 #ifdef DEBUG
     , mIsNotNull(true)
 #endif
   {}
 
   // Constructor taking reserved appId for the safebrowsing cookie.
   LoadContext(uint32_t aAppId)
     : mTopFrameElement(nullptr)
+    , mNestedFrameId(0)
     , mAppId(aAppId)
     , mIsContent(false)
     , mUsePrivateBrowsing(false)
     , mUseRemoteTabs(false)
     , mIsInBrowserElement(false)
 #ifdef DEBUG
     , mIsNotNull(true)
 #endif
   {}
 
 private:
   nsWeakPtr     mTopFrameElement;
+  uint64_t      mNestedFrameId;
   uint32_t      mAppId;
   bool          mIsContent;
   bool          mUsePrivateBrowsing;
   bool          mUseRemoteTabs;
   bool          mIsInBrowserElement;
 #ifdef DEBUG
   bool          mIsNotNull;
 #endif
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -12256,16 +12256,23 @@ nsDocShell::GetTopFrameElement(nsIDOMEle
     NS_ENSURE_TRUE(top, NS_ERROR_FAILURE);
 
     // GetFrameElement, /not/ GetScriptableFrameElement -- if |top| is inside
     // <iframe mozbrowser>, we want to return the iframe, not null.
     return top->GetFrameElement(aElement);
 }
 
 NS_IMETHODIMP
+nsDocShell::GetNestedFrameId(uint64_t* aId)
+{
+    *aId = 0;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDocShell::IsAppOfType(uint32_t aAppType, bool *aIsOfType)
 {
     nsCOMPtr<nsIDocShell> shell = this;
     while (shell) {
         uint32_t type;
         shell->GetAppType(&type);
         if (type == aAppType) {
             *aIsOfType = true;
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -205,16 +205,17 @@ public:
     nsDocShellInfoLoadType ConvertLoadTypeToDocShellLoadInfo(uint32_t aLoadType);
     uint32_t ConvertDocShellLoadInfoToLoadType(nsDocShellInfoLoadType aDocShellLoadType);
 
     // Don't use NS_DECL_NSILOADCONTEXT because some of nsILoadContext's methods
     // are shared with nsIDocShell (appID, etc.) and can't be declared twice.
     NS_IMETHOD GetAssociatedWindow(nsIDOMWindow**);
     NS_IMETHOD GetTopWindow(nsIDOMWindow**);
     NS_IMETHOD GetTopFrameElement(nsIDOMElement**);
+    NS_IMETHOD GetNestedFrameId(uint64_t*);
     NS_IMETHOD IsAppOfType(uint32_t, bool*);
     NS_IMETHOD GetIsContent(bool*);
     NS_IMETHOD GetUsePrivateBrowsing(bool*);
     NS_IMETHOD SetUsePrivateBrowsing(bool);
     NS_IMETHOD SetPrivateBrowsing(bool);
     NS_IMETHOD GetUseRemoteTabs(bool*);
     NS_IMETHOD SetRemoteTabs(bool);
 
--- a/docshell/base/nsILoadContext.idl
+++ b/docshell/base/nsILoadContext.idl
@@ -9,17 +9,17 @@
 interface nsIDOMWindow;
 interface nsIDOMElement;
 
 /**
  * An nsILoadContext represents the context of a load.  This interface
  * can be queried for various information about where the load is
  * happening.
  */
-[scriptable, uuid(852ed1f0-8ec0-11e3-baa8-0800200c9a66)]
+[scriptable, uuid(6ec837fa-af93-4350-bbb8-0985d54c74ca)]
 interface nsILoadContext : nsISupports
 {
   /**
    * associatedWindow is the window with which the load is associated, if any.
    * Note that the load may be triggered by a document which is different from
    * the document in associatedWindow, and in fact the source of the load need
    * not be same-origin with the document in associatedWindow.  This attribute
    * may be null if there is no associated window.
@@ -39,16 +39,24 @@ interface nsILoadContext : nsISupports
    * topWindow with which the load is associated.
    *
    * Note that we may have a topFrameElement even when we don't have an
    * associatedWindow, if the topFrameElement's content lives out of process.
    */
   readonly attribute nsIDOMElement topFrameElement;
 
   /**
+   * If this LoadContext corresponds to a nested remote iframe, we don't have
+   * access to the topFrameElement.  Instead, we must use this id to send
+   * messages. A return value of 0 signifies that this load context is not for
+   * a nested frame.
+   */
+  readonly attribute unsigned long long nestedFrameId;
+
+  /**
    * Check whether the load is happening in a particular type of application.
    *
    * @param an application type.  For now, the constants to be passed here are
    *        the nsIDocShell APP_TYPE_* constants.
    *
    * @return whether there is some ancestor of the associatedWindow that is of
    *         the given app type.
    */
--- a/dom/browser-element/BrowserElementPromptService.jsm
+++ b/dom/browser-element/BrowserElementPromptService.jsm
@@ -437,19 +437,22 @@ AuthPromptWrapper.prototype = {
       return this._browserElementImpl.asyncPromptAuth(channel, callback, context, level, authInfo);
     } else {
       return this._oldImpl.asyncPromptAuth(channel, callback, context, level, authInfo);
     }
   },
 
   _canGetParentElement: function(channel) {
     try {
-      let frame = channel.notificationCallbacks.getInterface(Ci.nsILoadContext).topFrameElement;
-      if (!frame)
-        return false;
+      let context = channel.notificationCallbacks.getInterface(Ci.nsILoadContext);
+      let frame = context.topFrameElement;
+      if (!frame) {
+        // This function returns a boolean value
+        return !!context.nestedFrameId;
+      }
 
       if (!BrowserElementPromptService.getBrowserElementParentForFrame(frame))
         return false;
 
       return true;
     } catch (e) {
       return false;
     }
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -352,16 +352,25 @@ parent:
     /**
      * Updates the zoom constraints for a scrollable frame in this tab.
      * The zoom controller code lives on the parent side and so this allows it to
      * have up-to-date zoom constraints.
      */
     UpdateZoomConstraints(uint32_t aPresShellId, ViewID aViewId, bool aIsRoot,
                           ZoomConstraints aConstraints);
 
+    /**
+     * Brings up the auth prompt dialog.
+     * Called when this is the PBrowserParent for a nested remote iframe.
+     * aCallbackId corresponds to an nsIAuthPromptCallback that lives in the
+     * root process.  It will be passed back to the root process with either the
+     * OnAuthAvailable or OnAuthCancelled message.
+     */
+    AsyncAuthPrompt(nsCString uri, nsString realm, uint64_t aCallbackId);
+
     __delete__();
 
     ReplyKeyEvent(WidgetKeyboardEvent event);
 
     sync RequestNativeKeyBindings(WidgetKeyboardEvent event)
         returns (MaybeNativeKeyBinding bindings);
 
 child:
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -612,16 +612,25 @@ private:
 
         mInfo->FireCallback();
         return NS_OK;
     }
 };
 
 StaticRefPtr<TabChild> sPreallocatedTab;
 
+/*static*/
+std::map<uint64_t, nsRefPtr<TabChild> >&
+TabChild::NestedTabChildMap()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  static std::map<uint64_t, nsRefPtr<TabChild> > sNestedTabChildMap;
+  return sNestedTabChildMap;
+}
+
 /*static*/ void
 TabChild::PreloadSlowThings()
 {
     MOZ_ASSERT(!sPreallocatedTab);
 
     nsRefPtr<TabChild> tab(new TabChild(ContentChild::GetSingleton(),
                                         TabContext(), /* chromeFlags */ 0));
     if (!NS_SUCCEEDED(tab->Init()) ||
@@ -691,16 +700,17 @@ TabChild::TabChild(nsIContentChild* aMan
   , mOrientation(eScreenOrientation_PortraitPrimary)
   , mUpdateHitRegion(false)
   , mContextMenuHandled(false)
   , mLongTapEventHandled(false)
   , mWaitingTouchListeners(false)
   , mIgnoreKeyPressEvent(false)
   , mActiveElementManager(new ActiveElementManager())
   , mHasValidInnerSize(false)
+  , mUniqueId(0)
 {
   if (!sActiveDurationMsSet) {
     Preferences::AddIntVarCache(&sActiveDurationMs,
                                 "ui.touch_activation.duration_ms",
                                 sActiveDurationMs);
     sActiveDurationMsSet = true;
   }
 }
@@ -1367,16 +1377,19 @@ TabChild::ActorDestroy(ActorDestroyReaso
 {
   if (mTabChildGlobal) {
     // The messageManager relays messages via the TabChild which
     // no longer exists.
     static_cast<nsFrameMessageManager*>
       (mTabChildGlobal->mMessageManager.get())->Disconnect();
     mTabChildGlobal->mMessageManager = nullptr;
   }
+  if (Id() != 0) {
+    NestedTabChildMap().erase(Id());
+  }
 }
 
 TabChild::~TabChild()
 {
     DestroyWindow();
 
     nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(WebNavigation());
     if (webBrowser) {
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -236,31 +236,52 @@ class TabChild : public TabChildBase,
                  public nsITooltipListener
 {
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
     typedef mozilla::layout::RenderFrameChild RenderFrameChild;
     typedef mozilla::layout::ScrollingBehavior ScrollingBehavior;
     typedef mozilla::layers::ActiveElementManager ActiveElementManager;
 
 public:
+    static std::map<uint64_t, nsRefPtr<TabChild> >& NestedTabChildMap();
+
+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(nsIContentChild* aManager, const TabContext& aContext, uint32_t aChromeFlags);
 
     virtual ~TabChild();
 
     bool IsRootContentDocument();
 
+    const uint64_t Id() const {
+        return mUniqueId;
+    }
+
+    static uint64_t
+    GetTabChildId(TabChild* aTabChild)
+    {
+        MOZ_ASSERT(NS_IsMainThread());
+        if (aTabChild->Id() != 0) {
+            return aTabChild->Id();
+        }
+        static uint64_t sId = 0;
+        sId++;
+        aTabChild->mUniqueId = sId;
+        NestedTabChildMap()[sId] = aTabChild;
+        return sId;
+    }
+
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIWEBBROWSERCHROME
     NS_DECL_NSIWEBBROWSERCHROME2
     NS_DECL_NSIEMBEDDINGSITEWINDOW
     NS_DECL_NSIWEBBROWSERCHROMEFOCUS
     NS_DECL_NSIINTERFACEREQUESTOR
     NS_DECL_NSIWINDOWPROVIDER
     NS_DECL_NSIDOMEVENTLISTENER
@@ -563,16 +584,17 @@ private:
     bool mContextMenuHandled;
     bool mLongTapEventHandled;
     bool mWaitingTouchListeners;
     void FireSingleTapEvent(LayoutDevicePoint aPoint);
 
     bool mIgnoreKeyPressEvent;
     nsRefPtr<ActiveElementManager> mActiveElementManager;
     bool mHasValidInnerSize;
+    uint64_t mUniqueId;
 
     DISALLOW_EVIL_CONSTRUCTORS(TabChild);
 };
 
 }
 }
 
 #endif // mozilla_dom_TabChild_h
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -17,16 +17,17 @@
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/PContentPermissionRequestParent.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/Hal.h"
 #include "mozilla/ipc/DocumentRendererParent.h"
 #include "mozilla/layers/CompositorParent.h"
 #include "mozilla/layout/RenderFrameParent.h"
 #include "mozilla/MouseEvents.h"
+#include "mozilla/net/NeckoChild.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
 #include "mozilla/unused.h"
 #include "nsCOMPtr.h"
 #include "nsContentPermissionHelper.h"
 #include "nsContentUtils.h"
 #include "nsDebug.h"
@@ -56,16 +57,20 @@
 #include "PermissionMessageUtils.h"
 #include "StructuredCloneUtils.h"
 #include "ColorPickerParent.h"
 #include "JavaScriptParent.h"
 #include "FilePickerParent.h"
 #include "TabChild.h"
 #include "LoadContext.h"
 #include "nsNetCID.h"
+#include "nsIAuthInformation.h"
+#include "nsIAuthPromptCallback.h"
+#include "nsAuthInformationHolder.h"
+#include "nsICancelable.h"
 #include "gfxPrefs.h"
 #include <algorithm>
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 using namespace mozilla::services;
@@ -2071,10 +2076,150 @@ TabParent::GetUseAsyncPanZoom(bool* useA
 
 NS_IMETHODIMP
 TabParent::SetIsDocShellActive(bool isActive)
 {
   unused << SendSetIsDocShellActive(isActive);
   return NS_OK;
 }
 
+class FakeChannel MOZ_FINAL : public nsIChannel,
+                              public nsIAuthPromptCallback,
+                              public nsIInterfaceRequestor,
+                              public nsILoadContext
+{
+public:
+  FakeChannel(const nsCString& aUri, uint64_t aCallbackId, Element* aElement)
+    : mCallbackId(aCallbackId)
+    , mElement(aElement)
+  {
+    NS_NewURI(getter_AddRefs(mUri), aUri);
+  }
+
+  NS_DECL_ISUPPORTS
+#define NO_IMPL { return NS_ERROR_NOT_IMPLEMENTED; }
+  NS_IMETHOD GetName(nsACString&) NO_IMPL
+  NS_IMETHOD IsPending(bool*) NO_IMPL
+  NS_IMETHOD GetStatus(nsresult*) NO_IMPL
+  NS_IMETHOD Cancel(nsresult) NO_IMPL
+  NS_IMETHOD Suspend() NO_IMPL
+  NS_IMETHOD Resume() NO_IMPL
+  NS_IMETHOD GetLoadGroup(nsILoadGroup**) NO_IMPL
+  NS_IMETHOD SetLoadGroup(nsILoadGroup*) NO_IMPL
+  NS_IMETHOD SetLoadFlags(nsLoadFlags) NO_IMPL
+  NS_IMETHOD GetLoadFlags(nsLoadFlags*) NO_IMPL
+  NS_IMETHOD GetOriginalURI(nsIURI**) NO_IMPL
+  NS_IMETHOD SetOriginalURI(nsIURI*) NO_IMPL
+  NS_IMETHOD GetURI(nsIURI** aUri)
+  {
+    NS_IF_ADDREF(mUri);
+    *aUri = mUri;
+    return NS_OK;
+  }
+  NS_IMETHOD GetOwner(nsISupports**) NO_IMPL
+  NS_IMETHOD SetOwner(nsISupports*) NO_IMPL
+  NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor** aRequestor)
+  {
+    NS_ADDREF(*aRequestor = this);
+    return NS_OK;
+  }
+  NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor*) NO_IMPL
+  NS_IMETHOD GetSecurityInfo(nsISupports**) NO_IMPL
+  NS_IMETHOD GetContentType(nsACString&) NO_IMPL
+  NS_IMETHOD SetContentType(const nsACString&) NO_IMPL
+  NS_IMETHOD GetContentCharset(nsACString&) NO_IMPL
+  NS_IMETHOD SetContentCharset(const nsACString&) NO_IMPL
+  NS_IMETHOD GetContentLength(int64_t*) NO_IMPL
+  NS_IMETHOD SetContentLength(int64_t) NO_IMPL
+  NS_IMETHOD Open(nsIInputStream**) NO_IMPL
+  NS_IMETHOD AsyncOpen(nsIStreamListener*, nsISupports*) NO_IMPL
+  NS_IMETHOD GetContentDisposition(uint32_t*) NO_IMPL
+  NS_IMETHOD SetContentDisposition(uint32_t) NO_IMPL
+  NS_IMETHOD GetContentDispositionFilename(nsAString&) NO_IMPL
+  NS_IMETHOD SetContentDispositionFilename(const nsAString&) NO_IMPL
+  NS_IMETHOD GetContentDispositionHeader(nsACString&) NO_IMPL
+  NS_IMETHOD OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo);
+  NS_IMETHOD OnAuthCancelled(nsISupports *aContext, bool userCancel);
+  NS_IMETHOD GetInterface(const nsIID & uuid, void **result)
+  {
+    return QueryInterface(uuid, result);
+  }
+  NS_IMETHOD GetAssociatedWindow(nsIDOMWindow**) NO_IMPL
+  NS_IMETHOD GetTopWindow(nsIDOMWindow**) NO_IMPL
+  NS_IMETHOD GetTopFrameElement(nsIDOMElement** aElement)
+  {
+    nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mElement);
+    elem.forget(aElement);
+    return NS_OK;
+  }
+  NS_IMETHOD GetNestedFrameId(uint64_t*) NO_IMPL
+  NS_IMETHOD IsAppOfType(uint32_t, bool*) NO_IMPL
+  NS_IMETHOD GetIsContent(bool*) NO_IMPL
+  NS_IMETHOD GetUsePrivateBrowsing(bool*) NO_IMPL
+  NS_IMETHOD SetUsePrivateBrowsing(bool) NO_IMPL
+  NS_IMETHOD SetPrivateBrowsing(bool) NO_IMPL
+  NS_IMETHOD GetIsInBrowserElement(bool*) NO_IMPL
+  NS_IMETHOD GetAppId(uint32_t*) NO_IMPL
+  NS_IMETHOD GetUseRemoteTabs(bool*) NO_IMPL
+  NS_IMETHOD SetRemoteTabs(bool) NO_IMPL
+#undef NO_IMPL
+
+protected:
+  nsCOMPtr<nsIURI> mUri;
+  uint64_t mCallbackId;
+  nsCOMPtr<Element> mElement;
+};
+
+NS_IMPL_ISUPPORTS(FakeChannel, nsIChannel, nsIAuthPromptCallback,
+                  nsIRequest, nsIInterfaceRequestor, nsILoadContext);
+
+bool
+TabParent::RecvAsyncAuthPrompt(const nsCString& aUri,
+                               const nsString& aRealm,
+                               const uint64_t& aCallbackId)
+{
+  nsCOMPtr<nsIAuthPrompt2> authPrompt;
+  GetAuthPrompt(nsIAuthPromptProvider::PROMPT_NORMAL,
+                NS_GET_IID(nsIAuthPrompt2),
+                getter_AddRefs(authPrompt));
+  nsRefPtr<FakeChannel> channel = new FakeChannel(aUri, aCallbackId, mFrameElement);
+  uint32_t promptFlags = nsIAuthInformation::AUTH_HOST;
+
+  nsRefPtr<nsAuthInformationHolder> holder =
+    new nsAuthInformationHolder(promptFlags, aRealm,
+                                EmptyCString());
+
+  uint32_t level = nsIAuthPrompt2::LEVEL_NONE;
+  nsCOMPtr<nsICancelable> dummy;
+  nsresult rv =
+    authPrompt->AsyncPromptAuth(channel, channel, nullptr,
+                                level, holder, getter_AddRefs(dummy));
+
+  return rv == NS_OK;
+}
+
+NS_IMETHODIMP
+FakeChannel::OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo)
+{
+  nsAuthInformationHolder* holder =
+    static_cast<nsAuthInformationHolder*>(aAuthInfo);
+
+  if (!net::gNeckoChild->SendOnAuthAvailable(mCallbackId,
+                                             holder->User(),
+                                             holder->Password(),
+                                             holder->Domain())) {
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+FakeChannel::OnAuthCancelled(nsISupports *aContext, bool userCancel)
+{
+  if (!net::gNeckoChild->SendOnAuthCancelled(mCallbackId, userCancel)) {
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
+
 } // namespace tabs
 } // namespace mozilla
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -302,16 +302,20 @@ public:
 protected:
     bool ReceiveMessage(const nsString& aMessage,
                         bool aSync,
                         const StructuredCloneData* aCloneData,
                         CpowHolder* aCpows,
                         nsIPrincipal* aPrincipal,
                         InfallibleTArray<nsString>* aJSONRetVal = nullptr);
 
+    virtual bool RecvAsyncAuthPrompt(const nsCString& aUri,
+                                     const nsString& aRealm,
+                                     const uint64_t& aCallbackId) MOZ_OVERRIDE;
+
     virtual bool Recv__delete__() MOZ_OVERRIDE;
 
     virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
     virtual PIndexedDBParent* AllocPIndexedDBParent(
                                                   const nsCString& aGroup,
                                                   const nsCString& aASCIIOrigin,
                                                   bool* /* aAllowed */) MOZ_OVERRIDE;
--- a/netwerk/ipc/NeckoChild.cpp
+++ b/netwerk/ipc/NeckoChild.cpp
@@ -4,16 +4,17 @@
 /* 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 "necko-config.h"
 #include "nsHttp.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/TabChild.h"
 #include "mozilla/net/HttpChannelChild.h"
 #include "mozilla/net/CookieServiceChild.h"
 #include "mozilla/net/WyciwygChannelChild.h"
 #include "mozilla/net/FTPChannelChild.h"
 #include "mozilla/net/WebSocketChannelChild.h"
 #include "mozilla/net/DNSRequestChild.h"
 #include "mozilla/net/RemoteOpenFileChild.h"
 #include "mozilla/net/ChannelDiverterChild.h"
@@ -68,17 +69,17 @@ void NeckoChild::DestroyNeckoChild()
   if (!alreadyDestroyed) {
     Send__delete__(gNeckoChild); 
     gNeckoChild = nullptr;
     alreadyDestroyed = true;
   }
 }
 
 PHttpChannelChild*
-NeckoChild::AllocPHttpChannelChild(PBrowserChild* browser,
+NeckoChild::AllocPHttpChannelChild(const PBrowserOrId& browser,
                                    const SerializedLoadContext& loadContext,
                                    const HttpChannelCreationArgs& aOpenArgs)
 {
   // We don't allocate here: instead we always use IPDL constructor that takes
   // an existing HttpChildChannel
   NS_NOTREACHED("AllocPHttpChannelChild should not be called on child");
   return nullptr;
 }
@@ -89,17 +90,17 @@ NeckoChild::DeallocPHttpChannelChild(PHt
   NS_ABORT_IF_FALSE(IsNeckoChild(), "DeallocPHttpChannelChild called by non-child!");
 
   HttpChannelChild* child = static_cast<HttpChannelChild*>(channel);
   child->ReleaseIPDLReference();
   return true;
 }
 
 PFTPChannelChild*
-NeckoChild::AllocPFTPChannelChild(PBrowserChild* aBrowser,
+NeckoChild::AllocPFTPChannelChild(const PBrowserOrId& aBrowser,
                                   const SerializedLoadContext& aSerialized,
                                   const FTPChannelCreationArgs& aOpenArgs)
 {
   // We don't allocate here: see FTPChannelChild::AsyncOpen()
   NS_RUNTIMEABORT("AllocPFTPChannelChild should not be called");
   return nullptr;
 }
 
@@ -145,17 +146,17 @@ NeckoChild::DeallocPWyciwygChannelChild(
   NS_ABORT_IF_FALSE(IsNeckoChild(), "DeallocPWyciwygChannelChild called by non-child!");
 
   WyciwygChannelChild *p = static_cast<WyciwygChannelChild*>(channel);
   p->ReleaseIPDLReference();
   return true;
 }
 
 PWebSocketChild*
-NeckoChild::AllocPWebSocketChild(PBrowserChild* browser,
+NeckoChild::AllocPWebSocketChild(const PBrowserOrId& browser,
                                  const SerializedLoadContext& aSerialized)
 {
   NS_NOTREACHED("AllocPWebSocketChild should not be called");
   return nullptr;
 }
 
 bool
 NeckoChild::DeallocPWebSocketChild(PWebSocketChild* child)
@@ -295,10 +296,26 @@ NeckoChild::AllocPChannelDiverterChild(c
 
 bool
 NeckoChild::DeallocPChannelDiverterChild(PChannelDiverterChild* child)
 {
   delete static_cast<ChannelDiverterChild*>(child);
   return true;
 }
 
+bool
+NeckoChild::RecvAsyncAuthPromptForNestedFrame(const uint64_t& aNestedFrameId,
+                                              const nsCString& aUri,
+                                              const nsString& aRealm,
+                                              const uint64_t& aCallbackId)
+{
+  auto iter = dom::TabChild::NestedTabChildMap().find(aNestedFrameId);
+  if (iter == dom::TabChild::NestedTabChildMap().end()) {
+    MOZ_CRASH();
+    return false;
+  }
+  dom::TabChild* tabChild = iter->second;
+  tabChild->SendAsyncAuthPrompt(aUri, aRealm, aCallbackId);
+  return true;
+}
+
 }} // mozilla::net
 
--- a/netwerk/ipc/NeckoChild.h
+++ b/netwerk/ipc/NeckoChild.h
@@ -22,30 +22,31 @@ public:
   NeckoChild();
   virtual ~NeckoChild();
 
   static void InitNeckoChild();
   static void DestroyNeckoChild();
 
 protected:
   virtual PHttpChannelChild*
-    AllocPHttpChannelChild(PBrowserChild*, const SerializedLoadContext&,
+    AllocPHttpChannelChild(const PBrowserOrId&, const SerializedLoadContext&,
                            const HttpChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
   virtual bool DeallocPHttpChannelChild(PHttpChannelChild*) MOZ_OVERRIDE;
   virtual PCookieServiceChild* AllocPCookieServiceChild() MOZ_OVERRIDE;
   virtual bool DeallocPCookieServiceChild(PCookieServiceChild*) MOZ_OVERRIDE;
   virtual PWyciwygChannelChild* AllocPWyciwygChannelChild() MOZ_OVERRIDE;
   virtual bool DeallocPWyciwygChannelChild(PWyciwygChannelChild*) MOZ_OVERRIDE;
   virtual PFTPChannelChild*
-    AllocPFTPChannelChild(PBrowserChild* aBrowser,
+    AllocPFTPChannelChild(const PBrowserOrId& aBrowser,
                           const SerializedLoadContext& aSerialized,
                           const FTPChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
   virtual bool DeallocPFTPChannelChild(PFTPChannelChild*) MOZ_OVERRIDE;
   virtual PWebSocketChild*
-    AllocPWebSocketChild(PBrowserChild*, const SerializedLoadContext&) MOZ_OVERRIDE;
+    AllocPWebSocketChild(const PBrowserOrId&,
+                         const SerializedLoadContext&) MOZ_OVERRIDE;
   virtual bool DeallocPWebSocketChild(PWebSocketChild*) MOZ_OVERRIDE;
   virtual PTCPSocketChild* AllocPTCPSocketChild() MOZ_OVERRIDE;
   virtual bool DeallocPTCPSocketChild(PTCPSocketChild*) MOZ_OVERRIDE;
   virtual PTCPServerSocketChild*
     AllocPTCPServerSocketChild(const uint16_t& aLocalPort,
                                const uint16_t& aBacklog,
                                const nsString& aBinaryType) MOZ_OVERRIDE;
   virtual bool DeallocPTCPServerSocketChild(PTCPServerSocketChild*) MOZ_OVERRIDE;
@@ -66,16 +67,20 @@ protected:
   virtual PRtspChannelChild*
     AllocPRtspChannelChild(const RtspChannelConnectArgs& aArgs)
                            MOZ_OVERRIDE;
   virtual bool DeallocPRtspChannelChild(PRtspChannelChild*) MOZ_OVERRIDE;
   virtual PChannelDiverterChild*
   AllocPChannelDiverterChild(const ChannelDiverterArgs& channel) MOZ_OVERRIDE;
   virtual bool
   DeallocPChannelDiverterChild(PChannelDiverterChild* actor) MOZ_OVERRIDE;
+  virtual bool RecvAsyncAuthPromptForNestedFrame(const uint64_t& aNestedFrameId,
+                                                 const nsCString& aUri,
+                                                 const nsString& aRealm,
+                                                 const uint64_t& aCallbackId) MOZ_OVERRIDE;
 };
 
 /**
  * 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
@@ -30,16 +30,18 @@
 #include "mozilla/AppProcessChecker.h"
 #include "nsPrintfCString.h"
 #include "nsHTMLDNSPrefetch.h"
 #include "nsIAppsService.h"
 #include "nsIUDPSocketFilter.h"
 #include "nsEscape.h"
 #include "RemoteOpenFileParent.h"
 #include "SerializedLoadContext.h"
+#include "nsAuthInformationHolder.h"
+#include "nsIAuthPromptCallback.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 mozilla::net::PUDPSocketParent;
@@ -146,51 +148,66 @@ NeckoParent::GetValidatedAppInfo(const S
     }
     return nullptr;
   }
 
   return "ContentParent does not have any PBrowsers";
 }
 
 const char *
-NeckoParent::CreateChannelLoadContext(PBrowserParent* aBrowser,
+NeckoParent::CreateChannelLoadContext(const PBrowserOrId& 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);
   if (error) {
     return error;
   }
 
-  if (aBrowser) {
-    nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(aBrowser);
-    topFrameElement = tabParent->GetOwnerElement();
-  }
-
   // if !UsingNeckoIPCSecurity(), we may not have a LoadContext to set. This is
   // the common case for most xpcshell tests.
   if (aSerialized.IsNotNull()) {
-    aResult = new LoadContext(aSerialized, topFrameElement, appId, inBrowser);
+    switch (aBrowser.type()) {
+      case PBrowserOrId::TPBrowserParent:
+      {
+        nsRefPtr<TabParent> tabParent =
+          static_cast<TabParent*>(aBrowser.get_PBrowserParent());
+        dom::Element* topFrameElement = nullptr;
+        if (tabParent) {
+          topFrameElement = tabParent->GetOwnerElement();
+        }
+        aResult = new LoadContext(aSerialized, topFrameElement,
+                                  appId, inBrowser);
+        break;
+      }
+      case PBrowserOrId::Tuint64_t:
+      {
+        aResult = new LoadContext(aSerialized, aBrowser.get_uint64_t(),
+                                  appId, inBrowser);
+        break;
+      }
+      default:
+        MOZ_CRASH();
+    }
   }
 
   return nullptr;
 }
 
 void
 NeckoParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   // Implement me! Bug 1005184
 }
 
 PHttpChannelParent*
-NeckoParent::AllocPHttpChannelParent(PBrowserParent* aBrowser,
+NeckoParent::AllocPHttpChannelParent(const PBrowserOrId& aBrowser,
                                      const SerializedLoadContext& aSerialized,
                                      const HttpChannelCreationArgs& aOpenArgs)
 {
   nsCOMPtr<nsILoadContext> loadContext;
   const char *error = CreateChannelLoadContext(aBrowser, Manager(),
                                                aSerialized, loadContext);
   if (error) {
     printf_stderr("NeckoParent::AllocPHttpChannelParent: "
@@ -210,26 +227,26 @@ NeckoParent::DeallocPHttpChannelParent(P
   HttpChannelParent *p = static_cast<HttpChannelParent *>(channel);
   p->Release();
   return true;
 }
 
 bool
 NeckoParent::RecvPHttpChannelConstructor(
                       PHttpChannelParent* aActor,
-                      PBrowserParent* aBrowser,
+                      const PBrowserOrId& aBrowser,
                       const SerializedLoadContext& aSerialized,
                       const HttpChannelCreationArgs& aOpenArgs)
 {
   HttpChannelParent* p = static_cast<HttpChannelParent*>(aActor);
   return p->Init(aOpenArgs);
 }
 
 PFTPChannelParent*
-NeckoParent::AllocPFTPChannelParent(PBrowserParent* aBrowser,
+NeckoParent::AllocPFTPChannelParent(const PBrowserOrId& aBrowser,
                                     const SerializedLoadContext& aSerialized,
                                     const FTPChannelCreationArgs& aOpenArgs)
 {
   nsCOMPtr<nsILoadContext> loadContext;
   const char *error = CreateChannelLoadContext(aBrowser, Manager(),
                                                aSerialized, loadContext);
   if (error) {
     printf_stderr("NeckoParent::AllocPFTPChannelParent: "
@@ -249,17 +266,17 @@ NeckoParent::DeallocPFTPChannelParent(PF
   FTPChannelParent *p = static_cast<FTPChannelParent *>(channel);
   p->Release();
   return true;
 }
 
 bool
 NeckoParent::RecvPFTPChannelConstructor(
                       PFTPChannelParent* aActor,
-                      PBrowserParent* aBrowser,
+                      const PBrowserOrId& aBrowser,
                       const SerializedLoadContext& aSerialized,
                       const FTPChannelCreationArgs& aOpenArgs)
 {
   FTPChannelParent* p = static_cast<FTPChannelParent*>(aActor);
   return p->Init(aOpenArgs);
 }
 
 PCookieServiceParent*
@@ -287,30 +304,30 @@ bool
 NeckoParent::DeallocPWyciwygChannelParent(PWyciwygChannelParent* channel)
 {
   WyciwygChannelParent *p = static_cast<WyciwygChannelParent *>(channel);
   p->Release();
   return true;
 }
 
 PWebSocketParent*
-NeckoParent::AllocPWebSocketParent(PBrowserParent* browser,
+NeckoParent::AllocPWebSocketParent(const PBrowserOrId& browser,
                                    const SerializedLoadContext& serialized)
 {
   nsCOMPtr<nsILoadContext> loadContext;
   const char *error = CreateChannelLoadContext(browser, Manager(),
                                                serialized, loadContext);
   if (error) {
     printf_stderr("NeckoParent::AllocPWebSocketParent: "
                   "FATAL error: %s: KILLING CHILD PROCESS\n",
                   error);
     return nullptr;
   }
 
-  TabParent* tabParent = static_cast<TabParent*>(browser);
+  nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(browser.get_PBrowserParent());
   PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(serialized);
   WebSocketChannelParent* p = new WebSocketChannelParent(tabParent, loadContext,
                                                          overrideStatus);
   p->AddRef();
   return p;
 }
 
 bool
@@ -696,9 +713,92 @@ NeckoParent::CloneProtocol(Channel* aCha
   ContentParent* contentParent = aCtx->GetContentParent();
   nsAutoPtr<PNeckoParent> actor(contentParent->AllocPNeckoParent());
   if (!actor || !contentParent->RecvPNeckoConstructor(actor)) {
     return nullptr;
   }
   return actor.forget();
 }
 
+namespace {
+std::map<uint64_t, nsCOMPtr<nsIAuthPromptCallback> >&
+CallbackMap()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  static std::map<uint64_t, nsCOMPtr<nsIAuthPromptCallback> > sCallbackMap;
+  return sCallbackMap;
+}
+} // anonymous namespace
+
+NS_IMPL_ISUPPORTS(NeckoParent::NestedFrameAuthPrompt, nsIAuthPrompt2)
+
+NeckoParent::NestedFrameAuthPrompt::NestedFrameAuthPrompt(PNeckoParent* aParent,
+                                                          uint64_t aNestedFrameId)
+  : mNeckoParent(aParent)
+  , mNestedFrameId(aNestedFrameId)
+{}
+
+NS_IMETHODIMP
+NeckoParent::NestedFrameAuthPrompt::AsyncPromptAuth(
+  nsIChannel* aChannel, nsIAuthPromptCallback* callback,
+  nsISupports*, uint32_t,
+  nsIAuthInformation* aInfo, nsICancelable**)
+{
+  static uint64_t callbackId = 0;
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsAutoCString spec;
+  if (uri) {
+    rv = uri->GetSpec(spec);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  nsString realm;
+  rv = aInfo->GetRealm(realm);
+  NS_ENSURE_SUCCESS(rv, rv);
+  callbackId++;
+  if (mNeckoParent->SendAsyncAuthPromptForNestedFrame(mNestedFrameId,
+                                                      spec,
+                                                      realm,
+                                                      callbackId)) {
+    CallbackMap()[callbackId] = callback;
+    return NS_OK;
+  }
+  return NS_ERROR_FAILURE;
+}
+
+bool
+NeckoParent::RecvOnAuthAvailable(const uint64_t& aCallbackId,
+                                 const nsString& aUser,
+                                 const nsString& aPassword,
+                                 const nsString& aDomain)
+{
+  nsCOMPtr<nsIAuthPromptCallback> callback = CallbackMap()[aCallbackId];
+  if (!callback) {
+    return true;
+  }
+  CallbackMap().erase(aCallbackId);
+
+  nsRefPtr<nsAuthInformationHolder> holder =
+    new nsAuthInformationHolder(0, EmptyString(), EmptyCString());
+  holder->SetUsername(aUser);
+  holder->SetPassword(aPassword);
+  holder->SetDomain(aDomain);
+
+  callback->OnAuthAvailable(nullptr, holder);
+  return true;
+}
+
+bool
+NeckoParent::RecvOnAuthCancelled(const uint64_t& aCallbackId,
+                                 const bool& aUserCancel)
+{
+  nsCOMPtr<nsIAuthPromptCallback> callback = CallbackMap()[aCallbackId];
+  if (!callback) {
+    return true;
+  }
+  CallbackMap().erase(aCallbackId);
+  callback->OnAuthCancelled(nullptr, aUserCancel);
+  return true;
+}
+
 }} // mozilla::net
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -27,80 +27,107 @@ class NeckoParent :
 {
 public:
   NeckoParent();
   virtual ~NeckoParent();
 
   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.
    *
    * Returns null if successful, or an error string if failed.
    */
   MOZ_WARN_UNUSED_RESULT
   static const char*
-  CreateChannelLoadContext(PBrowserParent* aBrowser,
+  CreateChannelLoadContext(const PBrowserOrId& aBrowser,
                            PContentParent* aContent,
                            const SerializedLoadContext& aSerialized,
                            nsCOMPtr<nsILoadContext> &aResult);
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   virtual void
   CloneManagees(ProtocolBase* aSource,
               mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
   virtual PCookieServiceParent* AllocPCookieServiceParent() MOZ_OVERRIDE;
   virtual bool
   RecvPCookieServiceConstructor(PCookieServiceParent* aActor) MOZ_OVERRIDE
   {
     return PNeckoParent::RecvPCookieServiceConstructor(aActor);
   }
 
+  /*
+   * This implementation of nsIAuthPrompt2 is used for nested remote iframes that
+   * want an auth prompt.  This class lives in the parent process and informs the
+   * NeckoChild that we want an auth prompt, which forwards the request to the
+   * TabParent in the remote iframe that contains the nested iframe
+   */
+  class NestedFrameAuthPrompt MOZ_FINAL : public nsIAuthPrompt2
+  {
+  public:
+    NS_DECL_ISUPPORTS
+
+    NestedFrameAuthPrompt(PNeckoParent* aParent, uint64_t aNestedFrameId);
+
+    NS_IMETHOD PromptAuth(nsIChannel*, uint32_t, nsIAuthInformation*, bool*)
+    {
+      return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    NS_IMETHOD AsyncPromptAuth(nsIChannel* aChannel, nsIAuthPromptCallback* callback,
+                               nsISupports*, uint32_t,
+                               nsIAuthInformation* aInfo, nsICancelable**);
+
+    NS_IMETHOD AsyncPromptAuth2(nsIChannel*, nsIDOMElement*,
+                                nsIAuthPromptCallback*, nsISupports*,
+                                uint32_t, nsIAuthInformation*, nsICancelable**)
+    {
+      return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+  protected:
+    PNeckoParent* mNeckoParent;
+    uint64_t mNestedFrameId;
+  };
+
 protected:
   virtual PHttpChannelParent*
-    AllocPHttpChannelParent(PBrowserParent*, const SerializedLoadContext&,
+    AllocPHttpChannelParent(const PBrowserOrId&, const SerializedLoadContext&,
                             const HttpChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
   virtual bool
     RecvPHttpChannelConstructor(
                       PHttpChannelParent* aActor,
-                      PBrowserParent* aBrowser,
+                      const PBrowserOrId& aBrowser,
                       const SerializedLoadContext& aSerialized,
                       const HttpChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
   virtual bool DeallocPHttpChannelParent(PHttpChannelParent*) MOZ_OVERRIDE;
   virtual bool DeallocPCookieServiceParent(PCookieServiceParent*) MOZ_OVERRIDE;
   virtual PWyciwygChannelParent* AllocPWyciwygChannelParent() MOZ_OVERRIDE;
   virtual bool DeallocPWyciwygChannelParent(PWyciwygChannelParent*) MOZ_OVERRIDE;
   virtual PFTPChannelParent*
-    AllocPFTPChannelParent(PBrowserParent* aBrowser,
+    AllocPFTPChannelParent(const PBrowserOrId& aBrowser,
                            const SerializedLoadContext& aSerialized,
                            const FTPChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
   virtual bool
     RecvPFTPChannelConstructor(
                       PFTPChannelParent* aActor,
-                      PBrowserParent* aBrowser,
+                      const PBrowserOrId& aBrowser,
                       const SerializedLoadContext& aSerialized,
                       const FTPChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
   virtual bool DeallocPFTPChannelParent(PFTPChannelParent*) MOZ_OVERRIDE;
   virtual PWebSocketParent*
-    AllocPWebSocketParent(PBrowserParent* browser,
+    AllocPWebSocketParent(const PBrowserOrId& browser,
                           const SerializedLoadContext& aSerialized) MOZ_OVERRIDE;
   virtual bool DeallocPWebSocketParent(PWebSocketParent*) MOZ_OVERRIDE;
   virtual PTCPSocketParent* AllocPTCPSocketParent() MOZ_OVERRIDE;
 
   virtual PRemoteOpenFileParent*
     AllocPRemoteOpenFileParent(const SerializedLoadContext& aSerialized,
                                const URIParams& aFileURI,
                                const OptionalURIParams& aAppURI) MOZ_OVERRIDE;
@@ -161,16 +188,23 @@ protected:
   virtual PChannelDiverterParent*
   AllocPChannelDiverterParent(const ChannelDiverterArgs& channel) MOZ_OVERRIDE;
   virtual bool
   RecvPChannelDiverterConstructor(PChannelDiverterParent* actor,
                                   const ChannelDiverterArgs& channel) MOZ_OVERRIDE;
   virtual bool DeallocPChannelDiverterParent(PChannelDiverterParent* actor)
                                                                 MOZ_OVERRIDE;
 
+  virtual bool RecvOnAuthAvailable(const uint64_t& aCallbackId,
+                                   const nsString& aUser,
+                                   const nsString& aPassword,
+                                   const nsString& aDomain) MOZ_OVERRIDE;
+  virtual bool RecvOnAuthCancelled(const uint64_t& aCallbackId,
+                                   const bool& aUserCancel) MOZ_OVERRIDE;
+
 private:
   nsCString mCoreAppsBasePath;
   nsCString mWebAppsBasePath;
 };
 
 } // namespace net
 } // namespace mozilla
 
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -28,16 +28,21 @@ include InputStreamParams;
 include NeckoChannelParams;
 
 
 using class IPC::SerializedLoadContext from "SerializedLoadContext.h";
 
 namespace mozilla {
 namespace net {
 
+union PBrowserOrId {
+  nullable PBrowser;
+  uint64_t;
+};
+
 //-------------------------------------------------------------------
 sync protocol PNecko
 {
   manager PContent;
   manages PHttpChannel;
   manages PCookieService;
   manages PWyciwygChannel;
   manages PFTPChannel;
@@ -50,38 +55,56 @@ sync protocol PNecko
   manages PRtspController;
   manages PRtspChannel;
   manages PChannelDiverter;
 
 parent:
   __delete__();
 
   PCookieService();
-  PHttpChannel(nullable PBrowser browser,
+  PHttpChannel(PBrowserOrId browser,
                SerializedLoadContext loadContext,
                HttpChannelCreationArgs args);
   PWyciwygChannel();
-  PFTPChannel(PBrowser browser, SerializedLoadContext loadContext,
+  PFTPChannel(PBrowserOrId browser, SerializedLoadContext loadContext,
               FTPChannelCreationArgs args);
 
-  PWebSocket(PBrowser browser, SerializedLoadContext loadContext);
+  PWebSocket(PBrowserOrId browser, SerializedLoadContext loadContext);
   PTCPServerSocket(uint16_t localPort, uint16_t backlog, nsString binaryType);
   PUDPSocket(nsCString host, uint16_t port, nsCString filter);
 
   PDNSRequest(nsCString hostName, uint32_t flags);
 
   PRemoteOpenFile(SerializedLoadContext loadContext,
                   URIParams fileuri,
                   OptionalURIParams appuri);
 
   HTMLDNSPrefetch(nsString hostname, uint16_t flags);
   CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason);
   PRtspController();
   PRtspChannel(RtspChannelConnectArgs args);
   PChannelDiverter(ChannelDiverterArgs channel);
 
+  /**
+   * These are called from the child with the results of the auth prompt.
+   * callbackId is the id that was passed in PBrowser::AsyncAuthPrompt,
+   * corresponding to an nsIAuthPromptCallback
+   */
+  OnAuthAvailable(uint64_t callbackId, nsString user,
+                  nsString password, nsString domain);
+  OnAuthCancelled(uint64_t callbackId, bool userCancel);
+
+child:
+  /*
+   * Bring up the http auth prompt for a nested remote mozbrowser.
+   * NestedFrameId is the id corresponding to the PBrowser.  It is the same id
+   * that was passed to the PBrowserOrId param in to the PHttpChannel constructor
+   */
+  AsyncAuthPromptForNestedFrame(uint64_t nestedFrameId, nsCString uri,
+                                nsString realm, uint64_t callbackId);
+
 both:
   PTCPSocket();
 };
 
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -959,18 +959,25 @@ HttpChannelChild::ConnectParent(uint32_t
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
   // The socket transport in the chrome process now holds a logical ref to us
   // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
   AddIPDLReference();
 
   HttpChannelConnectArgs connectArgs(id);
+  PBrowserOrId browser;
+  if (!tabChild ||
+      static_cast<ContentChild*>(gNeckoChild->Manager()) == tabChild->Manager()) {
+    browser = tabChild;
+  } else {
+    browser = TabChild::GetTabChildId(tabChild);
+  }
   if (!gNeckoChild->
-        SendPHttpChannelConstructor(this, tabChild,
+        SendPHttpChannelConstructor(this, browser,
                                     IPC::SerializedLoadContext(this),
                                     connectArgs)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
@@ -1269,17 +1276,24 @@ HttpChannelChild::AsyncOpen(nsIStreamLis
   openArgs.chooseApplicationCache() = mChooseApplicationCache;
   openArgs.appCacheClientID() = appCacheClientId;
   openArgs.allowSpdy() = mAllowSpdy;
 
   // The socket transport in the chrome process now holds a logical ref to us
   // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
   AddIPDLReference();
 
-  gNeckoChild->SendPHttpChannelConstructor(this, tabChild,
+  PBrowserOrId browser;
+  if (!tabChild ||
+      static_cast<ContentChild*>(gNeckoChild->Manager()) == tabChild->Manager()) {
+    browser = tabChild;
+  } else {
+    browser = TabChild::GetTabChildId(tabChild);
+  }
+  gNeckoChild->SendPHttpChannelConstructor(this, browser,
                                            IPC::SerializedLoadContext(this),
                                            openArgs);
 
   if (fdSet) {
     FileDescriptorSetChild* fdSetActor =
       static_cast<FileDescriptorSetChild*>(fdSet);
 
     fdSetActor->ForgetFileDescriptors(fds);
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -20,48 +20,55 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsSerializationHelper.h"
 #include "nsISerializable.h"
 #include "nsIAssociatedContentSecurity.h"
 #include "nsIApplicationCacheService.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "SerializedLoadContext.h"
+#include "nsIAuthInformation.h"
+#include "nsIAuthPromptCallback.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
 
-HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding,
+HttpChannelParent::HttpChannelParent(const PBrowserOrId& iframeEmbedding,
                                      nsILoadContext* aLoadContext,
                                      PBOverrideStatus aOverrideStatus)
   : mIPCClosed(false)
   , mStoredStatus(NS_OK)
   , mStoredProgress(0)
   , mStoredProgressMax(0)
   , mSentRedirect1Begin(false)
   , mSentRedirect1BeginFailed(false)
   , mReceivedRedirect2Verify(false)
   , mPBOverride(aOverrideStatus)
   , mLoadContext(aLoadContext)
   , mStatus(NS_OK)
   , mDivertingFromChild(false)
   , mDivertedOnStartRequest(false)
   , mSuspendedForDiversion(false)
+  , mNestedFrameId(0)
 {
   // Ensure gHttpHandler is initialized: we need the atom table up and running.
   nsCOMPtr<nsIHttpProtocolHandler> dummyInitializer =
     do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http");
 
   MOZ_ASSERT(gHttpHandler);
   mHttpHandler = gHttpHandler;
 
-  mTabParent = static_cast<mozilla::dom::TabParent*>(iframeEmbedding);
+  if (iframeEmbedding.type() == PBrowserOrId::TPBrowserParent) {
+    mTabParent = static_cast<dom::TabParent*>(iframeEmbedding.get_PBrowserParent());
+  } else {
+    mNestedFrameId = iframeEmbedding.get_uint64_t();
+  }
 }
 
 HttpChannelParent::~HttpChannelParent()
 {
 }
 
 void
 HttpChannelParent::ActorDestroy(ActorDestroyReason why)
@@ -104,31 +111,38 @@ HttpChannelParent::Init(const HttpChanne
 //-----------------------------------------------------------------------------
 
 NS_IMPL_ISUPPORTS(HttpChannelParent,
                   nsIInterfaceRequestor,
                   nsIProgressEventSink,
                   nsIRequestObserver,
                   nsIStreamListener,
                   nsIParentChannel,
+                  nsIAuthPromptProvider,
                   nsIParentRedirectingChannel)
 
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsIInterfaceRequestor
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpChannelParent::GetInterface(const nsIID& aIID, void **result)
 {
   if (aIID.Equals(NS_GET_IID(nsIAuthPromptProvider)) ||
       aIID.Equals(NS_GET_IID(nsISecureBrowserUI))) {
-    if (!mTabParent)
-      return NS_NOINTERFACE;
+    if (mTabParent) {
+      return mTabParent->QueryInterface(aIID, result);
+    }
+  }
 
-    return mTabParent->QueryInterface(aIID, result);
+  // Only support nsIAuthPromptProvider in Content process
+  if (XRE_GetProcessType() == GeckoProcessType_Default &&
+      aIID.Equals(NS_GET_IID(nsIAuthPromptProvider))) {
+    *result = nullptr;
+    return NS_OK;
   }
 
   // Only support nsILoadContext if child channel's callbacks did too
   if (aIID.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) {
     NS_ADDREF(mLoadContext);
     *result = static_cast<nsILoadContext*>(mLoadContext);
     return NS_OK;
   }
@@ -982,9 +996,19 @@ HttpChannelParent::NotifyDiversionFailed
   mParentListener = nullptr;
   mChannel = nullptr;
 
   if (!mIPCClosed) {
     unused << SendDeleteSelf();
   }
 }
 
+NS_IMETHODIMP
+HttpChannelParent::GetAuthPrompt(uint32_t aPromptReason, const nsIID& iid,
+                                 void** aResult)
+{
+  nsCOMPtr<nsIAuthPrompt2> prompt =
+    new NeckoParent::NestedFrameAuthPrompt(Manager(), mNestedFrameId);
+  prompt.forget(aResult);
+  return NS_OK;
+}
+
 }} // mozilla::net
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -5,53 +5,56 @@
  * 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_net_HttpChannelParent_h
 #define mozilla_net_HttpChannelParent_h
 
 #include "ADivertableParentChannel.h"
 #include "nsHttp.h"
-#include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/net/PHttpChannelParent.h"
 #include "mozilla/net/NeckoCommon.h"
 #include "mozilla/net/NeckoParent.h"
 #include "nsIParentRedirectingChannel.h"
 #include "nsIProgressEventSink.h"
 #include "nsHttpChannel.h"
+#include "nsIAuthPromptProvider.h"
 
 class nsICacheEntry;
 class nsIAssociatedContentSecurity;
 
 namespace mozilla {
 
 namespace dom{
 class TabParent;
 }
 
 namespace net {
 
 class HttpChannelParentListener;
+class PBrowserOrId;
 
 class HttpChannelParent : public PHttpChannelParent
                         , public nsIParentRedirectingChannel
                         , public nsIProgressEventSink
                         , public nsIInterfaceRequestor
                         , public ADivertableParentChannel
+                        , public nsIAuthPromptProvider
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIPARENTCHANNEL
   NS_DECL_NSIPARENTREDIRECTINGCHANNEL
   NS_DECL_NSIPROGRESSEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
+  NS_DECL_NSIAUTHPROMPTPROVIDER
 
-  HttpChannelParent(mozilla::dom::PBrowserParent* iframeEmbedding,
+  HttpChannelParent(const PBrowserOrId& iframeEmbedding,
                     nsILoadContext* aLoadContext,
                     PBOverrideStatus aStatus);
   virtual ~HttpChannelParent();
 
   bool Init(const HttpChannelCreationArgs& aOpenArgs);
 
   // ADivertableParentChannel functions.
   void DivertTo(nsIStreamListener *aListener) MOZ_OVERRIDE;
@@ -155,14 +158,16 @@ private:
   // must be set when RecvDivertOnData/~DivertOnStop/~DivertComplete are
   // received from the child channel.
   bool mDivertingFromChild;
 
   // Set if OnStart|StopRequest was called during a diversion from the child.
   bool mDivertedOnStartRequest;
 
   bool mSuspendedForDiversion;
+
+  uint64_t mNestedFrameId;
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // mozilla_net_HttpChannelParent_h
--- a/uriloader/prefetch/OfflineCacheUpdateParent.cpp
+++ b/uriloader/prefetch/OfflineCacheUpdateParent.cpp
@@ -200,16 +200,22 @@ OfflineCacheUpdateParent::GetTopWindow(n
 
 NS_IMETHODIMP
 OfflineCacheUpdateParent::GetTopFrameElement(nsIDOMElement** aElement)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+OfflineCacheUpdateParent::GetNestedFrameId(uint64_t* aId)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 OfflineCacheUpdateParent::IsAppOfType(uint32_t appType, bool *_retval)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 OfflineCacheUpdateParent::GetIsContent(bool *aIsContent)
 {