Home | History | Annotate | Download | only in filesystem
      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 
     49 namespace blink {
     50 
     51 namespace {
     52 
     53 void reportFailure(ExecutionContext*, PassOwnPtr<AsyncFileSystemCallbacks> callbacks, FileError::ErrorCode error)
     54 {
     55     callbacks->didFail(error);
     56 }
     57 
     58 } // namespace
     59 
     60 class CallbackWrapper FINAL : public GarbageCollectedFinalized<CallbackWrapper> {
     61 public:
     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 
     74 private:
     75     OwnPtr<AsyncFileSystemCallbacks> m_callbacks;
     76 };
     77 
     78 PassOwnPtrWillBeRawPtr<LocalFileSystem> LocalFileSystem::create(PassOwnPtr<FileSystemClient> client)
     79 {
     80     return adoptPtrWillBeNoop(new LocalFileSystem(client));
     81 }
     82 
     83 LocalFileSystem::~LocalFileSystem()
     84 {
     85 }
     86 
     87 void 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 
     96 void 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 
    105 void 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 
    117 WebFileSystem* LocalFileSystem::fileSystem() const
    118 {
    119     Platform* platform = Platform::current();
    120     if (!platform)
    121         return nullptr;
    122     return Platform::current()->fileSystem();
    123 }
    124 
    125 void 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 
    142 void LocalFileSystem::fileSystemNotAvailable(
    143     PassRefPtrWillBeRawPtr<ExecutionContext> context,
    144     CallbackWrapper* callbacks)
    145 {
    146     context->postTask(createCrossThreadTask(&reportFailure, callbacks->release(), FileError::ABORT_ERR));
    147 }
    148 
    149 void LocalFileSystem::fileSystemNotAllowedInternal(
    150     PassRefPtrWillBeRawPtr<ExecutionContext> context,
    151     CallbackWrapper* callbacks)
    152 {
    153     context->postTask(createCrossThreadTask(&reportFailure, callbacks->release(), FileError::ABORT_ERR));
    154 }
    155 
    156 void 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 
    170 void 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 
    182 void 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 
    195 LocalFileSystem::LocalFileSystem(PassOwnPtr<FileSystemClient> client)
    196     : m_client(client)
    197 {
    198 }
    199 
    200 const char* LocalFileSystem::supplementName()
    201 {
    202     return "LocalFileSystem";
    203 }
    204 
    205 LocalFileSystem* 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 
    214 void provideLocalFileSystemTo(LocalFrame& frame, PassOwnPtr<FileSystemClient> client)
    215 {
    216     frame.provideSupplement(LocalFileSystem::supplementName(), LocalFileSystem::create(client));
    217 }
    218 
    219 void provideLocalFileSystemToWorker(WorkerClients* clients, PassOwnPtr<FileSystemClient> client)
    220 {
    221     clients->provideSupplement(LocalFileSystem::supplementName(), LocalFileSystem::create(client));
    222 }
    223 
    224 } // namespace blink
    225