Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / filesystem / FileSystemCallbacks.cpp
index 419f7b6..20e0f70 100644 (file)
 #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)
@@ -94,22 +153,21 @@ void EntryCallbacks::didSucceed()
 {
     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)
@@ -128,114 +186,76 @@ void EntriesCallbacks::didReadDirectoryEntry(const String& name, bool isDirector
 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)
 {
 }
@@ -243,41 +263,67 @@ MetadataCallbacks::MetadataCallbacks(PassRefPtr<MetadataCallback> successCallbac
 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)
 {
 }
@@ -285,8 +331,7 @@ VoidCallbacks::VoidCallbacks(PassRefPtr<VoidCallback> successCallback, PassRefPt
 void VoidCallbacks::didSucceed()
 {
     if (m_successCallback)
-        m_successCallback->handleEvent();
-    m_successCallback.clear();
+        handleEventOrScheduleCallback(m_successCallback.release());
 }
 
-} // namespace
+} // namespace blink