[XForms] Some controls should not be allowed to bind to complexContent. Bug 356190, patch by msterlin, r=olli+aaronr
git-svn-id: svn://10.0.0.236/trunk@218683 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -183,12 +183,31 @@ nsXFormsControlStub::ResetBoundNode(const nsString &aBindAttribute,
|
||||
|
||||
*aContextChanged = (oldBoundNode != mBoundNode);
|
||||
|
||||
if (!mBoundNode) {
|
||||
// Some controls may not be bound to certain types of content. If the content
|
||||
// is a disallowed type, report the error and dispatch a binding exception
|
||||
// event.
|
||||
PRBool isAllowed = PR_TRUE;
|
||||
IsContentAllowed(&isAllowed);
|
||||
|
||||
if (!mBoundNode || !isAllowed) {
|
||||
// If there's no result (ie, no instance node) returned by the above, it
|
||||
// means that the binding is not pointing to an instance data node, so we
|
||||
// should disable the control.
|
||||
mAppearDisabled = PR_TRUE;
|
||||
|
||||
if (!isAllowed) {
|
||||
// build the error string that we want output to the ErrorConsole
|
||||
nsAutoString localName;
|
||||
mElement->GetLocalName(localName);
|
||||
const PRUnichar *strings[] = { localName.get() };
|
||||
|
||||
nsXFormsUtils::ReportError(
|
||||
NS_LITERAL_STRING("boundTypeErrorComplexContent"),
|
||||
strings, 1, mElement, mElement);
|
||||
|
||||
nsXFormsUtils::DispatchEvent(mElement, eEvent_BindingException);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXTFElementWrapper> wrapper(do_QueryInterface(mElement));
|
||||
NS_ENSURE_STATE(wrapper);
|
||||
|
||||
@@ -817,6 +836,39 @@ nsXFormsControlStub::GetBoundBuiltinType(PRUint16 *aBuiltinType)
|
||||
return mModel->GetRootBuiltinType(schemaType, aBuiltinType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsControlStub::IsContentAllowed(PRBool *aIsAllowed)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsAllowed);
|
||||
*aIsAllowed = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsControlStub::IsContentComplex(PRBool *aIsComplex)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsComplex);
|
||||
*aIsComplex = PR_FALSE;
|
||||
|
||||
if (mBoundNode) {
|
||||
// If the bound node has any Element children, then it has complexContent.
|
||||
nsCOMPtr<nsIDOMNode> currentNode;
|
||||
mBoundNode->GetFirstChild(getter_AddRefs(currentNode));
|
||||
while (currentNode) {
|
||||
PRUint16 nodeType;
|
||||
currentNode->GetNodeType(&nodeType);
|
||||
if (nodeType == nsIDOMNode::ELEMENT_NODE) {
|
||||
*aIsComplex = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
currentNode->GetNextSibling(getter_AddRefs(node));
|
||||
currentNode.swap(node);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED3(nsXFormsControlStub,
|
||||
nsXFormsStubElement,
|
||||
|
||||
@@ -129,6 +129,24 @@ public:
|
||||
*/
|
||||
void AddRemoveSNBAttr(nsIAtom *aName, const nsAString &aValue);
|
||||
|
||||
/**
|
||||
* This function is overridden by controls that are restricted in the
|
||||
* type of content that may be bound to the control. For example,
|
||||
* xf:input may only be bound to simpleContent.
|
||||
*
|
||||
* @param aIsAllowed Indicates whether the control is allowed to bind
|
||||
* to the content type.
|
||||
*/
|
||||
NS_IMETHOD IsContentAllowed(PRBool *aIsAllowed);
|
||||
|
||||
/**
|
||||
* This function determines if the content to which the control is being
|
||||
* bound is complex; ie contains Element children.
|
||||
*
|
||||
* @param aIsComplex Indicates whether the content is complex.
|
||||
*/
|
||||
NS_IMETHOD IsContentComplex(PRBool *aIsComplex);
|
||||
|
||||
// nsIXFormsContextControl
|
||||
NS_DECL_NSIXFORMSCONTEXTCONTROL
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ public:
|
||||
nsRestrictionFlag *aRestriction,
|
||||
nsAString &aUnallowedTypes);
|
||||
|
||||
NS_IMETHOD IsContentAllowed(PRBool *aIsAllowed);
|
||||
|
||||
nsXFormsInputElement(const nsAString& aType)
|
||||
: nsXFormsDelegateStub(aType)
|
||||
{}
|
||||
@@ -79,6 +81,22 @@ nsXFormsInputElement::IsTypeAllowed(PRUint16 aType, PRBool *aIsAllowed,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::IsContentAllowed(PRBool *aIsAllowed)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsAllowed);
|
||||
*aIsAllowed = PR_TRUE;
|
||||
|
||||
|
||||
// For input and secret elements, complexContent is not allowed.
|
||||
PRBool isComplex = PR_FALSE;
|
||||
IsContentComplex(&isComplex);
|
||||
if (isComplex) {
|
||||
*aIsAllowed = PR_FALSE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsXFormsTextareaElement : public nsXFormsDelegateStub
|
||||
{
|
||||
public:
|
||||
@@ -87,6 +105,8 @@ public:
|
||||
nsRestrictionFlag *aRestriction,
|
||||
nsAString &aAllowedTypes);
|
||||
|
||||
NS_IMETHOD IsContentAllowed(PRBool *aIsAllowed);
|
||||
|
||||
nsXFormsTextareaElement()
|
||||
: nsXFormsDelegateStub(NS_LITERAL_STRING("textarea"))
|
||||
{}
|
||||
@@ -115,6 +135,21 @@ nsXFormsTextareaElement::IsTypeAllowed(PRUint16 aType, PRBool *aIsAllowed,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsTextareaElement::IsContentAllowed(PRBool *aIsAllowed)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsAllowed);
|
||||
*aIsAllowed = PR_TRUE;
|
||||
|
||||
// Textareas may not be bound to complexContent.
|
||||
PRBool isComplex = PR_FALSE;
|
||||
IsContentComplex(&isComplex);
|
||||
if (isComplex) {
|
||||
*aIsAllowed = PR_FALSE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Creators
|
||||
|
||||
NS_HIDDEN_(nsresult)
|
||||
|
||||
@@ -84,6 +84,8 @@ public:
|
||||
NS_IMETHOD SetValue(const nsAString& aValue);
|
||||
NS_IMETHOD GetHasBoundNode(PRBool *aHasBoundNode);
|
||||
|
||||
NS_IMETHOD IsContentAllowed(PRBool *aIsAllowed);
|
||||
|
||||
nsXFormsOutputElement();
|
||||
|
||||
private:
|
||||
@@ -197,6 +199,21 @@ nsXFormsOutputElement::SetValue(const nsAString& aValue)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsOutputElement::IsContentAllowed(PRBool *aIsAllowed)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsAllowed);
|
||||
*aIsAllowed = PR_TRUE;
|
||||
|
||||
// Output may not be bound to complexContent.
|
||||
PRBool isComplex = PR_FALSE;
|
||||
IsContentComplex(&isComplex);
|
||||
if (isComplex) {
|
||||
*aIsAllowed = PR_FALSE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_HIDDEN_(nsresult)
|
||||
NS_NewXFormsOutputElement(nsIXTFElement **aResult)
|
||||
{
|
||||
|
||||
@@ -80,6 +80,8 @@ public:
|
||||
// nsIXFormsDelegate overrides
|
||||
NS_IMETHOD GetXFormsAccessors(nsIXFormsAccessors **aAccessor);
|
||||
|
||||
NS_IMETHOD IsContentAllowed(PRBool *aIsAllowed);
|
||||
|
||||
nsXFormsSelect1Element(const nsAString& aType)
|
||||
: nsXFormsDelegateStub(aType)
|
||||
{}
|
||||
@@ -193,6 +195,23 @@ nsXFormsSelect1Element::GetXFormsAccessors(nsIXFormsAccessors **aAccessor)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsSelect1Element::IsContentAllowed(PRBool *aIsAllowed)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsAllowed);
|
||||
*aIsAllowed = PR_TRUE;
|
||||
|
||||
// For select1 elements, non-simpleContent is only allowed if the select
|
||||
// element contains an itemset.
|
||||
PRBool isComplex = PR_FALSE;
|
||||
IsContentComplex(&isComplex);
|
||||
if (isComplex && !nsXFormsUtils::NodeHasItemset(mElement)) {
|
||||
*aIsAllowed = PR_FALSE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_HIDDEN_(nsresult)
|
||||
NS_NewXFormsSelect1Element(nsIXTFElement **aResult)
|
||||
{
|
||||
|
||||
@@ -75,6 +75,8 @@ public:
|
||||
// nsIXFormsDelegate overrides
|
||||
NS_IMETHOD GetXFormsAccessors(nsIXFormsAccessors **aAccessor);
|
||||
|
||||
NS_IMETHOD IsContentAllowed(PRBool *aIsAllowed);
|
||||
|
||||
#ifdef DEBUG_smaug
|
||||
virtual const char* Name() { return "select"; }
|
||||
#endif
|
||||
@@ -165,6 +167,23 @@ nsXFormsSelectElement::GetXFormsAccessors(nsIXFormsAccessors **aAccessor)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsSelectElement::IsContentAllowed(PRBool *aIsAllowed)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsAllowed);
|
||||
*aIsAllowed = PR_TRUE;
|
||||
|
||||
// For select elements, non-simpleContent is only allowed if the select
|
||||
// element contains an itemset.
|
||||
PRBool isComplex = PR_FALSE;
|
||||
IsContentComplex(&isComplex);
|
||||
if (isComplex && !nsXFormsUtils::NodeHasItemset(mElement)) {
|
||||
*aIsAllowed = PR_FALSE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_HIDDEN_(nsresult)
|
||||
NS_NewXFormsSelectElement(nsIXTFElement **aResult)
|
||||
{
|
||||
|
||||
@@ -2719,3 +2719,35 @@ nsXFormsUtils::SetSingleNodeBindingValue(nsIDOMElement *aElement,
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* static */ PRBool
|
||||
nsXFormsUtils::NodeHasItemset(nsIDOMNode *aNode)
|
||||
{
|
||||
PRBool hasItemset = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> children;
|
||||
aNode->GetChildNodes(getter_AddRefs(children));
|
||||
|
||||
PRUint32 childCount = 0;
|
||||
if (children) {
|
||||
children->GetLength(&childCount);
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < childCount; ++i) {
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
children->Item(i, getter_AddRefs(child));
|
||||
if (nsXFormsUtils::IsXFormsElement(child, NS_LITERAL_STRING("itemset"))) {
|
||||
hasItemset = PR_TRUE;
|
||||
break;
|
||||
} else if (nsXFormsUtils::IsXFormsElement(child,
|
||||
NS_LITERAL_STRING("choices"))) {
|
||||
// The choices element may have an itemset.
|
||||
hasItemset = nsXFormsUtils::NodeHasItemset(child);
|
||||
if (hasItemset) {
|
||||
// No need to look at any other children.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hasItemset;
|
||||
}
|
||||
|
||||
|
||||
@@ -704,6 +704,15 @@ public:
|
||||
static NS_HIDDEN_(nsresult) GetDaysFromDateTime(const nsAString & aValue,
|
||||
PRInt32 * aDays);
|
||||
|
||||
/**
|
||||
* Determine whether the given node contains an xf:itemset as a child.
|
||||
* In valid XForms documents this should only be possible if aNode is an
|
||||
* xf:select/1 or an xf:choices element. This function is used primarily
|
||||
* as a worker function for select/1's IsContentAllowed override.
|
||||
|
||||
*/
|
||||
static NS_HIDDEN_(PRBool) NodeHasItemset(nsIDOMNode *aNode);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Do same origin checks on aBaseDocument and aTestURI. Hosts can be
|
||||
|
||||
@@ -77,6 +77,7 @@ modelLoopError = XForms Error (38): There seems to be an infinite loop in
|
||||
duplicateSchema = XForms Error (39): Ignoring duplicate schema with target namespace: %S
|
||||
boundTypeErrorInclusive = XForms Error (40): %S element not bound to valid datatype. Must be bound to one of these datatypes or a type derived from one of these datatypes: %S.
|
||||
boundTypeErrorExclusive = XForms Error (41): %S element not bound to valid datatype. Must not be bound to one of these datatypes or a type derived from one of these datatypes: %S.
|
||||
boundTypeErrorComplexContent = XForms Error (42): %S element may not be bound to complex content.
|
||||
|
||||
# Warning Messages:
|
||||
warnSOAP = XForms Warning (1): You are using the SOAP post feature, which is an experimental feature! Beware that the functionality might change, and forms may stop working at any time.
|
||||
|
||||
Reference in New Issue
Block a user