From 8d5ee45263afa259b2815addaf6b8b0cbd2e31c0 Mon Sep 17 00:00:00 2001 From: "allan%beaufour.dk" Date: Mon, 21 Feb 2005 11:20:46 +0000 Subject: [PATCH] Delays dispatching of document load event until all instances have been loaded. Bug 282351, r=aaronr/darin/me, patch by smaug@welho.com git-svn-id: svn://10.0.0.236/trunk@169560 18797224-902f-48f8-a5cc-f745e15eee43 --- .../xforms/nsXFormsInstanceElement.cpp | 160 ++++++++++-------- .../xforms/nsXFormsInstanceElement.h | 26 ++- 2 files changed, 96 insertions(+), 90 deletions(-) diff --git a/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp b/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp index 294957caae5..90e5e6706c9 100644 --- a/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Brian Ryner + * Olli Pettay * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -45,17 +46,18 @@ #include "nsXFormsAtoms.h" #include "nsString.h" #include "nsIDOMEventReceiver.h" -#include "nsIDOMXMLDocument.h" #include "nsIDOMDOMImplementation.h" #include "nsIXTFGenericElementWrapper.h" #include "nsXFormsUtils.h" #include "nsNetUtil.h" +static const char* kLoadAsData = "loadAsData"; + NS_IMPL_ISUPPORTS_INHERITED3(nsXFormsInstanceElement, nsXFormsStubElement, nsIInstanceElementPrivate, - nsIDOMLoadListener, - nsIDOMEventListener) + nsIStreamListener, + nsIRequestObserver) nsXFormsInstanceElement::nsXFormsInstanceElement() : mElement(nsnull) @@ -66,10 +68,7 @@ nsXFormsInstanceElement::nsXFormsInstanceElement() NS_IMETHODIMP nsXFormsInstanceElement::OnDestroyed() { - nsCOMPtr rec = do_QueryInterface(mDocument); - if (rec) - rec->RemoveEventListenerByIID(this, NS_GET_IID(nsIDOMLoadListener)); - + mListener = nsnull; mElement = nsnull; return NS_OK; } @@ -156,55 +155,60 @@ nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper) return NS_OK; } -// nsIDOMLoadListener +// nsIStreamListener NS_IMETHODIMP -nsXFormsInstanceElement::Load(nsIDOMEvent *aEvent) +nsXFormsInstanceElement::OnStartRequest(nsIRequest *request, nsISupports *ctx) { + NS_ASSERTION(mListener, "No stream listener for document!"); + return mListener->OnStartRequest(request, ctx); +} + +NS_IMETHODIMP +nsXFormsInstanceElement::OnDataAvailable(nsIRequest *aRequest, + nsISupports *ctxt, + nsIInputStream *inStr, + PRUint32 sourceOffset, + PRUint32 count) +{ + NS_ASSERTION(mListener, "No stream listener for document!"); + return mListener->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset, count); +} + +NS_IMETHODIMP +nsXFormsInstanceElement::OnStopRequest(nsIRequest *request, nsISupports *ctx, + nsresult status) +{ + NS_ASSERTION(mListener, "No stream listener for document!"); + mListener->OnStopRequest(request, ctx, status); + + PRBool succeeded = NS_SUCCEEDED(status); + if (!succeeded) + mDocument = nsnull; + + if (mDocument) { + nsCOMPtr docElem; + mDocument->GetDocumentElement(getter_AddRefs(docElem)); + if (docElem) { + nsAutoString tagName, namespaceURI; + docElem->GetTagName(tagName); + docElem->GetNamespaceURI(namespaceURI); + + if (tagName.EqualsLiteral("parsererror") && + namespaceURI.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) { + NS_WARNING("resulting instance document could not be parsed"); + succeeded = PR_FALSE; + mDocument = nsnull; + } + } + } + nsCOMPtr model = GetModel(); - if (model) - model->InstanceLoadFinished(PR_TRUE); + if (model) { + model->InstanceLoadFinished(succeeded); + } - return NS_OK; -} - -NS_IMETHODIMP -nsXFormsInstanceElement::BeforeUnload(nsIDOMEvent *aEvent) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsXFormsInstanceElement::Unload(nsIDOMEvent *aEvent) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsXFormsInstanceElement::Abort(nsIDOMEvent *aEvent) -{ - nsCOMPtr model = GetModel(); - if (model) - model->InstanceLoadFinished(PR_FALSE); - - return NS_OK; -} - -NS_IMETHODIMP -nsXFormsInstanceElement::Error(nsIDOMEvent *aEvent) -{ - nsCOMPtr model = GetModel(); - if (model) - model->InstanceLoadFinished(PR_FALSE); - - return NS_OK; -} - -// nsIDOMEventListener - -NS_IMETHODIMP -nsXFormsInstanceElement::HandleEvent(nsIDOMEvent *aEvent) -{ + mListener = nsnull; return NS_OK; } @@ -332,38 +336,46 @@ nsXFormsInstanceElement::CloneInlineInstance() void nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc) { + nsresult rv = NS_ERROR_FAILURE; // Clear out our existing instance data - if (NS_FAILED(CreateInstanceDocument())) - return; + if (NS_SUCCEEDED(CreateInstanceDocument())) { + nsCOMPtr newDoc = do_QueryInterface(mDocument); - nsCOMPtr doc = do_QueryInterface(mDocument); - if (!doc) - return; + nsCOMPtr domDoc; + mElement->GetOwnerDocument(getter_AddRefs(domDoc)); + nsCOMPtr doc(do_QueryInterface(domDoc)); + if (doc) { + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), aSrc, doc->GetDocumentCharacterSet().get(), + doc->GetDocumentURI()); + if (uri) { + if (nsXFormsUtils::CheckSameOrigin(doc->GetDocumentURI(), uri)) { + nsCOMPtr loadGroup; + loadGroup = doc->GetDocumentLoadGroup(); + NS_WARN_IF_FALSE(loadGroup, "No load group!"); - nsCOMPtr uri; - NS_NewURI(getter_AddRefs(uri), aSrc, doc->GetDocumentCharacterSet().get(), - doc->GetDocumentURI()); - if (!uri) - return; + // Using the same load group as the main document and creating + // the channel with LOAD_NORMAL flag delays the dispatching of + // the 'load' event until all instance data documents have been loaded. + nsCOMPtr docChannel; + NS_NewChannel(getter_AddRefs(docChannel), uri, nsnull, loadGroup, + nsnull, nsIRequest::LOAD_NORMAL); - PRBool success = PR_FALSE; - - if (nsXFormsUtils::CheckSameOrigin(doc->GetDocumentURI(), uri)) { - nsCOMPtr rec = do_QueryInterface(mDocument); - rec->AddEventListenerByIID(this, NS_GET_IID(nsIDOMLoadListener)); - - nsCOMPtr xmlDoc = do_QueryInterface(mDocument); - NS_ASSERTION(xmlDoc, "we created a document but it's not an XMLDocument?"); - - nsCAutoString spec; - uri->GetSpec(spec); - xmlDoc->Load(NS_ConvertUTF8toUTF16(spec), &success); + if (docChannel) { + rv = newDoc->StartDocumentLoad(kLoadAsData, docChannel, loadGroup, nsnull, + getter_AddRefs(mListener), PR_TRUE); + if (NS_SUCCEEDED(rv)) + rv = docChannel->AsyncOpen(this, nsnull); + } + } + } + } } nsCOMPtr model = GetModel(); if (model) { model->InstanceLoadStarted(); - if (!success) { + if (NS_FAILED(rv)) { model->InstanceLoadFinished(PR_FALSE); } } diff --git a/mozilla/extensions/xforms/nsXFormsInstanceElement.h b/mozilla/extensions/xforms/nsXFormsInstanceElement.h index b88fe5c6e08..163bc01d609 100644 --- a/mozilla/extensions/xforms/nsXFormsInstanceElement.h +++ b/mozilla/extensions/xforms/nsXFormsInstanceElement.h @@ -42,9 +42,10 @@ #include "nsXFormsStubElement.h" #include "nsIDOMDocument.h" #include "nsCOMPtr.h" -#include "nsIDOMLoadListener.h" #include "nsIModelElementPrivate.h" #include "nsIInstanceElementPrivate.h" +#include "nsIRequestObserver.h" +#include "nsIStreamListener.h" class nsIDOMElement; @@ -56,11 +57,13 @@ class nsIDOMElement; class nsXFormsInstanceElement : public nsXFormsStubElement, public nsIInstanceElementPrivate, - public nsIDOMLoadListener + public nsIStreamListener { public: NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSIINSTANCEELEMENTPRIVATE + NS_DECL_NSISTREAMLISTENER // nsIXTFGenericElement overrides NS_IMETHOD OnDestroyed(); @@ -70,16 +73,6 @@ public: NS_IMETHOD DoneAddingChildren(); NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper); - // nsIDOMEventListener - NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent); - - // nsIDOMLoadListener - NS_IMETHOD Load(nsIDOMEvent *aEvent); - NS_IMETHOD BeforeUnload(nsIDOMEvent *aEvent); - NS_IMETHOD Unload(nsIDOMEvent *aEvent); - NS_IMETHOD Abort(nsIDOMEvent *aEvent); - NS_IMETHOD Error(nsIDOMEvent *aEvent); - nsXFormsInstanceElement() NS_HIDDEN; private: @@ -88,10 +81,11 @@ private: NS_HIDDEN_(nsresult) CreateInstanceDocument(); NS_HIDDEN_(already_AddRefed) GetModel(); - nsCOMPtr mDocument; - nsCOMPtr mOriginalDocument; - nsIDOMElement *mElement; - PRBool mIgnoreAttributeChanges; + nsCOMPtr mDocument; + nsCOMPtr mOriginalDocument; + nsIDOMElement *mElement; + nsCOMPtr mListener; + PRBool mIgnoreAttributeChanges; }; NS_HIDDEN_(nsresult)