Skip to content

Commit

Permalink
Add support for Chrome Storage Extension API (issue chromiumembedded#…
Browse files Browse the repository at this point in the history
…1947)

- Supports chrome.storage.local and chrome.storage.sync
- chrome.storage.sync behaves identically to chrome.storage.local
  • Loading branch information
schetle authored and magreenblatt committed Sep 13, 2017
1 parent 88ebd43 commit ff8b4aa
Show file tree
Hide file tree
Showing 15 changed files with 1,159 additions and 5 deletions.
6 changes: 6 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,8 @@ static_library("libcef_static") {
"libcef/browser/download_manager_delegate.h",
"libcef/browser/extension_impl.cc",
"libcef/browser/extension_impl.h",
"libcef/browser/extensions/api/storage/sync_value_store_cache.cc",
"libcef/browser/extensions/api/storage/sync_value_store_cache.h",
"libcef/browser/extensions/api/tabs/tabs_api.cc",
"libcef/browser/extensions/api/tabs/tabs_api.h",
"libcef/browser/extensions/browser_context_keyed_service_factories.cc",
Expand Down Expand Up @@ -412,6 +414,10 @@ static_library("libcef_static") {
"libcef/browser/extensions/pdf_extension_util.h",
"libcef/browser/extensions/pdf_web_contents_helper_client.cc",
"libcef/browser/extensions/pdf_web_contents_helper_client.h",
"libcef/browser/extensions/value_store/cef_value_store.cc",
"libcef/browser/extensions/value_store/cef_value_store.h",
"libcef/browser/extensions/value_store/cef_value_store_factory.cc",
"libcef/browser/extensions/value_store/cef_value_store_factory.h",
"libcef/browser/file_dialog_runner.h",
"libcef/browser/file_dialog_manager.cc",
"libcef/browser/file_dialog_manager.h",
Expand Down
1 change: 1 addition & 0 deletions cef_paths2.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@
'tests/ceftests/draggable_regions_unittest.cc',
'tests/ceftests/extensions/background_unittest.cc',
'tests/ceftests/extensions/chrome_alarms_unittest.cc',
'tests/ceftests/extensions/chrome_storage_unittest.cc',
'tests/ceftests/extensions/chrome_tabs_unittest.cc',
'tests/ceftests/extensions/extension_test_handler.cc',
'tests/ceftests/extensions/extension_test_handler.h',
Expand Down
97 changes: 97 additions & 0 deletions libcef/browser/extensions/api/storage/sync_value_store_cache.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright 2017 The Chromium Embedded Framework Authors.
// Portions copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "libcef/browser/extensions/api/storage/sync_value_store_cache.h"

#include <stddef.h>

#include <limits>

#include "content/public/browser/browser_thread.h"
#include "extensions/browser/api/storage/backend_task_runner.h"
#include "extensions/browser/api/storage/weak_unlimited_settings_storage.h"
#include "extensions/browser/value_store/value_store_factory.h"
#include "extensions/common/api/storage.h"
#include "extensions/common/extension.h"
#include "extensions/common/permissions/permissions_data.h"

using content::BrowserThread;

namespace extensions {

namespace cef {

namespace {

// Returns the quota limit for local storage, taken from the schema in
// extensions/common/api/storage.json.
SettingsStorageQuotaEnforcer::Limits GetLocalQuotaLimits() {
SettingsStorageQuotaEnforcer::Limits limits = {
static_cast<size_t>(api::storage::local::QUOTA_BYTES),
std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max()};
return limits;
}

} // namespace

SyncValueStoreCache::SyncValueStoreCache(
const scoped_refptr<ValueStoreFactory>& factory)
: storage_factory_(factory), quota_(GetLocalQuotaLimits()) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

SyncValueStoreCache::~SyncValueStoreCache() {
DCHECK(IsOnBackendSequence());
}

void SyncValueStoreCache::RunWithValueStoreForExtension(
const StorageCallback& callback,
scoped_refptr<const Extension> extension) {
DCHECK(IsOnBackendSequence());

ValueStore* storage = GetStorage(extension.get());

// A neat way to implement unlimited storage; if the extension has the
// unlimited storage permission, force through all calls to Set().
if (extension->permissions_data()->HasAPIPermission(
APIPermission::kUnlimitedStorage)) {
WeakUnlimitedSettingsStorage unlimited_storage(storage);
callback.Run(&unlimited_storage);
} else {
callback.Run(storage);
}
}

void SyncValueStoreCache::DeleteStorageSoon(const std::string& extension_id) {
DCHECK(IsOnBackendSequence());
storage_map_.erase(extension_id);
storage_factory_->DeleteSettings(settings_namespace::SYNC,
ValueStoreFactory::ModelType::APP,
extension_id);
storage_factory_->DeleteSettings(settings_namespace::SYNC,
ValueStoreFactory::ModelType::EXTENSION,
extension_id);
}

ValueStore* SyncValueStoreCache::GetStorage(const Extension* extension) {
StorageMap::iterator iter = storage_map_.find(extension->id());
if (iter != storage_map_.end())
return iter->second.get();

ValueStoreFactory::ModelType model_type =
extension->is_app() ? ValueStoreFactory::ModelType::APP
: ValueStoreFactory::ModelType::EXTENSION;
std::unique_ptr<ValueStore> store = storage_factory_->CreateSettingsStore(
settings_namespace::SYNC, model_type, extension->id());
std::unique_ptr<SettingsStorageQuotaEnforcer> storage(
new SettingsStorageQuotaEnforcer(quota_, std::move(store)));
DCHECK(storage.get());

ValueStore* storage_ptr = storage.get();
storage_map_[extension->id()] = std::move(storage);
return storage_ptr;
}
} // namespace cef
} // namespace extensions
56 changes: 56 additions & 0 deletions libcef/browser/extensions/api/storage/sync_value_store_cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2017 The Chromium Embedded Framework Authors.
// Portions copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_API_STORAGE_SYNC_VALUE_STORE_CACHE_H_
#define CEF_LIBCEF_BROWSER_EXTENSIONS_API_STORAGE_SYNC_VALUE_STORE_CACHE_H_

#include <memory>

#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "extensions/browser/api/storage/settings_storage_quota_enforcer.h"
#include "extensions/browser/api/storage/value_store_cache.h"

namespace extensions {

class ValueStoreFactory;

namespace cef {

// Based on LocalValueStoreCache
// ValueStoreCache for the SYNC namespace. It owns a backend for apps and
// another for extensions. Each backend takes care of persistence.
class SyncValueStoreCache : public ValueStoreCache {
public:
explicit SyncValueStoreCache(const scoped_refptr<ValueStoreFactory>& factory);
~SyncValueStoreCache() override;

// ValueStoreCache implementation:
void RunWithValueStoreForExtension(
const StorageCallback& callback,
scoped_refptr<const Extension> extension) override;
void DeleteStorageSoon(const std::string& extension_id) override;

private:
using StorageMap = std::map<std::string, std::unique_ptr<ValueStore>>;

ValueStore* GetStorage(const Extension* extension);

// The Factory to use for creating new ValueStores.
const scoped_refptr<ValueStoreFactory> storage_factory_;

// Quota limits (see SettingsStorageQuotaEnforcer).
const SettingsStorageQuotaEnforcer::Limits quota_;

// The collection of ValueStores for local storage.
StorageMap storage_map_;

DISALLOW_COPY_AND_ASSIGN(SyncValueStoreCache);
};
} // namespace cef
} // namespace extensions

#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_API_STORAGE_SYNC_VALUE_STORE_CACHE_H_
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "chrome/browser/extensions/api/streams_private/streams_private_api.h"
#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
#include "extensions/browser/api/alarms/alarm_manager.h"
#include "extensions/browser/api/storage/storage_frontend.h"
#include "extensions/browser/renderer_startup_helper.h"

namespace extensions {
Expand All @@ -18,6 +19,7 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
CookieSettingsFactory::GetInstance();
PrefsTabHelper::GetServiceInstance();
RendererStartupHelperFactory::GetInstance();
StorageFrontend::GetFactoryInstance();
StreamsPrivateAPI::GetFactoryInstance();
}

Expand Down
12 changes: 12 additions & 0 deletions libcef/browser/extensions/chrome_api_registration.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "chrome/browser/extensions/api/resources_private/resources_private_api.h"
#include "chrome/browser/extensions/api/streams_private/streams_private_api.h"
#include "extensions/browser/api/alarms/alarms_api.h"
#include "extensions/browser/api/storage/storage_api.h"
#include "extensions/browser/extension_function_registry.h"

namespace extensions {
Expand All @@ -36,6 +37,12 @@ const char* const kSupportedAPIs[] = {
EXTENSION_FUNCTION_NAME(AlarmsGetAllFunction),
EXTENSION_FUNCTION_NAME(AlarmsClearFunction),
EXTENSION_FUNCTION_NAME(AlarmsClearAllFunction),
"storage",
EXTENSION_FUNCTION_NAME(StorageStorageAreaGetFunction),
EXTENSION_FUNCTION_NAME(StorageStorageAreaSetFunction),
EXTENSION_FUNCTION_NAME(StorageStorageAreaRemoveFunction),
EXTENSION_FUNCTION_NAME(StorageStorageAreaClearFunction),
EXTENSION_FUNCTION_NAME(StorageStorageAreaGetBytesInUseFunction),
"tabs",
EXTENSION_FUNCTION_NAME(cefimpl::TabsGetFunction),
EXTENSION_FUNCTION_NAME(cefimpl::TabsExecuteScriptFunction),
Expand Down Expand Up @@ -67,6 +74,11 @@ void ChromeFunctionRegistry::RegisterAll(ExtensionFunctionRegistry* registry) {
registry->RegisterFunction<AlarmsGetAllFunction>();
registry->RegisterFunction<AlarmsClearFunction>();
registry->RegisterFunction<AlarmsClearAllFunction>();
registry->RegisterFunction<StorageStorageAreaGetFunction>();
registry->RegisterFunction<StorageStorageAreaSetFunction>();
registry->RegisterFunction<StorageStorageAreaRemoveFunction>();
registry->RegisterFunction<StorageStorageAreaClearFunction>();
registry->RegisterFunction<StorageStorageAreaGetBytesInUseFunction>();
registry->RegisterFunction<cefimpl::TabsExecuteScriptFunction>();
registry->RegisterFunction<cefimpl::TabsInsertCSSFunction>();
registry->RegisterFunction<cefimpl::TabsGetFunction>();
Expand Down
29 changes: 24 additions & 5 deletions libcef/browser/extensions/extension_system.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "libcef/browser/extension_impl.h"
#include "libcef/browser/extensions/pdf_extension_util.h"
#include "libcef/browser/extensions/value_store/cef_value_store_factory.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/extensions/extensions_util.h"

Expand All @@ -21,6 +22,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_paths.h"
#include "components/crx_file/id_util.h"
#include "content/public/browser/browser_context.h"
Expand All @@ -40,7 +42,7 @@
#include "extensions/browser/renderer_startup_helper.h"
#include "extensions/browser/runtime_data.h"
#include "extensions/browser/service_worker_manager.h"
#include "extensions/browser/value_store/value_store_factory.h"
#include "extensions/browser/state_store.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/file_util.h"
Expand Down Expand Up @@ -153,7 +155,9 @@ CefExtensionSystem::CefExtensionSystem(BrowserContext* browser_context)
renderer_helper_(
extensions::RendererStartupHelperFactory::GetForBrowserContext(
browser_context)),
weak_ptr_factory_(this) {}
weak_ptr_factory_(this) {
InitPrefs();
}

CefExtensionSystem::~CefExtensionSystem() {}

Expand Down Expand Up @@ -384,15 +388,15 @@ SharedUserScriptMaster* CefExtensionSystem::shared_user_script_master() {
}

StateStore* CefExtensionSystem::state_store() {
return nullptr;
return state_store_.get();
}

StateStore* CefExtensionSystem::rules_store() {
return nullptr;
return rules_store_.get();
}

scoped_refptr<ValueStoreFactory> CefExtensionSystem::store_factory() {
return nullptr;
return store_factory_;
}

InfoMap* CefExtensionSystem::info_map() {
Expand Down Expand Up @@ -467,6 +471,21 @@ CefExtensionSystem::ComponentExtensionInfo::ComponentExtensionInfo(
}
}

void CefExtensionSystem::InitPrefs() {
store_factory_ = new CefValueStoreFactory(browser_context_->GetPath());

Profile* profile = Profile::FromBrowserContext(browser_context_);

// Two state stores. The latter, which contains declarative rules, must be
// loaded immediately so that the rules are ready before we issue network
// requests.
state_store_.reset(new StateStore(
profile, store_factory_, ValueStoreFrontend::BackendType::STATE, true));

rules_store_.reset(new StateStore(
profile, store_factory_, ValueStoreFrontend::BackendType::RULES, false));
}

// Implementation based on ComponentLoader::CreateExtension.
scoped_refptr<const Extension> CefExtensionSystem::CreateExtension(
const ComponentExtensionInfo& info,
Expand Down
6 changes: 6 additions & 0 deletions libcef/browser/extensions/extension_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ class CefExtensionSystem : public ExtensionSystem {
bool initialized() const { return initialized_; }

private:
virtual void InitPrefs();

// Information about a registered component extension.
struct ComponentExtensionInfo {
ComponentExtensionInfo(const base::DictionaryValue* manifest,
Expand Down Expand Up @@ -169,6 +171,10 @@ class CefExtensionSystem : public ExtensionSystem {
std::unique_ptr<QuotaService> quota_service_;
std::unique_ptr<AppSorting> app_sorting_;

std::unique_ptr<StateStore> state_store_;
std::unique_ptr<StateStore> rules_store_;
scoped_refptr<ValueStoreFactory> store_factory_;

// Signaled when the extension system has completed its startup tasks.
OneShotEvent ready_;

Expand Down
14 changes: 14 additions & 0 deletions libcef/browser/extensions/extensions_api_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "include/internal/cef_types_wrappers.h"
#include "libcef/browser/browser_context_impl.h"
#include "libcef/browser/extensions/api/storage/sync_value_store_cache.h"
#include "libcef/browser/extensions/extension_web_contents_observer.h"
#include "libcef/browser/extensions/mime_handler_view_guest_delegate.h"
#include "libcef/browser/extensions/pdf_web_contents_helper_client.h"
Expand Down Expand Up @@ -66,4 +67,17 @@ void CefExtensionsAPIClient::AttachWebContentsHelpers(
zoom::ZoomController::CreateForWebContents(web_contents);
}

void CefExtensionsAPIClient::AddAdditionalValueStoreCaches(
content::BrowserContext* context,
const scoped_refptr<ValueStoreFactory>& factory,
const scoped_refptr<base::ObserverListThreadSafe<SettingsObserver>>&
observers,
std::map<settings_namespace::Namespace, ValueStoreCache*>* caches) {
// Add support for chrome.storage.sync.
// Because we don't support syncing with Google, we follow the behavior of
// chrome.storage.sync as if Chrome were permanently offline, by using a local
// store see: https://developer.chrome.com/apps/storage for more information
(*caches)[settings_namespace::SYNC] = new cef::SyncValueStoreCache(factory);
}

} // namespace extensions
12 changes: 12 additions & 0 deletions libcef/browser/extensions/extensions_api_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ class CefExtensionsAPIClient : public ExtensionsAPIClient {
MimeHandlerViewGuest* guest) const override;
void AttachWebContentsHelpers(
content::WebContents* web_contents) const override;

// Storage API support.

// Add any additional value store caches (e.g. for chrome.storage.managed)
// to |caches|. By default adds nothing.
void AddAdditionalValueStoreCaches(
content::BrowserContext* context,
const scoped_refptr<ValueStoreFactory>& factory,
const scoped_refptr<base::ObserverListThreadSafe<SettingsObserver>>&
observers,
std::map<settings_namespace::Namespace, ValueStoreCache*>* caches)
override;
};

} // namespace extensions
Expand Down
Loading

0 comments on commit ff8b4aa

Please sign in to comment.