| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 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 #include "webkit/browser/quota/quota_manager.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <deque> | |
| 9 #include <functional> | |
| 10 #include <set> | |
| 11 | |
| 12 #include "base/bind.h" | |
| 13 #include "base/bind_helpers.h" | |
| 14 #include "base/callback.h" | |
| 15 #include "base/command_line.h" | |
| 16 #include "base/file_util.h" | |
| 17 #include "base/files/file_path.h" | |
| 18 #include "base/metrics/histogram.h" | |
| 19 #include "base/sequenced_task_runner.h" | |
| 20 #include "base/single_thread_task_runner.h" | |
| 21 #include "base/strings/string_number_conversions.h" | |
| 22 #include "base/sys_info.h" | |
| 23 #include "base/task_runner_util.h" | |
| 24 #include "base/time/time.h" | |
| 25 #include "net/base/net_util.h" | |
| 26 #include "webkit/browser/quota/quota_database.h" | |
| 27 #include "webkit/browser/quota/quota_manager_proxy.h" | |
| 28 #include "webkit/browser/quota/quota_temporary_storage_evictor.h" | |
| 29 #include "webkit/browser/quota/storage_monitor.h" | |
| 30 #include "webkit/browser/quota/usage_tracker.h" | |
| 31 #include "webkit/common/quota/quota_types.h" | |
| 32 | |
| 33 #define UMA_HISTOGRAM_MBYTES(name, sample) \ | |
| 34 UMA_HISTOGRAM_CUSTOM_COUNTS( \ | |
| 35 (name), static_cast<int>((sample) / kMBytes), \ | |
| 36 1, 10 * 1024 * 1024 /* 10TB */, 100) | |
| 37 | |
| 38 namespace quota { | |
| 39 | |
| 40 namespace { | |
| 41 | |
| 42 const int64 kMBytes = 1024 * 1024; | |
| 43 const int kMinutesInMilliSeconds = 60 * 1000; | |
| 44 | |
| 45 const int64 kReportHistogramInterval = 60 * 60 * 1000; // 1 hour | |
| 46 const double kTemporaryQuotaRatioToAvail = 1.0 / 3.0; // 33% | |
| 47 | |
| 48 } // namespace | |
| 49 | |
| 50 // Arbitrary for now, but must be reasonably small so that | |
| 51 // in-memory databases can fit. | |
| 52 // TODO(kinuko): Refer SysInfo::AmountOfPhysicalMemory() to determine this. | |
| 53 const int64 QuotaManager::kIncognitoDefaultQuotaLimit = 100 * kMBytes; | |
| 54 | |
| 55 const int64 QuotaManager::kNoLimit = kint64max; | |
| 56 | |
| 57 const int QuotaManager::kPerHostTemporaryPortion = 5; // 20% | |
| 58 | |
| 59 // Cap size for per-host persistent quota determined by the histogram. | |
| 60 // This is a bit lax value because the histogram says nothing about per-host | |
| 61 // persistent storage usage and we determined by global persistent storage | |
| 62 // usage that is less than 10GB for almost all users. | |
| 63 const int64 QuotaManager::kPerHostPersistentQuotaLimit = 10 * 1024 * kMBytes; | |
| 64 | |
| 65 const char QuotaManager::kDatabaseName[] = "QuotaManager"; | |
| 66 | |
| 67 const int QuotaManager::kThresholdOfErrorsToBeBlacklisted = 3; | |
| 68 | |
| 69 // Preserve kMinimumPreserveForSystem disk space for system book-keeping | |
| 70 // when returning the quota to unlimited apps/extensions. | |
| 71 // TODO(kinuko): This should be like 10% of the actual disk space. | |
| 72 // For now we simply use a constant as getting the disk size needs | |
| 73 // platform-dependent code. (http://crbug.com/178976) | |
| 74 int64 QuotaManager::kMinimumPreserveForSystem = 1024 * kMBytes; | |
| 75 | |
| 76 const int QuotaManager::kEvictionIntervalInMilliSeconds = | |
| 77 30 * kMinutesInMilliSeconds; | |
| 78 | |
| 79 // Heuristics: assuming average cloud server allows a few Gigs storage | |
| 80 // on the server side and the storage needs to be shared for user data | |
| 81 // and by multiple apps. | |
| 82 int64 QuotaManager::kSyncableStorageDefaultHostQuota = 500 * kMBytes; | |
| 83 | |
| 84 namespace { | |
| 85 | |
| 86 void CountOriginType(const std::set<GURL>& origins, | |
| 87 SpecialStoragePolicy* policy, | |
| 88 size_t* protected_origins, | |
| 89 size_t* unlimited_origins) { | |
| 90 DCHECK(protected_origins); | |
| 91 DCHECK(unlimited_origins); | |
| 92 *protected_origins = 0; | |
| 93 *unlimited_origins = 0; | |
| 94 if (!policy) | |
| 95 return; | |
| 96 for (std::set<GURL>::const_iterator itr = origins.begin(); | |
| 97 itr != origins.end(); | |
| 98 ++itr) { | |
| 99 if (policy->IsStorageProtected(*itr)) | |
| 100 ++*protected_origins; | |
| 101 if (policy->IsStorageUnlimited(*itr)) | |
| 102 ++*unlimited_origins; | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 bool SetTemporaryGlobalOverrideQuotaOnDBThread(int64* new_quota, | |
| 107 QuotaDatabase* database) { | |
| 108 DCHECK(database); | |
| 109 if (!database->SetQuotaConfigValue( | |
| 110 QuotaDatabase::kTemporaryQuotaOverrideKey, *new_quota)) { | |
| 111 *new_quota = -1; | |
| 112 return false; | |
| 113 } | |
| 114 return true; | |
| 115 } | |
| 116 | |
| 117 bool GetPersistentHostQuotaOnDBThread(const std::string& host, | |
| 118 int64* quota, | |
| 119 QuotaDatabase* database) { | |
| 120 DCHECK(database); | |
| 121 database->GetHostQuota(host, kStorageTypePersistent, quota); | |
| 122 return true; | |
| 123 } | |
| 124 | |
| 125 bool SetPersistentHostQuotaOnDBThread(const std::string& host, | |
| 126 int64* new_quota, | |
| 127 QuotaDatabase* database) { | |
| 128 DCHECK(database); | |
| 129 if (database->SetHostQuota(host, kStorageTypePersistent, *new_quota)) | |
| 130 return true; | |
| 131 *new_quota = 0; | |
| 132 return false; | |
| 133 } | |
| 134 | |
| 135 bool InitializeOnDBThread(int64* temporary_quota_override, | |
| 136 int64* desired_available_space, | |
| 137 QuotaDatabase* database) { | |
| 138 DCHECK(database); | |
| 139 database->GetQuotaConfigValue(QuotaDatabase::kTemporaryQuotaOverrideKey, | |
| 140 temporary_quota_override); | |
| 141 database->GetQuotaConfigValue(QuotaDatabase::kDesiredAvailableSpaceKey, | |
| 142 desired_available_space); | |
| 143 return true; | |
| 144 } | |
| 145 | |
| 146 bool GetLRUOriginOnDBThread(StorageType type, | |
| 147 std::set<GURL>* exceptions, | |
| 148 SpecialStoragePolicy* policy, | |
| 149 GURL* url, | |
| 150 QuotaDatabase* database) { | |
| 151 DCHECK(database); | |
| 152 database->GetLRUOrigin(type, *exceptions, policy, url); | |
| 153 return true; | |
| 154 } | |
| 155 | |
| 156 bool DeleteOriginInfoOnDBThread(const GURL& origin, | |
| 157 StorageType type, | |
| 158 QuotaDatabase* database) { | |
| 159 DCHECK(database); | |
| 160 return database->DeleteOriginInfo(origin, type); | |
| 161 } | |
| 162 | |
| 163 bool InitializeTemporaryOriginsInfoOnDBThread(const std::set<GURL>* origins, | |
| 164 QuotaDatabase* database) { | |
| 165 DCHECK(database); | |
| 166 if (database->IsOriginDatabaseBootstrapped()) | |
| 167 return true; | |
| 168 | |
| 169 // Register existing origins with 0 last time access. | |
| 170 if (database->RegisterInitialOriginInfo(*origins, kStorageTypeTemporary)) { | |
| 171 database->SetOriginDatabaseBootstrapped(true); | |
| 172 return true; | |
| 173 } | |
| 174 return false; | |
| 175 } | |
| 176 | |
| 177 bool UpdateAccessTimeOnDBThread(const GURL& origin, | |
| 178 StorageType type, | |
| 179 base::Time accessed_time, | |
| 180 QuotaDatabase* database) { | |
| 181 DCHECK(database); | |
| 182 return database->SetOriginLastAccessTime(origin, type, accessed_time); | |
| 183 } | |
| 184 | |
| 185 bool UpdateModifiedTimeOnDBThread(const GURL& origin, | |
| 186 StorageType type, | |
| 187 base::Time modified_time, | |
| 188 QuotaDatabase* database) { | |
| 189 DCHECK(database); | |
| 190 return database->SetOriginLastModifiedTime(origin, type, modified_time); | |
| 191 } | |
| 192 | |
| 193 int64 CallSystemGetAmountOfFreeDiskSpace(const base::FilePath& profile_path) { | |
| 194 // Ensure the profile path exists. | |
| 195 if (!base::CreateDirectory(profile_path)) { | |
| 196 LOG(WARNING) << "Create directory failed for path" << profile_path.value(); | |
| 197 return 0; | |
| 198 } | |
| 199 return base::SysInfo::AmountOfFreeDiskSpace(profile_path); | |
| 200 } | |
| 201 | |
| 202 int64 CalculateTemporaryGlobalQuota(int64 global_limited_usage, | |
| 203 int64 available_space) { | |
| 204 DCHECK_GE(global_limited_usage, 0); | |
| 205 int64 avail_space = available_space; | |
| 206 if (avail_space < kint64max - global_limited_usage) { | |
| 207 // We basically calculate the temporary quota by | |
| 208 // [available_space + space_used_for_temp] * kTempQuotaRatio, | |
| 209 // but make sure we'll have no overflow. | |
| 210 avail_space += global_limited_usage; | |
| 211 } | |
| 212 return avail_space * kTemporaryQuotaRatioToAvail; | |
| 213 } | |
| 214 | |
| 215 void DispatchTemporaryGlobalQuotaCallback( | |
| 216 const QuotaCallback& callback, | |
| 217 QuotaStatusCode status, | |
| 218 const UsageAndQuota& usage_and_quota) { | |
| 219 if (status != kQuotaStatusOk) { | |
| 220 callback.Run(status, 0); | |
| 221 return; | |
| 222 } | |
| 223 | |
| 224 callback.Run(status, CalculateTemporaryGlobalQuota( | |
| 225 usage_and_quota.global_limited_usage, | |
| 226 usage_and_quota.available_disk_space)); | |
| 227 } | |
| 228 | |
| 229 int64 CalculateQuotaWithDiskSpace( | |
| 230 int64 available_disk_space, int64 usage, int64 quota) { | |
| 231 if (available_disk_space < QuotaManager::kMinimumPreserveForSystem) { | |
| 232 LOG(WARNING) | |
| 233 << "Running out of disk space for profile." | |
| 234 << " QuotaManager starts forbidding further quota consumption."; | |
| 235 return usage; | |
| 236 } | |
| 237 | |
| 238 if (quota < usage) { | |
| 239 // No more space; cap the quota to the current usage. | |
| 240 return usage; | |
| 241 } | |
| 242 | |
| 243 available_disk_space -= QuotaManager::kMinimumPreserveForSystem; | |
| 244 if (available_disk_space < quota - usage) | |
| 245 return available_disk_space + usage; | |
| 246 | |
| 247 return quota; | |
| 248 } | |
| 249 | |
| 250 int64 CalculateTemporaryHostQuota(int64 host_usage, | |
| 251 int64 global_quota, | |
| 252 int64 global_limited_usage) { | |
| 253 DCHECK_GE(global_limited_usage, 0); | |
| 254 int64 host_quota = global_quota / QuotaManager::kPerHostTemporaryPortion; | |
| 255 if (global_limited_usage > global_quota) | |
| 256 host_quota = std::min(host_quota, host_usage); | |
| 257 return host_quota; | |
| 258 } | |
| 259 | |
| 260 void DispatchUsageAndQuotaForWebApps( | |
| 261 StorageType type, | |
| 262 bool is_incognito, | |
| 263 bool is_unlimited, | |
| 264 bool can_query_disk_size, | |
| 265 const QuotaManager::GetUsageAndQuotaCallback& callback, | |
| 266 QuotaStatusCode status, | |
| 267 const UsageAndQuota& usage_and_quota) { | |
| 268 if (status != kQuotaStatusOk) { | |
| 269 callback.Run(status, 0, 0); | |
| 270 return; | |
| 271 } | |
| 272 | |
| 273 int64 usage = usage_and_quota.usage; | |
| 274 int64 quota = usage_and_quota.quota; | |
| 275 | |
| 276 if (type == kStorageTypeTemporary && !is_unlimited) { | |
| 277 quota = CalculateTemporaryHostQuota( | |
| 278 usage, quota, usage_and_quota.global_limited_usage); | |
| 279 } | |
| 280 | |
| 281 if (is_incognito) { | |
| 282 quota = std::min(quota, QuotaManager::kIncognitoDefaultQuotaLimit); | |
| 283 callback.Run(status, usage, quota); | |
| 284 return; | |
| 285 } | |
| 286 | |
| 287 // For apps with unlimited permission or can_query_disk_size is true (and not | |
| 288 // in incognito mode). | |
| 289 // We assume we can expose the actual disk size for them and cap the quota by | |
| 290 // the available disk space. | |
| 291 if (is_unlimited || can_query_disk_size) { | |
| 292 callback.Run( | |
| 293 status, usage, | |
| 294 CalculateQuotaWithDiskSpace( | |
| 295 usage_and_quota.available_disk_space, | |
| 296 usage, quota)); | |
| 297 return; | |
| 298 } | |
| 299 | |
| 300 callback.Run(status, usage, quota); | |
| 301 } | |
| 302 | |
| 303 } // namespace | |
| 304 | |
| 305 UsageAndQuota::UsageAndQuota() | |
| 306 : usage(0), | |
| 307 global_limited_usage(0), | |
| 308 quota(0), | |
| 309 available_disk_space(0) { | |
| 310 } | |
| 311 | |
| 312 UsageAndQuota::UsageAndQuota( | |
| 313 int64 usage, | |
| 314 int64 global_limited_usage, | |
| 315 int64 quota, | |
| 316 int64 available_disk_space) | |
| 317 : usage(usage), | |
| 318 global_limited_usage(global_limited_usage), | |
| 319 quota(quota), | |
| 320 available_disk_space(available_disk_space) { | |
| 321 } | |
| 322 | |
| 323 class UsageAndQuotaCallbackDispatcher | |
| 324 : public QuotaTask, | |
| 325 public base::SupportsWeakPtr<UsageAndQuotaCallbackDispatcher> { | |
| 326 public: | |
| 327 explicit UsageAndQuotaCallbackDispatcher(QuotaManager* manager) | |
| 328 : QuotaTask(manager), | |
| 329 has_usage_(false), | |
| 330 has_global_limited_usage_(false), | |
| 331 has_quota_(false), | |
| 332 has_available_disk_space_(false), | |
| 333 status_(kQuotaStatusUnknown), | |
| 334 usage_and_quota_(-1, -1, -1, -1), | |
| 335 waiting_callbacks_(1) {} | |
| 336 | |
| 337 virtual ~UsageAndQuotaCallbackDispatcher() {} | |
| 338 | |
| 339 void WaitForResults(const QuotaManager::UsageAndQuotaCallback& callback) { | |
| 340 callback_ = callback; | |
| 341 Start(); | |
| 342 } | |
| 343 | |
| 344 void set_usage(int64 usage) { | |
| 345 usage_and_quota_.usage = usage; | |
| 346 has_usage_ = true; | |
| 347 } | |
| 348 | |
| 349 void set_global_limited_usage(int64 global_limited_usage) { | |
| 350 usage_and_quota_.global_limited_usage = global_limited_usage; | |
| 351 has_global_limited_usage_ = true; | |
| 352 } | |
| 353 | |
| 354 void set_quota(int64 quota) { | |
| 355 usage_and_quota_.quota = quota; | |
| 356 has_quota_ = true; | |
| 357 } | |
| 358 | |
| 359 void set_available_disk_space(int64 available_disk_space) { | |
| 360 usage_and_quota_.available_disk_space = available_disk_space; | |
| 361 has_available_disk_space_ = true; | |
| 362 } | |
| 363 | |
| 364 UsageCallback GetHostUsageCallback() { | |
| 365 ++waiting_callbacks_; | |
| 366 has_usage_ = true; | |
| 367 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetHostUsage, | |
| 368 AsWeakPtr()); | |
| 369 } | |
| 370 | |
| 371 UsageCallback GetGlobalLimitedUsageCallback() { | |
| 372 ++waiting_callbacks_; | |
| 373 has_global_limited_usage_ = true; | |
| 374 return base::Bind( | |
| 375 &UsageAndQuotaCallbackDispatcher::DidGetGlobalLimitedUsage, | |
| 376 AsWeakPtr()); | |
| 377 } | |
| 378 | |
| 379 QuotaCallback GetQuotaCallback() { | |
| 380 ++waiting_callbacks_; | |
| 381 has_quota_ = true; | |
| 382 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetQuota, | |
| 383 AsWeakPtr()); | |
| 384 } | |
| 385 | |
| 386 QuotaCallback GetAvailableSpaceCallback() { | |
| 387 ++waiting_callbacks_; | |
| 388 has_available_disk_space_ = true; | |
| 389 return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetAvailableSpace, | |
| 390 AsWeakPtr()); | |
| 391 } | |
| 392 | |
| 393 private: | |
| 394 void DidGetHostUsage(int64 usage) { | |
| 395 if (status_ == kQuotaStatusUnknown) | |
| 396 status_ = kQuotaStatusOk; | |
| 397 usage_and_quota_.usage = usage; | |
| 398 CheckCompleted(); | |
| 399 } | |
| 400 | |
| 401 void DidGetGlobalLimitedUsage(int64 limited_usage) { | |
| 402 if (status_ == kQuotaStatusUnknown) | |
| 403 status_ = kQuotaStatusOk; | |
| 404 usage_and_quota_.global_limited_usage = limited_usage; | |
| 405 CheckCompleted(); | |
| 406 } | |
| 407 | |
| 408 void DidGetQuota(QuotaStatusCode status, int64 quota) { | |
| 409 if (status_ == kQuotaStatusUnknown || status_ == kQuotaStatusOk) | |
| 410 status_ = status; | |
| 411 usage_and_quota_.quota = quota; | |
| 412 CheckCompleted(); | |
| 413 } | |
| 414 | |
| 415 void DidGetAvailableSpace(QuotaStatusCode status, int64 space) { | |
| 416 DCHECK_GE(space, 0); | |
| 417 if (status_ == kQuotaStatusUnknown || status_ == kQuotaStatusOk) | |
| 418 status_ = status; | |
| 419 usage_and_quota_.available_disk_space = space; | |
| 420 CheckCompleted(); | |
| 421 } | |
| 422 | |
| 423 virtual void Run() OVERRIDE { | |
| 424 // We initialize waiting_callbacks to 1 so that we won't run | |
| 425 // the completion callback until here even some of the callbacks | |
| 426 // are dispatched synchronously. | |
| 427 CheckCompleted(); | |
| 428 } | |
| 429 | |
| 430 virtual void Aborted() OVERRIDE { | |
| 431 callback_.Run(kQuotaErrorAbort, UsageAndQuota()); | |
| 432 DeleteSoon(); | |
| 433 } | |
| 434 | |
| 435 virtual void Completed() OVERRIDE { | |
| 436 DCHECK(!has_usage_ || usage_and_quota_.usage >= 0); | |
| 437 DCHECK(!has_global_limited_usage_ || | |
| 438 usage_and_quota_.global_limited_usage >= 0); | |
| 439 DCHECK(!has_quota_ || usage_and_quota_.quota >= 0); | |
| 440 DCHECK(!has_available_disk_space_ || | |
| 441 usage_and_quota_.available_disk_space >= 0); | |
| 442 | |
| 443 callback_.Run(status_, usage_and_quota_); | |
| 444 DeleteSoon(); | |
| 445 } | |
| 446 | |
| 447 void CheckCompleted() { | |
| 448 if (--waiting_callbacks_ <= 0) | |
| 449 CallCompleted(); | |
| 450 } | |
| 451 | |
| 452 // For sanity checks, they're checked only when DCHECK is on. | |
| 453 bool has_usage_; | |
| 454 bool has_global_limited_usage_; | |
| 455 bool has_quota_; | |
| 456 bool has_available_disk_space_; | |
| 457 | |
| 458 QuotaStatusCode status_; | |
| 459 UsageAndQuota usage_and_quota_; | |
| 460 QuotaManager::UsageAndQuotaCallback callback_; | |
| 461 int waiting_callbacks_; | |
| 462 | |
| 463 DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaCallbackDispatcher); | |
| 464 }; | |
| 465 | |
| 466 class QuotaManager::GetUsageInfoTask : public QuotaTask { | |
| 467 public: | |
| 468 GetUsageInfoTask( | |
| 469 QuotaManager* manager, | |
| 470 const GetUsageInfoCallback& callback) | |
| 471 : QuotaTask(manager), | |
| 472 callback_(callback), | |
| 473 weak_factory_(this) { | |
| 474 } | |
| 475 | |
| 476 protected: | |
| 477 virtual void Run() OVERRIDE { | |
| 478 remaining_trackers_ = 3; | |
| 479 // This will populate cached hosts and usage info. | |
| 480 manager()->GetUsageTracker(kStorageTypeTemporary)->GetGlobalUsage( | |
| 481 base::Bind(&GetUsageInfoTask::DidGetGlobalUsage, | |
| 482 weak_factory_.GetWeakPtr(), | |
| 483 kStorageTypeTemporary)); | |
| 484 manager()->GetUsageTracker(kStorageTypePersistent)->GetGlobalUsage( | |
| 485 base::Bind(&GetUsageInfoTask::DidGetGlobalUsage, | |
| 486 weak_factory_.GetWeakPtr(), | |
| 487 kStorageTypePersistent)); | |
| 488 manager()->GetUsageTracker(kStorageTypeSyncable)->GetGlobalUsage( | |
| 489 base::Bind(&GetUsageInfoTask::DidGetGlobalUsage, | |
| 490 weak_factory_.GetWeakPtr(), | |
| 491 kStorageTypeSyncable)); | |
| 492 } | |
| 493 | |
| 494 virtual void Completed() OVERRIDE { | |
| 495 callback_.Run(entries_); | |
| 496 DeleteSoon(); | |
| 497 } | |
| 498 | |
| 499 virtual void Aborted() OVERRIDE { | |
| 500 callback_.Run(UsageInfoEntries()); | |
| 501 DeleteSoon(); | |
| 502 } | |
| 503 | |
| 504 private: | |
| 505 void AddEntries(StorageType type, UsageTracker* tracker) { | |
| 506 std::map<std::string, int64> host_usage; | |
| 507 tracker->GetCachedHostsUsage(&host_usage); | |
| 508 for (std::map<std::string, int64>::const_iterator iter = host_usage.begin(); | |
| 509 iter != host_usage.end(); | |
| 510 ++iter) { | |
| 511 entries_.push_back(UsageInfo(iter->first, type, iter->second)); | |
| 512 } | |
| 513 if (--remaining_trackers_ == 0) | |
| 514 CallCompleted(); | |
| 515 } | |
| 516 | |
| 517 void DidGetGlobalUsage(StorageType type, int64, int64) { | |
| 518 DCHECK(manager()->GetUsageTracker(type)); | |
| 519 AddEntries(type, manager()->GetUsageTracker(type)); | |
| 520 } | |
| 521 | |
| 522 QuotaManager* manager() const { | |
| 523 return static_cast<QuotaManager*>(observer()); | |
| 524 } | |
| 525 | |
| 526 GetUsageInfoCallback callback_; | |
| 527 UsageInfoEntries entries_; | |
| 528 int remaining_trackers_; | |
| 529 base::WeakPtrFactory<GetUsageInfoTask> weak_factory_; | |
| 530 | |
| 531 DISALLOW_COPY_AND_ASSIGN(GetUsageInfoTask); | |
| 532 }; | |
| 533 | |
| 534 class QuotaManager::OriginDataDeleter : public QuotaTask { | |
| 535 public: | |
| 536 OriginDataDeleter(QuotaManager* manager, | |
| 537 const GURL& origin, | |
| 538 StorageType type, | |
| 539 int quota_client_mask, | |
| 540 const StatusCallback& callback) | |
| 541 : QuotaTask(manager), | |
| 542 origin_(origin), | |
| 543 type_(type), | |
| 544 quota_client_mask_(quota_client_mask), | |
| 545 error_count_(0), | |
| 546 remaining_clients_(-1), | |
| 547 skipped_clients_(0), | |
| 548 callback_(callback), | |
| 549 weak_factory_(this) {} | |
| 550 | |
| 551 protected: | |
| 552 virtual void Run() OVERRIDE { | |
| 553 error_count_ = 0; | |
| 554 remaining_clients_ = manager()->clients_.size(); | |
| 555 for (QuotaClientList::iterator iter = manager()->clients_.begin(); | |
| 556 iter != manager()->clients_.end(); ++iter) { | |
| 557 if (quota_client_mask_ & (*iter)->id()) { | |
| 558 (*iter)->DeleteOriginData( | |
| 559 origin_, type_, | |
| 560 base::Bind(&OriginDataDeleter::DidDeleteOriginData, | |
| 561 weak_factory_.GetWeakPtr())); | |
| 562 } else { | |
| 563 ++skipped_clients_; | |
| 564 if (--remaining_clients_ == 0) | |
| 565 CallCompleted(); | |
| 566 } | |
| 567 } | |
| 568 } | |
| 569 | |
| 570 virtual void Completed() OVERRIDE { | |
| 571 if (error_count_ == 0) { | |
| 572 // Only remove the entire origin if we didn't skip any client types. | |
| 573 if (skipped_clients_ == 0) | |
| 574 manager()->DeleteOriginFromDatabase(origin_, type_); | |
| 575 callback_.Run(kQuotaStatusOk); | |
| 576 } else { | |
| 577 callback_.Run(kQuotaErrorInvalidModification); | |
| 578 } | |
| 579 DeleteSoon(); | |
| 580 } | |
| 581 | |
| 582 virtual void Aborted() OVERRIDE { | |
| 583 callback_.Run(kQuotaErrorAbort); | |
| 584 DeleteSoon(); | |
| 585 } | |
| 586 | |
| 587 private: | |
| 588 void DidDeleteOriginData(QuotaStatusCode status) { | |
| 589 DCHECK_GT(remaining_clients_, 0); | |
| 590 | |
| 591 if (status != kQuotaStatusOk) | |
| 592 ++error_count_; | |
| 593 | |
| 594 if (--remaining_clients_ == 0) | |
| 595 CallCompleted(); | |
| 596 } | |
| 597 | |
| 598 QuotaManager* manager() const { | |
| 599 return static_cast<QuotaManager*>(observer()); | |
| 600 } | |
| 601 | |
| 602 GURL origin_; | |
| 603 StorageType type_; | |
| 604 int quota_client_mask_; | |
| 605 int error_count_; | |
| 606 int remaining_clients_; | |
| 607 int skipped_clients_; | |
| 608 StatusCallback callback_; | |
| 609 | |
| 610 base::WeakPtrFactory<OriginDataDeleter> weak_factory_; | |
| 611 DISALLOW_COPY_AND_ASSIGN(OriginDataDeleter); | |
| 612 }; | |
| 613 | |
| 614 class QuotaManager::HostDataDeleter : public QuotaTask { | |
| 615 public: | |
| 616 HostDataDeleter(QuotaManager* manager, | |
| 617 const std::string& host, | |
| 618 StorageType type, | |
| 619 int quota_client_mask, | |
| 620 const StatusCallback& callback) | |
| 621 : QuotaTask(manager), | |
| 622 host_(host), | |
| 623 type_(type), | |
| 624 quota_client_mask_(quota_client_mask), | |
| 625 error_count_(0), | |
| 626 remaining_clients_(-1), | |
| 627 remaining_deleters_(-1), | |
| 628 callback_(callback), | |
| 629 weak_factory_(this) {} | |
| 630 | |
| 631 protected: | |
| 632 virtual void Run() OVERRIDE { | |
| 633 error_count_ = 0; | |
| 634 remaining_clients_ = manager()->clients_.size(); | |
| 635 for (QuotaClientList::iterator iter = manager()->clients_.begin(); | |
| 636 iter != manager()->clients_.end(); ++iter) { | |
| 637 (*iter)->GetOriginsForHost( | |
| 638 type_, host_, | |
| 639 base::Bind(&HostDataDeleter::DidGetOriginsForHost, | |
| 640 weak_factory_.GetWeakPtr())); | |
| 641 } | |
| 642 } | |
| 643 | |
| 644 virtual void Completed() OVERRIDE { | |
| 645 if (error_count_ == 0) { | |
| 646 callback_.Run(kQuotaStatusOk); | |
| 647 } else { | |
| 648 callback_.Run(kQuotaErrorInvalidModification); | |
| 649 } | |
| 650 DeleteSoon(); | |
| 651 } | |
| 652 | |
| 653 virtual void Aborted() OVERRIDE { | |
| 654 callback_.Run(kQuotaErrorAbort); | |
| 655 DeleteSoon(); | |
| 656 } | |
| 657 | |
| 658 private: | |
| 659 void DidGetOriginsForHost(const std::set<GURL>& origins) { | |
| 660 DCHECK_GT(remaining_clients_, 0); | |
| 661 | |
| 662 origins_.insert(origins.begin(), origins.end()); | |
| 663 | |
| 664 if (--remaining_clients_ == 0) { | |
| 665 if (!origins_.empty()) | |
| 666 ScheduleOriginsDeletion(); | |
| 667 else | |
| 668 CallCompleted(); | |
| 669 } | |
| 670 } | |
| 671 | |
| 672 void ScheduleOriginsDeletion() { | |
| 673 remaining_deleters_ = origins_.size(); | |
| 674 for (std::set<GURL>::const_iterator p = origins_.begin(); | |
| 675 p != origins_.end(); | |
| 676 ++p) { | |
| 677 OriginDataDeleter* deleter = | |
| 678 new OriginDataDeleter( | |
| 679 manager(), *p, type_, quota_client_mask_, | |
| 680 base::Bind(&HostDataDeleter::DidDeleteOriginData, | |
| 681 weak_factory_.GetWeakPtr())); | |
| 682 deleter->Start(); | |
| 683 } | |
| 684 } | |
| 685 | |
| 686 void DidDeleteOriginData(QuotaStatusCode status) { | |
| 687 DCHECK_GT(remaining_deleters_, 0); | |
| 688 | |
| 689 if (status != kQuotaStatusOk) | |
| 690 ++error_count_; | |
| 691 | |
| 692 if (--remaining_deleters_ == 0) | |
| 693 CallCompleted(); | |
| 694 } | |
| 695 | |
| 696 QuotaManager* manager() const { | |
| 697 return static_cast<QuotaManager*>(observer()); | |
| 698 } | |
| 699 | |
| 700 std::string host_; | |
| 701 StorageType type_; | |
| 702 int quota_client_mask_; | |
| 703 std::set<GURL> origins_; | |
| 704 int error_count_; | |
| 705 int remaining_clients_; | |
| 706 int remaining_deleters_; | |
| 707 StatusCallback callback_; | |
| 708 | |
| 709 base::WeakPtrFactory<HostDataDeleter> weak_factory_; | |
| 710 DISALLOW_COPY_AND_ASSIGN(HostDataDeleter); | |
| 711 }; | |
| 712 | |
| 713 class QuotaManager::GetModifiedSinceHelper { | |
| 714 public: | |
| 715 bool GetModifiedSinceOnDBThread(StorageType type, | |
| 716 base::Time modified_since, | |
| 717 QuotaDatabase* database) { | |
| 718 DCHECK(database); | |
| 719 return database->GetOriginsModifiedSince(type, &origins_, modified_since); | |
| 720 } | |
| 721 | |
| 722 void DidGetModifiedSince(const base::WeakPtr<QuotaManager>& manager, | |
| 723 const GetOriginsCallback& callback, | |
| 724 StorageType type, | |
| 725 bool success) { | |
| 726 if (!manager) { | |
| 727 // The operation was aborted. | |
| 728 callback.Run(std::set<GURL>(), type); | |
| 729 return; | |
| 730 } | |
| 731 manager->DidDatabaseWork(success); | |
| 732 callback.Run(origins_, type); | |
| 733 } | |
| 734 | |
| 735 private: | |
| 736 std::set<GURL> origins_; | |
| 737 }; | |
| 738 | |
| 739 class QuotaManager::DumpQuotaTableHelper { | |
| 740 public: | |
| 741 bool DumpQuotaTableOnDBThread(QuotaDatabase* database) { | |
| 742 DCHECK(database); | |
| 743 return database->DumpQuotaTable( | |
| 744 base::Bind(&DumpQuotaTableHelper::AppendEntry, base::Unretained(this))); | |
| 745 } | |
| 746 | |
| 747 void DidDumpQuotaTable(const base::WeakPtr<QuotaManager>& manager, | |
| 748 const DumpQuotaTableCallback& callback, | |
| 749 bool success) { | |
| 750 if (!manager) { | |
| 751 // The operation was aborted. | |
| 752 callback.Run(QuotaTableEntries()); | |
| 753 return; | |
| 754 } | |
| 755 manager->DidDatabaseWork(success); | |
| 756 callback.Run(entries_); | |
| 757 } | |
| 758 | |
| 759 private: | |
| 760 bool AppendEntry(const QuotaTableEntry& entry) { | |
| 761 entries_.push_back(entry); | |
| 762 return true; | |
| 763 } | |
| 764 | |
| 765 QuotaTableEntries entries_; | |
| 766 }; | |
| 767 | |
| 768 class QuotaManager::DumpOriginInfoTableHelper { | |
| 769 public: | |
| 770 bool DumpOriginInfoTableOnDBThread(QuotaDatabase* database) { | |
| 771 DCHECK(database); | |
| 772 return database->DumpOriginInfoTable( | |
| 773 base::Bind(&DumpOriginInfoTableHelper::AppendEntry, | |
| 774 base::Unretained(this))); | |
| 775 } | |
| 776 | |
| 777 void DidDumpOriginInfoTable(const base::WeakPtr<QuotaManager>& manager, | |
| 778 const DumpOriginInfoTableCallback& callback, | |
| 779 bool success) { | |
| 780 if (!manager) { | |
| 781 // The operation was aborted. | |
| 782 callback.Run(OriginInfoTableEntries()); | |
| 783 return; | |
| 784 } | |
| 785 manager->DidDatabaseWork(success); | |
| 786 callback.Run(entries_); | |
| 787 } | |
| 788 | |
| 789 private: | |
| 790 bool AppendEntry(const OriginInfoTableEntry& entry) { | |
| 791 entries_.push_back(entry); | |
| 792 return true; | |
| 793 } | |
| 794 | |
| 795 OriginInfoTableEntries entries_; | |
| 796 }; | |
| 797 | |
| 798 // QuotaManager --------------------------------------------------------------- | |
| 799 | |
| 800 QuotaManager::QuotaManager(bool is_incognito, | |
| 801 const base::FilePath& profile_path, | |
| 802 base::SingleThreadTaskRunner* io_thread, | |
| 803 base::SequencedTaskRunner* db_thread, | |
| 804 SpecialStoragePolicy* special_storage_policy) | |
| 805 : is_incognito_(is_incognito), | |
| 806 profile_path_(profile_path), | |
| 807 proxy_(new QuotaManagerProxy( | |
| 808 this, io_thread)), | |
| 809 db_disabled_(false), | |
| 810 eviction_disabled_(false), | |
| 811 io_thread_(io_thread), | |
| 812 db_thread_(db_thread), | |
| 813 temporary_quota_initialized_(false), | |
| 814 temporary_quota_override_(-1), | |
| 815 desired_available_space_(-1), | |
| 816 special_storage_policy_(special_storage_policy), | |
| 817 get_disk_space_fn_(&CallSystemGetAmountOfFreeDiskSpace), | |
| 818 storage_monitor_(new StorageMonitor(this)), | |
| 819 weak_factory_(this) { | |
| 820 } | |
| 821 | |
| 822 void QuotaManager::GetUsageInfo(const GetUsageInfoCallback& callback) { | |
| 823 LazyInitialize(); | |
| 824 GetUsageInfoTask* get_usage_info = new GetUsageInfoTask(this, callback); | |
| 825 get_usage_info->Start(); | |
| 826 } | |
| 827 | |
| 828 void QuotaManager::GetUsageAndQuotaForWebApps( | |
| 829 const GURL& origin, | |
| 830 StorageType type, | |
| 831 const GetUsageAndQuotaCallback& callback) { | |
| 832 if (type != kStorageTypeTemporary && | |
| 833 type != kStorageTypePersistent && | |
| 834 type != kStorageTypeSyncable) { | |
| 835 callback.Run(kQuotaErrorNotSupported, 0, 0); | |
| 836 return; | |
| 837 } | |
| 838 | |
| 839 DCHECK(origin == origin.GetOrigin()); | |
| 840 LazyInitialize(); | |
| 841 | |
| 842 bool unlimited = IsStorageUnlimited(origin, type); | |
| 843 bool can_query_disk_size = CanQueryDiskSize(origin); | |
| 844 | |
| 845 UsageAndQuotaCallbackDispatcher* dispatcher = | |
| 846 new UsageAndQuotaCallbackDispatcher(this); | |
| 847 | |
| 848 UsageAndQuota usage_and_quota; | |
| 849 if (unlimited) { | |
| 850 dispatcher->set_quota(kNoLimit); | |
| 851 } else { | |
| 852 if (type == kStorageTypeTemporary) { | |
| 853 GetUsageTracker(type)->GetGlobalLimitedUsage( | |
| 854 dispatcher->GetGlobalLimitedUsageCallback()); | |
| 855 GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback()); | |
| 856 } else if (type == kStorageTypePersistent) { | |
| 857 GetPersistentHostQuota(net::GetHostOrSpecFromURL(origin), | |
| 858 dispatcher->GetQuotaCallback()); | |
| 859 } else { | |
| 860 dispatcher->set_quota(kSyncableStorageDefaultHostQuota); | |
| 861 } | |
| 862 } | |
| 863 | |
| 864 DCHECK(GetUsageTracker(type)); | |
| 865 GetUsageTracker(type)->GetHostUsage(net::GetHostOrSpecFromURL(origin), | |
| 866 dispatcher->GetHostUsageCallback()); | |
| 867 | |
| 868 if (!is_incognito_ && (unlimited || can_query_disk_size)) | |
| 869 GetAvailableSpace(dispatcher->GetAvailableSpaceCallback()); | |
| 870 | |
| 871 dispatcher->WaitForResults(base::Bind( | |
| 872 &DispatchUsageAndQuotaForWebApps, | |
| 873 type, is_incognito_, unlimited, can_query_disk_size, | |
| 874 callback)); | |
| 875 } | |
| 876 | |
| 877 void QuotaManager::GetUsageAndQuota( | |
| 878 const GURL& origin, StorageType type, | |
| 879 const GetUsageAndQuotaCallback& callback) { | |
| 880 DCHECK(origin == origin.GetOrigin()); | |
| 881 | |
| 882 if (IsStorageUnlimited(origin, type)) { | |
| 883 callback.Run(kQuotaStatusOk, 0, kNoLimit); | |
| 884 return; | |
| 885 } | |
| 886 | |
| 887 GetUsageAndQuotaForWebApps(origin, type, callback); | |
| 888 } | |
| 889 | |
| 890 void QuotaManager::NotifyStorageAccessed( | |
| 891 QuotaClient::ID client_id, | |
| 892 const GURL& origin, StorageType type) { | |
| 893 DCHECK(origin == origin.GetOrigin()); | |
| 894 NotifyStorageAccessedInternal(client_id, origin, type, base::Time::Now()); | |
| 895 } | |
| 896 | |
| 897 void QuotaManager::NotifyStorageModified( | |
| 898 QuotaClient::ID client_id, | |
| 899 const GURL& origin, StorageType type, int64 delta) { | |
| 900 DCHECK(origin == origin.GetOrigin()); | |
| 901 NotifyStorageModifiedInternal(client_id, origin, type, delta, | |
| 902 base::Time::Now()); | |
| 903 } | |
| 904 | |
| 905 void QuotaManager::NotifyOriginInUse(const GURL& origin) { | |
| 906 DCHECK(io_thread_->BelongsToCurrentThread()); | |
| 907 origins_in_use_[origin]++; | |
| 908 } | |
| 909 | |
| 910 void QuotaManager::NotifyOriginNoLongerInUse(const GURL& origin) { | |
| 911 DCHECK(io_thread_->BelongsToCurrentThread()); | |
| 912 DCHECK(IsOriginInUse(origin)); | |
| 913 int& count = origins_in_use_[origin]; | |
| 914 if (--count == 0) | |
| 915 origins_in_use_.erase(origin); | |
| 916 } | |
| 917 | |
| 918 void QuotaManager::SetUsageCacheEnabled(QuotaClient::ID client_id, | |
| 919 const GURL& origin, | |
| 920 StorageType type, | |
| 921 bool enabled) { | |
| 922 LazyInitialize(); | |
| 923 DCHECK(GetUsageTracker(type)); | |
| 924 GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled); | |
| 925 } | |
| 926 | |
| 927 void QuotaManager::DeleteOriginData( | |
| 928 const GURL& origin, StorageType type, int quota_client_mask, | |
| 929 const StatusCallback& callback) { | |
| 930 LazyInitialize(); | |
| 931 | |
| 932 if (origin.is_empty() || clients_.empty()) { | |
| 933 callback.Run(kQuotaStatusOk); | |
| 934 return; | |
| 935 } | |
| 936 | |
| 937 DCHECK(origin == origin.GetOrigin()); | |
| 938 OriginDataDeleter* deleter = | |
| 939 new OriginDataDeleter(this, origin, type, quota_client_mask, callback); | |
| 940 deleter->Start(); | |
| 941 } | |
| 942 | |
| 943 void QuotaManager::DeleteHostData(const std::string& host, | |
| 944 StorageType type, | |
| 945 int quota_client_mask, | |
| 946 const StatusCallback& callback) { | |
| 947 LazyInitialize(); | |
| 948 | |
| 949 if (host.empty() || clients_.empty()) { | |
| 950 callback.Run(kQuotaStatusOk); | |
| 951 return; | |
| 952 } | |
| 953 | |
| 954 HostDataDeleter* deleter = | |
| 955 new HostDataDeleter(this, host, type, quota_client_mask, callback); | |
| 956 deleter->Start(); | |
| 957 } | |
| 958 | |
| 959 void QuotaManager::GetAvailableSpace(const AvailableSpaceCallback& callback) { | |
| 960 if (!available_space_callbacks_.Add(callback)) | |
| 961 return; | |
| 962 | |
| 963 PostTaskAndReplyWithResult(db_thread_.get(), | |
| 964 FROM_HERE, | |
| 965 base::Bind(get_disk_space_fn_, profile_path_), | |
| 966 base::Bind(&QuotaManager::DidGetAvailableSpace, | |
| 967 weak_factory_.GetWeakPtr())); | |
| 968 } | |
| 969 | |
| 970 void QuotaManager::GetTemporaryGlobalQuota(const QuotaCallback& callback) { | |
| 971 LazyInitialize(); | |
| 972 if (!temporary_quota_initialized_) { | |
| 973 db_initialization_callbacks_.Add(base::Bind( | |
| 974 &QuotaManager::GetTemporaryGlobalQuota, | |
| 975 weak_factory_.GetWeakPtr(), callback)); | |
| 976 return; | |
| 977 } | |
| 978 | |
| 979 if (temporary_quota_override_ > 0) { | |
| 980 callback.Run(kQuotaStatusOk, temporary_quota_override_); | |
| 981 return; | |
| 982 } | |
| 983 | |
| 984 UsageAndQuotaCallbackDispatcher* dispatcher = | |
| 985 new UsageAndQuotaCallbackDispatcher(this); | |
| 986 GetUsageTracker(kStorageTypeTemporary)-> | |
| 987 GetGlobalLimitedUsage(dispatcher->GetGlobalLimitedUsageCallback()); | |
| 988 GetAvailableSpace(dispatcher->GetAvailableSpaceCallback()); | |
| 989 dispatcher->WaitForResults( | |
| 990 base::Bind(&DispatchTemporaryGlobalQuotaCallback, callback)); | |
| 991 } | |
| 992 | |
| 993 void QuotaManager::SetTemporaryGlobalOverrideQuota( | |
| 994 int64 new_quota, const QuotaCallback& callback) { | |
| 995 LazyInitialize(); | |
| 996 | |
| 997 if (new_quota < 0) { | |
| 998 if (!callback.is_null()) | |
| 999 callback.Run(kQuotaErrorInvalidModification, -1); | |
| 1000 return; | |
| 1001 } | |
| 1002 | |
| 1003 if (db_disabled_) { | |
| 1004 if (!callback.is_null()) | |
| 1005 callback.Run(kQuotaErrorInvalidAccess, -1); | |
| 1006 return; | |
| 1007 } | |
| 1008 | |
| 1009 int64* new_quota_ptr = new int64(new_quota); | |
| 1010 PostTaskAndReplyWithResultForDBThread( | |
| 1011 FROM_HERE, | |
| 1012 base::Bind(&SetTemporaryGlobalOverrideQuotaOnDBThread, | |
| 1013 base::Unretained(new_quota_ptr)), | |
| 1014 base::Bind(&QuotaManager::DidSetTemporaryGlobalOverrideQuota, | |
| 1015 weak_factory_.GetWeakPtr(), | |
| 1016 callback, | |
| 1017 base::Owned(new_quota_ptr))); | |
| 1018 } | |
| 1019 | |
| 1020 void QuotaManager::GetPersistentHostQuota(const std::string& host, | |
| 1021 const QuotaCallback& callback) { | |
| 1022 LazyInitialize(); | |
| 1023 if (host.empty()) { | |
| 1024 // This could happen if we are called on file:///. | |
| 1025 // TODO(kinuko) We may want to respect --allow-file-access-from-files | |
| 1026 // command line switch. | |
| 1027 callback.Run(kQuotaStatusOk, 0); | |
| 1028 return; | |
| 1029 } | |
| 1030 | |
| 1031 if (!persistent_host_quota_callbacks_.Add(host, callback)) | |
| 1032 return; | |
| 1033 | |
| 1034 int64* quota_ptr = new int64(0); | |
| 1035 PostTaskAndReplyWithResultForDBThread( | |
| 1036 FROM_HERE, | |
| 1037 base::Bind(&GetPersistentHostQuotaOnDBThread, | |
| 1038 host, | |
| 1039 base::Unretained(quota_ptr)), | |
| 1040 base::Bind(&QuotaManager::DidGetPersistentHostQuota, | |
| 1041 weak_factory_.GetWeakPtr(), | |
| 1042 host, | |
| 1043 base::Owned(quota_ptr))); | |
| 1044 } | |
| 1045 | |
| 1046 void QuotaManager::SetPersistentHostQuota(const std::string& host, | |
| 1047 int64 new_quota, | |
| 1048 const QuotaCallback& callback) { | |
| 1049 LazyInitialize(); | |
| 1050 if (host.empty()) { | |
| 1051 // This could happen if we are called on file:///. | |
| 1052 callback.Run(kQuotaErrorNotSupported, 0); | |
| 1053 return; | |
| 1054 } | |
| 1055 | |
| 1056 if (new_quota < 0) { | |
| 1057 callback.Run(kQuotaErrorInvalidModification, -1); | |
| 1058 return; | |
| 1059 } | |
| 1060 | |
| 1061 if (kPerHostPersistentQuotaLimit < new_quota) { | |
| 1062 // Cap the requested size at the per-host quota limit. | |
| 1063 new_quota = kPerHostPersistentQuotaLimit; | |
| 1064 } | |
| 1065 | |
| 1066 if (db_disabled_) { | |
| 1067 callback.Run(kQuotaErrorInvalidAccess, -1); | |
| 1068 return; | |
| 1069 } | |
| 1070 | |
| 1071 int64* new_quota_ptr = new int64(new_quota); | |
| 1072 PostTaskAndReplyWithResultForDBThread( | |
| 1073 FROM_HERE, | |
| 1074 base::Bind(&SetPersistentHostQuotaOnDBThread, | |
| 1075 host, | |
| 1076 base::Unretained(new_quota_ptr)), | |
| 1077 base::Bind(&QuotaManager::DidSetPersistentHostQuota, | |
| 1078 weak_factory_.GetWeakPtr(), | |
| 1079 host, | |
| 1080 callback, | |
| 1081 base::Owned(new_quota_ptr))); | |
| 1082 } | |
| 1083 | |
| 1084 void QuotaManager::GetGlobalUsage(StorageType type, | |
| 1085 const GlobalUsageCallback& callback) { | |
| 1086 LazyInitialize(); | |
| 1087 DCHECK(GetUsageTracker(type)); | |
| 1088 GetUsageTracker(type)->GetGlobalUsage(callback); | |
| 1089 } | |
| 1090 | |
| 1091 void QuotaManager::GetHostUsage(const std::string& host, | |
| 1092 StorageType type, | |
| 1093 const UsageCallback& callback) { | |
| 1094 LazyInitialize(); | |
| 1095 DCHECK(GetUsageTracker(type)); | |
| 1096 GetUsageTracker(type)->GetHostUsage(host, callback); | |
| 1097 } | |
| 1098 | |
| 1099 void QuotaManager::GetHostUsage(const std::string& host, | |
| 1100 StorageType type, | |
| 1101 QuotaClient::ID client_id, | |
| 1102 const UsageCallback& callback) { | |
| 1103 LazyInitialize(); | |
| 1104 DCHECK(GetUsageTracker(type)); | |
| 1105 ClientUsageTracker* tracker = | |
| 1106 GetUsageTracker(type)->GetClientTracker(client_id); | |
| 1107 if (!tracker) { | |
| 1108 callback.Run(0); | |
| 1109 return; | |
| 1110 } | |
| 1111 tracker->GetHostUsage(host, callback); | |
| 1112 } | |
| 1113 | |
| 1114 bool QuotaManager::IsTrackingHostUsage(StorageType type, | |
| 1115 QuotaClient::ID client_id) const { | |
| 1116 UsageTracker* tracker = GetUsageTracker(type); | |
| 1117 return tracker && tracker->GetClientTracker(client_id); | |
| 1118 } | |
| 1119 | |
| 1120 void QuotaManager::GetStatistics( | |
| 1121 std::map<std::string, std::string>* statistics) { | |
| 1122 DCHECK(statistics); | |
| 1123 if (temporary_storage_evictor_) { | |
| 1124 std::map<std::string, int64> stats; | |
| 1125 temporary_storage_evictor_->GetStatistics(&stats); | |
| 1126 for (std::map<std::string, int64>::iterator p = stats.begin(); | |
| 1127 p != stats.end(); | |
| 1128 ++p) | |
| 1129 (*statistics)[p->first] = base::Int64ToString(p->second); | |
| 1130 } | |
| 1131 } | |
| 1132 | |
| 1133 bool QuotaManager::IsStorageUnlimited(const GURL& origin, | |
| 1134 StorageType type) const { | |
| 1135 // For syncable storage we should always enforce quota (since the | |
| 1136 // quota must be capped by the server limit). | |
| 1137 if (type == kStorageTypeSyncable) | |
| 1138 return false; | |
| 1139 if (type == kStorageTypeQuotaNotManaged) | |
| 1140 return true; | |
| 1141 return special_storage_policy_.get() && | |
| 1142 special_storage_policy_->IsStorageUnlimited(origin); | |
| 1143 } | |
| 1144 | |
| 1145 void QuotaManager::GetOriginsModifiedSince(StorageType type, | |
| 1146 base::Time modified_since, | |
| 1147 const GetOriginsCallback& callback) { | |
| 1148 LazyInitialize(); | |
| 1149 GetModifiedSinceHelper* helper = new GetModifiedSinceHelper; | |
| 1150 PostTaskAndReplyWithResultForDBThread( | |
| 1151 FROM_HERE, | |
| 1152 base::Bind(&GetModifiedSinceHelper::GetModifiedSinceOnDBThread, | |
| 1153 base::Unretained(helper), | |
| 1154 type, | |
| 1155 modified_since), | |
| 1156 base::Bind(&GetModifiedSinceHelper::DidGetModifiedSince, | |
| 1157 base::Owned(helper), | |
| 1158 weak_factory_.GetWeakPtr(), | |
| 1159 callback, | |
| 1160 type)); | |
| 1161 } | |
| 1162 | |
| 1163 bool QuotaManager::ResetUsageTracker(StorageType type) { | |
| 1164 DCHECK(GetUsageTracker(type)); | |
| 1165 if (GetUsageTracker(type)->IsWorking()) | |
| 1166 return false; | |
| 1167 switch (type) { | |
| 1168 case kStorageTypeTemporary: | |
| 1169 temporary_usage_tracker_.reset(new UsageTracker( | |
| 1170 clients_, kStorageTypeTemporary, special_storage_policy_.get(), | |
| 1171 storage_monitor_.get())); | |
| 1172 return true; | |
| 1173 case kStorageTypePersistent: | |
| 1174 persistent_usage_tracker_.reset(new UsageTracker( | |
| 1175 clients_, kStorageTypePersistent, special_storage_policy_.get(), | |
| 1176 storage_monitor_.get())); | |
| 1177 return true; | |
| 1178 case kStorageTypeSyncable: | |
| 1179 syncable_usage_tracker_.reset(new UsageTracker( | |
| 1180 clients_, kStorageTypeSyncable, special_storage_policy_.get(), | |
| 1181 storage_monitor_.get())); | |
| 1182 return true; | |
| 1183 default: | |
| 1184 NOTREACHED(); | |
| 1185 } | |
| 1186 return true; | |
| 1187 } | |
| 1188 | |
| 1189 void QuotaManager::AddStorageObserver( | |
| 1190 StorageObserver* observer, const StorageObserver::MonitorParams& params) { | |
| 1191 DCHECK(observer); | |
| 1192 storage_monitor_->AddObserver(observer, params); | |
| 1193 } | |
| 1194 | |
| 1195 void QuotaManager::RemoveStorageObserver(StorageObserver* observer) { | |
| 1196 DCHECK(observer); | |
| 1197 storage_monitor_->RemoveObserver(observer); | |
| 1198 } | |
| 1199 | |
| 1200 void QuotaManager::RemoveStorageObserverForFilter( | |
| 1201 StorageObserver* observer, const StorageObserver::Filter& filter) { | |
| 1202 DCHECK(observer); | |
| 1203 storage_monitor_->RemoveObserverForFilter(observer, filter); | |
| 1204 } | |
| 1205 | |
| 1206 QuotaManager::~QuotaManager() { | |
| 1207 proxy_->manager_ = NULL; | |
| 1208 std::for_each(clients_.begin(), clients_.end(), | |
| 1209 std::mem_fun(&QuotaClient::OnQuotaManagerDestroyed)); | |
| 1210 if (database_) | |
| 1211 db_thread_->DeleteSoon(FROM_HERE, database_.release()); | |
| 1212 } | |
| 1213 | |
| 1214 QuotaManager::EvictionContext::EvictionContext() | |
| 1215 : evicted_type(kStorageTypeUnknown) { | |
| 1216 } | |
| 1217 | |
| 1218 QuotaManager::EvictionContext::~EvictionContext() { | |
| 1219 } | |
| 1220 | |
| 1221 void QuotaManager::LazyInitialize() { | |
| 1222 DCHECK(io_thread_->BelongsToCurrentThread()); | |
| 1223 if (database_) { | |
| 1224 // Initialization seems to be done already. | |
| 1225 return; | |
| 1226 } | |
| 1227 | |
| 1228 // Use an empty path to open an in-memory only databse for incognito. | |
| 1229 database_.reset(new QuotaDatabase(is_incognito_ ? base::FilePath() : | |
| 1230 profile_path_.AppendASCII(kDatabaseName))); | |
| 1231 | |
| 1232 temporary_usage_tracker_.reset(new UsageTracker( | |
| 1233 clients_, kStorageTypeTemporary, special_storage_policy_.get(), | |
| 1234 storage_monitor_.get())); | |
| 1235 persistent_usage_tracker_.reset(new UsageTracker( | |
| 1236 clients_, kStorageTypePersistent, special_storage_policy_.get(), | |
| 1237 storage_monitor_.get())); | |
| 1238 syncable_usage_tracker_.reset(new UsageTracker( | |
| 1239 clients_, kStorageTypeSyncable, special_storage_policy_.get(), | |
| 1240 storage_monitor_.get())); | |
| 1241 | |
| 1242 int64* temporary_quota_override = new int64(-1); | |
| 1243 int64* desired_available_space = new int64(-1); | |
| 1244 PostTaskAndReplyWithResultForDBThread( | |
| 1245 FROM_HERE, | |
| 1246 base::Bind(&InitializeOnDBThread, | |
| 1247 base::Unretained(temporary_quota_override), | |
| 1248 base::Unretained(desired_available_space)), | |
| 1249 base::Bind(&QuotaManager::DidInitialize, | |
| 1250 weak_factory_.GetWeakPtr(), | |
| 1251 base::Owned(temporary_quota_override), | |
| 1252 base::Owned(desired_available_space))); | |
| 1253 } | |
| 1254 | |
| 1255 void QuotaManager::RegisterClient(QuotaClient* client) { | |
| 1256 DCHECK(!database_.get()); | |
| 1257 clients_.push_back(client); | |
| 1258 } | |
| 1259 | |
| 1260 UsageTracker* QuotaManager::GetUsageTracker(StorageType type) const { | |
| 1261 switch (type) { | |
| 1262 case kStorageTypeTemporary: | |
| 1263 return temporary_usage_tracker_.get(); | |
| 1264 case kStorageTypePersistent: | |
| 1265 return persistent_usage_tracker_.get(); | |
| 1266 case kStorageTypeSyncable: | |
| 1267 return syncable_usage_tracker_.get(); | |
| 1268 case kStorageTypeQuotaNotManaged: | |
| 1269 return NULL; | |
| 1270 case kStorageTypeUnknown: | |
| 1271 NOTREACHED(); | |
| 1272 } | |
| 1273 return NULL; | |
| 1274 } | |
| 1275 | |
| 1276 void QuotaManager::GetCachedOrigins( | |
| 1277 StorageType type, std::set<GURL>* origins) { | |
| 1278 DCHECK(origins); | |
| 1279 LazyInitialize(); | |
| 1280 DCHECK(GetUsageTracker(type)); | |
| 1281 GetUsageTracker(type)->GetCachedOrigins(origins); | |
| 1282 } | |
| 1283 | |
| 1284 void QuotaManager::NotifyStorageAccessedInternal( | |
| 1285 QuotaClient::ID client_id, | |
| 1286 const GURL& origin, StorageType type, | |
| 1287 base::Time accessed_time) { | |
| 1288 LazyInitialize(); | |
| 1289 if (type == kStorageTypeTemporary && !lru_origin_callback_.is_null()) { | |
| 1290 // Record the accessed origins while GetLRUOrigin task is runing | |
| 1291 // to filter out them from eviction. | |
| 1292 access_notified_origins_.insert(origin); | |
| 1293 } | |
| 1294 | |
| 1295 if (db_disabled_) | |
| 1296 return; | |
| 1297 PostTaskAndReplyWithResultForDBThread( | |
| 1298 FROM_HERE, | |
| 1299 base::Bind(&UpdateAccessTimeOnDBThread, origin, type, accessed_time), | |
| 1300 base::Bind(&QuotaManager::DidDatabaseWork, | |
| 1301 weak_factory_.GetWeakPtr())); | |
| 1302 } | |
| 1303 | |
| 1304 void QuotaManager::NotifyStorageModifiedInternal( | |
| 1305 QuotaClient::ID client_id, | |
| 1306 const GURL& origin, | |
| 1307 StorageType type, | |
| 1308 int64 delta, | |
| 1309 base::Time modified_time) { | |
| 1310 LazyInitialize(); | |
| 1311 DCHECK(GetUsageTracker(type)); | |
| 1312 GetUsageTracker(type)->UpdateUsageCache(client_id, origin, delta); | |
| 1313 | |
| 1314 PostTaskAndReplyWithResultForDBThread( | |
| 1315 FROM_HERE, | |
| 1316 base::Bind(&UpdateModifiedTimeOnDBThread, origin, type, modified_time), | |
| 1317 base::Bind(&QuotaManager::DidDatabaseWork, | |
| 1318 weak_factory_.GetWeakPtr())); | |
| 1319 } | |
| 1320 | |
| 1321 void QuotaManager::DumpQuotaTable(const DumpQuotaTableCallback& callback) { | |
| 1322 DumpQuotaTableHelper* helper = new DumpQuotaTableHelper; | |
| 1323 PostTaskAndReplyWithResultForDBThread( | |
| 1324 FROM_HERE, | |
| 1325 base::Bind(&DumpQuotaTableHelper::DumpQuotaTableOnDBThread, | |
| 1326 base::Unretained(helper)), | |
| 1327 base::Bind(&DumpQuotaTableHelper::DidDumpQuotaTable, | |
| 1328 base::Owned(helper), | |
| 1329 weak_factory_.GetWeakPtr(), | |
| 1330 callback)); | |
| 1331 } | |
| 1332 | |
| 1333 void QuotaManager::DumpOriginInfoTable( | |
| 1334 const DumpOriginInfoTableCallback& callback) { | |
| 1335 DumpOriginInfoTableHelper* helper = new DumpOriginInfoTableHelper; | |
| 1336 PostTaskAndReplyWithResultForDBThread( | |
| 1337 FROM_HERE, | |
| 1338 base::Bind(&DumpOriginInfoTableHelper::DumpOriginInfoTableOnDBThread, | |
| 1339 base::Unretained(helper)), | |
| 1340 base::Bind(&DumpOriginInfoTableHelper::DidDumpOriginInfoTable, | |
| 1341 base::Owned(helper), | |
| 1342 weak_factory_.GetWeakPtr(), | |
| 1343 callback)); | |
| 1344 } | |
| 1345 | |
| 1346 void QuotaManager::StartEviction() { | |
| 1347 DCHECK(!temporary_storage_evictor_.get()); | |
| 1348 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor( | |
| 1349 this, kEvictionIntervalInMilliSeconds)); | |
| 1350 if (desired_available_space_ >= 0) | |
| 1351 temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction( | |
| 1352 desired_available_space_); | |
| 1353 temporary_storage_evictor_->Start(); | |
| 1354 } | |
| 1355 | |
| 1356 void QuotaManager::DeleteOriginFromDatabase( | |
| 1357 const GURL& origin, StorageType type) { | |
| 1358 LazyInitialize(); | |
| 1359 if (db_disabled_) | |
| 1360 return; | |
| 1361 | |
| 1362 PostTaskAndReplyWithResultForDBThread( | |
| 1363 FROM_HERE, | |
| 1364 base::Bind(&DeleteOriginInfoOnDBThread, origin, type), | |
| 1365 base::Bind(&QuotaManager::DidDatabaseWork, | |
| 1366 weak_factory_.GetWeakPtr())); | |
| 1367 } | |
| 1368 | |
| 1369 void QuotaManager::DidOriginDataEvicted(QuotaStatusCode status) { | |
| 1370 DCHECK(io_thread_->BelongsToCurrentThread()); | |
| 1371 | |
| 1372 // We only try evict origins that are not in use, so basically | |
| 1373 // deletion attempt for eviction should not fail. Let's record | |
| 1374 // the origin if we get error and exclude it from future eviction | |
| 1375 // if the error happens consistently (> kThresholdOfErrorsToBeBlacklisted). | |
| 1376 if (status != kQuotaStatusOk) | |
| 1377 origins_in_error_[eviction_context_.evicted_origin]++; | |
| 1378 | |
| 1379 eviction_context_.evict_origin_data_callback.Run(status); | |
| 1380 eviction_context_.evict_origin_data_callback.Reset(); | |
| 1381 } | |
| 1382 | |
| 1383 void QuotaManager::ReportHistogram() { | |
| 1384 GetGlobalUsage(kStorageTypeTemporary, | |
| 1385 base::Bind( | |
| 1386 &QuotaManager::DidGetTemporaryGlobalUsageForHistogram, | |
| 1387 weak_factory_.GetWeakPtr())); | |
| 1388 GetGlobalUsage(kStorageTypePersistent, | |
| 1389 base::Bind( | |
| 1390 &QuotaManager::DidGetPersistentGlobalUsageForHistogram, | |
| 1391 weak_factory_.GetWeakPtr())); | |
| 1392 } | |
| 1393 | |
| 1394 void QuotaManager::DidGetTemporaryGlobalUsageForHistogram( | |
| 1395 int64 usage, | |
| 1396 int64 unlimited_usage) { | |
| 1397 UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfTemporaryStorage", usage); | |
| 1398 | |
| 1399 std::set<GURL> origins; | |
| 1400 GetCachedOrigins(kStorageTypeTemporary, &origins); | |
| 1401 | |
| 1402 size_t num_origins = origins.size(); | |
| 1403 size_t protected_origins = 0; | |
| 1404 size_t unlimited_origins = 0; | |
| 1405 CountOriginType(origins, | |
| 1406 special_storage_policy_.get(), | |
| 1407 &protected_origins, | |
| 1408 &unlimited_origins); | |
| 1409 | |
| 1410 UMA_HISTOGRAM_COUNTS("Quota.NumberOfTemporaryStorageOrigins", | |
| 1411 num_origins); | |
| 1412 UMA_HISTOGRAM_COUNTS("Quota.NumberOfProtectedTemporaryStorageOrigins", | |
| 1413 protected_origins); | |
| 1414 UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedTemporaryStorageOrigins", | |
| 1415 unlimited_origins); | |
| 1416 } | |
| 1417 | |
| 1418 void QuotaManager::DidGetPersistentGlobalUsageForHistogram( | |
| 1419 int64 usage, | |
| 1420 int64 unlimited_usage) { | |
| 1421 UMA_HISTOGRAM_MBYTES("Quota.GlobalUsageOfPersistentStorage", usage); | |
| 1422 | |
| 1423 std::set<GURL> origins; | |
| 1424 GetCachedOrigins(kStorageTypePersistent, &origins); | |
| 1425 | |
| 1426 size_t num_origins = origins.size(); | |
| 1427 size_t protected_origins = 0; | |
| 1428 size_t unlimited_origins = 0; | |
| 1429 CountOriginType(origins, | |
| 1430 special_storage_policy_.get(), | |
| 1431 &protected_origins, | |
| 1432 &unlimited_origins); | |
| 1433 | |
| 1434 UMA_HISTOGRAM_COUNTS("Quota.NumberOfPersistentStorageOrigins", | |
| 1435 num_origins); | |
| 1436 UMA_HISTOGRAM_COUNTS("Quota.NumberOfProtectedPersistentStorageOrigins", | |
| 1437 protected_origins); | |
| 1438 UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedPersistentStorageOrigins", | |
| 1439 unlimited_origins); | |
| 1440 } | |
| 1441 | |
| 1442 void QuotaManager::GetLRUOrigin( | |
| 1443 StorageType type, | |
| 1444 const GetLRUOriginCallback& callback) { | |
| 1445 LazyInitialize(); | |
| 1446 // This must not be called while there's an in-flight task. | |
| 1447 DCHECK(lru_origin_callback_.is_null()); | |
| 1448 lru_origin_callback_ = callback; | |
| 1449 if (db_disabled_) { | |
| 1450 lru_origin_callback_.Run(GURL()); | |
| 1451 lru_origin_callback_.Reset(); | |
| 1452 return; | |
| 1453 } | |
| 1454 | |
| 1455 std::set<GURL>* exceptions = new std::set<GURL>; | |
| 1456 for (std::map<GURL, int>::const_iterator p = origins_in_use_.begin(); | |
| 1457 p != origins_in_use_.end(); | |
| 1458 ++p) { | |
| 1459 if (p->second > 0) | |
| 1460 exceptions->insert(p->first); | |
| 1461 } | |
| 1462 for (std::map<GURL, int>::const_iterator p = origins_in_error_.begin(); | |
| 1463 p != origins_in_error_.end(); | |
| 1464 ++p) { | |
| 1465 if (p->second > QuotaManager::kThresholdOfErrorsToBeBlacklisted) | |
| 1466 exceptions->insert(p->first); | |
| 1467 } | |
| 1468 | |
| 1469 GURL* url = new GURL; | |
| 1470 PostTaskAndReplyWithResultForDBThread( | |
| 1471 FROM_HERE, | |
| 1472 base::Bind(&GetLRUOriginOnDBThread, | |
| 1473 type, | |
| 1474 base::Owned(exceptions), | |
| 1475 special_storage_policy_, | |
| 1476 base::Unretained(url)), | |
| 1477 base::Bind(&QuotaManager::DidGetLRUOrigin, | |
| 1478 weak_factory_.GetWeakPtr(), | |
| 1479 base::Owned(url))); | |
| 1480 } | |
| 1481 | |
| 1482 void QuotaManager::EvictOriginData( | |
| 1483 const GURL& origin, | |
| 1484 StorageType type, | |
| 1485 const EvictOriginDataCallback& callback) { | |
| 1486 DCHECK(io_thread_->BelongsToCurrentThread()); | |
| 1487 DCHECK_EQ(type, kStorageTypeTemporary); | |
| 1488 | |
| 1489 eviction_context_.evicted_origin = origin; | |
| 1490 eviction_context_.evicted_type = type; | |
| 1491 eviction_context_.evict_origin_data_callback = callback; | |
| 1492 | |
| 1493 DeleteOriginData(origin, type, QuotaClient::kAllClientsMask, | |
| 1494 base::Bind(&QuotaManager::DidOriginDataEvicted, | |
| 1495 weak_factory_.GetWeakPtr())); | |
| 1496 } | |
| 1497 | |
| 1498 void QuotaManager::GetUsageAndQuotaForEviction( | |
| 1499 const UsageAndQuotaCallback& callback) { | |
| 1500 DCHECK(io_thread_->BelongsToCurrentThread()); | |
| 1501 LazyInitialize(); | |
| 1502 | |
| 1503 UsageAndQuotaCallbackDispatcher* dispatcher = | |
| 1504 new UsageAndQuotaCallbackDispatcher(this); | |
| 1505 GetUsageTracker(kStorageTypeTemporary)-> | |
| 1506 GetGlobalLimitedUsage(dispatcher->GetGlobalLimitedUsageCallback()); | |
| 1507 GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback()); | |
| 1508 GetAvailableSpace(dispatcher->GetAvailableSpaceCallback()); | |
| 1509 dispatcher->WaitForResults(callback); | |
| 1510 } | |
| 1511 | |
| 1512 void QuotaManager::DidSetTemporaryGlobalOverrideQuota( | |
| 1513 const QuotaCallback& callback, | |
| 1514 const int64* new_quota, | |
| 1515 bool success) { | |
| 1516 QuotaStatusCode status = kQuotaErrorInvalidAccess; | |
| 1517 DidDatabaseWork(success); | |
| 1518 if (success) { | |
| 1519 temporary_quota_override_ = *new_quota; | |
| 1520 status = kQuotaStatusOk; | |
| 1521 } | |
| 1522 | |
| 1523 if (callback.is_null()) | |
| 1524 return; | |
| 1525 | |
| 1526 callback.Run(status, *new_quota); | |
| 1527 } | |
| 1528 | |
| 1529 void QuotaManager::DidGetPersistentHostQuota(const std::string& host, | |
| 1530 const int64* quota, | |
| 1531 bool success) { | |
| 1532 DidDatabaseWork(success); | |
| 1533 persistent_host_quota_callbacks_.Run( | |
| 1534 host, MakeTuple(kQuotaStatusOk, *quota)); | |
| 1535 } | |
| 1536 | |
| 1537 void QuotaManager::DidSetPersistentHostQuota(const std::string& host, | |
| 1538 const QuotaCallback& callback, | |
| 1539 const int64* new_quota, | |
| 1540 bool success) { | |
| 1541 DidDatabaseWork(success); | |
| 1542 callback.Run(success ? kQuotaStatusOk : kQuotaErrorInvalidAccess, *new_quota); | |
| 1543 } | |
| 1544 | |
| 1545 void QuotaManager::DidInitialize(int64* temporary_quota_override, | |
| 1546 int64* desired_available_space, | |
| 1547 bool success) { | |
| 1548 temporary_quota_override_ = *temporary_quota_override; | |
| 1549 desired_available_space_ = *desired_available_space; | |
| 1550 temporary_quota_initialized_ = true; | |
| 1551 DidDatabaseWork(success); | |
| 1552 | |
| 1553 histogram_timer_.Start(FROM_HERE, | |
| 1554 base::TimeDelta::FromMilliseconds( | |
| 1555 kReportHistogramInterval), | |
| 1556 this, &QuotaManager::ReportHistogram); | |
| 1557 | |
| 1558 db_initialization_callbacks_.Run(MakeTuple()); | |
| 1559 GetTemporaryGlobalQuota( | |
| 1560 base::Bind(&QuotaManager::DidGetInitialTemporaryGlobalQuota, | |
| 1561 weak_factory_.GetWeakPtr())); | |
| 1562 } | |
| 1563 | |
| 1564 void QuotaManager::DidGetLRUOrigin(const GURL* origin, | |
| 1565 bool success) { | |
| 1566 DidDatabaseWork(success); | |
| 1567 // Make sure the returned origin is (still) not in the origin_in_use_ set | |
| 1568 // and has not been accessed since we posted the task. | |
| 1569 if (origins_in_use_.find(*origin) != origins_in_use_.end() || | |
| 1570 access_notified_origins_.find(*origin) != access_notified_origins_.end()) | |
| 1571 lru_origin_callback_.Run(GURL()); | |
| 1572 else | |
| 1573 lru_origin_callback_.Run(*origin); | |
| 1574 access_notified_origins_.clear(); | |
| 1575 lru_origin_callback_.Reset(); | |
| 1576 } | |
| 1577 | |
| 1578 void QuotaManager::DidGetInitialTemporaryGlobalQuota( | |
| 1579 QuotaStatusCode status, int64 quota_unused) { | |
| 1580 if (eviction_disabled_) | |
| 1581 return; | |
| 1582 | |
| 1583 std::set<GURL>* origins = new std::set<GURL>; | |
| 1584 temporary_usage_tracker_->GetCachedOrigins(origins); | |
| 1585 // This will call the StartEviction() when initial origin registration | |
| 1586 // is completed. | |
| 1587 PostTaskAndReplyWithResultForDBThread( | |
| 1588 FROM_HERE, | |
| 1589 base::Bind(&InitializeTemporaryOriginsInfoOnDBThread, | |
| 1590 base::Owned(origins)), | |
| 1591 base::Bind(&QuotaManager::DidInitializeTemporaryOriginsInfo, | |
| 1592 weak_factory_.GetWeakPtr())); | |
| 1593 } | |
| 1594 | |
| 1595 void QuotaManager::DidInitializeTemporaryOriginsInfo(bool success) { | |
| 1596 DidDatabaseWork(success); | |
| 1597 if (success) | |
| 1598 StartEviction(); | |
| 1599 } | |
| 1600 | |
| 1601 void QuotaManager::DidGetAvailableSpace(int64 space) { | |
| 1602 available_space_callbacks_.Run(MakeTuple(kQuotaStatusOk, space)); | |
| 1603 } | |
| 1604 | |
| 1605 void QuotaManager::DidDatabaseWork(bool success) { | |
| 1606 db_disabled_ = !success; | |
| 1607 } | |
| 1608 | |
| 1609 void QuotaManager::DeleteOnCorrectThread() const { | |
| 1610 if (!io_thread_->BelongsToCurrentThread() && | |
| 1611 io_thread_->DeleteSoon(FROM_HERE, this)) { | |
| 1612 return; | |
| 1613 } | |
| 1614 delete this; | |
| 1615 } | |
| 1616 | |
| 1617 void QuotaManager::PostTaskAndReplyWithResultForDBThread( | |
| 1618 const tracked_objects::Location& from_here, | |
| 1619 const base::Callback<bool(QuotaDatabase*)>& task, | |
| 1620 const base::Callback<void(bool)>& reply) { | |
| 1621 // Deleting manager will post another task to DB thread to delete | |
| 1622 // |database_|, therefore we can be sure that database_ is alive when this | |
| 1623 // task runs. | |
| 1624 base::PostTaskAndReplyWithResult( | |
| 1625 db_thread_.get(), | |
| 1626 from_here, | |
| 1627 base::Bind(task, base::Unretained(database_.get())), | |
| 1628 reply); | |
| 1629 } | |
| 1630 | |
| 1631 } // namespace quota | |
| OLD | NEW |