Bug 389508: Fix regressions and bugs in the new Cross Site XMLHttpRequest support. r/sr=jst a=roc
git-svn-id: svn://10.0.0.236/trunk@231205 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
60a8dfe73b
commit
33c7643cbb
@ -73,8 +73,12 @@ nsCrossSiteListenerProxy::ForwardRequest(PRBool aFromStop)
|
||||
}
|
||||
|
||||
mHasForwardedRequest = PR_TRUE;
|
||||
mParser = nsnull;
|
||||
mParserListener = nsnull;
|
||||
|
||||
if (mParser) {
|
||||
mParser->Terminate();
|
||||
mParser = nsnull;
|
||||
mParserListener = nsnull;
|
||||
}
|
||||
|
||||
if (mAcceptState != eAccept) {
|
||||
mOuterRequest->Cancel(NS_ERROR_DOM_BAD_URI);
|
||||
@ -290,8 +294,15 @@ nsCrossSiteListenerProxy::OnDataAvailable(nsIRequest* aRequest,
|
||||
|
||||
// Hold a local reference to make sure the parser doesn't go away
|
||||
nsCOMPtr<nsIStreamListener> stackedListener = mParserListener;
|
||||
return stackedListener->OnDataAvailable(aRequest, aContext, stream, aOffset,
|
||||
aCount);
|
||||
rv = stackedListener->OnDataAvailable(aRequest, aContext, stream, aOffset,
|
||||
aCount);
|
||||
// When we forward the request we also terminate the parsing which will
|
||||
// result in an error bubbling up to here. We want to ignore the error
|
||||
// in that case.
|
||||
if (mHasForwardedRequest) {
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -302,7 +313,11 @@ nsCrossSiteListenerProxy::HandleStartElement(const PRUnichar *aName,
|
||||
PRUint32 aLineNumber)
|
||||
{
|
||||
// We're done processing the prolog.
|
||||
return ForwardRequest(PR_FALSE);
|
||||
ForwardRequest(PR_FALSE);
|
||||
|
||||
// Block the parser since we don't want to spend more cycles on parsing
|
||||
// stuff.
|
||||
return NS_ERROR_HTMLPARSER_BLOCK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -463,7 +478,11 @@ nsCrossSiteListenerProxy::WillBuildModel()
|
||||
mParser->GetDTD(getter_AddRefs(dtd));
|
||||
NS_ASSERTION(dtd, "missing dtd in WillBuildModel");
|
||||
if (dtd && !(dtd->GetType() & NS_IPARSER_FLAG_XML)) {
|
||||
return ForwardRequest(PR_FALSE);
|
||||
ForwardRequest(PR_FALSE);
|
||||
|
||||
// Block the parser since we don't want to spend more cycles on parsing
|
||||
// stuff.
|
||||
return NS_ERROR_HTMLPARSER_BLOCK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
@ -87,6 +87,7 @@
|
||||
#include "nsDOMError.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsIMultiPartChannel.h"
|
||||
|
||||
#define LOAD_STR "load"
|
||||
#define ERROR_STR "error"
|
||||
@ -116,6 +117,7 @@
|
||||
#define XML_HTTP_REQUEST_MULTIPART (1 << 12) // Internal
|
||||
#define XML_HTTP_REQUEST_USE_XSITE_AC (1 << 13) // Internal
|
||||
#define XML_HTTP_REQUEST_NON_GET (1 << 14) // Internal
|
||||
#define XML_HTTP_REQUEST_GOT_FINAL_STOP (1 << 15) // Internal
|
||||
|
||||
#define XML_HTTP_REQUEST_LOADSTATES \
|
||||
(XML_HTTP_REQUEST_UNINITIALIZED | \
|
||||
@ -1133,6 +1135,12 @@ nsXMLHttpRequest::GetCurrentHttpChannel()
|
||||
static PRBool
|
||||
IsSameOrigin(nsIPrincipal* aPrincipal, nsIChannel* aChannel)
|
||||
{
|
||||
if (!aPrincipal) {
|
||||
// XXX Until we got our principal story straight we have to do this to
|
||||
// support C++ callers.
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> codebase;
|
||||
nsresult rv = aPrincipal->GetURI(getter_AddRefs(codebase));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -1629,6 +1637,19 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
|
||||
rv = mXMLParserStreamListener->OnStopRequest(request, ctxt, status);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMultiPartChannel> mpChannel = do_QueryInterface(request);
|
||||
if (mpChannel) {
|
||||
PRBool last;
|
||||
rv = mpChannel->GetIsLastPart(&last);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (last) {
|
||||
mState |= XML_HTTP_REQUEST_GOT_FINAL_STOP;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mState |= XML_HTTP_REQUEST_GOT_FINAL_STOP;
|
||||
}
|
||||
|
||||
mXMLParserStreamListener = nsnull;
|
||||
mReadRequest = nsnull;
|
||||
mContext = nsnull;
|
||||
@ -1719,13 +1740,13 @@ nsXMLHttpRequest::RequestCompleted()
|
||||
|
||||
// Clear listeners here unless we're multipart
|
||||
ChangeState(XML_HTTP_REQUEST_COMPLETED, PR_TRUE,
|
||||
!(mState & XML_HTTP_REQUEST_MULTIPART));
|
||||
!!(mState & XML_HTTP_REQUEST_GOT_FINAL_STOP));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && domevent) {
|
||||
NotifyEventListeners(loadEventListeners, domevent);
|
||||
}
|
||||
|
||||
if (mState & XML_HTTP_REQUEST_MULTIPART) {
|
||||
if (!(mState & XML_HTTP_REQUEST_GOT_FINAL_STOP)) {
|
||||
// We're a multipart request, so we're not done. Reset to opened.
|
||||
ChangeState(XML_HTTP_REQUEST_OPENED);
|
||||
}
|
||||
@ -1958,13 +1979,6 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
||||
|
||||
// Create our listener
|
||||
nsCOMPtr<nsIStreamListener> listener = this;
|
||||
if (!(mState & XML_HTTP_REQUEST_XSITEENABLED)) {
|
||||
// Always create a nsCrossSiteListenerProxy here even if it's
|
||||
// a same-origin request right now, since it could be redirected.
|
||||
listener = new nsCrossSiteListenerProxy(listener, mPrincipal);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
if (mState & XML_HTTP_REQUEST_MULTIPART) {
|
||||
listener = new nsMultipartProxyListener(listener);
|
||||
if (!listener) {
|
||||
@ -1972,6 +1986,13 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
||||
}
|
||||
}
|
||||
|
||||
if (!(mState & XML_HTTP_REQUEST_XSITEENABLED)) {
|
||||
// Always create a nsCrossSiteListenerProxy here even if it's
|
||||
// a same-origin request right now, since it could be redirected.
|
||||
listener = new nsCrossSiteListenerProxy(listener, mPrincipal);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
// Bypass the network cache in cases where it makes no sense:
|
||||
// 1) Multipart responses are very large and would likely be doomed by the
|
||||
// cache once they grow too large, so they are not worth caching.
|
||||
@ -2009,7 +2030,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
||||
listener = new nsCrossSiteListenerProxy(acListener, mPrincipal);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = mACGetChannel->AsyncOpen(acListener, nsnull);
|
||||
rv = mACGetChannel->AsyncOpen(listener, nsnull);
|
||||
}
|
||||
else {
|
||||
// Start reading from the channel
|
||||
@ -2066,10 +2087,14 @@ nsXMLHttpRequest::SetRequestHeader(const nsACString& header,
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel));
|
||||
if (!httpChannel) // open() initializes mChannel, and open()
|
||||
if (!mChannel) // open() initializes mChannel, and open()
|
||||
return NS_ERROR_FAILURE; // must be called before first setRequestHeader()
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel));
|
||||
if (!httpChannel) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Prevent modification to certain HTTP headers (see bug 302263), unless
|
||||
// the executing script has UniversalBrowserWrite permission.
|
||||
|
||||
|
||||
@ -168,6 +168,7 @@ protected:
|
||||
nsCOMPtr<nsISupports> mContext;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
// mReadRequest is different from mChannel for multipart requests
|
||||
nsCOMPtr<nsIRequest> mReadRequest;
|
||||
nsCOMPtr<nsIDOMDocument> mDocument;
|
||||
nsCOMPtr<nsIChannel> mACGetChannel;
|
||||
|
||||
@ -47,6 +47,8 @@ include $(topsrcdir)/config/rules.mk
|
||||
_TEST_FILES = test_bug5141.html \
|
||||
test_bug51034.html \
|
||||
test_bug218236.html \
|
||||
file_bug218236_multipart.txt \
|
||||
file_bug218236_multipart.txt^headers^ \
|
||||
test_bug218277.html \
|
||||
test_bug238409.html \
|
||||
test_bug276037-1.html \
|
||||
|
||||
15
mozilla/content/base/test/file_bug218236_multipart.txt
Normal file
15
mozilla/content/base/test/file_bug218236_multipart.txt
Normal file
@ -0,0 +1,15 @@
|
||||
----boundary
|
||||
Content-Type: text/html
|
||||
|
||||
<html><body>File 1</body></html>
|
||||
|
||||
------boundary
|
||||
Content-Type: text/html
|
||||
|
||||
<p>File 2</p>
|
||||
|
||||
------boundary
|
||||
Content-Type: text/plain
|
||||
|
||||
File 3
|
||||
--
|
||||
@ -0,0 +1,2 @@
|
||||
HTTP 200 OK
|
||||
Content-Type: multipart/x-mixed-replace;boundary="----boundary"
|
||||
@ -14,30 +14,48 @@
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var passFiles = ['file_CrossSiteXHR_pass1.xml',
|
||||
'file_CrossSiteXHR_pass2.xml',
|
||||
'file_CrossSiteXHR_pass3.xml'];
|
||||
var local = "http://example.com/tests/content/base/test/";
|
||||
var post = "http://people.mozilla.com/cgi-bin/sicking/xhr/posttest.pl/";
|
||||
|
||||
var failFiles = ['file_CrossSiteXHR_fail1.xml',
|
||||
'file_CrossSiteXHR_fail2.xml',
|
||||
'file_CrossSiteXHR_fail3.xml',
|
||||
'file_CrossSiteXHR_fail4.xml'];
|
||||
var passFiles = [[local + 'file_CrossSiteXHR_pass1.xml', 'GET'],
|
||||
[local + 'file_CrossSiteXHR_pass2.xml', 'GET'],
|
||||
[local + 'file_CrossSiteXHR_pass3.xml', 'GET'],
|
||||
[post + 'pass1', 'POST'],
|
||||
[post + 'pass2', 'POST'],
|
||||
[post + 'pass3', 'POST'],
|
||||
];
|
||||
|
||||
var failFiles = [[local + 'file_CrossSiteXHR_fail1.xml', 'GET'],
|
||||
[local + 'file_CrossSiteXHR_fail2.xml', 'GET'],
|
||||
[local + 'file_CrossSiteXHR_fail3.xml', 'GET'],
|
||||
[local + 'file_CrossSiteXHR_fail4.xml', 'GET'],
|
||||
[post + 'fail1', 'POST'],
|
||||
[post + 'fail2', 'POST'],
|
||||
[post + 'fail3', 'POST'],
|
||||
[post + 'fail4', 'POST'],
|
||||
[post + 'fail5', 'POST'],
|
||||
];
|
||||
|
||||
for (i = 0; i < passFiles.length; ++i) {
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "http://example.com/tests/content/base/test/" + passFiles[i], false);
|
||||
xhr.open(passFiles[i][1], passFiles[i][0], false);
|
||||
xhr.send(null);
|
||||
ok(xhr.status == 200, "wrong status");
|
||||
ok((new XMLSerializer()).serializeToString(xhr.responseXML.documentElement) ==
|
||||
is(xhr.status, 200, "wrong status");
|
||||
if (xhr.responseXML) {
|
||||
is((new XMLSerializer()).serializeToString(xhr.responseXML.documentElement),
|
||||
"<res>hello</res>",
|
||||
"wrong response");
|
||||
"wrong response");
|
||||
}
|
||||
else {
|
||||
is(xhr.responseText, "hello pass\n", "wrong response");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < failFiles.length; ++i) {
|
||||
xhr = new XMLHttpRequest();
|
||||
success = false;
|
||||
try {
|
||||
xhr.open("GET", "http://example.com/tests/content/base/test/" + failFiles[i], false);
|
||||
xhr.open(failFiles[i][1], failFiles[i][0], false);
|
||||
xhr.send(null);
|
||||
}
|
||||
catch (e) {
|
||||
@ -45,8 +63,6 @@ for (i = 0; i < failFiles.length; ++i) {
|
||||
}
|
||||
ok(success, "should have thrown");
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
@ -27,17 +27,21 @@ SimpleTest.waitForExplicitFinish();
|
||||
var url_200 = window.location.href;
|
||||
var url_404 = url_200.replace(/[^/]+$/, "this_file_is_not_going_to_be_there.dummy");
|
||||
var url_connection_error = url_200.replace(/^(\w+:\/\/[^/]+?)(:\d+)?\//, "$1:9546/");
|
||||
var url_multipart = "file_bug218236_multipart.txt";
|
||||
|
||||
// List of tests: name of the test, URL to be requested, expected sequence
|
||||
// of events and optionally a function to be called from readystatechange handler.
|
||||
// Numbers in the list of events are values of XMLHttpRequest.readyState
|
||||
// when readystatechange event is triggered.
|
||||
var tests = [
|
||||
["200 OK", url_200, [1, 2, 3, 4, "load"], null],
|
||||
["404 Not Found", url_404, [1, 2, 3, 4, "load"], null],
|
||||
["connection error", url_connection_error, [1, 2, 4, "error"], null],
|
||||
["abort() call on readyState = 1", url_200, [1, 4], doAbort1],
|
||||
["abort() call on readyState = 2", url_200, [1, 2, 4], doAbort2],
|
||||
["200 OK", url_200, [1, 2, 3, 4, "load"], 0, null],
|
||||
["404 Not Found", url_404, [1, 2, 3, 4, "load"], 0, null],
|
||||
["connection error", url_connection_error, [1, 2, 4, "error"], 0, null],
|
||||
["abort() call on readyState = 1", url_200, [1, 4], 0, doAbort1],
|
||||
["abort() call on readyState = 2", url_200, [1, 2, 4], 0, doAbort2],
|
||||
["multipart document", url_multipart, [1, 2, 3, 4, "load",
|
||||
1, 2, 3, 4, "load",
|
||||
1, 2, 3, 4, "load"], 1, null],
|
||||
];
|
||||
|
||||
var testName = null;
|
||||
@ -45,6 +49,7 @@ var currentState = 0;
|
||||
var currentSequence = null;
|
||||
var expectedSequence = null;
|
||||
var currentCallback = null;
|
||||
var finalizeTimeoutID = null;
|
||||
|
||||
var request = null;
|
||||
|
||||
@ -69,6 +74,7 @@ function runNextTest() {
|
||||
|
||||
// Prepare request object
|
||||
request = new XMLHttpRequest();
|
||||
request.multipart = test[3];
|
||||
request.open("GET", test[1]);
|
||||
request.onreadystatechange = onReadyStateChange;
|
||||
request.onload = onLoad;
|
||||
@ -79,7 +85,7 @@ function runNextTest() {
|
||||
currentState = 0;
|
||||
currentSequence = [];
|
||||
expectedSequence = test[2];
|
||||
currentCallback = test[3];
|
||||
currentCallback = test[4];
|
||||
|
||||
// Start request
|
||||
request.send(null);
|
||||
@ -89,12 +95,16 @@ function runNextTest() {
|
||||
}
|
||||
|
||||
function finalizeTest() {
|
||||
ok(compareArrays(expectedSequence, currentSequence), "event sequence for '" + testName + "' should be " + expectedSequence.join(", "));
|
||||
finalizeTimeoutID = null;
|
||||
ok(compareArrays(expectedSequence, currentSequence), "event sequence for '" + testName + "' was " + currentSequence.join(", "));
|
||||
|
||||
runNextTest();
|
||||
}
|
||||
|
||||
function onReadyStateChange() {
|
||||
clearTimeout(finalizeTimeoutID);
|
||||
finalizeTimeoutID = null;
|
||||
|
||||
// Ignore duplicated calls for the same ready state
|
||||
if (request.readyState != currentState) {
|
||||
currentState = request.readyState;
|
||||
@ -103,7 +113,9 @@ function onReadyStateChange() {
|
||||
|
||||
if (currentState == 4) {
|
||||
// Allow remaining event to fire but then we are finished with this test
|
||||
setTimeout(finalizeTest, 0);
|
||||
// unless we get another onReadyStateChange in which case we'll cancel
|
||||
// this timeout
|
||||
finalizeTimeoutID = setTimeout(finalizeTest, 0);
|
||||
}
|
||||
|
||||
if (currentCallback)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user