(our grandparent):
- *
- * <-- gParent
- *
- * <-- this
- *
- *
- *
- */
- nsCOMPtr parent;
- mElement->GetParentNode(getter_AddRefs(parent));
- NS_ASSERTION(parent, "how can we get focus without a parent?");
-
- nsCOMPtr gParent;
- parent->GetParentNode(getter_AddRefs(gParent));
- nsCOMPtr repeat = do_QueryInterface(gParent);
- if (!repeat)
- // Not a child to a \
- return NS_OK;
+ // Need to explicitly create the parent chain. This ensures that this code
+ // works both in 1.8, which has the old event dispatching code, and also in
+ // the later versions of Gecko with the new event dispatching.
+ // See also Bug 331081.
+ nsCOMPtr event = do_QueryInterface(aEvent);
+ NS_ENSURE_STATE(event);
+ nsCOMPtr target;
+ event->GetOriginalTarget(getter_AddRefs(target));
+ nsCOMPtr currentNode = do_QueryInterface(target);
- // Tell \ about the new index position
- PRUint32 tmp = mContextPosition;
- return repeat->SetIndex(&tmp, PR_FALSE);
+ nsCOMArray containerStack(4);
+ while (currentNode) {
+ nsCOMPtr repeatItem =
+ do_QueryInterface(currentNode);
+ if (repeatItem) {
+ containerStack.AppendObject(currentNode);
+ }
+ nsCOMPtr parent;
+ currentNode->GetParentNode(getter_AddRefs(parent));
+ currentNode.swap(parent);
+ }
+
+ for (PRInt32 i = containerStack.Count() - 1; i >= 0; --i) {
+ nsCOMPtr node = containerStack[i];
+ if (node) {
+ // Either we, or an element we contain, has gotten focus, so we need to
+ // set the repeat index. This is done through the the
+ // nsXFormsContextContainer belongs to.
+ //
+ // Start by finding the (our grandparent):
+ // <-- gParent
+ //
+ // <-- this
+ //
+ //
+ nsCOMPtr parent;
+ node->GetParentNode(getter_AddRefs(parent));
+ if (parent) {
+ nsCOMPtr grandParent;
+ parent->GetParentNode(getter_AddRefs(grandParent));
+ nsCOMPtr repeat =
+ do_QueryInterface(grandParent);
+ nsCOMPtr repeatItem =
+ do_QueryInterface(node);
+ if (repeat && repeatItem) {
+ PRInt32 position = 1;
+ repeatItem->GetContextPosition(&position);
+ // Tell about the new index position
+ PRUint32 tmp = position;
+ repeat->SetIndex(&tmp, PR_FALSE);
+ }
+ }
+ }
+ }
+
+ *aHandled = PR_TRUE;
+ return NS_OK;
}
NS_IMETHODIMP
@@ -200,19 +231,7 @@ nsXFormsContextContainer::SetContext(nsIDOMNode *aContextNode,
mContextPosition = aContextPosition;
mContextSize = aContextSize;
- // Remove from old model (if any)
- if (mModel) {
- mModel->RemoveFormControl(this);
- }
-
- // Add to new model
- mModel = nsXFormsUtils::GetModel(mElement);
- if (mModel) {
- mModel->AddFormControl(this);
- mModel->SetStates(this, mBoundNode);
- }
-
- return NS_OK;
+ return Bind();
}
NS_IMETHODIMP
@@ -238,6 +257,14 @@ nsXFormsContextContainer::GetContext(nsAString &aModelID,
NS_IMETHODIMP
nsXFormsContextContainer::Bind()
{
+
+ nsresult rv = BindToModel();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (mModel) {
+ mModel->SetStates(this, mBoundNode);
+ }
+
return NS_OK;
}
@@ -283,6 +310,13 @@ nsXFormsContextContainer::GetIndexState(PRBool *aHasIndex)
return NS_OK;
}
+NS_IMETHODIMP
+nsXFormsContextContainer::GetContextPosition(PRInt32 *aContextPosition)
+{
+ *aContextPosition = mContextPosition;
+ return NS_OK;
+}
+
// Factory
NS_HIDDEN_(nsresult)
NS_NewXFormsContextContainer(nsIXTFElement **aResult)
diff --git a/mozilla/extensions/xforms/nsXFormsControlStub.cpp b/mozilla/extensions/xforms/nsXFormsControlStub.cpp
index 7f4243d87f4..2faee0fe9e1 100644
--- a/mozilla/extensions/xforms/nsXFormsControlStub.cpp
+++ b/mozilla/extensions/xforms/nsXFormsControlStub.cpp
@@ -51,10 +51,10 @@
#include "nsXFormsModelElement.h"
#include "nsPIDOMWindow.h"
#include "nsIFocusController.h"
-#include "nsIScriptGlobalObject.h"
#include "nsIServiceManager.h"
#include "nsIEventStateManager.h"
#include "nsIContent.h"
+#include "nsIDOM3Node.h"
/** This class is used to generate xforms-hint and xforms-help events.*/
class nsXFormsHintHelpListener : public nsIDOMEventListener {
@@ -147,6 +147,7 @@ nsXFormsControlStubBase::ResetBoundNode(const nsString &aBindAttribute,
{
// Clear existing bound node, etc.
mBoundNode = nsnull;
+ mUsesModelBinding = PR_FALSE;
mDependencies.Clear();
RemoveIndexListeners();
@@ -167,8 +168,13 @@ nsXFormsControlStubBase::ResetBoundNode(const nsString &aBindAttribute,
if (!result)
return NS_OK;
- // Get context node, if any
- result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
+ // Get context node, if any
+ if (mUsesModelBinding) {
+ // When bound via @bind, we'll get a snapshot back
+ result->SnapshotItem(0, getter_AddRefs(mBoundNode));
+ } else {
+ result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
+ }
if (mBoundNode && mModel) {
mModel->SetStates(this, mBoundNode);
@@ -177,12 +183,10 @@ nsXFormsControlStubBase::ResetBoundNode(const nsString &aBindAttribute,
// doesn't exist in the instance document. Disable the control
// per 4.2.2 in the spec
- // Set pseudo class
- ///
- /// @bug Set via attributes right now. Bug 271720. (XXX)
- mElement->SetAttribute(NS_LITERAL_STRING("disabled"),
- NS_LITERAL_STRING("1"));
- mElement->RemoveAttribute(NS_LITERAL_STRING("enabled"));
+ nsCOMPtr xtfWrap(do_QueryInterface(mElement));
+ NS_ENSURE_STATE(xtfWrap);
+ xtfWrap->SetIntrinsicState(NS_EVENT_STATE_DISABLED);
+
// Dispatch event
nsXFormsUtils::DispatchEvent(mElement, eEvent_Disabled);
}
@@ -215,13 +219,42 @@ nsXFormsControlStubBase::IsEventTarget(PRBool *aOK)
*aOK = PR_TRUE;
return NS_OK;
}
-
+
+NS_IMETHODIMP
+nsXFormsControlStubBase::GetUsesModelBinding(PRBool *aRes)
+{
+ *aRes = mUsesModelBinding;
+ return NS_OK;
+}
+
+nsresult
+nsXFormsControlStubBase::MaybeAddToModel(nsIModelElementPrivate *aOldModel,
+ nsIXFormsControl *aParent)
+{
+ // XXX: just doing pointer comparison would be nice....
+ PRBool sameModel = PR_FALSE;
+ nsCOMPtr n3Model(do_QueryInterface(mModel));
+ nsCOMPtr nOldModel(do_QueryInterface(aOldModel));
+ NS_ASSERTION(n3Model, "model element not supporting nsIDOM3Node?!");
+ nsresult rv = n3Model->IsSameNode(nOldModel, &sameModel);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!sameModel) {
+ if (aOldModel) {
+ rv = aOldModel->RemoveFormControl(this);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ rv = mModel->AddFormControl(this, aParent);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ return NS_OK;
+}
+
nsresult
nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAttr,
- PRUint16 aResultType,
- nsIDOMXPathResult **aResult,
- nsIModelElementPrivate **aModel)
+ PRUint16 aResultType,
+ nsIDOMXPathResult **aResult,
+ nsIModelElementPrivate **aModel)
{
nsStringArray indexesUsed;
@@ -240,6 +273,9 @@ nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAtt
}
nsresult rv;
+ PRBool usesModelBinding;
+ nsCOMPtr oldModel(mModel);
+ nsCOMPtr parentControl;
rv = nsXFormsUtils::EvaluateNodeBinding(mElement,
kElementFlags,
aBindingAttr,
@@ -247,17 +283,22 @@ nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAtt
aResultType,
getter_AddRefs(mModel),
aResult,
+ &usesModelBinding,
+ getter_AddRefs(parentControl),
&mDependencies,
&indexesUsed);
NS_ENSURE_STATE(mModel);
-
- mModel->AddFormControl(this);
+
+ rv = MaybeAddToModel(oldModel, parentControl);
+ NS_ENSURE_SUCCESS(rv, rv);
+
if (aModel)
NS_ADDREF(*aModel = mModel);
+ mUsesModelBinding = usesModelBinding;
if (NS_SUCCEEDED(rv) && indexesUsed.Count()) {
// add index listeners on repeat elements
-
+
for (PRInt32 i = 0; i < indexesUsed.Count(); ++i) {
// Find the repeat element and add |this| as a listener
nsCOMPtr repElem;
@@ -278,6 +319,23 @@ nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAtt
return rv;
}
+nsresult
+nsXFormsControlStubBase::BindToModel(PRBool aSetBoundNode)
+{
+ nsCOMPtr oldModel(mModel);
+
+ nsCOMPtr parentControl;
+ nsCOMPtr boundNode;
+ mModel = nsXFormsUtils::GetModel(mElement, getter_AddRefs(parentControl),
+ kElementFlags,
+ getter_AddRefs(boundNode));
+ if (aSetBoundNode) {
+ mBoundNode.swap(boundNode);
+ }
+
+ return MaybeAddToModel(oldModel, parentControl);
+}
+
void
nsXFormsControlStubBase::ResetHelpAndHint(PRBool aInitialize)
{
@@ -397,15 +455,13 @@ nsXFormsControlStubBase::HandleDefault(nsIDOMEvent *aEvent,
// element isn't in a document, yet? Odd, indeed. Well, if not in
// document, these two events have no meaning.
NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
- nsCOMPtr win =
- do_QueryInterface(doc->GetScriptGlobalObject());
-
// An inelegant way to retrieve this to be sure, but we are
// guaranteed that the focus controller outlives us, so it
// is safe to hold on to it (since we can't die until it has
// died).
- nsIFocusController *focusController = win->GetRootFocusController();
+ nsIFocusController *focusController =
+ doc->GetWindow()->GetRootFocusController();
if (focusController &&
type.EqualsASCII(sXFormsEventsEntries[eEvent_Next].name)) {
focusController->MoveFocus(PR_TRUE, nsnull);
@@ -413,7 +469,8 @@ nsXFormsControlStubBase::HandleDefault(nsIDOMEvent *aEvent,
focusController->MoveFocus(PR_FALSE, nsnull);
}
} else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_BindingException].name)) {
- *aHandled = nsXFormsUtils::HandleBindingException(mElement);
+ *aHandled = nsXFormsUtils::HandleFatalError(mElement,
+ NS_LITERAL_STRING("XFormsBindingException"));
}
}
@@ -461,9 +518,6 @@ nsXFormsControlStubBase::Create(nsIXTFElementWrapper *aWrapper)
ResetHelpAndHint(PR_TRUE);
- // enabled is on pr. default
- aWrapper->SetIntrinsicState(NS_EVENT_STATE_ENABLED);
-
#ifdef DEBUG_smaug
sControlList->AppendElement(this);
#endif
@@ -476,6 +530,7 @@ nsXFormsControlStubBase::OnDestroyed()
{
ResetHelpAndHint(PR_FALSE);
RemoveIndexListeners();
+ mDependencies.Clear();
if (mModel) {
mModel->RemoveFormControl(this);
@@ -490,14 +545,32 @@ nsXFormsControlStubBase::OnDestroyed()
return NS_OK;
}
+nsresult
+nsXFormsControlStubBase::ForceModelRebind()
+{
+ if (mModel) {
+ // Remove from model, so Bind() will be forced to reattach
+ mModel->RemoveFormControl(this);
+ mModel = nsnull;
+ }
+ nsresult rv = Bind();
+ NS_ENSURE_SUCCESS(rv, rv);
+ return Refresh();
+}
+
+
nsresult
nsXFormsControlStubBase::DocumentChanged(nsIDOMDocument *aNewDocument)
{
// We need to re-evaluate our instance data binding when our document
// changes, since our context can change
+
if (aNewDocument) {
- Bind();
- Refresh();
+ // The intrinsic state needs to be initialized here since
+ // SetIntrinsicState will do nothing until the element lives in a document.
+ ResetProperties();
+
+ return ForceModelRebind();
}
return NS_OK;
@@ -509,39 +582,34 @@ nsXFormsControlStubBase::ParentChanged(nsIDOMElement *aNewParent)
mHasParent = aNewParent != nsnull;
// We need to re-evaluate our instance data binding when our parent changes,
// since xmlns declarations or our context could have changed.
- if (mHasParent) {
- Bind();
- Refresh();
- }
-
- return NS_OK;
+ return mHasParent ? ForceModelRebind() : NS_OK;
}
nsresult
nsXFormsControlStubBase::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
{
- MaybeRemoveFromModel(aName, aValue);
+ BeforeSetAttribute(aName, aValue);
return NS_OK;
}
nsresult
nsXFormsControlStubBase::AttributeSet(nsIAtom *aName, const nsAString &aValue)
{
- MaybeBindAndRefresh(aName);
+ AfterSetAttribute(aName);
return NS_OK;
}
nsresult
nsXFormsControlStubBase::WillRemoveAttribute(nsIAtom *aName)
{
- MaybeRemoveFromModel(aName, EmptyString());
+ BeforeSetAttribute(aName, EmptyString());
return NS_OK;
}
nsresult
nsXFormsControlStubBase::AttributeRemoved(nsIAtom *aName)
{
- MaybeBindAndRefresh(aName);
+ AfterSetAttribute(aName);
return NS_OK;
}
@@ -570,8 +638,7 @@ nsXFormsControlStubBase::GetContext(nsAString &aModelID,
if (aContextNode) {
if (mBoundNode) {
// We are bound to a node: This is the context node
- CallQueryInterface(mBoundNode, aContextNode); // addrefs
- NS_ASSERTION(*aContextNode, "could not QI context node from bound node?");
+ NS_ADDREF(*aContextNode = mBoundNode);
} else if (mModel) {
// We are bound to a model: The document element of its default instance
// document is the context node
@@ -630,13 +697,22 @@ nsXFormsControlStubBase::AddRemoveSNBAttr(nsIAtom *aName, const nsAString &aValu
}
}
-void
-nsXFormsControlStubBase::MaybeBindAndRefresh(nsIAtom *aName)
+PRBool
+nsXFormsControlStubBase::IsBindingAttribute(const nsIAtom *aAttr) const
{
- if (aName == nsXFormsAtoms::bind ||
- aName == nsXFormsAtoms::ref ||
- aName == nsXFormsAtoms::model) {
+ if (aAttr == nsXFormsAtoms::bind ||
+ aAttr == nsXFormsAtoms::ref ||
+ aAttr == nsXFormsAtoms::model) {
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
+void
+nsXFormsControlStubBase::AfterSetAttribute(nsIAtom *aName)
+{
+ if (IsBindingAttribute(aName)) {
Bind();
Refresh();
}
@@ -644,15 +720,10 @@ nsXFormsControlStubBase::MaybeBindAndRefresh(nsIAtom *aName)
}
void
-nsXFormsControlStubBase::MaybeRemoveFromModel(nsIAtom *aName,
- const nsAString &aValue)
+nsXFormsControlStubBase::BeforeSetAttribute(nsIAtom *aName,
+ const nsAString &aValue)
{
- if (aName == nsXFormsAtoms::model ||
- aName == nsXFormsAtoms::bind ||
- aName == nsXFormsAtoms::ref) {
- if (mModel)
- mModel->RemoveFormControl(this);
-
+ if (IsBindingAttribute(aName)) {
AddRemoveSNBAttr(aName, aValue);
}
}
diff --git a/mozilla/extensions/xforms/nsXFormsControlStub.h b/mozilla/extensions/xforms/nsXFormsControlStub.h
index 5cd440b1dce..f0fd11f70c6 100644
--- a/mozilla/extensions/xforms/nsXFormsControlStub.h
+++ b/mozilla/extensions/xforms/nsXFormsControlStub.h
@@ -89,6 +89,7 @@ public:
NS_IMETHOD Bind();
NS_IMETHOD TryFocus(PRBool* aOK);
NS_IMETHOD IsEventTarget(PRBool *aOK);
+ NS_IMETHOD GetUsesModelBinding(PRBool *aRes);
nsresult Create(nsIXTFElementWrapper *aWrapper);
// for nsIXTFElement
@@ -140,6 +141,7 @@ public:
kElementFlags(nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR),
mHasParent(PR_FALSE),
mPreventLoop(PR_FALSE),
+ mUsesModelBinding(PR_FALSE),
mBindAttrsCount(0)
{};
@@ -160,12 +162,17 @@ protected:
nsCOMPtr mEventListener;
/** State that tells whether control has a parent or not */
- PRBool mHasParent;
+ PRPackedBool mHasParent;
/** State to prevent infinite loop when generating and handling xforms-next
* and xforms-previous events
*/
- PRBool mPreventLoop;
+ PRPackedBool mPreventLoop;
+
+ /**
+ * Does the control use a model bind? That is, does it have a @bind.
+ */
+ PRPackedBool mUsesModelBinding;
/**
* Array of repeat-elements of which the control uses repeat-index.
@@ -203,12 +210,21 @@ protected:
*/
void ResetProperties();
+ /**
+ * Checks whether an attribute is a binding attribute for the control. This
+ * should be overriden by controls that have "non-standard" binding
+ * attributes.
+ *
+ * @param aAttr The attribute to check.
+ */
+ virtual PRBool IsBindingAttribute(const nsIAtom *aAttr) const;
+
/**
* Causes Bind() and Refresh() to be called if aName is the atom of a
* single node binding attribute for this control. Called by AttributeSet
* and AttributeRemoved.
*/
- void MaybeBindAndRefresh(nsIAtom *aName);
+ void AfterSetAttribute(nsIAtom *aName);
/**
* Removes this control from its model's list of controls if a single node
@@ -218,10 +234,35 @@ protected:
* @param aName - atom of the attribute being changed
* @param aValue - value that the attribute is being changed to.
*/
- void MaybeRemoveFromModel(nsIAtom *aName, const nsAString &aValue);
+ void BeforeSetAttribute(nsIAtom *aName, const nsAString &aValue);
/** Removes the index change event listeners */
void RemoveIndexListeners();
+
+ /**
+ * Binds the control to the model. Just sets mModel, and handle attaching to
+ * the model (including reattaching from any old model).
+ *
+ * @note It can also set the mBoundNode, but does not do a proper node
+ * binding, as in setting up dependencies, attaching index() listeners, etc.
+ *
+ * @param aSetBoundNode Set mBoundNode too?
+ */
+ nsresult BindToModel(PRBool aSetBoundNode = PR_FALSE);
+
+ /**
+ * Forces a rebinding to the model.
+ */
+ nsresult ForceModelRebind();
+
+ /**
+ * Adds the form control to the model, if the model has changed.
+ *
+ * @param aOldModel The previous model the control was bound to
+ * @param aParent The parent XForms control
+ */
+ nsresult MaybeAddToModel(nsIModelElementPrivate *aOldModel,
+ nsIXFormsControl *aParent);
};
diff --git a/mozilla/extensions/xforms/nsXFormsCopyElement.cpp b/mozilla/extensions/xforms/nsXFormsCopyElement.cpp
index 8429991c4db..f139932d075 100644
--- a/mozilla/extensions/xforms/nsXFormsCopyElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsCopyElement.cpp
@@ -157,24 +157,15 @@ nsXFormsCopyElement::GetCopyNode(nsIDOMNode **aNode)
NS_ENSURE_ARG_POINTER(aNode);
*aNode = nsnull;
+ nsCOMPtr singleNode;
nsCOMPtr model;
- nsCOMPtr result;
- nsresult rv =
- nsXFormsUtils::EvaluateNodeBinding(mElement,
- nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
- NS_LITERAL_STRING("ref"), EmptyString(),
- nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
- getter_AddRefs(model),
- getter_AddRefs(result));
+ PRBool succeeded =
+ nsXFormsUtils::GetSingleNodeBinding(mElement,
+ getter_AddRefs(singleNode),
+ getter_AddRefs(model));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (result) {
- nsCOMPtr singleNode;
- result->GetSingleNodeValue(getter_AddRefs(singleNode));
-
- NS_IF_ADDREF(*aNode = singleNode);
- }
+ if (succeeded && singleNode)
+ NS_ADDREF(*aNode = singleNode);
return NS_OK;
}
diff --git a/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp b/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp
index bee04c1eb5f..e1dd8925b97 100644
--- a/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp
+++ b/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp
@@ -102,19 +102,19 @@ NS_IMETHODIMP
nsXFormsDelegateStub::Refresh()
{
if (mRepeatState == eType_Template)
- return NS_OK;
+ return NS_OK_XFORMS_NOREFRESH;
const nsVoidArray* list = nsPostRefresh::PostRefreshList();
if (list && list->IndexOf(this) >= 0) {
// This control will be refreshed later.
- return NS_OK;
+ return NS_OK_XFORMS_NOREFRESH;
}
SetMozTypeAttribute();
nsCOMPtr widget = do_QueryInterface(mElement);
if (!widget)
- return NS_OK;
+ return NS_ERROR_FAILURE;
return widget->Refresh();
}
@@ -190,9 +190,20 @@ nsXFormsDelegateStub::ReportError(const nsAString& aErrorMsg)
NS_IMETHODIMP
nsXFormsDelegateStub::WidgetAttached()
{
- if (UpdateRepeatState() != eType_Template)
- nsXFormsModelElement::NeedsPostRefresh(this);
+ if (UpdateRepeatState() == eType_Template)
+ return NS_OK;
+ if (mBindAttrsCount) {
+ // If control is bounded to instance data then we should ask for refresh
+ // only when model is loaded entirely. The reason is control is refreshed
+ // by model when it get loaded.
+ nsCOMPtr domDoc;
+ mElement->GetOwnerDocument(getter_AddRefs(domDoc));
+ if (!nsXFormsUtils::IsDocumentReadyForBind(domDoc))
+ return NS_OK;
+ }
+
+ nsXFormsModelElement::NeedsPostRefresh(this);
return NS_OK;
}
@@ -213,6 +224,10 @@ nsXFormsDelegateStub::UpdateRepeatState()
mRepeatState = eType_Template;
break;
}
+ if (nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("itemset"))) {
+ mRepeatState = eType_Template;
+ break;
+ }
nsCOMPtr tmp;
parent->GetParentNode(getter_AddRefs(tmp));
parent = tmp;
diff --git a/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp b/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp
index 1315d32d2ce..badcc3e623c 100644
--- a/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp
@@ -41,6 +41,8 @@
#include "nsIDOMElement.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNodeList.h"
+#include "nsIXFormsRepeatElement.h"
+#include "nsIXFormsControl.h"
#include "nsString.h"
@@ -48,6 +50,7 @@
#include "nsXFormsActionModuleBase.h"
#include "nsXFormsActionElement.h"
#include "nsXFormsUtils.h"
+#include "nsIDOM3Node.h"
#include "math.h"
@@ -65,14 +68,14 @@
* @see http://www.w3.org/TR/xforms/slice4.html#evt-insert
* @see https://bugzilla.mozilla.org/show_bug.cgi?id=280423
*
- * @todo Any \ elements need to set their repeat-indexes properly if
- * they are bound to the same nodeset. (XXX)
*/
class nsXFormsInsertDeleteElement : public nsXFormsActionModuleBase
{
private:
PRBool mIsInsert;
-
+
+ nsresult RefreshRepeats(nsIDOMNode *aNode);
+
public:
NS_DECL_NSIXFORMSACTIONMODULEELEMENT
@@ -97,13 +100,15 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
nsresult rv;
nsCOMPtr model;
nsCOMPtr nodeset;
+ PRBool usesModelBinding;
rv = nsXFormsUtils::EvaluateNodeBinding(mElement,
- 0,
+ nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
NS_LITERAL_STRING("nodeset"),
EmptyString(),
nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
getter_AddRefs(model),
- getter_AddRefs(nodeset));
+ getter_AddRefs(nodeset),
+ &usesModelBinding);
NS_ENSURE_SUCCESS(rv, rv);
if (!model || !nodeset)
@@ -169,7 +174,7 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
#ifdef DEBUG_XF_INSERTDELETE
if (mIsInsert) {
printf("Will try to INSERT node _%s_ index %d (set size: %d)\n",
- NS_ConvertUCS2toUTF8(position).get(),
+ NS_ConvertUTF16toUTF8(position).get(),
atInt,
setSize);
} else {
@@ -198,7 +203,6 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
nsCOMPtr resNode;
if (mIsInsert) {
- //
// Get prototype and clone it (last member of nodeset)
nsCOMPtr prototype;
nodeset->SnapshotItem(setSize - 1, getter_AddRefs(prototype));
@@ -212,6 +216,11 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
location,
getter_AddRefs(resNode));
NS_ENSURE_STATE(resNode);
+
+ // Set indexes for repeats
+ rv = RefreshRepeats(resNode);
+ NS_ENSURE_SUCCESS(rv, rv);
+
} else {
rv = parent->RemoveChild(location, getter_AddRefs(resNode));
NS_ENSURE_SUCCESS(rv, rv);
@@ -219,9 +228,6 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
// Dispatch xforms-insert/delete event to the instance node we have modified
// data for
- nsCOMPtr modelElem = do_QueryInterface(model);
- NS_ENSURE_STATE(modelElem);
-
nsCOMPtr instNode;
rv = nsXFormsUtils::GetInstanceNodeForData(resNode, getter_AddRefs(instNode));
NS_ENSURE_SUCCESS(rv, rv);
@@ -231,6 +237,8 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
NS_ENSURE_SUCCESS(rv, rv);
// Dispatch refreshing events to the model
+ nsCOMPtr modelElem(do_QueryInterface(model));
+ NS_ASSERTION(modelElem, "Model not implementing nsIDOMElement?!");
if (aParentAction) {
aParentAction->SetRebuild(modelElem, PR_TRUE);
aParentAction->SetRecalculate(modelElem, PR_TRUE);
@@ -246,6 +254,46 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
return NS_OK;
}
+
+nsresult
+nsXFormsInsertDeleteElement::RefreshRepeats(nsIDOMNode *aNode)
+{
+ // XXXbeaufour: only check repeats belonging to the same model...
+ // possibly use mFormControls? Should be quicker than searching through
+ // entire document!! mModel->GetControls("repeat"); Would also possibly
+ // save a QI?
+
+ nsCOMPtr document;
+
+ nsresult rv = mElement->GetOwnerDocument(getter_AddRefs(document));
+ NS_ENSURE_STATE(document);
+
+ nsCOMPtr repeatNodes;
+ document->GetElementsByTagNameNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS),
+ NS_LITERAL_STRING("repeat"),
+ getter_AddRefs(repeatNodes));
+ NS_ENSURE_STATE(repeatNodes);
+
+ // work over each node and if the node contains the inserted element
+ PRUint32 nodeCount;
+ rv = repeatNodes->GetLength(&nodeCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ for (PRUint32 node = 0; node < nodeCount; ++node) {
+ nsCOMPtr repeatNode;
+
+ rv = repeatNodes->Item(node, getter_AddRefs(repeatNode));
+ nsCOMPtr repeatEl(do_QueryInterface(repeatNode));
+ NS_ENSURE_STATE(repeatEl);
+
+ rv = repeatEl->HandleNodeInsert(aNode);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+}
+
+
NS_HIDDEN_(nsresult)
NS_NewXFormsInsertElement(nsIXTFElement **aResult)
{
diff --git a/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp b/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp
index e3a01fed7b1..a9ace90b5dc 100644
--- a/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp
@@ -53,8 +53,9 @@
static const char* kLoadAsData = "loadAsData";
-NS_IMPL_ISUPPORTS_INHERITED5(nsXFormsInstanceElement,
+NS_IMPL_ISUPPORTS_INHERITED6(nsXFormsInstanceElement,
nsXFormsStubElement,
+ nsIXFormsNSInstanceElement,
nsIInstanceElementPrivate,
nsIStreamListener,
nsIRequestObserver,
@@ -78,7 +79,7 @@ nsXFormsInstanceElement::OnDestroyed()
mChannel = nsnull;
}
mListener = nsnull;
- SetDocument(nsnull);
+ SetInstanceDocument(nsnull);
mElement = nsnull;
return NS_OK;
}
@@ -139,7 +140,9 @@ NS_IMETHODIMP
nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
{
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
- nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED);
+ nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED |
+ nsIXTFElement::NOTIFY_WILL_CHANGE_PARENT |
+ nsIXTFElement::NOTIFY_PARENT_CHANGED);
nsCOMPtr node;
aWrapper->GetElementNode(getter_AddRefs(node));
@@ -184,7 +187,9 @@ nsXFormsInstanceElement::OnChannelRedirect(nsIChannel *OldChannel,
NS_ENSURE_STATE(doc);
if (!nsXFormsUtils::CheckSameOrigin(doc, newURI)) {
- nsXFormsUtils::ReportError(NS_LITERAL_STRING("instanceLoadOrigin"), domDoc);
+ const PRUnichar *strings[] = { NS_LITERAL_STRING("instance").get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLinkLoadOrigin"),
+ strings, 1, mElement, mElement);
return NS_ERROR_ABORT;
}
@@ -244,7 +249,7 @@ nsXFormsInstanceElement::OnStopRequest(nsIRequest *request, nsISupports *ctx,
PRBool succeeded = NS_SUCCEEDED(status);
if (!succeeded) {
- SetDocument(nsnull);
+ SetInstanceDocument(nsnull);
}
if (mDocument) {
@@ -259,7 +264,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;
- SetDocument(nsnull);
+ SetInstanceDocument(nsnull);
}
}
}
@@ -273,17 +278,19 @@ nsXFormsInstanceElement::OnStopRequest(nsIRequest *request, nsISupports *ctx,
return NS_OK;
}
-// nsIInstanceElementPrivate
+// nsIXFormsNSInstanceElement
NS_IMETHODIMP
-nsXFormsInstanceElement::GetDocument(nsIDOMDocument **aDocument)
+nsXFormsInstanceElement::GetInstanceDocument(nsIDOMDocument **aDocument)
{
NS_IF_ADDREF(*aDocument = mDocument);
return NS_OK;
}
+// nsIInstanceElementPrivate
+
NS_IMETHODIMP
-nsXFormsInstanceElement::SetDocument(nsIDOMDocument *aDocument)
+nsXFormsInstanceElement::SetInstanceDocument(nsIDOMDocument *aDocument)
{
nsCOMPtr doc(do_QueryInterface(mDocument));
if (doc) {
@@ -389,74 +396,81 @@ nsXFormsInstanceElement::GetElement(nsIDOMElement **aElement)
}
NS_IMETHODIMP
-nsXFormsInstanceElement::Initialize()
+nsXFormsInstanceElement::WillChangeParent(nsIDOMElement *aNewParent)
{
+ if (!aNewParent) {
+ nsCOMPtr model = GetModel();
+ if (model) {
+ model->RemoveInstanceElement(this);
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsInstanceElement::ParentChanged(nsIDOMElement *aNewParent)
+{
+ nsCOMPtr model = GetModel();
+ if (!model) return NS_OK;
+
if (mInitialized || !mElement) {
return NS_OK;
}
mInitialized = PR_TRUE;
-
- nsCOMPtr model = GetModel();
- NS_ENSURE_TRUE(model, NS_ERROR_FAILURE);
model->AddInstanceElement(this);
+ // If model isn't loaded entirely (It means xforms-ready event hasn't been
+ // fired) then the instance will be initialized by model and will be backed up
+ // when xforms-ready event is fired.
+ PRBool isready;
+ model->GetIsReady(&isready);
+ if (!isready)
+ return NS_OK;
+
+ // If the model is loaded and ready then the instance is inserted dynamically.
+ // The instance should create instance document and back it up.
+
+ // Probably dynamic instances should be handled too when model isn't loaded
+ // entirely (for more information see a comment 29 of bug 320081
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=320081#c29).
+
+ nsAutoString src;
+ mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
+
+ if (!src.IsEmpty()) {
+ // XXX: external dynamic instances isn't handled (see a bug 325684
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=325684)
+ return NS_OK;
+ }
+
+ // If we don't have a linked external instance, use our inline data.
+ nsresult rv = CloneInlineInstance();
+ if (NS_FAILED(rv))
+ return rv;
+ return BackupOriginalDocument();
+}
+
+NS_IMETHODIMP
+nsXFormsInstanceElement::Initialize()
+{
mElement->HasAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_MOZ_XFORMS_LAZY),
NS_LITERAL_STRING("lazy"), &mLazy);
- // Lazy instance
- if (mLazy) {
- nsCOMPtr domDoc;
- mElement->GetOwnerDocument(getter_AddRefs(domDoc));
- NS_ENSURE_STATE(domDoc);
-
- nsCOMPtr domImpl;
- nsresult rv = domDoc->GetImplementation(getter_AddRefs(domImpl));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr 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 instanceDataElement;
- nsCOMPtr 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!!");
- } else {
- // Normal instance
-
- // 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);
-
- if (src.IsEmpty()) {
- // If we don't have a linked external instance, use our inline data.
- CloneInlineInstance();
- } else {
- LoadExternalInstance(src);
- }
+ if (mLazy) { // Lazy instance
+ return CreateInstanceDocument(NS_LITERAL_STRING("instanceData"));
}
+ // Normal instance
+ nsAutoString src;
+ mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
+
+ if (src.IsEmpty()) {
+ return CloneInlineInstance();
+ }
+
+ LoadExternalInstance(src);
return NS_OK;
}
@@ -466,7 +480,7 @@ nsresult
nsXFormsInstanceElement::CloneInlineInstance()
{
// Clear out our existing instance data
- nsresult rv = CreateInstanceDocument();
+ nsresult rv = CreateInstanceDocument(EmptyString());
if (NS_FAILED(rv))
return rv; // don't warn, we might just not be in the document yet
@@ -519,9 +533,7 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc)
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr doc(do_QueryInterface(domDoc));
if (doc) {
- nsresult tmp;
- doc->GetProperty(nsXFormsAtoms::isInstanceDocument, &tmp);
- if (NS_SUCCEEDED(tmp)) {
+ if (doc->GetProperty(nsXFormsAtoms::isInstanceDocument)) {
/// Property exists, which means we are an instance document trying
/// to load an external instance document. We do not allow that.
const nsPromiseFlatString& flat = PromiseFlatString(aSrc);
@@ -530,7 +542,7 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc)
strings, 1, mElement, mElement);
} else {
// Clear out our existing instance data
- if (NS_SUCCEEDED(CreateInstanceDocument())) {
+ if (NS_SUCCEEDED(CreateInstanceDocument(EmptyString()))) {
nsCOMPtr newDoc = do_QueryInterface(mDocument);
nsCOMPtr uri;
@@ -559,8 +571,9 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc)
}
}
} else {
- nsXFormsUtils::ReportError(NS_LITERAL_STRING("instanceLoadOrigin"),
- domDoc);
+ const PRUnichar *strings[] = {NS_LITERAL_STRING("instance").get()};
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLinkLoadOrigin"),
+ strings, 1, mElement, mElement);
}
}
}
@@ -583,7 +596,7 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc)
}
nsresult
-nsXFormsInstanceElement::CreateInstanceDocument()
+nsXFormsInstanceElement::CreateInstanceDocument(const nsAString &aQualifiedName)
{
nsCOMPtr doc;
nsresult rv = mElement->GetOwnerDocument(getter_AddRefs(doc));
@@ -597,18 +610,18 @@ nsXFormsInstanceElement::CreateInstanceDocument()
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr newDoc;
- rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
+ rv = domImpl->CreateDocument(EmptyString(), aQualifiedName, nsnull,
getter_AddRefs(newDoc));
NS_ENSURE_SUCCESS(rv, rv);
- rv = SetDocument(newDoc);
+ rv = SetInstanceDocument(newDoc);
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,
+ domImpl->CreateDocument(EmptyString(), aQualifiedName, nsnull,
getter_AddRefs(mOriginalDocument));
return rv;
}
diff --git a/mozilla/extensions/xforms/nsXFormsInstanceElement.h b/mozilla/extensions/xforms/nsXFormsInstanceElement.h
index 81a2e364c38..a37f32ef2ef 100644
--- a/mozilla/extensions/xforms/nsXFormsInstanceElement.h
+++ b/mozilla/extensions/xforms/nsXFormsInstanceElement.h
@@ -66,6 +66,7 @@ class nsXFormsInstanceElement : public nsXFormsStubElement,
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSIXFORMSNSINSTANCEELEMENT
NS_DECL_NSIINSTANCEELEMENTPRIVATE
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSICHANNELEVENTSINK
@@ -75,6 +76,8 @@ public:
NS_IMETHOD OnDestroyed();
NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aNewValue);
NS_IMETHOD AttributeRemoved(nsIAtom *aName);
+ NS_IMETHOD WillChangeParent(nsIDOMElement *aNewParent);
+ NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent);
NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper);
nsXFormsInstanceElement() NS_HIDDEN;
@@ -82,7 +85,7 @@ public:
private:
NS_HIDDEN_(nsresult) CloneInlineInstance();
NS_HIDDEN_(void) LoadExternalInstance(const nsAString &aSrc);
- NS_HIDDEN_(nsresult) CreateInstanceDocument();
+ NS_HIDDEN_(nsresult) CreateInstanceDocument(const nsAString &aQualifiedName);
NS_HIDDEN_(already_AddRefed) GetModel();
nsCOMPtr mDocument;
diff --git a/mozilla/extensions/xforms/nsXFormsItemElement.cpp b/mozilla/extensions/xforms/nsXFormsItemElement.cpp
index 442864441cc..e93a0b0a47e 100644
--- a/mozilla/extensions/xforms/nsXFormsItemElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsItemElement.cpp
@@ -94,6 +94,7 @@ public:
// nsIXFormsSelectChild
NS_DECL_NSIXFORMSSELECTCHILD
+
private:
nsIDOMElement* mElement;
PRBool mDoneAddingChildren;
@@ -101,9 +102,6 @@ private:
// If true, indicates that this item contains a xf:copy element (via
// xf:itemset) rather than a xf:value element
PRBool mIsCopyItem;
-
- // context node (used by itemset in select)
- nsCOMPtr mContextNode;
};
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsItemElement,
diff --git a/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp b/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp
index a2ecfd487d7..a3d04307875 100644
--- a/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp
@@ -225,12 +225,7 @@ nsXFormsItemSetElement::SelectItemByNode(nsIDOMNode *aNode,
NS_IMETHODIMP
nsXFormsItemSetElement::Bind()
{
- mModel = nsXFormsUtils::GetModel(mElement);
- if (mModel) {
- mModel->AddFormControl(this);
- }
-
- return NS_OK;
+ return BindToModel();
}
NS_IMETHODIMP
@@ -337,11 +332,11 @@ nsXFormsItemSetElement::Refresh()
anonContent->AppendChild(itemNode, getter_AddRefs(tmpNode));
}
- // tell parent we appended a child
+ // refresh parent we
if (parent) {
- nsCOMPtr stub = do_QueryInterface(parent);
- if (stub) {
- stub->ChildAppended(parent);
+ nsCOMPtr control = do_QueryInterface(parent);
+ if (control) {
+ control->Refresh();
}
}
diff --git a/mozilla/extensions/xforms/nsXFormsLabelElement.cpp b/mozilla/extensions/xforms/nsXFormsLabelElement.cpp
index ed5760729c8..281e780a6a7 100644
--- a/mozilla/extensions/xforms/nsXFormsLabelElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsLabelElement.cpp
@@ -233,12 +233,11 @@ nsXFormsLabelElement::LoadExternalLabel(const nsAString& aSrc)
// URI doesn't exist; report error.
mChannel = nsnull;
- // XXX Passing |mElement| as |aContext| param to ReportError leads
- // to an infinite loop. Avoid for now.
const nsPromiseFlatString& flat = PromiseFlatString(aSrc);
- const PRUnichar *strings[] = { flat.get() };
- nsXFormsUtils::ReportError(NS_LITERAL_STRING("labelLink1Error"),
- strings, 1, mElement, nsnull);
+ const PRUnichar *strings[] = { flat.get(),
+ NS_LITERAL_STRING("label").get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink1Error"),
+ strings, 2, mElement, mElement);
nsCOMPtr modelPriv =
nsXFormsUtils::GetModel(mElement);
@@ -247,8 +246,9 @@ nsXFormsLabelElement::LoadExternalLabel(const nsAString& aSrc)
}
}
} else {
- nsXFormsUtils::ReportError(NS_LITERAL_STRING("labelLinkLoadOrigin"),
- domDoc);
+ const PRUnichar *strings[] = { NS_LITERAL_STRING("label").get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLinkLoadOrigin"),
+ strings, 1, mElement, mElement);
}
}
}
@@ -259,7 +259,10 @@ nsXFormsLabelElement::LoadExternalLabel(const nsAString& aSrc)
NS_IMETHODIMP
nsXFormsLabelElement::Refresh()
{
- nsXFormsDelegateStub::Refresh();
+ nsresult rv = nsXFormsDelegateStub::Refresh();
+ if (NS_FAILED(rv) || rv == NS_OK_XFORMS_NOREFRESH)
+ return rv;
+
nsCOMPtr parent;
mElement->GetParentNode(getter_AddRefs(parent));
@@ -375,13 +378,12 @@ nsXFormsLabelElement::OnStopRequest(nsIRequest *aRequest,
if (aStatusCode == NS_BINDING_ABORTED)
return NS_OK;
- // XXX Passing |mElement| as |aContext| param to ReportError leads
- // to an infinite loop. Avoid for now.
nsAutoString src;
mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
- const PRUnichar *strings[] = { src.get() };
- nsXFormsUtils::ReportError(NS_LITERAL_STRING("labelLink2Error"),
- strings, 1, mElement, nsnull);
+ const PRUnichar *strings[] = { NS_LITERAL_STRING("label").get(),
+ src.get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink2Error"),
+ strings, 2, mElement, mElement);
nsCOMPtr modelPriv =
nsXFormsUtils::GetModel(mElement);
diff --git a/mozilla/extensions/xforms/nsXFormsMDGEngine.cpp b/mozilla/extensions/xforms/nsXFormsMDGEngine.cpp
index 66209a358ef..d17faf82504 100644
--- a/mozilla/extensions/xforms/nsXFormsMDGEngine.cpp
+++ b/mozilla/extensions/xforms/nsXFormsMDGEngine.cpp
@@ -45,9 +45,10 @@
#include "nsIDOMNSXPathExpression.h"
#include "nsIDOMXPathResult.h"
#include "nsDeque.h"
-#include "nsIModelElementPrivate.h"
#include "nsXFormsUtils.h"
#include "nsDOMError.h"
+#include "nsIDOMElement.h"
+#include "nsXFormsModelElement.h"
#ifdef DEBUG
//# define DEBUG_XF_MDG
@@ -64,7 +65,6 @@
/* ------------------------------------ */
/* --------- nsXFormsMDGNode ---------- */
/* ------------------------------------ */
-MOZ_DECL_CTOR_COUNTER(nsXFormsMDGNode)
nsXFormsMDGNode::nsXFormsMDGNode(nsIDOMNode *aNode,
const ModelItemPropName aType)
@@ -122,7 +122,6 @@ nsXFormsMDGNode::MarkClean()
/* ------------------------------------ */
/* -------- nsXFormsMDGEngine --------- */
/* ------------------------------------ */
-MOZ_DECL_CTOR_COUNTER(nsXFormsMDGEngine)
nsXFormsMDGEngine::nsXFormsMDGEngine()
: mNodesInGraph(0)
@@ -138,7 +137,7 @@ nsXFormsMDGEngine::~nsXFormsMDGEngine()
}
nsresult
-nsXFormsMDGEngine::Init(nsIModelElementPrivate *aModel)
+nsXFormsMDGEngine::Init(nsXFormsModelElement *aModel)
{
nsresult rv = NS_ERROR_FAILURE;
if (mNodeStates.Init() && mNodeToMDG.Init()) {
@@ -165,7 +164,7 @@ nsXFormsMDGEngine::AddMIP(ModelItemPropName aType,
nsAutoString nodename;
aContextNode->GetNodeName(nodename);
printf("nsXFormsMDGEngine::AddMIP(aContextNode=%s, aExpression=%p, aDependencies=|%d|,\n",
- NS_ConvertUCS2toUTF8(nodename).get(),
+ NS_ConvertUTF16toUTF8(nodename).get(),
(void*) aExpression,
aDependencies ? aDependencies->Count() : 0);
printf(" aContextPos=%d, aContextSize=%d, aType=%s, aDynFunc=%d)\n",
@@ -275,7 +274,7 @@ nsXFormsMDGEngine::PrintDot(const char* aFile)
if (g->IsDirty()) {
fprintf(FD, "\t%s [color=red];\n",
- NS_ConvertUCS2toUTF8(domNodeName).get());
+ NS_ConvertUTF16toUTF8(domNodeName).get());
}
for (PRInt32 j = 0; j < g->mSuc.Count(); ++j) {
@@ -285,8 +284,8 @@ nsXFormsMDGEngine::PrintDot(const char* aFile)
nsAutoString sucName;
sucnode->mContextNode->GetNodeName(sucName);
fprintf(FD, "\t%s -> %s [label=\"%s\"];\n",
- NS_ConvertUCS2toUTF8(sucName).get(),
- NS_ConvertUCS2toUTF8(domNodeName).get(),
+ NS_ConvertUTF16toUTF8(sucName).get(),
+ NS_ConvertUTF16toUTF8(domNodeName).get(),
gMIPNames[sucnode->mType]);
}
}
@@ -345,7 +344,7 @@ nsXFormsMDGEngine::Recalculate(nsCOMArray *aChangedNodes)
printf("\tNode #%d: This=%p, Dirty=%d, DynFunc=%d, Type=%d, Count=%d, Suc=%d, CSize=%d, CPos=%d, Next=%p, domnode=%s\n",
i, (void*) g, g->IsDirty(), g->mDynFunc, g->mType,
g->mCount, g->mSuc.Count(), g->mContextSize, g->mContextPosition,
- (void*) g->mNext, NS_ConvertUCS2toUTF8(domNodeName).get());
+ (void*) g->mNext, NS_ConvertUTF16toUTF8(domNodeName).get());
#endif
// Ignore node if it is not dirty
@@ -557,7 +556,11 @@ nsXFormsMDGEngine::Rebuild()
#endif
if (mGraph.Count() != mNodesInGraph) {
- NS_WARNING("XForms: There are loops in the MDG\n");
+ nsCOMPtr modelElement;
+ if (mModel) {
+ modelElement = mModel->GetDOMElement();
+ }
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("MDGLoopError"), modelElement);
rv = NS_ERROR_ABORT;
}
diff --git a/mozilla/extensions/xforms/nsXFormsMDGEngine.h b/mozilla/extensions/xforms/nsXFormsMDGEngine.h
index c16821b4065..64785ce030f 100644
--- a/mozilla/extensions/xforms/nsXFormsMDGEngine.h
+++ b/mozilla/extensions/xforms/nsXFormsMDGEngine.h
@@ -50,9 +50,9 @@
#include "nsXFormsTypes.h"
#include "nsXFormsNodeState.h"
-#include "nsIModelElementPrivate.h"
class nsIDOMNSXPathExpression;
+class nsXFormsModelElement;
/**
* Data structure for nodes in the graph.
@@ -174,7 +174,7 @@ protected:
nsVoidArray mGraph;
/** The model that created the MDG */
- nsIModelElementPrivate *mModel;
+ nsXFormsModelElement *mModel;
/**
* Nodes that are marked as changed, and should be included in recalculation
@@ -343,7 +343,7 @@ public:
*
* @param aModel The model that created this MDGEngine instance.
*/
- nsresult Init(nsIModelElementPrivate *aModel);
+ nsresult Init(nsXFormsModelElement *aModel);
/**
* Insert new MIP (Model Item Property) into graph.
diff --git a/mozilla/extensions/xforms/nsXFormsMessageElement.cpp b/mozilla/extensions/xforms/nsXFormsMessageElement.cpp
index c4482aaa535..d8215b9ce97 100644
--- a/mozilla/extensions/xforms/nsXFormsMessageElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsMessageElement.cpp
@@ -78,6 +78,9 @@
#include "nsIDOMSerializer.h"
#include "nsIServiceManager.h"
#include "nsIDelegateInternal.h"
+#include "nsNetUtil.h"
+#include "nsIDOMDocumentEvent.h"
+#include "nsIChannelEventSink.h"
#define EPHEMERAL_STYLE \
"position:absolute;z-index:2147483647; \
@@ -98,8 +101,15 @@
\
"
+
+#define MESSAGE_WINDOW_UI_PART1_WITHOUT_SRC \
+ "onload='window.sizeToContent(); \
+ document.documentElement.lastChild.previousSibling \
.firstChild.nextSibling.focus();'>"
#define MESSAGE_WINDOW_UI_PART2 \
@@ -121,7 +131,10 @@ class nsXFormsEventListener;
*/
class nsXFormsMessageElement : public nsXFormsXMLVisualStub,
public nsIDOMEventListener,
- public nsIXFormsActionModuleElement
+ public nsIXFormsActionModuleElement,
+ public nsIStreamListener,
+ public nsIInterfaceRequestor,
+ public nsIChannelEventSink
{
public:
NS_DECL_ISUPPORTS_INHERITED
@@ -138,7 +151,13 @@ public:
NS_IMETHOD GetInsertionPoint(nsIDOMElement **aElement);
NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent);
NS_IMETHOD WillChangeParent(nsIDOMElement *aNewParent);
+ NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aSrc);
+ NS_IMETHOD AttributeRemoved(nsIAtom *aName);
+ NS_DECL_NSICHANNELEVENTSINK
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIDOMEVENTLISTENER
NS_DECL_NSIXFORMSACTIONMODULEELEMENT
@@ -161,18 +180,41 @@ public:
eType_Alert
};
+ enum StopType {
+ eStopType_None,
+ eStopType_Security,
+ eStopType_LinkError
+ };
+
+
nsXFormsMessageElement(MessageType aType) :
- mType(aType), mElement(nsnull), mPosX(-1), mPosY(-1) {}
+ mType(aType), mElement(nsnull), mPosX(-1), mPosY(-1),
+ mStopType(eStopType_None) {}
private:
nsresult HandleEphemeralMessage(nsIDOMDocument* aDoc, nsIDOMEvent* aEvent);
nsresult HandleModalAndModelessMessage(nsIDOMDocument* aDoc, nsAString& aLevel);
void CloneNode(nsIDOMNode* aSrc, nsIDOMNode** aTarget);
- void AppendCSSOptions(nsIDOMViewCSS* aViewCSS, nsAString& aOptions);
PRBool HandleInlineAlert(nsIDOMEvent* aEvent);
nsresult ConstructMessageWindowURL(nsAString& aData,
PRBool aIsLink,
/*out*/ nsAString& aURL);
+ /**
+ * Begin the process of testing to see if this message element could get held
+ * up later by linking to an external resource. Run this when the element is
+ * set up and it will try to access any external resource that this message
+ * may later try to access. If we can't get to it by the time the message
+ * is triggered, then throw a xforms-link-error.
+ */
+ nsresult TestExternalFile();
+
+ /**
+ * Either add or subtract from the number of messages with external resources
+ * currently loading in this document. aAdd == PR_TRUE will add to the total
+ * otherwise we will subtract from the total (as long as it isn't already 0).
+ */
+ void AddRemoveExternalResource(PRBool aAdd);
+
MessageType mType;
nsCOMPtr mVisualElement;
@@ -184,12 +226,17 @@ private:
nsCOMPtr mEphemeralTimer;
nsCOMPtr mDocument;
+ nsCOMPtr mChannel;
+ StopType mStopType;
};
NS_IMPL_ADDREF_INHERITED(nsXFormsMessageElement, nsXFormsXMLVisualStub)
NS_IMPL_RELEASE_INHERITED(nsXFormsMessageElement, nsXFormsXMLVisualStub)
NS_INTERFACE_MAP_BEGIN(nsXFormsMessageElement)
+ NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
+ NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
+ NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIXFormsActionModuleElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_END_INHERITING(nsXFormsXMLVisualStub)
@@ -203,7 +250,9 @@ nsXFormsMessageElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper)
NS_ENSURE_SUCCESS(rv, rv);
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT |
- nsIXTFElement::NOTIFY_PARENT_CHANGED);
+ nsIXTFElement::NOTIFY_PARENT_CHANGED |
+ nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
+ nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED);
nsCOMPtr node;
rv = aWrapper->GetElementNode(getter_AddRefs(node));
@@ -261,6 +310,12 @@ nsXFormsMessageElement::WillChangeDocument(nsIDOMDocument *aNewDocument)
if (msg == this)
doc->UnsetProperty(nsXFormsAtoms::messageProperty);
}
+
+ // If we are currently trying to load an external message, cancel the
+ // request.
+ if (mChannel) {
+ mChannel->Cancel(NS_BINDING_ABORTED);
+ }
}
mDocument = aNewDocument;
@@ -272,6 +327,7 @@ nsXFormsMessageElement::OnDestroyed()
{
mElement = nsnull;
mVisualElement = nsnull;
+ mChannel = nsnull;
return NS_OK;
}
@@ -391,6 +447,39 @@ nsXFormsMessageElement::ParentChanged(nsIDOMElement *aNewParent)
return NS_OK;
}
+NS_IMETHODIMP
+nsXFormsMessageElement::AttributeSet(nsIAtom *aName, const nsAString &aValue)
+{
+ if (aName == nsXFormsAtoms::src) {
+ // If we are currently trying to load an external message, cancel the
+ // request.
+ if (mChannel) {
+ mChannel->Cancel(NS_BINDING_ABORTED);
+ }
+
+ mStopType = eStopType_None;
+ TestExternalFile();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsMessageElement::AttributeRemoved(nsIAtom *aName)
+{
+ if (aName == nsXFormsAtoms::src) {
+ // If we are currently trying to test an external resource, cancel the
+ // request.
+ if (mChannel) {
+ mChannel->Cancel(NS_BINDING_ABORTED);
+ }
+
+ mStopType = eStopType_None;
+ }
+
+ return NS_OK;
+}
+
NS_IMETHODIMP
nsXFormsMessageElement::HandleAction(nsIDOMEvent* aEvent,
nsIXFormsActionElement *aParentAction)
@@ -398,6 +487,35 @@ nsXFormsMessageElement::HandleAction(nsIDOMEvent* aEvent,
if (!mElement)
return NS_OK;
+ // If TestExternalFile fails, then there is an external link that we need
+ // to use that we can't reach right now. If it won't load, then might as
+ // well stop here. We don't want to be popping up empty windows
+ // or windows that will just end up showing 404 messages.
+ if (mStopType == eStopType_LinkError) {
+ // we couldn't successfully link to our external resource. Better throw
+ // the xforms-link-error event
+ nsCOMPtr modelPriv =
+ nsXFormsUtils::GetModel(mElement);
+ nsCOMPtr model = do_QueryInterface(modelPriv);
+ nsXFormsUtils::DispatchEvent(model, eEvent_LinkError);
+ return NS_OK;
+ }
+
+ // If we couldn't test the external link due to it not living in an
+ // acceptable domain, then no sense going any further down this path.
+ if (mStopType == eStopType_Security) {
+ return NS_OK;
+ }
+
+ // If there is still a channel, then someone must have changed the value of
+ // the src attribute since the document finished loading and we haven't yet
+ // determined whether the new link is valid or not. For now we'll assume
+ // that the value is good rather than returning a link error. Also
+ // canceling the channel since it is too late now.
+ if (mChannel) {
+ mChannel->Cancel(NS_BINDING_ABORTED);
+ }
+
if (mType != eType_Normal) {
nsCOMPtr target;
@@ -604,16 +722,13 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc,
instanceData);
nsAutoString options;
- options.AppendLiteral(MESSAGE_WINDOW_PROPERTIES);
+ options.AssignLiteral(MESSAGE_WINDOW_PROPERTIES);
nsAutoString src;
if (!hasBinding) {
mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
}
- nsCOMPtr cssView(do_QueryInterface(internal));
- AppendCSSOptions(cssView, options);
-
// order of precedence is single-node binding, linking attribute then
// inline text
nsresult rv;
@@ -625,7 +740,7 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc,
} else {
// Cloning the content of the xf:message and creating a
// dialog for it.
- options.AppendLiteral(",dialog,chrome,dependent");
+ options.AppendLiteral(",dialog,chrome,dependent,width=200,height=200");
nsCOMPtr ddoc;
nsCOMPtr domImpl;
rv = aDoc->GetImplementation(getter_AddRefs(domImpl));
@@ -644,14 +759,14 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc,
getter_AddRefs(htmlEl));
NS_ENSURE_SUCCESS(rv, rv);
ddoc->AppendChild(htmlEl, getter_AddRefs(tmp));
-
+
nsCOMPtr bodyEl;
rv = ddoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
NS_LITERAL_STRING("body"),
getter_AddRefs(bodyEl));
NS_ENSURE_SUCCESS(rv, rv);
htmlEl->AppendChild(bodyEl, getter_AddRefs(tmp));
-
+
// If we have a binding, it is enough to show a simple message
if (hasBinding) {
nsCOMPtr body3(do_QueryInterface(bodyEl));
@@ -680,7 +795,7 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc,
}
}
}
-
+
nsCOMPtr serializer =
do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
@@ -688,11 +803,11 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc,
nsAutoString docString;
rv = serializer->SerializeToString(ddoc, docString);
NS_ENSURE_SUCCESS(rv, rv);
-
+
rv = ConstructMessageWindowURL(docString, PR_FALSE, src);
NS_ENSURE_SUCCESS(rv, rv);
}
-
+
nsCOMPtr arg;
PRBool isModal = aLevel.EqualsLiteral("modal");
if (isModal) {
@@ -702,71 +817,15 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc,
// cycles between the windows.
arg = nsXFormsAtoms::messageProperty;
}
-
- //XXX Add support for xforms-link-error.
+
nsCOMPtr messageWindow;
- internal->OpenDialog(src, aLevel, options, arg, getter_AddRefs(messageWindow));
- if (!isModal) {
- nsCOMPtr msgWinInternal =
- do_QueryInterface(messageWindow);
- if (msgWinInternal)
- msgWinInternal->Focus();
- }
+ // The 2nd argument is the window name, and if a window with the name exists,
+ // it gets reused. Using "_blank" makes sure we get a new window each time.
+ internal->OpenDialog(src, NS_LITERAL_STRING("_blank"), options, arg,
+ getter_AddRefs(messageWindow));
return NS_OK;
}
-void
-nsXFormsMessageElement::AppendCSSOptions(nsIDOMViewCSS* aViewCSS, nsAString& aOptions)
-{
- if (!aViewCSS)
- return;
- // Try to get the calculated size of the message element. It will
- // be used for the new window.
- //XXX This could be extended also for 'top', 'left' etc. properties.
- PRInt32 computedWidth = 0;
- PRInt32 computedHeight = 0;
-
- nsAutoString tmp;
- nsCOMPtr styles;
- aViewCSS->GetComputedStyle(mElement, tmp, getter_AddRefs(styles));
- if (styles) {
- nsCOMPtr cssWidth;
- styles->GetPropertyCSSValue(NS_LITERAL_STRING("width"),
- getter_AddRefs(cssWidth));
- nsCOMPtr pvalueWidth(do_QueryInterface(cssWidth));
- float width = 0;
- if (pvalueWidth) {
- PRUint16 type;
- pvalueWidth->GetPrimitiveType(&type);
- if (type == nsIDOMCSSPrimitiveValue::CSS_PX)
- pvalueWidth->GetFloatValue(type, &width);
- }
-
- nsCOMPtr cssHeight;
- styles->GetPropertyCSSValue(NS_LITERAL_STRING("height"),
- getter_AddRefs(cssHeight));
- nsCOMPtr pvalueHeight(do_QueryInterface(cssHeight));
- float height = 0;
- if (pvalueHeight) {
- PRUint16 type;
- pvalueHeight->GetPrimitiveType(&type);
- if (type == nsIDOMCSSPrimitiveValue::CSS_PX)
- pvalueHeight->GetFloatValue(type, &height);
- }
- computedWidth = NS_STATIC_CAST(PRInt32, width);
- computedHeight = NS_STATIC_CAST(PRInt32, height);
- }
-
- if (computedWidth > 0 && computedHeight > 0) {
- nsAutoString options;
- options.AppendLiteral(",innerWidth=");
- options.AppendInt(computedWidth);
- options.AppendLiteral(",innerHeight=");
- options.AppendInt(computedHeight);
- aOptions.Append(options);
- }
-}
-
nsresult
nsXFormsMessageElement::ConstructMessageWindowURL(nsAString& aData,
PRBool aIsLink,
@@ -789,8 +848,12 @@ nsXFormsMessageElement::ConstructMessageWindowURL(nsAString& aData,
nsAutoString xul;
xul.AssignLiteral(MESSAGE_WINDOW_UI_PART1);
- if (aIsLink)
+ if (aIsLink) {
+ xul.AppendLiteral(MESSAGE_WINDOW_UI_PART1_WITH_SRC);
xul.AppendLiteral("GetAttribute(NS_LITERAL_STRING("bind"), snb);
+ if (!snb.IsEmpty()) {
+ return NS_OK;
+ }
+ mElement->GetAttribute(NS_LITERAL_STRING("ref"), snb);
+ if (!snb.IsEmpty()) {
+ return NS_OK;
+ }
+
+ // if no linking attribute, no need to go on
+ nsAutoString src;
+ mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
+ if (src.IsEmpty()) {
+ return NS_OK;
+ }
+
+ nsCOMPtr domDoc;
+ mElement->GetOwnerDocument(getter_AddRefs(domDoc));
+ nsCOMPtr doc(do_QueryInterface(domDoc));
+ NS_ENSURE_STATE(doc);
+ nsCOMPtr uri;
+ NS_NewURI(getter_AddRefs(uri), src, doc->GetDocumentCharacterSet().get(),
+ doc->GetDocumentURI());
+ NS_ENSURE_STATE(uri);
+
+ if (!nsXFormsUtils::CheckSameOrigin(doc, uri)) {
+ nsAutoString tagName;
+ mElement->GetLocalName(tagName);
+ const PRUnichar *strings[] = { tagName.get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLinkLoadOrigin"),
+ strings, 1, mElement, mElement);
+ // Keep the the dialog from popping up. Won't be able to reach the
+ // resource anyhow.
+ mStopType = eStopType_Security;
+ return NS_ERROR_FAILURE;
+ }
+
+ nsCOMPtr loadGroup = doc->GetDocumentLoadGroup();
+ NS_WARN_IF_FALSE(loadGroup, "No load group!");
+
+ // 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 message data document has been loaded.
+ nsresult rv = NS_NewChannel(getter_AddRefs(mChannel), uri, nsnull, loadGroup,
+ this, nsIRequest::LOAD_NORMAL);
+ NS_ENSURE_TRUE(mChannel, rv);
+
+ // See if it's an http channel. We'll look at the http status code more
+ // closely and only request the "HEAD" to keep the response small.
+ // Especially since we are requesting this for every message in the document
+ // and in most cases we pass off the URL to another browser service to
+ // get and display the message so no good to try to look at the contents
+ // anyway.
+
+ // XXX ephemeral messages should probably get their full contents here once
+ // they are set up to handle external resources.
+ nsCOMPtr httpChannel = do_QueryInterface(mChannel);
+ if (httpChannel) {
+ PRBool isReallyHTTP = PR_FALSE;
+ uri->SchemeIs("http", &isReallyHTTP);
+ if (!isReallyHTTP) {
+ uri->SchemeIs("https", &isReallyHTTP);
+ }
+ if (isReallyHTTP) {
+ httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("HEAD"));
+ }
+ }
+
+ rv = mChannel->AsyncOpen(this, nsnull);
+ if (NS_FAILED(rv)) {
+ mChannel = nsnull;
+
+ // URI doesn't exist; report error.
+ // set up the error strings
+ nsAutoString tagName;
+ mElement->GetLocalName(tagName);
+ const PRUnichar *strings[] = { src.get(), tagName.get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink1Error"),
+ strings, 2, mElement, mElement);
+ mStopType = eStopType_LinkError;
+ return NS_ERROR_FAILURE;
+ }
+
+ // channel should be running along smoothly, increment the count
+ AddRemoveExternalResource(PR_TRUE);
+ return NS_OK;
+}
+
+// nsIInterfaceRequestor
+
+NS_IMETHODIMP
+nsXFormsMessageElement::GetInterface(const nsIID &aIID, void **aResult)
+{
+ *aResult = nsnull;
+ return QueryInterface(aIID, aResult);
+}
+
+// nsIChannelEventSink
+
+NS_IMETHODIMP
+nsXFormsMessageElement::OnChannelRedirect(nsIChannel *OldChannel,
+ nsIChannel *aNewChannel,
+ PRUint32 aFlags)
+{
+ NS_PRECONDITION(aNewChannel, "Redirect without a channel?");
+
+ nsCOMPtr newURI;
+ nsresult rv = aNewChannel->GetURI(getter_AddRefs(newURI));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_ENSURE_STATE(mElement);
+ nsCOMPtr domDoc;
+ mElement->GetOwnerDocument(getter_AddRefs(domDoc));
+ nsCOMPtr doc(do_QueryInterface(domDoc));
+ NS_ENSURE_STATE(doc);
+
+ if (!nsXFormsUtils::CheckSameOrigin(doc, newURI)) {
+ nsAutoString tagName;
+ mElement->GetLocalName(tagName);
+ const PRUnichar *strings[] = { tagName.get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLinkLoadOrigin"),
+ strings, 1, mElement, mElement);
+ return NS_ERROR_ABORT;
+ }
+
+ return NS_OK;
+}
+
+// nsIStreamListener
+
+NS_IMETHODIMP
+nsXFormsMessageElement::OnStartRequest(nsIRequest *aRequest,
+ nsISupports *aContext)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsMessageElement::OnDataAvailable(nsIRequest *aRequest,
+ nsISupports *aContext,
+ nsIInputStream *aInputStream,
+ PRUint32 aOffset,
+ PRUint32 aCount)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsMessageElement::OnStopRequest(nsIRequest *aRequest,
+ nsISupports *aContext,
+ nsresult aStatusCode)
+{
+
+ // We are done with the load request, whatever the result, so make sure to
+ // null out mChannel before we return. Keep in mind that if this is the last
+ // message channel to be loaded for the xforms document then when
+ // AddRemoveExternalResource is called, it may result in xforms-ready firing.
+ // Should there be a message acting as a handler for xforms-ready, it will
+ // start the logic to display itself (HandleAction()). So we can't call
+ // AddRemoveExternalResource to remove this channel from the count until we've
+ // set the mStopType to be the proper value. Entering this function,
+ // mStopType will be eStopType_None, so if we need mStopType to be any other
+ // value (like in an error condition), please make sure it is set before
+ // AddRemoveExternalResource is called.
+
+ if (NS_FAILED(aStatusCode)) {
+ // NS_BINDING_ABORTED means that we have been cancelled by a later
+ // AttributeSet() call (which will also reset mStopType). So don't treat
+ // like an error.
+ if (aStatusCode != NS_BINDING_ABORTED) {
+ nsAutoString src, tagName;
+ mElement->GetLocalName(tagName);
+ mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
+ const PRUnichar *strings[] = { tagName.get(), src.get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink2Error"),
+ strings, 2, mElement, mElement);
+ mStopType = eStopType_LinkError;
+ AddRemoveExternalResource(PR_FALSE);
+ mChannel = nsnull;
+
+ return NS_OK;
+ }
+ }
+
+ PRUint32 responseStatus;
+ nsCOMPtr httpChannel = do_QueryInterface(mChannel);
+ if (NS_SUCCEEDED(aStatusCode) && httpChannel) {
+ nsresult rv = httpChannel->GetResponseStatus(&responseStatus);
+
+ // If responseStatus is 4xx or 5xx, it is an error. 2xx is success.
+ // 3xx (various flavors of redirection) COULD be successful. Can't really
+ // follow those to conclusion so we'll assume they were successful.
+ if (NS_FAILED(rv) || (responseStatus >= 400)) {
+ nsAutoString src, tagName;
+ mElement->GetLocalName(tagName);
+ mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
+ const PRUnichar *strings[] = { tagName.get(), src.get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink2Error"),
+ strings, 2, mElement, mElement);
+ mStopType = eStopType_LinkError;
+ }
+ }
+
+ AddRemoveExternalResource(PR_FALSE);
+ mChannel = nsnull;
+
+ return NS_OK;
+}
+
+void
+nsXFormsMessageElement::AddRemoveExternalResource(PRBool aAdd)
+{
+ // if this message doesn't have a channel established already or it has
+ // already returned, then no sense bumping the counter.
+ if (!mChannel) {
+ return;
+ }
+
+ nsCOMPtr domDoc;
+ mElement->GetOwnerDocument(getter_AddRefs(domDoc));
+ if (!domDoc) {
+ return;
+ }
+
+ nsCOMPtr doc = do_QueryInterface(domDoc);
+ PRUint32 loadingMessages = NS_PTR_TO_UINT32(
+ doc->GetProperty(nsXFormsAtoms::externalMessagesProperty));
+ if (aAdd) {
+ loadingMessages++;
+ } else {
+ if (loadingMessages) {
+ loadingMessages--;
+ }
+ }
+ doc->SetProperty(nsXFormsAtoms::externalMessagesProperty,
+ NS_REINTERPRET_CAST(void *, loadingMessages), nsnull);
+
+ if (!loadingMessages) {
+ // no outstanding loads left, let the model in the document know in case
+ // the models are waiting to send out the xforms-ready event
+
+ nsCOMPtr modelPriv =
+ nsXFormsUtils::GetModel(mElement);
+ if (modelPriv) {
+ // if there are no more messages loading then it is probably the case
+ // that my mChannel is going to get nulled out as soon as this function
+ // returns. If the model is waiting for this notification, then it may
+ // kick off the message right away and we should probably ensure that
+ // mChannel is gone before HandleAction is called. So...if the channel
+ // isn't pending, let's null it out right here.
+ PRBool isPending = PR_TRUE;
+ mChannel->IsPending(&isPending);
+ if (!isPending) {
+ mChannel = nsnull;
+ }
+ modelPriv->MessageLoadFinished();
+ }
+ }
+}
+
NS_HIDDEN_(nsresult)
NS_NewXFormsMessageElement(nsIXTFElement **aResult)
{
diff --git a/mozilla/extensions/xforms/nsXFormsModelElement.cpp b/mozilla/extensions/xforms/nsXFormsModelElement.cpp
index 7093edc24fd..10f6483a336 100644
--- a/mozilla/extensions/xforms/nsXFormsModelElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsModelElement.cpp
@@ -50,7 +50,6 @@
#include "nsXFormsAtoms.h"
#include "nsINameSpaceManager.h"
#include "nsIServiceManager.h"
-#include "nsINodeInfo.h"
#include "nsIDOMEvent.h"
#include "nsIDOMDOMImplementation.h"
#include "nsIDOMXMLDocument.h"
@@ -59,7 +58,6 @@
#include "nsIXFormsXPathEvaluator.h"
#include "nsIDOMXPathNSResolver.h"
#include "nsIDOMNSXPathExpression.h"
-#include "nsIScriptGlobalObject.h"
#include "nsIContent.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
@@ -76,10 +74,13 @@
#include "nsISchema.h"
#include "nsAutoPtr.h"
#include "nsArray.h"
-#include "nsIEventStateManager.h"
#include "nsIDOMDocumentXBL.h"
+#include "nsIProgrammingLanguage.h"
+#include "nsDOMError.h"
+#include "nsIDOMXPathException.h"
+
#define XFORMS_LAZY_INSTANCE_BINDING \
- "chrome://xforms/content/xforms.xml#xforms-lazy-instance"
+ "chrome://xforms/content/xforms.xml#xforms-lazy-instance"
#ifdef DEBUG
//#define DEBUG_MODEL
@@ -170,6 +171,321 @@ GetModelList(nsIDOMDocument *domDoc)
doc->GetProperty(nsXFormsAtoms::modelListProperty));
}
+static void
+SupportsDtorFunc(void *aObject, nsIAtom *aPropertyName,
+ void *aPropertyValue, void *aData)
+{
+ nsISupports *propertyValue = NS_STATIC_CAST(nsISupports*, aPropertyValue);
+ NS_IF_RELEASE(propertyValue);
+}
+
+
+//------------------------------------------------------------------------------
+// --- nsXFormsControlListItem ---
+
+
+nsXFormsControlListItem::iterator::iterator()
+ : mCur(0)
+{
+}
+
+nsXFormsControlListItem::iterator::iterator(const nsXFormsControlListItem::iterator& aCopy)
+ : mCur(aCopy.mCur)
+{
+ mStack = aCopy.mStack;
+}
+
+nsXFormsControlListItem::iterator
+nsXFormsControlListItem::iterator::operator=(nsXFormsControlListItem* aCnt)
+{
+ mCur = aCnt;
+ return *this;
+}
+
+bool
+nsXFormsControlListItem::iterator::operator!=(const nsXFormsControlListItem* aCnt)
+{
+ return mCur != aCnt;
+}
+
+nsXFormsControlListItem::iterator
+nsXFormsControlListItem::iterator::operator++()
+{
+ if (!mCur)
+ return *this;
+
+ if (mCur->mFirstChild) {
+ if (!mCur->mNextSibling) {
+ mCur = mCur->mFirstChild;
+ return *this;
+ }
+ mStack.AppendElement(mCur->mFirstChild);
+ }
+
+ if (mCur->mNextSibling) {
+ mCur = mCur->mNextSibling;
+ } else if (mStack.Count()) {
+ mCur = (nsXFormsControlListItem*) mStack[mStack.Count() - 1];
+ mStack.RemoveElementAt(mStack.Count() - 1);
+ } else {
+ mCur = nsnull;
+ }
+
+ return *this;
+}
+
+nsXFormsControlListItem*
+nsXFormsControlListItem::iterator::operator*()
+{
+ return mCur;
+}
+
+nsXFormsControlListItem::nsXFormsControlListItem(nsIXFormsControl* aControl)
+ : mNode(aControl),
+ mNextSibling(nsnull),
+ mFirstChild(nsnull)
+{
+
+}
+
+nsXFormsControlListItem::~nsXFormsControlListItem()
+{
+ Clear();
+}
+
+nsXFormsControlListItem::nsXFormsControlListItem(const nsXFormsControlListItem& aCopy)
+ : mNode(aCopy.mNode)
+{
+ if (aCopy.mNextSibling) {
+ mNextSibling = new nsXFormsControlListItem(*aCopy.mNextSibling);
+ NS_WARN_IF_FALSE(mNextSibling, "could not new?!");
+ } else {
+ mNextSibling = nsnull;
+ }
+
+ if (aCopy.mFirstChild) {
+ mFirstChild = new nsXFormsControlListItem(*aCopy.mFirstChild);
+ NS_WARN_IF_FALSE(mFirstChild, "could not new?!");
+ } else {
+ mFirstChild = nsnull;
+ }
+}
+
+void
+nsXFormsControlListItem::Clear()
+{
+ if (mFirstChild) {
+ mFirstChild->Clear();
+ NS_ASSERTION(!(mFirstChild->mFirstChild || mFirstChild->mNextSibling),
+ "child did not clear members!!");
+ delete mFirstChild;
+ mFirstChild = nsnull;
+ }
+ if (mNextSibling) {
+ mNextSibling->Clear();
+ NS_ASSERTION(!(mNextSibling->mFirstChild || mNextSibling->mNextSibling),
+ "sibling did not clear members!!");
+ delete mNextSibling;
+ mNextSibling = nsnull;
+ }
+ if (mNode)
+ mNode = nsnull;
+}
+
+nsresult
+nsXFormsControlListItem::AddControl(nsIXFormsControl *aControl,
+ nsIXFormsControl *aParent)
+{
+ // Four insertion posibilities:
+
+ // 1) Delegate to first child from root node
+ if (!mNode && mFirstChild) {
+ return mFirstChild->AddControl(aControl, aParent);
+ }
+
+ // 2) control with no parent
+ if (!aParent) {
+ nsXFormsControlListItem* newNode = new nsXFormsControlListItem(aControl);
+ NS_ENSURE_STATE(newNode);
+
+ // Empty tree (we have already checked mFirstChild)
+ if (!mNode) {
+ mFirstChild = newNode;
+ return NS_OK;
+ }
+
+ if (mNextSibling) {
+ newNode->mNextSibling = mNextSibling;
+ }
+ mNextSibling = newNode;
+#ifdef DEBUG
+ nsXFormsControlListItem* next = newNode->mNextSibling;
+ while (next) {
+ NS_ASSERTION(aControl != next->mNode,
+ "Node already in tree!!");
+ next = next->mNextSibling;
+ }
+#endif
+
+ return NS_OK;
+ }
+
+ // Locate parent
+ nsXFormsControlListItem* parentControl = FindControl(aParent);
+ NS_ASSERTION(parentControl, "Parent not found?!");
+
+ // 3) parentControl has a first child, insert as sibling to that
+ if (parentControl->mFirstChild) {
+ return parentControl->mFirstChild->AddControl(aControl, nsnull);
+ }
+
+ // 4) first child for parentControl
+ nsXFormsControlListItem* newNode = new nsXFormsControlListItem(aControl);
+ NS_ENSURE_STATE(newNode);
+ parentControl->mFirstChild = newNode;
+
+ return NS_OK;
+}
+
+nsresult
+nsXFormsControlListItem::RemoveControl(nsIXFormsControl *aControl,
+ PRBool &aRemoved)
+{
+ nsXFormsControlListItem* deleteMe = nsnull;
+ aRemoved = PR_FALSE;
+
+ // Try children
+ if (mFirstChild) {
+ // The control to remove is our first child
+ if (mFirstChild->mNode == aControl) {
+ deleteMe = mFirstChild;
+
+ // Fix siblings
+ if (deleteMe->mNextSibling) {
+ mFirstChild = deleteMe->mNextSibling;
+ deleteMe->mNextSibling = nsnull;
+ } else {
+ mFirstChild = nsnull;
+ }
+
+ // Fix children
+ if (deleteMe->mFirstChild) {
+ if (!mFirstChild) {
+ mFirstChild = deleteMe->mFirstChild;
+ } else {
+ nsXFormsControlListItem *insertPos = mFirstChild;
+ while (insertPos->mNextSibling) {
+ insertPos = insertPos->mNextSibling;
+ }
+ insertPos->mNextSibling = deleteMe->mFirstChild;
+ }
+ deleteMe->mFirstChild = nsnull;
+ }
+ } else {
+ // Run through children
+ nsresult rv = mFirstChild->RemoveControl(aControl, aRemoved);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (aRemoved)
+ return rv;
+ }
+ }
+
+ // Try siblings
+ if (!deleteMe && mNextSibling) {
+ if (mNextSibling->mNode == aControl) {
+ deleteMe = mNextSibling;
+ // Fix siblings
+ if (deleteMe->mNextSibling) {
+ mNextSibling = deleteMe->mNextSibling;
+ deleteMe->mNextSibling = nsnull;
+ } else {
+ mNextSibling = nsnull;
+ }
+ // Fix children
+ if (deleteMe->mFirstChild) {
+ if (!mNextSibling) {
+ mNextSibling = deleteMe->mFirstChild;
+ } else {
+ nsXFormsControlListItem *insertPos = mNextSibling;
+ while (insertPos->mNextSibling) {
+ insertPos = insertPos->mNextSibling;
+ }
+ insertPos->mNextSibling = deleteMe->mFirstChild;
+ }
+ deleteMe->mFirstChild = nsnull;
+ }
+ } else {
+ // run through siblings
+ return mNextSibling->RemoveControl(aControl, aRemoved);
+ }
+ }
+
+ if (deleteMe) {
+ NS_ASSERTION(!(deleteMe->mNextSibling),
+ "Deleted control should not have siblings!");
+ NS_ASSERTION(!(deleteMe->mFirstChild),
+ "Deleted control should not have children!");
+ delete deleteMe;
+ aRemoved = PR_TRUE;
+ }
+
+ return NS_OK;
+}
+
+nsXFormsControlListItem*
+nsXFormsControlListItem::FindControl(nsIXFormsControl *aControl)
+{
+ if (!aControl)
+ return nsnull;
+
+ // this should only be false for the root
+ if (mNode) {
+ // XXX: *sigh* pointer comparision of nsIXFormsControl would be nice...
+ nsCOMPtr el1, el2;
+ aControl->GetElement(getter_AddRefs(el1));
+ mNode->GetElement(getter_AddRefs(el2));
+
+ if (el1 == el2)
+ return this;
+ }
+
+ nsXFormsControlListItem* cur = nsnull;
+ if (mFirstChild) {
+ cur = mFirstChild->FindControl(aControl);
+ }
+ if (!cur && mNextSibling) {
+ cur = mNextSibling->FindControl(aControl);
+ }
+ return cur;
+}
+
+already_AddRefed
+nsXFormsControlListItem::Control()
+{
+ nsIXFormsControl* res = nsnull;
+ if (mNode)
+ NS_ADDREF(res = mNode);
+ NS_WARN_IF_FALSE(res, "Returning nsnull for a control. Bad sign.");
+ return res;
+}
+
+nsXFormsControlListItem*
+nsXFormsControlListItem::begin()
+{
+ // handle root
+ if (!mNode)
+ return mFirstChild;
+
+ return this;
+}
+
+nsXFormsControlListItem*
+nsXFormsControlListItem::end()
+{
+ return nsnull;
+}
+
+
//------------------------------------------------------------------------------
static const nsIID sScriptingIIDs[] = {
@@ -255,14 +571,17 @@ nsXFormsModelElement::CancelPostRefresh(nsIXFormsControl* aControl)
nsXFormsModelElement::nsXFormsModelElement()
: mElement(nsnull),
+ mFormControls(nsnull),
mSchemaCount(0),
mSchemaTotal(0),
mPendingInstanceCount(0),
mDocumentLoaded(PR_FALSE),
mNeedsRefresh(PR_FALSE),
mInstancesInitialized(PR_FALSE),
+ mReadyHandled(PR_FALSE),
mInstanceDocuments(nsnull),
- mLazyModel(PR_FALSE)
+ mLazyModel(PR_FALSE),
+ mConstructDoneHandled(PR_FALSE)
{
}
@@ -290,6 +609,8 @@ nsXFormsModelElement::OnDestroyed()
if (mInstanceDocuments)
mInstanceDocuments->DropReferences();
+ mFormControls.Clear();
+
return NS_OK;
}
@@ -401,6 +722,8 @@ nsXFormsModelElement::InitializeInstances()
// Parse the whitespace-separated list.
nsCOMPtr content = do_QueryInterface(mElement);
nsRefPtr baseURI = content->GetBaseURI();
+ nsRefPtr docURI = content->GetOwnerDoc() ?
+ content->GetOwnerDoc()->GetDocumentURI() : nsnull;
nsCStringArray schemas;
schemas.ParseString(NS_ConvertUTF16toUTF8(schemaList).get(), " \t\r\n");
@@ -422,7 +745,7 @@ nsXFormsModelElement::InitializeInstances()
newURL->GetRef(ref);
newURL->SetRef(EmptyCString());
PRBool equals = PR_FALSE;
- newURL->Equals(baseURI, &equals);
+ newURL->Equals(docURI, &equals);
if (equals) {
// We will not be able to locate the element using the
// getElementById function defined on our document when
@@ -454,10 +777,15 @@ nsXFormsModelElement::InitializeInstances()
}
}
if (NS_FAILED(rv)) {
- // this is a fatal error (XXX)
+ // this is a fatal error
nsXFormsUtils::ReportError(NS_LITERAL_STRING("schemaLoadError"), mElement);
nsXFormsUtils::DispatchEvent(mElement, eEvent_LinkException);
- return NS_OK;
+ rv = NS_OK;
+ if (!nsXFormsUtils::HandleFatalError(mElement,
+ NS_LITERAL_STRING("XFormsLinkException"))) {
+ rv = NS_ERROR_FAILURE;
+ }
+ return rv;
}
}
}
@@ -465,6 +793,7 @@ nsXFormsModelElement::InitializeInstances()
// 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 element is created in anonymous content using XBL.
NS_ENSURE_STATE(mInstanceDocuments);
PRUint32 instCount;
mInstanceDocuments->GetLength(&instCount);
@@ -549,20 +878,18 @@ nsXFormsModelElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled)
rv = Rebuild();
} else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_ModelConstructDone].name)) {
rv = ConstructDone();
- } else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_Ready].name)) {
- Ready();
+ mConstructDoneHandled = PR_TRUE;
} else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_Reset].name)) {
Reset();
} else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_BindingException].name)) {
- *aHandled = nsXFormsUtils::HandleBindingException(mElement);
+ *aHandled = nsXFormsUtils::HandleFatalError(mElement,
+ NS_LITERAL_STRING("XFormsBindingException"));
} else {
*aHandled = PR_FALSE;
}
-#ifdef DEBUG
- if (NS_FAILED(rv))
- printf("nsXFormsModelElement::HandleDefault() failed!\n");
-#endif
+ NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
+ "nsXFormsModelElement::HandleDefault() failed!\n");
return rv;
}
@@ -597,7 +924,7 @@ nsXFormsModelElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
nsresult rv = mMDG.Init(this);
NS_ENSURE_SUCCESS(rv, rv);
- mSchemas = do_GetService(NS_SCHEMALOADER_CONTRACTID);
+ mSchemas = do_CreateInstance(NS_SCHEMALOADER_CONTRACTID);
mInstanceDocuments = new nsXFormsModelInstanceDocuments();
NS_ASSERTION(mInstanceDocuments, "could not create mInstanceDocuments?!");
@@ -627,7 +954,18 @@ nsXFormsModelElement::GetInstanceDocument(const nsAString& aInstanceID,
NS_ENSURE_ARG_POINTER(aDocument);
*aDocument = FindInstanceDocument(aInstanceID).get(); // transfer reference
- return *aDocument ? NS_OK : NS_ERROR_FAILURE;
+
+ if (*aDocument) {
+ return NS_OK;
+ }
+
+ const nsPromiseFlatString& flat = PromiseFlatString(aInstanceID);
+ const PRUnichar *strings[] = { flat.get() };
+ nsXFormsUtils::ReportError(aInstanceID.IsEmpty() ?
+ NS_LITERAL_STRING("defInstanceNotFound") :
+ NS_LITERAL_STRING("instanceNotFound"),
+ strings, 1, mElement, nsnull);
+ return NS_ERROR_DOM_NOT_FOUND_ERR;
}
NS_IMETHODIMP
@@ -648,45 +986,26 @@ nsXFormsModelElement::Rebuild()
mNodeToType.Clear();
mNodeToP3PType.Clear();
- // 2. Re-attach all elements
+ // 2. Process bind elements
+ rv = ProcessBindElements();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // 3. Re-attach all elements
if (mDocumentLoaded) { // if it's not during initializing phase
- // Copy the form control list as it stands right now.
- nsVoidArray *oldFormList = new nsVoidArray();
- NS_ENSURE_TRUE(oldFormList, NS_ERROR_OUT_OF_MEMORY);
- *oldFormList = mFormControls;
-
- // Clear out mFormControls so that we can rebuild the list. We'll go control
- // by control over the old list and rebind the controls.
- mFormControls.Clear(); // if this happens on a documentchange
+ nsXFormsControlListItem::iterator it;
+ for (it = mFormControls.begin(); it != mFormControls.end(); ++it) {
+ nsCOMPtr control = (*it)->Control();
+ NS_ASSERTION(control, "mFormControls has null control?!");
- PRInt32 controlCount = oldFormList->Count();
- for (PRInt32 i = 0; i < controlCount; ++i) {
- nsIXFormsControl* control = NS_STATIC_CAST(nsIXFormsControl*,
- (*oldFormList)[i]);
- /// @todo If a control is removed because of previous control has been
- /// refreshed, we do, obviously, not need to refresh it. So mFormControls
- /// should have weak bindings to the controls I guess? (XXX)
- ///
- /// This could happen for \s for example.
- if (!control) {
- continue;
- }
-
- // run bind to reset mBoundNode for all of these controls and also, in the
- // process, they will be added to the model that they should be bound to.
+ // run bind to reset mBoundNode for all of the model's controls
control->Bind();
}
-
- delete oldFormList;
// Triggers a refresh of all controls
mNeedsRefresh = PR_TRUE;
}
- // 3. Rebuild graph
- rv = ProcessBindElements();
- NS_ENSURE_SUCCESS(rv, rv);
-
+ // 4. Rebuild graph
return mMDG.Rebuild();
}
@@ -714,7 +1033,7 @@ nsXFormsModelElement::SetSingleState(nsIDOMElement *aElement,
nsresult
nsXFormsModelElement::SetStatesInternal(nsIXFormsControl *aControl,
nsIDOMNode *aNode,
- PRBool aAllStates)
+ PRBool aDispatchEvents)
{
NS_ENSURE_ARG(aControl);
if (!aNode)
@@ -730,32 +1049,25 @@ nsXFormsModelElement::SetStatesInternal(nsIXFormsControl *aControl,
const nsXFormsNodeState *ns = mMDG.GetNodeState(aNode);
NS_ENSURE_STATE(ns);
- // XXX nsXFormsNodeState could expose a bitmask using NS_EVENTs, to avoid
- // most of this...
- PRBool tmp = ns->IsValid();
- PRUint32 state = tmp ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID;
- if (aAllStates || ns->ShouldDispatchValid()) {
- SetSingleState(element, tmp, eEvent_Valid);
- }
- tmp = ns->IsReadonly();
- state |= tmp ? NS_EVENT_STATE_MOZ_READONLY : NS_EVENT_STATE_MOZ_READWRITE;
- if (aAllStates || ns->ShouldDispatchReadonly()) {
- SetSingleState(element, tmp, eEvent_Readonly);
- }
- tmp = ns->IsRequired();
- state |= tmp ? NS_EVENT_STATE_REQUIRED : NS_EVENT_STATE_OPTIONAL;
- if (aAllStates || ns->ShouldDispatchRequired()) {
- SetSingleState(element, tmp, eEvent_Required);
- }
- tmp = ns->IsRelevant();
- state |= tmp ? NS_EVENT_STATE_ENABLED : NS_EVENT_STATE_DISABLED;
- if (aAllStates || ns->ShouldDispatchRelevant()) {
- SetSingleState(element, tmp, eEvent_Enabled);
- }
-
- nsresult rv = xtfWrap->SetIntrinsicState(state);
+ nsresult rv = xtfWrap->SetIntrinsicState(ns->GetIntrinsicState());
NS_ENSURE_SUCCESS(rv, rv);
+ if (!aDispatchEvents)
+ return NS_OK;
+
+ if (ns->ShouldDispatchValid()) {
+ SetSingleState(element, ns->IsValid(), eEvent_Valid);
+ }
+ if (ns->ShouldDispatchReadonly()) {
+ SetSingleState(element, ns->IsReadonly(), eEvent_Readonly);
+ }
+ if (ns->ShouldDispatchRequired()) {
+ SetSingleState(element, ns->IsRequired(), eEvent_Required);
+ }
+ if (ns->ShouldDispatchRelevant()) {
+ SetSingleState(element, ns->IsRelevant(), eEvent_Enabled);
+ }
+
if (ns->ShouldDispatchValueChanged()) {
nsXFormsUtils::DispatchEvent(element, eEvent_ValueChanged);
}
@@ -777,7 +1089,7 @@ nsXFormsModelElement::Revalidate()
nsAutoString name;
node->GetNodeName(name);
printf("\t%s [%p]\n",
- NS_ConvertUCS2toUTF8(name).get(),
+ NS_ConvertUTF16toUTF8(name).get(),
(void*) node);
}
#endif
@@ -788,6 +1100,159 @@ nsXFormsModelElement::Revalidate()
return NS_OK;
}
+nsresult
+nsXFormsModelElement::RefreshSubTree(nsXFormsControlListItem *aCurrent,
+ PRBool aForceRebind)
+{
+ nsresult rv;
+
+ while (aCurrent) {
+ nsCOMPtr control(aCurrent->Control());
+ NS_ASSERTION(control, "A tree node without a control?!");
+
+ // Get bound node
+ nsCOMPtr boundNode;
+ control->GetBoundNode(getter_AddRefs(boundNode));
+
+ PRBool rebind = aForceRebind;
+ PRBool refresh = PR_FALSE;
+ PRBool rebindChildren = PR_FALSE;
+
+#ifdef DEBUG_MODEL
+ nsCOMPtr controlElement;
+ control->GetElement(getter_AddRefs(controlElement));
+ printf("rebind: %d, mNeedsRefresh: %d, rebindChildren: %d\n",
+ rebind, mNeedsRefresh, rebindChildren);
+ if (controlElement) {
+ printf("Checking control: ");
+ //DBG_TAGINFO(controlElement);
+ }
+#endif
+
+ if (mNeedsRefresh || rebind) {
+ refresh = PR_TRUE;
+ } else {
+ PRBool usesModelBinding = PR_FALSE;
+ control->GetUsesModelBinding(&usesModelBinding);
+
+#ifdef DEBUG_MODEL
+ printf("usesModelBinding: %d\n", usesModelBinding);
+#endif
+
+ nsCOMArray *deps = nsnull;
+ if (usesModelBinding) {
+ if (!boundNode) {
+ // If a control uses a model binding, but has no bound node a
+ // rebuild is the only thing that'll (eventually) change it
+ aCurrent = aCurrent->NextSibling();
+ continue;
+ }
+ } else {
+ // Get dependencies
+ control->GetDependencies(&deps);
+ }
+ PRUint32 depCount = deps ? deps->Count() : 0;
+
+#ifdef DEBUG_MODEL
+ nsAutoString boundName;
+ if (boundNode)
+ boundNode->GetNodeName(boundName);
+ printf("\tDependencies: %d, Bound to: '%s' [%p]\n",
+ depCount,
+ NS_ConvertUTF16toUTF8(boundName).get(),
+ (void*) boundNode);
+
+ nsAutoString depNodeName;
+ for (PRUint32 t = 0; t < depCount; ++t) {
+ nsCOMPtr tmpdep = deps->ObjectAt(t);
+ if (tmpdep) {
+ tmpdep->GetNodeName(depNodeName);
+ printf("\t\t%s [%p]\n",
+ NS_ConvertUTF16toUTF8(depNodeName).get(),
+ (void*) tmpdep);
+ }
+ }
+#endif
+
+ nsCOMPtr curChanged;
+
+ // Iterator over changed nodes. Checking for rebind, too. If it ever
+ // becomes true due to some condition below, we can stop this testing
+ // since any control that needs to rebind will also refresh.
+ for (PRInt32 j = 0; j < mChangedNodes.Count() && !rebind; ++j) {
+ curChanged = do_QueryInterface(mChangedNodes[j]);
+
+ // Check whether the bound node is dirty. If so, we need to refresh the
+ // control (get updated node value from the bound node)
+ if (!refresh && boundNode) {
+ curChanged->IsSameNode(boundNode, &refresh);
+
+ // Two ways to go here. Keep in mind that controls using model
+ // binding expressions never needs to have dependencies checked as
+ // they only rebind on xforms-rebuild
+ if (refresh && usesModelBinding) {
+ // 1) If the control needs a refresh, and uses model bindings,
+ // we can stop checking here
+ break;
+ }
+ if (refresh || usesModelBinding) {
+ // 2) If either the control needs a refresh or it uses a model
+ // binding we can continue to next changed node
+ continue;
+ }
+ }
+
+ // Check whether any dependencies are dirty. If so, we need to rebind
+ // the control (re-evaluate it's binding expression)
+ for (PRUint32 k = 0; k < depCount; ++k) {
+ /// @note beaufour: I'm not too happy about this ...
+ /// O(mChangedNodes.Count() * deps->Count()), but using the pointers
+ /// for sorting and comparing does not work...
+ curChanged->IsSameNode(deps->ObjectAt(k), &rebind);
+ if (rebind)
+ // We need to rebind the control, no need to check any more
+ break;
+ }
+ }
+#ifdef DEBUG_MODEL
+ printf("\trebind: %d, refresh: %d\n", rebind, refresh);
+#endif
+ }
+
+ // Handle rebinding
+ if (rebind) {
+ nsCOMPtr oldBoundNode;
+ control->GetBoundNode(getter_AddRefs(oldBoundNode));
+ rv = control->Bind();
+ NS_ENSURE_SUCCESS(rv, rv);
+ control->GetBoundNode(getter_AddRefs(boundNode));
+ rebindChildren = (oldBoundNode != boundNode);
+ }
+
+ // Handle refreshing
+ if (rebind || refresh) {
+ rv = SetStatesInternal(control, boundNode);
+ NS_ENSURE_SUCCESS(rv, rv);
+ control->Refresh();
+ // XXX: we should really check the return result, but f.x. select1
+ // returns error because of no widget...? so we should ensure that an
+ // error is only returned when there actually is an error, and we should
+ // report that on the console... possibly we should then continue,
+ // instead of bailing totally.
+ // NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ // Refresh children
+ rv = RefreshSubTree(aCurrent->FirstChild(), rebindChildren);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aCurrent = aCurrent->NextSibling();
+ }
+
+ return NS_OK;
+}
+
+
NS_IMETHODIMP
nsXFormsModelElement::Refresh()
{
@@ -796,111 +1261,17 @@ nsXFormsModelElement::Refresh()
#endif
nsPostRefresh postRefresh = nsPostRefresh();
- // Iterate over all form controls if not during initialization phase (then
- // this is handled in InitializeControls())
- if (mDocumentLoaded) {
- PRInt32 controlCount = mFormControls.Count();
- for (PRInt32 i = 0; i < controlCount; ++i) {
- nsIXFormsControl* control = NS_STATIC_CAST(nsIXFormsControl*, mFormControls[i]);
- /// @todo If a control is removed because of previous control has been
- /// refreshed, we do, obviously, not need to refresh it. So mFormControls
- /// should have weak bindings to the controls I guess? (XXX)
- ///
- /// This could happen for \s for example.
- if (!control) {
- continue;
- }
-
- // Get bound node
- nsCOMPtr boundNode;
- control->GetBoundNode(getter_AddRefs(boundNode));
-
- PRBool rebind = PR_FALSE;
- PRBool refresh = PR_FALSE;
-
- if (mNeedsRefresh) {
- refresh = PR_TRUE;
- } else {
- // Get dependencies
- nsCOMArray *deps = nsnull;
- control->GetDependencies(&deps);
-
-#ifdef DEBUG_MODEL
- PRUint32 depCount = deps ? deps->Count() : 0;
- nsCOMPtr controlElement;
- control->GetElement(getter_AddRefs(controlElement));
- if (controlElement) {
- printf("Checking control: ");
- //DBG_TAGINFO(controlElement);
- nsAutoString boundName;
- if (boundNode)
- boundNode->GetNodeName(boundName);
- printf("\tDependencies: %d, Bound to: '%s' [%p]\n",
- depCount,
- NS_ConvertUCS2toUTF8(boundName).get(),
- (void*) boundNode);
-
- nsAutoString depNodeName;
- for (PRUint32 t = 0; t < depCount; ++t) {
- nsCOMPtr tmpdep = deps->ObjectAt(t);
- if (tmpdep) {
- tmpdep->GetNodeName(depNodeName);
- printf("\t\t%s [%p]\n",
- NS_ConvertUCS2toUTF8(depNodeName).get(),
- (void*) tmpdep);
- }
- }
- }
-#endif
-
- nsCOMPtr curChanged;
-
- for (PRInt32 j = 0; j < mChangedNodes.Count(); ++j) {
- curChanged = do_QueryInterface(mChangedNodes[j]);
-
- // Check whether the bound node is dirty. If so, we need to refresh the
- // control (get updated node value from the bound node)
- if (!refresh && boundNode) {
- curChanged->IsSameNode(boundNode, &refresh);
-
- if (refresh)
- // We need to refresh the control. We cannot break out of the loop
- // as we need to check dependencies
- continue;
- }
-
- // Check whether any dependencies are dirty. If so, we need to rebind
- // the control (re-evaluate it's binding expression)
- for (PRInt32 k = 0; k < deps->Count(); ++k) {
- /// @note beaufour: I'm not to happy about this ...
- /// O(mChangedNodes.Count() * deps->Count()), but using the pointers
- /// for sorting and comparing does not work...
- curChanged->IsSameNode(deps->ObjectAt(k), &rebind);
- if (rebind)
- // We need to rebind the control, no need to check any more
- break;
- }
- }
-#ifdef DEBUG_MODEL
- printf("\trebind: %d, refresh: %d\n", rebind, refresh);
-#endif
- }
-
- if (rebind) {
- control->Bind();
- control->GetBoundNode(getter_AddRefs(boundNode));
- }
- if (rebind || refresh) {
- nsresult rv = SetStatesInternal(control, boundNode);
- NS_ENSURE_SUCCESS(rv, rv);
- control->Refresh();
- }
- }
-
- mChangedNodes.Clear();
- mNeedsRefresh = PR_FALSE;
+ if (!mDocumentLoaded) {
+ return NS_OK;
}
-
+
+ // Kick off refreshing on root node
+ nsresult rv = RefreshSubTree(mFormControls.FirstChild(), PR_FALSE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Clear refresh structures
+ mChangedNodes.Clear();
+ mNeedsRefresh = PR_FALSE;
mMDG.ClearDispatchFlags();
return NS_OK;
@@ -917,8 +1288,6 @@ nsXFormsModelElement::OnLoad(nsISchema* aSchema)
nsresult rv = FinishConstruction();
NS_ENSURE_SUCCESS(rv, rv);
- nsXFormsUtils::DispatchEvent(mElement, eEvent_Refresh);
-
MaybeNotifyCompletion();
}
@@ -959,18 +1328,22 @@ nsXFormsModelElement::HandleEvent(nsIDOMEvent* aEvent)
// nsIModelElementPrivate
NS_IMETHODIMP
-nsXFormsModelElement::AddFormControl(nsIXFormsControl *aControl)
+nsXFormsModelElement::AddFormControl(nsIXFormsControl *aControl,
+ nsIXFormsControl *aParent)
{
- if (mFormControls.IndexOf(aControl) == -1)
- mFormControls.AppendElement(aControl);
- return NS_OK;
+ NS_ENSURE_ARG(aControl);
+ return mFormControls.AddControl(aControl, aParent);
}
NS_IMETHODIMP
nsXFormsModelElement::RemoveFormControl(nsIXFormsControl *aControl)
{
- mFormControls.RemoveElement(aControl);
- return NS_OK;
+ NS_ENSURE_ARG(aControl);
+ PRBool removed;
+ nsresult rv = mFormControls.RemoveControl(aControl, removed);
+ NS_WARN_IF_FALSE(removed,
+ "Tried to remove control that was not in the model");
+ return rv;
}
NS_IMETHODIMP
@@ -1034,14 +1407,20 @@ nsXFormsModelElement::InstanceLoadStarted()
NS_IMETHODIMP
nsXFormsModelElement::InstanceLoadFinished(PRBool aSuccess)
{
- --mPendingInstanceCount;
if (!aSuccess) {
+ // This will leave mPendingInstanceCount in an invalid state, which is
+ // exactly what we want, because this is a fatal error, and processing
+ // should stop. If we decrease mPendingInstanceCount, the model would
+ // finish construction, which is wrong.
nsXFormsUtils::ReportError(NS_LITERAL_STRING("instanceLoadError"), mElement);
nsXFormsUtils::DispatchEvent(mElement, eEvent_LinkException);
- } else if (IsComplete()) {
+ return NS_OK;
+ }
+
+ --mPendingInstanceCount;
+ if (IsComplete()) {
nsresult rv = FinishConstruction();
if (NS_SUCCEEDED(rv)) {
- nsXFormsUtils::DispatchEvent(mElement, eEvent_Refresh);
MaybeNotifyCompletion();
}
}
@@ -1147,6 +1526,62 @@ nsXFormsModelElement::ValidateNode(nsIDOMNode *aInstanceNode, PRBool *aResult)
return NS_OK;
}
+nsresult
+nsXFormsModelElement::ValidateDocument(nsIDOMDocument *aInstanceDocument,
+ PRBool *aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG(aInstanceDocument);
+
+ /*
+ This will process the instance document and check for schema validity. It
+ will mark nodes in the document with their schema types using nsIProperty
+ until it hits a structural schema validation error. So if the instance
+ document's XML structure is invalid, don't expect type properties to be
+ set.
+
+ Note that if the structure is fine but some simple types nodes (nodes
+ that contain text only) are invalid (say one has a empty nodeValue but
+ should be a date), the schema validator will continue processing and add
+ the type properties. Schema validation will return false at the end.
+ */
+
+ nsCOMPtr element;
+ nsresult rv = aInstanceDocument->GetDocumentElement(getter_AddRefs(element));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRBool isValid = PR_FALSE;
+
+ // get namespace from node
+ nsAutoString nsuri;
+ element->GetNamespaceURI(nsuri);
+
+ nsCOMPtr schemaColl = do_QueryInterface(mSchemas);
+ NS_ENSURE_STATE(schemaColl);
+
+ nsCOMPtr schema;
+ schemaColl->GetSchema(nsuri, getter_AddRefs(schema));
+ if (schema) {
+ nsXFormsSchemaValidator validator;
+ validator.LoadSchema(schema);
+ // Validate will validate the node and its subtree, as per the schema
+ // specification.
+ isValid = validator.Validate(element);
+ } else {
+ // no schema found for the instance document's namespace.
+ nsCOMPtr instanceElement;
+ nsXFormsUtils::GetInstanceNodeForData(element,
+ getter_AddRefs(instanceElement));
+ const PRUnichar *strings[] = { nsuri.get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("noSchemaForInstance"),
+ strings, 1, instanceElement, nsnull);
+ rv = NS_ERROR_UNEXPECTED;
+ }
+
+ *aResult = isValid;
+ return rv;
+}
+
/*
* SUBMIT_SERIALIZE_NODE - node is to be serialized
* SUBMIT_SKIP_NODE - node is not to be serialized
@@ -1179,6 +1614,20 @@ nsXFormsModelElement::HandleInstanceDataNode(nsIDOMNode *aInstanceDataNode, unsi
return NS_OK;
}
+NS_IMETHODIMP
+nsXFormsModelElement::GetLazyAuthored(PRBool *aLazyInstance)
+{
+ *aLazyInstance = mLazyModel;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsModelElement::GetIsReady(PRBool *aIsReady)
+{
+ *aIsReady = mReadyHandled;
+ return NS_OK;
+}
+
NS_IMETHODIMP
nsXFormsModelElement::GetTypeFromNode(nsIDOMNode *aInstanceData,
nsAString &aType,
@@ -1203,6 +1652,21 @@ nsXFormsModelElement::GetTypeFromNode(nsIDOMNode *aInstanceData,
// If there was no type information on the node itself, check for a type
// bound to the node via \
if (!typeVal && !mNodeToType.Get(aInstanceData, &typeVal)) {
+ // check if schema validation left us a nsISchemaType*
+ nsCOMPtr content = do_QueryInterface(aInstanceData);
+
+ if (content) {
+ nsISchemaType *type;
+ nsCOMPtr myAtom = do_GetAtom("xsdtype");
+
+ type = NS_STATIC_CAST(nsISchemaType *, content->GetProperty(myAtom));
+ if (type) {
+ type->GetName(aType);
+ type->GetTargetNamespace(aNSUri);
+ return NS_OK;
+ }
+ }
+
// No type information found
return NS_ERROR_NOT_AVAILABLE;
}
@@ -1252,7 +1716,6 @@ nsXFormsModelElement::GetTypeFromNode(nsIDOMNode *aInstanceData,
return rv;
}
-
// nsIXFormsContextControl
NS_IMETHODIMP
@@ -1308,13 +1771,6 @@ nsXFormsModelElement::GetContext(nsAString &aModelID,
return NS_OK;
}
-NS_IMETHODIMP
-nsXFormsModelElement::GetLazyAuthored(PRBool *aLazyInstance)
-{
- *aLazyInstance = mLazyModel;
- return NS_OK;
-}
-
// internal methods
already_AddRefed
@@ -1324,8 +1780,9 @@ nsXFormsModelElement::FindInstanceDocument(const nsAString &aID)
nsXFormsModelElement::FindInstanceElement(aID, getter_AddRefs(instance));
nsIDOMDocument *doc = nsnull;
- if (instance)
- instance->GetDocument(&doc); // addrefs
+ if (instance) {
+ instance->GetInstanceDocument(&doc); // addrefs
+ }
return doc;
}
@@ -1370,7 +1827,8 @@ nsXFormsModelElement::ProcessBindElements()
child->GetNamespaceURI(namespaceURI);
if (namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
rv = ProcessBind(xpath, firstInstanceRoot, 1, 1,
- nsCOMPtr(do_QueryInterface(child)));
+ nsCOMPtr(do_QueryInterface(child)),
+ PR_TRUE);
if (NS_FAILED(rv)) {
return NS_OK;
}
@@ -1391,12 +1849,6 @@ nsXFormsModelElement::Reset()
nsXFormsUtils::DispatchEvent(mElement, eEvent_Refresh);
}
-void
-nsXFormsModelElement::Ready()
-{
- BackupOrRestoreInstanceData(PR_FALSE);
-}
-
// This function will restore all of the model's instance data to it's original
// state if the supplied boolean is PR_TRUE. If it is PR_FALSE, this function
// will cause this model's instance data to be backed up.
@@ -1492,15 +1944,19 @@ nsXFormsModelElement::InitializeControls()
#endif
nsPostRefresh postRefresh = nsPostRefresh();
- PRInt32 controlCount = mFormControls.Count();
+ nsXFormsControlListItem::iterator it;
nsresult rv;
- for (PRInt32 i = 0; i < controlCount; ++i) {
+ for (it = mFormControls.begin(); it != mFormControls.end(); ++it) {
// Get control
- nsIXFormsControl *control = NS_STATIC_CAST(nsIXFormsControl*,
- mFormControls[i]);
- if (!control)
- continue;
+ nsCOMPtr control = (*it)->Control();
+ NS_ASSERTION(control, "mFormControls has null control?!");
+#ifdef DEBUG_MODEL
+ printf("\tControl (%p): ", (void*) control);
+ nsCOMPtr controlElement;
+ control->GetElement(getter_AddRefs(controlElement));
+ // DBG_TAGINFO(controlElement);
+#endif
// Rebind
rv = control->Bind();
NS_ENSURE_SUCCESS(rv, rv);
@@ -1511,7 +1967,7 @@ nsXFormsModelElement::InitializeControls()
NS_ENSURE_SUCCESS(rv, rv);
// Set MIP states on control
- rv = SetStatesInternal(control, boundNode, PR_TRUE);
+ rv = SetStatesInternal(control, boundNode, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
// Refresh controls
@@ -1519,6 +1975,8 @@ nsXFormsModelElement::InitializeControls()
NS_ENSURE_SUCCESS(rv, rv);
}
+ mChangedNodes.Clear();
+
return NS_OK;
}
@@ -1553,12 +2011,58 @@ nsXFormsModelElement::MaybeNotifyCompletion()
nsXFormsUtils::DispatchEvent(model->mElement, eEvent_ModelConstructDone);
}
+ // validate the instance documents becauar we want schemaValidation to add
+ // schema type properties from the schema file unto our instance document
+ // elements. We don't care about the validation results.
+ if (mInstanceDocuments) {
+ PRUint32 instCount;
+ mInstanceDocuments->GetLength(&instCount);
+ if (instCount) {
+ nsCOMPtr document;
+
+ for (PRUint32 i = 0; i < instCount; ++i) {
+ nsIInstanceElementPrivate* instEle = mInstanceDocuments->GetInstanceAt(i);
+ nsCOMPtr NSInstEle(instEle);
+ NSInstEle->GetInstanceDocument(getter_AddRefs(document));
+ NS_ASSERTION(document, "nsIXFormsNSInstanceElement::GetInstanceDocument returned null?!");
+
+ if (document) {
+ PRBool isValid = PR_FALSE;
+ ValidateDocument(document, &isValid);
+
+ if (!isValid) {
+ nsCOMPtr instanceElement;
+ instEle->GetElement(getter_AddRefs(instanceElement));
+
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("instDocumentInvalid"),
+ instanceElement);
+ }
+ }
+ }
+ }
+ }
+
nsXFormsModelElement::ProcessDeferredBinds(domDoc);
+ nsCOMPtr doc = do_QueryInterface(domDoc);
+ if (doc) {
+ PRUint32 loadingMessages = NS_PTR_TO_UINT32(
+ doc->GetProperty(nsXFormsAtoms::externalMessagesProperty));
+ if (loadingMessages) {
+ // if we are still waiting for external messages to load, then put off
+ // the xforms-ready until a model in the document is notified that they
+ // are finished loading
+
+ return;
+ }
+ }
+
for (i = 0; i < models->Count(); ++i) {
nsXFormsModelElement *model =
NS_STATIC_CAST(nsXFormsModelElement *, models->ElementAt(i));
- nsXFormsUtils::DispatchEvent(model->mElement, eEvent_Ready);
+ model->BackupOrRestoreInstanceData(PR_FALSE);
+ model->mReadyHandled = PR_TRUE;
+ nsXFormsUtils::DispatchEvent(model->mElement, eEvent_Ready);
}
}
@@ -1567,7 +2071,8 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
nsIDOMNode *aContextNode,
PRInt32 aContextPosition,
PRInt32 aContextSize,
- nsIDOMElement *aBindElement)
+ nsIDOMElement *aBindElement,
+ PRBool aIsOuter)
{
// Get the model item properties specified by this \.
nsCOMPtr props[eModel__count];
@@ -1602,22 +2107,45 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
if (expr.IsEmpty()) {
expr = NS_LITERAL_STRING(".");
}
- rv = aEvaluator->Evaluate(expr, aContextNode, aContextSize, aContextPosition,
+ rv = aEvaluator->Evaluate(expr, aContextNode, aContextPosition, aContextSize,
aBindElement,
nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
nsnull, getter_AddRefs(result));
if (NS_FAILED(rv)) {
+ if (rv == nsIDOMXPathException::INVALID_EXPRESSION_ERR) {
+ // the xpath expression isn't valid xpath
+
+ const nsPromiseFlatString& flat = PromiseFlatString(expr);
+ const PRUnichar *strings[] = { flat.get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("exprParseError"),
+ strings, 1, aBindElement, nsnull);
+ nsXFormsUtils::DispatchEvent(mElement, eEvent_ComputeException);
+ } else {
#ifdef DEBUG
- printf("xforms-binding-exception: XPath Evaluation failed\n");
+ printf("xforms-binding-exception: XPath Evaluation failed\n");
#endif
- const PRUnichar *strings[] = { expr.get() };
- nsXFormsUtils::ReportError(NS_LITERAL_STRING("nodesetEvaluateError"),
- strings, 1, aBindElement, aBindElement);
- nsXFormsUtils::DispatchEvent(mElement, eEvent_BindingException);
+ const PRUnichar *strings[] = { expr.get() };
+ nsXFormsUtils::ReportError(NS_LITERAL_STRING("nodesetEvaluateError"),
+ strings, 1, aBindElement, aBindElement);
+ nsXFormsUtils::DispatchEvent(mElement, eEvent_BindingException);
+ }
return rv;
}
NS_ENSURE_STATE(result);
+
+ // If this is an outer bind, store the nodeset, as controls binding to this
+ // bind will need this.
+ if (aIsOuter) {
+ nsCOMPtr content(do_QueryInterface(aBindElement));
+ NS_ASSERTION(content, "nsIDOMElement not implementing nsIContent?!");
+ rv = content->SetProperty(nsXFormsAtoms::bind, result,
+ SupportsDtorFunc);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // addref, circumventing nsDerivedSave
+ NS_ADDREF(NS_STATIC_CAST(nsIDOMXPathResult*, result));
+ }
PRUint32 snapLen;
rv = result->GetSnapshotLength(&snapLen);
@@ -1681,7 +2209,7 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
nsAutoPtr xNode(parser.Parse(propStrings[j]));
deps.Clear();
rv = analyzer.Analyze(node, xNode, expr, &propStrings[j], &deps,
- snapItem + 1, snapLen);
+ snapItem + 1, snapLen, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
// Insert into MDG
@@ -1754,7 +2282,7 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
NS_IMETHODIMP
nsXFormsModelElement::SetStates(nsIXFormsControl *aControl, nsIDOMNode *aBoundNode)
{
- return SetStatesInternal(aControl, aBoundNode, PR_TRUE);
+ return SetStatesInternal(aControl, aBoundNode, PR_FALSE);
}
nsresult
@@ -1766,6 +2294,60 @@ nsXFormsModelElement::AddInstanceElement(nsIInstanceElementPrivate *aInstEle)
return NS_OK;
}
+nsresult
+nsXFormsModelElement::RemoveInstanceElement(nsIInstanceElementPrivate *aInstEle)
+{
+ NS_ENSURE_STATE(mInstanceDocuments);
+ mInstanceDocuments->RemoveInstance(aInstEle);
+
+ return NS_OK;
+}
+
+nsresult
+nsXFormsModelElement::MessageLoadFinished()
+{
+ // This is our signal that all external message links have been tested. If
+ // we were waiting for this to send out xforms-ready, then now is the time.
+
+ // if this document hasn't processed xforms-model-construct-done, yet (which
+ // must precede xforms-ready), then we'll send out the xforms-ready later
+ // as part of our normal handling. If we've already become ready, then this
+ // event was probably generated by a change in the src attribute on the
+ // message element. Ignore it in that case.
+ if (!mConstructDoneHandled || mReadyHandled) {
+ return NS_OK;
+ }
+
+ nsCOMPtr domDoc;
+ mElement->GetOwnerDocument(getter_AddRefs(domDoc));
+ const nsVoidArray *models = GetModelList(domDoc);
+ nsCOMPtrdoc = do_QueryInterface(domDoc);
+ nsCOMArray *deferredBindList =
+ NS_STATIC_CAST(nsCOMArray *,
+ doc->GetProperty(nsXFormsAtoms::deferredBindListProperty));
+
+ // if we've already gotten the xforms-model-construct-done event and not
+ // yet the xforms-ready, we've hit a window where we may still be
+ // processing the deferred control binding. If so, we'll leave now and
+ // leave it to MaybeNotifyCompletion to generate the xforms-ready event.
+ if (deferredBindList) {
+ return NS_OK;
+ }
+
+
+ // if we reached here, then we had to wait on sending out the xforms-ready
+ // events until the external messages were tested. Now we are finally
+ // ready to send out xforms-ready to all of the models.
+ for (int i = 0; i < models->Count(); ++i) {
+ nsXFormsModelElement *model =
+ NS_STATIC_CAST(nsXFormsModelElement *, models->ElementAt(i));
+ model->mReadyHandled = PR_TRUE;
+ nsXFormsUtils::DispatchEvent(model->mElement, eEvent_Ready);
+ }
+
+ return NS_OK;
+}
+
/* static */ void
nsXFormsModelElement::Startup()
{
@@ -1778,6 +2360,14 @@ nsXFormsModelElement::Startup()
sModelPropsList[eModel_p3ptype] = nsXFormsAtoms::p3ptype;
}
+already_AddRefed
+nsXFormsModelElement::GetDOMElement()
+{
+ nsIDOMElement* element = nsnull;
+ NS_IF_ADDREF(element = mElement);
+ return element;
+}
+
static void
DeleteBindList(void *aObject,
nsIAtom *aPropertyName,
@@ -1897,7 +2487,6 @@ nsXFormsModelElement::HandleLoad(nsIDOMEvent* aEvent)
if (IsComplete()) {
rv = FinishConstruction();
NS_ENSURE_SUCCESS(rv, rv);
- nsXFormsUtils::DispatchEvent(mElement, eEvent_Refresh);
}
mPendingInlineSchemas.Clear();
}
@@ -1954,7 +2543,7 @@ nsXFormsModelInstanceDocuments::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
nsIInstanceElementPrivate* instance = mInstanceList.SafeObjectAt(aIndex);
if (instance) {
nsCOMPtr doc;
- if (NS_SUCCEEDED(instance->GetDocument(getter_AddRefs(doc))) && doc) {
+ if (NS_SUCCEEDED(instance->GetInstanceDocument(getter_AddRefs(doc))) && doc) {
NS_ADDREF(*aReturn = doc);
}
}
@@ -1977,6 +2566,12 @@ nsXFormsModelInstanceDocuments::AddInstance(nsIInstanceElementPrivate *aInst)
mInstanceList.AppendObject(aInst);
}
+void
+nsXFormsModelInstanceDocuments::RemoveInstance(nsIInstanceElementPrivate *aInst)
+{
+ mInstanceList.RemoveObject(aInst);
+}
+
void
nsXFormsModelInstanceDocuments::DropReferences()
{
diff --git a/mozilla/extensions/xforms/nsXFormsModelElement.h b/mozilla/extensions/xforms/nsXFormsModelElement.h
index ec1041eb7c2..20d20847396 100644
--- a/mozilla/extensions/xforms/nsXFormsModelElement.h
+++ b/mozilla/extensions/xforms/nsXFormsModelElement.h
@@ -89,6 +89,13 @@ public:
*/
void AddInstance(nsIInstanceElementPrivate *aInstance);
+ /**
+ * Remove an instance element
+ *
+ * @param aInstance The instance element
+ */
+ void RemoveInstance(nsIInstanceElementPrivate *aInstance);
+
/**
* Get the instance document at a given index
*
@@ -109,6 +116,101 @@ protected:
nsCOMArray mInstanceList;
};
+/**
+ * A class for storing pointers to XForms controls added to an XForms
+ * model. Organized as a tree, with pointers to first child and next sibling.
+ *
+ * Notes:
+ * 1) The root node is special; only has children and a nsnull mNode.
+ * 2) All functions operate on the node they are called on, and its
+ * subtree. Functions will never go up (as in: nearer the root) in the tree.
+ */
+class nsXFormsControlListItem
+{
+ /** The XForms control itself */
+ nsCOMPtr mNode;
+
+ /** The next sibling of the node */
+ nsXFormsControlListItem *mNextSibling;
+
+ /** The first child of the node */
+ nsXFormsControlListItem *mFirstChild;
+
+public:
+ nsXFormsControlListItem(nsIXFormsControl* aControl);
+ ~nsXFormsControlListItem();
+ nsXFormsControlListItem(const nsXFormsControlListItem& aCopy);
+
+ /** Clear contents of current node, all siblings, and all children */
+ void Clear();
+
+ /**
+ * Remove a control from the current (sub-) tree. Will search from that node
+ * and down in the tree for the node.
+ *
+ * @param aControl The control to remove
+ * @param aRemoved Was the control found and removed?
+ */
+ nsresult RemoveControl(nsIXFormsControl *aControl, PRBool &aRemoved);
+
+ /**
+ * Add a control to the (sub-) tree as a child to the given |aParent|. If
+ * there is no |aParent|, it will insert it as a sibling to |this|. If
+ * |aParent| is not found, it will bail.
+ *
+ * @param aControl The control to insert
+ * @param aParent The (eventual) parent to insert it under
+ */
+ nsresult AddControl(nsIXFormsControl *aControl,
+ nsIXFormsControl *aParent);
+
+ /**
+ * Find a control in the (sub-) tree.
+ *
+ * @param aControl The control to find
+ */
+ nsXFormsControlListItem* FindControl(nsIXFormsControl *aControl);
+
+ /**
+ * Return the nsIXFormsControl that this node contains.
+ */
+ already_AddRefed Control();
+
+ /** Return the first child of the node */
+ nsXFormsControlListItem* FirstChild() { return mFirstChild; };
+
+ /** Return the next sibling of the node */
+ nsXFormsControlListItem* NextSibling() { return mNextSibling; };
+
+ /**
+ * An iterator implementation for the class.
+ */
+ class iterator
+ {
+ private:
+ /** The control the iterator is currently pointing at */
+ nsXFormsControlListItem *mCur;
+
+ /** A stack of non-visited nodes */
+ nsVoidArray mStack;
+
+ public:
+ iterator();
+ iterator(const iterator&);
+ iterator operator=(nsXFormsControlListItem*);
+ bool operator!=(const nsXFormsControlListItem*);
+ iterator operator++();
+ nsXFormsControlListItem* operator*();
+ };
+ friend class nsXFormsControlListItem::iterator;
+
+ /** The begining position for the node (itself) */
+ nsXFormsControlListItem* begin();
+
+ /** The end position for the node (nsnull) */
+ nsXFormsControlListItem* end();
+};
+
/**
* Implementation of the XForms \ element.
*
@@ -167,12 +269,17 @@ public:
static nsresult NeedsPostRefresh(nsIXFormsControl* aControl);
static void CancelPostRefresh(nsIXFormsControl* aControl);
+
+ /**
+ * Returns the DOM element for the model.
+ */
+ already_AddRefed GetDOMElement();
+
private:
NS_HIDDEN_(already_AddRefed)
FindInstanceDocument(const nsAString &aID);
NS_HIDDEN_(void) Reset();
- NS_HIDDEN_(void) Ready();
NS_HIDDEN_(void) BackupOrRestoreInstanceData(PRBool restore);
/** Initializes the MIPs on all form controls */
@@ -189,7 +296,8 @@ private:
nsIDOMNode *aContextNode,
PRInt32 aContextPosition,
PRInt32 aContextSize,
- nsIDOMElement *aBindElement);
+ nsIDOMElement *aBindElement,
+ PRBool aIsOuter = PR_FALSE);
NS_HIDDEN_(void) RemoveModelFromDocument();
@@ -205,7 +313,7 @@ private:
*/
NS_HIDDEN_(nsresult) SetStatesInternal(nsIXFormsControl *aControl,
nsIDOMNode *aNode,
- PRBool aAllStates = PR_FALSE);
+ PRBool aDispatchEvents = PR_TRUE);
/**
* Sets the state of a specific state.
@@ -240,10 +348,16 @@ private:
*/
NS_HIDDEN_(nsresult) HandleUnload(nsIDOMEvent *aEvent);
+ NS_HIDDEN_(nsresult) RefreshSubTree(nsXFormsControlListItem *aCurrent,
+ PRBool aForceRebind);
+
+ NS_HIDDEN_(nsresult) ValidateDocument(nsIDOMDocument *aInstanceDocument,
+ PRBool *aResult);
+
nsIDOMElement *mElement;
nsCOMPtr mSchemas;
nsStringArray mPendingInlineSchemas;
- nsVoidArray mFormControls;
+ nsXFormsControlListItem mFormControls;
PRInt32 mSchemaCount;
PRInt32 mSchemaTotal;
@@ -268,13 +382,18 @@ private:
// This flag indicates whether instance elements have been initialized
PRBool mInstancesInitialized;
+ /**
+ * Indicates whether the model has handled the xforms-ready event
+ */
+ PRBool mReadyHandled;
+
/**
* All instance documents contained by this model, including lazy-authored
* instance documents.
*/
nsRefPtr mInstanceDocuments;
- /** Indicates whether the model's instance was built by lazy authoring */
+ // Indicates whether the model's instance was built by lazy authoring
PRBool mLazyModel;
/**
@@ -291,6 +410,12 @@ private:
* @see http://www.w3.org/TR/xforms/slice6.html#model-prop-p3ptype
*/
nsClassHashtable mNodeToP3PType;
+
+ /**
+ * Indicates whether the model has handled the xforms-model-construct-done
+ * event
+ */
+ PRBool mConstructDoneHandled;
};
/**
diff --git a/mozilla/extensions/xforms/nsXFormsNodeState.cpp b/mozilla/extensions/xforms/nsXFormsNodeState.cpp
index 738a7ade28b..b523e797d58 100644
--- a/mozilla/extensions/xforms/nsXFormsNodeState.cpp
+++ b/mozilla/extensions/xforms/nsXFormsNodeState.cpp
@@ -38,6 +38,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsXFormsNodeState.h"
+#include "nsIEventStateManager.h"
void
nsXFormsNodeState::Set(PRUint16 aFlags, PRBool aVal)
@@ -70,27 +71,31 @@ nsXFormsNodeState::TestAndClear(eFlag_t aFlag)
return test ? PR_TRUE : PR_FALSE;
}
-PRBool
-nsXFormsNodeState::TestAndSet(eFlag_t aFlag)
-{
- PRUint16 test = mState & aFlag;
- mState |= aFlag;
- return test ? PR_TRUE : PR_FALSE;
-}
-
PRBool
nsXFormsNodeState::Test(eFlag_t aFlag) const
{
return (mState & aFlag) ? PR_TRUE : PR_FALSE;
}
+PRUint32
+nsXFormsNodeState::GetIntrinsicState() const
+{
+ PRUint32 state =
+ (IsValid() ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID) |
+ (IsReadonly() ? NS_EVENT_STATE_MOZ_READONLY
+ : NS_EVENT_STATE_MOZ_READWRITE) |
+ (IsRequired() ? NS_EVENT_STATE_REQUIRED : NS_EVENT_STATE_OPTIONAL) |
+ (IsRelevant() ? NS_EVENT_STATE_ENABLED : NS_EVENT_STATE_DISABLED);
+
+ return state;
+}
+
#ifdef DEBUG_XF_NODESTATE
const char* flagnames[] = {0,
"eFlag_READONLY",
"eFlag_CONSTRAINT",
"eFlag_RELEVANT",
"eFlag_REQUIRED",
- "eFlag_SCHEMA_VALID",
"eFlag_VALID",
"eFlag_INHERITED_RELEVANT",
"eFlag_INHERITED_READONLY",
diff --git a/mozilla/extensions/xforms/nsXFormsNodeState.h b/mozilla/extensions/xforms/nsXFormsNodeState.h
index 26387f248ce..94773e85991 100644
--- a/mozilla/extensions/xforms/nsXFormsNodeState.h
+++ b/mozilla/extensions/xforms/nsXFormsNodeState.h
@@ -54,16 +54,15 @@ enum eFlag_t {
eFlag_CONSTRAINT_SCHEMA = 1 << 3,
eFlag_RELEVANT = 1 << 4,
eFlag_REQUIRED = 1 << 5,
- eFlag_SCHEMA_VALID = 1 << 6,
- eFlag_INHERITED_RELEVANT = 1 << 7,
- eFlag_INHERITED_READONLY = 1 << 8,
+ eFlag_INHERITED_RELEVANT = 1 << 6,
+ eFlag_INHERITED_READONLY = 1 << 7,
// Events to be dispatched
- eFlag_DISPATCH_VALUE_CHANGED = 1 << 9,
- eFlag_DISPATCH_READONLY_CHANGED = 1 << 10,
- eFlag_DISPATCH_VALID_CHANGED = 1 << 11,
- eFlag_DISPATCH_RELEVANT_CHANGED = 1 << 12,
- eFlag_DISPATCH_REQUIRED_CHANGED = 1 << 13,
- eFlag_DISPATCH_CONSTRAINT_CHANGED = 1 << 14
+ eFlag_DISPATCH_VALUE_CHANGED = 1 << 8,
+ eFlag_DISPATCH_READONLY_CHANGED = 1 << 9,
+ eFlag_DISPATCH_VALID_CHANGED = 1 << 10,
+ eFlag_DISPATCH_RELEVANT_CHANGED = 1 << 11,
+ eFlag_DISPATCH_REQUIRED_CHANGED = 1 << 12,
+ eFlag_DISPATCH_CONSTRAINT_CHANGED = 1 << 13
};
// Default flags set for new states
@@ -147,14 +146,6 @@ public:
*/
PRBool TestAndClear(eFlag_t aFlag);
- /**
- * Get flag state and set flag.
- *
- * @param aFlag The flag
- * @return The flag state
- */
- PRBool TestAndSet(eFlag_t aFlag);
-
/**
* Get flag state
*
@@ -192,6 +183,8 @@ public:
PRBool ShouldDispatchValueChanged() const
{ return Test(eFlag_DISPATCH_VALUE_CHANGED); };
+ PRUint32 GetIntrinsicState() const;
+
#ifdef DEBUG_XF_NODESTATE
/** Print the flags currently set to stdout */
void PrintFlags() const;
diff --git a/mozilla/extensions/xforms/nsXFormsOutputElement.cpp b/mozilla/extensions/xforms/nsXFormsOutputElement.cpp
index 4800ec298e8..76a011bd131 100755
--- a/mozilla/extensions/xforms/nsXFormsOutputElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsOutputElement.cpp
@@ -61,6 +61,7 @@
#include "nsXFormsAtoms.h"
#include "nsXFormsUtils.h"
#include "nsIXFormsUIWidget.h"
+#include "nsXFormsModelElement.h"
/**
@@ -74,19 +75,26 @@ public:
// nsIXFormsControl
NS_IMETHOD Bind();
NS_IMETHOD Refresh();
+ NS_IMETHOD GetBoundNode(nsIDOMNode **aBoundNode);
// nsIXFormsDelegate
NS_IMETHOD GetValue(nsAString& aValue);
+ NS_IMETHOD GetHasBoundNode(PRBool *aHasBoundNode);
- nsXFormsOutputElement() :
- nsXFormsDelegateStub(NS_LITERAL_STRING("output")) {}
-
+ nsXFormsOutputElement();
private:
- PRBool mHasBinding;
- nsString mValue;
+ PRPackedBool mHasBinding;
+ PRPackedBool mValueIsDirty;
+ nsString mValue;
};
+nsXFormsOutputElement::nsXFormsOutputElement()
+ : nsXFormsDelegateStub(NS_LITERAL_STRING("output")),
+ mHasBinding(PR_FALSE), mValueIsDirty(PR_TRUE)
+{
+}
+
// nsIXFormsControl
nsresult
@@ -99,24 +107,39 @@ nsXFormsOutputElement::Bind()
if (!mHasParent)
return NS_OK;
-
- nsresult rv = mElement->HasAttribute(NS_LITERAL_STRING("ref"), &mHasBinding);
+
+ PRBool tmp;
+ nsresult rv = mElement->HasAttribute(NS_LITERAL_STRING("ref"), &tmp);
NS_ENSURE_SUCCESS(rv, rv);
+ mHasBinding = tmp;
if (!mHasBinding) {
- rv = mElement->HasAttribute(NS_LITERAL_STRING("bind"), &mHasBinding);
+ rv = mElement->HasAttribute(NS_LITERAL_STRING("bind"), &tmp);
NS_ENSURE_SUCCESS(rv, rv);
+ mHasBinding = tmp;
+
+ if (!mHasBinding) {
+ // If output only has a value attribute, it can't have a proper single
+ // node binding. In an effort to streamline this a bit, we'll just bind
+ // to the model here and add output to the deferred bind list if
+ // necessary. This should be all that we need from the services that
+ // ProcessNodeBinding provides. ProcessNodeBinding is called during
+ // ::Refresh (via GetValue) so we just need a few things set up before
+ // ::Refresh gets called (usually right after ::Bind)
+
+ nsCOMPtr domDoc;
+ mElement->GetOwnerDocument(getter_AddRefs(domDoc));
+ if (!nsXFormsUtils::IsDocumentReadyForBind(domDoc)) {
+ nsXFormsModelElement::DeferElementBind(domDoc, this);
+ }
+
+ return BindToModel(PR_TRUE);
+ }
}
nsCOMPtr result;
- if (mHasBinding) {
- rv = ProcessNodeBinding(NS_LITERAL_STRING("ref"),
- nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
- getter_AddRefs(result));
- } else {
- rv = ProcessNodeBinding(NS_LITERAL_STRING("value"),
- nsIDOMXPathResult::STRING_TYPE,
- getter_AddRefs(result));
- }
+ rv = ProcessNodeBinding(NS_LITERAL_STRING("ref"),
+ nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
+ getter_AddRefs(result));
if (NS_FAILED(rv)) {
nsXFormsUtils::ReportError(NS_LITERAL_STRING("controlBindError"), mElement);
@@ -124,7 +147,12 @@ nsXFormsOutputElement::Bind()
}
if (result) {
- result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
+ if (mUsesModelBinding) {
+ // When bound via @bind, we'll get a snapshot back
+ result->SnapshotItem(0, getter_AddRefs(mBoundNode));
+ } else {
+ result->GetSingleNodeValue(getter_AddRefs(mBoundNode));
+ }
}
if (mBoundNode && mModel) {
@@ -137,43 +165,49 @@ nsXFormsOutputElement::Bind()
NS_IMETHODIMP
nsXFormsOutputElement::Refresh()
{
- if (mRepeatState == eType_Template)
- return NS_OK;
+ mValueIsDirty = PR_TRUE;
+ return nsXFormsDelegateStub::Refresh();
+}
- nsresult rv = NS_OK;
- SetDOMStringToNull(mValue);
+NS_IMETHODIMP
+nsXFormsOutputElement::GetBoundNode(nsIDOMNode **aBoundNode)
+{
+ return mHasBinding ? nsXFormsDelegateStub::GetBoundNode(aBoundNode) : NS_OK;
+}
- if (mModel) {
- if (mHasBinding) {
- if (mBoundNode) {
- nsXFormsUtils::GetNodeValue(mBoundNode, mValue);
- }
- } else {
- nsCOMPtr result;
- rv = ProcessNodeBinding(NS_LITERAL_STRING("value"),
- nsIDOMXPathResult::STRING_TYPE,
- getter_AddRefs(result));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (result) {
- rv = result->GetStringValue(mValue);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
-
- SetMozTypeAttribute();
-
- nsCOMPtr widget = do_QueryInterface(mElement);
- if (widget)
- widget->Refresh();
-
- return rv;
+NS_IMETHODIMP
+nsXFormsOutputElement::GetHasBoundNode(PRBool *aHasBoundNode)
+{
+ NS_ENSURE_ARG_POINTER(aHasBoundNode);
+ *aHasBoundNode = (mBoundNode && mHasBinding) ? PR_TRUE : PR_FALSE;
+ return NS_OK;
}
NS_IMETHODIMP
nsXFormsOutputElement::GetValue(nsAString& aValue)
{
+ NS_ENSURE_STATE(mModel);
+
+ if (mValueIsDirty) {
+ if (mHasBinding) {
+ NS_ENSURE_STATE(mBoundNode);
+ nsXFormsUtils::GetNodeValue(mBoundNode, mValue);
+ } else {
+ nsCOMPtr result;
+ nsresult rv = ProcessNodeBinding(NS_LITERAL_STRING("value"),
+ nsIDOMXPathResult::STRING_TYPE,
+ getter_AddRefs(result));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (result) {
+ SetDOMStringToNull(mValue);
+ rv = result->GetStringValue(mValue);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ }
+ mValueIsDirty = PR_FALSE;
+ }
+
aValue = mValue;
return NS_OK;
}
diff --git a/mozilla/extensions/xforms/nsXFormsRangeAccessors.cpp b/mozilla/extensions/xforms/nsXFormsRangeAccessors.cpp
index abae6142851..dc0c046b143 100644
--- a/mozilla/extensions/xforms/nsXFormsRangeAccessors.cpp
+++ b/mozilla/extensions/xforms/nsXFormsRangeAccessors.cpp
@@ -95,8 +95,7 @@ nsXFormsRangeAccessors::GetRangeStep(nsAString &aStep)
static const nsIID sScriptingIIDs[] = {
NS_IXFORMSACCESSORS_IID,
- NS_IXFORMSRANGEACCESSORS_IID,
-
+ NS_IXFORMSRANGEACCESSORS_IID
};
NS_IMETHODIMP
diff --git a/mozilla/extensions/xforms/nsXFormsRangeAccessors.h b/mozilla/extensions/xforms/nsXFormsRangeAccessors.h
index 23ff0a7dca9..ceb22f36f45 100644
--- a/mozilla/extensions/xforms/nsXFormsRangeAccessors.h
+++ b/mozilla/extensions/xforms/nsXFormsRangeAccessors.h
@@ -45,8 +45,8 @@
*
* @todo Support out-of/in-range events (XXX)
*/
-class nsXFormsRangeAccessors : public nsIXFormsRangeAccessors,
- public nsXFormsAccessors
+class nsXFormsRangeAccessors : public nsXFormsAccessors,
+ public nsIXFormsRangeAccessors
{
public:
NS_DECL_ISUPPORTS_INHERITED
diff --git a/mozilla/extensions/xforms/nsXFormsRepeatElement.cpp b/mozilla/extensions/xforms/nsXFormsRepeatElement.cpp
index 0bcb54f7c40..ca2e92c0267 100644
--- a/mozilla/extensions/xforms/nsXFormsRepeatElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsRepeatElement.cpp
@@ -281,18 +281,15 @@ protected:
*/
nsresult CloneNode(nsIDOMNode *aSrc, nsIDOMNode **aTarget);
- /**
- * If this attribute name is bind, model or nodeset, then remove the repeat
- * control from the list of controls that the model keeps.
- */
- void MaybeRemoveFromModel(nsIAtom *aName);
+ PRBool IsBindingAttribute(const nsIAtom *aAttr) const;
/**
- * If this attribute name is bind, model or nodeset, then try to Bind and
- * Refresh to keep the repeat element current
+ * Make sure that an index value is inside the valid index range.
+ *
+ * @param aIndex The index value to sanitize
+ * @param aIsScroll Send scroll events if first or last index?
*/
- void MaybeBindAndRefresh(nsIAtom *aName);
-
+ void SanitizeIndex(PRUint32 *aIndex, PRBool aIsScroll = PR_FALSE);
public:
NS_DECL_ISUPPORTS_INHERITED
@@ -305,10 +302,6 @@ public:
// nsIXTFElement overrides
NS_IMETHOD OnDestroyed();
- NS_IMETHOD WillSetAttribute(nsIAtom *aName, const nsAString &aValue);
- NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue);
- NS_IMETHOD WillRemoveAttribute(nsIAtom *aName);
- NS_IMETHOD AttributeRemoved(nsIAtom *aName);
NS_IMETHOD BeginAddingChildren();
NS_IMETHOD DoneAddingChildren();
@@ -383,34 +376,6 @@ nsXFormsRepeatElement::OnDestroyed()
return nsXFormsControlStub::OnDestroyed();
}
-NS_IMETHODIMP
-nsXFormsRepeatElement::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
-{
- MaybeRemoveFromModel(aName);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXFormsRepeatElement::AttributeSet(nsIAtom *aName, const nsAString &aValue)
-{
- MaybeBindAndRefresh(aName);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXFormsRepeatElement::WillRemoveAttribute(nsIAtom *aName)
-{
- MaybeRemoveFromModel(aName);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXFormsRepeatElement::AttributeRemoved(nsIAtom *aName)
-{
- MaybeBindAndRefresh(aName);
- return NS_OK;
-}
-
NS_IMETHODIMP
nsXFormsRepeatElement::BeginAddingChildren()
{
@@ -445,32 +410,32 @@ nsXFormsRepeatElement::SetIndex(PRUint32 *aIndex,
// Set repeat-index
if (mIsParent) {
- NS_ASSERTION(mCurrentRepeat, "How can we be a repeat parent without a child?");
+ NS_ASSERTION(mCurrentRepeat,
+ "How can we be a repeat parent without a child?");
// We're the parent of nested repeats, set through the correct repeat
return mCurrentRepeat->SetIndex(aIndex, aIsRefresh);
}
// Do nothing if we are not showing anything
- if (mMaxIndex == 0)
+ if (mMaxIndex == 0) {
+ // 9.3.6 states that the index position becomes 0 if there are
+ // no elements in the repeat.
+ mCurrentIndex = 0;
+
+ // XXXbeaufour: handle scroll-first/last
return NS_OK;
+ }
if (aIsRefresh && !mCurrentIndex) {
// If we are refreshing, get existing index value from parent
- NS_ASSERTION(mParent, "SetIndex with aIsRefresh == PR_TRUE for a non-nested repeat?!");
+ NS_ASSERTION(mParent,
+ "SetIndex with aIsRefresh == PR_TRUE for a non-nested repeat?!");
rv = mParent->GetIndex(aIndex);
NS_ENSURE_SUCCESS(rv, rv);
}
// Check min. and max. value
- if (*aIndex < 1) {
- *aIndex = 1;
- if (!aIsRefresh)
- nsXFormsUtils::DispatchEvent(mElement, eEvent_ScrollFirst);
- } else if (*aIndex > mMaxIndex) {
- *aIndex = mMaxIndex;
- if (!aIsRefresh)
- nsXFormsUtils::DispatchEvent(mElement, eEvent_ScrollLast);
- }
+ SanitizeIndex(aIndex, PR_TRUE);
// Do nothing if setting to existing value
if (!aIsRefresh && mCurrentIndex && *aIndex == mCurrentIndex)
@@ -490,7 +455,9 @@ nsXFormsRepeatElement::SetIndex(PRUint32 *aIndex,
if (mCurrentIndex) {
// We had the previous selection, unset directly
SetChildIndex(mCurrentIndex, PR_FALSE, aIsRefresh);
- } if (mParent) {
+ }
+
+ if (mParent) {
// Selection is in another repeat, inform parent (it will inform the
// previous owner of its new state)
rv = mParent->SetCurrentRepeat(this, *aIndex);
@@ -534,17 +501,16 @@ nsXFormsRepeatElement::Deselect(void)
NS_IMETHODIMP
nsXFormsRepeatElement::GetStartingIndex(PRUint32 *aRes)
{
+ NS_ENSURE_ARG(aRes);
+
nsresult rv = GetIntAttr(NS_LITERAL_STRING("startindex"),
(PRInt32*) aRes,
nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER);
if (NS_FAILED(rv)) {
*aRes = 1;
}
- if (*aRes < 1) {
- *aRes = 1;
- } else if (*aRes > mMaxIndex) {
- *aRes = mMaxIndex;
- }
+ SanitizeIndex(aRes);
+
return NS_OK;
}
@@ -628,6 +594,7 @@ nsXFormsRepeatElement::IndexHasChanged()
NS_IMETHODIMP
nsXFormsRepeatElement::GetIsParent(PRBool *aIsParent)
{
+ NS_ENSURE_ARG(aIsParent);
*aIsParent = mIsParent;
return NS_OK;
}
@@ -674,6 +641,58 @@ nsXFormsRepeatElement::GetLevel(PRUint32 *aLevel)
return NS_OK;
}
+NS_IMETHODIMP
+nsXFormsRepeatElement::HandleNodeInsert(nsIDOMNode *aNode)
+{
+ NS_ENSURE_STATE(mHTMLElement);
+
+ nsCOMPtr node(do_QueryInterface(aNode));
+ NS_ENSURE_STATE(node);
+
+ // XXX, badness^2: If it is a insert we have to refresh before we can
+ // figure out whether the node is in our nodeset... refactor this so
+ // repeat actually gets the nodeset in Bind() and then uses it refresh,
+ // then we can "just" re-evaluate the nodeset, and only refresh if the
+ // node actually hits this repeat
+
+ // XXX, moreover it is also wrong to refresh at this point. It will happen
+ // in insert processing (and possibly deferred...)
+ nsresult rv = Refresh();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr child;
+ mHTMLElement->GetFirstChild(getter_AddRefs(child));
+
+ PRUint32 index = 1;
+ while (child) {
+ nsCOMPtr context(do_QueryInterface(child));
+ NS_ASSERTION(context,
+ "repeat child not implementing nsIXFormsContextControl?!");
+
+ nsAutoString modelID;
+ PRInt32 position, size;
+ nsCOMPtr boundNode;
+ rv = context->GetContext(modelID, getter_AddRefs(boundNode), &position,
+ &size);
+ NS_ENSURE_SUCCESS(rv, rv);
+ PRBool sameNode = PR_FALSE;
+ node->IsSameNode(boundNode, &sameNode);
+ if (sameNode) {
+ rv = SetIndex(&index, PR_FALSE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ break;
+ }
+
+ nsCOMPtr tmp;
+ child->GetNextSibling(getter_AddRefs(tmp));
+ child.swap(tmp);
+ ++index;
+ }
+
+ return NS_OK;
+}
+
// nsXFormsControl
NS_IMETHODIMP
@@ -682,11 +701,7 @@ nsXFormsRepeatElement::Bind()
if (mAddingChildren)
return NS_OK;
- mModel = nsXFormsUtils::GetModel(mElement);
- if (mModel)
- mModel->AddFormControl(this);
-
- return NS_OK;
+ return BindToModel();
}
NS_IMETHODIMP
@@ -717,7 +732,7 @@ nsXFormsRepeatElement::Refresh()
if (NS_FAILED(rv) | !result | !model)
return rv;
-
+
/// @todo The spec says: "This node-set must consist of contiguous child
/// element nodes, with the same local name and namespace name of a common
/// parent node. The behavior of element repeat with respect to
@@ -725,14 +740,14 @@ nsXFormsRepeatElement::Refresh()
/// @see http://www.w3.org/TR/xforms/slice9.html#ui-repeat
///
/// Can/should we check this somehow? (XXX)
-
+
PRUint32 contextSize;
rv = result->GetSnapshotLength(&contextSize);
NS_ENSURE_SUCCESS(rv, rv);
if (!contextSize)
return NS_OK;
-
+
// Get model ID
nsCOMPtr modelElement = do_QueryInterface(model);
NS_ENSURE_TRUE(modelElement, NS_ERROR_FAILURE);
@@ -748,15 +763,18 @@ nsXFormsRepeatElement::Refresh()
for (PRUint32 i = 1; i < mMaxIndex + 1; ++i) {
// Create
nsCOMPtr riElement;
- rv = domDoc->CreateElementNS(NS_LITERAL_STRING("http://www.w3.org/2002/xforms"),
+ rv = domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS),
NS_LITERAL_STRING("contextcontainer"),
getter_AddRefs(riElement));
NS_ENSURE_SUCCESS(rv, rv);
-
+
+ riElement->SetAttribute(NS_LITERAL_STRING("class"),
+ NS_LITERAL_STRING("xf-repeat-item"));
+
// Set model as attribute
if (!modelID.IsEmpty()) {
riElement->SetAttribute(NS_LITERAL_STRING("model"), modelID);
- }
+ }
// Get context node
nsCOMPtr riContext = do_QueryInterface(riElement);
@@ -765,7 +783,7 @@ nsXFormsRepeatElement::Refresh()
nsCOMPtr contextNode;
rv = result->SnapshotItem(i - 1, getter_AddRefs(contextNode));
NS_ENSURE_SUCCESS(rv, rv);
-
+
// Set context node, position, and size
rv = riContext->SetContext(contextNode, i, contextSize);
NS_ENSURE_SUCCESS(rv, rv);
@@ -776,7 +794,8 @@ nsXFormsRepeatElement::Refresh()
rv = mHTMLElement->AppendChild(riElement, getter_AddRefs(domNode));
NS_ENSURE_SUCCESS(rv, rv);
- // Iterate over template children, clone them, and append them to
+ // Iterate over template children, clone them, and append them to
+ // \
nsCOMPtr child;
rv = mElement->GetFirstChild(getter_AddRefs(child));
NS_ENSURE_SUCCESS(rv, rv);
@@ -786,18 +805,23 @@ nsXFormsRepeatElement::Refresh()
nsCOMPtr childClone;
rv = CloneNode(child, getter_AddRefs(childClone));
NS_ENSURE_SUCCESS(rv, rv);
-
+
nsCOMPtr newNode;
rv = riElement->AppendChild(childClone, getter_AddRefs(newNode));
NS_ENSURE_SUCCESS(rv, rv);
-
+
rv = child->GetNextSibling(getter_AddRefs(newNode));
NS_ENSURE_SUCCESS(rv, rv);
child = newNode;
}
}
- if (!mParent && !mCurrentIndex && mMaxIndex) {
+ if (mCurrentIndex) {
+ // somebody might have been fooling around with our children since last
+ // refresh (either using delete or through script, so check the index
+ // value
+ SanitizeIndex(&mCurrentIndex);
+ } else if (!mParent && mMaxIndex) {
// repeat-index has not been initialized, set it.
GetStartingIndex(&mCurrentIndex);
}
@@ -829,11 +853,14 @@ nsXFormsRepeatElement::SetChildIndex(PRUint32 aPosition,
mHTMLElement->GetChildNodes(getter_AddRefs(children));
NS_ENSURE_STATE(children);
+ PRUint32 index = aPosition - 1; // Indexes are 1-based, the DOM is 0-based;
+
nsCOMPtr child;
- children->Item(aPosition - 1, // Indexes are 1-based, the DOM is 0-based
+ children->Item(index,
getter_AddRefs(child));
- nsCOMPtr repeatItem = do_QueryInterface(child);
- NS_ENSURE_STATE(repeatItem);
+ nsCOMPtr repeatItem(do_QueryInterface(child));
+ NS_ASSERTION(repeatItem,
+ "repeat child not implementing nsIXFormsRepeatItemElement?!");
nsresult rv;
PRBool curState;
@@ -854,6 +881,23 @@ nsXFormsRepeatElement::SetChildIndex(PRUint32 aPosition,
return NS_OK;
}
+void
+nsXFormsRepeatElement::SanitizeIndex(PRUint32 *aIndex, PRBool aIsScroll)
+{
+ if (!aIndex)
+ return;
+
+ if (*aIndex < 1) {
+ *aIndex = 1;
+ if (aIsScroll)
+ nsXFormsUtils::DispatchEvent(mElement, eEvent_ScrollFirst);
+ } else if (*aIndex > mMaxIndex) {
+ *aIndex = mMaxIndex;
+ if (aIsScroll)
+ nsXFormsUtils::DispatchEvent(mElement, eEvent_ScrollLast);
+ }
+}
+
nsresult
nsXFormsRepeatElement::ResetInnerRepeats(nsIDOMNode *aNode,
PRBool aIsRefresh)
@@ -1055,29 +1099,18 @@ nsXFormsRepeatElement::GetIntAttr(const nsAString &aName,
return rv;
}
-void nsXFormsRepeatElement::MaybeBindAndRefresh(nsIAtom *aName)
+PRBool
+nsXFormsRepeatElement::IsBindingAttribute(const nsIAtom *aAttr) const
{
- if (aName == nsXFormsAtoms::bind ||
- aName == nsXFormsAtoms::nodeset ||
- aName == nsXFormsAtoms::model) {
-
- Bind();
- Refresh();
+ if (aAttr == nsXFormsAtoms::bind ||
+ aAttr == nsXFormsAtoms::nodeset ||
+ aAttr == nsXFormsAtoms::model) {
+ return PR_TRUE;
}
+
+ return PR_FALSE;
}
-void nsXFormsRepeatElement::MaybeRemoveFromModel(nsIAtom *aName)
-{
- if (aName == nsXFormsAtoms::bind ||
- aName == nsXFormsAtoms::nodeset ||
- aName == nsXFormsAtoms::model) {
- if (mModel) {
- mModel->RemoveFormControl(this);
- }
- }
-}
-
-
// Factory
NS_HIDDEN_(nsresult)
NS_NewXFormsRepeatElement(nsIXTFElement **aResult)
diff --git a/mozilla/extensions/xforms/nsXFormsSchemaValidator.cpp b/mozilla/extensions/xforms/nsXFormsSchemaValidator.cpp
index e03860b33b5..144fff24fcf 100644
--- a/mozilla/extensions/xforms/nsXFormsSchemaValidator.cpp
+++ b/mozilla/extensions/xforms/nsXFormsSchemaValidator.cpp
@@ -51,7 +51,7 @@
nsXFormsSchemaValidator::nsXFormsSchemaValidator()
{
- mSchemaValidator = do_GetService(NS_SCHEMAVALIDATOR_CONTRACTID);
+ mSchemaValidator = do_CreateInstance(NS_SCHEMAVALIDATOR_CONTRACTID);
}
nsresult
@@ -83,28 +83,12 @@ nsXFormsSchemaValidator::ValidateString(const nsAString & aValue,
}
PRBool
-nsXFormsSchemaValidator::ValidateNode(nsIDOMNode* aElement,
- const nsAString & aType,
- const nsAString & aNamespace)
+nsXFormsSchemaValidator::Validate(nsIDOMNode* aElement)
{
PRBool isValid = PR_FALSE;
NS_ENSURE_TRUE(mSchemaValidator, isValid);
- if (aNamespace.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
- // XXX: currently, we will only support validating a lone node. When
- // we get complex type support, we should load the schema for the xforms
- // types and use ValidateAgainstType like below.
- nsAutoString nodeValue;
- nsCOMPtr domNode3 = do_QueryInterface(aElement);
- domNode3->GetTextContent(nodeValue);
-
- isValid = ValidateString(nodeValue, aType, aNamespace);
- } else {
- nsCOMPtr type;
- if (GetType(aType, aNamespace, getter_AddRefs(type))) {
- mSchemaValidator->ValidateAgainstType(aElement, type, &isValid);
- }
- }
+ mSchemaValidator->Validate(aElement, &isValid);
return isValid;
}
diff --git a/mozilla/extensions/xforms/nsXFormsSchemaValidator.h b/mozilla/extensions/xforms/nsXFormsSchemaValidator.h
index b1ddf0ebfe3..aaebe121586 100644
--- a/mozilla/extensions/xforms/nsXFormsSchemaValidator.h
+++ b/mozilla/extensions/xforms/nsXFormsSchemaValidator.h
@@ -64,15 +64,12 @@ public:
const nsAString & aNamespace);
/**
- * Validates a node against a namespace and schema type
+ * Validates a node and its subtree against the loaded schema(s)
*
* @param aElement Node to validate
- * @param aType Type
- * @param aNamespace Namespace
* @return Whether the string is valid or not
*/
- PRBool ValidateNode(nsIDOMNode* aElement, const nsAString & aType,
- const nsAString & aNamespace);
+ PRBool Validate(nsIDOMNode* aElement);
/**
* Returns a nsISchemaType given an type and namespace
diff --git a/mozilla/extensions/xforms/nsXFormsSelectElement.cpp b/mozilla/extensions/xforms/nsXFormsSelectElement.cpp
index c7409ec949e..8820920c6d0 100644
--- a/mozilla/extensions/xforms/nsXFormsSelectElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsSelectElement.cpp
@@ -65,8 +65,6 @@ public:
NS_IMETHOD ChildAppended(nsIDOMNode *aChild);
NS_IMETHOD ChildRemoved(PRUint32 aIndex);
- // nsIXFormsDelegate
- NS_IMETHOD SetValue(const nsAString& aValue);
#ifdef DEBUG_smaug
virtual const char* Name() { return "select"; }
#endif
@@ -109,31 +107,6 @@ nsXFormsSelectElement::ChildRemoved(PRUint32 aIndex)
return NS_OK;
}
-NS_IMETHODIMP
-nsXFormsSelectElement::SetValue(const nsAString& aValue)
-{
- if (!mBoundNode || !mModel)
- return NS_OK;
-
- PRBool changed;
- nsresult rv = mModel->SetNodeValue(mBoundNode, aValue, &changed);
- NS_ENSURE_SUCCESS(rv, rv);
- if (changed) {
- nsCOMPtr model = do_QueryInterface(mModel);
-
- if (model) {
- rv = nsXFormsUtils::DispatchEvent(model, eEvent_Recalculate);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = nsXFormsUtils::DispatchEvent(model, eEvent_Revalidate);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = nsXFormsUtils::DispatchEvent(model, eEvent_Refresh);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- return NS_OK;
-}
-
NS_HIDDEN_(nsresult)
NS_NewXFormsSelectElement(nsIXTFElement **aResult)
{
diff --git a/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp b/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp
index 11e3e991bbd..5075fc5fa39 100644
--- a/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp
@@ -91,13 +91,15 @@ nsXFormsSetIndexElement::HandleAction(nsIDOMEvent *aEvent,
nsCOMPtr result;
// EvaluateNodeBinding uses @bind if @index is not present, but we have
// checked that @index is present above
+ PRBool usesModelBinding;
rv = nsXFormsUtils::EvaluateNodeBinding(mElement,
0,
indexStr,
EmptyString(),
nsIDOMXPathResult::NUMBER_TYPE,
getter_AddRefs(model),
- getter_AddRefs(result));
+ getter_AddRefs(result),
+ &usesModelBinding);
NS_ENSURE_SUCCESS(rv, rv);
if (!result) {
nsXFormsUtils::ReportError(NS_LITERAL_STRING("indexEvalError"),
@@ -116,7 +118,7 @@ nsXFormsSetIndexElement::HandleAction(nsIDOMEvent *aEvent,
#ifdef DEBUG_XF_SETINDEX
printf(": Setting index '%s' to '%d'\n",
- NS_ConvertUCS2toUTF8(id).get(),
+ NS_ConvertUTF16toUTF8(id).get(),
indexInt);
#endif
nsCOMPtr repeatElem;
diff --git a/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp b/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp
index b1733fd811a..39582adb5a2 100644
--- a/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp
@@ -66,23 +66,13 @@ nsXFormsSetValueElement::HandleAction(nsIDOMEvent* aEvent,
return NS_OK;
nsCOMPtr modelPriv;
- nsCOMPtr result;
- nsresult rv =
- nsXFormsUtils:: EvaluateNodeBinding(mElement,
- nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
- NS_LITERAL_STRING("ref"),
- EmptyString(),
- nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
- getter_AddRefs(modelPriv),
- getter_AddRefs(result));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!result | !modelPriv)
- return NS_OK;
-
nsCOMPtr singleNode;
- result->GetSingleNodeValue(getter_AddRefs(singleNode));
- if (!singleNode)
+ PRBool succeeded =
+ nsXFormsUtils::GetSingleNodeBinding(mElement,
+ getter_AddRefs(singleNode),
+ getter_AddRefs(modelPriv));
+
+ if (!succeeded | !modelPriv | !singleNode)
return NS_OK;
nsAutoString value;
@@ -105,7 +95,8 @@ nsXFormsSetValueElement::HandleAction(nsIDOMEvent* aEvent,
}
PRBool changed;
- rv = modelPriv->SetNodeValue(singleNode, value, &changed);
+ nsresult rv =
+ modelPriv->SetNodeValue(singleNode, value, &changed);
NS_ENSURE_SUCCESS(rv, rv);
if (changed) {
diff --git a/mozilla/extensions/xforms/nsXFormsSubmissionElement.cpp b/mozilla/extensions/xforms/nsXFormsSubmissionElement.cpp
index d4dae50af42..b497c45ec06 100644
--- a/mozilla/extensions/xforms/nsXFormsSubmissionElement.cpp
+++ b/mozilla/extensions/xforms/nsXFormsSubmissionElement.cpp
@@ -67,8 +67,8 @@
#include "nsIDOMProcessingInstruction.h"
#include "nsIDOMParser.h"
#include "nsComponentManagerUtils.h"
+#include "nsStringStream.h"
#include "nsIDocShell.h"
-#include "nsIStringStream.h"
#include "nsIInputStream.h"
#include "nsIStorageStream.h"
#include "nsIMultiplexInputStream.h"
@@ -515,48 +515,48 @@ nsXFormsSubmissionElement::LoadReplaceInstance(nsIChannel *channel)
nsCOMPtr instanceElement;
nsAutoString value;
mElement->GetAttribute(NS_LITERAL_STRING("instance"), value);
- if (!value.IsEmpty()){
+ if (!value.IsEmpty()) {
rv = GetSelectedInstanceElement(value, model,
getter_AddRefs(instanceElement));
} else {
nsCOMPtr data;
rv = GetBoundInstanceData(getter_AddRefs(data));
- if (NS_SUCCEEDED(rv)) {
- nsCOMPtr instanceNode;
- rv = nsXFormsUtils::GetInstanceNodeForData(data,
- getter_AddRefs(instanceNode));
- NS_ENSURE_SUCCESS(rv, rv);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr instanceNode;
+ rv = nsXFormsUtils::GetInstanceNodeForData(data,
+ getter_AddRefs(instanceNode));
+ NS_ENSURE_SUCCESS(rv, rv);
instanceElement = do_QueryInterface(instanceNode);
}
}
- // replace the document referenced by this instance element with the info
- // returned back from the submission
+ // replace the document referenced by this instance element with the info
+ // returned back from the submission
if (NS_SUCCEEDED(rv) && instanceElement) {
- instanceElement->SetDocument(newDoc);
+ instanceElement->SetInstanceDocument(newDoc);
- // refresh everything
- model->Rebuild();
- model->Recalculate();
- model->Revalidate();
- model->Refresh();
- }
+ // refresh everything
+ model->Rebuild();
+ model->Recalculate();
+ model->Revalidate();
+ model->Refresh();
+ }
return NS_OK;
- }
+}
nsresult
nsXFormsSubmissionElement::GetSelectedInstanceElement(
- const nsString &aInstanceID,
+ const nsAString &aInstanceID,
nsIModelElementPrivate *aModel,
nsIInstanceElementPrivate **aResult)
{
aModel->FindInstanceElement(aInstanceID, aResult);
if (*aResult == nsnull) {
// if failed to get desired instance, dispatch binding exception
- const PRUnichar *strings[] = { aInstanceID.get() };
+ const PRUnichar *strings[] = { PromiseFlatString(aInstanceID).get() };
nsXFormsUtils::ReportError(NS_LITERAL_STRING("instanceBindError"),
strings, 1, mElement, mElement);
nsXFormsUtils::DispatchEvent(mElement, eEvent_BindingException);
@@ -636,8 +636,7 @@ nsXFormsSubmissionElement::Submit()
// 3. revalidate selected instance data (only for namespaces considered for
// serialization)
- // XXX call nsISchemaValidator::validate on each node
-
+ // This is handled by the SerializeData() method
// 4. serialize instance data
// Checking the format only before starting the submission.
@@ -663,18 +662,21 @@ nsXFormsSubmissionElement::GetBoundInstanceData(nsIDOMNode **result)
{
nsCOMPtr model;
nsCOMPtr xpRes;
+ PRBool usesModelBind;
nsresult rv =
nsXFormsUtils::EvaluateNodeBinding(mElement, 0,
NS_LITERAL_STRING("ref"),
NS_LITERAL_STRING("/"),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(model),
- getter_AddRefs(xpRes));
+ getter_AddRefs(xpRes),
+ &usesModelBind);
if (NS_FAILED(rv) || !xpRes)
return NS_ERROR_UNEXPECTED;
- return xpRes->GetSingleNodeValue(result);
+ return usesModelBind ? xpRes->SnapshotItem(0, result)
+ : xpRes->GetSingleNodeValue(result);
}
PRBool
@@ -751,6 +753,13 @@ nsXFormsSubmissionElement::SerializeData(nsIDOMNode *data,
if (mFormat & ENCODING_XML)
return SerializeDataXML(data, stream, contentType, nsnull);
+ // Ensure the data is valid and required nodes are non-empty
+ // This is handled directly within SerializeDataXML()
+ nsCOMPtr model = GetModel();
+ NS_ENSURE_STATE(model);
+ nsresult rv = CanSubmit(data, model, PR_FALSE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
if (mFormat & ENCODING_URL)
return SerializeDataURLEncoded(data, uri, stream, contentType);
@@ -792,49 +801,35 @@ nsXFormsSubmissionElement::SerializeDataXML(nsIDOMNode *data,
nsCOMPtr serializer =
do_GetService("@mozilla.org/xmlextras/xmlserializer;1");
- NS_ENSURE_TRUE(serializer, NS_ERROR_UNEXPECTED);
+ NS_ENSURE_STATE(serializer);
- nsCOMPtr doc, newDoc;
- data->GetOwnerDocument(getter_AddRefs(doc));
+ nsCOMPtr instDoc, submDoc;
+ data->GetOwnerDocument(getter_AddRefs(instDoc));
- nsresult rv;
// XXX: We can't simply pass in data if !doc, since it crashes
- if (!doc) {
+ nsresult rv;
+ if (!instDoc) {
// owner doc is null when the data node is the document (e.g., ref="/")
// so we can just get the document via QI.
- doc = do_QueryInterface(data);
- NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
+ instDoc = do_QueryInterface(data);
+ NS_ENSURE_STATE(instDoc);
- rv = CreateSubmissionDoc(doc, encoding, attachments,
- getter_AddRefs(newDoc));
+ rv = CreateSubmissionDoc(instDoc, encoding, attachments,
+ getter_AddRefs(submDoc));
} else {
// if we got a document, we need to create a new
rv = CreateSubmissionDoc(data, encoding, attachments,
- getter_AddRefs(newDoc));
+ getter_AddRefs(submDoc));
}
// clone and possibly modify the document for submission
NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(newDoc, NS_ERROR_UNEXPECTED);
+ NS_ENSURE_STATE(submDoc);
// We now need to add namespaces to the submission document. We get them
// from 3 sources - the main document's documentElement, the model and the
// xforms:instance that contains the submitted instance data node.
- // first handle the main document
- nsCOMPtr mainDoc;
- mElement->GetOwnerDocument(getter_AddRefs(mainDoc));
- NS_ENSURE_TRUE(mainDoc, NS_ERROR_UNEXPECTED);
-
- nsCOMPtr docElm;
- mainDoc->GetDocumentElement(getter_AddRefs(docElm));
- nsCOMPtr node(do_QueryInterface(docElm));
- NS_ENSURE_TRUE(node, NS_ERROR_UNEXPECTED);
-
- // get the document element of the document we are going to submit
- nsCOMPtr newDocElm;
- newDoc->GetDocumentElement(getter_AddRefs(newDocElm));
-
nsCOMPtr instanceNode;
rv = nsXFormsUtils::GetInstanceNodeForData(data, getter_AddRefs(instanceNode));
NS_ENSURE_SUCCESS(rv, rv);
@@ -864,24 +859,54 @@ nsXFormsSubmissionElement::SerializeDataXML(nsIDOMNode *data,
NS_ENSURE_SUCCESS(rv, rv);
}
- // handle namespace on main document
- rv = AddNameSpaces(newDocElm, node, prefixHash);
+ // get the document element of the document we are going to submit
+ nsCOMPtr submDocElm;
+ submDoc->GetDocumentElement(getter_AddRefs(submDocElm));
+ NS_ENSURE_STATE(submDocElm);
+
+ // if submission document has empty default namespace attribute and if
+ // @includenamespaceprefixes attribute doesn't contain "#default" value then
+ // we should remove default namespace attribute (see the specs 11.3).
+ nsAutoString XMLNSAttrValue;
+ submDocElm->GetAttributeNS(kXMLNSNameSpaceURI, NS_LITERAL_STRING("xmlns"),
+ XMLNSAttrValue);
+
+ if (XMLNSAttrValue.IsEmpty() && (!prefixHash ||
+ !prefixHash->Contains(NS_LITERAL_STRING("#default")))) {
+ submDocElm->RemoveAttributeNS(kXMLNSNameSpaceURI,
+ NS_LITERAL_STRING("xmlns"));
+ }
+
+ // handle namespaces on the root element of the instance document
+ nsCOMPtr instDocElm;
+ instDoc->GetDocumentElement(getter_AddRefs(instDocElm));
+ nsCOMPtr instDocNode(do_QueryInterface(instDocElm));
+ NS_ENSURE_STATE(instDocNode);
+ rv = AddNameSpaces(submDocElm, instDocNode, prefixHash);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // handle namespaces on the xforms:instance
+ rv = AddNameSpaces(submDocElm, instanceNode, prefixHash);
NS_ENSURE_SUCCESS(rv, rv);
// handle namespaces on the model
nsCOMPtr model = GetModel();
- node = do_QueryInterface(model);
- NS_ENSURE_STATE(node);
- rv = AddNameSpaces(newDocElm, node, prefixHash);
+ nsCOMPtr modelNode(do_QueryInterface(model));
+ NS_ENSURE_STATE(modelNode);
+ rv = AddNameSpaces(submDocElm, modelNode, prefixHash);
NS_ENSURE_SUCCESS(rv, rv);
- // handle namespaces on the xforms:instance
- rv = AddNameSpaces(newDocElm, instanceNode, prefixHash);
- NS_ENSURE_SUCCESS(rv, rv);
+ // handle namespace on main document
+ nsCOMPtr mainDoc;
+ mElement->GetOwnerDocument(getter_AddRefs(mainDoc));
+ NS_ENSURE_STATE(mainDoc);
- // handle namespaces on the root element of the instance document
- doc->GetDocumentElement(getter_AddRefs(docElm));
- rv = AddNameSpaces(newDocElm, docElm, prefixHash);
+ nsCOMPtr mainDocElm;
+ mainDoc->GetDocumentElement(getter_AddRefs(mainDocElm));
+ nsCOMPtr mainDocNode(do_QueryInterface(mainDocElm));
+ NS_ENSURE_STATE(mainDocNode);
+
+ rv = AddNameSpaces(submDocElm, mainDocNode, prefixHash);
NS_ENSURE_SUCCESS(rv, rv);
if (prefixHash)
@@ -889,7 +914,7 @@ nsXFormsSubmissionElement::SerializeDataXML(nsIDOMNode *data,
}
// Serialize content
- rv = serializer->SerializeToStream(newDoc, sink,
+ rv = serializer->SerializeToStream(submDoc, sink,
NS_LossyConvertUTF16toASCII(encoding));
NS_ENSURE_SUCCESS(rv, rv);
@@ -991,10 +1016,10 @@ nsXFormsSubmissionElement::AddNameSpaces(nsIDOMElement* aTarget,
{
nsCOMPtr attrMap;
nsCOMPtr attrNode;
- nsAutoString nsURI, localName, value, attrName;
+ nsAutoString nsURI, localName, value;
aSource->GetAttributes(getter_AddRefs(attrMap));
- NS_ENSURE_TRUE(attrMap, NS_ERROR_UNEXPECTED);
+ NS_ENSURE_STATE(attrMap);
PRUint32 length;
attrMap->GetLength(&length);
@@ -1007,18 +1032,26 @@ nsXFormsSubmissionElement::AddNameSpaces(nsIDOMElement* aTarget,
attrNode->GetLocalName(localName);
attrNode->GetNodeValue(value);
- attrName.AssignLiteral("xmlns");
- // xmlns:foo, not xmlns=
if (!localName.EqualsLiteral("xmlns")) {
- // If "includenamespaceprefixes" attribute is present, don't add
- // namespace unless it appears in hash
- if (aPrefixHash && !aPrefixHash->Contains(localName))
- continue;
- attrName.AppendLiteral(":");
- attrName.Append(localName);
- }
+ if (!aPrefixHash || aPrefixHash->Contains(localName)) {
+ nsAutoString attrName(NS_LITERAL_STRING("xmlns:"));
+ attrName.Append(localName);
+ aTarget->SetAttributeNS(kXMLNSNameSpaceURI, attrName, value);
+ }
+ } else if (!value.IsEmpty()) {
+ PRBool hasDefaultNSAttr;
+ aTarget->HasAttributeNS(kXMLNSNameSpaceURI,
+ NS_LITERAL_STRING("xmlns"), &hasDefaultNSAttr);
- aTarget->SetAttribute(attrName, value);
+ if (!hasDefaultNSAttr) {
+ aTarget->GetNamespaceURI(nsURI);
+ if (!nsURI.IsEmpty()) {
+ // if aTarget default namespace uri isn't empty and it hasn't
+ // default namespace attribute then we should add it.
+ aTarget->SetAttributeNS(kXMLNSNameSpaceURI, localName, value);
+ }
+ }
+ }
}
}
@@ -1097,12 +1130,12 @@ nsXFormsSubmissionElement::CreateSubmissionDoc(nsIDOMNode *source,
source->GetOwnerDocument(getter_AddRefs(tmpDoc));
tmpDoc->GetImplementation(getter_AddRefs(impl));
}
- NS_ENSURE_TRUE(impl, NS_ERROR_UNEXPECTED);
+ NS_ENSURE_STATE(impl);
nsCOMPtr doc;
impl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(doc));
- NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
+ NS_ENSURE_STATE(doc);
if (!omit_xml_declaration)
{
@@ -1129,8 +1162,10 @@ nsXFormsSubmissionElement::CreateSubmissionDoc(nsIDOMNode *source,
startNode = source;
}
- nsresult rv = CopyChildren(startNode, doc, doc, attachments, cdataElements,
- indent, 0);
+ nsCOMPtr model = GetModel();
+ NS_ENSURE_STATE(model);
+ nsresult rv = CopyChildren(model, startNode, doc, doc, attachments,
+ cdataElements, indent, 0);
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*result = doc);
@@ -1138,14 +1173,14 @@ nsXFormsSubmissionElement::CreateSubmissionDoc(nsIDOMNode *source,
}
nsresult
-nsXFormsSubmissionElement::CopyChildren(nsIDOMNode *source, nsIDOMNode *dest,
+nsXFormsSubmissionElement::CopyChildren(nsIModelElementPrivate* model,
+ nsIDOMNode *source, nsIDOMNode *dest,
nsIDOMDocument *destDoc,
SubmissionAttachmentArray *attachments,
const nsString &cdataElements,
PRBool indent, PRUint32 depth)
{
nsCOMPtr currentNode(source), node, destChild;
- nsCOMPtr model = GetModel();
while (currentNode)
{
@@ -1156,14 +1191,14 @@ nsXFormsSubmissionElement::CopyChildren(nsIDOMNode *source, nsIDOMNode *dest,
// (remains to be determined) reference external entities.
destDoc->ImportNode(currentNode, PR_FALSE, getter_AddRefs(destChild));
- NS_ENSURE_TRUE(destChild, NS_ERROR_UNEXPECTED);
+ NS_ENSURE_STATE(destChild);
PRUint16 type;
destChild->GetNodeType(&type);
if (type == nsIDOMNode::PROCESSING_INSTRUCTION_NODE)
{
nsCOMPtr pi = do_QueryInterface(destChild);
- NS_ENSURE_TRUE(pi, NS_ERROR_UNEXPECTED);
+ NS_ENSURE_STATE(pi);
// ignore "" since we would have already inserted this.
@@ -1256,7 +1291,7 @@ nsXFormsSubmissionElement::CopyChildren(nsIDOMNode *source, nsIDOMNode *dest,
nsCOMPtr text;
destDoc->CreateTextNode(cidURI, getter_AddRefs(text));
- NS_ENSURE_TRUE(text, NS_ERROR_UNEXPECTED);
+ NS_ENSURE_STATE(text);
destChild->AppendChild(text, getter_AddRefs(node));
dest->AppendChild(destChild, getter_AddRefs(node));
@@ -1271,18 +1306,73 @@ nsXFormsSubmissionElement::CopyChildren(nsIDOMNode *source, nsIDOMNode *dest,
nsCOMPtr startNode;
currentNode->GetFirstChild(getter_AddRefs(startNode));
- nsresult rv = CopyChildren(startNode, destChild, destDoc, attachments,
- cdataElements, indent, depth + 1);
+ nsresult rv = CopyChildren(model, startNode, destChild, destDoc,
+ attachments, cdataElements, indent,
+ depth + 1);
NS_ENSURE_SUCCESS(rv, rv);
}
}
+ if (!depth) {
+ break;
+ }
+
currentNode->GetNextSibling(getter_AddRefs(node));
currentNode.swap(node);
}
return NS_OK;
}
+nsresult
+nsXFormsSubmissionElement::CanSubmit(nsIDOMNode *aTopNode,
+ nsIModelElementPrivate *aModel,
+ PRBool aCheckSiblings)
+{
+ nsCOMPtr currentNode(aTopNode), node;
+
+ while (currentNode) {
+ PRUint16 handleNodeResult;
+ aModel->HandleInstanceDataNode(currentNode, &handleNodeResult);
+
+ /*
+ * SUBMIT_SERIALIZE_NODE - node is to be serialized
+ * SUBMIT_SKIP_NODE - node is not to be serialized
+ * SUBMIT_ABORT_SUBMISSION - abort submission
+ * (invalid node or empty required node)
+ */
+ if (handleNodeResult == nsIModelElementPrivate::SUBMIT_SKIP_NODE) {
+ // skip node and subtree
+ currentNode->GetNextSibling(getter_AddRefs(node));
+ currentNode.swap(node);
+ continue;
+ } else if (handleNodeResult ==
+ nsIModelElementPrivate::SUBMIT_ABORT_SUBMISSION) {
+
+ // abort
+ return NS_ERROR_ABORT;
+ }
+ NS_ASSERTION(
+ handleNodeResult == nsIModelElementPrivate::SUBMIT_SERIALIZE_NODE,
+ "unexpected node type");
+
+ // recurse
+ nsCOMPtr firstChild;
+ currentNode->GetFirstChild(getter_AddRefs(firstChild));
+
+ nsresult rv = CanSubmit(firstChild, aModel);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!aCheckSiblings) {
+ break;
+ }
+
+ currentNode->GetNextSibling(getter_AddRefs(node));
+ currentNode.swap(node);
+ }
+
+ return NS_OK;
+}
+
nsresult
nsXFormsSubmissionElement::SerializeDataURLEncoded(nsIDOMNode *data,
nsCString &uri,
@@ -1331,7 +1421,7 @@ nsXFormsSubmissionElement::SerializeDataURLEncoded(nsIDOMNode *data,
// make new stream
NS_NewCStringInputStream(stream, buf);
- NS_ENSURE_TRUE(*stream, NS_ERROR_UNEXPECTED);
+ NS_ENSURE_STATE(*stream);
contentType.AssignLiteral("application/x-www-form-urlencoded");
}
@@ -1431,7 +1521,7 @@ nsXFormsSubmissionElement::SerializeDataMultipartRelated(nsIDOMNode *data,
nsCOMPtr