#include "modules/filesystem/FileSystemCallbacks.h"
#include "core/dom/ExecutionContext.h"
+#include "core/fileapi/File.h"
#include "core/fileapi/FileError.h"
#include "core/html/VoidCallback.h"
+#include "core/inspector/InspectorInstrumentation.h"
#include "modules/filesystem/DOMFilePath.h"
+#include "modules/filesystem/DOMFileSystem.h"
#include "modules/filesystem/DOMFileSystemBase.h"
#include "modules/filesystem/DirectoryEntry.h"
#include "modules/filesystem/DirectoryReader.h"
-#include "modules/filesystem/EntriesCallback.h"
#include "modules/filesystem/Entry.h"
#include "modules/filesystem/EntryCallback.h"
#include "modules/filesystem/ErrorCallback.h"
+#include "modules/filesystem/FileCallback.h"
#include "modules/filesystem/FileEntry.h"
#include "modules/filesystem/FileSystemCallback.h"
#include "modules/filesystem/FileWriterBase.h"
#include "platform/FileMetadata.h"
#include "public/platform/WebFileWriter.h"
-namespace WebCore {
+namespace blink {
-FileSystemCallbacksBase::FileSystemCallbacksBase(PassRefPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem)
+FileSystemCallbacksBase::FileSystemCallbacksBase(ErrorCallback* errorCallback, DOMFileSystemBase* fileSystem, ExecutionContext* context)
: m_errorCallback(errorCallback)
, m_fileSystem(fileSystem)
+ , m_executionContext(context)
+ , m_asyncOperationId(0)
{
if (m_fileSystem)
m_fileSystem->addPendingCallbacks();
+ if (m_executionContext)
+ m_asyncOperationId = InspectorInstrumentation::traceAsyncOperationStarting(m_executionContext.get(), "FileSystem");
}
FileSystemCallbacksBase::~FileSystemCallbacksBase()
{
if (m_fileSystem)
m_fileSystem->removePendingCallbacks();
+ if (m_asyncOperationId && m_executionContext)
+ InspectorInstrumentation::traceAsyncOperationCompleted(m_executionContext.get(), m_asyncOperationId);
}
void FileSystemCallbacksBase::didFail(int code)
{
- if (m_errorCallback) {
- m_errorCallback->handleEvent(FileError::create(static_cast<FileError::ErrorCode>(code)).get());
- m_errorCallback.clear();
- }
+ if (m_errorCallback)
+ handleEventOrScheduleCallback(m_errorCallback.release(), FileError::create(static_cast<FileError::ErrorCode>(code)));
+}
+
+bool FileSystemCallbacksBase::shouldScheduleCallback() const
+{
+ return !shouldBlockUntilCompletion() && m_executionContext && m_executionContext->activeDOMObjectsAreSuspended();
+}
+
+#if !ENABLE(OILPAN)
+template <typename CB, typename CBArg>
+void FileSystemCallbacksBase::handleEventOrScheduleCallback(RawPtr<CB> callback, RawPtr<CBArg> arg)
+{
+ handleEventOrScheduleCallback(callback, arg.get());
+}
+#endif
+
+template <typename CB, typename CBArg>
+void FileSystemCallbacksBase::handleEventOrScheduleCallback(RawPtr<CB> callback, CBArg* arg)
+{
+ ASSERT(callback);
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::traceAsyncOperationCompletedCallbackStarting(m_executionContext.get(), m_asyncOperationId);
+ if (shouldScheduleCallback())
+ DOMFileSystem::scheduleCallback(m_executionContext.get(), callback.get(), arg);
+ else if (callback)
+ callback->handleEvent(arg);
+ m_executionContext.clear();
+ InspectorInstrumentation::traceAsyncCallbackCompleted(cookie);
+}
+
+template <typename CB, typename CBArg>
+void FileSystemCallbacksBase::handleEventOrScheduleCallback(RawPtr<CB> callback, PassRefPtrWillBeRawPtr<CBArg> arg)
+{
+ ASSERT(callback);
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::traceAsyncOperationCompletedCallbackStarting(m_executionContext.get(), m_asyncOperationId);
+ if (shouldScheduleCallback())
+ DOMFileSystem::scheduleCallback(m_executionContext.get(), callback.get(), arg);
+ else if (callback)
+ callback->handleEvent(arg.get());
+ m_executionContext.clear();
+ InspectorInstrumentation::traceAsyncCallbackCompleted(cookie);
+}
+
+template <typename CB>
+void FileSystemCallbacksBase::handleEventOrScheduleCallback(RawPtr<CB> callback)
+{
+ ASSERT(callback);
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::traceAsyncOperationCompletedCallbackStarting(m_executionContext.get(), m_asyncOperationId);
+ if (shouldScheduleCallback())
+ DOMFileSystem::scheduleCallback(m_executionContext.get(), callback.get());
+ else if (callback)
+ callback->handleEvent();
+ m_executionContext.clear();
+ InspectorInstrumentation::traceAsyncCallbackCompleted(cookie);
}
// EntryCallbacks -------------------------------------------------------------
-PassOwnPtr<AsyncFileSystemCallbacks> EntryCallbacks::create(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DOMFileSystemBase> fileSystem, const String& expectedPath, bool isDirectory)
+PassOwnPtr<AsyncFileSystemCallbacks> EntryCallbacks::create(EntryCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem, const String& expectedPath, bool isDirectory)
{
- return adoptPtr(static_cast<AsyncFileSystemCallbacks*>(new EntryCallbacks(successCallback, errorCallback, fileSystem, expectedPath, isDirectory)));
+ return adoptPtr(new EntryCallbacks(successCallback, errorCallback, context, fileSystem, expectedPath, isDirectory));
}
-EntryCallbacks::EntryCallbacks(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DOMFileSystemBase> fileSystem, const String& expectedPath, bool isDirectory)
- : FileSystemCallbacksBase(errorCallback, fileSystem.get())
+EntryCallbacks::EntryCallbacks(EntryCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem, const String& expectedPath, bool isDirectory)
+ : FileSystemCallbacksBase(errorCallback, fileSystem, context)
, m_successCallback(successCallback)
, m_expectedPath(expectedPath)
, m_isDirectory(isDirectory)
{
if (m_successCallback) {
if (m_isDirectory)
- m_successCallback->handleEvent(DirectoryEntry::create(m_fileSystem, m_expectedPath).get());
+ handleEventOrScheduleCallback(m_successCallback.release(), DirectoryEntry::create(m_fileSystem, m_expectedPath));
else
- m_successCallback->handleEvent(FileEntry::create(m_fileSystem, m_expectedPath).get());
+ handleEventOrScheduleCallback(m_successCallback.release(), FileEntry::create(m_fileSystem, m_expectedPath));
}
- m_successCallback.clear();
}
// EntriesCallbacks -----------------------------------------------------------
-PassOwnPtr<AsyncFileSystemCallbacks> EntriesCallbacks::create(PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryReaderBase> directoryReader, const String& basePath)
+PassOwnPtr<AsyncFileSystemCallbacks> EntriesCallbacks::create(EntriesCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, DirectoryReaderBase* directoryReader, const String& basePath)
{
- return adoptPtr(static_cast<AsyncFileSystemCallbacks*>(new EntriesCallbacks(successCallback, errorCallback, directoryReader, basePath)));
+ return adoptPtr(new EntriesCallbacks(successCallback, errorCallback, context, directoryReader, basePath));
}
-EntriesCallbacks::EntriesCallbacks(PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryReaderBase> directoryReader, const String& basePath)
- : FileSystemCallbacksBase(errorCallback, directoryReader->filesystem())
+EntriesCallbacks::EntriesCallbacks(EntriesCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, DirectoryReaderBase* directoryReader, const String& basePath)
+ : FileSystemCallbacksBase(errorCallback, directoryReader->filesystem(), context)
, m_successCallback(successCallback)
, m_directoryReader(directoryReader)
, m_basePath(basePath)
void EntriesCallbacks::didReadDirectoryEntries(bool hasMore)
{
m_directoryReader->setHasMoreEntries(hasMore);
+ EntryHeapVector entries;
+ entries.swap(m_entries);
+ // FIXME: delay the callback iff shouldScheduleCallback() is true.
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::traceAsyncCallbackStarting(m_executionContext.get(), m_asyncOperationId);
if (m_successCallback)
- m_successCallback->handleEvent(m_entries);
+ m_successCallback->handleEvent(entries);
+ InspectorInstrumentation::traceAsyncCallbackCompleted(cookie);
+ if (!hasMore)
+ InspectorInstrumentation::traceAsyncOperationCompleted(m_executionContext.get(), m_asyncOperationId);
}
// FileSystemCallbacks --------------------------------------------------------
-PassOwnPtr<AsyncFileSystemCallbacks> FileSystemCallbacks::create(PassRefPtr<FileSystemCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ExecutionContext* executionContext, FileSystemType type)
+PassOwnPtr<AsyncFileSystemCallbacks> FileSystemCallbacks::create(FileSystemCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, FileSystemType type)
{
- return adoptPtr(static_cast<AsyncFileSystemCallbacks*>(new FileSystemCallbacks(successCallback, errorCallback, executionContext, type)));
+ return adoptPtr(new FileSystemCallbacks(successCallback, errorCallback, context, type));
}
-FileSystemCallbacks::FileSystemCallbacks(PassRefPtr<FileSystemCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ExecutionContext* context, FileSystemType type)
- : FileSystemCallbacksBase(errorCallback, 0)
+FileSystemCallbacks::FileSystemCallbacks(FileSystemCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, FileSystemType type)
+ : FileSystemCallbacksBase(errorCallback, nullptr, context)
, m_successCallback(successCallback)
- , m_executionContext(context)
, m_type(type)
{
}
void FileSystemCallbacks::didOpenFileSystem(const String& name, const KURL& rootURL)
{
- if (m_successCallback) {
- RefPtr<DOMFileSystem> fileSystem = DOMFileSystem::create(m_executionContext.get(), name, m_type, rootURL);
- m_successCallback->handleEvent(fileSystem.get());
- m_executionContext.clear();
- }
- m_successCallback.clear();
+ if (m_successCallback)
+ handleEventOrScheduleCallback(m_successCallback.release(), DOMFileSystem::create(m_executionContext.get(), name, m_type, rootURL));
}
// ResolveURICallbacks --------------------------------------------------------
-namespace {
-
-class ErrorCallbackWrapper : public ErrorCallback {
-public:
- static PassRefPtr<ErrorCallbackWrapper> create(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryEntry> root, const String& filePath)
- {
- return adoptRef(new ErrorCallbackWrapper(successCallback, errorCallback, root, filePath));
- }
-
- virtual bool handleEvent(FileError* error)
- {
- ASSERT(error);
- if (error->code() == FileError::TYPE_MISMATCH_ERR)
- m_root->getFile(m_filePath, Dictionary(), m_successCallback, m_errorCallback);
- else if (m_errorCallback)
- m_errorCallback->handleEvent(error);
- return true;
- }
-
-private:
- ErrorCallbackWrapper(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryEntry> root, const String& filePath)
- : m_successCallback(successCallback)
- , m_errorCallback(errorCallback)
- , m_root(root)
- , m_filePath(filePath)
- {
- ASSERT(m_root);
- }
-
- RefPtr<EntryCallback> m_successCallback;
- RefPtr<ErrorCallback> m_errorCallback;
- RefPtr<DirectoryEntry> m_root;
- String m_filePath;
-};
-
-} // namespace
-
-PassOwnPtr<AsyncFileSystemCallbacks> ResolveURICallbacks::create(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ExecutionContext* executionContext)
+PassOwnPtr<AsyncFileSystemCallbacks> ResolveURICallbacks::create(EntryCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context)
{
- return adoptPtr(static_cast<AsyncFileSystemCallbacks*>(new ResolveURICallbacks(successCallback, errorCallback, executionContext)));
+ return adoptPtr(new ResolveURICallbacks(successCallback, errorCallback, context));
}
-ResolveURICallbacks::ResolveURICallbacks(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ExecutionContext* context)
- : FileSystemCallbacksBase(errorCallback, 0)
+ResolveURICallbacks::ResolveURICallbacks(EntryCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context)
+ : FileSystemCallbacksBase(errorCallback, nullptr, context)
, m_successCallback(successCallback)
- , m_executionContext(context)
{
}
void ResolveURICallbacks::didResolveURL(const String& name, const KURL& rootURL, FileSystemType type, const String& filePath, bool isDirectory)
{
- RefPtr<DOMFileSystem> filesystem = DOMFileSystem::create(m_executionContext.get(), name, type, rootURL);
- RefPtr<DirectoryEntry> root = filesystem->root();
+ DOMFileSystem* filesystem = DOMFileSystem::create(m_executionContext.get(), name, type, rootURL);
+ DirectoryEntry* root = filesystem->root();
String absolutePath;
- if (!DOMFileSystemBase::pathToAbsolutePath(type, root.get(), filePath, absolutePath)) {
- m_errorCallback->handleEvent(FileError::create(FileError::INVALID_MODIFICATION_ERR).get());
- m_errorCallback.clear();
+ if (!DOMFileSystemBase::pathToAbsolutePath(type, root, filePath, absolutePath)) {
+ handleEventOrScheduleCallback(m_errorCallback.release(), FileError::create(FileError::INVALID_MODIFICATION_ERR));
return;
}
if (isDirectory)
- m_successCallback->handleEvent(DirectoryEntry::create(filesystem, absolutePath).get());
+ handleEventOrScheduleCallback(m_successCallback.release(), DirectoryEntry::create(filesystem, absolutePath));
else
- m_successCallback->handleEvent(FileEntry::create(filesystem, absolutePath).get());
- m_successCallback.clear();
+ handleEventOrScheduleCallback(m_successCallback.release(), FileEntry::create(filesystem, absolutePath));
}
// MetadataCallbacks ----------------------------------------------------------
-PassOwnPtr<AsyncFileSystemCallbacks> MetadataCallbacks::create(PassRefPtr<MetadataCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem)
+PassOwnPtr<AsyncFileSystemCallbacks> MetadataCallbacks::create(MetadataCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem)
{
- return adoptPtr(static_cast<AsyncFileSystemCallbacks*>(new MetadataCallbacks(successCallback, errorCallback, fileSystem)));
+ return adoptPtr(new MetadataCallbacks(successCallback, errorCallback, context, fileSystem));
}
-MetadataCallbacks::MetadataCallbacks(PassRefPtr<MetadataCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem)
- : FileSystemCallbacksBase(errorCallback, fileSystem)
+MetadataCallbacks::MetadataCallbacks(MetadataCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem)
+ : FileSystemCallbacksBase(errorCallback, fileSystem, context)
, m_successCallback(successCallback)
{
}
void MetadataCallbacks::didReadMetadata(const FileMetadata& metadata)
{
if (m_successCallback)
- m_successCallback->handleEvent(Metadata::create(metadata).get());
- m_successCallback.clear();
+ handleEventOrScheduleCallback(m_successCallback.release(), Metadata::create(metadata));
}
-// FileWriterBaseCallbacks ----------------------------------------------------------
+// FileWriterBaseCallbacks ----------------------------------------------------
-PassOwnPtr<AsyncFileSystemCallbacks> FileWriterBaseCallbacks::create(PassRefPtr<FileWriterBase> fileWriter, PassRefPtr<FileWriterBaseCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
+PassOwnPtr<AsyncFileSystemCallbacks> FileWriterBaseCallbacks::create(PassRefPtrWillBeRawPtr<FileWriterBase> fileWriter, FileWriterBaseCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context)
{
- return adoptPtr(static_cast<AsyncFileSystemCallbacks*>(new FileWriterBaseCallbacks(fileWriter, successCallback, errorCallback)));
+ return adoptPtr(new FileWriterBaseCallbacks(fileWriter, successCallback, errorCallback, context));
}
-FileWriterBaseCallbacks::FileWriterBaseCallbacks(PassRefPtr<FileWriterBase> fileWriter, PassRefPtr<FileWriterBaseCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
- : FileSystemCallbacksBase(errorCallback, 0)
- , m_fileWriter(fileWriter)
+FileWriterBaseCallbacks::FileWriterBaseCallbacks(PassRefPtrWillBeRawPtr<FileWriterBase> fileWriter, FileWriterBaseCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context)
+ : FileSystemCallbacksBase(errorCallback, nullptr, context)
+ , m_fileWriter(fileWriter.get())
, m_successCallback(successCallback)
{
}
-void FileWriterBaseCallbacks::didCreateFileWriter(PassOwnPtr<WebKit::WebFileWriter> fileWriter, long long length)
+void FileWriterBaseCallbacks::didCreateFileWriter(PassOwnPtr<WebFileWriter> fileWriter, long long length)
{
m_fileWriter->initialize(fileWriter, length);
if (m_successCallback)
- m_successCallback->handleEvent(m_fileWriter.release().get());
- m_successCallback.clear();
+ handleEventOrScheduleCallback(m_successCallback.release(), m_fileWriter.release());
+}
+
+// SnapshotFileCallback -------------------------------------------------------
+
+PassOwnPtr<AsyncFileSystemCallbacks> SnapshotFileCallback::create(DOMFileSystemBase* filesystem, const String& name, const KURL& url, FileCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context)
+{
+ return adoptPtr(new SnapshotFileCallback(filesystem, name, url, successCallback, errorCallback, context));
+}
+
+SnapshotFileCallback::SnapshotFileCallback(DOMFileSystemBase* filesystem, const String& name, const KURL& url, FileCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context)
+ : FileSystemCallbacksBase(errorCallback, filesystem, context)
+ , m_name(name)
+ , m_url(url)
+ , m_successCallback(successCallback)
+{
+}
+
+void SnapshotFileCallback::didCreateSnapshotFile(const FileMetadata& metadata, PassRefPtr<BlobDataHandle> snapshot)
+{
+ if (!m_successCallback)
+ return;
+
+ // We can't directly use the snapshot blob data handle because the content type on it hasn't been set.
+ // The |snapshot| param is here to provide a a chain of custody thru thread bridging that is held onto until
+ // *after* we've coined a File with a new handle that has the correct type set on it. This allows the
+ // blob storage system to track when a temp file can and can't be safely deleted.
+
+ handleEventOrScheduleCallback(m_successCallback.release(), DOMFileSystemBase::createFile(metadata, m_url, m_fileSystem->type(), m_name));
}
// VoidCallbacks --------------------------------------------------------------
-PassOwnPtr<AsyncFileSystemCallbacks> VoidCallbacks::create(PassRefPtr<VoidCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem)
+PassOwnPtr<AsyncFileSystemCallbacks> VoidCallbacks::create(VoidCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem)
{
- return adoptPtr(static_cast<AsyncFileSystemCallbacks*>(new VoidCallbacks(successCallback, errorCallback, fileSystem)));
+ return adoptPtr(new VoidCallbacks(successCallback, errorCallback, context, fileSystem));
}
-VoidCallbacks::VoidCallbacks(PassRefPtr<VoidCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem)
- : FileSystemCallbacksBase(errorCallback, fileSystem)
+VoidCallbacks::VoidCallbacks(VoidCallback* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem)
+ : FileSystemCallbacksBase(errorCallback, fileSystem, context)
, m_successCallback(successCallback)
{
}
void VoidCallbacks::didSucceed()
{
if (m_successCallback)
- m_successCallback->handleEvent();
- m_successCallback.clear();
+ handleEventOrScheduleCallback(m_successCallback.release());
}
-} // namespace
+} // namespace blink