michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsIInputStream.h" michael@0: #include "nsNetCID.h" michael@0: #include "nsNetUtil.h" michael@0: #include "nsIParser.h" michael@0: #include "nsParserCIID.h" michael@0: #include "nsStreamUtils.h" michael@0: #include "nsStringStream.h" michael@0: #include "nsIScriptError.h" michael@0: #include "nsSAXAttributes.h" michael@0: #include "nsSAXLocator.h" michael@0: #include "nsSAXXMLReader.h" michael@0: #include "nsCharsetSource.h" michael@0: michael@0: #include "mozilla/dom/EncodingUtils.h" michael@0: michael@0: using mozilla::dom::EncodingUtils; michael@0: michael@0: #define XMLNS_URI "http://www.w3.org/2000/xmlns/" michael@0: michael@0: static NS_DEFINE_CID(kParserCID, NS_PARSER_CID); michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION(nsSAXXMLReader, michael@0: mContentHandler, michael@0: mDTDHandler, michael@0: mErrorHandler, michael@0: mLexicalHandler, michael@0: mDeclarationHandler, michael@0: mBaseURI, michael@0: mListener, michael@0: mParserObserver) michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSAXXMLReader) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSAXXMLReader) michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSAXXMLReader) michael@0: NS_INTERFACE_MAP_ENTRY(nsISAXXMLReader) michael@0: NS_INTERFACE_MAP_ENTRY(nsIExpatSink) michael@0: NS_INTERFACE_MAP_ENTRY(nsIExtendedExpatSink) michael@0: NS_INTERFACE_MAP_ENTRY(nsIContentSink) michael@0: NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) michael@0: NS_INTERFACE_MAP_ENTRY(nsIStreamListener) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISAXXMLReader) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: nsSAXXMLReader::nsSAXXMLReader() : michael@0: mIsAsyncParse(false), michael@0: mEnableNamespacePrefixes(false) michael@0: { michael@0: } michael@0: michael@0: // nsIContentSink michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::WillBuildModel(nsDTDMode) michael@0: { michael@0: if (mContentHandler) michael@0: return mContentHandler->StartDocument(); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::DidBuildModel(bool aTerminated) michael@0: { michael@0: if (mContentHandler) michael@0: return mContentHandler->EndDocument(); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::SetParser(nsParserBase *aParser) michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: // nsIExtendedExpatSink michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleStartElement(const char16_t *aName, michael@0: const char16_t **aAtts, michael@0: uint32_t aAttsCount, michael@0: int32_t aIndex, michael@0: uint32_t aLineNumber) michael@0: { michael@0: if (!mContentHandler) michael@0: return NS_OK; michael@0: michael@0: nsRefPtr atts = new nsSAXAttributes(); michael@0: if (!atts) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: nsAutoString uri, localName, qName; michael@0: for (; *aAtts; aAtts += 2) { michael@0: SplitExpatName(aAtts[0], uri, localName, qName); michael@0: // XXX don't have attr type information michael@0: NS_NAMED_LITERAL_STRING(cdataType, "CDATA"); michael@0: // could support xmlns reporting, it's a standard SAX feature michael@0: if (mEnableNamespacePrefixes || !uri.EqualsLiteral(XMLNS_URI)) { michael@0: NS_ASSERTION(aAtts[1], "null passed to handler"); michael@0: atts->AddAttribute(uri, localName, qName, cdataType, michael@0: nsDependentString(aAtts[1])); michael@0: } michael@0: } michael@0: michael@0: // Deal with the element name michael@0: SplitExpatName(aName, uri, localName, qName); michael@0: return mContentHandler->StartElement(uri, localName, qName, atts); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleEndElement(const char16_t *aName) michael@0: { michael@0: if (mContentHandler) { michael@0: nsAutoString uri, localName, qName; michael@0: SplitExpatName(aName, uri, localName, qName); michael@0: return mContentHandler->EndElement(uri, localName, qName); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleComment(const char16_t *aName) michael@0: { michael@0: NS_ASSERTION(aName, "null passed to handler"); michael@0: if (mLexicalHandler) michael@0: return mLexicalHandler->Comment(nsDependentString(aName)); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleCDataSection(const char16_t *aData, michael@0: uint32_t aLength) michael@0: { michael@0: nsresult rv; michael@0: if (mLexicalHandler) { michael@0: rv = mLexicalHandler->StartCDATA(); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: } michael@0: michael@0: if (mContentHandler) { michael@0: rv = mContentHandler->Characters(Substring(aData, aData+aLength)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: } michael@0: michael@0: if (mLexicalHandler) { michael@0: rv = mLexicalHandler->EndCDATA(); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleStartDTD(const char16_t *aName, michael@0: const char16_t *aSystemId, michael@0: const char16_t *aPublicId) michael@0: { michael@0: char16_t nullChar = char16_t(0); michael@0: if (!aName) michael@0: aName = &nullChar; michael@0: if (!aSystemId) michael@0: aSystemId = &nullChar; michael@0: if (!aPublicId) michael@0: aPublicId = &nullChar; michael@0: michael@0: mSystemId = aSystemId; michael@0: mPublicId = aPublicId; michael@0: if (mLexicalHandler) { michael@0: return mLexicalHandler->StartDTD(nsDependentString(aName), michael@0: nsDependentString(aPublicId), michael@0: nsDependentString(aSystemId)); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleDoctypeDecl(const nsAString & aSubset, michael@0: const nsAString & aName, michael@0: const nsAString & aSystemId, michael@0: const nsAString & aPublicId, michael@0: nsISupports* aCatalogData) michael@0: { michael@0: if (mLexicalHandler) michael@0: return mLexicalHandler->EndDTD(); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleCharacterData(const char16_t *aData, michael@0: uint32_t aLength) michael@0: { michael@0: if (mContentHandler) michael@0: return mContentHandler->Characters(Substring(aData, aData+aLength)); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleStartNamespaceDecl(const char16_t *aPrefix, michael@0: const char16_t *aUri) michael@0: { michael@0: if (!mContentHandler) michael@0: return NS_OK; michael@0: michael@0: char16_t nullChar = char16_t(0); michael@0: if (!aPrefix) michael@0: aPrefix = &nullChar; michael@0: if (!aUri) michael@0: aUri = &nullChar; michael@0: michael@0: return mContentHandler->StartPrefixMapping(nsDependentString(aPrefix), michael@0: nsDependentString(aUri)); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleEndNamespaceDecl(const char16_t *aPrefix) michael@0: { michael@0: if (!mContentHandler) michael@0: return NS_OK; michael@0: michael@0: if (aPrefix) michael@0: return mContentHandler->EndPrefixMapping(nsDependentString(aPrefix)); michael@0: michael@0: return mContentHandler->EndPrefixMapping(EmptyString()); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleProcessingInstruction(const char16_t *aTarget, michael@0: const char16_t *aData) michael@0: { michael@0: NS_ASSERTION(aTarget && aData, "null passed to handler"); michael@0: if (mContentHandler) { michael@0: return mContentHandler->ProcessingInstruction(nsDependentString(aTarget), michael@0: nsDependentString(aData)); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleNotationDecl(const char16_t *aNotationName, michael@0: const char16_t *aSystemId, michael@0: const char16_t *aPublicId) michael@0: { michael@0: NS_ASSERTION(aNotationName, "null passed to handler"); michael@0: if (mDTDHandler) { michael@0: char16_t nullChar = char16_t(0); michael@0: if (!aSystemId) michael@0: aSystemId = &nullChar; michael@0: if (!aPublicId) michael@0: aPublicId = &nullChar; michael@0: michael@0: return mDTDHandler->NotationDecl(nsDependentString(aNotationName), michael@0: nsDependentString(aSystemId), michael@0: nsDependentString(aPublicId)); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleUnparsedEntityDecl(const char16_t *aEntityName, michael@0: const char16_t *aSystemId, michael@0: const char16_t *aPublicId, michael@0: const char16_t *aNotationName) michael@0: { michael@0: NS_ASSERTION(aEntityName && aNotationName, "null passed to handler"); michael@0: if (mDTDHandler) { michael@0: char16_t nullChar = char16_t(0); michael@0: if (!aSystemId) michael@0: aSystemId = &nullChar; michael@0: if (!aPublicId) michael@0: aPublicId = &nullChar; michael@0: michael@0: return mDTDHandler->UnparsedEntityDecl(nsDependentString(aEntityName), michael@0: nsDependentString(aSystemId), michael@0: nsDependentString(aPublicId), michael@0: nsDependentString(aNotationName)); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::HandleXMLDeclaration(const char16_t *aVersion, michael@0: const char16_t *aEncoding, michael@0: int32_t aStandalone) michael@0: { michael@0: NS_ASSERTION(aVersion, "null passed to handler"); michael@0: if (mDeclarationHandler) { michael@0: char16_t nullChar = char16_t(0); michael@0: if (!aEncoding) michael@0: aEncoding = &nullChar; michael@0: mDeclarationHandler->HandleXMLDeclaration(nsDependentString(aVersion), michael@0: nsDependentString(aEncoding), michael@0: aStandalone > 0); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::ReportError(const char16_t* aErrorText, michael@0: const char16_t* aSourceText, michael@0: nsIScriptError *aError, michael@0: bool *_retval) michael@0: { michael@0: NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!"); michael@0: // Normally, the expat driver should report the error. michael@0: *_retval = true; michael@0: michael@0: if (mErrorHandler) { michael@0: uint32_t lineNumber; michael@0: nsresult rv = aError->GetLineNumber(&lineNumber); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: uint32_t columnNumber; michael@0: rv = aError->GetColumnNumber(&columnNumber); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr locator = new nsSAXLocator(mPublicId, michael@0: mSystemId, michael@0: lineNumber, michael@0: columnNumber); michael@0: if (!locator) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: rv = mErrorHandler->FatalError(locator, nsDependentString(aErrorText)); michael@0: if (NS_SUCCEEDED(rv)) { michael@0: // The error handler has handled the script error. Don't log to console. michael@0: *_retval = false; michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: // nsISAXXMLReader michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::GetBaseURI(nsIURI **aBaseURI) michael@0: { michael@0: NS_IF_ADDREF(*aBaseURI = mBaseURI); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::SetBaseURI(nsIURI *aBaseURI) michael@0: { michael@0: mBaseURI = aBaseURI; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::GetContentHandler(nsISAXContentHandler **aContentHandler) michael@0: { michael@0: NS_IF_ADDREF(*aContentHandler = mContentHandler); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::SetContentHandler(nsISAXContentHandler *aContentHandler) michael@0: { michael@0: mContentHandler = aContentHandler; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::GetDtdHandler(nsISAXDTDHandler **aDtdHandler) michael@0: { michael@0: NS_IF_ADDREF(*aDtdHandler = mDTDHandler); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::SetDtdHandler(nsISAXDTDHandler *aDtdHandler) michael@0: { michael@0: mDTDHandler = aDtdHandler; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::GetErrorHandler(nsISAXErrorHandler **aErrorHandler) michael@0: { michael@0: NS_IF_ADDREF(*aErrorHandler = mErrorHandler); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::SetErrorHandler(nsISAXErrorHandler *aErrorHandler) michael@0: { michael@0: mErrorHandler = aErrorHandler; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::SetFeature(const nsAString &aName, bool aValue) michael@0: { michael@0: if (aName.EqualsLiteral("http://xml.org/sax/features/namespace-prefixes")) { michael@0: mEnableNamespacePrefixes = aValue; michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::GetFeature(const nsAString &aName, bool *aResult) michael@0: { michael@0: if (aName.EqualsLiteral("http://xml.org/sax/features/namespace-prefixes")) { michael@0: *aResult = mEnableNamespacePrefixes; michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::GetDeclarationHandler(nsIMozSAXXMLDeclarationHandler **aDeclarationHandler) { michael@0: NS_IF_ADDREF(*aDeclarationHandler = mDeclarationHandler); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::SetDeclarationHandler(nsIMozSAXXMLDeclarationHandler *aDeclarationHandler) { michael@0: mDeclarationHandler = aDeclarationHandler; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::GetLexicalHandler(nsISAXLexicalHandler **aLexicalHandler) michael@0: { michael@0: NS_IF_ADDREF(*aLexicalHandler = mLexicalHandler); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::SetLexicalHandler(nsISAXLexicalHandler *aLexicalHandler) michael@0: { michael@0: mLexicalHandler = aLexicalHandler; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::SetProperty(const nsAString &aName, nsISupports* aValue) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::GetProperty(const nsAString &aName, bool *aResult) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::ParseFromString(const nsAString &aStr, michael@0: const char *aContentType) michael@0: { michael@0: // Don't call this in the middle of an async parse michael@0: NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE); michael@0: michael@0: NS_ConvertUTF16toUTF8 data(aStr); michael@0: michael@0: // The new stream holds a reference to the buffer michael@0: nsCOMPtr stream; michael@0: nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), michael@0: data.get(), data.Length(), michael@0: NS_ASSIGNMENT_DEPEND); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: return ParseFromStream(stream, "UTF-8", aContentType); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream, michael@0: const char *aCharset, michael@0: const char *aContentType) michael@0: { michael@0: // Don't call this in the middle of an async parse michael@0: NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE); michael@0: michael@0: NS_ENSURE_ARG(aStream); michael@0: NS_ENSURE_ARG(aContentType); michael@0: michael@0: // Put the nsCOMPtr out here so we hold a ref to the stream as needed michael@0: nsresult rv; michael@0: nsCOMPtr bufferedStream; michael@0: if (!NS_InputStreamIsBuffered(aStream)) { michael@0: rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), michael@0: aStream, 4096); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: aStream = bufferedStream; michael@0: } michael@0: michael@0: rv = EnsureBaseURI(); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr parserChannel; michael@0: rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel), mBaseURI, michael@0: aStream, nsDependentCString(aContentType)); michael@0: if (!parserChannel || NS_FAILED(rv)) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: if (aCharset) michael@0: parserChannel->SetContentCharset(nsDependentCString(aCharset)); michael@0: michael@0: rv = InitParser(nullptr, parserChannel); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = mListener->OnStartRequest(parserChannel, nullptr); michael@0: if (NS_FAILED(rv)) michael@0: parserChannel->Cancel(rv); michael@0: michael@0: /* When parsing a new document, we need to clear the XML identifiers. michael@0: HandleStartDTD will set these values from the DTD declaration tag. michael@0: We won't have them, of course, if there's a well-formedness error michael@0: before the DTD tag (such as a space before an XML declaration). michael@0: */ michael@0: mSystemId.Truncate(); michael@0: mPublicId.Truncate(); michael@0: michael@0: nsresult status; michael@0: parserChannel->GetStatus(&status); michael@0: michael@0: uint64_t offset = 0; michael@0: while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) { michael@0: uint64_t available; michael@0: rv = aStream->Available(&available); michael@0: if (rv == NS_BASE_STREAM_CLOSED) { michael@0: rv = NS_OK; michael@0: available = 0; michael@0: } michael@0: if (NS_FAILED(rv)) { michael@0: parserChannel->Cancel(rv); michael@0: break; michael@0: } michael@0: if (! available) michael@0: break; // blocking input stream has none available when done michael@0: michael@0: if (available > UINT32_MAX) michael@0: available = UINT32_MAX; michael@0: michael@0: rv = mListener->OnDataAvailable(parserChannel, nullptr, michael@0: aStream, michael@0: offset, michael@0: (uint32_t)available); michael@0: if (NS_SUCCEEDED(rv)) michael@0: offset += available; michael@0: else michael@0: parserChannel->Cancel(rv); michael@0: parserChannel->GetStatus(&status); michael@0: } michael@0: rv = mListener->OnStopRequest(parserChannel, nullptr, status); michael@0: mListener = nullptr; michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::ParseAsync(nsIRequestObserver *aObserver) michael@0: { michael@0: mParserObserver = aObserver; michael@0: mIsAsyncParse = true; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // nsIRequestObserver michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) michael@0: { michael@0: NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE); michael@0: nsresult rv; michael@0: rv = EnsureBaseURI(); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: nsCOMPtr channel = do_QueryInterface(aRequest); michael@0: rv = InitParser(mParserObserver, channel); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: // we don't need or want this anymore michael@0: mParserObserver = nullptr; michael@0: return mListener->OnStartRequest(aRequest, aContext); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, michael@0: nsresult status) michael@0: { michael@0: NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE); michael@0: NS_ENSURE_STATE(mListener); michael@0: nsresult rv = mListener->OnStopRequest(aRequest, aContext, status); michael@0: mListener = nullptr; michael@0: mIsAsyncParse = false; michael@0: return rv; michael@0: } michael@0: michael@0: // nsIStreamListener michael@0: michael@0: NS_IMETHODIMP michael@0: nsSAXXMLReader::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, michael@0: nsIInputStream *aInputStream, uint64_t offset, michael@0: uint32_t count) michael@0: { michael@0: NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE); michael@0: NS_ENSURE_STATE(mListener); michael@0: return mListener->OnDataAvailable(aRequest, aContext, aInputStream, offset, michael@0: count); michael@0: } michael@0: michael@0: nsresult michael@0: nsSAXXMLReader::InitParser(nsIRequestObserver *aObserver, nsIChannel *aChannel) michael@0: { michael@0: nsresult rv; michael@0: michael@0: // setup the parser michael@0: nsCOMPtr parser = do_CreateInstance(kParserCID, &rv); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: parser->SetContentSink(this); michael@0: michael@0: int32_t charsetSource = kCharsetFromDocTypeDefault; michael@0: nsAutoCString charset(NS_LITERAL_CSTRING("UTF-8")); michael@0: TryChannelCharset(aChannel, charsetSource, charset); michael@0: parser->SetDocumentCharset(charset, charsetSource); michael@0: michael@0: rv = parser->Parse(mBaseURI, aObserver); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: mListener = do_QueryInterface(parser, &rv); michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: // from nsDocument.cpp michael@0: bool michael@0: nsSAXXMLReader::TryChannelCharset(nsIChannel *aChannel, michael@0: int32_t& aCharsetSource, michael@0: nsACString& aCharset) michael@0: { michael@0: if (aCharsetSource >= kCharsetFromChannel) michael@0: return true; michael@0: michael@0: if (aChannel) { michael@0: nsAutoCString charsetVal; michael@0: nsresult rv = aChannel->GetContentCharset(charsetVal); michael@0: if (NS_SUCCEEDED(rv)) { michael@0: nsAutoCString preferred; michael@0: if (!EncodingUtils::FindEncodingForLabel(charsetVal, preferred)) michael@0: return false; michael@0: michael@0: aCharset = preferred; michael@0: aCharsetSource = kCharsetFromChannel; michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: nsresult michael@0: nsSAXXMLReader::EnsureBaseURI() michael@0: { michael@0: if (mBaseURI) michael@0: return NS_OK; michael@0: michael@0: return NS_NewURI(getter_AddRefs(mBaseURI), "about:blank"); michael@0: } michael@0: michael@0: nsresult michael@0: nsSAXXMLReader::SplitExpatName(const char16_t *aExpatName, michael@0: nsString &aURI, michael@0: nsString &aLocalName, michael@0: nsString &aQName) michael@0: { michael@0: /** michael@0: * Adapted from RDFContentSinkImpl michael@0: * michael@0: * Expat can send the following: michael@0: * localName michael@0: * namespaceURIlocalName michael@0: * namespaceURIlocalNameprefix michael@0: * michael@0: * and we use 0xFFFF for the . michael@0: * michael@0: */ michael@0: michael@0: NS_ASSERTION(aExpatName, "null passed to handler"); michael@0: nsDependentString expatStr(aExpatName); michael@0: int32_t break1, break2 = kNotFound; michael@0: break1 = expatStr.FindChar(char16_t(0xFFFF)); michael@0: michael@0: if (break1 == kNotFound) { michael@0: aLocalName = expatStr; // no namespace michael@0: aURI.Truncate(); michael@0: aQName = expatStr; michael@0: } else { michael@0: aURI = StringHead(expatStr, break1); michael@0: break2 = expatStr.FindChar(char16_t(0xFFFF), break1 + 1); michael@0: if (break2 == kNotFound) { // namespace, but no prefix michael@0: aLocalName = Substring(expatStr, break1 + 1); michael@0: aQName = aLocalName; michael@0: } else { // namespace with prefix michael@0: aLocalName = Substring(expatStr, break1 + 1, break2 - break1 - 1); michael@0: aQName = Substring(expatStr, break2 + 1) + michael@0: NS_LITERAL_STRING(":") + aLocalName; michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: }