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::didFail(int code)
69{
70    if (m_errorCallback) {
71        m_errorCallback->handleEvent(FileError::create(static_cast<FileError::ErrorCode>(code)).get());
72        m_errorCallback.clear();
73    }
74}
75
76// EntryCallbacks -------------------------------------------------------------
77
78PassOwnPtr<EntryCallbacks> EntryCallbacks::create(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DOMFileSystemBase> fileSystem, const String& expectedPath, bool isDirectory)
79{
80    return adoptPtr(new EntryCallbacks(successCallback, errorCallback, fileSystem, expectedPath, isDirectory));
81}
82
83EntryCallbacks::EntryCallbacks(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DOMFileSystemBase> fileSystem, const String& expectedPath, bool isDirectory)
84    : FileSystemCallbacksBase(errorCallback)
85    , m_successCallback(successCallback)
86    , m_fileSystem(fileSystem)
87    , m_expectedPath(expectedPath)
88    , m_isDirectory(isDirectory)
89{
90}
91
92void EntryCallbacks::didSucceed()
93{
94    if (m_successCallback) {
95        if (m_isDirectory)
96            m_successCallback->handleEvent(DirectoryEntry::create(m_fileSystem, m_expectedPath).get());
97        else
98            m_successCallback->handleEvent(FileEntry::create(m_fileSystem, m_expectedPath).get());
99    }
100    m_successCallback.clear();
101}
102
103// EntriesCallbacks -----------------------------------------------------------
104
105PassOwnPtr<EntriesCallbacks> EntriesCallbacks::create(PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryReaderBase> directoryReader, const String& basePath)
106{
107    return adoptPtr(new EntriesCallbacks(successCallback, errorCallback, directoryReader, basePath));
108}
109
110EntriesCallbacks::EntriesCallbacks(PassRefPtr<EntriesCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryReaderBase> directoryReader, const String& basePath)
111    : FileSystemCallbacksBase(errorCallback)
112    , m_successCallback(successCallback)
113    , m_directoryReader(directoryReader)
114    , m_basePath(basePath)
115    , m_entries(EntryArray::create())
116{
117    ASSERT(m_directoryReader);
118}
119
120void EntriesCallbacks::didReadDirectoryEntry(const String& name, bool isDirectory)
121{
122    if (isDirectory)
123        m_entries->append(DirectoryEntry::create(m_directoryReader->filesystem(), DOMFilePath::append(m_basePath, name)));
124    else
125        m_entries->append(FileEntry::create(m_directoryReader->filesystem(), DOMFilePath::append(m_basePath, name)));
126}
127
128void EntriesCallbacks::didReadDirectoryEntries(bool hasMore)
129{
130    m_directoryReader->setHasMoreEntries(hasMore);
131    if (m_successCallback)
132        m_successCallback->handleEvent(m_entries.get());
133}
134
135// FileSystemCallbacks --------------------------------------------------------
136
137PassOwnPtr<FileSystemCallbacks> FileSystemCallbacks::create(PassRefPtr<FileSystemCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ScriptExecutionContext* scriptExecutionContext, FileSystemType type)
138{
139    return adoptPtr(new FileSystemCallbacks(successCallback, errorCallback, scriptExecutionContext, type));
140}
141
142FileSystemCallbacks::FileSystemCallbacks(PassRefPtr<FileSystemCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ScriptExecutionContext* context, FileSystemType type)
143    : FileSystemCallbacksBase(errorCallback)
144    , m_successCallback(successCallback)
145    , m_scriptExecutionContext(context)
146    , m_type(type)
147{
148}
149
150void FileSystemCallbacks::didOpenFileSystem(const String& name, const KURL& rootURL, PassOwnPtr<AsyncFileSystem> asyncFileSystem)
151{
152    if (m_successCallback) {
153        ASSERT(asyncFileSystem);
154        RefPtr<DOMFileSystem> fileSystem = DOMFileSystem::create(m_scriptExecutionContext.get(), name, m_type, rootURL, asyncFileSystem);
155        m_successCallback->handleEvent(fileSystem.get());
156        m_scriptExecutionContext.clear();
157    }
158    m_successCallback.clear();
159}
160
161// ResolveURICallbacks --------------------------------------------------------
162
163namespace {
164
165class ErrorCallbackWrapper : public ErrorCallback {
166public:
167    static PassRefPtr<ErrorCallbackWrapper> create(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryEntry> root, const String& filePath)
168    {
169        return adoptRef(new ErrorCallbackWrapper(successCallback, errorCallback, root, filePath));
170    }
171
172    virtual bool handleEvent(FileError* error)
173    {
174        ASSERT(error);
175        if (error->code() == FileError::TYPE_MISMATCH_ERR)
176            m_root->getFile(m_filePath, Dictionary(), m_successCallback, m_errorCallback);
177        else if (m_errorCallback)
178            m_errorCallback->handleEvent(error);
179        return true;
180    }
181
182private:
183    ErrorCallbackWrapper(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryEntry> root, const String& filePath)
184        : m_successCallback(successCallback)
185        , m_errorCallback(errorCallback)
186        , m_root(root)
187        , m_filePath(filePath)
188    {
189        ASSERT(m_root);
190    }
191
192    RefPtr<EntryCallback> m_successCallback;
193    RefPtr<ErrorCallback> m_errorCallback;
194    RefPtr<DirectoryEntry> m_root;
195    String m_filePath;
196};
197
198} // namespace
199
200PassOwnPtr<ResolveURICallbacks> ResolveURICallbacks::create(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ScriptExecutionContext* scriptExecutionContext, FileSystemType type, const String& filePath)
201{
202    return adoptPtr(new ResolveURICallbacks(successCallback, errorCallback, scriptExecutionContext, type, filePath));
203}
204
205ResolveURICallbacks::ResolveURICallbacks(PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback, ScriptExecutionContext* context, FileSystemType type, const String& filePath)
206    : FileSystemCallbacksBase(errorCallback)
207    , m_successCallback(successCallback)
208    , m_scriptExecutionContext(context)
209    , m_type(type)
210    , m_filePath(filePath)
211{
212}
213
214void ResolveURICallbacks::didOpenFileSystem(const String& name, const KURL& rootURL, PassOwnPtr<AsyncFileSystem> asyncFileSystem)
215{
216    ASSERT(asyncFileSystem);
217    RefPtr<DirectoryEntry> root = DOMFileSystem::create(m_scriptExecutionContext.get(), name, m_type, rootURL, asyncFileSystem)->root();
218    root->getDirectory(m_filePath, Dictionary(), m_successCallback, ErrorCallbackWrapper::create(m_successCallback, m_errorCallback, root, m_filePath));
219}
220
221// MetadataCallbacks ----------------------------------------------------------
222
223PassOwnPtr<MetadataCallbacks> MetadataCallbacks::create(PassRefPtr<MetadataCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
224{
225    return adoptPtr(new MetadataCallbacks(successCallback, errorCallback));
226}
227
228MetadataCallbacks::MetadataCallbacks(PassRefPtr<MetadataCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
229    : FileSystemCallbacksBase(errorCallback)
230    , m_successCallback(successCallback)
231{
232}
233
234void MetadataCallbacks::didReadMetadata(const FileMetadata& metadata)
235{
236    if (m_successCallback)
237        m_successCallback->handleEvent(Metadata::create(metadata).get());
238    m_successCallback.clear();
239}
240
241// FileWriterBaseCallbacks ----------------------------------------------------------
242
243PassOwnPtr<FileWriterBaseCallbacks> FileWriterBaseCallbacks::create(PassRefPtr<FileWriterBase> fileWriter, PassRefPtr<FileWriterBaseCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
244{
245    return adoptPtr(new FileWriterBaseCallbacks(fileWriter, successCallback, errorCallback));
246}
247
248FileWriterBaseCallbacks::FileWriterBaseCallbacks(PassRefPtr<FileWriterBase> fileWriter, PassRefPtr<FileWriterBaseCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
249    : FileSystemCallbacksBase(errorCallback)
250    , m_fileWriter(fileWriter)
251    , m_successCallback(successCallback)
252{
253}
254
255void FileWriterBaseCallbacks::didCreateFileWriter(PassOwnPtr<AsyncFileWriter> asyncFileWriter, long long length)
256{
257    m_fileWriter->initialize(asyncFileWriter, length);
258    if (m_successCallback)
259        m_successCallback->handleEvent(m_fileWriter.release().get());
260    m_successCallback.clear();
261}
262
263// VoidCallbacks --------------------------------------------------------------
264
265PassOwnPtr<VoidCallbacks> VoidCallbacks::create(PassRefPtr<VoidCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
266{
267    return adoptPtr(new VoidCallbacks(successCallback, errorCallback));
268}
269
270VoidCallbacks::VoidCallbacks(PassRefPtr<VoidCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
271    : FileSystemCallbacksBase(errorCallback)
272    , m_successCallback(successCallback)
273{
274}
275
276void VoidCallbacks::didSucceed()
277{
278    if (m_successCallback)
279        m_successCallback->handleEvent();
280    m_successCallback.clear();
281}
282
283} // namespace
284
285#endif // ENABLE(FILE_SYSTEM)
286