|
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 |
|
7 #include "mozilla/dom/XMLDocument.h" |
|
8 #include "nsParserCIID.h" |
|
9 #include "nsCharsetSource.h" |
|
10 #include "nsIXMLContentSink.h" |
|
11 #include "nsPresContext.h" |
|
12 #include "nsIContent.h" |
|
13 #include "nsIContentViewerContainer.h" |
|
14 #include "nsIContentViewer.h" |
|
15 #include "nsIDocShell.h" |
|
16 #include "nsIMarkupDocumentViewer.h" |
|
17 #include "nsHTMLParts.h" |
|
18 #include "nsIComponentManager.h" |
|
19 #include "nsIDOMElement.h" |
|
20 #include "nsIBaseWindow.h" |
|
21 #include "nsIDOMWindow.h" |
|
22 #include "nsIDOMDocumentType.h" |
|
23 #include "nsCOMPtr.h" |
|
24 #include "nsXPIDLString.h" |
|
25 #include "nsIHttpChannel.h" |
|
26 #include "nsIURI.h" |
|
27 #include "nsIServiceManager.h" |
|
28 #include "nsNetUtil.h" |
|
29 #include "nsError.h" |
|
30 #include "nsIScriptSecurityManager.h" |
|
31 #include "nsIPrincipal.h" |
|
32 #include "nsLayoutCID.h" |
|
33 #include "mozilla/dom/Attr.h" |
|
34 #include "nsCExternalHandlerService.h" |
|
35 #include "nsMimeTypes.h" |
|
36 #include "mozilla/EventListenerManager.h" |
|
37 #include "nsContentUtils.h" |
|
38 #include "nsThreadUtils.h" |
|
39 #include "nsJSUtils.h" |
|
40 #include "nsCRT.h" |
|
41 #include "nsIAuthPrompt.h" |
|
42 #include "nsContentCreatorFunctions.h" |
|
43 #include "nsContentPolicyUtils.h" |
|
44 #include "nsIDOMUserDataHandler.h" |
|
45 #include "nsNodeUtils.h" |
|
46 #include "nsIConsoleService.h" |
|
47 #include "nsIScriptError.h" |
|
48 #include "nsIHTMLDocument.h" |
|
49 #include "mozilla/BasicEvents.h" |
|
50 #include "mozilla/EventDispatcher.h" |
|
51 #include "mozilla/dom/Element.h" |
|
52 #include "mozilla/dom/XMLDocumentBinding.h" |
|
53 |
|
54 using namespace mozilla; |
|
55 using namespace mozilla::dom; |
|
56 |
|
57 // ================================================================== |
|
58 // = |
|
59 // ================================================================== |
|
60 |
|
61 |
|
62 nsresult |
|
63 NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult, |
|
64 const nsAString& aNamespaceURI, |
|
65 const nsAString& aQualifiedName, |
|
66 nsIDOMDocumentType* aDoctype, |
|
67 nsIURI* aDocumentURI, |
|
68 nsIURI* aBaseURI, |
|
69 nsIPrincipal* aPrincipal, |
|
70 bool aLoadedAsData, |
|
71 nsIGlobalObject* aEventObject, |
|
72 DocumentFlavor aFlavor) |
|
73 { |
|
74 // Note: can't require that aDocumentURI/aBaseURI/aPrincipal be non-null, |
|
75 // since at least one caller (XMLHttpRequest) doesn't have decent args to |
|
76 // pass in. |
|
77 |
|
78 nsresult rv; |
|
79 |
|
80 *aInstancePtrResult = nullptr; |
|
81 |
|
82 nsCOMPtr<nsIDocument> d; |
|
83 bool isHTML = false; |
|
84 bool isXHTML = false; |
|
85 if (aFlavor == DocumentFlavorSVG) { |
|
86 rv = NS_NewSVGDocument(getter_AddRefs(d)); |
|
87 } else if (aFlavor == DocumentFlavorHTML) { |
|
88 rv = NS_NewHTMLDocument(getter_AddRefs(d)); |
|
89 isHTML = true; |
|
90 } else if (aDoctype) { |
|
91 nsAutoString publicId, name; |
|
92 aDoctype->GetPublicId(publicId); |
|
93 if (publicId.IsEmpty()) { |
|
94 aDoctype->GetName(name); |
|
95 } |
|
96 if (name.EqualsLiteral("html") || |
|
97 publicId.EqualsLiteral("-//W3C//DTD HTML 4.01//EN") || |
|
98 publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Frameset//EN") || |
|
99 publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Transitional//EN") || |
|
100 publicId.EqualsLiteral("-//W3C//DTD HTML 4.0//EN") || |
|
101 publicId.EqualsLiteral("-//W3C//DTD HTML 4.0 Frameset//EN") || |
|
102 publicId.EqualsLiteral("-//W3C//DTD HTML 4.0 Transitional//EN")) { |
|
103 rv = NS_NewHTMLDocument(getter_AddRefs(d)); |
|
104 isHTML = true; |
|
105 } else if (publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Strict//EN") || |
|
106 publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Transitional//EN") || |
|
107 publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Frameset//EN")) { |
|
108 rv = NS_NewHTMLDocument(getter_AddRefs(d)); |
|
109 isHTML = true; |
|
110 isXHTML = true; |
|
111 } |
|
112 else if (publicId.EqualsLiteral("-//W3C//DTD SVG 1.1//EN")) { |
|
113 rv = NS_NewSVGDocument(getter_AddRefs(d)); |
|
114 } |
|
115 // XXX Add support for XUL documents. |
|
116 else { |
|
117 rv = NS_NewXMLDocument(getter_AddRefs(d)); |
|
118 } |
|
119 } else { |
|
120 rv = NS_NewXMLDocument(getter_AddRefs(d)); |
|
121 } |
|
122 |
|
123 if (NS_FAILED(rv)) { |
|
124 return rv; |
|
125 } |
|
126 |
|
127 if (nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aEventObject)) { |
|
128 d->SetScriptHandlingObject(sgo); |
|
129 } else if (aEventObject){ |
|
130 d->SetScopeObject(aEventObject); |
|
131 } |
|
132 |
|
133 if (isHTML) { |
|
134 nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(d); |
|
135 NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?"); |
|
136 htmlDoc->SetCompatibilityMode(eCompatibility_FullStandards); |
|
137 htmlDoc->SetIsXHTML(isXHTML); |
|
138 } |
|
139 nsDocument* doc = static_cast<nsDocument*>(d.get()); |
|
140 doc->SetLoadedAsData(aLoadedAsData); |
|
141 doc->nsDocument::SetDocumentURI(aDocumentURI); |
|
142 // Must set the principal first, since SetBaseURI checks it. |
|
143 doc->SetPrincipal(aPrincipal); |
|
144 doc->SetBaseURI(aBaseURI); |
|
145 |
|
146 // XMLDocuments and documents "created in memory" get to be UTF-8 by default, |
|
147 // unlike the legacy HTML mess |
|
148 doc->SetDocumentCharacterSet(NS_LITERAL_CSTRING("UTF-8")); |
|
149 |
|
150 if (aDoctype) { |
|
151 nsCOMPtr<nsIDOMNode> tmpNode; |
|
152 rv = doc->AppendChild(aDoctype, getter_AddRefs(tmpNode)); |
|
153 NS_ENSURE_SUCCESS(rv, rv); |
|
154 } |
|
155 |
|
156 if (!aQualifiedName.IsEmpty()) { |
|
157 nsCOMPtr<nsIDOMElement> root; |
|
158 rv = doc->CreateElementNS(aNamespaceURI, aQualifiedName, |
|
159 getter_AddRefs(root)); |
|
160 NS_ENSURE_SUCCESS(rv, rv); |
|
161 |
|
162 nsCOMPtr<nsIDOMNode> tmpNode; |
|
163 |
|
164 rv = doc->AppendChild(root, getter_AddRefs(tmpNode)); |
|
165 NS_ENSURE_SUCCESS(rv, rv); |
|
166 } |
|
167 |
|
168 *aInstancePtrResult = doc; |
|
169 NS_ADDREF(*aInstancePtrResult); |
|
170 |
|
171 return NS_OK; |
|
172 } |
|
173 |
|
174 nsresult |
|
175 NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData) |
|
176 { |
|
177 nsRefPtr<XMLDocument> doc = new XMLDocument(); |
|
178 |
|
179 nsresult rv = doc->Init(); |
|
180 |
|
181 if (NS_FAILED(rv)) { |
|
182 *aInstancePtrResult = nullptr; |
|
183 return rv; |
|
184 } |
|
185 |
|
186 doc->SetLoadedAsData(aLoadedAsData); |
|
187 doc.forget(aInstancePtrResult); |
|
188 |
|
189 return NS_OK; |
|
190 } |
|
191 |
|
192 nsresult |
|
193 NS_NewXBLDocument(nsIDOMDocument** aInstancePtrResult, |
|
194 nsIURI* aDocumentURI, |
|
195 nsIURI* aBaseURI, |
|
196 nsIPrincipal* aPrincipal) |
|
197 { |
|
198 nsresult rv = NS_NewDOMDocument(aInstancePtrResult, |
|
199 NS_LITERAL_STRING("http://www.mozilla.org/xbl"), |
|
200 NS_LITERAL_STRING("bindings"), nullptr, |
|
201 aDocumentURI, aBaseURI, aPrincipal, false, |
|
202 nullptr, DocumentFlavorLegacyGuess); |
|
203 NS_ENSURE_SUCCESS(rv, rv); |
|
204 |
|
205 nsCOMPtr<nsIDocument> idoc = do_QueryInterface(*aInstancePtrResult); |
|
206 nsDocument* doc = static_cast<nsDocument*>(idoc.get()); |
|
207 doc->SetLoadedAsInteractiveData(true); |
|
208 doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); |
|
209 |
|
210 return NS_OK; |
|
211 } |
|
212 |
|
213 namespace mozilla { |
|
214 namespace dom { |
|
215 |
|
216 XMLDocument::XMLDocument(const char* aContentType) |
|
217 : nsDocument(aContentType), |
|
218 mAsync(true) |
|
219 { |
|
220 // NOTE! nsDocument::operator new() zeroes out all members, so don't |
|
221 // bother initializing members to 0. |
|
222 } |
|
223 |
|
224 XMLDocument::~XMLDocument() |
|
225 { |
|
226 // XXX We rather crash than hang |
|
227 mLoopingForSyncLoad = false; |
|
228 } |
|
229 |
|
230 // QueryInterface implementation for XMLDocument |
|
231 NS_IMPL_ISUPPORTS_INHERITED(XMLDocument, nsDocument, nsIDOMXMLDocument) |
|
232 |
|
233 nsresult |
|
234 XMLDocument::Init() |
|
235 { |
|
236 nsresult rv = nsDocument::Init(); |
|
237 NS_ENSURE_SUCCESS(rv, rv); |
|
238 |
|
239 return rv; |
|
240 } |
|
241 |
|
242 void |
|
243 XMLDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) |
|
244 { |
|
245 nsDocument::Reset(aChannel, aLoadGroup); |
|
246 } |
|
247 |
|
248 void |
|
249 XMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, |
|
250 nsIPrincipal* aPrincipal) |
|
251 { |
|
252 if (mChannelIsPending) { |
|
253 StopDocumentLoad(); |
|
254 mChannel->Cancel(NS_BINDING_ABORTED); |
|
255 mChannelIsPending = false; |
|
256 } |
|
257 |
|
258 nsDocument::ResetToURI(aURI, aLoadGroup, aPrincipal); |
|
259 } |
|
260 |
|
261 NS_IMETHODIMP |
|
262 XMLDocument::GetAsync(bool *aAsync) |
|
263 { |
|
264 NS_ENSURE_ARG_POINTER(aAsync); |
|
265 *aAsync = mAsync; |
|
266 return NS_OK; |
|
267 } |
|
268 |
|
269 NS_IMETHODIMP |
|
270 XMLDocument::SetAsync(bool aAsync) |
|
271 { |
|
272 mAsync = aAsync; |
|
273 return NS_OK; |
|
274 } |
|
275 |
|
276 NS_IMETHODIMP |
|
277 XMLDocument::Load(const nsAString& aUrl, bool *aReturn) |
|
278 { |
|
279 ErrorResult rv; |
|
280 *aReturn = Load(aUrl, rv); |
|
281 return rv.ErrorCode(); |
|
282 } |
|
283 |
|
284 bool |
|
285 XMLDocument::Load(const nsAString& aUrl, ErrorResult& aRv) |
|
286 { |
|
287 bool hasHadScriptObject = true; |
|
288 nsIScriptGlobalObject* scriptObject = |
|
289 GetScriptHandlingObject(hasHadScriptObject); |
|
290 if (!scriptObject && hasHadScriptObject) { |
|
291 aRv.Throw(NS_ERROR_UNEXPECTED); |
|
292 return false; |
|
293 } |
|
294 |
|
295 WarnOnceAbout(nsIDocument::eUseOfDOM3LoadMethod); |
|
296 |
|
297 nsCOMPtr<nsIDocument> callingDoc = nsContentUtils::GetDocumentFromContext(); |
|
298 |
|
299 nsIURI *baseURI = mDocumentURI; |
|
300 nsAutoCString charset; |
|
301 |
|
302 if (callingDoc) { |
|
303 baseURI = callingDoc->GetDocBaseURI(); |
|
304 charset = callingDoc->GetDocumentCharacterSet(); |
|
305 } |
|
306 |
|
307 // Create a new URI |
|
308 nsCOMPtr<nsIURI> uri; |
|
309 nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, charset.get(), baseURI); |
|
310 if (NS_FAILED(rv)) { |
|
311 aRv.Throw(rv); |
|
312 return false; |
|
313 } |
|
314 |
|
315 // Check to see whether the current document is allowed to load this URI. |
|
316 // It's important to use the current document's principal for this check so |
|
317 // that we don't end up in a case where code with elevated privileges is |
|
318 // calling us and changing the principal of this document. |
|
319 |
|
320 // Enforce same-origin even for chrome loaders to avoid someone accidentally |
|
321 // using a document that content has a reference to and turn that into a |
|
322 // chrome document. |
|
323 nsCOMPtr<nsIPrincipal> principal = NodePrincipal(); |
|
324 if (!nsContentUtils::IsSystemPrincipal(principal)) { |
|
325 rv = principal->CheckMayLoad(uri, false, false); |
|
326 if (NS_FAILED(rv)) { |
|
327 aRv.Throw(rv); |
|
328 return false; |
|
329 } |
|
330 |
|
331 int16_t shouldLoad = nsIContentPolicy::ACCEPT; |
|
332 rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XMLHTTPREQUEST, |
|
333 uri, |
|
334 principal, |
|
335 callingDoc ? callingDoc.get() : |
|
336 static_cast<nsIDocument*>(this), |
|
337 NS_LITERAL_CSTRING("application/xml"), |
|
338 nullptr, |
|
339 &shouldLoad, |
|
340 nsContentUtils::GetContentPolicy(), |
|
341 nsContentUtils::GetSecurityManager()); |
|
342 if (NS_FAILED(rv)) { |
|
343 aRv.Throw(rv); |
|
344 return false; |
|
345 } |
|
346 if (NS_CP_REJECTED(shouldLoad)) { |
|
347 aRv.Throw(NS_ERROR_CONTENT_BLOCKED); |
|
348 return false; |
|
349 } |
|
350 } else { |
|
351 // We're called from chrome, check to make sure the URI we're |
|
352 // about to load is also chrome. |
|
353 |
|
354 bool isChrome = false; |
|
355 if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) { |
|
356 nsAutoCString spec; |
|
357 if (mDocumentURI) |
|
358 mDocumentURI->GetSpec(spec); |
|
359 |
|
360 nsAutoString error; |
|
361 error.AssignLiteral("Cross site loading using document.load is no " |
|
362 "longer supported. Use XMLHttpRequest instead."); |
|
363 nsCOMPtr<nsIScriptError> errorObject = |
|
364 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv); |
|
365 if (NS_FAILED(rv)) { |
|
366 aRv.Throw(rv); |
|
367 return false; |
|
368 } |
|
369 |
|
370 rv = errorObject->InitWithWindowID(error, |
|
371 NS_ConvertUTF8toUTF16(spec), |
|
372 EmptyString(), |
|
373 0, 0, nsIScriptError::warningFlag, |
|
374 "DOM", |
|
375 callingDoc ? |
|
376 callingDoc->InnerWindowID() : |
|
377 this->InnerWindowID()); |
|
378 |
|
379 if (NS_FAILED(rv)) { |
|
380 aRv.Throw(rv); |
|
381 return false; |
|
382 } |
|
383 |
|
384 nsCOMPtr<nsIConsoleService> consoleService = |
|
385 do_GetService(NS_CONSOLESERVICE_CONTRACTID); |
|
386 if (consoleService) { |
|
387 consoleService->LogMessage(errorObject); |
|
388 } |
|
389 |
|
390 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); |
|
391 return false; |
|
392 } |
|
393 } |
|
394 |
|
395 // Partial Reset, need to restore principal for security reasons and |
|
396 // event listener manager so that load listeners etc. will |
|
397 // remain. This should be done before the security check is done to |
|
398 // ensure that the document is reset even if the new document can't |
|
399 // be loaded. Note that we need to hold a strong ref to |principal| |
|
400 // here, because ResetToURI will null out our node principal before |
|
401 // setting the new one. |
|
402 nsRefPtr<EventListenerManager> elm(mListenerManager); |
|
403 mListenerManager = nullptr; |
|
404 |
|
405 // When we are called from JS we can find the load group for the page, |
|
406 // and add ourselves to it. This way any pending requests |
|
407 // will be automatically aborted if the user leaves the page. |
|
408 |
|
409 nsCOMPtr<nsILoadGroup> loadGroup; |
|
410 if (callingDoc) { |
|
411 loadGroup = callingDoc->GetDocumentLoadGroup(); |
|
412 } |
|
413 |
|
414 ResetToURI(uri, loadGroup, principal); |
|
415 |
|
416 mListenerManager = elm; |
|
417 |
|
418 // Create a channel |
|
419 nsCOMPtr<nsIInterfaceRequestor> req = nsContentUtils::GetSameOriginChecker(); |
|
420 if (!req) { |
|
421 aRv.Throw(NS_ERROR_OUT_OF_MEMORY); |
|
422 return false; |
|
423 } |
|
424 |
|
425 nsCOMPtr<nsIChannel> channel; |
|
426 // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, |
|
427 // which in turn keeps STOP button from becoming active |
|
428 rv = NS_NewChannel(getter_AddRefs(channel), uri, nullptr, loadGroup, req, |
|
429 nsIRequest::LOAD_BACKGROUND); |
|
430 if (NS_FAILED(rv)) { |
|
431 aRv.Throw(rv); |
|
432 return false; |
|
433 } |
|
434 |
|
435 // StartDocumentLoad asserts that readyState is uninitialized, so |
|
436 // uninitialize it. SetReadyStateInternal make this transition invisible to |
|
437 // Web content. But before doing that, assert that the current readyState |
|
438 // is complete as it should be after the call to ResetToURI() above. |
|
439 MOZ_ASSERT(GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE, |
|
440 "Bad readyState"); |
|
441 SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED); |
|
442 |
|
443 // Prepare for loading the XML document "into oneself" |
|
444 nsCOMPtr<nsIStreamListener> listener; |
|
445 if (NS_FAILED(rv = StartDocumentLoad(kLoadAsData, channel, |
|
446 loadGroup, nullptr, |
|
447 getter_AddRefs(listener), |
|
448 false))) { |
|
449 NS_ERROR("XMLDocument::Load: Failed to start the document load."); |
|
450 aRv.Throw(rv); |
|
451 return false; |
|
452 } |
|
453 |
|
454 // After this point, if we error out of this method we should clear |
|
455 // mChannelIsPending. |
|
456 |
|
457 // Start an asynchronous read of the XML document |
|
458 rv = channel->AsyncOpen(listener, nullptr); |
|
459 if (NS_FAILED(rv)) { |
|
460 mChannelIsPending = false; |
|
461 aRv.Throw(rv); |
|
462 return false; |
|
463 } |
|
464 |
|
465 if (!mAsync) { |
|
466 nsCOMPtr<nsIThread> thread = do_GetCurrentThread(); |
|
467 |
|
468 nsAutoSyncOperation sync(this); |
|
469 mLoopingForSyncLoad = true; |
|
470 while (mLoopingForSyncLoad) { |
|
471 if (!NS_ProcessNextEvent(thread)) |
|
472 break; |
|
473 } |
|
474 |
|
475 // We set return to true unless there was a parsing error |
|
476 Element* rootElement = GetRootElement(); |
|
477 if (!rootElement) { |
|
478 return false; |
|
479 } |
|
480 |
|
481 if (rootElement->LocalName().EqualsLiteral("parsererror")) { |
|
482 nsAutoString ns; |
|
483 rootElement->GetNamespaceURI(ns); |
|
484 if (ns.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) { |
|
485 return false; |
|
486 } |
|
487 } |
|
488 } |
|
489 |
|
490 return true; |
|
491 } |
|
492 |
|
493 nsresult |
|
494 XMLDocument::StartDocumentLoad(const char* aCommand, |
|
495 nsIChannel* aChannel, |
|
496 nsILoadGroup* aLoadGroup, |
|
497 nsISupports* aContainer, |
|
498 nsIStreamListener **aDocListener, |
|
499 bool aReset, |
|
500 nsIContentSink* aSink) |
|
501 { |
|
502 nsresult rv = nsDocument::StartDocumentLoad(aCommand, |
|
503 aChannel, aLoadGroup, |
|
504 aContainer, |
|
505 aDocListener, aReset, aSink); |
|
506 if (NS_FAILED(rv)) return rv; |
|
507 |
|
508 if (nsCRT::strcmp("loadAsInteractiveData", aCommand) == 0) { |
|
509 mLoadedAsInteractiveData = true; |
|
510 aCommand = kLoadAsData; // XBL, for example, needs scripts and styles |
|
511 } |
|
512 |
|
513 |
|
514 int32_t charsetSource = kCharsetFromDocTypeDefault; |
|
515 nsAutoCString charset(NS_LITERAL_CSTRING("UTF-8")); |
|
516 TryChannelCharset(aChannel, charsetSource, charset, nullptr); |
|
517 |
|
518 nsCOMPtr<nsIURI> aUrl; |
|
519 rv = aChannel->GetURI(getter_AddRefs(aUrl)); |
|
520 if (NS_FAILED(rv)) return rv; |
|
521 |
|
522 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID); |
|
523 |
|
524 mParser = do_CreateInstance(kCParserCID, &rv); |
|
525 NS_ENSURE_SUCCESS(rv, rv); |
|
526 |
|
527 nsCOMPtr<nsIXMLContentSink> sink; |
|
528 |
|
529 if (aSink) { |
|
530 sink = do_QueryInterface(aSink); |
|
531 } |
|
532 else { |
|
533 nsCOMPtr<nsIDocShell> docShell; |
|
534 if (aContainer) { |
|
535 docShell = do_QueryInterface(aContainer); |
|
536 NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); |
|
537 } |
|
538 rv = NS_NewXMLContentSink(getter_AddRefs(sink), this, aUrl, docShell, |
|
539 aChannel); |
|
540 NS_ENSURE_SUCCESS(rv, rv); |
|
541 } |
|
542 |
|
543 // Set the parser as the stream listener for the document loader... |
|
544 rv = CallQueryInterface(mParser, aDocListener); |
|
545 NS_ENSURE_SUCCESS(rv, rv); |
|
546 |
|
547 NS_ASSERTION(mChannel, "How can we not have a channel here?"); |
|
548 mChannelIsPending = true; |
|
549 |
|
550 SetDocumentCharacterSet(charset); |
|
551 mParser->SetDocumentCharset(charset, charsetSource); |
|
552 mParser->SetCommand(aCommand); |
|
553 mParser->SetContentSink(sink); |
|
554 mParser->Parse(aUrl, nullptr, (void *)this); |
|
555 |
|
556 return NS_OK; |
|
557 } |
|
558 |
|
559 void |
|
560 XMLDocument::EndLoad() |
|
561 { |
|
562 mChannelIsPending = false; |
|
563 mLoopingForSyncLoad = false; |
|
564 |
|
565 mSynchronousDOMContentLoaded = (mLoadedAsData || mLoadedAsInteractiveData); |
|
566 nsDocument::EndLoad(); |
|
567 if (mSynchronousDOMContentLoaded) { |
|
568 mSynchronousDOMContentLoaded = false; |
|
569 nsDocument::SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); |
|
570 // Generate a document load event for the case when an XML |
|
571 // document was loaded as pure data without any presentation |
|
572 // attached to it. |
|
573 WidgetEvent event(true, NS_LOAD); |
|
574 EventDispatcher::Dispatch(static_cast<nsIDocument*>(this), nullptr, &event); |
|
575 } |
|
576 } |
|
577 |
|
578 /* virtual */ void |
|
579 XMLDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const |
|
580 { |
|
581 nsDocument::DocAddSizeOfExcludingThis(aWindowSizes); |
|
582 } |
|
583 |
|
584 // nsIDOMDocument interface |
|
585 |
|
586 nsresult |
|
587 XMLDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const |
|
588 { |
|
589 NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager, |
|
590 "Can't import this document into another document!"); |
|
591 |
|
592 nsRefPtr<XMLDocument> clone = new XMLDocument(); |
|
593 nsresult rv = CloneDocHelper(clone); |
|
594 NS_ENSURE_SUCCESS(rv, rv); |
|
595 |
|
596 // State from XMLDocument |
|
597 clone->mAsync = mAsync; |
|
598 |
|
599 return CallQueryInterface(clone.get(), aResult); |
|
600 } |
|
601 |
|
602 JSObject* |
|
603 XMLDocument::WrapNode(JSContext *aCx) |
|
604 { |
|
605 return XMLDocumentBinding::Wrap(aCx, this); |
|
606 } |
|
607 |
|
608 } // namespace dom |
|
609 } // namespace mozilla |