Home | History | Annotate | Download | only in filesystem
      1 /*
      2  * Copyright (C) 2010 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "modules/filesystem/FileSystemCallbacks.h"
     33 
     34 #include "core/dom/ExecutionContext.h"
     35 #include "core/fileapi/FileError.h"
     36 #include "core/html/VoidCallback.h"
     37 #include "modules/filesystem/DOMFilePath.h"
     38 #include "modules/filesystem/DOMFileSystem.h"
     39 #include "modules/filesystem/DOMFileSystemBase.h"
     40 #include "modules/filesystem/DirectoryEntry.h"
     41 #include "modules/filesystem/DirectoryReader.h"
     42 #include "modules/filesystem/Entry.h"
     43 #include "modules/filesystem/EntryCallback.h"
     44 #include "modules/filesystem/ErrorCallback.h"
     45 #include "modules/filesystem/FileEntry.h"
     46 #include "modules/filesystem/FileSystemCallback.h"
     47 #include "modules/filesystem/FileWriterBase.h"
     48 #include "modules/filesystem/FileWriterBaseCallback.h"
     49 #include "modules/filesystem/Metadata.h"
     50 #include "modules/filesystem/MetadataCallback.h"
     51 #include "platform/FileMetadata.h"
     52 #include "public/platform/WebFileWriter.h"
     53 
     54 namespace WebCore {
     55 
     56 FileSystemCallbacksBase::FileSystemCallbacksBase(PassOwnPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem, ExecutionContext* context)
     57     : m_errorCallback(errorCallback)
     58     , m_fileSystem(fileSystem)
     59     , m_executionContext(context)
     60 {
     61     if (m_fileSystem)
     62         m_fileSystem->addPendingCallbacks();
     63 }
     64 
     65 FileSystemCallbacksBase::~FileSystemCallbacksBase()
     66 {
     67     if (m_fileSystem)
     68         m_fileSystem->removePendingCallbacks();
     69 }
     70 
     71 void FileSystemCallbacksBase::didFail(int code)
     72 {
     73     if (m_errorCallback)
     74         handleEventOrScheduleCallback(m_errorCallback.release(), FileError::create(static_cast<FileError::ErrorCode>(code)));
     75 }
     76 
     77 bool FileSystemCallbacksBase::shouldScheduleCallback() const
     78 {
     79     return !shouldBlockUntilCompletion() && m_executionContext && m_executionContext->activeDOMObjectsAreSuspended();
     80 }
     81 
     82 template <typename CB, typename CBArg>
     83 void FileSystemCallbacksBase::handleEventOrScheduleCallback(PassOwnPtr<CB> callback, CBArg* arg)
     84 {
     85     ASSERT(callback.get());
     86     if (shouldScheduleCallback())
     87         DOMFileSystem::scheduleCallback(m_executionContext.get(), callback, arg);
     88     else if (callback)
     89         callback->handleEvent(arg);
     90     m_executionContext.clear();
     91 }
     92 
     93 template <typename CB, typename CBArg>
     94 void FileSystemCallbacksBase::handleEventOrScheduleCallback(PassOwnPtr<CB> callback, PassRefPtrWillBeRawPtr<CBArg> arg)
     95 {
     96     ASSERT(callback.get());
     97     if (shouldScheduleCallback())
     98         DOMFileSystem::scheduleCallback(m_executionContext.get(), callback, arg);
     99     else if (callback)
    100         callback->handleEvent(arg.get());
    101     m_executionContext.clear();
    102 }
    103 
    104 template <typename CB>
    105 void FileSystemCallbacksBase::handleEventOrScheduleCallback(PassOwnPtr<CB> callback)
    106 {
    107     ASSERT(callback.get());
    108     if (shouldScheduleCallback())
    109         DOMFileSystem::scheduleCallback(m_executionContext.get(), callback);
    110     else if (callback)
    111         callback->handleEvent();
    112     m_executionContext.clear();
    113 }
    114 
    115 // EntryCallbacks -------------------------------------------------------------
    116 
    117 PassOwnPtr<AsyncFileSystemCallbacks> EntryCallbacks::create(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem, const String& expectedPath, bool isDirectory)
    118 {
    119     return adoptPtr(new EntryCallbacks(successCallback, errorCallback, context, fileSystem, expectedPath, isDirectory));
    120 }
    121 
    122 EntryCallbacks::EntryCallbacks(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem, const String& expectedPath, bool isDirectory)
    123     : FileSystemCallbacksBase(errorCallback, fileSystem, context)
    124     , m_successCallback(successCallback)
    125     , m_expectedPath(expectedPath)
    126     , m_isDirectory(isDirectory)
    127 {
    128 }
    129 
    130 void EntryCallbacks::didSucceed()
    131 {
    132     if (m_successCallback) {
    133         if (m_isDirectory)
    134             handleEventOrScheduleCallback(m_successCallback.release(), DirectoryEntry::create(m_fileSystem, m_expectedPath));
    135         else
    136             handleEventOrScheduleCallback(m_successCallback.release(), FileEntry::create(m_fileSystem, m_expectedPath));
    137     }
    138 }
    139 
    140 // EntriesCallbacks -----------------------------------------------------------
    141 
    142 PassOwnPtr<AsyncFileSystemCallbacks> EntriesCallbacks::create(PassOwnPtr<EntriesCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DirectoryReaderBase* directoryReader, const String& basePath)
    143 {
    144     return adoptPtr(new EntriesCallbacks(successCallback, errorCallback, context, directoryReader, basePath));
    145 }
    146 
    147 EntriesCallbacks::EntriesCallbacks(PassOwnPtr<EntriesCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DirectoryReaderBase* directoryReader, const String& basePath)
    148     : FileSystemCallbacksBase(errorCallback, directoryReader->filesystem(), context)
    149     , m_successCallback(successCallback)
    150     , m_directoryReader(directoryReader)
    151     , m_basePath(basePath)
    152 {
    153     ASSERT(m_directoryReader);
    154 }
    155 
    156 void EntriesCallbacks::didReadDirectoryEntry(const String& name, bool isDirectory)
    157 {
    158     if (isDirectory)
    159         m_entries.append(DirectoryEntry::create(m_directoryReader->filesystem(), DOMFilePath::append(m_basePath, name)));
    160     else
    161         m_entries.append(FileEntry::create(m_directoryReader->filesystem(), DOMFilePath::append(m_basePath, name)));
    162 }
    163 
    164 void EntriesCallbacks::didReadDirectoryEntries(bool hasMore)
    165 {
    166     m_directoryReader->setHasMoreEntries(hasMore);
    167     EntryHeapVector entries;
    168     entries.swap(m_entries);
    169     // FIXME: delay the callback iff shouldScheduleCallback() is true.
    170     if (m_successCallback)
    171         m_successCallback->handleEvent(entries);
    172 }
    173 
    174 // FileSystemCallbacks --------------------------------------------------------
    175 
    176 PassOwnPtr<AsyncFileSystemCallbacks> FileSystemCallbacks::create(PassOwnPtr<FileSystemCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, FileSystemType type)
    177 {
    178     return adoptPtr(new FileSystemCallbacks(successCallback, errorCallback, context, type));
    179 }
    180 
    181 FileSystemCallbacks::FileSystemCallbacks(PassOwnPtr<FileSystemCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, FileSystemType type)
    182     : FileSystemCallbacksBase(errorCallback, nullptr, context)
    183     , m_successCallback(successCallback)
    184     , m_type(type)
    185 {
    186 }
    187 
    188 void FileSystemCallbacks::didOpenFileSystem(const String& name, const KURL& rootURL)
    189 {
    190     if (m_successCallback)
    191         handleEventOrScheduleCallback(m_successCallback.release(), DOMFileSystem::create(m_executionContext.get(), name, m_type, rootURL));
    192 }
    193 
    194 // ResolveURICallbacks --------------------------------------------------------
    195 
    196 PassOwnPtr<AsyncFileSystemCallbacks> ResolveURICallbacks::create(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context)
    197 {
    198     return adoptPtr(new ResolveURICallbacks(successCallback, errorCallback, context));
    199 }
    200 
    201 ResolveURICallbacks::ResolveURICallbacks(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context)
    202     : FileSystemCallbacksBase(errorCallback, nullptr, context)
    203     , m_successCallback(successCallback)
    204 {
    205 }
    206 
    207 void ResolveURICallbacks::didResolveURL(const String& name, const KURL& rootURL, FileSystemType type, const String& filePath, bool isDirectory)
    208 {
    209     DOMFileSystem* filesystem = DOMFileSystem::create(m_executionContext.get(), name, type, rootURL);
    210     DirectoryEntry* root = filesystem->root();
    211 
    212     String absolutePath;
    213     if (!DOMFileSystemBase::pathToAbsolutePath(type, root, filePath, absolutePath)) {
    214         handleEventOrScheduleCallback(m_errorCallback.release(), FileError::create(FileError::INVALID_MODIFICATION_ERR));
    215         return;
    216     }
    217 
    218     if (isDirectory)
    219         handleEventOrScheduleCallback(m_successCallback.release(), DirectoryEntry::create(filesystem, absolutePath));
    220     else
    221         handleEventOrScheduleCallback(m_successCallback.release(), FileEntry::create(filesystem, absolutePath));
    222 }
    223 
    224 // MetadataCallbacks ----------------------------------------------------------
    225 
    226 PassOwnPtr<AsyncFileSystemCallbacks> MetadataCallbacks::create(PassOwnPtr<MetadataCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem)
    227 {
    228     return adoptPtr(new MetadataCallbacks(successCallback, errorCallback, context, fileSystem));
    229 }
    230 
    231 MetadataCallbacks::MetadataCallbacks(PassOwnPtr<MetadataCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem)
    232     : FileSystemCallbacksBase(errorCallback, fileSystem, context)
    233     , m_successCallback(successCallback)
    234 {
    235 }
    236 
    237 void MetadataCallbacks::didReadMetadata(const FileMetadata& metadata)
    238 {
    239     if (m_successCallback)
    240         handleEventOrScheduleCallback(m_successCallback.release(), Metadata::create(metadata));
    241 }
    242 
    243 // FileWriterBaseCallbacks ----------------------------------------------------------
    244 
    245 PassOwnPtr<AsyncFileSystemCallbacks> FileWriterBaseCallbacks::create(PassRefPtrWillBeRawPtr<FileWriterBase> fileWriter, PassOwnPtr<FileWriterBaseCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context)
    246 {
    247     return adoptPtr(new FileWriterBaseCallbacks(fileWriter, successCallback, errorCallback, context));
    248 }
    249 
    250 FileWriterBaseCallbacks::FileWriterBaseCallbacks(PassRefPtrWillBeRawPtr<FileWriterBase> fileWriter, PassOwnPtr<FileWriterBaseCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context)
    251     : FileSystemCallbacksBase(errorCallback, nullptr, context)
    252     , m_fileWriter(fileWriter.get())
    253     , m_successCallback(successCallback)
    254 {
    255 }
    256 
    257 void FileWriterBaseCallbacks::didCreateFileWriter(PassOwnPtr<blink::WebFileWriter> fileWriter, long long length)
    258 {
    259     m_fileWriter->initialize(fileWriter, length);
    260     if (m_successCallback)
    261         handleEventOrScheduleCallback(m_successCallback.release(), m_fileWriter.release());
    262 }
    263 
    264 // VoidCallbacks --------------------------------------------------------------
    265 
    266 PassOwnPtr<AsyncFileSystemCallbacks> VoidCallbacks::create(PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem)
    267 {
    268     return adoptPtr(new VoidCallbacks(successCallback, errorCallback, context, fileSystem));
    269 }
    270 
    271 VoidCallbacks::VoidCallbacks(PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem)
    272     : FileSystemCallbacksBase(errorCallback, fileSystem, context)
    273     , m_successCallback(successCallback)
    274 {
    275 }
    276 
    277 void VoidCallbacks::didSucceed()
    278 {
    279     if (m_successCallback)
    280         handleEventOrScheduleCallback(m_successCallback.release());
    281 }
    282 
    283 } // namespace
    284