зеркало из https://github.com/mozilla/gecko-dev.git
Bug 275453 - Finish <upload> implementation. r=allan, r=aaronr. Not part of default build.
This commit is contained in:
Родитель
e01ea0902e
Коммит
2f5b9ff526
|
@ -97,6 +97,7 @@ REQUIRES = \
|
||||||
intl \
|
intl \
|
||||||
pref \
|
pref \
|
||||||
htmlparser \
|
htmlparser \
|
||||||
|
exthandler \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# XForms IDLs
|
# XForms IDLs
|
||||||
|
@ -123,6 +124,8 @@ XPIDLSRCS = \
|
||||||
nsIXFormsItemElement.idl \
|
nsIXFormsItemElement.idl \
|
||||||
nsIXFormsLabelElement.idl \
|
nsIXFormsLabelElement.idl \
|
||||||
nsIXFormsItemSetUIElement.idl \
|
nsIXFormsItemSetUIElement.idl \
|
||||||
|
nsIXFormsUploadElement.idl \
|
||||||
|
nsIXFormsUploadUIElement.idl \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# XForms source files
|
# XForms source files
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla XForms support.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* IBM Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Javier Pedemonte <jhpedemonte@gmail.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of 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"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface implemented by the XTF part of the upload element to allow
|
||||||
|
* communication from XBL code.
|
||||||
|
*/
|
||||||
|
[scriptable, uuid(6dc00fd0-674c-41b3-8b0b-ba6c02aa769a)]
|
||||||
|
interface nsIXFormsUploadElement : nsISupports
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display file picker dialog so user can select a file.
|
||||||
|
*/
|
||||||
|
void pickFile();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unset file from \<upload\> and instance data.
|
||||||
|
*/
|
||||||
|
void clearFile();
|
||||||
|
};
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla XForms support.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* IBM Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Javier Pedemonte <jhpedemonte@gmail.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of 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"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface implemented by the XBL part of the upload element.
|
||||||
|
*/
|
||||||
|
[scriptable, uuid(82c82c46-f111-416c-a3e6-ce9a0864d00f)]
|
||||||
|
interface nsIXFormsUploadUIElement : nsISupports
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Set text value of \<upload\>'s text field.
|
||||||
|
*/
|
||||||
|
void setFieldText(in AString value);
|
||||||
|
};
|
|
@ -315,17 +315,6 @@ nsXFormsControlStubBase::ResetHelpAndHint(PRBool aInitialize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
|
||||||
nsXFormsControlStubBase::GetReadOnlyState()
|
|
||||||
{
|
|
||||||
PRBool res = PR_FALSE;
|
|
||||||
nsCOMPtr<nsIContent> content(do_QueryInterface(mElement));
|
|
||||||
if (content && (content->IntrinsicState() & NS_EVENT_STATE_MOZ_READONLY)) {
|
|
||||||
res = PR_TRUE;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsXFormsControlStubBase::GetRelevantState()
|
nsXFormsControlStubBase::GetRelevantState()
|
||||||
{
|
{
|
||||||
|
|
|
@ -178,9 +178,6 @@ protected:
|
||||||
*/
|
*/
|
||||||
PRInt32 mBindAttrsCount;
|
PRInt32 mBindAttrsCount;
|
||||||
|
|
||||||
/** Returns the read only state of the control (ie. mBoundNode) */
|
|
||||||
PRBool GetReadOnlyState();
|
|
||||||
|
|
||||||
/** Returns the relevant state of the control */
|
/** Returns the relevant state of the control */
|
||||||
PRBool GetRelevantState();
|
PRBool GetRelevantState();
|
||||||
|
|
||||||
|
|
|
@ -1289,8 +1289,8 @@ nsXFormsSubmissionElement::CopyChildren(nsIDOMNode *source, nsIDOMNode *dest,
|
||||||
nsCOMPtr<nsIContent> content = do_QueryInterface(currentNode);
|
nsCOMPtr<nsIContent> content = do_QueryInterface(currentNode);
|
||||||
NS_ENSURE_STATE(content);
|
NS_ENSURE_STATE(content);
|
||||||
|
|
||||||
nsILocalFile *file =
|
nsIFile *file =
|
||||||
NS_STATIC_CAST(nsILocalFile *,
|
NS_STATIC_CAST(nsIFile *,
|
||||||
content->GetProperty(nsXFormsAtoms::uploadFileProperty));
|
content->GetProperty(nsXFormsAtoms::uploadFileProperty));
|
||||||
// NOTE: this value may be null if a file hasn't been selected.
|
// NOTE: this value may be null if a file hasn't been selected.
|
||||||
|
|
||||||
|
@ -1655,8 +1655,8 @@ nsXFormsSubmissionElement::AppendMultipartFormData(nsIDOMNode *data,
|
||||||
nsCOMPtr<nsIContent> content = do_QueryInterface(data);
|
nsCOMPtr<nsIContent> content = do_QueryInterface(data);
|
||||||
NS_ENSURE_STATE(content);
|
NS_ENSURE_STATE(content);
|
||||||
|
|
||||||
nsILocalFile *file =
|
nsIFile *file =
|
||||||
NS_STATIC_CAST(nsILocalFile *,
|
NS_STATIC_CAST(nsIFile *,
|
||||||
content->GetProperty(nsXFormsAtoms::uploadFileProperty));
|
content->GetProperty(nsXFormsAtoms::uploadFileProperty));
|
||||||
|
|
||||||
nsAutoString leafName;
|
nsAutoString leafName;
|
||||||
|
|
|
@ -36,26 +36,142 @@
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#include "nsIDOMEventTarget.h"
|
#include "nsIXFormsUploadElement.h"
|
||||||
#include "nsIDOM3Node.h"
|
#include "nsIXFormsUploadUIElement.h"
|
||||||
#include "nsIDOMElement.h"
|
|
||||||
#include "nsMemory.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
#include "nsIXTFXMLVisualWrapper.h"
|
|
||||||
#include "nsIDOMDocument.h"
|
|
||||||
#include "nsXFormsControlStub.h"
|
|
||||||
#include "nsISchema.h"
|
|
||||||
#include "nsIDOMHTMLInputElement.h"
|
|
||||||
#include "nsXFormsAtoms.h"
|
|
||||||
#include "nsAutoPtr.h"
|
|
||||||
#include "nsIDOMXPathResult.h"
|
|
||||||
#include "nsIDOMFocusListener.h"
|
|
||||||
#include "nsXFormsUtils.h"
|
#include "nsXFormsUtils.h"
|
||||||
#include "nsIModelElementPrivate.h"
|
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsIDOMXPathExpression.h"
|
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
|
#include "nsXFormsDelegateStub.h"
|
||||||
|
#include "nsIMIMEService.h"
|
||||||
|
#include "nsCExternalHandlerService.h"
|
||||||
|
#include "plbase64.h"
|
||||||
|
#include "nsIFilePicker.h"
|
||||||
|
#include "nsIDOMDocument.h"
|
||||||
|
#include "nsIDOMDocumentView.h"
|
||||||
|
#include "nsIDOMAbstractView.h"
|
||||||
|
#include "nsIDOMWindowInternal.h"
|
||||||
|
#include "nsIStringBundle.h"
|
||||||
|
#include "nsIDOM3Node.h"
|
||||||
|
#include "nsAutoBuffer.h"
|
||||||
|
#include "nsIEventStateManager.h"
|
||||||
|
#include "prmem.h"
|
||||||
|
|
||||||
|
#define NS_HTMLFORM_BUNDLE_URL \
|
||||||
|
"chrome://global/locale/layout/HtmlForm.properties"
|
||||||
|
|
||||||
|
|
||||||
|
enum nsBoundType {
|
||||||
|
TYPE_DEFAULT,
|
||||||
|
TYPE_ANYURI,
|
||||||
|
TYPE_BASE64,
|
||||||
|
TYPE_HEX
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the \<upload\> element.
|
||||||
|
*/
|
||||||
|
class nsXFormsUploadElement : public nsXFormsDelegateStub,
|
||||||
|
public nsIXFormsUploadElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_DECL_NSIXFORMSUPLOADELEMENT
|
||||||
|
|
||||||
|
NS_IMETHOD Refresh();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Returns the type of the node to which this element is bound.
|
||||||
|
*/
|
||||||
|
nsBoundType GetBoundType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets file path/contents into instance data. If aFile is nsnull,
|
||||||
|
* this clears the data.
|
||||||
|
*/
|
||||||
|
nsresult SetFile(nsILocalFile *aFile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets "filename" & "mediatype" in the instance data, using the given file.
|
||||||
|
* If aFile == nsnull, then this function clears the values in the
|
||||||
|
* instance data.
|
||||||
|
*/
|
||||||
|
nsresult HandleChildElements(nsILocalFile *aFile, PRBool *aChanged);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the contents of the file and encode in Base64 or Hex. |aResult| must
|
||||||
|
* be freed by nsMemory::Free().
|
||||||
|
*/
|
||||||
|
nsresult EncodeFileContents(nsIFile *aFile, nsBoundType aType,
|
||||||
|
PRUnichar **aResult);
|
||||||
|
|
||||||
|
void BinaryToHex(const char *aBuffer, PRUint32 aCount,
|
||||||
|
PRUnichar **aHexString);
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS_INHERITED1(nsXFormsUploadElement,
|
||||||
|
nsXFormsDelegateStub,
|
||||||
|
nsIXFormsUploadElement)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsUploadElement::Refresh()
|
||||||
|
{
|
||||||
|
// This is called when the 'bind', 'ref' or 'model' attribute has changed.
|
||||||
|
// So we need to make sure that the element is still bound to a node of
|
||||||
|
// type 'anyURI', 'base64Binary', or 'hexBinary'.
|
||||||
|
|
||||||
|
nsresult rv = nsXFormsDelegateStub::Refresh();
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (!mBoundNode)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
// If it is not bound to 'anyURI', 'base64Binary', or 'hexBinary', then
|
||||||
|
// mark as not relevant.
|
||||||
|
// XXX Bug 313313 - the 'relevant' state should be handled in XBL constructor.
|
||||||
|
nsCOMPtr<nsIXTFElementWrapper> xtfWrap(do_QueryInterface(mElement));
|
||||||
|
NS_ENSURE_STATE(xtfWrap);
|
||||||
|
if (GetBoundType() == TYPE_DEFAULT) {
|
||||||
|
xtfWrap->SetIntrinsicState(NS_EVENT_STATE_DISABLED);
|
||||||
|
nsXFormsUtils::ReportError(NS_LITERAL_STRING("uploadBoundTypeError"),
|
||||||
|
mElement);
|
||||||
|
} else {
|
||||||
|
xtfWrap->SetIntrinsicState(NS_EVENT_STATE_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsBoundType
|
||||||
|
nsXFormsUploadElement::GetBoundType()
|
||||||
|
{
|
||||||
|
nsBoundType result = TYPE_DEFAULT;
|
||||||
|
|
||||||
|
// get type bound to node
|
||||||
|
nsAutoString type, prefix, nsuri;
|
||||||
|
nsresult rv = nsXFormsUtils::ParseTypeFromNode(mBoundNode, type, prefix);
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
// get the namespace url from the prefix
|
||||||
|
nsCOMPtr<nsIDOM3Node> domNode3 = do_QueryInterface(mElement, &rv);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
rv = domNode3->LookupNamespaceURI(prefix, nsuri);
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv) && nsuri.EqualsLiteral(NS_NAMESPACE_XML_SCHEMA)) {
|
||||||
|
if (type.EqualsLiteral("anyURI")) {
|
||||||
|
result = TYPE_ANYURI;
|
||||||
|
} else if (type.EqualsLiteral("base64Binary")) {
|
||||||
|
result = TYPE_BASE64;
|
||||||
|
} else if (type.EqualsLiteral("hexBinary")) {
|
||||||
|
result = TYPE_HEX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ReleaseObject(void *aObject,
|
ReleaseObject(void *aObject,
|
||||||
|
@ -66,215 +182,153 @@ ReleaseObject(void *aObject,
|
||||||
NS_STATIC_CAST(nsISupports *, aPropertyValue)->Release();
|
NS_STATIC_CAST(nsISupports *, aPropertyValue)->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of the \<upload\> element.
|
|
||||||
*/
|
|
||||||
class nsXFormsUploadElement : public nsIDOMFocusListener,
|
|
||||||
public nsXFormsControlStub
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
|
|
||||||
// nsIXTFXMLVisual overrides
|
|
||||||
NS_IMETHOD OnCreated(nsIXTFXMLVisualWrapper *aWrapper);
|
|
||||||
|
|
||||||
// nsIXTFVisual overrides
|
|
||||||
NS_IMETHOD GetVisualContent(nsIDOMElement **aElement);
|
|
||||||
NS_IMETHOD GetInsertionPoint(nsIDOMElement **aPoint);
|
|
||||||
|
|
||||||
// nsIXTFElement overrides
|
|
||||||
NS_IMETHOD OnDestroyed();
|
|
||||||
NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue);
|
|
||||||
NS_IMETHOD AttributeRemoved(nsIAtom *aName);
|
|
||||||
|
|
||||||
// nsIXFormsControl
|
|
||||||
NS_IMETHOD Refresh();
|
|
||||||
NS_IMETHOD TryFocus(PRBool* aOK);
|
|
||||||
|
|
||||||
// nsIDOMEventListener
|
|
||||||
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
|
|
||||||
|
|
||||||
// nsIDOMFocusListener
|
|
||||||
NS_IMETHOD Focus(nsIDOMEvent *aEvent);
|
|
||||||
NS_IMETHOD Blur(nsIDOMEvent *aEvent);
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsCOMPtr<nsIDOMElement> mLabel;
|
|
||||||
nsCOMPtr<nsIDOMHTMLInputElement> mInput;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsUploadElement,
|
|
||||||
nsXFormsControlStub,
|
|
||||||
nsIDOMFocusListener,
|
|
||||||
nsIDOMEventListener)
|
|
||||||
|
|
||||||
// nsIXTFXMLVisual
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXFormsUploadElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper)
|
nsXFormsUploadElement::PickFile()
|
||||||
{
|
{
|
||||||
nsresult rv = nsXFormsControlStub::OnCreated(aWrapper);
|
if (!mElement)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
// get localized file picker title text
|
||||||
|
nsCOMPtr<nsIStringBundleService> bundleService =
|
||||||
|
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
nsCOMPtr<nsIStringBundle> bundle;
|
||||||
|
rv = bundleService->CreateBundle(NS_HTMLFORM_BUNDLE_URL,
|
||||||
|
getter_AddRefs(bundle));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
nsXPIDLString filepickerTitle;
|
||||||
|
rv = bundle->GetStringFromName(NS_LITERAL_STRING("FileUpload").get(),
|
||||||
|
getter_Copies(filepickerTitle));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
// fall back to English text
|
||||||
|
filepickerTitle.AssignASCII("File Upload");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get nsIDOMWindowInternal
|
||||||
|
nsCOMPtr<nsIDOMDocument> doc;
|
||||||
|
mElement->GetOwnerDocument(getter_AddRefs(doc));
|
||||||
|
nsCOMPtr<nsIDOMDocumentView> dview = do_QueryInterface(doc);
|
||||||
|
NS_ENSURE_STATE(dview);
|
||||||
|
nsCOMPtr<nsIDOMAbstractView> aview;
|
||||||
|
dview->GetDefaultView(getter_AddRefs(aview));
|
||||||
|
nsCOMPtr<nsIDOMWindowInternal> internal = do_QueryInterface(aview);
|
||||||
|
NS_ENSURE_STATE(internal);
|
||||||
|
|
||||||
|
// init filepicker
|
||||||
|
nsCOMPtr<nsIFilePicker> filePicker =
|
||||||
|
do_CreateInstance("@mozilla.org/filepicker;1");
|
||||||
|
if (!filePicker)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
rv = filePicker->Init(internal, filepickerTitle, nsIFilePicker::modeOpen);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Our anonymous content structure will look like this:
|
// set filter "All Files"
|
||||||
//
|
// XXX implement "@mediatype" file filters
|
||||||
// <label> (mLabel)
|
filePicker->AppendFilters(nsIFilePicker::filterAll);
|
||||||
// <span/> (insertion point)
|
|
||||||
// <input/> (mInput)
|
|
||||||
// </label>
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
// open dialog
|
||||||
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
|
PRInt16 mode;
|
||||||
|
rv = filePicker->Show(&mode);
|
||||||
domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
NS_LITERAL_STRING("label"),
|
if (mode == nsIFilePicker::returnCancel)
|
||||||
getter_AddRefs(mLabel));
|
|
||||||
NS_ENSURE_STATE(mLabel);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMElement> element;
|
|
||||||
nsCOMPtr<nsIDOMNode> childReturn;
|
|
||||||
|
|
||||||
domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
|
|
||||||
NS_LITERAL_STRING("span"),
|
|
||||||
getter_AddRefs(element));
|
|
||||||
NS_ENSURE_STATE(element);
|
|
||||||
|
|
||||||
mLabel->AppendChild(element, getter_AddRefs(childReturn));
|
|
||||||
|
|
||||||
domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
|
|
||||||
NS_LITERAL_STRING("input"),
|
|
||||||
getter_AddRefs(element));
|
|
||||||
mInput = do_QueryInterface(element);
|
|
||||||
NS_ENSURE_STATE(mInput);
|
|
||||||
|
|
||||||
mInput->SetType(NS_LITERAL_STRING("file"));
|
|
||||||
|
|
||||||
mLabel->AppendChild(mInput, getter_AddRefs(childReturn));
|
|
||||||
|
|
||||||
// We can't use xtf handleDefault here because editor stops blur events from
|
|
||||||
// bubbling, and we can't use a system event group handler because blur
|
|
||||||
// events don't go to the system event group (bug 263240). So, just install
|
|
||||||
// a bubbling listener in the normal event group. This works out because
|
|
||||||
// content can't get at the anonymous content to install an event handler,
|
|
||||||
// and the event doesn't bubble up.
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(mInput);
|
|
||||||
NS_ASSERTION(targ, "input must be an event target!");
|
|
||||||
|
|
||||||
targ->AddEventListener(NS_LITERAL_STRING("blur"), this, PR_FALSE);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXFormsUploadElement::AttributeSet(nsIAtom *aName, const nsAString &aValue)
|
|
||||||
{
|
|
||||||
if (aName == nsXFormsAtoms::accesskey) {
|
|
||||||
// accesskey
|
|
||||||
mInput->SetAttribute(NS_LITERAL_STRING("accesskey"), aValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXFormsUploadElement::AttributeRemoved(nsIAtom *aName)
|
|
||||||
{
|
|
||||||
if (aName == nsXFormsAtoms::accesskey) {
|
|
||||||
// accesskey
|
|
||||||
mInput->RemoveAttribute(NS_LITERAL_STRING("accesskey"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIXTFVisual
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXFormsUploadElement::GetVisualContent(nsIDOMElement **aElement)
|
|
||||||
{
|
|
||||||
NS_ADDREF(*aElement = mLabel);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXFormsUploadElement::GetInsertionPoint(nsIDOMElement **aPoint)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMNode> childNode;
|
|
||||||
mLabel->GetFirstChild(getter_AddRefs(childNode));
|
|
||||||
return CallQueryInterface(childNode, aPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIXTFElement
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXFormsUploadElement::OnDestroyed()
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(mInput);
|
|
||||||
if (NS_LIKELY(targ != nsnull)) {
|
|
||||||
targ->RemoveEventListener(NS_LITERAL_STRING("blur"), this, PR_FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nsXFormsControlStub::OnDestroyed();
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIDOMEventListener
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXFormsUploadElement::HandleEvent(nsIDOMEvent *aEvent)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXFormsUploadElement::Focus(nsIDOMEvent *aEvent)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXFormsUploadElement::Blur(nsIDOMEvent *aEvent)
|
|
||||||
{
|
|
||||||
if (!mInput || !mBoundNode || !mModel ||
|
|
||||||
!nsXFormsUtils::EventHandlingAllowed(aEvent, mElement))
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
nsAutoString value;
|
// file was selected
|
||||||
mInput->GetValue(value);
|
nsCOMPtr<nsILocalFile> localFile;
|
||||||
|
rv = filePicker->GetFile(getter_AddRefs(localFile));
|
||||||
|
if (localFile) {
|
||||||
|
// set path value in \<upload\>'s text field.
|
||||||
|
nsCOMPtr<nsIXFormsUploadUIElement> uiUpload = do_QueryInterface(mElement);
|
||||||
|
if (uiUpload) {
|
||||||
|
nsCAutoString spec;
|
||||||
|
NS_GetURLSpecFromFile(localFile, spec);
|
||||||
|
uiUpload->SetFieldText(NS_ConvertUTF8toUTF16(spec));
|
||||||
|
}
|
||||||
|
|
||||||
// store the file as a property on the selected content node. the submission
|
// set file into instance data
|
||||||
// code will read this value.
|
return SetFile(localFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsUploadElement::ClearFile()
|
||||||
|
{
|
||||||
|
// clear path value in \<upload\>'s text field.
|
||||||
|
nsCOMPtr<nsIXFormsUploadUIElement> uiUpload = do_QueryInterface(mElement);
|
||||||
|
if (uiUpload) {
|
||||||
|
uiUpload->SetFieldText(EmptyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear file from instance data
|
||||||
|
return SetFile(nsnull);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsXFormsUploadElement::SetFile(nsILocalFile *aFile)
|
||||||
|
{
|
||||||
|
if (!mBoundNode || !mModel)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mBoundNode);
|
nsCOMPtr<nsIContent> content = do_QueryInterface(mBoundNode);
|
||||||
NS_ENSURE_STATE(content);
|
NS_ENSURE_STATE(content);
|
||||||
|
|
||||||
nsILocalFile *file = nsnull;
|
PRBool dataChanged = PR_FALSE;
|
||||||
nsCAutoString spec;
|
if (!aFile) {
|
||||||
|
// clear instance data
|
||||||
// We need to special case an empty value. If the input field is blank,
|
|
||||||
// then I assume that the intention is that all bound nodes will become
|
|
||||||
// (or stay) empty and that there shouldn't be any file kept in the property.
|
|
||||||
if (!value.IsEmpty()) {
|
|
||||||
NS_NewLocalFile(value, PR_FALSE, &file);
|
|
||||||
NS_ENSURE_STATE(file);
|
|
||||||
NS_GetURLSpecFromFile(file, spec);
|
|
||||||
content->SetProperty(nsXFormsAtoms::uploadFileProperty, file,
|
|
||||||
ReleaseObject);
|
|
||||||
} else {
|
|
||||||
content->DeleteProperty(nsXFormsAtoms::uploadFileProperty);
|
content->DeleteProperty(nsXFormsAtoms::uploadFileProperty);
|
||||||
|
rv = mModel->SetNodeValue(mBoundNode, EmptyString(), &dataChanged);
|
||||||
|
} else {
|
||||||
|
// set file into instance data
|
||||||
|
|
||||||
|
nsBoundType type = GetBoundType();
|
||||||
|
if (type == TYPE_ANYURI) {
|
||||||
|
// set fully qualified path as value in instance data node
|
||||||
|
nsCAutoString spec;
|
||||||
|
NS_GetURLSpecFromFile(aFile, spec);
|
||||||
|
rv = mModel->SetNodeValue(mBoundNode, NS_ConvertUTF8toUTF16(spec),
|
||||||
|
&dataChanged);
|
||||||
|
} else if (type == TYPE_BASE64 || type == TYPE_HEX) {
|
||||||
|
// encode file contents in base64/hex and set into instance data node
|
||||||
|
PRUnichar *fileData;
|
||||||
|
rv = EncodeFileContents(aFile, type, &fileData);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
rv = mModel->SetNodeValue(mBoundNode, nsDependentString(fileData),
|
||||||
|
&dataChanged);
|
||||||
|
nsMemory::Free(fileData);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rv = NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX need to handle derived types
|
||||||
|
|
||||||
// update the instance data node. this value is never used by the submission
|
// Set nsIFile object as property on instance data node, so submission
|
||||||
// code. instead, it exists so that the instance data will appear to be in-
|
// code can use it.
|
||||||
// sync with what is actually submitted.
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
nsIFile *fileCopy = nsnull;
|
||||||
PRBool changed;
|
rv = aFile->Clone(&fileCopy);
|
||||||
nsresult rv = mModel->SetNodeValue(mBoundNode, NS_ConvertUTF8toUTF16(spec),
|
|
||||||
&changed);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
if (changed) {
|
rv = content->SetProperty(nsXFormsAtoms::uploadFileProperty, fileCopy,
|
||||||
|
ReleaseObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// Handle <filename> and <mediatype> children
|
||||||
|
PRBool childrenChanged;
|
||||||
|
rv = HandleChildElements(aFile, &childrenChanged);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (dataChanged || childrenChanged) {
|
||||||
nsCOMPtr<nsIDOMNode> model = do_QueryInterface(mModel);
|
nsCOMPtr<nsIDOMNode> model = do_QueryInterface(mModel);
|
||||||
|
|
||||||
if (model) {
|
if (model) {
|
||||||
rv = nsXFormsUtils::DispatchEvent(model, eEvent_Recalculate);
|
rv = nsXFormsUtils::DispatchEvent(model, eEvent_Recalculate);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
@ -284,42 +338,199 @@ nsXFormsUploadElement::Blur(nsIDOMEvent *aEvent)
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsIXFormsControl
|
nsresult
|
||||||
|
nsXFormsUploadElement::HandleChildElements(nsILocalFile *aFile,
|
||||||
NS_IMETHODIMP
|
PRBool *aChanged)
|
||||||
nsXFormsUploadElement::Refresh()
|
|
||||||
{
|
{
|
||||||
if (!mInput || !mBoundNode)
|
if (!aChanged) {
|
||||||
return NS_OK;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mBoundNode);
|
|
||||||
NS_ENSURE_STATE(content);
|
|
||||||
|
|
||||||
nsILocalFile *file =
|
|
||||||
NS_STATIC_CAST(nsILocalFile *,
|
|
||||||
content->GetProperty(nsXFormsAtoms::uploadFileProperty));
|
|
||||||
|
|
||||||
// get the text value for the control
|
|
||||||
nsAutoString value;
|
|
||||||
if (file)
|
|
||||||
file->GetPath(value);
|
|
||||||
|
|
||||||
mInput->SetValue(value);
|
|
||||||
mInput->SetReadOnly(GetReadOnlyState());
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
*aChanged = PR_FALSE;
|
||||||
|
|
||||||
NS_IMETHODIMP
|
// return immediately if we have no children
|
||||||
nsXFormsUploadElement::TryFocus(PRBool* aOK)
|
PRBool hasNodes;
|
||||||
|
mElement->HasChildNodes(&hasNodes);
|
||||||
|
if (!hasNodes)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
|
// look for the \<filename\> & \<mediatype\> elements in the
|
||||||
|
// \<upload\> children
|
||||||
|
nsCOMPtr<nsIDOMNode> filenameNode, mediatypeNode;
|
||||||
|
nsCOMPtr<nsIDOMNode> child, temp;
|
||||||
|
mElement->GetFirstChild(getter_AddRefs(child));
|
||||||
|
while (child && (!filenameNode || !mediatypeNode)) {
|
||||||
|
if (!filenameNode &&
|
||||||
|
nsXFormsUtils::IsXFormsElement(child,
|
||||||
|
NS_LITERAL_STRING("filename")))
|
||||||
{
|
{
|
||||||
*aOK = GetRelevantState() && nsXFormsUtils::FocusControl(mInput);
|
filenameNode = child;
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mediatypeNode &&
|
||||||
|
nsXFormsUtils::IsXFormsElement(child,
|
||||||
|
NS_LITERAL_STRING("mediatype")))
|
||||||
|
{
|
||||||
|
mediatypeNode = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp.swap(child);
|
||||||
|
temp->GetNextSibling(getter_AddRefs(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle "filename"
|
||||||
|
PRBool filenameChanged = PR_FALSE;
|
||||||
|
if (filenameNode) {
|
||||||
|
nsCOMPtr<nsIDOMElement> filenameElem = do_QueryInterface(filenameNode);
|
||||||
|
if (aFile) {
|
||||||
|
nsAutoString filename;
|
||||||
|
rv = aFile->GetLeafName(filename);
|
||||||
|
if (!filename.IsEmpty()) {
|
||||||
|
rv = nsXFormsUtils::SetSingleNodeBindingValue(filenameElem, filename,
|
||||||
|
&filenameChanged);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rv = nsXFormsUtils::SetSingleNodeBindingValue(filenameElem, EmptyString(),
|
||||||
|
&filenameChanged);
|
||||||
|
}
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle "mediatype"
|
||||||
|
PRBool mediatypechanged = PR_FALSE;
|
||||||
|
if (mediatypeNode) {
|
||||||
|
nsCOMPtr<nsIDOMElement> mediatypeElem = do_QueryInterface(mediatypeNode);
|
||||||
|
if (aFile) {
|
||||||
|
nsCOMPtr<nsIMIMEService> mimeService =
|
||||||
|
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
nsCAutoString contentType;
|
||||||
|
rv = mimeService->GetTypeFromFile(aFile, contentType);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
contentType.AssignLiteral("application/octet-stream");
|
||||||
|
}
|
||||||
|
rv = nsXFormsUtils::SetSingleNodeBindingValue(mediatypeElem,
|
||||||
|
NS_ConvertUTF8toUTF16(contentType), &mediatypechanged);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rv = nsXFormsUtils::SetSingleNodeBindingValue(mediatypeElem,
|
||||||
|
EmptyString(), &mediatypechanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*aChanged = filenameChanged || mediatypechanged;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef nsAutoBuffer<char, 256> nsAutoCharBuffer;
|
||||||
|
|
||||||
|
static void
|
||||||
|
ReportEncodingMemoryError(nsIDOMElement* aElement, nsIFile *aFile,
|
||||||
|
PRUint32 aFailedSize)
|
||||||
|
{
|
||||||
|
nsAutoString filename;
|
||||||
|
if (NS_FAILED(aFile->GetLeafName(filename))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString size;
|
||||||
|
size.AppendInt((PRInt64)aFailedSize);
|
||||||
|
const PRUnichar *strings[] = { filename.get(), size.get() };
|
||||||
|
nsXFormsUtils::ReportError(NS_LITERAL_STRING("encodingMemoryError"),
|
||||||
|
strings, 2, aElement, aElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsXFormsUploadElement::EncodeFileContents(nsIFile *aFile, nsBoundType aType,
|
||||||
|
PRUnichar **aResult)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
// get file contents
|
||||||
|
nsCOMPtr<nsIInputStream> fileStream;
|
||||||
|
rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), aFile,
|
||||||
|
PR_RDONLY, -1 /* no mode bits */,
|
||||||
|
nsIFileInputStream::CLOSE_ON_EOF);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
PRUint32 size;
|
||||||
|
rv = fileStream->Available(&size);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsAutoCharBuffer fileData;
|
||||||
|
if (!fileData.EnsureElemCapacity(size + 1)) {
|
||||||
|
ReportEncodingMemoryError(mElement, aFile, size + 1);
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRUint32 bytesRead;
|
||||||
|
rv = fileStream->Read(fileData.get(), size, &bytesRead);
|
||||||
|
NS_ASSERTION(NS_SUCCEEDED(rv) && bytesRead == size,
|
||||||
|
"fileStream->Read failed");
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
if (aType == TYPE_BASE64) {
|
||||||
|
// encode file contents
|
||||||
|
*aResult = nsnull;
|
||||||
|
char *buffer = PL_Base64Encode(fileData.get(), bytesRead, nsnull);
|
||||||
|
if (buffer) {
|
||||||
|
*aResult = ToNewUnicode(nsDependentCString(buffer));
|
||||||
|
PR_Free(buffer);
|
||||||
|
}
|
||||||
|
if (!*aResult) {
|
||||||
|
PRUint32 failedSize = buffer ? strlen(buffer) * sizeof(PRUnichar)
|
||||||
|
: ((bytesRead + 2) / 3) * 4 + 1;
|
||||||
|
ReportEncodingMemoryError(mElement, aFile, failedSize);
|
||||||
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
} else if (aType == TYPE_HEX) {
|
||||||
|
// create buffer for hex encoded data
|
||||||
|
PRUint32 length = bytesRead * 2 + 1;
|
||||||
|
PRUnichar *fileDataHex =
|
||||||
|
NS_STATIC_CAST(PRUnichar*, nsMemory::Alloc(length * sizeof(PRUnichar)));
|
||||||
|
if (!fileDataHex) {
|
||||||
|
ReportEncodingMemoryError(mElement, aFile, length * sizeof(PRUnichar));
|
||||||
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
} else {
|
||||||
|
// encode file contents
|
||||||
|
BinaryToHex(fileData.get(), bytesRead, &fileDataHex);
|
||||||
|
fileDataHex[bytesRead * 2] = 0;
|
||||||
|
*aResult = fileDataHex;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NS_ERROR("Unknown encoding type for <upload> element");
|
||||||
|
rv = NS_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PRUnichar
|
||||||
|
ToHexChar(PRInt16 aValue)
|
||||||
|
{
|
||||||
|
if (aValue < 10)
|
||||||
|
return (PRUnichar) aValue + '0';
|
||||||
|
else
|
||||||
|
return (PRUnichar) aValue - 10 + 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXFormsUploadElement::BinaryToHex(const char *aBuffer, PRUint32 aCount,
|
||||||
|
PRUnichar **aHexString)
|
||||||
|
{
|
||||||
|
for (PRUint32 index = 0; index < aCount; index++) {
|
||||||
|
(*aHexString)[index * 2] = ToHexChar((aBuffer[index] >> 4) & 0xf);
|
||||||
|
(*aHexString)[index * 2 + 1] = ToHexChar(aBuffer[index] & 0xf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NS_HIDDEN_(nsresult)
|
NS_HIDDEN_(nsresult)
|
||||||
NS_NewXFormsUploadElement(nsIXTFElement **aResult)
|
NS_NewXFormsUploadElement(nsIXTFElement **aResult)
|
||||||
{
|
{
|
||||||
|
|
|
@ -754,11 +754,10 @@ nsXFormsUtils::SetNodeValue(nsIDOMNode* aDataNode, const nsString& aNodeValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// @todo Use this consistently, or delete? (XXX)
|
|
||||||
/* static */ PRBool
|
/* static */ PRBool
|
||||||
nsXFormsUtils::GetSingleNodeBindingValue(nsIDOMElement* aElement,
|
nsXFormsUtils::GetSingleNodeBinding(nsIDOMElement* aElement,
|
||||||
nsString& aValue)
|
nsIDOMNode** aNode,
|
||||||
|
nsIModelElementPrivate** aModel)
|
||||||
{
|
{
|
||||||
if (!aElement)
|
if (!aElement)
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
|
@ -781,10 +780,44 @@ nsXFormsUtils::GetSingleNodeBindingValue(nsIDOMElement* aElement,
|
||||||
if (!singleNode)
|
if (!singleNode)
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
|
|
||||||
nsXFormsUtils::GetNodeValue(singleNode, aValue);
|
singleNode.swap(*aNode);
|
||||||
|
if (aModel)
|
||||||
|
model.swap(*aModel); // transfers ref
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @todo Use this consistently, or delete? (XXX)
|
||||||
|
/* static */ PRBool
|
||||||
|
nsXFormsUtils::GetSingleNodeBindingValue(nsIDOMElement* aElement,
|
||||||
|
nsString& aValue)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> node;
|
||||||
|
if (GetSingleNodeBinding(aElement, getter_AddRefs(node), nsnull)) {
|
||||||
|
nsXFormsUtils::GetNodeValue(node, aValue);
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ PRBool
|
||||||
|
nsXFormsUtils::SetSingleNodeBindingValue(nsIDOMElement *aElement,
|
||||||
|
const nsAString &aValue,
|
||||||
|
PRBool *aChanged)
|
||||||
|
{
|
||||||
|
*aChanged = PR_FALSE;
|
||||||
|
nsCOMPtr<nsIDOMNode> node;
|
||||||
|
nsCOMPtr<nsIModelElementPrivate> model;
|
||||||
|
if (GetSingleNodeBinding(aElement, getter_AddRefs(node),
|
||||||
|
getter_AddRefs(model)))
|
||||||
|
{
|
||||||
|
nsresult rv = model->SetNodeValue(node, aValue, aChanged);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ nsresult
|
/* static */ nsresult
|
||||||
nsXFormsUtils::DispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
|
nsXFormsUtils::DispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent,
|
||||||
PRBool *aDefaultActionEnabled)
|
PRBool *aDefaultActionEnabled)
|
||||||
|
|
|
@ -252,6 +252,15 @@ public:
|
||||||
static NS_HIDDEN_(void) SetNodeValue(nsIDOMNode *aDataNode,
|
static NS_HIDDEN_(void) SetNodeValue(nsIDOMNode *aDataNode,
|
||||||
const nsString &aNodeValue);
|
const nsString &aNodeValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method for doing XPath evaluations to get bound node
|
||||||
|
* for an element. Also returns the associated model if aModel != null.
|
||||||
|
* Returns PR_TRUE if the evaluation succeeds.
|
||||||
|
*/
|
||||||
|
static NS_HIDDEN_(PRBool)
|
||||||
|
GetSingleNodeBinding(nsIDOMElement* aElement, nsIDOMNode** aNode,
|
||||||
|
nsIModelElementPrivate** aModel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method for doing XPath evaluations to get string value
|
* Convenience method for doing XPath evaluations to get string value
|
||||||
* for an element.
|
* for an element.
|
||||||
|
@ -260,6 +269,14 @@ public:
|
||||||
static NS_HIDDEN_(PRBool)
|
static NS_HIDDEN_(PRBool)
|
||||||
GetSingleNodeBindingValue(nsIDOMElement* aElement, nsString& aValue);
|
GetSingleNodeBindingValue(nsIDOMElement* aElement, nsString& aValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method for doing XPath evaluations to set string value
|
||||||
|
* for an element.
|
||||||
|
* Returns PR_TRUE if the evaluation succeeds.
|
||||||
|
*/
|
||||||
|
static NS_HIDDEN_(PRBool)
|
||||||
|
SetSingleNodeBindingValue(nsIDOMElement *aElement, const nsAString &aValue,
|
||||||
|
PRBool *aChanged);
|
||||||
/**
|
/**
|
||||||
* Dispatch an XForms event. aDefaultActionEnabled is returned indicating
|
* Dispatch an XForms event. aDefaultActionEnabled is returned indicating
|
||||||
* if the default action of the dispatched event was enabled.
|
* if the default action of the dispatched event was enabled.
|
||||||
|
|
|
@ -255,4 +255,19 @@ select html|div.select-choice-content {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
upload {
|
||||||
|
-moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-upload-disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
upload[mozType|type="http://www.w3.org/2001/XMLSchema#anyURI"] {
|
||||||
|
-moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-upload');
|
||||||
|
}
|
||||||
|
|
||||||
|
upload[mozType|type="http://www.w3.org/2001/XMLSchema#base64Binary"] {
|
||||||
|
-moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-upload');
|
||||||
|
}
|
||||||
|
|
||||||
|
upload[mozType|type="http://www.w3.org/2001/XMLSchema#hexBinary"] {
|
||||||
|
-moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-upload');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,11 @@
|
||||||
-
|
-
|
||||||
- ***** END LICENSE BLOCK ***** -->
|
- ***** END LICENSE BLOCK ***** -->
|
||||||
|
|
||||||
|
<!DOCTYPE bindings [
|
||||||
|
<!ENTITY % xformsDTD SYSTEM "chrome://xforms/locale/xforms.dtd">
|
||||||
|
%xformsDTD;
|
||||||
|
]>
|
||||||
|
|
||||||
<bindings id="xformsBindings"
|
<bindings id="xformsBindings"
|
||||||
xmlns="http://www.mozilla.org/xbl"
|
xmlns="http://www.mozilla.org/xbl"
|
||||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||||
|
@ -443,4 +448,111 @@
|
||||||
</method>
|
</method>
|
||||||
</implementation>
|
</implementation>
|
||||||
</binding>
|
</binding>
|
||||||
|
|
||||||
|
<!-- UPLOAD: <DEFAULT> -->
|
||||||
|
<binding id="xformswidget-upload"
|
||||||
|
extends="chrome://xforms/content/xforms.xml#xformswidget-base">
|
||||||
|
<content>
|
||||||
|
<children includes="label"/>
|
||||||
|
<html:input anonid="upload_text_control"
|
||||||
|
readonly="true"
|
||||||
|
xbl:inherits="accesskey"/>
|
||||||
|
<html:button anonid="upload_browse_button"
|
||||||
|
type="button"
|
||||||
|
onclick="this.parentNode.uploadElem.pickFile();"
|
||||||
|
onkeypress="if (event.keyCode == event.DOM_VK_RETURN) this.parentNode.dispatchDOMActivate();"
|
||||||
|
xbl:inherits="accesskey"> &xforms.upload.browsetext; </html:button>
|
||||||
|
<html:button anonid="upload_clear_button"
|
||||||
|
type="button"
|
||||||
|
onclick="this.parentNode.uploadElem.clearFile();"
|
||||||
|
onkeypress="if (event.keyCode == event.DOM_VK_RETURN) this.parentNode.dispatchDOMActivate();"
|
||||||
|
xbl:inherits="accesskey"> &xforms.upload.cleartext; </html:button>
|
||||||
|
<children/>
|
||||||
|
</content>
|
||||||
|
|
||||||
|
<implementation implements="nsIXFormsUIWidget, nsIXFormsUploadUIElement">
|
||||||
|
<destructor>
|
||||||
|
this._uploadElem = null;
|
||||||
|
this._textControl = null;
|
||||||
|
this._browseButton = null;
|
||||||
|
this._clearButton = null;
|
||||||
|
</destructor>
|
||||||
|
|
||||||
|
<field name="_uploadElem">null</field>
|
||||||
|
|
||||||
|
<property name="uploadElem" readonly="true">
|
||||||
|
<getter>
|
||||||
|
if (!this._uploadElem) {
|
||||||
|
this._uploadElem =
|
||||||
|
this.QueryInterface(Components.interfaces.nsIXFormsUploadElement);
|
||||||
|
}
|
||||||
|
return this._uploadElem;
|
||||||
|
</getter>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<field name="_textControl">null</field>
|
||||||
|
|
||||||
|
<property name="textControl" readonly="true">
|
||||||
|
<getter>
|
||||||
|
if (!this._textControl) {
|
||||||
|
this._textControl =
|
||||||
|
document.getAnonymousElementByAttribute(this, "anonid",
|
||||||
|
"upload_text_control");
|
||||||
|
}
|
||||||
|
return this._textControl;
|
||||||
|
</getter>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<field name="_browseButton">null</field>
|
||||||
|
|
||||||
|
<property name="browseButton" readonly="true">
|
||||||
|
<getter>
|
||||||
|
if (!this._browseButton) {
|
||||||
|
this._browseButton =
|
||||||
|
document.getAnonymousElementByAttribute(this, "anonid",
|
||||||
|
"upload_browse_button");
|
||||||
|
}
|
||||||
|
return this._browseButton;
|
||||||
|
</getter>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<field name="_clearButton">null</field>
|
||||||
|
|
||||||
|
<property name="clearButton" readonly="true">
|
||||||
|
<getter>
|
||||||
|
if (!this._clearButton) {
|
||||||
|
this._clearButton =
|
||||||
|
document.getAnonymousElementByAttribute(this, "anonid",
|
||||||
|
"upload_clear_button");
|
||||||
|
}
|
||||||
|
return this._clearButton;
|
||||||
|
</getter>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<method name="setFieldText">
|
||||||
|
<parameter name="aString"/>
|
||||||
|
<body>
|
||||||
|
this.textControl.value = aString;
|
||||||
|
</body>
|
||||||
|
</method>
|
||||||
|
</implementation>
|
||||||
|
</binding>
|
||||||
|
|
||||||
|
<!-- UPLOAD: DISABLED -->
|
||||||
|
<binding id="xformswidget-upload-disabled"
|
||||||
|
extends="chrome://xforms/content/xforms.xml#xformswidget-base">
|
||||||
|
<content>
|
||||||
|
<children includes="label"/>
|
||||||
|
<html:input readonly="true"
|
||||||
|
xbl:inherits="accesskey"/>
|
||||||
|
<html:button type="button"
|
||||||
|
disabled="true"
|
||||||
|
xbl:inherits="accesskey"> &xforms.upload.browsetext; </html:button>
|
||||||
|
<html:button type="button"
|
||||||
|
disabled="true"
|
||||||
|
xbl:inherits="accesskey"> &xforms.upload.cleartext; </html:button>
|
||||||
|
<children/>
|
||||||
|
</content>
|
||||||
|
</binding>
|
||||||
|
|
||||||
</bindings>
|
</bindings>
|
||||||
|
|
|
@ -43,3 +43,6 @@
|
||||||
<!ENTITY xforms.bindingdialog.title "XForms Error">
|
<!ENTITY xforms.bindingdialog.title "XForms Error">
|
||||||
<!ENTITY xforms.bindingdialog.description1 "The form on this page contains an error and will not work properly">
|
<!ENTITY xforms.bindingdialog.description1 "The form on this page contains an error and will not work properly">
|
||||||
<!ENTITY xforms.bindingdialog.description2 "See the JavaScript Console for details">
|
<!ENTITY xforms.bindingdialog.description2 "See the JavaScript Console for details">
|
||||||
|
|
||||||
|
<!ENTITY xforms.upload.browsetext "Browse...">
|
||||||
|
<!ENTITY xforms.upload.cleartext "Clear">
|
||||||
|
|
|
@ -58,6 +58,8 @@ labelLink2Error = XForms Error (19): Failed to load Label element from exte
|
||||||
invalidSeparator = XForms Error (20): Submission separator may only be either "&" or ";", but found "%S".
|
invalidSeparator = XForms Error (20): Submission separator may only be either "&" or ";", but found "%S".
|
||||||
instanceBindError = XForms Error (21): Submission failed trying to replace instance document '%S'. Instance document doesn't exist in same model as submission element.
|
instanceBindError = XForms Error (21): Submission failed trying to replace instance document '%S'. Instance document doesn't exist in same model as submission element.
|
||||||
instanceInstanceLoad = XForms Error (22): Instance document not allowed to load external instance: %S
|
instanceInstanceLoad = XForms Error (22): Instance document not allowed to load external instance: %S
|
||||||
|
encodingMemoryError = XForms Error (23): Not enough available memory to encode file %S, size = %S.
|
||||||
|
uploadBoundTypeError = XForms Error (24): Upload element not bound to valid datatype. Must be bound to datatype 'xsd:anyURI', 'xsd:base64Binary', or 'xsd:hexBinary'.
|
||||||
|
|
||||||
# Warning Messages:
|
# 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.
|
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.
|
||||||
|
@ -65,4 +67,3 @@ warnSOAP = XForms Warning (1): You are using the SOAP post feature,
|
||||||
# XForms Permission Messages:
|
# XForms Permission Messages:
|
||||||
xformsXDPermissionDialogTitle = Allowed Sites - XForms Cross Domain Access
|
xformsXDPermissionDialogTitle = Allowed Sites - XForms Cross Domain Access
|
||||||
xformsXDPermissionDialogIntro = You can specify which web sites containing XForms may submit data to other domains. Type the exact address of the site you want to allow and then press Allow.
|
xformsXDPermissionDialogIntro = You can specify which web sites containing XForms may submit data to other domains. Type the exact address of the site you want to allow and then press Allow.
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче