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