зеркало из https://github.com/mozilla/gecko-dev.git
Bug 464954: Update Access-Control implementation to latest draft and fix some bugs. r/sr=bz
This commit is contained in:
Родитель
66dbffe909
Коммит
8c5f8ef332
|
@ -1359,6 +1359,26 @@ public:
|
|||
{
|
||||
return sThreadJSContextStack;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the Origin of the passed in nsIPrincipal or nsIURI. If the passed in
|
||||
* nsIURI or the URI of the passed in nsIPrincipal does not have a host, the
|
||||
* origin is set to 'null'.
|
||||
*
|
||||
* The ASCII versions return a ASCII strings that are puny-code encoded,
|
||||
* suitable for for example header values. The UTF versions return strings
|
||||
* containing international characters.
|
||||
*
|
||||
* aPrincipal/aOrigin must not be null.
|
||||
*/
|
||||
static nsresult GetASCIIOrigin(nsIPrincipal* aPrincipal,
|
||||
nsCString& aOrigin);
|
||||
static nsresult GetASCIIOrigin(nsIURI* aURI, nsCString& aOrigin);
|
||||
static nsresult GetUTFOrigin(nsIPrincipal* aPrincipal,
|
||||
nsString& aOrigin);
|
||||
static nsresult GetUTFOrigin(nsIURI* aURI, nsString& aOrigin);
|
||||
|
||||
private:
|
||||
|
||||
static PRBool InitializeEventTable();
|
||||
|
|
|
@ -4525,6 +4525,125 @@ nsSameOriginChecker::GetInterface(const nsIID & aIID, void **aResult)
|
|||
return QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::GetASCIIOrigin(nsIPrincipal* aPrincipal, nsCString& aOrigin)
|
||||
{
|
||||
NS_PRECONDITION(aPrincipal, "missing principal");
|
||||
|
||||
aOrigin.Truncate();
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (uri) {
|
||||
return GetASCIIOrigin(uri, aOrigin);
|
||||
}
|
||||
|
||||
aOrigin.AssignLiteral("null");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::GetASCIIOrigin(nsIURI* aURI, nsCString& aOrigin)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "missing uri");
|
||||
|
||||
aOrigin.Truncate();
|
||||
|
||||
nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
|
||||
NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCString host;
|
||||
nsresult rv = uri->GetAsciiHost(host);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
|
||||
nsCString scheme;
|
||||
rv = uri->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aOrigin = scheme + NS_LITERAL_CSTRING("://") + host;
|
||||
|
||||
// If needed, append the port
|
||||
PRInt32 port;
|
||||
uri->GetPort(&port);
|
||||
if (port != -1) {
|
||||
PRInt32 defaultPort = NS_GetDefaultPort(scheme.get());
|
||||
if (port != defaultPort) {
|
||||
aOrigin.Append(':');
|
||||
aOrigin.AppendInt(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
aOrigin.AssignLiteral("null");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::GetUTFOrigin(nsIPrincipal* aPrincipal, nsString& aOrigin)
|
||||
{
|
||||
NS_PRECONDITION(aPrincipal, "missing principal");
|
||||
|
||||
aOrigin.Truncate();
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (uri) {
|
||||
return GetUTFOrigin(uri, aOrigin);
|
||||
}
|
||||
|
||||
aOrigin.AssignLiteral("null");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::GetUTFOrigin(nsIURI* aURI, nsString& aOrigin)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "missing uri");
|
||||
|
||||
aOrigin.Truncate();
|
||||
|
||||
nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
|
||||
NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCString host;
|
||||
nsresult rv = uri->GetHost(host);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
|
||||
nsCString scheme;
|
||||
rv = uri->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aOrigin = NS_ConvertUTF8toUTF16(scheme + NS_LITERAL_CSTRING("://") + host);
|
||||
|
||||
// If needed, append the port
|
||||
PRInt32 port;
|
||||
uri->GetPort(&port);
|
||||
if (port != -1) {
|
||||
PRInt32 defaultPort = NS_GetDefaultPort(scheme.get());
|
||||
if (port != defaultPort) {
|
||||
aOrigin.Append(':');
|
||||
aOrigin.AppendInt(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
aOrigin.AssignLiteral("null");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
nsContentTypeParser::nsContentTypeParser(const nsAString& aString)
|
||||
: mString(aString), mService(nsnull)
|
||||
{
|
||||
|
|
|
@ -105,7 +105,7 @@ NS_IMETHODIMP
|
|||
nsCrossSiteListenerProxy::OnStartRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext)
|
||||
{
|
||||
mRequestApproved = NS_SUCCEEDED(CheckRequestApproved(aRequest));
|
||||
mRequestApproved = NS_SUCCEEDED(CheckRequestApproved(aRequest, PR_FALSE));
|
||||
if (!mRequestApproved) {
|
||||
aRequest->Cancel(NS_ERROR_DOM_BAD_URI);
|
||||
mOuterListener->OnStartRequest(aRequest, aContext);
|
||||
|
@ -157,45 +157,8 @@ IsValidHTTPToken(const nsCSubstring& aToken)
|
|||
}
|
||||
|
||||
nsresult
|
||||
GetOrigin(nsIPrincipal* aPrincipal, nsCString& aOrigin)
|
||||
{
|
||||
aOrigin.AssignLiteral("null");
|
||||
|
||||
nsCString host;
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = uri->GetAsciiHost(host);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!host.IsEmpty()) {
|
||||
nsCString scheme;
|
||||
rv = uri->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aOrigin = scheme + NS_LITERAL_CSTRING("://") + host;
|
||||
|
||||
// If needed, append the port
|
||||
PRInt32 port;
|
||||
uri->GetPort(&port);
|
||||
if (port != -1) {
|
||||
PRInt32 defaultPort = NS_GetDefaultPort(scheme.get());
|
||||
if (port != defaultPort) {
|
||||
aOrigin.Append(":");
|
||||
aOrigin.AppendInt(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
aOrigin.AssignLiteral("null");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
|
||||
nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest,
|
||||
PRBool aIsRedirect)
|
||||
{
|
||||
// Check if this was actually a cross domain request
|
||||
if (!mHasBeenCrossSite) {
|
||||
|
@ -212,10 +175,14 @@ nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
|
|||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
|
||||
NS_ENSURE_TRUE(http, NS_ERROR_DOM_BAD_URI);
|
||||
|
||||
PRBool succeeded;
|
||||
rv = http->GetRequestSucceeded(&succeeded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(succeeded, NS_ERROR_DOM_BAD_URI);
|
||||
// Redirects aren't success-codes. But necko already checked that it was a
|
||||
// valid redirect.
|
||||
if (!aIsRedirect) {
|
||||
PRBool succeeded;
|
||||
rv = http->GetRequestSucceeded(&succeeded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(succeeded, NS_ERROR_DOM_BAD_URI);
|
||||
}
|
||||
|
||||
// Check the Access-Control-Allow-Origin header
|
||||
nsCAutoString allowedOriginHeader;
|
||||
|
@ -225,10 +192,11 @@ nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
|
|||
|
||||
if (mWithCredentials || !allowedOriginHeader.EqualsLiteral("*")) {
|
||||
nsCAutoString origin;
|
||||
rv = GetOrigin(mRequestingPrincipal, origin);
|
||||
rv = nsContentUtils::GetASCIIOrigin(mRequestingPrincipal, origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!allowedOriginHeader.Equals(origin)) {
|
||||
if (!allowedOriginHeader.Equals(origin) ||
|
||||
origin.EqualsLiteral("null")) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
}
|
||||
|
@ -268,6 +236,7 @@ nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
|
|||
|
||||
// The "Access-Control-Allow-Headers" header contains a comma separated
|
||||
// list of header names.
|
||||
headerVal.Truncate();
|
||||
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Headers"),
|
||||
headerVal);
|
||||
nsTArray<nsCString> headers;
|
||||
|
@ -335,8 +304,11 @@ nsCrossSiteListenerProxy::OnChannelRedirect(nsIChannel *aOldChannel,
|
|||
nsIChannel *aNewChannel,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
nsresult rv = CheckRequestApproved(aOldChannel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv;
|
||||
if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags)) {
|
||||
rv = CheckRequestApproved(aOldChannel, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannelEventSink> outer =
|
||||
do_GetInterface(mOuterNotificationCallbacks);
|
||||
|
@ -387,7 +359,7 @@ nsCrossSiteListenerProxy::UpdateChannel(nsIChannel* aChannel)
|
|||
|
||||
// Add the Origin header
|
||||
nsCAutoString origin;
|
||||
rv = GetOrigin(mRequestingPrincipal, origin);
|
||||
rv = nsContentUtils::GetASCIIOrigin(mRequestingPrincipal, origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aChannel);
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
|
||||
private:
|
||||
nsresult UpdateChannel(nsIChannel* aChannel);
|
||||
nsresult CheckRequestApproved(nsIRequest* aRequest);
|
||||
nsresult CheckRequestApproved(nsIRequest* aRequest, PRBool aIsRedirect);
|
||||
|
||||
nsCOMPtr<nsIStreamListener> mOuterListener;
|
||||
nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
|
||||
|
|
|
@ -489,8 +489,9 @@ nsACProxyListener::OnChannelRedirect(nsIChannel *aOldChannel,
|
|||
nsIChannel *aNewChannel,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
// No redirects allowed for now.
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
// Only internal redirects allowed for now.
|
||||
return NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags) ?
|
||||
NS_OK : NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -2634,7 +2635,8 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||
mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
|
||||
}
|
||||
}
|
||||
else if (!method.LowerCaseEqualsLiteral("get")) {
|
||||
else if (!method.LowerCaseEqualsLiteral("get") &&
|
||||
!method.LowerCaseEqualsLiteral("head")) {
|
||||
mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
|
||||
}
|
||||
|
||||
|
@ -3111,14 +3113,16 @@ nsXMLHttpRequest::OnChannelRedirect(nsIChannel *aOldChannel,
|
|||
|
||||
nsresult rv;
|
||||
|
||||
rv = CheckChannelForCrossSiteRequest(aNewChannel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags)) {
|
||||
rv = CheckChannelForCrossSiteRequest(aNewChannel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Disable redirects for preflighted cross-site requests entirely for now
|
||||
// Note, do this after the call to CheckChannelForCrossSiteRequest
|
||||
// to make sure that XML_HTTP_REQUEST_USE_XSITE_AC is up-to-date
|
||||
if ((mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT)) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
// Disable redirects for preflighted cross-site requests entirely for now
|
||||
// Note, do this after the call to CheckChannelForCrossSiteRequest
|
||||
// to make sure that XML_HTTP_REQUEST_USE_XSITE_AC is up-to-date
|
||||
if ((mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT)) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
}
|
||||
|
||||
if (mChannelEventSink) {
|
||||
|
|
|
@ -246,6 +246,8 @@ _TEST_FILES = test_bug5141.html \
|
|||
bug457746.sjs \
|
||||
test_CrossSiteXHR.html \
|
||||
file_CrossSiteXHR_inner.html \
|
||||
file_CrossSiteXHR_inner_data.sjs \
|
||||
file_CrossSiteXHR_inner.zip \
|
||||
file_CrossSiteXHR_server.sjs \
|
||||
test_CrossSiteXHR_cache.html \
|
||||
file_CrossSiteXHR_cache_server.sjs \
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
NOTE! The content of this file is duplicated in file_CrossSiteXHR_inner.zip
|
||||
and file_CrossSiteXHR_inner_data.sjs
|
||||
Please update those files if you update this one.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
window.addEventListener('message', function(e) {
|
||||
window.addEventListener("message", function(e) {
|
||||
|
||||
sendData = null;
|
||||
|
||||
|
|
Двоичный файл не отображается.
|
@ -0,0 +1,92 @@
|
|||
var data = '<!DOCTYPE HTML>\n\
|
||||
<html>\n\
|
||||
<head>\n\
|
||||
<script>\n\
|
||||
window.addEventListener("message", function(e) {\n\
|
||||
\n\
|
||||
sendData = null;\n\
|
||||
\n\
|
||||
req = eval(e.data);\n\
|
||||
var res = {\n\
|
||||
didFail: false,\n\
|
||||
events: [],\n\
|
||||
progressEvents: 0\n\
|
||||
};\n\
|
||||
\n\
|
||||
var xhr = new XMLHttpRequest();\n\
|
||||
for each(type in ["load", "abort", "error", "loadstart"]) {\n\
|
||||
xhr.addEventListener(type, function(e) {\n\
|
||||
res.events.push(e.type);\n\
|
||||
}, false);\n\
|
||||
}\n\
|
||||
xhr.addEventListener("readystatechange", function(e) {\n\
|
||||
res.events.push("rs" + xhr.readyState);\n\
|
||||
}, false);\n\
|
||||
xhr.addEventListener("progress", function(e) {\n\
|
||||
res.progressEvents++;\n\
|
||||
}, false);\n\
|
||||
if (req.uploadProgress) {\n\
|
||||
if (req.uploadProgress == "uploadProgress") {\n\
|
||||
xhr.addEventListener("uploadProgress", function(e) {\n\
|
||||
res.progressEvents++;\n\
|
||||
}, false);\n\
|
||||
}\n\
|
||||
else {\n\
|
||||
xhr.upload.addEventListener(req.uploadProgress, function(e) {\n\
|
||||
res.progressEvents++;\n\
|
||||
}, false);\n\
|
||||
}\n\
|
||||
}\n\
|
||||
xhr.onload = function () {\n\
|
||||
res.status = xhr.status;\n\
|
||||
res.responseXML = xhr.responseXML ?\n\
|
||||
(new XMLSerializer()).serializeToString(xhr.responseXML) :\n\
|
||||
null;\n\
|
||||
res.responseText = xhr.responseText;\n\
|
||||
post(e, res);\n\
|
||||
};\n\
|
||||
xhr.onerror = function () {\n\
|
||||
res.didFail = true;\n\
|
||||
res.status = xhr.status;\n\
|
||||
res.responseXML = xhr.responseXML ?\n\
|
||||
(new XMLSerializer()).serializeToString(xhr.responseXML) :\n\
|
||||
null;\n\
|
||||
res.responseText = xhr.responseText;\n\
|
||||
post(e, res);\n\
|
||||
}\n\
|
||||
\n\
|
||||
if (req.withCred)\n\
|
||||
xhr.withCredentials = true;\n\
|
||||
if (req.body)\n\
|
||||
sendData = req.body;\n\
|
||||
\n\
|
||||
res.events.push("opening");\n\
|
||||
xhr.open(req.method, req.url, true);\n\
|
||||
\n\
|
||||
for (header in req.headers) {\n\
|
||||
xhr.setRequestHeader(header, req.headers[header]);\n\
|
||||
}\n\
|
||||
\n\
|
||||
res.events.push("sending");\n\
|
||||
xhr.send(sendData);\n\
|
||||
\n\
|
||||
}, false);\n\
|
||||
\n\
|
||||
function post(e, res) {\n\
|
||||
e.source.postMessage(res.toSource(), "*");\n\
|
||||
}\n\
|
||||
\n\
|
||||
</script>\n\
|
||||
</head>\n\
|
||||
<body>\n\
|
||||
Inner page\n\
|
||||
</body>\n\
|
||||
</html>'
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
response.setStatusLine(null, 302, "Follow me");
|
||||
response.setHeader("Location", "data:text/html," + escape(data));
|
||||
response.setHeader("Content-Type", "text/plain");
|
||||
response.write("Follow that guy!");
|
||||
}
|
|
@ -93,7 +93,13 @@ function handleRequest(request, response)
|
|||
}
|
||||
|
||||
// Send response
|
||||
|
||||
|
||||
if (query.hop) {
|
||||
query.hop = parseInt(query.hop, 10);
|
||||
hops = eval(query.hops);
|
||||
query.allowOrigin = hops[query.hop-1].allowOrigin;
|
||||
}
|
||||
|
||||
if (query.allowOrigin && (!isPreflight || !query.noAllowPreflight))
|
||||
response.setHeader("Access-Control-Allow-Origin", query.allowOrigin);
|
||||
|
||||
|
@ -109,12 +115,23 @@ function handleRequest(request, response)
|
|||
|
||||
if (query.allowMethods)
|
||||
response.setHeader("Access-Control-Allow-Methods", query.allowMethods);
|
||||
}
|
||||
|
||||
if (query.hop && query.hop < hops.length) {
|
||||
newURL = hops[query.hop].server +
|
||||
"/tests/content/base/test/file_CrossSiteXHR_server.sjs?" +
|
||||
"hop=" + (query.hop + 1) + "&hops=" + query.hops;
|
||||
response.setStatusLine(null, 302, "redirect");
|
||||
response.setHeader("Location", newURL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
response.setHeader("Content-Type", "application/xml", false);
|
||||
response.write("<res>hello pass</res>\n");
|
||||
// Send response body
|
||||
if (!isPreflight) {
|
||||
response.setHeader("Content-Type", "application/xml", false);
|
||||
response.write("<res>hello pass</res>\n");
|
||||
}
|
||||
}
|
||||
|
||||
function sendHttp500(response, text) {
|
||||
|
|
|
@ -20,18 +20,35 @@
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var origins =
|
||||
[['http://example.org'],
|
||||
['http://example.org:80', 'http://example.org'],
|
||||
['http://sub1.test1.example.org'],
|
||||
['http://test2.example.org:8000'],
|
||||
[{ server: 'http://example.org' },
|
||||
{ server: 'http://example.org:80',
|
||||
origin: 'http://example.org'
|
||||
},
|
||||
{ server: 'http://sub1.test1.example.org' },
|
||||
{ server: 'http://test2.example.org:8000' },
|
||||
{ server: 'http://sub1.\xe4lt.example.org:8000',
|
||||
origin: 'http://sub1.xn--lt-uia.example.org:8000'
|
||||
},
|
||||
{ server: 'http://sub2.\xe4lt.example.org',
|
||||
origin: 'http://sub2.xn--lt-uia.example.org'
|
||||
},
|
||||
{ server: 'http://ex\xe4mple.test',
|
||||
origin: 'http://xn--exmple-cua.test'
|
||||
},
|
||||
{ server: 'http://xn--exmple-cua.test' },
|
||||
{ server: 'http://\u03c0\u03b1\u03c1\u03ac\u03b4\u03b5\u03b9\u03b3\u03bc\u03b1.\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae',
|
||||
origin: 'http://xn--hxajbheg2az3al.xn--jxalpdlp'
|
||||
},
|
||||
{ origin: 'http://example.org',
|
||||
file: 'jar:http://example.org/tests/content/base/test/file_CrossSiteXHR_inner.zip!/file_CrossSiteXHR_inner.html'
|
||||
},
|
||||
{ origin: 'null',
|
||||
file: 'http://example.org/tests/content/base/test/file_CrossSiteXHR_inner_data.sjs'
|
||||
},
|
||||
];
|
||||
|
||||
//['https://example.com:443'],
|
||||
//['https://sub1.test1.example.com:443'],
|
||||
['http://sub1.\xe4lt.example.org:8000', 'http://sub1.xn--lt-uia.example.org:8000'],
|
||||
['http://sub2.\xe4lt.example.org', 'http://sub2.xn--lt-uia.example.org'],
|
||||
['http://ex\xe4mple.test', 'http://xn--exmple-cua.test'],
|
||||
['http://\u03c0\u03b1\u03c1\u03ac\u03b4\u03b5\u03b9\u03b3\u03bc\u03b1.\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae',
|
||||
'http://xn--hxajbheg2az3al.xn--jxalpdlp'],
|
||||
];
|
||||
|
||||
window.addEventListener("message", function(e) {
|
||||
gen.send(e.data);
|
||||
|
@ -45,14 +62,17 @@ function runTest() {
|
|||
loader.onload = function () { gen.next() };
|
||||
|
||||
// Test preflight-less requests
|
||||
baseURL = "http://localhost:8888/tests/content/base/test/" +
|
||||
"file_CrossSiteXHR_server.sjs?";
|
||||
for each(originPair in origins) {
|
||||
origin = originPair[1] || originPair[0];
|
||||
basePath = "/tests/content/base/test/file_CrossSiteXHR_server.sjs?"
|
||||
baseURL = "http://localhost:8888" + basePath;
|
||||
for each(originEntry in origins) {
|
||||
origin = originEntry.origin || originEntry.server;
|
||||
|
||||
loader.src = originPair[0] + "/tests/content/base/test/file_CrossSiteXHR_inner.html";
|
||||
loader.src = originEntry.file ||
|
||||
(originEntry.server + "/tests/content/base/test/file_CrossSiteXHR_inner.html");
|
||||
yield;
|
||||
|
||||
var isNullOrigin = origin == "null";
|
||||
|
||||
port = /:\d+/;
|
||||
passTests = [
|
||||
origin,
|
||||
|
@ -67,6 +87,7 @@ function runTest() {
|
|||
: origin + ":1234",
|
||||
port.test(origin) ? origin.replace(port, ":")
|
||||
: origin + ":",
|
||||
origin + ".",
|
||||
origin + "/",
|
||||
origin + "#",
|
||||
origin + "?",
|
||||
|
@ -87,53 +108,51 @@ function runTest() {
|
|||
origin.replace(/\/[^.]+\./, "/"),
|
||||
];
|
||||
|
||||
for each(method in ["GET", "POST"]) {
|
||||
var headers = method == "POST" ?
|
||||
{ "Content-Type": "text/plain" } :
|
||||
null;
|
||||
if (isNullOrigin) {
|
||||
passTests = ["*", "\t \t* \t "];
|
||||
failTests = failTests.filter(function(v) { return v != origin });
|
||||
failTests.push("null");
|
||||
}
|
||||
|
||||
for each(allowOrigin in passTests) {
|
||||
req = {
|
||||
url: baseURL +
|
||||
"allowOrigin=" + escape(allowOrigin) +
|
||||
"&origin=" + escape(origin),
|
||||
method: "GET",
|
||||
};
|
||||
loaderWindow.postMessage(req.toSource(), isNullOrigin ? "*" : origin);
|
||||
|
||||
for each(allowOrigin in passTests) {
|
||||
req = {
|
||||
url: baseURL +
|
||||
"allowOrigin=" + escape(allowOrigin) +
|
||||
"&origin=" + escape(origin),
|
||||
method: method,
|
||||
headers: headers,
|
||||
};
|
||||
loaderWindow.postMessage(req.toSource(), origin);
|
||||
res = eval(yield);
|
||||
is(res.didFail, false, "shouldn't have failed");
|
||||
is(res.status, 200, "wrong status");
|
||||
is(res.responseXML,
|
||||
"<res>hello pass</res>",
|
||||
"wrong responseXML in test for " + allowOrigin);
|
||||
is(res.responseText, "<res>hello pass</res>\n",
|
||||
"wrong responseText in test for " + allowOrigin);
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
|
||||
"wrong responseText in test for " + allowOrigin);
|
||||
}
|
||||
|
||||
res = eval(yield);
|
||||
is(res.didFail, false, "shouldn't have failed");
|
||||
is(res.status, 200, "wrong status");
|
||||
is(res.responseXML,
|
||||
"<res>hello pass</res>",
|
||||
"wrong responseXML in test for " + allowOrigin);
|
||||
is(res.responseText, "<res>hello pass</res>\n",
|
||||
"wrong responseText in test for " + allowOrigin);
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
|
||||
"wrong responseText in test for " + allowOrigin);
|
||||
}
|
||||
for each(allowOrigin in failTests) {
|
||||
req = {
|
||||
url: baseURL + "allowOrigin=" + escape(allowOrigin),
|
||||
method: "GET",
|
||||
};
|
||||
loaderWindow.postMessage(req.toSource(), isNullOrigin ? "*" : origin);
|
||||
|
||||
for each(allowOrigin in failTests) {
|
||||
req = {
|
||||
url: baseURL + "allowOrigin=" + escape(allowOrigin),
|
||||
method: method,
|
||||
headers: headers,
|
||||
};
|
||||
loaderWindow.postMessage(req.toSource(), origin);
|
||||
|
||||
res = eval(yield);
|
||||
is(res.didFail, true, "should have failed for " + allowOrigin);
|
||||
is(res.responseText, "", "should have no text for " + allowOrigin);
|
||||
is(res.status, 0, "should have no status for " + allowOrigin);
|
||||
is(res.responseXML, null, "should have no XML for " + allowOrigin);
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
|
||||
"wrong events in test for " + allowOrigin);
|
||||
is(res.progressEvents, 0,
|
||||
"wrong events in test for " + allowOrigin);
|
||||
}
|
||||
res = eval(yield);
|
||||
is(res.didFail, true, "should have failed for " + allowOrigin);
|
||||
is(res.responseText, "", "should have no text for " + allowOrigin);
|
||||
is(res.status, 0, "should have no status for " + allowOrigin);
|
||||
is(res.responseXML, null, "should have no XML for " + allowOrigin);
|
||||
is(res.events.join(","),
|
||||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
|
||||
"wrong events in test for " + allowOrigin);
|
||||
is(res.progressEvents, 0,
|
||||
"wrong events in test for " + allowOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,6 +162,15 @@ function runTest() {
|
|||
yield;
|
||||
|
||||
passTests = [{ method: "GET",
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "Content-Type": "baz/bin",
|
||||
"Accept": "foo/bar",
|
||||
"Accept-Language": "sv-SE" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
|
@ -193,10 +221,14 @@ function runTest() {
|
|||
headers: { "x-my%-header": "myValue" },
|
||||
allowHeaders: "x-my%-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
{ method: "HEAD",
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "HEAD",
|
||||
headers: { "Content-Type": "baz/bin",
|
||||
"Accept": "foo/bar",
|
||||
"Accept-Language": "sv-SE" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "POST",
|
||||
body: "hi there",
|
||||
|
@ -318,6 +350,28 @@ function runTest() {
|
|||
"y-my-header": "" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "myheader": "" },
|
||||
allowMethods: "myheader",
|
||||
},
|
||||
{ method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
},
|
||||
{ method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "",
|
||||
},
|
||||
{ method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "y-my-header",
|
||||
},
|
||||
{ method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header y-my-header",
|
||||
},
|
||||
{ method: "XXDELETE",
|
||||
allowHeaders: "XXDELETE",
|
||||
},
|
||||
{ method: "POST",
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
|
@ -409,13 +463,24 @@ function runTest() {
|
|||
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());
|
||||
if (test.method !== "HEAD") {
|
||||
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.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,load",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
}
|
||||
}
|
||||
|
||||
for each(test in failTests) {
|
||||
|
@ -584,6 +649,164 @@ function runTest() {
|
|||
}
|
||||
}
|
||||
|
||||
// Test redirects
|
||||
is(loader.src, "http://example.org/tests/content/base/test/file_CrossSiteXHR_inner.html");
|
||||
is(origin, "http://example.org");
|
||||
|
||||
tests = [{ pass: 1,
|
||||
method: "GET",
|
||||
hops: [{ server: "http://example.com",
|
||||
allowOrigin: origin
|
||||
},
|
||||
],
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
hops: [{ server: "http://example.com",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://example.org",
|
||||
allowOrigin: origin
|
||||
},
|
||||
],
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
hops: [{ server: "http://example.com",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://example.org",
|
||||
},
|
||||
],
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
hops: [{ server: "http://example.org",
|
||||
},
|
||||
{ server: "http://example.org",
|
||||
},
|
||||
{ server: "http://example.com",
|
||||
allowOrigin: origin
|
||||
},
|
||||
],
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
hops: [{ server: "http://example.org",
|
||||
},
|
||||
{ server: "http://example.org",
|
||||
},
|
||||
{ server: "http://example.com",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://example.org",
|
||||
},
|
||||
],
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
hops: [{ server: "http://example.com",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://test2.example.org:8000",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://sub2.xn--lt-uia.example.org",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://sub1.test1.example.org",
|
||||
allowOrigin: origin
|
||||
},
|
||||
],
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
hops: [{ server: "http://example.com",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://test2.example.org:8000",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://sub2.xn--lt-uia.example.org",
|
||||
allowOrigin: "x"
|
||||
},
|
||||
{ server: "http://sub1.test1.example.org",
|
||||
allowOrigin: origin
|
||||
},
|
||||
],
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
hops: [{ server: "http://example.com",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://test2.example.org:8000",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://sub2.xn--lt-uia.example.org",
|
||||
allowOrigin: "*"
|
||||
},
|
||||
{ server: "http://sub1.test1.example.org",
|
||||
allowOrigin: origin
|
||||
},
|
||||
],
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
hops: [{ server: "http://example.com",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://test2.example.org:8000",
|
||||
allowOrigin: origin
|
||||
},
|
||||
{ server: "http://sub2.xn--lt-uia.example.org",
|
||||
allowOrigin: "*"
|
||||
},
|
||||
{ server: "http://sub1.test1.example.org",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
for each(test in tests) {
|
||||
req = {
|
||||
url: test.hops[0].server + basePath + "hop=1&hops=" +
|
||||
escape(test.hops.toSource()),
|
||||
method: test.method,
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
yield;
|
||||
|
|
|
@ -5266,26 +5266,25 @@ nsGlobalWindow::PostMessageMoz(const nsAString& aMessage, const nsAString& aOrig
|
|||
nsIPrincipal* callerPrin = callerInnerWin->GetPrincipal();
|
||||
if (!callerPrin)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIURI> callerOuterURI;
|
||||
if (NS_FAILED(callerPrin->GetURI(getter_AddRefs(callerOuterURI))))
|
||||
return NS_OK;
|
||||
if (!callerOuterURI) {
|
||||
|
||||
nsAutoString origin;
|
||||
if (callerOuterURI) {
|
||||
// if the principal has a URI, use that to generate the origin
|
||||
nsContentUtils::GetUTFOrigin(callerPrin, origin);
|
||||
}
|
||||
else {
|
||||
// otherwise use the URI of the document to generate origin
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(callerInnerWin->mDocument);
|
||||
if (!doc)
|
||||
return NS_OK;
|
||||
callerOuterURI = doc->GetDocumentURI();
|
||||
if (!callerOuterURI)
|
||||
return NS_OK;
|
||||
// if the principal has a URI, use that to generate the origin
|
||||
nsContentUtils::GetUTFOrigin(callerOuterURI, origin);
|
||||
}
|
||||
nsCOMPtr<nsIURI> callerURI = NS_GetInnermostURI(callerOuterURI);
|
||||
if (!callerURI)
|
||||
return NS_OK;
|
||||
const nsCString& empty = EmptyCString();
|
||||
nsCOMPtr<nsIURI> callerOrigin;
|
||||
if (NS_FAILED(callerURI->Clone(getter_AddRefs(callerOrigin))) ||
|
||||
NS_FAILED(callerOrigin->SetUserPass(empty)))
|
||||
return NS_OK;
|
||||
|
||||
|
||||
// Convert the provided origin string into a URI for comparison purposes.
|
||||
// "*" indicates no specific origin is required.
|
||||
|
@ -5293,22 +5292,18 @@ nsGlobalWindow::PostMessageMoz(const nsAString& aMessage, const nsAString& aOrig
|
|||
if (!aOrigin.EqualsASCII("*")) {
|
||||
if (NS_FAILED(NS_NewURI(getter_AddRefs(providedOrigin), aOrigin)))
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
if (NS_FAILED(providedOrigin->SetUserPass(empty)) ||
|
||||
NS_FAILED(providedOrigin->SetPath(empty)))
|
||||
if (NS_FAILED(providedOrigin->SetUserPass(EmptyCString())) ||
|
||||
NS_FAILED(providedOrigin->SetPath(EmptyCString())))
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCAutoString origin;
|
||||
if (NS_FAILED(callerOrigin->GetPrePath(origin)))
|
||||
return NS_OK;
|
||||
|
||||
// Create and asynchronously dispatch a runnable which will handle actual DOM
|
||||
// event creation and dispatch.
|
||||
nsRefPtr<PostMessageEvent> event =
|
||||
new PostMessageEvent(nsContentUtils::IsCallerChrome()
|
||||
? nsnull
|
||||
: callerInnerWin->GetOuterWindowInternal(),
|
||||
NS_ConvertUTF8toUTF16(origin),
|
||||
origin,
|
||||
aMessage,
|
||||
this,
|
||||
providedOrigin,
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
#include "nsIMutable.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "nsIIDNService.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
|
||||
// Helper, to simplify getting the I/O service.
|
||||
inline const nsGetServiceByContractIDWithError
|
||||
|
@ -1581,4 +1582,25 @@ NS_SecurityCompareURIs(nsIURI* aSourceURI,
|
|||
return NS_GetRealPort(targetBaseURI) == NS_GetRealPort(sourceBaseURI);
|
||||
}
|
||||
|
||||
inline PRBool
|
||||
NS_IsInternalSameURIRedirect(nsIChannel *aOldChannel,
|
||||
nsIChannel *aNewChannel,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> oldURI, newURI;
|
||||
aOldChannel->GetURI(getter_AddRefs(oldURI));
|
||||
aNewChannel->GetURI(getter_AddRefs(newURI));
|
||||
|
||||
if (!oldURI || !newURI) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool res;
|
||||
return NS_SUCCEEDED(oldURI->Equals(newURI, &res)) && res;
|
||||
}
|
||||
|
||||
#endif // !nsNetUtil_h__
|
||||
|
|
|
@ -193,6 +193,7 @@ function createMochitestServer(serverBasePath)
|
|||
server.registerDirectory("/", serverBasePath);
|
||||
server.registerPathHandler("/server/shutdown", serverShutdown);
|
||||
server.registerContentType("sjs", "sjs"); // .sjs == CGI-like functionality
|
||||
server.registerContentType("zip", "application/x-jar");
|
||||
server.setIndexHandler(defaultDirHandler);
|
||||
|
||||
processLocations(server);
|
||||
|
|
Загрузка…
Ссылка в новой задаче