mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Implement cookieless requests for Access-Control. b=389508 r=biesi sr=jst
This commit is contained in:
parent
7a655650a9
commit
cce6fbac9b
@ -101,7 +101,7 @@ interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget {
|
|||||||
* you're aware of all the security implications. And then think twice about
|
* you're aware of all the security implications. And then think twice about
|
||||||
* it.
|
* it.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(acda85ab-d06c-4176-b834-6d129ca97ca3)]
|
[scriptable, uuid(48ce10a0-c585-4e8f-a5f5-1ac1e47cc501)]
|
||||||
interface nsIXMLHttpRequest : nsISupports
|
interface nsIXMLHttpRequest : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -321,6 +321,16 @@ interface nsIXMLHttpRequest : nsISupports
|
|||||||
*/
|
*/
|
||||||
attribute boolean mozBackgroundRequest;
|
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
|
* Initialize the object for use from C++ code with the principal, script
|
||||||
* context, and owner window that should be used.
|
* context, and owner window that should be used.
|
||||||
|
@ -63,9 +63,11 @@ NS_IMPL_ISUPPORTS4(nsCrossSiteListenerProxy, nsIStreamListener,
|
|||||||
nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
||||||
nsIPrincipal* aRequestingPrincipal,
|
nsIPrincipal* aRequestingPrincipal,
|
||||||
nsIChannel* aChannel,
|
nsIChannel* aChannel,
|
||||||
|
PRBool aWithCredentials,
|
||||||
nsresult* aResult)
|
nsresult* aResult)
|
||||||
: mOuterListener(aOuter),
|
: mOuterListener(aOuter),
|
||||||
mRequestingPrincipal(aRequestingPrincipal),
|
mRequestingPrincipal(aRequestingPrincipal),
|
||||||
|
mWithCredentials(aWithCredentials),
|
||||||
mRequestApproved(PR_FALSE),
|
mRequestApproved(PR_FALSE),
|
||||||
mHasBeenCrossSite(PR_FALSE),
|
mHasBeenCrossSite(PR_FALSE),
|
||||||
mIsPreflight(PR_FALSE)
|
mIsPreflight(PR_FALSE)
|
||||||
@ -80,11 +82,13 @@ nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
|||||||
nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
||||||
nsIPrincipal* aRequestingPrincipal,
|
nsIPrincipal* aRequestingPrincipal,
|
||||||
nsIChannel* aChannel,
|
nsIChannel* aChannel,
|
||||||
|
PRBool aWithCredentials,
|
||||||
const nsCString& aPreflightMethod,
|
const nsCString& aPreflightMethod,
|
||||||
const nsTArray<nsCString>& aPreflightHeaders,
|
const nsTArray<nsCString>& aPreflightHeaders,
|
||||||
nsresult* aResult)
|
nsresult* aResult)
|
||||||
: mOuterListener(aOuter),
|
: mOuterListener(aOuter),
|
||||||
mRequestingPrincipal(aRequestingPrincipal),
|
mRequestingPrincipal(aRequestingPrincipal),
|
||||||
|
mWithCredentials(aWithCredentials),
|
||||||
mRequestApproved(PR_FALSE),
|
mRequestApproved(PR_FALSE),
|
||||||
mHasBeenCrossSite(PR_FALSE),
|
mHasBeenCrossSite(PR_FALSE),
|
||||||
mIsPreflight(PR_TRUE),
|
mIsPreflight(PR_TRUE),
|
||||||
@ -219,7 +223,7 @@ nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
|
|||||||
NS_LITERAL_CSTRING("Access-Control-Allow-Origin"), allowedOriginHeader);
|
NS_LITERAL_CSTRING("Access-Control-Allow-Origin"), allowedOriginHeader);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (!allowedOriginHeader.EqualsLiteral("*")) {
|
if (mWithCredentials || !allowedOriginHeader.EqualsLiteral("*")) {
|
||||||
nsCAutoString origin;
|
nsCAutoString origin;
|
||||||
rv = GetOrigin(mRequestingPrincipal, origin);
|
rv = GetOrigin(mRequestingPrincipal, origin);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
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) {
|
if (mIsPreflight) {
|
||||||
nsCAutoString headerVal;
|
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;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -62,10 +62,12 @@ public:
|
|||||||
nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
||||||
nsIPrincipal* aRequestingPrincipal,
|
nsIPrincipal* aRequestingPrincipal,
|
||||||
nsIChannel* aChannel,
|
nsIChannel* aChannel,
|
||||||
|
PRBool aWithCredentials,
|
||||||
nsresult* aResult);
|
nsresult* aResult);
|
||||||
nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
||||||
nsIPrincipal* aRequestingPrincipal,
|
nsIPrincipal* aRequestingPrincipal,
|
||||||
nsIChannel* aChannel,
|
nsIChannel* aChannel,
|
||||||
|
PRBool aWithCredentials,
|
||||||
const nsCString& aPreflightMethod,
|
const nsCString& aPreflightMethod,
|
||||||
const nsTArray<nsCString>& aPreflightHeaders,
|
const nsTArray<nsCString>& aPreflightHeaders,
|
||||||
nsresult* aResult);
|
nsresult* aResult);
|
||||||
@ -83,6 +85,7 @@ private:
|
|||||||
nsCOMPtr<nsIStreamListener> mOuterListener;
|
nsCOMPtr<nsIStreamListener> mOuterListener;
|
||||||
nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
|
nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
|
||||||
nsCOMPtr<nsIInterfaceRequestor> mOuterNotificationCallbacks;
|
nsCOMPtr<nsIInterfaceRequestor> mOuterNotificationCallbacks;
|
||||||
|
PRBool mWithCredentials;
|
||||||
PRBool mRequestApproved;
|
PRBool mRequestApproved;
|
||||||
PRBool mHasBeenCrossSite;
|
PRBool mHasBeenCrossSite;
|
||||||
PRBool mIsPreflight;
|
PRBool mIsPreflight;
|
||||||
|
@ -221,7 +221,7 @@ nsSyncLoader::LoadDocument(nsIChannel* aChannel,
|
|||||||
|
|
||||||
if (aLoaderPrincipal) {
|
if (aLoaderPrincipal) {
|
||||||
listener = new nsCrossSiteListenerProxy(listener, aLoaderPrincipal,
|
listener = new nsCrossSiteListenerProxy(listener, aLoaderPrincipal,
|
||||||
mChannel, &rv);
|
mChannel, PR_FALSE, &rv);
|
||||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,7 @@
|
|||||||
#define XML_HTTP_REQUEST_MPART_HEADERS (1 << 15) // Internal
|
#define XML_HTTP_REQUEST_MPART_HEADERS (1 << 15) // Internal
|
||||||
#define XML_HTTP_REQUEST_USE_XSITE_AC (1 << 16) // 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_NEED_AC_PREFLIGHT (1 << 17) // Internal
|
||||||
|
#define XML_HTTP_REQUEST_AC_WITH_CREDENTIALS (1 << 18) // Internal
|
||||||
|
|
||||||
#define XML_HTTP_REQUEST_LOADSTATES \
|
#define XML_HTTP_REQUEST_LOADSTATES \
|
||||||
(XML_HTTP_REQUEST_UNINITIALIZED | \
|
(XML_HTTP_REQUEST_UNINITIALIZED | \
|
||||||
@ -293,10 +294,11 @@ public:
|
|||||||
nsIStreamListener* aOuterListener,
|
nsIStreamListener* aOuterListener,
|
||||||
nsISupports* aOuterContext,
|
nsISupports* aOuterContext,
|
||||||
nsIPrincipal* aReferrerPrincipal,
|
nsIPrincipal* aReferrerPrincipal,
|
||||||
const nsACString& aRequestMethod)
|
const nsACString& aRequestMethod,
|
||||||
|
PRBool aWithCredentials)
|
||||||
: mOuterChannel(aOuterChannel), mOuterListener(aOuterListener),
|
: mOuterChannel(aOuterChannel), mOuterListener(aOuterListener),
|
||||||
mOuterContext(aOuterContext), mReferrerPrincipal(aReferrerPrincipal),
|
mOuterContext(aOuterContext), mReferrerPrincipal(aReferrerPrincipal),
|
||||||
mRequestMethod(aRequestMethod)
|
mRequestMethod(aRequestMethod), mWithCredentials(aWithCredentials)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
@ -313,6 +315,7 @@ private:
|
|||||||
nsCOMPtr<nsISupports> mOuterContext;
|
nsCOMPtr<nsISupports> mOuterContext;
|
||||||
nsCOMPtr<nsIPrincipal> mReferrerPrincipal;
|
nsCOMPtr<nsIPrincipal> mReferrerPrincipal;
|
||||||
nsCString mRequestMethod;
|
nsCString mRequestMethod;
|
||||||
|
PRBool mWithCredentials;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS4(nsACProxyListener, nsIStreamListener, nsIRequestObserver,
|
NS_IMPL_ISUPPORTS4(nsACProxyListener, nsIStreamListener, nsIRequestObserver,
|
||||||
@ -366,7 +369,7 @@ nsACProxyListener::AddResultToCache(nsIRequest *aRequest)
|
|||||||
|
|
||||||
nsAccessControlLRUCache::CacheEntry* entry =
|
nsAccessControlLRUCache::CacheEntry* entry =
|
||||||
nsXMLHttpRequest::sAccessControlCache->
|
nsXMLHttpRequest::sAccessControlCache->
|
||||||
GetEntry(uri, mReferrerPrincipal, PR_TRUE);
|
GetEntry(uri, mReferrerPrincipal, mWithCredentials, PR_TRUE);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -886,10 +889,11 @@ nsAccessControlLRUCache::CacheEntry::CheckRequest(const nsCString& aMethod,
|
|||||||
nsAccessControlLRUCache::CacheEntry*
|
nsAccessControlLRUCache::CacheEntry*
|
||||||
nsAccessControlLRUCache::GetEntry(nsIURI* aURI,
|
nsAccessControlLRUCache::GetEntry(nsIURI* aURI,
|
||||||
nsIPrincipal* aPrincipal,
|
nsIPrincipal* aPrincipal,
|
||||||
|
PRBool aWithCredentials,
|
||||||
PRBool aCreate)
|
PRBool aCreate)
|
||||||
{
|
{
|
||||||
nsCString key;
|
nsCString key;
|
||||||
if (!GetCacheKey(aURI, aPrincipal, key)) {
|
if (!GetCacheKey(aURI, aPrincipal, aWithCredentials, key)) {
|
||||||
NS_WARNING("Invalid cache key!");
|
NS_WARNING("Invalid cache key!");
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
@ -983,6 +987,7 @@ nsAccessControlLRUCache::RemoveExpiredEntries(const nsACString& aKey,
|
|||||||
/* static */ PRBool
|
/* static */ PRBool
|
||||||
nsAccessControlLRUCache::GetCacheKey(nsIURI* aURI,
|
nsAccessControlLRUCache::GetCacheKey(nsIURI* aURI,
|
||||||
nsIPrincipal* aPrincipal,
|
nsIPrincipal* aPrincipal,
|
||||||
|
PRBool aWithCredentials,
|
||||||
nsACString& _retval)
|
nsACString& _retval)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aURI, "Null uri!");
|
NS_ASSERTION(aURI, "Null uri!");
|
||||||
@ -1002,11 +1007,20 @@ nsAccessControlLRUCache::GetCacheKey(nsIURI* aURI,
|
|||||||
port.AppendInt(portInt);
|
port.AppendInt(portInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsCAutoString cred;
|
||||||
|
if (aWithCredentials) {
|
||||||
|
_retval.AssignLiteral("cred");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_retval.AssignLiteral("nocred");
|
||||||
|
}
|
||||||
|
|
||||||
nsCAutoString spec;
|
nsCAutoString spec;
|
||||||
rv = aURI->GetSpec(spec);
|
rv = aURI->GetSpec(spec);
|
||||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
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;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
@ -2572,6 +2586,8 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||||||
rv = CheckChannelForCrossSiteRequest(mChannel);
|
rv = CheckChannelForCrossSiteRequest(mChannel);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
PRBool withCredentials = !!(mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS);
|
||||||
|
|
||||||
if (mState & XML_HTTP_REQUEST_USE_XSITE_AC) {
|
if (mState & XML_HTTP_REQUEST_USE_XSITE_AC) {
|
||||||
// Check if we need to do a preflight request.
|
// Check if we need to do a preflight request.
|
||||||
NS_ENSURE_TRUE(httpChannel, NS_ERROR_DOM_BAD_URI);
|
NS_ENSURE_TRUE(httpChannel, NS_ERROR_DOM_BAD_URI);
|
||||||
@ -2610,7 +2626,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||||||
|
|
||||||
nsAccessControlLRUCache::CacheEntry* entry =
|
nsAccessControlLRUCache::CacheEntry* entry =
|
||||||
sAccessControlCache ?
|
sAccessControlCache ?
|
||||||
sAccessControlCache->GetEntry(uri, mPrincipal, PR_FALSE) :
|
sAccessControlCache->GetEntry(uri, mPrincipal, withCredentials, PR_FALSE) :
|
||||||
nsnull;
|
nsnull;
|
||||||
|
|
||||||
if (!entry || !entry->CheckRequest(method, mACUnsafeHeaders)) {
|
if (!entry || !entry->CheckRequest(method, mACUnsafeHeaders)) {
|
||||||
@ -2653,7 +2669,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||||||
// Always create a nsCrossSiteListenerProxy here even if it's
|
// Always create a nsCrossSiteListenerProxy here even if it's
|
||||||
// a same-origin request right now, since it could be redirected.
|
// a same-origin request right now, since it could be redirected.
|
||||||
listener = new nsCrossSiteListenerProxy(listener, mPrincipal, mChannel,
|
listener = new nsCrossSiteListenerProxy(listener, mPrincipal, mChannel,
|
||||||
&rv);
|
withCredentials, &rv);
|
||||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
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
|
// a GET request to the same URI. Set that up if needed
|
||||||
if (mACGetChannel) {
|
if (mACGetChannel) {
|
||||||
nsCOMPtr<nsIStreamListener> acProxyListener =
|
nsCOMPtr<nsIStreamListener> 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);
|
NS_ENSURE_TRUE(acProxyListener, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
acProxyListener =
|
acProxyListener =
|
||||||
new nsCrossSiteListenerProxy(acProxyListener, mPrincipal, mACGetChannel,
|
new nsCrossSiteListenerProxy(acProxyListener, mPrincipal, mACGetChannel,
|
||||||
method, mACUnsafeHeaders, &rv);
|
withCredentials, method, mACUnsafeHeaders,
|
||||||
|
&rv);
|
||||||
NS_ENSURE_TRUE(acProxyListener, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(acProxyListener, NS_ERROR_OUT_OF_MEMORY);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
@ -2924,6 +2942,33 @@ nsXMLHttpRequest::SetMozBackgroundRequest(PRBool aMozBackgroundRequest)
|
|||||||
return NS_OK;
|
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
|
// nsIDOMEventListener
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -124,7 +124,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
CacheEntry* GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
CacheEntry* GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
||||||
PRBool aCreate);
|
PRBool aWithCredentials, PRBool aCreate);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ private:
|
|||||||
void* aUserData);
|
void* aUserData);
|
||||||
|
|
||||||
static PRBool GetCacheKey(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
static PRBool GetCacheKey(nsIURI* aURI, nsIPrincipal* aPrincipal,
|
||||||
nsACString& _retval);
|
PRBool aWithCredentials, nsACString& _retval);
|
||||||
|
|
||||||
nsClassHashtable<nsCStringHashKey, CacheEntry> mTable;
|
nsClassHashtable<nsCStringHashKey, CacheEntry> mTable;
|
||||||
PRCList mList;
|
PRCList mList;
|
||||||
|
@ -55,6 +55,9 @@ window.addEventListener('message', function(e) {
|
|||||||
post(e, res);
|
post(e, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req.withCred)
|
||||||
|
xhr.withCredentials = true;
|
||||||
|
|
||||||
res.events.push("opening");
|
res.events.push("opening");
|
||||||
xhr.open(req.method, req.url, true);
|
xhr.open(req.method, req.url, true);
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ function handleRequest(request, response)
|
|||||||
try {
|
try {
|
||||||
var query = {};
|
var query = {};
|
||||||
request.queryString.split('&').forEach(function (val) {
|
request.queryString.split('&').forEach(function (val) {
|
||||||
var [name, value] = val.split('=');
|
[name, value] = val.split('=');
|
||||||
query[name] = unescape(value);
|
query[name] = unescape(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -35,6 +35,24 @@ function handleRequest(request, response)
|
|||||||
throw "Origin had wrong value. Expected " + query.origin + " got " +
|
throw "Origin had wrong value. Expected " + query.origin + " got " +
|
||||||
request.getHeader("Origin");
|
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
|
// Send response
|
||||||
@ -42,6 +60,12 @@ function handleRequest(request, response)
|
|||||||
if (query.allowOrigin && (!isPreflight || !query.noAllowPreflight))
|
if (query.allowOrigin && (!isPreflight || !query.noAllowPreflight))
|
||||||
response.setHeader("Access-Control-Allow-Origin", query.allowOrigin);
|
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 (isPreflight) {
|
||||||
if (query.allowHeaders)
|
if (query.allowHeaders)
|
||||||
|
@ -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, "<res>hello pass</res>",
|
||||||
|
"wrong responseXML in test for " + test.toSource());
|
||||||
|
is(res.responseText, "<res>hello pass</res>\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();
|
SimpleTest.finish();
|
||||||
|
|
||||||
yield;
|
yield;
|
||||||
|
@ -539,7 +539,8 @@ txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler,
|
|||||||
|
|
||||||
// Always install in case of redirects
|
// Always install in case of redirects
|
||||||
nsCOMPtr<nsIStreamListener> listener =
|
nsCOMPtr<nsIStreamListener> 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_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
@ -214,4 +214,11 @@ interface nsIRequest : nsISupports
|
|||||||
const unsigned long VALIDATE_ALWAYS = 1 << 11;
|
const unsigned long VALIDATE_ALWAYS = 1 << 11;
|
||||||
const unsigned long VALIDATE_NEVER = 1 << 12;
|
const unsigned long VALIDATE_NEVER = 1 << 12;
|
||||||
const unsigned long VALIDATE_ONCE_PER_SESSION = 1 << 13;
|
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;
|
||||||
};
|
};
|
||||||
|
@ -663,6 +663,10 @@ nsHttpChannel::SetupTransaction()
|
|||||||
void
|
void
|
||||||
nsHttpChannel::AddCookiesToRequest()
|
nsHttpChannel::AddCookiesToRequest()
|
||||||
{
|
{
|
||||||
|
if (mLoadFlags & LOAD_ANONYMOUS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nsXPIDLCString cookie;
|
nsXPIDLCString cookie;
|
||||||
|
|
||||||
nsICookieService *cs = gHttpHandler->GetCookieService();
|
nsICookieService *cs = gHttpHandler->GetCookieService();
|
||||||
@ -1746,13 +1750,22 @@ nsHttpChannel::OpenOfflineCacheEntryForWriting()
|
|||||||
nsresult
|
nsresult
|
||||||
nsHttpChannel::GenerateCacheKey(nsACString &cacheKey)
|
nsHttpChannel::GenerateCacheKey(nsACString &cacheKey)
|
||||||
{
|
{
|
||||||
|
cacheKey.Truncate();
|
||||||
|
|
||||||
|
if (mLoadFlags & LOAD_ANONYMOUS) {
|
||||||
|
cacheKey.AssignLiteral("anon&");
|
||||||
|
}
|
||||||
|
|
||||||
if (mPostID) {
|
if (mPostID) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
PR_snprintf(buf, sizeof(buf), "id=%x&uri=", mPostID);
|
PR_snprintf(buf, sizeof(buf), "id=%x&", mPostID);
|
||||||
cacheKey.Assign(buf);
|
cacheKey.Append(buf);
|
||||||
} else
|
}
|
||||||
cacheKey.Truncate();
|
|
||||||
|
if (!cacheKey.IsEmpty()) {
|
||||||
|
cacheKey.AppendLiteral("uri=");
|
||||||
|
}
|
||||||
|
|
||||||
// Strip any trailing #ref from the URL before using it as the key
|
// Strip any trailing #ref from the URL before using it as the key
|
||||||
const char *spec = mFallbackChannel ? mFallbackKey.get() : mSpec.get();
|
const char *spec = mFallbackChannel ? mFallbackKey.get() : mSpec.get();
|
||||||
const char *p = strchr(spec, '#');
|
const char *p = strchr(spec, '#');
|
||||||
@ -2888,6 +2901,10 @@ nsHttpChannel::ProcessAuthentication(PRUint32 httpStatus)
|
|||||||
LOG(("nsHttpChannel::ProcessAuthentication [this=%x code=%u]\n",
|
LOG(("nsHttpChannel::ProcessAuthentication [this=%x code=%u]\n",
|
||||||
this, httpStatus));
|
this, httpStatus));
|
||||||
|
|
||||||
|
if (mLoadFlags & LOAD_ANONYMOUS) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
const char *challenges;
|
const char *challenges;
|
||||||
PRBool proxyAuth = (httpStatus == 407);
|
PRBool proxyAuth = (httpStatus == 407);
|
||||||
|
|
||||||
@ -3608,6 +3625,10 @@ nsHttpChannel::AddAuthorizationHeaders()
|
|||||||
{
|
{
|
||||||
LOG(("nsHttpChannel::AddAuthorizationHeaders? [this=%x]\n", this));
|
LOG(("nsHttpChannel::AddAuthorizationHeaders? [this=%x]\n", this));
|
||||||
|
|
||||||
|
if (mLoadFlags & LOAD_ANONYMOUS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// this getter never fails
|
// this getter never fails
|
||||||
nsHttpAuthCache *authCache = gHttpHandler->AuthCache();
|
nsHttpAuthCache *authCache = gHttpHandler->AuthCache();
|
||||||
|
|
||||||
@ -4500,6 +4521,10 @@ nsHttpChannel::GetResponseVersion(PRUint32 *major, PRUint32 *minor)
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsHttpChannel::SetCookie(const char *aCookieHeader)
|
nsHttpChannel::SetCookie(const char *aCookieHeader)
|
||||||
{
|
{
|
||||||
|
if (mLoadFlags & LOAD_ANONYMOUS) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// empty header isn't an error
|
// empty header isn't an error
|
||||||
if (!(aCookieHeader && *aCookieHeader))
|
if (!(aCookieHeader && *aCookieHeader))
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
Loading…
Reference in New Issue
Block a user