Home | History | Annotate | Download | only in storage
      1 // Copyright 2014 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 "extensions/browser/api/storage/local_value_store_cache.h"
      6 
      7 #include <limits>
      8 
      9 #include "base/bind.h"
     10 #include "base/callback.h"
     11 #include "base/files/file_path.h"
     12 #include "base/metrics/histogram.h"
     13 #include "content/public/browser/browser_thread.h"
     14 #include "extensions/browser/api/storage/settings_storage_factory.h"
     15 #include "extensions/browser/api/storage/settings_storage_quota_enforcer.h"
     16 #include "extensions/browser/api/storage/weak_unlimited_settings_storage.h"
     17 #include "extensions/browser/value_store/value_store.h"
     18 #include "extensions/common/api/storage.h"
     19 #include "extensions/common/constants.h"
     20 #include "extensions/common/extension.h"
     21 #include "extensions/common/permissions/api_permission.h"
     22 #include "extensions/common/permissions/permissions_data.h"
     23 
     24 using content::BrowserThread;
     25 
     26 namespace extensions {
     27 
     28 namespace {
     29 
     30 // Returns the quota limit for local storage, taken from the schema in
     31 // extensions/common/api/storage.json.
     32 SettingsStorageQuotaEnforcer::Limits GetLocalQuotaLimits() {
     33   SettingsStorageQuotaEnforcer::Limits limits = {
     34     static_cast<size_t>(core_api::storage::local::QUOTA_BYTES),
     35     std::numeric_limits<size_t>::max(),
     36     std::numeric_limits<size_t>::max()
     37   };
     38   return limits;
     39 }
     40 
     41 }  // namespace
     42 
     43 LocalValueStoreCache::LocalValueStoreCache(
     44     const scoped_refptr<SettingsStorageFactory>& factory,
     45     const base::FilePath& profile_path)
     46     : storage_factory_(factory),
     47       extension_base_path_(
     48           profile_path.AppendASCII(kLocalExtensionSettingsDirectoryName)),
     49       app_base_path_(profile_path.AppendASCII(kLocalAppSettingsDirectoryName)),
     50       quota_(GetLocalQuotaLimits()) {
     51   DCHECK_CURRENTLY_ON(BrowserThread::UI);
     52 }
     53 
     54 LocalValueStoreCache::~LocalValueStoreCache() {
     55   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     56 }
     57 
     58 void LocalValueStoreCache::RunWithValueStoreForExtension(
     59     const StorageCallback& callback,
     60     scoped_refptr<const Extension> extension) {
     61   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     62 
     63   ValueStore* storage = GetStorage(extension);
     64 
     65   // A neat way to implement unlimited storage; if the extension has the
     66   // unlimited storage permission, force through all calls to Set().
     67   if (extension->permissions_data()->HasAPIPermission(
     68           APIPermission::kUnlimitedStorage)) {
     69     WeakUnlimitedSettingsStorage unlimited_storage(storage);
     70     callback.Run(&unlimited_storage);
     71   } else {
     72     callback.Run(storage);
     73   }
     74 }
     75 
     76 void LocalValueStoreCache::DeleteStorageSoon(const std::string& extension_id) {
     77   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     78   storage_map_.erase(extension_id);
     79   storage_factory_->DeleteDatabaseIfExists(app_base_path_, extension_id);
     80   storage_factory_->DeleteDatabaseIfExists(extension_base_path_, extension_id);
     81 }
     82 
     83 ValueStore* LocalValueStoreCache::GetStorage(
     84     scoped_refptr<const Extension> extension) {
     85   StorageMap::iterator iter = storage_map_.find(extension->id());
     86   if (iter != storage_map_.end())
     87     return iter->second.get();
     88 
     89   const base::FilePath& file_path =
     90       extension->is_app() ? app_base_path_ : extension_base_path_;
     91   linked_ptr<SettingsStorageQuotaEnforcer> storage(
     92       new SettingsStorageQuotaEnforcer(
     93           quota_, storage_factory_->Create(file_path, extension->id())));
     94   DCHECK(storage.get());
     95 
     96   if (extension->permissions_data()->HasAPIPermission(
     97           APIPermission::kUnlimitedStorage) &&
     98       extension->is_hosted_app()) {
     99     // We're interested in the amount of space hosted apps are using. Record it
    100     // the first time we load the storage for the extension.
    101     UMA_HISTOGRAM_MEMORY_KB("Extensions.HostedAppUnlimitedStorageUsage",
    102                             storage->GetBytesInUse());
    103   }
    104 
    105   storage_map_[extension->id()] = storage;
    106   return storage.get();
    107 }
    108 
    109 }  // namespace extensions
    110