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#ifndef DOMFileSystem_h
32#define DOMFileSystem_h
33
34#include "bindings/core/v8/ScriptWrappable.h"
35#include "core/dom/ActiveDOMObject.h"
36#include "core/dom/ExecutionContext.h"
37#include "core/dom/ExecutionContextTask.h"
38#include "modules/filesystem/DOMFileSystemBase.h"
39#include "modules/filesystem/EntriesCallback.h"
40#include "platform/heap/Handle.h"
41
42namespace blink {
43
44class DirectoryEntry;
45class File;
46class FileCallback;
47class FileEntry;
48class FileWriterCallback;
49
50class DOMFileSystem FINAL : public DOMFileSystemBase, public ScriptWrappable, public ActiveDOMObject {
51    DEFINE_WRAPPERTYPEINFO();
52public:
53    static DOMFileSystem* create(ExecutionContext*, const String& name, FileSystemType, const KURL& rootURL);
54
55    // Creates a new isolated file system for the given filesystemId.
56    static DOMFileSystem* createIsolatedFileSystem(ExecutionContext*, const String& filesystemId);
57
58    DirectoryEntry* root();
59
60    // DOMFileSystemBase overrides.
61    virtual void addPendingCallbacks() OVERRIDE;
62    virtual void removePendingCallbacks() OVERRIDE;
63    virtual void reportError(ErrorCallback*, PassRefPtrWillBeRawPtr<FileError>) OVERRIDE;
64
65    // ActiveDOMObject overrides.
66    virtual bool hasPendingActivity() const OVERRIDE;
67
68    void createWriter(const FileEntry*, FileWriterCallback*, ErrorCallback*);
69    void createFile(const FileEntry*, FileCallback*, ErrorCallback*);
70
71    // Schedule a callback. This should not cross threads (should be called on the same context thread).
72    // FIXME: move this to a more generic place.
73    template <typename CB, typename CBArg>
74    static void scheduleCallback(ExecutionContext*, CB*, PassRefPtrWillBeRawPtr<CBArg>);
75
76    template <typename CB, typename CBArg>
77    static void scheduleCallback(ExecutionContext*, CB*, CBArg*);
78
79    template <typename CB, typename CBArg>
80    static void scheduleCallback(ExecutionContext*, CB*, const HeapVector<CBArg>&);
81
82    template <typename CB, typename CBArg>
83    static void scheduleCallback(ExecutionContext*, CB*, const CBArg&);
84
85    template <typename CB>
86    static void scheduleCallback(ExecutionContext*, CB*);
87
88    template <typename CB, typename CBArg>
89    void scheduleCallback(CB* callback, PassRefPtrWillBeRawPtr<CBArg> callbackArg)
90    {
91        scheduleCallback(executionContext(), callback, callbackArg);
92    }
93
94    template <typename CB, typename CBArg>
95    void scheduleCallback(CB* callback, CBArg* callbackArg)
96    {
97        scheduleCallback(executionContext(), callback, callbackArg);
98    }
99
100    template <typename CB, typename CBArg>
101    void scheduleCallback(CB* callback, const CBArg& callbackArg)
102    {
103        scheduleCallback(executionContext(), callback, callbackArg);
104    }
105
106private:
107    DOMFileSystem(ExecutionContext*, const String& name, FileSystemType, const KURL& rootURL);
108
109    class DispatchCallbackTaskBase : public ExecutionContextTask {
110    public:
111        DispatchCallbackTaskBase()
112            : m_taskName("FileSystem")
113        {
114        }
115
116        virtual const String& taskNameForInstrumentation() const OVERRIDE
117        {
118            return m_taskName;
119        }
120
121    private:
122        const String m_taskName;
123    };
124
125    // A helper template to schedule a callback task.
126    template <typename CB, typename CBArg>
127    class DispatchCallbackRefPtrArgTask FINAL : public DispatchCallbackTaskBase {
128    public:
129        DispatchCallbackRefPtrArgTask(CB* callback, PassRefPtrWillBeRawPtr<CBArg> arg)
130            : m_callback(callback)
131            , m_callbackArg(arg)
132        {
133        }
134
135        virtual void performTask(ExecutionContext*) OVERRIDE
136        {
137            m_callback->handleEvent(m_callbackArg.get());
138        }
139
140    private:
141        Persistent<CB> m_callback;
142        RefPtrWillBePersistent<CBArg> m_callbackArg;
143    };
144
145    template <typename CB, typename CBArg>
146    class DispatchCallbackPtrArgTask FINAL : public DispatchCallbackTaskBase {
147    public:
148        DispatchCallbackPtrArgTask(CB* callback, CBArg* arg)
149            : m_callback(callback)
150            , m_callbackArg(arg)
151        {
152        }
153
154        virtual void performTask(ExecutionContext*) OVERRIDE
155        {
156            m_callback->handleEvent(m_callbackArg.get());
157        }
158
159    private:
160        Persistent<CB> m_callback;
161        Persistent<CBArg> m_callbackArg;
162    };
163
164    template <typename CB, typename CBArg>
165    class DispatchCallbackNonPtrArgTask FINAL : public DispatchCallbackTaskBase {
166    public:
167        DispatchCallbackNonPtrArgTask(CB* callback, const CBArg& arg)
168            : m_callback(callback)
169            , m_callbackArg(arg)
170        {
171        }
172
173        virtual void performTask(ExecutionContext*) OVERRIDE
174        {
175            m_callback->handleEvent(m_callbackArg);
176        }
177
178    private:
179        Persistent<CB> m_callback;
180        CBArg m_callbackArg;
181    };
182
183    template <typename CB>
184    class DispatchCallbackNoArgTask FINAL : public DispatchCallbackTaskBase {
185    public:
186        DispatchCallbackNoArgTask(CB* callback)
187            : m_callback(callback)
188        {
189        }
190
191        virtual void performTask(ExecutionContext*) OVERRIDE
192        {
193            m_callback->handleEvent();
194        }
195
196    private:
197        Persistent<CB> m_callback;
198    };
199
200    int m_numberOfPendingCallbacks;
201};
202
203template <typename CB, typename CBArg>
204void DOMFileSystem::scheduleCallback(ExecutionContext* executionContext, CB* callback, PassRefPtrWillBeRawPtr<CBArg> arg)
205{
206    ASSERT(executionContext->isContextThread());
207    if (callback)
208        executionContext->postTask(adoptPtr(new DispatchCallbackRefPtrArgTask<CB, CBArg>(callback, arg)));
209}
210
211template <typename CB, typename CBArg>
212void DOMFileSystem::scheduleCallback(ExecutionContext* executionContext, CB* callback, CBArg* arg)
213{
214    ASSERT(executionContext->isContextThread());
215    if (callback)
216        executionContext->postTask(adoptPtr(new DispatchCallbackPtrArgTask<CB, CBArg>(callback, arg)));
217}
218
219template <typename CB, typename CBArg>
220void DOMFileSystem::scheduleCallback(ExecutionContext* executionContext, CB* callback, const HeapVector<CBArg>& arg)
221{
222    ASSERT(executionContext->isContextThread());
223    if (callback)
224        executionContext->postTask(adoptPtr(new DispatchCallbackNonPtrArgTask<CB, PersistentHeapVector<CBArg> >(callback, arg)));
225}
226
227template <typename CB, typename CBArg>
228void DOMFileSystem::scheduleCallback(ExecutionContext* executionContext, CB* callback, const CBArg& arg)
229{
230    ASSERT(executionContext->isContextThread());
231    if (callback)
232        executionContext->postTask(adoptPtr(new DispatchCallbackNonPtrArgTask<CB, CBArg>(callback, arg)));
233}
234
235template <typename CB>
236void DOMFileSystem::scheduleCallback(ExecutionContext* executionContext, CB* callback)
237{
238    ASSERT(executionContext->isContextThread());
239    if (callback)
240        executionContext->postTask(adoptPtr(new DispatchCallbackNoArgTask<CB>(callback)));
241}
242
243} // namespace blink
244
245#endif // DOMFileSystem_h
246