[XForms] NPOTDB We need to be able to set context information for XForms events. Bug 280423, p=msterlin r=olli+surkov

This commit is contained in:
aaronr%us.ibm.com 2008-01-10 23:34:08 +00:00
Родитель 2eb389fe0c
Коммит c6098ae396
21 изменённых файлов: 1494 добавлений и 61 удалений

Просмотреть файл

@ -154,6 +154,8 @@ XPIDLSRCS = \
nsIXFormsComboboxUIWidget.idl \
nsIXFormsXPathFunctions.idl \
nsIXFormsXPathState.idl \
nsIXFormsDOMEvent.idl \
nsIXFormsContextInfo.idl \
$(NULL)
# XForms source files
@ -217,6 +219,8 @@ CPPSRCS = \
nsXFormsRangeConditionAccessors.cpp \
nsXFormsXPathFunctions.cpp \
nsXFormsXPathState.cpp \
nsXFormsDOMEvent.cpp \
nsXFormsContextInfo.cpp \
$(NULL)
# Standard Mozilla make rules

Просмотреть файл

@ -41,9 +41,15 @@
interface nsIDOMEvent;
interface nsIXFormsActionElement;
[uuid(b19c47e4-2478-4a73-91a3-d86f91d91ffd)]
[uuid(4fa5fd18-902b-4ea8-a197-e93d5ce1ce71)]
interface nsIXFormsActionModuleElement : nsISupports
{
void handleAction(in nsIDOMEvent aEvent, in nsIXFormsActionElement aParentAction);
/**
* Get the event currently being processed in handleAction. The XPath
* event() method uses this method to get the context info for the
* current event.
*/
nsIDOMEvent getCurrentEvent();
};

Просмотреть файл

@ -0,0 +1,76 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Merle Sterling <msterlin@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsIDOMNode.idl"
#include "nsIDOMXPathResult.idl"
/**
* Interface exposing the event context info of an XForms control.
*
* Context info is accessed by name using nsIXFormsDOMEvent::GetContextInfo
* or the XPath function event().
*
*/
[scriptable, uuid(b012a3e5-7dbc-42b4-99da-5e94c37dc44e)]
interface nsIXFormsContextInfo : nsISupports
{
// Name of the event property; eg. 'resource-uri'
readonly attribute DOMString name;
// Type of the property: String, Number, Node, Nodeset
const unsigned short STRING_TYPE = 1;
const unsigned short NUMBER_TYPE = 2;
const unsigned short NODE_TYPE = 3;
const unsigned short NODESET_TYPE = 4;
readonly attribute long type;
/** Get the value of a STRING_TYPE context info property.
*/
readonly attribute DOMString stringValue;
/** Get the value of a NUMBER_TYPE context info property.
*/
readonly attribute long numberValue;
/** Get the value of a NODE_TYPE context info property.
*/
readonly attribute nsIDOMNode nodeValue;
/** Get the value of a NODESET_TYPE context info property.
*/
readonly attribute nsIDOMXPathResult nodesetValue;
};

Просмотреть файл

@ -0,0 +1,54 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Merle Sterling <msterlin@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIXFormsContextInfo.idl"
#include "nsIDOMEvent.idl"
/**
* Interface exposing the events of an XForms control.
*
*/
[scriptable, uuid(ae6735d5-a8a4-4ac5-9f00-ec653433005c)]
interface nsIXFormsDOMEvent : nsIDOMEvent
{
/** Get a context property from an nsXFormsDOMEvent.
* @param aName - context property name.
*/
nsIXFormsContextInfo getContextInfo(in DOMString aName);
};

Просмотреть файл

@ -58,4 +58,5 @@ interface nsIXFormsXPathFunctions : nsISupports
double seconds(in DOMString aDuration);
double secondsFromDateTime(in DOMString aDateTime);
txINodeSet current(in txIFunctionEvaluationContext aContext);
txINodeSet event(in txIFunctionEvaluationContext aContext, in DOMString aString);
};

Просмотреть файл

@ -148,6 +148,8 @@ nsXFormsActionModuleBase::HandleAction(nsIDOMEvent *aEvent,
if (!mElement)
return NS_OK;
mCurrentEvent = aEvent;
// Set the maximum run time for the loop (in microseconds).
PRTime microseconds = nsXFormsUtils::waitLimit * PR_USEC_PER_SEC;
@ -262,3 +264,11 @@ nsXFormsActionModuleBase::CanPerformAction(PRBool *aUsesWhile,
return PR_TRUE;
}
NS_IMETHODIMP
nsXFormsActionModuleBase::GetCurrentEvent(nsIDOMEvent **aEvent)
{
NS_IF_ADDREF(*aEvent = mCurrentEvent);
return NS_OK;
}

Просмотреть файл

@ -99,6 +99,11 @@ protected:
* additional information in the future.
*/
PRBool mCanIterate;
/**
* The event currently being processed.
*/
nsCOMPtr<nsIDOMEvent> mCurrentEvent;
};
#endif

Просмотреть файл

@ -0,0 +1,226 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Merle Sterling <msterlin@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXFormsContextInfo.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDOMImplementation.h"
#include "nsIDOMText.h"
#include "nsXFormsUtils.h"
/**
* Implementation for XForms event context info.
*
*/
NS_IMPL_ISUPPORTS1(nsXFormsContextInfo, nsIXFormsContextInfo)
nsXFormsContextInfo::nsXFormsContextInfo(nsIDOMElement *aElement)
: mElement(aElement), mType(0)
{
mNode = nsnull;
}
nsXFormsContextInfo::~nsXFormsContextInfo()
{
if (mType == nsIXFormsContextInfo::NODESET_TYPE) {
NS_IF_RELEASE(mNodeset);
} else {
// String, Number, and Node are all nodes.
NS_IF_RELEASE(mNode);
}
}
nsresult
nsXFormsContextInfo::SetName(nsAString &aName)
{
mName = aName;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsContextInfo::GetName(nsAString &aResult)
{
aResult = mName;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsContextInfo::GetType(PRInt32 *aType)
{
*aType = mType;
return NS_OK;
}
nsresult
nsXFormsContextInfo::SetStringValue(const char *aName, nsAString &aString)
{
// Store the string value of the context property as a node.
SetNodeValueInternal(aName, aString);
mType = nsIXFormsContextInfo::STRING_TYPE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsContextInfo::GetStringValue(nsAString &aResult)
{
aResult.Truncate();
if (mType == nsIXFormsContextInfo::STRING_TYPE) {
nsXFormsUtils::GetNodeValue(mNode, aResult);
} else {
NS_WARNING("GetStringValue: context type is not a string!");
}
return NS_OK;
}
nsresult
nsXFormsContextInfo::SetNumberValue(const char *aName, PRInt32 aNumber)
{
// Convert the number to a string and store the (string)number
// value of the context property as a node.
nsAutoString numberStr;
numberStr.AppendInt(aNumber);
SetNodeValueInternal(aName, numberStr);
mType = nsIXFormsContextInfo::NUMBER_TYPE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsContextInfo::GetNumberValue(PRInt32 *aResult)
{
*aResult = 0;
if (mType == nsIXFormsContextInfo::NUMBER_TYPE) {
nsAutoString numberStr;
nsXFormsUtils::GetNodeValue(mNode, numberStr);
nsresult rv;
*aResult = numberStr.ToInteger(&rv);
NS_ENSURE_SUCCESS(rv, rv);
} else {
NS_WARNING("GetNumberValue: context type is not a number!");
}
return NS_OK;
}
nsresult
nsXFormsContextInfo::SetNodeValue(const char *aName, nsIDOMNode *aNode)
{
// Set the name of the context property.
nsAutoString name;
name.AppendLiteral(aName);
SetName(name);
// Set the node value of the context property.
NS_IF_ADDREF(mNode = aNode);
mType = nsIXFormsContextInfo::NODE_TYPE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsContextInfo::GetNodeValue(nsIDOMNode **aResult)
{
*aResult = nsnull;
// String and number context types are stored as nodes, so
// GetNodeValue can be used to get a string or number type
// as a node.
if (mType == nsIXFormsContextInfo::NODE_TYPE ||
mType == nsIXFormsContextInfo::STRING_TYPE ||
mType == nsIXFormsContextInfo::NUMBER_TYPE) {
NS_IF_ADDREF(*aResult = mNode);
} else {
NS_WARNING("GetNodeValue: context type is not a node, string, or number!");
}
return NS_OK;
}
nsresult
nsXFormsContextInfo::SetNodesetValue(const char *aName,
nsIDOMXPathResult *aNodeset)
{
// Set the name of the context property.
nsAutoString name;
name.AppendLiteral(aName);
SetName(name);
// Set the nodeset value of the context property.
NS_IF_ADDREF(mNodeset = aNodeset);
mType = nsIXFormsContextInfo::NODESET_TYPE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsContextInfo::GetNodesetValue(nsIDOMXPathResult **aResult)
{
*aResult = nsnull;
if (mType == nsIXFormsContextInfo::NODESET_TYPE) {
NS_IF_ADDREF(*aResult = mNodeset);
} else {
NS_WARNING("GetNodesetValue: context type is not a nodeset!");
}
return NS_OK;
}
nsresult
nsXFormsContextInfo::SetNodeValueInternal(const char *aName, nsAString &aValue)
{
if (!mElement)
return NS_ERROR_FAILURE;
nsresult rv;
nsCOMPtr<nsIDOMDocument> doc;
rv = mElement->GetOwnerDocument(getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMDOMImplementation> domImpl;
rv = doc->GetImplementation(getter_AddRefs(domImpl));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMText> textNode;
rv = doc->CreateTextNode(aValue, getter_AddRefs(textNode));
NS_ENSURE_SUCCESS(rv, rv);
SetNodeValue(aName, textNode);
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,126 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Merle Sterling <msterlin@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsXFormsContextInfo_h_
#define nsXFormsContextInfo_h_
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsIDOMElement.h"
#include "nsIDOMNode.h"
#include "nsIDOMXPathResult.h"
#include "nsIXFormsContextInfo.h"
/**
* Implementation for XForms Event Context Info.
*
*/
class nsXFormsContextInfo : public nsIXFormsContextInfo
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXFORMSCONTEXTINFO
nsXFormsContextInfo(nsIDOMElement *aElement);
virtual ~nsXFormsContextInfo();
/** Set the name of the context info property; eg. 'resource-uri'
*
* @param aName - property name
*/
nsresult SetName(nsAString &aName);
/** Set a string value for a context info property.
* String values are encapsulated in a text node because
* the XPath Event function can only work with nodes.
*
* @param aName - name of the string property.
* @param aString - string value.
*/
nsresult SetStringValue(const char *aName, nsAString &aString);
/** Set a number value for a context info property.
* Number values are encapsulated in a text node because
* the XPath Event function can only work with nodes.
*
* @param aName - name of the number property.
* @param aNumber - number value.
*/
nsresult SetNumberValue(const char *aName, PRInt32 aNumber);
/** Set a node value for a context info property.
*
* @param aName - name of the node property.
* @param aNode - node value.
*/
nsresult SetNodeValue(const char *aName, nsIDOMNode *aNode);
/** Set a nodeset value for a context info property.
*
* @param aName - name of the nodeset property.
* @param aNodeset - nodeset value.
*/
nsresult SetNodesetValue(const char *aName, nsIDOMXPathResult *aNodeset);
private:
/**
* Create a text node to encapsulate string and number context property
* types. The XPath Event function returns a txINodeset and only nodes
* can be added to the nodeset.
*
* @param aName - name of the node property.
* @param aValue - value of the text node.
*/
nsresult SetNodeValueInternal(const char *aName, nsAString &aValue);
// The element to which the context info refers.
nsIDOMElement *mElement;
// The name of the context info property.
nsString mName;
// The type of the context info property.
PRInt32 mType;
// The value of the context property.
union {
nsIDOMNode *mNode;
nsIDOMXPathResult *mNodeset;
};
};
#endif

Просмотреть файл

@ -0,0 +1,180 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Merle Sterling <msterlin@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXFormsDOMEvent.h"
/**
* Implementation for XForms events.
*
*/
NS_IMPL_ISUPPORTS3(nsXFormsDOMEvent, nsIXFormsDOMEvent, nsIDOMNSEvent, nsIPrivateDOMEvent)
nsXFormsDOMEvent::nsXFormsDOMEvent(nsIDOMEvent *aInner,
nsCOMArray<nsIXFormsContextInfo> *aContextInfo)
{
mInner = aInner;
mContextInfo.Init();
SetContextInfo(aContextInfo);
}
nsXFormsDOMEvent::~nsXFormsDOMEvent()
{}
nsresult
nsXFormsDOMEvent::SetContextInfo(nsCOMArray<nsIXFormsContextInfo> *aContextInfo)
{
if (aContextInfo) {
for (int i = 0; i < aContextInfo->Count(); i++) {
nsCOMPtr<nsIXFormsContextInfo> ctxtInfo = aContextInfo->ObjectAt(i);
nsAutoString name;
ctxtInfo->GetName(name);
mContextInfo.Put(name, ctxtInfo);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsDOMEvent::GetContextInfo(const nsAString &aName,
nsIXFormsContextInfo **aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
mContextInfo.Get(aName, aResult);
return NS_OK;
}
// nsIDOMNSEvent interface
NS_IMETHODIMP
nsXFormsDOMEvent::GetOriginalTarget(nsIDOMEventTarget **aOriginalTarget)
{
nsCOMPtr<nsIDOMNSEvent> nsevent = do_QueryInterface(mInner);
return nsevent->GetOriginalTarget(aOriginalTarget);
}
NS_IMETHODIMP
nsXFormsDOMEvent::GetExplicitOriginalTarget(nsIDOMEventTarget **aExplicitOriginalTarget)
{
nsCOMPtr<nsIDOMNSEvent> nsevent = do_QueryInterface(mInner);
return nsevent->GetExplicitOriginalTarget(aExplicitOriginalTarget);
}
NS_IMETHODIMP
nsXFormsDOMEvent::GetTmpRealOriginalTarget(nsIDOMEventTarget **aTmpRealOriginalTarget)
{
nsCOMPtr<nsIDOMNSEvent> nsevent = do_QueryInterface(mInner);
return nsevent->GetTmpRealOriginalTarget(aTmpRealOriginalTarget);
}
NS_IMETHODIMP
nsXFormsDOMEvent::PreventBubble(void)
{
nsCOMPtr<nsIDOMNSEvent> nsevent = do_QueryInterface(mInner);
return nsevent->PreventBubble();
}
NS_IMETHODIMP
nsXFormsDOMEvent::PreventCapture(void)
{
nsCOMPtr<nsIDOMNSEvent> nsevent = do_QueryInterface(mInner);
return nsevent->PreventCapture();
}
NS_IMETHODIMP
nsXFormsDOMEvent::GetIsTrusted(PRBool *aIsTrusted)
{
nsCOMPtr<nsIDOMNSEvent> nsevent = do_QueryInterface(mInner);
return nsevent->GetIsTrusted(aIsTrusted);
}
// nsIPrivateDOMEvent interface
NS_METHOD
nsXFormsDOMEvent::DuplicatePrivateData()
{
nsCOMPtr<nsIPrivateDOMEvent> privEvent = do_QueryInterface(mInner);
return privEvent->DuplicatePrivateData();
}
NS_METHOD
nsXFormsDOMEvent::SetTarget(nsIDOMEventTarget* aTarget)
{
nsCOMPtr<nsIPrivateDOMEvent> privEvent = do_QueryInterface(mInner);
return privEvent->SetTarget(aTarget);
}
NS_METHOD
nsXFormsDOMEvent::SetCurrentTarget(nsIDOMEventTarget* aTarget)
{
nsCOMPtr<nsIPrivateDOMEvent> privEvent = do_QueryInterface(mInner);
return privEvent->SetCurrentTarget(aTarget);
}
NS_METHOD
nsXFormsDOMEvent::SetOriginalTarget(nsIDOMEventTarget* aTarget)
{
nsCOMPtr<nsIPrivateDOMEvent> privEvent = do_QueryInterface(mInner);
return privEvent->SetOriginalTarget(aTarget);
}
NS_METHOD
nsXFormsDOMEvent::IsDispatchStopped(PRBool* aIsDispatchPrevented)
{
nsCOMPtr<nsIPrivateDOMEvent> privEvent = do_QueryInterface(mInner);
return privEvent->IsDispatchStopped(aIsDispatchPrevented);
}
NS_METHOD
nsXFormsDOMEvent::GetInternalNSEvent(nsEvent** aNSEvent)
{
nsCOMPtr<nsIPrivateDOMEvent> privEvent = do_QueryInterface(mInner);
return privEvent->GetInternalNSEvent(aNSEvent);
}
NS_METHOD
nsXFormsDOMEvent::HasOriginalTarget(PRBool* aResult)
{
nsCOMPtr<nsIPrivateDOMEvent> privEvent = do_QueryInterface(mInner);
return privEvent->HasOriginalTarget(aResult);
}
NS_METHOD
nsXFormsDOMEvent::SetTrusted(PRBool aTrusted)
{
nsCOMPtr<nsIPrivateDOMEvent> privEvent = do_QueryInterface(mInner);
return privEvent->SetTrusted(aTrusted);
}

Просмотреть файл

@ -0,0 +1,86 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Merle Sterling <msterlin@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsInterfaceHashtable.h"
#include "nsXFormsContextInfo.h"
#include "nsIXFormsDOMEvent.h"
#include "nsIDOMNSEvent.h"
#include "nsIPrivateDOMEvent.h"
/**
* Implementation for XForms events.
*
*/
class nsXFormsDOMEvent : public nsIXFormsDOMEvent,
public nsIDOMNSEvent,
public nsIPrivateDOMEvent
{
public:
NS_DECL_ISUPPORTS
// nsIXFormsDOMEvent interface
NS_DECL_NSIXFORMSDOMEVENT
// nsIDOMNSEvent interface
NS_DECL_NSIDOMNSEVENT
// nsIDOMEvent interface
NS_FORWARD_NSIDOMEVENT(mInner->)
// nsIPrivateDOMEvent interface
NS_IMETHOD DuplicatePrivateData();
NS_IMETHOD SetTarget(nsIDOMEventTarget* aTarget);
NS_IMETHOD SetCurrentTarget(nsIDOMEventTarget* aTarget);
NS_IMETHOD SetOriginalTarget(nsIDOMEventTarget* aTarget);
NS_IMETHOD IsDispatchStopped(PRBool* aIsDispatchPrevented);
NS_IMETHOD GetInternalNSEvent(nsEvent** aNSEvent);
NS_IMETHOD HasOriginalTarget(PRBool* aResult);
NS_IMETHOD SetTrusted(PRBool aTrusted);
nsXFormsDOMEvent(nsIDOMEvent *aInner,
nsCOMArray<nsIXFormsContextInfo> *aContextInfo);
virtual ~nsXFormsDOMEvent();
nsresult SetContextInfo(nsCOMArray<nsIXFormsContextInfo> *aContextInfo);
protected:
nsCOMPtr<nsIDOMEvent> mInner;
/**
* Hashtable of all context info properties for a given event.
* key = context property name, value = nsIXFormsContextInfo
*/
nsInterfaceHashtable<nsStringHashKey, nsIXFormsContextInfo> mContextInfo;
};

Просмотреть файл

@ -46,6 +46,7 @@
#include "nsIDOMNamedNodeMap.h"
#include "nsIXFormsRepeatElement.h"
#include "nsIXFormsControl.h"
#include "nsIXFormsContextInfo.h"
#include "nsStringAPI.h"
@ -63,14 +64,6 @@
/**
* Implementation of the XForms \<insert\> and \<delete\> elements.
*
* @see http://www.w3.org/TR/xforms/slice9.html#action-insert
*
* @todo The spec. states that the events must set their Context Info to:
* "Path expression used for insert/delete (xsd:string)" (XXX)
* @see http://www.w3.org/TR/xforms/slice4.html#evt-insert
* @see https://bugzilla.mozilla.org/show_bug.cgi?id=280423
*
*/
class nsXFormsInsertDeleteElement : public nsXFormsActionModuleBase
{
@ -83,6 +76,9 @@ private:
eLocation_FirstChild
};
// Context Info for events.
nsCOMArray<nsIXFormsContextInfo> mContextInfo;
/** Get the first node of a given type in aNodes.
*
* @param aNodes array of nodes
@ -108,13 +104,15 @@ private:
nsresult RefreshRepeats(nsCOMArray<nsIDOMNode> *aNodes);
public:
NS_DECL_NSIXFORMSACTIONMODULEELEMENT
/** Constructor */
nsXFormsInsertDeleteElement(PRBool aIsInsert) :
nsXFormsActionModuleBase(PR_TRUE),
mIsInsert(aIsInsert)
{}
NS_IMETHOD
HandleAction(nsIDOMEvent* aEvent, nsIXFormsActionElement *aParentAction);
protected:
/**
* Normally, an action element implements the body of its action handler
@ -137,6 +135,8 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
if (!mElement)
return NS_OK;
mCurrentEvent = aEvent;
nsresult rv;
//
@ -242,9 +242,9 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
//
nsCOMPtr<nsIDOMXPathResult> nodeset;
PRUint32 nodesetSize = 0;
nsAutoString nodesetExpr;
if (bindExpr.IsEmpty()) {
nsAutoString nodesetExpr;
mElement->GetAttribute(NS_LITERAL_STRING("nodeset"), nodesetExpr);
if (!nodesetExpr.IsEmpty()) {
// Evaluate the nodeset attribute within the insert context.
@ -321,6 +321,13 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
// is the empty node-set.
if (originNodesetSize < 1)
return NS_OK;
// Context Info: 'origin-nodes'
nsCOMPtr<nsXFormsContextInfo> contextInfo =
new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetNodesetValue("origin-nodes", originNodeset);
mContextInfo.AppendObject(contextInfo);
}
}
@ -404,6 +411,20 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
}
}
// Context Info: 'insert-location-node' or 'delete-location'
nsCOMPtr<nsXFormsContextInfo> contextInfo;
if (mIsInsert) {
contextInfo = new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetNodeValue("insert-location-node", locationNode);
mContextInfo.AppendObject(contextInfo);
} else {
contextInfo = new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetNumberValue("delete-location", atInt);
mContextInfo.AppendObject(contextInfo);
}
//
// Step 5 (Insert): Each node in the origin node-set is cloned in the
// order it appears in the origin node-set. If the origin node-set is empty
@ -437,6 +458,12 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
cloneNodesetSize = originNodesetSize;
cloneIndex = 0;
}
// Context Info: 'inserted-nodes'
nsCOMPtr<nsXFormsContextInfo> contextInfo =
new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetNodesetValue("inserted-nodes", cloneNodeset);
mContextInfo.AppendObject(contextInfo);
cloneNodeset->SnapshotItem(cloneIndex, getter_AddRefs(prototypeNode));
NS_ENSURE_STATE(prototypeNode);
@ -556,6 +583,13 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
return NS_ERROR_FAILURE;
}
}
// Context Info: 'position'.
nsCOMPtr<nsXFormsContextInfo> contextInfo =
new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetStringValue("position", position);
mContextInfo.AppendObject(contextInfo);
InsertNode(locationNode, newNode,
insertAfter ? eLocation_After: eLocation_Before,
getter_AddRefs(resNode));
@ -591,6 +625,12 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
deleteIndex = atInt - 1;
deleteCount = atInt;
}
// Context Info: 'deleted-nodes'
nsCOMPtr<nsXFormsContextInfo> contextInfo =
new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetNodesetValue("deleted-nodes", nodeset);
mContextInfo.AppendObject(contextInfo);
nodeset->SnapshotItem(deleteIndex, getter_AddRefs(locationNode));
NS_ENSURE_STATE(locationNode);
@ -645,7 +685,8 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
// Dispatch xforms-insert/delete event to the instance node we have modified
// data for
rv = nsXFormsUtils::DispatchEvent(instNode,
mIsInsert ? eEvent_Insert : eEvent_Delete);
mIsInsert ? eEvent_Insert : eEvent_Delete,
nsnull, nsnull, &mContextInfo);
NS_ENSURE_SUCCESS(rv, rv);
// Dispatch refreshing events to the model
@ -674,7 +715,6 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
return NS_OK;
}
nsresult
nsXFormsInsertDeleteElement::GetFirstNodeOfType(nsCOMArray<nsIDOMNode> *aNodes,
PRUint16 aNodeType,

Просмотреть файл

@ -94,9 +94,18 @@ public:
private:
NS_HIDDEN_(void) LoadExternalLabel(const nsAString& aValue);
/** Set context info for events.
*
* @param aName Name of the context property.
* @param aValue Value of the context property.
*/
nsresult SetContextInfo(const char *aName, nsAString &aValue);
nsCString mSrcAttrText;
nsCOMPtr<nsIChannel> mChannel;
PRBool mWidgetLoaded;
// Context Info for events.
nsCOMArray<nsIXFormsContextInfo> mContextInfo;
};
NS_IMPL_ISUPPORTS_INHERITED3(nsXFormsLabelElement,
@ -279,8 +288,13 @@ nsXFormsLabelElement::LoadExternalLabel(const nsAString& aSrc)
nsCOMPtr<nsIModelElementPrivate> modelPriv =
nsXFormsUtils::GetModel(mElement);
nsCOMPtr<nsIDOMNode> model = do_QueryInterface(modelPriv);
// Context Info: 'resource-uri'
// The URI associated with the failed link.
nsAutoString resourceURI(aSrc);
SetContextInfo("resource-uri", resourceURI);
nsXFormsUtils::DispatchEvent(model, eEvent_LinkError, nsnull,
mElement);
mElement, &mContextInfo);
}
}
} else {
@ -290,7 +304,13 @@ nsXFormsLabelElement::LoadExternalLabel(const nsAString& aSrc)
nsCOMPtr<nsIModelElementPrivate> modelPriv =
nsXFormsUtils::GetModel(mElement);
nsCOMPtr<nsIDOMNode> model = do_QueryInterface(modelPriv);
nsXFormsUtils::DispatchEvent(model, eEvent_LinkError, nsnull, mElement);
// Context Info: 'resource-uri'
// The URI associated with the failed link.
nsAutoString resourceURI(aSrc);
SetContextInfo("resource-uri", resourceURI);
nsXFormsUtils::DispatchEvent(model, eEvent_LinkError, nsnull, mElement,
&mContextInfo);
}
}
}
@ -416,7 +436,12 @@ nsXFormsLabelElement::OnStopRequest(nsIRequest *aRequest,
nsCOMPtr<nsIModelElementPrivate> modelPriv =
nsXFormsUtils::GetModel(mElement);
nsCOMPtr<nsIDOMNode> model = do_QueryInterface(modelPriv);
nsXFormsUtils::DispatchEvent(model, eEvent_LinkError, nsnull, mElement);
// Context Info: 'resource-uri'
// The URI associated with the failed link.
SetContextInfo("resource-uri", src);
nsXFormsUtils::DispatchEvent(model, eEvent_LinkError, nsnull, mElement,
&mContextInfo);
mSrcAttrText.Truncate();
}
@ -427,6 +452,17 @@ nsXFormsLabelElement::OnStopRequest(nsIRequest *aRequest,
return NS_OK;
}
nsresult
nsXFormsLabelElement::SetContextInfo(const char *aName, nsAString &aValue)
{
nsCOMPtr<nsXFormsContextInfo> contextInfo = new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetStringValue(aName, aValue);
mContextInfo.AppendObject(contextInfo);
return NS_OK;
}
NS_HIDDEN_(nsresult)
NS_NewXFormsLabelElement(nsIXTFElement **aResult)
{

Просмотреть файл

@ -197,6 +197,13 @@ private:
*/
PRBool IsEphemeral();
/** Set context info for events.
*
* @param aName Name of the context property.
* @param aValue Value of the context property.
*/
nsresult SetContextInfo(const char *aName, nsAString &aValue);
MessageType mType;
// The position of the ephemeral message
@ -209,6 +216,9 @@ private:
StopType mStopType;
nsCString mSrcAttrText;
PRBool mDoneAddingChildren;
// Context Info for events.
nsCOMArray<nsIXFormsContextInfo> mContextInfo;
nsString mSrc;
};
NS_IMPL_ADDREF_INHERITED(nsXFormsMessageElement, nsXFormsDelegateStub)
@ -473,7 +483,13 @@ nsXFormsMessageElement::HandleSingleAction(nsIDOMEvent *aEvent,
nsCOMPtr<nsIModelElementPrivate> modelPriv =
nsXFormsUtils::GetModel(mElement);
nsCOMPtr<nsIDOMNode> model = do_QueryInterface(modelPriv);
nsXFormsUtils::DispatchEvent(model, eEvent_LinkError);
// Context Info: 'resource-uri'
// The URI associated with the failed link.
SetContextInfo("resource-uri", mSrc);
nsXFormsUtils::DispatchEvent(model, eEvent_LinkError, nsnull, nsnull,
&mContextInfo);
return NS_OK;
}
@ -934,6 +950,9 @@ nsXFormsMessageElement::TestExternalFile()
if (src.IsEmpty()) {
return NS_OK;
}
// Remember the src attribute so we can set it in the context info
// for the xforms-link-error event if the link fails.
mSrc = src;
nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
@ -997,6 +1016,9 @@ nsXFormsMessageElement::TestExternalFile()
nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink1Error"),
strings, 2, mElement, mElement);
mStopType = eStopType_LinkError;
// Remember the src attribute so we can set it in the context info
// for the xforms-link-error event.
mSrc = src;
return NS_ERROR_FAILURE;
}
@ -1107,6 +1129,9 @@ nsXFormsMessageElement::OnStartRequest(nsIRequest *aRequest,
nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink2Error"),
strings, 2, mElement, mElement);
mStopType = eStopType_LinkError;
// Remember the src attribute so we can set it in the context info
// for the xforms-link-error event.
mSrc = src;
}
AddRemoveExternalResource(PR_FALSE);
@ -1133,6 +1158,9 @@ nsXFormsMessageElement::OnStartRequest(nsIRequest *aRequest,
nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink2Error"),
strings, 2, mElement, mElement);
mStopType = eStopType_LinkError;
// Remember the src attribute so we can set it in the context info
// for the xforms-link-error event.
mSrc = src;
}
}
@ -1260,6 +1288,17 @@ PRBool nsXFormsMessageElement::IsEphemeral()
return level.Equals(NS_LITERAL_STRING("ephemeral"));
}
nsresult
nsXFormsMessageElement::SetContextInfo(const char *aName, nsAString &aValue)
{
nsCOMPtr<nsXFormsContextInfo> contextInfo = new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetStringValue(aName, aValue);
mContextInfo.AppendObject(contextInfo);
return NS_OK;
}
NS_HIDDEN_(nsresult)
NS_NewXFormsMessageElement(nsIXTFElement **aResult)
{

Просмотреть файл

@ -811,6 +811,7 @@ nsXFormsModelElement::InitializeInstances()
for (PRInt32 i=0; i<mSchemaTotal; ++i) {
rv = NS_OK;
nsCAutoString uriSpec;
nsCOMPtr<nsIURI> newURI;
NS_NewURI(getter_AddRefs(newURI), *schemas[i], nsnull, baseURI);
nsCOMPtr<nsIURL> newURL = do_QueryInterface(newURI);
@ -848,7 +849,6 @@ nsXFormsModelElement::InitializeInstances()
i--;
}
} else {
nsCAutoString uriSpec;
newURI->GetSpec(uriSpec);
rv = mSchemas->LoadAsync(NS_ConvertUTF8toUTF16(uriSpec), this);
}
@ -856,7 +856,11 @@ nsXFormsModelElement::InitializeInstances()
if (NS_FAILED(rv)) {
// this is a fatal error
nsXFormsUtils::ReportError(NS_LITERAL_STRING("schemaLoadError"), mElement);
nsXFormsUtils::DispatchEvent(mElement, eEvent_LinkException);
// Context Info: 'resource-uri'
// The URI associated with the failed link.
SetContextInfo("resource-uri", NS_ConvertUTF8toUTF16(uriSpec));
nsXFormsUtils::DispatchEvent(mElement, eEvent_LinkException, nsnull,
nsnull, &mContextInfo);
return NS_OK;
}
}
@ -2336,7 +2340,15 @@ nsXFormsModelElement::MaybeNotifyCompletion()
if (!extFunctionAtt.IsEmpty()) {
nsXFormsUtils::ReportError(NS_LITERAL_STRING("invalidExtFunction"),
tElement);
nsXFormsUtils::DispatchEvent(tElement, eEvent_ComputeException);
// Context Info: 'error-message'
// Error message containing the expression being processed.
nsAutoString errorMsg;
errorMsg.AssignLiteral("Non-existent extension functions: ");
errorMsg.Append(extFunctionAtt);
SetContextInfo("error-message", errorMsg);
nsXFormsUtils::DispatchEvent(tElement, eEvent_ComputeException, nsnull,
nsnull, &mContextInfo);
return;
}
}
@ -2431,7 +2443,15 @@ nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
const PRUnichar *strings[] = { exprString.get() };
nsXFormsUtils::ReportError(NS_LITERAL_STRING("exprParseError"),
strings, 1, aBindElement, nsnull);
nsXFormsUtils::DispatchEvent(mElement, eEvent_ComputeException);
// Context Info: 'error-message'
// Error message containing the expression being processed.
nsAutoString errorMsg;
errorMsg.AssignLiteral("Error parsing XPath expression: ");
errorMsg.Append(exprString);
SetContextInfo("error-message", errorMsg);
nsXFormsUtils::DispatchEvent(mElement, eEvent_ComputeException, nsnull,
nsnull, &mContextInfo);
} else {
#ifdef DEBUG
printf("xforms-binding-exception: XPath Evaluation failed\n");
@ -2559,7 +2579,15 @@ nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
const PRUnichar *strings[] = { propStrings[j].get() };
nsXFormsUtils::ReportError(NS_LITERAL_STRING("mipParseError"),
strings, 1, aBindElement, aBindElement);
nsXFormsUtils::DispatchEvent(mElement, eEvent_ComputeException);
// Context Info: 'error-message'
// Error message containing the expression being processed.
nsAutoString errorMsg;
errorMsg.AssignLiteral("Error while parsing model item property: ");
errorMsg.Append(propStrings[j]);
SetContextInfo("error-message", errorMsg);
nsXFormsUtils::DispatchEvent(mElement, eEvent_ComputeException,
nsnull, nsnull, &mContextInfo);
return rv;
}
@ -3495,6 +3523,17 @@ nsXFormsModelElement::IsDuplicateSchema(nsIDOMElement *aSchemaElement)
return PR_TRUE;
}
nsresult
nsXFormsModelElement::SetContextInfo(const char *aName, nsAString &aValue)
{
nsCOMPtr<nsXFormsContextInfo> contextInfo = new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetStringValue(aName, aValue);
mContextInfo.AppendObject(contextInfo);
return NS_OK;
}
nsresult
NS_NewXFormsModelElement(nsIXTFElement **aResult)
{

Просмотреть файл

@ -462,6 +462,13 @@ private:
NS_HIDDEN_(nsresult) BuiltinTypeToPrimative(nsISchemaBuiltinType *aSchemaType,
PRUint16 *aPrimType);
/** Set context info for events.
*
* @param aName Name of the context property.
* @param aValue Value of the context property.
*/
nsresult SetContextInfo(const char *aName, nsAString &aValue);
nsCOMPtr<nsISchemaLoader> mSchemas;
nsStringArray mPendingInlineSchemas;
nsXFormsControlListItem mFormControls;
@ -554,6 +561,9 @@ private:
*/
nsClassHashtable<nsISupportsHashKey, nsString> mNodeToP3PType;
// Context Info for events.
nsCOMArray<nsIXFormsContextInfo> mContextInfo;
friend class Updating;
};

Просмотреть файл

@ -22,6 +22,7 @@
* Contributor(s):
* Darin Fisher <darin@meer.net>
* Doron Rosenberg <doronr@us.ibm.com>
* Merle Sterling <msterlin@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -116,6 +117,20 @@
#define ENCODING_MULTIPART_RELATED 0x40 // multipart/related
#define ENCODING_MULTIPART_FORM_DATA 0x80 // multipart/form-data
// submission errors
#define kError_SubmissionInProgress \
NS_LITERAL_STRING("submission-in-progress");
#define kError_NoData \
NS_LITERAL_STRING("no-data");
#define kError_ValidationError \
NS_LITERAL_STRING("validation-error");
#define kError_ParseError \
NS_LITERAL_STRING("parse-error");
#define kError_ResourceError \
NS_LITERAL_STRING("resource-error");
#define kError_TargetError \
NS_LITERAL_STRING("target-error");
struct SubmissionFormat
{
const char *method;
@ -300,6 +315,23 @@ nsXFormsSubmissionElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled)
EndSubmit(PR_FALSE);
}
*aHandled = PR_TRUE;
} else if (type.EqualsLiteral("xforms-submit-serialize")) {
nsCOMPtr<nsIXFormsDOMEvent> xfEvent = do_QueryInterface(aEvent);
if (xfEvent) {
nsCOMPtr<nsIXFormsContextInfo> contextInfo;
nsAutoString contextName;
contextName.AssignLiteral("submission-body");
xfEvent->GetContextInfo(contextName, getter_AddRefs(contextInfo));
if (contextInfo) {
nsAutoString submissionBody;
contextInfo->GetStringValue(submissionBody);
if (!submissionBody.EqualsLiteral(" ")) {
// Save the new submission body.
contextInfo->GetNodeValue(&mSubmissionBody);
}
}
}
*aHandled = PR_TRUE;
} else {
*aHandled = PR_FALSE;
@ -413,22 +445,40 @@ nsXFormsSubmissionElement::OnStopRequest(nsIRequest *aRequest,
PRBool succeeded = NS_SUCCEEDED(aStatus);
if (succeeded) {
PRUint32 avail = 0;
mPipeIn->Available(&avail);
if (avail > 0) {
nsresult rv;
// If it is a HTTP request, then check for error responses, which should
// result in NOP and an xforms-submit-error.
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
if (httpChannel) {
PRUint32 response;
nsresult rv = httpChannel->GetResponseStatus(&response);
succeeded = NS_SUCCEEDED(rv) && (response < 400);
}
// Regardless of whether the response status represents success
// or failure, we want to read the response. For an error response
// nothing in the document is replaced, and submission processing
// concludes after dispatching xforms-submit-error with appropriate
// context information, including an error-type of resource-error.
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
if (httpChannel) {
PRUint32 response;
nsresult rv = httpChannel->GetResponseStatus(&response);
nsCAutoString statusText;
httpChannel->GetResponseStatusText(statusText);
httpChannel->VisitResponseHeaders(this);
SetHttpContextInfo(response, NS_ConvertUTF8toUTF16(statusText));
if (succeeded) {
PRUint32 avail = 0;
mPipeIn->Available(&avail);
if (avail > 0) {
PRBool requestSucceeded;
httpChannel->GetRequestSucceeded(&requestSucceeded);
if (!requestSucceeded) {
// Server returned an error response code. Parse the error
// response body into an XML document for 'response-body'
// context info.
ParseErrorResponse(httpChannel);
mSubmitError = kError_ResourceError;
succeeded = PR_FALSE;
} else {
succeeded = PR_TRUE;
}
}
nsresult rv;
if (succeeded) {
if (mIsReplaceInstance) {
rv = LoadReplaceInstance(channel);
} else {
@ -437,13 +487,15 @@ nsXFormsSubmissionElement::OnStopRequest(nsIRequest *aRequest,
if (replace.IsEmpty() || replace.EqualsLiteral("all"))
rv = LoadReplaceAll(channel);
else
// replace="none"
rv = NS_OK;
}
succeeded = NS_SUCCEEDED(rv);
}
} else {
mSubmitError = kError_ResourceError;
}
}
mPipeIn = 0;
EndSubmit(succeeded);
@ -461,8 +513,20 @@ nsXFormsSubmissionElement::EndSubmit(PRBool aSucceeded)
mActivator->SetDisabled(PR_FALSE);
mActivator = nsnull;
}
// If there were any errors, set 'error-type' context info.
if (!mSubmitError.IsEmpty()) {
nsCOMPtr<nsXFormsContextInfo> contextInfo =
new nsXFormsContextInfo(mElement);
if (contextInfo) {
contextInfo->SetStringValue("error-type", mSubmitError);
mContextInfo.AppendObject(contextInfo);
}
}
nsXFormsUtils::DispatchEvent(mElement, aSucceeded ?
eEvent_SubmitDone : eEvent_SubmitError);
eEvent_SubmitDone : eEvent_SubmitError,
nsnull, nsnull, &mContextInfo);
}
already_AddRefed<nsIModelElementPrivate>
@ -518,6 +582,7 @@ nsXFormsSubmissionElement::LoadReplaceInstance(nsIChannel *channel)
if (!newDoc) {
nsXFormsUtils::ReportError(NS_LITERAL_STRING("instanceParseError"),
mElement);
mSubmitError = kError_ParseError;
return NS_ERROR_UNEXPECTED;
}
@ -535,6 +600,7 @@ nsXFormsSubmissionElement::LoadReplaceInstance(nsIChannel *channel)
namespaceURI.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) {
nsXFormsUtils::ReportError(NS_LITERAL_STRING("instanceParseError"),
mElement);
mSubmitError = kError_ParseError;
return NS_ERROR_UNEXPECTED;
}
}
@ -572,9 +638,10 @@ nsXFormsSubmissionElement::LoadReplaceInstance(nsIChannel *channel)
model->Recalculate();
model->Revalidate();
model->Refresh();
} else {
mSubmitError = kError_NoData;
}
return NS_OK;
}
@ -639,6 +706,7 @@ nsXFormsSubmissionElement::Submit()
if (mSubmissionActive) {
nsXFormsUtils::ReportError(NS_LITERAL_STRING("warnSubmitAlreadyRunning"),
mElement, nsIScriptError::warningFlag);
mSubmitError = kError_SubmissionInProgress;
return NS_ERROR_FAILURE;
}
mSubmissionActive = PR_TRUE;
@ -652,14 +720,37 @@ nsXFormsSubmissionElement::Submit()
mElement->GetAttribute(NS_LITERAL_STRING("replace"), replace);
mIsReplaceInstance = replace.EqualsLiteral("instance");
// 2. Dispatch xforms-submit-serialize.
// If the event context submission-body property string is empty, then no
// operation is performed so that the submission will use the normal
// serialization data. Otherwise, if the event context submission-body
// property string is non-empty, then the serialization data for the
// submission is set to be the content of the submission-body string.
nsCOMPtr<nsXFormsContextInfo> contextInfo = new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
nsAutoString submissionBody;
submissionBody.AssignLiteral(" ");
contextInfo->SetStringValue("submission-body", submissionBody);
mContextInfo.AppendObject(contextInfo);
nsXFormsUtils::DispatchEvent(mElement, eEvent_SubmitSerialize, nsnull,
nsnull, &mContextInfo);
//
// 2. get selected node from the instance data
nsCOMPtr<nsIDOMNode> data;
rv = GetBoundInstanceData(getter_AddRefs(data));
NS_ENSURE_SUCCESS(rv, rv);
if (mSubmissionBody) {
// submission-body property was modified during submit-serialize and its
// contents is the new serialization data.
data = mSubmissionBody;
} else {
// get selected node from the instance data.
rv = GetBoundInstanceData(getter_AddRefs(data));
NS_ENSURE_SUCCESS(rv, rv);
}
// No data to submit
if (!data) {
mSubmitError = kError_NoData;
EndSubmit(PR_FALSE);
return NS_OK;
}
@ -668,8 +759,10 @@ nsXFormsSubmissionElement::Submit()
// 3. Create submission document (include namespaces, purge non-relevant
// nodes, check simple type validity)
nsCOMPtr<nsIDOMDocument> submissionDoc;
rv = CreateSubmissionDoc(data, getter_AddRefs(submissionDoc));
NS_ENSURE_SUCCESS(rv, rv);
if (!mSubmissionBody) {
rv = CreateSubmissionDoc(data, getter_AddRefs(submissionDoc));
NS_ENSURE_SUCCESS(rv, rv);
}
//
// 4. Validate document
@ -688,7 +781,27 @@ nsXFormsSubmissionElement::Submit()
nsCAutoString uri, contentType;
GetSubmissionURI(uri);
rv = SerializeData(submissionDoc, uri, getter_AddRefs(stream), contentType);
if (mSubmissionBody) {
// submission-body property was modified during submit-serialize and we will
// serialize it as a simple string.
nsAutoString nodeValue;
nsXFormsUtils::GetNodeValue(mSubmissionBody, nodeValue);
// make new stream
nsCOMPtr<nsIStringInputStream> stringInput =
do_CreateInstance("@mozilla.org/io/string-input-stream;1");
NS_ENSURE_TRUE(stringInput, NS_ERROR_OUT_OF_MEMORY);
nsCAutoString submissionBody = NS_ConvertUTF16toUTF8(nodeValue);
nsresult rv = stringInput->SetData(submissionBody.get(),
submissionBody.Length());
NS_ENSURE_SUCCESS(rv, rv);
stream = stringInput;
contentType.AssignLiteral("application/xml");
rv = NS_OK;
} else {
// Serialize a document based on the submission format and content type.
rv = SerializeData(submissionDoc, uri, getter_AddRefs(stream), contentType);
}
if (NS_FAILED(rv)) {
nsXFormsUtils::ReportError(NS_LITERAL_STRING("warnSubmitSerializeFailed"),
mElement, nsIScriptError::warningFlag);
@ -801,6 +914,13 @@ nsXFormsSubmissionElement::GetSubmissionURI(nsACString& aURI)
nsXFormsUtils::ReportError(NS_LITERAL_STRING("warnSubmitURI"), mElement,
nsIScriptError::warningFlag);
// Context Info: 'resource-uri'
nsCOMPtr<nsXFormsContextInfo> contextInfo =
new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetStringValue("resource-uri", uri);
mContextInfo.AppendObject(contextInfo);
CopyUTF16toUTF8(uri, aURI);
return rv;
@ -1558,6 +1678,7 @@ nsXFormsSubmissionElement::CopyChildren(nsIModelElementPrivate *aModel,
// abort
nsXFormsUtils::ReportError(NS_LITERAL_STRING("warnSubmitInvalidNode"),
currentNode, nsIScriptError::warningFlag);
mSubmitError = kError_ValidationError;
return NS_ERROR_ILLEGAL_VALUE;
}
@ -1593,6 +1714,7 @@ nsXFormsSubmissionElement::CopyChildren(nsIModelElementPrivate *aModel,
// abort
nsXFormsUtils::ReportError(NS_LITERAL_STRING("warnSubmitInvalidNode"),
currentNode, nsIScriptError::warningFlag);
mSubmitError = kError_ValidationError;
return NS_ERROR_ILLEGAL_VALUE;
}
@ -2476,6 +2598,232 @@ nsXFormsSubmissionElement::SendData(const nsCString &uriSpec,
return rv;
}
// nsIHttpHeaderVisitor
NS_IMETHODIMP
nsXFormsSubmissionElement::VisitHeader(const nsACString &aHeader,
const nsACString &aValue)
{
nsresult rv;
nsCOMPtr<nsIDOMElement> rootElt;
nsCOMPtr<nsIDOMNode> newChild;
// Every time this callback is called, we add another
// <header><name>aHeader</name><value>aValue</value></header> element
// to the http header document. The header document is used to create
// a nodeset of header elements in the context info.
if (!mHttpHeaderDoc) {
nsCOMPtr<nsIDOMDocument> doc;
rv = mElement->GetOwnerDocument(getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMDOMImplementation> domImpl;
rv = doc->GetImplementation(getter_AddRefs(domImpl));
NS_ENSURE_SUCCESS(rv, rv);
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mHttpHeaderDoc));
NS_ENSURE_SUCCESS(rv, rv);
rv = mHttpHeaderDoc->CreateElement(NS_LITERAL_STRING("headers"),
getter_AddRefs(rootElt));
NS_ENSURE_SUCCESS(rv, rv);
mHttpHeaderDoc->AppendChild(rootElt, getter_AddRefs(newChild));
}
nsCOMPtr<nsIDOMElement> headerElt, nameElt, valueElt;
nsCOMPtr<nsIDOMNode> rootNode;
// Root <headers> element.
rv = mHttpHeaderDoc->GetFirstChild(getter_AddRefs(rootNode));
NS_ENSURE_SUCCESS(rv, rv);
// <header>
rv = mHttpHeaderDoc->CreateElement(NS_LITERAL_STRING("header"),
getter_AddRefs(headerElt));
// <name>
rv = mHttpHeaderDoc->CreateElement(NS_LITERAL_STRING("name"),
getter_AddRefs(nameElt));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMText> nameTextNode;
rv = mHttpHeaderDoc->CreateTextNode(NS_ConvertUTF8toUTF16(aHeader),
getter_AddRefs(nameTextNode));
NS_ENSURE_SUCCESS(rv, rv);
nameElt->AppendChild(nameTextNode, getter_AddRefs(newChild));
headerElt->AppendChild(nameElt, getter_AddRefs(newChild));
// <value>
rv = mHttpHeaderDoc->CreateElement(NS_LITERAL_STRING("value"),
getter_AddRefs(valueElt));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMText> valueTextNode;
rv = mHttpHeaderDoc->CreateTextNode(NS_ConvertUTF8toUTF16(aValue),
getter_AddRefs(valueTextNode));
NS_ENSURE_SUCCESS(rv, rv);
valueElt->AppendChild(valueTextNode, getter_AddRefs(newChild));
headerElt->AppendChild(valueElt, getter_AddRefs(newChild));
// Append <header> element to root <headers> element.
rootElt = do_QueryInterface(rootNode);
rootElt->AppendChild(headerElt, getter_AddRefs(newChild));
return NS_OK;
}
nsresult
nsXFormsSubmissionElement::SetContextInfo()
{
return NS_OK;
}
nsresult
nsXFormsSubmissionElement::SetHttpContextInfo(PRUint32 aResponse,
nsAString &aResponseText)
{
nsresult rv;
nsCOMPtr<nsXFormsContextInfo> contextInfo = new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
// response-status-code
if (aResponse > 0) {
contextInfo->SetNumberValue("response-status-code", aResponse);
mContextInfo.AppendObject(contextInfo);
}
// response-reason-phrase
contextInfo = new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetStringValue("response-reason-phrase", aResponseText);
mContextInfo.AppendObject(contextInfo);
// response-headers
if (mHttpHeaderDoc) {
nsCOMPtr<nsIDOMNode> rootNode;
rv = mHttpHeaderDoc->GetFirstChild(getter_AddRefs(rootNode));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMXPathResult> headerNodeset;
nsAutoString expr;
expr.AssignLiteral("header");
rv = nsXFormsUtils::EvaluateXPath(expr, rootNode, rootNode,
nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
getter_AddRefs(headerNodeset));
NS_ENSURE_SUCCESS(rv, rv);
if (headerNodeset) {
contextInfo = new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetNodesetValue("response-headers", headerNodeset);
mContextInfo.AppendObject(contextInfo);
#ifdef DEBUG
PRUint32 nodesetSize = 0;
headerNodeset->GetSnapshotLength(&nodesetSize);
for (PRUint32 i = 0; i < nodesetSize; i++) {
nsCOMPtr<nsIDOMNode> headerNode, nameNode, valueNode;
headerNodeset->SnapshotItem(i, getter_AddRefs(headerNode));
headerNode->GetFirstChild(getter_AddRefs(nameNode));
nsAutoString name, value;
nsXFormsUtils::GetNodeValue(nameNode, name);
nameNode->GetNextSibling(getter_AddRefs(valueNode));
nsXFormsUtils::GetNodeValue(valueNode, value);
}
}
#endif // DEBUG
}
return NS_OK;
}
nsresult
nsXFormsSubmissionElement::ParseErrorResponse(nsIChannel *aChannel)
{
// Context Info: response-body
// When the error response specifies an XML media type as defined by
// RFC 3023], the response body is parsed into an XML document and the
// root element of the document is returned. If the parse fails, or if
// the error response specifies a text media type (starting with text/),
// then the response body is returned as a string.
// Otherwise, an empty string is returned.
nsCString contentCharset, contentType;
aChannel->GetContentCharset(contentCharset);
aChannel->GetContentType(contentType);
// use DOM parser to construct nsIDOMDocument
nsCOMPtr<nsIDOMParser> parser =
do_CreateInstance("@mozilla.org/xmlextras/domparser;1");
NS_ENSURE_STATE(parser);
PRUint32 contentLength;
mPipeIn->Available(&contentLength);
// set the base uri so that the document can get the correct security
// principal.
nsCOMPtr<nsIURI> uri;
nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(mElement);
nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
NS_ENSURE_STATE(doc);
NS_ENSURE_STATE(doc->GetScriptGlobalObject());
rv = parser->Init(nsnull, uri, nsnull, doc->GetScriptGlobalObject());
NS_ENSURE_SUCCESS(rv, rv);
// Try to parse the content into an XML document. If the parse fails, the
// content type is not an XML type that ParseFromStream can handle. In that
// case, read the response as a simple string.
nsCOMPtr<nsXFormsContextInfo> contextInfo;
nsCOMPtr<nsIDOMDocument> newDoc;
rv = parser->ParseFromStream(mPipeIn, contentCharset.get(), contentLength,
contentType.get(), getter_AddRefs(newDoc));
if (NS_SUCCEEDED(rv)) {
// Succeeded in parsing the error response as an XML document.
nsCOMPtr<nsIDOMNode> responseBody = do_QueryInterface(newDoc);
if (newDoc) {
contextInfo = new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetNodeValue("response-body", responseBody);
mContextInfo.AppendObject(contextInfo);
}
} else {
// Read the content as a simple string and set a string into the
// context info.
PRUint32 len, read, numReadIn = 1;
nsCAutoString responseBody;
rv = mPipeIn->Available(&len);
NS_ENSURE_SUCCESS(rv, rv);
char *buf = new char[len+1];
NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
memset(buf, 0, len+1);
// Read returns 0 if eos
while (numReadIn != 0) {
numReadIn = mPipeIn->Read(buf, len, &read);
responseBody.Append(buf);
}
delete [] buf;
// Set the string response body as context info.
contextInfo = new nsXFormsContextInfo(mElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetStringValue("response-body",
NS_ConvertUTF8toUTF16(responseBody));
mContextInfo.AppendObject(contextInfo);
}
return NS_OK;
}
// factory constructor
nsresult

Просмотреть файл

@ -21,6 +21,7 @@
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
* Merle Sterling <msterlin@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -49,6 +50,8 @@
#include "nsIChannelEventSink.h"
#include "nsIInterfaceRequestor.h"
#include "nsIDocument.h"
#include "nsIHttpHeaderVisitor.h"
#include "nsIXFormsContextInfo.h"
#include "nsDataHashtable.h"
@ -71,7 +74,8 @@ class nsXFormsSubmissionElement : public nsXFormsStubElement,
public nsIRequestObserver,
public nsIXFormsSubmissionElement,
public nsIChannelEventSink,
public nsIInterfaceRequestor
public nsIInterfaceRequestor,
public nsIHttpHeaderVisitor
{
public:
NS_DECL_ISUPPORTS_INHERITED
@ -79,13 +83,15 @@ public:
NS_DECL_NSIXFORMSSUBMISSIONELEMENT
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIHTTPHEADERVISITOR
nsXFormsSubmissionElement()
: nsXFormsStubElement(),
mSubmissionActive(PR_FALSE),
mIsReplaceInstance(PR_FALSE),
mIsSOAPRequest(PR_FALSE),
mFormat(0)
mFormat(0),
mSubmissionBody(nsnull)
{}
// nsIXTFElement overrides
@ -156,6 +162,15 @@ private:
// input end of pipe, which contains response data.
nsCOMPtr<nsIAsyncInputStream> mPipeIn;
// Context Info for events.
nsCOMArray<nsIXFormsContextInfo> mContextInfo;
// Document for http header context info.
nsCOMPtr<nsIDOMDocument> mHttpHeaderDoc;
// Submission body from xforms-submit-serialize.
nsIDOMNode* mSubmissionBody;
// Type of submit error.
nsString mSubmitError;
/**
* @return true if aTestURI has the same origin as aBaseURI or if
* there is no need for a same origin check.
@ -198,6 +213,21 @@ private:
*/
nsresult CreateAttachments(nsIModelElementPrivate *aModel, nsIDOMNode *aDoc,
SubmissionAttachmentArray *aAttachments);
/**
* Set context info.
*/
nsresult SetContextInfo();
/**
* Set Http context info.
*
* @param aResponse Protocol response code
* @param aResponseText Protocol response reason phrase
*/
nsresult SetHttpContextInfo(PRUint32 aResponse, nsAString &aResponseText);
nsresult ParseErrorResponse(nsIChannel *aChannel);
};
NS_HIDDEN_(nsresult)

Просмотреть файл

@ -124,7 +124,7 @@
#define CANCELABLE 0x01
#define BUBBLES 0x02
const EventData sXFormsEventsEntries[42] = {
const EventData sXFormsEventsEntries[43] = {
{ "xforms-model-construct", PR_FALSE, PR_TRUE },
{ "xforms-model-construct-done", PR_FALSE, PR_TRUE },
{ "xforms-ready", PR_FALSE, PR_TRUE },
@ -166,7 +166,8 @@ const EventData sXFormsEventsEntries[42] = {
{ "xforms-link-exception", PR_FALSE, PR_TRUE },
{ "xforms-link-error", PR_FALSE, PR_TRUE },
{ "xforms-compute-exception", PR_FALSE, PR_TRUE },
{ "xforms-moz-hint-off", PR_FALSE, PR_TRUE }
{ "xforms-moz-hint-off", PR_FALSE, PR_TRUE },
{ "xforms-submit-serialize", PR_FALSE, PR_TRUE }
};
static const EventData sEventDefaultsEntries[] = {
@ -222,6 +223,7 @@ struct EventItem
nsXFormsEvent event;
nsCOMPtr<nsIDOMNode> eventTarget;
nsCOMPtr<nsIDOMElement> srcElement;
nsCOMArray<nsIXFormsContextInfo> *contextInfo;
};
static PRBool gExperimentalFeaturesEnabled = PR_FALSE;
@ -627,7 +629,21 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
nsCOMPtr<nsIModelElementPrivate> modelPriv =
nsXFormsUtils::GetModel(resolverElement);
nsCOMPtr<nsIDOMNode> model = do_QueryInterface(modelPriv);
DispatchEvent(model, eEvent_ComputeException, nsnull, resolverElement);
// Context Info: 'error-message'
// Error message containing the expression being processed.
nsAutoString errorMsg;
errorMsg.AssignLiteral("Error evaluating expression: ");
errorMsg.Append(aExpression);
nsCOMPtr<nsXFormsContextInfo> contextInfo =
new nsXFormsContextInfo(resolverElement);
NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY);
contextInfo->SetStringValue("error-message", errorMsg);
nsCOMArray<nsIXFormsContextInfo> contextInfoArray;
contextInfoArray.AppendObject(contextInfo);
DispatchEvent(model, eEvent_ComputeException, nsnull, resolverElement,
&contextInfoArray);
}
return rv;
@ -972,7 +988,8 @@ nsXFormsUtils::GetSingleNodeBindingValue(nsIDOMElement* aElement,
nsresult
DispatchXFormsEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
PRBool *aDefaultActionEnabled)
PRBool *aDefaultActionEnabled,
nsCOMArray<nsIXFormsContextInfo> *aContextInfo)
{
nsCOMPtr<nsIDOMDocument> domDoc;
aTarget->GetOwnerDocument(getter_AddRefs(domDoc));
@ -992,8 +1009,12 @@ DispatchXFormsEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
nsXFormsUtils::SetEventTrusted(event, aTarget);
// Create an nsXFormsDOMEvent with the context info for the event.
nsCOMPtr<nsIXFormsDOMEvent> xfDOMEvent = new nsXFormsDOMEvent(event, aContextInfo);
NS_ENSURE_TRUE(xfDOMEvent, NS_ERROR_OUT_OF_MEMORY);
PRBool defaultActionEnabled = PR_TRUE;
nsresult rv = target->DispatchEvent(event, &defaultActionEnabled);
nsresult rv = target->DispatchEvent(xfDOMEvent, &defaultActionEnabled);
if (NS_SUCCEEDED(rv) && aDefaultActionEnabled)
*aDefaultActionEnabled = defaultActionEnabled;
@ -1025,6 +1046,10 @@ DispatchXFormsEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
break;
}
// Clear the context info array before the next event.
if (aContextInfo)
aContextInfo->Clear();
return rv;
}
@ -1047,7 +1072,8 @@ DeleteVoidArray(void *aObject,
nsresult
DeferDispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
nsIDOMElement *aSrcElement)
nsIDOMElement *aSrcElement,
nsCOMArray<nsIXFormsContextInfo> *aContextInfo)
{
nsCOMPtr<nsIDOMDocument> domDoc;
if (aTarget) {
@ -1077,6 +1103,7 @@ DeferDispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
deferredEvent->event = aEvent;
deferredEvent->eventTarget = aTarget;
deferredEvent->srcElement = aSrcElement;
deferredEvent->contextInfo = aContextInfo;
eventList->AppendElement(deferredEvent);
return NS_OK;
@ -1085,7 +1112,8 @@ DeferDispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
/* static */ nsresult
nsXFormsUtils::DispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
PRBool *aDefaultActionEnabled,
nsIDOMElement *aSrcElement)
nsIDOMElement *aSrcElement,
nsCOMArray<nsIXFormsContextInfo> *aContextInfo)
{
// it is valid to have aTarget be null if this is an event that must be
// targeted at a model per spec and aSrcElement is non-null. Basically we
@ -1139,7 +1167,7 @@ nsXFormsUtils::DispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
// model later when the DOM is finished loading
if (!aTarget) {
if (aSrcElement) {
DeferDispatchEvent(aTarget, aEvent, aSrcElement);
DeferDispatchEvent(aTarget, aEvent, aSrcElement, aContextInfo);
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -1151,7 +1179,7 @@ nsXFormsUtils::DispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
PRBool safeToSendEvent = PR_FALSE;
modelPriv->GetHasDOMContentFired(&safeToSendEvent);
if (!safeToSendEvent) {
DeferDispatchEvent(aTarget, aEvent, nsnull);
DeferDispatchEvent(aTarget, aEvent, nsnull, aContextInfo);
return NS_OK;
}
@ -1193,7 +1221,7 @@ nsXFormsUtils::DispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
PRBool safeToSendEvent = PR_FALSE;
modelPriv->GetHasDOMContentFired(&safeToSendEvent);
if (!safeToSendEvent) {
DeferDispatchEvent(aTarget, aEvent, nsnull);
DeferDispatchEvent(aTarget, aEvent, nsnull, aContextInfo);
return NS_OK;
}
@ -1203,7 +1231,7 @@ nsXFormsUtils::DispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
break;
}
return DispatchXFormsEvent(aTarget, aEvent, aDefaultActionEnabled);
return DispatchXFormsEvent(aTarget, aEvent, aDefaultActionEnabled, aContextInfo);
}
@ -1259,7 +1287,7 @@ nsXFormsUtils::DispatchDeferredEvents(nsIDOMDocument* aDocument)
NS_ENSURE_STATE(item->eventTarget);
}
DispatchXFormsEvent(item->eventTarget, item->event, nsnull);
DispatchXFormsEvent(item->eventTarget, item->event, nsnull, item->contextInfo);
}
doc->DeleteProperty(nsXFormsAtoms::deferredEventListProperty);

Просмотреть файл

@ -51,6 +51,7 @@
#include "nsVoidArray.h"
#include "nsIDOMWindowInternal.h"
#include "nsXFormsXPathState.h"
#include "nsXFormsDOMEvent.h"
class nsIDOMElement;
class nsIXFormsModelElement;
@ -146,7 +147,8 @@ enum nsXFormsEvent {
eEvent_LinkException,
eEvent_LinkError,
eEvent_ComputeException,
eEvent_MozHintOff
eEvent_MozHintOff,
eEvent_SubmitSerialize
};
struct EventData
@ -156,7 +158,7 @@ struct EventData
PRBool canBubble;
};
extern const EventData sXFormsEventsEntries[42];
extern const EventData sXFormsEventsEntries[43];
// Default intrinsic state for XForms Controls
extern const PRInt32 kDefaultIntrinsicState;
@ -358,7 +360,8 @@ public:
static NS_HIDDEN_(nsresult)
DispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
PRBool *aDefaultActionEnabled = nsnull,
nsIDOMElement *aSrcElement = nsnull);
nsIDOMElement *aSrcElement = nsnull,
nsCOMArray<nsIXFormsContextInfo> *aContextInfo = nsnull);
static NS_HIDDEN_(nsresult)
DispatchDeferredEvents(nsIDOMDocument* aDocument);

Просмотреть файл

@ -21,6 +21,7 @@
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
* Merle Sterling <msterlin@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -48,6 +49,8 @@
#include "txIFunctionEvaluationContext.h"
#include "txINodeSet.h"
#include "nsIClassInfoImpl.h"
#include "nsIXFormsActionModuleElement.h"
#include "nsIXFormsContextInfo.h"
#define NS_NAMESPACE_XFORMS "http://www.w3.org/2002/xforms"
@ -457,3 +460,86 @@ nsXFormsXPathFunctions::Current(txIFunctionEvaluationContext *aContext,
return NS_OK;
}
NS_IMETHODIMP
nsXFormsXPathFunctions::Event(txIFunctionEvaluationContext *aContext,
const nsAString &aName,
txINodeSet **aResult)
{
*aResult = nsnull;
nsresult rv;
nsCOMPtr<nsIXFormsXPathState> state;
aContext->GetState(getter_AddRefs(state));
nsCOMPtr<nsIDOMNode> xfNode;
state->GetXformsNode(getter_AddRefs(xfNode));
NS_ENSURE_TRUE(xfNode, NS_ERROR_FAILURE);
nsCOMPtr<txINodeSet> result =
do_CreateInstance("@mozilla.org/transformiix-nodeset;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXFormsContextInfo> contextInfo;
nsCOMPtr<nsIXFormsActionModuleElement> actionElt = do_QueryInterface(xfNode);
if (actionElt) {
nsCOMPtr<nsIDOMEvent> domEvent;
actionElt->GetCurrentEvent(getter_AddRefs(domEvent));
nsCOMPtr<nsIXFormsDOMEvent> xfEvent = do_QueryInterface(domEvent);
if (!xfEvent) {
// Event being called for an nsIDOMEvent that is not an
// nsIXFormsDOMEvent.
result.swap(*aResult);
return NS_OK;
}
xfEvent->GetContextInfo(aName, getter_AddRefs(contextInfo));
if (!contextInfo) {
// The requested context info property does not exist.
result.swap(*aResult);
return NS_OK;
}
}
// Determine the type of context info property.
PRInt32 resultType;
contextInfo->GetType(&resultType);
if (resultType == nsIXFormsContextInfo::NODESET_TYPE) {
// The context property is a nodeset. Snapshot each individual node
// in the nodeset and add them one at a time to the txINodeset.
nsCOMPtr<nsIDOMXPathResult> nodeset;
contextInfo->GetNodesetValue(getter_AddRefs(nodeset));
if (nodeset) {
PRUint32 nodesetSize;
rv = nodeset->GetSnapshotLength(&nodesetSize);
NS_ENSURE_SUCCESS(rv, rv);
for (PRUint32 i=0; i < nodesetSize; ++i) {
nsCOMPtr<nsIDOMNode> node;
nodeset->SnapshotItem(i, getter_AddRefs(node));
result->Add(node);
}
}
} else {
// The type is a dom node, string, or number. Strings and numbers
// are encapsulated in a text node.
nsCOMPtr<nsIDOMNode> node;
contextInfo->GetNodeValue(getter_AddRefs(node));
if (node) {
result->Add(node);
}
#ifdef DEBUG
PRInt32 type;
contextInfo->GetType(&type);
if (type == nsXFormsContextInfo::STRING_TYPE) {
nsAutoString str;
contextInfo->GetStringValue(str);
} else if (type == nsXFormsContextInfo::NUMBER_TYPE) {
PRInt32 number;
contextInfo->GetNumberValue(&number);
}
#endif
}
result.swap(*aResult);
return NS_OK;
}