Bug 305763, Application control models and fixes to lazy instances, r=aaronr+allan

This commit is contained in:
Olli.Pettay%helsinki.fi 2005-10-10 19:11:23 +00:00
parent db2b6408e1
commit 5ffd707e38
14 changed files with 188 additions and 351 deletions

View File

@ -151,7 +151,6 @@ CPPSRCS = \
nsXFormsControlStub.cpp \
nsXFormsUtilityService.cpp \
nsXFormsDelegateStub.cpp \
nsXFormsLazyInstanceElement.cpp \
$(NULL)
EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS)

View File

@ -44,7 +44,7 @@ interface nsIDOMElement;
/**
* Private interface implemented by the instance element.
*/
[uuid(8c9dd10d-4189-4a7b-a2eb-fd695cf33b27)]
[uuid(446dc7b6-91fc-4de5-b6de-5ac22538ee5e)]
interface nsIInstanceElementPrivate : nsISupports
{
/**
@ -54,4 +54,5 @@ interface nsIInstanceElementPrivate : nsISupports
readonly attribute nsIDOMElement element;
void backupOriginalDocument();
void restoreOriginalDocument();
void initializeLazyInstance();
};

View File

@ -64,6 +64,7 @@ nsIAtom *nsXFormsAtoms::readyForBindProperty;
nsIAtom *nsXFormsAtoms::accesskey;
nsIAtom *nsXFormsAtoms::fatalError;
nsIAtom *nsXFormsAtoms::isInstanceDocument;
nsIAtom *nsXFormsAtoms::instanceDocumentOwner;
const nsStaticAtom nsXFormsAtoms::Atoms_info[] = {
{ "src", &nsXFormsAtoms::src },
@ -90,7 +91,8 @@ const nsStaticAtom nsXFormsAtoms::Atoms_info[] = {
{ "ReadyForBindProperty", &nsXFormsAtoms::readyForBindProperty },
{ "accesskey", &nsXFormsAtoms::accesskey },
{ "fatalError", &nsXFormsAtoms::fatalError },
{ "isInstanceDocument", &nsXFormsAtoms::isInstanceDocument }
{ "isInstanceDocument", &nsXFormsAtoms::isInstanceDocument },
{ "instanceDocumentOwner", &nsXFormsAtoms::instanceDocumentOwner }
};
void

View File

@ -72,6 +72,7 @@ class nsXFormsAtoms
static NS_HIDDEN_(nsIAtom *) accesskey;
static NS_HIDDEN_(nsIAtom *) fatalError;
static NS_HIDDEN_(nsIAtom *) isInstanceDocument;
static NS_HIDDEN_(nsIAtom *) instanceDocumentOwner;
static NS_HIDDEN_(void) InitAtoms();

View File

@ -221,7 +221,7 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
NS_ENSURE_STATE(modelElem);
nsCOMPtr<nsIDOMNode> instNode;
rv = nsXFormsUtils::GetInstanceNodeForData(resNode, model, getter_AddRefs(instNode));
rv = nsXFormsUtils::GetInstanceNodeForData(resNode, getter_AddRefs(instNode));
NS_ENSURE_SUCCESS(rv, rv);
rv = nsXFormsUtils::DispatchEvent(instNode,

View File

@ -63,7 +63,8 @@ NS_IMPL_ISUPPORTS_INHERITED5(nsXFormsInstanceElement,
nsXFormsInstanceElement::nsXFormsInstanceElement()
: mElement(nsnull)
, mIgnoreAttributeChanges(PR_FALSE)
, mAddingChildren(PR_FALSE)
, mLazy(PR_FALSE)
{
}
@ -77,6 +78,7 @@ nsXFormsInstanceElement::OnDestroyed()
mChannel = nsnull;
}
mListener = nsnull;
SetDocument(nsnull);
mElement = nsnull;
return NS_OK;
}
@ -85,7 +87,7 @@ NS_IMETHODIMP
nsXFormsInstanceElement::AttributeSet(nsIAtom *aName,
const nsAString &aNewValue)
{
if (mIgnoreAttributeChanges)
if (mAddingChildren || mLazy)
return NS_OK;
if (aName == nsXFormsAtoms::src) {
@ -98,7 +100,7 @@ nsXFormsInstanceElement::AttributeSet(nsIAtom *aName,
NS_IMETHODIMP
nsXFormsInstanceElement::AttributeRemoved(nsIAtom *aName)
{
if (mIgnoreAttributeChanges)
if (mAddingChildren || mLazy)
return NS_OK;
if (aName == nsXFormsAtoms::src) {
@ -136,18 +138,24 @@ nsXFormsInstanceElement::AttributeRemoved(nsIAtom *aName)
NS_IMETHODIMP
nsXFormsInstanceElement::BeginAddingChildren()
{
// Ignore attribute changes during document construction. Attributes will be
// handled in the DoneAddingChildren.
mIgnoreAttributeChanges = PR_TRUE;
mAddingChildren = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::DoneAddingChildren()
{
// By the time this is called, we should be inserted in the document and have
// all of our child elements, so this is our first opportunity to create the
// instance document.
mElement->HasAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_MOZ_XFORMS_LAZY),
NS_LITERAL_STRING("lazy"), &mLazy);
if (!mLazy) {
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
NS_ENSURE_TRUE(model, NS_ERROR_FAILURE);
model->AddInstanceElement(this);
// By the time this is called, we should be inserted in the document and
// have all of our child elements, so this is our first opportunity to
// create the instance document.
nsAutoString src;
mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
@ -158,9 +166,9 @@ nsXFormsInstanceElement::DoneAddingChildren()
} else {
LoadExternalInstance(src);
}
}
// Now, observe changes to the "src" attribute.
mIgnoreAttributeChanges = PR_FALSE;
mAddingChildren = PR_FALSE;
return NS_OK;
}
@ -189,14 +197,15 @@ nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
NS_IMETHODIMP
nsXFormsInstanceElement::ParentChanged(nsIDOMElement *aNewParent)
{
if (!aNewParent)
if (!aNewParent || mAddingChildren || mLazy)
return NS_OK;
// Once we are set up in the DOM, can find the model and make sure that this
// instance is on the list of instance elements that model keeps
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
NS_ENSURE_TRUE(model, NS_ERROR_FAILURE);
if (model) {
model->AddInstanceElement(this);
}
return NS_OK;
}
@ -218,6 +227,8 @@ nsXFormsInstanceElement::OnChannelRedirect(nsIChannel *OldChannel,
PRUint32 aFlags)
{
NS_PRECONDITION(aNewChannel, "Redirect without a channel?");
NS_PRECONDITION(!mLazy, "Loading an instance document for a lazy instance?");
nsCOMPtr<nsIURI> newURI;
nsresult rv = aNewChannel->GetURI(getter_AddRefs(newURI));
NS_ENSURE_SUCCESS(rv, rv);
@ -252,6 +263,7 @@ nsXFormsInstanceElement::OnChannelRedirect(nsIChannel *OldChannel,
NS_IMETHODIMP
nsXFormsInstanceElement::OnStartRequest(nsIRequest *request, nsISupports *ctx)
{
NS_PRECONDITION(!mLazy, "Loading an instance document for a lazy instance?");
if (!mElement || !mListener) {
return NS_OK;
}
@ -265,6 +277,7 @@ nsXFormsInstanceElement::OnDataAvailable(nsIRequest *aRequest,
PRUint32 sourceOffset,
PRUint32 count)
{
NS_PRECONDITION(!mLazy, "Loading an instance document for a lazy instance?");
if (!mElement || !mListener) {
return NS_OK;
}
@ -275,6 +288,7 @@ NS_IMETHODIMP
nsXFormsInstanceElement::OnStopRequest(nsIRequest *request, nsISupports *ctx,
nsresult status)
{
NS_PRECONDITION(!mLazy, "Loading an instance document for a lazy instance?");
if (status == NS_BINDING_ABORTED) {
// looks like our element has already been destroyed. No use continuing on.
return NS_OK;
@ -285,8 +299,9 @@ nsXFormsInstanceElement::OnStopRequest(nsIRequest *request, nsISupports *ctx,
mListener->OnStopRequest(request, ctx, status);
PRBool succeeded = NS_SUCCEEDED(status);
if (!succeeded)
mDocument = nsnull;
if (!succeeded) {
SetDocument(nsnull);
}
if (mDocument) {
nsCOMPtr<nsIDOMElement> docElem;
@ -300,7 +315,7 @@ nsXFormsInstanceElement::OnStopRequest(nsIRequest *request, nsISupports *ctx,
namespaceURI.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) {
NS_WARNING("resulting instance document could not be parsed");
succeeded = PR_FALSE;
mDocument = nsnull;
SetDocument(nsnull);
}
}
}
@ -326,7 +341,26 @@ nsXFormsInstanceElement::GetDocument(nsIDOMDocument **aDocument)
NS_IMETHODIMP
nsXFormsInstanceElement::SetDocument(nsIDOMDocument *aDocument)
{
nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
if (doc) {
doc->UnsetProperty(nsXFormsAtoms::instanceDocumentOwner);
}
mDocument = aDocument;
doc = do_QueryInterface(mDocument);
if (doc) {
// Set property to prevent an instance document loading an external instance
// document
nsresult rv = doc->SetProperty(nsXFormsAtoms::isInstanceDocument, doc);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> owner(do_QueryInterface(mElement));
NS_ENSURE_STATE(owner);
rv = doc->SetProperty(nsXFormsAtoms::instanceDocumentOwner, owner);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
@ -340,7 +374,12 @@ nsXFormsInstanceElement::BackupOriginalDocument()
// that the instance document, whether external or inline, is loaded into
// mDocument. Get the root node, clone it, and insert it into our copy of
// the document. This is the magic behind getting xforms-reset to work.
if(mDocument && mOriginalDocument) {
nsCOMPtr<nsIDocument> origDoc(do_QueryInterface(mOriginalDocument));
if(mDocument && origDoc) {
// xf:instance elements in original document must not try to load anything.
rv = origDoc->SetProperty(nsXFormsAtoms::isInstanceDocument, origDoc);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> newNode;
nsCOMPtr<nsIDOMElement> instanceRoot;
rv = mDocument->GetDocumentElement(getter_AddRefs(instanceRoot));
@ -405,6 +444,54 @@ nsXFormsInstanceElement::GetElement(nsIDOMElement **aElement)
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::InitializeLazyInstance()
{
NS_ENSURE_STATE(mElement);
if (!mLazy) {
mElement->HasAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_MOZ_XFORMS_LAZY),
NS_LITERAL_STRING("lazy"), &mLazy);
}
NS_ENSURE_STATE(mLazy);
nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
NS_ENSURE_STATE(domDoc);
nsCOMPtr<nsIDOMDOMImplementation> domImpl;
nsresult rv = domDoc->GetImplementation(getter_AddRefs(domImpl));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMDocument> newDoc;
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(newDoc));
NS_ENSURE_SUCCESS(rv, rv);
rv = SetDocument(newDoc);
NS_ENSURE_SUCCESS(rv, rv);
// Lazy authored instance documents have a root named "instanceData"
nsCOMPtr<nsIDOMElement> instanceDataElement;
nsCOMPtr<nsIDOMNode> childReturn;
rv = mDocument->CreateElementNS(EmptyString(),
NS_LITERAL_STRING("instanceData"),
getter_AddRefs(instanceDataElement));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->AppendChild(instanceDataElement, getter_AddRefs(childReturn));
NS_ENSURE_SUCCESS(rv, rv);
// I don't know if not being able to create a backup document is worth
// failing this function. Since it probably won't be used often, we'll
// let it slide. But it probably does mean that things are going south
// with the browser.
domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mOriginalDocument));
NS_WARN_IF_FALSE(mOriginalDocument, "Couldn't create mOriginalDocument!!");
return NS_OK;
}
// private methods
nsresult
@ -539,15 +626,12 @@ nsXFormsInstanceElement::CreateInstanceDocument()
rv = doc->GetImplementation(getter_AddRefs(domImpl));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMDocument> newDoc;
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mDocument));
getter_AddRefs(newDoc));
NS_ENSURE_SUCCESS(rv, rv);
// Set property to prevent an instance document loading an external instance
// document
nsCOMPtr<nsIDocument> idoc(do_QueryInterface(mDocument));
NS_ENSURE_STATE(idoc);
rv = idoc->SetProperty(nsXFormsAtoms::isInstanceDocument, idoc);
rv = SetDocument(newDoc);
NS_ENSURE_SUCCESS(rv, rv);
// I don't know if not being able to create a backup document is worth

View File

@ -92,7 +92,8 @@ private:
nsCOMPtr<nsIDOMDocument> mOriginalDocument;
nsIDOMElement *mElement;
nsCOMPtr<nsIStreamListener> mListener;
PRBool mIgnoreAttributeChanges;
PRBool mAddingChildren;
PRBool mLazy;
nsCOMPtr<nsIChannel> mChannel;
};

View File

@ -1,191 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
*
* 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
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXFormsLazyInstanceElement.h"
#include "nsIDOMElement.h"
#include "nsIDocument.h"
#include "nsIDOMDOMImplementation.h"
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsLazyInstanceElement,
nsXFormsStubElement,
nsIInstanceElementPrivate,
nsIInterfaceRequestor)
nsXFormsLazyInstanceElement::nsXFormsLazyInstanceElement()
{
}
// nsIInstanceElementPrivate
NS_IMETHODIMP
nsXFormsLazyInstanceElement::GetDocument(nsIDOMDocument **aDocument)
{
NS_IF_ADDREF(*aDocument = mDocument);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsLazyInstanceElement::SetDocument(nsIDOMDocument *aDocument)
{
mDocument = aDocument;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsLazyInstanceElement::BackupOriginalDocument()
{
nsresult rv = NS_OK;
// This is called when xforms-ready is received by the model. By now we know
// that the lazy instance document has been populated and is loaded into
// mDocument. Get the root node, clone it, and insert it into our copy of
// the document. This is the magic behind getting xforms-reset to work.
if(mDocument && mOriginalDocument) {
nsCOMPtr<nsIDOMNode> newNode;
nsCOMPtr<nsIDOMElement> instanceRoot;
rv = mDocument->GetDocumentElement(getter_AddRefs(instanceRoot));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(instanceRoot, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMNode> nodeReturn;
rv = instanceRoot->CloneNode(PR_TRUE, getter_AddRefs(newNode));
if(NS_SUCCEEDED(rv)) {
rv = mOriginalDocument->AppendChild(newNode, getter_AddRefs(nodeReturn));
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"failed to set up original instance document");
}
}
return rv;
}
NS_IMETHODIMP
nsXFormsLazyInstanceElement::RestoreOriginalDocument()
{
nsresult rv = NS_OK;
// This is called when xforms-reset is received by the model. We assume
// that the backup of the lazy instance document has been populated and is
// loaded into mOriginalDocument. Get the backup's root node, clone it, and
// insert it into the live copy of the instance document. This is the magic
// behind getting xforms-reset to work.
if(mDocument && mOriginalDocument) {
nsCOMPtr<nsIDOMNode> newNode, instanceRootNode, nodeReturn;
nsCOMPtr<nsIDOMElement> instanceRoot;
// first remove all the old stuff
rv = mDocument->GetDocumentElement(getter_AddRefs(instanceRoot));
if(NS_SUCCEEDED(rv)) {
if(instanceRoot) {
rv = mDocument->RemoveChild(instanceRoot, getter_AddRefs(nodeReturn));
NS_ENSURE_SUCCESS(rv, rv);
}
}
// now all of the garbage is out o' there! Put the original data back
// into mDocument
rv = mOriginalDocument->GetDocumentElement(getter_AddRefs(instanceRoot));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(instanceRoot, NS_ERROR_FAILURE);
instanceRootNode = do_QueryInterface(instanceRoot);
rv = instanceRootNode->CloneNode(PR_TRUE, getter_AddRefs(newNode));
if(NS_SUCCEEDED(rv)) {
rv = mDocument->AppendChild(newNode, getter_AddRefs(nodeReturn));
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"failed to restore original instance document");
}
}
return rv;
}
NS_IMETHODIMP
nsXFormsLazyInstanceElement::GetElement(nsIDOMElement **aElement)
{
*aElement = nsnull;
return NS_OK;
}
// nsIInterfaceRequestor
NS_IMETHODIMP
nsXFormsLazyInstanceElement::GetInterface(const nsIID & aIID, void **aResult)
{
*aResult = nsnull;
return QueryInterface(aIID, aResult);
}
nsresult
nsXFormsLazyInstanceElement::CreateLazyInstanceDocument(nsIDOMDocument *aXFormsDocument)
{
NS_ENSURE_ARG(aXFormsDocument);
// Do not try to load an instance document if the current document is not
// associated with a DOM window. This could happen, for example, if some
// XForms document loaded itself as instance data (which is what the Forms
// 1.0 testsuite does).
nsCOMPtr<nsIDocument> d = do_QueryInterface(aXFormsDocument);
if (d && !d->GetScriptGlobalObject())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMDOMImplementation> domImpl;
nsresult rv = aXFormsDocument->GetImplementation(getter_AddRefs(domImpl));
NS_ENSURE_SUCCESS(rv, rv);
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mDocument));
NS_ENSURE_SUCCESS(rv, rv);
// Lazy authored instance documents have a root named "instanceData"
nsCOMPtr<nsIDOMElement> instanceDataElement;
nsCOMPtr<nsIDOMNode> childReturn;
rv = mDocument->CreateElementNS(EmptyString(),
NS_LITERAL_STRING("instanceData"),
getter_AddRefs(instanceDataElement));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->AppendChild(instanceDataElement, getter_AddRefs(childReturn));
NS_ENSURE_SUCCESS(rv, rv);
// I don't know if not being able to create a backup document is worth
// failing this function. Since it probably won't be used often, we'll
// let it slide. But it probably does mean that things are going south
// with the browser.
domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mOriginalDocument));
return rv;
}

View File

@ -1,76 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
*
* 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
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsXFormsLazyInstanceElement_h_
#define nsXFormsLazyInstanceElement_h_
#include "nsXFormsStubElement.h"
#include "nsIDOMDocument.h"
#include "nsCOMPtr.h"
#include "nsIModelElementPrivate.h"
#include "nsIInstanceElementPrivate.h"
#include "nsIInterfaceRequestor.h"
class nsIDOMElement;
/**
* Implementation of the XForms \<instance\> element created through lazy
* authoring. It creates an instance document by cloning the contained
* instance data.
*/
class nsXFormsLazyInstanceElement : public nsXFormsStubElement,
public nsIInstanceElementPrivate,
public nsIInterfaceRequestor
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIINSTANCEELEMENTPRIVATE
NS_DECL_NSIINTERFACEREQUESTOR
NS_HIDDEN_(nsresult) CreateLazyInstanceDocument(nsIDOMDocument *aXFormsDocument);
nsXFormsLazyInstanceElement() NS_HIDDEN;
private:
nsCOMPtr<nsIDOMDocument> mDocument;
nsCOMPtr<nsIDOMDocument> mOriginalDocument;
};
#endif

View File

@ -75,7 +75,10 @@
#include "nsISchema.h"
#include "nsAutoPtr.h"
#include "nsArray.h"
#include "nsXFormsLazyInstanceElement.h"
#include "nsIDOMDocumentXBL.h"
#define XFORMS_LAZY_INSTANCE_BINDING \
"chrome://xforms/content/xforms.xml#xforms-lazy-instance"
#ifdef DEBUG
//#define DEBUG_MODEL
@ -411,16 +414,43 @@ nsXFormsModelElement::DoneAddingChildren()
// If all of the children are added and there aren't any instance elements,
// yet, then we need to make sure that one is ready in case the form author
// is using lazy authoring.
// Lazy <xforms:intance> element is created in anonymous content using XBL.
PRUint32 instCount = mInstanceList.Count();
if (!instCount) {
nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
if (domDoc) {
nsXFormsLazyInstanceElement *lazyInstance =
new nsXFormsLazyInstanceElement();
lazyInstance->CreateLazyInstanceDocument(domDoc);
AddInstanceElement(lazyInstance);
nsCOMPtr<nsIDOMDocumentXBL> xblDoc(do_QueryInterface(domDoc));
if (xblDoc) {
nsresult rv =
xblDoc->AddBinding(mElement,
NS_LITERAL_STRING(XFORMS_LAZY_INSTANCE_BINDING));
NS_ENSURE_SUCCESS(rv, rv);
NS_WARN_IF_FALSE(mInstanceList.Count() == 1,
"Installing lazy instance didn't succeed!");
nsCOMPtr<nsIDOMNodeList> list;
xblDoc->GetAnonymousNodes(mElement, getter_AddRefs(list));
if (list) {
PRUint32 childCount = 0;
if (list) {
list->GetLength(&childCount);
}
for (PRUint32 i = 0; i < childCount; ++i) {
nsCOMPtr<nsIDOMNode> item;
list->Item(i, getter_AddRefs(item));
nsCOMPtr<nsIInstanceElementPrivate> instance =
do_QueryInterface(item);
if (instance) {
rv = instance->InitializeLazyInstance();
NS_ENSURE_SUCCESS(rv, rv);
mLazyModel = PR_TRUE;
break;
}
}
}
}
}

View File

@ -526,7 +526,7 @@ nsXFormsSubmissionElement::LoadReplaceInstance(nsIChannel *channel)
rv = GetBoundInstanceData(getter_AddRefs(data));
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIDOMNode> instanceNode;
rv = nsXFormsUtils::GetInstanceNodeForData(data, model,
rv = nsXFormsUtils::GetInstanceNodeForData(data,
getter_AddRefs(instanceNode));
NS_ENSURE_SUCCESS(rv, rv);
@ -839,8 +839,7 @@ nsXFormsSubmissionElement::SerializeDataXML(nsIDOMNode *data,
newDoc->GetDocumentElement(getter_AddRefs(newDocElm));
nsCOMPtr<nsIDOMNode> instanceNode;
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
rv = nsXFormsUtils::GetInstanceNodeForData(data, model, getter_AddRefs(instanceNode));
rv = nsXFormsUtils::GetInstanceNodeForData(data, getter_AddRefs(instanceNode));
NS_ENSURE_SUCCESS(rv, rv);
// add namespaces from the main document to the submission document, but only
@ -873,6 +872,7 @@ nsXFormsSubmissionElement::SerializeDataXML(nsIDOMNode *data,
NS_ENSURE_SUCCESS(rv, rv);
// handle namespaces on the model
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
node = do_QueryInterface(model);
NS_ENSURE_STATE(node);
rv = AddNameSpaces(newDocElm, node, prefixHash);

View File

@ -1176,52 +1176,33 @@ nsXFormsUtils::MakeUniqueAndSort(nsCOMArray<nsIDOMNode> *aArray)
/* static */ nsresult
nsXFormsUtils::GetInstanceNodeForData(nsIDOMNode *aInstanceDataNode,
nsIModelElementPrivate *aModel,
nsIDOMNode **aInstanceNode)
{
NS_ENSURE_ARG(aInstanceDataNode);
NS_ENSURE_ARG(aModel);
NS_ENSURE_ARG_POINTER(aInstanceNode);
*aInstanceNode = nsnull;
/* We want to get at the <xf:instance> that aInstanceDataNode belongs to.
We get all xf:instance nodes in the aModel, QI it to nsIInstanceElementPrivate
and compare its document to the document aInstanceDataNode lives in.
*/
nsCOMPtr<nsIDOMDocument> instanceDoc;
aInstanceDataNode->GetOwnerDocument(getter_AddRefs(instanceDoc));
nsCOMPtr<nsIDOMDocument> instanceDOMDoc;
aInstanceDataNode->GetOwnerDocument(getter_AddRefs(instanceDOMDoc));
// owner doc is null when the data node is the document (e.g., ref="/")
if (!instanceDoc)
instanceDoc = do_QueryInterface(aInstanceDataNode);
if (!instanceDOMDoc) {
instanceDOMDoc = do_QueryInterface(aInstanceDataNode);
}
nsCOMPtr<nsIDocument> instanceDoc(do_QueryInterface(instanceDOMDoc));
NS_ENSURE_TRUE(instanceDoc, NS_ERROR_UNEXPECTED);
nsCOMArray<nsIInstanceElementPrivate> *instList = nsnull;
aModel->GetInstanceList(&instList);
NS_ENSURE_TRUE(instList, NS_ERROR_FAILURE);
nsISupports* owner =
NS_STATIC_CAST(
nsISupports*,
instanceDoc->GetProperty(nsXFormsAtoms::instanceDocumentOwner));
PRUint32 i;
PRUint32 childCount = instList->Count();
for (i = 0; i < childCount; ++i) {
nsCOMPtr<nsIInstanceElementPrivate> instPriv = instList->ObjectAt(i);
nsCOMPtr<nsIDOMDocument> tmpDoc;
instPriv->GetDocument(getter_AddRefs(tmpDoc));
if (tmpDoc == instanceDoc) {
// ok, so we found the instance element that contains the provided
// aInstanceDataNode. Now set the return value.
nsCOMPtr<nsIDOMElement> instanceElement;
instPriv->GetElement(getter_AddRefs(instanceElement));
if (instanceElement) {
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(instanceElement);
node.swap(*aInstanceNode);
nsCOMPtr<nsIDOMNode> instanceNode(do_QueryInterface(owner));
if (instanceNode) {
NS_ADDREF(*aInstanceNode = instanceNode);
return NS_OK;
}
}
}
// Two possibilities. No instance nodes in model (which should never happen)
// or instance node not found.
return NS_ERROR_ABORT;
@ -1430,7 +1411,7 @@ FindRepeatContext(nsIDOMElement *aElement, PRBool aFindContainer)
// save running up the tree?
nsCOMPtr<nsIDOMNode> context, temp;
aElement->GetParentNode(getter_AddRefs(context));
nsresult rv;
nsresult rv = NS_OK;
while (context) {
if (nsXFormsUtils::IsXFormsElement(context,
aFindContainer ?

View File

@ -61,6 +61,7 @@ class nsIDOMEvent;
#define NS_NAMESPACE_XML_SCHEMA "http://www.w3.org/2001/XMLSchema"
#define NS_NAMESPACE_XML_SCHEMA_INSTANCE "http://www.w3.org/2001/XMLSchema-instance"
#define NS_NAMESPACE_MOZ_XFORMS_TYPE "http://www.mozilla.org/projects/xforms/2005/type"
#define NS_NAMESPACE_MOZ_XFORMS_LAZY "http://www.mozilla.org/projects/xforms/2005/lazy"
/**
* XForms event types
@ -367,7 +368,6 @@ public:
* Returns the <xf:instance> for a given instance data node.
*/
static NS_HIDDEN_(nsresult) GetInstanceNodeForData(nsIDOMNode *aInstanceDataNode,
nsIModelElementPrivate *aModel,
nsIDOMNode **aInstanceNode);
/**

View File

@ -42,7 +42,12 @@
xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:xforms="http://www.w3.org/2002/xforms">
xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:lazy="http://www.mozilla.org/projects/xforms/2005/lazy">
<binding id="xforms-lazy-instance">
<content><xforms:instance lazy:lazy="true"/><children/></content>
</binding>
<!-- BASE -->
<binding id="xformswidget-base">