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