blob: 9f265b2be93feb6c813fd044cd7e9f57c50fe7c4 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/policy/content/policy_blocklist_service.h"
#include <utility>
#include "base/functional/bind.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "base/functional/callback_forward.h"
#endif
#if BUILDFLAG(IS_CHROMEOS)
constexpr char kAllTrafficWildcard[] = "*";
// Returns a URL filter that covers all URL navigations.
base::Value::List GetAllTrafficFilter() {
base::Value::List all_traffic;
all_traffic.Append(kAllTrafficWildcard);
return all_traffic;
}
// BlocklistSource implementation that blocks all traffic with the
// exception of URLs specified by the admin via the policy
// AlwaysOnVpnPreConnectUrlAllowlist.
// Note that this implementation only supports one observer at a time. Adding a
// new observer will remove the previous one.
class AlwaysOnVpnPreConnectBlocklistSource : public policy::BlocklistSource {
public:
AlwaysOnVpnPreConnectBlocklistSource(PrefService* pref_service)
: blocklist_(GetAllTrafficFilter()) {
pref_change_registrar_.Init(pref_service);
}
AlwaysOnVpnPreConnectBlocklistSource(
const AlwaysOnVpnPreConnectBlocklistSource&) = delete;
AlwaysOnVpnPreConnectBlocklistSource& operator=(
const AlwaysOnVpnPreConnectBlocklistSource&) = delete;
~AlwaysOnVpnPreConnectBlocklistSource() override = default;
const base::Value::List* GetBlocklistSpec() const override {
return &blocklist_;
}
const base::Value::List* GetAllowlistSpec() const override {
return &pref_change_registrar_.prefs()->GetList(
policy::policy_prefs::kAlwaysOnVpnPreConnectUrlAllowlist);
}
// Adds an observer which will be notified when the blocklist is updated, i.e.
// when the preference `
// policy::policy_prefs::kAlwaysOnVpnPreConnectUrlAllowlist` has a new value.
// If an observer already exists, it will be removed.
void SetBlocklistObserver(base::RepeatingClosure observer) override {
pref_change_registrar_.RemoveAll();
pref_change_registrar_.Add(
policy::policy_prefs::kAlwaysOnVpnPreConnectUrlAllowlist, observer);
}
private:
const base::Value::List blocklist_;
PrefChangeRegistrar pref_change_registrar_;
};
#endif
PolicyBlocklistService::PolicyBlocklistService(
std::unique_ptr<policy::URLBlocklistManager> url_blocklist_manager,
PrefService* user_prefs)
: url_blocklist_manager_(std::move(url_blocklist_manager)),
user_prefs_(user_prefs) {
CHECK(user_prefs_);
}
PolicyBlocklistService::~PolicyBlocklistService() = default;
policy::URLBlocklist::URLBlocklistState
PolicyBlocklistService::GetURLBlocklistState(const GURL& url) const {
return url_blocklist_manager_->GetURLBlocklistState(url);
}
#if BUILDFLAG(IS_CHROMEOS)
void PolicyBlocklistService::SetAlwaysOnVpnPreConnectUrlAllowlistEnforced(
bool enforced) {
if (enforced) {
url_blocklist_manager_->SetOverrideBlockListSource(
std::make_unique<AlwaysOnVpnPreConnectBlocklistSource>(user_prefs_));
return;
}
url_blocklist_manager_->SetOverrideBlockListSource(nullptr);
}
#endif
// static
PolicyBlocklistFactory* PolicyBlocklistFactory::GetInstance() {
return base::Singleton<PolicyBlocklistFactory>::get();
}
// static
PolicyBlocklistService* PolicyBlocklistFactory::GetForBrowserContext(
content::BrowserContext* context) {
return static_cast<PolicyBlocklistService*>(
GetInstance()->GetServiceForBrowserContext(context, true));
}
PolicyBlocklistFactory::PolicyBlocklistFactory()
: BrowserContextKeyedServiceFactory(
"PolicyBlocklist",
BrowserContextDependencyManager::GetInstance()) {}
PolicyBlocklistFactory::~PolicyBlocklistFactory() = default;
std::unique_ptr<KeyedService>
PolicyBlocklistFactory::BuildServiceInstanceForBrowserContext(
content::BrowserContext* context) const {
PrefService* pref_service = user_prefs::UserPrefs::Get(context);
auto url_blocklist_manager = std::make_unique<policy::URLBlocklistManager>(
pref_service, policy::policy_prefs::kUrlBlocklist,
policy::policy_prefs::kUrlAllowlist);
return std::make_unique<PolicyBlocklistService>(
std::move(url_blocklist_manager), pref_service);
}
content::BrowserContext* PolicyBlocklistFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return context;
}