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 STORAGE_BROWSER_DATABASE_DATABASE_TRACKER_H_ 6 #define STORAGE_BROWSER_DATABASE_DATABASE_TRACKER_H_ 7 8 #include <map> 9 #include <set> 10 #include <utility> 11 12 #include "base/files/file.h" 13 #include "base/files/file_path.h" 14 #include "base/gtest_prod_util.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/memory/scoped_ptr.h" 17 #include "base/observer_list.h" 18 #include "base/strings/string16.h" 19 #include "base/strings/string_util.h" 20 #include "base/time/time.h" 21 #include "net/base/completion_callback.h" 22 #include "storage/browser/storage_browser_export.h" 23 #include "storage/common/database/database_connections.h" 24 25 namespace base { 26 class MessageLoopProxy; 27 } 28 29 namespace content { 30 class DatabaseTracker_TestHelper_Test; 31 class MockDatabaseTracker; 32 } 33 34 namespace sql { 35 class Connection; 36 class MetaTable; 37 } 38 39 namespace storage { 40 class QuotaManagerProxy; 41 class SpecialStoragePolicy; 42 } 43 44 namespace storage { 45 46 STORAGE_EXPORT extern const base::FilePath::CharType 47 kDatabaseDirectoryName[]; 48 STORAGE_EXPORT extern const base::FilePath::CharType 49 kTrackerDatabaseFileName[]; 50 51 class DatabasesTable; 52 53 // This class is used to store information about all databases in an origin. 54 class STORAGE_EXPORT OriginInfo { 55 public: 56 OriginInfo(); 57 OriginInfo(const OriginInfo& origin_info); 58 ~OriginInfo(); 59 GetOriginIdentifier()60 const std::string& GetOriginIdentifier() const { return origin_identifier_; } TotalSize()61 int64 TotalSize() const { return total_size_; } 62 void GetAllDatabaseNames(std::vector<base::string16>* databases) const; 63 int64 GetDatabaseSize(const base::string16& database_name) const; 64 base::string16 GetDatabaseDescription( 65 const base::string16& database_name) const; 66 67 protected: 68 typedef std::map<base::string16, std::pair<int64, base::string16> > 69 DatabaseInfoMap; 70 71 OriginInfo(const std::string& origin_identifier, int64 total_size); 72 73 std::string origin_identifier_; 74 int64 total_size_; 75 DatabaseInfoMap database_info_; 76 }; 77 78 // This class manages the main database and keeps track of open databases. 79 // 80 // The data in this class is not thread-safe, so all methods of this class 81 // should be called on the same thread. The only exceptions are the ctor(), 82 // the dtor() and the database_directory() and quota_manager_proxy() getters. 83 // 84 // Furthermore, some methods of this class have to read/write data from/to 85 // the disk. Therefore, in a multi-threaded application, all methods of this 86 // class should be called on the thread dedicated to file operations (file 87 // thread in the browser process, for example), if such a thread exists. 88 class STORAGE_EXPORT DatabaseTracker 89 : public base::RefCountedThreadSafe<DatabaseTracker> { 90 public: 91 class Observer { 92 public: 93 virtual void OnDatabaseSizeChanged(const std::string& origin_identifier, 94 const base::string16& database_name, 95 int64 database_size) = 0; 96 virtual void OnDatabaseScheduledForDeletion( 97 const std::string& origin_identifier, 98 const base::string16& database_name) = 0; 99 100 protected: ~Observer()101 virtual ~Observer() {} 102 }; 103 104 DatabaseTracker(const base::FilePath& profile_path, 105 bool is_incognito, 106 storage::SpecialStoragePolicy* special_storage_policy, 107 storage::QuotaManagerProxy* quota_manager_proxy, 108 base::MessageLoopProxy* db_tracker_thread); 109 110 void DatabaseOpened(const std::string& origin_identifier, 111 const base::string16& database_name, 112 const base::string16& database_details, 113 int64 estimated_size, 114 int64* database_size); 115 void DatabaseModified(const std::string& origin_identifier, 116 const base::string16& database_name); 117 void DatabaseClosed(const std::string& origin_identifier, 118 const base::string16& database_name); 119 void HandleSqliteError(const std::string& origin_identifier, 120 const base::string16& database_name, 121 int error); 122 123 void CloseDatabases(const DatabaseConnections& connections); 124 125 void AddObserver(Observer* observer); 126 void RemoveObserver(Observer* observer); 127 128 void CloseTrackerDatabaseAndClearCaches(); 129 DatabaseDirectory()130 const base::FilePath& DatabaseDirectory() const { return db_dir_; } 131 base::FilePath GetFullDBFilePath(const std::string& origin_identifier, 132 const base::string16& database_name); 133 134 // virtual for unit-testing only 135 virtual bool GetOriginInfo(const std::string& origin_id, OriginInfo* info); 136 virtual bool GetAllOriginIdentifiers(std::vector<std::string>* origin_ids); 137 virtual bool GetAllOriginsInfo(std::vector<OriginInfo>* origins_info); 138 139 // Safe to call on any thread. quota_manager_proxy()140 storage::QuotaManagerProxy* quota_manager_proxy() const { 141 return quota_manager_proxy_.get(); 142 } 143 144 bool IsDatabaseScheduledForDeletion(const std::string& origin_identifier, 145 const base::string16& database_name); 146 147 // Deletes a single database. Returns net::OK on success, net::FAILED on 148 // failure, or net::ERR_IO_PENDING and |callback| is invoked upon completion, 149 // if non-NULL. 150 int DeleteDatabase(const std::string& origin_identifier, 151 const base::string16& database_name, 152 const net::CompletionCallback& callback); 153 154 // Delete any databases that have been touched since the cutoff date that's 155 // supplied, omitting any that match IDs within |protected_origins|. 156 // Returns net::OK on success, net::FAILED if not all databases could be 157 // deleted, and net::ERR_IO_PENDING and |callback| is invoked upon completion, 158 // if non-NULL. Protected origins, according the the SpecialStoragePolicy, 159 // are not deleted by this method. 160 int DeleteDataModifiedSince(const base::Time& cutoff, 161 const net::CompletionCallback& callback); 162 163 // Delete all databases that belong to the given origin. Returns net::OK on 164 // success, net::FAILED if not all databases could be deleted, and 165 // net::ERR_IO_PENDING and |callback| is invoked upon completion, if non-NULL. 166 // virtual for unit testing only 167 virtual int DeleteDataForOrigin(const std::string& origin_identifier, 168 const net::CompletionCallback& callback); 169 IsIncognitoProfile()170 bool IsIncognitoProfile() const { return is_incognito_; } 171 172 const base::File* GetIncognitoFile(const base::string16& vfs_file_path) const; 173 const base::File* SaveIncognitoFile(const base::string16& vfs_file_path, 174 base::File file); 175 void CloseIncognitoFileHandle(const base::string16& vfs_file_path); 176 bool HasSavedIncognitoFileHandle(const base::string16& vfs_file_path) const; 177 178 // Shutdown the database tracker, deleting database files if the tracker is 179 // used for an incognito profile. 180 void Shutdown(); 181 // Disables the exit-time deletion of session-only data. 182 void SetForceKeepSessionState(); 183 184 private: 185 friend class base::RefCountedThreadSafe<DatabaseTracker>; 186 friend class content::DatabaseTracker_TestHelper_Test; 187 friend class content::MockDatabaseTracker; // for testing 188 189 typedef std::map<std::string, std::set<base::string16> > DatabaseSet; 190 typedef std::vector<std::pair<net::CompletionCallback, DatabaseSet> > 191 PendingDeletionCallbacks; 192 typedef std::map<base::string16, base::File*> FileHandlesMap; 193 typedef std::map<std::string, base::string16> OriginDirectoriesMap; 194 195 class CachedOriginInfo : public OriginInfo { 196 public: CachedOriginInfo()197 CachedOriginInfo() : OriginInfo(std::string(), 0) {} SetOriginIdentifier(const std::string & origin_identifier)198 void SetOriginIdentifier(const std::string& origin_identifier) { 199 origin_identifier_ = origin_identifier; 200 } SetDatabaseSize(const base::string16 & database_name,int64 new_size)201 void SetDatabaseSize(const base::string16& database_name, int64 new_size) { 202 int64 old_size = 0; 203 if (database_info_.find(database_name) != database_info_.end()) 204 old_size = database_info_[database_name].first; 205 database_info_[database_name].first = new_size; 206 if (new_size != old_size) 207 total_size_ += new_size - old_size; 208 } SetDatabaseDescription(const base::string16 & database_name,const base::string16 & description)209 void SetDatabaseDescription(const base::string16& database_name, 210 const base::string16& description) { 211 database_info_[database_name].second = description; 212 } 213 }; 214 215 // virtual for unit-testing only. 216 virtual ~DatabaseTracker(); 217 218 // Deletes the directory that stores all DBs in incognito mode, if it exists. 219 void DeleteIncognitoDBDirectory(); 220 221 // Deletes session-only databases. Blocks databases from being created/opened. 222 void ClearSessionOnlyOrigins(); 223 224 bool DeleteClosedDatabase(const std::string& origin_identifier, 225 const base::string16& database_name); 226 227 // Delete all files belonging to the given origin given that no database 228 // connections within this origin are open, or if |force| is true, delete 229 // the meta data and rename the associated directory. 230 bool DeleteOrigin(const std::string& origin_identifier, bool force); 231 void DeleteDatabaseIfNeeded(const std::string& origin_identifier, 232 const base::string16& database_name); 233 234 bool LazyInit(); 235 bool UpgradeToCurrentVersion(); 236 void InsertOrUpdateDatabaseDetails(const std::string& origin_identifier, 237 const base::string16& database_name, 238 const base::string16& database_details, 239 int64 estimated_size); 240 241 void ClearAllCachedOriginInfo(); 242 CachedOriginInfo* MaybeGetCachedOriginInfo( 243 const std::string& origin_identifier, 244 bool create_if_needed); GetCachedOriginInfo(const std::string & origin_identifier)245 CachedOriginInfo* GetCachedOriginInfo( 246 const std::string& origin_identifier) { 247 return MaybeGetCachedOriginInfo(origin_identifier, true); 248 } 249 250 int64 GetDBFileSize(const std::string& origin_identifier, 251 const base::string16& database_name); 252 int64 SeedOpenDatabaseInfo(const std::string& origin_identifier, 253 const base::string16& database_name, 254 const base::string16& description); 255 int64 UpdateOpenDatabaseInfoAndNotify(const std::string& origin_identifier, 256 const base::string16& database_name, 257 const base::string16* opt_description); UpdateOpenDatabaseSizeAndNotify(const std::string & origin_identifier,const base::string16 & database_name)258 int64 UpdateOpenDatabaseSizeAndNotify(const std::string& origin_identifier, 259 const base::string16& database_name) { 260 return UpdateOpenDatabaseInfoAndNotify( 261 origin_identifier, database_name, NULL); 262 } 263 264 265 void ScheduleDatabaseForDeletion(const std::string& origin_identifier, 266 const base::string16& database_name); 267 // Schedule a set of open databases for deletion. If non-null, callback is 268 // invoked upon completion. 269 void ScheduleDatabasesForDeletion(const DatabaseSet& databases, 270 const net::CompletionCallback& callback); 271 272 // Returns the directory where all DB files for the given origin are stored. 273 base::string16 GetOriginDirectory(const std::string& origin_identifier); 274 275 bool is_initialized_; 276 const bool is_incognito_; 277 bool force_keep_session_state_; 278 bool shutting_down_; 279 const base::FilePath profile_path_; 280 const base::FilePath db_dir_; 281 scoped_ptr<sql::Connection> db_; 282 scoped_ptr<DatabasesTable> databases_table_; 283 scoped_ptr<sql::MetaTable> meta_table_; 284 ObserverList<Observer, true> observers_; 285 std::map<std::string, CachedOriginInfo> origins_info_map_; 286 DatabaseConnections database_connections_; 287 288 // The set of databases that should be deleted but are still opened 289 DatabaseSet dbs_to_be_deleted_; 290 PendingDeletionCallbacks deletion_callbacks_; 291 292 // Apps and Extensions can have special rights. 293 scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_; 294 295 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; 296 297 // The database tracker thread we're supposed to run file IO on. 298 scoped_refptr<base::MessageLoopProxy> db_tracker_thread_; 299 300 // When in incognito mode, store a DELETE_ON_CLOSE handle to each 301 // main DB and journal file that was accessed. When the incognito profile 302 // goes away (or when the browser crashes), all these handles will be 303 // closed, and the files will be deleted. 304 FileHandlesMap incognito_file_handles_; 305 306 // In a non-incognito profile, all DBs in an origin are stored in a directory 307 // named after the origin. In an incognito profile though, we do not want the 308 // directory structure to reveal the origins visited by the user (in case the 309 // browser process crashes and those directories are not deleted). So we use 310 // this map to assign directory names that do not reveal this information. 311 OriginDirectoriesMap incognito_origin_directories_; 312 int incognito_origin_directories_generator_; 313 314 FRIEND_TEST_ALL_PREFIXES(DatabaseTracker, TestHelper); 315 }; 316 317 } // namespace storage 318 319 #endif // STORAGE_BROWSER_DATABASE_DATABASE_TRACKER_H_ 320