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. * 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 interface nsIXULTemplateBuilder : nsISupports
{ {
/** /**
@ -166,10 +166,24 @@ interface nsIXULTemplateBuilder : nsISupports
*/ */
readonly attribute nsIDOMElement root; 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 * The composite datasource that the template builder observes
* and uses to create content. This is used only for RDF queries and * and uses to create content. This is used only for RDF queries and is
* is maintained for backwards compatibility. * 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; readonly attribute nsIRDFCompositeDataSource database;

View File

@ -320,6 +320,25 @@ nsXULTemplateBuilder::GetRoot(nsIDOMElement** aResult)
return NS_OK; 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 NS_IMETHODIMP
nsXULTemplateBuilder::GetDatabase(nsIRDFCompositeDataSource** aResult) nsXULTemplateBuilder::GetDatabase(nsIRDFCompositeDataSource** aResult)
{ {

View File

@ -55,6 +55,7 @@
#include "nsIArray.h" #include "nsIArray.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsArrayUtils.h" #include "nsArrayUtils.h"
#include "nsPIDOMWindow.h"
#include "nsXULTemplateBuilder.h" #include "nsXULTemplateBuilder.h"
#include "nsXULTemplateQueryProcessorXML.h" #include "nsXULTemplateQueryProcessorXML.h"
@ -109,9 +110,11 @@ nsXULTemplateResultSetXML::GetNext(nsISupports **aResult)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorXML) NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorXML)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorXML) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorXML)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTemplateBuilder) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTemplateBuilder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateQueryProcessorXML) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateQueryProcessorXML)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTemplateBuilder) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTemplateBuilder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXULTemplateQueryProcessorXML, NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXULTemplateQueryProcessorXML,
nsIXULTemplateQueryProcessor) nsIXULTemplateQueryProcessor)
@ -123,6 +126,14 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULTemplateQueryProcessorXML)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULTemplateQueryProcessor) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULTemplateQueryProcessor)
NS_INTERFACE_MAP_END 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 NS_IMETHODIMP
nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources, nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
nsIDOMNode* aRootNode, nsIDOMNode* aRootNode,
@ -141,6 +152,22 @@ nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
if (length == 0) if (length == 0)
return NS_OK; 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); nsCOMPtr<nsIContent> root = do_QueryInterface(aRootNode);
if (!root) if (!root)
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
@ -149,52 +176,43 @@ nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
if (!doc) if (!doc)
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
nsIURI *docurl = doc->GetDocumentURI();
nsIPrincipal *docPrincipal = doc->NodePrincipal(); nsIPrincipal *docPrincipal = doc->NodePrincipal();
nsCOMPtr<nsIURI> uri2;
// we get only the first item, because the query processor supports only docPrincipal->GetURI(getter_AddRefs(uri2));
// 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;
PRBool hasHadScriptObject = PR_TRUE; PRBool hasHadScriptObject = PR_TRUE;
nsIScriptGlobalObject* scriptObject = nsIScriptGlobalObject* scriptObject =
doc->GetScriptHandlingObject(hasHadScriptObject); doc->GetScriptHandlingObject(hasHadScriptObject);
NS_ENSURE_STATE(scriptObject || !hasHadScriptObject); NS_ENSURE_STATE(scriptObject || !hasHadScriptObject);
nsAutoString emptyStr;
nsCOMPtr<nsIDOMDocument> domDocument; nsIScriptContext *context = scriptObject->GetContext();
rv = nsContentUtils::CreateDocument(emptyStr, emptyStr, nsnull, NS_ENSURE_TRUE(context, NS_OK);
docurl, doc->GetBaseURI(),
docPrincipal, nsCOMPtr<nsIXMLHttpRequest> req =
scriptObject, do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
getter_AddRefs(domDocument)); 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); NS_ENSURE_SUCCESS(rv, rv);
mTemplateBuilder = aBuilder; mTemplateBuilder = aBuilder;
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(domDocument); mRequest = req;
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);
}
*aShouldDelayBuilding = PR_TRUE;
return NS_OK; return NS_OK;
} }
@ -455,20 +473,19 @@ nsXULTemplateQueryProcessorXML::HandleEvent(nsIDOMEvent* aEvent)
aEvent->GetType(eventType); aEvent->GetType(eventType);
if (eventType.EqualsLiteral("load") && mTemplateBuilder) { if (eventType.EqualsLiteral("load") && mTemplateBuilder) {
// remove the listener NS_ASSERTION(mRequest, "request was not set");
nsCOMPtr<nsIDOMEventTarget> target; nsCOMPtr<nsIDOMDocument> doc;
aEvent->GetTarget(getter_AddRefs(target)); if (NS_SUCCEEDED(mRequest->GetResponseXML(getter_AddRefs(doc))))
if (target) { mTemplateBuilder->SetDatasource(doc);
target->RemoveEventListener(NS_LITERAL_STRING("load"), this, PR_FALSE);
}
// rebuild the template
nsresult rv = mTemplateBuilder->Rebuild();
// to avoid leak. we don't need it after... // to avoid leak. we don't need it after...
mTemplateBuilder = nsnull; mTemplateBuilder = nsnull;
mRequest = nsnull;
return rv;
} }
else if (eventType.EqualsLiteral("error")) {
mTemplateBuilder = nsnull;
mRequest = nsnull;
}
return NS_OK; return NS_OK;
} }

View File

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