blob: 1f422dfbfffba3de666f5ddafdfdfcce78154539 [file] [log] [blame]
// Copyright 2019 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/chromeos/printing/calculators_policies_binder.h"
#include <list>
#include <map>
#include <string>
#include <vector>
#include "chrome/browser/chromeos/printing/bulk_printers_calculator.h"
#include "chrome/browser/chromeos/printing/bulk_printers_calculator_factory.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector_factory.h"
#include "chrome/common/pref_names.h"
#include "chromeos/settings/cros_settings_names.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
namespace chromeos {
namespace {
// It stores the number of bindings (instances of this class) connected to each
// BulkPrintersCalculator object. It allows us to make sure, that every
// BulkPrintersCalculator object is not binded more that once.
std::map<BulkPrintersCalculator*, unsigned>& BindingsCount() {
static base::NoDestructor<std::map<BulkPrintersCalculator*, unsigned>>
bindings_count;
return *bindings_count;
}
BulkPrintersCalculator::AccessMode ConvertToAccessMode(int mode_val) {
if (mode_val >= BulkPrintersCalculator::BLACKLIST_ONLY &&
mode_val <= BulkPrintersCalculator::ALL_ACCESS) {
return static_cast<BulkPrintersCalculator::AccessMode>(mode_val);
}
// Error occurred, let's return the default value.
LOG(ERROR) << "Unrecognized access mode";
return BulkPrintersCalculator::ALL_ACCESS;
}
std::vector<std::string> ConvertToVector(const base::ListValue* list) {
std::vector<std::string> string_list;
if (list) {
for (const base::Value& value : *list) {
if (value.is_string()) {
string_list.push_back(value.GetString());
}
}
}
return string_list;
}
class CalculatorsPoliciesBinderImpl : public CalculatorsPoliciesBinder {
public:
CalculatorsPoliciesBinderImpl(CrosSettings* settings, Profile* profile)
: settings_(settings), profile_(profile) {
pref_change_registrar_.Init(profile->GetPrefs());
// Bind device policies to corresponding instance of BulkPrintersCalculator.
device_printers_ = BulkPrintersCalculatorFactory::Get()->GetForDevice();
if (device_printers_ && ++(BindingsCount()[device_printers_.get()]) == 1) {
BindSettings(kDeviceNativePrintersAccessMode,
&CalculatorsPoliciesBinderImpl::UpdateDeviceAccessMode);
BindSettings(kDeviceNativePrintersBlacklist,
&CalculatorsPoliciesBinderImpl::UpdateDeviceBlacklist);
BindSettings(kDeviceNativePrintersWhitelist,
&CalculatorsPoliciesBinderImpl::UpdateDeviceWhitelist);
}
// Bind user policies to corresponding instance of BulkPrintersCalculator.
user_printers_ =
BulkPrintersCalculatorFactory::Get()->GetForProfile(profile);
if (user_printers_ && ++(BindingsCount()[user_printers_.get()]) == 1) {
BindPref(prefs::kRecommendedNativePrintersAccessMode,
&CalculatorsPoliciesBinderImpl::UpdateUserAccessMode);
BindPref(prefs::kRecommendedNativePrintersBlacklist,
&CalculatorsPoliciesBinderImpl::UpdateUserBlacklist);
BindPref(prefs::kRecommendedNativePrintersWhitelist,
&CalculatorsPoliciesBinderImpl::UpdateUserWhitelist);
}
}
~CalculatorsPoliciesBinderImpl() override {
// We have to decrease counters in bindings_count.
if (device_printers_ && --(BindingsCount()[device_printers_.get()]) == 0) {
BindingsCount().erase(device_printers_.get());
}
if (user_printers_ && --(BindingsCount()[user_printers_.get()]) == 0) {
BindingsCount().erase(user_printers_.get());
}
}
private:
// Methods propagating values from policies to BulkPrintersCalculator.
void UpdateDeviceAccessMode() {
int mode_val;
if (!settings_->GetInteger(kDeviceNativePrintersAccessMode, &mode_val)) {
mode_val = BulkPrintersCalculator::AccessMode::UNSET;
}
device_printers_->SetAccessMode(ConvertToAccessMode(mode_val));
}
void UpdateDeviceBlacklist() {
device_printers_->SetBlacklist(
FromSettings(kDeviceNativePrintersBlacklist));
}
void UpdateDeviceWhitelist() {
device_printers_->SetWhitelist(
FromSettings(kDeviceNativePrintersWhitelist));
}
void UpdateUserAccessMode() {
user_printers_->SetAccessMode(
ConvertToAccessMode(profile_->GetPrefs()->GetInteger(
prefs::kRecommendedNativePrintersAccessMode)));
}
void UpdateUserBlacklist() {
user_printers_->SetBlacklist(
FromPrefs(prefs::kRecommendedNativePrintersBlacklist));
}
void UpdateUserWhitelist() {
user_printers_->SetWhitelist(
FromPrefs(prefs::kRecommendedNativePrintersWhitelist));
}
typedef void (CalculatorsPoliciesBinderImpl::*SimpleMethod)();
// Binds given device policy to given method and calls this method once.
void BindPref(const char* policy_name, SimpleMethod method_to_call) {
pref_change_registrar_.Add(
policy_name,
base::BindRepeating(method_to_call, base::Unretained(this)));
(this->*method_to_call)();
}
// Binds given user policy to given method and calls this method once.
void BindSettings(const char* policy_name, SimpleMethod method_to_call) {
subscriptions_.push_back(settings_->AddSettingsObserver(
policy_name,
base::BindRepeating(method_to_call, base::Unretained(this))));
(this->*method_to_call)();
}
// Extracts the list of strings named |policy_name| from device policies.
std::vector<std::string> FromSettings(const std::string& policy_name) {
const base::ListValue* list;
if (!settings_->GetList(policy_name, &list)) {
list = nullptr;
}
return ConvertToVector(list);
}
// Extracts the list of strings named |policy_name| from user policies.
std::vector<std::string> FromPrefs(const std::string& policy_name) {
return ConvertToVector(profile_->GetPrefs()->GetList(policy_name));
}
// Device and user bulk printers. Unowned.
base::WeakPtr<BulkPrintersCalculator> device_printers_;
base::WeakPtr<BulkPrintersCalculator> user_printers_;
// Device and profile (user) settings.
CrosSettings* settings_;
std::list<std::unique_ptr<CrosSettings::ObserverSubscription>> subscriptions_;
Profile* profile_;
PrefChangeRegistrar pref_change_registrar_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(CalculatorsPoliciesBinderImpl);
};
} // namespace
// static
void CalculatorsPoliciesBinder::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
// Default value for access mode is AllAccess.
registry->RegisterIntegerPref(prefs::kRecommendedNativePrintersAccessMode,
BulkPrintersCalculator::ALL_ACCESS);
registry->RegisterListPref(prefs::kRecommendedNativePrintersBlacklist);
registry->RegisterListPref(prefs::kRecommendedNativePrintersWhitelist);
}
// static
std::unique_ptr<CalculatorsPoliciesBinder> CalculatorsPoliciesBinder::Create(
CrosSettings* settings,
Profile* profile) {
return std::make_unique<CalculatorsPoliciesBinderImpl>(settings, profile);
}
} // namespace chromeos