1/*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * Copyright (C) 2013 Samsung Electronics. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#ifndef SyncCallbackHelper_h
33#define SyncCallbackHelper_h
34
35#include "bindings/v8/ExceptionState.h"
36#include "core/fileapi/FileError.h"
37#include "core/html/VoidCallback.h"
38#include "modules/filesystem/DirectoryEntry.h"
39#include "modules/filesystem/DirectoryReaderSync.h"
40#include "modules/filesystem/EntriesCallback.h"
41#include "modules/filesystem/EntryCallback.h"
42#include "modules/filesystem/EntrySync.h"
43#include "modules/filesystem/ErrorCallback.h"
44#include "modules/filesystem/FileEntry.h"
45#include "modules/filesystem/FileSystemCallback.h"
46#include "modules/filesystem/MetadataCallback.h"
47#include "wtf/PassRefPtr.h"
48#include "wtf/RefCounted.h"
49
50namespace WebCore {
51
52template <typename ResultType, typename CallbackArg>
53struct HelperResultType {
54    typedef PassRefPtr<ResultType> ReturnType;
55    typedef RefPtr<ResultType> StorageType;
56
57    static ReturnType createFromCallbackArg(CallbackArg argument)
58    {
59        return ResultType::create(argument);
60    }
61};
62
63template <>
64struct HelperResultType<EntrySyncVector, const EntryVector&> {
65    typedef EntrySyncVector ReturnType;
66    typedef EntrySyncVector StorageType;
67
68    static EntrySyncVector createFromCallbackArg(const EntryVector& entries)
69    {
70        EntrySyncVector result;
71        size_t entryCount = entries.size();
72        result.reserveInitialCapacity(entryCount);
73        for (size_t i = 0; i < entryCount; ++i)
74            result.uncheckedAppend(EntrySync::create(entries[i].get()));
75        return result;
76    }
77};
78
79// A helper template for FileSystemSync implementation.
80template <typename SuccessCallback, typename ObserverType, typename CallbackArg, typename ResultType>
81class SyncCallbackHelper {
82    WTF_MAKE_NONCOPYABLE(SyncCallbackHelper);
83public:
84    typedef SyncCallbackHelper<SuccessCallback, ObserverType, CallbackArg, ResultType> HelperType;
85    typedef HelperResultType<ResultType, CallbackArg> ResultTypeTrait;
86    typedef typename ResultTypeTrait::StorageType ResultStorageType;
87    typedef typename ResultTypeTrait::ReturnType ResultReturnType;
88
89    SyncCallbackHelper(ObserverType* observer = 0)
90        : m_observer(observer)
91        , m_successCallback(SuccessCallbackImpl::create(this))
92        , m_errorCallback(ErrorCallbackImpl::create(this))
93        , m_errorCode(FileError::OK)
94        , m_completed(false)
95    {
96    }
97
98    ResultReturnType getResult(ExceptionState& es)
99    {
100        if (m_observer) {
101            while (!m_completed) {
102                if (!m_observer->waitForOperationToComplete()) {
103                    m_errorCode = FileError::ABORT_ERR;
104                    break;
105                }
106            }
107        }
108        if (m_errorCode)
109            FileError::throwDOMException(es, m_errorCode);
110
111        return m_result;
112    }
113
114    PassRefPtr<SuccessCallback> successCallback() { return m_successCallback; }
115    PassRefPtr<ErrorCallback> errorCallback() { return m_errorCallback; }
116
117private:
118    class SuccessCallbackImpl : public SuccessCallback {
119    public:
120        static PassRefPtr<SuccessCallbackImpl> create(HelperType* helper)
121        {
122            return adoptRef(new SuccessCallbackImpl(helper));
123        }
124
125        virtual bool handleEvent()
126        {
127            m_helper->setError(FileError::OK);
128            return true;
129        }
130
131        virtual bool handleEvent(CallbackArg arg)
132        {
133            m_helper->setResult(arg);
134            return true;
135        }
136
137    private:
138        explicit SuccessCallbackImpl(HelperType* helper)
139            : m_helper(helper)
140        {
141        }
142        HelperType* m_helper;
143    };
144
145    class ErrorCallbackImpl : public ErrorCallback {
146    public:
147        static PassRefPtr<ErrorCallbackImpl> create(HelperType* helper)
148        {
149            return adoptRef(new ErrorCallbackImpl(helper));
150        }
151
152        virtual bool handleEvent(FileError* error)
153        {
154            ASSERT(error);
155            m_helper->setError(error->code());
156            return true;
157        }
158
159    private:
160        explicit ErrorCallbackImpl(HelperType* helper)
161            : m_helper(helper)
162        {
163        }
164        HelperType* m_helper;
165    };
166
167    friend class SuccessCallbackImpl;
168    friend class ErrorCallbackImpl;
169
170    void setError(FileError::ErrorCode code)
171    {
172        m_errorCode = code;
173        m_completed = true;
174    }
175
176    void setResult(CallbackArg result)
177    {
178        m_result = ResultTypeTrait::createFromCallbackArg(result);
179        m_completed = true;
180    }
181
182    ObserverType* m_observer;
183    RefPtr<SuccessCallbackImpl> m_successCallback;
184    RefPtr<ErrorCallbackImpl> m_errorCallback;
185    ResultStorageType m_result;
186    FileError::ErrorCode m_errorCode;
187    bool m_completed;
188};
189
190struct EmptyType : public RefCounted<EmptyType> {
191    static PassRefPtr<EmptyType> create(EmptyType*)
192    {
193        return 0;
194    }
195};
196
197struct EmptyObserverType {
198    bool waitForOperationToComplete()
199    {
200        return false;
201    }
202};
203
204typedef SyncCallbackHelper<EntryCallback, AsyncFileSystem, Entry*, EntrySync> EntrySyncCallbackHelper;
205typedef SyncCallbackHelper<EntriesCallback, AsyncFileSystem, const EntryVector&, EntrySyncVector> EntriesSyncCallbackHelper;
206typedef SyncCallbackHelper<MetadataCallback, AsyncFileSystem, Metadata*, Metadata> MetadataSyncCallbackHelper;
207typedef SyncCallbackHelper<VoidCallback, AsyncFileSystem, EmptyType*, EmptyType> VoidSyncCallbackHelper;
208typedef SyncCallbackHelper<FileSystemCallback, EmptyObserverType, DOMFileSystem*, DOMFileSystemSync> FileSystemSyncCallbackHelper;
209
210} // namespace WebCore
211
212#endif // SyncCallbackHelper_h
213