• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 #if ENABLE(FILE_SYSTEM)
35 
36 #include "CrossThreadTask.h"
37 #include "WebCommonWorkerClient.h"
38 #include "WebFileInfo.h"
39 #include "WebFileSystemCallbacks.h"
40 #include "WebFileSystemEntry.h"
41 #include "WebString.h"
42 #include "WebWorkerBase.h"
43 #include "WorkerContext.h"
44 #include "WorkerScriptController.h"
45 #include "WorkerThread.h"
46 #include <wtf/MainThread.h>
47 #include <wtf/Threading.h>
48 #include <wtf/UnusedParam.h>
49 
50 namespace WebCore {
51 
52 template<> struct CrossThreadCopierBase<false, false, WebKit::WebFileInfo> {
53     typedef WebKit::WebFileInfo Type;
copyWebCore::CrossThreadCopierBase54     static Type copy(const WebKit::WebFileInfo& info)
55     {
56         // Perform per-field copy to make sure we don't do any (unexpected) non-thread safe copy here.
57         struct WebKit::WebFileInfo newInfo;
58         newInfo.modificationTime = info.modificationTime;
59         newInfo.length = info.length;
60         newInfo.type = info.type;
61         newInfo.platformPath.assign(info.platformPath.data(), info.platformPath.length());
62         return newInfo;
63     }
64 };
65 
66 template<> struct CrossThreadCopierBase<false, false, WebKit::WebVector<WebKit::WebFileSystemEntry> > {
67     typedef WebKit::WebVector<WebKit::WebFileSystemEntry> Type;
copyWebCore::CrossThreadCopierBase68     static Type copy(const WebKit::WebVector<WebKit::WebFileSystemEntry>& entries)
69     {
70         WebKit::WebVector<WebKit::WebFileSystemEntry> newEntries(entries.size());
71         for (size_t i = 0; i < entries.size(); ++i) {
72             String name = entries[i].name;
73             newEntries[i].isDirectory = entries[i].isDirectory;
74             newEntries[i].name = name.crossThreadString();
75         }
76         return newEntries;
77     }
78 };
79 
80 }
81 
82 using namespace WebCore;
83 
84 namespace WebKit {
85 
86 // FileSystemCallbacks that are to be dispatched on the main thread.
87 class MainThreadFileSystemCallbacks : public WebFileSystemCallbacks {
88 public:
89     // Callbacks are self-destructed and we always return leaked pointer here.
createLeakedPtr(WorkerFileSystemCallbacksBridge * bridge,const String & mode)90     static MainThreadFileSystemCallbacks* createLeakedPtr(WorkerFileSystemCallbacksBridge* bridge, const String& mode)
91     {
92         OwnPtr<MainThreadFileSystemCallbacks> callbacks = adoptPtr(new MainThreadFileSystemCallbacks(bridge, mode));
93         return callbacks.leakPtr();
94     }
95 
~MainThreadFileSystemCallbacks()96     virtual ~MainThreadFileSystemCallbacks()
97     {
98     }
99 
didOpenFileSystem(const WebString & name,const WebString & path)100     virtual void didOpenFileSystem(const WebString& name, const WebString& path)
101     {
102         m_bridge->didOpenFileSystemOnMainThread(name, path, m_mode);
103         delete this;
104     }
105 
didFail(WebFileError error)106     virtual void didFail(WebFileError error)
107     {
108         m_bridge->didFailOnMainThread(error, m_mode);
109         delete this;
110     }
111 
didSucceed()112     virtual void didSucceed()
113     {
114         m_bridge->didSucceedOnMainThread(m_mode);
115         delete this;
116     }
117 
didReadMetadata(const WebFileInfo & info)118     virtual void didReadMetadata(const WebFileInfo& info)
119     {
120         m_bridge->didReadMetadataOnMainThread(info, m_mode);
121         delete this;
122     }
123 
didReadDirectory(const WebVector<WebFileSystemEntry> & entries,bool hasMore)124     virtual void didReadDirectory(const WebVector<WebFileSystemEntry>& entries, bool hasMore)
125     {
126         m_bridge->didReadDirectoryOnMainThread(entries, hasMore, m_mode);
127         delete this;
128     }
129 
130 private:
MainThreadFileSystemCallbacks(WorkerFileSystemCallbacksBridge * bridge,const String & mode)131     MainThreadFileSystemCallbacks(WorkerFileSystemCallbacksBridge* bridge, const String& mode)
132         : m_bridge(bridge)
133         , m_mode(mode)
134     {
135         ASSERT(m_bridge);
136     }
137 
138     friend class WorkerFileSystemCallbacksBridge;
139     // The bridge pointer is kept by the bridge itself on the WorkerThread.
140     WorkerFileSystemCallbacksBridge* m_bridge;
141     const String m_mode;
142 };
143 
stop()144 void WorkerFileSystemCallbacksBridge::stop()
145 {
146     ASSERT(m_workerContext->isContextThread());
147     MutexLocker locker(m_mutex);
148     m_worker = 0;
149 
150     if (m_callbacksOnWorkerThread) {
151         m_callbacksOnWorkerThread->didFail(WebFileErrorAbort);
152         m_callbacksOnWorkerThread = 0;
153     }
154 }
155 
postOpenFileSystemToMainThread(WebCommonWorkerClient * commonClient,WebFileSystem::Type type,long long size,bool create,const String & mode)156 void WorkerFileSystemCallbacksBridge::postOpenFileSystemToMainThread(WebCommonWorkerClient* commonClient, WebFileSystem::Type type, long long size, bool create, const String& mode)
157 {
158     dispatchTaskToMainThread(createCallbackTask(&openFileSystemOnMainThread, commonClient, type, size, create, this, mode));
159 }
160 
postMoveToMainThread(WebFileSystem * fileSystem,const String & sourcePath,const String & destinationPath,const String & mode)161 void WorkerFileSystemCallbacksBridge::postMoveToMainThread(WebFileSystem* fileSystem, const String& sourcePath, const String& destinationPath, const String& mode)
162 {
163     dispatchTaskToMainThread(createCallbackTask(&moveOnMainThread, fileSystem, sourcePath, destinationPath, this, mode));
164 }
165 
postCopyToMainThread(WebFileSystem * fileSystem,const String & sourcePath,const String & destinationPath,const String & mode)166 void WorkerFileSystemCallbacksBridge::postCopyToMainThread(WebFileSystem* fileSystem, const String& sourcePath, const String& destinationPath, const String& mode)
167 {
168     dispatchTaskToMainThread(createCallbackTask(&copyOnMainThread, fileSystem, sourcePath, destinationPath, this, mode));
169 }
170 
postRemoveToMainThread(WebFileSystem * fileSystem,const String & path,const String & mode)171 void WorkerFileSystemCallbacksBridge::postRemoveToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode)
172 {
173     ASSERT(fileSystem);
174     dispatchTaskToMainThread(createCallbackTask(&removeOnMainThread, fileSystem, path, this, mode));
175 }
176 
postRemoveRecursivelyToMainThread(WebFileSystem * fileSystem,const String & path,const String & mode)177 void WorkerFileSystemCallbacksBridge::postRemoveRecursivelyToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode)
178 {
179     ASSERT(fileSystem);
180     dispatchTaskToMainThread(createCallbackTask(&removeRecursivelyOnMainThread, fileSystem, path, this, mode));
181 }
182 
postReadMetadataToMainThread(WebFileSystem * fileSystem,const String & path,const String & mode)183 void WorkerFileSystemCallbacksBridge::postReadMetadataToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode)
184 {
185     ASSERT(fileSystem);
186     dispatchTaskToMainThread(createCallbackTask(&readMetadataOnMainThread, fileSystem, path, this, mode));
187 }
188 
postCreateFileToMainThread(WebFileSystem * fileSystem,const String & path,bool exclusive,const String & mode)189 void WorkerFileSystemCallbacksBridge::postCreateFileToMainThread(WebFileSystem* fileSystem, const String& path, bool exclusive, const String& mode)
190 {
191     dispatchTaskToMainThread(createCallbackTask(&createFileOnMainThread, fileSystem, path, exclusive, this, mode));
192 }
193 
postCreateDirectoryToMainThread(WebFileSystem * fileSystem,const String & path,bool exclusive,const String & mode)194 void WorkerFileSystemCallbacksBridge::postCreateDirectoryToMainThread(WebFileSystem* fileSystem, const String& path, bool exclusive, const String& mode)
195 {
196     ASSERT(fileSystem);
197     dispatchTaskToMainThread(createCallbackTask(&createDirectoryOnMainThread, fileSystem, path, exclusive, this, mode));
198 }
199 
postFileExistsToMainThread(WebFileSystem * fileSystem,const String & path,const String & mode)200 void WorkerFileSystemCallbacksBridge::postFileExistsToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode)
201 {
202     ASSERT(fileSystem);
203     dispatchTaskToMainThread(createCallbackTask(&fileExistsOnMainThread, fileSystem, path, this, mode));
204 }
205 
postDirectoryExistsToMainThread(WebFileSystem * fileSystem,const String & path,const String & mode)206 void WorkerFileSystemCallbacksBridge::postDirectoryExistsToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode)
207 {
208     ASSERT(fileSystem);
209     dispatchTaskToMainThread(createCallbackTask(&directoryExistsOnMainThread, fileSystem, path, this, mode));
210 }
211 
postReadDirectoryToMainThread(WebFileSystem * fileSystem,const String & path,const String & mode)212 void WorkerFileSystemCallbacksBridge::postReadDirectoryToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode)
213 {
214     ASSERT(fileSystem);
215     dispatchTaskToMainThread(createCallbackTask(&readDirectoryOnMainThread, fileSystem, path, this, mode));
216 }
217 
openFileSystemOnMainThread(ScriptExecutionContext *,WebCommonWorkerClient * commonClient,WebFileSystem::Type type,long long size,bool create,WorkerFileSystemCallbacksBridge * bridge,const String & mode)218 void WorkerFileSystemCallbacksBridge::openFileSystemOnMainThread(ScriptExecutionContext*, WebCommonWorkerClient* commonClient, WebFileSystem::Type type, long long size, bool create, WorkerFileSystemCallbacksBridge* bridge, const String& mode)
219 {
220     if (!commonClient)
221         bridge->didFailOnMainThread(WebFileErrorAbort, mode);
222     else {
223         commonClient->openFileSystem(type, size, create, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
224     }
225 }
226 
moveOnMainThread(WebCore::ScriptExecutionContext *,WebFileSystem * fileSystem,const String & sourcePath,const String & destinationPath,WorkerFileSystemCallbacksBridge * bridge,const String & mode)227 void WorkerFileSystemCallbacksBridge::moveOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& sourcePath, const String& destinationPath, WorkerFileSystemCallbacksBridge* bridge, const String& mode)
228 {
229     fileSystem->move(sourcePath, destinationPath, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
230 }
231 
copyOnMainThread(WebCore::ScriptExecutionContext *,WebFileSystem * fileSystem,const String & sourcePath,const String & destinationPath,WorkerFileSystemCallbacksBridge * bridge,const String & mode)232 void WorkerFileSystemCallbacksBridge::copyOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& sourcePath, const String& destinationPath, WorkerFileSystemCallbacksBridge* bridge, const String& mode)
233 {
234     fileSystem->copy(sourcePath, destinationPath, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
235 }
236 
removeOnMainThread(WebCore::ScriptExecutionContext *,WebFileSystem * fileSystem,const String & path,WorkerFileSystemCallbacksBridge * bridge,const String & mode)237 void WorkerFileSystemCallbacksBridge::removeOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode)
238 {
239     fileSystem->remove(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
240 }
241 
removeRecursivelyOnMainThread(WebCore::ScriptExecutionContext *,WebFileSystem * fileSystem,const String & path,WorkerFileSystemCallbacksBridge * bridge,const String & mode)242 void WorkerFileSystemCallbacksBridge::removeRecursivelyOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode)
243 {
244     fileSystem->removeRecursively(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
245 }
246 
readMetadataOnMainThread(WebCore::ScriptExecutionContext *,WebFileSystem * fileSystem,const String & path,WorkerFileSystemCallbacksBridge * bridge,const String & mode)247 void WorkerFileSystemCallbacksBridge::readMetadataOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode)
248 {
249     fileSystem->readMetadata(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
250 }
251 
createFileOnMainThread(WebCore::ScriptExecutionContext *,WebFileSystem * fileSystem,const String & path,bool exclusive,WorkerFileSystemCallbacksBridge * bridge,const String & mode)252 void WorkerFileSystemCallbacksBridge::createFileOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, bool exclusive, WorkerFileSystemCallbacksBridge* bridge, const String& mode)
253 {
254     fileSystem->createFile(path, exclusive, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
255 }
256 
createDirectoryOnMainThread(WebCore::ScriptExecutionContext *,WebFileSystem * fileSystem,const String & path,bool exclusive,WorkerFileSystemCallbacksBridge * bridge,const String & mode)257 void WorkerFileSystemCallbacksBridge::createDirectoryOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, bool exclusive, WorkerFileSystemCallbacksBridge* bridge, const String& mode)
258 {
259     fileSystem->createDirectory(path, exclusive, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
260 }
261 
fileExistsOnMainThread(WebCore::ScriptExecutionContext *,WebFileSystem * fileSystem,const String & path,WorkerFileSystemCallbacksBridge * bridge,const String & mode)262 void WorkerFileSystemCallbacksBridge::fileExistsOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode)
263 {
264     fileSystem->fileExists(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
265 }
266 
directoryExistsOnMainThread(WebCore::ScriptExecutionContext *,WebFileSystem * fileSystem,const String & path,WorkerFileSystemCallbacksBridge * bridge,const String & mode)267 void WorkerFileSystemCallbacksBridge::directoryExistsOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode)
268 {
269     fileSystem->directoryExists(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
270 }
271 
readDirectoryOnMainThread(WebCore::ScriptExecutionContext *,WebFileSystem * fileSystem,const String & path,WorkerFileSystemCallbacksBridge * bridge,const String & mode)272 void WorkerFileSystemCallbacksBridge::readDirectoryOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode)
273 {
274     fileSystem->readDirectory(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
275 }
276 
didFailOnMainThread(WebFileError error,const String & mode)277 void WorkerFileSystemCallbacksBridge::didFailOnMainThread(WebFileError error, const String& mode)
278 {
279     mayPostTaskToWorker(createCallbackTask(&didFailOnWorkerThread, this, error), mode);
280 }
281 
didOpenFileSystemOnMainThread(const String & name,const String & rootPath,const String & mode)282 void WorkerFileSystemCallbacksBridge::didOpenFileSystemOnMainThread(const String& name, const String& rootPath, const String& mode)
283 {
284     mayPostTaskToWorker(createCallbackTask(&didOpenFileSystemOnWorkerThread, this, name, rootPath), mode);
285 }
286 
didSucceedOnMainThread(const String & mode)287 void WorkerFileSystemCallbacksBridge::didSucceedOnMainThread(const String& mode)
288 {
289     mayPostTaskToWorker(createCallbackTask(&didSucceedOnWorkerThread, this), mode);
290 }
291 
didReadMetadataOnMainThread(const WebFileInfo & info,const String & mode)292 void WorkerFileSystemCallbacksBridge::didReadMetadataOnMainThread(const WebFileInfo& info, const String& mode)
293 {
294     mayPostTaskToWorker(createCallbackTask(&didReadMetadataOnWorkerThread, this, info), mode);
295 }
296 
didReadDirectoryOnMainThread(const WebVector<WebFileSystemEntry> & entries,bool hasMore,const String & mode)297 void WorkerFileSystemCallbacksBridge::didReadDirectoryOnMainThread(const WebVector<WebFileSystemEntry>& entries, bool hasMore, const String& mode)
298 {
299     mayPostTaskToWorker(createCallbackTask(&didReadDirectoryOnWorkerThread, this, entries, hasMore), mode);
300 }
301 
WorkerFileSystemCallbacksBridge(WebWorkerBase * worker,ScriptExecutionContext * scriptExecutionContext,WebFileSystemCallbacks * callbacks)302 WorkerFileSystemCallbacksBridge::WorkerFileSystemCallbacksBridge(WebWorkerBase* worker, ScriptExecutionContext* scriptExecutionContext, WebFileSystemCallbacks* callbacks)
303     : WorkerContext::Observer(static_cast<WorkerContext*>(scriptExecutionContext))
304     , m_worker(worker)
305     , m_workerContext(scriptExecutionContext)
306     , m_callbacksOnWorkerThread(callbacks)
307 {
308     ASSERT(m_workerContext->isContextThread());
309 }
310 
~WorkerFileSystemCallbacksBridge()311 WorkerFileSystemCallbacksBridge::~WorkerFileSystemCallbacksBridge()
312 {
313     ASSERT(!m_callbacksOnWorkerThread);
314 }
315 
didFailOnWorkerThread(ScriptExecutionContext *,WorkerFileSystemCallbacksBridge * bridge,WebFileError error)316 void WorkerFileSystemCallbacksBridge::didFailOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge, WebFileError error)
317 {
318     bridge->m_callbacksOnWorkerThread->didFail(error);
319 }
320 
didOpenFileSystemOnWorkerThread(ScriptExecutionContext *,WorkerFileSystemCallbacksBridge * bridge,const String & name,const String & rootPath)321 void WorkerFileSystemCallbacksBridge::didOpenFileSystemOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge, const String& name, const String& rootPath)
322 {
323     bridge->m_callbacksOnWorkerThread->didOpenFileSystem(name, rootPath);
324 }
325 
didSucceedOnWorkerThread(ScriptExecutionContext *,WorkerFileSystemCallbacksBridge * bridge)326 void WorkerFileSystemCallbacksBridge::didSucceedOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge)
327 {
328     bridge->m_callbacksOnWorkerThread->didSucceed();
329 }
330 
didReadMetadataOnWorkerThread(ScriptExecutionContext *,WorkerFileSystemCallbacksBridge * bridge,const WebFileInfo & info)331 void WorkerFileSystemCallbacksBridge::didReadMetadataOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge, const WebFileInfo& info)
332 {
333     bridge->m_callbacksOnWorkerThread->didReadMetadata(info);
334 }
335 
didReadDirectoryOnWorkerThread(ScriptExecutionContext *,WorkerFileSystemCallbacksBridge * bridge,const WebVector<WebFileSystemEntry> & entries,bool hasMore)336 void WorkerFileSystemCallbacksBridge::didReadDirectoryOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge, const WebVector<WebFileSystemEntry>& entries, bool hasMore)
337 {
338     bridge->m_callbacksOnWorkerThread->didReadDirectory(entries, hasMore);
339 }
340 
341 
runTaskOnMainThread(WebCore::ScriptExecutionContext * scriptExecutionContext,PassRefPtr<WorkerFileSystemCallbacksBridge> bridge,PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun)342 void WorkerFileSystemCallbacksBridge::runTaskOnMainThread(WebCore::ScriptExecutionContext* scriptExecutionContext, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun)
343 {
344     ASSERT(isMainThread());
345 
346     // Every task run will result in one call to mayPostTaskToWorker, which is where this ref is released.
347     WorkerFileSystemCallbacksBridge* leaked = bridge.leakRef();
348     UNUSED_PARAM(leaked);
349     taskToRun->performTask(scriptExecutionContext);
350 }
351 
runTaskOnWorkerThread(WebCore::ScriptExecutionContext * scriptExecutionContext,PassRefPtr<WorkerFileSystemCallbacksBridge> bridge,PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun)352 void WorkerFileSystemCallbacksBridge::runTaskOnWorkerThread(WebCore::ScriptExecutionContext* scriptExecutionContext, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun)
353 {
354     if (!bridge->m_callbacksOnWorkerThread)
355         return;
356     ASSERT(bridge->m_workerContext->isContextThread());
357     taskToRun->performTask(scriptExecutionContext);
358     bridge->m_callbacksOnWorkerThread = 0;
359     bridge->stopObserving();
360 }
361 
dispatchTaskToMainThread(PassOwnPtr<WebCore::ScriptExecutionContext::Task> task)362 void WorkerFileSystemCallbacksBridge::dispatchTaskToMainThread(PassOwnPtr<WebCore::ScriptExecutionContext::Task> task)
363 {
364     ASSERT(m_worker);
365     ASSERT(m_workerContext->isContextThread());
366     m_worker->dispatchTaskToMainThread(createCallbackTask(&runTaskOnMainThread, RefPtr<WorkerFileSystemCallbacksBridge>(this).release(), task));
367 }
368 
mayPostTaskToWorker(PassOwnPtr<ScriptExecutionContext::Task> task,const String & mode)369 void WorkerFileSystemCallbacksBridge::mayPostTaskToWorker(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode)
370 {
371     ASSERT(isMainThread());
372 
373     // Balancing out the ref() done in runTaskOnMainThread. (Since m_mutex is a member and the deref may result
374     // in the destruction of WorkerFileSystemCallbacksBridge, the ordering of the RefPtr and the MutexLocker
375     // is very important, to ensure that the m_mutex is still valid when it gets unlocked.)
376     RefPtr<WorkerFileSystemCallbacksBridge> bridge = adoptRef(this);
377     MutexLocker locker(m_mutex);
378     if (m_worker)
379         m_worker->postTaskForModeToWorkerContext(createCallbackTask(&runTaskOnWorkerThread, bridge, task), mode);
380 }
381 
382 } // namespace WebCore
383 
384 #endif // ENABLE(FILE_SYSTEM)
385