Bug 415772, use XMLHttpRequest to load xml datasources, r=smaug,sr=peterv

This commit is contained in:
enndeakin@sympatico.ca 2008-02-20 11:02:31 -08:00
parent b3510107b1
commit 6a0b59e258
4 changed files with 103 additions and 50 deletions

View File

@ -158,7 +158,7 @@ interface nsIXULTemplateQueryProcessor;
*
* See http://wiki.mozilla.org/XUL:Templates_Plan for details about templates.
*/
[scriptable, uuid(fd8fe8a1-5dc3-4830-84b7-f75baccb4a9b)]
[scriptable, uuid(1762801E-1147-4197-BF0D-D749C903AF74)]
interface nsIXULTemplateBuilder : nsISupports
{
/**
@ -166,10 +166,24 @@ interface nsIXULTemplateBuilder : nsISupports
*/
readonly attribute nsIDOMElement root;
/**
* The opaque datasource object that is used for the template. This object
* is created by the getDataSource method of the query processor. May be
* null if the datasource has not been loaded yet. Set this attribute to
* use a different datasource and rebuild the template.
*
* For an RDF datasource, this will be the same as the database. For XML
* this will be the nsIDOMNode for the datasource document or node for
* an inline reference (such as #name). Other query processors may use
* other types for the datasource.
*/
attribute nsISupports datasource;
/**
* The composite datasource that the template builder observes
* and uses to create content. This is used only for RDF queries and
* is maintained for backwards compatibility.
* and uses to create content. This is used only for RDF queries and is
* maintained for backwards compatibility. It will be the same object as
* the datasource property. For non-RDF queries, it will always be null.
*/
readonly attribute nsIRDFCompositeDataSource database;

View File

@ -320,6 +320,25 @@ nsXULTemplateBuilder::GetRoot(nsIDOMElement** aResult)
return NS_OK;
}
NS_IMETHODIMP
nsXULTemplateBuilder::GetDatasource(nsISupports** aResult)
{
if (mCompDB)
NS_ADDREF(*aResult = mCompDB);
else
NS_IF_ADDREF(*aResult = mDataSource);
return NS_OK;
}
NS_IMETHODIMP
nsXULTemplateBuilder::SetDatasource(nsISupports* aResult)
{
mDataSource = aResult;
mCompDB = do_QueryInterface(mDataSource);
return Rebuild();
}
NS_IMETHODIMP
nsXULTemplateBuilder::GetDatabase(nsIRDFCompositeDataSource** aResult)
{

View File

@ -55,6 +55,7 @@
#include "nsIArray.h"
#include "nsContentUtils.h"
#include "nsArrayUtils.h"
#include "nsPIDOMWindow.h"
#include "nsXULTemplateBuilder.h"
#include "nsXULTemplateQueryProcessorXML.h"
@ -109,9 +110,11 @@ nsXULTemplateResultSetXML::GetNext(nsISupports **aResult)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorXML)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorXML)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTemplateBuilder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateQueryProcessorXML)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTemplateBuilder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXULTemplateQueryProcessorXML,
nsIXULTemplateQueryProcessor)
@ -123,6 +126,14 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULTemplateQueryProcessorXML)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULTemplateQueryProcessor)
NS_INTERFACE_MAP_END
/*
* Only the first datasource in aDataSource is used, which should be either an
* nsIURI of an XML document, or a DOM node. If the former, GetDatasource will
* load the document asynchronously and return null in aResult. Once the
* document has loaded, the builder's datasource will be set to the XML
* document. If the datasource is a DOM node, the node will be returned in
* aResult.
*/
NS_IMETHODIMP
nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
nsIDOMNode* aRootNode,
@ -141,6 +152,22 @@ nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
if (length == 0)
return NS_OK;
// we get only the first item, because the query processor supports only
// one document as a datasource
nsCOMPtr<nsIDOMNode> node = do_QueryElementAt(aDataSources, 0);
if (node) {
return CallQueryInterface(node, aResult);
}
nsCOMPtr<nsIURI> uri = do_QueryElementAt(aDataSources, 0);
if (!uri)
return NS_ERROR_UNEXPECTED;
nsCAutoString uriStr;
rv = uri->GetSpec(uriStr);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> root = do_QueryInterface(aRootNode);
if (!root)
return NS_ERROR_UNEXPECTED;
@ -149,52 +176,43 @@ nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
if (!doc)
return NS_ERROR_UNEXPECTED;
nsIURI *docurl = doc->GetDocumentURI();
nsIPrincipal *docPrincipal = doc->NodePrincipal();
// we get only the first item, because the query processor supports only
// one document as a datasource
nsCOMPtr<nsIDOMNode> node = do_QueryElementAt(aDataSources, 0);
if (node) {
return CallQueryInterface(node, aResult);
}
nsCOMPtr<nsIURI> uri = do_QueryElementAt(aDataSources,0);
if (!uri)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIURI> uri2;
docPrincipal->GetURI(getter_AddRefs(uri2));
PRBool hasHadScriptObject = PR_TRUE;
nsIScriptGlobalObject* scriptObject =
doc->GetScriptHandlingObject(hasHadScriptObject);
NS_ENSURE_STATE(scriptObject || !hasHadScriptObject);
nsAutoString emptyStr;
nsCOMPtr<nsIDOMDocument> domDocument;
rv = nsContentUtils::CreateDocument(emptyStr, emptyStr, nsnull,
docurl, doc->GetBaseURI(),
docPrincipal,
scriptObject,
getter_AddRefs(domDocument));
nsIScriptContext *context = scriptObject->GetContext();
NS_ENSURE_TRUE(context, NS_OK);
nsCOMPtr<nsIXMLHttpRequest> req =
do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(scriptObject);
req->Init(docPrincipal, context, owner);
rv = req->OpenRequest(NS_LITERAL_CSTRING("GET"), uriStr, PR_TRUE,
EmptyString(), EmptyString());
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(req));
rv = target->AddEventListener(NS_LITERAL_STRING("load"), this, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = target->AddEventListener(NS_LITERAL_STRING("error"), this, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = req->Send(nsnull);
NS_ENSURE_SUCCESS(rv, rv);
mTemplateBuilder = aBuilder;
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(domDocument);
target->AddEventListener(NS_LITERAL_STRING("load"), this, PR_FALSE);
nsCOMPtr<nsIDOMXMLDocument> xmldoc = do_QueryInterface(domDocument);
PRBool ok;
nsCAutoString uristrC;
uri->GetSpec(uristrC);
xmldoc->Load(NS_ConvertUTF8toUTF16(uristrC), &ok);
if (ok) {
*aShouldDelayBuilding = PR_TRUE;
return CallQueryInterface(domDocument, aResult);
}
mRequest = req;
*aShouldDelayBuilding = PR_TRUE;
return NS_OK;
}
@ -455,20 +473,19 @@ nsXULTemplateQueryProcessorXML::HandleEvent(nsIDOMEvent* aEvent)
aEvent->GetType(eventType);
if (eventType.EqualsLiteral("load") && mTemplateBuilder) {
// remove the listener
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));
if (target) {
target->RemoveEventListener(NS_LITERAL_STRING("load"), this, PR_FALSE);
}
// rebuild the template
nsresult rv = mTemplateBuilder->Rebuild();
NS_ASSERTION(mRequest, "request was not set");
nsCOMPtr<nsIDOMDocument> doc;
if (NS_SUCCEEDED(mRequest->GetResponseXML(getter_AddRefs(doc))))
mTemplateBuilder->SetDatasource(doc);
// to avoid leak. we don't need it after...
mTemplateBuilder = nsnull;
return rv;
mRequest = nsnull;
}
else if (eventType.EqualsLiteral("error")) {
mTemplateBuilder = nsnull;
mRequest = nsnull;
}
return NS_OK;
}

View File

@ -52,6 +52,7 @@
#include "nsIDOMXPathResult.h"
#include "nsXMLBinding.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIXMLHttpRequest.h"
class nsXULTemplateQueryProcessorXML;
@ -185,6 +186,8 @@ private:
nsCOMPtr<nsIDOMXPathEvaluator> mEvaluator;
nsCOMPtr<nsIXULTemplateBuilder> mTemplateBuilder;
nsCOMPtr<nsIXMLHttpRequest> mRequest;
};