diff --git a/content/xul/templates/public/nsIXULTemplateBuilder.idl b/content/xul/templates/public/nsIXULTemplateBuilder.idl index a704caa6439..a9635d1f2ae 100644 --- a/content/xul/templates/public/nsIXULTemplateBuilder.idl +++ b/content/xul/templates/public/nsIXULTemplateBuilder.idl @@ -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; diff --git a/content/xul/templates/src/nsXULTemplateBuilder.cpp b/content/xul/templates/src/nsXULTemplateBuilder.cpp index 76f68d70ea1..28afe0132e9 100644 --- a/content/xul/templates/src/nsXULTemplateBuilder.cpp +++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp @@ -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) { diff --git a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp index ef096f6cb41..8cad430fc7b 100644 --- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp +++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp @@ -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 node = do_QueryElementAt(aDataSources, 0); + if (node) { + return CallQueryInterface(node, aResult); + } + + nsCOMPtr uri = do_QueryElementAt(aDataSources, 0); + if (!uri) + return NS_ERROR_UNEXPECTED; + + nsCAutoString uriStr; + rv = uri->GetSpec(uriStr); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr 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 node = do_QueryElementAt(aDataSources, 0); - - if (node) { - return CallQueryInterface(node, aResult); - } - - nsCOMPtr uri = do_QueryElementAt(aDataSources,0); - if (!uri) - return NS_ERROR_UNEXPECTED; + nsCOMPtr uri2; + docPrincipal->GetURI(getter_AddRefs(uri2)); PRBool hasHadScriptObject = PR_TRUE; nsIScriptGlobalObject* scriptObject = doc->GetScriptHandlingObject(hasHadScriptObject); NS_ENSURE_STATE(scriptObject || !hasHadScriptObject); - nsAutoString emptyStr; - nsCOMPtr 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 req = + do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr 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 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 target = do_QueryInterface(domDocument); - target->AddEventListener(NS_LITERAL_STRING("load"), this, PR_FALSE); - - nsCOMPtr 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 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 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; } diff --git a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.h b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.h index 179057cee7c..b6b08d112c3 100644 --- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.h +++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.h @@ -52,6 +52,7 @@ #include "nsIDOMXPathResult.h" #include "nsXMLBinding.h" #include "nsCycleCollectionParticipant.h" +#include "nsIXMLHttpRequest.h" class nsXULTemplateQueryProcessorXML; @@ -185,6 +186,8 @@ private: nsCOMPtr mEvaluator; nsCOMPtr mTemplateBuilder; + + nsCOMPtr mRequest; };