blob: 5d317f8273d75012140d1b48fe887464ede50c75 [file] [log] [blame]
// 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 "chrome/browser/extensions/extension_management_internal.h"
#include <utility>
#include "base/logging.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/extensions/extension_management_constants.h"
#include "extensions/common/url_pattern_set.h"
#include "url/gurl.h"
namespace extensions {
namespace internal {
namespace {
const char kMalformedPreferenceWarning[] =
"Malformed extension management preference.";
} // namespace
IndividualSettings::IndividualSettings() {
Reset();
}
// Initializes from default settings.
IndividualSettings::IndividualSettings(
const IndividualSettings* default_settings) {
installation_mode = default_settings->installation_mode;
update_url = default_settings->installation_mode;
blocked_permissions = default_settings->blocked_permissions;
// We are not initializing |minimum_version_required| from |default_settings|
// here since it's not applicable to default settings.
}
IndividualSettings::~IndividualSettings() {
}
bool IndividualSettings::Parse(const base::DictionaryValue* dict,
ParsingScope scope) {
std::string installation_mode_str;
if (dict->GetStringWithoutPathExpansion(schema_constants::kInstallationMode,
&installation_mode_str)) {
if (installation_mode_str == schema_constants::kAllowed) {
installation_mode = ExtensionManagement::INSTALLATION_ALLOWED;
} else if (installation_mode_str == schema_constants::kBlocked) {
installation_mode = ExtensionManagement::INSTALLATION_BLOCKED;
} else if (installation_mode_str == schema_constants::kForceInstalled) {
installation_mode = ExtensionManagement::INSTALLATION_FORCED;
} else if (installation_mode_str == schema_constants::kNormalInstalled) {
installation_mode = ExtensionManagement::INSTALLATION_RECOMMENDED;
} else {
// Invalid value for 'installation_mode'.
LOG(WARNING) << kMalformedPreferenceWarning;
return false;
}
// Only proceed to fetch update url if force or recommended install mode
// is set.
if (installation_mode == ExtensionManagement::INSTALLATION_FORCED ||
installation_mode == ExtensionManagement::INSTALLATION_RECOMMENDED) {
if (scope != SCOPE_INDIVIDUAL) {
// Only individual extensions are allowed to be automatically installed.
LOG(WARNING) << kMalformedPreferenceWarning;
return false;
}
std::string update_url_str;
if (dict->GetStringWithoutPathExpansion(schema_constants::kUpdateUrl,
&update_url_str) &&
GURL(update_url_str).is_valid()) {
update_url = update_url_str;
} else {
// No valid update URL for extension.
LOG(WARNING) << kMalformedPreferenceWarning;
return false;
}
}
}
// Parses the blocked permission settings.
const base::ListValue* list_value = nullptr;
base::string16 error;
// If applicable, inherit from global block list and remove all explicitly
// allowed permissions.
if (scope != SCOPE_DEFAULT &&
dict->GetListWithoutPathExpansion(schema_constants::kAllowedPermissions,
&list_value)) {
// It is assumed that Parse() is already called for SCOPE_DEFAULT and
// settings specified for |this| is initialized by copying from default
// settings, including the |blocked_permissions| setting here.
// That is, |blocked_permissions| should be the default block permissions
// list settings here.
APIPermissionSet globally_blocked_permissions = blocked_permissions;
APIPermissionSet explicitly_allowed_permissions;
// Reuses code for parsing API permissions from manifest. But note that we
// only support list of strings type.
if (!APIPermissionSet::ParseFromJSON(
list_value,
APIPermissionSet::kDisallowInternalPermissions,
&explicitly_allowed_permissions,
&error,
nullptr)) {
// There might be unknown permissions, warn and just ignore them;
LOG(WARNING) << error;
}
APIPermissionSet::Difference(globally_blocked_permissions,
explicitly_allowed_permissions,
&blocked_permissions);
}
// Then add all newly blocked permissions to the list.
if (dict->GetListWithoutPathExpansion(schema_constants::kBlockedPermissions,
&list_value)) {
// The |blocked_permissions| might be the result of the routines above,
// or remains the same as default block permissions settings.
APIPermissionSet permissions_to_merge_from = blocked_permissions;
APIPermissionSet permissions_parsed;
if (!APIPermissionSet::ParseFromJSON(
list_value,
APIPermissionSet::kDisallowInternalPermissions,
&permissions_parsed,
&error,
nullptr)) {
LOG(WARNING) << error;
}
APIPermissionSet::Union(
permissions_to_merge_from, permissions_parsed, &blocked_permissions);
}
// Parses the minimum version settings.
std::string minimum_version_required_str;
if (scope == SCOPE_INDIVIDUAL &&
dict->GetStringWithoutPathExpansion(
schema_constants::kMinimumVersionRequired,
&minimum_version_required_str)) {
std::unique_ptr<base::Version> version(
new base::Version(minimum_version_required_str));
// We accept a general version string here. Note that count of components in
// version string of extensions is limited to 4.
if (!version->IsValid())
LOG(WARNING) << kMalformedPreferenceWarning;
else
minimum_version_required = std::move(version);
}
return true;
}
void IndividualSettings::Reset() {
installation_mode = ExtensionManagement::INSTALLATION_ALLOWED;
update_url.clear();
blocked_permissions.clear();
}
GlobalSettings::GlobalSettings() {
Reset();
}
GlobalSettings::~GlobalSettings() {
}
void GlobalSettings::Reset() {
has_restricted_install_sources = false;
install_sources.ClearPatterns();
has_restricted_allowed_types = false;
allowed_types.clear();
}
} // namespace internal
} // namespace extensions