1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/parser/xml/src/nsSAXXMLReader.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,710 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsIInputStream.h" 1.10 +#include "nsNetCID.h" 1.11 +#include "nsNetUtil.h" 1.12 +#include "nsIParser.h" 1.13 +#include "nsParserCIID.h" 1.14 +#include "nsStreamUtils.h" 1.15 +#include "nsStringStream.h" 1.16 +#include "nsIScriptError.h" 1.17 +#include "nsSAXAttributes.h" 1.18 +#include "nsSAXLocator.h" 1.19 +#include "nsSAXXMLReader.h" 1.20 +#include "nsCharsetSource.h" 1.21 + 1.22 +#include "mozilla/dom/EncodingUtils.h" 1.23 + 1.24 +using mozilla::dom::EncodingUtils; 1.25 + 1.26 +#define XMLNS_URI "http://www.w3.org/2000/xmlns/" 1.27 + 1.28 +static NS_DEFINE_CID(kParserCID, NS_PARSER_CID); 1.29 + 1.30 +NS_IMPL_CYCLE_COLLECTION(nsSAXXMLReader, 1.31 + mContentHandler, 1.32 + mDTDHandler, 1.33 + mErrorHandler, 1.34 + mLexicalHandler, 1.35 + mDeclarationHandler, 1.36 + mBaseURI, 1.37 + mListener, 1.38 + mParserObserver) 1.39 +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSAXXMLReader) 1.40 +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSAXXMLReader) 1.41 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSAXXMLReader) 1.42 + NS_INTERFACE_MAP_ENTRY(nsISAXXMLReader) 1.43 + NS_INTERFACE_MAP_ENTRY(nsIExpatSink) 1.44 + NS_INTERFACE_MAP_ENTRY(nsIExtendedExpatSink) 1.45 + NS_INTERFACE_MAP_ENTRY(nsIContentSink) 1.46 + NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) 1.47 + NS_INTERFACE_MAP_ENTRY(nsIStreamListener) 1.48 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISAXXMLReader) 1.49 +NS_INTERFACE_MAP_END 1.50 + 1.51 +nsSAXXMLReader::nsSAXXMLReader() : 1.52 + mIsAsyncParse(false), 1.53 + mEnableNamespacePrefixes(false) 1.54 +{ 1.55 +} 1.56 + 1.57 +// nsIContentSink 1.58 +NS_IMETHODIMP 1.59 +nsSAXXMLReader::WillBuildModel(nsDTDMode) 1.60 +{ 1.61 + if (mContentHandler) 1.62 + return mContentHandler->StartDocument(); 1.63 + 1.64 + return NS_OK; 1.65 +} 1.66 + 1.67 +NS_IMETHODIMP 1.68 +nsSAXXMLReader::DidBuildModel(bool aTerminated) 1.69 +{ 1.70 + if (mContentHandler) 1.71 + return mContentHandler->EndDocument(); 1.72 + 1.73 + return NS_OK; 1.74 +} 1.75 + 1.76 +NS_IMETHODIMP 1.77 +nsSAXXMLReader::SetParser(nsParserBase *aParser) 1.78 +{ 1.79 + return NS_OK; 1.80 +} 1.81 + 1.82 +// nsIExtendedExpatSink 1.83 +NS_IMETHODIMP 1.84 +nsSAXXMLReader::HandleStartElement(const char16_t *aName, 1.85 + const char16_t **aAtts, 1.86 + uint32_t aAttsCount, 1.87 + int32_t aIndex, 1.88 + uint32_t aLineNumber) 1.89 +{ 1.90 + if (!mContentHandler) 1.91 + return NS_OK; 1.92 + 1.93 + nsRefPtr<nsSAXAttributes> atts = new nsSAXAttributes(); 1.94 + if (!atts) 1.95 + return NS_ERROR_OUT_OF_MEMORY; 1.96 + nsAutoString uri, localName, qName; 1.97 + for (; *aAtts; aAtts += 2) { 1.98 + SplitExpatName(aAtts[0], uri, localName, qName); 1.99 + // XXX don't have attr type information 1.100 + NS_NAMED_LITERAL_STRING(cdataType, "CDATA"); 1.101 + // could support xmlns reporting, it's a standard SAX feature 1.102 + if (mEnableNamespacePrefixes || !uri.EqualsLiteral(XMLNS_URI)) { 1.103 + NS_ASSERTION(aAtts[1], "null passed to handler"); 1.104 + atts->AddAttribute(uri, localName, qName, cdataType, 1.105 + nsDependentString(aAtts[1])); 1.106 + } 1.107 + } 1.108 + 1.109 + // Deal with the element name 1.110 + SplitExpatName(aName, uri, localName, qName); 1.111 + return mContentHandler->StartElement(uri, localName, qName, atts); 1.112 +} 1.113 + 1.114 +NS_IMETHODIMP 1.115 +nsSAXXMLReader::HandleEndElement(const char16_t *aName) 1.116 +{ 1.117 + if (mContentHandler) { 1.118 + nsAutoString uri, localName, qName; 1.119 + SplitExpatName(aName, uri, localName, qName); 1.120 + return mContentHandler->EndElement(uri, localName, qName); 1.121 + } 1.122 + return NS_OK; 1.123 +} 1.124 + 1.125 +NS_IMETHODIMP 1.126 +nsSAXXMLReader::HandleComment(const char16_t *aName) 1.127 +{ 1.128 + NS_ASSERTION(aName, "null passed to handler"); 1.129 + if (mLexicalHandler) 1.130 + return mLexicalHandler->Comment(nsDependentString(aName)); 1.131 + 1.132 + return NS_OK; 1.133 +} 1.134 + 1.135 +NS_IMETHODIMP 1.136 +nsSAXXMLReader::HandleCDataSection(const char16_t *aData, 1.137 + uint32_t aLength) 1.138 +{ 1.139 + nsresult rv; 1.140 + if (mLexicalHandler) { 1.141 + rv = mLexicalHandler->StartCDATA(); 1.142 + NS_ENSURE_SUCCESS(rv, rv); 1.143 + } 1.144 + 1.145 + if (mContentHandler) { 1.146 + rv = mContentHandler->Characters(Substring(aData, aData+aLength)); 1.147 + NS_ENSURE_SUCCESS(rv, rv); 1.148 + } 1.149 + 1.150 + if (mLexicalHandler) { 1.151 + rv = mLexicalHandler->EndCDATA(); 1.152 + NS_ENSURE_SUCCESS(rv, rv); 1.153 + } 1.154 + 1.155 + return NS_OK; 1.156 +} 1.157 + 1.158 +NS_IMETHODIMP 1.159 +nsSAXXMLReader::HandleStartDTD(const char16_t *aName, 1.160 + const char16_t *aSystemId, 1.161 + const char16_t *aPublicId) 1.162 +{ 1.163 + char16_t nullChar = char16_t(0); 1.164 + if (!aName) 1.165 + aName = &nullChar; 1.166 + if (!aSystemId) 1.167 + aSystemId = &nullChar; 1.168 + if (!aPublicId) 1.169 + aPublicId = &nullChar; 1.170 + 1.171 + mSystemId = aSystemId; 1.172 + mPublicId = aPublicId; 1.173 + if (mLexicalHandler) { 1.174 + return mLexicalHandler->StartDTD(nsDependentString(aName), 1.175 + nsDependentString(aPublicId), 1.176 + nsDependentString(aSystemId)); 1.177 + } 1.178 + 1.179 + return NS_OK; 1.180 +} 1.181 + 1.182 +NS_IMETHODIMP 1.183 +nsSAXXMLReader::HandleDoctypeDecl(const nsAString & aSubset, 1.184 + const nsAString & aName, 1.185 + const nsAString & aSystemId, 1.186 + const nsAString & aPublicId, 1.187 + nsISupports* aCatalogData) 1.188 +{ 1.189 + if (mLexicalHandler) 1.190 + return mLexicalHandler->EndDTD(); 1.191 + 1.192 + return NS_OK; 1.193 +} 1.194 + 1.195 +NS_IMETHODIMP 1.196 +nsSAXXMLReader::HandleCharacterData(const char16_t *aData, 1.197 + uint32_t aLength) 1.198 +{ 1.199 + if (mContentHandler) 1.200 + return mContentHandler->Characters(Substring(aData, aData+aLength)); 1.201 + 1.202 + return NS_OK; 1.203 +} 1.204 + 1.205 +NS_IMETHODIMP 1.206 +nsSAXXMLReader::HandleStartNamespaceDecl(const char16_t *aPrefix, 1.207 + const char16_t *aUri) 1.208 +{ 1.209 + if (!mContentHandler) 1.210 + return NS_OK; 1.211 + 1.212 + char16_t nullChar = char16_t(0); 1.213 + if (!aPrefix) 1.214 + aPrefix = &nullChar; 1.215 + if (!aUri) 1.216 + aUri = &nullChar; 1.217 + 1.218 + return mContentHandler->StartPrefixMapping(nsDependentString(aPrefix), 1.219 + nsDependentString(aUri)); 1.220 +} 1.221 + 1.222 +NS_IMETHODIMP 1.223 +nsSAXXMLReader::HandleEndNamespaceDecl(const char16_t *aPrefix) 1.224 +{ 1.225 + if (!mContentHandler) 1.226 + return NS_OK; 1.227 + 1.228 + if (aPrefix) 1.229 + return mContentHandler->EndPrefixMapping(nsDependentString(aPrefix)); 1.230 + 1.231 + return mContentHandler->EndPrefixMapping(EmptyString()); 1.232 +} 1.233 + 1.234 +NS_IMETHODIMP 1.235 +nsSAXXMLReader::HandleProcessingInstruction(const char16_t *aTarget, 1.236 + const char16_t *aData) 1.237 +{ 1.238 + NS_ASSERTION(aTarget && aData, "null passed to handler"); 1.239 + if (mContentHandler) { 1.240 + return mContentHandler->ProcessingInstruction(nsDependentString(aTarget), 1.241 + nsDependentString(aData)); 1.242 + } 1.243 + 1.244 + return NS_OK; 1.245 +} 1.246 + 1.247 +NS_IMETHODIMP 1.248 +nsSAXXMLReader::HandleNotationDecl(const char16_t *aNotationName, 1.249 + const char16_t *aSystemId, 1.250 + const char16_t *aPublicId) 1.251 +{ 1.252 + NS_ASSERTION(aNotationName, "null passed to handler"); 1.253 + if (mDTDHandler) { 1.254 + char16_t nullChar = char16_t(0); 1.255 + if (!aSystemId) 1.256 + aSystemId = &nullChar; 1.257 + if (!aPublicId) 1.258 + aPublicId = &nullChar; 1.259 + 1.260 + return mDTDHandler->NotationDecl(nsDependentString(aNotationName), 1.261 + nsDependentString(aSystemId), 1.262 + nsDependentString(aPublicId)); 1.263 + } 1.264 + 1.265 + return NS_OK; 1.266 +} 1.267 + 1.268 +NS_IMETHODIMP 1.269 +nsSAXXMLReader::HandleUnparsedEntityDecl(const char16_t *aEntityName, 1.270 + const char16_t *aSystemId, 1.271 + const char16_t *aPublicId, 1.272 + const char16_t *aNotationName) 1.273 +{ 1.274 + NS_ASSERTION(aEntityName && aNotationName, "null passed to handler"); 1.275 + if (mDTDHandler) { 1.276 + char16_t nullChar = char16_t(0); 1.277 + if (!aSystemId) 1.278 + aSystemId = &nullChar; 1.279 + if (!aPublicId) 1.280 + aPublicId = &nullChar; 1.281 + 1.282 + return mDTDHandler->UnparsedEntityDecl(nsDependentString(aEntityName), 1.283 + nsDependentString(aSystemId), 1.284 + nsDependentString(aPublicId), 1.285 + nsDependentString(aNotationName)); 1.286 + } 1.287 + 1.288 + return NS_OK; 1.289 +} 1.290 + 1.291 +NS_IMETHODIMP 1.292 +nsSAXXMLReader::HandleXMLDeclaration(const char16_t *aVersion, 1.293 + const char16_t *aEncoding, 1.294 + int32_t aStandalone) 1.295 +{ 1.296 + NS_ASSERTION(aVersion, "null passed to handler"); 1.297 + if (mDeclarationHandler) { 1.298 + char16_t nullChar = char16_t(0); 1.299 + if (!aEncoding) 1.300 + aEncoding = &nullChar; 1.301 + mDeclarationHandler->HandleXMLDeclaration(nsDependentString(aVersion), 1.302 + nsDependentString(aEncoding), 1.303 + aStandalone > 0); 1.304 + } 1.305 + return NS_OK; 1.306 +} 1.307 + 1.308 +NS_IMETHODIMP 1.309 +nsSAXXMLReader::ReportError(const char16_t* aErrorText, 1.310 + const char16_t* aSourceText, 1.311 + nsIScriptError *aError, 1.312 + bool *_retval) 1.313 +{ 1.314 + NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!"); 1.315 + // Normally, the expat driver should report the error. 1.316 + *_retval = true; 1.317 + 1.318 + if (mErrorHandler) { 1.319 + uint32_t lineNumber; 1.320 + nsresult rv = aError->GetLineNumber(&lineNumber); 1.321 + NS_ENSURE_SUCCESS(rv, rv); 1.322 + 1.323 + uint32_t columnNumber; 1.324 + rv = aError->GetColumnNumber(&columnNumber); 1.325 + NS_ENSURE_SUCCESS(rv, rv); 1.326 + 1.327 + nsCOMPtr<nsISAXLocator> locator = new nsSAXLocator(mPublicId, 1.328 + mSystemId, 1.329 + lineNumber, 1.330 + columnNumber); 1.331 + if (!locator) 1.332 + return NS_ERROR_OUT_OF_MEMORY; 1.333 + 1.334 + rv = mErrorHandler->FatalError(locator, nsDependentString(aErrorText)); 1.335 + if (NS_SUCCEEDED(rv)) { 1.336 + // The error handler has handled the script error. Don't log to console. 1.337 + *_retval = false; 1.338 + } 1.339 + } 1.340 + 1.341 + return NS_OK; 1.342 +} 1.343 + 1.344 +// nsISAXXMLReader 1.345 + 1.346 +NS_IMETHODIMP 1.347 +nsSAXXMLReader::GetBaseURI(nsIURI **aBaseURI) 1.348 +{ 1.349 + NS_IF_ADDREF(*aBaseURI = mBaseURI); 1.350 + return NS_OK; 1.351 +} 1.352 + 1.353 +NS_IMETHODIMP 1.354 +nsSAXXMLReader::SetBaseURI(nsIURI *aBaseURI) 1.355 +{ 1.356 + mBaseURI = aBaseURI; 1.357 + return NS_OK; 1.358 +} 1.359 + 1.360 +NS_IMETHODIMP 1.361 +nsSAXXMLReader::GetContentHandler(nsISAXContentHandler **aContentHandler) 1.362 +{ 1.363 + NS_IF_ADDREF(*aContentHandler = mContentHandler); 1.364 + return NS_OK; 1.365 +} 1.366 + 1.367 +NS_IMETHODIMP 1.368 +nsSAXXMLReader::SetContentHandler(nsISAXContentHandler *aContentHandler) 1.369 +{ 1.370 + mContentHandler = aContentHandler; 1.371 + return NS_OK; 1.372 +} 1.373 + 1.374 +NS_IMETHODIMP 1.375 +nsSAXXMLReader::GetDtdHandler(nsISAXDTDHandler **aDtdHandler) 1.376 +{ 1.377 + NS_IF_ADDREF(*aDtdHandler = mDTDHandler); 1.378 + return NS_OK; 1.379 +} 1.380 + 1.381 +NS_IMETHODIMP 1.382 +nsSAXXMLReader::SetDtdHandler(nsISAXDTDHandler *aDtdHandler) 1.383 +{ 1.384 + mDTDHandler = aDtdHandler; 1.385 + return NS_OK; 1.386 +} 1.387 + 1.388 +NS_IMETHODIMP 1.389 +nsSAXXMLReader::GetErrorHandler(nsISAXErrorHandler **aErrorHandler) 1.390 +{ 1.391 + NS_IF_ADDREF(*aErrorHandler = mErrorHandler); 1.392 + return NS_OK; 1.393 +} 1.394 + 1.395 +NS_IMETHODIMP 1.396 +nsSAXXMLReader::SetErrorHandler(nsISAXErrorHandler *aErrorHandler) 1.397 +{ 1.398 + mErrorHandler = aErrorHandler; 1.399 + return NS_OK; 1.400 +} 1.401 + 1.402 +NS_IMETHODIMP 1.403 +nsSAXXMLReader::SetFeature(const nsAString &aName, bool aValue) 1.404 +{ 1.405 + if (aName.EqualsLiteral("http://xml.org/sax/features/namespace-prefixes")) { 1.406 + mEnableNamespacePrefixes = aValue; 1.407 + return NS_OK; 1.408 + } 1.409 + return NS_ERROR_NOT_IMPLEMENTED; 1.410 +} 1.411 + 1.412 +NS_IMETHODIMP 1.413 +nsSAXXMLReader::GetFeature(const nsAString &aName, bool *aResult) 1.414 +{ 1.415 + if (aName.EqualsLiteral("http://xml.org/sax/features/namespace-prefixes")) { 1.416 + *aResult = mEnableNamespacePrefixes; 1.417 + return NS_OK; 1.418 + } 1.419 + return NS_ERROR_NOT_IMPLEMENTED; 1.420 +} 1.421 + 1.422 +NS_IMETHODIMP 1.423 +nsSAXXMLReader::GetDeclarationHandler(nsIMozSAXXMLDeclarationHandler **aDeclarationHandler) { 1.424 + NS_IF_ADDREF(*aDeclarationHandler = mDeclarationHandler); 1.425 + return NS_OK; 1.426 +} 1.427 + 1.428 +NS_IMETHODIMP 1.429 +nsSAXXMLReader::SetDeclarationHandler(nsIMozSAXXMLDeclarationHandler *aDeclarationHandler) { 1.430 + mDeclarationHandler = aDeclarationHandler; 1.431 + return NS_OK; 1.432 +} 1.433 + 1.434 +NS_IMETHODIMP 1.435 +nsSAXXMLReader::GetLexicalHandler(nsISAXLexicalHandler **aLexicalHandler) 1.436 +{ 1.437 + NS_IF_ADDREF(*aLexicalHandler = mLexicalHandler); 1.438 + return NS_OK; 1.439 +} 1.440 + 1.441 +NS_IMETHODIMP 1.442 +nsSAXXMLReader::SetLexicalHandler(nsISAXLexicalHandler *aLexicalHandler) 1.443 +{ 1.444 + mLexicalHandler = aLexicalHandler; 1.445 + return NS_OK; 1.446 +} 1.447 + 1.448 +NS_IMETHODIMP 1.449 +nsSAXXMLReader::SetProperty(const nsAString &aName, nsISupports* aValue) 1.450 +{ 1.451 + return NS_ERROR_NOT_IMPLEMENTED; 1.452 +} 1.453 + 1.454 +NS_IMETHODIMP 1.455 +nsSAXXMLReader::GetProperty(const nsAString &aName, bool *aResult) 1.456 +{ 1.457 + return NS_ERROR_NOT_IMPLEMENTED; 1.458 +} 1.459 + 1.460 +NS_IMETHODIMP 1.461 +nsSAXXMLReader::ParseFromString(const nsAString &aStr, 1.462 + const char *aContentType) 1.463 +{ 1.464 + // Don't call this in the middle of an async parse 1.465 + NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE); 1.466 + 1.467 + NS_ConvertUTF16toUTF8 data(aStr); 1.468 + 1.469 + // The new stream holds a reference to the buffer 1.470 + nsCOMPtr<nsIInputStream> stream; 1.471 + nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), 1.472 + data.get(), data.Length(), 1.473 + NS_ASSIGNMENT_DEPEND); 1.474 + NS_ENSURE_SUCCESS(rv, rv); 1.475 + return ParseFromStream(stream, "UTF-8", aContentType); 1.476 +} 1.477 + 1.478 +NS_IMETHODIMP 1.479 +nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream, 1.480 + const char *aCharset, 1.481 + const char *aContentType) 1.482 +{ 1.483 + // Don't call this in the middle of an async parse 1.484 + NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE); 1.485 + 1.486 + NS_ENSURE_ARG(aStream); 1.487 + NS_ENSURE_ARG(aContentType); 1.488 + 1.489 + // Put the nsCOMPtr out here so we hold a ref to the stream as needed 1.490 + nsresult rv; 1.491 + nsCOMPtr<nsIInputStream> bufferedStream; 1.492 + if (!NS_InputStreamIsBuffered(aStream)) { 1.493 + rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), 1.494 + aStream, 4096); 1.495 + NS_ENSURE_SUCCESS(rv, rv); 1.496 + aStream = bufferedStream; 1.497 + } 1.498 + 1.499 + rv = EnsureBaseURI(); 1.500 + NS_ENSURE_SUCCESS(rv, rv); 1.501 + 1.502 + nsCOMPtr<nsIChannel> parserChannel; 1.503 + rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel), mBaseURI, 1.504 + aStream, nsDependentCString(aContentType)); 1.505 + if (!parserChannel || NS_FAILED(rv)) 1.506 + return NS_ERROR_FAILURE; 1.507 + 1.508 + if (aCharset) 1.509 + parserChannel->SetContentCharset(nsDependentCString(aCharset)); 1.510 + 1.511 + rv = InitParser(nullptr, parserChannel); 1.512 + NS_ENSURE_SUCCESS(rv, rv); 1.513 + 1.514 + rv = mListener->OnStartRequest(parserChannel, nullptr); 1.515 + if (NS_FAILED(rv)) 1.516 + parserChannel->Cancel(rv); 1.517 + 1.518 + /* When parsing a new document, we need to clear the XML identifiers. 1.519 + HandleStartDTD will set these values from the DTD declaration tag. 1.520 + We won't have them, of course, if there's a well-formedness error 1.521 + before the DTD tag (such as a space before an XML declaration). 1.522 + */ 1.523 + mSystemId.Truncate(); 1.524 + mPublicId.Truncate(); 1.525 + 1.526 + nsresult status; 1.527 + parserChannel->GetStatus(&status); 1.528 + 1.529 + uint64_t offset = 0; 1.530 + while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) { 1.531 + uint64_t available; 1.532 + rv = aStream->Available(&available); 1.533 + if (rv == NS_BASE_STREAM_CLOSED) { 1.534 + rv = NS_OK; 1.535 + available = 0; 1.536 + } 1.537 + if (NS_FAILED(rv)) { 1.538 + parserChannel->Cancel(rv); 1.539 + break; 1.540 + } 1.541 + if (! available) 1.542 + break; // blocking input stream has none available when done 1.543 + 1.544 + if (available > UINT32_MAX) 1.545 + available = UINT32_MAX; 1.546 + 1.547 + rv = mListener->OnDataAvailable(parserChannel, nullptr, 1.548 + aStream, 1.549 + offset, 1.550 + (uint32_t)available); 1.551 + if (NS_SUCCEEDED(rv)) 1.552 + offset += available; 1.553 + else 1.554 + parserChannel->Cancel(rv); 1.555 + parserChannel->GetStatus(&status); 1.556 + } 1.557 + rv = mListener->OnStopRequest(parserChannel, nullptr, status); 1.558 + mListener = nullptr; 1.559 + 1.560 + return rv; 1.561 +} 1.562 + 1.563 +NS_IMETHODIMP 1.564 +nsSAXXMLReader::ParseAsync(nsIRequestObserver *aObserver) 1.565 +{ 1.566 + mParserObserver = aObserver; 1.567 + mIsAsyncParse = true; 1.568 + return NS_OK; 1.569 +} 1.570 + 1.571 +// nsIRequestObserver 1.572 + 1.573 +NS_IMETHODIMP 1.574 +nsSAXXMLReader::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) 1.575 +{ 1.576 + NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE); 1.577 + nsresult rv; 1.578 + rv = EnsureBaseURI(); 1.579 + NS_ENSURE_SUCCESS(rv, rv); 1.580 + nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); 1.581 + rv = InitParser(mParserObserver, channel); 1.582 + NS_ENSURE_SUCCESS(rv, rv); 1.583 + // we don't need or want this anymore 1.584 + mParserObserver = nullptr; 1.585 + return mListener->OnStartRequest(aRequest, aContext); 1.586 +} 1.587 + 1.588 +NS_IMETHODIMP 1.589 +nsSAXXMLReader::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, 1.590 + nsresult status) 1.591 +{ 1.592 + NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE); 1.593 + NS_ENSURE_STATE(mListener); 1.594 + nsresult rv = mListener->OnStopRequest(aRequest, aContext, status); 1.595 + mListener = nullptr; 1.596 + mIsAsyncParse = false; 1.597 + return rv; 1.598 +} 1.599 + 1.600 +// nsIStreamListener 1.601 + 1.602 +NS_IMETHODIMP 1.603 +nsSAXXMLReader::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, 1.604 + nsIInputStream *aInputStream, uint64_t offset, 1.605 + uint32_t count) 1.606 +{ 1.607 + NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE); 1.608 + NS_ENSURE_STATE(mListener); 1.609 + return mListener->OnDataAvailable(aRequest, aContext, aInputStream, offset, 1.610 + count); 1.611 +} 1.612 + 1.613 +nsresult 1.614 +nsSAXXMLReader::InitParser(nsIRequestObserver *aObserver, nsIChannel *aChannel) 1.615 +{ 1.616 + nsresult rv; 1.617 + 1.618 + // setup the parser 1.619 + nsCOMPtr<nsIParser> parser = do_CreateInstance(kParserCID, &rv); 1.620 + NS_ENSURE_SUCCESS(rv, rv); 1.621 + 1.622 + parser->SetContentSink(this); 1.623 + 1.624 + int32_t charsetSource = kCharsetFromDocTypeDefault; 1.625 + nsAutoCString charset(NS_LITERAL_CSTRING("UTF-8")); 1.626 + TryChannelCharset(aChannel, charsetSource, charset); 1.627 + parser->SetDocumentCharset(charset, charsetSource); 1.628 + 1.629 + rv = parser->Parse(mBaseURI, aObserver); 1.630 + NS_ENSURE_SUCCESS(rv, rv); 1.631 + 1.632 + mListener = do_QueryInterface(parser, &rv); 1.633 + 1.634 + return rv; 1.635 +} 1.636 + 1.637 +// from nsDocument.cpp 1.638 +bool 1.639 +nsSAXXMLReader::TryChannelCharset(nsIChannel *aChannel, 1.640 + int32_t& aCharsetSource, 1.641 + nsACString& aCharset) 1.642 +{ 1.643 + if (aCharsetSource >= kCharsetFromChannel) 1.644 + return true; 1.645 + 1.646 + if (aChannel) { 1.647 + nsAutoCString charsetVal; 1.648 + nsresult rv = aChannel->GetContentCharset(charsetVal); 1.649 + if (NS_SUCCEEDED(rv)) { 1.650 + nsAutoCString preferred; 1.651 + if (!EncodingUtils::FindEncodingForLabel(charsetVal, preferred)) 1.652 + return false; 1.653 + 1.654 + aCharset = preferred; 1.655 + aCharsetSource = kCharsetFromChannel; 1.656 + return true; 1.657 + } 1.658 + } 1.659 + 1.660 + return false; 1.661 +} 1.662 + 1.663 +nsresult 1.664 +nsSAXXMLReader::EnsureBaseURI() 1.665 +{ 1.666 + if (mBaseURI) 1.667 + return NS_OK; 1.668 + 1.669 + return NS_NewURI(getter_AddRefs(mBaseURI), "about:blank"); 1.670 +} 1.671 + 1.672 +nsresult 1.673 +nsSAXXMLReader::SplitExpatName(const char16_t *aExpatName, 1.674 + nsString &aURI, 1.675 + nsString &aLocalName, 1.676 + nsString &aQName) 1.677 +{ 1.678 + /** 1.679 + * Adapted from RDFContentSinkImpl 1.680 + * 1.681 + * Expat can send the following: 1.682 + * localName 1.683 + * namespaceURI<separator>localName 1.684 + * namespaceURI<separator>localName<separator>prefix 1.685 + * 1.686 + * and we use 0xFFFF for the <separator>. 1.687 + * 1.688 + */ 1.689 + 1.690 + NS_ASSERTION(aExpatName, "null passed to handler"); 1.691 + nsDependentString expatStr(aExpatName); 1.692 + int32_t break1, break2 = kNotFound; 1.693 + break1 = expatStr.FindChar(char16_t(0xFFFF)); 1.694 + 1.695 + if (break1 == kNotFound) { 1.696 + aLocalName = expatStr; // no namespace 1.697 + aURI.Truncate(); 1.698 + aQName = expatStr; 1.699 + } else { 1.700 + aURI = StringHead(expatStr, break1); 1.701 + break2 = expatStr.FindChar(char16_t(0xFFFF), break1 + 1); 1.702 + if (break2 == kNotFound) { // namespace, but no prefix 1.703 + aLocalName = Substring(expatStr, break1 + 1); 1.704 + aQName = aLocalName; 1.705 + } else { // namespace with prefix 1.706 + aLocalName = Substring(expatStr, break1 + 1, break2 - break1 - 1); 1.707 + aQName = Substring(expatStr, break2 + 1) + 1.708 + NS_LITERAL_STRING(":") + aLocalName; 1.709 + } 1.710 + } 1.711 + 1.712 + return NS_OK; 1.713 +}