blob: 44c08566d117109fdf23103b8886d5deb05841ca [file] [log] [blame]
// Copyright 2016 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 "extensions/browser/value_store/legacy_value_store_factory.h"
#include <string>
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "extensions/browser/value_store/leveldb_value_store.h"
#include "extensions/common/constants.h"
using base::AutoLock;
namespace {
// Statistics are logged to UMA with these strings as part of histogram name.
// They can all be found under Extensions.Database.Open.<client>. Changing this
// needs to synchronize with histograms.xml, AND will also become incompatible
// with older browsers still reporting the previous values.
const char kSettingsDatabaseUMAClientName[] = "Settings";
const char kRulesDatabaseUMAClientName[] = "Rules";
const char kStateDatabaseUMAClientName[] = "State";
bool ValidDBExists(const base::FilePath& path) {
// TODO(cmumford): Enhance to detect if dir contains valid database.
return base::DirectoryExists(path);
}
} // namespace
namespace extensions {
//
// ModelSettings
//
LegacyValueStoreFactory::ModelSettings::ModelSettings(
const base::FilePath& data_path)
: data_path_(data_path) {}
base::FilePath LegacyValueStoreFactory::ModelSettings::GetDBPath(
const ExtensionId& extension_id) const {
return data_path_.AppendASCII(extension_id);
}
bool LegacyValueStoreFactory::ModelSettings::DeleteData(
const ExtensionId& extension_id) {
return base::DeleteFile(GetDBPath(extension_id), true /* recursive */);
}
bool LegacyValueStoreFactory::ModelSettings::DataExists(
const ExtensionId& extension_id) const {
return ValidDBExists(GetDBPath(extension_id));
}
std::set<ExtensionId>
LegacyValueStoreFactory::ModelSettings::GetKnownExtensionIDs() const {
std::set<ExtensionId> result;
// Leveldb databases are directories inside |base_path_|.
base::FileEnumerator extension_dirs(data_path_, false,
base::FileEnumerator::DIRECTORIES);
while (!extension_dirs.Next().empty()) {
base::FilePath extension_dir = extension_dirs.GetInfo().GetName();
DCHECK(!extension_dir.IsAbsolute());
// Extension ID's are 'a'..'p', so any directory within this folder will
// either be ASCII, or created by some other application and safe to ignore.
std::string maybe_as_ascii(extension_dir.MaybeAsASCII());
if (!maybe_as_ascii.empty()) {
result.insert(maybe_as_ascii);
}
}
return result;
}
//
// SettingsRoot
//
LegacyValueStoreFactory::SettingsRoot::SettingsRoot(
const base::FilePath& base_path,
const std::string& extension_dirname,
const std::string& app_dirname) {
if (!extension_dirname.empty())
extensions_.reset(
new ModelSettings(base_path.AppendASCII(extension_dirname)));
if (!app_dirname.empty())
apps_.reset(new ModelSettings(base_path.AppendASCII(app_dirname)));
}
LegacyValueStoreFactory::SettingsRoot::~SettingsRoot() = default;
const LegacyValueStoreFactory::ModelSettings*
LegacyValueStoreFactory::SettingsRoot::GetModel(ModelType model_type) const {
switch (model_type) {
case ValueStoreFactory::ModelType::APP:
DCHECK(apps_ != nullptr);
return apps_.get();
case ValueStoreFactory::ModelType::EXTENSION:
DCHECK(extensions_ != nullptr);
return extensions_.get();
}
NOTREACHED();
return nullptr;
}
LegacyValueStoreFactory::ModelSettings*
LegacyValueStoreFactory::SettingsRoot::GetModel(ModelType model_type) {
switch (model_type) {
case ValueStoreFactory::ModelType::APP:
DCHECK(apps_ != nullptr);
return apps_.get();
case ValueStoreFactory::ModelType::EXTENSION:
DCHECK(extensions_ != nullptr);
return extensions_.get();
}
NOTREACHED();
return nullptr;
}
std::set<ExtensionId>
LegacyValueStoreFactory::SettingsRoot::GetKnownExtensionIDs(
ModelType model_type) const {
switch (model_type) {
case ValueStoreFactory::ModelType::APP:
DCHECK(apps_ != nullptr);
return apps_->GetKnownExtensionIDs();
case ValueStoreFactory::ModelType::EXTENSION:
DCHECK(extensions_ != nullptr);
return extensions_->GetKnownExtensionIDs();
}
NOTREACHED();
return std::set<ExtensionId>();
}
//
// LegacyValueStoreFactory
//
LegacyValueStoreFactory::LegacyValueStoreFactory(
const base::FilePath& profile_path)
: profile_path_(profile_path),
local_settings_(profile_path,
kLocalExtensionSettingsDirectoryName,
kLocalAppSettingsDirectoryName),
sync_settings_(profile_path,
kSyncExtensionSettingsDirectoryName,
kSyncAppSettingsDirectoryName),
// Currently no such thing as a managed app - only an extension.
managed_settings_(profile_path, kManagedSettingsDirectoryName, "") {}
LegacyValueStoreFactory::~LegacyValueStoreFactory() = default;
bool LegacyValueStoreFactory::RulesDBExists() const {
return ValidDBExists(GetRulesDBPath());
}
bool LegacyValueStoreFactory::StateDBExists() const {
return ValidDBExists(GetStateDBPath());
}
std::unique_ptr<ValueStore> LegacyValueStoreFactory::CreateRulesStore() {
return std::make_unique<LeveldbValueStore>(kRulesDatabaseUMAClientName,
GetRulesDBPath());
}
std::unique_ptr<ValueStore> LegacyValueStoreFactory::CreateStateStore() {
return std::make_unique<LeveldbValueStore>(kStateDatabaseUMAClientName,
GetStateDBPath());
}
std::unique_ptr<ValueStore> LegacyValueStoreFactory::CreateSettingsStore(
settings_namespace::Namespace settings_namespace,
ModelType model_type,
const ExtensionId& extension_id) {
const ModelSettings* settings_root =
GetSettingsRoot(settings_namespace).GetModel(model_type);
DCHECK(settings_root != nullptr);
return std::make_unique<LeveldbValueStore>(
kSettingsDatabaseUMAClientName, settings_root->GetDBPath(extension_id));
}
void LegacyValueStoreFactory::DeleteSettings(
settings_namespace::Namespace settings_namespace,
ModelType model_type,
const ExtensionId& extension_id) {
ModelSettings* model_settings =
GetSettingsRoot(settings_namespace).GetModel(model_type);
if (model_settings == nullptr) {
NOTREACHED();
return;
}
model_settings->DeleteData(extension_id);
}
bool LegacyValueStoreFactory::HasSettings(
settings_namespace::Namespace settings_namespace,
ModelType model_type,
const ExtensionId& extension_id) {
const ModelSettings* model_settings =
GetSettingsRoot(settings_namespace).GetModel(model_type);
if (model_settings == nullptr)
return false;
return model_settings->DataExists(extension_id);
}
std::set<ExtensionId> LegacyValueStoreFactory::GetKnownExtensionIDs(
settings_namespace::Namespace settings_type,
ModelType model_type) const {
return GetSettingsRoot(settings_type).GetKnownExtensionIDs(model_type);
}
const LegacyValueStoreFactory::SettingsRoot&
LegacyValueStoreFactory::GetSettingsRoot(
settings_namespace::Namespace settings_namespace) const {
switch (settings_namespace) {
case settings_namespace::LOCAL:
return local_settings_;
case settings_namespace::SYNC:
return sync_settings_;
case settings_namespace::MANAGED:
return managed_settings_;
case settings_namespace::INVALID:
break;
}
NOTREACHED();
return local_settings_;
}
LegacyValueStoreFactory::SettingsRoot& LegacyValueStoreFactory::GetSettingsRoot(
settings_namespace::Namespace settings_namespace) {
switch (settings_namespace) {
case settings_namespace::LOCAL:
return local_settings_;
case settings_namespace::SYNC:
return sync_settings_;
case settings_namespace::MANAGED:
return managed_settings_;
case settings_namespace::INVALID:
break;
}
NOTREACHED();
return local_settings_;
}
base::FilePath LegacyValueStoreFactory::GetRulesDBPath() const {
return profile_path_.AppendASCII(kRulesStoreName);
}
base::FilePath LegacyValueStoreFactory::GetStateDBPath() const {
return profile_path_.AppendASCII(kStateStoreName);
}
} // namespace extensions