Chromium Code Reviews| 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" | 
| 11 #include "app/sql/diagnostic_error_delegate.h" | 11 #include "app/sql/diagnostic_error_delegate.h" | 
| 12 #include "app/sql/meta_table.h" | 12 #include "app/sql/meta_table.h" | 
| 13 #include "app/sql/statement.h" | 13 #include "app/sql/statement.h" | 
| 14 #include "app/sql/transaction.h" | 14 #include "app/sql/transaction.h" | 
| 15 #include "base/basictypes.h" | 15 #include "base/basictypes.h" | 
| 16 #include "base/file_util.h" | 16 #include "base/file_util.h" | 
| 17 #include "base/message_loop_proxy.h" | 17 #include "base/message_loop_proxy.h" | 
| 18 #include "base/string_number_conversions.h" | 18 #include "base/string_number_conversions.h" | 
| 19 #include "base/utf_string_conversions.h" | 19 #include "base/utf_string_conversions.h" | 
| 20 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" | 
| 21 #include "webkit/database/database_quota_client.h" | 21 #include "webkit/database/database_quota_client.h" | 
| 22 #include "webkit/database/database_util.h" | 22 #include "webkit/database/database_util.h" | 
| 23 #include "webkit/database/databases_table.h" | 23 #include "webkit/database/databases_table.h" | 
| 24 #include "webkit/database/quota_table.h" | |
| 25 #include "webkit/quota/quota_manager.h" | 24 #include "webkit/quota/quota_manager.h" | 
| 26 #include "webkit/quota/special_storage_policy.h" | 25 #include "webkit/quota/special_storage_policy.h" | 
| 27 | 26 | 
| 28 namespace { | 27 namespace { | 
| 29 | 28 | 
| 30 class HistogramUniquifier { | 29 class HistogramUniquifier { | 
| 31 public: | 30 public: | 
| 32 static const char* name() { return "Sqlite.DatabaseTracker.Error"; } | 31 static const char* name() { return "Sqlite.DatabaseTracker.Error"; } | 
| 33 }; | 32 }; | 
| 34 | 33 | 
| 35 sql::ErrorDelegate* GetErrorHandlerForTrackerDb() { | 34 sql::ErrorDelegate* GetErrorHandlerForTrackerDb() { | 
| 36 return new sql::DiagnosticErrorDelegate<HistogramUniquifier>(); | 35 return new sql::DiagnosticErrorDelegate<HistogramUniquifier>(); | 
| 37 } | 36 } | 
| 38 | 37 | 
| 39 } // anon namespace | 38 } // anon namespace | 
| 40 | 39 | 
| 41 namespace webkit_database { | 40 namespace webkit_database { | 
| 42 | 41 | 
| 43 const FilePath::CharType kDatabaseDirectoryName[] = | 42 const FilePath::CharType kDatabaseDirectoryName[] = | 
| 44 FILE_PATH_LITERAL("databases"); | 43 FILE_PATH_LITERAL("databases"); | 
| 45 const FilePath::CharType kIncognitoDatabaseDirectoryName[] = | 44 const FilePath::CharType kIncognitoDatabaseDirectoryName[] = | 
| 46 FILE_PATH_LITERAL("databases-incognito"); | 45 FILE_PATH_LITERAL("databases-incognito"); | 
| 47 const FilePath::CharType kTrackerDatabaseFileName[] = | 46 const FilePath::CharType kTrackerDatabaseFileName[] = | 
| 48 FILE_PATH_LITERAL("Databases.db"); | 47 FILE_PATH_LITERAL("Databases.db"); | 
| 49 static const int kCurrentVersion = 2; | 48 static const int kCurrentVersion = 2; | 
| 50 static const int kCompatibleVersion = 1; | 49 static const int kCompatibleVersion = 1; | 
| 51 static const char* kExtensionOriginIdentifierPrefix = "chrome-extension_"; | 50 static const char* kExtensionOriginIdentifierPrefix = "chrome-extension_"; | 
| 52 | 51 | 
| 53 OriginInfo::OriginInfo() | 52 OriginInfo::OriginInfo() | 
| 54 : total_size_(0), | 53 : total_size_(0) {} | 
| 55 quota_(0) {} | |
| 56 | 54 | 
| 57 OriginInfo::OriginInfo(const OriginInfo& origin_info) | 55 OriginInfo::OriginInfo(const OriginInfo& origin_info) | 
| 58 : origin_(origin_info.origin_), | 56 : origin_(origin_info.origin_), | 
| 59 total_size_(origin_info.total_size_), | 57 total_size_(origin_info.total_size_), | 
| 60 quota_(origin_info.quota_), | |
| 61 database_info_(origin_info.database_info_) {} | 58 database_info_(origin_info.database_info_) {} | 
| 62 | 59 | 
| 63 OriginInfo::~OriginInfo() {} | 60 OriginInfo::~OriginInfo() {} | 
| 64 | 61 | 
| 65 void OriginInfo::GetAllDatabaseNames(std::vector<string16>* databases) const { | 62 void OriginInfo::GetAllDatabaseNames(std::vector<string16>* databases) const { | 
| 66 for (DatabaseInfoMap::const_iterator it = database_info_.begin(); | 63 for (DatabaseInfoMap::const_iterator it = database_info_.begin(); | 
| 67 it != database_info_.end(); it++) { | 64 it != database_info_.end(); it++) { | 
| 68 databases->push_back(it->first); | 65 databases->push_back(it->first); | 
| 69 } | 66 } | 
| 70 } | 67 } | 
| 71 | 68 | 
| 72 int64 OriginInfo::GetDatabaseSize(const string16& database_name) const { | 69 int64 OriginInfo::GetDatabaseSize(const string16& database_name) const { | 
| 73 DatabaseInfoMap::const_iterator it = database_info_.find(database_name); | 70 DatabaseInfoMap::const_iterator it = database_info_.find(database_name); | 
| 74 if (it != database_info_.end()) | 71 if (it != database_info_.end()) | 
| 75 return it->second.first; | 72 return it->second.first; | 
| 76 return 0; | 73 return 0; | 
| 77 } | 74 } | 
| 78 | 75 | 
| 79 string16 OriginInfo::GetDatabaseDescription( | 76 string16 OriginInfo::GetDatabaseDescription( | 
| 80 const string16& database_name) const { | 77 const string16& database_name) const { | 
| 81 DatabaseInfoMap::const_iterator it = database_info_.find(database_name); | 78 DatabaseInfoMap::const_iterator it = database_info_.find(database_name); | 
| 82 if (it != database_info_.end()) | 79 if (it != database_info_.end()) | 
| 83 return it->second.second; | 80 return it->second.second; | 
| 84 return string16(); | 81 return string16(); | 
| 85 } | 82 } | 
| 86 | 83 | 
| 87 OriginInfo::OriginInfo(const string16& origin, int64 total_size, int64 quota) | 84 OriginInfo::OriginInfo(const string16& origin, int64 total_size) | 
| 88 : origin_(origin), total_size_(total_size), quota_(quota) {} | 85 : origin_(origin), total_size_(total_size) {} | 
| 89 | 86 | 
| 90 DatabaseTracker::DatabaseTracker( | 87 DatabaseTracker::DatabaseTracker( | 
| 91 const FilePath& profile_path, | 88 const FilePath& profile_path, | 
| 92 bool is_incognito, | 89 bool is_incognito, | 
| 93 quota::SpecialStoragePolicy* special_storage_policy, | 90 quota::SpecialStoragePolicy* special_storage_policy, | 
| 94 quota::QuotaManagerProxy* quota_manager_proxy, | 91 quota::QuotaManagerProxy* quota_manager_proxy, | 
| 95 base::MessageLoopProxy* db_tracker_thread) | 92 base::MessageLoopProxy* db_tracker_thread) | 
| 96 : is_initialized_(false), | 93 : is_initialized_(false), | 
| 97 is_incognito_(is_incognito), | 94 is_incognito_(is_incognito), | 
| 98 shutting_down_(false), | 95 shutting_down_(false), | 
| 99 profile_path_(profile_path), | 96 profile_path_(profile_path), | 
| 100 db_dir_(is_incognito_ ? | 97 db_dir_(is_incognito_ ? | 
| 101 profile_path_.Append(kIncognitoDatabaseDirectoryName) : | 98 profile_path_.Append(kIncognitoDatabaseDirectoryName) : | 
| 102 profile_path_.Append(kDatabaseDirectoryName)), | 99 profile_path_.Append(kDatabaseDirectoryName)), | 
| 103 db_(new sql::Connection()), | 100 db_(new sql::Connection()), | 
| 104 databases_table_(NULL), | 101 databases_table_(NULL), | 
| 105 meta_table_(NULL), | 102 meta_table_(NULL), | 
| 106 default_quota_(5 * 1024 * 1024), | |
| 107 special_storage_policy_(special_storage_policy), | 103 special_storage_policy_(special_storage_policy), | 
| 108 quota_manager_proxy_(quota_manager_proxy), | 104 quota_manager_proxy_(quota_manager_proxy), | 
| 109 incognito_origin_directories_generator_(0) { | 105 incognito_origin_directories_generator_(0) { | 
| 110 if (quota_manager_proxy) { | 106 if (quota_manager_proxy) { | 
| 111 quota_manager_proxy->RegisterClient( | 107 quota_manager_proxy->RegisterClient( | 
| 112 new DatabaseQuotaClient(db_tracker_thread, this)); | 108 new DatabaseQuotaClient(db_tracker_thread, this)); | 
| 113 } | 109 } | 
| 114 } | 110 } | 
| 115 | 111 | 
| 116 DatabaseTracker::~DatabaseTracker() { | 112 DatabaseTracker::~DatabaseTracker() { | 
| 117 DCHECK(dbs_to_be_deleted_.empty()); | 113 DCHECK(dbs_to_be_deleted_.empty()); | 
| 118 DCHECK(deletion_callbacks_.empty()); | 114 DCHECK(deletion_callbacks_.empty()); | 
| 119 } | 115 } | 
| 120 | 116 | 
| 121 void DatabaseTracker::SetDefaultQuota(int64 quota) { | |
| 122 default_quota_ = quota; | |
| 123 ClearAllCachedOriginInfo(); | |
| 124 } | |
| 125 | |
| 126 void DatabaseTracker::DatabaseOpened(const string16& origin_identifier, | 117 void DatabaseTracker::DatabaseOpened(const string16& origin_identifier, | 
| 127 const string16& database_name, | 118 const string16& database_name, | 
| 128 const string16& database_description, | 119 const string16& database_description, | 
| 129 int64 estimated_size, | 120 int64 estimated_size, | 
| 130 int64* database_size, | 121 int64* database_size) { | 
| 131 int64* space_available) { | |
| 132 if (!LazyInit()) { | 122 if (!LazyInit()) { | 
| 133 *database_size = 0; | 123 *database_size = 0; | 
| 134 *space_available = 0; | |
| 135 return; | 124 return; | 
| 136 } | 125 } | 
| 137 | 126 | 
| 138 InsertOrUpdateDatabaseDetails(origin_identifier, database_name, | 127 if (quota_manager_proxy_) | 
| 139 database_description, estimated_size); | |
| 140 database_connections_.AddConnection(origin_identifier, database_name); | |
| 141 | |
| 142 CachedOriginInfo* info = GetCachedOriginInfo(origin_identifier); | |
| 143 *database_size = (info ? info->GetDatabaseSize(database_name) : 0); | |
| 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( | 128 quota_manager_proxy_->NotifyStorageAccessed( | 
| 151 quota::QuotaClient::kDatabase, | 129 quota::QuotaClient::kDatabase, | 
| 152 DatabaseUtil::GetOriginFromIdentifier(origin_identifier), | 130 DatabaseUtil::GetOriginFromIdentifier(origin_identifier), | 
| 153 quota::kStorageTypeTemporary); | 131 quota::kStorageTypeTemporary); | 
| 132 | |
| 133 InsertOrUpdateDatabaseDetails(origin_identifier, database_name, | |
| 134 database_description, estimated_size); | |
| 135 if (database_connections_.AddConnection(origin_identifier, database_name)) { | |
| 136 *database_size = SeedOpenDatabaseSize(origin_identifier, database_name); | |
| 137 return; | |
| 154 } | 138 } | 
| 139 *database_size = UpdateOpenDatabaseSizeAndNotify(origin_identifier, | |
| 140 database_name); | |
| 155 } | 141 } | 
| 156 | 142 | 
| 157 void DatabaseTracker::DatabaseModified(const string16& origin_identifier, | 143 void DatabaseTracker::DatabaseModified(const string16& origin_identifier, | 
| 158 const string16& database_name) { | 144 const string16& database_name) { | 
| 159 if (!LazyInit()) | 145 if (!LazyInit()) | 
| 160 return; | 146 return; | 
| 161 | 147 UpdateOpenDatabaseSizeAndNotify(origin_identifier, database_name); | 
| 162 int64 new_size = | |
| 163 UpdateCachedDatabaseFileSize(origin_identifier, database_name); | |
| 164 int64 space_available = GetOriginSpaceAvailable(origin_identifier); | |
| 165 FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseSizeChanged( | |
| 166 origin_identifier, database_name, new_size, space_available)); | |
| 167 | |
| 168 if (quota_manager_proxy_) { | |
| 169 int64 old_size = database_connections_.GetOpenDatabaseSize( | |
| 170 origin_identifier, database_name); | |
| 171 if (old_size != new_size) { | |
| 172 database_connections_.SetOpenDatabaseSize( | |
| 173 origin_identifier, database_name, new_size); | |
| 174 quota_manager_proxy_->NotifyStorageModified( | |
| 175 quota::QuotaClient::kDatabase, | |
| 176 DatabaseUtil::GetOriginFromIdentifier(origin_identifier), | |
| 177 quota::kStorageTypeTemporary, | |
| 178 new_size - old_size); | |
| 179 } | |
| 180 } | |
| 181 } | 148 } | 
| 182 | 149 | 
| 183 void DatabaseTracker::DatabaseClosed(const string16& origin_identifier, | 150 void DatabaseTracker::DatabaseClosed(const string16& origin_identifier, | 
| 184 const string16& database_name) { | 151 const string16& database_name) { | 
| 185 if (database_connections_.IsEmpty()) { | 152 if (database_connections_.IsEmpty()) { | 
| 186 DCHECK(!is_initialized_); | 153 DCHECK(!is_initialized_); | 
| 187 return; | 154 return; | 
| 188 } | 155 } | 
| 189 database_connections_.RemoveConnection(origin_identifier, database_name); | 156 | 
| 190 if (!database_connections_.IsDatabaseOpened(origin_identifier, database_name)) | 157 if (quota_manager_proxy_) | 
| 158 quota_manager_proxy_->NotifyStorageAccessed( | |
| 
 
kinuko
2011/05/26 03:35:13
Why are we notifying access on close?  Could we ha
 
michaeln
2011/05/26 03:57:32
Will do...
We only call NotifiyStorageAccessed wh
 
 | |
| 159 quota::QuotaClient::kDatabase, | |
| 160 DatabaseUtil::GetOriginFromIdentifier(origin_identifier), | |
| 161 quota::kStorageTypeTemporary); | |
| 162 | |
| 163 UpdateOpenDatabaseSizeAndNotify(origin_identifier, database_name); | |
| 164 if (database_connections_.RemoveConnection(origin_identifier, database_name)) | |
| 191 DeleteDatabaseIfNeeded(origin_identifier, database_name); | 165 DeleteDatabaseIfNeeded(origin_identifier, database_name); | 
| 192 } | 166 } | 
| 193 | 167 | 
| 194 void DatabaseTracker::CloseDatabases(const DatabaseConnections& connections) { | 168 void DatabaseTracker::CloseDatabases(const DatabaseConnections& connections) { | 
| 195 if (database_connections_.IsEmpty()) { | 169 if (database_connections_.IsEmpty()) { | 
| 196 DCHECK(!is_initialized_ || connections.IsEmpty()); | 170 DCHECK(!is_initialized_ || connections.IsEmpty()); | 
| 197 return; | 171 return; | 
| 198 } | 172 } | 
| 199 | 173 | 
| 200 if (quota_manager_proxy_) { | 174 // When being closed by this route, there's a chance that | 
| 201 // When being closed by this route, there's a chance that | 175 // the tracker missed some DatabseModified calls. This method is used | 
| 202 // the tracker missed some DatabseModified calls. This method is used | 176 // when a renderer crashes to cleanup it's open resources. | 
| 203 // when a renderer crashes to cleanup it's open resources. | 177 // We need to examine what we have in connections for the | 
| 204 // We need to examine what we have in connections for the | 178 // size of each open databases and notify any differences between the | 
| 205 // size of each open databases and notify any differences between the | 179 // actual file sizes now. | 
| 206 // actual file sizes now. | 180 std::vector<std::pair<string16, string16> > open_dbs; | 
| 207 std::vector<std::pair<string16, string16> > open_dbs; | 181 connections.ListConnections(&open_dbs); | 
| 208 connections.ListConnections(&open_dbs); | 182 for (std::vector<std::pair<string16, string16> >::iterator it = | 
| 209 for (std::vector<std::pair<string16, string16> >::iterator it = | 183 open_dbs.begin(); it != open_dbs.end(); ++it) | 
| 210 open_dbs.begin(); it != open_dbs.end(); ++it) { | 184 UpdateOpenDatabaseSizeAndNotify(it->first, it->second); | 
| 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 | 185 | 
| 226 std::vector<std::pair<string16, string16> > closed_dbs; | 186 std::vector<std::pair<string16, string16> > closed_dbs; | 
| 227 database_connections_.RemoveConnections(connections, &closed_dbs); | 187 database_connections_.RemoveConnections(connections, &closed_dbs); | 
| 228 for (std::vector<std::pair<string16, string16> >::iterator it = | 188 for (std::vector<std::pair<string16, string16> >::iterator it = | 
| 229 closed_dbs.begin(); it != closed_dbs.end(); ++it) { | 189 closed_dbs.begin(); it != closed_dbs.end(); ++it) { | 
| 230 DeleteDatabaseIfNeeded(it->first, it->second); | 190 DeleteDatabaseIfNeeded(it->first, it->second); | 
| 231 } | 191 } | 
| 232 } | 192 } | 
| 233 | 193 | 
| 234 void DatabaseTracker::DeleteDatabaseIfNeeded(const string16& origin_identifier, | 194 void DatabaseTracker::DeleteDatabaseIfNeeded(const string16& origin_identifier, | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 observers_.RemoveObserver(observer); | 236 observers_.RemoveObserver(observer); | 
| 277 ClearAllCachedOriginInfo(); | 237 ClearAllCachedOriginInfo(); | 
| 278 } | 238 } | 
| 279 | 239 | 
| 280 void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() { | 240 void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() { | 
| 281 ClearAllCachedOriginInfo(); | 241 ClearAllCachedOriginInfo(); | 
| 282 | 242 | 
| 283 if (!is_incognito_) { | 243 if (!is_incognito_) { | 
| 284 meta_table_.reset(NULL); | 244 meta_table_.reset(NULL); | 
| 285 databases_table_.reset(NULL); | 245 databases_table_.reset(NULL); | 
| 286 quota_table_.reset(NULL); | |
| 287 db_->Close(); | 246 db_->Close(); | 
| 288 is_initialized_ = false; | 247 is_initialized_ = false; | 
| 289 } | 248 } | 
| 290 } | 249 } | 
| 291 | 250 | 
| 292 string16 DatabaseTracker::GetOriginDirectory( | 251 string16 DatabaseTracker::GetOriginDirectory( | 
| 293 const string16& origin_identifier) { | 252 const string16& origin_identifier) { | 
| 294 if (!is_incognito_) | 253 if (!is_incognito_) | 
| 295 return origin_identifier; | 254 return origin_identifier; | 
| 296 | 255 | 
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 358 // Restore 'origins_info' to its initial state. | 317 // Restore 'origins_info' to its initial state. | 
| 359 origins_info->clear(); | 318 origins_info->clear(); | 
| 360 return false; | 319 return false; | 
| 361 } | 320 } | 
| 362 origins_info->push_back(OriginInfo(*origin_info)); | 321 origins_info->push_back(OriginInfo(*origin_info)); | 
| 363 } | 322 } | 
| 364 | 323 | 
| 365 return true; | 324 return true; | 
| 366 } | 325 } | 
| 367 | 326 | 
| 368 void DatabaseTracker::SetOriginQuota(const string16& origin_identifier, | |
| 369 int64 new_quota) { | |
| 370 if (!LazyInit()) | |
| 371 return; | |
| 372 | |
| 373 if (quota_table_->SetOriginQuota(origin_identifier, new_quota) && | |
| 374 (origins_info_map_.find(origin_identifier) != origins_info_map_.end())) { | |
| 375 origins_info_map_[origin_identifier].SetQuota(new_quota); | |
| 376 } | |
| 377 } | |
| 378 | |
| 379 | |
| 380 bool DatabaseTracker::DeleteClosedDatabase(const string16& origin_identifier, | 327 bool DatabaseTracker::DeleteClosedDatabase(const string16& origin_identifier, | 
| 381 const string16& database_name) { | 328 const string16& database_name) { | 
| 382 if (!LazyInit()) | 329 if (!LazyInit()) | 
| 383 return false; | 330 return false; | 
| 384 | 331 | 
| 385 // Check if the database is opened by any renderer. | 332 // Check if the database is opened by any renderer. | 
| 386 if (database_connections_.IsDatabaseOpened(origin_identifier, database_name)) | 333 if (database_connections_.IsDatabaseOpened(origin_identifier, database_name)) | 
| 387 return false; | 334 return false; | 
| 388 | 335 | 
| 389 int64 db_file_size = quota_manager_proxy_ ? | 336 int64 db_file_size = quota_manager_proxy_ ? | 
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 return false; | 411 return false; | 
| 465 | 412 | 
| 466 std::set<string16>& databases = it->second; | 413 std::set<string16>& databases = it->second; | 
| 467 return (databases.find(database_name) != databases.end()); | 414 return (databases.find(database_name) != databases.end()); | 
| 468 } | 415 } | 
| 469 | 416 | 
| 470 bool DatabaseTracker::LazyInit() { | 417 bool DatabaseTracker::LazyInit() { | 
| 471 if (!is_initialized_ && !shutting_down_) { | 418 if (!is_initialized_ && !shutting_down_) { | 
| 472 DCHECK(!db_->is_open()); | 419 DCHECK(!db_->is_open()); | 
| 473 DCHECK(!databases_table_.get()); | 420 DCHECK(!databases_table_.get()); | 
| 474 DCHECK(!quota_table_.get()); | |
| 475 DCHECK(!meta_table_.get()); | 421 DCHECK(!meta_table_.get()); | 
| 476 | 422 | 
| 477 // If the tracker database exists, but it's corrupt or doesn't | 423 // If the tracker database exists, but it's corrupt or doesn't | 
| 478 // have a meta table, delete the database directory. | 424 // have a meta table, delete the database directory. | 
| 479 const FilePath kTrackerDatabaseFullPath = | 425 const FilePath kTrackerDatabaseFullPath = | 
| 480 db_dir_.Append(FilePath(kTrackerDatabaseFileName)); | 426 db_dir_.Append(FilePath(kTrackerDatabaseFileName)); | 
| 481 if (file_util::DirectoryExists(db_dir_) && | 427 if (file_util::DirectoryExists(db_dir_) && | 
| 482 file_util::PathExists(kTrackerDatabaseFullPath) && | 428 file_util::PathExists(kTrackerDatabaseFullPath) && | 
| 483 (!db_->Open(kTrackerDatabaseFullPath) || | 429 (!db_->Open(kTrackerDatabaseFullPath) || | 
| 484 !sql::MetaTable::DoesTableExist(db_.get()))) { | 430 !sql::MetaTable::DoesTableExist(db_.get()))) { | 
| 485 db_->Close(); | 431 db_->Close(); | 
| 486 if (!file_util::Delete(db_dir_, true)) | 432 if (!file_util::Delete(db_dir_, true)) | 
| 487 return false; | 433 return false; | 
| 488 } | 434 } | 
| 489 | 435 | 
| 490 db_->set_error_delegate(GetErrorHandlerForTrackerDb()); | 436 db_->set_error_delegate(GetErrorHandlerForTrackerDb()); | 
| 491 | 437 | 
| 492 databases_table_.reset(new DatabasesTable(db_.get())); | 438 databases_table_.reset(new DatabasesTable(db_.get())); | 
| 493 quota_table_.reset(new QuotaTable(db_.get())); | |
| 494 meta_table_.reset(new sql::MetaTable()); | 439 meta_table_.reset(new sql::MetaTable()); | 
| 495 | 440 | 
| 496 is_initialized_ = | 441 is_initialized_ = | 
| 497 file_util::CreateDirectory(db_dir_) && | 442 file_util::CreateDirectory(db_dir_) && | 
| 498 (db_->is_open() || | 443 (db_->is_open() || | 
| 499 (is_incognito_ ? db_->OpenInMemory() : | 444 (is_incognito_ ? db_->OpenInMemory() : | 
| 500 db_->Open(kTrackerDatabaseFullPath))) && | 445 db_->Open(kTrackerDatabaseFullPath))) && | 
| 501 UpgradeToCurrentVersion(); | 446 UpgradeToCurrentVersion(); | 
| 502 if (!is_initialized_) { | 447 if (!is_initialized_) { | 
| 503 databases_table_.reset(NULL); | 448 databases_table_.reset(NULL); | 
| 504 quota_table_.reset(NULL); | |
| 505 meta_table_.reset(NULL); | 449 meta_table_.reset(NULL); | 
| 506 db_->Close(); | 450 db_->Close(); | 
| 507 } | 451 } | 
| 508 } | 452 } | 
| 509 return is_initialized_; | 453 return is_initialized_; | 
| 510 } | 454 } | 
| 511 | 455 | 
| 512 bool DatabaseTracker::UpgradeToCurrentVersion() { | 456 bool DatabaseTracker::UpgradeToCurrentVersion() { | 
| 513 sql::Transaction transaction(db_.get()); | 457 sql::Transaction transaction(db_.get()); | 
| 514 if (!transaction.Begin() || | 458 if (!transaction.Begin() || | 
| 515 !meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion) || | 459 !meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion) || | 
| 516 (meta_table_->GetCompatibleVersionNumber() > kCurrentVersion) || | 460 (meta_table_->GetCompatibleVersionNumber() > kCurrentVersion) || | 
| 517 !databases_table_->Init() || | 461 !databases_table_->Init()) | 
| 518 !quota_table_->Init()) | |
| 519 return false; | 462 return false; | 
| 520 | 463 | 
| 521 if (meta_table_->GetVersionNumber() < kCurrentVersion) | 464 if (meta_table_->GetVersionNumber() < kCurrentVersion) | 
| 522 meta_table_->SetVersionNumber(kCurrentVersion); | 465 meta_table_->SetVersionNumber(kCurrentVersion); | 
| 523 | 466 | 
| 524 return transaction.Commit(); | 467 return transaction.Commit(); | 
| 525 } | 468 } | 
| 526 | 469 | 
| 527 void DatabaseTracker::InsertOrUpdateDatabaseDetails( | 470 void DatabaseTracker::InsertOrUpdateDatabaseDetails( | 
| 528 const string16& origin_identifier, | 471 const string16& origin_identifier, | 
| (...skipping 30 matching lines...) Expand all Loading... | |
| 559 std::vector<DatabaseDetails> details; | 502 std::vector<DatabaseDetails> details; | 
| 560 if (!databases_table_->GetAllDatabaseDetailsForOrigin( | 503 if (!databases_table_->GetAllDatabaseDetailsForOrigin( | 
| 561 origin_identifier, &details)) { | 504 origin_identifier, &details)) { | 
| 562 return NULL; | 505 return NULL; | 
| 563 } | 506 } | 
| 564 | 507 | 
| 565 CachedOriginInfo& origin_info = origins_info_map_[origin_identifier]; | 508 CachedOriginInfo& origin_info = origins_info_map_[origin_identifier]; | 
| 566 origin_info.SetOrigin(origin_identifier); | 509 origin_info.SetOrigin(origin_identifier); | 
| 567 for (std::vector<DatabaseDetails>::const_iterator it = details.begin(); | 510 for (std::vector<DatabaseDetails>::const_iterator it = details.begin(); | 
| 568 it != details.end(); it++) { | 511 it != details.end(); it++) { | 
| 569 int64 db_file_size = | 512 int64 db_file_size; | 
| 570 GetDBFileSize(origin_identifier, it->database_name); | 513 if (database_connections_.IsDatabaseOpened( | 
| 514 origin_identifier, it->database_name)) { | |
| 515 db_file_size = database_connections_.GetOpenDatabaseSize( | |
| 516 origin_identifier, it->database_name); | |
| 517 } else { | |
| 518 db_file_size = GetDBFileSize(origin_identifier, it->database_name); | |
| 519 } | |
| 571 origin_info.SetDatabaseSize(it->database_name, db_file_size); | 520 origin_info.SetDatabaseSize(it->database_name, db_file_size); | 
| 572 origin_info.SetDatabaseDescription(it->database_name, it->description); | 521 origin_info.SetDatabaseDescription(it->database_name, it->description); | 
| 573 } | 522 } | 
| 574 | |
| 575 if (special_storage_policy_.get() && | |
| 576 special_storage_policy_->IsStorageUnlimited( | |
| 577 DatabaseUtil::GetOriginFromIdentifier(origin_identifier))) { | |
| 578 // TODO(michaeln): handle the case where it changes status sometime after | |
| 579 // the cached origin_info has been established | |
| 580 origin_info.SetQuota(kint64max); | |
| 581 } else { | |
| 582 int64 origin_quota = quota_table_->GetOriginQuota(origin_identifier); | |
| 583 if (origin_quota > 0) | |
| 584 origin_info.SetQuota(origin_quota); | |
| 585 else | |
| 586 origin_info.SetQuota(default_quota_); | |
| 587 } | |
| 588 } | 523 } | 
| 589 | 524 | 
| 590 return &origins_info_map_[origin_identifier]; | 525 return &origins_info_map_[origin_identifier]; | 
| 591 } | 526 } | 
| 592 | 527 | 
| 593 int64 DatabaseTracker::GetDBFileSize(const string16& origin_identifier, | 528 int64 DatabaseTracker::GetDBFileSize(const string16& origin_identifier, | 
| 594 const string16& database_name) { | 529 const string16& database_name) { | 
| 595 FilePath db_file_name = GetFullDBFilePath(origin_identifier, database_name); | 530 FilePath db_file_name = GetFullDBFilePath(origin_identifier, database_name); | 
| 596 int64 db_file_size = 0; | 531 int64 db_file_size = 0; | 
| 597 if (!file_util::GetFileSize(db_file_name, &db_file_size)) | 532 if (!file_util::GetFileSize(db_file_name, &db_file_size)) | 
| 598 db_file_size = 0; | 533 db_file_size = 0; | 
| 599 return db_file_size; | 534 return db_file_size; | 
| 600 } | 535 } | 
| 601 | 536 | 
| 602 int64 DatabaseTracker::GetOriginSpaceAvailable( | 537 int64 DatabaseTracker::SeedOpenDatabaseSize( | 
| 603 const string16& origin_identifier) { | 538 const string16& origin_id, const string16& name) { | 
| 604 // TODO(michaeln): Come up with a value according to the the QuotaMgr. | 539 DCHECK(database_connections_.IsDatabaseOpened(origin_id, name)); | 
| 605 CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier); | 540 int64 size = GetDBFileSize(origin_id, name); | 
| 606 if (!origin_info) | 541 database_connections_.SetOpenDatabaseSize(origin_id, name, size); | 
| 607 return 0; | 542 if (origins_info_map_.find(origin_id) != origins_info_map_.end()) | 
| 608 int64 space_available = origin_info->Quota() - origin_info->TotalSize(); | 543 origins_info_map_[origin_id].SetDatabaseSize(name, size); | 
| 609 return (space_available < 0 ? 0 : space_available); | 544 return size; | 
| 610 } | 545 } | 
| 611 | 546 | 
| 612 int64 DatabaseTracker::UpdateCachedDatabaseFileSize( | 547 int64 DatabaseTracker::UpdateOpenDatabaseSizeAndNotify( | 
| 613 const string16& origin_identifier, | 548 const string16& origin_id, const string16& name) { | 
| 614 const string16& database_name) { | 549 DCHECK(database_connections_.IsDatabaseOpened(origin_id, name)); | 
| 615 int64 new_size = GetDBFileSize(origin_identifier, database_name); | 550 int64 new_size = GetDBFileSize(origin_id, name); | 
| 616 CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier); | 551 int64 old_size = database_connections_.GetOpenDatabaseSize(origin_id, name); | 
| 617 if (origin_info) | 552 if (old_size != new_size) { | 
| 618 origin_info->SetDatabaseSize(database_name, new_size); | 553 database_connections_.SetOpenDatabaseSize(origin_id, name, new_size); | 
| 554 if (origins_info_map_.find(origin_id) != origins_info_map_.end()) | |
| 555 origins_info_map_[origin_id].SetDatabaseSize(name, new_size); | |
| 556 if (quota_manager_proxy_) | |
| 557 quota_manager_proxy_->NotifyStorageModified( | |
| 558 quota::QuotaClient::kDatabase, | |
| 559 DatabaseUtil::GetOriginFromIdentifier(origin_id), | |
| 560 quota::kStorageTypeTemporary, | |
| 561 new_size - old_size); | |
| 562 FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseSizeChanged( | |
| 563 origin_id, name, new_size)); | |
| 564 } | |
| 619 return new_size; | 565 return new_size; | 
| 620 } | 566 } | 
| 621 | 567 | 
| 622 void DatabaseTracker::ScheduleDatabaseForDeletion( | 568 void DatabaseTracker::ScheduleDatabaseForDeletion( | 
| 623 const string16& origin_identifier, | 569 const string16& origin_identifier, | 
| 624 const string16& database_name) { | 570 const string16& database_name) { | 
| 625 DCHECK(database_connections_.IsDatabaseOpened(origin_identifier, | 571 DCHECK(database_connections_.IsDatabaseOpened(origin_identifier, | 
| 626 database_name)); | 572 database_name)); | 
| 627 dbs_to_be_deleted_[origin_identifier].insert(database_name); | 573 dbs_to_be_deleted_[origin_identifier].insert(database_name); | 
| 628 FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseScheduledForDeletion( | 574 FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseScheduledForDeletion( | 
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 833 std::string basename = file_path.BaseName().MaybeAsASCII(); | 779 std::string basename = file_path.BaseName().MaybeAsASCII(); | 
| 834 if (!basename.empty() && | 780 if (!basename.empty() && | 
| 835 !StartsWithASCII(basename, kExtensionOriginIdentifierPrefix, true)) { | 781 !StartsWithASCII(basename, kExtensionOriginIdentifierPrefix, true)) { | 
| 836 file_util::Delete(file_path, true); | 782 file_util::Delete(file_path, true); | 
| 837 } | 783 } | 
| 838 } | 784 } | 
| 839 } | 785 } | 
| 840 } | 786 } | 
| 841 | 787 | 
| 842 } // namespace webkit_database | 788 } // namespace webkit_database | 
| OLD | NEW |