зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1182571: Make nsXMLHttpRequest use AsyncOpen2. r=ehsan
This commit is contained in:
Родитель
4316c13003
Коммит
cc10dd7ad3
|
@ -51,10 +51,7 @@
|
|||
#include "nsICachingChannel.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsError.h"
|
||||
#include "nsCORSListenerProxy.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsIStorageStream.h"
|
||||
#include "nsIPromptFactory.h"
|
||||
|
@ -126,7 +123,7 @@ using namespace mozilla::dom;
|
|||
#define XML_HTTP_REQUEST_SYNCLOOPING (1 << 10) // Internal
|
||||
#define XML_HTTP_REQUEST_BACKGROUND (1 << 13) // Internal
|
||||
#define XML_HTTP_REQUEST_USE_XSITE_AC (1 << 14) // Internal
|
||||
#define XML_HTTP_REQUEST_NEED_AC_PREFLIGHT (1 << 15) // Internal
|
||||
#define XML_HTTP_REQUEST_NEED_AC_PREFLIGHT_IF_XSITE (1 << 15) // Internal
|
||||
#define XML_HTTP_REQUEST_AC_WITH_CREDENTIALS (1 << 16) // Internal
|
||||
#define XML_HTTP_REQUEST_TIMED_OUT (1 << 17) // Internal
|
||||
#define XML_HTTP_REQUEST_DELETED (1 << 18) // Internal
|
||||
|
@ -1533,47 +1530,15 @@ nsXMLHttpRequest::IsSystemXHR()
|
|||
return mIsSystem || nsContentUtils::IsSystemPrincipal(mPrincipal);
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
|
||||
{
|
||||
// A system XHR (chrome code or a web app with the right permission) can
|
||||
// always perform cross-site requests. In the web app case, however, we
|
||||
// must still check for protected URIs like file:///.
|
||||
if (IsSystemXHR()) {
|
||||
if (!nsContentUtils::IsSystemPrincipal(mPrincipal)) {
|
||||
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aChannel->GetOriginalURI(getter_AddRefs(uri));
|
||||
return secMan->CheckLoadURIWithPrincipal(
|
||||
mPrincipal, uri, nsIScriptSecurityManager::STANDARD);
|
||||
}
|
||||
return NS_OK;
|
||||
// load anything, and same-origin loads are always allowed.
|
||||
if (!IsSystemXHR() &&
|
||||
!nsContentUtils::CheckMayLoad(mPrincipal, aChannel, true)) {
|
||||
mState |= XML_HTTP_REQUEST_USE_XSITE_AC;
|
||||
}
|
||||
|
||||
// If this is a same-origin request or the channel's URI inherits
|
||||
// its principal, it's allowed.
|
||||
if (nsContentUtils::CheckMayLoad(mPrincipal, aChannel, true)) {
|
||||
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);
|
||||
|
||||
nsAutoCString method;
|
||||
httpChannel->GetRequestMethod(method);
|
||||
if (!mCORSUnsafeHeaders.IsEmpty() ||
|
||||
(mUpload && mUpload->HasListeners()) ||
|
||||
(!method.LowerCaseEqualsLiteral("get") &&
|
||||
!method.LowerCaseEqualsLiteral("post") &&
|
||||
!method.LowerCaseEqualsLiteral("head"))) {
|
||||
mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1680,21 +1645,6 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
|
|||
|
||||
rv = CheckInnerWindowCorrectness();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
|
||||
uri,
|
||||
mPrincipal,
|
||||
doc,
|
||||
EmptyCString(), //mime guess
|
||||
nullptr, //extra
|
||||
&shouldLoad,
|
||||
nsContentUtils::GetContentPolicy(),
|
||||
nsContentUtils::GetSecurityManager());
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_CP_REJECTED(shouldLoad)) {
|
||||
// Disallowed by content policy
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
|
||||
// XXXbz this is wrong: we should only be looking at whether
|
||||
// user/password were passed, not at the values! See bug 759624.
|
||||
|
@ -1717,20 +1667,27 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
|
|||
// will be automatically aborted if the user leaves the page.
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = GetLoadGroup();
|
||||
|
||||
nsSecurityFlags secFlags = nsILoadInfo::SEC_NORMAL;
|
||||
nsSecurityFlags secFlags;
|
||||
nsLoadFlags loadFlags = nsIRequest::LOAD_BACKGROUND;
|
||||
if (IsSystemXHR()) {
|
||||
// Don't give this document the system principal. We need to keep track of
|
||||
// mPrincipal being system because we use it for various security checks
|
||||
// that should be passing, but the document data shouldn't get a system
|
||||
// principal. Hence we set the sandbox flag in loadinfo, so that
|
||||
// GetChannelResultPrincipal will give us the nullprincipal.
|
||||
secFlags |= nsILoadInfo::SEC_SANDBOXED;
|
||||
|
||||
//For a XHR, disable interception
|
||||
if (nsContentUtils::IsSystemPrincipal(mPrincipal)) {
|
||||
// When chrome is loading we want to make sure to sandbox any potential
|
||||
// result document. We also want to allow cross-origin loads.
|
||||
secFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL |
|
||||
nsILoadInfo::SEC_SANDBOXED;
|
||||
}
|
||||
else if (IsSystemXHR()) {
|
||||
// For pages that have appropriate permissions, we want to still allow
|
||||
// cross-origin loads, but make sure that the any potential result
|
||||
// documents get the same principal as the loader.
|
||||
secFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
|
||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
|
||||
loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
|
||||
} else {
|
||||
secFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
|
||||
}
|
||||
else {
|
||||
// Otherwise use CORS. Again, make sure that potential result documents
|
||||
// use the same principal as the loader.
|
||||
secFlags = nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS |
|
||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
|
||||
}
|
||||
|
||||
// If we have the document, use it
|
||||
|
@ -1755,10 +1712,10 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
|
|||
loadFlags);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mState &= ~(XML_HTTP_REQUEST_USE_XSITE_AC |
|
||||
XML_HTTP_REQUEST_NEED_AC_PREFLIGHT);
|
||||
XML_HTTP_REQUEST_NEED_AC_PREFLIGHT_IF_XSITE);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel));
|
||||
if (httpChannel) {
|
||||
|
@ -1774,7 +1731,7 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
|
|||
|
||||
ChangeState(XML_HTTP_REQUEST_OPENED);
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2818,14 +2775,21 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
|||
|
||||
ResetResponse();
|
||||
|
||||
rv = CheckChannelForCrossSiteRequest(mChannel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
CheckChannelForCrossSiteRequest(mChannel);
|
||||
|
||||
bool withCredentials = !!(mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS);
|
||||
|
||||
// Hook us up to listen to redirects and the like
|
||||
mChannel->GetNotificationCallbacks(getter_AddRefs(mNotificationCallbacks));
|
||||
mChannel->SetNotificationCallbacks(this);
|
||||
if (!IsSystemXHR() && withCredentials) {
|
||||
// This is quite sad. We have to create the channel in .open(), since the
|
||||
// chrome-only xhr.channel API depends on that. However .withCredentials
|
||||
// can be modified after, so we don't know what to set the
|
||||
// SEC_REQUIRE_CORS_WITH_CREDENTIALS flag to when the channel is
|
||||
// created. So set it here using a hacky internal API.
|
||||
|
||||
// Not doing this for system XHR uses since those don't use CORS.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
|
||||
static_cast<LoadInfo*>(loadInfo.get())->SetWithCredentialsSecFlag();
|
||||
}
|
||||
|
||||
// Blocking gets are common enough out of XHR that we should mark
|
||||
// the channel slow by default for pipeline purposes
|
||||
|
@ -2846,24 +2810,6 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
|||
internalHttpChannel->SetResponseTimeoutEnabled(false);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStreamListener> listener = this;
|
||||
if (!IsSystemXHR()) {
|
||||
// Always create a nsCORSListenerProxy here even if it's
|
||||
// a same-origin request right now, since it could be redirected.
|
||||
RefPtr<nsCORSListenerProxy> corsListener =
|
||||
new nsCORSListenerProxy(listener, mPrincipal, withCredentials);
|
||||
rv = corsListener->Init(mChannel, DataURIHandling::Allow);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
listener = corsListener;
|
||||
}
|
||||
else {
|
||||
// Because of bug 682305, we can't let listener be the XHR object itself
|
||||
// because JS wouldn't be able to use it. So if we haven't otherwise
|
||||
// created a listener around 'this', do so now.
|
||||
|
||||
listener = new nsStreamListenerWrapper(listener);
|
||||
}
|
||||
|
||||
if (mIsAnon) {
|
||||
AddLoadFlags(mChannel, nsIRequest::LOAD_ANONYMOUS);
|
||||
}
|
||||
|
@ -2906,10 +2852,19 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
|||
mRequestSentTime = PR_Now();
|
||||
StartTimeoutTimer();
|
||||
|
||||
// Check if we need to do a preflight request.
|
||||
if (!mCORSUnsafeHeaders.IsEmpty() ||
|
||||
(mUpload && mUpload->HasListeners()) ||
|
||||
(!method.LowerCaseEqualsLiteral("get") &&
|
||||
!method.LowerCaseEqualsLiteral("post") &&
|
||||
!method.LowerCaseEqualsLiteral("head"))) {
|
||||
mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT_IF_XSITE;
|
||||
}
|
||||
|
||||
// Set up the preflight if needed
|
||||
if (mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT) {
|
||||
// Check to see if this initial OPTIONS request has already been cached
|
||||
// in our special Access Control Cache.
|
||||
if ((mState & XML_HTTP_REQUEST_USE_XSITE_AC) &&
|
||||
(mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT_IF_XSITE)) {
|
||||
NS_ENSURE_TRUE(internalHttpChannel, NS_ERROR_DOM_BAD_URI);
|
||||
|
||||
rv = internalHttpChannel->SetCorsPreflightParameters(mCORSUnsafeHeaders,
|
||||
withCredentials, mPrincipal);
|
||||
|
@ -2932,16 +2887,30 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
|||
}
|
||||
}
|
||||
|
||||
// Hook us up to listen to redirects and the like
|
||||
// Only do this very late since this creates a cycle between
|
||||
// the channel and us. This cycle has to be manually broken if anything
|
||||
// below fails.
|
||||
mChannel->GetNotificationCallbacks(getter_AddRefs(mNotificationCallbacks));
|
||||
mChannel->SetNotificationCallbacks(this);
|
||||
|
||||
// Start reading from the channel
|
||||
rv = mChannel->AsyncOpen(listener, nullptr);
|
||||
// Because of bug 682305, we can't let listener be the XHR object itself
|
||||
// because JS wouldn't be able to use it. So create a listener around 'this'.
|
||||
// Make sure to hold a strong reference so that we don't leak the wrapper.
|
||||
nsCOMPtr<nsIStreamListener> listener = new nsStreamListenerWrapper(this);
|
||||
rv = mChannel->AsyncOpen2(listener);
|
||||
listener = nullptr;
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
// Drop our ref to the channel to avoid cycles
|
||||
// Drop our ref to the channel to avoid cycles. Also drop channel's
|
||||
// ref to us to be extra safe.
|
||||
mChannel->SetNotificationCallbacks(mNotificationCallbacks);
|
||||
mChannel = nullptr;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Either AsyncOpen was called, or CORS will open the channel later.
|
||||
mWaitingForOnStopRequest = true;
|
||||
|
||||
// If we're synchronous, spin an event loop here and wait
|
||||
|
@ -3384,17 +3353,12 @@ nsXMLHttpRequest::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
|||
nsresult rv;
|
||||
|
||||
if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags)) {
|
||||
rv = CheckChannelForCrossSiteRequest(aNewChannel);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsXMLHttpRequest::OnChannelRedirect: "
|
||||
"CheckChannelForCrossSiteRequest returned failure");
|
||||
return rv;
|
||||
}
|
||||
CheckChannelForCrossSiteRequest(aNewChannel);
|
||||
|
||||
// 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)) {
|
||||
if ((mState & XML_HTTP_REQUEST_USE_XSITE_AC) &&
|
||||
(mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT_IF_XSITE)) {
|
||||
aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
}
|
||||
|
@ -3555,7 +3519,7 @@ bool
|
|||
nsXMLHttpRequest::AllowUploadProgress()
|
||||
{
|
||||
return !(mState & XML_HTTP_REQUEST_USE_XSITE_AC) ||
|
||||
(mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT);
|
||||
(mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT_IF_XSITE);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
@ -626,7 +626,7 @@ protected:
|
|||
*
|
||||
* Also updates the XML_HTTP_REQUEST_USE_XSITE_AC bit.
|
||||
*/
|
||||
nsresult CheckChannelForCrossSiteRequest(nsIChannel* aChannel);
|
||||
void CheckChannelForCrossSiteRequest(nsIChannel* aChannel);
|
||||
|
||||
void StartProgressEventTimer();
|
||||
|
||||
|
|
|
@ -50,28 +50,6 @@ function info(aMessage) {
|
|||
message(obj);
|
||||
}
|
||||
|
||||
function todo(aBool, aMessage) {
|
||||
var obj = {
|
||||
type: "todo",
|
||||
bool: aBool,
|
||||
message: aMessage
|
||||
};
|
||||
++message.ping;
|
||||
message(obj);
|
||||
}
|
||||
|
||||
function todo_is(aActual, aExpected, aMessage) {
|
||||
var obj = {
|
||||
type: "todo_is",
|
||||
actual: aActual,
|
||||
expected: aExpected,
|
||||
message: aMessage
|
||||
};
|
||||
++message.ping;
|
||||
message(obj);
|
||||
}
|
||||
|
||||
|
||||
function request(aURL) {
|
||||
return new Promise(function (aResolve, aReject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
@ -125,15 +103,11 @@ function testSuccessResponse() {
|
|||
message: "request to same-origin redirect to cross-origin URL",
|
||||
requestURL: "http://mochi.test:8888/tests/dom/base/test/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/base/test/file_XHRResponseURL.text",
|
||||
responseURL: "http://example.com/tests/dom/base/test/file_XHRResponseURL.text",
|
||||
skip: isInWorker(),
|
||||
reason: "cross-origin redirect request not works on Workers, see bug 882458"
|
||||
},
|
||||
{
|
||||
message: "request to same-origin redirects several times and finally go to cross-origin URL",
|
||||
requestURL: "http://mochi.test:8888/tests/dom/base/test/file_XHRResponseURL.sjs?url=" + encodeURIComponent("http://mochi.test:8888/tests/dom/base/test/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/base/test/file_XHRResponseURL.text"),
|
||||
responseURL: "http://example.com/tests/dom/base/test/file_XHRResponseURL.text",
|
||||
skip: isInWorker(),
|
||||
reason: "cross-origin redirect request not works on Workers, see bug 882458"
|
||||
},
|
||||
|
||||
// tests that start with cross-origin request
|
||||
|
@ -151,43 +125,31 @@ function testSuccessResponse() {
|
|||
message: "request to cross-origin redirect to the same cross-origin URL",
|
||||
requestURL: "http://example.com/tests/dom/base/test/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/base/test/file_XHRResponseURL.text",
|
||||
responseURL: "http://example.com/tests/dom/base/test/file_XHRResponseURL.text",
|
||||
skip: isInWorker(),
|
||||
reason: "cross-origin redirect request not works on Workers, see bug 882458"
|
||||
},
|
||||
{
|
||||
message: "request to cross-origin redirect to another cross-origin URL",
|
||||
requestURL: "http://example.com/tests/dom/base/test/file_XHRResponseURL.sjs?url=http://example.org/tests/dom/base/test/file_XHRResponseURL.text",
|
||||
responseURL: "http://example.org/tests/dom/base/test/file_XHRResponseURL.text",
|
||||
skip: isInWorker(),
|
||||
reason: "cross-origin redirect request not works on Workers, see bug 882458"
|
||||
},
|
||||
{
|
||||
message: "request to cross-origin redirects several times and finally go to same-origin URL",
|
||||
requestURL: "http://example.com/tests/dom/base/test/file_XHRResponseURL.sjs?url=" + encodeURIComponent("http://example.com/tests/dom/base/test/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/base/test/file_XHRResponseURL.text"),
|
||||
responseURL: "http://mochi.test:8888/tests/dom/base/test/file_XHRResponseURL.text",
|
||||
skip: isInWorker(),
|
||||
reason: "cross-origin redirect request not works on Workers, see bug 882458"
|
||||
},
|
||||
{
|
||||
message: "request to cross-origin redirects several times and finally go to the same cross-origin URL",
|
||||
requestURL: "http://example.com/tests/dom/base/test/file_XHRResponseURL.sjs?url=" + encodeURIComponent("http://example.com/tests/dom/base/test/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/base/test/file_XHRResponseURL.text"),
|
||||
responseURL: "http://example.com/tests/dom/base/test/file_XHRResponseURL.text",
|
||||
skip: isInWorker(),
|
||||
reason: "cross-origin redirect request not works on Workers, see bug 882458"
|
||||
},
|
||||
{
|
||||
message: "request to cross-origin redirects several times and finally go to another cross-origin URL",
|
||||
requestURL: "http://example.com/tests/dom/base/test/file_XHRResponseURL.sjs?url=" + encodeURIComponent("http://example.com/tests/dom/base/test/file_XHRResponseURL.sjs?url=http://example.org/tests/dom/base/test/file_XHRResponseURL.text"),
|
||||
responseURL: "http://example.org/tests/dom/base/test/file_XHRResponseURL.text",
|
||||
skip: isInWorker(),
|
||||
reason: "cross-origin redirect request not works on Workers, see bug 882458"
|
||||
},
|
||||
{
|
||||
message: "request to cross-origin redirects to another cross-origin and finally go to the other cross-origin URL",
|
||||
requestURL: "http://example.com/tests/dom/base/test/file_XHRResponseURL.sjs?url=" + encodeURIComponent("http://example.org/tests/dom/base/test/file_XHRResponseURL.sjs?url=http://test1.example.com/tests/dom/base/test/file_XHRResponseURL.text"),
|
||||
responseURL: "http://test1.example.com/tests/dom/base/test/file_XHRResponseURL.text",
|
||||
skip: isInWorker(),
|
||||
reason: "cross-origin redirect request not works on Workers, see bug 882458"
|
||||
},
|
||||
{
|
||||
message: "request URL has fragment",
|
||||
|
@ -209,13 +171,8 @@ function testSuccessResponse() {
|
|||
];
|
||||
|
||||
var sequence = createSequentialRequest(parameters, function (aXHR, aParam) {
|
||||
if (aParam.skip) {
|
||||
todo(aXHR.succeeded, aParam.reason);
|
||||
todo_is(aXHR.responseURL, aParam.responseURL, aParam.reason);
|
||||
} else {
|
||||
ok(aXHR.succeeded, "assert request succeeded");
|
||||
is(aXHR.responseURL, aParam.responseURL, aParam.message);
|
||||
}
|
||||
ok(aXHR.succeeded, "assert request succeeded");
|
||||
is(aXHR.responseURL, aParam.responseURL, aParam.message);
|
||||
});
|
||||
|
||||
sequence.then(function () {
|
||||
|
|
|
@ -172,9 +172,13 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
|
|||
requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
|
||||
"type_xml requires requestingContext of type Document");
|
||||
|
||||
// We're checking for the external TYPE_XMLHTTPREQUEST here in case
|
||||
// an addon creates a request with that type.
|
||||
if (internalContentPolicyType ==
|
||||
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST) {
|
||||
mimeTypeGuess = NS_LITERAL_CSTRING("application/xml");
|
||||
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST ||
|
||||
internalContentPolicyType ==
|
||||
nsIContentPolicy::TYPE_XMLHTTPREQUEST) {
|
||||
mimeTypeGuess = EmptyCString();
|
||||
}
|
||||
else {
|
||||
MOZ_ASSERT(internalContentPolicyType ==
|
||||
|
|
|
@ -155,29 +155,20 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=62178
|
|||
|
||||
|
||||
// Test 1e: insecure xhr
|
||||
var xhrsuccess = true;
|
||||
var xhr = new XMLHttpRequest;
|
||||
try {
|
||||
xhr.open("GET", baseUrl + "?type=xhr", true);
|
||||
} catch(ex) {
|
||||
xhrsuccess = false;
|
||||
parent.postMessage({"test": "xhr", "msg": "insecure xhr blocked"}, "http://mochi.test:8888");
|
||||
}
|
||||
|
||||
if(xhrsuccess) {
|
||||
xhr.onreadystatechange = function (oEvent) {
|
||||
var result = false;
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status == 200) {
|
||||
parent.postMessage({"test": "xhr", "msg": "insecure xhr loaded"}, "http://mochi.test:8888");
|
||||
}
|
||||
else {
|
||||
parent.postMessage({"test": "xhr", "msg": "insecure xhr blocked"}, "http://mochi.test:8888");
|
||||
}
|
||||
xhr.send();
|
||||
xhr.onloadend = function (oEvent) {
|
||||
if (xhr.status == 200) {
|
||||
parent.postMessage({"test": "xhr", "msg": "insecure xhr loaded"}, "http://mochi.test:8888");
|
||||
}
|
||||
else {
|
||||
parent.postMessage({"test": "xhr", "msg": "insecure xhr blocked"}, "http://mochi.test:8888");
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send(null);
|
||||
} catch(ex) {
|
||||
parent.postMessage({"test": "xhr", "msg": "insecure xhr blocked"}, "http://mochi.test:8888");
|
||||
}
|
||||
|
||||
/* Part 2: Mixed Display tests */
|
||||
|
|
|
@ -45,16 +45,6 @@ worker.addEventListener("message", function (aEvent) {
|
|||
worker.postMessage("pong");
|
||||
return;
|
||||
}
|
||||
if (data.type === "todo") {
|
||||
SimpleTest.todo(data.bool, data.message);
|
||||
worker.postMessage("pong");
|
||||
return;
|
||||
}
|
||||
if (data.type === "todo_is") {
|
||||
SimpleTest.todo_is(data.actual, data.expected, data.message);
|
||||
worker.postMessage("pong");
|
||||
return;
|
||||
}
|
||||
if (data.type === "redirect_test") {
|
||||
if (data.status === "start") {
|
||||
SpecialPowers.addObserver(requestObserver, "specialpowers-http-notify-request", false);
|
||||
|
|
|
@ -190,6 +190,14 @@ LoadInfo::GetSecurityFlags(nsSecurityFlags* aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
LoadInfo::SetWithCredentialsSecFlag()
|
||||
{
|
||||
MOZ_ASSERT(!mEnforceSecurity,
|
||||
"Request should not have been opened yet");
|
||||
mSecurityFlags |= nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadInfo::GetSecurityMode(uint32_t *aFlags)
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "nsTArray.h"
|
||||
|
||||
class nsINode;
|
||||
class nsXMLHttpRequest;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -77,6 +78,12 @@ private:
|
|||
|
||||
~LoadInfo();
|
||||
|
||||
// This function is the *only* function which can change the securityflags
|
||||
// of a loadinfo. It only exists because of the XHR code. Don't call it
|
||||
// from anywhere else!
|
||||
void SetWithCredentialsSecFlag();
|
||||
friend class ::nsXMLHttpRequest;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
|
||||
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
|
||||
nsWeakPtr mLoadingContext;
|
||||
|
|
|
@ -414,8 +414,7 @@ nsPreflightCache::GetCacheKey(nsIURI* aURI,
|
|||
|
||||
NS_IMPL_ISUPPORTS(nsCORSListenerProxy, nsIStreamListener,
|
||||
nsIRequestObserver, nsIChannelEventSink,
|
||||
nsIInterfaceRequestor, nsIAsyncVerifyRedirectCallback,
|
||||
nsIThreadRetargetableStreamListener)
|
||||
nsIInterfaceRequestor, nsIThreadRetargetableStreamListener)
|
||||
|
||||
/* static */
|
||||
void
|
||||
|
@ -592,9 +591,6 @@ nsCORSListenerProxy::OnStopRequest(nsIRequest* aRequest,
|
|||
nsresult rv = mOuterListener->OnStopRequest(aRequest, aContext, aStatusCode);
|
||||
mOuterListener = nullptr;
|
||||
mOuterNotificationCallbacks = nullptr;
|
||||
mRedirectCallback = nullptr;
|
||||
mOldRedirectChannel = nullptr;
|
||||
mNewRedirectChannel = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -650,7 +646,7 @@ NS_IMETHODIMP
|
|||
nsCORSListenerProxy::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
||||
nsIChannel *aNewChannel,
|
||||
uint32_t aFlags,
|
||||
nsIAsyncVerifyRedirectCallback *cb)
|
||||
nsIAsyncVerifyRedirectCallback *aCb)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags) &&
|
||||
|
@ -714,54 +710,24 @@ nsCORSListenerProxy::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
|||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare to receive callback
|
||||
mRedirectCallback = cb;
|
||||
mOldRedirectChannel = aOldChannel;
|
||||
mNewRedirectChannel = aNewChannel;
|
||||
rv = UpdateChannel(aNewChannel, DataURIHandling::Disallow);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsCORSListenerProxy::AsyncOnChannelRedirect: "
|
||||
"UpdateChannel() returned failure");
|
||||
aOldChannel->Cancel(rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannelEventSink> outer =
|
||||
do_GetInterface(mOuterNotificationCallbacks);
|
||||
if (outer) {
|
||||
rv = outer->AsyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
aOldChannel->Cancel(rv); // is this necessary...?
|
||||
mRedirectCallback = nullptr;
|
||||
mOldRedirectChannel = nullptr;
|
||||
mNewRedirectChannel = nullptr;
|
||||
}
|
||||
return rv;
|
||||
return outer->AsyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags, aCb);
|
||||
}
|
||||
|
||||
(void) OnRedirectVerifyCallback(NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
aCb->OnRedirectVerifyCallback(NS_OK);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCORSListenerProxy::OnRedirectVerifyCallback(nsresult result)
|
||||
{
|
||||
NS_ASSERTION(mRedirectCallback, "mRedirectCallback not set in callback");
|
||||
NS_ASSERTION(mOldRedirectChannel, "mOldRedirectChannel not set in callback");
|
||||
NS_ASSERTION(mNewRedirectChannel, "mNewRedirectChannel not set in callback");
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
nsresult rv = UpdateChannel(mNewRedirectChannel, DataURIHandling::Disallow);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsCORSListenerProxy::OnRedirectVerifyCallback: "
|
||||
"UpdateChannel() returned failure");
|
||||
}
|
||||
result = rv;
|
||||
}
|
||||
|
||||
if (NS_FAILED(result)) {
|
||||
mOldRedirectChannel->Cancel(result);
|
||||
}
|
||||
|
||||
mOldRedirectChannel = nullptr;
|
||||
mNewRedirectChannel = nullptr;
|
||||
mRedirectCallback->OnRedirectVerifyCallback(result);
|
||||
mRedirectCallback = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ enum class DataURIHandling
|
|||
class nsCORSListenerProxy final : public nsIStreamListener,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIChannelEventSink,
|
||||
public nsIAsyncVerifyRedirectCallback,
|
||||
public nsIThreadRetargetableStreamListener
|
||||
{
|
||||
public:
|
||||
|
@ -53,7 +52,6 @@ public:
|
|||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
|
||||
// Must be called at startup.
|
||||
|
@ -103,9 +101,6 @@ private:
|
|||
#ifdef DEBUG
|
||||
bool mInited;
|
||||
#endif
|
||||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
|
||||
nsCOMPtr<nsIChannel> mOldRedirectChannel;
|
||||
nsCOMPtr<nsIChannel> mNewRedirectChannel;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[shared-worker-connect-src-allowed.sub.html]
|
||||
type: testharness
|
||||
[Expecting alerts: ["xhr allowed","TEST COMPLETE"\]]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[shared-worker-connect-src-blocked.sub.html]
|
||||
type: testharness
|
||||
[Expecting alerts: ["xhr blocked","TEST COMPLETE"\]]
|
||||
expected: FAIL
|
|
@ -0,0 +1,4 @@
|
|||
[worker-connect-src-blocked.sub.html]
|
||||
type: testharness
|
||||
[Expecting alerts: ["xhr blocked","TEST COMPLETE"\]]
|
||||
expected: FAIL
|
|
@ -1,12 +0,0 @@
|
|||
[redirect-userinfo.htm]
|
||||
type: testharness
|
||||
expected: TIMEOUT
|
||||
[Disallow redirect with userinfo (//user:pass@)]
|
||||
expected: TIMEOUT
|
||||
|
||||
[Disallow redirect with userinfo (//user:@)]
|
||||
expected: TIMEOUT
|
||||
|
||||
[Disallow redirect with userinfo (//user@)]
|
||||
expected: TIMEOUT
|
||||
|
|
@ -18,7 +18,13 @@ connect-src 'self'; script-src 'self' 'unsafe-inline';
|
|||
try {
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.open("GET", "http://www1.{{host}}:{{ports[http][0]}}/content-security-policy/support/fail.png", true);
|
||||
log("Fail");
|
||||
xhr.send();
|
||||
xhr.onload = function() {
|
||||
log("Fail");
|
||||
}
|
||||
xhr.onerror = function() {
|
||||
log("Pass");
|
||||
}
|
||||
} catch (e) {
|
||||
log("Pass");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче