Source code

Revision control

Other Tools

1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#ifndef mozilla_places_Database_h_
6
#define mozilla_places_Database_h_
7
8
#include "MainThreadUtils.h"
9
#include "nsWeakReference.h"
10
#include "nsIInterfaceRequestorUtils.h"
11
#include "nsIObserver.h"
12
#include "nsIAsyncShutdown.h"
13
#include "mozilla/storage.h"
14
#include "mozilla/storage/StatementCache.h"
15
#include "mozilla/Attributes.h"
16
#include "nsIEventTarget.h"
17
#include "Shutdown.h"
18
#include "nsCategoryCache.h"
19
20
// This is the schema version. Update it at any schema change and add a
21
// corresponding migrateVxx method below.
22
#define DATABASE_SCHEMA_VERSION 53
23
24
// Fired after Places inited.
25
#define TOPIC_PLACES_INIT_COMPLETE "places-init-complete"
26
// This topic is received when the profile is about to be lost. Places does
27
// initial shutdown work and notifies TOPIC_PLACES_SHUTDOWN to all listeners.
28
// Any shutdown work that requires the Places APIs should happen here.
29
#define TOPIC_PROFILE_CHANGE_TEARDOWN "profile-change-teardown"
30
// Fired when Places is shutting down. Any code should stop accessing Places
31
// APIs after this notification. If you need to listen for Places shutdown
32
// you should only use this notification, next ones are intended only for
33
// internal Places use.
34
#define TOPIC_PLACES_SHUTDOWN "places-shutdown"
35
// Fired when the connection has gone, nothing will work from now on.
36
#define TOPIC_PLACES_CONNECTION_CLOSED "places-connection-closed"
37
38
// Simulate profile-before-change. This topic may only be used by
39
// calling `observe` directly on the database. Used for testing only.
40
#define TOPIC_SIMULATE_PLACES_SHUTDOWN "test-simulate-places-shutdown"
41
42
class nsIRunnable;
43
44
namespace mozilla {
45
namespace places {
46
47
enum JournalMode {
48
// Default SQLite journal mode.
49
JOURNAL_DELETE = 0
50
// Can reduce fsyncs on Linux when journal is deleted (See bug 460315).
51
// We fallback to this mode when WAL is unavailable.
52
,
53
JOURNAL_TRUNCATE
54
// Unsafe in case of crashes on database swap or low memory.
55
,
56
JOURNAL_MEMORY
57
// Can reduce number of fsyncs. We try to use this mode by default.
58
,
59
JOURNAL_WAL
60
};
61
62
class ClientsShutdownBlocker;
63
class ConnectionShutdownBlocker;
64
65
class Database final : public nsIObserver, public nsSupportsWeakReference {
66
typedef mozilla::storage::StatementCache<mozIStorageStatement> StatementCache;
67
typedef mozilla::storage::StatementCache<mozIStorageAsyncStatement>
68
AsyncStatementCache;
69
70
public:
71
NS_DECL_THREADSAFE_ISUPPORTS
72
NS_DECL_NSIOBSERVER
73
74
Database();
75
76
/**
77
* Initializes the database connection and the schema.
78
* In case of corruption the database is copied to a backup file and replaced.
79
*/
80
nsresult Init();
81
82
/**
83
* The AsyncShutdown client used by clients of this API to be informed of
84
* shutdown.
85
*/
86
already_AddRefed<nsIAsyncShutdownClient> GetClientsShutdown();
87
88
/**
89
* The AsyncShutdown client used by clients of this API to be informed of
90
* connection shutdown.
91
*/
92
already_AddRefed<nsIAsyncShutdownClient> GetConnectionShutdown();
93
94
/**
95
* Getter to use when instantiating the class.
96
*
97
* @return Singleton instance of this class.
98
*/
99
static already_AddRefed<Database> GetDatabase();
100
101
/**
102
* Actually initialized the connection on first need.
103
*/
104
nsresult EnsureConnection();
105
106
/**
107
* Notifies that the connection has been initialized.
108
*/
109
nsresult NotifyConnectionInitalized();
110
111
/**
112
* Returns last known database status.
113
*
114
* @return one of the nsINavHistoryService::DATABASE_STATUS_* constants.
115
*/
116
uint16_t GetDatabaseStatus() {
117
mozilla::Unused << EnsureConnection();
118
return mDatabaseStatus;
119
}
120
121
/**
122
* Returns a pointer to the storage connection.
123
*
124
* @return The connection handle.
125
*/
126
mozIStorageConnection* MainConn() {
127
mozilla::Unused << EnsureConnection();
128
return mMainConn;
129
}
130
131
/**
132
* Dispatches a runnable to the connection async thread, to be serialized
133
* with async statements.
134
*
135
* @param aEvent
136
* The runnable to be dispatched.
137
*/
138
void DispatchToAsyncThread(nsIRunnable* aEvent) {
139
if (mClosed || NS_FAILED(EnsureConnection())) {
140
return;
141
}
142
nsCOMPtr<nsIEventTarget> target = do_GetInterface(mMainConn);
143
if (target) {
144
(void)target->Dispatch(aEvent, NS_DISPATCH_NORMAL);
145
}
146
}
147
148
//////////////////////////////////////////////////////////////////////////////
149
//// Statements Getters.
150
151
/**
152
* Gets a cached synchronous statement.
153
*
154
* @param aQuery
155
* SQL query literal.
156
* @return The cached statement.
157
* @note Always null check the result.
158
* @note Always use a scoper to reset the statement.
159
*/
160
template <int N>
161
already_AddRefed<mozIStorageStatement> GetStatement(const char (&aQuery)[N]) {
162
nsDependentCString query(aQuery, N - 1);
163
return GetStatement(query);
164
}
165
166
/**
167
* Gets a cached synchronous statement.
168
*
169
* @param aQuery
170
* nsCString of SQL query.
171
* @return The cached statement.
172
* @note Always null check the result.
173
* @note Always use a scoper to reset the statement.
174
*/
175
already_AddRefed<mozIStorageStatement> GetStatement(const nsACString& aQuery);
176
177
/**
178
* Gets a cached asynchronous statement.
179
*
180
* @param aQuery
181
* SQL query literal.
182
* @return The cached statement.
183
* @note Always null check the result.
184
* @note AsyncStatements are automatically reset on execution.
185
*/
186
template <int N>
187
already_AddRefed<mozIStorageAsyncStatement> GetAsyncStatement(
188
const char (&aQuery)[N]) {
189
nsDependentCString query(aQuery, N - 1);
190
return GetAsyncStatement(query);
191
}
192
193
/**
194
* Gets a cached asynchronous statement.
195
*
196
* @param aQuery
197
* nsCString of SQL query.
198
* @return The cached statement.
199
* @note Always null check the result.
200
* @note AsyncStatements are automatically reset on execution.
201
*/
202
already_AddRefed<mozIStorageAsyncStatement> GetAsyncStatement(
203
const nsACString& aQuery);
204
205
uint32_t MaxUrlLength();
206
207
int64_t GetRootFolderId() {
208
mozilla::Unused << EnsureConnection();
209
return mRootId;
210
}
211
int64_t GetMenuFolderId() {
212
mozilla::Unused << EnsureConnection();
213
return mMenuRootId;
214
}
215
int64_t GetTagsFolderId() {
216
mozilla::Unused << EnsureConnection();
217
return mTagsRootId;
218
}
219
int64_t GetUnfiledFolderId() {
220
mozilla::Unused << EnsureConnection();
221
return mUnfiledRootId;
222
}
223
int64_t GetToolbarFolderId() {
224
mozilla::Unused << EnsureConnection();
225
return mToolbarRootId;
226
}
227
int64_t GetMobileFolderId() {
228
mozilla::Unused << EnsureConnection();
229
return mMobileRootId;
230
}
231
232
protected:
233
/**
234
* Finalizes the cached statements and closes the database connection.
235
* A TOPIC_PLACES_CONNECTION_CLOSED notification is fired when done.
236
*/
237
void Shutdown();
238
239
bool IsShutdownStarted() const;
240
241
/**
242
* Ensure the favicons database file exists.
243
*
244
* @param aStorage
245
* mozStorage service instance.
246
*/
247
nsresult EnsureFaviconsDatabaseAttached(
248
const nsCOMPtr<mozIStorageService>& aStorage);
249
250
/**
251
* Creates a database backup and replaces the original file with a new
252
* one.
253
*
254
* @param aStorage
255
* mozStorage service instance.
256
* @param aDbfilename
257
* the database file name to replace.
258
* @param aTryToClone
259
* whether we should try to clone a corrupt database.
260
* @param aReopenConnection
261
* whether we should open a new connection to the replaced database.
262
*/
263
nsresult BackupAndReplaceDatabaseFile(nsCOMPtr<mozIStorageService>& aStorage,
264
const nsString& aDbFilename,
265
bool aTryToClone,
266
bool aReopenConnection);
267
268
/**
269
* Tries to recover tables and their contents from a corrupt database.
270
*
271
* @param aStorage
272
* mozStorage service instance.
273
* @param aDatabaseFile
274
* nsIFile pointing to the places.sqlite file considered corrupt.
275
*/
276
nsresult TryToCloneTablesFromCorruptDatabase(
277
const nsCOMPtr<mozIStorageService>& aStorage,
278
const nsCOMPtr<nsIFile>& aDatabaseFile);
279
280
/**
281
* Set up the connection environment through PRAGMAs.
282
* Will return NS_ERROR_FILE_CORRUPTED if any critical setting fails.
283
*
284
* @param aStorage
285
* mozStorage service instance.
286
*/
287
nsresult SetupDatabaseConnection(nsCOMPtr<mozIStorageService>& aStorage);
288
289
/**
290
* Initializes the schema. This performs any necessary migrations for the
291
* database. All migration is done inside a transaction that is rolled back
292
* if any error occurs.
293
* @param aDatabaseMigrated
294
* Whether a schema upgrade happened.
295
*/
296
nsresult InitSchema(bool* aDatabaseMigrated);
297
298
/**
299
* Checks the root bookmark folders are present, and saves the IDs for them.
300
*/
301
nsresult CheckRoots();
302
303
/**
304
* Creates bookmark roots in a new DB.
305
*/
306
nsresult EnsureBookmarkRoots(const int32_t startPosition,
307
bool shouldReparentRoots);
308
309
/**
310
* Initializes additionale SQLite functions, defined in SQLFunctions.h
311
*/
312
nsresult InitFunctions();
313
314
/**
315
* Initializes temp entities, like triggers, tables, views...
316
*/
317
nsresult InitTempEntities();
318
319
/**
320
* Helpers used by schema upgrades.
321
*/
322
nsresult MigrateV36Up();
323
nsresult MigrateV37Up();
324
nsresult MigrateV38Up();
325
nsresult MigrateV39Up();
326
nsresult MigrateV40Up();
327
nsresult MigrateV41Up();
328
nsresult MigrateV42Up();
329
nsresult MigrateV43Up();
330
nsresult MigrateV44Up();
331
nsresult MigrateV45Up();
332
nsresult MigrateV46Up();
333
nsresult MigrateV47Up();
334
nsresult MigrateV48Up();
335
nsresult MigrateV49Up();
336
nsresult MigrateV50Up();
337
nsresult MigrateV51Up();
338
nsresult MigrateV52Up();
339
nsresult MigrateV53Up();
340
341
void MigrateV52OriginFrecencies();
342
343
nsresult UpdateBookmarkRootTitles();
344
345
friend class ConnectionShutdownBlocker;
346
347
int64_t CreateMobileRoot();
348
nsresult ConvertOldStyleQuery(nsCString& aURL);
349
350
private:
351
~Database();
352
353
/**
354
* Singleton getter, invoked by class instantiation.
355
*/
356
static already_AddRefed<Database> GetSingleton();
357
358
static Database* gDatabase;
359
360
nsCOMPtr<mozIStorageConnection> mMainConn;
361
362
mutable StatementCache mMainThreadStatements;
363
mutable AsyncStatementCache mMainThreadAsyncStatements;
364
mutable StatementCache mAsyncThreadStatements;
365
366
int32_t mDBPageSize;
367
uint16_t mDatabaseStatus;
368
bool mClosed;
369
// Used to track whether icon payloads should be converted at the end of
370
// schema migration.
371
bool mShouldConvertIconPayloads;
372
// Used to track whether the favicons database should be vacuumed at the end
373
// of the schema migration.
374
bool mShouldVacuumIcons;
375
376
/**
377
* Phases for shutting down the Database.
378
* See Shutdown.h for further details about the shutdown procedure.
379
*/
380
already_AddRefed<nsIAsyncShutdownClient> GetProfileChangeTeardownPhase();
381
already_AddRefed<nsIAsyncShutdownClient> GetProfileBeforeChangePhase();
382
383
/**
384
* Blockers in charge of waiting for the Places clients and then shutting
385
* down the mozStorage connection.
386
* See Shutdown.h for further details about the shutdown procedure.
387
*
388
* Cycles with these are broken in `Shutdown()`.
389
*/
390
RefPtr<ClientsShutdownBlocker> mClientsShutdown;
391
RefPtr<ConnectionShutdownBlocker> mConnectionShutdown;
392
393
// Maximum length of a stored url.
394
// For performance reasons we don't store very long urls in history, since
395
// they are slower to search through and cause abnormal database growth,
396
// affecting the awesomebar fetch time.
397
uint32_t mMaxUrlLength;
398
399
// Used to initialize components on places startup.
400
nsCategoryCache<nsIObserver> mCacheObservers;
401
402
// Used to cache the places folder Ids when the connection is started.
403
int64_t mRootId;
404
int64_t mMenuRootId;
405
int64_t mTagsRootId;
406
int64_t mUnfiledRootId;
407
int64_t mToolbarRootId;
408
int64_t mMobileRootId;
409
};
410
411
} // namespace places
412
} // namespace mozilla
413
414
#endif // mozilla_places_Database_h_