Bug 811615: Enable chrome code to create a new File object by wrapping an existing Blob and provide a custom name/type. r=sicking a=basecamp-blocking

This commit is contained in:
Kyle Huey 2012-12-11 03:54:08 -08:00
parent 20f055be42
commit 10448fbbb9
10 changed files with 136 additions and 107 deletions

View File

@ -201,8 +201,7 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMFileCC, nsIDOMFile)
};
class nsDOMFileFile : public nsDOMFile,
public nsIJSNativeInitializer
class nsDOMFileFile : public nsDOMFile
{
public:
// Create as a file
@ -290,15 +289,6 @@ public:
mName.SetIsVoid(true);
}
NS_DECL_ISUPPORTS_INHERITED
// nsIJSNativeInitializer
NS_IMETHOD Initialize(nsISupports* aOwner,
JSContext* aCx,
JSObject* aObj,
uint32_t aArgc,
jsval* aArgv);
// Overrides
NS_IMETHOD GetSize(uint64_t* aSize);
NS_IMETHOD GetType(nsAString& aType);
@ -307,10 +297,6 @@ public:
NS_IMETHOD GetMozFullPathInternal(nsAString& aFullPath);
NS_IMETHOD GetInternalStream(nsIInputStream**);
// DOMClassInfo constructor (for File("foo"))
static nsresult
NewFile(nsISupports* *aNewObject);
protected:
// Create slice
nsDOMFileFile(const nsDOMFileFile* aOther, uint64_t aStart, uint64_t aLength,

View File

@ -6,6 +6,7 @@
#include "nsDOMBlobBuilder.h"
#include "jsfriendapi.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/FileBinding.h"
#include "nsAutoPtr.h"
#include "nsDOMClassInfoID.h"
#include "nsIMultiplexInputStream.h"
@ -171,14 +172,17 @@ nsDOMMultipartFile::Initialize(nsISupports* aOwner,
uint32_t aArgc,
jsval* aArgv)
{
return InitInternal(aCx, aArgc, aArgv, GetXPConnectNative);
if (!mIsFile) {
return InitBlob(aCx, aArgc, aArgv, GetXPConnectNative);
}
return InitFile(aCx, aArgc, aArgv);
}
nsresult
nsDOMMultipartFile::InitInternal(JSContext* aCx,
uint32_t aArgc,
jsval* aArgv,
UnwrapFuncPtr aUnwrapFunc)
nsDOMMultipartFile::InitBlob(JSContext* aCx,
uint32_t aArgc,
jsval* aArgv,
UnwrapFuncPtr aUnwrapFunc)
{
bool nativeEOL = false;
if (aArgc > 1) {
@ -260,6 +264,96 @@ nsDOMMultipartFile::InitInternal(JSContext* aCx,
return NS_OK;
}
nsresult
nsDOMMultipartFile::InitFile(JSContext* aCx,
uint32_t aArgc,
jsval* aArgv)
{
nsresult rv;
NS_ASSERTION(!mImmutable, "Something went wrong ...");
NS_ENSURE_TRUE(!mImmutable, NS_ERROR_UNEXPECTED);
if (!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR; // Real short trip
}
NS_ENSURE_TRUE(aArgc > 0, NS_ERROR_UNEXPECTED);
bool nativeEOL = false;
if (aArgc > 1) {
FilePropertyBag d;
if (!d.Init(aCx, nullptr, aArgv[1])) {
return NS_ERROR_TYPE_ERR;
}
mName = d.name;
mContentType = d.type;
nativeEOL = d.endings == EndingTypesValues::Native;
}
// We expect to get a path to represent as a File object,
// an nsIFile, or an nsIDOMFile.
nsCOMPtr<nsIFile> file;
nsCOMPtr<nsIDOMFile> domFile;
if (!aArgv[0].isString()) {
// Lets see if it's an nsIFile
if (!aArgv[0].isObject()) {
return NS_ERROR_UNEXPECTED; // We're not interested
}
JSObject* obj = &aArgv[0].toObject();
nsISupports* supports =
nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
if (!supports) {
return NS_ERROR_UNEXPECTED;
}
domFile = do_QueryInterface(supports);
file = do_QueryInterface(supports);
if (!domFile && !file) {
return NS_ERROR_UNEXPECTED;
}
} else {
// It's a string
JSString* str = JS_ValueToString(aCx, aArgv[0]);
NS_ENSURE_TRUE(str, NS_ERROR_XPC_BAD_CONVERT_JS);
nsDependentJSString xpcomStr;
if (!xpcomStr.init(aCx, str)) {
return NS_ERROR_XPC_BAD_CONVERT_JS;
}
rv = NS_NewLocalFile(xpcomStr, false, getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
}
if (file) {
bool exists;
rv = file->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(exists, NS_ERROR_FILE_NOT_FOUND);
bool isDir;
rv = file->IsDirectory(&isDir);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_FALSE(isDir, NS_ERROR_FILE_IS_DIRECTORY);
domFile = new nsDOMFileFile(file);
}
// XXXkhuey this is terrible
if (mContentType.IsEmpty()) {
domFile->GetType(mContentType);
}
BlobSet blobSet;
blobSet.AppendBlob(domFile);
mBlobs = blobSet.GetBlobs();
return NS_OK;
}
nsresult
BlobSet::AppendVoidPtr(const void* aData, uint32_t aLength)
{

View File

@ -54,10 +54,13 @@ public:
jsval* aArgv);
typedef nsIDOMBlob* (*UnwrapFuncPtr)(JSContext*, JSObject*);
nsresult InitInternal(JSContext* aCx,
uint32_t aArgc,
jsval* aArgv,
UnwrapFuncPtr aUnwrapFunc);
nsresult InitBlob(JSContext* aCx,
uint32_t aArgc,
jsval* aArgv,
UnwrapFuncPtr aUnwrapFunc);
nsresult InitFile(JSContext* aCx,
uint32_t aArgc,
jsval* aArgv);
already_AddRefed<nsIDOMBlob>
CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType);
@ -72,6 +75,16 @@ public:
static nsresult
NewBlob(nsISupports* *aNewObject);
// DOMClassInfo constructor (for File([b1, "foo"], { type: "image/png",
// name: "foo.png" }))
inline static nsresult
NewFile(nsISupports* *aNewObject)
{
// Initialization will set the filename, so we can pass in an empty string
// for now.
return NewFile(EmptyString(), aNewObject);
}
virtual const nsTArray<nsCOMPtr<nsIDOMBlob> >*
GetSubBlobs() const { return &mBlobs; }

View File

@ -470,9 +470,6 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMFileCC)
////////////////////////////////////////////////////////////////////////////
// nsDOMFileFile implementation
NS_IMPL_ISUPPORTS_INHERITED1(nsDOMFileFile, nsDOMFile,
nsIJSNativeInitializer)
already_AddRefed<nsIDOMBlob>
nsDOMFileFile::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
@ -481,14 +478,6 @@ nsDOMFileFile::CreateSlice(uint64_t aStart, uint64_t aLength,
return t.forget();
}
/* static */ nsresult
nsDOMFileFile::NewFile(nsISupports* *aNewObject)
{
nsCOMPtr<nsISupports> file = do_QueryObject(new nsDOMFileFile());
file.forget(aNewObject);
return NS_OK;
}
NS_IMETHODIMP
nsDOMFileFile::GetMozFullPathInternal(nsAString &aFilename)
{
@ -593,71 +582,6 @@ nsDOMFileFile::GetInternalStream(nsIInputStream **aStream)
-1, -1, sFileStreamFlags);
}
NS_IMETHODIMP
nsDOMFileFile::Initialize(nsISupports* aOwner,
JSContext* aCx,
JSObject* aObj,
uint32_t aArgc,
JS::Value* aArgv)
{
nsresult rv;
NS_ASSERTION(!mImmutable, "Something went wrong ...");
NS_ENSURE_TRUE(!mImmutable, NS_ERROR_UNEXPECTED);
if (!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR; // Real short trip
}
NS_ENSURE_TRUE(aArgc > 0, NS_ERROR_UNEXPECTED);
// We expect to get a path to represent as a File object,
// or an nsIFile
nsCOMPtr<nsIFile> file;
if (!aArgv[0].isString()) {
// Lets see if it's an nsIFile
if (!aArgv[0].isObject()) {
return NS_ERROR_UNEXPECTED; // We're not interested
}
JSObject* obj = &aArgv[0].toObject();
// Is it an nsIFile
file = do_QueryInterface(
nsContentUtils::XPConnect()->
GetNativeOfWrapper(aCx, obj));
if (!file)
return NS_ERROR_UNEXPECTED;
} else {
// It's a string
JSString* str = JS_ValueToString(aCx, aArgv[0]);
NS_ENSURE_TRUE(str, NS_ERROR_XPC_BAD_CONVERT_JS);
nsDependentJSString xpcomStr;
if (!xpcomStr.init(aCx, str)) {
return NS_ERROR_XPC_BAD_CONVERT_JS;
}
rv = NS_NewLocalFile(xpcomStr, false, getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
}
bool exists;
rv = file->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(exists, NS_ERROR_FILE_NOT_FOUND);
bool isDir;
rv = file->IsDirectory(&isDir);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_FALSE(isDir, NS_ERROR_FILE_IS_DIRECTORY);
mFile = file;
file->GetLeafName(mName);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////
// nsDOMMemoryFile implementation

View File

@ -1757,7 +1757,7 @@ struct nsConstructorFuncMapData
static const nsConstructorFuncMapData kConstructorFuncMap[] =
{
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Blob, nsDOMMultipartFile::NewBlob)
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFileFile::NewFile)
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMMultipartFile::NewFile)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(Event)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(UIEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MouseEvent)

9
dom/webidl/File.webidl Normal file
View File

@ -0,0 +1,9 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
dictionary FilePropertyBag : BlobPropertyBag {
DOMString name = "";
};

View File

@ -33,6 +33,7 @@ webidl_files = \
EventHandler.webidl \
EventListener.webidl \
EventTarget.webidl \
File.webidl \
FileHandle.webidl \
FileList.webidl \
FileReaderSync.webidl \

View File

@ -88,8 +88,7 @@ private:
Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
{
nsRefPtr<nsDOMMultipartFile> file = new nsDOMMultipartFile();
nsresult rv = file->InitInternal(aCx, aArgc, JS_ARGV(aCx, aVp),
Unwrap);
nsresult rv = file->InitBlob(aCx, aArgc, JS_ARGV(aCx, aVp), Unwrap);
if (NS_FAILED(rv)) {
ThrowDOMExceptionForNSResult(aCx, rv);
return false;

View File

@ -13,8 +13,11 @@ MODULE = jsloader
LIBRARY_NAME = jsloader_s
FORCE_STATIC_LIB = 1
LIBXUL_LIBRARY = 1
LOCAL_INCLUDES += -I$(srcdir)/../src \
-I$(srcdir)/../wrappers
LOCAL_INCLUDES += \
-I$(srcdir)/../src \
-I$(srcdir)/../wrappers \
-I$(topsrcdir)/content/base/src \
$(NULL)
CPPSRCS = mozJSComponentLoader.cpp mozJSSubScriptLoader.cpp mozJSLoaderUtils.cpp

View File

@ -43,7 +43,7 @@
#include "nsIFileURL.h"
#include "nsIJARURI.h"
#include "nsNetUtil.h"
#include "nsDOMFile.h"
#include "nsDOMBlobBuilder.h"
#include "jsprf.h"
#include "nsJSPrincipals.h"
// For reporting errors with the console service
@ -245,7 +245,7 @@ File(JSContext *cx, unsigned argc, jsval *vp)
}
nsCOMPtr<nsISupports> native;
rv = nsDOMFileFile::NewFile(getter_AddRefs(native));
rv = nsDOMMultipartFile::NewFile(getter_AddRefs(native));
if (NS_FAILED(rv)) {
XPCThrower::Throw(rv, cx);
return false;