Make IDBCursor::m_request a WeakPtr
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / IDBRequest.h
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 "IDBResourceIdentifier.h"
35 #include "IndexedDB.h"
36 #include <JavaScriptCore/Strong.h>
37 #include <wtf/Function.h>
38 #include <wtf/Scope.h>
39 #include <wtf/WeakPtr.h>
40
41 namespace WebCore {
42
43 class DOMException;
44 class Event;
45 class IDBCursor;
46 class IDBDatabase;
47 class IDBIndex;
48 class IDBKeyData;
49 class IDBObjectStore;
50 class IDBResultData;
51 class IDBTransaction;
52 class IDBValue;
53 class ThreadSafeDataBuffer;
54
55 namespace IDBClient {
56 class IDBConnectionProxy;
57 class IDBConnectionToServer;
58 }
59
60 class IDBRequest : public EventTargetWithInlineData, public IDBActiveDOMObject, public RefCounted<IDBRequest>, public CanMakeWeakPtr<IDBRequest> {
61 public:
62     static Ref<IDBRequest> create(ScriptExecutionContext&, IDBObjectStore&, IDBTransaction&);
63     static Ref<IDBRequest> create(ScriptExecutionContext&, IDBCursor&, IDBTransaction&);
64     static Ref<IDBRequest> create(ScriptExecutionContext&, IDBIndex&, IDBTransaction&);
65     static Ref<IDBRequest> createObjectStoreGet(ScriptExecutionContext&, IDBObjectStore&, IndexedDB::ObjectStoreRecordType, IDBTransaction&);
66     static Ref<IDBRequest> createIndexGet(ScriptExecutionContext&, IDBIndex&, IndexedDB::IndexRecordType, IDBTransaction&);
67
68     const IDBResourceIdentifier& resourceIdentifier() const { return m_resourceIdentifier; }
69
70     virtual ~IDBRequest();
71
72     // FIXME: The following use of JSC::Strong is incorrect and can lead to storage leaks
73     // due to reference cycles; we should use JSValueInWrappedObject instead.
74     using Result = Variant<RefPtr<IDBCursor>, RefPtr<IDBDatabase>, JSC::Strong<JSC::Unknown>>;
75     ExceptionOr<std::optional<Result>> result() const;
76
77     using Source = Variant<RefPtr<IDBObjectStore>, RefPtr<IDBIndex>, RefPtr<IDBCursor>>;
78     const std::optional<Source>& source() const { return m_source; }
79
80     ExceptionOr<DOMException*> error() const;
81
82     RefPtr<IDBTransaction> transaction() const;
83     
84     enum class ReadyState { Pending, Done };
85     ReadyState readyState() const { return m_readyState; }
86
87     bool isDone() const { return m_readyState == ReadyState::Done; }
88
89     uint64_t sourceObjectStoreIdentifier() const;
90     uint64_t sourceIndexIdentifier() const;
91     IndexedDB::ObjectStoreRecordType requestedObjectStoreRecordType() const;
92     IndexedDB::IndexRecordType requestedIndexRecordType() const;
93
94     ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
95
96     using RefCounted::ref;
97     using RefCounted::deref;
98
99     void completeRequestAndDispatchEvent(const IDBResultData&);
100
101     void setResult(const IDBKeyData&);
102     void setResult(const Vector<IDBKeyData>&);
103     void setResult(const Vector<IDBValue>&);
104     void setResult(uint64_t);
105     void setResultToStructuredClone(const IDBValue&);
106     void setResultToUndefined();
107
108     void willIterateCursor(IDBCursor&);
109     void didOpenOrIterateCursor(const IDBResultData&);
110
111     const IDBCursor* pendingCursor() const { return m_pendingCursor.get(); }
112
113     void setSource(IDBCursor&);
114     void setVersionChangeTransaction(IDBTransaction&);
115
116     IndexedDB::RequestType requestType() const { return m_requestType; }
117
118     bool hasPendingActivity() const final;
119
120 protected:
121     IDBRequest(ScriptExecutionContext&, IDBClient::IDBConnectionProxy&);
122
123     void enqueueEvent(Ref<Event>&&);
124     void dispatchEvent(Event&) override;
125
126     void setResult(Ref<IDBDatabase>&&);
127
128     IDBClient::IDBConnectionProxy& connectionProxy() { return m_connectionProxy.get(); }
129
130     // FIXME: Protected data members aren't great for maintainability.
131     // Consider adding protected helper functions and making these private.
132     ReadyState m_readyState { ReadyState::Pending };
133     RefPtr<IDBTransaction> m_transaction;
134     bool m_shouldExposeTransactionToDOM { true };
135     RefPtr<DOMException> m_domError;
136     IndexedDB::RequestType m_requestType { IndexedDB::RequestType::Other };
137     bool m_contextStopped { false };
138     Event* m_openDatabaseSuccessEvent { nullptr };
139
140 private:
141     IDBRequest(ScriptExecutionContext&, IDBObjectStore&, IDBTransaction&);
142     IDBRequest(ScriptExecutionContext&, IDBCursor&, IDBTransaction&);
143     IDBRequest(ScriptExecutionContext&, IDBIndex&, IDBTransaction&);
144     IDBRequest(ScriptExecutionContext&, IDBObjectStore&, IndexedDB::ObjectStoreRecordType, IDBTransaction&);
145     IDBRequest(ScriptExecutionContext&, IDBIndex&, IndexedDB::IndexRecordType, IDBTransaction&);
146
147     EventTargetInterface eventTargetInterface() const override;
148
149     const char* activeDOMObjectName() const final;
150     bool canSuspendForDocumentSuspension() const final;
151     void stop() final;
152     virtual void cancelForStop();
153
154     void refEventTarget() final { RefCounted::ref(); }
155     void derefEventTarget() final { RefCounted::deref(); }
156     void uncaughtExceptionInEventHandler() final;
157
158     virtual bool isOpenDBRequest() const { return false; }
159
160     void onError();
161     void onSuccess();
162
163     IDBCursor* resultCursor();
164
165     IDBError m_idbError;
166     IDBResourceIdentifier m_resourceIdentifier;
167
168     std::optional<Result> m_result;
169     std::optional<Source> m_source;
170
171     bool m_hasPendingActivity { true };
172     IndexedDB::ObjectStoreRecordType m_requestedObjectStoreRecordType { IndexedDB::ObjectStoreRecordType::ValueOnly };
173     IndexedDB::IndexRecordType m_requestedIndexRecordType { IndexedDB::IndexRecordType::Key };
174
175     RefPtr<IDBCursor> m_pendingCursor;
176
177     Ref<IDBClient::IDBConnectionProxy> m_connectionProxy;
178 };
179
180 } // namespace WebCore
181
182 #endif // ENABLE(INDEXED_DATABASE)