1/* 2 * Copyright (C) 2013 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/LocalFileSystem.h" 33 34#include "core/dom/CrossThreadTask.h" 35#include "core/dom/Document.h" 36#include "core/dom/ExceptionCode.h" 37#include "core/dom/ExecutionContext.h" 38#include "core/fileapi/FileError.h" 39#include "core/frame/LocalFrame.h" 40#include "core/workers/WorkerGlobalScope.h" 41#include "modules/filesystem/FileSystemClient.h" 42#include "platform/AsyncFileSystemCallbacks.h" 43#include "platform/PermissionCallbacks.h" 44#include "public/platform/Platform.h" 45#include "public/platform/WebFileSystem.h" 46#include "wtf/Functional.h" 47#include "wtf/RefCounted.h" 48 49namespace blink { 50 51namespace { 52 53void reportFailure(ExecutionContext*, PassOwnPtr<AsyncFileSystemCallbacks> callbacks, FileError::ErrorCode error) 54{ 55 callbacks->didFail(error); 56} 57 58} // namespace 59 60class CallbackWrapper FINAL : public GarbageCollectedFinalized<CallbackWrapper> { 61public: 62 CallbackWrapper(PassOwnPtr<AsyncFileSystemCallbacks> c) 63 : m_callbacks(c) 64 { 65 } 66 virtual ~CallbackWrapper() { } 67 PassOwnPtr<AsyncFileSystemCallbacks> release() 68 { 69 return m_callbacks.release(); 70 } 71 72 void trace(Visitor*) { } 73 74private: 75 OwnPtr<AsyncFileSystemCallbacks> m_callbacks; 76}; 77 78PassOwnPtrWillBeRawPtr<LocalFileSystem> LocalFileSystem::create(PassOwnPtr<FileSystemClient> client) 79{ 80 return adoptPtrWillBeNoop(new LocalFileSystem(client)); 81} 82 83LocalFileSystem::~LocalFileSystem() 84{ 85} 86 87void LocalFileSystem::resolveURL(ExecutionContext* context, const KURL& fileSystemURL, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 88{ 89 RefPtrWillBeRawPtr<ExecutionContext> contextPtr(context); 90 CallbackWrapper* wrapper = new CallbackWrapper(callbacks); 91 requestFileSystemAccessInternal(context, 92 bind(&LocalFileSystem::resolveURLInternal, this, contextPtr, fileSystemURL, wrapper), 93 bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, contextPtr, wrapper)); 94} 95 96void LocalFileSystem::requestFileSystem(ExecutionContext* context, FileSystemType type, long long size, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 97{ 98 RefPtrWillBeRawPtr<ExecutionContext> contextPtr(context); 99 CallbackWrapper* wrapper = new CallbackWrapper(callbacks); 100 requestFileSystemAccessInternal(context, 101 bind(&LocalFileSystem::fileSystemAllowedInternal, this, contextPtr, type, wrapper), 102 bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, contextPtr, wrapper)); 103} 104 105void LocalFileSystem::deleteFileSystem(ExecutionContext* context, FileSystemType type, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) 106{ 107 RefPtrWillBeRawPtr<ExecutionContext> contextPtr(context); 108 ASSERT(context); 109 ASSERT_WITH_SECURITY_IMPLICATION(context->isDocument()); 110 111 CallbackWrapper* wrapper = new CallbackWrapper(callbacks); 112 requestFileSystemAccessInternal(context, 113 bind(&LocalFileSystem::deleteFileSystemInternal, this, contextPtr, type, wrapper), 114 bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, contextPtr, wrapper)); 115} 116 117WebFileSystem* LocalFileSystem::fileSystem() const 118{ 119 Platform* platform = Platform::current(); 120 if (!platform) 121 return nullptr; 122 return Platform::current()->fileSystem(); 123} 124 125void LocalFileSystem::requestFileSystemAccessInternal(ExecutionContext* context, const Closure& allowed, const Closure& denied) 126{ 127 if (!client()) { 128 denied(); 129 return; 130 } 131 if (!context->isDocument()) { 132 if (!client()->requestFileSystemAccessSync(context)) { 133 denied(); 134 return; 135 } 136 allowed(); 137 return; 138 } 139 client()->requestFileSystemAccessAsync(context, PermissionCallbacks::create(allowed, denied)); 140} 141 142void LocalFileSystem::fileSystemNotAvailable( 143 PassRefPtrWillBeRawPtr<ExecutionContext> context, 144 CallbackWrapper* callbacks) 145{ 146 context->postTask(createCrossThreadTask(&reportFailure, callbacks->release(), FileError::ABORT_ERR)); 147} 148 149void LocalFileSystem::fileSystemNotAllowedInternal( 150 PassRefPtrWillBeRawPtr<ExecutionContext> context, 151 CallbackWrapper* callbacks) 152{ 153 context->postTask(createCrossThreadTask(&reportFailure, callbacks->release(), FileError::ABORT_ERR)); 154} 155 156void LocalFileSystem::fileSystemAllowedInternal( 157 PassRefPtrWillBeRawPtr<ExecutionContext> context, 158 FileSystemType type, 159 CallbackWrapper* callbacks) 160{ 161 if (!fileSystem()) { 162 fileSystemNotAvailable(context, callbacks); 163 return; 164 } 165 166 KURL storagePartition = KURL(KURL(), context->securityOrigin()->toString()); 167 fileSystem()->openFileSystem(storagePartition, static_cast<WebFileSystemType>(type), callbacks->release()); 168} 169 170void LocalFileSystem::resolveURLInternal( 171 PassRefPtrWillBeRawPtr<ExecutionContext> context, 172 const KURL& fileSystemURL, 173 CallbackWrapper* callbacks) 174{ 175 if (!fileSystem()) { 176 fileSystemNotAvailable(context, callbacks); 177 return; 178 } 179 fileSystem()->resolveURL(fileSystemURL, callbacks->release()); 180} 181 182void LocalFileSystem::deleteFileSystemInternal( 183 PassRefPtrWillBeRawPtr<ExecutionContext> context, 184 FileSystemType type, 185 CallbackWrapper* callbacks) 186{ 187 if (!fileSystem()) { 188 fileSystemNotAvailable(context, callbacks); 189 return; 190 } 191 KURL storagePartition = KURL(KURL(), context->securityOrigin()->toString()); 192 fileSystem()->deleteFileSystem(storagePartition, static_cast<WebFileSystemType>(type), callbacks->release()); 193} 194 195LocalFileSystem::LocalFileSystem(PassOwnPtr<FileSystemClient> client) 196 : m_client(client) 197{ 198} 199 200const char* LocalFileSystem::supplementName() 201{ 202 return "LocalFileSystem"; 203} 204 205LocalFileSystem* LocalFileSystem::from(ExecutionContext& context) 206{ 207 if (context.isDocument()) { 208 return static_cast<LocalFileSystem*>(WillBeHeapSupplement<LocalFrame>::from(toDocument(context).frame(), supplementName())); 209 } 210 ASSERT(context.isWorkerGlobalScope()); 211 return static_cast<LocalFileSystem*>(WillBeHeapSupplement<WorkerClients>::from(toWorkerGlobalScope(context).clients(), supplementName())); 212} 213 214void provideLocalFileSystemTo(LocalFrame& frame, PassOwnPtr<FileSystemClient> client) 215{ 216 frame.provideSupplement(LocalFileSystem::supplementName(), LocalFileSystem::create(client)); 217} 218 219void provideLocalFileSystemToWorker(WorkerClients* clients, PassOwnPtr<FileSystemClient> client) 220{ 221 clients->provideSupplement(LocalFileSystem::supplementName(), LocalFileSystem::create(client)); 222} 223 224} // namespace blink 225