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(©OnMainThread, 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