1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/xbl/nsXBLService.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1060 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "mozilla/ArrayUtils.h" 1.10 + 1.11 +#include "nsCOMPtr.h" 1.12 +#include "nsNetUtil.h" 1.13 +#include "nsXBLService.h" 1.14 +#include "nsXBLWindowKeyHandler.h" 1.15 +#include "nsIInputStream.h" 1.16 +#include "nsNameSpaceManager.h" 1.17 +#include "nsIURI.h" 1.18 +#include "nsIDOMElement.h" 1.19 +#include "nsIURL.h" 1.20 +#include "nsIChannel.h" 1.21 +#include "nsXPIDLString.h" 1.22 +#include "plstr.h" 1.23 +#include "nsIContent.h" 1.24 +#include "nsIDocument.h" 1.25 +#include "nsIXMLContentSink.h" 1.26 +#include "nsContentCID.h" 1.27 +#include "mozilla/dom/XMLDocument.h" 1.28 +#include "nsGkAtoms.h" 1.29 +#include "nsIMemory.h" 1.30 +#include "nsIObserverService.h" 1.31 +#include "nsIDOMNodeList.h" 1.32 +#include "nsXBLContentSink.h" 1.33 +#include "nsXBLBinding.h" 1.34 +#include "nsXBLPrototypeBinding.h" 1.35 +#include "nsXBLDocumentInfo.h" 1.36 +#include "nsCRT.h" 1.37 +#include "nsContentUtils.h" 1.38 +#include "nsSyncLoadService.h" 1.39 +#include "nsContentPolicyUtils.h" 1.40 +#include "nsTArray.h" 1.41 +#include "nsError.h" 1.42 + 1.43 +#include "nsIPresShell.h" 1.44 +#include "nsIDocumentObserver.h" 1.45 +#include "nsFrameManager.h" 1.46 +#include "nsStyleContext.h" 1.47 +#include "nsIScriptSecurityManager.h" 1.48 +#include "nsIScriptError.h" 1.49 +#include "nsXBLSerialize.h" 1.50 + 1.51 +#ifdef MOZ_XUL 1.52 +#include "nsXULPrototypeCache.h" 1.53 +#endif 1.54 +#include "nsIDOMEventListener.h" 1.55 +#include "mozilla/Attributes.h" 1.56 +#include "mozilla/EventListenerManager.h" 1.57 +#include "mozilla/Preferences.h" 1.58 +#include "mozilla/dom/Event.h" 1.59 +#include "mozilla/dom/Element.h" 1.60 + 1.61 +using namespace mozilla; 1.62 +using namespace mozilla::dom; 1.63 + 1.64 +#define NS_MAX_XBL_BINDING_RECURSION 20 1.65 + 1.66 +nsXBLService* nsXBLService::gInstance = nullptr; 1.67 + 1.68 +static bool 1.69 +IsAncestorBinding(nsIDocument* aDocument, 1.70 + nsIURI* aChildBindingURI, 1.71 + nsIContent* aChild) 1.72 +{ 1.73 + NS_ASSERTION(aDocument, "expected a document"); 1.74 + NS_ASSERTION(aChildBindingURI, "expected a binding URI"); 1.75 + NS_ASSERTION(aChild, "expected a child content"); 1.76 + 1.77 + uint32_t bindingRecursion = 0; 1.78 + for (nsIContent *bindingParent = aChild->GetBindingParent(); 1.79 + bindingParent; 1.80 + bindingParent = bindingParent->GetBindingParent()) { 1.81 + nsXBLBinding* binding = bindingParent->GetXBLBinding(); 1.82 + if (!binding) { 1.83 + continue; 1.84 + } 1.85 + 1.86 + if (binding->PrototypeBinding()->CompareBindingURI(aChildBindingURI)) { 1.87 + ++bindingRecursion; 1.88 + if (bindingRecursion < NS_MAX_XBL_BINDING_RECURSION) { 1.89 + continue; 1.90 + } 1.91 + nsAutoCString spec; 1.92 + aChildBindingURI->GetSpec(spec); 1.93 + NS_ConvertUTF8toUTF16 bindingURI(spec); 1.94 + const char16_t* params[] = { bindingURI.get() }; 1.95 + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, 1.96 + NS_LITERAL_CSTRING("XBL"), aDocument, 1.97 + nsContentUtils::eXBL_PROPERTIES, 1.98 + "TooDeepBindingRecursion", 1.99 + params, ArrayLength(params)); 1.100 + return true; 1.101 + } 1.102 + } 1.103 + 1.104 + return false; 1.105 +} 1.106 + 1.107 +// Individual binding requests. 1.108 +class nsXBLBindingRequest 1.109 +{ 1.110 +public: 1.111 + nsCOMPtr<nsIURI> mBindingURI; 1.112 + nsCOMPtr<nsIContent> mBoundElement; 1.113 + 1.114 + void DocumentLoaded(nsIDocument* aBindingDoc) 1.115 + { 1.116 + // We only need the document here to cause frame construction, so 1.117 + // we need the current doc, not the owner doc. 1.118 + nsIDocument* doc = mBoundElement->GetCurrentDoc(); 1.119 + if (!doc) 1.120 + return; 1.121 + 1.122 + // Get the binding. 1.123 + bool ready = false; 1.124 + nsXBLService::GetInstance()->BindingReady(mBoundElement, mBindingURI, &ready); 1.125 + if (!ready) 1.126 + return; 1.127 + 1.128 + // If |mBoundElement| is (in addition to having binding |mBinding|) 1.129 + // also a descendant of another element with binding |mBinding|, 1.130 + // then we might have just constructed it due to the 1.131 + // notification of its parent. (We can know about both if the 1.132 + // binding loads were triggered from the DOM rather than frame 1.133 + // construction.) So we have to check both whether the element 1.134 + // has a primary frame and whether it's in the undisplayed map 1.135 + // before sending a ContentInserted notification, or bad things 1.136 + // will happen. 1.137 + nsIPresShell *shell = doc->GetShell(); 1.138 + if (shell) { 1.139 + nsIFrame* childFrame = mBoundElement->GetPrimaryFrame(); 1.140 + if (!childFrame) { 1.141 + // Check to see if it's in the undisplayed content map. 1.142 + nsStyleContext* sc = 1.143 + shell->FrameManager()->GetUndisplayedContent(mBoundElement); 1.144 + 1.145 + if (!sc) { 1.146 + shell->RecreateFramesFor(mBoundElement); 1.147 + } 1.148 + } 1.149 + } 1.150 + } 1.151 + 1.152 + nsXBLBindingRequest(nsIURI* aURI, nsIContent* aBoundElement) 1.153 + : mBindingURI(aURI), 1.154 + mBoundElement(aBoundElement) 1.155 + { 1.156 + } 1.157 +}; 1.158 + 1.159 +// nsXBLStreamListener, a helper class used for 1.160 +// asynchronous parsing of URLs 1.161 +/* Header file */ 1.162 +class nsXBLStreamListener MOZ_FINAL : public nsIStreamListener, 1.163 + public nsIDOMEventListener 1.164 +{ 1.165 +public: 1.166 + NS_DECL_ISUPPORTS 1.167 + NS_DECL_NSISTREAMLISTENER 1.168 + NS_DECL_NSIREQUESTOBSERVER 1.169 + NS_DECL_NSIDOMEVENTLISTENER 1.170 + 1.171 + nsXBLStreamListener(nsIDocument* aBoundDocument, 1.172 + nsIXMLContentSink* aSink, 1.173 + nsIDocument* aBindingDocument); 1.174 + ~nsXBLStreamListener(); 1.175 + 1.176 + void AddRequest(nsXBLBindingRequest* aRequest) { mBindingRequests.AppendElement(aRequest); } 1.177 + bool HasRequest(nsIURI* aURI, nsIContent* aBoundElement); 1.178 + 1.179 +private: 1.180 + nsCOMPtr<nsIStreamListener> mInner; 1.181 + nsAutoTArray<nsXBLBindingRequest*, 8> mBindingRequests; 1.182 + 1.183 + nsCOMPtr<nsIWeakReference> mBoundDocument; 1.184 + nsCOMPtr<nsIXMLContentSink> mSink; // Only set until OnStartRequest 1.185 + nsCOMPtr<nsIDocument> mBindingDocument; // Only set until OnStartRequest 1.186 +}; 1.187 + 1.188 +/* Implementation file */ 1.189 +NS_IMPL_ISUPPORTS(nsXBLStreamListener, 1.190 + nsIStreamListener, 1.191 + nsIRequestObserver, 1.192 + nsIDOMEventListener) 1.193 + 1.194 +nsXBLStreamListener::nsXBLStreamListener(nsIDocument* aBoundDocument, 1.195 + nsIXMLContentSink* aSink, 1.196 + nsIDocument* aBindingDocument) 1.197 +: mSink(aSink), mBindingDocument(aBindingDocument) 1.198 +{ 1.199 + /* member initializers and constructor code */ 1.200 + mBoundDocument = do_GetWeakReference(aBoundDocument); 1.201 +} 1.202 + 1.203 +nsXBLStreamListener::~nsXBLStreamListener() 1.204 +{ 1.205 + for (uint32_t i = 0; i < mBindingRequests.Length(); i++) { 1.206 + nsXBLBindingRequest* req = mBindingRequests.ElementAt(i); 1.207 + delete req; 1.208 + } 1.209 +} 1.210 + 1.211 +NS_IMETHODIMP 1.212 +nsXBLStreamListener::OnDataAvailable(nsIRequest *request, nsISupports* aCtxt, 1.213 + nsIInputStream* aInStr, 1.214 + uint64_t aSourceOffset, uint32_t aCount) 1.215 +{ 1.216 + if (mInner) 1.217 + return mInner->OnDataAvailable(request, aCtxt, aInStr, aSourceOffset, aCount); 1.218 + return NS_ERROR_FAILURE; 1.219 +} 1.220 + 1.221 +NS_IMETHODIMP 1.222 +nsXBLStreamListener::OnStartRequest(nsIRequest* request, nsISupports* aCtxt) 1.223 +{ 1.224 + // Make sure we don't hold on to the sink and binding document past this point 1.225 + nsCOMPtr<nsIXMLContentSink> sink; 1.226 + mSink.swap(sink); 1.227 + nsCOMPtr<nsIDocument> doc; 1.228 + mBindingDocument.swap(doc); 1.229 + 1.230 + nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); 1.231 + NS_ENSURE_TRUE(channel, NS_ERROR_UNEXPECTED); 1.232 + 1.233 + nsCOMPtr<nsILoadGroup> group; 1.234 + request->GetLoadGroup(getter_AddRefs(group)); 1.235 + 1.236 + nsresult rv = doc->StartDocumentLoad("loadAsInteractiveData", 1.237 + channel, 1.238 + group, 1.239 + nullptr, 1.240 + getter_AddRefs(mInner), 1.241 + true, 1.242 + sink); 1.243 + NS_ENSURE_SUCCESS(rv, rv); 1.244 + 1.245 + // Make sure to add ourselves as a listener after StartDocumentLoad, 1.246 + // since that resets the event listners on the document. 1.247 + doc->AddEventListener(NS_LITERAL_STRING("load"), this, false); 1.248 + 1.249 + return mInner->OnStartRequest(request, aCtxt); 1.250 +} 1.251 + 1.252 +NS_IMETHODIMP 1.253 +nsXBLStreamListener::OnStopRequest(nsIRequest* request, nsISupports* aCtxt, nsresult aStatus) 1.254 +{ 1.255 + nsresult rv = NS_OK; 1.256 + if (mInner) { 1.257 + rv = mInner->OnStopRequest(request, aCtxt, aStatus); 1.258 + } 1.259 + 1.260 + // Don't hold onto the inner listener; holding onto it can create a cycle 1.261 + // with the document 1.262 + mInner = nullptr; 1.263 + 1.264 + return rv; 1.265 +} 1.266 + 1.267 +bool 1.268 +nsXBLStreamListener::HasRequest(nsIURI* aURI, nsIContent* aElt) 1.269 +{ 1.270 + // XXX Could be more efficient. 1.271 + uint32_t count = mBindingRequests.Length(); 1.272 + for (uint32_t i = 0; i < count; i++) { 1.273 + nsXBLBindingRequest* req = mBindingRequests.ElementAt(i); 1.274 + bool eq; 1.275 + if (req->mBoundElement == aElt && 1.276 + NS_SUCCEEDED(req->mBindingURI->Equals(aURI, &eq)) && eq) 1.277 + return true; 1.278 + } 1.279 + 1.280 + return false; 1.281 +} 1.282 + 1.283 +nsresult 1.284 +nsXBLStreamListener::HandleEvent(nsIDOMEvent* aEvent) 1.285 +{ 1.286 + nsresult rv = NS_OK; 1.287 + uint32_t i; 1.288 + uint32_t count = mBindingRequests.Length(); 1.289 + 1.290 + // Get the binding document; note that we don't hold onto it in this object 1.291 + // to avoid creating a cycle 1.292 + Event* event = aEvent->InternalDOMEvent(); 1.293 + EventTarget* target = event->GetCurrentTarget(); 1.294 + nsCOMPtr<nsIDocument> bindingDocument = do_QueryInterface(target); 1.295 + NS_ASSERTION(bindingDocument, "Event not targeted at document?!"); 1.296 + 1.297 + // See if we're still alive. 1.298 + nsCOMPtr<nsIDocument> doc(do_QueryReferent(mBoundDocument)); 1.299 + if (!doc) { 1.300 + NS_WARNING("XBL load did not complete until after document went away! Modal dialog bug?\n"); 1.301 + } 1.302 + else { 1.303 + // We have to do a flush prior to notification of the document load. 1.304 + // This has to happen since the HTML content sink can be holding on 1.305 + // to notifications related to our children (e.g., if you bind to the 1.306 + // <body> tag) that result in duplication of content. 1.307 + // We need to get the sink's notifications flushed and then make the binding 1.308 + // ready. 1.309 + if (count > 0) { 1.310 + nsXBLBindingRequest* req = mBindingRequests.ElementAt(0); 1.311 + nsIDocument* document = req->mBoundElement->GetCurrentDoc(); 1.312 + if (document) 1.313 + document->FlushPendingNotifications(Flush_ContentAndNotify); 1.314 + } 1.315 + 1.316 + // Remove ourselves from the set of pending docs. 1.317 + nsBindingManager *bindingManager = doc->BindingManager(); 1.318 + nsIURI* documentURI = bindingDocument->GetDocumentURI(); 1.319 + bindingManager->RemoveLoadingDocListener(documentURI); 1.320 + 1.321 + if (!bindingDocument->GetRootElement()) { 1.322 + // FIXME: How about an error console warning? 1.323 + NS_WARNING("XBL doc with no root element - this usually shouldn't happen"); 1.324 + return NS_ERROR_FAILURE; 1.325 + } 1.326 + 1.327 + // Put our doc info in the doc table. 1.328 + nsBindingManager *xblDocBindingManager = bindingDocument->BindingManager(); 1.329 + nsRefPtr<nsXBLDocumentInfo> info = 1.330 + xblDocBindingManager->GetXBLDocumentInfo(documentURI); 1.331 + xblDocBindingManager->RemoveXBLDocumentInfo(info); // Break the self-imposed cycle. 1.332 + if (!info) { 1.333 + if (nsXBLService::IsChromeOrResourceURI(documentURI)) { 1.334 + NS_WARNING("An XBL file is malformed. Did you forget the XBL namespace on the bindings tag?"); 1.335 + } 1.336 + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, 1.337 + NS_LITERAL_CSTRING("XBL"), nullptr, 1.338 + nsContentUtils::eXBL_PROPERTIES, 1.339 + "MalformedXBL", 1.340 + nullptr, 0, documentURI); 1.341 + return NS_ERROR_FAILURE; 1.342 + } 1.343 + 1.344 + // If the doc is a chrome URI, then we put it into the XUL cache. 1.345 +#ifdef MOZ_XUL 1.346 + if (nsXBLService::IsChromeOrResourceURI(documentURI)) { 1.347 + nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance(); 1.348 + if (cache && cache->IsEnabled()) 1.349 + cache->PutXBLDocumentInfo(info); 1.350 + } 1.351 +#endif 1.352 + 1.353 + bindingManager->PutXBLDocumentInfo(info); 1.354 + 1.355 + // Notify all pending requests that their bindings are 1.356 + // ready and can be installed. 1.357 + for (i = 0; i < count; i++) { 1.358 + nsXBLBindingRequest* req = mBindingRequests.ElementAt(i); 1.359 + req->DocumentLoaded(bindingDocument); 1.360 + } 1.361 + } 1.362 + 1.363 + target->RemoveEventListener(NS_LITERAL_STRING("load"), this, false); 1.364 + 1.365 + return rv; 1.366 +} 1.367 + 1.368 +// Implementation ///////////////////////////////////////////////////////////////// 1.369 + 1.370 +// Static member variable initialization 1.371 +bool nsXBLService::gAllowDataURIs = false; 1.372 + 1.373 +// Implement our nsISupports methods 1.374 +NS_IMPL_ISUPPORTS(nsXBLService, nsISupportsWeakReference) 1.375 + 1.376 +void 1.377 +nsXBLService::Init() 1.378 +{ 1.379 + gInstance = new nsXBLService(); 1.380 + NS_ADDREF(gInstance); 1.381 +} 1.382 + 1.383 +// Constructors/Destructors 1.384 +nsXBLService::nsXBLService(void) 1.385 +{ 1.386 + Preferences::AddBoolVarCache(&gAllowDataURIs, "layout.debug.enable_data_xbl"); 1.387 +} 1.388 + 1.389 +nsXBLService::~nsXBLService(void) 1.390 +{ 1.391 +} 1.392 + 1.393 +// static 1.394 +bool 1.395 +nsXBLService::IsChromeOrResourceURI(nsIURI* aURI) 1.396 +{ 1.397 + bool isChrome = false; 1.398 + bool isResource = false; 1.399 + if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && 1.400 + NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource))) 1.401 + return (isChrome || isResource); 1.402 + return false; 1.403 +} 1.404 + 1.405 + 1.406 +// This function loads a particular XBL file and installs all of the bindings 1.407 +// onto the element. 1.408 +nsresult 1.409 +nsXBLService::LoadBindings(nsIContent* aContent, nsIURI* aURL, 1.410 + nsIPrincipal* aOriginPrincipal, 1.411 + nsXBLBinding** aBinding, bool* aResolveStyle) 1.412 +{ 1.413 + NS_PRECONDITION(aOriginPrincipal, "Must have an origin principal"); 1.414 + 1.415 + *aBinding = nullptr; 1.416 + *aResolveStyle = false; 1.417 + 1.418 + nsresult rv; 1.419 + 1.420 + nsCOMPtr<nsIDocument> document = aContent->OwnerDoc(); 1.421 + 1.422 + nsAutoCString urlspec; 1.423 + if (nsContentUtils::GetWrapperSafeScriptFilename(document, aURL, urlspec)) { 1.424 + // Block an attempt to load a binding that has special wrapper 1.425 + // automation needs. 1.426 + 1.427 + return NS_OK; 1.428 + } 1.429 + 1.430 + nsXBLBinding *binding = aContent->GetXBLBinding(); 1.431 + if (binding) { 1.432 + if (binding->MarkedForDeath()) { 1.433 + FlushStyleBindings(aContent); 1.434 + binding = nullptr; 1.435 + } 1.436 + else { 1.437 + // See if the URIs match. 1.438 + if (binding->PrototypeBinding()->CompareBindingURI(aURL)) 1.439 + return NS_OK; 1.440 + FlushStyleBindings(aContent); 1.441 + binding = nullptr; 1.442 + } 1.443 + } 1.444 + 1.445 + bool ready; 1.446 + nsRefPtr<nsXBLBinding> newBinding; 1.447 + if (NS_FAILED(rv = GetBinding(aContent, aURL, false, aOriginPrincipal, 1.448 + &ready, getter_AddRefs(newBinding)))) { 1.449 + return rv; 1.450 + } 1.451 + 1.452 + if (!newBinding) { 1.453 +#ifdef DEBUG 1.454 + nsAutoCString spec; 1.455 + aURL->GetSpec(spec); 1.456 + nsAutoCString str(NS_LITERAL_CSTRING("Failed to locate XBL binding. XBL is now using id instead of name to reference bindings. Make sure you have switched over. The invalid binding name is: ") + spec); 1.457 + NS_ERROR(str.get()); 1.458 +#endif 1.459 + return NS_OK; 1.460 + } 1.461 + 1.462 + if (::IsAncestorBinding(document, aURL, aContent)) { 1.463 + return NS_ERROR_ILLEGAL_VALUE; 1.464 + } 1.465 + 1.466 + // We loaded a style binding. It goes on the end. 1.467 + if (binding) { 1.468 + // Get the last binding that is in the append layer. 1.469 + binding->RootBinding()->SetBaseBinding(newBinding); 1.470 + } 1.471 + else { 1.472 + // Install the binding on the content node. 1.473 + aContent->SetXBLBinding(newBinding); 1.474 + } 1.475 + 1.476 + { 1.477 + nsAutoScriptBlocker scriptBlocker; 1.478 + 1.479 + // Set the binding's bound element. 1.480 + newBinding->SetBoundElement(aContent); 1.481 + 1.482 + // Tell the binding to build the anonymous content. 1.483 + newBinding->GenerateAnonymousContent(); 1.484 + 1.485 + // Tell the binding to install event handlers 1.486 + newBinding->InstallEventHandlers(); 1.487 + 1.488 + // Set up our properties 1.489 + rv = newBinding->InstallImplementation(); 1.490 + NS_ENSURE_SUCCESS(rv, rv); 1.491 + 1.492 + // Figure out if we have any scoped sheets. If so, we do a second resolve. 1.493 + *aResolveStyle = newBinding->HasStyleSheets(); 1.494 + 1.495 + newBinding.swap(*aBinding); 1.496 + } 1.497 + 1.498 + return NS_OK; 1.499 +} 1.500 + 1.501 +nsresult 1.502 +nsXBLService::FlushStyleBindings(nsIContent* aContent) 1.503 +{ 1.504 + nsCOMPtr<nsIDocument> document = aContent->OwnerDoc(); 1.505 + 1.506 + nsXBLBinding *binding = aContent->GetXBLBinding(); 1.507 + if (binding) { 1.508 + // Clear out the script references. 1.509 + binding->ChangeDocument(document, nullptr); 1.510 + 1.511 + aContent->SetXBLBinding(nullptr); // Flush old style bindings 1.512 + } 1.513 + 1.514 + return NS_OK; 1.515 +} 1.516 + 1.517 +// 1.518 +// AttachGlobalKeyHandler 1.519 +// 1.520 +// Creates a new key handler and prepares to listen to key events on the given 1.521 +// event receiver (either a document or an content node). If the receiver is content, 1.522 +// then extra work needs to be done to hook it up to the document (XXX WHY??) 1.523 +// 1.524 +nsresult 1.525 +nsXBLService::AttachGlobalKeyHandler(EventTarget* aTarget) 1.526 +{ 1.527 + // check if the receiver is a content node (not a document), and hook 1.528 + // it to the document if that is the case. 1.529 + nsCOMPtr<EventTarget> piTarget = aTarget; 1.530 + nsCOMPtr<nsIContent> contentNode(do_QueryInterface(aTarget)); 1.531 + if (contentNode) { 1.532 + // Only attach if we're really in a document 1.533 + nsCOMPtr<nsIDocument> doc = contentNode->GetCurrentDoc(); 1.534 + if (doc) 1.535 + piTarget = doc; // We're a XUL keyset. Attach to our document. 1.536 + } 1.537 + 1.538 + EventListenerManager* manager = piTarget->GetOrCreateListenerManager(); 1.539 + 1.540 + if (!piTarget || !manager) 1.541 + return NS_ERROR_FAILURE; 1.542 + 1.543 + // the listener already exists, so skip this 1.544 + if (contentNode && contentNode->GetProperty(nsGkAtoms::listener)) 1.545 + return NS_OK; 1.546 + 1.547 + nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(contentNode)); 1.548 + 1.549 + // Create the key handler 1.550 + nsRefPtr<nsXBLWindowKeyHandler> handler = 1.551 + NS_NewXBLWindowKeyHandler(elt, piTarget); 1.552 + 1.553 + // listen to these events 1.554 + manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keydown"), 1.555 + TrustedEventsAtSystemGroupBubble()); 1.556 + manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keyup"), 1.557 + TrustedEventsAtSystemGroupBubble()); 1.558 + manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keypress"), 1.559 + TrustedEventsAtSystemGroupBubble()); 1.560 + 1.561 + // The capturing listener is only used for XUL keysets to properly handle 1.562 + // shortcut keys in a multi-process environment. 1.563 + manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keydown"), 1.564 + TrustedEventsAtSystemGroupCapture()); 1.565 + manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keyup"), 1.566 + TrustedEventsAtSystemGroupCapture()); 1.567 + manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keypress"), 1.568 + TrustedEventsAtSystemGroupCapture()); 1.569 + 1.570 + if (contentNode) 1.571 + return contentNode->SetProperty(nsGkAtoms::listener, 1.572 + handler.forget().take(), 1.573 + nsPropertyTable::SupportsDtorFunc, true); 1.574 + 1.575 + // The reference to the handler will be maintained by the event target, 1.576 + // and, if there is a content node, the property. 1.577 + return NS_OK; 1.578 +} 1.579 + 1.580 +// 1.581 +// DetachGlobalKeyHandler 1.582 +// 1.583 +// Removes a key handler added by DeatchGlobalKeyHandler. 1.584 +// 1.585 +nsresult 1.586 +nsXBLService::DetachGlobalKeyHandler(EventTarget* aTarget) 1.587 +{ 1.588 + nsCOMPtr<EventTarget> piTarget = aTarget; 1.589 + nsCOMPtr<nsIContent> contentNode(do_QueryInterface(aTarget)); 1.590 + if (!contentNode) // detaching is only supported for content nodes 1.591 + return NS_ERROR_FAILURE; 1.592 + 1.593 + // Only attach if we're really in a document 1.594 + nsCOMPtr<nsIDocument> doc = contentNode->GetCurrentDoc(); 1.595 + if (doc) 1.596 + piTarget = do_QueryInterface(doc); 1.597 + 1.598 + EventListenerManager* manager = piTarget->GetOrCreateListenerManager(); 1.599 + 1.600 + if (!piTarget || !manager) 1.601 + return NS_ERROR_FAILURE; 1.602 + 1.603 + nsIDOMEventListener* handler = 1.604 + static_cast<nsIDOMEventListener*>(contentNode->GetProperty(nsGkAtoms::listener)); 1.605 + if (!handler) 1.606 + return NS_ERROR_FAILURE; 1.607 + 1.608 + manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keydown"), 1.609 + TrustedEventsAtSystemGroupBubble()); 1.610 + manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keyup"), 1.611 + TrustedEventsAtSystemGroupBubble()); 1.612 + manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keypress"), 1.613 + TrustedEventsAtSystemGroupBubble()); 1.614 + 1.615 + manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keydown"), 1.616 + TrustedEventsAtSystemGroupCapture()); 1.617 + manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keyup"), 1.618 + TrustedEventsAtSystemGroupCapture()); 1.619 + manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keypress"), 1.620 + TrustedEventsAtSystemGroupCapture()); 1.621 + 1.622 + contentNode->DeleteProperty(nsGkAtoms::listener); 1.623 + 1.624 + return NS_OK; 1.625 +} 1.626 + 1.627 +// Internal helper methods //////////////////////////////////////////////////////////////// 1.628 + 1.629 +nsresult 1.630 +nsXBLService::BindingReady(nsIContent* aBoundElement, 1.631 + nsIURI* aURI, 1.632 + bool* aIsReady) 1.633 +{ 1.634 + // Don't do a security check here; we know this binding is set to go. 1.635 + return GetBinding(aBoundElement, aURI, true, nullptr, aIsReady, nullptr); 1.636 +} 1.637 + 1.638 +nsresult 1.639 +nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI, 1.640 + bool aPeekOnly, nsIPrincipal* aOriginPrincipal, 1.641 + bool* aIsReady, nsXBLBinding** aResult) 1.642 +{ 1.643 + // More than 6 binding URIs are rare, see bug 55070 comment 18. 1.644 + nsAutoTArray<nsIURI*, 6> uris; 1.645 + return GetBinding(aBoundElement, aURI, aPeekOnly, aOriginPrincipal, aIsReady, 1.646 + aResult, uris); 1.647 +} 1.648 + 1.649 +nsresult 1.650 +nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI, 1.651 + bool aPeekOnly, nsIPrincipal* aOriginPrincipal, 1.652 + bool* aIsReady, nsXBLBinding** aResult, 1.653 + nsTArray<nsIURI*>& aDontExtendURIs) 1.654 +{ 1.655 + NS_ASSERTION(aPeekOnly || aResult, 1.656 + "Must have non-null out param if not just peeking to see " 1.657 + "whether the binding is ready"); 1.658 + 1.659 + if (aResult) 1.660 + *aResult = nullptr; 1.661 + 1.662 + if (!aURI) 1.663 + return NS_ERROR_FAILURE; 1.664 + 1.665 + nsAutoCString ref; 1.666 + aURI->GetRef(ref); 1.667 + 1.668 + nsCOMPtr<nsIDocument> boundDocument = aBoundElement->OwnerDoc(); 1.669 + 1.670 + nsRefPtr<nsXBLDocumentInfo> docInfo; 1.671 + nsresult rv = LoadBindingDocumentInfo(aBoundElement, boundDocument, aURI, 1.672 + aOriginPrincipal, 1.673 + false, getter_AddRefs(docInfo)); 1.674 + NS_ENSURE_SUCCESS(rv, rv); 1.675 + 1.676 + if (!docInfo) 1.677 + return NS_ERROR_FAILURE; 1.678 + 1.679 + nsXBLPrototypeBinding* protoBinding = docInfo->GetPrototypeBinding(ref); 1.680 + 1.681 + if (!protoBinding) { 1.682 +#ifdef DEBUG 1.683 + nsAutoCString uriSpec; 1.684 + aURI->GetSpec(uriSpec); 1.685 + nsAutoCString doc; 1.686 + boundDocument->GetDocumentURI()->GetSpec(doc); 1.687 + nsAutoCString message("Unable to locate an XBL binding for URI "); 1.688 + message += uriSpec; 1.689 + message += " in document "; 1.690 + message += doc; 1.691 + NS_WARNING(message.get()); 1.692 +#endif 1.693 + return NS_ERROR_FAILURE; 1.694 + } 1.695 + 1.696 + NS_ENSURE_TRUE(aDontExtendURIs.AppendElement(protoBinding->BindingURI()), 1.697 + NS_ERROR_OUT_OF_MEMORY); 1.698 + nsCOMPtr<nsIURI> altBindingURI = protoBinding->AlternateBindingURI(); 1.699 + if (altBindingURI) { 1.700 + NS_ENSURE_TRUE(aDontExtendURIs.AppendElement(altBindingURI), 1.701 + NS_ERROR_OUT_OF_MEMORY); 1.702 + } 1.703 + 1.704 + // Our prototype binding must have all its resources loaded. 1.705 + bool ready = protoBinding->LoadResources(); 1.706 + if (!ready) { 1.707 + // Add our bound element to the protos list of elts that should 1.708 + // be notified when the stylesheets and scripts finish loading. 1.709 + protoBinding->AddResourceListener(aBoundElement); 1.710 + return NS_ERROR_FAILURE; // The binding isn't ready yet. 1.711 + } 1.712 + 1.713 + rv = protoBinding->ResolveBaseBinding(); 1.714 + NS_ENSURE_SUCCESS(rv, rv); 1.715 + 1.716 + nsIURI* baseBindingURI; 1.717 + nsXBLPrototypeBinding* baseProto = protoBinding->GetBasePrototype(); 1.718 + if (baseProto) { 1.719 + baseBindingURI = baseProto->BindingURI(); 1.720 + } 1.721 + else { 1.722 + baseBindingURI = protoBinding->GetBaseBindingURI(); 1.723 + if (baseBindingURI) { 1.724 + uint32_t count = aDontExtendURIs.Length(); 1.725 + for (uint32_t index = 0; index < count; ++index) { 1.726 + bool equal; 1.727 + rv = aDontExtendURIs[index]->Equals(baseBindingURI, &equal); 1.728 + NS_ENSURE_SUCCESS(rv, rv); 1.729 + if (equal) { 1.730 + nsAutoCString spec, basespec; 1.731 + protoBinding->BindingURI()->GetSpec(spec); 1.732 + NS_ConvertUTF8toUTF16 protoSpec(spec); 1.733 + baseBindingURI->GetSpec(basespec); 1.734 + NS_ConvertUTF8toUTF16 baseSpecUTF16(basespec); 1.735 + const char16_t* params[] = { protoSpec.get(), baseSpecUTF16.get() }; 1.736 + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, 1.737 + NS_LITERAL_CSTRING("XBL"), nullptr, 1.738 + nsContentUtils::eXBL_PROPERTIES, 1.739 + "CircularExtendsBinding", 1.740 + params, ArrayLength(params), 1.741 + boundDocument->GetDocumentURI()); 1.742 + return NS_ERROR_ILLEGAL_VALUE; 1.743 + } 1.744 + } 1.745 + } 1.746 + } 1.747 + 1.748 + nsRefPtr<nsXBLBinding> baseBinding; 1.749 + if (baseBindingURI) { 1.750 + nsIContent* child = protoBinding->GetBindingElement(); 1.751 + rv = GetBinding(aBoundElement, baseBindingURI, aPeekOnly, 1.752 + child->NodePrincipal(), aIsReady, 1.753 + getter_AddRefs(baseBinding), aDontExtendURIs); 1.754 + if (NS_FAILED(rv)) 1.755 + return rv; // We aren't ready yet. 1.756 + } 1.757 + 1.758 + *aIsReady = true; 1.759 + 1.760 + if (!aPeekOnly) { 1.761 + // Make a new binding 1.762 + nsXBLBinding *newBinding = new nsXBLBinding(protoBinding); 1.763 + NS_ENSURE_TRUE(newBinding, NS_ERROR_OUT_OF_MEMORY); 1.764 + 1.765 + if (baseBinding) { 1.766 + if (!baseProto) { 1.767 + protoBinding->SetBasePrototype(baseBinding->PrototypeBinding()); 1.768 + } 1.769 + newBinding->SetBaseBinding(baseBinding); 1.770 + } 1.771 + 1.772 + NS_ADDREF(*aResult = newBinding); 1.773 + } 1.774 + 1.775 + return NS_OK; 1.776 +} 1.777 + 1.778 +static bool SchemeIs(nsIURI* aURI, const char* aScheme) 1.779 +{ 1.780 + nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI); 1.781 + NS_ENSURE_TRUE(baseURI, false); 1.782 + 1.783 + bool isScheme = false; 1.784 + return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme; 1.785 +} 1.786 + 1.787 +static bool 1.788 +IsSystemOrChromeURLPrincipal(nsIPrincipal* aPrincipal) 1.789 +{ 1.790 + if (nsContentUtils::IsSystemPrincipal(aPrincipal)) { 1.791 + return true; 1.792 + } 1.793 + 1.794 + nsCOMPtr<nsIURI> uri; 1.795 + aPrincipal->GetURI(getter_AddRefs(uri)); 1.796 + NS_ENSURE_TRUE(uri, false); 1.797 + 1.798 + bool isChrome = false; 1.799 + return NS_SUCCEEDED(uri->SchemeIs("chrome", &isChrome)) && isChrome; 1.800 +} 1.801 + 1.802 +nsresult 1.803 +nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement, 1.804 + nsIDocument* aBoundDocument, 1.805 + nsIURI* aBindingURI, 1.806 + nsIPrincipal* aOriginPrincipal, 1.807 + bool aForceSyncLoad, 1.808 + nsXBLDocumentInfo** aResult) 1.809 +{ 1.810 + NS_PRECONDITION(aBindingURI, "Must have a binding URI"); 1.811 + NS_PRECONDITION(!aOriginPrincipal || aBoundDocument, 1.812 + "If we're doing a security check, we better have a document!"); 1.813 + 1.814 + nsresult rv; 1.815 + if (aOriginPrincipal) { 1.816 + // Security check - Enforce same-origin policy, except to chrome. 1.817 + // We have to be careful to not pass aContent as the context here. 1.818 + // Otherwise, if there is a JS-implemented content policy, we will attempt 1.819 + // to wrap the content node, which will try to load XBL bindings for it, if 1.820 + // any. Since we're not done loading this binding yet, that will reenter 1.821 + // this method and we'll end up creating a binding and then immediately 1.822 + // clobbering it in our table. That makes things very confused, leading to 1.823 + // misbehavior and crashes. 1.824 + rv = nsContentUtils:: 1.825 + CheckSecurityBeforeLoad(aBindingURI, aOriginPrincipal, 1.826 + nsIScriptSecurityManager::ALLOW_CHROME, 1.827 + gAllowDataURIs, 1.828 + nsIContentPolicy::TYPE_XBL, 1.829 + aBoundDocument); 1.830 + NS_ENSURE_SUCCESS(rv, NS_ERROR_XBL_BLOCKED); 1.831 + 1.832 + if (!IsSystemOrChromeURLPrincipal(aOriginPrincipal)) { 1.833 + // Also make sure that we're same-origin with the bound document 1.834 + // except if the stylesheet has the system principal. 1.835 + if (!(gAllowDataURIs && SchemeIs(aBindingURI, "data")) && 1.836 + !SchemeIs(aBindingURI, "chrome")) { 1.837 + rv = aBoundDocument->NodePrincipal()->CheckMayLoad(aBindingURI, 1.838 + true, false); 1.839 + NS_ENSURE_SUCCESS(rv, NS_ERROR_XBL_BLOCKED); 1.840 + } 1.841 + 1.842 + // Finally check if this document is allowed to use XBL at all. 1.843 + NS_ENSURE_TRUE(aBoundDocument->AllowXULXBL(), 1.844 + NS_ERROR_XBL_BLOCKED); 1.845 + } 1.846 + } 1.847 + 1.848 + *aResult = nullptr; 1.849 + nsRefPtr<nsXBLDocumentInfo> info; 1.850 + 1.851 + nsCOMPtr<nsIURI> documentURI; 1.852 + rv = aBindingURI->CloneIgnoringRef(getter_AddRefs(documentURI)); 1.853 + NS_ENSURE_SUCCESS(rv, rv); 1.854 + 1.855 +#ifdef MOZ_XUL 1.856 + // We've got a file. Check our XBL document cache. 1.857 + nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance(); 1.858 + bool useXULCache = cache && cache->IsEnabled(); 1.859 + 1.860 + if (useXULCache) { 1.861 + // The first line of defense is the chrome cache. 1.862 + // This cache crosses the entire product, so that any XBL bindings that are 1.863 + // part of chrome will be reused across all XUL documents. 1.864 + info = cache->GetXBLDocumentInfo(documentURI); 1.865 + } 1.866 +#endif 1.867 + 1.868 + if (!info) { 1.869 + // The second line of defense is the binding manager's document table. 1.870 + nsBindingManager *bindingManager = nullptr; 1.871 + 1.872 + if (aBoundDocument) { 1.873 + bindingManager = aBoundDocument->BindingManager(); 1.874 + info = bindingManager->GetXBLDocumentInfo(documentURI); 1.875 + if (aBoundDocument->IsStaticDocument() && 1.876 + IsChromeOrResourceURI(aBindingURI)) { 1.877 + aForceSyncLoad = true; 1.878 + } 1.879 + } 1.880 + 1.881 + nsINodeInfo *ni = nullptr; 1.882 + if (aBoundElement) 1.883 + ni = aBoundElement->NodeInfo(); 1.884 + 1.885 + if (!info && bindingManager && 1.886 + (!ni || !(ni->Equals(nsGkAtoms::scrollbar, kNameSpaceID_XUL) || 1.887 + ni->Equals(nsGkAtoms::thumb, kNameSpaceID_XUL) || 1.888 + ((ni->Equals(nsGkAtoms::input) || 1.889 + ni->Equals(nsGkAtoms::select)) && 1.890 + aBoundElement->IsHTML()))) && !aForceSyncLoad) { 1.891 + // The third line of defense is to investigate whether or not the 1.892 + // document is currently being loaded asynchronously. If so, there's no 1.893 + // document yet, but we need to glom on our request so that it will be 1.894 + // processed whenever the doc does finish loading. 1.895 + nsCOMPtr<nsIStreamListener> listener; 1.896 + if (bindingManager) 1.897 + listener = bindingManager->GetLoadingDocListener(documentURI); 1.898 + if (listener) { 1.899 + nsXBLStreamListener* xblListener = 1.900 + static_cast<nsXBLStreamListener*>(listener.get()); 1.901 + // Create a new load observer. 1.902 + if (!xblListener->HasRequest(aBindingURI, aBoundElement)) { 1.903 + nsXBLBindingRequest* req = new nsXBLBindingRequest(aBindingURI, aBoundElement); 1.904 + xblListener->AddRequest(req); 1.905 + } 1.906 + return NS_OK; 1.907 + } 1.908 + } 1.909 + 1.910 +#ifdef MOZ_XUL 1.911 + // Next, look in the startup cache 1.912 + bool useStartupCache = useXULCache && IsChromeOrResourceURI(documentURI); 1.913 + if (!info && useStartupCache) { 1.914 + rv = nsXBLDocumentInfo::ReadPrototypeBindings(documentURI, getter_AddRefs(info)); 1.915 + if (NS_SUCCEEDED(rv)) { 1.916 + cache->PutXBLDocumentInfo(info); 1.917 + 1.918 + if (bindingManager) { 1.919 + // Cache it in our binding manager's document table. 1.920 + bindingManager->PutXBLDocumentInfo(info); 1.921 + } 1.922 + } 1.923 + } 1.924 +#endif 1.925 + 1.926 + if (!info) { 1.927 + // Finally, if all lines of defense fail, we go and fetch the binding 1.928 + // document. 1.929 + 1.930 + // Always load chrome synchronously 1.931 + bool chrome; 1.932 + if (NS_SUCCEEDED(documentURI->SchemeIs("chrome", &chrome)) && chrome) 1.933 + aForceSyncLoad = true; 1.934 + 1.935 + nsCOMPtr<nsIDocument> document; 1.936 + FetchBindingDocument(aBoundElement, aBoundDocument, documentURI, 1.937 + aBindingURI, aForceSyncLoad, getter_AddRefs(document)); 1.938 + 1.939 + if (document) { 1.940 + nsBindingManager *xblDocBindingManager = document->BindingManager(); 1.941 + info = xblDocBindingManager->GetXBLDocumentInfo(documentURI); 1.942 + if (!info) { 1.943 + NS_ERROR("An XBL file is malformed. Did you forget the XBL namespace on the bindings tag?"); 1.944 + return NS_ERROR_FAILURE; 1.945 + } 1.946 + xblDocBindingManager->RemoveXBLDocumentInfo(info); // Break the self-imposed cycle. 1.947 + 1.948 + // If the doc is a chrome URI, then we put it into the XUL cache. 1.949 +#ifdef MOZ_XUL 1.950 + if (useStartupCache) { 1.951 + cache->PutXBLDocumentInfo(info); 1.952 + 1.953 + // now write the bindings into the startup cache 1.954 + info->WritePrototypeBindings(); 1.955 + } 1.956 +#endif 1.957 + 1.958 + if (bindingManager) { 1.959 + // Also put it in our binding manager's document table. 1.960 + bindingManager->PutXBLDocumentInfo(info); 1.961 + } 1.962 + } 1.963 + } 1.964 + } 1.965 + 1.966 + info.forget(aResult); 1.967 + 1.968 + return NS_OK; 1.969 +} 1.970 + 1.971 +nsresult 1.972 +nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoundDocument, 1.973 + nsIURI* aDocumentURI, nsIURI* aBindingURI, 1.974 + bool aForceSyncLoad, nsIDocument** aResult) 1.975 +{ 1.976 + nsresult rv = NS_OK; 1.977 + // Initialize our out pointer to nullptr 1.978 + *aResult = nullptr; 1.979 + 1.980 + // Now we have to synchronously load the binding file. 1.981 + // Create an XML content sink and a parser. 1.982 + nsCOMPtr<nsILoadGroup> loadGroup; 1.983 + if (aBoundDocument) 1.984 + loadGroup = aBoundDocument->GetDocumentLoadGroup(); 1.985 + 1.986 + // We really shouldn't have to force a sync load for anything here... could 1.987 + // we get away with not doing that? Not sure. 1.988 + if (IsChromeOrResourceURI(aDocumentURI)) 1.989 + aForceSyncLoad = true; 1.990 + 1.991 + // Create document and contentsink and set them up. 1.992 + nsCOMPtr<nsIDocument> doc; 1.993 + rv = NS_NewXMLDocument(getter_AddRefs(doc)); 1.994 + NS_ENSURE_SUCCESS(rv, rv); 1.995 + 1.996 + nsCOMPtr<nsIXMLContentSink> xblSink; 1.997 + rv = NS_NewXBLContentSink(getter_AddRefs(xblSink), doc, aDocumentURI, nullptr); 1.998 + NS_ENSURE_SUCCESS(rv, rv); 1.999 + 1.1000 + // Open channel 1.1001 + nsCOMPtr<nsIChannel> channel; 1.1002 + rv = NS_NewChannel(getter_AddRefs(channel), aDocumentURI, nullptr, loadGroup); 1.1003 + NS_ENSURE_SUCCESS(rv, rv); 1.1004 + 1.1005 + nsCOMPtr<nsIInterfaceRequestor> sameOriginChecker = nsContentUtils::GetSameOriginChecker(); 1.1006 + NS_ENSURE_TRUE(sameOriginChecker, NS_ERROR_OUT_OF_MEMORY); 1.1007 + 1.1008 + channel->SetNotificationCallbacks(sameOriginChecker); 1.1009 + 1.1010 + if (!aForceSyncLoad) { 1.1011 + // We can be asynchronous 1.1012 + nsXBLStreamListener* xblListener = 1.1013 + new nsXBLStreamListener(aBoundDocument, xblSink, doc); 1.1014 + NS_ENSURE_TRUE(xblListener,NS_ERROR_OUT_OF_MEMORY); 1.1015 + 1.1016 + // Add ourselves to the list of loading docs. 1.1017 + nsBindingManager *bindingManager; 1.1018 + if (aBoundDocument) 1.1019 + bindingManager = aBoundDocument->BindingManager(); 1.1020 + else 1.1021 + bindingManager = nullptr; 1.1022 + 1.1023 + if (bindingManager) 1.1024 + bindingManager->PutLoadingDocListener(aDocumentURI, xblListener); 1.1025 + 1.1026 + // Add our request. 1.1027 + nsXBLBindingRequest* req = new nsXBLBindingRequest(aBindingURI, 1.1028 + aBoundElement); 1.1029 + xblListener->AddRequest(req); 1.1030 + 1.1031 + // Now kick off the async read. 1.1032 + rv = channel->AsyncOpen(xblListener, nullptr); 1.1033 + if (NS_FAILED(rv)) { 1.1034 + // Well, we won't be getting a load. Make sure to clean up our stuff! 1.1035 + if (bindingManager) { 1.1036 + bindingManager->RemoveLoadingDocListener(aDocumentURI); 1.1037 + } 1.1038 + } 1.1039 + return NS_OK; 1.1040 + } 1.1041 + 1.1042 + nsCOMPtr<nsIStreamListener> listener; 1.1043 + rv = doc->StartDocumentLoad("loadAsInteractiveData", 1.1044 + channel, 1.1045 + loadGroup, 1.1046 + nullptr, 1.1047 + getter_AddRefs(listener), 1.1048 + true, 1.1049 + xblSink); 1.1050 + NS_ENSURE_SUCCESS(rv, rv); 1.1051 + 1.1052 + // Now do a blocking synchronous parse of the file. 1.1053 + nsCOMPtr<nsIInputStream> in; 1.1054 + rv = channel->Open(getter_AddRefs(in)); 1.1055 + NS_ENSURE_SUCCESS(rv, rv); 1.1056 + 1.1057 + rv = nsSyncLoadService::PushSyncStreamToListener(in, listener, channel); 1.1058 + NS_ENSURE_SUCCESS(rv, rv); 1.1059 + 1.1060 + doc.swap(*aResult); 1.1061 + 1.1062 + return NS_OK; 1.1063 +}