| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "app/sql/connection.h" | 10 #include "app/sql/connection.h" |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 return; | 135 return; |
| 136 } | 136 } |
| 137 | 137 |
| 138 InsertOrUpdateDatabaseDetails(origin_identifier, database_name, | 138 InsertOrUpdateDatabaseDetails(origin_identifier, database_name, |
| 139 database_description, estimated_size); | 139 database_description, estimated_size); |
| 140 database_connections_.AddConnection(origin_identifier, database_name); | 140 database_connections_.AddConnection(origin_identifier, database_name); |
| 141 | 141 |
| 142 CachedOriginInfo* info = GetCachedOriginInfo(origin_identifier); | 142 CachedOriginInfo* info = GetCachedOriginInfo(origin_identifier); |
| 143 *database_size = (info ? info->GetDatabaseSize(database_name) : 0); | 143 *database_size = (info ? info->GetDatabaseSize(database_name) : 0); |
| 144 *space_available = GetOriginSpaceAvailable(origin_identifier); | 144 *space_available = GetOriginSpaceAvailable(origin_identifier); |
| 145 |
| 146 if (quota_manager_proxy_) { |
| 147 // So we can compute deltas as modifications are made. |
| 148 database_connections_.SetOpenDatabaseSize( |
| 149 origin_identifier, database_name, *database_size); |
| 150 quota_manager_proxy_->NotifyStorageAccessed( |
| 151 quota::QuotaClient::kDatabase, |
| 152 DatabaseUtil::GetOriginFromIdentifier(origin_identifier), |
| 153 quota::kStorageTypeTemporary); |
| 154 } |
| 145 } | 155 } |
| 146 | 156 |
| 147 void DatabaseTracker::DatabaseModified(const string16& origin_identifier, | 157 void DatabaseTracker::DatabaseModified(const string16& origin_identifier, |
| 148 const string16& database_name) { | 158 const string16& database_name) { |
| 149 if (!LazyInit()) | 159 if (!LazyInit()) |
| 150 return; | 160 return; |
| 151 | 161 |
| 152 int64 updated_db_size = | 162 int64 new_size = |
| 153 UpdateCachedDatabaseFileSize(origin_identifier, database_name); | 163 UpdateCachedDatabaseFileSize(origin_identifier, database_name); |
| 154 int64 space_available = GetOriginSpaceAvailable(origin_identifier); | 164 int64 space_available = GetOriginSpaceAvailable(origin_identifier); |
| 155 FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseSizeChanged( | 165 FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseSizeChanged( |
| 156 origin_identifier, database_name, updated_db_size, space_available)); | 166 origin_identifier, database_name, new_size, space_available)); |
| 157 | 167 |
| 158 if (quota_manager_proxy_) { | 168 if (quota_manager_proxy_) { |
| 159 // TODO(michaeln): notify the quota manager | 169 int64 old_size = database_connections_.GetOpenDatabaseSize( |
| 160 // CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier); | 170 origin_identifier, database_name); |
| 161 // if (origin_info) | 171 if (old_size != new_size) { |
| 162 // quota_manager_proxy_->NotifyStorageConsumed( | 172 database_connections_.SetOpenDatabaseSize( |
| 163 // quota::QuotaClient::kDatabase, | 173 origin_identifier, database_name, new_size); |
| 164 // DatabaseUtil::GetOriginFromIdentifier(origin_identifier), | 174 quota_manager_proxy_->NotifyStorageModified( |
| 165 // quota::kStorageTypeTemporary, | 175 quota::QuotaClient::kDatabase, |
| 166 // origin_info->TotalSize()); | 176 DatabaseUtil::GetOriginFromIdentifier(origin_identifier), |
| 177 quota::kStorageTypeTemporary, |
| 178 new_size - old_size); |
| 179 } |
| 167 } | 180 } |
| 168 } | 181 } |
| 169 | 182 |
| 170 void DatabaseTracker::DatabaseClosed(const string16& origin_identifier, | 183 void DatabaseTracker::DatabaseClosed(const string16& origin_identifier, |
| 171 const string16& database_name) { | 184 const string16& database_name) { |
| 172 if (database_connections_.IsEmpty()) { | 185 if (database_connections_.IsEmpty()) { |
| 173 DCHECK(!is_initialized_); | 186 DCHECK(!is_initialized_); |
| 174 return; | 187 return; |
| 175 } | 188 } |
| 176 database_connections_.RemoveConnection(origin_identifier, database_name); | 189 database_connections_.RemoveConnection(origin_identifier, database_name); |
| 177 if (!database_connections_.IsDatabaseOpened(origin_identifier, database_name)) | 190 if (!database_connections_.IsDatabaseOpened(origin_identifier, database_name)) |
| 178 DeleteDatabaseIfNeeded(origin_identifier, database_name); | 191 DeleteDatabaseIfNeeded(origin_identifier, database_name); |
| 179 } | 192 } |
| 180 | 193 |
| 181 void DatabaseTracker::CloseDatabases(const DatabaseConnections& connections) { | 194 void DatabaseTracker::CloseDatabases(const DatabaseConnections& connections) { |
| 182 if (database_connections_.IsEmpty()) { | 195 if (database_connections_.IsEmpty()) { |
| 183 DCHECK(!is_initialized_ || connections.IsEmpty()); | 196 DCHECK(!is_initialized_ || connections.IsEmpty()); |
| 184 return; | 197 return; |
| 185 } | 198 } |
| 199 |
| 200 if (quota_manager_proxy_) { |
| 201 // When being closed by this route, there's a chance that |
| 202 // the tracker missed some DatabseModified calls. This method is used |
| 203 // when a renderer crashes to cleanup it's open resources. |
| 204 // We need to examine what we have in connections for the |
| 205 // size of each open databases and notify any differences between the |
| 206 // actual file sizes now. |
| 207 std::vector<std::pair<string16, string16> > open_dbs; |
| 208 connections.ListConnections(&open_dbs); |
| 209 for (std::vector<std::pair<string16, string16> >::iterator it = |
| 210 open_dbs.begin(); it != open_dbs.end(); ++it) { |
| 211 int64 old_size = database_connections_.GetOpenDatabaseSize( |
| 212 it->first, it->second); |
| 213 int64 new_size = GetDBFileSize(it->first, it->second); |
| 214 if (new_size != old_size) { |
| 215 database_connections_.SetOpenDatabaseSize( |
| 216 it->first, it->second, new_size); |
| 217 quota_manager_proxy_->NotifyStorageModified( |
| 218 quota::QuotaClient::kDatabase, |
| 219 DatabaseUtil::GetOriginFromIdentifier(it->first), |
| 220 quota::kStorageTypeTemporary, |
| 221 new_size - old_size); |
| 222 } |
| 223 } |
| 224 } |
| 225 |
| 186 std::vector<std::pair<string16, string16> > closed_dbs; | 226 std::vector<std::pair<string16, string16> > closed_dbs; |
| 187 database_connections_.RemoveConnections(connections, &closed_dbs); | 227 database_connections_.RemoveConnections(connections, &closed_dbs); |
| 188 for (std::vector<std::pair<string16, string16> >::iterator it = | 228 for (std::vector<std::pair<string16, string16> >::iterator it = |
| 189 closed_dbs.begin(); it != closed_dbs.end(); ++it) { | 229 closed_dbs.begin(); it != closed_dbs.end(); ++it) { |
| 190 DeleteDatabaseIfNeeded(it->first, it->second); | 230 DeleteDatabaseIfNeeded(it->first, it->second); |
| 191 } | 231 } |
| 192 } | 232 } |
| 193 | 233 |
| 194 void DatabaseTracker::DeleteDatabaseIfNeeded(const string16& origin_identifier, | 234 void DatabaseTracker::DeleteDatabaseIfNeeded(const string16& origin_identifier, |
| 195 const string16& database_name) { | 235 const string16& database_name) { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 | 379 |
| 340 bool DatabaseTracker::DeleteClosedDatabase(const string16& origin_identifier, | 380 bool DatabaseTracker::DeleteClosedDatabase(const string16& origin_identifier, |
| 341 const string16& database_name) { | 381 const string16& database_name) { |
| 342 if (!LazyInit()) | 382 if (!LazyInit()) |
| 343 return false; | 383 return false; |
| 344 | 384 |
| 345 // Check if the database is opened by any renderer. | 385 // Check if the database is opened by any renderer. |
| 346 if (database_connections_.IsDatabaseOpened(origin_identifier, database_name)) | 386 if (database_connections_.IsDatabaseOpened(origin_identifier, database_name)) |
| 347 return false; | 387 return false; |
| 348 | 388 |
| 389 int64 db_file_size = quota_manager_proxy_ ? |
| 390 GetDBFileSize(origin_identifier, database_name) : 0; |
| 391 |
| 349 // Try to delete the file on the hard drive. | 392 // Try to delete the file on the hard drive. |
| 350 // TODO(jochen): Delete journal files associated with this database. | |
| 351 FilePath db_file = GetFullDBFilePath(origin_identifier, database_name); | 393 FilePath db_file = GetFullDBFilePath(origin_identifier, database_name); |
| 352 if (file_util::PathExists(db_file) && !file_util::Delete(db_file, false)) | 394 if (file_util::PathExists(db_file) && !file_util::Delete(db_file, false)) |
| 353 return false; | 395 return false; |
| 354 | 396 |
| 397 // Also delete any orphaned journal file. |
| 398 DCHECK(db_file.Extension().empty()); |
| 399 file_util::Delete(db_file.InsertBeforeExtensionASCII( |
| 400 DatabaseUtil::kJournalFileSuffix), false); |
| 401 |
| 402 if (quota_manager_proxy_ && db_file_size) |
| 403 quota_manager_proxy_->NotifyStorageModified( |
| 404 quota::QuotaClient::kDatabase, |
| 405 DatabaseUtil::GetOriginFromIdentifier(origin_identifier), |
| 406 quota::kStorageTypeTemporary, |
| 407 -db_file_size); |
| 408 |
| 355 // Clean up the main database and invalidate the cached record. | 409 // Clean up the main database and invalidate the cached record. |
| 356 databases_table_->DeleteDatabaseDetails(origin_identifier, database_name); | 410 databases_table_->DeleteDatabaseDetails(origin_identifier, database_name); |
| 357 origins_info_map_.erase(origin_identifier); | 411 origins_info_map_.erase(origin_identifier); |
| 358 | 412 |
| 359 std::vector<DatabaseDetails> details; | 413 std::vector<DatabaseDetails> details; |
| 360 if (databases_table_->GetAllDatabaseDetailsForOrigin( | 414 if (databases_table_->GetAllDatabaseDetailsForOrigin( |
| 361 origin_identifier, &details) && details.empty()) { | 415 origin_identifier, &details) && details.empty()) { |
| 362 // Try to delete the origin in case this was the last database. | 416 // Try to delete the origin in case this was the last database. |
| 363 DeleteOrigin(origin_identifier); | 417 DeleteOrigin(origin_identifier); |
| 364 } else if (quota_manager_proxy_) { | |
| 365 // TODO(michaeln): notify the quota manager | |
| 366 // CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier); | |
| 367 // if (origin_info) | |
| 368 // quota_manager_proxy_->NotifyStorageConsumed( | |
| 369 // quota::QuotaClient::kDatabase, | |
| 370 // DatabaseUtil::GetOriginFromIdentifier(origin_identifier), | |
| 371 // quota::kStorageTypeTemporary, | |
| 372 // origin_info->TotalSize()); | |
| 373 } | 418 } |
| 374 return true; | 419 return true; |
| 375 } | 420 } |
| 376 | 421 |
| 377 bool DatabaseTracker::DeleteOrigin(const string16& origin_identifier) { | 422 bool DatabaseTracker::DeleteOrigin(const string16& origin_identifier) { |
| 378 if (!LazyInit()) | 423 if (!LazyInit()) |
| 379 return false; | 424 return false; |
| 380 | 425 |
| 381 // Check if any database in this origin is opened by any renderer. | 426 // Check if any database in this origin is opened by any renderer. |
| 382 if (database_connections_.IsOriginUsed(origin_identifier)) | 427 if (database_connections_.IsOriginUsed(origin_identifier)) |
| 383 return false; | 428 return false; |
| 384 | 429 |
| 430 int64 deleted_size = 0; |
| 431 if (quota_manager_proxy_) { |
| 432 CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier); |
| 433 if (origin_info) |
| 434 deleted_size = origin_info->TotalSize(); |
| 435 } |
| 436 |
| 385 // We need to invalidate the cached record whether file_util::Delete() | 437 // We need to invalidate the cached record whether file_util::Delete() |
| 386 // succeeds or not, because even if it fails, it might still delete some | 438 // succeeds or not, because even if it fails, it might still delete some |
| 387 // DB files on the hard drive. | 439 // DB files on the hard drive. |
| 388 origins_info_map_.erase(origin_identifier); | 440 origins_info_map_.erase(origin_identifier); |
| 389 FilePath origin_dir = db_dir_.Append(FilePath::FromWStringHack( | 441 FilePath origin_dir = db_dir_.Append(FilePath::FromWStringHack( |
| 390 UTF16ToWide(origin_identifier))); | 442 UTF16ToWide(origin_identifier))); |
| 391 if (!file_util::Delete(origin_dir, true)) | 443 if (!file_util::Delete(origin_dir, true)) |
| 392 return false; | 444 return false; |
| 393 | 445 |
| 394 databases_table_->DeleteOrigin(origin_identifier); | 446 databases_table_->DeleteOrigin(origin_identifier); |
| 395 | 447 |
| 396 if (quota_manager_proxy_) { | 448 if (quota_manager_proxy_ && deleted_size) { |
| 397 // TODO(michaeln): notify the quota manager | 449 quota_manager_proxy_->NotifyStorageModified( |
| 398 // quota_manager_proxy_->NotifyStorageConsumed( | 450 quota::QuotaClient::kDatabase, |
| 399 // quota::QuotaClient::kDatabase, | 451 DatabaseUtil::GetOriginFromIdentifier(origin_identifier), |
| 400 // DatabaseUtil::GetOriginFromIdentifier(origin_identifier), | 452 quota::kStorageTypeTemporary, |
| 401 // quota::kStorageTypeTemporary, | 453 -deleted_size); |
| 402 // 0); | |
| 403 } | 454 } |
| 404 | 455 |
| 405 return true; | 456 return true; |
| 406 } | 457 } |
| 407 | 458 |
| 408 bool DatabaseTracker::IsDatabaseScheduledForDeletion( | 459 bool DatabaseTracker::IsDatabaseScheduledForDeletion( |
| 409 const string16& origin_identifier, | 460 const string16& origin_identifier, |
| 410 const string16& database_name) { | 461 const string16& database_name) { |
| 411 DatabaseSet::iterator it = dbs_to_be_deleted_.find(origin_identifier); | 462 DatabaseSet::iterator it = dbs_to_be_deleted_.find(origin_identifier); |
| 412 if (it == dbs_to_be_deleted_.end()) | 463 if (it == dbs_to_be_deleted_.end()) |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 std::string basename = file_path.BaseName().MaybeAsASCII(); | 833 std::string basename = file_path.BaseName().MaybeAsASCII(); |
| 783 if (!basename.empty() && | 834 if (!basename.empty() && |
| 784 !StartsWithASCII(basename, kExtensionOriginIdentifierPrefix, true)) { | 835 !StartsWithASCII(basename, kExtensionOriginIdentifierPrefix, true)) { |
| 785 file_util::Delete(file_path, true); | 836 file_util::Delete(file_path, true); |
| 786 } | 837 } |
| 787 } | 838 } |
| 788 } | 839 } |
| 789 } | 840 } |
| 790 | 841 |
| 791 } // namespace webkit_database | 842 } // namespace webkit_database |
| OLD | NEW |