CORS: A "data:" URL = the same-origin

This commit is contained in:
janekptacijarabaci
2017-01-30 10:12:35 +01:00
committed by roytam1
parent 56c725cca9
commit 7cf33c4329
21 changed files with 115 additions and 21 deletions
+1 -1
View File
@@ -796,7 +796,7 @@ EventSource::InitChannelAndRequestEventSource()
nsRefPtr<nsCORSListenerProxy> listener =
new nsCORSListenerProxy(this, mPrincipal, mWithCredentials);
rv = listener->Init(mHttpChannel);
rv = listener->Init(mHttpChannel, DataURIHandling::Allow);
NS_ENSURE_SUCCESS(rv, rv);
// Start reading from the channel
+1 -1
View File
@@ -504,7 +504,7 @@ ImportLoader::Open()
nsRefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(this, principal,
/* aWithCredentials */ false);
rv = corsListener->Init(channel, true);
rv = corsListener->Init(channel, DataURIHandling::Allow);
NS_ENSURE_SUCCESS_VOID(rv);
rv = channel->AsyncOpen(corsListener, nullptr);
+1 -1
View File
@@ -1201,7 +1201,7 @@ Navigator::SendBeacon(const nsAString& aUrl,
principal,
true);
rv = cors->Init(channel, true);
rv = cors->Init(channel, DataURIHandling::Allow);
NS_ENSURE_SUCCESS(rv, false);
// Start a preflight if cross-origin and content type is not whitelisted
+1 -1
View File
@@ -367,7 +367,7 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
nsRefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(listener, mDocument->NodePrincipal(),
withCredentials);
rv = corsListener->Init(channel);
rv = corsListener->Init(channel, DataURIHandling::Allow);
NS_ENSURE_SUCCESS(rv, rv);
listener = corsListener;
}
+1 -1
View File
@@ -189,7 +189,7 @@ nsSyncLoader::LoadDocument(nsIChannel* aChannel,
if (aLoaderPrincipal) {
nsRefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(listener, aLoaderPrincipal, false);
rv = corsListener->Init(mChannel);
rv = corsListener->Init(mChannel, DataURIHandling::Disallow);
NS_ENSURE_SUCCESS(rv, rv);
listener = corsListener;
}
+1 -1
View File
@@ -2932,7 +2932,7 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
// a same-origin request right now, since it could be redirected.
nsRefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(listener, mPrincipal, withCredentials);
rv = corsListener->Init(mChannel, true);
rv = corsListener->Init(mChannel, DataURIHandling::Allow);
NS_ENSURE_SUCCESS(rv, rv);
listener = corsListener;
}
+1
View File
@@ -778,3 +778,4 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g'
[test_bug1118689.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g'
[test_getAttribute_after_createAttribute.html]
[test_script_loader_crossorigin_data_url.html]
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test for handling of 'crossorigin' attribute on script with data: URL</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
// We're going to mess with window.onerror.
setup({ allow_uncaught_exception: true });
</script>
<!-- First check that data: scripts with @crossorigin run at all -->
<script>
var ran = false;
</script>
<script crossorigin src="data:application/javascript,ran = true"></script>
<script>
test(function() {
assert_true(ran);
}, "script@crossorigin with data: src should have run");
</script>
<!-- Then check that their syntax errors are not sanitized -->
<script>
var errorFired = false;
ran = false;
window.onerror = function(message, uri, line) {
errorFired = true;
test(function() {
assert_equals(line, 3);
}, "Should have a useful line number for exception in script@crossorigin with data: src");
}
</script>
<script crossorigin src="data:application/javascript,var%20a;%0aran=true%0anoSuchFunctionHere()"></script>
<script>
test(function() {
assert_true(ran, "Script with error should have run");
assert_true(errorFired, "Script with error should have fired onerror");
}, "Should run and correctly fire onerror");
</script>
+1 -1
View File
@@ -472,7 +472,7 @@ FetchDriver::HttpFetch(bool aCORSFlag, bool aCORSPreflightFlag, bool aAuthentica
// directly.
nsRefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(this, mPrincipal, useCredentials);
rv = corsListener->Init(chan, true /* allow data uri */);
rv = corsListener->Init(chan, DataURIHandling::Allow);
if (NS_WARN_IF(NS_FAILED(rv))) {
return FailWithNetworkError();
}
+1 -1
View File
@@ -1254,7 +1254,7 @@ nsresult HTMLMediaElement::LoadResource()
new nsCORSListenerProxy(loadListener,
NodePrincipal(),
GetCORSMode() == CORS_USE_CREDENTIALS);
rv = corsListener->Init(channel);
rv = corsListener->Init(channel, DataURIHandling::Allow);
NS_ENSURE_SUCCESS(rv, rv);
listener = corsListener;
} else {
+1 -1
View File
@@ -619,7 +619,7 @@ nsresult ChannelMediaResource::OpenChannel(nsIStreamListener** aStreamListener)
element->NodePrincipal(),
false);
NS_ENSURE_TRUE(crossSiteListener, NS_ERROR_OUT_OF_MEMORY);
rv = crossSiteListener->Init(mChannel);
rv = crossSiteListener->Init(mChannel, DataURIHandling::Allow);
NS_ENSURE_SUCCESS(rv, rv);
listener = crossSiteListener;
} else {
+6 -5
View File
@@ -467,7 +467,7 @@ nsCORSListenerProxy::~nsCORSListenerProxy()
}
nsresult
nsCORSListenerProxy::Init(nsIChannel* aChannel, bool aAllowDataURI)
nsCORSListenerProxy::Init(nsIChannel* aChannel, DataURIHandling aAllowDataURI)
{
aChannel->GetNotificationCallbacks(getter_AddRefs(mOuterNotificationCallbacks));
aChannel->SetNotificationCallbacks(this);
@@ -780,7 +780,7 @@ nsCORSListenerProxy::OnRedirectVerifyCallback(nsresult result)
NS_ASSERTION(mNewRedirectChannel, "mNewRedirectChannel not set in callback");
if (NS_SUCCEEDED(result)) {
nsresult rv = UpdateChannel(mNewRedirectChannel);
nsresult rv = UpdateChannel(mNewRedirectChannel, DataURIHandling::Disallow);
if (NS_FAILED(rv)) {
NS_WARNING("nsCORSListenerProxy::OnRedirectVerifyCallback: "
"UpdateChannel() returned failure");
@@ -800,7 +800,8 @@ nsCORSListenerProxy::OnRedirectVerifyCallback(nsresult result)
}
nsresult
nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel, bool aAllowDataURI)
nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel,
DataURIHandling aAllowDataURI)
{
nsCOMPtr<nsIURI> uri, originalURI;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
@@ -809,7 +810,7 @@ nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel, bool aAllowDataURI)
NS_ENSURE_SUCCESS(rv, rv);
// exempt data URIs from the same origin check.
if (aAllowDataURI && originalURI == uri) {
if (aAllowDataURI == DataURIHandling::Allow && originalURI == uri) {
bool dataScheme = false;
rv = uri->SchemeIs("data", &dataScheme);
NS_ENSURE_SUCCESS(rv, rv);
@@ -1208,7 +1209,7 @@ NS_StartCORSPreflight(nsIChannel* aRequestChannel,
new nsCORSListenerProxy(preflightListener, aPrincipal,
aWithCredentials, method,
aUnsafeHeaders);
rv = corsListener->Init(preflightChannel);
rv = corsListener->Init(preflightChannel, DataURIHandling::Disallow);
NS_ENSURE_SUCCESS(rv, rv);
preflightListener = corsListener;
+8 -2
View File
@@ -29,6 +29,12 @@ NS_StartCORSPreflight(nsIChannel* aRequestChannel,
nsTArray<nsCString>& aACUnsafeHeaders,
nsIChannel** aPreflightChannel);
enum class DataURIHandling
{
Allow,
Disallow
};
class nsCORSListenerProxy final : public nsIStreamListener,
public nsIInterfaceRequestor,
public nsIChannelEventSink,
@@ -56,12 +62,12 @@ public:
static void Shutdown();
nsresult Init(nsIChannel* aChannel, bool aAllowDataURI = false);
nsresult Init(nsIChannel* aChannel, DataURIHandling aAllowDataURI);
private:
~nsCORSListenerProxy();
nsresult UpdateChannel(nsIChannel* aChannel, bool aAllowDataURI = false);
nsresult UpdateChannel(nsIChannel* aChannel, DataURIHandling aAllowDataURI);
nsresult CheckRequestApproved(nsIRequest* aRequest);
nsCOMPtr<nsIStreamListener> mOuterListener;
@@ -505,7 +505,7 @@ txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler,
// Always install in case of redirects
nsRefPtr<nsCORSListenerProxy> listener =
new nsCORSListenerProxy(sink, aReferrerPrincipal, false);
rv = listener->Init(channel);
rv = listener->Init(channel, DataURIHandling::Disallow);
NS_ENSURE_SUCCESS(rv, rv);
return channel->AsyncOpen(listener, parser);
+2 -2
View File
@@ -1525,7 +1525,7 @@ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
bool withCredentials = aCORSMode == imgIRequest::CORS_USE_CREDENTIALS;
nsRefPtr<nsCORSListenerProxy> corsproxy =
new nsCORSListenerProxy(listener, aLoadingPrincipal, withCredentials);
rv = corsproxy->Init(newChannel);
rv = corsproxy->Init(newChannel, DataURIHandling::Allow);
if (NS_FAILED(rv)) {
return false;
}
@@ -2071,7 +2071,7 @@ nsresult imgLoader::LoadImage(nsIURI *aURI,
nsRefPtr<nsCORSListenerProxy> corsproxy =
new nsCORSListenerProxy(pl, aLoadingPrincipal, withCredentials);
rv = corsproxy->Init(newChannel);
rv = corsproxy->Init(newChannel, DataURIHandling::Allow);
if (NS_FAILED(rv)) {
PR_LOG(GetImgLog(), PR_LOG_DEBUG,
("[this=%p] imgLoader::LoadImage -- nsCORSListenerProxy "
+1
View File
@@ -95,3 +95,4 @@ skip-if = toolkit == "gonk" #Bug 997034 - canvas.toDataURL() often causes lost c
[test_image_buffer_limit.html]
#run-if = toolkit == "gonk" #Image buffer limit is only set for Firefox OS currently.
disabled = bug 1060869
[test_image_crossorigin_data_url.html]
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test for handling of 'crossorigin' attribute on CSS link with data: URL</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<div id="someuniqueidhere"></div>
<img id="testimg" crossorigin src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC">
<script>
var t = async_test("img@crossorigin with data: src");
window.addEventListener("load", t.step_func_done(function() {
var img = document.getElementById("testimg");
assert_equals(img.naturalWidth, 1, "Should have 1px width");
assert_equals(img.naturalHeight, 1, "Should have 1px height");
var c = document.createElement("canvas");
c.width = c.height = 1;
var ctx = c.getContext("2d");
ctx.drawImage(img, 0, 0);
var data = ctx.getImageData(0, 0, 1, 1);
assert_equals(data.width, 1, "Should have 1px data width");
assert_equals(data.height, 1, "Should have 1px data height");
assert_equals(data.data[0], 255, "Should have lots of red");
assert_equals(data.data[1], 0, "Should have no green");
assert_equals(data.data[2], 0, "Should have no blue");
assert_equals(data.data[3], 255, "Should have no translucency");
}));
</script>
+3 -1
View File
@@ -462,7 +462,9 @@ FontFaceSet::StartLoad(gfxUserFontEntry* aUserFontEntry,
} else {
nsRefPtr<nsCORSListenerProxy> listener =
new nsCORSListenerProxy(streamLoader, aUserFontEntry->GetPrincipal(), false);
rv = listener->Init(channel);
// Doesn't matter what data: URI handling we use here, since we
// don't even use a CORS listener proxy for the data: case.
rv = listener->Init(channel, DataURIHandling::Disallow);
if (NS_SUCCEEDED(rv)) {
rv = channel->AsyncOpen(listener, nullptr);
}
+1 -1
View File
@@ -1670,7 +1670,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
nsRefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(streamLoader, aLoadData->mLoaderPrincipal,
withCredentials);
rv = corsListener->Init(channel);
rv = corsListener->Init(channel, DataURIHandling::Allow);
if (NS_FAILED(rv)) {
#ifdef DEBUG
mSyncCallback = false;
+1
View File
@@ -261,3 +261,4 @@ support-files = bug732209-css.sjs
[test_animations_async_tests.html]
support-files = ../../reftests/fonts/Ahem.ttf
[test_setPropertyWithNull.html]
[test_css_loader_crossorigin_data_url.html]
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test for handling of 'crossorigin' attribute on CSS link with data: URL</title>
<link id="testlink" crossorigin rel="stylesheet" href="data:text/css,%23someuniqueidhere{display:none}">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<div id="someuniqueidhere"></div>
<script>
var t = async_test("link@crossorigin with data: href");
window.addEventListener("load", t.step_func_done(function() {
assert_equals(getComputedStyle(document.getElementById("someuniqueidhere")).display,
"none", "sheet should be applied");
assert_equals(document.getElementById("testlink").sheet.cssRules[0].style.display,
"none", "should be able to read data from the sheet");
}));
</script>