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