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