| OLD | NEW |
| (Empty) |
| 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.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 "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 content { | |
| 30 class DatabaseTracker_TestHelper_Test; | |
| 31 class MockDatabaseTracker; | |
| 32 } | |
| 33 | |
| 34 namespace sql { | |
| 35 class Connection; | |
| 36 class MetaTable; | |
| 37 } | |
| 38 | |
| 39 namespace quota { | |
| 40 class QuotaManagerProxy; | |
| 41 class SpecialStoragePolicy; | |
| 42 } | |
| 43 | |
| 44 namespace webkit_database { | |
| 45 | |
| 46 WEBKIT_STORAGE_BROWSER_EXPORT extern const base::FilePath::CharType | |
| 47 kDatabaseDirectoryName[]; | |
| 48 WEBKIT_STORAGE_BROWSER_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 WEBKIT_STORAGE_BROWSER_EXPORT OriginInfo { | |
| 55 public: | |
| 56 OriginInfo(); | |
| 57 OriginInfo(const OriginInfo& origin_info); | |
| 58 ~OriginInfo(); | |
| 59 | |
| 60 const std::string& GetOriginIdentifier() const { return origin_identifier_; } | |
| 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 WEBKIT_STORAGE_BROWSER_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: | |
| 101 virtual ~Observer() {} | |
| 102 }; | |
| 103 | |
| 104 DatabaseTracker(const base::FilePath& profile_path, | |
| 105 bool is_incognito, | |
| 106 quota::SpecialStoragePolicy* special_storage_policy, | |
| 107 quota::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 | |
| 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. | |
| 140 quota::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 | |
| 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: | |
| 197 CachedOriginInfo() : OriginInfo(std::string(), 0) {} | |
| 198 void SetOriginIdentifier(const std::string& origin_identifier) { | |
| 199 origin_identifier_ = origin_identifier; | |
| 200 } | |
| 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 } | |
| 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); | |
| 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); | |
| 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<quota::SpecialStoragePolicy> special_storage_policy_; | |
| 294 | |
| 295 scoped_refptr<quota::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 webkit_database | |
| 318 | |
| 319 #endif // WEBKIT_BROWSER_DATABASE_DATABASE_TRACKER_H_ | |
| OLD | NEW |