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 "DOMFileSystemSync.h" 33 34 #if ENABLE(FILE_SYSTEM) 35 36 #include "AsyncFileSystem.h" 37 #include "AsyncFileWriter.h" 38 #include "DOMFilePath.h" 39 #include "DirectoryEntrySync.h" 40 #include "ErrorCallback.h" 41 #include "File.h" 42 #include "FileEntrySync.h" 43 #include "FileError.h" 44 #include "FileException.h" 45 #include "FileMetadata.h" 46 #include "FileSystemCallbacks.h" 47 #include "FileWriterBaseCallback.h" 48 #include "FileWriterSync.h" 49 50 namespace WebCore { 51 52 class FileWriterBase; 53 54 PassRefPtr<DOMFileSystemSync> DOMFileSystemSync::create(DOMFileSystemBase* fileSystem) 55 { 56 return adoptRef(new DOMFileSystemSync(fileSystem->m_context, fileSystem->m_name, fileSystem->m_asyncFileSystem.release())); 57 } 58 59 DOMFileSystemSync::DOMFileSystemSync(ScriptExecutionContext* context, const String& name, PassOwnPtr<AsyncFileSystem> asyncFileSystem) 60 : DOMFileSystemBase(context, name, asyncFileSystem) 61 { 62 } 63 64 DOMFileSystemSync::~DOMFileSystemSync() 65 { 66 } 67 68 PassRefPtr<DirectoryEntrySync> DOMFileSystemSync::root() 69 { 70 return DirectoryEntrySync::create(this, DOMFilePath::root); 71 } 72 73 namespace { 74 75 class GetPathHelper : public AsyncFileSystemCallbacks { 76 public: 77 class GetPathResult : public RefCounted<GetPathResult> { 78 public: 79 static PassRefPtr<GetPathResult> create() 80 { 81 return adoptRef(new GetPathResult()); 82 } 83 84 bool m_failed; 85 int m_code; 86 String m_path; 87 88 private: 89 GetPathResult() 90 : m_failed(false) 91 , m_code(0) 92 { 93 } 94 95 ~GetPathResult() 96 { 97 } 98 friend class WTF::RefCounted<GetPathResult>; 99 }; 100 101 static PassOwnPtr<GetPathHelper> create(PassRefPtr<GetPathResult> result) 102 { 103 return adoptPtr(new GetPathHelper(result)); 104 } 105 106 virtual void didSucceed() 107 { 108 ASSERT_NOT_REACHED(); 109 } 110 111 virtual void didOpenFileSystem(const String&, PassOwnPtr<AsyncFileSystem>) 112 { 113 ASSERT_NOT_REACHED(); 114 } 115 116 virtual void didReadDirectoryEntry(const String&, bool) 117 { 118 ASSERT_NOT_REACHED(); 119 } 120 121 virtual void didReadDirectoryEntries(bool) 122 { 123 ASSERT_NOT_REACHED(); 124 } 125 126 virtual void didCreateFileWriter(PassOwnPtr<AsyncFileWriter>, long long) 127 { 128 ASSERT_NOT_REACHED(); 129 } 130 131 virtual void didFail(int code) 132 { 133 m_result->m_failed = true; 134 m_result->m_code = code; 135 } 136 137 virtual ~GetPathHelper() 138 { 139 } 140 141 void didReadMetadata(const FileMetadata& metadata) 142 { 143 m_result->m_path = metadata.platformPath; 144 } 145 private: 146 GetPathHelper(PassRefPtr<GetPathResult> result) 147 : m_result(result) 148 { 149 } 150 151 RefPtr<GetPathResult> m_result; 152 }; 153 154 } // namespace 155 156 PassRefPtr<File> DOMFileSystemSync::createFile(const FileEntrySync* fileEntry, ExceptionCode& ec) 157 { 158 ec = 0; 159 String platformPath = m_asyncFileSystem->virtualToPlatformPath(fileEntry->fullPath()); 160 RefPtr<GetPathHelper::GetPathResult> result(GetPathHelper::GetPathResult::create()); 161 m_asyncFileSystem->readMetadata(platformPath, GetPathHelper::create(result)); 162 if (!m_asyncFileSystem->waitForOperationToComplete()) { 163 ec = FileException::ABORT_ERR; 164 return 0; 165 } 166 if (result->m_failed) { 167 ec = result->m_code; 168 return 0; 169 } 170 if (!result->m_path.isEmpty()) 171 platformPath = result->m_path; 172 return File::create(platformPath); 173 } 174 175 namespace { 176 177 class ReceiveFileWriterCallback : public FileWriterBaseCallback { 178 public: 179 static PassRefPtr<ReceiveFileWriterCallback> create() 180 { 181 return adoptRef(new ReceiveFileWriterCallback()); 182 } 183 184 bool handleEvent(FileWriterBase* fileWriterBase) 185 { 186 #ifndef NDEBUG 187 m_fileWriterBase = fileWriterBase; 188 #else 189 ASSERT_UNUSED(fileWriterBase, fileWriterBase); 190 #endif 191 return true; 192 } 193 194 #ifndef NDEBUG 195 FileWriterBase* fileWriterBase() 196 { 197 return m_fileWriterBase; 198 } 199 #endif 200 201 private: 202 ReceiveFileWriterCallback() 203 #ifndef NDEBUG 204 : m_fileWriterBase(0) 205 #endif 206 { 207 } 208 209 #ifndef NDEBUG 210 FileWriterBase* m_fileWriterBase; 211 #endif 212 }; 213 214 class LocalErrorCallback : public ErrorCallback { 215 public: 216 static PassRefPtr<LocalErrorCallback> create() 217 { 218 return adoptRef(new LocalErrorCallback()); 219 } 220 221 bool handleEvent(FileError* error) 222 { 223 m_error = error; 224 return true; 225 } 226 227 FileError* error() 228 { 229 return m_error.get(); 230 } 231 232 private: 233 LocalErrorCallback() 234 { 235 } 236 RefPtr<FileError> m_error; 237 }; 238 239 } 240 241 PassRefPtr<FileWriterSync> DOMFileSystemSync::createWriter(const FileEntrySync* fileEntry, ExceptionCode& ec) 242 { 243 ASSERT(fileEntry); 244 ec = 0; 245 246 String platformPath = m_asyncFileSystem->virtualToPlatformPath(fileEntry->fullPath()); 247 248 RefPtr<FileWriterSync> fileWriter = FileWriterSync::create(); 249 RefPtr<ReceiveFileWriterCallback> successCallback = ReceiveFileWriterCallback::create(); 250 RefPtr<LocalErrorCallback> errorCallback = LocalErrorCallback::create(); 251 252 OwnPtr<FileWriterBaseCallbacks> callbacks = FileWriterBaseCallbacks::create(fileWriter, successCallback, errorCallback); 253 m_asyncFileSystem->createWriter(fileWriter.get(), platformPath, callbacks.release()); 254 if (!m_asyncFileSystem->waitForOperationToComplete()) { 255 ec = FileException::ABORT_ERR; 256 return 0; 257 } 258 if (errorCallback->error()) { 259 ASSERT(!successCallback->fileWriterBase()); 260 ec = FileException::ErrorCodeToExceptionCode(errorCallback->error()->code()); 261 return 0; 262 } 263 ASSERT(successCallback->fileWriterBase()); 264 ASSERT(static_cast<FileWriterSync*>(successCallback->fileWriterBase()) == fileWriter.get()); 265 return fileWriter; 266 } 267 268 } 269 270 #endif // ENABLE(FILE_SYSTEM) 271