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 WebCore {
     50 
     51 namespace {
     52 
     53 void fileSystemNotAllowed(ExecutionContext*, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
     54 {
     55     callbacks->didFail(FileError::ABORT_ERR);
     56 }
     57 
     58 } // namespace
     59 
     60 class CallbackWrapper : public RefCounted<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 private:
     73     OwnPtr<AsyncFileSystemCallbacks> m_callbacks;
     74 };
     75 
     76 PassOwnPtrWillBeRawPtr<LocalFileSystem> LocalFileSystem::create(PassOwnPtr<FileSystemClient> client)
     77 {
     78     return adoptPtrWillBeNoop(new LocalFileSystem(client));
     79 }
     80 
     81 LocalFileSystem::~LocalFileSystem()
     82 {
     83 }
     84 
     85 void LocalFileSystem::resolveURL(ExecutionContext* context, const KURL& fileSystemURL, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
     86 {
     87     RefPtr<CallbackWrapper> wrapper = adoptRef(new CallbackWrapper(callbacks));
     88     requestFileSystemAccessInternal(context,
     89         bind(&LocalFileSystem::resolveURLInternal, this, fileSystemURL, wrapper),
     90         bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, PassRefPtrWillBeRawPtr<ExecutionContext>(context), wrapper));
     91 }
     92 
     93 void LocalFileSystem::requestFileSystem(ExecutionContext* context, FileSystemType type, long long size, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
     94 {
     95     RefPtrWillBeRawPtr<ExecutionContext> contextPtr(context);
     96     RefPtr<CallbackWrapper> wrapper = adoptRef(new CallbackWrapper(callbacks));
     97     requestFileSystemAccessInternal(context,
     98         bind(&LocalFileSystem::fileSystemAllowedInternal, this, contextPtr, type, wrapper),
     99         bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, contextPtr, wrapper));
    100 }
    101 
    102 void LocalFileSystem::deleteFileSystem(ExecutionContext* context, FileSystemType type, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
    103 {
    104     RefPtrWillBeRawPtr<ExecutionContext> contextPtr(context);
    105     ASSERT(context);
    106     ASSERT_WITH_SECURITY_IMPLICATION(context->isDocument());
    107 
    108     RefPtr<CallbackWrapper> wrapper = adoptRef(new CallbackWrapper(callbacks));
    109     requestFileSystemAccessInternal(context,
    110         bind(&LocalFileSystem::deleteFileSystemInternal, this, contextPtr, type, wrapper),
    111         bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, contextPtr, wrapper));
    112 }
    113 
    114 void LocalFileSystem::requestFileSystemAccessInternal(ExecutionContext* context, const Closure& allowed, const Closure& denied)
    115 {
    116     if (!client()) {
    117         denied();
    118         return;
    119     }
    120     if (!context->isDocument()) {
    121         if (!client()->requestFileSystemAccessSync(context)) {
    122             denied();
    123             return;
    124         }
    125         allowed();
    126         return;
    127     }
    128     client()->requestFileSystemAccessAsync(context, PermissionCallbacks::create(allowed, denied));
    129 }
    130 
    131 void LocalFileSystem::fileSystemNotAllowedInternal(
    132     PassRefPtrWillBeRawPtr<ExecutionContext> context,
    133     PassRefPtr<CallbackWrapper> callbacks)
    134 {
    135     context->postTask(createCallbackTask(&fileSystemNotAllowed, callbacks->release()));
    136 }
    137 
    138 void LocalFileSystem::fileSystemAllowedInternal(
    139     PassRefPtrWillBeRawPtr<ExecutionContext> context,
    140     FileSystemType type,
    141     PassRefPtr<CallbackWrapper> callbacks)
    142 {
    143     KURL storagePartition = KURL(KURL(), context->securityOrigin()->toString());
    144     blink::Platform::current()->fileSystem()->openFileSystem(storagePartition, static_cast<blink::WebFileSystemType>(type), callbacks->release());
    145 }
    146 
    147 void LocalFileSystem::resolveURLInternal(
    148     const KURL& fileSystemURL,
    149     PassRefPtr<CallbackWrapper> callbacks)
    150 {
    151     blink::Platform::current()->fileSystem()->resolveURL(fileSystemURL, callbacks->release());
    152 }
    153 
    154 void LocalFileSystem::deleteFileSystemInternal(
    155     PassRefPtrWillBeRawPtr<ExecutionContext> context,
    156     FileSystemType type,
    157     PassRefPtr<CallbackWrapper> callbacks)
    158 {
    159     KURL storagePartition = KURL(KURL(), context->securityOrigin()->toString());
    160     blink::Platform::current()->fileSystem()->deleteFileSystem(storagePartition, static_cast<blink::WebFileSystemType>(type), callbacks->release());
    161 }
    162 
    163 LocalFileSystem::LocalFileSystem(PassOwnPtr<FileSystemClient> client)
    164     : m_client(client)
    165 {
    166 }
    167 
    168 const char* LocalFileSystem::supplementName()
    169 {
    170     return "LocalFileSystem";
    171 }
    172 
    173 LocalFileSystem* LocalFileSystem::from(ExecutionContext& context)
    174 {
    175     if (context.isDocument()) {
    176         return static_cast<LocalFileSystem*>(WillBeHeapSupplement<LocalFrame>::from(toDocument(context).frame(), supplementName()));
    177     }
    178     ASSERT(context.isWorkerGlobalScope());
    179     return static_cast<LocalFileSystem*>(WillBeHeapSupplement<WorkerClients>::from(toWorkerGlobalScope(context).clients(), supplementName()));
    180 }
    181 
    182 void provideLocalFileSystemTo(LocalFrame& frame, PassOwnPtr<FileSystemClient> client)
    183 {
    184     frame.provideSupplement(LocalFileSystem::supplementName(), LocalFileSystem::create(client));
    185 }
    186 
    187 void provideLocalFileSystemToWorker(WorkerClients* clients, PassOwnPtr<FileSystemClient> client)
    188 {
    189     clients->provideSupplement(LocalFileSystem::supplementName(), LocalFileSystem::create(client));
    190 }
    191 
    192 } // namespace WebCore
    193