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 SyncCallbackHelper_h
32#define SyncCallbackHelper_h
33
34#if ENABLE(FILE_SYSTEM)
35
36#include "DirectoryEntry.h"
37#include "EntriesCallback.h"
38#include "EntryArraySync.h"
39#include "EntryCallback.h"
40#include "ErrorCallback.h"
41#include "ExceptionCode.h"
42#include "FileEntry.h"
43#include "FileError.h"
44#include "FileException.h"
45#include "FileSystemCallback.h"
46#include "MetadataCallback.h"
47#include "VoidCallback.h"
48#include <wtf/PassRefPtr.h>
49#include <wtf/RefCounted.h>
50
51namespace WebCore {
52
53class AsyncFileSystem;
54class DirectoryEntrySync;
55class EntryArraySync;
56class EntrySync;
57class FileEntrySync;
58
59// A helper template for FileSystemSync implementation.
60template <typename SuccessCallback, typename ObserverType, typename CallbackArg, typename ResultType>
61class SyncCallbackHelper {
62    WTF_MAKE_NONCOPYABLE(SyncCallbackHelper);
63public:
64    typedef SyncCallbackHelper<SuccessCallback, ObserverType, CallbackArg, ResultType> HelperType;
65    SyncCallbackHelper(ObserverType* observer = 0)
66        : m_observer(observer)
67        , m_successCallback(SuccessCallbackImpl::create(this))
68        , m_errorCallback(ErrorCallbackImpl::create(this))
69        , m_exceptionCode(0)
70        , m_completed(false)
71    {
72    }
73
74    PassRefPtr<ResultType> getResult(ExceptionCode& ec)
75    {
76        if (m_observer) {
77            while (!m_completed) {
78                if (!m_observer->waitForOperationToComplete()) {
79                    m_exceptionCode = FileException::ABORT_ERR;
80                    break;
81                }
82            }
83        }
84        ec = m_exceptionCode;
85        return m_result.release();
86    }
87
88    PassRefPtr<SuccessCallback> successCallback() { return m_successCallback; }
89    PassRefPtr<ErrorCallback> errorCallback() { return m_errorCallback; }
90
91private:
92    class SuccessCallbackImpl : public SuccessCallback {
93    public:
94        static PassRefPtr<SuccessCallbackImpl> create(HelperType* helper)
95        {
96            return adoptRef(new SuccessCallbackImpl(helper));
97        }
98
99        virtual void handleEvent()
100        {
101            m_helper->setError(0);
102        }
103
104        virtual bool handleEvent(CallbackArg* arg)
105        {
106            m_helper->setResult(ResultType::create(arg));
107            return true;
108        }
109
110    private:
111        SuccessCallbackImpl(HelperType* helper)
112            : m_helper(helper)
113        {
114        }
115        HelperType* m_helper;
116    };
117
118    class ErrorCallbackImpl : public ErrorCallback {
119    public:
120        static PassRefPtr<ErrorCallbackImpl> create(HelperType* helper)
121        {
122            return adoptRef(new ErrorCallbackImpl(helper));
123        }
124
125        virtual bool handleEvent(FileError* error)
126        {
127            ASSERT(error);
128            m_helper->setError(error->code());
129            return true;
130        }
131
132    private:
133        ErrorCallbackImpl(HelperType* helper)
134            : m_helper(helper)
135        {
136        }
137        HelperType* m_helper;
138    };
139
140    friend class SuccessCallbackImpl;
141    friend class ErrorCallbackImpl;
142
143    void setError(int code)
144    {
145        m_exceptionCode = FileException::ErrorCodeToExceptionCode(code);
146        m_completed = true;
147    }
148
149    void setResult(PassRefPtr<ResultType> result)
150    {
151        m_result = result;
152        m_completed = true;
153    }
154
155    ObserverType* m_observer;
156    RefPtr<SuccessCallbackImpl> m_successCallback;
157    RefPtr<ErrorCallbackImpl> m_errorCallback;
158    RefPtr<ResultType> m_result;
159    ExceptionCode m_exceptionCode;
160    bool m_completed;
161};
162
163struct EmptyType : public RefCounted<EmptyType> {
164    static PassRefPtr<EmptyType> create(EmptyType*)
165    {
166        return 0;
167    }
168};
169
170struct EmptyObserverType {
171    bool waitForOperationToComplete()
172    {
173        return false;
174    }
175};
176
177typedef SyncCallbackHelper<EntryCallback, AsyncFileSystem, Entry, EntrySync> EntrySyncCallbackHelper;
178typedef SyncCallbackHelper<EntriesCallback, AsyncFileSystem, EntryArray, EntryArraySync> EntriesSyncCallbackHelper;
179typedef SyncCallbackHelper<MetadataCallback, AsyncFileSystem, Metadata, Metadata> MetadataSyncCallbackHelper;
180typedef SyncCallbackHelper<VoidCallback, AsyncFileSystem, EmptyType, EmptyType> VoidSyncCallbackHelper;
181typedef SyncCallbackHelper<FileSystemCallback, EmptyObserverType, DOMFileSystem, DOMFileSystemSync> FileSystemSyncCallbackHelper;
182
183} // namespace WebCore
184
185#endif // ENABLE(FILE_SYSTEM)
186
187#endif // SyncCallbackHelper_h
188