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