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 "WorkerAsyncFileSystemChromium.h" 33 34 #if ENABLE(FILE_SYSTEM) 35 36 #include "AsyncFileSystemCallbacks.h" 37 #include "FileMetadata.h" 38 #include "FileSystem.h" 39 #include "NotImplemented.h" 40 #include "WebFileSystem.h" 41 #include "WebFileSystemCallbacksImpl.h" 42 #include "WebFileWriter.h" 43 #include "WebKit.h" 44 #include "WebKitClient.h" 45 #include "WebWorkerBase.h" 46 #include "WorkerAsyncFileWriterChromium.h" 47 #include "WorkerContext.h" 48 #include "WorkerFileSystemCallbacksBridge.h" 49 #include "WorkerScriptController.h" 50 #include "WorkerThread.h" 51 #include <wtf/text/CString.h> 52 53 using namespace WebKit; 54 55 namespace WebCore { 56 57 static const char fileSystemOperationsMode[] = "fileSystemOperationsMode"; 58 59 WorkerAsyncFileSystemChromium::WorkerAsyncFileSystemChromium(ScriptExecutionContext* context, AsyncFileSystem::Type type, const String& rootPath, bool synchronous) 60 : AsyncFileSystem(type, rootPath) 61 , m_scriptExecutionContext(context) 62 , m_webFileSystem(WebKit::webKitClient()->fileSystem()) 63 , m_workerContext(static_cast<WorkerContext*>(context)) 64 , m_synchronous(synchronous) 65 { 66 ASSERT(m_webFileSystem); 67 ASSERT(m_scriptExecutionContext->isWorkerContext()); 68 69 WorkerLoaderProxy* workerLoaderProxy = &m_workerContext->thread()->workerLoaderProxy(); 70 m_worker = static_cast<WebWorkerBase*>(workerLoaderProxy); 71 } 72 73 WorkerAsyncFileSystemChromium::~WorkerAsyncFileSystemChromium() 74 { 75 } 76 77 bool WorkerAsyncFileSystemChromium::waitForOperationToComplete() 78 { 79 if (!m_bridgeForCurrentOperation.get()) 80 return false; 81 82 RefPtr<WorkerFileSystemCallbacksBridge> bridge = m_bridgeForCurrentOperation.release(); 83 if (m_workerContext->thread()->runLoop().runInMode(m_workerContext, m_modeForCurrentOperation) == MessageQueueTerminated) { 84 bridge->stop(); 85 return false; 86 } 87 return true; 88 } 89 90 void WorkerAsyncFileSystemChromium::move(const String& sourcePath, const String& destinationPath, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 91 { 92 createWorkerFileSystemCallbacksBridge(callbacks)->postMoveToMainThread(m_webFileSystem, sourcePath, destinationPath, m_modeForCurrentOperation); 93 } 94 95 void WorkerAsyncFileSystemChromium::copy(const String& sourcePath, const String& destinationPath, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 96 { 97 createWorkerFileSystemCallbacksBridge(callbacks)->postCopyToMainThread(m_webFileSystem, sourcePath, destinationPath, m_modeForCurrentOperation); 98 } 99 100 void WorkerAsyncFileSystemChromium::remove(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 101 { 102 createWorkerFileSystemCallbacksBridge(callbacks)->postRemoveToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 103 } 104 105 void WorkerAsyncFileSystemChromium::removeRecursively(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 106 { 107 createWorkerFileSystemCallbacksBridge(callbacks)->postRemoveRecursivelyToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 108 } 109 110 void WorkerAsyncFileSystemChromium::readMetadata(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 111 { 112 createWorkerFileSystemCallbacksBridge(callbacks)->postReadMetadataToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 113 } 114 115 void WorkerAsyncFileSystemChromium::createFile(const String& path, bool exclusive, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 116 { 117 createWorkerFileSystemCallbacksBridge(callbacks)->postCreateFileToMainThread(m_webFileSystem, path, exclusive, m_modeForCurrentOperation); 118 } 119 120 void WorkerAsyncFileSystemChromium::createDirectory(const String& path, bool exclusive, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 121 { 122 createWorkerFileSystemCallbacksBridge(callbacks)->postCreateDirectoryToMainThread(m_webFileSystem, path, exclusive, m_modeForCurrentOperation); 123 } 124 125 void WorkerAsyncFileSystemChromium::fileExists(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 126 { 127 createWorkerFileSystemCallbacksBridge(callbacks)->postFileExistsToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 128 } 129 130 void WorkerAsyncFileSystemChromium::directoryExists(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 131 { 132 createWorkerFileSystemCallbacksBridge(callbacks)->postDirectoryExistsToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 133 } 134 135 void WorkerAsyncFileSystemChromium::readDirectory(const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 136 { 137 createWorkerFileSystemCallbacksBridge(callbacks)->postReadDirectoryToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 138 } 139 140 class WorkerFileWriterHelperCallbacks : public AsyncFileSystemCallbacks { 141 public: 142 static PassOwnPtr<WorkerFileWriterHelperCallbacks> create(AsyncFileWriterClient* client, const String& path, WebKit::WebFileSystem* webFileSystem, PassOwnPtr<WebCore::AsyncFileSystemCallbacks> callbacks, WorkerContext* workerContext) 143 { 144 return adoptPtr(new WorkerFileWriterHelperCallbacks(client, path, webFileSystem, callbacks, workerContext)); 145 } 146 147 virtual void didSucceed() 148 { 149 ASSERT_NOT_REACHED(); 150 } 151 152 virtual void didReadMetadata(const FileMetadata& metadata) 153 { 154 ASSERT(m_callbacks); 155 if (metadata.type != FileMetadata::TypeFile || metadata.length < 0) 156 m_callbacks->didFail(WebKit::WebFileErrorInvalidState); 157 else { 158 OwnPtr<WorkerAsyncFileWriterChromium> asyncFileWriterChromium = WorkerAsyncFileWriterChromium::create(m_webFileSystem, m_path, m_workerContext, m_client, WorkerAsyncFileWriterChromium::Asynchronous); 159 m_callbacks->didCreateFileWriter(asyncFileWriterChromium.release(), metadata.length); 160 } 161 } 162 163 virtual void didReadDirectoryEntry(const String& name, bool isDirectory) 164 { 165 ASSERT_NOT_REACHED(); 166 } 167 168 virtual void didReadDirectoryEntries(bool hasMore) 169 { 170 ASSERT_NOT_REACHED(); 171 } 172 173 virtual void didOpenFileSystem(const String&, PassOwnPtr<AsyncFileSystem>) 174 { 175 ASSERT_NOT_REACHED(); 176 } 177 178 // Called when an AsyncFileWrter has been created successfully. 179 virtual void didCreateFileWriter(PassOwnPtr<AsyncFileWriter>, long long) 180 { 181 ASSERT_NOT_REACHED(); 182 } 183 184 virtual void didFail(int code) 185 { 186 ASSERT(m_callbacks); 187 m_callbacks->didFail(code); 188 } 189 190 private: 191 WorkerFileWriterHelperCallbacks(AsyncFileWriterClient* client, const String& path, WebKit::WebFileSystem* webFileSystem, PassOwnPtr<WebCore::AsyncFileSystemCallbacks> callbacks, WorkerContext* workerContext) 192 : m_client(client) 193 , m_path(path) 194 , m_webFileSystem(webFileSystem) 195 , m_callbacks(callbacks) 196 , m_workerContext(workerContext) 197 { 198 } 199 200 AsyncFileWriterClient* m_client; 201 String m_path; 202 WebKit::WebFileSystem* m_webFileSystem; 203 OwnPtr<WebCore::AsyncFileSystemCallbacks> m_callbacks; 204 WorkerContext* m_workerContext; 205 }; 206 207 void WorkerAsyncFileSystemChromium::createWriter(AsyncFileWriterClient* client, const String& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 208 { 209 createWorkerFileSystemCallbacksBridge(WorkerFileWriterHelperCallbacks::create(client, path, m_webFileSystem, callbacks, m_workerContext))->postReadMetadataToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 210 } 211 212 PassRefPtr<WorkerFileSystemCallbacksBridge> WorkerAsyncFileSystemChromium::createWorkerFileSystemCallbacksBridge(PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 213 { 214 ASSERT(!m_synchronous || !m_bridgeForCurrentOperation.get()); 215 216 m_modeForCurrentOperation = fileSystemOperationsMode; 217 m_modeForCurrentOperation.append(String::number(m_workerContext->thread()->runLoop().createUniqueId())); 218 219 m_bridgeForCurrentOperation = WorkerFileSystemCallbacksBridge::create(m_worker, m_scriptExecutionContext, new WebKit::WebFileSystemCallbacksImpl(callbacks)); 220 return m_bridgeForCurrentOperation; 221 } 222 223 } // namespace WebCore 224 225 #endif // ENABLE(FILE_SYSTEM) 226