Bug 702820 - Allow XHR to data URL. r=sicking

This commit is contained in:
Masatoshi Kimura 2012-01-11 10:47:46 +01:00
Родитель e2e7224870
Коммит 16de863cf7
4 изменённых файлов: 61 добавлений и 9 удалений

Просмотреть файл

@ -409,6 +409,30 @@ nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
}
}
nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
nsIPrincipal* aRequestingPrincipal,
nsIChannel* aChannel,
bool aWithCredentials,
bool aAllowDataURI,
nsresult* aResult)
: mOuterListener(aOuter),
mRequestingPrincipal(aRequestingPrincipal),
mWithCredentials(aWithCredentials && !gDisableCORSPrivateData),
mRequestApproved(false),
mHasBeenCrossSite(false),
mIsPreflight(false)
{
aChannel->GetNotificationCallbacks(getter_AddRefs(mOuterNotificationCallbacks));
aChannel->SetNotificationCallbacks(this);
*aResult = UpdateChannel(aChannel, aAllowDataURI);
if (NS_FAILED(*aResult)) {
mOuterListener = nsnull;
mRequestingPrincipal = nsnull;
mOuterNotificationCallbacks = nsnull;
}
}
nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
nsIPrincipal* aRequestingPrincipal,
nsIChannel* aChannel,
@ -723,13 +747,23 @@ nsCORSListenerProxy::OnRedirectVerifyCallback(nsresult result)
}
nsresult
nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel)
nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel, bool aAllowDataURI)
{
nsCOMPtr<nsIURI> uri, originalURI;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
rv = aChannel->GetOriginalURI(getter_AddRefs(originalURI));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_SUCCESS(rv, rv);
// exempt data URIs from the same origin check.
if (aAllowDataURI && originalURI == uri) {
bool dataScheme = false;
rv = uri->SchemeIs("data", &dataScheme);
NS_ENSURE_SUCCESS(rv, rv);
if (dataScheme) {
return NS_OK;
}
}
// Check that the uri is ok to load
rv = nsContentUtils::GetSecurityManager()->

Просмотреть файл

@ -74,6 +74,12 @@ public:
nsIChannel* aChannel,
bool aWithCredentials,
nsresult* aResult);
nsCORSListenerProxy(nsIStreamListener* aOuter,
nsIPrincipal* aRequestingPrincipal,
nsIChannel* aChannel,
bool aWithCredentials,
bool aAllowDataURI,
nsresult* aResult);
nsCORSListenerProxy(nsIStreamListener* aOuter,
nsIPrincipal* aRequestingPrincipal,
nsIChannel* aChannel,
@ -95,7 +101,7 @@ public:
static void Shutdown();
private:
nsresult UpdateChannel(nsIChannel* aChannel);
nsresult UpdateChannel(nsIChannel* aChannel, bool aAllowDataURI = false);
nsresult CheckRequestApproved(nsIRequest* aRequest);
nsCOMPtr<nsIStreamListener> mOuterListener;

Просмотреть файл

@ -1459,13 +1459,23 @@ nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
return NS_OK;
}
// exempt data URIs from the same origin check.
nsCOMPtr<nsIURI> channelURI;
bool dataScheme = false;
if (NS_SUCCEEDED(NS_GetFinalChannelURI(aChannel,
getter_AddRefs(channelURI))) &&
NS_SUCCEEDED(channelURI->SchemeIs("data", &dataScheme)) &&
dataScheme) {
return NS_OK;
}
// This is a cross-site request
mState |= XML_HTTP_REQUEST_USE_XSITE_AC;
// Check if we need to do a preflight request.
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
NS_ENSURE_TRUE(httpChannel, NS_ERROR_DOM_BAD_URI);
nsCAutoString method;
httpChannel->GetRequestMethod(method);
if (!mCORSUnsafeHeaders.IsEmpty() ||
@ -2587,7 +2597,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
// Always create a nsCORSListenerProxy here even if it's
// a same-origin request right now, since it could be redirected.
listener = new nsCORSListenerProxy(listener, mPrincipal, mChannel,
withCredentials, &rv);
withCredentials, true, &rv);
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_SUCCESS(rv, rv);
}

Просмотреть файл

@ -21,9 +21,11 @@ function runTests() {
var path = "/tests/content/base/test/";
var passFiles = [['file_XHR_pass1.xml', 'GET'],
['file_XHR_pass2.txt', 'GET'],
['file_XHR_pass3.txt', 'GET'],
var passFiles = [['file_XHR_pass1.xml', 'GET', 200],
['file_XHR_pass2.txt', 'GET', 200],
['file_XHR_pass3.txt', 'GET', 200],
['data:text/xml,%3Cres%3Ehello%3C/res%3E%0A', 'GET', 0],
['data:text/plain,hello%20pass%0A', 'GET', 0],
];
var failFiles = [['//example.com' + path + 'file_XHR_pass1.xml', 'GET'],
@ -36,7 +38,7 @@ for (i = 0; i < passFiles.length; ++i) {
is(xhr.responseType, "", "wrong initial responseType");
xhr.open(passFiles[i][1], passFiles[i][0], false);
xhr.send(null);
is(xhr.status, 200, "wrong status");
is(xhr.status, passFiles[i][2], "wrong status");
if (xhr.responseXML) {
is((new XMLSerializer()).serializeToString(xhr.responseXML.documentElement),
"<res>hello</res>",