зеркало из https://github.com/mozilla/gecko-dev.git
Bug 129607, avoid trying to parse the response if we cannot be sure it is XML. This fixes hang in HTML parser, and is a big performance improvement if you are loading non-XML data. r=harishd, sr=vidur.
This commit is contained in:
Родитель
dd39b64008
Коммит
65afff3e5d
|
@ -181,8 +181,6 @@ nsXMLHttpRequest::AddEventListener(const nsAString& type,
|
|||
NS_ENSURE_ARG(listener);
|
||||
nsresult rv;
|
||||
|
||||
// I know, I know - strcmp's. But it's only for a couple of
|
||||
// cases...and they are short strings. :-)
|
||||
if (type.Equals(LOADSTR)) {
|
||||
if (!mLoadEventListeners) {
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(mLoadEventListeners));
|
||||
|
@ -784,23 +782,25 @@ nsXMLHttpRequest::StreamReaderFunc(nsIInputStream* in,
|
|||
// Copy for our own use
|
||||
xmlHttpRequest->mResponseBody.Append(fromRawSegment,count);
|
||||
|
||||
nsresult rv;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Give the same data to the parser.
|
||||
if (xmlHttpRequest->mParseResponseBody) {
|
||||
// Give the same data to the parser.
|
||||
|
||||
// We need to wrap the data in a new lightweight stream and pass that
|
||||
// to the parser, because calling ReadSegments() recursively on the same
|
||||
// stream is not supported.
|
||||
nsCOMPtr<nsISupports> supportsStream;
|
||||
rv = NS_NewByteInputStream(getter_AddRefs(supportsStream),fromRawSegment,count);
|
||||
// We need to wrap the data in a new lightweight stream and pass that
|
||||
// to the parser, because calling ReadSegments() recursively on the same
|
||||
// stream is not supported.
|
||||
nsCOMPtr<nsISupports> supportsStream;
|
||||
rv = NS_NewByteInputStream(getter_AddRefs(supportsStream),fromRawSegment,count);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIInputStream> copyStream(do_QueryInterface(supportsStream));
|
||||
if (copyStream) {
|
||||
rv = xmlHttpRequest->mXMLParserStreamListener->OnDataAvailable(xmlHttpRequest->mReadRequest,xmlHttpRequest->mContext,copyStream,toOffset,count);
|
||||
} else {
|
||||
NS_ERROR("NS_NewByteInputStream did not give out nsIInputStream!");
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIInputStream> copyStream(do_QueryInterface(supportsStream));
|
||||
if (copyStream) {
|
||||
rv = xmlHttpRequest->mXMLParserStreamListener->OnDataAvailable(xmlHttpRequest->mReadRequest,xmlHttpRequest->mContext,copyStream,toOffset,count);
|
||||
} else {
|
||||
NS_ERROR("NS_NewByteInputStream did not give out nsIInputStream!");
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -833,8 +833,22 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
|||
{
|
||||
mReadRequest = request;
|
||||
mContext = ctxt;
|
||||
mParseResponseBody = PR_TRUE;
|
||||
ChangeState(XML_HTTP_REQUEST_LOADED);
|
||||
if (!mOverrideMimeType.IsEmpty()) {
|
||||
if (mOverrideMimeType.IsEmpty()) {
|
||||
// If we are not overriding the mime type, we can gain a huge performance
|
||||
// win by not even trying to parse non-XML data. This also protects us
|
||||
// from the situation where we have an XML document and sink, but HTML (or other)
|
||||
// parser, which can produce unreliable results.
|
||||
nsCAutoString type;
|
||||
mChannel->GetContentType(type);
|
||||
nsACString::const_iterator start, end;
|
||||
type.BeginReading(start);
|
||||
type.EndReading(end);
|
||||
if (!FindInReadable(NS_LITERAL_CSTRING("xml"), start, end)) {
|
||||
mParseResponseBody = PR_FALSE;
|
||||
}
|
||||
} else {
|
||||
nsresult status;
|
||||
request->GetStatus(&status);
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
|
@ -842,7 +856,8 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
|||
channel->SetContentType(mOverrideMimeType);
|
||||
}
|
||||
}
|
||||
return mXMLParserStreamListener->OnStartRequest(request,ctxt);
|
||||
|
||||
return mParseResponseBody ? mXMLParserStreamListener->OnStartRequest(request,ctxt) : NS_OK;
|
||||
}
|
||||
|
||||
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status, in wstring statusArg); */
|
||||
|
@ -852,7 +867,7 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
|
|||
nsCOMPtr<nsIParser> parser(do_QueryInterface(mXMLParserStreamListener));
|
||||
NS_ABORT_IF_FALSE(parser, "stream listener was expected to be a parser");
|
||||
|
||||
nsresult rv = mXMLParserStreamListener->OnStopRequest(request,ctxt,status);
|
||||
nsresult rv = mParseResponseBody ? mXMLParserStreamListener->OnStopRequest(request,ctxt,status) : NS_OK;
|
||||
mXMLParserStreamListener = nsnull;
|
||||
mReadRequest = nsnull;
|
||||
mContext = nsnull;
|
||||
|
@ -1043,6 +1058,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case nsIDataType::VTYPE_VOID:
|
||||
case nsIDataType::VTYPE_EMPTY:
|
||||
// Makes us act as if !aBody, don't upload anything
|
||||
|
|
|
@ -160,7 +160,8 @@ protected:
|
|||
nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
|
||||
|
||||
PRInt32 mStatus;
|
||||
PRBool mAsync;
|
||||
PRPackedBool mAsync;
|
||||
PRPackedBool mParseResponseBody;
|
||||
nsCString mOverrideMimeType;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче