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 #include "WebFileSystemCallbacksImpl.h" 35 #include "WebFileWriter.h" 36 #include "WorkerAsyncFileWriterChromium.h" 37 #include "WorkerFileSystemCallbacksBridge.h" 38 #include "bindings/v8/WorkerScriptController.h" 39 #include "core/fileapi/BlobURL.h" 40 #include "core/platform/AsyncFileSystemCallbacks.h" 41 #include "core/platform/FileMetadata.h" 42 #include "core/platform/FileSystem.h" 43 #include "core/platform/NotImplemented.h" 44 #include "core/workers/WorkerGlobalScope.h" 45 #include "core/workers/WorkerThread.h" 46 #include "public/platform/WebFileSystem.h" 47 #include "wtf/text/CString.h" 48 49 using namespace WebKit; 50 51 namespace WebCore { 52 53 static const char fileSystemOperationsMode[] = "fileSystemOperationsMode"; 54 55 WorkerAsyncFileSystemChromium::WorkerAsyncFileSystemChromium(ScriptExecutionContext* context, FileSystemSynchronousType synchronousType) 56 : m_scriptExecutionContext(context) 57 , m_workerGlobalScope(toWorkerGlobalScope(context)) 58 , m_synchronousType(synchronousType) 59 { 60 ASSERT(m_scriptExecutionContext->isWorkerGlobalScope()); 61 62 m_workerLoaderProxy = &m_workerGlobalScope->thread()->workerLoaderProxy(); 63 } 64 65 WorkerAsyncFileSystemChromium::~WorkerAsyncFileSystemChromium() 66 { 67 } 68 69 bool WorkerAsyncFileSystemChromium::waitForOperationToComplete() 70 { 71 if (!m_bridgeForCurrentOperation) 72 return false; 73 74 RefPtr<WorkerFileSystemCallbacksBridge> bridge = m_bridgeForCurrentOperation.release(); 75 if (m_workerGlobalScope->thread()->runLoop().runInMode(m_workerGlobalScope, m_modeForCurrentOperation) == MessageQueueTerminated) { 76 bridge->stop(); 77 return false; 78 } 79 return true; 80 } 81 82 void WorkerAsyncFileSystemChromium::move(const KURL& sourcePath, const KURL& destinationPath, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 83 { 84 createWorkerFileSystemCallbacksBridge(callbacks)->postMoveToMainThread(m_webFileSystem, sourcePath, destinationPath, m_modeForCurrentOperation); 85 } 86 87 void WorkerAsyncFileSystemChromium::copy(const KURL& sourcePath, const KURL& destinationPath, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 88 { 89 createWorkerFileSystemCallbacksBridge(callbacks)->postCopyToMainThread(m_webFileSystem, sourcePath, destinationPath, m_modeForCurrentOperation); 90 } 91 92 void WorkerAsyncFileSystemChromium::remove(const KURL& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 93 { 94 createWorkerFileSystemCallbacksBridge(callbacks)->postRemoveToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 95 } 96 97 void WorkerAsyncFileSystemChromium::removeRecursively(const KURL& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 98 { 99 createWorkerFileSystemCallbacksBridge(callbacks)->postRemoveRecursivelyToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 100 } 101 102 void WorkerAsyncFileSystemChromium::readMetadata(const KURL& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 103 { 104 createWorkerFileSystemCallbacksBridge(callbacks)->postReadMetadataToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 105 } 106 107 void WorkerAsyncFileSystemChromium::createFile(const KURL& path, bool exclusive, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 108 { 109 createWorkerFileSystemCallbacksBridge(callbacks)->postCreateFileToMainThread(m_webFileSystem, path, exclusive, m_modeForCurrentOperation); 110 } 111 112 void WorkerAsyncFileSystemChromium::createDirectory(const KURL& path, bool exclusive, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 113 { 114 createWorkerFileSystemCallbacksBridge(callbacks)->postCreateDirectoryToMainThread(m_webFileSystem, path, exclusive, m_modeForCurrentOperation); 115 } 116 117 void WorkerAsyncFileSystemChromium::fileExists(const KURL& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 118 { 119 createWorkerFileSystemCallbacksBridge(callbacks)->postFileExistsToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 120 } 121 122 void WorkerAsyncFileSystemChromium::directoryExists(const KURL& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 123 { 124 createWorkerFileSystemCallbacksBridge(callbacks)->postDirectoryExistsToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 125 } 126 127 void WorkerAsyncFileSystemChromium::readDirectory(const KURL& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 128 { 129 createWorkerFileSystemCallbacksBridge(callbacks)->postReadDirectoryToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 130 } 131 132 class WorkerFileWriterHelperCallbacks : public AsyncFileSystemCallbacks { 133 public: 134 static PassOwnPtr<WorkerFileWriterHelperCallbacks> create(AsyncFileWriterClient* client, const WebURL& path, WebKit::WebFileSystem* webFileSystem, PassOwnPtr<WebCore::AsyncFileSystemCallbacks> callbacks, WorkerGlobalScope* workerGlobalScope) 135 { 136 return adoptPtr(new WorkerFileWriterHelperCallbacks(client, path, webFileSystem, callbacks, workerGlobalScope)); 137 } 138 139 virtual void didReadMetadata(const FileMetadata& metadata) 140 { 141 ASSERT(m_callbacks); 142 if (metadata.type != FileMetadata::TypeFile || metadata.length < 0) 143 m_callbacks->didFail(WebKit::WebFileErrorInvalidState); 144 else { 145 OwnPtr<WorkerAsyncFileWriterChromium> asyncFileWriterChromium = WorkerAsyncFileWriterChromium::create(m_webFileSystem, m_path, m_workerGlobalScope, m_client, WorkerAsyncFileWriterChromium::Asynchronous); 146 m_callbacks->didCreateFileWriter(asyncFileWriterChromium.release(), metadata.length); 147 } 148 } 149 150 virtual void didFail(int code) 151 { 152 ASSERT(m_callbacks); 153 m_callbacks->didFail(code); 154 } 155 156 private: 157 WorkerFileWriterHelperCallbacks(AsyncFileWriterClient* client, const WebURL& path, WebKit::WebFileSystem* webFileSystem, PassOwnPtr<WebCore::AsyncFileSystemCallbacks> callbacks, WorkerGlobalScope* workerGlobalScope) 158 : m_client(client) 159 , m_path(path) 160 , m_webFileSystem(webFileSystem) 161 , m_callbacks(callbacks) 162 , m_workerGlobalScope(workerGlobalScope) 163 { 164 } 165 166 AsyncFileWriterClient* m_client; 167 WebURL m_path; 168 WebKit::WebFileSystem* m_webFileSystem; 169 OwnPtr<WebCore::AsyncFileSystemCallbacks> m_callbacks; 170 WorkerGlobalScope* m_workerGlobalScope; 171 }; 172 173 void WorkerAsyncFileSystemChromium::createWriter(AsyncFileWriterClient* client, const KURL& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 174 { 175 createWorkerFileSystemCallbacksBridge(WorkerFileWriterHelperCallbacks::create(client, path, m_webFileSystem, callbacks, m_workerGlobalScope))->postReadMetadataToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 176 } 177 178 void WorkerAsyncFileSystemChromium::createSnapshotFileAndReadMetadata(const KURL& path, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 179 { 180 createWorkerFileSystemCallbacksBridge(callbacks)->postCreateSnapshotFileToMainThread(m_webFileSystem, path, m_modeForCurrentOperation); 181 } 182 183 PassRefPtr<WorkerFileSystemCallbacksBridge> WorkerAsyncFileSystemChromium::createWorkerFileSystemCallbacksBridge(PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 184 { 185 ASSERT_UNUSED(m_synchronousType, m_synchronousType == AsynchronousFileSystem || !m_bridgeForCurrentOperation); 186 187 m_modeForCurrentOperation = fileSystemOperationsMode; 188 m_modeForCurrentOperation.append(String::number(m_workerGlobalScope->thread()->runLoop().createUniqueId())); 189 190 m_bridgeForCurrentOperation = WorkerFileSystemCallbacksBridge::create(m_workerLoaderProxy, m_scriptExecutionContext, new WebKit::WebFileSystemCallbacksImpl(callbacks)); 191 return m_bridgeForCurrentOperation; 192 } 193 194 } // namespace WebCore 195