diff -up firefox-48.0/extensions/auth/nsHttpNegotiateAuth.cpp.890908-async-nego firefox-48.0/extensions/auth/nsHttpNegotiateAuth.cpp --- firefox-48.0/extensions/auth/nsHttpNegotiateAuth.cpp.890908-async-nego 2016-07-25 22:22:05.000000000 +0200 +++ firefox-48.0/extensions/auth/nsHttpNegotiateAuth.cpp 2016-07-27 09:56:55.652261702 +0200 @@ -40,6 +40,10 @@ #include "mozilla/Snprintf.h" #include "nsIChannel.h" #include "nsNetUtil.h" +#include "nsThreadUtils.h" +#include "nsIHttpAuthenticatorCallback.h" +#include "mozilla/Mutex.h" +#include "nsICancelable.h" //----------------------------------------------------------------------------- @@ -51,6 +55,7 @@ static const char kNegotiateAuthAllowNon static const char kNegotiateAuthSSPI[] = "network.auth.use-sspi"; #define kNegotiateLen (sizeof(kNegotiate)-1) +#define DEFAULT_THREAD_TIMEOUT_MS 30000 //----------------------------------------------------------------------------- @@ -184,7 +189,260 @@ nsHttpNegotiateAuth::ChallengeReceived(n } NS_IMPL_ISUPPORTS(nsHttpNegotiateAuth, nsIHttpAuthenticator) - + +namespace { + +// +// GetNextTokenCompleteEvent +// +// This event is fired on main thread when async call of +// nsHttpNegotiateAuth::GenerateCredentials is finished. During the Run() +// method the nsIHttpAuthenticatorCallback::OnCredsAvailable is called with +// obtained credentials, flags and NS_OK when successful, otherwise +// NS_ERROR_FAILURE is returned as a result of failed operation. +// +class GetNextTokenCompleteEvent final : public nsIRunnable, + public nsICancelable +{ + virtual ~GetNextTokenCompleteEvent() + { + if (mCreds) { + free(mCreds); + } + }; + +public: + NS_DECL_THREADSAFE_ISUPPORTS + + explicit GetNextTokenCompleteEvent(nsIHttpAuthenticatorCallback* aCallback) + : mCallback(aCallback) + , mCreds(nullptr) + , mCancelled(false) + { + } + + NS_IMETHODIMP DispatchSuccess(char *aCreds, + uint32_t aFlags, + already_AddRefed aSessionState, + already_AddRefed aContinuationState) + { + // Called from worker thread + MOZ_ASSERT(!NS_IsMainThread()); + + mCreds = aCreds; + mFlags = aFlags; + mResult = NS_OK; + mSessionState = aSessionState; + mContinuationState = aContinuationState; + return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); + } + + NS_IMETHODIMP DispatchError(already_AddRefed aSessionState, + already_AddRefed aContinuationState) + { + // Called from worker thread + MOZ_ASSERT(!NS_IsMainThread()); + + mResult = NS_ERROR_FAILURE; + mSessionState = aSessionState; + mContinuationState = aContinuationState; + return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); + } + + NS_IMETHODIMP Run() override + { + // Runs on main thread + MOZ_ASSERT(NS_IsMainThread()); + + if (!mCancelled) { + nsCOMPtr callback; + callback.swap(mCallback); + callback->OnCredsGenerated(mCreds, mFlags, mResult, mSessionState, mContinuationState); + } + return NS_OK; + } + + NS_IMETHODIMP Cancel(nsresult aReason) override + { + // Supposed to be called from main thread + MOZ_ASSERT(NS_IsMainThread()); + + mCancelled = true; + return NS_OK; + } + +private: + nsCOMPtr mCallback; + char *mCreds; // This class owns it, freed in destructor + uint32_t mFlags; + nsresult mResult; + bool mCancelled; + nsCOMPtr mSessionState; + nsCOMPtr mContinuationState; +}; + +NS_IMPL_ISUPPORTS(GetNextTokenCompleteEvent, nsIRunnable, nsICancelable) + +// +// GetNextTokenRunnable +// +// This runnable is created by GenerateCredentialsAsync and it runs +// in nsHttpNegotiateAuth::mNegotiateThread and calling GenerateCredentials. +// +class GetNextTokenRunnable final : public mozilla::Runnable +{ + virtual ~GetNextTokenRunnable() {} + public: + GetNextTokenRunnable(nsIHttpAuthenticableChannel *authChannel, + const char *challenge, + bool isProxyAuth, + const char16_t *domain, + const char16_t *username, + const char16_t *password, + nsISupports *sessionState, + nsISupports *continuationState, + GetNextTokenCompleteEvent *aCompleteEvent + ) + : mAuthChannel(authChannel) + , mChallenge(challenge) + , mIsProxyAuth(isProxyAuth) + , mDomain(domain) + , mUsername(username) + , mPassword(password) + , mSessionState(sessionState) + , mContinuationState(continuationState) + , mCompleteEvent(aCompleteEvent) + { + } + + NS_IMETHODIMP Run() override + { + // Runs on worker thread + MOZ_ASSERT(!NS_IsMainThread()); + + char *creds; + uint32_t flags; + nsresult rv = ObtainCredentialsAndFlags(&creds, &flags); + + // Passing session and continuation state this way to not touch + // referencing of the object that may not be thread safe. + // Not having a thread safe referencing doesn't mean the object + // cannot be used on multiple threads (one example is nsAuthSSPI.) + // This ensures state objects will be destroyed on the main thread + // when not changed by GenerateCredentials. + if (NS_FAILED(rv)) { + return mCompleteEvent->DispatchError(mSessionState.forget(), + mContinuationState.forget()); + } + + return mCompleteEvent->DispatchSuccess(creds, flags, + mSessionState.forget(), + mContinuationState.forget()); + } + + NS_IMETHODIMP ObtainCredentialsAndFlags(char **aCreds, uint32_t *aFlags) + { + nsresult rv; + + // Use negotiate service to call GenerateCredentials outside of main thread + nsAutoCString contractId; + contractId.Assign(NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX); + contractId.Append("negotiate"); + nsCOMPtr authenticator = + do_GetService(contractId.get(), &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsISupports *sessionState = mSessionState; + nsISupports *continuationState = mContinuationState; + // The continuationState is for the sake of completeness propagated + // to the caller (despite it is not changed in any GenerateCredentials + // implementation). + // + // The only implementation that use sessionState is the + // nsHttpDigestAuth::GenerateCredentials. Since there's no reason + // to implement nsHttpDigestAuth::GenerateCredentialsAsync + // because digest auth does not block the main thread, we won't + // propagate changes to sessionState to the caller because of + // the change is too complicated on the caller side. + // + // Should any of the session or continuation states change inside + // this method, they must be threadsafe. + rv = authenticator->GenerateCredentials(mAuthChannel, + mChallenge.get(), + mIsProxyAuth, + mDomain.get(), + mUsername.get(), + mPassword.get(), + &sessionState, + &continuationState, + aFlags, + aCreds); + if (mSessionState != sessionState) { + mSessionState = sessionState; + } + if (mContinuationState != continuationState) { + mContinuationState = continuationState; + } + return rv; + } + private: + nsCOMPtr mAuthChannel; + nsCString mChallenge; + bool mIsProxyAuth; + nsString mDomain; + nsString mUsername; + nsString mPassword; + nsCOMPtr mSessionState; + nsCOMPtr mContinuationState; + RefPtr mCompleteEvent; +}; + +} // anonymous namespace + +NS_IMETHODIMP +nsHttpNegotiateAuth::GenerateCredentialsAsync(nsIHttpAuthenticableChannel *authChannel, + nsIHttpAuthenticatorCallback* aCallback, + const char *challenge, + bool isProxyAuth, + const char16_t *domain, + const char16_t *username, + const char16_t *password, + nsISupports *sessionState, + nsISupports *continuationState, + nsICancelable **aCancelable) +{ + NS_ENSURE_ARG(aCallback); + NS_ENSURE_ARG_POINTER(aCancelable); + + RefPtr cancelEvent = + new GetNextTokenCompleteEvent(aCallback); + + + nsCOMPtr getNextTokenRunnable = + new GetNextTokenRunnable(authChannel, + challenge, + isProxyAuth, + domain, + username, + password, + sessionState, + continuationState, + cancelEvent); + cancelEvent.forget(aCancelable); + + nsresult rv; + if (!mNegotiateThread) { + mNegotiateThread = + new mozilla::LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS, + NS_LITERAL_CSTRING("NegotiateAuth")); + NS_ENSURE_TRUE(mNegotiateThread, NS_ERROR_OUT_OF_MEMORY); + } + rv = mNegotiateThread->Dispatch(getNextTokenRunnable, NS_DISPATCH_NORMAL); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + // // GenerateCredentials // diff -up firefox-48.0/extensions/auth/nsHttpNegotiateAuth.h.890908-async-nego firefox-48.0/extensions/auth/nsHttpNegotiateAuth.h --- firefox-48.0/extensions/auth/nsHttpNegotiateAuth.h.890908-async-nego 2016-05-12 19:13:34.000000000 +0200 +++ firefox-48.0/extensions/auth/nsHttpNegotiateAuth.h 2016-07-27 09:56:55.652261702 +0200 @@ -10,6 +10,7 @@ #include "nsIURI.h" #include "nsSubstring.h" #include "mozilla/Attributes.h" +#include "mozilla/LazyIdleThread.h" // The nsHttpNegotiateAuth class provides responses for the GSS-API Negotiate method // as specified by Microsoft in draft-brezak-spnego-http-04.txt @@ -17,7 +18,7 @@ class nsHttpNegotiateAuth final : public nsIHttpAuthenticator { public: - NS_DECL_ISUPPORTS + NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIHTTPAUTHENTICATOR private: @@ -37,5 +38,7 @@ private: int32_t port, const char *baseStart, const char *baseEnd); + // Thread for GenerateCredentialsAsync + RefPtr mNegotiateThread; }; #endif /* nsHttpNegotiateAuth_h__ */ diff -up firefox-48.0/netwerk/base/moz.build.890908-async-nego firefox-48.0/netwerk/base/moz.build --- firefox-48.0/netwerk/base/moz.build.890908-async-nego 2016-07-25 22:22:05.000000000 +0200 +++ firefox-48.0/netwerk/base/moz.build 2016-07-27 09:56:55.653261702 +0200 @@ -48,6 +48,7 @@ XPIDL_SOURCES += [ 'nsIFileURL.idl', 'nsIForcePendingChannel.idl', 'nsIFormPOSTActionChannel.idl', + 'nsIHttpAuthenticatorCallback.idl', 'nsIHttpPushListener.idl', 'nsIIncrementalDownload.idl', 'nsIIncrementalStreamLoader.idl', diff -up firefox-48.0/netwerk/base/nsIHttpAuthenticatorCallback.idl.890908-async-nego firefox-48.0/netwerk/base/nsIHttpAuthenticatorCallback.idl --- firefox-48.0/netwerk/base/nsIHttpAuthenticatorCallback.idl.890908-async-nego 2016-07-27 09:56:55.653261702 +0200 +++ firefox-48.0/netwerk/base/nsIHttpAuthenticatorCallback.idl 2016-07-27 09:56:55.653261702 +0200 @@ -0,0 +1,31 @@ +/* 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 "nsISupports.idl" + +[scriptable, uuid(d989cb03-e446-4086-b9e6-46842cb97bd5)] +interface nsIHttpAuthenticatorCallback : nsISupports +{ + /** + * Authentication data for a header is available. + * + * @param aCreds + * Credentials which were obtained asynchonously. + * @param aFlags + * Flags set by asynchronous call. + * @param aResult + * Result status of credentials generation + * @param aSessionState + * Modified session state to be passed to caller + * @param aContinuationState + * Modified continuation state to be passed to caller + */ + void onCredsGenerated(in string aCreds, + in unsigned long aFlags, + in nsresult aResult, + in nsISupports aSessionsState, + in nsISupports aContinuationState); + +}; + diff -up firefox-48.0/netwerk/protocol/http/nsHttpBasicAuth.cpp.890908-async-nego firefox-48.0/netwerk/protocol/http/nsHttpBasicAuth.cpp --- firefox-48.0/netwerk/protocol/http/nsHttpBasicAuth.cpp.890908-async-nego 2016-05-12 19:13:28.000000000 +0200 +++ firefox-48.0/netwerk/protocol/http/nsHttpBasicAuth.cpp 2016-07-27 09:56:55.653261702 +0200 @@ -49,6 +49,20 @@ nsHttpBasicAuth::ChallengeReceived(nsIHt *identityInvalid = true; return NS_OK; } +NS_IMETHODIMP +nsHttpBasicAuth::GenerateCredentialsAsync(nsIHttpAuthenticableChannel *authChannel, + nsIHttpAuthenticatorCallback* aCallback, + const char *challenge, + bool isProxyAuth, + const char16_t *domain, + const char16_t *username, + const char16_t *password, + nsISupports *sessionState, + nsISupports *continuationState, + nsICancelable **aCancellable) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} NS_IMETHODIMP nsHttpBasicAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel, diff -up firefox-48.0/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp.890908-async-nego firefox-48.0/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp --- firefox-48.0/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp.890908-async-nego 2016-05-12 19:13:28.000000000 +0200 +++ firefox-48.0/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp 2016-07-27 09:56:55.653261702 +0200 @@ -267,6 +267,11 @@ nsHttpChannelAuthProvider::Cancel(nsresu mAsyncPromptAuthCancelable->Cancel(status); mAsyncPromptAuthCancelable = nullptr; } + + if (mGenerateCredentialsCancelable) { + mGenerateCredentialsCancelable->Cancel(status); + mGenerateCredentialsCancelable = nullptr; + } return NS_OK; } @@ -280,6 +285,11 @@ nsHttpChannelAuthProvider::Disconnect(ns mAsyncPromptAuthCancelable = nullptr; } + if (mGenerateCredentialsCancelable) { + mGenerateCredentialsCancelable->Cancel(status); + mGenerateCredentialsCancelable = nullptr; + } + NS_IF_RELEASE(mProxyAuthContinuationState); NS_IF_RELEASE(mAuthContinuationState); @@ -355,11 +365,6 @@ nsHttpChannelAuthProvider::GenCredsAndSe char **result) { nsresult rv; - uint32_t authFlags; - - rv = auth->GetAuthFlags(&authFlags); - if (NS_FAILED(rv)) return rv; - nsISupports *ss = sessionState; // set informations that depend on whether @@ -373,6 +378,22 @@ nsHttpChannelAuthProvider::GenCredsAndSe continuationState = &mAuthContinuationState; } + rv = auth->GenerateCredentialsAsync(mAuthChannel, + this, + challenge, + proxyAuth, + ident.Domain(), + ident.User(), + ident.Password(), + ss, + *continuationState, + getter_AddRefs(mGenerateCredentialsCancelable)); + if (NS_SUCCEEDED(rv)) { + // Calling generate credentials async, results will be dispatched to the + // main thread by calling OnCredsGenerated method + return NS_ERROR_IN_PROGRESS; + } + uint32_t generateFlags; rv = auth->GenerateCredentials(mAuthChannel, challenge, @@ -393,6 +414,29 @@ nsHttpChannelAuthProvider::GenCredsAndSe LOG(("generated creds: %s\n", *result)); #endif + return UpdateCache(auth, scheme, host, port, directory, realm, + challenge, ident, *result, generateFlags, sessionState); +} + +nsresult +nsHttpChannelAuthProvider::UpdateCache(nsIHttpAuthenticator *auth, + const char *scheme, + const char *host, + int32_t port, + const char *directory, + const char *realm, + const char *challenge, + const nsHttpAuthIdentity &ident, + const char *creds, + uint32_t generateFlags, + nsISupports *sessionState) +{ + nsresult rv; + + uint32_t authFlags; + rv = auth->GetAuthFlags(&authFlags); + if (NS_FAILED(rv)) return rv; + // find out if this authenticator allows reuse of credentials and/or // challenge. bool saveCreds = @@ -410,6 +454,7 @@ nsHttpChannelAuthProvider::GenCredsAndSe nsAutoCString suffix; GetOriginAttributesSuffix(chan, suffix); + // create a cache entry. we do this even though we don't yet know that // these credentials are valid b/c we need to avoid prompting the user // more than once in case the credentials are valid. @@ -417,12 +462,13 @@ nsHttpChannelAuthProvider::GenCredsAndSe // if the credentials are not reusable, then we don't bother sticking // them in the auth cache. rv = authCache->SetAuthEntry(scheme, host, port, directory, realm, - saveCreds ? *result : nullptr, + saveCreds ? creds : nullptr, saveChallenge ? challenge : nullptr, suffix, saveIdentity ? &ident : nullptr, sessionState); return rv; + } nsresult @@ -1223,6 +1269,63 @@ NS_IMETHODIMP nsHttpChannelAuthProvider: return NS_OK; } +NS_IMETHODIMP nsHttpChannelAuthProvider::OnCredsGenerated(const char *aGeneratedCreds, + uint32_t aFlags, + nsresult aResult, + nsISupports* aSessionState, + nsISupports* aContinuationState) +{ + nsresult rv; + + MOZ_ASSERT(NS_IsMainThread()); + + // When channel is closed, do not proceed + if (!mAuthChannel) { + return NS_OK; + } + + mGenerateCredentialsCancelable = nullptr; + + if (NS_FAILED(aResult)) { + return OnAuthCancelled(nullptr, true); + } + + // We want to update m(Proxy)AuthContinuationState in case it was changed by + // nsHttpNegotiateAuth::GenerateCredentials + nsCOMPtr contState(aContinuationState); + if (mProxyAuth) { + contState.swap(mProxyAuthContinuationState); + } else { + contState.swap(mAuthContinuationState); + } + + nsCOMPtr auth; + nsAutoCString unused; + rv = GetAuthenticator(mCurrentChallenge.get(), unused, getter_AddRefs(auth)); + NS_ENSURE_SUCCESS(rv, rv); + + const char *host; + int32_t port; + nsHttpAuthIdentity *ident; + nsAutoCString directory, scheme; + nsISupports **unusedContinuationState; + + // Get realm from challenge + nsAutoCString realm; + ParseRealm(mCurrentChallenge.get(), realm); + + rv = GetAuthorizationMembers(mProxyAuth, scheme, host, port, + directory, ident, unusedContinuationState); + if (NS_FAILED(rv)) return rv; + + UpdateCache(auth, scheme.get(), host, port, directory.get(), realm.get(), + mCurrentChallenge.get(), *ident, aGeneratedCreds, aFlags, aSessionState); + mCurrentChallenge.Truncate(); + + ContinueOnAuthAvailable(nsDependentCString(aGeneratedCreds)); + return NS_OK; +} + nsresult nsHttpChannelAuthProvider::ContinueOnAuthAvailable(const nsCSubstring& creds) { @@ -1457,7 +1560,7 @@ nsHttpChannelAuthProvider::GetCurrentPat } NS_IMPL_ISUPPORTS(nsHttpChannelAuthProvider, nsICancelable, - nsIHttpChannelAuthProvider, nsIAuthPromptCallback) + nsIHttpChannelAuthProvider, nsIAuthPromptCallback, nsIHttpAuthenticatorCallback) } // namespace net } // namespace mozilla diff -up firefox-48.0/netwerk/protocol/http/nsHttpChannelAuthProvider.h.890908-async-nego firefox-48.0/netwerk/protocol/http/nsHttpChannelAuthProvider.h --- firefox-48.0/netwerk/protocol/http/nsHttpChannelAuthProvider.h.890908-async-nego 2016-05-12 19:13:28.000000000 +0200 +++ firefox-48.0/netwerk/protocol/http/nsHttpChannelAuthProvider.h 2016-07-27 09:57:34.084262023 +0200 @@ -9,11 +9,13 @@ #include "nsIHttpChannelAuthProvider.h" #include "nsIAuthPromptCallback.h" +#include "nsIHttpAuthenticatorCallback.h" #include "nsString.h" #include "nsCOMPtr.h" #include "nsHttpAuthCache.h" #include "nsProxyInfo.h" #include "nsCRT.h" +#include "nsICancelableRunnable.h" class nsIHttpAuthenticableChannel; class nsIHttpAuthenticator; @@ -25,12 +27,14 @@ class nsHttpHandler; class nsHttpChannelAuthProvider : public nsIHttpChannelAuthProvider , public nsIAuthPromptCallback + , public nsIHttpAuthenticatorCallback { public: NS_DECL_ISUPPORTS NS_DECL_NSICANCELABLE NS_DECL_NSIHTTPCHANNELAUTHPROVIDER NS_DECL_NSIAUTHPROMPTCALLBACK + NS_DECL_NSIHTTPAUTHENTICATORCALLBACK nsHttpChannelAuthProvider(); static void InitializePrefs(); @@ -117,6 +121,19 @@ private: // For more details look at the bug 647010. bool BlockPrompt(); + // Store credentials to the cache when appropriate aFlags are set. + nsresult UpdateCache(nsIHttpAuthenticator *aAuth, + const char *aScheme, + const char *aHost, + int32_t aPort, + const char *aDirectory, + const char *aRealm, + const char *aChallenge, + const nsHttpAuthIdentity &aIdent, + const char *aCreds, + uint32_t aGenerateFlags, + nsISupports *aSessionState); + private: nsIHttpAuthenticableChannel *mAuthChannel; // weak ref @@ -160,6 +177,7 @@ private: // authentication credentials dialogs for sub-resources and cross-origin // sub-resources. static uint32_t sAuthAllowPref; + nsCOMPtr mGenerateCredentialsCancelable; }; } // namespace net diff -up firefox-48.0/netwerk/protocol/http/nsHttpDigestAuth.cpp.890908-async-nego firefox-48.0/netwerk/protocol/http/nsHttpDigestAuth.cpp --- firefox-48.0/netwerk/protocol/http/nsHttpDigestAuth.cpp.890908-async-nego 2016-05-12 19:13:28.000000000 +0200 +++ firefox-48.0/netwerk/protocol/http/nsHttpDigestAuth.cpp 2016-07-27 09:56:55.654261702 +0200 @@ -158,6 +158,22 @@ nsHttpDigestAuth::ChallengeReceived(nsIH return NS_OK; } + +NS_IMETHODIMP +nsHttpDigestAuth::GenerateCredentialsAsync(nsIHttpAuthenticableChannel *authChannel, + nsIHttpAuthenticatorCallback* aCallback, + const char *challenge, + bool isProxyAuth, + const char16_t *domain, + const char16_t *username, + const char16_t *password, + nsISupports *sessionState, + nsISupports *continuationState, + nsICancelable **aCancellable) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + NS_IMETHODIMP nsHttpDigestAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel, const char *challenge, diff -up firefox-48.0/netwerk/protocol/http/nsHttpNTLMAuth.cpp.890908-async-nego firefox-48.0/netwerk/protocol/http/nsHttpNTLMAuth.cpp --- firefox-48.0/netwerk/protocol/http/nsHttpNTLMAuth.cpp.890908-async-nego 2016-07-25 22:22:06.000000000 +0200 +++ firefox-48.0/netwerk/protocol/http/nsHttpNTLMAuth.cpp 2016-07-27 09:56:55.654261702 +0200 @@ -333,6 +333,21 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHtt } NS_IMETHODIMP +nsHttpNTLMAuth::GenerateCredentialsAsync(nsIHttpAuthenticableChannel *authChannel, + nsIHttpAuthenticatorCallback* aCallback, + const char *challenge, + bool isProxyAuth, + const char16_t *domain, + const char16_t *username, + const char16_t *password, + nsISupports *sessionState, + nsISupports *continuationState, + nsICancelable **aCancellable) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsHttpNTLMAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel, const char *challenge, bool isProxyAuth, diff -up firefox-48.0/netwerk/protocol/http/nsIHttpAuthenticator.idl.890908-async-nego firefox-48.0/netwerk/protocol/http/nsIHttpAuthenticator.idl --- firefox-48.0/netwerk/protocol/http/nsIHttpAuthenticator.idl.890908-async-nego 2016-05-12 19:13:28.000000000 +0200 +++ firefox-48.0/netwerk/protocol/http/nsIHttpAuthenticator.idl 2016-07-27 09:56:55.654261702 +0200 @@ -6,6 +6,8 @@ #include "nsISupports.idl" interface nsIHttpAuthenticableChannel; +interface nsIHttpAuthenticatorCallback; +interface nsICancelable; /** * nsIHttpAuthenticator @@ -18,7 +20,7 @@ interface nsIHttpAuthenticableChannel; * where is the lower-cased value of the authentication scheme * found in the server challenge per the rules of RFC 2617. */ -[scriptable, uuid(16784db0-fcb1-4352-b0c9-6a3a67e3cf79)] +[scriptable, uuid(fef7db8a-a4e2-49d1-9685-19ed7e309b7d)] interface nsIHttpAuthenticator : nsISupports { /** @@ -54,6 +56,54 @@ interface nsIHttpAuthenticator : nsISupp /** * Called to generate the authentication credentials for a particular + * server/proxy challenge asynchronously. Credentials will be sent back + * to the server via an Authorization/Proxy-Authorization header. + * + * @param aChannel + * the http channel requesting credentials + * @param aCallback + * callback function to be called when credentials are available + * @param aChallenge + * the challenge from the WWW-Authenticate/Proxy-Authenticate + * server response header. (possibly from the auth cache.) + * @param aProxyAuth + * flag indicating whether or not aChallenge is from a proxy. + * @param aDomain + * string containing the domain name (if appropriate) + * @param aUser + * string containing the user name + * @param aPassword + * string containing the password + * @param aSessionState + * state stored along side the user's identity in the auth cache + * for the lifetime of the browser session. if a new auth cache + * entry is created for this challenge, then this parameter will + * be null. on return, the result will be stored in the new auth + * cache entry. this parameter is non-null when an auth cache entry + * is being reused. currently modification of session state is not + * communicated to caller, thus caching credentials obtained by + * asynchronous way is not supported. + * @param aContinuationState + * state held by the channel between consecutive calls to + * generateCredentials, assuming multiple calls are required + * to authenticate. this state is held for at most the lifetime of + * the channel. + * @pram aCancel + * returns cancellable runnable object which caller can use to cancel + * calling aCallback when finished. + */ + void generateCredentialsAsync(in nsIHttpAuthenticableChannel aChannel, + in nsIHttpAuthenticatorCallback aCallback, + in string aChallenge, + in boolean aProxyAuth, + in wstring aDomain, + in wstring aUser, + in wstring aPassword, + in nsISupports aSessionState, + in nsISupports aContinuationState, + out nsICancelable aCancel); + /** + * Called to generate the authentication credentials for a particular * server/proxy challenge. This is the value that will be sent back * to the server via an Authorization/Proxy-Authorization header. *