Bug 507805: Support FileRequest API for reading Files. r/sr=sicking

This commit is contained in:
Matin Movassate 2009-10-07 01:30:26 -07:00
parent 1ed03f8f31
commit 1ba0cf09e4
15 changed files with 1411 additions and 9 deletions

View File

@ -93,9 +93,11 @@ XPIDLSRCS = \
nsIContentPolicy.idl \
nsIDocumentEncoder.idl \
nsIDOMFile.idl \
nsIDOMFileRequest.idl \
nsIDOMFileInternal.idl \
nsIDOMFileList.idl \
nsIDOMFileException.idl \
nsIDOMFileError.idl \
nsIDOMParser.idl \
nsIDOMSerializer.idl \
nsISelection2.idl \

View File

@ -43,6 +43,7 @@
#include "nsIDOMFile.h"
#include "nsIDOMFileInternal.h"
#include "nsIDOMFileList.h"
#include "nsIDOMFileError.h"
#include "nsIInputStream.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
@ -117,4 +118,16 @@ private:
nsCOMArray<nsIDOMFile> mFiles;
};
class nsDOMFileError : public nsIDOMFileError
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMFILEERROR
nsDOMFileError(PRUint16 aErrorCode) : mCode(aErrorCode) {}
private:
PRUint16 mCode;
};
#endif

View File

@ -37,16 +37,20 @@
#include "domstubs.idl"
[scriptable, uuid(4a17d83b-424f-43f3-8a7c-430f406921be)]
interface nsIDOMFileError;
[scriptable, uuid(0845E8AE-56BD-4F0E-962A-3B3E92638A0B)]
interface nsIDOMFile : nsISupports
{
//fileName and fileSize are now deprecated attributes
readonly attribute DOMString fileName;
readonly attribute unsigned long long fileSize;
DOMString getAsText(in DOMString encoding);
// raises(FileException) on retrieval
DOMString getAsDataURL();
// raises(FileException) on retrieval
DOMString getAsBinary();
// raises(FileException) on retrieval
readonly attribute DOMString name;
readonly attribute unsigned long long size;
readonly attribute DOMString mediaType;
DOMString getAsText(in DOMString encoding); // raises(FileException) on retrieval
DOMString getAsDataURL(); // raises(FileException) on retrieval
DOMString getAsBinary(); // raises(FileException) on retrieval
};

View File

@ -0,0 +1,52 @@
/* -*- 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.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 "domstubs.idl"
[scriptable, uuid(4BDAFB64-15E2-49C1-A090-4315A7884A56)]
interface nsIDOMFileError : nsISupports
{
//File error codes
const unsigned short NOT_FOUND_ERR = 8;
const unsigned short NOT_READABLE_ERR = 24;
const unsigned short SECURITY_ERR = 18;
const unsigned short ABORT_ERR = 25;
const unsigned short ENCODING_ERR = 26;
readonly attribute unsigned short code;
};

View File

@ -0,0 +1,71 @@
/* -*- 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.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 "nsIDOMEventTarget.idl"
interface nsIDOMEventListener;
interface nsIDOMFile;
interface nsIDOMFileError;
[scriptable, uuid(074FEC26-7FAB-4E05-9E60-EC49E148F5EF)]
interface nsIDOMFileRequest : nsISupports
{
void readAsBinaryString(in nsIDOMFile filedata);
void readAsText(in nsIDOMFile filedata, [optional] in DOMString encoding);
void readAsDataURL(in nsIDOMFile file);
void abort();
const unsigned short INITIAL = 0;
const unsigned short LOADING = 1;
const unsigned short DONE = 2;
readonly attribute unsigned short readyState;
readonly attribute DOMString response;
readonly attribute nsIDOMFileError error;
// event handler attributes
attribute nsIDOMEventListener onloadend;
};
%{ C++
#define NS_FILEREQUEST_CID \
{0x06aa7c21, 0xfe05, 0x4cf2, \
{0xb1, 0xc4, 0x0c, 0x71, 0x26, 0xa4, 0xf7, 0x13}}
#define NS_FILEREQUEST_CONTRACTID \
"@mozilla.org/files/filerequest;1"
%}

View File

@ -84,6 +84,7 @@ CPPSRCS = \
nsDOMAttributeMap.cpp \
nsDOMDocumentType.cpp \
nsDOMFile.cpp \
nsDOMFileRequest.cpp \
nsDOMLists.cpp \
nsDOMParser.cpp \
nsDOMSerializer.cpp \

View File

@ -93,11 +93,23 @@ DOMFileResult(nsresult rv)
NS_IMETHODIMP
nsDOMFile::GetFileName(nsAString &aFileName)
{
return mFile->GetLeafName(aFileName);
return GetName(aFileName);
}
NS_IMETHODIMP
nsDOMFile::GetFileSize(PRUint64 *aFileSize)
{
return GetSize(aFileSize);
}
NS_IMETHODIMP
nsDOMFile::GetName(nsAString &aFileName)
{
return mFile->GetLeafName(aFileName);
}
NS_IMETHODIMP
nsDOMFile::GetSize(PRUint64 *aFileSize)
{
PRInt64 fileSize;
nsresult rv = mFile->GetFileSize(&fileSize);
@ -112,6 +124,30 @@ nsDOMFile::GetFileSize(PRUint64 *aFileSize)
return NS_OK;
}
NS_IMETHODIMP
nsDOMFile::GetMediaType(nsAString &aMediaType)
{
if (!mContentType.Length()) {
nsresult rv;
nsCOMPtr<nsIMIMEService> mimeService =
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString mediaType;
rv = mimeService->GetTypeFromFile(mFile, mediaType);
if (NS_FAILED(rv)) {
SetDOMStringToNull(aMediaType);
return NS_OK;
}
AppendUTF8toUTF16(mediaType, mContentType);
}
aMediaType = mContentType;
return NS_OK;
}
NS_IMETHODIMP
nsDOMFile::GetAsText(const nsAString &aCharset, nsAString &aResult)
{
@ -405,3 +441,21 @@ nsDOMFileList::Item(PRUint32 aIndex, nsIDOMFile **aFile)
return NS_OK;
}
// nsDOMFileError implementation
NS_INTERFACE_MAP_BEGIN(nsDOMFileError)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFileError)
NS_INTERFACE_MAP_ENTRY(nsIDOMFileError)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(FileError)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsDOMFileError)
NS_IMPL_RELEASE(nsDOMFileError)
NS_IMETHODIMP
nsDOMFileError::GetCode(PRUint16* aCode)
{
*aCode = mCode;
return NS_OK;
}

View File

@ -0,0 +1,737 @@
/* -*- 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 mozila.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 "nsDOMFileRequest.h"
#include "nsContentCID.h"
#include "nsContentUtils.h"
#include "nsDOMClassInfo.h"
#include "nsDOMFile.h"
#include "nsDOMError.h"
#include "nsICharsetAlias.h"
#include "nsICharsetDetector.h"
#include "nsICharsetConverterManager.h"
#include "nsIConverterInputStream.h"
#include "nsIFile.h"
#include "nsIFileStreams.h"
#include "nsIInputStream.h"
#include "nsIMIMEService.h"
#include "nsIPlatformCharset.h"
#include "nsIUnicharInputStream.h"
#include "nsIUnicodeDecoder.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "plbase64.h"
#include "prmem.h"
#include "nsLayoutCID.h"
#include "nsXPIDLString.h"
#include "nsReadableUtils.h"
#include "nsIURI.h"
#include "nsStreamUtils.h"
#include "nsXPCOM.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMEventListener.h"
#include "nsIJSContextStack.h"
#include "nsJSEnvironment.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDOMClassInfo.h"
#include "nsIDOMFileInternal.h"
#include "nsCExternalHandlerService.h"
#include "nsIStreamConverterService.h"
#include "nsEventDispatcher.h"
#include "nsCycleCollectionParticipant.h"
#include "nsLayoutStatics.h"
#include "nsIScriptObjectPrincipal.h"
#define LOAD_STR "load"
#define ERROR_STR "error"
#define ABORT_STR "abort"
#define LOADSTART_STR "loadstart"
#define PROGRESS_STR "progress"
#define UPLOADPROGRESS_STR "uploadprogress"
#define LOADEND_STR "loadend"
#define NS_PROGRESS_EVENT_INTERVAL 50
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileRequest,
nsXHREventTarget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadEndListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFile)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mProgressNotifier)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileRequest,
nsXHREventTarget)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadEndListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFile)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressNotifier)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrincipal)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMFileRequest)
NS_INTERFACE_MAP_ENTRY(nsIDOMFileRequest)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(FileRequest)
NS_INTERFACE_MAP_END_INHERITING(nsXHREventTarget)
NS_IMPL_ADDREF_INHERITED(nsDOMFileRequest, nsXHREventTarget)
NS_IMPL_RELEASE_INHERITED(nsDOMFileRequest, nsXHREventTarget)
static const PRUint32 FILE_AS_BINARY = 1;
static const PRUint32 FILE_AS_TEXT = 2;
static const PRUint32 FILE_AS_DATAURL = 3;
NS_IMETHODIMP
nsDOMFileRequest::GetOnloadend(nsIDOMEventListener** aOnloadend)
{
return GetInnerEventListener(mOnLoadEndListener, aOnloadend);
}
NS_IMETHODIMP
nsDOMFileRequest::SetOnloadend(nsIDOMEventListener* aOnloadend)
{
return RemoveAddEventListener(NS_LITERAL_STRING(LOADEND_STR),
mOnLoadEndListener, aOnloadend);
}
//nsICharsetDetectionObserver
NS_IMETHODIMP
nsDOMFileRequest::Notify(const char *aCharset, nsDetectionConfident aConf)
{
CopyASCIItoUTF16(aCharset, mCharset);
return NS_OK;
}
//nsDOMFileRequest constructors/initializers
nsDOMFileRequest::nsDOMFileRequest()
: mFileData(nsnull), mReadCount(0),
mDataLen(0), mDataFormat(0),
mReadyState(nsIDOMFileRequest::INITIAL),
mProgressEventWasDelayed(PR_FALSE),
mTimerIsActive(PR_FALSE),
mReadTotal(0), mReadTransferred(0),
mReadComplete(PR_TRUE)
{
nsLayoutStatics::AddRef();
}
nsDOMFileRequest::~nsDOMFileRequest()
{
if (mListenerManager)
mListenerManager->Disconnect();
nsLayoutStatics::Release();
}
nsresult
nsDOMFileRequest::Init()
{
// Set the original mScriptContext and mPrincipal, if available.
// Get JSContext from stack.
nsCOMPtr<nsIJSContextStack> stack =
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
if (!stack) {
return NS_OK;
}
JSContext *cx;
if (NS_FAILED(stack->Peek(&cx)) || !cx) {
return NS_OK;
}
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
nsCOMPtr<nsIPrincipal> subjectPrincipal;
if (secMan) {
secMan->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
}
NS_ENSURE_STATE(subjectPrincipal);
mPrincipal = subjectPrincipal;
nsIScriptContext* context = GetScriptContextFromJSContext(cx);
if (context) {
mScriptContext = context;
nsCOMPtr<nsPIDOMWindow> window =
do_QueryInterface(context->GetGlobalObject());
if (window) {
mOwner = window->GetCurrentInnerWindow();
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
PRUint32 argc, jsval *argv)
{
mOwner = do_QueryInterface(aOwner);
if (!mOwner) {
NS_WARNING("Unexpected nsIJSNativeInitializer owner");
return NS_OK;
}
// This object is bound to a |window|,
// so reset the principal and script context.
nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal = do_QueryInterface(aOwner);
NS_ENSURE_STATE(scriptPrincipal);
mPrincipal = scriptPrincipal->GetPrincipal();
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aOwner);
NS_ENSURE_STATE(sgo);
mScriptContext = sgo->GetContext();
NS_ENSURE_STATE(mScriptContext);
return NS_OK;
}
// nsIInterfaceRequestor
NS_IMETHODIMP
nsDOMFileRequest::GetInterface(const nsIID & aIID, void **aResult)
{
return QueryInterface(aIID, aResult);
}
// nsIDOMFileRequest
NS_IMETHODIMP
nsDOMFileRequest::GetReadyState(PRUint16 *aReadyState)
{
*aReadyState = mReadyState;
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::GetResponse(nsAString& aResponse)
{
aResponse = mResponse;
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::GetError(nsIDOMFileError** aError)
{
NS_IF_ADDREF(*aError = mError);
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::ReadAsBinaryString(nsIDOMFile* aFile)
{
return ReadFileContent(aFile, EmptyString(), FILE_AS_BINARY);
}
NS_IMETHODIMP
nsDOMFileRequest::ReadAsText(nsIDOMFile* aFile,
const nsAString &aCharset)
{
return ReadFileContent(aFile, aCharset, FILE_AS_TEXT);
}
NS_IMETHODIMP
nsDOMFileRequest::ReadAsDataURL(nsIDOMFile* aFile)
{
return ReadFileContent(aFile, EmptyString(), FILE_AS_DATAURL);
}
NS_IMETHODIMP
nsDOMFileRequest::Abort()
{
if (mReadyState != nsIDOMFileRequest::LOADING)
return NS_OK;
//Clear progress and file data
mProgressEventWasDelayed = PR_FALSE;
mTimerIsActive = PR_FALSE;
if (mProgressNotifier) {
mProgressNotifier->Cancel();
}
mReadCount = 0;
mDataLen = 0;
//Revert status, response and readystate attributes
SetDOMStringToNull(mResponse);
mReadyState = nsIDOMFileRequest::DONE;
mError = new nsDOMFileError(nsIDOMFileError::ABORT_ERR);
//Non-null channel indicates a read is currently active
if (mChannel) {
//Cancel request requires an error status
mChannel->Cancel(NS_ERROR_FAILURE);
mChannel = nsnull;
}
mFile = nsnull;
//Clean up memory buffer
PR_Free(mFileData);
mFileData = nsnull;
//Dispatch the abort event
DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR));
DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
mReadyState = nsIDOMFileRequest::INITIAL;
return NS_OK;
}
// nsITimerCallback
NS_IMETHODIMP
nsDOMFileRequest::Notify(nsITimer* aTimer)
{
mTimerIsActive = PR_FALSE;
if (mProgressEventWasDelayed) {
DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR));
StartProgressEventTimer();
}
return NS_OK;
}
void
nsDOMFileRequest::StartProgressEventTimer()
{
if (!mProgressNotifier) {
mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
}
if (mProgressNotifier) {
mProgressEventWasDelayed = PR_FALSE;
mTimerIsActive = PR_TRUE;
mProgressNotifier->Cancel();
mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,
nsITimer::TYPE_ONE_SHOT);
}
}
// nsIStreamListener
NS_IMETHODIMP
nsDOMFileRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::OnDataAvailable(nsIRequest *aRequest,
nsISupports *aContext,
nsIInputStream *aInputStream,
PRUint32 aOffset,
PRUint32 aCount)
{
//Update memory buffer to reflect the contents of the file
mFileData = (char *)PR_Realloc(mFileData, aOffset + aCount);
NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY);
aInputStream->Read(mFileData + aOffset, aCount, &mReadCount);
mDataLen += aCount;
mReadTransferred = mDataLen;
//Continuously update our binary string as data comes in
if (mDataFormat == FILE_AS_BINARY) {
PRUint32 oldLen = mResponse.Length();
PRUint32 newLen = oldLen + aCount;
PRUnichar *buf;
if (mResponse.GetMutableData(&buf, newLen) != newLen) {
return NS_ERROR_OUT_OF_MEMORY;
}
PRUnichar *bufEnd = buf + newLen;
buf += oldLen;
char *source = mFileData + aOffset;
while (buf < bufEnd) {
*buf = *source;
++buf;
++source;
}
}
//Notify the timer is the appropriate timeframe has passed
if (mTimerIsActive) {
mProgressEventWasDelayed = PR_TRUE;
}
else {
DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR));
StartProgressEventTimer();
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileRequest::OnStopRequest(nsIRequest *aRequest,
nsISupports *aContext,
nsresult aStatus)
{
//If we're here as a result of a call from Abort(),
//simply ignore the request.
if (aRequest != mChannel)
return NS_OK;
//Cancel the progress event timer
mProgressEventWasDelayed = PR_FALSE;
mTimerIsActive = PR_FALSE;
if (mProgressNotifier) {
mProgressNotifier->Cancel();
}
//FileRequest must be in DONE stage after a load
mReadyState = nsIDOMFileRequest::DONE;
//Set the status field as appropriate
if (NS_FAILED(aStatus)) {
DispatchError(aStatus);
return NS_OK;
}
nsresult rv;
switch (mDataFormat) {
case FILE_AS_BINARY:
break; //Already accumulated mResponse
case FILE_AS_TEXT:
rv = GetAsText(mCharset, mFileData, mDataLen, mResponse);
break;
case FILE_AS_DATAURL:
rv = GetAsDataURL(mFile, mFileData, mDataLen, mResponse);
break;
default:
return NS_ERROR_FAILURE;
}
//Dispatch load event to signify end of a successful load
DispatchProgressEvent(NS_LITERAL_STRING(LOAD_STR));
DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
return rv;
}
// Helper methods
nsresult
nsDOMFileRequest::ReadFileContent(nsIDOMFile* aFile,
const nsAString &aCharset,
PRUint32 aDataFormat)
{
NS_ENSURE_TRUE(aFile, NS_ERROR_NULL_POINTER);
//Implicit abort to clear any other activity going on
Abort();
mDataFormat = aDataFormat;
mCharset = aCharset;
mError = nsnull;
//Obtain the nsDOMFile's underlying nsIFile
nsresult rv;
nsCOMPtr<nsIDOMFileInternal> domFile(do_QueryInterface(aFile));
rv = domFile->GetInternalFile(getter_AddRefs(mFile));
NS_ENSURE_SUCCESS(rv, rv);
//Establish a channel with our file
nsCOMPtr<nsIURI> uri;
rv = NS_NewFileURI(getter_AddRefs(uri), mFile);
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewChannel(getter_AddRefs(mChannel), uri);
NS_ENSURE_SUCCESS(rv, rv);
//Obtain the total size of the file before reading
aFile->GetSize(&mReadTotal);
rv = mChannel->AsyncOpen(this, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
//FileRequest should be in loading state here
mReadyState = nsIDOMFileRequest::LOADING;
DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
return NS_OK;
}
void
nsDOMFileRequest::DispatchError(nsresult rv)
{
//Set the status attribute, and dispatch the error event
switch (rv) {
case NS_ERROR_FILE_NOT_FOUND:
mError = new nsDOMFileError(nsIDOMFileError::NOT_FOUND_ERR);
break;
case NS_ERROR_FILE_ACCESS_DENIED:
mError = new nsDOMFileError(nsIDOMFileError::SECURITY_ERR);
break;
default:
mError = new nsDOMFileError(nsIDOMFileError::NOT_READABLE_ERR);
break;
}
//Dispatch error event to signify load failure
DispatchProgressEvent(NS_LITERAL_STRING(ERROR_STR));
DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
}
void
nsDOMFileRequest::DispatchProgressEvent(const nsAString& aType)
{
nsCOMPtr<nsIDOMEvent> event;
nsresult rv = nsEventDispatcher::CreateEvent(nsnull, nsnull,
NS_LITERAL_STRING("ProgressEvent"),
getter_AddRefs(event));
if (NS_FAILED(rv))
return;
nsCOMPtr<nsIPrivateDOMEvent> privevent(do_QueryInterface(event));
if (!privevent)
return;
privevent->SetTrusted(PR_TRUE);
nsCOMPtr<nsIDOMProgressEvent> progress = do_QueryInterface(event);
if (!progress)
return;
progress->InitProgressEvent(aType, PR_FALSE, PR_FALSE, mReadComplete,
mReadTransferred, (mReadTotal == LL_MAXUINT) ? 0 : mReadTotal);
this->DispatchDOMEvent(nsnull, event, nsnull, nsnull);
}
nsresult
nsDOMFileRequest::GetAsText(const nsAString &aCharset,
const char *aFileData,
PRUint32 aDataLen,
nsAString& aResult)
{
nsresult rv;
nsCAutoString charsetGuess;
if (!aCharset.IsEmpty()) {
CopyUTF16toUTF8(aCharset, charsetGuess);
} else {
rv = GuessCharset(aFileData, aDataLen, charsetGuess);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCAutoString charset;
nsCOMPtr<nsICharsetAlias> alias = do_GetService(NS_CHARSETALIAS_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = alias->GetPreferred(charsetGuess, charset);
NS_ENSURE_SUCCESS(rv, rv);
rv = ConvertStream(aFileData, aDataLen, charset.get(), aResult);
return NS_OK;
}
nsresult
nsDOMFileRequest::GetAsDataURL(nsIFile *aFile,
const char *aFileData,
PRUint32 aDataLen,
nsAString& aResult)
{
aResult.AssignLiteral("data:");
nsresult rv;
nsCOMPtr<nsIMIMEService> mimeService =
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString contentType;
rv = mimeService->GetTypeFromFile(aFile, contentType);
if (NS_SUCCEEDED(rv)) {
AppendUTF8toUTF16(contentType, aResult);
} else {
aResult.AppendLiteral("application/octet-stream");
}
aResult.AppendLiteral(";base64,");
PRUint32 totalRead = 0;
do {
PRUint32 numEncode = 4096;
PRUint32 amtRemaining = aDataLen - totalRead;
if (numEncode > amtRemaining)
numEncode = amtRemaining;
//Unless this is the end of the file, encode in multiples of 3
if (numEncode > 3) {
PRUint32 leftOver = numEncode % 3;
numEncode -= leftOver;
}
//Out buffer should be at least 4/3rds the read buf, plus a terminator
char *base64 = PL_Base64Encode(aFileData + totalRead, numEncode, nsnull);
AppendASCIItoUTF16(nsDependentCString(base64), aResult);
PR_Free(base64);
totalRead += numEncode;
} while (aDataLen > totalRead);
return NS_OK;
}
nsresult
nsDOMFileRequest::ConvertStream(const char *aFileData,
PRUint32 aDataLen,
const char *aCharset,
nsAString &aResult)
{
nsresult rv;
nsCOMPtr<nsICharsetConverterManager> charsetConverter =
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIUnicodeDecoder> unicodeDecoder;
rv = charsetConverter->GetUnicodeDecoder(aCharset, getter_AddRefs(unicodeDecoder));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 destLength;
rv = unicodeDecoder->GetMaxLength(aFileData, aDataLen, &destLength);
NS_ENSURE_SUCCESS(rv, rv);
aResult.SetLength(destLength); //Make sure we have enough space for the conversion
destLength = aResult.Length();
PRInt32 srcLength = aDataLen;
rv = unicodeDecoder->Convert(aFileData, &srcLength, aResult.BeginWriting(), &destLength);
aResult.SetLength(destLength); //Trim down to the correct size
return rv;
}
nsresult
nsDOMFileRequest::GuessCharset(const char *aFileData,
PRUint32 aDataLen,
nsACString &aCharset)
{
// First try the universal charset detector
nsCOMPtr<nsICharsetDetector> detector
= do_CreateInstance(NS_CHARSET_DETECTOR_CONTRACTID_BASE
"universal_charset_detector");
if (!detector) {
// No universal charset detector, try the default charset detector
const nsAdoptingString& detectorName =
nsContentUtils::GetLocalizedStringPref("intl.charset.detector");
if (!detectorName.IsEmpty()) {
nsCAutoString detectorContractID;
detectorContractID.AssignLiteral(NS_CHARSET_DETECTOR_CONTRACTID_BASE);
AppendUTF16toUTF8(detectorName, detectorContractID);
detector = do_CreateInstance(detectorContractID.get());
}
}
nsresult rv;
if (detector) {
mCharset.Truncate();
detector->Init(this);
PRBool done;
rv = detector->DoIt(aFileData, aDataLen, &done);
NS_ENSURE_SUCCESS(rv, rv);
rv = detector->Done();
NS_ENSURE_SUCCESS(rv, rv);
CopyUTF16toUTF8(mCharset, aCharset);
} else {
// no charset detector available, check the BOM
unsigned char sniffBuf[4];
PRUint32 numRead = (aDataLen >= sizeof(sniffBuf) ? sizeof(sniffBuf) : aDataLen);
memcpy(sniffBuf, aFileData, numRead);
if (numRead >= 4 &&
sniffBuf[0] == 0x00 &&
sniffBuf[1] == 0x00 &&
sniffBuf[2] == 0xfe &&
sniffBuf[3] == 0xff) {
aCharset = "UTF-32BE";
} else if (numRead >= 4 &&
sniffBuf[0] == 0xff &&
sniffBuf[1] == 0xfe &&
sniffBuf[2] == 0x00 &&
sniffBuf[3] == 0x00) {
aCharset = "UTF-32LE";
} else if (numRead >= 2 &&
sniffBuf[0] == 0xfe &&
sniffBuf[1] == 0xff) {
aCharset = "UTF-16BE";
} else if (numRead >= 2 &&
sniffBuf[0] == 0xff &&
sniffBuf[1] == 0xfe) {
aCharset = "UTF-16LE";
} else if (numRead >= 3 &&
sniffBuf[0] == 0xef &&
sniffBuf[1] == 0xbb &&
sniffBuf[2] == 0xbf) {
aCharset = "UTF-8";
}
}
if (aCharset.IsEmpty()) {
// no charset detected, default to the system charset
nsCOMPtr<nsIPlatformCharset> platformCharset =
do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = platformCharset->GetCharset(kPlatformCharsetSel_PlainTextInFile,
aCharset);
}
}
if (aCharset.IsEmpty()) {
// no sniffed or default charset, try UTF-8
aCharset.AssignLiteral("UTF-8");
}
return NS_OK;
}

View File

@ -0,0 +1,147 @@
/* -*- 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 mozila.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 nsDOMFileRequest_h__
#define nsDOMFileRequest_h__
#include "nsISupportsUtils.h"
#include "nsString.h"
#include "nsIStreamListener.h"
#include "nsIScriptContext.h"
#include "nsIInterfaceRequestor.h"
#include "nsJSUtils.h"
#include "nsTArray.h"
#include "nsIJSNativeInitializer.h"
#include "prtime.h"
#include "nsITimer.h"
#include "nsDOMEventTargetHelper.h"
#include "nsICharsetDetector.h"
#include "nsICharsetDetectionObserver.h"
#include "nsIDOMFile.h"
#include "nsIDOMFileRequest.h"
#include "nsIDOMFileList.h"
#include "nsIDOMFileError.h"
#include "nsIInputStream.h"
#include "nsCOMPtr.h"
#include "nsIStreamLoader.h"
#include "nsIChannel.h"
#include "nsXMLHttpRequest.h"
class nsDOMFileRequest : public nsXHREventTarget,
public nsIDOMFileRequest,
public nsIStreamListener,
public nsIInterfaceRequestor,
public nsSupportsWeakReference,
public nsIJSNativeInitializer,
public nsITimerCallback,
public nsICharsetDetectionObserver
{
public:
nsDOMFileRequest();
virtual ~nsDOMFileRequest();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMFILEREQUEST
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMFileRequest, nsXHREventTarget)
NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::);
// nsIStreamListener
NS_DECL_NSISTREAMLISTENER
// nsIRequestObserver
NS_DECL_NSIREQUESTOBSERVER
// nsIInterfaceRequestor
NS_DECL_NSIINTERFACEREQUESTOR
// nsITimerCallback
NS_DECL_NSITIMERCALLBACK
// nsIJSNativeInitializer
NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
PRUint32 argc, jsval* argv);
NS_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget::)
NS_FORWARD_NSIDOMNSEVENTTARGET(nsXHREventTarget::)
// nsICharsetDetectionObserver
NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf);
void DispatchProgressEvent(const nsAString& aType);
nsresult Init();
protected:
nsresult ReadFileContent(nsIDOMFile *aFile, const nsAString &aCharset, PRUint32 aDataFormat);
nsresult GetAsText(const nsAString &aCharset,
const char *aFileData, PRUint32 aDataLen, nsAString &aResult);
nsresult GetAsDataURL(nsIFile *aFile, const char *aFileData, PRUint32 aDataLen, nsAString &aResult);
nsresult GuessCharset(const char *aFileData, PRUint32 aDataLen, nsACString &aCharset);
nsresult ConvertStream(const char *aFileData, PRUint32 aDataLen, const char *aCharset, nsAString &aResult);
void DispatchError(nsresult rv);
void StartProgressEventTimer();
char *mFileData;
nsCOMPtr<nsIFile> mFile;
nsString mCharset;
PRUint32 mReadCount;
PRUint32 mDataLen;
PRUint32 mDataFormat;
nsString mResponse;
PRUint16 mReadyState;
PRBool mProgressEventWasDelayed;
PRBool mTimerIsActive;
nsCOMPtr<nsIDOMFileError> mError;
nsCOMPtr<nsITimer> mProgressNotifier;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIChannel> mChannel;
PRUint64 mReadTotal;
PRUint64 mReadTransferred;
PRPackedBool mReadComplete;
nsRefPtr<nsDOMEventListenerWrapper> mOnLoadEndListener;
};
#endif

View File

@ -143,6 +143,7 @@ _TEST_FILES = test_bug5141.html \
test_bug402150.html^headers^ \
test_bug401662.html \
test_bug403852.html \
test_fileapi.html \
test_bug403868.xml \
test_bug405182.html \
test_bug403841.html \

View File

@ -33,7 +33,7 @@ fileList.value = testFile.path;
// Make sure the file is accessible with indexed notation
var domFile = fileList.files[0];
is(domFile.fileName, "prefs.js", "fileName should be prefs.js");
is(domFile.name, "prefs.js", "fileName should be prefs.js");
</script>
</pre>

View File

@ -0,0 +1,293 @@
<!DOCTYPE HTML>
<html>
<head>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=414796
-->
<title>Test for Bug 414796</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=414796">Mozilla Bug 414796</a>
<p id="display">
<input id="fileList" type="file"></input>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var testCounter = 0;
SimpleTest.waitForExplicitFinish();
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
// Write a test file > 8192 characters
var testData = "asdfblahqwer";
for (var i = 0; i < 10; i++) {
testData = testData + testData;
}
var testData2 = testData + "a";
var testData3 = testData + "as";
//Ensure we have different sizes of data for thoroughly testing data URI retrieval
is(testData.length % 3, 0, "Need to have data length % 3 == 0");
is(testData2.length % 3, 1, "Need to have data length % 3 == 1");
is(testData3.length % 3, 2, "Need to have data lenght % 3 == 2");
//Create UTF data that should be the same for UTF-16
var utf16Data = "\0a\0s\0d\0f\0b\0l\0a\0h\0q\0w\0e\0r";
for (var i = 0; i < 10; i++) {
utf16Data = utf16Data + utf16Data;
}
var utf16File = createFileWithData(utf16Data, "01");
//Create UTF data that should be the same for UTF-32
var utf32Data = "\0\0\0a\0\0\0s\0\0\0d\0\0\0f\0\0\0b\0\0\0l\0\0\0a\0\0\0h\0\0\0q\0\0\0w\0\0\0e\0\0\0r";
for (var i = 0; i < 10; i++) {
utf32Data = utf32Data + utf32Data;
}
var utf32File = createFileWithData(utf32Data, "001");
//Obtain a variety of encodings so we can test async return values
var file = createFileWithData(testData, "00");
var domFileData = file.getAsDataURL();
var domFileBinary = file.getAsBinary();
var domFileBinary2 = utf16File.getAsBinary();
var domFileBinary3 = utf32File.getAsBinary();
var request1 = new FileRequest();
request1.onload = handleTextISO1;
request1.readAsText(file, "iso-8859-1");
var request2 = new FileRequest();
request2.onload = handleTextUTF8;
request2.readAsText(file);
var request3 = new FileRequest();
request3.onload = handleTextUTF8;
request3.readAsText(file, "");
var request4 = new FileRequest();
request4.onload = handleTextUTF8;
request4.readAsText(file, "UTF-8");
//Test a variety of encodings, and make sure they work properly
//Also, test a variety of the same calls with different numbers of arguments
var request5 = new FileRequest();
request5.onload = handleTextUTF16;
request5.readAsText(utf16File, "UTF-16");
var request6 = new FileRequest();
request6.onload = handleTextUTF32;
request6.readAsText(utf32File, "UTF-32");
//Test binary data accessor
var request7 = new FileRequest();
request7.onload = handleDataBinary;
request7.readAsBinaryString(file);
var request71 = new FileRequest();
request71.onload = handleDataBinary16;
request71.readAsBinaryString(utf16File);
var request72 = new FileRequest();
request72.onload = handleDataBinary32;
request72.readAsBinaryString(utf32File);
//Test data URI encoding on differing file sizes
//Testing data URI when length % 3 == 0
var request8 = new FileRequest();
request8.onload = handleDataURI;
request8.readAsDataURL(file);
//Testing data URI when length % 3 == 1
var file2 = createFileWithData(testData2, "02");
var domFileData1 = file2.getAsDataURL();
var request9 = new FileRequest();
request9.onload = handleDataURI1;
request9.readAsDataURL(file2);
//Testing data URI when length % 3 == 2
var file3 = createFileWithData(testData3, "03");
var domFileData2 = file3.getAsDataURL();
var request10 = new FileRequest();
request10.onload = handleDataURI2;
request10.readAsDataURL(file3);
//Test asynchronous property of file access
var globalVar = 0;
var request105 = new FileRequest();
request105.onload = incGlobalVar;
request105.readAsText(file, "");
is(globalVar, 0, "testing to make sure getAsText doesn't block subsequent execution");
//Create second file for testing cancelReads()
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
var testFile4 = dirSvc.get("ProfD", Components.interfaces.nsIFile);
testFile4.append("testfile04");
var outStream4 = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
outStream4.init(testFile4, 0x02 | 0x08 | 0x20, 0666, 0);
outStream4.write(testData, testData.length);
outStream4.close();
var fileList = document.getElementById('fileList');
fileList.value = testFile4.path;
var file4 = fileList.files[0];
var request11 = new FileRequest();
request11.onabort = handleCancel;
request11.readAsText(file4);
request11.abort();
//Test error handling - Note: currently throws exceptions
/*testFile4.permissions = 0;
var request12 = new FileRequest();
request12.onerror = handleSecurityError;
request12.readAsText(file4, "");
testFile4.remove(false);
var request13 = new FileRequest();
request13.onerror = handleNotFoundError;
request13.readAsText(file4, "");*/
//Corresponding callback functions
function incGlobalVar(fileAsText) {
globalVar++;
}
function handleCancel(event) {
var fileAsText = event.target.response;
var error = event.target.error;
is(error.code, FileError.ABORT_ERR, "error code set to CANCELED for canceled reads");
is(fileAsText, null, "file data should be null on canceled reads");
testHasRun();
}
function handleTextISO1(event) {
var fileAsText = event.target.response;
var error = event.target.error;
is(error, null, "error code set to null for successful data accesses");
is(testData.length, fileAsText.length, "iso-1 async length should match testdata");
is(testData, fileAsText, "iso-1 async string result should match testdata");
testHasRun();
}
function handleTextUTF8(event) {
var fileAsUTF8 = event.target.response;
var error = event.target.error;
is(error, null, "error code set to null for successful data accesses");
is(testData.length, fileAsUTF8.length, "UTF-8 async length should match testdata");
is(testData, fileAsUTF8, "UTF-8 async string result should match testdata");
testHasRun();
}
function handleTextUTF16(event) {
var fileAsUTF16 = event.target.response;
var error = event.target.error;
is(error, null, "error code set to SUCCESS for successful data accesses");
is(testData.length, fileAsUTF16.length, "UTF-16 async length should match testdata");
is(testData, fileAsUTF16, "UTF-16 async string result should match testdata");
testHasRun();
}
function handleTextUTF32(event) {
var fileAsUTF32 = event.target.response;
var error = event.target.error;
is(error, null, "error code set to SUCCESS for successful data accesses");
is(testData.length, fileAsUTF32.length, "UTF-32 async length should match testdata");
is(testData, fileAsUTF32, "UTF-32 async string result should match testdata");
testHasRun();
}
//Tests dataURI.length % 3 == 0
function handleDataURI(event) {
var fileAsDataURI = event.target.response;
is(domFileData.length, fileAsDataURI.length, "data URI async length should match dom file data");
is(domFileData, fileAsDataURI, "data URI async string result should match dom file data");
testHasRun();
}
//Tests dataURI.length % 3 == 1
function handleDataURI1(event) {
var fileAsDataURI = event.target.response;
is(domFileData1.length, fileAsDataURI.length, "data URI async length should match dom file data1");
is(domFileData1, fileAsDataURI, "data URI async string result should match dom file data1");
testHasRun();
}
//Tests dataURI.length % 3 == 2
function handleDataURI2(event) {
var fileAsDataURI = event.target.response;
is(domFileData2.length, fileAsDataURI.length, "data URI async length should match dom file data2");
is(domFileData2, fileAsDataURI, "data URI async string result should match dom file data2");
testHasRun();
}
function handleDataBinary(event) {
var fileAsBinary = event.target.response;
is(domFileBinary.length, fileAsBinary.length, "binary data async length should match dom file binary");
is(domFileBinary, fileAsBinary, "binary data async string result should match dom file binary");
testHasRun();
}
function handleDataBinary16(event) {
var fileAsBinary = event.target.response;
is(domFileBinary2.length, fileAsBinary.length, "binary data async length should match dom file binary16");
is(domFileBinary2, fileAsBinary, "binary data async string result should match dom file binary16");
testHasRun();
}
function handleDataBinary32(event) {
var fileAsBinary = event.target.response;
is(domFileBinary3.length, fileAsBinary.length, "binary data async length should match dom file binary32");
is(domFileBinary3, fileAsBinary, "binary data async string result should match dom file binary32");
testHasRun();
}
function handleSecurityError(event) {
var fileAsText = event.target.response;
var error = event.target.error;
is(error.code, FileError.SECURITY_ERR, "code for file security error should have value 18");
is(fileAsText, null, "file content should be null when error is encountered");
testHasRun();
}
function handleNotFoundError(event) {
var fileAsText = event.target.response;
var error = event.target.error;
is(error.code, FileError.NOT_FOUND_ERR, "code for file not found error should have value 8");
is(fileAsText, null, "file content should be null when error is encountered");
testHasRun();
}
function testHasRun() {
if (++testCounter == 13) SimpleTest.finish();
}
function createFileWithData(fileData, fileNum) {
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
testFile.append("testfile" + fileNum);
var outStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
var fileList = document.getElementById('fileList');
fileList.value = testFile.path;
return fileList.files[0];
}
</script>
</pre>
</body> </html>

View File

@ -456,7 +456,9 @@
#include "nsDOMWorker.h"
#include "nsDOMFile.h"
#include "nsDOMFileRequest.h"
#include "nsIDOMFileException.h"
#include "nsIDOMFileError.h"
// Simple gestures include
#include "nsIDOMSimpleGestureEvent.h"
@ -1249,6 +1251,10 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(FileException, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(FileError, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(FileRequest, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH,
DEFAULT_SCRIPTABLE_FLAGS |
@ -1365,6 +1371,7 @@ struct nsContractIDMapData
static const nsContractIDMapData kConstructorMap[] =
{
NS_DEFINE_CONSTRUCTOR_DATA(DOMParser, NS_DOMPARSER_CONTRACTID)
NS_DEFINE_CONSTRUCTOR_DATA(FileRequest, NS_FILEREQUEST_CONTRACTID)
NS_DEFINE_CONSTRUCTOR_DATA(XMLSerializer, NS_XMLSERIALIZER_CONTRACTID)
NS_DEFINE_CONSTRUCTOR_DATA(XMLHttpRequest, NS_XMLHTTPREQUEST_CONTRACTID)
NS_DEFINE_CONSTRUCTOR_DATA(XPathEvaluator, NS_XPATH_EVALUATOR_CONTRACTID)
@ -3560,6 +3567,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileList)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(FileError, nsIDOMFileError)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileError)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
DOM_CLASSINFO_MAP_END
@ -3569,6 +3580,13 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIException)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(FileRequest, nsIDOMFileRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIXMLHttpRequestEventTarget)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_ENTRY(nsIInterfaceRequestor)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)

View File

@ -415,6 +415,8 @@ enum nsDOMClassInfoID {
eDOMClassInfo_FileList_id,
eDOMClassInfo_File_id,
eDOMClassInfo_FileException_id,
eDOMClassInfo_FileError_id,
eDOMClassInfo_FileRequest_id,
// DOM modal content window class, almost identical to Window
eDOMClassInfo_ModalContentWindow_id,

View File

@ -117,6 +117,7 @@
// DOM includes
#include "nsDOMException.h"
#include "nsDOMFileRequest.h"
#include "nsGlobalWindowCommands.h"
#include "nsIControllerCommandTable.h"
#include "nsJSProtocolHandler.h"
@ -289,6 +290,7 @@ NS_GENERIC_AGGREGATED_CONSTRUCTOR_INIT(nsXPathEvaluator, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSerializer)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsXMLHttpRequest, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDOMFileRequest, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMParser)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDOMStorageManager,
nsDOMStorageManager::GetInstance)
@ -1365,6 +1367,11 @@ static const nsModuleComponentInfo gComponents[] = {
NS_XMLSERIALIZER_CONTRACTID,
nsDOMSerializerConstructor },
{ "FileRequest",
NS_FILEREQUEST_CID,
NS_FILEREQUEST_CONTRACTID,
nsDOMFileRequestConstructor },
{ "XMLHttpRequest",
NS_XMLHTTPREQUEST_CID,
NS_XMLHTTPREQUEST_CONTRACTID,