mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-27 07:34:20 +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/. */
|
||||
|
||||
#include "DirectoryEntry.h"
|
||||
#include "DirectoryReader.h"
|
||||
#include "ErrorCallbackRunnable.h"
|
||||
#include "mozilla/dom/Directory.h"
|
||||
|
||||
@ -49,6 +50,14 @@ DirectoryEntry::GetFullPath(nsAString& aPath, ErrorResult& aRv) const
|
||||
mDirectory->GetPath(aPath, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<DirectoryReader>
|
||||
DirectoryEntry::CreateReader() const
|
||||
{
|
||||
RefPtr<DirectoryReader> reader =
|
||||
new DirectoryReader(GetParentObject(), mDirectory);
|
||||
return reader.forget();
|
||||
}
|
||||
|
||||
void
|
||||
DirectoryEntry::RemoveRecursively(VoidCallback& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const
|
||||
|
@ -39,11 +39,7 @@ public:
|
||||
GetFullPath(nsAString& aFullPath, ErrorResult& aRv) const override;
|
||||
|
||||
already_AddRefed<DirectoryReader>
|
||||
CreateReader(ErrorResult& aRv) const
|
||||
{
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return nullptr;
|
||||
}
|
||||
CreateReader() const;
|
||||
|
||||
void
|
||||
GetFile(const nsAString& aPath, const FileSystemFlags& aFlag,
|
||||
|
@ -5,12 +5,132 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#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"
|
||||
|
||||
namespace mozilla {
|
||||
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_RELEASE(DirectoryReader)
|
||||
@ -20,9 +140,15 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DirectoryReader)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
DirectoryReader::DirectoryReader(nsIGlobalObject* aGlobal)
|
||||
DirectoryReader::DirectoryReader(nsIGlobalObject* aGlobal,
|
||||
Directory* aDirectory)
|
||||
: mParent(aGlobal)
|
||||
{}
|
||||
, mDirectory(aDirectory)
|
||||
, mAlreadyRead(false)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT(aDirectory);
|
||||
}
|
||||
|
||||
DirectoryReader::~DirectoryReader()
|
||||
{}
|
||||
@ -33,5 +159,43 @@ DirectoryReader::WrapObject(JSContext* aCx, JS::Handle<JSObject*> 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
|
||||
} // mozilla namespace
|
||||
|
@ -18,6 +18,8 @@ class nsIGlobalObject;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Directory;
|
||||
|
||||
class DirectoryReader final
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
@ -26,7 +28,8 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DirectoryReader)
|
||||
|
||||
explicit DirectoryReader(nsIGlobalObject* aGlobalObject);
|
||||
explicit DirectoryReader(nsIGlobalObject* aGlobalObject,
|
||||
Directory* aDirectory);
|
||||
|
||||
nsIGlobalObject*
|
||||
GetParentObject() const
|
||||
@ -40,15 +43,15 @@ public:
|
||||
void
|
||||
ReadEntries(EntriesCallback& aSuccessCallback,
|
||||
const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
~DirectoryReader();
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mParent;
|
||||
RefPtr<Directory> mDirectory;
|
||||
|
||||
bool mAlreadyRead;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -17,12 +17,15 @@ class ErrorCallbackRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
explicit ErrorCallbackRunnable(nsIGlobalObject* aGlobalObject,
|
||||
ErrorCallback* aCallback)
|
||||
ErrorCallback* aCallback,
|
||||
nsresult aError = NS_ERROR_DOM_NOT_SUPPORTED_ERR)
|
||||
: mGlobal(aGlobalObject)
|
||||
, mCallback(aCallback)
|
||||
, mError(aError)
|
||||
{
|
||||
MOZ_ASSERT(aGlobalObject);
|
||||
MOZ_ASSERT(aCallback);
|
||||
MOZ_ASSERT(NS_FAILED(aError));
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
@ -33,8 +36,7 @@ public:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<DOMError> error =
|
||||
new DOMError(window, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
RefPtr<DOMError> error = new DOMError(window, mError);
|
||||
mCallback->HandleEvent(*error);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -42,6 +44,7 @@ public:
|
||||
private:
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<ErrorCallback> mCallback;
|
||||
nsresult mError;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
|
@ -89,6 +89,33 @@ function test_directoryEntry() {
|
||||
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 = [
|
||||
setup_tests,
|
||||
populate_entries,
|
||||
@ -100,6 +127,7 @@ var tests = [
|
||||
test_fileEntry_createWriter,
|
||||
|
||||
test_directoryEntry,
|
||||
test_directoryEntry_createReader,
|
||||
];
|
||||
|
||||
function next() {
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) = 0;
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
||||
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aWrapper);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
|
@ -43,7 +43,6 @@ callback interface VoidCallback {
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface DirectoryEntry : Entry {
|
||||
[Throws]
|
||||
DirectoryReader createReader();
|
||||
|
||||
[Throws]
|
||||
@ -68,6 +67,9 @@ callback interface ErrorCallback {
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface DirectoryReader {
|
||||
|
||||
// readEntries can be called just once. The second time it returns no data.
|
||||
|
||||
[Throws]
|
||||
void readEntries (EntriesCallback successCallback, optional ErrorCallback errorCallback);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user