1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_dom_indexeddatabase_h__
8 #define mozilla_dom_indexeddatabase_h__
9 
10 #include "DatabaseFileInfoFwd.h"
11 #include "js/StructuredClone.h"
12 #include "mozilla/InitializedOnce.h"
13 #include "mozilla/Variant.h"
14 #include "nsCOMPtr.h"
15 #include "nsTArray.h"
16 #include "SafeRefPtr.h"
17 
18 namespace mozilla {
19 namespace dom {
20 
21 class Blob;
22 class IDBDatabase;
23 class IDBMutableFile;
24 
25 namespace indexedDB {
26 
27 struct StructuredCloneFileBase {
28   enum FileType {
29     eBlob,
30     eMutableFile,
31     eStructuredClone,
32     eWasmBytecode,
33     eWasmCompiled,
34     eEndGuard
35   };
36 
TypeStructuredCloneFileBase37   FileType Type() const { return mType; }
38 
39  protected:
StructuredCloneFileBaseStructuredCloneFileBase40   explicit StructuredCloneFileBase(FileType aType) : mType{aType} {}
41 
42   FileType mType;
43 };
44 
45 struct StructuredCloneFileChild : StructuredCloneFileBase {
46   StructuredCloneFileChild(const StructuredCloneFileChild&) = delete;
47   StructuredCloneFileChild& operator=(const StructuredCloneFileChild&) = delete;
48 #ifdef NS_BUILD_REFCNT_LOGGING
49   // In IndexedDatabaseInlines.h
50   StructuredCloneFileChild(StructuredCloneFileChild&&);
51 #else
52   StructuredCloneFileChild(StructuredCloneFileChild&&) = default;
53 #endif
54   StructuredCloneFileChild& operator=(StructuredCloneFileChild&&) = delete;
55 
56   // In IndexedDatabaseInlines.h
57   ~StructuredCloneFileChild();
58 
59   // In IndexedDatabaseInlines.h
60   explicit StructuredCloneFileChild(FileType aType);
61 
62   // In IndexedDatabaseInlines.h
63   StructuredCloneFileChild(FileType aType, RefPtr<Blob> aBlob);
64 
65   // In IndexedDatabaseInlines.h
66   explicit StructuredCloneFileChild(RefPtr<IDBMutableFile> aMutableFile);
67 
BlobStructuredCloneFileChild68   const dom::Blob& Blob() const { return *mContents->as<RefPtr<dom::Blob>>(); }
69 
70   // XXX This is currently used for a number of reasons. Bug 1620560 will remove
71   // the need for one of them, but the uses of do_GetWeakReference in
72   // IDBDatabase::GetOrCreateFileActorForBlob and WrapAsJSObject in
73   // CopyingStructuredCloneReadCallback are probably harder to change.
MutableBlobStructuredCloneFileChild74   dom::Blob& MutableBlob() const { return *mContents->as<RefPtr<dom::Blob>>(); }
75 
76   // In IndexedDatabaseInlines.h
77   RefPtr<dom::Blob> BlobPtr() const;
78 
HasBlobStructuredCloneFileChild79   bool HasBlob() const { return mContents->is<RefPtr<dom::Blob>>(); }
80 
MutableFileStructuredCloneFileChild81   const IDBMutableFile& MutableFile() const {
82     return *mContents->as<RefPtr<IDBMutableFile>>();
83   }
84 
MutableMutableFileStructuredCloneFileChild85   IDBMutableFile& MutableMutableFile() const {
86     return *mContents->as<RefPtr<IDBMutableFile>>();
87   }
88 
HasMutableFileStructuredCloneFileChild89   bool HasMutableFile() const {
90     return mContents->is<RefPtr<IDBMutableFile>>();
91   }
92 
93  private:
94   InitializedOnce<
95       const Variant<Nothing, RefPtr<dom::Blob>, RefPtr<IDBMutableFile>>>
96       mContents;
97 };
98 
99 struct StructuredCloneFileParent : StructuredCloneFileBase {
100   StructuredCloneFileParent(const StructuredCloneFileParent&) = delete;
101   StructuredCloneFileParent& operator=(const StructuredCloneFileParent&) =
102       delete;
103 #ifdef NS_BUILD_REFCNT_LOGGING
104   // In IndexedDatabaseInlines.h
105   StructuredCloneFileParent(StructuredCloneFileParent&&);
106 #else
107   StructuredCloneFileParent(StructuredCloneFileParent&&) = default;
108 #endif
109   StructuredCloneFileParent& operator=(StructuredCloneFileParent&&) = delete;
110 
111   // In IndexedDatabaseInlines.h
112   StructuredCloneFileParent(FileType aType,
113                             SafeRefPtr<DatabaseFileInfo> aFileInfo);
114 
115   // In IndexedDatabaseInlines.h
116   ~StructuredCloneFileParent();
117 
118   // XXX This is used for a schema upgrade hack in UpgradeSchemaFrom19_0To20_0.
119   // When this is eventually removed, this function can be removed, and mType
120   // can be declared const in the base class.
MutateTypeStructuredCloneFileParent121   void MutateType(FileType aNewType) { mType = aNewType; }
122 
FileInfoStructuredCloneFileParent123   const DatabaseFileInfo& FileInfo() const { return ***mContents; }
124 
125   // In IndexedDatabaseInlines.h
126   SafeRefPtr<DatabaseFileInfo> FileInfoPtr() const;
127 
128  private:
129   InitializedOnce<const Maybe<SafeRefPtr<DatabaseFileInfo>>> mContents;
130 };
131 
132 struct StructuredCloneReadInfoBase {
133   // In IndexedDatabaseInlines.h
StructuredCloneReadInfoBaseStructuredCloneReadInfoBase134   explicit StructuredCloneReadInfoBase(JSStructuredCloneData&& aData)
135       : mData{std::move(aData)} {}
136 
DataStructuredCloneReadInfoBase137   const JSStructuredCloneData& Data() const { return mData; }
ReleaseDataStructuredCloneReadInfoBase138   JSStructuredCloneData ReleaseData() { return std::move(mData); }
139 
140  private:
141   JSStructuredCloneData mData;
142 };
143 
144 template <typename StructuredCloneFileT>
145 struct StructuredCloneReadInfo : StructuredCloneReadInfoBase {
146   using StructuredCloneFile = StructuredCloneFileT;
147 
148   // In IndexedDatabaseInlines.h
149   explicit StructuredCloneReadInfo(JS::StructuredCloneScope aScope);
150 
151   // In IndexedDatabaseInlines.h
152   StructuredCloneReadInfo();
153 
154   // In IndexedDatabaseInlines.h
155   StructuredCloneReadInfo(JSStructuredCloneData&& aData,
156                           nsTArray<StructuredCloneFile> aFiles);
157 
158 #ifdef NS_BUILD_REFCNT_LOGGING
159   // In IndexedDatabaseInlines.h
160   ~StructuredCloneReadInfo();
161 
162   // In IndexedDatabaseInlines.h
163   //
164   // This custom implementation of the move ctor is only necessary because of
165   // MOZ_COUNT_CTOR. It is less efficient as the compiler-generated move ctor,
166   // since it unnecessarily clears elements on the source.
167   StructuredCloneReadInfo(StructuredCloneReadInfo&& aOther) noexcept;
168 #else
169   StructuredCloneReadInfo(StructuredCloneReadInfo&& aOther) = default;
170 #endif
171   StructuredCloneReadInfo& operator=(StructuredCloneReadInfo&& aOther) =
172       default;
173 
174   StructuredCloneReadInfo(const StructuredCloneReadInfo& aOther) = delete;
175   StructuredCloneReadInfo& operator=(const StructuredCloneReadInfo& aOther) =
176       delete;
177 
178   // In IndexedDatabaseInlines.h
179   size_t Size() const;
180 
181   // XXX This is only needed for a schema upgrade (UpgradeSchemaFrom19_0To20_0).
182   // If support for older schemas is dropped, we can probably remove this method
183   // and make mFiles InitializedOnce.
MutableFileStructuredCloneReadInfo184   StructuredCloneFile& MutableFile(const size_t aIndex) {
185     return mFiles[aIndex];
186   }
FilesStructuredCloneReadInfo187   const nsTArray<StructuredCloneFile>& Files() const { return mFiles; }
188 
ReleaseFilesStructuredCloneReadInfo189   nsTArray<StructuredCloneFile> ReleaseFiles() { return std::move(mFiles); }
190 
HasFilesStructuredCloneReadInfo191   bool HasFiles() const { return !mFiles.IsEmpty(); }
192 
193  private:
194   nsTArray<StructuredCloneFile> mFiles;
195 };
196 
197 struct StructuredCloneReadInfoChild
198     : StructuredCloneReadInfo<StructuredCloneFileChild> {
199   inline StructuredCloneReadInfoChild(JSStructuredCloneData&& aData,
200                                       nsTArray<StructuredCloneFileChild> aFiles,
201                                       IDBDatabase* aDatabase);
202 
DatabaseStructuredCloneReadInfoChild203   IDBDatabase* Database() const { return mDatabase; }
204 
205  private:
206   IDBDatabase* mDatabase;
207 };
208 
209 // This is only defined in the header file to satisfy the clang-plugin static
210 // analysis, it could be placed in ActorsParent.cpp otherwise.
211 struct StructuredCloneReadInfoParent
212     : StructuredCloneReadInfo<StructuredCloneFileParent> {
StructuredCloneReadInfoParentStructuredCloneReadInfoParent213   StructuredCloneReadInfoParent(JSStructuredCloneData&& aData,
214                                 nsTArray<StructuredCloneFileParent> aFiles,
215                                 bool aHasPreprocessInfo)
216       : StructuredCloneReadInfo{std::move(aData), std::move(aFiles)},
217         mHasPreprocessInfo{aHasPreprocessInfo} {}
218 
HasPreprocessInfoStructuredCloneReadInfoParent219   bool HasPreprocessInfo() const { return mHasPreprocessInfo; }
220 
221  private:
222   bool mHasPreprocessInfo;
223 };
224 
225 template <typename StructuredCloneReadInfo>
226 JSObject* CommonStructuredCloneReadCallback(
227     JSContext* aCx, JSStructuredCloneReader* aReader,
228     const JS::CloneDataPolicy& aCloneDataPolicy, uint32_t aTag, uint32_t aData,
229     StructuredCloneReadInfo* aCloneReadInfo, IDBDatabase* aDatabase);
230 
231 template <typename StructuredCloneReadInfoType>
232 JSObject* StructuredCloneReadCallback(
233     JSContext* aCx, JSStructuredCloneReader* aReader,
234     const JS::CloneDataPolicy& aCloneDataPolicy, uint32_t aTag, uint32_t aData,
235     void* aClosure);
236 
237 }  // namespace indexedDB
238 }  // namespace dom
239 }  // namespace mozilla
240 
241 MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(
242     mozilla::dom::indexedDB::StructuredCloneReadInfo<
243         mozilla::dom::indexedDB::StructuredCloneFileChild>);
244 MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(
245     mozilla::dom::indexedDB::StructuredCloneReadInfo<
246         mozilla::dom::indexedDB::StructuredCloneFileParent>);
247 MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(
248     mozilla::dom::indexedDB::StructuredCloneReadInfoChild);
249 MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(
250     mozilla::dom::indexedDB::StructuredCloneReadInfoParent);
251 
252 #endif  // mozilla_dom_indexeddatabase_h__
253