content/xml/document/src/XMLDocument.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial