parser/xml/src/nsSAXXMLReader.cpp

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsIInputStream.h"
michael@0 7 #include "nsNetCID.h"
michael@0 8 #include "nsNetUtil.h"
michael@0 9 #include "nsIParser.h"
michael@0 10 #include "nsParserCIID.h"
michael@0 11 #include "nsStreamUtils.h"
michael@0 12 #include "nsStringStream.h"
michael@0 13 #include "nsIScriptError.h"
michael@0 14 #include "nsSAXAttributes.h"
michael@0 15 #include "nsSAXLocator.h"
michael@0 16 #include "nsSAXXMLReader.h"
michael@0 17 #include "nsCharsetSource.h"
michael@0 18
michael@0 19 #include "mozilla/dom/EncodingUtils.h"
michael@0 20
michael@0 21 using mozilla::dom::EncodingUtils;
michael@0 22
michael@0 23 #define XMLNS_URI "http://www.w3.org/2000/xmlns/"
michael@0 24
michael@0 25 static NS_DEFINE_CID(kParserCID, NS_PARSER_CID);
michael@0 26
michael@0 27 NS_IMPL_CYCLE_COLLECTION(nsSAXXMLReader,
michael@0 28 mContentHandler,
michael@0 29 mDTDHandler,
michael@0 30 mErrorHandler,
michael@0 31 mLexicalHandler,
michael@0 32 mDeclarationHandler,
michael@0 33 mBaseURI,
michael@0 34 mListener,
michael@0 35 mParserObserver)
michael@0 36 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSAXXMLReader)
michael@0 37 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSAXXMLReader)
michael@0 38 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSAXXMLReader)
michael@0 39 NS_INTERFACE_MAP_ENTRY(nsISAXXMLReader)
michael@0 40 NS_INTERFACE_MAP_ENTRY(nsIExpatSink)
michael@0 41 NS_INTERFACE_MAP_ENTRY(nsIExtendedExpatSink)
michael@0 42 NS_INTERFACE_MAP_ENTRY(nsIContentSink)
michael@0 43 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
michael@0 44 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
michael@0 45 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISAXXMLReader)
michael@0 46 NS_INTERFACE_MAP_END
michael@0 47
michael@0 48 nsSAXXMLReader::nsSAXXMLReader() :
michael@0 49 mIsAsyncParse(false),
michael@0 50 mEnableNamespacePrefixes(false)
michael@0 51 {
michael@0 52 }
michael@0 53
michael@0 54 // nsIContentSink
michael@0 55 NS_IMETHODIMP
michael@0 56 nsSAXXMLReader::WillBuildModel(nsDTDMode)
michael@0 57 {
michael@0 58 if (mContentHandler)
michael@0 59 return mContentHandler->StartDocument();
michael@0 60
michael@0 61 return NS_OK;
michael@0 62 }
michael@0 63
michael@0 64 NS_IMETHODIMP
michael@0 65 nsSAXXMLReader::DidBuildModel(bool aTerminated)
michael@0 66 {
michael@0 67 if (mContentHandler)
michael@0 68 return mContentHandler->EndDocument();
michael@0 69
michael@0 70 return NS_OK;
michael@0 71 }
michael@0 72
michael@0 73 NS_IMETHODIMP
michael@0 74 nsSAXXMLReader::SetParser(nsParserBase *aParser)
michael@0 75 {
michael@0 76 return NS_OK;
michael@0 77 }
michael@0 78
michael@0 79 // nsIExtendedExpatSink
michael@0 80 NS_IMETHODIMP
michael@0 81 nsSAXXMLReader::HandleStartElement(const char16_t *aName,
michael@0 82 const char16_t **aAtts,
michael@0 83 uint32_t aAttsCount,
michael@0 84 int32_t aIndex,
michael@0 85 uint32_t aLineNumber)
michael@0 86 {
michael@0 87 if (!mContentHandler)
michael@0 88 return NS_OK;
michael@0 89
michael@0 90 nsRefPtr<nsSAXAttributes> atts = new nsSAXAttributes();
michael@0 91 if (!atts)
michael@0 92 return NS_ERROR_OUT_OF_MEMORY;
michael@0 93 nsAutoString uri, localName, qName;
michael@0 94 for (; *aAtts; aAtts += 2) {
michael@0 95 SplitExpatName(aAtts[0], uri, localName, qName);
michael@0 96 // XXX don't have attr type information
michael@0 97 NS_NAMED_LITERAL_STRING(cdataType, "CDATA");
michael@0 98 // could support xmlns reporting, it's a standard SAX feature
michael@0 99 if (mEnableNamespacePrefixes || !uri.EqualsLiteral(XMLNS_URI)) {
michael@0 100 NS_ASSERTION(aAtts[1], "null passed to handler");
michael@0 101 atts->AddAttribute(uri, localName, qName, cdataType,
michael@0 102 nsDependentString(aAtts[1]));
michael@0 103 }
michael@0 104 }
michael@0 105
michael@0 106 // Deal with the element name
michael@0 107 SplitExpatName(aName, uri, localName, qName);
michael@0 108 return mContentHandler->StartElement(uri, localName, qName, atts);
michael@0 109 }
michael@0 110
michael@0 111 NS_IMETHODIMP
michael@0 112 nsSAXXMLReader::HandleEndElement(const char16_t *aName)
michael@0 113 {
michael@0 114 if (mContentHandler) {
michael@0 115 nsAutoString uri, localName, qName;
michael@0 116 SplitExpatName(aName, uri, localName, qName);
michael@0 117 return mContentHandler->EndElement(uri, localName, qName);
michael@0 118 }
michael@0 119 return NS_OK;
michael@0 120 }
michael@0 121
michael@0 122 NS_IMETHODIMP
michael@0 123 nsSAXXMLReader::HandleComment(const char16_t *aName)
michael@0 124 {
michael@0 125 NS_ASSERTION(aName, "null passed to handler");
michael@0 126 if (mLexicalHandler)
michael@0 127 return mLexicalHandler->Comment(nsDependentString(aName));
michael@0 128
michael@0 129 return NS_OK;
michael@0 130 }
michael@0 131
michael@0 132 NS_IMETHODIMP
michael@0 133 nsSAXXMLReader::HandleCDataSection(const char16_t *aData,
michael@0 134 uint32_t aLength)
michael@0 135 {
michael@0 136 nsresult rv;
michael@0 137 if (mLexicalHandler) {
michael@0 138 rv = mLexicalHandler->StartCDATA();
michael@0 139 NS_ENSURE_SUCCESS(rv, rv);
michael@0 140 }
michael@0 141
michael@0 142 if (mContentHandler) {
michael@0 143 rv = mContentHandler->Characters(Substring(aData, aData+aLength));
michael@0 144 NS_ENSURE_SUCCESS(rv, rv);
michael@0 145 }
michael@0 146
michael@0 147 if (mLexicalHandler) {
michael@0 148 rv = mLexicalHandler->EndCDATA();
michael@0 149 NS_ENSURE_SUCCESS(rv, rv);
michael@0 150 }
michael@0 151
michael@0 152 return NS_OK;
michael@0 153 }
michael@0 154
michael@0 155 NS_IMETHODIMP
michael@0 156 nsSAXXMLReader::HandleStartDTD(const char16_t *aName,
michael@0 157 const char16_t *aSystemId,
michael@0 158 const char16_t *aPublicId)
michael@0 159 {
michael@0 160 char16_t nullChar = char16_t(0);
michael@0 161 if (!aName)
michael@0 162 aName = &nullChar;
michael@0 163 if (!aSystemId)
michael@0 164 aSystemId = &nullChar;
michael@0 165 if (!aPublicId)
michael@0 166 aPublicId = &nullChar;
michael@0 167
michael@0 168 mSystemId = aSystemId;
michael@0 169 mPublicId = aPublicId;
michael@0 170 if (mLexicalHandler) {
michael@0 171 return mLexicalHandler->StartDTD(nsDependentString(aName),
michael@0 172 nsDependentString(aPublicId),
michael@0 173 nsDependentString(aSystemId));
michael@0 174 }
michael@0 175
michael@0 176 return NS_OK;
michael@0 177 }
michael@0 178
michael@0 179 NS_IMETHODIMP
michael@0 180 nsSAXXMLReader::HandleDoctypeDecl(const nsAString & aSubset,
michael@0 181 const nsAString & aName,
michael@0 182 const nsAString & aSystemId,
michael@0 183 const nsAString & aPublicId,
michael@0 184 nsISupports* aCatalogData)
michael@0 185 {
michael@0 186 if (mLexicalHandler)
michael@0 187 return mLexicalHandler->EndDTD();
michael@0 188
michael@0 189 return NS_OK;
michael@0 190 }
michael@0 191
michael@0 192 NS_IMETHODIMP
michael@0 193 nsSAXXMLReader::HandleCharacterData(const char16_t *aData,
michael@0 194 uint32_t aLength)
michael@0 195 {
michael@0 196 if (mContentHandler)
michael@0 197 return mContentHandler->Characters(Substring(aData, aData+aLength));
michael@0 198
michael@0 199 return NS_OK;
michael@0 200 }
michael@0 201
michael@0 202 NS_IMETHODIMP
michael@0 203 nsSAXXMLReader::HandleStartNamespaceDecl(const char16_t *aPrefix,
michael@0 204 const char16_t *aUri)
michael@0 205 {
michael@0 206 if (!mContentHandler)
michael@0 207 return NS_OK;
michael@0 208
michael@0 209 char16_t nullChar = char16_t(0);
michael@0 210 if (!aPrefix)
michael@0 211 aPrefix = &nullChar;
michael@0 212 if (!aUri)
michael@0 213 aUri = &nullChar;
michael@0 214
michael@0 215 return mContentHandler->StartPrefixMapping(nsDependentString(aPrefix),
michael@0 216 nsDependentString(aUri));
michael@0 217 }
michael@0 218
michael@0 219 NS_IMETHODIMP
michael@0 220 nsSAXXMLReader::HandleEndNamespaceDecl(const char16_t *aPrefix)
michael@0 221 {
michael@0 222 if (!mContentHandler)
michael@0 223 return NS_OK;
michael@0 224
michael@0 225 if (aPrefix)
michael@0 226 return mContentHandler->EndPrefixMapping(nsDependentString(aPrefix));
michael@0 227
michael@0 228 return mContentHandler->EndPrefixMapping(EmptyString());
michael@0 229 }
michael@0 230
michael@0 231 NS_IMETHODIMP
michael@0 232 nsSAXXMLReader::HandleProcessingInstruction(const char16_t *aTarget,
michael@0 233 const char16_t *aData)
michael@0 234 {
michael@0 235 NS_ASSERTION(aTarget && aData, "null passed to handler");
michael@0 236 if (mContentHandler) {
michael@0 237 return mContentHandler->ProcessingInstruction(nsDependentString(aTarget),
michael@0 238 nsDependentString(aData));
michael@0 239 }
michael@0 240
michael@0 241 return NS_OK;
michael@0 242 }
michael@0 243
michael@0 244 NS_IMETHODIMP
michael@0 245 nsSAXXMLReader::HandleNotationDecl(const char16_t *aNotationName,
michael@0 246 const char16_t *aSystemId,
michael@0 247 const char16_t *aPublicId)
michael@0 248 {
michael@0 249 NS_ASSERTION(aNotationName, "null passed to handler");
michael@0 250 if (mDTDHandler) {
michael@0 251 char16_t nullChar = char16_t(0);
michael@0 252 if (!aSystemId)
michael@0 253 aSystemId = &nullChar;
michael@0 254 if (!aPublicId)
michael@0 255 aPublicId = &nullChar;
michael@0 256
michael@0 257 return mDTDHandler->NotationDecl(nsDependentString(aNotationName),
michael@0 258 nsDependentString(aSystemId),
michael@0 259 nsDependentString(aPublicId));
michael@0 260 }
michael@0 261
michael@0 262 return NS_OK;
michael@0 263 }
michael@0 264
michael@0 265 NS_IMETHODIMP
michael@0 266 nsSAXXMLReader::HandleUnparsedEntityDecl(const char16_t *aEntityName,
michael@0 267 const char16_t *aSystemId,
michael@0 268 const char16_t *aPublicId,
michael@0 269 const char16_t *aNotationName)
michael@0 270 {
michael@0 271 NS_ASSERTION(aEntityName && aNotationName, "null passed to handler");
michael@0 272 if (mDTDHandler) {
michael@0 273 char16_t nullChar = char16_t(0);
michael@0 274 if (!aSystemId)
michael@0 275 aSystemId = &nullChar;
michael@0 276 if (!aPublicId)
michael@0 277 aPublicId = &nullChar;
michael@0 278
michael@0 279 return mDTDHandler->UnparsedEntityDecl(nsDependentString(aEntityName),
michael@0 280 nsDependentString(aSystemId),
michael@0 281 nsDependentString(aPublicId),
michael@0 282 nsDependentString(aNotationName));
michael@0 283 }
michael@0 284
michael@0 285 return NS_OK;
michael@0 286 }
michael@0 287
michael@0 288 NS_IMETHODIMP
michael@0 289 nsSAXXMLReader::HandleXMLDeclaration(const char16_t *aVersion,
michael@0 290 const char16_t *aEncoding,
michael@0 291 int32_t aStandalone)
michael@0 292 {
michael@0 293 NS_ASSERTION(aVersion, "null passed to handler");
michael@0 294 if (mDeclarationHandler) {
michael@0 295 char16_t nullChar = char16_t(0);
michael@0 296 if (!aEncoding)
michael@0 297 aEncoding = &nullChar;
michael@0 298 mDeclarationHandler->HandleXMLDeclaration(nsDependentString(aVersion),
michael@0 299 nsDependentString(aEncoding),
michael@0 300 aStandalone > 0);
michael@0 301 }
michael@0 302 return NS_OK;
michael@0 303 }
michael@0 304
michael@0 305 NS_IMETHODIMP
michael@0 306 nsSAXXMLReader::ReportError(const char16_t* aErrorText,
michael@0 307 const char16_t* aSourceText,
michael@0 308 nsIScriptError *aError,
michael@0 309 bool *_retval)
michael@0 310 {
michael@0 311 NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!");
michael@0 312 // Normally, the expat driver should report the error.
michael@0 313 *_retval = true;
michael@0 314
michael@0 315 if (mErrorHandler) {
michael@0 316 uint32_t lineNumber;
michael@0 317 nsresult rv = aError->GetLineNumber(&lineNumber);
michael@0 318 NS_ENSURE_SUCCESS(rv, rv);
michael@0 319
michael@0 320 uint32_t columnNumber;
michael@0 321 rv = aError->GetColumnNumber(&columnNumber);
michael@0 322 NS_ENSURE_SUCCESS(rv, rv);
michael@0 323
michael@0 324 nsCOMPtr<nsISAXLocator> locator = new nsSAXLocator(mPublicId,
michael@0 325 mSystemId,
michael@0 326 lineNumber,
michael@0 327 columnNumber);
michael@0 328 if (!locator)
michael@0 329 return NS_ERROR_OUT_OF_MEMORY;
michael@0 330
michael@0 331 rv = mErrorHandler->FatalError(locator, nsDependentString(aErrorText));
michael@0 332 if (NS_SUCCEEDED(rv)) {
michael@0 333 // The error handler has handled the script error. Don't log to console.
michael@0 334 *_retval = false;
michael@0 335 }
michael@0 336 }
michael@0 337
michael@0 338 return NS_OK;
michael@0 339 }
michael@0 340
michael@0 341 // nsISAXXMLReader
michael@0 342
michael@0 343 NS_IMETHODIMP
michael@0 344 nsSAXXMLReader::GetBaseURI(nsIURI **aBaseURI)
michael@0 345 {
michael@0 346 NS_IF_ADDREF(*aBaseURI = mBaseURI);
michael@0 347 return NS_OK;
michael@0 348 }
michael@0 349
michael@0 350 NS_IMETHODIMP
michael@0 351 nsSAXXMLReader::SetBaseURI(nsIURI *aBaseURI)
michael@0 352 {
michael@0 353 mBaseURI = aBaseURI;
michael@0 354 return NS_OK;
michael@0 355 }
michael@0 356
michael@0 357 NS_IMETHODIMP
michael@0 358 nsSAXXMLReader::GetContentHandler(nsISAXContentHandler **aContentHandler)
michael@0 359 {
michael@0 360 NS_IF_ADDREF(*aContentHandler = mContentHandler);
michael@0 361 return NS_OK;
michael@0 362 }
michael@0 363
michael@0 364 NS_IMETHODIMP
michael@0 365 nsSAXXMLReader::SetContentHandler(nsISAXContentHandler *aContentHandler)
michael@0 366 {
michael@0 367 mContentHandler = aContentHandler;
michael@0 368 return NS_OK;
michael@0 369 }
michael@0 370
michael@0 371 NS_IMETHODIMP
michael@0 372 nsSAXXMLReader::GetDtdHandler(nsISAXDTDHandler **aDtdHandler)
michael@0 373 {
michael@0 374 NS_IF_ADDREF(*aDtdHandler = mDTDHandler);
michael@0 375 return NS_OK;
michael@0 376 }
michael@0 377
michael@0 378 NS_IMETHODIMP
michael@0 379 nsSAXXMLReader::SetDtdHandler(nsISAXDTDHandler *aDtdHandler)
michael@0 380 {
michael@0 381 mDTDHandler = aDtdHandler;
michael@0 382 return NS_OK;
michael@0 383 }
michael@0 384
michael@0 385 NS_IMETHODIMP
michael@0 386 nsSAXXMLReader::GetErrorHandler(nsISAXErrorHandler **aErrorHandler)
michael@0 387 {
michael@0 388 NS_IF_ADDREF(*aErrorHandler = mErrorHandler);
michael@0 389 return NS_OK;
michael@0 390 }
michael@0 391
michael@0 392 NS_IMETHODIMP
michael@0 393 nsSAXXMLReader::SetErrorHandler(nsISAXErrorHandler *aErrorHandler)
michael@0 394 {
michael@0 395 mErrorHandler = aErrorHandler;
michael@0 396 return NS_OK;
michael@0 397 }
michael@0 398
michael@0 399 NS_IMETHODIMP
michael@0 400 nsSAXXMLReader::SetFeature(const nsAString &aName, bool aValue)
michael@0 401 {
michael@0 402 if (aName.EqualsLiteral("http://xml.org/sax/features/namespace-prefixes")) {
michael@0 403 mEnableNamespacePrefixes = aValue;
michael@0 404 return NS_OK;
michael@0 405 }
michael@0 406 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 407 }
michael@0 408
michael@0 409 NS_IMETHODIMP
michael@0 410 nsSAXXMLReader::GetFeature(const nsAString &aName, bool *aResult)
michael@0 411 {
michael@0 412 if (aName.EqualsLiteral("http://xml.org/sax/features/namespace-prefixes")) {
michael@0 413 *aResult = mEnableNamespacePrefixes;
michael@0 414 return NS_OK;
michael@0 415 }
michael@0 416 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 417 }
michael@0 418
michael@0 419 NS_IMETHODIMP
michael@0 420 nsSAXXMLReader::GetDeclarationHandler(nsIMozSAXXMLDeclarationHandler **aDeclarationHandler) {
michael@0 421 NS_IF_ADDREF(*aDeclarationHandler = mDeclarationHandler);
michael@0 422 return NS_OK;
michael@0 423 }
michael@0 424
michael@0 425 NS_IMETHODIMP
michael@0 426 nsSAXXMLReader::SetDeclarationHandler(nsIMozSAXXMLDeclarationHandler *aDeclarationHandler) {
michael@0 427 mDeclarationHandler = aDeclarationHandler;
michael@0 428 return NS_OK;
michael@0 429 }
michael@0 430
michael@0 431 NS_IMETHODIMP
michael@0 432 nsSAXXMLReader::GetLexicalHandler(nsISAXLexicalHandler **aLexicalHandler)
michael@0 433 {
michael@0 434 NS_IF_ADDREF(*aLexicalHandler = mLexicalHandler);
michael@0 435 return NS_OK;
michael@0 436 }
michael@0 437
michael@0 438 NS_IMETHODIMP
michael@0 439 nsSAXXMLReader::SetLexicalHandler(nsISAXLexicalHandler *aLexicalHandler)
michael@0 440 {
michael@0 441 mLexicalHandler = aLexicalHandler;
michael@0 442 return NS_OK;
michael@0 443 }
michael@0 444
michael@0 445 NS_IMETHODIMP
michael@0 446 nsSAXXMLReader::SetProperty(const nsAString &aName, nsISupports* aValue)
michael@0 447 {
michael@0 448 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 449 }
michael@0 450
michael@0 451 NS_IMETHODIMP
michael@0 452 nsSAXXMLReader::GetProperty(const nsAString &aName, bool *aResult)
michael@0 453 {
michael@0 454 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 455 }
michael@0 456
michael@0 457 NS_IMETHODIMP
michael@0 458 nsSAXXMLReader::ParseFromString(const nsAString &aStr,
michael@0 459 const char *aContentType)
michael@0 460 {
michael@0 461 // Don't call this in the middle of an async parse
michael@0 462 NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
michael@0 463
michael@0 464 NS_ConvertUTF16toUTF8 data(aStr);
michael@0 465
michael@0 466 // The new stream holds a reference to the buffer
michael@0 467 nsCOMPtr<nsIInputStream> stream;
michael@0 468 nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
michael@0 469 data.get(), data.Length(),
michael@0 470 NS_ASSIGNMENT_DEPEND);
michael@0 471 NS_ENSURE_SUCCESS(rv, rv);
michael@0 472 return ParseFromStream(stream, "UTF-8", aContentType);
michael@0 473 }
michael@0 474
michael@0 475 NS_IMETHODIMP
michael@0 476 nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
michael@0 477 const char *aCharset,
michael@0 478 const char *aContentType)
michael@0 479 {
michael@0 480 // Don't call this in the middle of an async parse
michael@0 481 NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
michael@0 482
michael@0 483 NS_ENSURE_ARG(aStream);
michael@0 484 NS_ENSURE_ARG(aContentType);
michael@0 485
michael@0 486 // Put the nsCOMPtr out here so we hold a ref to the stream as needed
michael@0 487 nsresult rv;
michael@0 488 nsCOMPtr<nsIInputStream> bufferedStream;
michael@0 489 if (!NS_InputStreamIsBuffered(aStream)) {
michael@0 490 rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
michael@0 491 aStream, 4096);
michael@0 492 NS_ENSURE_SUCCESS(rv, rv);
michael@0 493 aStream = bufferedStream;
michael@0 494 }
michael@0 495
michael@0 496 rv = EnsureBaseURI();
michael@0 497 NS_ENSURE_SUCCESS(rv, rv);
michael@0 498
michael@0 499 nsCOMPtr<nsIChannel> parserChannel;
michael@0 500 rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel), mBaseURI,
michael@0 501 aStream, nsDependentCString(aContentType));
michael@0 502 if (!parserChannel || NS_FAILED(rv))
michael@0 503 return NS_ERROR_FAILURE;
michael@0 504
michael@0 505 if (aCharset)
michael@0 506 parserChannel->SetContentCharset(nsDependentCString(aCharset));
michael@0 507
michael@0 508 rv = InitParser(nullptr, parserChannel);
michael@0 509 NS_ENSURE_SUCCESS(rv, rv);
michael@0 510
michael@0 511 rv = mListener->OnStartRequest(parserChannel, nullptr);
michael@0 512 if (NS_FAILED(rv))
michael@0 513 parserChannel->Cancel(rv);
michael@0 514
michael@0 515 /* When parsing a new document, we need to clear the XML identifiers.
michael@0 516 HandleStartDTD will set these values from the DTD declaration tag.
michael@0 517 We won't have them, of course, if there's a well-formedness error
michael@0 518 before the DTD tag (such as a space before an XML declaration).
michael@0 519 */
michael@0 520 mSystemId.Truncate();
michael@0 521 mPublicId.Truncate();
michael@0 522
michael@0 523 nsresult status;
michael@0 524 parserChannel->GetStatus(&status);
michael@0 525
michael@0 526 uint64_t offset = 0;
michael@0 527 while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
michael@0 528 uint64_t available;
michael@0 529 rv = aStream->Available(&available);
michael@0 530 if (rv == NS_BASE_STREAM_CLOSED) {
michael@0 531 rv = NS_OK;
michael@0 532 available = 0;
michael@0 533 }
michael@0 534 if (NS_FAILED(rv)) {
michael@0 535 parserChannel->Cancel(rv);
michael@0 536 break;
michael@0 537 }
michael@0 538 if (! available)
michael@0 539 break; // blocking input stream has none available when done
michael@0 540
michael@0 541 if (available > UINT32_MAX)
michael@0 542 available = UINT32_MAX;
michael@0 543
michael@0 544 rv = mListener->OnDataAvailable(parserChannel, nullptr,
michael@0 545 aStream,
michael@0 546 offset,
michael@0 547 (uint32_t)available);
michael@0 548 if (NS_SUCCEEDED(rv))
michael@0 549 offset += available;
michael@0 550 else
michael@0 551 parserChannel->Cancel(rv);
michael@0 552 parserChannel->GetStatus(&status);
michael@0 553 }
michael@0 554 rv = mListener->OnStopRequest(parserChannel, nullptr, status);
michael@0 555 mListener = nullptr;
michael@0 556
michael@0 557 return rv;
michael@0 558 }
michael@0 559
michael@0 560 NS_IMETHODIMP
michael@0 561 nsSAXXMLReader::ParseAsync(nsIRequestObserver *aObserver)
michael@0 562 {
michael@0 563 mParserObserver = aObserver;
michael@0 564 mIsAsyncParse = true;
michael@0 565 return NS_OK;
michael@0 566 }
michael@0 567
michael@0 568 // nsIRequestObserver
michael@0 569
michael@0 570 NS_IMETHODIMP
michael@0 571 nsSAXXMLReader::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
michael@0 572 {
michael@0 573 NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
michael@0 574 nsresult rv;
michael@0 575 rv = EnsureBaseURI();
michael@0 576 NS_ENSURE_SUCCESS(rv, rv);
michael@0 577 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
michael@0 578 rv = InitParser(mParserObserver, channel);
michael@0 579 NS_ENSURE_SUCCESS(rv, rv);
michael@0 580 // we don't need or want this anymore
michael@0 581 mParserObserver = nullptr;
michael@0 582 return mListener->OnStartRequest(aRequest, aContext);
michael@0 583 }
michael@0 584
michael@0 585 NS_IMETHODIMP
michael@0 586 nsSAXXMLReader::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
michael@0 587 nsresult status)
michael@0 588 {
michael@0 589 NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
michael@0 590 NS_ENSURE_STATE(mListener);
michael@0 591 nsresult rv = mListener->OnStopRequest(aRequest, aContext, status);
michael@0 592 mListener = nullptr;
michael@0 593 mIsAsyncParse = false;
michael@0 594 return rv;
michael@0 595 }
michael@0 596
michael@0 597 // nsIStreamListener
michael@0 598
michael@0 599 NS_IMETHODIMP
michael@0 600 nsSAXXMLReader::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
michael@0 601 nsIInputStream *aInputStream, uint64_t offset,
michael@0 602 uint32_t count)
michael@0 603 {
michael@0 604 NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
michael@0 605 NS_ENSURE_STATE(mListener);
michael@0 606 return mListener->OnDataAvailable(aRequest, aContext, aInputStream, offset,
michael@0 607 count);
michael@0 608 }
michael@0 609
michael@0 610 nsresult
michael@0 611 nsSAXXMLReader::InitParser(nsIRequestObserver *aObserver, nsIChannel *aChannel)
michael@0 612 {
michael@0 613 nsresult rv;
michael@0 614
michael@0 615 // setup the parser
michael@0 616 nsCOMPtr<nsIParser> parser = do_CreateInstance(kParserCID, &rv);
michael@0 617 NS_ENSURE_SUCCESS(rv, rv);
michael@0 618
michael@0 619 parser->SetContentSink(this);
michael@0 620
michael@0 621 int32_t charsetSource = kCharsetFromDocTypeDefault;
michael@0 622 nsAutoCString charset(NS_LITERAL_CSTRING("UTF-8"));
michael@0 623 TryChannelCharset(aChannel, charsetSource, charset);
michael@0 624 parser->SetDocumentCharset(charset, charsetSource);
michael@0 625
michael@0 626 rv = parser->Parse(mBaseURI, aObserver);
michael@0 627 NS_ENSURE_SUCCESS(rv, rv);
michael@0 628
michael@0 629 mListener = do_QueryInterface(parser, &rv);
michael@0 630
michael@0 631 return rv;
michael@0 632 }
michael@0 633
michael@0 634 // from nsDocument.cpp
michael@0 635 bool
michael@0 636 nsSAXXMLReader::TryChannelCharset(nsIChannel *aChannel,
michael@0 637 int32_t& aCharsetSource,
michael@0 638 nsACString& aCharset)
michael@0 639 {
michael@0 640 if (aCharsetSource >= kCharsetFromChannel)
michael@0 641 return true;
michael@0 642
michael@0 643 if (aChannel) {
michael@0 644 nsAutoCString charsetVal;
michael@0 645 nsresult rv = aChannel->GetContentCharset(charsetVal);
michael@0 646 if (NS_SUCCEEDED(rv)) {
michael@0 647 nsAutoCString preferred;
michael@0 648 if (!EncodingUtils::FindEncodingForLabel(charsetVal, preferred))
michael@0 649 return false;
michael@0 650
michael@0 651 aCharset = preferred;
michael@0 652 aCharsetSource = kCharsetFromChannel;
michael@0 653 return true;
michael@0 654 }
michael@0 655 }
michael@0 656
michael@0 657 return false;
michael@0 658 }
michael@0 659
michael@0 660 nsresult
michael@0 661 nsSAXXMLReader::EnsureBaseURI()
michael@0 662 {
michael@0 663 if (mBaseURI)
michael@0 664 return NS_OK;
michael@0 665
michael@0 666 return NS_NewURI(getter_AddRefs(mBaseURI), "about:blank");
michael@0 667 }
michael@0 668
michael@0 669 nsresult
michael@0 670 nsSAXXMLReader::SplitExpatName(const char16_t *aExpatName,
michael@0 671 nsString &aURI,
michael@0 672 nsString &aLocalName,
michael@0 673 nsString &aQName)
michael@0 674 {
michael@0 675 /**
michael@0 676 * Adapted from RDFContentSinkImpl
michael@0 677 *
michael@0 678 * Expat can send the following:
michael@0 679 * localName
michael@0 680 * namespaceURI<separator>localName
michael@0 681 * namespaceURI<separator>localName<separator>prefix
michael@0 682 *
michael@0 683 * and we use 0xFFFF for the <separator>.
michael@0 684 *
michael@0 685 */
michael@0 686
michael@0 687 NS_ASSERTION(aExpatName, "null passed to handler");
michael@0 688 nsDependentString expatStr(aExpatName);
michael@0 689 int32_t break1, break2 = kNotFound;
michael@0 690 break1 = expatStr.FindChar(char16_t(0xFFFF));
michael@0 691
michael@0 692 if (break1 == kNotFound) {
michael@0 693 aLocalName = expatStr; // no namespace
michael@0 694 aURI.Truncate();
michael@0 695 aQName = expatStr;
michael@0 696 } else {
michael@0 697 aURI = StringHead(expatStr, break1);
michael@0 698 break2 = expatStr.FindChar(char16_t(0xFFFF), break1 + 1);
michael@0 699 if (break2 == kNotFound) { // namespace, but no prefix
michael@0 700 aLocalName = Substring(expatStr, break1 + 1);
michael@0 701 aQName = aLocalName;
michael@0 702 } else { // namespace with prefix
michael@0 703 aLocalName = Substring(expatStr, break1 + 1, break2 - break1 - 1);
michael@0 704 aQName = Substring(expatStr, break2 + 1) +
michael@0 705 NS_LITERAL_STRING(":") + aLocalName;
michael@0 706 }
michael@0 707 }
michael@0 708
michael@0 709 return NS_OK;
michael@0 710 }

mercurial