Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/xml/XMLDocument.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
8
#include "mozilla/dom/XMLDocument.h"
9
#include "nsParserCIID.h"
10
#include "nsCharsetSource.h"
11
#include "nsIXMLContentSink.h"
12
#include "nsPresContext.h"
13
#include "nsIContent.h"
14
#include "nsIContentViewer.h"
15
#include "nsIDocShell.h"
16
#include "nsHTMLParts.h"
17
#include "nsIComponentManager.h"
18
#include "nsIBaseWindow.h"
19
#include "nsIDOMWindow.h"
20
#include "nsCOMPtr.h"
21
#include "nsString.h"
22
#include "nsIHttpChannelInternal.h"
23
#include "nsIURI.h"
24
#include "nsIServiceManager.h"
25
#include "nsNetUtil.h"
26
#include "nsError.h"
27
#include "nsIScriptSecurityManager.h"
28
#include "nsIPrincipal.h"
29
#include "nsLayoutCID.h"
30
#include "mozilla/dom/Attr.h"
31
#include "nsCExternalHandlerService.h"
32
#include "nsMimeTypes.h"
33
#include "mozilla/EventListenerManager.h"
34
#include "nsContentUtils.h"
35
#include "nsThreadUtils.h"
36
#include "nsJSUtils.h"
37
#include "nsCRT.h"
38
#include "nsIAuthPrompt.h"
39
#include "nsContentCreatorFunctions.h"
40
#include "nsContentPolicyUtils.h"
41
#include "nsNodeUtils.h"
42
#include "nsIConsoleService.h"
43
#include "nsIScriptError.h"
44
#include "nsIHTMLDocument.h"
45
#include "mozilla/BasicEvents.h"
46
#include "mozilla/EventDispatcher.h"
47
#include "mozilla/dom/DocumentType.h"
48
#include "mozilla/dom/Element.h"
49
#include "mozilla/dom/XMLDocumentBinding.h"
50
#include "mozilla/dom/DocumentBinding.h"
51
52
using namespace mozilla;
53
using namespace mozilla::dom;
54
55
// ==================================================================
56
// =
57
// ==================================================================
58
59
60
nsresult
61
NS_NewDOMDocument(nsIDocument** aInstancePtrResult,
62
                  const nsAString& aNamespaceURI,
63
                  const nsAString& aQualifiedName,
64
                  DocumentType* aDoctype,
65
                  nsIURI* aDocumentURI,
66
                  nsIURI* aBaseURI,
67
                  nsIPrincipal* aPrincipal,
68
                  bool aLoadedAsData,
69
                  nsIGlobalObject* aEventObject,
70
                  DocumentFlavor aFlavor)
71
0
{
72
0
  // Note: can't require that aDocumentURI/aBaseURI/aPrincipal be non-null,
73
0
  // since at least one caller (XMLHttpRequest) doesn't have decent args to
74
0
  // pass in.
75
0
76
0
  nsresult rv;
77
0
78
0
  *aInstancePtrResult = nullptr;
79
0
80
0
  nsCOMPtr<nsIDocument> d;
81
0
  bool isHTML = false;
82
0
  bool isXHTML = false;
83
0
  if (aFlavor == DocumentFlavorSVG) {
84
0
    rv = NS_NewSVGDocument(getter_AddRefs(d));
85
0
  } else if (aFlavor == DocumentFlavorHTML) {
86
0
    rv = NS_NewHTMLDocument(getter_AddRefs(d));
87
0
    isHTML = true;
88
0
  } else if (aFlavor == DocumentFlavorPlain) {
89
0
    rv = NS_NewXMLDocument(getter_AddRefs(d), aLoadedAsData, true);
90
0
  } else if (aDoctype) {
91
0
    MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess);
92
0
    nsAutoString publicId, name;
93
0
    aDoctype->GetPublicId(publicId);
94
0
    if (publicId.IsEmpty()) {
95
0
      aDoctype->GetName(name);
96
0
    }
97
0
    if (name.EqualsLiteral("html") ||
98
0
        publicId.EqualsLiteral("-//W3C//DTD HTML 4.01//EN") ||
99
0
        publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Frameset//EN") ||
100
0
        publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Transitional//EN") ||
101
0
        publicId.EqualsLiteral("-//W3C//DTD HTML 4.0//EN") ||
102
0
        publicId.EqualsLiteral("-//W3C//DTD HTML 4.0 Frameset//EN") ||
103
0
        publicId.EqualsLiteral("-//W3C//DTD HTML 4.0 Transitional//EN")) {
104
0
      rv = NS_NewHTMLDocument(getter_AddRefs(d));
105
0
      isHTML = true;
106
0
    } else if (publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Strict//EN") ||
107
0
               publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Transitional//EN") ||
108
0
               publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Frameset//EN")) {
109
0
      rv = NS_NewHTMLDocument(getter_AddRefs(d));
110
0
      isHTML = true;
111
0
      isXHTML = true;
112
0
    }
113
0
    else if (publicId.EqualsLiteral("-//W3C//DTD SVG 1.1//EN")) {
114
0
      rv = NS_NewSVGDocument(getter_AddRefs(d));
115
0
    }
116
0
    // XXX Add support for XUL documents.
117
0
    else {
118
0
      rv = NS_NewXMLDocument(getter_AddRefs(d));
119
0
    }
120
0
  } else {
121
0
    MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess);
122
0
    rv = NS_NewXMLDocument(getter_AddRefs(d));
123
0
  }
124
0
125
0
  if (NS_FAILED(rv)) {
126
0
    return rv;
127
0
  }
128
0
129
0
  if (isHTML) {
130
0
    nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(d);
131
0
    NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?");
132
0
    htmlDoc->SetCompatibilityMode(eCompatibility_FullStandards);
133
0
    htmlDoc->SetIsXHTML(isXHTML);
134
0
  }
135
0
  nsDocument* doc = static_cast<nsDocument*>(d.get());
136
0
  doc->SetLoadedAsData(aLoadedAsData);
137
0
  doc->nsDocument::SetDocumentURI(aDocumentURI);
138
0
  // Must set the principal first, since SetBaseURI checks it.
139
0
  doc->SetPrincipal(aPrincipal);
140
0
  doc->SetBaseURI(aBaseURI);
141
0
142
0
  // We need to set the script handling object after we set the principal such
143
0
  // that the doc group is assigned correctly.
144
0
  if (nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aEventObject)) {
145
0
    d->SetScriptHandlingObject(sgo);
146
0
  } else if (aEventObject){
147
0
    d->SetScopeObject(aEventObject);
148
0
  }
149
0
150
0
  // XMLDocuments and documents "created in memory" get to be UTF-8 by default,
151
0
  // unlike the legacy HTML mess
152
0
  doc->SetDocumentCharacterSet(UTF_8_ENCODING);
153
0
154
0
  if (aDoctype) {
155
0
    ErrorResult result;
156
0
    d->AppendChild(*aDoctype, result);
157
0
    // Need to WouldReportJSException() if our callee can throw a JS
158
0
    // exception (which it can) and we're neither propagating the
159
0
    // error out nor unconditionally suppressing it.
160
0
    result.WouldReportJSException();
161
0
    if (NS_WARN_IF(result.Failed())) {
162
0
      return result.StealNSResult();
163
0
    }
164
0
  }
165
0
166
0
  if (!aQualifiedName.IsEmpty()) {
167
0
    ErrorResult result;
168
0
    ElementCreationOptionsOrString options;
169
0
    options.SetAsString();
170
0
171
0
    nsCOMPtr<Element> root =
172
0
      doc->CreateElementNS(aNamespaceURI, aQualifiedName, options, result);
173
0
    if (NS_WARN_IF(result.Failed())) {
174
0
      return result.StealNSResult();
175
0
    }
176
0
177
0
    d->AppendChild(*root, result);
178
0
    // Need to WouldReportJSException() if our callee can throw a JS
179
0
    // exception (which it can) and we're neither propagating the
180
0
    // error out nor unconditionally suppressing it.
181
0
    result.WouldReportJSException();
182
0
    if (NS_WARN_IF(result.Failed())) {
183
0
      return result.StealNSResult();
184
0
    }
185
0
  }
186
0
187
0
  d.forget(aInstancePtrResult);
188
0
189
0
  return NS_OK;
190
0
}
191
192
nsresult
193
NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData,
194
                  bool aIsPlainDocument)
195
0
{
196
0
  RefPtr<XMLDocument> doc = new XMLDocument();
197
0
198
0
  nsresult rv = doc->Init();
199
0
200
0
  if (NS_FAILED(rv)) {
201
0
    *aInstancePtrResult = nullptr;
202
0
    return rv;
203
0
  }
204
0
205
0
  doc->SetLoadedAsData(aLoadedAsData);
206
0
  doc->mIsPlainDocument = aIsPlainDocument;
207
0
  doc.forget(aInstancePtrResult);
208
0
209
0
  return NS_OK;
210
0
}
211
212
nsresult
213
NS_NewXBLDocument(nsIDocument** aInstancePtrResult,
214
                  nsIURI* aDocumentURI,
215
                  nsIURI* aBaseURI,
216
                  nsIPrincipal* aPrincipal)
217
0
{
218
0
  nsresult rv = NS_NewDOMDocument(aInstancePtrResult,
219
0
                                  NS_LITERAL_STRING("http://www.mozilla.org/xbl"),
220
0
                                  NS_LITERAL_STRING("bindings"), nullptr,
221
0
                                  aDocumentURI, aBaseURI, aPrincipal, false,
222
0
                                  nullptr, DocumentFlavorLegacyGuess);
223
0
  NS_ENSURE_SUCCESS(rv, rv);
224
0
225
0
  nsIDocument* idoc = *aInstancePtrResult;
226
0
227
0
  // XBL documents must allow XUL and XBL elements in them but the usual check
228
0
  // only checks if the document is loaded in the system principal which is
229
0
  // sometimes not the case.
230
0
  idoc->ForceEnableXULXBL();
231
0
232
0
  nsDocument* doc = static_cast<nsDocument*>(idoc);
233
0
  doc->SetLoadedAsInteractiveData(true);
234
0
  doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
235
0
236
0
  return NS_OK;
237
0
}
238
239
namespace mozilla {
240
namespace dom {
241
242
XMLDocument::XMLDocument(const char* aContentType)
243
  : nsDocument(aContentType),
244
    mChannelIsPending(false),
245
    mAsync(true),
246
    mLoopingForSyncLoad(false),
247
    mIsPlainDocument(false),
248
    mSuppressParserErrorElement(false),
249
    mSuppressParserErrorConsoleMessages(false)
250
0
{
251
0
  mType = eGenericXML;
252
0
}
253
254
XMLDocument::~XMLDocument()
255
0
{
256
0
  // XXX We rather crash than hang
257
0
  mLoopingForSyncLoad = false;
258
0
}
259
260
nsresult
261
XMLDocument::Init()
262
0
{
263
0
  nsresult rv = nsDocument::Init();
264
0
  NS_ENSURE_SUCCESS(rv, rv);
265
0
266
0
  return rv;
267
0
}
268
269
void
270
XMLDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
271
0
{
272
0
  nsDocument::Reset(aChannel, aLoadGroup);
273
0
}
274
275
void
276
XMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
277
                        nsIPrincipal* aPrincipal)
278
0
{
279
0
  if (mChannelIsPending) {
280
0
    StopDocumentLoad();
281
0
    mChannel->Cancel(NS_BINDING_ABORTED);
282
0
    mChannelIsPending = false;
283
0
  }
284
0
285
0
  nsDocument::ResetToURI(aURI, aLoadGroup, aPrincipal);
286
0
}
287
288
bool
289
XMLDocument::Load(const nsAString& aUrl, CallerType aCallerType,
290
                  ErrorResult& aRv)
291
0
{
292
0
  bool hasHadScriptObject = true;
293
0
  nsIScriptGlobalObject* scriptObject =
294
0
    GetScriptHandlingObject(hasHadScriptObject);
295
0
  if (!scriptObject && hasHadScriptObject) {
296
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
297
0
    return false;
298
0
  }
299
0
300
0
  nsCOMPtr<nsIDocument> callingDoc = GetEntryDocument();
301
0
  nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
302
0
303
0
  // The callingDoc's Principal and doc's Principal should be the same
304
0
  if (callingDoc && (callingDoc->NodePrincipal() != principal)) {
305
0
    nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
306
0
                                    NS_LITERAL_CSTRING("DOM"),
307
0
                                    callingDoc,
308
0
                                    nsContentUtils::eDOM_PROPERTIES,
309
0
                                    "XMLDocumentLoadPrincipalMismatch");
310
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
311
0
    return false;
312
0
  }
313
0
314
0
  // Reporting a warning on ourselves is rather pointless, because we probably
315
0
  // have no window id (and hence the warning won't show up in any web console)
316
0
  // and probably aren't considered a "content document" because we're not
317
0
  // loaded in a docshell, so won't accumulate telemetry for use counters.  Try
318
0
  // warning on our entry document, if any, since that should have things like
319
0
  // window ids and associated docshells.
320
0
  nsIDocument* docForWarning = callingDoc ? callingDoc.get() : this;
321
0
  if (aCallerType == CallerType::System) {
322
0
    docForWarning->WarnOnceAbout(nsIDocument::eChromeUseOfDOM3LoadMethod);
323
0
  } else {
324
0
    docForWarning->WarnOnceAbout(nsIDocument::eUseOfDOM3LoadMethod);
325
0
  }
326
0
327
0
  nsIURI *baseURI = mDocumentURI;
328
0
  nsAutoCString charset;
329
0
330
0
  if (callingDoc) {
331
0
    baseURI = callingDoc->GetDocBaseURI();
332
0
    callingDoc->GetDocumentCharacterSet()->Name(charset);
333
0
  }
334
0
335
0
  // Create a new URI
336
0
  nsCOMPtr<nsIURI> uri;
337
0
  nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, charset.get(), baseURI);
338
0
  if (NS_FAILED(rv)) {
339
0
    aRv.Throw(rv);
340
0
    return false;
341
0
  }
342
0
343
0
  if (nsContentUtils::IsSystemPrincipal(principal)) {
344
0
    // We're called from chrome, check to make sure the URI we're
345
0
    // about to load is also chrome.
346
0
347
0
    bool isChrome = false;
348
0
    if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) {
349
0
350
0
      nsAutoString error;
351
0
      error.AssignLiteral("Cross site loading using document.load is no "
352
0
                          "longer supported. Use XMLHttpRequest instead.");
353
0
      nsCOMPtr<nsIScriptError> errorObject =
354
0
          do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
355
0
      if (NS_FAILED(rv)) {
356
0
        aRv.Throw(rv);
357
0
        return false;
358
0
      }
359
0
360
0
      rv = errorObject->InitWithSourceURI(error,
361
0
                                          mDocumentURI,
362
0
                                          EmptyString(),
363
0
                                          0, 0,
364
0
                                          nsIScriptError::warningFlag,
365
0
                                          "DOM",
366
0
                                          callingDoc ?
367
0
                                          callingDoc->InnerWindowID() :
368
0
                                          this->InnerWindowID());
369
0
370
0
      if (NS_FAILED(rv)) {
371
0
        aRv.Throw(rv);
372
0
        return false;
373
0
      }
374
0
375
0
      nsCOMPtr<nsIConsoleService> consoleService =
376
0
        do_GetService(NS_CONSOLESERVICE_CONTRACTID);
377
0
      if (consoleService) {
378
0
        consoleService->LogMessage(errorObject);
379
0
      }
380
0
381
0
      aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
382
0
      return false;
383
0
    }
384
0
  }
385
0
386
0
  // Partial Reset, need to restore principal for security reasons and
387
0
  // event listener manager so that load listeners etc. will
388
0
  // remain. This should be done before the security check is done to
389
0
  // ensure that the document is reset even if the new document can't
390
0
  // be loaded.  Note that we need to hold a strong ref to |principal|
391
0
  // here, because ResetToURI will null out our node principal before
392
0
  // setting the new one.
393
0
  RefPtr<EventListenerManager> elm(mListenerManager);
394
0
  mListenerManager = nullptr;
395
0
396
0
  // When we are called from JS we can find the load group for the page,
397
0
  // and add ourselves to it. This way any pending requests
398
0
  // will be automatically aborted if the user leaves the page.
399
0
400
0
  nsCOMPtr<nsILoadGroup> loadGroup;
401
0
  if (callingDoc) {
402
0
    loadGroup = callingDoc->GetDocumentLoadGroup();
403
0
  }
404
0
405
0
  ResetToURI(uri, loadGroup, principal);
406
0
407
0
  mListenerManager = elm;
408
0
409
0
  // Create a channel
410
0
  nsCOMPtr<nsIInterfaceRequestor> req = nsContentUtils::SameOriginChecker();
411
0
412
0
  nsCOMPtr<nsIChannel> channel;
413
0
  // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active,
414
0
  // which in turn keeps STOP button from becoming active
415
0
  rv = NS_NewChannel(getter_AddRefs(channel),
416
0
                     uri,
417
0
                     callingDoc ? callingDoc.get() :
418
0
                                  static_cast<nsIDocument*>(this),
419
0
                     nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
420
0
                     nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
421
0
                     nullptr, // aPerformanceStorage
422
0
                     loadGroup,
423
0
                     req,
424
0
                     nsIRequest::LOAD_BACKGROUND);
425
0
426
0
  if (NS_FAILED(rv)) {
427
0
    aRv.Throw(rv);
428
0
    return false;
429
0
  }
430
0
431
0
  // TODO Bug 1189945: Remove nsIChannel CorsMode flag and set Request.mode
432
0
  // based on nsILoadInfo securityFlags instead. This block will be removed
433
0
  // when Request.mode set correctly.
434
0
  nsCOMPtr<nsIHttpChannelInternal> httpChannel = do_QueryInterface(channel);
435
0
  if (httpChannel) {
436
0
    rv = httpChannel->SetCorsMode(nsIHttpChannelInternal::CORS_MODE_SAME_ORIGIN);
437
0
    MOZ_ASSERT(NS_SUCCEEDED(rv));
438
0
  }
439
0
440
0
  // StartDocumentLoad asserts that readyState is uninitialized, so
441
0
  // uninitialize it. SetReadyStateInternal make this transition invisible to
442
0
  // Web content. But before doing that, assert that the current readyState
443
0
  // is complete as it should be after the call to ResetToURI() above.
444
0
  MOZ_ASSERT(GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE,
445
0
             "Bad readyState");
446
0
  SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED);
447
0
448
0
  // Prepare for loading the XML document "into oneself"
449
0
  nsCOMPtr<nsIStreamListener> listener;
450
0
  if (NS_FAILED(rv = StartDocumentLoad(kLoadAsData, channel,
451
0
                                       loadGroup, nullptr,
452
0
                                       getter_AddRefs(listener),
453
0
                                       false))) {
454
0
    NS_ERROR("XMLDocument::Load: Failed to start the document load.");
455
0
    aRv.Throw(rv);
456
0
    return false;
457
0
  }
458
0
459
0
  // After this point, if we error out of this method we should clear
460
0
  // mChannelIsPending.
461
0
462
0
  // Start an asynchronous read of the XML document
463
0
  rv = channel->AsyncOpen2(listener);
464
0
  if (NS_FAILED(rv)) {
465
0
    mChannelIsPending = false;
466
0
    aRv.Throw(rv);
467
0
    return false;
468
0
  }
469
0
470
0
  if (!mAsync) {
471
0
    nsAutoSyncOperation sync(this);
472
0
    mLoopingForSyncLoad = true;
473
0
    SpinEventLoopUntil([&]() { return !mLoopingForSyncLoad; });
474
0
475
0
    // We set return to true unless there was a parsing error
476
0
    Element* rootElement = GetRootElement();
477
0
    if (!rootElement) {
478
0
      return false;
479
0
    }
480
0
481
0
    if (rootElement->LocalName().EqualsLiteral("parsererror")) {
482
0
      nsAutoString ns;
483
0
      rootElement->GetNamespaceURI(ns);
484
0
      if (ns.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) {
485
0
        return false;
486
0
      }
487
0
    }
488
0
  }
489
0
490
0
  return true;
491
0
}
492
493
void
494
XMLDocument::SetSuppressParserErrorElement(bool aSuppress)
495
0
{
496
0
  mSuppressParserErrorElement = aSuppress;
497
0
}
498
499
bool
500
XMLDocument::SuppressParserErrorElement()
501
0
{
502
0
  return mSuppressParserErrorElement;
503
0
}
504
505
void
506
XMLDocument::SetSuppressParserErrorConsoleMessages(bool aSuppress)
507
0
{
508
0
  mSuppressParserErrorConsoleMessages = aSuppress;
509
0
}
510
511
bool
512
XMLDocument::SuppressParserErrorConsoleMessages()
513
0
{
514
0
  return mSuppressParserErrorConsoleMessages;
515
0
}
516
517
nsresult
518
XMLDocument::StartDocumentLoad(const char* aCommand,
519
                               nsIChannel* aChannel,
520
                               nsILoadGroup* aLoadGroup,
521
                               nsISupports* aContainer,
522
                               nsIStreamListener **aDocListener,
523
                               bool aReset,
524
                               nsIContentSink* aSink)
525
0
{
526
0
  nsresult rv = nsDocument::StartDocumentLoad(aCommand,
527
0
                                              aChannel, aLoadGroup,
528
0
                                              aContainer,
529
0
                                              aDocListener, aReset, aSink);
530
0
  if (NS_FAILED(rv)) return rv;
531
0
532
0
  if (nsCRT::strcmp("loadAsInteractiveData", aCommand) == 0) {
533
0
    mLoadedAsInteractiveData = true;
534
0
    aCommand = kLoadAsData; // XBL, for example, needs scripts and styles
535
0
  }
536
0
537
0
538
0
  int32_t charsetSource = kCharsetFromDocTypeDefault;
539
0
  NotNull<const Encoding*> encoding = UTF_8_ENCODING;
540
0
  TryChannelCharset(aChannel, charsetSource, encoding, nullptr);
541
0
542
0
  nsCOMPtr<nsIURI> aUrl;
543
0
  rv = aChannel->GetURI(getter_AddRefs(aUrl));
544
0
  if (NS_FAILED(rv)) return rv;
545
0
546
0
  static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
547
0
548
0
  mParser = do_CreateInstance(kCParserCID, &rv);
549
0
  NS_ENSURE_SUCCESS(rv, rv);
550
0
551
0
  nsCOMPtr<nsIXMLContentSink> sink;
552
0
553
0
  if (aSink) {
554
0
    sink = do_QueryInterface(aSink);
555
0
  }
556
0
  else {
557
0
    nsCOMPtr<nsIDocShell> docShell;
558
0
    if (aContainer) {
559
0
      docShell = do_QueryInterface(aContainer);
560
0
      NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
561
0
    }
562
0
    rv = NS_NewXMLContentSink(getter_AddRefs(sink), this, aUrl, docShell,
563
0
                              aChannel);
564
0
    NS_ENSURE_SUCCESS(rv, rv);
565
0
  }
566
0
567
0
  // Set the parser as the stream listener for the document loader...
568
0
  rv = CallQueryInterface(mParser, aDocListener);
569
0
  NS_ENSURE_SUCCESS(rv, rv);
570
0
571
0
  NS_ASSERTION(mChannel, "How can we not have a channel here?");
572
0
  mChannelIsPending = true;
573
0
574
0
  SetDocumentCharacterSet(encoding);
575
0
  mParser->SetDocumentCharset(encoding, charsetSource);
576
0
  mParser->SetCommand(aCommand);
577
0
  mParser->SetContentSink(sink);
578
0
  mParser->Parse(aUrl, nullptr, (void *)this);
579
0
580
0
  return NS_OK;
581
0
}
582
583
void
584
XMLDocument::EndLoad()
585
0
{
586
0
  mChannelIsPending = false;
587
0
  mLoopingForSyncLoad = false;
588
0
589
0
  mSynchronousDOMContentLoaded = (mLoadedAsData || mLoadedAsInteractiveData);
590
0
  nsDocument::EndLoad();
591
0
  if (mSynchronousDOMContentLoaded) {
592
0
    mSynchronousDOMContentLoaded = false;
593
0
    nsDocument::SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
594
0
    // Generate a document load event for the case when an XML
595
0
    // document was loaded as pure data without any presentation
596
0
    // attached to it.
597
0
    WidgetEvent event(true, eLoad);
598
0
    EventDispatcher::Dispatch(static_cast<nsIDocument*>(this), nullptr, &event);
599
0
  }
600
0
}
601
602
/* virtual */ void
603
XMLDocument::DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const
604
0
{
605
0
  nsDocument::DocAddSizeOfExcludingThis(aWindowSizes);
606
0
}
607
608
// nsIDocument interface
609
610
nsresult
611
XMLDocument::Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const
612
0
{
613
0
  NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
614
0
               "Can't import this document into another document!");
615
0
616
0
  RefPtr<XMLDocument> clone = new XMLDocument();
617
0
  nsresult rv = CloneDocHelper(clone);
618
0
  NS_ENSURE_SUCCESS(rv, rv);
619
0
620
0
  // State from XMLDocument
621
0
  clone->mAsync = mAsync;
622
0
  clone->mIsPlainDocument = mIsPlainDocument;
623
0
624
0
  return CallQueryInterface(clone.get(), aResult);
625
0
}
626
627
JSObject*
628
XMLDocument::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
629
0
{
630
0
  if (mIsPlainDocument) {
631
0
    return Document_Binding::Wrap(aCx, this, aGivenProto);
632
0
  }
633
0
634
0
  return XMLDocument_Binding::Wrap(aCx, this, aGivenProto);
635
0
}
636
637
} // namespace dom
638
} // namespace mozilla