diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /toolkit/components/places/Database.h | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/places/Database.h')
-rw-r--r-- | toolkit/components/places/Database.h | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/toolkit/components/places/Database.h b/toolkit/components/places/Database.h new file mode 100644 index 0000000000..1798f73eec --- /dev/null +++ b/toolkit/components/places/Database.h @@ -0,0 +1,375 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_places_Database_h_ +#define mozilla_places_Database_h_ + +#include "MainThreadUtils.h" +#include "nsWeakReference.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIObserver.h" +#include "mozilla/storage.h" +#include "mozilla/storage/StatementCache.h" +#include "mozilla/Attributes.h" +#include "nsIEventTarget.h" +#include "Shutdown.h" +#include "nsCategoryCache.h" + +// Fired after Places inited. +#define TOPIC_PLACES_INIT_COMPLETE "places-init-complete" +// This topic is received when the profile is about to be lost. Places does +// initial shutdown work and notifies TOPIC_PLACES_SHUTDOWN to all listeners. +// Any shutdown work that requires the Places APIs should happen here. +#define TOPIC_PROFILE_CHANGE_TEARDOWN "profile-change-teardown" +// Fired when Places is shutting down. Any code should stop accessing Places +// APIs after this notification. If you need to listen for Places shutdown +// you should only use this notification, next ones are intended only for +// internal Places use. +#define TOPIC_PLACES_SHUTDOWN "places-shutdown" +// Fired when the connection has gone, nothing will work from now on. +#define TOPIC_PLACES_CONNECTION_CLOSED "places-connection-closed" + +// Simulate profile-before-change. This topic may only be used by +// calling `observe` directly on the database. Used for testing only. +#define TOPIC_SIMULATE_PLACES_SHUTDOWN "test-simulate-places-shutdown" + +class mozIStorageService; +class nsIAsyncShutdownClient; +class nsIRunnable; + +namespace mozilla::places { + +enum JournalMode { + // Default SQLite journal mode. + JOURNAL_DELETE = 0 + // Can reduce fsyncs on Linux when journal is deleted (See bug 460315). + // We fallback to this mode when WAL is unavailable. + , + JOURNAL_TRUNCATE + // Unsafe in case of crashes on database swap or low memory. + , + JOURNAL_MEMORY + // Can reduce number of fsyncs. We try to use this mode by default. + , + JOURNAL_WAL +}; + +class ClientsShutdownBlocker; +class ConnectionShutdownBlocker; + +class Database final : public nsIObserver, public nsSupportsWeakReference { + using StatementCache = mozilla::storage::StatementCache<mozIStorageStatement>; + using AsyncStatementCache = + mozilla::storage::StatementCache<mozIStorageAsyncStatement>; + + public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIOBSERVER + + Database(); + + /** + * Initializes the database connection and the schema. + * In case of corruption the database is copied to a backup file and replaced. + */ + nsresult Init(); + + /** + * The AsyncShutdown client used by clients of this API to be informed of + * shutdown. + */ + already_AddRefed<nsIAsyncShutdownClient> GetClientsShutdown(); + + /** + * The AsyncShutdown client used by clients of this API to be informed of + * connection shutdown. + */ + already_AddRefed<nsIAsyncShutdownClient> GetConnectionShutdown(); + + /** + * Getter to use when instantiating the class. + * + * @return Singleton instance of this class. + */ + static already_AddRefed<Database> GetDatabase(); + + /** + * Actually initialized the connection on first need. + */ + nsresult EnsureConnection(); + + /** + * Notifies that the connection has been initialized. + */ + nsresult NotifyConnectionInitalized(); + + /** + * Returns last known database status. + * + * @return one of the nsINavHistoryService::DATABASE_STATUS_* constants. + */ + uint16_t GetDatabaseStatus() { + mozilla::Unused << EnsureConnection(); + return mDatabaseStatus; + } + + /** + * Returns a pointer to the storage connection. + * + * @return The connection handle. + */ + mozIStorageConnection* MainConn() { + mozilla::Unused << EnsureConnection(); + return mMainConn; + } + + /** + * Dispatches a runnable to the connection async thread, to be serialized + * with async statements. + * + * @param aEvent + * The runnable to be dispatched. + */ + void DispatchToAsyncThread(nsIRunnable* aEvent) { + if (mClosed || NS_FAILED(EnsureConnection())) { + return; + } + nsCOMPtr<nsIEventTarget> target = do_GetInterface(mMainConn); + if (target) { + (void)target->Dispatch(aEvent, NS_DISPATCH_NORMAL); + } + } + + ////////////////////////////////////////////////////////////////////////////// + //// Statements Getters. + + /** + * Gets a cached synchronous statement. + * + * @param aQuery + * SQL query literal. + * @return The cached statement. + * @note Always null check the result. + * @note Always use a scoper to reset the statement. + */ + template <int N> + already_AddRefed<mozIStorageStatement> GetStatement(const char (&aQuery)[N]) { + nsDependentCString query(aQuery, N - 1); + return GetStatement(query); + } + + /** + * Gets a cached synchronous statement. + * + * @param aQuery + * nsCString of SQL query. + * @return The cached statement. + * @note Always null check the result. + * @note Always use a scoper to reset the statement. + */ + already_AddRefed<mozIStorageStatement> GetStatement(const nsACString& aQuery); + + /** + * Gets a cached asynchronous statement. + * + * @param aQuery + * SQL query literal. + * @return The cached statement. + * @note Always null check the result. + * @note AsyncStatements are automatically reset on execution. + */ + template <int N> + already_AddRefed<mozIStorageAsyncStatement> GetAsyncStatement( + const char (&aQuery)[N]) { + nsDependentCString query(aQuery, N - 1); + return GetAsyncStatement(query); + } + + /** + * Gets a cached asynchronous statement. + * + * @param aQuery + * nsCString of SQL query. + * @return The cached statement. + * @note Always null check the result. + * @note AsyncStatements are automatically reset on execution. + */ + already_AddRefed<mozIStorageAsyncStatement> GetAsyncStatement( + const nsACString& aQuery); + + int64_t GetTagsFolderId() { + mozilla::Unused << EnsureConnection(); + return mTagsRootId; + } + + protected: + /** + * Finalizes the cached statements and closes the database connection. + * A TOPIC_PLACES_CONNECTION_CLOSED notification is fired when done. + */ + void Shutdown(); + + /** + * Ensure the favicons database file exists. + * + * @param aStorage + * mozStorage service instance. + */ + nsresult EnsureFaviconsDatabaseAttached( + const nsCOMPtr<mozIStorageService>& aStorage); + + /** + * Creates a database backup and replaces the original file with a new + * one. + * + * @param aStorage + * mozStorage service instance. + * @param aDbfilename + * the database file name to replace. + * @param aTryToClone + * whether we should try to clone a corrupt database. + * @param aReopenConnection + * whether we should open a new connection to the replaced database. + */ + nsresult BackupAndReplaceDatabaseFile(nsCOMPtr<mozIStorageService>& aStorage, + const nsString& aDbFilename, + bool aTryToClone, + bool aReopenConnection); + + /** + * Tries to recover tables and their contents from a corrupt database. + * + * @param aStorage + * mozStorage service instance. + * @param aDatabaseFile + * nsIFile pointing to the places.sqlite file considered corrupt. + */ + nsresult TryToCloneTablesFromCorruptDatabase( + const nsCOMPtr<mozIStorageService>& aStorage, + const nsCOMPtr<nsIFile>& aDatabaseFile); + + /** + * Set up the connection environment through PRAGMAs. + * Will return NS_ERROR_FILE_CORRUPTED if any critical setting fails. + * + * @param aStorage + * mozStorage service instance. + */ + nsresult SetupDatabaseConnection(nsCOMPtr<mozIStorageService>& aStorage); + + /** + * Initializes the schema. This performs any necessary migrations for the + * database. All migration is done inside a transaction that is rolled back + * if any error occurs. + * @param aDatabaseMigrated + * Whether a schema upgrade happened. + */ + nsresult InitSchema(bool* aDatabaseMigrated); + + /** + * Checks the root bookmark folders are present, and saves the IDs for them. + */ + nsresult CheckRoots(); + + /** + * Creates bookmark roots in a new DB. + */ + nsresult EnsureBookmarkRoots(const int32_t startPosition, + bool shouldReparentRoots); + + /** + * Initializes additionale SQLite functions, defined in SQLFunctions.h + */ + nsresult InitFunctions(); + + /** + * Initializes temp entities, like triggers, tables, views... + */ + nsresult InitTempEntities(); + + /** + * Helpers used by schema upgrades. + * When adding a new function remember to bump up the schema version in + * nsINavHistoryService. + */ + nsresult MigrateV53Up(); + nsresult MigrateV54Up(); + nsresult MigrateV55Up(); + nsresult MigrateV56Up(); + nsresult MigrateV57Up(); + nsresult MigrateV60Up(); + nsresult MigrateV61Up(); + nsresult MigrateV67Up(); + nsresult MigrateV69Up(); + nsresult MigrateV70Up(); + nsresult MigrateV71Up(); + nsresult MigrateV72Up(); + nsresult MigrateV73Up(); + nsresult MigrateV74Up(); + nsresult MigrateV75Up(); + + nsresult UpdateBookmarkRootTitles(); + + friend class ConnectionShutdownBlocker; + + int64_t CreateMobileRoot(); + + private: + ~Database(); + + /** + * Singleton getter, invoked by class instantiation. + */ + static already_AddRefed<Database> GetSingleton(); + + static Database* gDatabase; + + nsCOMPtr<mozIStorageConnection> mMainConn; + + mutable StatementCache mMainThreadStatements; + mutable AsyncStatementCache mMainThreadAsyncStatements; + mutable StatementCache mAsyncThreadStatements; + + int32_t mDBPageSize; + uint16_t mDatabaseStatus; + bool mClosed; + + /** + * Phases for shutting down the Database. + * See Shutdown.h for further details about the shutdown procedure. + */ + already_AddRefed<nsIAsyncShutdownClient> GetProfileChangeTeardownPhase(); + already_AddRefed<nsIAsyncShutdownClient> GetProfileBeforeChangePhase(); + + /** + * Blockers in charge of waiting for the Places clients and then shutting + * down the mozStorage connection. + * See Shutdown.h for further details about the shutdown procedure. + * + * Cycles with these are broken in `Shutdown()`. + */ + RefPtr<ClientsShutdownBlocker> mClientsShutdown; + RefPtr<ConnectionShutdownBlocker> mConnectionShutdown; + + // Maximum length of a stored url. + // For performance reasons we don't store very long urls in history, since + // they are slower to search through and cause abnormal database growth, + // affecting the awesomebar fetch time. + uint32_t mMaxUrlLength; + + // Used to initialize components on places startup. + nsCategoryCache<nsIObserver> mCacheObservers; + + // Used to cache the places folder Ids when the connection is started. + int64_t mRootId; + int64_t mMenuRootId; + int64_t mTagsRootId; + int64_t mUnfiledRootId; + int64_t mToolbarRootId; + int64_t mMobileRootId; +}; + +} // namespace mozilla::places + +#endif // mozilla_places_Database_h_ |