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 "FileSystemCallbacks.h"
33
34#if ENABLE(FILE_SYSTEM)
35
36#include "AsyncFileSystem.h"
37#include "AsyncFileWriter.h"
38#include "DOMFilePath.h"
39#include "DOMFileSystemBase.h"
40#include "DirectoryEntry.h"
41#include "DirectoryReader.h"
42#include "EntriesCallback.h"
43#include "EntryArray.h"
44#include "EntryCallback.h"
45#include "ErrorCallback.h"
46#include "FileEntry.h"
47#include "FileError.h"
48#include "FileMetadata.h"
49#include "FileSystemCallback.h"
50#include "FileWriterBase.h"
51#include "FileWriterBaseCallback.h"
52#include "Metadata.h"
53#include "MetadataCallback.h"
54#include "ScriptExecutionContext.h"
55#include "VoidCallback.h"
56
57namespace WebCore {
58
59FileSystemCallbacksBase::FileSystemCallbacksBase(PassRefPtr<ErrorCallback> errorCallback)
60    : m_errorCallback(errorCallback)
61{
62}
63
64FileSystemCallbacksBase::~FileSystemCallbacksBase()
65{
66}
67
68void FileSystemCallbacksBase::didSucceed()
69{
70    // Each subclass must implement an appropriate one.
71    ASSERT_NOT_REACHED();
72}
73
74void FileSystemCallbacksBase::didOpenFileSystem(const String&, PassOwnPtr<AsyncFileSystem>)
75{
76    // Each subclass must implement an appropriate one.
77    ASSERT_NOT_REACHED();
78}
79
80void FileSystemCallbacksBase::didReadMetadata(const FileMetadata&)
81{
82    // Each subclass must implement an appropriate one.
83    ASSERT_NOT_REACHED();
84}
85
86void FileSystemCallbacksBase::didReadDirectoryEntries(bool)
87{
88    // Each subclass must implement an appropriate one.
89    ASSERT_NOT_REACHED();
90}
91
92void FileSystemCallbacksBase::didReadDirectoryEntry(const String&, bool)
93{
94    // Each subclass must implement an appropriate one.
95    ASSERT_NOT_REACHED();
96}
97
98void FileSystemCallbacksBase::didCreateFileWriter(PassOwnPtr<AsyncFileWriter>, long long)
99{
100    // Each subclass must implement an appropriate one.
101    ASSERT_NOT_REACHED();
102}
103
104void FileSystemCallbacksBase::didFail(int code)
105{
106    if (m_errorCallback) {
107        m_errorCallback->handleEvent(FileError::create(static_cast<FileError::ErrorCode>(code)).get());
108        m_errorCallback.clear();
109    }
110}
111
112// EntryCallbacks -------------------------------------------------------------
113
114PassOwnPtr<EntryCallbacks> EntryCallbacks::create(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DOMFileSystemBase> fileSystem, const String& expectedPath, bool isDirectory)
115{
116    return adoptPtr(new EntryCallbacks(successCallback, errorCallback, fileSystem, expectedPath, isDirectory));
117}
118
119EntryCallbacks::EntryCallbacks(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DOMFileSystemBase> fileSystem, const String& expectedPath, bool isDirectory)
120    : FileSystemCallbacksBase(errorCallback)
121    , m_successCallback(successCallback)
122    , m_fileSystem(fileSystem)
123    , m_expectedPath(expectedPath)
124    , m_isDirectory(isDirectory)
125{
126}
127
128void EntryCallbacks::didSucceed()
129{
130    if (m_successCallback) {
131        if (m_isDirectory)
132            m_successCallback->handleEvent(DirectoryEntry::create(m_fileSystem, m_expectedPath).get());
133        else
134            m_successCallback->handleEvent(FileEntry::create(m_fileSystem, m_expectedPath).get());
135    }
136    m_successCallback.clear();
137}
138
139// EntriesCallbacks -----------------------------------------------------------
140
141PassOwnPtr<EntriesCallbacks> EntriesCallbacks::create(PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryReaderBase> directoryReader, const String& basePath)
142{
143    return adoptPtr(new EntriesCallbacks(successCallback, errorCallback, directoryReader, basePath));
144}
145
146EntriesCallbacks::EntriesCallbacks(PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryReaderBase> directoryReader, const String& basePath)
147    : FileSystemCallbacksBase(errorCallback)
148    , m_successCallback(successCallback)
149    , m_directoryReader(directoryReader)
150    , m_basePath(basePath)
151    , m_entries(EntryArray::create())
152{
153    ASSERT(m_directoryReader);
154}
155
156void EntriesCallbacks::didReadDirectoryEntry(const String& name, bool isDirectory)
157{
158    if (isDirectory)
159        m_entries->append(DirectoryEntry::create(m_directoryReader->filesystem(), DOMFilePath::append(m_basePath, name)));
160    else
161        m_entries->append(FileEntry::create(m_directoryReader->filesystem(), DOMFilePath::append(m_basePath, name)));
162}
163
164void EntriesCallbacks::didReadDirectoryEntries(bool hasMore)
165{
166    m_directoryReader->setHasMoreEntries(hasMore);
167    if (m_successCallback)
168        m_successCallback->handleEvent(m_entries.get());
169}
170
171// FileSystemCallbacks --------------------------------------------------------
172
173PassOwnPtr<FileSystemCallbacks> FileSystemCallbacks::create(PassRefPtr<FileSystemCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ScriptExecutionContext* scriptExecutionContext)
174{
175    return adoptPtr(new FileSystemCallbacks(successCallback, errorCallback, scriptExecutionContext));
176}
177
178FileSystemCallbacks::FileSystemCallbacks(PassRefPtr<FileSystemCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ScriptExecutionContext* context)
179    : FileSystemCallbacksBase(errorCallback)
180    , m_successCallback(successCallback)
181    , m_scriptExecutionContext(context)
182{
183}
184
185void FileSystemCallbacks::didOpenFileSystem(const String& name, PassOwnPtr<AsyncFileSystem> asyncFileSystem)
186{
187    if (m_successCallback) {
188        ASSERT(asyncFileSystem);
189        m_successCallback->handleEvent(DOMFileSystem::create(m_scriptExecutionContext.get(), name, asyncFileSystem.leakPtr()).get());
190        m_scriptExecutionContext.clear();
191    }
192    m_successCallback.clear();
193}
194
195// ResolveURICallbacks --------------------------------------------------------
196
197namespace {
198
199class ErrorCallbackWrapper : public ErrorCallback {
200public:
201    static PassRefPtr<ErrorCallbackWrapper> create(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryEntry> root, const String& filePath)
202    {
203        return adoptRef(new ErrorCallbackWrapper(successCallback, errorCallback, root, filePath));
204    }
205
206    virtual bool handleEvent(FileError* error)
207    {
208        ASSERT(error);
209        if (error->code() == FileError::TYPE_MISMATCH_ERR)
210            m_root->getFile(m_filePath, 0, m_successCallback, m_errorCallback);
211        else if (m_errorCallback)
212            m_errorCallback->handleEvent(error);
213        return true;
214    }
215
216private:
217    ErrorCallbackWrapper(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryEntry> root, const String& filePath)
218        : m_successCallback(successCallback)
219        , m_errorCallback(errorCallback)
220        , m_root(root)
221        , m_filePath(filePath)
222    {
223        ASSERT(m_root);
224    }
225
226    RefPtr<EntryCallback> m_successCallback;
227    RefPtr<ErrorCallback> m_errorCallback;
228    RefPtr<DirectoryEntry> m_root;
229    String m_filePath;
230};
231
232} // namespace
233
234PassOwnPtr<ResolveURICallbacks> ResolveURICallbacks::create(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ScriptExecutionContext* scriptExecutionContext, const String& filePath)
235{
236    return adoptPtr(new ResolveURICallbacks(successCallback, errorCallback, scriptExecutionContext, filePath));
237}
238
239ResolveURICallbacks::ResolveURICallbacks(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ScriptExecutionContext* context, const String& filePath)
240    : FileSystemCallbacksBase(errorCallback)
241    , m_successCallback(successCallback)
242    , m_scriptExecutionContext(context)
243    , m_filePath(filePath)
244{
245}
246
247void ResolveURICallbacks::didOpenFileSystem(const String& name, PassOwnPtr<AsyncFileSystem> asyncFileSystem)
248{
249    ASSERT(asyncFileSystem);
250    RefPtr<DirectoryEntry> root = DOMFileSystem::create(m_scriptExecutionContext.get(), name, asyncFileSystem.leakPtr())->root();
251    root->getDirectory(m_filePath, 0, m_successCallback, ErrorCallbackWrapper::create(m_successCallback, m_errorCallback, root, m_filePath));
252}
253
254// MetadataCallbacks ----------------------------------------------------------
255
256PassOwnPtr<MetadataCallbacks> MetadataCallbacks::create(PassRefPtr<MetadataCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
257{
258    return adoptPtr(new MetadataCallbacks(successCallback, errorCallback));
259}
260
261MetadataCallbacks::MetadataCallbacks(PassRefPtr<MetadataCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
262    : FileSystemCallbacksBase(errorCallback)
263    , m_successCallback(successCallback)
264{
265}
266
267void MetadataCallbacks::didReadMetadata(const FileMetadata& metadata)
268{
269    if (m_successCallback)
270        m_successCallback->handleEvent(Metadata::create(metadata.modificationTime).get());
271    m_successCallback.clear();
272}
273
274// FileWriterBaseCallbacks ----------------------------------------------------------
275
276PassOwnPtr<FileWriterBaseCallbacks> FileWriterBaseCallbacks::create(PassRefPtr<FileWriterBase> fileWriter, PassRefPtr<FileWriterBaseCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
277{
278    return adoptPtr(new FileWriterBaseCallbacks(fileWriter, successCallback, errorCallback));
279}
280
281FileWriterBaseCallbacks::FileWriterBaseCallbacks(PassRefPtr<FileWriterBase> fileWriter, PassRefPtr<FileWriterBaseCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
282    : FileSystemCallbacksBase(errorCallback)
283    , m_fileWriter(fileWriter)
284    , m_successCallback(successCallback)
285{
286}
287
288void FileWriterBaseCallbacks::didCreateFileWriter(PassOwnPtr<AsyncFileWriter> asyncFileWriter, long long length)
289{
290    m_fileWriter->initialize(asyncFileWriter, length);
291    if (m_successCallback)
292        m_successCallback->handleEvent(m_fileWriter.release().get());
293    m_successCallback.clear();
294}
295
296// VoidCallbacks --------------------------------------------------------------
297
298PassOwnPtr<VoidCallbacks> VoidCallbacks::create(PassRefPtr<VoidCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
299{
300    return adoptPtr(new VoidCallbacks(successCallback, errorCallback));
301}
302
303VoidCallbacks::VoidCallbacks(PassRefPtr<VoidCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
304    : FileSystemCallbacksBase(errorCallback)
305    , m_successCallback(successCallback)
306{
307}
308
309void VoidCallbacks::didSucceed()
310{
311    if (m_successCallback)
312        m_successCallback->handleEvent();
313    m_successCallback.clear();
314}
315
316} // namespace
317
318#endif // ENABLE(FILE_SYSTEM)
319