mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-27 15:54:21 +00:00
Bug 1265767 - Subset of Blink FileSystem API - patch 4 - DirectoryEntry methods, r=smaug
This commit is contained in:
parent
52fbfbc75d
commit
5a24e4a0ff
@ -5,6 +5,7 @@
|
|||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "DirectoryEntry.h"
|
#include "DirectoryEntry.h"
|
||||||
|
#include "DirectoryReader.h"
|
||||||
#include "ErrorCallbackRunnable.h"
|
#include "ErrorCallbackRunnable.h"
|
||||||
#include "mozilla/dom/Directory.h"
|
#include "mozilla/dom/Directory.h"
|
||||||
|
|
||||||
@ -49,6 +50,14 @@ DirectoryEntry::GetFullPath(nsAString& aPath, ErrorResult& aRv) const
|
|||||||
mDirectory->GetPath(aPath, aRv);
|
mDirectory->GetPath(aPath, aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<DirectoryReader>
|
||||||
|
DirectoryEntry::CreateReader() const
|
||||||
|
{
|
||||||
|
RefPtr<DirectoryReader> reader =
|
||||||
|
new DirectoryReader(GetParentObject(), mDirectory);
|
||||||
|
return reader.forget();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DirectoryEntry::RemoveRecursively(VoidCallback& aSuccessCallback,
|
DirectoryEntry::RemoveRecursively(VoidCallback& aSuccessCallback,
|
||||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const
|
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const
|
||||||
|
@ -39,11 +39,7 @@ public:
|
|||||||
GetFullPath(nsAString& aFullPath, ErrorResult& aRv) const override;
|
GetFullPath(nsAString& aFullPath, ErrorResult& aRv) const override;
|
||||||
|
|
||||||
already_AddRefed<DirectoryReader>
|
already_AddRefed<DirectoryReader>
|
||||||
CreateReader(ErrorResult& aRv) const
|
CreateReader() const;
|
||||||
{
|
|
||||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
GetFile(const nsAString& aPath, const FileSystemFlags& aFlag,
|
GetFile(const nsAString& aPath, const FileSystemFlags& aFlag,
|
||||||
|
@ -5,12 +5,132 @@
|
|||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "DirectoryReader.h"
|
#include "DirectoryReader.h"
|
||||||
|
#include "FileEntry.h"
|
||||||
|
#include "mozilla/dom/FileBinding.h"
|
||||||
|
#include "mozilla/dom/Directory.h"
|
||||||
|
#include "mozilla/dom/DirectoryBinding.h"
|
||||||
|
#include "mozilla/dom/Promise.h"
|
||||||
|
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||||
#include "nsIGlobalObject.h"
|
#include "nsIGlobalObject.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DirectoryReader, mParent)
|
namespace {
|
||||||
|
|
||||||
|
class EmptyEntriesCallbackRunnable final : public Runnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EmptyEntriesCallbackRunnable(EntriesCallback* aCallback)
|
||||||
|
: mCallback(aCallback)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD
|
||||||
|
Run() override
|
||||||
|
{
|
||||||
|
Sequence<OwningNonNull<Entry>> sequence;
|
||||||
|
mCallback->HandleEvent(sequence);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RefPtr<EntriesCallback> mCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PromiseHandler final : public PromiseNativeHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
PromiseHandler(nsIGlobalObject* aGlobalObject,
|
||||||
|
EntriesCallback* aSuccessCallback,
|
||||||
|
ErrorCallback* aErrorCallback)
|
||||||
|
: mGlobal(aGlobalObject)
|
||||||
|
, mSuccessCallback(aSuccessCallback)
|
||||||
|
, mErrorCallback(aErrorCallback)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aGlobalObject);
|
||||||
|
MOZ_ASSERT(aSuccessCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
||||||
|
{
|
||||||
|
if(NS_WARN_IF(!aValue.isObject())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
|
||||||
|
|
||||||
|
uint32_t length;
|
||||||
|
if (NS_WARN_IF(!JS_GetArrayLength(aCx, obj, &length))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sequence<OwningNonNull<Entry>> sequence;
|
||||||
|
if (NS_WARN_IF(!sequence.SetLength(length, fallible))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < length; ++i) {
|
||||||
|
JS::Rooted<JS::Value> value(aCx);
|
||||||
|
if (NS_WARN_IF(!JS_GetElement(aCx, obj, i, &value))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(NS_WARN_IF(!value.isObject())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JSObject*> valueObj(aCx, &value.toObject());
|
||||||
|
|
||||||
|
RefPtr<File> file;
|
||||||
|
if (NS_SUCCEEDED(UNWRAP_OBJECT(File, valueObj, file))) {
|
||||||
|
RefPtr<FileEntry> entry = new FileEntry(mGlobal, file);
|
||||||
|
sequence[i] = entry;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<Directory> directory;
|
||||||
|
if (NS_WARN_IF(NS_FAILED(UNWRAP_OBJECT(Directory, valueObj,
|
||||||
|
directory)))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<DirectoryEntry> entry = new DirectoryEntry(mGlobal, directory);
|
||||||
|
sequence[i] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSuccessCallback->HandleEvent(sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
||||||
|
{
|
||||||
|
if (mErrorCallback) {
|
||||||
|
RefPtr<ErrorCallbackRunnable> runnable =
|
||||||
|
new ErrorCallbackRunnable(mGlobal, mErrorCallback,
|
||||||
|
NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
|
nsresult rv = NS_DispatchToMainThread(runnable);
|
||||||
|
NS_WARN_IF(NS_FAILED(rv));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
~PromiseHandler() {}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||||
|
RefPtr<EntriesCallback> mSuccessCallback;
|
||||||
|
RefPtr<ErrorCallback> mErrorCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS0(PromiseHandler);
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DirectoryReader, mParent, mDirectory)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(DirectoryReader)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(DirectoryReader)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(DirectoryReader)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(DirectoryReader)
|
||||||
@ -20,9 +140,15 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DirectoryReader)
|
|||||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||||
NS_INTERFACE_MAP_END
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
DirectoryReader::DirectoryReader(nsIGlobalObject* aGlobal)
|
DirectoryReader::DirectoryReader(nsIGlobalObject* aGlobal,
|
||||||
|
Directory* aDirectory)
|
||||||
: mParent(aGlobal)
|
: mParent(aGlobal)
|
||||||
{}
|
, mDirectory(aDirectory)
|
||||||
|
, mAlreadyRead(false)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aGlobal);
|
||||||
|
MOZ_ASSERT(aDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
DirectoryReader::~DirectoryReader()
|
DirectoryReader::~DirectoryReader()
|
||||||
{}
|
{}
|
||||||
@ -33,5 +159,43 @@ DirectoryReader::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|||||||
return DirectoryReaderBinding::Wrap(aCx, this, aGivenProto);
|
return DirectoryReaderBinding::Wrap(aCx, this, aGivenProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DirectoryReader::ReadEntries(EntriesCallback& aSuccessCallback,
|
||||||
|
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
if (mAlreadyRead) {
|
||||||
|
RefPtr<EmptyEntriesCallbackRunnable> runnable =
|
||||||
|
new EmptyEntriesCallbackRunnable(&aSuccessCallback);
|
||||||
|
aRv = NS_DispatchToMainThread(runnable);
|
||||||
|
NS_WARN_IF(aRv.Failed());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This object can be used only once.
|
||||||
|
mAlreadyRead = true;
|
||||||
|
|
||||||
|
ErrorResult rv;
|
||||||
|
RefPtr<Promise> promise = mDirectory->GetFilesAndDirectories(rv);
|
||||||
|
if (NS_WARN_IF(rv.Failed())) {
|
||||||
|
if (aErrorCallback.WasPassed()) {
|
||||||
|
RefPtr<ErrorCallbackRunnable> runnable =
|
||||||
|
new ErrorCallbackRunnable(GetParentObject(),
|
||||||
|
&aErrorCallback.Value(),
|
||||||
|
rv.StealNSResult());
|
||||||
|
aRv = NS_DispatchToMainThread(runnable);
|
||||||
|
NS_WARN_IF(aRv.Failed());
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<PromiseHandler> handler =
|
||||||
|
new PromiseHandler(GetParentObject(), &aSuccessCallback,
|
||||||
|
aErrorCallback.WasPassed()
|
||||||
|
? &aErrorCallback.Value() : nullptr);
|
||||||
|
promise->AppendNativeHandler(handler);
|
||||||
|
}
|
||||||
|
|
||||||
} // dom namespace
|
} // dom namespace
|
||||||
} // mozilla namespace
|
} // mozilla namespace
|
||||||
|
@ -18,6 +18,8 @@ class nsIGlobalObject;
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
class Directory;
|
||||||
|
|
||||||
class DirectoryReader final
|
class DirectoryReader final
|
||||||
: public nsISupports
|
: public nsISupports
|
||||||
, public nsWrapperCache
|
, public nsWrapperCache
|
||||||
@ -26,7 +28,8 @@ public:
|
|||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DirectoryReader)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DirectoryReader)
|
||||||
|
|
||||||
explicit DirectoryReader(nsIGlobalObject* aGlobalObject);
|
explicit DirectoryReader(nsIGlobalObject* aGlobalObject,
|
||||||
|
Directory* aDirectory);
|
||||||
|
|
||||||
nsIGlobalObject*
|
nsIGlobalObject*
|
||||||
GetParentObject() const
|
GetParentObject() const
|
||||||
@ -40,15 +43,15 @@ public:
|
|||||||
void
|
void
|
||||||
ReadEntries(EntriesCallback& aSuccessCallback,
|
ReadEntries(EntriesCallback& aSuccessCallback,
|
||||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
|
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
|
||||||
ErrorResult& aRv) const
|
ErrorResult& aRv);
|
||||||
{
|
|
||||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~DirectoryReader();
|
~DirectoryReader();
|
||||||
|
|
||||||
nsCOMPtr<nsIGlobalObject> mParent;
|
nsCOMPtr<nsIGlobalObject> mParent;
|
||||||
|
RefPtr<Directory> mDirectory;
|
||||||
|
|
||||||
|
bool mAlreadyRead;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
@ -17,12 +17,15 @@ class ErrorCallbackRunnable final : public Runnable
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ErrorCallbackRunnable(nsIGlobalObject* aGlobalObject,
|
explicit ErrorCallbackRunnable(nsIGlobalObject* aGlobalObject,
|
||||||
ErrorCallback* aCallback)
|
ErrorCallback* aCallback,
|
||||||
|
nsresult aError = NS_ERROR_DOM_NOT_SUPPORTED_ERR)
|
||||||
: mGlobal(aGlobalObject)
|
: mGlobal(aGlobalObject)
|
||||||
, mCallback(aCallback)
|
, mCallback(aCallback)
|
||||||
|
, mError(aError)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aGlobalObject);
|
MOZ_ASSERT(aGlobalObject);
|
||||||
MOZ_ASSERT(aCallback);
|
MOZ_ASSERT(aCallback);
|
||||||
|
MOZ_ASSERT(NS_FAILED(aError));
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHOD
|
NS_IMETHOD
|
||||||
@ -33,8 +36,7 @@ public:
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<DOMError> error =
|
RefPtr<DOMError> error = new DOMError(window, mError);
|
||||||
new DOMError(window, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
|
||||||
mCallback->HandleEvent(*error);
|
mCallback->HandleEvent(*error);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -42,6 +44,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||||
RefPtr<ErrorCallback> mCallback;
|
RefPtr<ErrorCallback> mCallback;
|
||||||
|
nsresult mError;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // dom namespace
|
} // dom namespace
|
||||||
|
@ -89,6 +89,33 @@ function test_directoryEntry() {
|
|||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_directoryEntry_createReader() {
|
||||||
|
var reader = directoryEntry.createReader();
|
||||||
|
ok(reader, "We have a DirectoryReader");
|
||||||
|
|
||||||
|
reader.readEntries(function(a) {
|
||||||
|
ok(Array.isArray(a), "We want an array.");
|
||||||
|
is(a.length, 2, "reader.readyEntries returns 2 elements.");
|
||||||
|
|
||||||
|
for (var i = 0; i < 2; ++i) {
|
||||||
|
ok(a[i].name == "subdir" || a[i].name == "foo.txt", "Correct names");
|
||||||
|
is(a[i].fullPath, directoryEntry.fullPath + "/" + a[i].name, "FullPath is correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called twice:
|
||||||
|
reader.readEntries(function(a) {
|
||||||
|
ok(Array.isArray(a), "We want an array.");
|
||||||
|
is(a.length, 0, "reader.readyEntries returns 0 elements.");
|
||||||
|
next();
|
||||||
|
}, function() {
|
||||||
|
ok(false, "Something when wrong!");
|
||||||
|
});
|
||||||
|
|
||||||
|
}, function() {
|
||||||
|
ok(false, "Something when wrong!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var tests = [
|
var tests = [
|
||||||
setup_tests,
|
setup_tests,
|
||||||
populate_entries,
|
populate_entries,
|
||||||
@ -100,6 +127,7 @@ var tests = [
|
|||||||
test_fileEntry_createWriter,
|
test_fileEntry_createWriter,
|
||||||
|
|
||||||
test_directoryEntry,
|
test_directoryEntry,
|
||||||
|
test_directoryEntry_createReader,
|
||||||
];
|
];
|
||||||
|
|
||||||
function next() {
|
function next() {
|
||||||
|
@ -32,7 +32,7 @@ public:
|
|||||||
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) = 0;
|
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) = 0;
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
#ifdef SPIDERMONKEY_PROMISE
|
||||||
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
||||||
JS::MutableHandle<JSObject*> aWrapper);
|
JS::MutableHandle<JSObject*> aWrapper);
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
#endif // SPIDERMONKEY_PROMISE
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ callback interface VoidCallback {
|
|||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject]
|
||||||
interface DirectoryEntry : Entry {
|
interface DirectoryEntry : Entry {
|
||||||
[Throws]
|
|
||||||
DirectoryReader createReader();
|
DirectoryReader createReader();
|
||||||
|
|
||||||
[Throws]
|
[Throws]
|
||||||
@ -68,6 +67,9 @@ callback interface ErrorCallback {
|
|||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject]
|
||||||
interface DirectoryReader {
|
interface DirectoryReader {
|
||||||
|
|
||||||
|
// readEntries can be called just once. The second time it returns no data.
|
||||||
|
|
||||||
[Throws]
|
[Throws]
|
||||||
void readEntries (EntriesCallback successCallback, optional ErrorCallback errorCallback);
|
void readEntries (EntriesCallback successCallback, optional ErrorCallback errorCallback);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user