#include "modules/filesystem/Entry.h"
#include "modules/filesystem/ErrorCallback.h"
-namespace WebCore {
+namespace blink {
-DirectoryReader::DirectoryReader(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath)
+class DirectoryReader::EntriesCallbackHelper final : public EntriesCallback {
+public:
+ explicit EntriesCallbackHelper(DirectoryReader* reader)
+ : m_reader(reader)
+ {
+ }
+
+ virtual void handleEvent(const EntryHeapVector& entries) override
+ {
+ m_reader->addEntries(entries);
+ }
+
+ virtual void trace(Visitor* visitor) override
+ {
+ visitor->trace(m_reader);
+ EntriesCallback::trace(visitor);
+ }
+
+private:
+ // FIXME: This Member keeps the reader alive until all of the readDirectory results are received. crbug.com/350285
+ Member<DirectoryReader> m_reader;
+};
+
+class DirectoryReader::ErrorCallbackHelper final : public ErrorCallback {
+public:
+ explicit ErrorCallbackHelper(DirectoryReader* reader)
+ : m_reader(reader)
+ {
+ }
+
+ virtual void handleEvent(FileError* error) override
+ {
+ m_reader->onError(error);
+ }
+
+ virtual void trace(Visitor* visitor) override
+ {
+ visitor->trace(m_reader);
+ ErrorCallback::trace(visitor);
+ }
+
+private:
+ Member<DirectoryReader> m_reader;
+};
+
+DirectoryReader::DirectoryReader(DOMFileSystemBase* fileSystem, const String& fullPath)
: DirectoryReaderBase(fileSystem, fullPath)
+ , m_isReading(false)
{
- ScriptWrappable::init(this);
}
-void DirectoryReader::readEntries(PassOwnPtr<EntriesCallback> entriesCallback, PassOwnPtr<ErrorCallback> errorCallback)
+DirectoryReader::~DirectoryReader()
{
- if (!m_hasMoreEntries) {
- filesystem()->scheduleCallback(entriesCallback, EntryVector());
+}
+
+void DirectoryReader::readEntries(EntriesCallback* entriesCallback, ErrorCallback* errorCallback)
+{
+ if (!m_isReading) {
+ m_isReading = true;
+ filesystem()->readDirectory(this, m_fullPath, new EntriesCallbackHelper(this), new ErrorCallbackHelper(this));
+ }
+
+ if (m_error) {
+ filesystem()->scheduleCallback(errorCallback, m_error);
return;
}
- filesystem()->readDirectory(this, m_fullPath, entriesCallback, errorCallback);
+
+ if (m_entriesCallback) {
+ // Non-null m_entriesCallback means multiple readEntries() calls are made concurrently. We don't allow doing it.
+ filesystem()->scheduleCallback(errorCallback, FileError::create(FileError::INVALID_STATE_ERR));
+ return;
+ }
+
+ if (!m_hasMoreEntries || !m_entries.isEmpty()) {
+ filesystem()->scheduleCallback(entriesCallback, m_entries);
+ m_entries.clear();
+ return;
+ }
+
+ m_entriesCallback = entriesCallback;
+ m_errorCallback = errorCallback;
+}
+
+void DirectoryReader::addEntries(const EntryHeapVector& entries)
+{
+ m_entries.appendVector(entries);
+ m_errorCallback = nullptr;
+ if (m_entriesCallback) {
+ EntriesCallback* entriesCallback = m_entriesCallback.release();
+ EntryHeapVector entries;
+ entries.swap(m_entries);
+ entriesCallback->handleEvent(entries);
+ }
+}
+
+void DirectoryReader::onError(FileError* error)
+{
+ m_error = error;
+ m_entriesCallback = nullptr;
+ if (m_errorCallback) {
+ ErrorCallback* errorCallback = m_errorCallback.release();
+ errorCallback->handleEvent(error);
+ }
+}
+
+void DirectoryReader::trace(Visitor* visitor)
+{
+ visitor->trace(m_entries);
+ visitor->trace(m_error);
+ visitor->trace(m_entriesCallback);
+ visitor->trace(m_errorCallback);
+ DirectoryReaderBase::trace(visitor);
}
}