summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firefox-redhat-default-prefs.js4
-rw-r--r--firefox.spec9
-rw-r--r--mozilla-890908-async-negotiate.patch737
3 files changed, 747 insertions, 3 deletions
diff --git a/firefox-redhat-default-prefs.js b/firefox-redhat-default-prefs.js
index d7ed1c5..13fc643 100644
--- a/firefox-redhat-default-prefs.js
+++ b/firefox-redhat-default-prefs.js
@@ -26,4 +26,6 @@ pref("media.gmp-gmpopenh264.enabled",false);
pref("plugins.notifyMissingFlash", false);
/* See https://bugzilla.redhat.com/show_bug.cgi?id=1226489 */
pref("browser.display.use_system_colors", false);
-pref("layers.use-image-offscreen-surfaces", false); \ No newline at end of file
+pref("layers.use-image-offscreen-surfaces", false);
+/* Allow sending credetials to all https:// sites */
+pref("network.negotiate-auth.trusted-uris", "https://")
diff --git a/firefox.spec b/firefox.spec
index 8dade14..bc9995c 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -85,7 +85,7 @@
Summary: Mozilla Firefox Web browser
Name: firefox
Version: 46.0.1
-Release: 8%{?pre_tag}%{?dist}
+Release: 9%{?pre_tag}%{?dist}
URL: https://www.mozilla.org/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+
Group: Applications/Internet
@@ -101,7 +101,7 @@ Source23: firefox.1
Source24: mozilla-api-key
Source25: firefox-symbolic.svg
-#Build patches
+# Build patches
Patch0: firefox-install-dir.patch
Patch3: mozilla-build-arm.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=814879#c3
@@ -133,6 +133,7 @@ Patch403: mozilla-1216658.patch
Patch404: mozilla-1270046.patch
# Remove when mozbz#1269319 lands
Patch405: mozilla-1245783.patch
+Patch406: mozilla-890908-async-negotiate.patch
# Debian patches
Patch500: mozilla-440908.patch
@@ -280,6 +281,7 @@ cd %{tarballdir}
%patch403 -p1 -b .1216658
%patch404 -p1 -b .1270046
%patch405 -p1 -b .1245783
+%patch406 -p1 -b .890908-async-negotiate
# Debian extension patch
%patch500 -p1 -b .440908
@@ -791,6 +793,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
#---------------------------------------------------------------------
%changelog
+* Thu May 26 2016 Jan Horak <jhorak@redhat.com> - 46.0.1-9
+- Negotiate authentication is made off the main thread (mozbz#890908)
+
* Mon May 23 2016 Martin Stransky <stransky@redhat.com> - 46.0.1-8
- Rebuilt for new bookmarks (rhbz#1338010)
- Fixed build issue in Gtk3.20 patch
diff --git a/mozilla-890908-async-negotiate.patch b/mozilla-890908-async-negotiate.patch
new file mode 100644
index 0000000..4de1f23
--- /dev/null
+++ b/mozilla-890908-async-negotiate.patch
@@ -0,0 +1,737 @@
+diff -up firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.cpp.890908-async-negotiate firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.cpp
+--- firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.cpp.890908-async-negotiate 2016-05-03 07:31:11.000000000 +0200
++++ firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.cpp 2016-05-26 15:10:23.850901737 +0200
+@@ -38,6 +38,10 @@
+ #include "prnetdb.h"
+ #include "mozilla/Likely.h"
+ #include "mozilla/Snprintf.h"
++#include "nsThreadUtils.h"
++#include "nsIHttpAuthenticatorCallback.h"
++#include "mozilla/Mutex.h"
++#include "nsICancelable.h"
+
+ //-----------------------------------------------------------------------------
+
+@@ -49,6 +53,7 @@ static const char kNegotiateAuthAllowNon
+ static const char kNegotiateAuthSSPI[] = "network.auth.use-sspi";
+
+ #define kNegotiateLen (sizeof(kNegotiate)-1)
++#define DEFAULT_THREAD_TIMEOUT_MS 30000
+
+ //-----------------------------------------------------------------------------
+
+@@ -172,7 +177,237 @@ 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,
++ nsISupports *aSessionState,
++ nsISupports *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()
++ {
++ // Called from worker thread
++ MOZ_ASSERT(!NS_IsMainThread());
++
++ mResult = NS_ERROR_FAILURE;
++ return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
++ }
++
++ NS_IMETHODIMP Run() override
++ {
++ // Runs on main thread
++ MOZ_ASSERT(NS_IsMainThread());
++
++ if (!mCancelled) {
++ nsCOMPtr<nsIHttpAuthenticatorCallback> 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<nsIHttpAuthenticatorCallback> mCallback;
++ char *mCreds; // This class owns it, freed in destructor
++ uint32_t mFlags;
++ nsresult mResult;
++ bool mCancelled;
++ nsCOMPtr<nsISupports> mSessionState;
++ nsCOMPtr<nsISupports> 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 nsRunnable
++{
++ 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);
++ if (NS_FAILED(rv)) {
++ return mCompleteEvent->DispatchError();
++ }
++
++ return mCompleteEvent->DispatchSuccess(creds, flags, mSessionState, mContinuationState);
++ }
++
++ NS_IMETHODIMP ObtainCredentialsAndFlags(char **aCreds, uint32_t *aFlags)
++ {
++ // Use negotiate service to call GenerateCredentials outside of main thread
++ nsAutoCString contractId;
++ contractId.Assign(NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX);
++ contractId.Append("negotiate");
++ nsresult rv;
++ nsCOMPtr<nsIHttpAuthenticator> 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.
++ rv = authenticator->GenerateCredentials(mAuthChannel,
++ mChallenge.get(),
++ mIsProxyAuth,
++ mDomain.get(),
++ mUsername.get(),
++ mPassword.get(),
++ &sessionState,
++ &continuationState,
++ aFlags,
++ aCreds);
++ mSessionState = sessionState;
++ mContinuationState = continuationState;
++ return rv;
++ }
++ private:
++ nsCOMPtr<nsIHttpAuthenticableChannel> mAuthChannel;
++ nsCString mChallenge;
++ bool mIsProxyAuth;
++ nsString mDomain;
++ nsString mUsername;
++ nsString mPassword;
++ nsCOMPtr<nsISupports> mSessionState;
++ nsCOMPtr<nsISupports> mContinuationState;
++ RefPtr<GetNextTokenCompleteEvent> 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<GetNextTokenCompleteEvent> cancelEvent =
++ new GetNextTokenCompleteEvent(aCallback);
++
++
++ nsCOMPtr<nsIRunnable> 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-46.0.1/extensions/auth/nsHttpNegotiateAuth.h.890908-async-negotiate firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.h
+--- firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.h.890908-async-negotiate 2016-05-03 07:31:11.000000000 +0200
++++ firefox-46.0.1/extensions/auth/nsHttpNegotiateAuth.h 2016-05-26 15:04:33.971068476 +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<mozilla::LazyIdleThread> mNegotiateThread;
+ };
+ #endif /* nsHttpNegotiateAuth_h__ */
+diff -up firefox-46.0.1/netwerk/base/moz.build.890908-async-negotiate firefox-46.0.1/netwerk/base/moz.build
+--- firefox-46.0.1/netwerk/base/moz.build.890908-async-negotiate 2016-05-03 07:31:07.000000000 +0200
++++ firefox-46.0.1/netwerk/base/moz.build 2016-05-26 15:04:33.971068476 +0200
+@@ -46,6 +46,7 @@ XPIDL_SOURCES += [
+ 'nsIFileStreams.idl',
+ 'nsIFileURL.idl',
+ 'nsIForcePendingChannel.idl',
++ 'nsIHttpAuthenticatorCallback.idl',
+ 'nsIHttpPushListener.idl',
+ 'nsIIncrementalDownload.idl',
+ 'nsIIncrementalStreamLoader.idl',
+diff -up firefox-46.0.1/netwerk/base/nsIHttpAuthenticatorCallback.idl.890908-async-negotiate firefox-46.0.1/netwerk/base/nsIHttpAuthenticatorCallback.idl
+--- firefox-46.0.1/netwerk/base/nsIHttpAuthenticatorCallback.idl.890908-async-negotiate 2016-05-26 15:04:33.971068476 +0200
++++ firefox-46.0.1/netwerk/base/nsIHttpAuthenticatorCallback.idl 2016-05-26 15:04:33.971068476 +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-46.0.1/netwerk/protocol/http/nsHttpBasicAuth.cpp.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsHttpBasicAuth.cpp
+--- firefox-46.0.1/netwerk/protocol/http/nsHttpBasicAuth.cpp.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200
++++ firefox-46.0.1/netwerk/protocol/http/nsHttpBasicAuth.cpp 2016-05-26 15:04:33.971068476 +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-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp
+--- firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200
++++ firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp 2016-05-26 15:04:33.972068475 +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
+@@ -1224,6 +1270,66 @@ NS_IMETHODIMP nsHttpChannelAuthProvider:
+ }
+
+ nsresult
++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<nsISupports> contState(aContinuationState);
++ if (mProxyAuth) {
++ contState.swap(mProxyAuthContinuationState);
++ NS_IF_ADDREF(mProxyAuthContinuationState);
++ } else {
++ contState.swap(mAuthContinuationState);
++ NS_IF_ADDREF(mAuthContinuationState);
++ }
++
++ nsCOMPtr<nsIHttpAuthenticator> 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)
+ {
+ nsresult rv;
+@@ -1457,7 +1563,7 @@ nsHttpChannelAuthProvider::GetCurrentPat
+ }
+
+ NS_IMPL_ISUPPORTS(nsHttpChannelAuthProvider, nsICancelable,
+- nsIHttpChannelAuthProvider, nsIAuthPromptCallback)
++ nsIHttpChannelAuthProvider, nsIAuthPromptCallback, nsIHttpAuthenticatorCallback)
+
+ } // namespace net
+ } // namespace mozilla
+diff -up firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.h.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.h
+--- firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.h.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200
++++ firefox-46.0.1/netwerk/protocol/http/nsHttpChannelAuthProvider.h 2016-05-26 15:04:33.972068475 +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<nsICancelable> mGenerateCredentialsCancelable;
+ };
+
+ } // namespace net
+diff -up firefox-46.0.1/netwerk/protocol/http/nsHttpDigestAuth.cpp.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsHttpDigestAuth.cpp
+--- firefox-46.0.1/netwerk/protocol/http/nsHttpDigestAuth.cpp.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200
++++ firefox-46.0.1/netwerk/protocol/http/nsHttpDigestAuth.cpp 2016-05-26 15:04:33.972068475 +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-46.0.1/netwerk/protocol/http/nsHttpNTLMAuth.cpp.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsHttpNTLMAuth.cpp
+--- firefox-46.0.1/netwerk/protocol/http/nsHttpNTLMAuth.cpp.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200
++++ firefox-46.0.1/netwerk/protocol/http/nsHttpNTLMAuth.cpp 2016-05-26 15:04:33.972068475 +0200
+@@ -323,6 +323,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-46.0.1/netwerk/protocol/http/nsIHttpAuthenticator.idl.890908-async-negotiate firefox-46.0.1/netwerk/protocol/http/nsIHttpAuthenticator.idl
+--- firefox-46.0.1/netwerk/protocol/http/nsIHttpAuthenticator.idl.890908-async-negotiate 2016-05-03 07:31:08.000000000 +0200
++++ firefox-46.0.1/netwerk/protocol/http/nsIHttpAuthenticator.idl 2016-05-26 15:04:33.973068475 +0200
+@@ -6,6 +6,8 @@
+ #include "nsISupports.idl"
+
+ interface nsIHttpAuthenticableChannel;
++interface nsIHttpAuthenticatorCallback;
++interface nsICancelable;
+
+ /**
+ * nsIHttpAuthenticator
+@@ -18,7 +20,7 @@ interface nsIHttpAuthenticableChannel;
+ * where <auth-scheme> 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.
+ *
bgstack15