Bug 879475 - Part 006. Fix http auth prompts for nested content processes r=honzab

Based on original patch by David Zbarsky <dzbarsky@gmail.com>
This commit is contained in:
"Kan-Ru Chen (陳侃如)" 2014-06-11 13:44:36 +08:00
parent 0896e79e4f
commit 7df84372ff
20 changed files with 518 additions and 49 deletions

View File

@ -40,6 +40,14 @@ LoadContext::GetTopFrameElement(nsIDOMElement** 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*)
{

View File

@ -45,6 +45,24 @@ public:
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)
@ -62,6 +80,7 @@ public:
bool aUseRemoteTabs,
bool aIsInBrowserElement)
: mTopFrameElement(do_GetWeakReference(aTopFrameElement))
, mNestedFrameId(0)
, mAppId(aAppId)
, mIsContent(aIsContent)
, mUsePrivateBrowsing(aUsePrivateBrowsing)
@ -75,6 +94,7 @@ public:
// Constructor taking reserved appId for the safebrowsing cookie.
LoadContext(uint32_t aAppId)
: mTopFrameElement(nullptr)
, mNestedFrameId(0)
, mAppId(aAppId)
, mIsContent(false)
, mUsePrivateBrowsing(false)
@ -87,6 +107,7 @@ public:
private:
nsWeakPtr mTopFrameElement;
uint64_t mNestedFrameId;
uint32_t mAppId;
bool mIsContent;
bool mUsePrivateBrowsing;

View File

@ -12260,6 +12260,13 @@ nsDocShell::GetTopFrameElement(nsIDOMElement** aElement)
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)
{

View File

@ -210,6 +210,7 @@ public:
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*);

View File

@ -14,7 +14,7 @@ interface nsIDOMElement;
* 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
{
/**
@ -43,6 +43,14 @@ interface nsILoadContext : nsISupports
*/
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.
*

View File

@ -442,9 +442,12 @@ AuthPromptWrapper.prototype = {
_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;

View File

@ -357,6 +357,15 @@ parent:
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);

View File

@ -617,6 +617,15 @@ private:
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()
{
@ -696,6 +705,7 @@ TabChild::TabChild(nsIContentChild* aManager, const TabContext& aContext, uint32
, mIgnoreKeyPressEvent(false)
, mActiveElementManager(new ActiveElementManager())
, mHasValidInnerSize(false)
, mUniqueId(0)
{
if (!sActiveDurationMsSet) {
Preferences::AddIntVarCache(&sActiveDurationMs,
@ -1372,6 +1382,9 @@ TabChild::ActorDestroy(ActorDestroyReason why)
(mTabChildGlobal->mMessageManager.get())->Disconnect();
mTabChildGlobal->mMessageManager = nullptr;
}
if (Id() != 0) {
NestedTabChildMap().erase(Id());
}
}
TabChild::~TabChild()

View File

@ -240,6 +240,9 @@ class TabChild : public TabChildBase,
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
@ -256,6 +259,24 @@ public:
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
@ -568,6 +589,7 @@ private:
bool mIgnoreKeyPressEvent;
nsRefPtr<ActiveElementManager> mActiveElementManager;
bool mHasValidInnerSize;
uint64_t mUniqueId;
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
};

View File

@ -22,6 +22,7 @@
#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"
@ -61,6 +62,10 @@
#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>
@ -2076,5 +2081,145 @@ TabParent::SetIsDocShellActive(bool 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

View File

@ -307,6 +307,10 @@ protected:
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;

View File

@ -9,6 +9,7 @@
#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"
@ -73,7 +74,7 @@ void NeckoChild::DestroyNeckoChild()
}
PHttpChannelChild*
NeckoChild::AllocPHttpChannelChild(PBrowserChild* browser,
NeckoChild::AllocPHttpChannelChild(const PBrowserOrId& browser,
const SerializedLoadContext& loadContext,
const HttpChannelCreationArgs& aOpenArgs)
{
@ -94,7 +95,7 @@ NeckoChild::DeallocPHttpChannelChild(PHttpChannelChild* channel)
}
PFTPChannelChild*
NeckoChild::AllocPFTPChannelChild(PBrowserChild* aBrowser,
NeckoChild::AllocPFTPChannelChild(const PBrowserOrId& aBrowser,
const SerializedLoadContext& aSerialized,
const FTPChannelCreationArgs& aOpenArgs)
{
@ -150,7 +151,7 @@ NeckoChild::DeallocPWyciwygChannelChild(PWyciwygChannelChild* channel)
}
PWebSocketChild*
NeckoChild::AllocPWebSocketChild(PBrowserChild* browser,
NeckoChild::AllocPWebSocketChild(const PBrowserOrId& browser,
const SerializedLoadContext& aSerialized)
{
NS_NOTREACHED("AllocPWebSocketChild should not be called");
@ -300,5 +301,21 @@ NeckoChild::DeallocPChannelDiverterChild(PChannelDiverterChild* 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

View File

@ -27,7 +27,7 @@ public:
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;
@ -35,12 +35,13 @@ protected:
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;
@ -71,6 +72,10 @@ protected:
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;
};
/**

View File

@ -35,6 +35,8 @@
#include "nsEscape.h"
#include "RemoteOpenFileParent.h"
#include "SerializedLoadContext.h"
#include "nsAuthInformationHolder.h"
#include "nsIAuthPromptCallback.h"
using mozilla::dom::ContentParent;
using mozilla::dom::TabParent;
@ -151,28 +153,43 @@ NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
}
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;
@ -185,7 +202,7 @@ NeckoParent::ActorDestroy(ActorDestroyReason aWhy)
}
PHttpChannelParent*
NeckoParent::AllocPHttpChannelParent(PBrowserParent* aBrowser,
NeckoParent::AllocPHttpChannelParent(const PBrowserOrId& aBrowser,
const SerializedLoadContext& aSerialized,
const HttpChannelCreationArgs& aOpenArgs)
{
@ -215,7 +232,7 @@ NeckoParent::DeallocPHttpChannelParent(PHttpChannelParent* channel)
bool
NeckoParent::RecvPHttpChannelConstructor(
PHttpChannelParent* aActor,
PBrowserParent* aBrowser,
const PBrowserOrId& aBrowser,
const SerializedLoadContext& aSerialized,
const HttpChannelCreationArgs& aOpenArgs)
{
@ -224,7 +241,7 @@ NeckoParent::RecvPHttpChannelConstructor(
}
PFTPChannelParent*
NeckoParent::AllocPFTPChannelParent(PBrowserParent* aBrowser,
NeckoParent::AllocPFTPChannelParent(const PBrowserOrId& aBrowser,
const SerializedLoadContext& aSerialized,
const FTPChannelCreationArgs& aOpenArgs)
{
@ -254,7 +271,7 @@ NeckoParent::DeallocPFTPChannelParent(PFTPChannelParent* channel)
bool
NeckoParent::RecvPFTPChannelConstructor(
PFTPChannelParent* aActor,
PBrowserParent* aBrowser,
const PBrowserOrId& aBrowser,
const SerializedLoadContext& aSerialized,
const FTPChannelCreationArgs& aOpenArgs)
{
@ -292,7 +309,7 @@ NeckoParent::DeallocPWyciwygChannelParent(PWyciwygChannelParent* channel)
}
PWebSocketParent*
NeckoParent::AllocPWebSocketParent(PBrowserParent* browser,
NeckoParent::AllocPWebSocketParent(const PBrowserOrId& browser,
const SerializedLoadContext& serialized)
{
nsCOMPtr<nsILoadContext> loadContext;
@ -305,7 +322,7 @@ NeckoParent::AllocPWebSocketParent(PBrowserParent* browser,
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);
@ -701,4 +718,87 @@ NeckoParent::CloneProtocol(Channel* aChannel,
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

View File

@ -29,13 +29,6 @@ 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,
@ -52,7 +45,7 @@ public:
*/
MOZ_WARN_UNUSED_RESULT
static const char*
CreateChannelLoadContext(PBrowserParent* aBrowser,
CreateChannelLoadContext(const PBrowserOrId& aBrowser,
PContentParent* aContent,
const SerializedLoadContext& aSerialized,
nsCOMPtr<nsILoadContext> &aResult);
@ -69,14 +62,48 @@ public:
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;
@ -84,18 +111,18 @@ protected:
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;
@ -166,6 +193,13 @@ protected:
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;

View File

@ -33,6 +33,11 @@ using class IPC::SerializedLoadContext from "SerializedLoadContext.h";
namespace mozilla {
namespace net {
union PBrowserOrId {
nullable PBrowser;
uint64_t;
};
//-------------------------------------------------------------------
sync protocol PNecko
{
@ -55,14 +60,14 @@ 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);
@ -78,6 +83,24 @@ parent:
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();
};

View File

@ -964,8 +964,15 @@ HttpChannelChild::ConnectParent(uint32_t id)
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;
@ -1274,7 +1281,14 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
// 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);

View File

@ -25,6 +25,8 @@
#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;
@ -32,7 +34,7 @@ using namespace mozilla::ipc;
namespace mozilla {
namespace net {
HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding,
HttpChannelParent::HttpChannelParent(const PBrowserOrId& iframeEmbedding,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus)
: mIPCClosed(false)
@ -48,6 +50,7 @@ HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding,
, mDivertingFromChild(false)
, mDivertedOnStartRequest(false)
, mSuspendedForDiversion(false)
, mNestedFrameId(0)
{
// Ensure gHttpHandler is initialized: we need the atom table up and running.
nsCOMPtr<nsIHttpProtocolHandler> dummyInitializer =
@ -56,7 +59,11 @@ HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding,
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()
@ -109,6 +116,7 @@ NS_IMPL_ISUPPORTS(HttpChannelParent,
nsIRequestObserver,
nsIStreamListener,
nsIParentChannel,
nsIAuthPromptProvider,
nsIParentRedirectingChannel)
//-----------------------------------------------------------------------------
@ -120,10 +128,16 @@ 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
@ -987,4 +1001,14 @@ HttpChannelParent::NotifyDiversionFailed(nsresult aErrorCode,
}
}
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

View File

@ -10,13 +10,13 @@
#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;
@ -30,12 +30,14 @@ 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
@ -45,8 +47,9 @@ public:
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();
@ -160,6 +163,8 @@ private:
bool mDivertedOnStartRequest;
bool mSuspendedForDiversion;
uint64_t mNestedFrameId;
};
} // namespace net

View File

@ -204,6 +204,12 @@ 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)
{