1/*
2 * Copyright (C) 2015, 2016 Apple 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
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#if ENABLE(INDEXED_DATABASE)
29
30#include "EventTarget.h"
31#include "ExceptionOr.h"
32#include "IDBActiveDOMObject.h"
33#include "IDBError.h"
34#include "IDBGetAllResult.h"
35#include "IDBGetResult.h"
36#include "IDBKeyData.h"
37#include "IDBResourceIdentifier.h"
38#include "IDBValue.h"
39#include "IndexedDB.h"
40#include "JSValueInWrappedObject.h"
41#include <JavaScriptCore/Strong.h>
42#include <wtf/Function.h>
43#include <wtf/Scope.h>
44#include <wtf/WeakPtr.h>
45
46namespace WebCore {
47
48class DOMException;
49class Event;
50class IDBCursor;
51class IDBDatabase;
52class IDBIndex;
53class IDBObjectStore;
54class IDBResultData;
55class IDBTransaction;
56class ThreadSafeDataBuffer;
57
58namespace IDBClient {
59class IDBConnectionProxy;
60class IDBConnectionToServer;
61}
62
63class IDBRequest : public EventTargetWithInlineData, public IDBActiveDOMObject, public RefCounted<IDBRequest>, public CanMakeWeakPtr<IDBRequest> {
64 WTF_MAKE_ISO_ALLOCATED(IDBRequest);
65public:
66 enum class NullResultType {
67 Empty,
68 Undefined
69 };
70
71 static Ref<IDBRequest> create(ScriptExecutionContext&, IDBObjectStore&, IDBTransaction&);
72 static Ref<IDBRequest> create(ScriptExecutionContext&, IDBCursor&, IDBTransaction&);
73 static Ref<IDBRequest> create(ScriptExecutionContext&, IDBIndex&, IDBTransaction&);
74 static Ref<IDBRequest> createObjectStoreGet(ScriptExecutionContext&, IDBObjectStore&, IndexedDB::ObjectStoreRecordType, IDBTransaction&);
75 static Ref<IDBRequest> createIndexGet(ScriptExecutionContext&, IDBIndex&, IndexedDB::IndexRecordType, IDBTransaction&);
76
77 const IDBResourceIdentifier& resourceIdentifier() const { return m_resourceIdentifier; }
78
79 virtual ~IDBRequest();
80
81 using Result = Variant<RefPtr<IDBCursor>, RefPtr<IDBDatabase>, IDBKeyData, Vector<IDBKeyData>, IDBGetResult, IDBGetAllResult, uint64_t, NullResultType>;
82 ExceptionOr<Result> result() const;
83 JSValueInWrappedObject& resultWrapper() { return m_resultWrapper; }
84 JSValueInWrappedObject& cursorWrapper() { return m_cursorWrapper; }
85
86 using Source = Variant<RefPtr<IDBObjectStore>, RefPtr<IDBIndex>, RefPtr<IDBCursor>>;
87 const Optional<Source>& source() const { return m_source; }
88
89 ExceptionOr<DOMException*> error() const;
90
91 RefPtr<IDBTransaction> transaction() const;
92
93 enum class ReadyState { Pending, Done };
94 ReadyState readyState() const { return m_readyState; }
95
96 bool isDone() const { return m_readyState == ReadyState::Done; }
97
98 uint64_t sourceObjectStoreIdentifier() const;
99 uint64_t sourceIndexIdentifier() const;
100 IndexedDB::ObjectStoreRecordType requestedObjectStoreRecordType() const;
101 IndexedDB::IndexRecordType requestedIndexRecordType() const;
102
103 ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
104
105 using RefCounted::ref;
106 using RefCounted::deref;
107
108 void completeRequestAndDispatchEvent(const IDBResultData&);
109
110 void setResult(const IDBKeyData&);
111 void setResult(const Vector<IDBKeyData>&);
112 void setResultToStructuredClone(const IDBGetResult&);
113 void setResult(const IDBGetAllResult&);
114 void setResult(uint64_t);
115 void setResultToUndefined();
116
117 void willIterateCursor(IDBCursor&);
118 void didOpenOrIterateCursor(const IDBResultData&);
119
120 const IDBCursor* pendingCursor() const { return m_pendingCursor.get(); }
121
122 void setSource(IDBCursor&);
123 void setVersionChangeTransaction(IDBTransaction&);
124
125 IndexedDB::RequestType requestType() const { return m_requestType; }
126
127 bool hasPendingActivity() const final;
128
129protected:
130 IDBRequest(ScriptExecutionContext&, IDBClient::IDBConnectionProxy&);
131
132 void enqueueEvent(Ref<Event>&&);
133 void dispatchEvent(Event&) override;
134
135 void setResult(Ref<IDBDatabase>&&);
136
137 IDBClient::IDBConnectionProxy& connectionProxy() { return m_connectionProxy.get(); }
138
139 // FIXME: Protected data members aren't great for maintainability.
140 // Consider adding protected helper functions and making these private.
141 ReadyState m_readyState { ReadyState::Pending };
142 RefPtr<IDBTransaction> m_transaction;
143 bool m_shouldExposeTransactionToDOM { true };
144 RefPtr<DOMException> m_domError;
145 IndexedDB::RequestType m_requestType { IndexedDB::RequestType::Other };
146 bool m_contextStopped { false };
147 Event* m_openDatabaseSuccessEvent { nullptr };
148
149private:
150 IDBRequest(ScriptExecutionContext&, IDBObjectStore&, IDBTransaction&);
151 IDBRequest(ScriptExecutionContext&, IDBCursor&, IDBTransaction&);
152 IDBRequest(ScriptExecutionContext&, IDBIndex&, IDBTransaction&);
153 IDBRequest(ScriptExecutionContext&, IDBObjectStore&, IndexedDB::ObjectStoreRecordType, IDBTransaction&);
154 IDBRequest(ScriptExecutionContext&, IDBIndex&, IndexedDB::IndexRecordType, IDBTransaction&);
155
156 EventTargetInterface eventTargetInterface() const override;
157
158 const char* activeDOMObjectName() const final;
159 bool canSuspendForDocumentSuspension() const final;
160 void stop() final;
161 virtual void cancelForStop();
162
163 void refEventTarget() final { RefCounted::ref(); }
164 void derefEventTarget() final { RefCounted::deref(); }
165 void uncaughtExceptionInEventHandler() final;
166
167 virtual bool isOpenDBRequest() const { return false; }
168
169 void onError();
170 void onSuccess();
171
172 void clearWrappers();
173
174 IDBCursor* resultCursor();
175
176 IDBError m_idbError;
177 IDBResourceIdentifier m_resourceIdentifier;
178
179 JSValueInWrappedObject m_resultWrapper;
180 JSValueInWrappedObject m_cursorWrapper;
181 Result m_result;
182 Optional<Source> m_source;
183
184 bool m_hasPendingActivity { true };
185 IndexedDB::ObjectStoreRecordType m_requestedObjectStoreRecordType { IndexedDB::ObjectStoreRecordType::ValueOnly };
186 IndexedDB::IndexRecordType m_requestedIndexRecordType { IndexedDB::IndexRecordType::Key };
187
188 RefPtr<IDBCursor> m_pendingCursor;
189
190 Ref<IDBClient::IDBConnectionProxy> m_connectionProxy;
191
192 bool m_dispatchingEvent { false };
193 bool m_hasUncaughtException { false };
194};
195
196} // namespace WebCore
197
198#endif // ENABLE(INDEXED_DATABASE)
199