From bd5e92615c05bbfbdea200dc614ea104d48765e5 Mon Sep 17 00:00:00 2001 From: Jonas Sicking Date: Tue, 30 Sep 2008 17:52:52 -0700 Subject: [PATCH] Implement cookieless requests for Access-Control. b=389508 r=biesi sr=jst --- content/base/public/nsIXMLHttpRequest.idl | 12 +- content/base/src/nsCrossSiteListenerProxy.cpp | 28 +++- content/base/src/nsCrossSiteListenerProxy.h | 3 + content/base/src/nsSyncLoadService.cpp | 2 +- content/base/src/nsXMLHttpRequest.cpp | 63 +++++++-- content/base/src/nsXMLHttpRequest.h | 4 +- .../base/test/file_CrossSiteXHR_inner.html | 3 + .../base/test/file_CrossSiteXHR_server.sjs | 26 +++- content/base/test/test_CrossSiteXHR.html | 127 ++++++++++++++++++ .../src/xslt/txMozillaStylesheetCompiler.cpp | 3 +- netwerk/base/public/nsIRequest.idl | 7 + netwerk/protocol/http/src/nsHttpChannel.cpp | 35 ++++- 12 files changed, 292 insertions(+), 21 deletions(-) diff --git a/content/base/public/nsIXMLHttpRequest.idl b/content/base/public/nsIXMLHttpRequest.idl index b30f6c39edd5..f095d1ce1a43 100644 --- a/content/base/public/nsIXMLHttpRequest.idl +++ b/content/base/public/nsIXMLHttpRequest.idl @@ -101,7 +101,7 @@ interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget { * you're aware of all the security implications. And then think twice about * it. */ -[scriptable, uuid(acda85ab-d06c-4176-b834-6d129ca97ca3)] +[scriptable, uuid(48ce10a0-c585-4e8f-a5f5-1ac1e47cc501)] interface nsIXMLHttpRequest : nsISupports { /** @@ -321,6 +321,16 @@ interface nsIXMLHttpRequest : nsISupports */ attribute boolean mozBackgroundRequest; + /** + * When set to true attempts to make cross-site Access-Control requests + * with credentials such as cookies and authorization headers. + * + * Never affects same-site requests. + * + * Defaults to false. + */ + attribute boolean withCredentials; + /** * Initialize the object for use from C++ code with the principal, script * context, and owner window that should be used. diff --git a/content/base/src/nsCrossSiteListenerProxy.cpp b/content/base/src/nsCrossSiteListenerProxy.cpp index dfc2259fc7f2..ab48e85bc5a7 100644 --- a/content/base/src/nsCrossSiteListenerProxy.cpp +++ b/content/base/src/nsCrossSiteListenerProxy.cpp @@ -63,9 +63,11 @@ NS_IMPL_ISUPPORTS4(nsCrossSiteListenerProxy, nsIStreamListener, nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter, nsIPrincipal* aRequestingPrincipal, nsIChannel* aChannel, + PRBool aWithCredentials, nsresult* aResult) : mOuterListener(aOuter), mRequestingPrincipal(aRequestingPrincipal), + mWithCredentials(aWithCredentials), mRequestApproved(PR_FALSE), mHasBeenCrossSite(PR_FALSE), mIsPreflight(PR_FALSE) @@ -80,11 +82,13 @@ nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter, nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter, nsIPrincipal* aRequestingPrincipal, nsIChannel* aChannel, + PRBool aWithCredentials, const nsCString& aPreflightMethod, const nsTArray& aPreflightHeaders, nsresult* aResult) : mOuterListener(aOuter), mRequestingPrincipal(aRequestingPrincipal), + mWithCredentials(aWithCredentials), mRequestApproved(PR_FALSE), mHasBeenCrossSite(PR_FALSE), mIsPreflight(PR_TRUE), @@ -219,7 +223,7 @@ nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest) NS_LITERAL_CSTRING("Access-Control-Allow-Origin"), allowedOriginHeader); NS_ENSURE_SUCCESS(rv, rv); - if (!allowedOriginHeader.EqualsLiteral("*")) { + if (mWithCredentials || !allowedOriginHeader.EqualsLiteral("*")) { nsCAutoString origin; rv = GetOrigin(mRequestingPrincipal, origin); NS_ENSURE_SUCCESS(rv, rv); @@ -229,6 +233,17 @@ nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest) } } + // Check Access-Control-Allow-Credentials header + if (mWithCredentials) { + nsCAutoString allowCredentialsHeader; + rv = http->GetResponseHeader( + NS_LITERAL_CSTRING("Access-Control-Allow-Credentials"), allowCredentialsHeader); + NS_ENSURE_SUCCESS(rv, rv); + + if (!allowCredentialsHeader.EqualsLiteral("true")) { + return NS_ERROR_DOM_BAD_URI; + } + } if (mIsPreflight) { nsCAutoString headerVal; @@ -391,5 +406,16 @@ nsCrossSiteListenerProxy::UpdateChannel(nsIChannel* aChannel) } } + // Make cookie-less if needed + if (mIsPreflight || !mWithCredentials) { + nsLoadFlags flags; + rv = http->GetLoadFlags(&flags); + NS_ENSURE_SUCCESS(rv, rv); + + flags |= nsIRequest::LOAD_ANONYMOUS; + rv = http->SetLoadFlags(flags); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; } diff --git a/content/base/src/nsCrossSiteListenerProxy.h b/content/base/src/nsCrossSiteListenerProxy.h index 0fd42b943a4f..c889b78527ac 100644 --- a/content/base/src/nsCrossSiteListenerProxy.h +++ b/content/base/src/nsCrossSiteListenerProxy.h @@ -62,10 +62,12 @@ public: nsCrossSiteListenerProxy(nsIStreamListener* aOuter, nsIPrincipal* aRequestingPrincipal, nsIChannel* aChannel, + PRBool aWithCredentials, nsresult* aResult); nsCrossSiteListenerProxy(nsIStreamListener* aOuter, nsIPrincipal* aRequestingPrincipal, nsIChannel* aChannel, + PRBool aWithCredentials, const nsCString& aPreflightMethod, const nsTArray& aPreflightHeaders, nsresult* aResult); @@ -83,6 +85,7 @@ private: nsCOMPtr mOuterListener; nsCOMPtr mRequestingPrincipal; nsCOMPtr mOuterNotificationCallbacks; + PRBool mWithCredentials; PRBool mRequestApproved; PRBool mHasBeenCrossSite; PRBool mIsPreflight; diff --git a/content/base/src/nsSyncLoadService.cpp b/content/base/src/nsSyncLoadService.cpp index 6e85de6a61eb..96f8793a75cb 100644 --- a/content/base/src/nsSyncLoadService.cpp +++ b/content/base/src/nsSyncLoadService.cpp @@ -221,7 +221,7 @@ nsSyncLoader::LoadDocument(nsIChannel* aChannel, if (aLoaderPrincipal) { listener = new nsCrossSiteListenerProxy(listener, aLoaderPrincipal, - mChannel, &rv); + mChannel, PR_FALSE, &rv); NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/content/base/src/nsXMLHttpRequest.cpp b/content/base/src/nsXMLHttpRequest.cpp index a1d4760fc7ab..cbcdffea4949 100644 --- a/content/base/src/nsXMLHttpRequest.cpp +++ b/content/base/src/nsXMLHttpRequest.cpp @@ -127,6 +127,7 @@ #define XML_HTTP_REQUEST_MPART_HEADERS (1 << 15) // Internal #define XML_HTTP_REQUEST_USE_XSITE_AC (1 << 16) // Internal #define XML_HTTP_REQUEST_NEED_AC_PREFLIGHT (1 << 17) // Internal +#define XML_HTTP_REQUEST_AC_WITH_CREDENTIALS (1 << 18) // Internal #define XML_HTTP_REQUEST_LOADSTATES \ (XML_HTTP_REQUEST_UNINITIALIZED | \ @@ -293,10 +294,11 @@ public: nsIStreamListener* aOuterListener, nsISupports* aOuterContext, nsIPrincipal* aReferrerPrincipal, - const nsACString& aRequestMethod) + const nsACString& aRequestMethod, + PRBool aWithCredentials) : mOuterChannel(aOuterChannel), mOuterListener(aOuterListener), mOuterContext(aOuterContext), mReferrerPrincipal(aReferrerPrincipal), - mRequestMethod(aRequestMethod) + mRequestMethod(aRequestMethod), mWithCredentials(aWithCredentials) { } NS_DECL_ISUPPORTS @@ -313,6 +315,7 @@ private: nsCOMPtr mOuterContext; nsCOMPtr mReferrerPrincipal; nsCString mRequestMethod; + PRBool mWithCredentials; }; NS_IMPL_ISUPPORTS4(nsACProxyListener, nsIStreamListener, nsIRequestObserver, @@ -366,7 +369,7 @@ nsACProxyListener::AddResultToCache(nsIRequest *aRequest) nsAccessControlLRUCache::CacheEntry* entry = nsXMLHttpRequest::sAccessControlCache-> - GetEntry(uri, mReferrerPrincipal, PR_TRUE); + GetEntry(uri, mReferrerPrincipal, mWithCredentials, PR_TRUE); if (!entry) { return; } @@ -886,10 +889,11 @@ nsAccessControlLRUCache::CacheEntry::CheckRequest(const nsCString& aMethod, nsAccessControlLRUCache::CacheEntry* nsAccessControlLRUCache::GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal, + PRBool aWithCredentials, PRBool aCreate) { nsCString key; - if (!GetCacheKey(aURI, aPrincipal, key)) { + if (!GetCacheKey(aURI, aPrincipal, aWithCredentials, key)) { NS_WARNING("Invalid cache key!"); return nsnull; } @@ -983,6 +987,7 @@ nsAccessControlLRUCache::RemoveExpiredEntries(const nsACString& aKey, /* static */ PRBool nsAccessControlLRUCache::GetCacheKey(nsIURI* aURI, nsIPrincipal* aPrincipal, + PRBool aWithCredentials, nsACString& _retval) { NS_ASSERTION(aURI, "Null uri!"); @@ -1002,11 +1007,20 @@ nsAccessControlLRUCache::GetCacheKey(nsIURI* aURI, port.AppendInt(portInt); } + nsCAutoString cred; + if (aWithCredentials) { + _retval.AssignLiteral("cred"); + } + else { + _retval.AssignLiteral("nocred"); + } + nsCAutoString spec; rv = aURI->GetSpec(spec); NS_ENSURE_SUCCESS(rv, PR_FALSE); - _retval.Assign(scheme + space + host + space + port + space + spec); + _retval.Assign(cred + space + scheme + space + host + space + port + space + + spec); return PR_TRUE; } @@ -2572,6 +2586,8 @@ nsXMLHttpRequest::Send(nsIVariant *aBody) rv = CheckChannelForCrossSiteRequest(mChannel); NS_ENSURE_SUCCESS(rv, rv); + PRBool withCredentials = !!(mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS); + if (mState & XML_HTTP_REQUEST_USE_XSITE_AC) { // Check if we need to do a preflight request. NS_ENSURE_TRUE(httpChannel, NS_ERROR_DOM_BAD_URI); @@ -2610,7 +2626,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody) nsAccessControlLRUCache::CacheEntry* entry = sAccessControlCache ? - sAccessControlCache->GetEntry(uri, mPrincipal, PR_FALSE) : + sAccessControlCache->GetEntry(uri, mPrincipal, withCredentials, PR_FALSE) : nsnull; if (!entry || !entry->CheckRequest(method, mACUnsafeHeaders)) { @@ -2653,7 +2669,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody) // Always create a nsCrossSiteListenerProxy here even if it's // a same-origin request right now, since it could be redirected. listener = new nsCrossSiteListenerProxy(listener, mPrincipal, mChannel, - &rv); + withCredentials, &rv); NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_SUCCESS(rv, rv); } @@ -2689,12 +2705,14 @@ nsXMLHttpRequest::Send(nsIVariant *aBody) // a GET request to the same URI. Set that up if needed if (mACGetChannel) { nsCOMPtr acProxyListener = - new nsACProxyListener(mChannel, listener, nsnull, mPrincipal, method); + new nsACProxyListener(mChannel, listener, nsnull, mPrincipal, method, + withCredentials); NS_ENSURE_TRUE(acProxyListener, NS_ERROR_OUT_OF_MEMORY); acProxyListener = new nsCrossSiteListenerProxy(acProxyListener, mPrincipal, mACGetChannel, - method, mACUnsafeHeaders, &rv); + withCredentials, method, mACUnsafeHeaders, + &rv); NS_ENSURE_TRUE(acProxyListener, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_SUCCESS(rv, rv); @@ -2924,6 +2942,33 @@ nsXMLHttpRequest::SetMozBackgroundRequest(PRBool aMozBackgroundRequest) return NS_OK; } +/* attribute boolean withCredentials; */ +NS_IMETHODIMP +nsXMLHttpRequest::GetWithCredentials(PRBool *_retval) +{ + *_retval = !!(mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS); + + return NS_OK; +} + +/* attribute boolean withCredentials; */ +NS_IMETHODIMP +nsXMLHttpRequest::SetWithCredentials(PRBool aWithCredentials) +{ + // Return error if we're already processing a request + if (XML_HTTP_REQUEST_SENT & mState) { + return NS_ERROR_FAILURE; + } + + if (aWithCredentials) { + mState |= XML_HTTP_REQUEST_AC_WITH_CREDENTIALS; + } + else { + mState &= ~XML_HTTP_REQUEST_AC_WITH_CREDENTIALS; + } + return NS_OK; +} + // nsIDOMEventListener nsresult diff --git a/content/base/src/nsXMLHttpRequest.h b/content/base/src/nsXMLHttpRequest.h index b5d520ed13aa..03705d04c209 100644 --- a/content/base/src/nsXMLHttpRequest.h +++ b/content/base/src/nsXMLHttpRequest.h @@ -124,7 +124,7 @@ public: } CacheEntry* GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal, - PRBool aCreate); + PRBool aWithCredentials, PRBool aCreate); void Clear(); @@ -134,7 +134,7 @@ private: void* aUserData); static PRBool GetCacheKey(nsIURI* aURI, nsIPrincipal* aPrincipal, - nsACString& _retval); + PRBool aWithCredentials, nsACString& _retval); nsClassHashtable mTable; PRCList mList; diff --git a/content/base/test/file_CrossSiteXHR_inner.html b/content/base/test/file_CrossSiteXHR_inner.html index d1c21e3e5775..18e5bc7b772e 100644 --- a/content/base/test/file_CrossSiteXHR_inner.html +++ b/content/base/test/file_CrossSiteXHR_inner.html @@ -55,6 +55,9 @@ window.addEventListener('message', function(e) { post(e, res); } + if (req.withCred) + xhr.withCredentials = true; + res.events.push("opening"); xhr.open(req.method, req.url, true); diff --git a/content/base/test/file_CrossSiteXHR_server.sjs b/content/base/test/file_CrossSiteXHR_server.sjs index 79efbf91d8de..c4b60fa53a0f 100644 --- a/content/base/test/file_CrossSiteXHR_server.sjs +++ b/content/base/test/file_CrossSiteXHR_server.sjs @@ -3,7 +3,7 @@ function handleRequest(request, response) try { var query = {}; request.queryString.split('&').forEach(function (val) { - var [name, value] = val.split('='); + [name, value] = val.split('='); query[name] = unescape(value); }); @@ -35,6 +35,24 @@ function handleRequest(request, response) throw "Origin had wrong value. Expected " + query.origin + " got " + request.getHeader("Origin"); } + if ("cookie" in query) { + cookies = {}; + request.getHeader("Cookie").split(/ *; */).forEach(function (val) { + [name, value] = val.split('='); + cookies[name] = unescape(value); + }); + + query.cookie.split(",").forEach(function (val) { + [name, value] = val.split('='); + if (cookies[name] != value) { + throw "Cookie " + name + " had wrong value. Expected " + value + + " got " + cookies[name]; + } + }); + } + if ("noCookie" in query && request.hasHeader("Cookie")) { + throw "Got cookies when didn't expect to"; + } // Send response @@ -42,6 +60,12 @@ function handleRequest(request, response) if (query.allowOrigin && (!isPreflight || !query.noAllowPreflight)) response.setHeader("Access-Control-Allow-Origin", query.allowOrigin); + if (query.allowCred) + response.setHeader("Access-Control-Allow-Credentials", "true"); + + if (query.setCookie) + response.setHeader("Set-Cookie", query.setCookie + "; path=/"); + if (isPreflight) { if (query.allowHeaders) diff --git a/content/base/test/test_CrossSiteXHR.html b/content/base/test/test_CrossSiteXHR.html index 51b6d21e2235..1f830be3d13e 100644 --- a/content/base/test/test_CrossSiteXHR.html +++ b/content/base/test/test_CrossSiteXHR.html @@ -436,6 +436,133 @@ function runTest() { } + // Test cookie behavior + tests = [{ pass: 1, + method: "GET", + withCred: 1, + allowCred: 1, + }, + { pass: 0, + method: "GET", + withCred: 1, + allowCred: 0, + }, + { pass: 0, + method: "GET", + withCred: 1, + allowCred: 1, + origin: "*", + }, + { pass: 1, + method: "GET", + withCred: 0, + allowCred: 1, + origin: "*", + }, + { pass: 1, + method: "GET", + setCookie: "a=1", + withCred: 1, + allowCred: 1, + }, + { pass: 1, + method: "GET", + cookie: "a=1", + withCred: 1, + allowCred: 1, + }, + { pass: 1, + method: "GET", + noCookie: 1, + withCred: 0, + allowCred: 1, + }, + { pass: 0, + method: "GET", + noCookie: 1, + withCred: 1, + allowCred: 1, + }, + { pass: 1, + method: "GET", + setCookie: "a=2", + withCred: 0, + allowCred: 1, + }, + { pass: 1, + method: "GET", + cookie: "a=1", + withCred: 1, + allowCred: 1, + }, + { pass: 1, + method: "GET", + setCookie: "a=2", + withCred: 1, + allowCred: 1, + }, + { pass: 1, + method: "GET", + cookie: "a=2", + withCred: 1, + allowCred: 1, + }, + ]; + + for each(test in tests) { + req = { + url: baseURL + "allowOrigin=" + escape(test.origin || origin), + method: test.method, + headers: test.headers, + withCred: test.withCred, + }; + + if (test.allowCred) + req.url += "&allowCred"; + + if (test.setCookie) + req.url += "&setCookie=" + escape(test.setCookie); + if (test.cookie) + req.url += "&cookie=" + escape(test.cookie); + if (test.noCookie) + req.url += "&noCookie"; + + if ("allowHeaders" in test) + req.url += "&allowHeaders=" + escape(test.allowHeaders); + if ("allowMethods" in test) + req.url += "&allowMethods=" + escape(test.allowMethods); + + loaderWindow.postMessage(req.toSource(), origin); + + res = eval(yield); + if (test.pass) { + is(res.didFail, false, + "shouldn't have failed in test for " + test.toSource()); + is(res.status, 200, "wrong status in test for " + test.toSource()); + is(res.responseXML, "hello pass", + "wrong responseXML in test for " + test.toSource()); + is(res.responseText, "hello pass\n", + "wrong responseText in test for " + test.toSource()); + is(res.events.join(","), + "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load", + "wrong responseText in test for " + test.toSource()); + } + else { + is(res.didFail, true, + "should have failed in test for " + test.toSource()); + is(res.status, 0, "wrong status in test for " + test.toSource()); + is(res.responseXML, null, + "wrong responseXML in test for " + test.toSource()); + is(res.responseText, "", + "wrong responseText in test for " + test.toSource()); + is(res.events.join(","), + "opening,rs1,sending,rs1,loadstart,rs2,rs4,error", + "wrong events in test for " + test.toSource()); + is(res.progressEvents, 0, + "wrong events in test for " + test.toSource()); + } + } + SimpleTest.finish(); yield; diff --git a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp index adffb4a286c5..dcc4d29cd442 100644 --- a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp +++ b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp @@ -539,7 +539,8 @@ txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler, // Always install in case of redirects nsCOMPtr listener = - new nsCrossSiteListenerProxy(sink, aReferrerPrincipal, channel, &rv); + new nsCrossSiteListenerProxy(sink, aReferrerPrincipal, channel, + PR_FALSE, &rv); NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_SUCCESS(rv, rv); diff --git a/netwerk/base/public/nsIRequest.idl b/netwerk/base/public/nsIRequest.idl index 12e00bd9c3f8..4586abb8bb88 100644 --- a/netwerk/base/public/nsIRequest.idl +++ b/netwerk/base/public/nsIRequest.idl @@ -214,4 +214,11 @@ interface nsIRequest : nsISupports const unsigned long VALIDATE_ALWAYS = 1 << 11; const unsigned long VALIDATE_NEVER = 1 << 12; const unsigned long VALIDATE_ONCE_PER_SESSION = 1 << 13; + + /** + * When set, this flag indicates that no user-specific data should be added + * to the request when opened. This means that things like authorization + * tokens or cookie headers should not be added. + */ + const unsigned long LOAD_ANONYMOUS = 1 << 14; }; diff --git a/netwerk/protocol/http/src/nsHttpChannel.cpp b/netwerk/protocol/http/src/nsHttpChannel.cpp index 503447529548..4c261ecd7b5e 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -663,6 +663,10 @@ nsHttpChannel::SetupTransaction() void nsHttpChannel::AddCookiesToRequest() { + if (mLoadFlags & LOAD_ANONYMOUS) { + return; + } + nsXPIDLCString cookie; nsICookieService *cs = gHttpHandler->GetCookieService(); @@ -1746,13 +1750,22 @@ nsHttpChannel::OpenOfflineCacheEntryForWriting() nsresult nsHttpChannel::GenerateCacheKey(nsACString &cacheKey) { + cacheKey.Truncate(); + + if (mLoadFlags & LOAD_ANONYMOUS) { + cacheKey.AssignLiteral("anon&"); + } + if (mPostID) { char buf[32]; - PR_snprintf(buf, sizeof(buf), "id=%x&uri=", mPostID); - cacheKey.Assign(buf); - } else - cacheKey.Truncate(); - + PR_snprintf(buf, sizeof(buf), "id=%x&", mPostID); + cacheKey.Append(buf); + } + + if (!cacheKey.IsEmpty()) { + cacheKey.AppendLiteral("uri="); + } + // Strip any trailing #ref from the URL before using it as the key const char *spec = mFallbackChannel ? mFallbackKey.get() : mSpec.get(); const char *p = strchr(spec, '#'); @@ -2888,6 +2901,10 @@ nsHttpChannel::ProcessAuthentication(PRUint32 httpStatus) LOG(("nsHttpChannel::ProcessAuthentication [this=%x code=%u]\n", this, httpStatus)); + if (mLoadFlags & LOAD_ANONYMOUS) { + return NS_ERROR_NOT_AVAILABLE; + } + const char *challenges; PRBool proxyAuth = (httpStatus == 407); @@ -3608,6 +3625,10 @@ nsHttpChannel::AddAuthorizationHeaders() { LOG(("nsHttpChannel::AddAuthorizationHeaders? [this=%x]\n", this)); + if (mLoadFlags & LOAD_ANONYMOUS) { + return; + } + // this getter never fails nsHttpAuthCache *authCache = gHttpHandler->AuthCache(); @@ -4500,6 +4521,10 @@ nsHttpChannel::GetResponseVersion(PRUint32 *major, PRUint32 *minor) NS_IMETHODIMP nsHttpChannel::SetCookie(const char *aCookieHeader) { + if (mLoadFlags & LOAD_ANONYMOUS) { + return NS_OK; + } + // empty header isn't an error if (!(aCookieHeader && *aCookieHeader)) return NS_OK;