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