/src/mozilla-central/dom/indexedDB/FileInfo.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | #include "FileInfo.h" |
8 | | |
9 | | #include "FileManager.h" |
10 | | #include "IndexedDatabaseManager.h" |
11 | | #include "mozilla/Assertions.h" |
12 | | #include "mozilla/Attributes.h" |
13 | | #include "mozilla/Mutex.h" |
14 | | #include "mozilla/dom/quota/QuotaManager.h" |
15 | | #include "nsError.h" |
16 | | #include "nsThreadUtils.h" |
17 | | |
18 | | namespace mozilla { |
19 | | namespace dom { |
20 | | namespace indexedDB { |
21 | | |
22 | | using namespace mozilla::dom::quota; |
23 | | |
24 | | namespace { |
25 | | |
26 | | template <typename IdType> |
27 | | class FileInfoImpl final |
28 | | : public FileInfo |
29 | | { |
30 | | IdType mFileId; |
31 | | |
32 | | public: |
33 | | FileInfoImpl(FileManager* aFileManager, IdType aFileId) |
34 | | : FileInfo(aFileManager) |
35 | | , mFileId(aFileId) |
36 | 0 | { |
37 | 0 | MOZ_ASSERT(aFileManager); |
38 | 0 | MOZ_ASSERT(aFileId > 0); |
39 | 0 | } Unexecuted instantiation: Unified_cpp_dom_indexedDB0.cpp:mozilla::dom::indexedDB::(anonymous namespace)::FileInfoImpl<short>::FileInfoImpl(mozilla::dom::indexedDB::FileManager*, short) Unexecuted instantiation: Unified_cpp_dom_indexedDB0.cpp:mozilla::dom::indexedDB::(anonymous namespace)::FileInfoImpl<int>::FileInfoImpl(mozilla::dom::indexedDB::FileManager*, int) Unexecuted instantiation: Unified_cpp_dom_indexedDB0.cpp:mozilla::dom::indexedDB::(anonymous namespace)::FileInfoImpl<long>::FileInfoImpl(mozilla::dom::indexedDB::FileManager*, long) |
40 | | |
41 | | private: |
42 | | ~FileInfoImpl() |
43 | | { } |
44 | | |
45 | | virtual int64_t |
46 | | Id() const override |
47 | 0 | { |
48 | 0 | return int64_t(mFileId); |
49 | 0 | } Unexecuted instantiation: Unified_cpp_dom_indexedDB0.cpp:mozilla::dom::indexedDB::(anonymous namespace)::FileInfoImpl<short>::Id() const Unexecuted instantiation: Unified_cpp_dom_indexedDB0.cpp:mozilla::dom::indexedDB::(anonymous namespace)::FileInfoImpl<int>::Id() const Unexecuted instantiation: Unified_cpp_dom_indexedDB0.cpp:mozilla::dom::indexedDB::(anonymous namespace)::FileInfoImpl<long>::Id() const |
50 | | }; |
51 | | |
52 | | class CleanupFileRunnable final |
53 | | : public Runnable |
54 | | { |
55 | | RefPtr<FileManager> mFileManager; |
56 | | int64_t mFileId; |
57 | | |
58 | | public: |
59 | | static void |
60 | | DoCleanup(FileManager* aFileManager, int64_t aFileId); |
61 | | |
62 | | CleanupFileRunnable(FileManager* aFileManager, int64_t aFileId) |
63 | | : Runnable("dom::indexedDB::CleanupFileRunnable") |
64 | | , mFileManager(aFileManager) |
65 | | , mFileId(aFileId) |
66 | 0 | { |
67 | 0 | MOZ_ASSERT(aFileManager); |
68 | 0 | MOZ_ASSERT(aFileId > 0); |
69 | 0 | } |
70 | | |
71 | | NS_INLINE_DECL_REFCOUNTING_INHERITED(CleanupFileRunnable, Runnable); |
72 | | |
73 | | private: |
74 | | ~CleanupFileRunnable() |
75 | 0 | { } |
76 | | |
77 | | NS_DECL_NSIRUNNABLE |
78 | | }; |
79 | | |
80 | | } // namespace |
81 | | |
82 | | FileInfo::FileInfo(FileManager* aFileManager) |
83 | | : mFileManager(aFileManager) |
84 | 0 | { |
85 | 0 | MOZ_ASSERT(aFileManager); |
86 | 0 | } |
87 | | |
88 | | FileInfo::~FileInfo() |
89 | 0 | { |
90 | 0 | } |
91 | | |
92 | | // static |
93 | | FileInfo* |
94 | | FileInfo::Create(FileManager* aFileManager, int64_t aId) |
95 | 0 | { |
96 | 0 | MOZ_ASSERT(aFileManager); |
97 | 0 | MOZ_ASSERT(aId > 0); |
98 | 0 |
|
99 | 0 | if (aId <= INT16_MAX) { |
100 | 0 | return new FileInfoImpl<int16_t>(aFileManager, aId); |
101 | 0 | } |
102 | 0 | |
103 | 0 | if (aId <= INT32_MAX) { |
104 | 0 | return new FileInfoImpl<int32_t>(aFileManager, aId); |
105 | 0 | } |
106 | 0 | |
107 | 0 | return new FileInfoImpl<int64_t>(aFileManager, aId); |
108 | 0 | } |
109 | | |
110 | | void |
111 | | FileInfo::GetReferences(int32_t* aRefCnt, |
112 | | int32_t* aDBRefCnt, |
113 | | int32_t* aSliceRefCnt) |
114 | 0 | { |
115 | 0 | MOZ_ASSERT(!IndexedDatabaseManager::IsClosed()); |
116 | 0 |
|
117 | 0 | MutexAutoLock lock(IndexedDatabaseManager::FileMutex()); |
118 | 0 |
|
119 | 0 | if (aRefCnt) { |
120 | 0 | *aRefCnt = mRefCnt; |
121 | 0 | } |
122 | 0 |
|
123 | 0 | if (aDBRefCnt) { |
124 | 0 | *aDBRefCnt = mDBRefCnt; |
125 | 0 | } |
126 | 0 |
|
127 | 0 | if (aSliceRefCnt) { |
128 | 0 | *aSliceRefCnt = mSliceRefCnt; |
129 | 0 | } |
130 | 0 | } |
131 | | |
132 | | void |
133 | | FileInfo::UpdateReferences(ThreadSafeAutoRefCnt& aRefCount, |
134 | | int32_t aDelta, |
135 | | CustomCleanupCallback* aCustomCleanupCallback) |
136 | 0 | { |
137 | 0 | // XXX This can go away once DOM objects no longer hold FileInfo objects... |
138 | 0 | // Looking at you, BlobImplBase... |
139 | 0 | // BlobImplBase is being addressed in bug 1068975. |
140 | 0 | if (IndexedDatabaseManager::IsClosed()) { |
141 | 0 | MOZ_ASSERT(&aRefCount == &mRefCnt); |
142 | 0 | MOZ_ASSERT(aDelta == 1 || aDelta == -1); |
143 | 0 |
|
144 | 0 | if (aDelta > 0) { |
145 | 0 | ++aRefCount; |
146 | 0 | } else { |
147 | 0 | nsrefcnt count = --aRefCount; |
148 | 0 | if (!count) { |
149 | 0 | mRefCnt = 1; |
150 | 0 | delete this; |
151 | 0 | } |
152 | 0 | } |
153 | 0 | return; |
154 | 0 | } |
155 | 0 |
|
156 | 0 | MOZ_ASSERT(!IndexedDatabaseManager::IsClosed()); |
157 | 0 |
|
158 | 0 | bool needsCleanup; |
159 | 0 | { |
160 | 0 | MutexAutoLock lock(IndexedDatabaseManager::FileMutex()); |
161 | 0 |
|
162 | 0 | aRefCount = aRefCount + aDelta; |
163 | 0 |
|
164 | 0 | if (mRefCnt + mDBRefCnt + mSliceRefCnt > 0) { |
165 | 0 | return; |
166 | 0 | } |
167 | 0 | |
168 | 0 | mFileManager->mFileInfos.Remove(Id()); |
169 | 0 |
|
170 | 0 | needsCleanup = !mFileManager->Invalidated(); |
171 | 0 | } |
172 | 0 |
|
173 | 0 | if (needsCleanup) { |
174 | 0 | if (aCustomCleanupCallback) { |
175 | 0 | nsresult rv = aCustomCleanupCallback->Cleanup(mFileManager, Id()); |
176 | 0 | if (NS_FAILED(rv)) { |
177 | 0 | NS_WARNING("Custom cleanup failed!"); |
178 | 0 | } |
179 | 0 | } else { |
180 | 0 | Cleanup(); |
181 | 0 | } |
182 | 0 | } |
183 | 0 |
|
184 | 0 | delete this; |
185 | 0 | } |
186 | | |
187 | | bool |
188 | | FileInfo::LockedClearDBRefs() |
189 | 0 | { |
190 | 0 | MOZ_ASSERT(!IndexedDatabaseManager::IsClosed()); |
191 | 0 |
|
192 | 0 | IndexedDatabaseManager::FileMutex().AssertCurrentThreadOwns(); |
193 | 0 |
|
194 | 0 | mDBRefCnt = 0; |
195 | 0 |
|
196 | 0 | if (mRefCnt || mSliceRefCnt) { |
197 | 0 | return true; |
198 | 0 | } |
199 | 0 | |
200 | 0 | // In this case, we are not responsible for removing the file info from the |
201 | 0 | // hashtable. It's up to FileManager which is the only caller of this method. |
202 | 0 | |
203 | 0 | MOZ_ASSERT(mFileManager->Invalidated()); |
204 | 0 |
|
205 | 0 | delete this; |
206 | 0 |
|
207 | 0 | return false; |
208 | 0 | } |
209 | | |
210 | | void |
211 | | FileInfo::Cleanup() |
212 | 0 | { |
213 | 0 | int64_t id = Id(); |
214 | 0 |
|
215 | 0 | // IndexedDatabaseManager is main-thread only. |
216 | 0 | if (!NS_IsMainThread()) { |
217 | 0 | RefPtr<CleanupFileRunnable> cleaner = |
218 | 0 | new CleanupFileRunnable(mFileManager, id); |
219 | 0 |
|
220 | 0 | MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(cleaner)); |
221 | 0 | return; |
222 | 0 | } |
223 | 0 |
|
224 | 0 | CleanupFileRunnable::DoCleanup(mFileManager, id); |
225 | 0 | } |
226 | | |
227 | | // static |
228 | | void |
229 | | CleanupFileRunnable::DoCleanup(FileManager* aFileManager, int64_t aFileId) |
230 | 0 | { |
231 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
232 | 0 | MOZ_ASSERT(aFileManager); |
233 | 0 | MOZ_ASSERT(aFileId > 0); |
234 | 0 |
|
235 | 0 | if (NS_WARN_IF(QuotaManager::IsShuttingDown())) { |
236 | 0 | return; |
237 | 0 | } |
238 | 0 | |
239 | 0 | RefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get(); |
240 | 0 | MOZ_ASSERT(mgr); |
241 | 0 |
|
242 | 0 | if (NS_FAILED(mgr->AsyncDeleteFile(aFileManager, aFileId))) { |
243 | 0 | NS_WARNING("Failed to delete file asynchronously!"); |
244 | 0 | } |
245 | 0 | } |
246 | | |
247 | | NS_IMETHODIMP |
248 | | CleanupFileRunnable::Run() |
249 | 0 | { |
250 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
251 | 0 |
|
252 | 0 | DoCleanup(mFileManager, mFileId); |
253 | 0 |
|
254 | 0 | return NS_OK; |
255 | 0 | } |
256 | | |
257 | | /* static */ already_AddRefed<nsIFile> |
258 | | FileInfo::GetFileForFileInfo(FileInfo* aFileInfo) |
259 | 0 | { |
260 | 0 | FileManager* fileManager = aFileInfo->Manager(); |
261 | 0 | nsCOMPtr<nsIFile> directory = fileManager->GetDirectory(); |
262 | 0 | if (NS_WARN_IF(!directory)) { |
263 | 0 | return nullptr; |
264 | 0 | } |
265 | 0 | |
266 | 0 | nsCOMPtr<nsIFile> file = FileManager::GetFileForId(directory, |
267 | 0 | aFileInfo->Id()); |
268 | 0 | if (NS_WARN_IF(!file)) { |
269 | 0 | return nullptr; |
270 | 0 | } |
271 | 0 | |
272 | 0 | return file.forget(); |
273 | 0 | } |
274 | | |
275 | | } // namespace indexedDB |
276 | | } // namespace dom |
277 | | } // namespace mozilla |