Home | History | Annotate | Download | only in web
      1 /*
      2  * Copyright (C) 2010, 2012 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 "WorkerFileSystemCallbacksBridge.h"
     33 
     34 #include "WebCommonWorkerClient.h"
     35 #include "WebFileSystemCallbacksImpl.h"
     36 #include "WebWorkerBase.h"
     37 #include "bindings/v8/WorkerScriptController.h"
     38 #include "core/dom/CrossThreadTask.h"
     39 #include "core/platform/network/BlobData.h"
     40 #include "core/workers/WorkerGlobalScope.h"
     41 #include "core/workers/WorkerLoaderProxy.h"
     42 #include "core/workers/WorkerThread.h"
     43 #include "public/platform/WebFileInfo.h"
     44 #include "public/platform/WebFileSystemEntry.h"
     45 #include "public/platform/WebString.h"
     46 #include "public/platform/WebURL.h"
     47 #include "weborigin/KURL.h"
     48 #include "wtf/MainThread.h"
     49 #include "wtf/Threading.h"
     50 #include "wtf/UnusedParam.h"
     51 
     52 namespace WebCore {
     53 
     54 template<> struct CrossThreadCopierBase<false, false, WebKit::WebFileInfo> {
     55     typedef WebKit::WebFileInfo Type;
     56     static Type copy(const WebKit::WebFileInfo& info)
     57     {
     58         // Perform per-field copy to make sure we don't do any (unexpected) non-thread safe copy here.
     59         struct WebKit::WebFileInfo newInfo;
     60         newInfo.modificationTime = info.modificationTime;
     61         newInfo.length = info.length;
     62         newInfo.type = info.type;
     63         newInfo.platformPath.assign(info.platformPath);
     64         return newInfo;
     65     }
     66 };
     67 
     68 template<> struct CrossThreadCopierBase<false, false, WebKit::WebVector<WebKit::WebFileSystemEntry> > {
     69     typedef WebKit::WebVector<WebKit::WebFileSystemEntry> Type;
     70     static Type copy(const WebKit::WebVector<WebKit::WebFileSystemEntry>& entries)
     71     {
     72         WebKit::WebVector<WebKit::WebFileSystemEntry> newEntries(entries.size());
     73         for (size_t i = 0; i < entries.size(); ++i) {
     74             String name = entries[i].name;
     75             newEntries[i].isDirectory = entries[i].isDirectory;
     76             newEntries[i].name = name.isolatedCopy();
     77         }
     78         return newEntries;
     79     }
     80 };
     81 
     82 }
     83 
     84 using namespace WebCore;
     85 
     86 namespace WebKit {
     87 
     88 // FileSystemCallbacks that are to be dispatched on the main thread.
     89 class MainThreadFileSystemCallbacks : public WebFileSystemCallbacks {
     90 public:
     91     // Callbacks are self-destructed and we always return leaked pointer here.
     92     static MainThreadFileSystemCallbacks* createLeakedPtr(PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
     93     {
     94         OwnPtr<MainThreadFileSystemCallbacks> callbacks = adoptPtr(new MainThreadFileSystemCallbacks(bridge, mode));
     95         return callbacks.leakPtr();
     96     }
     97 
     98     virtual ~MainThreadFileSystemCallbacks()
     99     {
    100     }
    101 
    102     virtual void didOpenFileSystem(const WebString& name, const WebURL& rootURL)
    103     {
    104         m_bridge->didOpenFileSystemOnMainThread(name, rootURL, m_mode);
    105         delete this;
    106     }
    107 
    108     virtual void didFail(WebFileError error)
    109     {
    110         m_bridge->didFailOnMainThread(error, m_mode);
    111         delete this;
    112     }
    113 
    114     virtual void didSucceed()
    115     {
    116         m_bridge->didSucceedOnMainThread(m_mode);
    117         delete this;
    118     }
    119 
    120     virtual void didReadMetadata(const WebFileInfo& info)
    121     {
    122         m_bridge->didReadMetadataOnMainThread(info, m_mode);
    123         delete this;
    124     }
    125 
    126     virtual void didCreateSnapshotFile(const WebFileInfo& info)
    127     {
    128         // It's important to create a BlobDataHandle that refers to the platform file path prior
    129         // to return from this method so the underlying file will not be deleted.
    130         OwnPtr<BlobData> blobData = BlobData::create();
    131         blobData->appendFile(info.platformPath);
    132         RefPtr<BlobDataHandle> snapshotBlob = BlobDataHandle::create(blobData.release(), info.length);
    133         m_bridge->didCreateSnapshotFileOnMainThread(info, m_mode, snapshotBlob);
    134         delete this;
    135     }
    136 
    137     virtual void didReadDirectory(const WebVector<WebFileSystemEntry>& entries, bool hasMore)
    138     {
    139         m_bridge->didReadDirectoryOnMainThread(entries, hasMore, m_mode);
    140         delete this;
    141     }
    142 
    143     virtual bool shouldBlockUntilCompletion() const
    144     {
    145         return false;
    146     }
    147 
    148 private:
    149     MainThreadFileSystemCallbacks(PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    150         : m_bridge(bridge)
    151         , m_mode(mode)
    152     {
    153         ASSERT(m_bridge);
    154     }
    155 
    156     RefPtr<WorkerFileSystemCallbacksBridge> m_bridge;
    157     const String m_mode;
    158 };
    159 
    160 // Observes the worker context. By keeping this separate, it is easier to verify
    161 // that it only gets deleted on the worker context thread which is verified by ~Observer.
    162 class WorkerFileSystemContextObserver : public WebCore::WorkerGlobalScope::Observer {
    163 public:
    164     static PassOwnPtr<WorkerFileSystemContextObserver> create(WorkerGlobalScope* context, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge)
    165     {
    166         return adoptPtr(new WorkerFileSystemContextObserver(context, bridge));
    167     }
    168 
    169     // WorkerGlobalScope::Observer method.
    170     virtual void notifyStop()
    171     {
    172         m_bridge->stop();
    173     }
    174 
    175 private:
    176     WorkerFileSystemContextObserver(WorkerGlobalScope* context, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge)
    177         : WebCore::WorkerGlobalScope::Observer(context)
    178         , m_bridge(bridge)
    179     {
    180     }
    181 
    182     RefPtr<WorkerFileSystemCallbacksBridge> m_bridge;
    183 };
    184 
    185 void WorkerFileSystemCallbacksBridge::stop()
    186 {
    187     ASSERT(m_workerGlobalScope->isContextThread());
    188     {
    189         MutexLocker locker(m_loaderProxyMutex);
    190         m_workerLoaderProxy = 0;
    191     }
    192 
    193     if (m_callbacksOnWorkerThread)
    194         m_callbacksOnWorkerThread->didFail(WebFileErrorAbort);
    195 
    196     cleanUpAfterCallback();
    197 }
    198 
    199 void WorkerFileSystemCallbacksBridge::cleanUpAfterCallback()
    200 {
    201     ASSERT(m_workerGlobalScope->isContextThread());
    202 
    203     m_callbacksOnWorkerThread = 0;
    204     if (m_workerGlobalScopeObserver) {
    205         WorkerFileSystemContextObserver* observer = m_workerGlobalScopeObserver;
    206         m_workerGlobalScopeObserver = 0;
    207         // The next line may delete this.
    208         delete observer;
    209     }
    210 }
    211 
    212 void WorkerFileSystemCallbacksBridge::postOpenFileSystemToMainThread(WebCommonWorkerClient* commonClient, WebFileSystemType type, long long size, bool create, const String& mode)
    213 {
    214     dispatchTaskToMainThread(
    215         createCallbackTask(&openFileSystemOnMainThread,
    216                            AllowCrossThreadAccess(commonClient), type, size, create,
    217                            this, mode));
    218 }
    219 
    220 void WorkerFileSystemCallbacksBridge::postMoveToMainThread(WebFileSystem* fileSystem, const KURL& sourcePath, const KURL& destinationPath, const String& mode)
    221 {
    222     dispatchTaskToMainThread(
    223         createCallbackTask(&moveOnMainThread,
    224                            AllowCrossThreadAccess(fileSystem), sourcePath, destinationPath,
    225                            this, mode));
    226 }
    227 
    228 void WorkerFileSystemCallbacksBridge::postCopyToMainThread(WebFileSystem* fileSystem, const KURL& sourcePath, const KURL& destinationPath, const String& mode)
    229 {
    230     dispatchTaskToMainThread(
    231         createCallbackTask(&copyOnMainThread,
    232                            AllowCrossThreadAccess(fileSystem), sourcePath, destinationPath,
    233                            this, mode));
    234 }
    235 
    236 void WorkerFileSystemCallbacksBridge::postRemoveToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
    237 {
    238     ASSERT(fileSystem);
    239     dispatchTaskToMainThread(
    240         createCallbackTask(&removeOnMainThread,
    241                            AllowCrossThreadAccess(fileSystem), path,
    242                            this, mode));
    243 }
    244 
    245 void WorkerFileSystemCallbacksBridge::postRemoveRecursivelyToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
    246 {
    247     ASSERT(fileSystem);
    248     dispatchTaskToMainThread(
    249         createCallbackTask(&removeRecursivelyOnMainThread,
    250                            AllowCrossThreadAccess(fileSystem), path,
    251                            this, mode));
    252 }
    253 
    254 void WorkerFileSystemCallbacksBridge::postReadMetadataToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
    255 {
    256     ASSERT(fileSystem);
    257     dispatchTaskToMainThread(
    258         createCallbackTask(&readMetadataOnMainThread,
    259                            AllowCrossThreadAccess(fileSystem), path,
    260                            this, mode));
    261 }
    262 
    263 void WorkerFileSystemCallbacksBridge::postCreateFileToMainThread(WebFileSystem* fileSystem, const KURL& path, bool exclusive, const String& mode)
    264 {
    265     dispatchTaskToMainThread(
    266         createCallbackTask(&createFileOnMainThread,
    267                            AllowCrossThreadAccess(fileSystem), path, exclusive,
    268                            this, mode));
    269 }
    270 
    271 void WorkerFileSystemCallbacksBridge::postCreateDirectoryToMainThread(WebFileSystem* fileSystem, const KURL& path, bool exclusive, const String& mode)
    272 {
    273     ASSERT(fileSystem);
    274     dispatchTaskToMainThread(
    275         createCallbackTask(&createDirectoryOnMainThread,
    276                            AllowCrossThreadAccess(fileSystem), path, exclusive,
    277                            this, mode));
    278 }
    279 
    280 void WorkerFileSystemCallbacksBridge::postFileExistsToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
    281 {
    282     ASSERT(fileSystem);
    283     dispatchTaskToMainThread(
    284         createCallbackTask(&fileExistsOnMainThread,
    285                            AllowCrossThreadAccess(fileSystem), path,
    286                            this, mode));
    287 }
    288 
    289 void WorkerFileSystemCallbacksBridge::postDirectoryExistsToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
    290 {
    291     ASSERT(fileSystem);
    292     dispatchTaskToMainThread(
    293         createCallbackTask(&directoryExistsOnMainThread,
    294                            AllowCrossThreadAccess(fileSystem), path,
    295                            this, mode));
    296 }
    297 
    298 void WorkerFileSystemCallbacksBridge::postReadDirectoryToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
    299 {
    300     ASSERT(fileSystem);
    301     dispatchTaskToMainThread(
    302         createCallbackTask(&readDirectoryOnMainThread,
    303                            AllowCrossThreadAccess(fileSystem), path,
    304                            this, mode));
    305 }
    306 
    307 void WorkerFileSystemCallbacksBridge::postCreateSnapshotFileToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
    308 {
    309     ASSERT(fileSystem);
    310     dispatchTaskToMainThread(
    311         createCallbackTask(&createSnapshotFileOnMainThread,
    312                            AllowCrossThreadAccess(fileSystem),
    313                            path, this, mode));
    314 }
    315 
    316 void WorkerFileSystemCallbacksBridge::openFileSystemOnMainThread(ScriptExecutionContext*, WebCommonWorkerClient* commonClient, WebFileSystemType type, long long size, bool create, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    317 {
    318     if (!commonClient)
    319         bridge->didFailOnMainThread(WebFileErrorAbort, mode);
    320     else {
    321         commonClient->openFileSystem(type, size, create, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    322     }
    323 }
    324 
    325 void WorkerFileSystemCallbacksBridge::moveOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& sourcePath, const KURL& destinationPath, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    326 {
    327     fileSystem->move(sourcePath, destinationPath, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    328 }
    329 
    330 void WorkerFileSystemCallbacksBridge::copyOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& sourcePath, const KURL& destinationPath, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    331 {
    332     fileSystem->copy(sourcePath, destinationPath, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    333 }
    334 
    335 void WorkerFileSystemCallbacksBridge::removeOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    336 {
    337     fileSystem->remove(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    338 }
    339 
    340 void WorkerFileSystemCallbacksBridge::removeRecursivelyOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    341 {
    342     fileSystem->removeRecursively(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    343 }
    344 
    345 void WorkerFileSystemCallbacksBridge::readMetadataOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    346 {
    347     fileSystem->readMetadata(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    348 }
    349 
    350 void WorkerFileSystemCallbacksBridge::createFileOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, bool exclusive, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    351 {
    352     fileSystem->createFile(path, exclusive, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    353 }
    354 
    355 void WorkerFileSystemCallbacksBridge::createDirectoryOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, bool exclusive, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    356 {
    357     fileSystem->createDirectory(path, exclusive, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    358 }
    359 
    360 void WorkerFileSystemCallbacksBridge::fileExistsOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    361 {
    362     fileSystem->fileExists(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    363 }
    364 
    365 void WorkerFileSystemCallbacksBridge::directoryExistsOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    366 {
    367     fileSystem->directoryExists(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    368 }
    369 
    370 void WorkerFileSystemCallbacksBridge::readDirectoryOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    371 {
    372     fileSystem->readDirectory(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    373 }
    374 
    375 void WorkerFileSystemCallbacksBridge::createSnapshotFileOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
    376 {
    377     fileSystem->createSnapshotFileAndReadMetadata(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    378 }
    379 
    380 void WorkerFileSystemCallbacksBridge::didFailOnMainThread(WebFileError error, const String& mode)
    381 {
    382     mayPostTaskToWorker(createCallbackTask(&didFailOnWorkerThread, this, error), mode);
    383 }
    384 
    385 void WorkerFileSystemCallbacksBridge::didOpenFileSystemOnMainThread(const String& name, const KURL& rootURL, const String& mode)
    386 {
    387     mayPostTaskToWorker(createCallbackTask(&didOpenFileSystemOnWorkerThread,
    388                                            this, name, rootURL), mode);
    389 }
    390 
    391 void WorkerFileSystemCallbacksBridge::didSucceedOnMainThread(const String& mode)
    392 {
    393     mayPostTaskToWorker(createCallbackTask(&didSucceedOnWorkerThread, this), mode);
    394 }
    395 
    396 void WorkerFileSystemCallbacksBridge::didReadMetadataOnMainThread(const WebFileInfo& info, const String& mode)
    397 {
    398     mayPostTaskToWorker(createCallbackTask(&didReadMetadataOnWorkerThread, this, info), mode);
    399 }
    400 
    401 void WorkerFileSystemCallbacksBridge::didCreateSnapshotFileOnMainThread(const WebFileInfo& info, const String& mode, PassRefPtr<BlobDataHandle> snapshotBlob)
    402 {
    403     mayPostTaskToWorker(createCallbackTask(&didCreateSnapshotFileOnWorkerThread, this, info, snapshotBlob), mode);
    404 }
    405 
    406 void WorkerFileSystemCallbacksBridge::didReadDirectoryOnMainThread(const WebVector<WebFileSystemEntry>& entries, bool hasMore, const String& mode)
    407 {
    408     mayPostTaskToWorker(
    409         createCallbackTask(&didReadDirectoryOnWorkerThread,
    410                            this, entries, hasMore), mode);
    411 }
    412 
    413 WorkerFileSystemCallbacksBridge::WorkerFileSystemCallbacksBridge(WebCore::WorkerLoaderProxy* workerLoaderProxy, ScriptExecutionContext* scriptExecutionContext, WebFileSystemCallbacksImpl* callbacks)
    414     : m_workerLoaderProxy(workerLoaderProxy)
    415     , m_workerGlobalScope(scriptExecutionContext)
    416     , m_workerGlobalScopeObserver(WorkerFileSystemContextObserver::create(toWorkerGlobalScope(m_workerGlobalScope), this).leakPtr())
    417     , m_callbacksOnWorkerThread(callbacks)
    418 {
    419     ASSERT(m_workerGlobalScope->isContextThread());
    420 }
    421 
    422 WorkerFileSystemCallbacksBridge::~WorkerFileSystemCallbacksBridge()
    423 {
    424     ASSERT(!m_callbacksOnWorkerThread);
    425 }
    426 
    427 void WorkerFileSystemCallbacksBridge::didFailOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, WebFileError error)
    428 {
    429     bridge->m_callbacksOnWorkerThread->didFail(error);
    430 }
    431 
    432 void WorkerFileSystemCallbacksBridge::didOpenFileSystemOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& name, const KURL& rootURL)
    433 {
    434     bridge->m_callbacksOnWorkerThread->didOpenFileSystem(name, rootURL);
    435 }
    436 
    437 void WorkerFileSystemCallbacksBridge::didSucceedOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge)
    438 {
    439     bridge->m_callbacksOnWorkerThread->didSucceed();
    440 }
    441 
    442 void WorkerFileSystemCallbacksBridge::didReadMetadataOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const WebFileInfo& info)
    443 {
    444     bridge->m_callbacksOnWorkerThread->didReadMetadata(info);
    445 }
    446 
    447 void WorkerFileSystemCallbacksBridge::didCreateSnapshotFileOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const WebFileInfo& info, PassRefPtr<BlobDataHandle> snapshotBlob)
    448 {
    449     bridge->m_callbacksOnWorkerThread->didCreateSnapshotFile(info, snapshotBlob);
    450 }
    451 
    452 void WorkerFileSystemCallbacksBridge::didReadDirectoryOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const WebVector<WebFileSystemEntry>& entries, bool hasMore)
    453 {
    454     bridge->m_callbacksOnWorkerThread->didReadDirectory(entries, hasMore);
    455 }
    456 
    457 
    458 void WorkerFileSystemCallbacksBridge::runTaskOnMainThread(WebCore::ScriptExecutionContext* scriptExecutionContext, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun)
    459 {
    460     ASSERT(isMainThread());
    461     taskToRun->performTask(scriptExecutionContext);
    462 }
    463 
    464 void WorkerFileSystemCallbacksBridge::runTaskOnWorkerThread(WebCore::ScriptExecutionContext* scriptExecutionContext, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun)
    465 {
    466     if (!bridge->m_callbacksOnWorkerThread)
    467         return;
    468     ASSERT(bridge->m_workerGlobalScope->isContextThread());
    469     taskToRun->performTask(scriptExecutionContext);
    470 
    471     // taskToRun does the callback.
    472     bridge->cleanUpAfterCallback();
    473 
    474     // WorkerFileSystemCallbacksBridge may be deleted here when bridge goes out of scope.
    475 }
    476 
    477 void WorkerFileSystemCallbacksBridge::dispatchTaskToMainThread(PassOwnPtr<WebCore::ScriptExecutionContext::Task> task)
    478 {
    479     ASSERT(m_workerLoaderProxy);
    480     ASSERT(m_workerGlobalScope->isContextThread());
    481     WebWorkerBase::dispatchTaskToMainThread(createCallbackTask(&runTaskOnMainThread, RefPtr<WorkerFileSystemCallbacksBridge>(this).release(), task));
    482 }
    483 
    484 void WorkerFileSystemCallbacksBridge::mayPostTaskToWorker(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode)
    485 {
    486     // Relies on its caller (MainThreadFileSystemCallbacks:did*) to keep WorkerFileSystemCallbacksBridge alive.
    487     ASSERT(isMainThread());
    488 
    489     MutexLocker locker(m_loaderProxyMutex);
    490     if (m_workerLoaderProxy)
    491         m_workerLoaderProxy->postTaskForModeToWorkerGlobalScope(createCallbackTask(&runTaskOnWorkerThread, this, task), mode);
    492 }
    493 
    494 } // namespace WebCore
    495