1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_HISTORY_HISTORY_DATABASE_H_ 6 #define CHROME_BROWSER_HISTORY_HISTORY_DATABASE_H_ 7 8 #include "base/basictypes.h" 9 #include "base/compiler_specific.h" 10 #include "base/gtest_prod_util.h" 11 #include "build/build_config.h" 12 #include "chrome/browser/history/download_database.h" 13 #include "chrome/browser/history/history_types.h" 14 #include "chrome/browser/history/url_database.h" 15 #include "chrome/browser/history/visit_database.h" 16 #include "chrome/browser/history/visitsegment_database.h" 17 #include "sql/connection.h" 18 #include "sql/init_status.h" 19 #include "sql/meta_table.h" 20 21 #if defined(OS_ANDROID) 22 #include "chrome/browser/history/android/android_cache_database.h" 23 #include "chrome/browser/history/android/android_urls_database.h" 24 #endif 25 26 namespace base { 27 class FilePath; 28 } 29 30 class HistoryQuickProviderTest; 31 32 namespace history { 33 34 // Encapsulates the SQL connection for the history database. This class holds 35 // the database connection and has methods the history system (including full 36 // text search) uses for writing and retrieving information. 37 // 38 // We try to keep most logic out of the history database; this should be seen 39 // as the storage interface. Logic for manipulating this storage layer should 40 // be in HistoryBackend.cc. 41 class HistoryDatabase : public DownloadDatabase, 42 #if defined(OS_ANDROID) 43 public AndroidURLsDatabase, 44 public AndroidCacheDatabase, 45 #endif 46 public URLDatabase, 47 public VisitDatabase, 48 public VisitSegmentDatabase { 49 public: 50 // A simple class for scoping a history database transaction. This does not 51 // support rollback since the history database doesn't, either. 52 class TransactionScoper { 53 public: 54 explicit TransactionScoper(HistoryDatabase* db) : db_(db) { 55 db_->BeginTransaction(); 56 } 57 ~TransactionScoper() { 58 db_->CommitTransaction(); 59 } 60 private: 61 HistoryDatabase* db_; 62 }; 63 64 // Must call Init() to complete construction. Although it can be created on 65 // any thread, it must be destructed on the history thread for proper 66 // database cleanup. 67 HistoryDatabase(); 68 69 virtual ~HistoryDatabase(); 70 71 // Call before Init() to set the error callback to be used for the 72 // underlying database connection. 73 void set_error_callback( 74 const sql::Connection::ErrorCallback& error_callback) { 75 error_callback_ = error_callback; 76 } 77 78 // Must call this function to complete initialization. Will return 79 // sql::INIT_OK on success. Otherwise, no other function should be called. You 80 // may want to call BeginExclusiveMode after this when you are ready. 81 sql::InitStatus Init(const base::FilePath& history_name); 82 83 // Computes and records various metrics for the database. Should only be 84 // called once and only upon successful Init. 85 void ComputeDatabaseMetrics(const base::FilePath& filename); 86 87 // Call to set the mode on the database to exclusive. The default locking mode 88 // is "normal" but we want to run in exclusive mode for slightly better 89 // performance since we know nobody else is using the database. This is 90 // separate from Init() since the in-memory database attaches to slurp the 91 // data out, and this can't happen in exclusive mode. 92 void BeginExclusiveMode(); 93 94 // Returns the current version that we will generate history databases with. 95 static int GetCurrentVersion(); 96 97 // Transactions on the history database. Use the Transaction object above 98 // for most work instead of these directly. We support nested transactions 99 // and only commit when the outermost transaction is committed. This means 100 // that it is impossible to rollback a specific transaction. We could roll 101 // back the outermost transaction if any inner one is rolled back, but it 102 // turns out we don't really need this type of integrity for the history 103 // database, so we just don't support it. 104 void BeginTransaction(); 105 void CommitTransaction(); 106 int transaction_nesting() const { // for debugging and assertion purposes 107 return db_.transaction_nesting(); 108 } 109 void RollbackTransaction(); 110 111 // Drops all tables except the URL, and download tables, and recreates them 112 // from scratch. This is done to rapidly clean up stuff when deleting all 113 // history. It is faster and less likely to have problems that deleting all 114 // rows in the tables. 115 // 116 // We don't delete the downloads table, since there may be in progress 117 // downloads. We handle the download history clean up separately in: 118 // content::DownloadManager::RemoveDownloadsFromHistoryBetween. 119 // 120 // Returns true on success. On failure, the caller should assume that the 121 // database is invalid. There could have been an error recreating a table. 122 // This should be treated the same as an init failure, and the database 123 // should not be used any more. 124 // 125 // This will also recreate the supplementary URL indices, since these 126 // indices won't be created automatically when using the temporary URL 127 // table (what the caller does right before calling this). 128 bool RecreateAllTablesButURL(); 129 130 // Vacuums the database. This will cause sqlite to defragment and collect 131 // unused space in the file. It can be VERY SLOW. 132 void Vacuum(); 133 134 // Try to trim the cache memory used by the database. If |aggressively| is 135 // true try to trim all unused cache, otherwise trim by half. 136 void TrimMemory(bool aggressively); 137 138 // Razes the database. Returns true if successful. 139 bool Raze(); 140 141 // Visit table functions ---------------------------------------------------- 142 143 // Update the segment id of a visit. Return true on success. 144 bool SetSegmentID(VisitID visit_id, SegmentID segment_id); 145 146 // Query the segment ID for the provided visit. Return 0 on failure or if the 147 // visit id wasn't found. 148 SegmentID GetSegmentID(VisitID visit_id); 149 150 // Retrieves/Updates early expiration threshold, which specifies the earliest 151 // known point in history that may possibly to contain visits suitable for 152 // early expiration (AUTO_SUBFRAMES). 153 virtual base::Time GetEarlyExpirationThreshold(); 154 virtual void UpdateEarlyExpirationThreshold(base::Time threshold); 155 156 private: 157 #if defined(OS_ANDROID) 158 // AndroidProviderBackend uses the |db_|. 159 friend class AndroidProviderBackend; 160 FRIEND_TEST_ALL_PREFIXES(AndroidURLsMigrationTest, MigrateToVersion22); 161 #endif 162 friend class ::HistoryQuickProviderTest; 163 friend class InMemoryURLIndexTest; 164 165 // Overridden from URLDatabase: 166 virtual sql::Connection& GetDB() OVERRIDE; 167 168 // Migration ----------------------------------------------------------------- 169 170 // Makes sure the version is up-to-date, updating if necessary. If the 171 // database is too old to migrate, the user will be notified. Returns 172 // sql::INIT_OK iff the DB is up-to-date and ready for use. 173 // 174 // This assumes it is called from the init function inside a transaction. It 175 // may commit the transaction and start a new one if migration requires it. 176 sql::InitStatus EnsureCurrentVersion(); 177 178 #if !defined(OS_WIN) 179 // Converts the time epoch in the database from being 1970-based to being 180 // 1601-based which corresponds to the change in Time.internal_value_. 181 void MigrateTimeEpoch(); 182 #endif 183 184 // --------------------------------------------------------------------------- 185 186 sql::Connection::ErrorCallback error_callback_; 187 sql::Connection db_; 188 sql::MetaTable meta_table_; 189 190 base::Time cached_early_expiration_threshold_; 191 192 DISALLOW_COPY_AND_ASSIGN(HistoryDatabase); 193 }; 194 195 } // namespace history 196 197 #endif // CHROME_BROWSER_HISTORY_HISTORY_DATABASE_H_ 198