1/*
2 * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
18 */
19
20#include "config.h"
21#if ENABLE(FILE_SYSTEM) && ENABLE(WORKERS)
22#include "WorkerPlatformAsyncFileSystemCallbacks.h"
23
24#include "CrossThreadTask.h"
25#include "WorkerAsyncFileSystemBlackBerry.h"
26#include "WorkerAsyncFileWriterBlackBerry.h"
27#include "WorkerContext.h"
28#include "WorkerLoaderProxy.h"
29#include "WorkerThread.h"
30
31#include <wtf/MainThread.h>
32
33namespace WebCore {
34
35static void performTaskOnMainThread(void* context)
36{
37    OwnPtr<ScriptExecutionContext::Task> task = adoptPtr(static_cast<ScriptExecutionContext::Task*>(context));
38    task->performTask(0);
39}
40
41void postTaskToMainThread(PassOwnPtr<ScriptExecutionContext::Task> task)
42{
43    callOnMainThread(&performTaskOnMainThread, task.leakPtr());
44}
45
46template<> struct CrossThreadCopierBase<false, false, BlackBerry::Platform::WebFileInfo> {
47    typedef BlackBerry::Platform::WebFileInfo Type;
48    static Type copy(const Type& info)
49    {
50        Type result;
51        result.m_modificationTime = info.m_modificationTime;
52        result.m_length = info.m_length;
53        result.m_type = info.m_type;
54        result.m_platformPath = info.m_platformPath;
55        return result;
56    }
57};
58
59template <> struct CrossThreadCopierBase<false, false, std::vector<BlackBerry::Platform::WebFileSystemEntry> > {
60    typedef std::vector<BlackBerry::Platform::WebFileSystemEntry> Type;
61    static Type copy(const Type& entries)
62    {
63        Type result(entries.size());
64        for (size_t i = 0; i < entries.size(); ++i) {
65            result[i].m_name = entries[i].m_name;
66            result[i].m_isDirectory = entries[i].m_isDirectory;
67        }
68        return result;
69    }
70};
71
72void WorkerPlatformAsyncFileSystemCallbacks::notifyStop()
73{
74    m_callbacks.clear();
75    {
76        WTF::MutexLocker locker(m_mutex);
77        m_context = 0;
78    }
79}
80
81void WorkerPlatformAsyncFileSystemCallbacks::notifyOpenFileSystem(BlackBerry::Platform::WebFileSystem* platformFileSystem)
82{
83    m_mutex.lock();
84    if (!m_context) {
85        m_mutex.unlock();
86        PlatformAsyncFileSystemCallbacks::deleteMe();
87        return;
88    }
89
90    postTaskToWorkerThread(createCallbackTask(&notifyOpenFileSystemOnWorkerThread, this, platformFileSystem));
91    m_mutex.unlock();
92}
93
94void WorkerPlatformAsyncFileSystemCallbacks::notifySucceed()
95{
96    m_mutex.lock();
97    if (!m_context) {
98        m_mutex.unlock();
99        PlatformAsyncFileSystemCallbacks::deleteMe();
100        return;
101    }
102
103    postTaskToWorkerThread(createCallbackTask(&notifySucceedOnWorkerThread, this));
104    m_mutex.unlock();
105}
106
107void WorkerPlatformAsyncFileSystemCallbacks::notifyFail(BlackBerry::Platform::WebFileError error)
108{
109    m_mutex.lock();
110    if (!m_context) {
111        m_mutex.unlock();
112        PlatformAsyncFileSystemCallbacks::deleteMe();
113        return;
114    }
115
116    postTaskToWorkerThread(createCallbackTask(&notifyFailOnWorkerThread, this, error));
117    m_mutex.unlock();
118}
119
120void WorkerPlatformAsyncFileSystemCallbacks::notifyReadMetadata(const BlackBerry::Platform::WebFileInfo& fileInfo)
121{
122    m_mutex.lock();
123    if (!m_context) {
124        m_mutex.unlock();
125        PlatformAsyncFileSystemCallbacks::deleteMe();
126        return;
127    }
128
129    postTaskToWorkerThread(createCallbackTask(&notifyReadMetadataOnWorkerThread, this, fileInfo));
130    m_mutex.unlock();
131}
132
133void WorkerPlatformAsyncFileSystemCallbacks::notifyCreateSnapshotFileAndReadMetadata(const BlackBerry::Platform::WebFileInfo& fileInfo)
134{
135    m_mutex.lock();
136    if (!m_context) {
137        m_mutex.unlock();
138        PlatformAsyncFileSystemCallbacks::deleteMe();
139        return;
140    }
141
142    postTaskToWorkerThread(createCallbackTask(&notifyCreateSnapshotFileAndReadMetadataOnWorkerThread, this, fileInfo));
143    m_mutex.unlock();
144}
145
146void WorkerPlatformAsyncFileSystemCallbacks::notifyReadDirectory(const std::vector<BlackBerry::Platform::WebFileSystemEntry>& entries, bool hasMore)
147{
148    m_mutex.lock();
149    if (!m_context) {
150        m_mutex.unlock();
151        PlatformAsyncFileSystemCallbacks::deleteMe();
152        return;
153    }
154
155    postTaskToWorkerThread(createCallbackTask(&notifyReadDirectoryEntryOnWorkerThread, this, entries, hasMore));
156    m_mutex.unlock();
157}
158
159void WorkerPlatformAsyncFileSystemCallbacks::notifyCreateFileWriter(BlackBerry::Platform::WebFileWriter* platformWriter, long long length)
160{
161    m_mutex.lock();
162    if (!m_context) {
163        m_mutex.unlock();
164        PlatformAsyncFileSystemCallbacks::deleteMe();
165        return;
166    }
167
168    postTaskToWorkerThread(createCallbackTask(&notifyCreateFileWriterOnWorkerThread, this, platformWriter, length));
169    m_mutex.unlock();
170}
171
172PassOwnPtr<AsyncFileSystem> WorkerPlatformAsyncFileSystemCallbacks::createAsyncFileSystem(PassOwnPtr<BlackBerry::Platform::WebFileSystem> platformFileSystem)
173{
174    return WorkerAsyncFileSystemBlackBerry::create(m_context, m_mode, platformFileSystem);
175}
176
177PassOwnPtr<AsyncFileWriter> WorkerPlatformAsyncFileSystemCallbacks::createAsyncFileWriter(PassOwnPtr<BlackBerry::Platform::WebFileWriter> platformWriter)
178{
179    ASSERT(m_writerClient);
180    BlackBerry::Platform::WebFileWriter* platformWriterPtr = platformWriter.get();
181    OwnPtr<WorkerAsyncFileWriterBlackBerry> writer = WorkerAsyncFileWriterBlackBerry::create(m_context, m_mode, platformWriter, m_writerClient);
182    platformWriterPtr->setClient(writer->platformWriterClient());
183    return writer.release();
184}
185
186void WorkerPlatformAsyncFileSystemCallbacks::deleteMe()
187{
188    deleteGuardedObject(this);
189}
190
191void WorkerPlatformAsyncFileSystemCallbacks::postTaskToWorkerThread(PassOwnPtr<ScriptExecutionContext::Task> task)
192{
193    m_context->thread()->workerLoaderProxy().postTaskForModeToWorkerContext(task, m_mode);
194}
195
196void WorkerPlatformAsyncFileSystemCallbacks::notifyOpenFileSystemOnWorkerThread(ScriptExecutionContext*, WorkerPlatformAsyncFileSystemCallbacks* callbacks, BlackBerry::Platform::WebFileSystem* platformFileSystem)
197{
198    callbacks->PlatformAsyncFileSystemCallbacks::notifyOpenFileSystem(platformFileSystem);
199}
200
201void WorkerPlatformAsyncFileSystemCallbacks::notifySucceedOnWorkerThread(ScriptExecutionContext*, WorkerPlatformAsyncFileSystemCallbacks* callbacks)
202{
203    callbacks->PlatformAsyncFileSystemCallbacks::notifySucceed();
204}
205
206void WorkerPlatformAsyncFileSystemCallbacks::notifyFailOnWorkerThread(ScriptExecutionContext*, WorkerPlatformAsyncFileSystemCallbacks* callbacks, BlackBerry::Platform::WebFileError error)
207{
208    callbacks->PlatformAsyncFileSystemCallbacks::notifyFail(error);
209}
210
211void WorkerPlatformAsyncFileSystemCallbacks::notifyReadMetadataOnWorkerThread(ScriptExecutionContext*, WorkerPlatformAsyncFileSystemCallbacks* callbacks, const BlackBerry::Platform::WebFileInfo& fileInfo)
212{
213    callbacks->PlatformAsyncFileSystemCallbacks::notifyReadMetadata(fileInfo);
214}
215
216void WorkerPlatformAsyncFileSystemCallbacks::notifyCreateSnapshotFileAndReadMetadataOnWorkerThread(ScriptExecutionContext*, WorkerPlatformAsyncFileSystemCallbacks* callbacks, const BlackBerry::Platform::WebFileInfo& fileInfo)
217{
218    callbacks->PlatformAsyncFileSystemCallbacks::notifyCreateSnapshotFileAndReadMetadata(fileInfo);
219}
220
221void WorkerPlatformAsyncFileSystemCallbacks::notifyReadDirectoryEntryOnWorkerThread(ScriptExecutionContext*, WorkerPlatformAsyncFileSystemCallbacks* callbacks, const std::vector<BlackBerry::Platform::WebFileSystemEntry>& entries, bool hasMore)
222{
223    callbacks->PlatformAsyncFileSystemCallbacks::notifyReadDirectory(entries, hasMore);
224}
225
226void WorkerPlatformAsyncFileSystemCallbacks::notifyCreateFileWriterOnWorkerThread(ScriptExecutionContext*, WorkerPlatformAsyncFileSystemCallbacks* callbacks, BlackBerry::Platform::WebFileWriter* platformWriter, long long length)
227{
228    callbacks->PlatformAsyncFileSystemCallbacks::notifyCreateFileWriter(platformWriter, length);
229}
230
231} // namespace WebCore
232#endif
233