From 22ca2b61fd04fd296d711c3740e201655553a4e0 Mon Sep 17 00:00:00 2001 From: "heikki%netscape.com" Date: Fri, 19 Apr 2002 00:06:40 +0000 Subject: [PATCH] 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. --- .../xmlextras/base/src/nsXMLHttpRequest.cpp | 54 ++++++++++++------- .../xmlextras/base/src/nsXMLHttpRequest.h | 3 +- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp b/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp index f60d7a4ae8c..4408013fbdd 100644 --- a/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp +++ b/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp @@ -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 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 supportsStream; + rv = NS_NewByteInputStream(getter_AddRefs(supportsStream),fromRawSegment,count); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr 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 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 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 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 diff --git a/extensions/xmlextras/base/src/nsXMLHttpRequest.h b/extensions/xmlextras/base/src/nsXMLHttpRequest.h index f9c515774d0..71619d161a2 100644 --- a/extensions/xmlextras/base/src/nsXMLHttpRequest.h +++ b/extensions/xmlextras/base/src/nsXMLHttpRequest.h @@ -160,7 +160,8 @@ protected: nsCOMPtr mXMLParserStreamListener; PRInt32 mStatus; - PRBool mAsync; + PRPackedBool mAsync; + PRPackedBool mParseResponseBody; nsCString mOverrideMimeType; };