Bug 1182571: Make nsXMLHttpRequest use AsyncOpen2. r=ehsan

This commit is contained in:
Jonas Sicking 2015-10-19 11:14:54 -07:00
Родитель 4316c13003
Коммит cc10dd7ad3
15 изменённых файлов: 134 добавлений и 255 удалений

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

@ -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");
}