Home | History | Annotate | Download | only in storage
      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 "chrome/browser/extensions/api/storage/sync_or_local_value_store_cache.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "base/files/file_path.h"
     10 #include "base/sequenced_task_runner.h"
     11 #include "chrome/browser/extensions/api/storage/settings_backend.h"
     12 #include "chrome/browser/extensions/api/storage/settings_frontend.h"
     13 #include "chrome/browser/extensions/api/storage/settings_storage_quota_enforcer.h"
     14 #include "chrome/browser/extensions/api/storage/weak_unlimited_settings_storage.h"
     15 #include "chrome/browser/extensions/extension_service.h"
     16 #include "chrome/browser/sync/glue/sync_start_util.h"
     17 #include "chrome/common/extensions/extension.h"
     18 #include "chrome/common/extensions/permissions/api_permission.h"
     19 #include "content/public/browser/browser_thread.h"
     20 
     21 using content::BrowserThread;
     22 
     23 namespace extensions {
     24 
     25 SyncOrLocalValueStoreCache::SyncOrLocalValueStoreCache(
     26     settings_namespace::Namespace settings_namespace,
     27     const scoped_refptr<SettingsStorageFactory>& factory,
     28     const SettingsStorageQuotaEnforcer::Limits& quota,
     29     const scoped_refptr<SettingsObserverList>& observers,
     30     const base::FilePath& profile_path)
     31     : settings_namespace_(settings_namespace) {
     32   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     33   DCHECK(settings_namespace_ == settings_namespace::LOCAL ||
     34          settings_namespace_ == settings_namespace::SYNC);
     35 
     36   // This post is safe since the destructor can only be invoked from the
     37   // same message loop, and any potential post of a deletion task must come
     38   // after the constructor returns.
     39   BrowserThread::PostTask(
     40       BrowserThread::FILE, FROM_HERE,
     41       base::Bind(&SyncOrLocalValueStoreCache::InitOnFileThread,
     42                  base::Unretained(this),
     43                  factory, quota, observers, profile_path));
     44 }
     45 
     46 SyncOrLocalValueStoreCache::~SyncOrLocalValueStoreCache() {
     47   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
     48 }
     49 
     50 SettingsBackend* SyncOrLocalValueStoreCache::GetAppBackend() const {
     51   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
     52   DCHECK(app_backend_.get());
     53   return app_backend_.get();
     54 }
     55 
     56 SettingsBackend* SyncOrLocalValueStoreCache::GetExtensionBackend() const {
     57   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
     58   DCHECK(extension_backend_.get());
     59   return extension_backend_.get();
     60 }
     61 
     62 void SyncOrLocalValueStoreCache::RunWithValueStoreForExtension(
     63     const StorageCallback& callback,
     64     scoped_refptr<const Extension> extension) {
     65   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
     66   DCHECK(app_backend_.get());
     67   DCHECK(extension_backend_.get());
     68   SettingsBackend* backend =
     69       extension->is_app() ? app_backend_.get() : extension_backend_.get();
     70   ValueStore* storage = backend->GetStorage(extension->id());
     71 
     72   // A neat way to implement unlimited storage; if the extension has the
     73   // unlimited storage permission, force through all calls to Set() (in the
     74   // same way that writes from sync ignore quota).
     75   // But only if it's local storage (bad stuff would happen if sync'ed
     76   // storage is allowed to be unlimited).
     77   bool is_unlimited =
     78       settings_namespace_ == settings_namespace::LOCAL &&
     79       extension->HasAPIPermission(APIPermission::kUnlimitedStorage);
     80 
     81   if (is_unlimited) {
     82     WeakUnlimitedSettingsStorage unlimited_storage(storage);
     83     callback.Run(&unlimited_storage);
     84   } else {
     85     callback.Run(storage);
     86   }
     87 }
     88 
     89 void SyncOrLocalValueStoreCache::DeleteStorageSoon(
     90     const std::string& extension_id) {
     91   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
     92   app_backend_->DeleteStorage(extension_id);
     93   extension_backend_->DeleteStorage(extension_id);
     94 }
     95 
     96 void SyncOrLocalValueStoreCache::InitOnFileThread(
     97     const scoped_refptr<SettingsStorageFactory>& factory,
     98     const SettingsStorageQuotaEnforcer::Limits& quota,
     99     const scoped_refptr<SettingsObserverList>& observers,
    100     const base::FilePath& profile_path) {
    101   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    102   DCHECK(!app_backend_.get());
    103   DCHECK(!extension_backend_.get());
    104   const bool local = settings_namespace_ == settings_namespace::LOCAL;
    105   const base::FilePath app_path = profile_path.AppendASCII(
    106       local ? ExtensionService::kLocalAppSettingsDirectoryName
    107             : ExtensionService::kSyncAppSettingsDirectoryName);
    108   const base::FilePath extension_path = profile_path.AppendASCII(
    109       local ? ExtensionService::kLocalExtensionSettingsDirectoryName
    110             : ExtensionService::kSyncExtensionSettingsDirectoryName);
    111   app_backend_.reset(new SettingsBackend(
    112       factory, app_path, syncer::APP_SETTINGS,
    113       sync_start_util::GetFlareForSyncableService(profile_path),
    114       quota, observers));
    115   extension_backend_.reset(new SettingsBackend(
    116       factory, extension_path, syncer::EXTENSION_SETTINGS,
    117       sync_start_util::GetFlareForSyncableService(profile_path),
    118       quota, observers));
    119 }
    120 
    121 }  // namespace extensions
    122