From b9be660c266eec7c8c83125894a4e460bd2dd858 Mon Sep 17 00:00:00 2001 From: "cbiesinger%web.de" Date: Fri, 22 Sep 2006 21:06:57 +0000 Subject: [PATCH] Bug 265780 make FTP use nsIAuthPrompt2 r=darin git-svn-id: svn://10.0.0.236/trunk@212180 18797224-902f-48f8-a5cc-f745e15eee43 --- .../windowwatcher/public/nsPromptUtils.h | 11 +++ .../components/windowwatcher/src/nsPrompt.cpp | 11 ++- mozilla/extensions/wallet/src/singsign.cpp | 7 ++ mozilla/netwerk/base/src/Makefile.in | 1 + .../netwerk/protocol/ftp/src/nsFTPChannel.h | 7 -- .../ftp/src/nsFtpConnectionThread.cpp | 98 +++++------------- .../protocol/ftp/src/nsFtpConnectionThread.h | 1 - .../protocol/http/src/nsHttpChannel.cpp | 99 +++---------------- .../test/unit/test_authpromptwrapper.js | 49 +++++++-- 9 files changed, 108 insertions(+), 176 deletions(-) diff --git a/mozilla/embedding/components/windowwatcher/public/nsPromptUtils.h b/mozilla/embedding/components/windowwatcher/public/nsPromptUtils.h index 2925b25ce04..fd73289f9fe 100644 --- a/mozilla/embedding/components/windowwatcher/public/nsPromptUtils.h +++ b/mozilla/embedding/components/windowwatcher/public/nsPromptUtils.h @@ -38,6 +38,8 @@ #ifndef NSPROMPTUTILS_H_ #define NSPROMPTUTILS_H_ +#include "nsIHttpChannel.h" + /** * @file * This file defines some helper functions that simplify interaction @@ -139,6 +141,15 @@ inline void NS_GetAuthKey(nsIChannel* aChannel, nsIAuthInformation* aAuthInfo, nsCString& key) { + // HTTP does this differently from other protocols + nsCOMPtr http(do_QueryInterface(aChannel)); + if (!http) { + nsCOMPtr uri; + aChannel->GetURI(getter_AddRefs(uri)); + uri->GetPrePath(key); + return; + } + // NOTE: For backwards-compatibility reasons, this must be the ASCII host. nsCString host; PRInt32 port = -1; diff --git a/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp b/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp index 1095d5162f0..3d378ef4b61 100644 --- a/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp +++ b/mozilla/embedding/components/windowwatcher/src/nsPrompt.cpp @@ -667,9 +667,14 @@ nsPrompt::PromptPasswordAdapter(nsIPromptService* aService, PRUnichar *user = ToNewUnicode(defaultUser), *pass = ToNewUnicode(defaultPass); nsresult rv; - rv = aService->PromptUsernameAndPassword(aParent, nsnull, message.get(), - &user, &pass, aCheckLabel, - aCheckValue, retval); + if (flags & nsIAuthInformation::ONLY_PASSWORD) + rv = aService->PromptPassword(aParent, nsnull, message.get(), + &pass, aCheckLabel, + aCheckValue, retval); + else + rv = aService->PromptUsernameAndPassword(aParent, nsnull, message.get(), + &user, &pass, aCheckLabel, + aCheckValue, retval); nsAdoptingString userStr(user); nsAdoptingString passStr(pass); diff --git a/mozilla/extensions/wallet/src/singsign.cpp b/mozilla/extensions/wallet/src/singsign.cpp index 9046d59bc39..4fb69e46f79 100644 --- a/mozilla/extensions/wallet/src/singsign.cpp +++ b/mozilla/extensions/wallet/src/singsign.cpp @@ -2855,8 +2855,15 @@ SINGSIGN_PromptAuth username, password); + PRUint32 flags = 0; + aAuthInfo->GetFlags(&flags); + if (checked) { NS_SetAuthInfo(aAuthInfo, username, password); + // If we were only asked for a password, return immediately + // (to match SINGSIGN_PromptPassword) + if (flags & nsIAuthInformation::ONLY_PASSWORD) + return NS_OK; } PRBool remembered = checked; diff --git a/mozilla/netwerk/base/src/Makefile.in b/mozilla/netwerk/base/src/Makefile.in index 9eb81e7256a..e8055df80c5 100644 --- a/mozilla/netwerk/base/src/Makefile.in +++ b/mozilla/netwerk/base/src/Makefile.in @@ -58,6 +58,7 @@ REQUIRES = xpcom \ CPPSRCS = \ nsTransportUtils.cpp \ nsAsyncStreamCopier.cpp \ + nsAuthInformationHolder.cpp \ nsBaseChannel.cpp \ nsBaseContentStream.cpp \ nsBufferedStreams.cpp \ diff --git a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h index 08beee70cdc..bec646460a9 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h +++ b/mozilla/netwerk/protocol/ftp/src/nsFTPChannel.h @@ -56,8 +56,6 @@ #include "netCore.h" #include "nsIStreamListener.h" #include "nsAutoLock.h" -#include "nsIPrompt.h" -#include "nsIAuthPrompt.h" #include "nsIFTPChannel.h" #include "nsIUploadChannel.h" #include "nsIProxyInfo.h" @@ -65,11 +63,6 @@ #include "nsIResumableChannel.h" #include "nsHashPropertyBag.h" -#include "nsICacheService.h" -#include "nsICacheEntryDescriptor.h" -#include "nsICacheListener.h" -#include "nsICacheSession.h" - #define FTP_COMMAND_CHANNEL_SEG_SIZE 64 #define FTP_COMMAND_CHANNEL_SEG_COUNT 8 diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp index 9165a18468a..041bf9e8a3d 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp @@ -58,6 +58,7 @@ #include "nsNetUtil.h" #include "nsThreadUtils.h" #include "nsStreamUtils.h" +#include "nsICacheService.h" #include "nsIURL.h" #include "nsISocketTransport.h" #include "nsIStreamListenerTee.h" @@ -65,6 +66,7 @@ #include "nsIPrefBranch.h" #include "nsIStringBundle.h" #include "nsCPasswordManager.h" +#include "nsAuthInformationHolder.h" #if defined(PR_LOGGING) extern PRLogModuleInfo* gFTPLog; @@ -658,51 +660,27 @@ nsFtpState::S_user() { usernameStr.AppendLiteral("anonymous"); } else { if (mUsername.IsEmpty()) { - nsCOMPtr prompter; - mChannel->GetCallback(prompter); + nsCOMPtr prompter; + NS_QueryAuthPrompt2(NS_STATIC_CAST(nsIChannel*, mChannel), + getter_AddRefs(prompter)); if (!prompter) return NS_ERROR_NOT_INITIALIZED; - nsXPIDLString user, passwd; - nsCAutoString prePath; - rv = mChannel->URI()->GetPrePath(prePath); - if (NS_FAILED(rv)) - return rv; - NS_ConvertUTF8toUTF16 prePathU(prePath); - - nsCOMPtr bundleService = - do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr bundle; - rv = bundleService->CreateBundle(NECKO_MSGS_URL, getter_AddRefs(bundle)); - if (NS_FAILED(rv)) - return rv; - - const PRUnichar *formatStrings[] = { prePathU.get() }; - NS_NAMED_LITERAL_STRING(name, "EnterUserPasswordFor"); - - nsXPIDLString formattedString; - rv = bundle->FormatStringFromName(name.get(), formatStrings, 1, - getter_Copies(formattedString)); - if (NS_FAILED(rv)) - return rv; + nsRefPtr info = + new nsAuthInformationHolder(nsIAuthInformation::AUTH_HOST, + EmptyString(), + EmptyCString()); PRBool retval; - rv = prompter->PromptUsernameAndPassword(nsnull, - formattedString, - prePathU.get(), - nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY, - getter_Copies(user), - getter_Copies(passwd), - &retval); + rv = prompter->PromptAuth(mChannel, nsIAuthPrompt2::LEVEL_NONE, + info, &retval); + // if the user canceled or didn't supply a username we want to fail - if (NS_FAILED(rv) || !retval || (user && !*user) ) + if (NS_FAILED(rv) || !retval || info->User().IsEmpty()) return NS_ERROR_FAILURE; - mUsername = user; - mPassword = passwd; + mUsername = info->User(); + mPassword = info->Password(); } // XXX Is UTF-8 the best choice? AppendUTF16toUTF8(mUsername, usernameStr); @@ -772,50 +750,28 @@ nsFtpState::S_pass() { } } else { if (mPassword.IsEmpty() || mRetryPass) { - nsCOMPtr prompter; - mChannel->GetCallback(prompter); + nsCOMPtr prompter; + NS_QueryAuthPrompt2(NS_STATIC_CAST(nsIChannel*, mChannel), + getter_AddRefs(prompter)); if (!prompter) return NS_ERROR_NOT_INITIALIZED; - nsCAutoString prePath; - rv = mChannel->URI()->GetPrePath(prePath); - if (NS_FAILED(rv)) - return rv; - NS_ConvertUTF8toUTF16 prePathU(prePath); - - nsCOMPtr bundleService = - do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return rv; + nsRefPtr info = + new nsAuthInformationHolder(nsIAuthInformation::AUTH_HOST | + nsIAuthInformation::ONLY_PASSWORD, + EmptyString(), + EmptyCString()); - nsCOMPtr bundle; - rv = bundleService->CreateBundle(NECKO_MSGS_URL, - getter_AddRefs(bundle)); - - const PRUnichar *formatStrings[2] = { - mUsername.get(), prePathU.get() - }; - NS_NAMED_LITERAL_STRING(name, "EnterPasswordFor"); - - nsXPIDLString formattedString; - rv = bundle->FormatStringFromName(name.get(), formatStrings, 2, - getter_Copies(formattedString)); - if (NS_FAILED(rv)) - return rv; - - nsXPIDLString passwd; PRBool retval; - rv = prompter->PromptPassword(nsnull, - formattedString, - prePathU.get(), - nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY, - getter_Copies(passwd), &retval); + rv = prompter->PromptAuth(mChannel, nsIAuthPrompt2::LEVEL_NONE, + info, &retval); + // we want to fail if the user canceled. Note here that if they want // a blank password, we will pass it along. if (NS_FAILED(rv) || !retval) return NS_ERROR_FAILURE; - mPassword = passwd; + mPassword = info->Password(); } // XXX Is UTF-8 the best choice? AppendUTF16toUTF8(mPassword, passwordStr); diff --git a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h index b650a3169a3..e826c195d70 100644 --- a/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h +++ b/mozilla/netwerk/protocol/ftp/src/nsFtpConnectionThread.h @@ -62,7 +62,6 @@ #include "nsAutoLock.h" #include "nsAutoPtr.h" #include "nsIPrompt.h" -#include "nsIAuthPrompt.h" #include "nsITransport.h" #include "nsIProxyInfo.h" diff --git a/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp b/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp index bfba679e40e..d25c7e7b71b 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -75,6 +75,7 @@ #include "nsChannelProperties.h" #include "nsStreamUtils.h" #include "nsIOService.h" +#include "nsAuthInformationHolder.h" // True if the local cache should be bypassed when processing a request. #define BYPASS_LOCAL_CACHE(loadFlags) \ @@ -2665,99 +2666,20 @@ nsHttpChannel::ParseRealm(const char *challenge, nsACString &realm) } } -class nsAuthInformationHolder : public nsIAuthInformation { -public: - // aAuthType must be ASCII - nsAuthInformationHolder(PRUint32 aFlags, const nsString& aRealm, - const nsCString& aAuthType) - : mFlags(aFlags), mRealm(aRealm), mAuthType(aAuthType) {} - NS_DECL_ISUPPORTS - NS_DECL_NSIAUTHINFORMATION +class nsHTTPAuthInformation : public nsAuthInformationHolder { +public: + nsHTTPAuthInformation(PRUint32 aFlags, const nsString& aRealm, + const nsCString& aAuthType) + : nsAuthInformationHolder(aFlags, aRealm, aAuthType) {} void SetToHttpAuthIdentity(PRUint32 authFlags, nsHttpAuthIdentity& identity); -private: - nsString mUser; - nsString mPassword; - nsString mDomain; - - PRUint32 mFlags; - nsString mRealm; - nsCString mAuthType; }; -NS_IMPL_ISUPPORTS1(nsAuthInformationHolder, nsIAuthInformation) - -NS_IMETHODIMP -nsAuthInformationHolder::GetFlags(PRUint32* aFlags) -{ - *aFlags = mFlags; - return NS_OK; -} - -NS_IMETHODIMP -nsAuthInformationHolder::GetRealm(nsAString& aRealm) -{ - aRealm = mRealm; - return NS_OK; -} - -NS_IMETHODIMP -nsAuthInformationHolder::GetAuthenticationScheme(nsACString& aScheme) -{ - aScheme = mAuthType; - return NS_OK; -} - -NS_IMETHODIMP -nsAuthInformationHolder::GetUsername(nsAString& aUserName) -{ - aUserName = mUser; - return NS_OK; -} - -NS_IMETHODIMP -nsAuthInformationHolder::SetUsername(const nsAString& aUserName) -{ - if (!(mFlags & ONLY_PASSWORD)) - mUser = aUserName; - return NS_OK; -} - -NS_IMETHODIMP -nsAuthInformationHolder::GetPassword(nsAString& aPassword) -{ - aPassword = mPassword; - return NS_OK; -} - -NS_IMETHODIMP -nsAuthInformationHolder::SetPassword(const nsAString& aPassword) -{ - mPassword = aPassword; - return NS_OK; -} - -NS_IMETHODIMP -nsAuthInformationHolder::GetDomain(nsAString& aDomain) -{ - aDomain = mDomain; - return NS_OK; -} - -NS_IMETHODIMP -nsAuthInformationHolder::SetDomain(const nsAString& aDomain) -{ - if (mFlags & NEED_DOMAIN) - mDomain = aDomain; - return NS_OK; -} - void -nsAuthInformationHolder::SetToHttpAuthIdentity(PRUint32 authFlags, nsHttpAuthIdentity& identity) +nsHTTPAuthInformation::SetToHttpAuthIdentity(PRUint32 authFlags, nsHttpAuthIdentity& identity) { - SetIdent(identity, authFlags, ToNewUnicode(mUser), ToNewUnicode(mPassword)); - identity.Set(mDomain.get(), mUser.get(), mPassword.get()); + identity.Set(Domain().get(), User().get(), Password().get()); } nsresult @@ -2795,8 +2717,9 @@ nsHttpChannel::PromptForIdentity(PRUint32 level, if (authFlags & nsIHttpAuthenticator::IDENTITY_INCLUDES_DOMAIN) promptFlags |= nsIAuthInformation::NEED_DOMAIN; - nsRefPtr holder = - new nsAuthInformationHolder(promptFlags, realmU, nsDependentCString(authType)); + nsRefPtr holder = + new nsHTTPAuthInformation(promptFlags, realmU, + nsDependentCString(authType)); if (!holder) return NS_ERROR_OUT_OF_MEMORY; PRBool retval = PR_FALSE; diff --git a/mozilla/netwerk/test/unit/test_authpromptwrapper.js b/mozilla/netwerk/test/unit/test_authpromptwrapper.js index f9376e50ca3..f1032c7a194 100644 --- a/mozilla/netwerk/test/unit/test_authpromptwrapper.js +++ b/mozilla/netwerk/test/unit/test_authpromptwrapper.js @@ -1,6 +1,10 @@ // NOTE: This tests code outside of Necko. The test still lives here because // the contract is part of Necko. +// TODO: +// - HTTPS +// - Proxies + const nsIAuthInformation = Components.interfaces.nsIAuthInformation; const nsIAuthPromptAdapterFactory = Components.interfaces.nsIAuthPromptAdapterFactory; @@ -41,6 +45,8 @@ function run_test() { user: "foo\\bar", pw: "bar", + scheme: "http", + QueryInterface: function authprompt_qi(iid) { if (iid.equals(Components.interfaces.nsISupports) || iid.equals(Components.interfaces.nsIAuthPrompt)) @@ -72,18 +78,21 @@ function run_test() { }, doChecks: function ap1_check(text, realm) { - do_check_eq(host + ":80 (" + info.realm + ")", realm); + if (this.scheme == "http") + do_check_eq(host + ":80 (" + info.realm + ")", realm); + else + do_check_eq(this.scheme + "://" + host, realm); do_check_neq(text.indexOf(host), -1); - do_check_neq(text.indexOf(info.realm), -1); + // Only HTTP has realms + if (this.scheme == "http") + do_check_neq(text.indexOf(info.realm), -1); // No explicit port in the URL; message should not contain -1 // for those cases do_check_eq(text.indexOf("-1"), -1); } }; - var prompt1 = new Prompt1(); - var wrapper = adapter.createAdapter(prompt1); // Also have to make up a channel var ios = Components.classes["@mozilla.org/network/io-service;1"] @@ -91,8 +100,14 @@ function run_test() { var chan = ios.newChannel("http://" + host, "", null); function do_tests(expectedRV) { + var prompt1; + var wrapper; + // 1: The simple case + prompt1 = new Prompt1(); prompt1.rv = expectedRV; + wrapper = adapter.createAdapter(prompt1); + var rv = wrapper.promptAuth(chan, 0, info); do_check_eq(rv, prompt1.rv); do_check_eq(prompt1.called, CALLED_PROMPTUP); @@ -145,7 +160,7 @@ function run_test() { do_check_eq(info.password, prompt1.pw); } - info.flags &= ~nsIAuthInformation.ONLY_PASSWORD; + info.flags &= ~nsIAuthInformation.NEED_DOMAIN; info.domain = ""; info.username = ""; @@ -169,7 +184,29 @@ function run_test() { do_check_eq(info.password, prompt1.pw); } - info.flags &= ~nsIAuthInformation.ONLY_PASSWORD; + info.flags &= ~nsIAuthInformation.NEED_DOMAIN; + + info.domain = ""; + info.username = ""; + info.password = ""; + + // 5: FTP + var ftpchan = ios.newChannel("ftp://" + host, "", null); + + prompt1 = new Prompt1(); + prompt1.rv = expectedRV; + prompt1.scheme = "ftp"; + + wrapper = adapter.createAdapter(prompt1); + var rv = wrapper.promptAuth(ftpchan, 0, info); + do_check_eq(rv, prompt1.rv); + do_check_eq(prompt1.called, CALLED_PROMPTUP); + + if (rv) { + do_check_eq(info.domain, ""); + do_check_eq(info.username, prompt1.user); + do_check_eq(info.password, prompt1.pw); + } info.domain = ""; info.username = "";