diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 55115b622a5..9da956c3f7e 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -230,6 +230,10 @@ DOMInterfaces = { 'concrete': False }], +'FileHandle': { + 'nativeType': 'mozilla::dom::file::FileHandle' +}, + 'FileList': { 'nativeType': 'nsDOMFileList', 'headerFile': 'nsDOMFile.h', @@ -736,11 +740,13 @@ addExternalIface('ClientRect') addExternalIface('CSSRule') addExternalIface('CSSValue') addExternalIface('DocumentType', nativeType='nsIDOMDocumentType') +addExternalIface('DOMRequest') addExternalIface('DOMStringList', nativeType='nsDOMStringList', headerFile='nsDOMLists.h') addExternalIface('File') addExternalIface('HitRegionOptions', nativeType='nsISupports') addExternalIface('HTMLElement') +addExternalIface('LockedFile') addExternalIface('MediaStream') addExternalIface('NamedNodeMap') addExternalIface('PaintRequest') diff --git a/dom/file/FileHandle.cpp b/dom/file/FileHandle.cpp index 0222d057cda..c673c97fbef 100644 --- a/dom/file/FileHandle.cpp +++ b/dom/file/FileHandle.cpp @@ -17,6 +17,8 @@ #include "LockedFile.h" #include "MetadataHelper.h" +using namespace mozilla; +using namespace mozilla::dom; USING_FILE_NAMESPACE namespace { @@ -63,14 +65,14 @@ NS_IMPL_EVENT_HANDLER(FileHandle, abort) NS_IMPL_EVENT_HANDLER(FileHandle, error) NS_IMETHODIMP -FileHandle::GetName(nsAString& aName) +FileHandle::GetDOMName(nsAString& aName) { aName = mName; return NS_OK; } NS_IMETHODIMP -FileHandle::GetType(nsAString& aType) +FileHandle::GetDOMType(nsAString& aType) { aType = mType; return NS_OK; @@ -81,48 +83,77 @@ FileHandle::Open(const nsAString& aMode, uint8_t aOptionalArgCount, nsIDOMLockedFile** _retval) { - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - if (FileService::IsShuttingDown() || mFileStorage->IsStorageShuttingDown()) { - return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR; - } - - LockedFile::Mode mode; + FileMode mode; if (aOptionalArgCount) { if (aMode.EqualsLiteral("readwrite")) { - mode = LockedFile::READ_WRITE; - } - else if (aMode.EqualsLiteral("readonly")) { - mode = LockedFile::READ_ONLY; - } - else { + mode = FileModeValues::Readwrite; + } else if (aMode.EqualsLiteral("readonly")) { + mode = FileModeValues::Readonly; + } else { return NS_ERROR_TYPE_ERR; } - } - else { - mode = LockedFile::READ_ONLY; + } else { + mode = FileModeValues::Readonly; } - nsRefPtr lockedFile = LockedFile::Create(this, mode); - NS_ENSURE_TRUE(lockedFile, NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); - + ErrorResult rv; + nsCOMPtr lockedFile = Open(mode, rv); lockedFile.forget(_retval); - return NS_OK; + return rv.ErrorCode(); +} + +already_AddRefed +FileHandle::Open(FileMode aMode, ErrorResult& aError) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (FileService::IsShuttingDown() || mFileStorage->IsStorageShuttingDown()) { + aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); + return nullptr; + } + + MOZ_STATIC_ASSERT(static_cast(FileModeValues::Readonly) == + static_cast(LockedFile::READ_ONLY), + "Enum values should match."); + MOZ_STATIC_ASSERT(static_cast(FileModeValues::Readwrite) == + static_cast(LockedFile::READ_WRITE), + "Enum values should match."); + + nsRefPtr lockedFile = + LockedFile::Create(this, static_cast(aMode)); + if (!lockedFile) { + aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); + return nullptr; + } + + return lockedFile.forget(); } NS_IMETHODIMP FileHandle::GetFile(nsIDOMDOMRequest** _retval) { - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + ErrorResult rv; + nsCOMPtr request = GetFile(rv); + request.forget(_retval); + return rv.ErrorCode(); +} + +already_AddRefed +FileHandle::GetFile(ErrorResult& aError) +{ + MOZ_ASSERT(NS_IsMainThread()); // Do nothing if the window is closed if (!GetOwner()) { - return NS_OK; + return nullptr; } nsRefPtr lockedFile = LockedFile::Create(this, LockedFile::READ_ONLY, LockedFile::PARALLEL); - NS_ENSURE_TRUE(lockedFile, NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); + if (!lockedFile) { + aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); + return nullptr; + } nsRefPtr request = FileRequest::Create(GetOwner(), lockedFile, false); @@ -134,12 +165,13 @@ FileHandle::GetFile(nsIDOMDOMRequest** _retval) new GetFileHelper(lockedFile, request, params, this); nsresult rv = helper->Enqueue(); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); + if (NS_FAILED(rv)) { + aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); + return nullptr; + } - nsCOMPtr result = static_cast(request); - result.forget(_retval); - - return NS_OK; + nsRefPtr domRequest = request.forget(); + return domRequest.forget(); } NS_IMETHODIMP_(int64_t) @@ -167,3 +199,10 @@ GetFileHelper::GetSuccessResult(JSContext* aCx, jsval* aVal) return NS_OK; } + +/* virtual */ +JSObject* +FileHandle::WrapObject(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap) +{ + return FileHandleBinding::Wrap(aCx, aScope, this, aTriedToWrap); +} diff --git a/dom/file/FileHandle.h b/dom/file/FileHandle.h index 7dcaf539617..6e7e75fa05b 100644 --- a/dom/file/FileHandle.h +++ b/dom/file/FileHandle.h @@ -15,6 +15,9 @@ #include "nsDOMEventTargetHelper.h" +#include "mozilla/Attributes.h" +#include "mozilla/dom/FileHandleBinding.h" + class nsIDOMFile; class nsIFileStorage; @@ -43,6 +46,26 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMFILEHANDLE + nsPIDOMWindow* GetParentObject() const + { + return GetOwner(); + } + virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope, + bool* aTriedToWrap) MOZ_OVERRIDE; + + void GetName(nsString& aName) const + { + aName = mName; + } + void GetType(nsString& aType) const + { + aType = mType; + } + already_AddRefed Open(FileMode aMode, ErrorResult& aError); + already_AddRefed GetFile(ErrorResult& aError); + IMPL_EVENT_HANDLER(abort) + IMPL_EVENT_HANDLER(error) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FileHandle, nsDOMEventTargetHelper) const nsAString& @@ -65,7 +88,9 @@ public: protected: FileHandle() - { } + { + SetIsDOMBinding(); + } ~FileHandle() { } diff --git a/dom/file/nsIDOMFileHandle.idl b/dom/file/nsIDOMFileHandle.idl index 57a0cca3541..4e692605e35 100644 --- a/dom/file/nsIDOMFileHandle.idl +++ b/dom/file/nsIDOMFileHandle.idl @@ -25,8 +25,10 @@ interface nsIDOMLockedFile; [scriptable, builtinclass, uuid(47438729-7f3f-4a66-b6d4-d1297c593d46)] interface nsIDOMFileHandle : nsISupports { + [binaryname(DOMName)] readonly attribute DOMString name; + [binaryname(DOMType)] readonly attribute DOMString type; // mode can be either "readonly" or "readwrite" diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp index 73361ac7ffd..746d4731837 100644 --- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -1280,6 +1280,40 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx, return JS_WriteBytes(aWriter, &value, sizeof(value)); } + IDBTransaction* transaction = cloneWriteInfo->mTransaction; + FileManager* fileManager = transaction->Database()->Manager(); + + file::FileHandle* fileHandle = nullptr; + if (NS_SUCCEEDED(UnwrapObject(aCx, aObj, fileHandle))) { + nsRefPtr fileInfo = fileHandle->GetFileInfo(); + + // Throw when trying to store non IDB file handles or IDB file handles + // across databases. + if (!fileInfo || fileInfo->Manager() != fileManager) { + return false; + } + + NS_ConvertUTF16toUTF8 convType(fileHandle->Type()); + uint32_t convTypeLength = SwapBytes(convType.Length()); + + NS_ConvertUTF16toUTF8 convName(fileHandle->Name()); + uint32_t convNameLength = SwapBytes(convName.Length()); + + if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILEHANDLE, + cloneWriteInfo->mFiles.Length()) || + !JS_WriteBytes(aWriter, &convTypeLength, sizeof(uint32_t)) || + !JS_WriteBytes(aWriter, convType.get(), convType.Length()) || + !JS_WriteBytes(aWriter, &convNameLength, sizeof(uint32_t)) || + !JS_WriteBytes(aWriter, convName.get(), convName.Length())) { + return false; + } + + StructuredCloneFile* file = cloneWriteInfo->mFiles.AppendElement(); + file->mFileInfo = fileInfo.forget(); + + return true; + } + nsCOMPtr wrappedNative; nsContentUtils::XPConnect()-> GetWrappedNativeOfJSObject(aCx, aObj, getter_AddRefs(wrappedNative)); @@ -1287,9 +1321,6 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx, if (wrappedNative) { nsISupports* supports = wrappedNative->Native(); - IDBTransaction* transaction = cloneWriteInfo->mTransaction; - FileManager* fileManager = transaction->Database()->Manager(); - nsCOMPtr blob = do_QueryInterface(supports); if (blob) { nsCOMPtr inputStream; @@ -1372,47 +1403,6 @@ IDBObjectStore::StructuredCloneWriteCallback(JSContext* aCx, return true; } - - nsCOMPtr fileHandle = do_QueryInterface(supports); - if (fileHandle) { - nsRefPtr fileInfo = fileHandle->GetFileInfo(); - - // Throw when trying to store non IDB file handles or IDB file handles - // across databases. - if (!fileInfo || fileInfo->Manager() != fileManager) { - return false; - } - - nsString type; - if (NS_FAILED(fileHandle->GetType(type))) { - NS_WARNING("Failed to get type!"); - return false; - } - NS_ConvertUTF16toUTF8 convType(type); - uint32_t convTypeLength = SwapBytes(convType.Length()); - - nsString name; - if (NS_FAILED(fileHandle->GetName(name))) { - NS_WARNING("Failed to get name!"); - return false; - } - NS_ConvertUTF16toUTF8 convName(name); - uint32_t convNameLength = SwapBytes(convName.Length()); - - if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILEHANDLE, - cloneWriteInfo->mFiles.Length()) || - !JS_WriteBytes(aWriter, &convTypeLength, sizeof(uint32_t)) || - !JS_WriteBytes(aWriter, convType.get(), convType.Length()) || - !JS_WriteBytes(aWriter, &convNameLength, sizeof(uint32_t)) || - !JS_WriteBytes(aWriter, convName.get(), convName.Length())) { - return false; - } - - StructuredCloneFile* file = cloneWriteInfo->mFiles.AppendElement(); - file->mFileInfo = fileInfo.forget(); - - return true; - } } // try using the runtime callbacks diff --git a/dom/webidl/FileHandle.webidl b/dom/webidl/FileHandle.webidl new file mode 100644 index 00000000000..57da19887cd --- /dev/null +++ b/dom/webidl/FileHandle.webidl @@ -0,0 +1,24 @@ +/* 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/. */ + +interface DOMRequest; +interface LockedFile; + +enum FileMode { "readonly", "readwrite" }; + +interface FileHandle : EventTarget { + readonly attribute DOMString name; + readonly attribute DOMString type; + + [Throws] + LockedFile open(optional FileMode mode = "readonly"); + + [Throws] + DOMRequest getFile(); + + [SetterThrows] + attribute EventHandler onabort; + [SetterThrows] + attribute EventHandler onerror; +}; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 6bbfb8a1e6e..6d1b717cfbc 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -32,6 +32,7 @@ webidl_files = \ EventHandler.webidl \ EventListener.webidl \ EventTarget.webidl \ + FileHandle.webidl \ FileList.webidl \ FileReaderSync.webidl \ Function.webidl \