Source code

Revision control

Other Tools

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 "ActorsParent.h"
10
#include "FileManager.h"
11
#include "IndexedDatabaseManager.h"
12
#include "mozilla/Assertions.h"
13
#include "mozilla/Attributes.h"
14
#include "mozilla/Mutex.h"
15
#include "mozilla/dom/quota/QuotaManager.h"
16
#include "mozilla/ipc/BackgroundParent.h"
17
#include "nsError.h"
18
#include "nsThreadUtils.h"
19
20
namespace mozilla {
21
namespace dom {
22
namespace indexedDB {
23
24
using namespace mozilla::dom::quota;
25
using namespace mozilla::ipc;
26
27
namespace {
28
29
template <typename IdType>
30
class FileInfoImpl final : public FileInfo {
31
IdType mFileId;
32
33
public:
34
FileInfoImpl(FileManager* aFileManager, IdType aFileId)
35
: FileInfo(aFileManager), mFileId(aFileId) {
36
MOZ_ASSERT(aFileManager);
37
MOZ_ASSERT(aFileId > 0);
38
}
39
40
private:
41
~FileInfoImpl() = default;
42
43
virtual int64_t Id() const override { return int64_t(mFileId); }
44
};
45
46
} // namespace
47
48
FileInfo::FileInfo(FileManager* aFileManager) : mFileManager(aFileManager) {
49
MOZ_ASSERT(aFileManager);
50
}
51
52
// static
53
FileInfo* FileInfo::Create(FileManager* aFileManager, int64_t aId) {
54
MOZ_ASSERT(aFileManager);
55
MOZ_ASSERT(aId > 0);
56
57
if (aId <= INT16_MAX) {
58
return new FileInfoImpl<int16_t>(aFileManager, aId);
59
}
60
61
if (aId <= INT32_MAX) {
62
return new FileInfoImpl<int32_t>(aFileManager, aId);
63
}
64
65
return new FileInfoImpl<int64_t>(aFileManager, aId);
66
}
67
68
void FileInfo::GetReferences(int32_t* aRefCnt, int32_t* aDBRefCnt,
69
int32_t* aSliceRefCnt) {
70
MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
71
72
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
73
74
if (aRefCnt) {
75
*aRefCnt = mRefCnt;
76
}
77
78
if (aDBRefCnt) {
79
*aDBRefCnt = mDBRefCnt;
80
}
81
82
if (aSliceRefCnt) {
83
*aSliceRefCnt = mSliceRefCnt;
84
}
85
}
86
87
void FileInfo::UpdateReferences(ThreadSafeAutoRefCnt& aRefCount, int32_t aDelta,
88
CustomCleanupCallback* aCustomCleanupCallback) {
89
// XXX This can go away once DOM objects no longer hold FileInfo objects...
90
// Looking at you, BlobImplBase...
91
// BlobImplBase is being addressed in bug 1068975.
92
if (IndexedDatabaseManager::IsClosed()) {
93
MOZ_ASSERT(&aRefCount == &mRefCnt);
94
MOZ_ASSERT(aDelta == 1 || aDelta == -1);
95
96
if (aDelta > 0) {
97
++aRefCount;
98
} else {
99
nsrefcnt count = --aRefCount;
100
if (!count) {
101
mRefCnt = 1;
102
delete this;
103
}
104
}
105
return;
106
}
107
108
MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
109
110
bool needsCleanup;
111
{
112
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
113
114
aRefCount = aRefCount + aDelta;
115
116
if (mRefCnt + mDBRefCnt + mSliceRefCnt > 0) {
117
return;
118
}
119
120
mFileManager->mFileInfos.Remove(Id());
121
122
needsCleanup = !mFileManager->Invalidated();
123
}
124
125
if (needsCleanup) {
126
if (aCustomCleanupCallback) {
127
nsresult rv = aCustomCleanupCallback->Cleanup(mFileManager, Id());
128
if (NS_FAILED(rv)) {
129
NS_WARNING("Custom cleanup failed!");
130
}
131
} else {
132
Cleanup();
133
}
134
}
135
136
delete this;
137
}
138
139
bool FileInfo::LockedClearDBRefs() {
140
MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
141
142
IndexedDatabaseManager::FileMutex().AssertCurrentThreadOwns();
143
144
mDBRefCnt = 0;
145
146
if (mRefCnt || mSliceRefCnt) {
147
return true;
148
}
149
150
// In this case, we are not responsible for removing the file info from the
151
// hashtable. It's up to FileManager which is the only caller of this method.
152
153
MOZ_ASSERT(mFileManager->Invalidated());
154
155
delete this;
156
157
return false;
158
}
159
160
void FileInfo::Cleanup() {
161
AssertIsOnBackgroundThread();
162
163
int64_t id = Id();
164
165
if (NS_FAILED(AsyncDeleteFile(mFileManager, id))) {
166
NS_WARNING("Failed to delete file asynchronously!");
167
}
168
}
169
170
/* static */
171
already_AddRefed<nsIFile> FileInfo::GetFileForFileInfo(FileInfo* aFileInfo) {
172
FileManager* fileManager = aFileInfo->Manager();
173
nsCOMPtr<nsIFile> directory = fileManager->GetDirectory();
174
if (NS_WARN_IF(!directory)) {
175
return nullptr;
176
}
177
178
nsCOMPtr<nsIFile> file =
179
FileManager::GetFileForId(directory, aFileInfo->Id());
180
if (NS_WARN_IF(!file)) {
181
return nullptr;
182
}
183
184
return file.forget();
185
}
186
187
} // namespace indexedDB
188
} // namespace dom
189
} // namespace mozilla