blob: f4ef73694f07cda6e476b07c70ddf253207a24d1 [file] [log] [blame]
// Copyright 2020 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_allowlist.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "extensions/browser/allowlist_state.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension_features.h"
namespace extensions {
ExtensionAllowlist::ExtensionAllowlist(Profile* profile,
ExtensionPrefs* extension_prefs,
ExtensionService* extension_service)
: profile_(profile),
extension_prefs_(extension_prefs),
extension_service_(extension_service),
registry_(ExtensionRegistry::Get(profile)) {}
void ExtensionAllowlist::Init() {
SetAllowlistEnforcedField();
// Register to Enhanced Safe Browsing setting changes for allowlist
// enforcements.
pref_change_registrar_.Init(profile_->GetPrefs());
pref_change_registrar_.Add(
prefs::kSafeBrowsingEnhanced,
base::BindRepeating(&ExtensionAllowlist::OnSafeBrowsingEnhancedChanged,
base::Unretained(this)));
if (is_allowlist_enforced_) {
ActivateAllowlistEnforcement();
} else {
DeactivateAllowlistEnforcement();
}
}
void ExtensionAllowlist::PerformActionBasedOnOmahaAttributes(
const std::string& extension_id,
const base::Value& attributes) {
const base::Value* allowlist_value = attributes.FindKey("_esbAllowist");
if (!allowlist_value) {
// TODO(jeffcyr): Add metric to track if there is an issue.
// Ignore missing attribute. Omaha server should set the attribute to |true|
// or |false|. This way the allowlist state won't flip if there is a server
// bug where the attribute isn't sent. This will also leave external
// extensions in the |ALLOWLIST_UNDEFINED| state.
return;
}
bool allowlisted = allowlist_value->GetBool();
// TODO(jeffcyr): Add an observer when allowlist state change, otherwise the
// 'chrome://extensions' warning may not be refreshed.
// Set the allowlist state even if there is no enforcement. This will allow
// immediate enforcement when it is activated.
extension_prefs_->SetExtensionAllowlistState(
extension_id,
allowlisted ? ALLOWLIST_ALLOWLISTED : ALLOWLIST_NOT_ALLOWLISTED);
if (!is_allowlist_enforced_) {
DCHECK(!extension_prefs_->HasDisableReason(
extension_id, disable_reason::DISABLE_NOT_ALLOWLISTED));
return;
}
if (allowlisted) {
extension_service_->RemoveDisableReasonAndMaybeEnable(
extension_id, disable_reason::DISABLE_NOT_ALLOWLISTED);
} else {
// TODO(jeffcyr): User re-enable is broken, if the user manually re-enabled
// the extension, it is currently disabled again on the next update check or
// restart. This will be fixed before launch.
extension_service_->DisableExtension(
extension_id, disable_reason::DISABLE_NOT_ALLOWLISTED);
}
}
bool ExtensionAllowlist::ShouldDisplayWarning(
const std::string& extension_id) const {
return is_allowlist_enforced_ &&
extension_prefs_->GetExtensionAllowlistState(extension_id) ==
ALLOWLIST_NOT_ALLOWLISTED;
}
void ExtensionAllowlist::SetAllowlistEnforcedField() {
is_allowlist_enforced_ =
base::FeatureList::IsEnabled(
extensions_features::kEnforceSafeBrowsingExtensionAllowlist) &&
safe_browsing::IsEnhancedProtectionEnabled(*profile_->GetPrefs());
}
void ExtensionAllowlist::ActivateAllowlistEnforcement() {
DCHECK(is_allowlist_enforced_);
std::unique_ptr<ExtensionSet> all_extensions =
registry_->GenerateInstalledExtensionsSet();
for (const auto& extension : *all_extensions) {
if (extension_prefs_->GetExtensionAllowlistState(extension->id()) ==
ALLOWLIST_NOT_ALLOWLISTED) {
extension_service_->DisableExtension(
extension->id(), disable_reason::DISABLE_NOT_ALLOWLISTED);
}
}
}
void ExtensionAllowlist::DeactivateAllowlistEnforcement() {
DCHECK(!is_allowlist_enforced_);
std::unique_ptr<ExtensionSet> all_extensions =
registry_->GenerateInstalledExtensionsSet();
for (const auto& extension : *all_extensions) {
extension_service_->RemoveDisableReasonAndMaybeEnable(
extension->id(), disable_reason::DISABLE_NOT_ALLOWLISTED);
}
}
void ExtensionAllowlist::OnSafeBrowsingEnhancedChanged() {
bool old_value = is_allowlist_enforced_;
// Note that |is_allowlist_enforced_| could remain |false| even if the ESB
// setting was turned on if the feature flag is disabled.
SetAllowlistEnforcedField();
if (old_value == is_allowlist_enforced_)
return;
if (is_allowlist_enforced_) {
ActivateAllowlistEnforcement();
} else {
DeactivateAllowlistEnforcement();
}
}
} // namespace extensions