Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: webkit/database/database_tracker.cc

Issue 507014: Adding methods that will be used by the quota management UI.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/database/database_tracker.h ('k') | webkit/database/database_tracker_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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 #include "webkit/database/database_tracker.h" 5 #include "webkit/database/database_tracker.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "app/sql/connection.h" 9 #include "app/sql/connection.h"
10 #include "app/sql/meta_table.h" 10 #include "app/sql/meta_table.h"
11 #include "app/sql/statement.h" 11 #include "app/sql/statement.h"
12 #include "app/sql/transaction.h"
12 #include "base/basictypes.h" 13 #include "base/basictypes.h"
13 #include "base/file_path.h" 14 #include "base/file_path.h"
14 #include "base/file_util.h" 15 #include "base/file_util.h"
15 #include "base/string_util.h" 16 #include "base/string_util.h"
16 #include "webkit/database/databases_table.h" 17 #include "webkit/database/databases_table.h"
18 #include "webkit/database/quota_table.h"
17 19
18 namespace webkit_database { 20 namespace webkit_database {
19 21
20 const FilePath::CharType kDatabaseDirectoryName[] = 22 const FilePath::CharType kDatabaseDirectoryName[] =
21 FILE_PATH_LITERAL("databases"); 23 FILE_PATH_LITERAL("databases");
22 const FilePath::CharType kTrackerDatabaseFileName[] = 24 const FilePath::CharType kTrackerDatabaseFileName[] =
23 FILE_PATH_LITERAL("Databases.db"); 25 FILE_PATH_LITERAL("Databases.db");
24 const int kCurrentVersion = 1; 26 const int kCurrentVersion = 2;
25 const int kCompatibleVersion = 1; 27 const int kCompatibleVersion = 1;
26 const int64 kDefaultQuota = 5 * 1024 * 1024; 28 const int64 kDefaultQuota = 5 * 1024 * 1024;
27 const int64 kDefaultExtensionQuota = 50 * 1024 * 1024; 29 const int64 kDefaultExtensionQuota = 50 * 1024 * 1024;
28 const char* kExtensionOriginIdentifierPrefix = "chrome-extension_"; 30 const char* kExtensionOriginIdentifierPrefix = "chrome-extension_";
29 31
30 DatabaseTracker::DatabaseTracker(const FilePath& profile_path) 32 DatabaseTracker::DatabaseTracker(const FilePath& profile_path)
31 : initialized_(false), 33 : initialized_(false),
32 db_dir_(profile_path.Append(FilePath(kDatabaseDirectoryName))), 34 db_dir_(profile_path.Append(FilePath(kDatabaseDirectoryName))),
33 db_(new sql::Connection()), 35 db_(new sql::Connection()),
34 databases_table_(NULL), 36 databases_table_(NULL),
(...skipping 11 matching lines...) Expand all
46 int64* database_size, 48 int64* database_size,
47 int64* space_available) { 49 int64* space_available) {
48 if (!LazyInit()) { 50 if (!LazyInit()) {
49 *database_size = 0; 51 *database_size = 0;
50 *space_available = 0; 52 *space_available = 0;
51 return; 53 return;
52 } 54 }
53 55
54 InsertOrUpdateDatabaseDetails(origin_identifier, database_name, 56 InsertOrUpdateDatabaseDetails(origin_identifier, database_name,
55 database_description, estimated_size); 57 database_description, estimated_size);
58 database_connections_.AddConnection(origin_identifier, database_name);
56 59
57 *database_size = GetCachedDatabaseFileSize(origin_identifier, database_name); 60 CachedOriginInfo* info = GetCachedOriginInfo(origin_identifier);
61 *database_size = (info ? info->GetDatabaseSize(database_name) : 0);
58 *space_available = GetOriginSpaceAvailable(origin_identifier); 62 *space_available = GetOriginSpaceAvailable(origin_identifier);
59 } 63 }
60 64
61 void DatabaseTracker::DatabaseModified(const string16& origin_identifier, 65 void DatabaseTracker::DatabaseModified(const string16& origin_identifier,
62 const string16& database_name) { 66 const string16& database_name) {
63 if (!LazyInit()) 67 if (!LazyInit())
64 return; 68 return;
65 69
66 int64 updated_db_size = 70 int64 updated_db_size =
67 UpdateCachedDatabaseFileSize(origin_identifier, database_name); 71 UpdateCachedDatabaseFileSize(origin_identifier, database_name);
68 int64 space_available = GetOriginSpaceAvailable(origin_identifier); 72 int64 space_available = GetOriginSpaceAvailable(origin_identifier);
69 FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseSizeChanged( 73 FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseSizeChanged(
70 origin_identifier, database_name, updated_db_size, space_available)); 74 origin_identifier, database_name, updated_db_size, space_available));
71 } 75 }
72 76
73 void DatabaseTracker::DatabaseClosed(const string16& origin_identifier, 77 void DatabaseTracker::DatabaseClosed(const string16& origin_identifier,
74 const string16& database_name) { 78 const string16& database_name) {
75 // TODO(dumi): figure out how to use this information at a later time 79 database_connections_.RemoveConnection(origin_identifier, database_name);
80 }
81
82 void DatabaseTracker::CloseDatabases(const DatabaseConnections& connections) {
83 database_connections_.RemoveConnections(connections);
76 } 84 }
77 85
78 void DatabaseTracker::AddObserver(Observer* observer) { 86 void DatabaseTracker::AddObserver(Observer* observer) {
79 observers_.AddObserver(observer); 87 observers_.AddObserver(observer);
80 } 88 }
81 89
82 void DatabaseTracker::RemoveObserver(Observer* observer) { 90 void DatabaseTracker::RemoveObserver(Observer* observer) {
83 // When we remove a listener, we do not know which cached information 91 // When we remove a listener, we do not know which cached information
84 // is still needed and which information can be discarded. So we just 92 // is still needed and which information can be discarded. So we just
85 // clear all caches and re-populate them as needed. 93 // clear all caches and re-populate them as needed.
86 observers_.RemoveObserver(observer); 94 observers_.RemoveObserver(observer);
87 ClearAllCachedOriginInfo(); 95 ClearAllCachedOriginInfo();
88 } 96 }
89 97
90 void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() { 98 void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() {
91 ClearAllCachedOriginInfo(); 99 ClearAllCachedOriginInfo();
92 meta_table_.reset(NULL); 100 meta_table_.reset(NULL);
93 databases_table_.reset(NULL); 101 databases_table_.reset(NULL);
102 quota_table_.reset(NULL);
94 db_->Close(); 103 db_->Close();
95 initialized_ = false; 104 initialized_ = false;
96 } 105 }
97 106
98 FilePath DatabaseTracker::GetFullDBFilePath( 107 FilePath DatabaseTracker::GetFullDBFilePath(
99 const string16& origin_identifier, 108 const string16& origin_identifier,
100 const string16& database_name) const { 109 const string16& database_name) const {
101 DCHECK(!origin_identifier.empty()); 110 DCHECK(!origin_identifier.empty());
102 DCHECK(!database_name.empty()); 111 DCHECK(!database_name.empty());
103 int64 id = databases_table_->GetDatabaseID( 112 int64 id = databases_table_->GetDatabaseID(
104 origin_identifier, database_name); 113 origin_identifier, database_name);
105 if (id < 0) 114 if (id < 0)
106 return FilePath(); 115 return FilePath();
107 116
108 FilePath file_name = FilePath::FromWStringHack(Int64ToWString(id)); 117 FilePath file_name = FilePath::FromWStringHack(Int64ToWString(id));
109 return db_dir_.Append(FilePath::FromWStringHack( 118 return db_dir_.Append(FilePath::FromWStringHack(
110 UTF16ToWide(origin_identifier))).Append(file_name); 119 UTF16ToWide(origin_identifier))).Append(file_name);
111 } 120 }
112 121
122 bool DatabaseTracker::GetAllOriginsInfo(std::vector<OriginInfo>* origins_info) {
123 DCHECK(origins_info);
124 DCHECK(origins_info->empty());
125 std::vector<string16> origins;
126 if (!databases_table_->GetAllOrigins(&origins))
127 return false;
128
129 for (std::vector<string16>::const_iterator it = origins.begin();
130 it != origins.end(); it++) {
131 CachedOriginInfo* origin_info = GetCachedOriginInfo(*it);
132 if (!origin_info) {
133 // Restore 'origins_info' to its initial state.
134 origins_info->clear();
135 return false;
136 }
137 origins_info->push_back(OriginInfo(*origin_info));
138 }
139
140 return true;
141 }
142
143 void DatabaseTracker::SetOriginQuota(const string16& origin_identifier,
144 int64 new_quota) {
145 if (quota_table_->SetOriginQuota(origin_identifier, new_quota) &&
146 (origins_info_map_.find(origin_identifier) != origins_info_map_.end())) {
147 origins_info_map_[origin_identifier].SetQuota(new_quota);
148 }
149 }
150
151 bool DatabaseTracker::DeleteDatabase(const string16& origin_identifier,
152 const string16& database_name) {
153 // Check if the database is opened by any renderer.
154 if (database_connections_.IsDatabaseOpened(origin_identifier, database_name))
155 return false;
156
157 // Try to delete the file on the hard drive.
158 FilePath db_file = GetFullDBFilePath(origin_identifier, database_name);
159 if (file_util::PathExists(db_file) && !file_util::Delete(db_file, false))
160 return false;
161
162 // Clean up the main database and invalidate the cached record.
163 databases_table_->DeleteDatabaseDetails(origin_identifier, database_name);
164 origins_info_map_.erase(origin_identifier);
165 return true;
166 }
167
168 bool DatabaseTracker::DeleteOrigin(const string16& origin_identifier) {
169 // Check if any database in this origin is opened by any renderer.
170 if (database_connections_.IsOriginUsed(origin_identifier))
171 return false;
172
173 // We need to invalidate the cached record whether file_util::Delete()
174 // succeeds or not, because even if it fails, it might still delete some
175 // DB files on the hard drive.
176 origins_info_map_.erase(origin_identifier);
177 FilePath origin_dir = db_dir_.Append(FilePath::FromWStringHack(
178 UTF16ToWide(origin_identifier)));
179 if (!file_util::Delete(origin_dir, true))
180 return false;
181
182 databases_table_->DeleteOrigin(origin_identifier);
183 return true;
184 }
185
113 bool DatabaseTracker::LazyInit() { 186 bool DatabaseTracker::LazyInit() {
114 if (!initialized_) { 187 if (!initialized_) {
115 DCHECK(!db_->is_open()); 188 DCHECK(!db_->is_open());
116 DCHECK(!databases_table_.get()); 189 DCHECK(!databases_table_.get());
190 DCHECK(!quota_table_.get());
117 DCHECK(!meta_table_.get()); 191 DCHECK(!meta_table_.get());
118 192
119 // If the tracker database exists, but it's corrupt or doesn't 193 // If the tracker database exists, but it's corrupt or doesn't
120 // have a meta table, delete the database directory 194 // have a meta table, delete the database directory.
121 const FilePath kTrackerDatabaseFullPath = 195 const FilePath kTrackerDatabaseFullPath =
122 db_dir_.Append(FilePath(kTrackerDatabaseFileName)); 196 db_dir_.Append(FilePath(kTrackerDatabaseFileName));
123 if (file_util::DirectoryExists(db_dir_) && 197 if (file_util::DirectoryExists(db_dir_) &&
124 file_util::PathExists(kTrackerDatabaseFullPath) && 198 file_util::PathExists(kTrackerDatabaseFullPath) &&
125 (!db_->Open(kTrackerDatabaseFullPath) || 199 (!db_->Open(kTrackerDatabaseFullPath) ||
126 !db_->DoesTableExist("meta"))) { 200 !sql::MetaTable::DoesTableExist(db_.get()))) {
127 db_->Close(); 201 db_->Close();
128 if (!file_util::Delete(db_dir_, true)) 202 if (!file_util::Delete(db_dir_, true))
129 return false; 203 return false;
130 } 204 }
131 205
132 databases_table_.reset(new DatabasesTable(db_.get())); 206 databases_table_.reset(new DatabasesTable(db_.get()));
207 quota_table_.reset(new QuotaTable(db_.get()));
133 meta_table_.reset(new sql::MetaTable()); 208 meta_table_.reset(new sql::MetaTable());
134 209
135 initialized_ = 210 initialized_ =
136 file_util::CreateDirectory(db_dir_) && 211 file_util::CreateDirectory(db_dir_) &&
137 (db_->is_open() || db_->Open(kTrackerDatabaseFullPath)) && 212 (db_->is_open() || db_->Open(kTrackerDatabaseFullPath)) &&
138 meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion) && 213 UpgradeToCurrentVersion();
139 (meta_table_->GetCompatibleVersionNumber() <= kCurrentVersion) &&
140 databases_table_->Init();
141 if (!initialized_) { 214 if (!initialized_) {
142 databases_table_.reset(NULL); 215 databases_table_.reset(NULL);
216 quota_table_.reset(NULL);
143 meta_table_.reset(NULL); 217 meta_table_.reset(NULL);
144 db_->Close(); 218 db_->Close();
145 } 219 }
146 } 220 }
147 return initialized_; 221 return initialized_;
148 } 222 }
149 223
224 bool DatabaseTracker::UpgradeToCurrentVersion() {
225 sql::Transaction transaction(db_.get());
226 if (!transaction.Begin() ||
227 !meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion) ||
228 (meta_table_->GetCompatibleVersionNumber() > kCurrentVersion) ||
229 !databases_table_->Init() ||
230 !quota_table_->Init())
231 return false;
232
233 if (meta_table_->GetVersionNumber() < kCurrentVersion)
234 meta_table_->SetVersionNumber(kCurrentVersion);
235
236 return transaction.Commit();
237 }
238
150 void DatabaseTracker::InsertOrUpdateDatabaseDetails( 239 void DatabaseTracker::InsertOrUpdateDatabaseDetails(
151 const string16& origin_identifier, 240 const string16& origin_identifier,
152 const string16& database_name, 241 const string16& database_name,
153 const string16& database_description, 242 const string16& database_description,
154 int64 estimated_size) { 243 int64 estimated_size) {
155 DatabaseDetails details; 244 DatabaseDetails details;
156 if (!databases_table_->GetDatabaseDetails( 245 if (!databases_table_->GetDatabaseDetails(
157 origin_identifier, database_name, &details)) { 246 origin_identifier, database_name, &details)) {
158 details.origin_identifier = origin_identifier; 247 details.origin_identifier = origin_identifier;
159 details.database_name = database_name; 248 details.database_name = database_name;
160 details.description = database_description; 249 details.description = database_description;
161 details.estimated_size = estimated_size; 250 details.estimated_size = estimated_size;
162 databases_table_->InsertDatabaseDetails(details); 251 databases_table_->InsertDatabaseDetails(details);
163 } else if ((details.description != database_description) || 252 } else if ((details.description != database_description) ||
164 (details.estimated_size != estimated_size)) { 253 (details.estimated_size != estimated_size)) {
165 details.description = database_description; 254 details.description = database_description;
166 details.estimated_size = estimated_size; 255 details.estimated_size = estimated_size;
167 databases_table_->UpdateDatabaseDetails(details); 256 databases_table_->UpdateDatabaseDetails(details);
168 } 257 }
169 } 258 }
170 259
171 int64 DatabaseTracker::GetDBFileSize(const string16& origin_identifier,
172 const string16& database_name) const {
173 FilePath db_file_name = GetFullDBFilePath(origin_identifier, database_name);
174 int64 db_file_size = 0;
175 if (!file_util::GetFileSize(db_file_name, &db_file_size))
176 db_file_size = 0;
177 return db_file_size;
178 }
179
180 void DatabaseTracker::ClearAllCachedOriginInfo() { 260 void DatabaseTracker::ClearAllCachedOriginInfo() {
181 origins_info_map_.clear(); 261 origins_info_map_.clear();
182 } 262 }
183 263
184 DatabaseTracker::CachedOriginInfo* DatabaseTracker::GetCachedOriginInfo( 264 DatabaseTracker::CachedOriginInfo* DatabaseTracker::GetCachedOriginInfo(
185 const string16& origin_identifier) { 265 const string16& origin_identifier) {
266 if (!LazyInit())
267 return NULL;
268
186 // Populate the cache with data for this origin if needed. 269 // Populate the cache with data for this origin if needed.
187 if (origins_info_map_.find(origin_identifier) == origins_info_map_.end()) { 270 if (origins_info_map_.find(origin_identifier) == origins_info_map_.end()) {
188 std::vector<DatabaseDetails> details; 271 std::vector<DatabaseDetails> details;
189 if (!databases_table_->GetAllDatabaseDetailsForOrigin( 272 if (!databases_table_->GetAllDatabaseDetailsForOrigin(
190 origin_identifier, &details)) { 273 origin_identifier, &details)) {
191 return NULL; 274 return NULL;
192 } 275 }
193 276
194 CachedOriginInfo& origin_info = origins_info_map_[origin_identifier]; 277 CachedOriginInfo& origin_info = origins_info_map_[origin_identifier];
278 origin_info.SetOrigin(origin_identifier);
195 for (std::vector<DatabaseDetails>::const_iterator it = details.begin(); 279 for (std::vector<DatabaseDetails>::const_iterator it = details.begin();
196 it != details.end(); it++) { 280 it != details.end(); it++) {
197 int64 db_file_size = 281 int64 db_file_size =
198 GetDBFileSize(it->origin_identifier, it->database_name); 282 GetDBFileSize(origin_identifier, it->database_name);
199 origin_info.SetCachedDatabaseSize(it->database_name, db_file_size); 283 origin_info.SetDatabaseSize(it->database_name, db_file_size);
284 }
285
286 int64 origin_quota = quota_table_->GetOriginQuota(origin_identifier);
287 if (origin_quota > 0) {
288 origin_info.SetQuota(origin_quota);
289 } else if (StartsWith(origin_identifier,
290 ASCIIToUTF16(kExtensionOriginIdentifierPrefix),
291 true)) {
292 origin_info.SetQuota(kDefaultExtensionQuota);
293 } else {
294 origin_info.SetQuota(kDefaultQuota);
200 } 295 }
201 } 296 }
202 297
203 return &origins_info_map_[origin_identifier]; 298 return &origins_info_map_[origin_identifier];
204 } 299 }
205 300
206 int64 DatabaseTracker::GetCachedDatabaseFileSize( 301 int64 DatabaseTracker::GetDBFileSize(const string16& origin_identifier,
207 const string16& origin_identifier, 302 const string16& database_name) const {
208 const string16& database_name) { 303 FilePath db_file_name = GetFullDBFilePath(origin_identifier, database_name);
304 int64 db_file_size = 0;
305 if (!file_util::GetFileSize(db_file_name, &db_file_size))
306 db_file_size = 0;
307 return db_file_size;
308 }
309
310 int64 DatabaseTracker::GetOriginSpaceAvailable(
311 const string16& origin_identifier) {
209 CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier); 312 CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
210 if (!origin_info) 313 if (!origin_info)
211 return 0; 314 return 0;
212 return origin_info->GetCachedDatabaseSize(database_name); 315 int64 space_available = origin_info->Quota() - origin_info->TotalSize();
316 return (space_available < 0 ? 0 : space_available);
213 } 317 }
214 318
215 int64 DatabaseTracker::UpdateCachedDatabaseFileSize( 319 int64 DatabaseTracker::UpdateCachedDatabaseFileSize(
216 const string16& origin_identifier, 320 const string16& origin_identifier,
217 const string16& database_name) { 321 const string16& database_name) {
218 int64 new_size = GetDBFileSize(origin_identifier, database_name); 322 int64 new_size = GetDBFileSize(origin_identifier, database_name);
219 CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier); 323 CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
220 if (origin_info) 324 if (origin_info)
221 origin_info->SetCachedDatabaseSize(database_name, new_size); 325 origin_info->SetDatabaseSize(database_name, new_size);
222 return new_size; 326 return new_size;
223 } 327 }
224 328
225 int64 DatabaseTracker::GetOriginUsage(const string16& origin_identifier) {
226 CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
227 if (!origin_info)
228 return kint64max;
229 return origin_info->TotalSize();
230 }
231
232 int64 DatabaseTracker::GetOriginQuota(
233 const string16& origin_identifier) const {
234 if (StartsWith(origin_identifier,
235 ASCIIToUTF16(kExtensionOriginIdentifierPrefix), true)) {
236 return kDefaultExtensionQuota;
237 }
238
239 return kDefaultQuota;
240 }
241
242 int64 DatabaseTracker::GetOriginSpaceAvailable(
243 const string16& origin_identifier) {
244 int64 space_available = GetOriginQuota(origin_identifier) -
245 GetOriginUsage(origin_identifier);
246 return (space_available < 0 ? 0 : space_available);
247 }
248
249 } // namespace webkit_database 329 } // namespace webkit_database
OLDNEW
« no previous file with comments | « webkit/database/database_tracker.h ('k') | webkit/database/database_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698