Commit 9deda679 authored by Piotr Pawliczek's avatar Piotr Pawliczek Committed by Commit Bot

Delay querying for printers list until the policy file is parsed

A list of enterpise printers is not ready immediately after creation of
CupsPrintersManager. It caused a problem for testing procedure since from the
level of autotest_private_api we do not know if the final list is ready or
there are still some ongoing calculations. A new method called
OnEnterprisePrintersInitialized() was added to the observer of
CupsPrintersManager to solve this issue. Also whole code related to
enterprise printers were refactored, large part of functionality was moved
from SyncedPrintersManager to new class EnterprisePrintersProvider. Classes
ExternalPrintersPrefBridge and DeviceExternalPrintersSettingsBridge have been
merged into one class called CalculatorsPoliciesBinder.
This is reland of CL:1220547, it fixes the problem detected by the test
AutotestPrivateApiTest.AutotestPrivate (method execution after destruction
of CupsPrintersManager object).

BUG=chromium:816996
TEST=Tested on cave with the use of CL:1451591
TBR=achuith@chromium.org

Change-Id: I70958421aadd9fab9a2401555bef0dbb28ad5a6a
Reviewed-on: https://chromium-review.googlesource.com/c/1491909
Commit-Queue: Piotr Pawliczek <pawliczek@chromium.org>
Reviewed-by: default avatarSean Kau <skau@chromium.org>
Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Auto-Submit: Piotr Pawliczek <pawliczek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#636618}
parent e9d84e43
......@@ -1744,6 +1744,12 @@ source_set("chromeos") {
"preferences.h",
"prefs/pref_connector_service.cc",
"prefs/pref_connector_service.h",
"printing/bulk_printers_calculator.cc",
"printing/bulk_printers_calculator.h",
"printing/bulk_printers_calculator_factory.cc",
"printing/bulk_printers_calculator_factory.h",
"printing/calculators_policies_binder.cc",
"printing/calculators_policies_binder.h",
"printing/cups_print_job.cc",
"printing/cups_print_job.h",
"printing/cups_print_job_manager.cc",
......@@ -1758,17 +1764,8 @@ source_set("chromeos") {
"printing/cups_printers_manager.h",
"printing/cups_printers_manager_factory.cc",
"printing/cups_printers_manager_factory.h",
"printing/device_external_printers_factory.cc",
"printing/device_external_printers_factory.h",
"printing/device_external_printers_settings_bridge.cc",
"printing/device_external_printers_settings_bridge.h",
"printing/external_printers.cc",
"printing/external_printers.h",
"printing/external_printers_factory.cc",
"printing/external_printers_factory.h",
"printing/external_printers_policies.h",
"printing/external_printers_pref_bridge.cc",
"printing/external_printers_pref_bridge.h",
"printing/enterprise_printers_provider.cc",
"printing/enterprise_printers_provider.h",
"printing/ppd_provider_factory.cc",
"printing/ppd_provider_factory.h",
"printing/printer_configurer.cc",
......@@ -2464,8 +2461,8 @@ source_set("unit_tests") {
"power/process_data_collector_unittest.cc",
"power/renderer_freezer_unittest.cc",
"preferences_unittest.cc",
"printing/bulk_printers_calculator_unittest.cc",
"printing/cups_printers_manager_unittest.cc",
"printing/external_printers_unittest.cc",
"printing/printer_detector_test_util.h",
"printing/printer_event_tracker_unittest.cc",
"printing/printers_sync_bridge_unittest.cc",
......
......@@ -1065,32 +1065,69 @@ void AutotestPrivateTakeScreenshotFunction::ScreenshotTaken(
// AutotestPrivateGetPrinterListFunction
///////////////////////////////////////////////////////////////////////////////
AutotestPrivateGetPrinterListFunction::AutotestPrivateGetPrinterListFunction()
: results_(std::make_unique<base::Value>(base::Value::Type::LIST)) {}
AutotestPrivateGetPrinterListFunction::
~AutotestPrivateGetPrinterListFunction() = default;
~AutotestPrivateGetPrinterListFunction() {
printers_manager_->RemoveObserver(this);
}
ExtensionFunction::ResponseAction AutotestPrivateGetPrinterListFunction::Run() {
DVLOG(1) << "AutotestPrivateGetPrinterListFunction";
auto values = std::make_unique<base::ListValue>();
Profile* profile = Profile::FromBrowserContext(browser_context());
std::unique_ptr<chromeos::CupsPrintersManager> printers_manager =
chromeos::CupsPrintersManager::Create(profile);
printers_manager_ = chromeos::CupsPrintersManager::Create(profile);
printers_manager_->AddObserver(this);
// Set up a timer to finish waiting after 10 seconds
timeout_timer_.Start(
FROM_HERE, base::TimeDelta::FromSeconds(10),
base::BindOnce(
&AutotestPrivateGetPrinterListFunction::RespondWithTimeoutError,
this));
return RespondLater();
}
void AutotestPrivateGetPrinterListFunction::RespondWithTimeoutError() {
if (did_respond())
return;
Respond(Error("Timeout occured before Enterprise printers were initialized"));
}
void AutotestPrivateGetPrinterListFunction::RespondWithSuccess() {
if (did_respond())
return;
Respond(OneArgument(std::move(results_)));
}
void AutotestPrivateGetPrinterListFunction::OnEnterprisePrintersInitialized() {
// We are ready to get the list of printers and finish.
std::vector<chromeos::CupsPrintersManager::PrinterClass> printer_type = {
chromeos::CupsPrintersManager::PrinterClass::kConfigured,
chromeos::CupsPrintersManager::PrinterClass::kEnterprise,
chromeos::CupsPrintersManager::PrinterClass::kAutomatic};
base::Value::ListStorage& vresults = results_->GetList();
for (const auto& type : printer_type) {
std::vector<chromeos::Printer> printer_list =
printers_manager->GetPrinters(type);
printers_manager_->GetPrinters(type);
for (const auto& printer : printer_list) {
auto result = std::make_unique<base::DictionaryValue>();
result->SetString("printerName", printer.display_name());
result->SetString("printerId", printer.id());
result->SetString("printerType", GetPrinterType(type));
values->Append(std::move(result));
vresults.push_back(base::Value(base::Value::Type::DICTIONARY));
base::Value& result = vresults.back();
result.SetKey("printerName", base::Value(printer.display_name()));
result.SetKey("printerId", base::Value(printer.id()));
result.SetKey("printerType", base::Value(GetPrinterType(type)));
}
}
return RespondNow(OneArgument(std::move(values)));
// We have to respond in separate task, because it will cause a destruction of
// CupsPrintersManager
const bool posted = PostTask(
FROM_HERE,
base::BindOnce(&AutotestPrivateGetPrinterListFunction::RespondWithSuccess,
this));
if (posted)
timeout_timer_.AbandonAndStop();
}
///////////////////////////////////////////////////////////////////////////////
......
......@@ -382,14 +382,24 @@ class AutotestPrivateTakeScreenshotFunction : public UIThreadExtensionFunction {
scoped_refptr<base::RefCountedMemory> png_data);
};
class AutotestPrivateGetPrinterListFunction : public UIThreadExtensionFunction {
class AutotestPrivateGetPrinterListFunction
: public UIThreadExtensionFunction,
public chromeos::CupsPrintersManager::Observer {
public:
DECLARE_EXTENSION_FUNCTION("autotestPrivate.getPrinterList",
AUTOTESTPRIVATE_GETPRINTERLIST)
AutotestPrivateGetPrinterListFunction();
private:
~AutotestPrivateGetPrinterListFunction() override;
ResponseAction Run() override;
void RespondWithTimeoutError();
void RespondWithSuccess();
// chromeos::CupsPrintersManager::Observer
void OnEnterprisePrintersInitialized() override;
std::unique_ptr<base::Value> results_;
std::unique_ptr<chromeos::CupsPrintersManager> printers_manager_;
base::OneShotTimer timeout_timer_;
};
class AutotestPrivateUpdatePrinterFunction : public UIThreadExtensionFunction {
......
......@@ -52,8 +52,8 @@
#include "chrome/browser/chromeos/login/users/supervised_user_manager_impl.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/device_network_configuration_updater.h"
#include "chrome/browser/chromeos/printing/external_printers.h"
#include "chrome/browser/chromeos/printing/external_printers_factory.h"
#include "chrome/browser/chromeos/printing/bulk_printers_calculator.h"
#include "chrome/browser/chromeos/printing/bulk_printers_calculator_factory.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/session_length_limiter.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
......@@ -194,9 +194,9 @@ policy::MinimumVersionPolicyHandler* GetMinimumVersionPolicyHandler() {
->GetMinimumVersionPolicyHandler();
}
base::WeakPtr<ExternalPrinters> GetExternalPrinters(
base::WeakPtr<BulkPrintersCalculator> GetBulkPrintersCalculator(
const AccountId& account_id) {
return ExternalPrintersFactory::Get()->GetForAccountId(account_id);
return BulkPrintersCalculatorFactory::Get()->GetForAccountId(account_id);
}
// Starts bluetooth logging service for accounts ending with |kGoogleDotCom|
......@@ -466,7 +466,7 @@ void ChromeUserManagerImpl::Shutdown() {
wallpaper_policy_observer_.reset();
// Remove the observer before shutting down the printer policy objects.
printers_policy_observer_.reset();
ExternalPrintersFactory::Get()->Shutdown();
BulkPrintersCalculatorFactory::Get()->ShutdownProfiles();
registrar_.RemoveAll();
}
......@@ -712,7 +712,7 @@ void ChromeUserManagerImpl::OnExternalDataSet(const std::string& policy,
if (policy == policy::key::kUserAvatarImage)
GetUserImageManager(account_id)->OnExternalDataSet(policy);
else if (policy == policy::key::kNativePrintersBulkConfiguration)
GetExternalPrinters(account_id)->ClearData();
GetBulkPrintersCalculator(account_id)->ClearData();
else if (policy != policy::key::kWallpaperImage)
NOTREACHED();
}
......@@ -724,7 +724,7 @@ void ChromeUserManagerImpl::OnExternalDataCleared(const std::string& policy,
if (policy == policy::key::kUserAvatarImage)
GetUserImageManager(account_id)->OnExternalDataCleared(policy);
else if (policy == policy::key::kNativePrintersBulkConfiguration)
GetExternalPrinters(account_id)->ClearData();
GetBulkPrintersCalculator(account_id)->ClearData();
else if (policy == policy::key::kWallpaperImage)
WallpaperControllerClient::Get()->RemovePolicyWallpaper(account_id);
else
......@@ -742,7 +742,7 @@ void ChromeUserManagerImpl::OnExternalDataFetched(
GetUserImageManager(account_id)
->OnExternalDataFetched(policy, std::move(data));
} else if (policy == policy::key::kNativePrintersBulkConfiguration) {
GetExternalPrinters(account_id)->SetData(std::move(data));
GetBulkPrintersCalculator(account_id)->SetData(std::move(data));
} else if (policy == policy::key::kWallpaperImage) {
WallpaperControllerClient::Get()->SetPolicyWallpaper(account_id,
std::move(data));
......@@ -1163,7 +1163,7 @@ void ChromeUserManagerImpl::RemoveNonCryptohomeData(
// |known_user::RemovePrefs|. See https://crbug.com/778077.
WallpaperControllerClient::Get()->RemoveUserWallpaper(account_id);
GetUserImageManager(account_id)->DeleteUserImage();
ExternalPrintersFactory::Get()->RemoveForUserId(account_id);
BulkPrintersCalculatorFactory::Get()->RemoveForUserId(account_id);
// TODO(tbarzic): Forward data removal request to ash::HammerDeviceHandler,
// instead of removing the prefs value here.
if (GetLocalState()->FindPreference(ash::prefs::kDetachableBaseDevices)) {
......
......@@ -26,7 +26,6 @@
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
#include "chrome/browser/chromeos/policy/minimum_version_policy_handler.h"
#include "chrome/browser/chromeos/printing/external_printers.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "components/account_id/account_id.h"
......
......@@ -7,16 +7,15 @@
#include <utility>
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/printing/device_external_printers_factory.h"
#include "chrome/browser/chromeos/printing/external_printers.h"
#include "chrome/browser/chromeos/printing/bulk_printers_calculator_factory.h"
#include "components/policy/policy_constants.h"
namespace policy {
namespace {
base::WeakPtr<chromeos::ExternalPrinters> GetExternalPrinters() {
return chromeos::DeviceExternalPrintersFactory::Get()->GetForDevice();
base::WeakPtr<chromeos::BulkPrintersCalculator> GetBulkPrintersCalculator() {
return chromeos::BulkPrintersCalculatorFactory::Get()->GetForDevice();
}
} // namespace
......@@ -33,25 +32,25 @@ DeviceNativePrintersHandler::~DeviceNativePrintersHandler() {}
void DeviceNativePrintersHandler::OnDeviceExternalDataSet(
const std::string& policy) {
GetExternalPrinters()->ClearData();
GetBulkPrintersCalculator()->ClearData();
}
void DeviceNativePrintersHandler::OnDeviceExternalDataCleared(
const std::string& policy) {
GetExternalPrinters()->ClearData();
GetBulkPrintersCalculator()->ClearData();
}
void DeviceNativePrintersHandler::OnDeviceExternalDataFetched(
const std::string& policy,
std::unique_ptr<std::string> data,
const base::FilePath& file_path) {
GetExternalPrinters()->SetData(std::move(data));
GetBulkPrintersCalculator()->SetData(std::move(data));
}
void DeviceNativePrintersHandler::Shutdown() {
if (device_native_printers_observer_)
device_native_printers_observer_.reset();
chromeos::DeviceExternalPrintersFactory::Get()->Shutdown();
chromeos::BulkPrintersCalculatorFactory::Get()->Shutdown();
}
} // namespace policy
......@@ -8,8 +8,8 @@
#include <string>
#include "base/test/scoped_task_environment.h"
#include "chrome/browser/chromeos/printing/device_external_printers_factory.h"
#include "chrome/browser/chromeos/printing/external_printers.h"
#include "chrome/browser/chromeos/printing/bulk_printers_calculator.h"
#include "chrome/browser/chromeos/printing/bulk_printers_calculator_factory.h"
#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
#include "chromeos/printing/printer_configuration.h"
#include "chromeos/settings/cros_settings_names.h"
......@@ -73,8 +73,9 @@ class DeviceNativePrintersHandlerTest : public testing::Test {
device_native_printers_handler_ =
std::make_unique<DeviceNativePrintersHandler>(&policy_service_);
external_printers_ =
chromeos::DeviceExternalPrintersFactory::Get()->GetForDevice();
external_printers_->SetAccessMode(chromeos::ExternalPrinters::ALL_ACCESS);
chromeos::BulkPrintersCalculatorFactory::Get()->GetForDevice();
external_printers_->SetAccessMode(
chromeos::BulkPrintersCalculator::ALL_ACCESS);
}
void TearDown() override { device_native_printers_handler_->Shutdown(); }
......@@ -83,7 +84,7 @@ class DeviceNativePrintersHandlerTest : public testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_;
MockPolicyService policy_service_;
std::unique_ptr<DeviceNativePrintersHandler> device_native_printers_handler_;
base::WeakPtr<chromeos::ExternalPrinters> external_printers_;
base::WeakPtr<chromeos::BulkPrintersCalculator> external_printers_;
};
TEST_F(DeviceNativePrintersHandlerTest, OnDataFetched) {
......
// 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.
#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_BULK_PRINTERS_CALCULATOR_H_
#define CHROME_BROWSER_CHROMEOS_PRINTING_BULK_PRINTERS_CALCULATOR_H_
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "chromeos/printing/printer_configuration.h"
namespace chromeos {
// Calculates a list of available printers from four policies: Data (json with
// all printers), AccessMode (see below), Whitelist and Blacklist (lists with
// ids). All methods must be called from the same sequence and all observers'
// notifications will be called from this sequence. Resultant list of available
// printers are calculated asynchronously on a dedicated internal sequence.
class BulkPrintersCalculator
: public base::SupportsWeakPtr<BulkPrintersCalculator> {
public:
// Algorithm used to calculate a list of available printers from the content
// of the "Data" policy.
enum AccessMode {
UNSET = -1,
// Printers in the blacklist are disallowed. Others are allowed.
BLACKLIST_ONLY = 0,
// Only printers in the whitelist are allowed.
WHITELIST_ONLY = 1,
// All printers in the "Data" policy are allowed.
ALL_ACCESS = 2
};
class Observer {
public:
// Observer is notified by this call when the state of the object changes.
// See the section "Methods returning the state of the object" below to
// learn about parameters defining the state of the object. |sender| is
// a pointer to the object calling the notification.
virtual void OnPrintersChanged(const BulkPrintersCalculator* sender) = 0;
};
static std::unique_ptr<BulkPrintersCalculator> Create();
virtual ~BulkPrintersCalculator() = default;
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
// ========================= Methods setting values of the four policies
// Sets the "Data" policy. |data| is a list of all printers in JSON format.
virtual void SetData(std::unique_ptr<std::string> data) = 0;
// Clears the "Data" policy.
virtual void ClearData() = 0;
// Sets the "AccessMode" policy. See description of the AccessMode enum.
virtual void SetAccessMode(AccessMode mode) = 0;
// Sets the "Blacklist" policy. |blacklist| is a list of printers ids.
virtual void SetBlacklist(const std::vector<std::string>& blacklist) = 0;
// Sets the "Whitelist" policy. |whitelist| is a list of printers ids.
virtual void SetWhitelist(const std::vector<std::string>& whitelist) = 0;
// ========================= Methods returning the state of the object
// Methods returning the three parameters defining the state of the object.
// Returns true if the "Data" policy has been set with SetData(...) method
// (may be not processed yet). Returns false if the "Data" policy has been
// cleared with ClearData() method or SetData(...) has been never called.
virtual bool IsDataPolicySet() const = 0;
// Returns false if current policies were not processed yet. Returns true
// if there is no on-going calculations and the method below returns the
// list of available printers that is up-to-date with current policies.
virtual bool IsComplete() const = 0;
// Returns a reference to a resultant list of available printers. Keys are
// printers ids. If the list of available printers cannot be calculated
// (because of some error or missing policy), an empty map is returned.
virtual const std::unordered_map<std::string, Printer>& GetPrinters()
const = 0;
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_PRINTING_BULK_PRINTERS_CALCULATOR_H_
......@@ -2,12 +2,12 @@
// 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/external_printers_factory.h"
#include "chrome/browser/chromeos/printing/bulk_printers_calculator_factory.h"
#include <memory>
#include "base/lazy_instance.h"
#include "chrome/browser/chromeos/printing/external_printers.h"
#include "chrome/browser/chromeos/printing/bulk_printers_calculator.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "components/user_manager/user.h"
......@@ -16,30 +16,30 @@ namespace chromeos {
namespace {
base::LazyInstance<ExternalPrintersFactory>::DestructorAtExit
base::LazyInstance<BulkPrintersCalculatorFactory>::DestructorAtExit
g_printers_factory = LAZY_INSTANCE_INITIALIZER;
} // namespace
// static
ExternalPrintersFactory* ExternalPrintersFactory::Get() {
BulkPrintersCalculatorFactory* BulkPrintersCalculatorFactory::Get() {
return g_printers_factory.Pointer();
}
base::WeakPtr<ExternalPrinters> ExternalPrintersFactory::GetForAccountId(
const AccountId& account_id) {
base::WeakPtr<BulkPrintersCalculator>
BulkPrintersCalculatorFactory::GetForAccountId(const AccountId& account_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto found = printers_by_user_.find(account_id);
if (found != printers_by_user_.end()) {
return found->second->AsWeakPtr();
}
printers_by_user_[account_id] = ExternalPrinters::Create();
printers_by_user_[account_id] = BulkPrintersCalculator::Create();
return printers_by_user_[account_id]->AsWeakPtr();
}
base::WeakPtr<ExternalPrinters> ExternalPrintersFactory::GetForProfile(
Profile* profile) {
base::WeakPtr<BulkPrintersCalculator>
BulkPrintersCalculatorFactory::GetForProfile(Profile* profile) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const user_manager::User* user =
ProfileHelper::Get()->GetUserByProfile(profile);
......@@ -49,17 +49,32 @@ base::WeakPtr<ExternalPrinters> ExternalPrintersFactory::GetForProfile(
return GetForAccountId(user->GetAccountId());
}
void ExternalPrintersFactory::RemoveForUserId(const AccountId& account_id) {
void BulkPrintersCalculatorFactory::RemoveForUserId(
const AccountId& account_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
printers_by_user_.erase(account_id);
}
void ExternalPrintersFactory::Shutdown() {
base::WeakPtr<BulkPrintersCalculator>
BulkPrintersCalculatorFactory::GetForDevice() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_printers_)
device_printers_ = BulkPrintersCalculator::Create();
return device_printers_->AsWeakPtr();
}
void BulkPrintersCalculatorFactory::ShutdownProfiles() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
printers_by_user_.clear();
}
void BulkPrintersCalculatorFactory::Shutdown() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
printers_by_user_.clear();
device_printers_.reset();
}
ExternalPrintersFactory::ExternalPrintersFactory() = default;
ExternalPrintersFactory::~ExternalPrintersFactory() = default;
BulkPrintersCalculatorFactory::BulkPrintersCalculatorFactory() = default;
BulkPrintersCalculatorFactory::~BulkPrintersCalculatorFactory() = default;
} // namespace chromeos
// Copyright 2017 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.
#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_BULK_PRINTERS_CALCULATOR_FACTORY_H_
#define CHROME_BROWSER_CHROMEOS_PRINTING_BULK_PRINTERS_CALCULATOR_FACTORY_H_
#include <map>
#include <memory>
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "chrome/browser/chromeos/printing/bulk_printers_calculator.h"
#include "components/account_id/account_id.h"
class Profile;
namespace chromeos {
// Dispenses BulkPrintersCalculator objects based on account id. Access to this
// object should be sequenced.
class BulkPrintersCalculatorFactory {
public:
static BulkPrintersCalculatorFactory* Get();
// Returns a WeakPtr to the BulkPrintersCalculator registered for
// |account_id|. If an BulkPrintersCalculator does not exist, one will be
// created for |account_id|. The returned object remains valid until
// RemoveForUserId or Shutdown is called.
base::WeakPtr<BulkPrintersCalculator> GetForAccountId(
const AccountId& account_id);
// Returns a WeakPtr to the BulkPrintersCalculator registered for |profile|
// which could be null if |profile| does not map to a valid AccountId. The
// returned object remains valid until RemoveForUserId or Shutdown is called.
base::WeakPtr<BulkPrintersCalculator> GetForProfile(Profile* profile);
// Returns a WeakPtr to the BulkPrintersCalculator registered for the device.
base::WeakPtr<BulkPrintersCalculator> GetForDevice();
// Deletes the BulkPrintersCalculator registered for |account_id|.
void RemoveForUserId(const AccountId& account_id);
// Tear down all BulkPrintersCalculator created for users/profiles.
void ShutdownProfiles();
// Tear down all BulkPrintersCalculator.
void Shutdown();
private:
friend struct base::LazyInstanceTraitsBase<BulkPrintersCalculatorFactory>;
BulkPrintersCalculatorFactory();
~BulkPrintersCalculatorFactory();
std::map<AccountId, std::unique_ptr<BulkPrintersCalculator>>
printers_by_user_;
std::unique_ptr<BulkPrintersCalculator> device_printers_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(BulkPrintersCalculatorFactory);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_PRINTING_BULK_PRINTERS_CALCULATOR_FACTORY_H_
// 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
// Copyright 2018 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.
#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_CALCULATORS_POLICIES_BINDER_H_
#define CHROME_BROWSER_CHROMEOS_PRINTING_CALCULATORS_POLICIES_BINDER_H_
#include <memory>
#include "base/macros.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/profiles/profile.h"
#include "components/pref_registry/pref_registry_syncable.h"
namespace chromeos {
// Observes device settings & user profile modifications and propagates them to
// BulkPrintersCalculator objects associated with given device context and user
// profile. All methods must be called from the same sequence (UI).
class CalculatorsPoliciesBinder {
public:
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// |settings| is the source of device policies. |profile| is a user profile.
static std::unique_ptr<CalculatorsPoliciesBinder> Create(
CrosSettings* settings,
Profile* profile);
virtual ~CalculatorsPoliciesBinder() = default;
protected:
CalculatorsPoliciesBinder() = default;
private:
DISALLOW_COPY_AND_ASSIGN(CalculatorsPoliciesBinder);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_PRINTING_CALCULATORS_POLICIES_BINDER_H_
......@@ -487,7 +487,7 @@ class CupsPrintJobManagerImpl : public CupsPrintJobManager,
jobs_.clear();
}
// Notify observers that a state update has occured for |job|.
// Notify observers that a state update has occurred for |job|.
void NotifyJobStateUpdate(base::WeakPtr<CupsPrintJob> job) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
......
......@@ -111,8 +111,9 @@ class CupsPrintersManagerImpl : public CupsPrintersManager,
// Prime the printer cache with the configured and enterprise printers.
printers_[kConfigured] = synced_printers_manager_->GetConfiguredPrinters();
RebuildConfiguredPrintersIndex();
printers_[kEnterprise] = synced_printers_manager_->GetEnterprisePrinters();
synced_printers_manager_observer_.Add(synced_printers_manager_);
enterprise_printers_are_ready_ =
synced_printers_manager_->GetEnterprisePrinters(printers_[kEnterprise]);
// Callbacks may ensue immediately when the observer proxies are set up, so
// these instantiations must come after everything else is initialized.
......@@ -197,6 +198,9 @@ class CupsPrintersManagerImpl : public CupsPrintersManager,
void AddObserver(CupsPrintersManager::Observer* observer) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
observer_list_.AddObserver(observer);
if (enterprise_printers_are_ready_) {
observer->OnEnterprisePrintersInitialized();
}
}
// Public API function.
......@@ -258,9 +262,16 @@ class CupsPrintersManagerImpl : public CupsPrintersManager,
// SyncedPrintersManager::Observer implementation
void OnEnterprisePrintersChanged(
const std::vector<Printer>& printers) override {
const std::vector<Printer>& printers,
bool enterprise_printers_are_ready) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
printers_[kEnterprise] = printers;
if (enterprise_printers_are_ready && !enterprise_printers_are_ready_) {
enterprise_printers_are_ready_ = true;
for (auto& observer : observer_list_) {
observer.OnEnterprisePrintersInitialized();
}
}
NotifyObservers({kEnterprise});
}
......@@ -548,6 +559,13 @@ class CupsPrintersManagerImpl : public CupsPrintersManager,
// Categorized printers. This is indexed by PrinterClass.
std::vector<std::vector<Printer>> printers_;
// Equals true if the list of enterprise printers and related policies
// is initialized and configured correctly.
bool enterprise_printers_are_ready_ = false;
// Printer ids that occur in one of our categories or printers.
std::unordered_set<std::string> known_printer_ids_;
// This is a dual-purpose structure. The keys in the map are printer ids.
// If an entry exists in this map it means we have received a response from
// PpdProvider about a PpdReference for the given printer. A null value
......
......@@ -45,9 +45,13 @@ class CupsPrintersManager : public KeyedService {
public:
// The list of printers in this class has changed to the given printers.
virtual void OnPrintersChanged(PrinterClass printer_class,
const std::vector<Printer>& printers) = 0;
const std::vector<Printer>& printers) {}
// It is called exactly once for each observer. It means that the
// subsystem for enterprise printers is initialized. When an observer is
// being registered after the subsystem's initialization, this call is
// scheduled immediately in AddObserver method.
virtual void OnEnterprisePrintersInitialized() {}
protected:
virtual ~Observer() = default;
};
......@@ -90,9 +94,9 @@ class CupsPrintersManager : public KeyedService {
// the printer_id is not that of a configured printer.
virtual void RemoveConfiguredPrinter(const std::string& printer_id) = 0;
// Add or remove observers. Observers do not need to be on the same
// Add or remove observers. Observers must be on the same
// sequence as the CupsPrintersManager. Callbacks for a given observer
// will be on the same sequence as was used to call AddObserver().
// will be on the same sequence as the CupsPrintersManager.
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
......
......@@ -36,8 +36,9 @@ class FakeSyncedPrintersManager : public SyncedPrintersManager {
}
// Returns printers from enterprise policy.
std::vector<Printer> GetEnterprisePrinters() const override {
return enterprise_printers_;
bool GetEnterprisePrinters(std::vector<Printer>& printers) const override {
printers = enterprise_printers_;
return true;
}
// Attach |observer| for notification of events. |observer| is expected to
......@@ -128,7 +129,7 @@ class FakeSyncedPrintersManager : public SyncedPrintersManager {
enterprise_printers_.insert(enterprise_printers_.end(), printers.begin(),
printers.end());
for (Observer& observer : observers_) {
observer.OnEnterprisePrintersChanged(enterprise_printers_);
observer.OnEnterprisePrintersChanged(enterprise_printers_, true);
}
}
......@@ -137,7 +138,7 @@ class FakeSyncedPrintersManager : public SyncedPrintersManager {
void RemoveEnterprisePrinters(const std::unordered_set<std::string>& ids) {
RemovePrinters(ids, &enterprise_printers_);
for (Observer& observer : observers_) {
observer.OnEnterprisePrintersChanged(enterprise_printers_);
observer.OnEnterprisePrintersChanged(enterprise_printers_, true);
}
}
......
// Copyright 2018 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/device_external_printers_factory.h"
#include <memory>
#include "base/lazy_instance.h"
#include "chrome/browser/chromeos/printing/external_printers.h"
namespace chromeos {
namespace {
base::LazyInstance<DeviceExternalPrintersFactory>::DestructorAtExit
g_printers_factory = LAZY_INSTANCE_INITIALIZER;
} // namespace
// static
DeviceExternalPrintersFactory* DeviceExternalPrintersFactory::Get() {
return g_printers_factory.Pointer();
}
base::WeakPtr<ExternalPrinters> DeviceExternalPrintersFactory::GetForDevice() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!device_printers_)
device_printers_ = ExternalPrinters::Create();
return device_printers_->AsWeakPtr();
}
void DeviceExternalPrintersFactory::Shutdown() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
device_printers_.reset();
}
DeviceExternalPrintersFactory::DeviceExternalPrintersFactory() = default;
DeviceExternalPrintersFactory::~DeviceExternalPrintersFactory() = default;
} // namespace chromeos
// Copyright 2018 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.
#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_DEVICE_EXTERNAL_PRINTERS_FACTORY_H_
#define CHROME_BROWSER_CHROMEOS_PRINTING_DEVICE_EXTERNAL_PRINTERS_FACTORY_H_
#include <memory>
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "chrome/browser/chromeos/printing/external_printers.h"
namespace chromeos {
// Dispenses ExternalPrinters object for device. Access to this object should be
// sequenced.
class DeviceExternalPrintersFactory {
public:
static DeviceExternalPrintersFactory* Get();
// Returns a WeakPtr to the ExternalPrinters registered for the device.
base::WeakPtr<ExternalPrinters> GetForDevice();
// Tear down device ExternalPrinters object.
void Shutdown();
private:
friend struct base::LazyInstanceTraitsBase<DeviceExternalPrintersFactory>;
DeviceExternalPrintersFactory();
~DeviceExternalPrintersFactory();
std::unique_ptr<ExternalPrinters> device_printers_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(DeviceExternalPrintersFactory);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_PRINTING_DEVICE_EXTERNAL_PRINTERS_FACTORY_H_
// Copyright 2018 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/device_external_printers_settings_bridge.h"
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/values.h"
#include "chrome/browser/chromeos/printing/device_external_printers_factory.h"
#include "chrome/browser/chromeos/printing/external_printers.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
namespace chromeos {
namespace {
// Extracts the list of strings named |policy_name| from |settings| and returns
// it.
std::vector<std::string> FromSettings(const CrosSettings* settings,
const std::string& policy_name) {
std::vector<std::string> string_list;
const base::ListValue* list = nullptr;
if (!settings->GetList(policy_name, &list) || !list) {
return string_list;
}
for (const base::Value& value : *list) {
if (value.is_string()) {
string_list.push_back(value.GetString());
}
}
return string_list;
}
} // namespace
DeviceExternalPrintersSettingsBridge::DeviceExternalPrintersSettingsBridge(
const ExternalPrinterPolicies& policies,
CrosSettings* settings)
: settings_(settings), policies_(policies) {
access_mode_subscription_ = settings->AddSettingsObserver(
policies_.access_mode,
base::BindRepeating(
&DeviceExternalPrintersSettingsBridge::AccessModeUpdated,
base::Unretained(this)));
blacklist_subscription_ = settings->AddSettingsObserver(
policies_.blacklist,
base::BindRepeating(
&DeviceExternalPrintersSettingsBridge::BlacklistUpdated,
base::Unretained(this)));
whitelist_subscription_ = settings->AddSettingsObserver(
policies_.whitelist,
base::BindRepeating(
&DeviceExternalPrintersSettingsBridge::WhitelistUpdated,
base::Unretained(this)));
Initialize();
}
DeviceExternalPrintersSettingsBridge::~DeviceExternalPrintersSettingsBridge() =
default;
void DeviceExternalPrintersSettingsBridge::Initialize() {
BlacklistUpdated();
WhitelistUpdated();
AccessModeUpdated();
}
void DeviceExternalPrintersSettingsBridge::AccessModeUpdated() {
int mode_val;
// Settings should contain value for access mode device setting.
// Even if it's not pushed with device policy, the default value should be
// set.
CHECK(settings_->GetInteger(policies_.access_mode, &mode_val));
ExternalPrinters::AccessMode mode =
static_cast<ExternalPrinters::AccessMode>(mode_val);
base::WeakPtr<ExternalPrinters> printers =
DeviceExternalPrintersFactory::Get()->GetForDevice();
if (printers)
printers->SetAccessMode(mode);
}
void DeviceExternalPrintersSettingsBridge::BlacklistUpdated() {
base::WeakPtr<ExternalPrinters> printers =
DeviceExternalPrintersFactory::Get()->GetForDevice();
if (printers)
printers->SetBlacklist(FromSettings(settings_, policies_.blacklist));
}
void DeviceExternalPrintersSettingsBridge::WhitelistUpdated() {
base::WeakPtr<ExternalPrinters> printers =
DeviceExternalPrintersFactory::Get()->GetForDevice();
if (printers)
printers->SetWhitelist(FromSettings(settings_, policies_.whitelist));
}
} // namespace chromeos
// Copyright 2018 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.
#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_DEVICE_EXTERNAL_PRINTERS_SETTINGS_BRIDGE_H_
#define CHROME_BROWSER_CHROMEOS_PRINTING_DEVICE_EXTERNAL_PRINTERS_SETTINGS_BRIDGE_H_
#include "base/macros.h"
#include "chrome/browser/chromeos/printing/external_printers_policies.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
namespace chromeos {
class ExternalPrinters;
// Observe device settings changes and propagate changes to ExternalPrinters.
class DeviceExternalPrintersSettingsBridge {
public:
DeviceExternalPrintersSettingsBridge(const ExternalPrinterPolicies& policies,
CrosSettings* settings);
~DeviceExternalPrintersSettingsBridge();
private:
// Retrieve initial values for device settings.
void Initialize();
// Handle update for the access mode policy.
void AccessModeUpdated();
// Handle updates for the blacklist policy.
void BlacklistUpdated();
// Handle updates for the whitelist policy.
void WhitelistUpdated();
CrosSettings* settings_;
const ExternalPrinterPolicies policies_;
std::unique_ptr<CrosSettings::ObserverSubscription> access_mode_subscription_;
std::unique_ptr<CrosSettings::ObserverSubscription> blacklist_subscription_;
std::unique_ptr<CrosSettings::ObserverSubscription> whitelist_subscription_;
DISALLOW_COPY_AND_ASSIGN(DeviceExternalPrintersSettingsBridge);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_PRINTING_DEVICE_EXTERNAL_PRINTERS_SETTINGS_BRIDGE_H_
// Copyright 2018 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/enterprise_printers_provider.h"
#include <list>
#include <vector>
#include "base/feature_list.h"
#include "base/json/json_reader.h"
#include "base/md5.h"
#include "chrome/browser/chromeos/printing/bulk_printers_calculator.h"
#include "chrome/browser/chromeos/printing/bulk_printers_calculator_factory.h"
#include "chrome/browser/chromeos/printing/calculators_policies_binder.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector_factory.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chromeos/printing/printer_translator.h"
#include "components/policy/core/common/policy_service.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
namespace chromeos {
namespace {
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 EnterprisePrintersProviderImpl : public EnterprisePrintersProvider,
public BulkPrintersCalculator::Observer {
public:
EnterprisePrintersProviderImpl(CrosSettings* settings, Profile* profile)
: profile_(profile) {
// initialization of pref_change_registrar
pref_change_registrar_.Init(profile->GetPrefs());
if (base::FeatureList::IsEnabled(features::kBulkPrinters)) {
// Binds instances of BulkPrintersCalculator to policies.
policies_binder_ = CalculatorsPoliciesBinder::Create(settings, profile);
// Get instance of BulkPrintersCalculator for device policies.
device_printers_ = BulkPrintersCalculatorFactory::Get()->GetForDevice();
if (device_printers_) {
device_printers_->AddObserver(this);
RecalculateCompleteFlagForDevicePrinters();
}
// Get instance of BulkPrintersCalculator for user policies.
user_printers_ =
BulkPrintersCalculatorFactory::Get()->GetForProfile(profile);
if (user_printers_) {
user_printers_->AddObserver(this);
RecalculateCompleteFlagForUserPrinters();
}
} else {
// If a "Bulk Printers" feature is inactive, we do not bind anything.
// The list of printers is always empty and is reported as complete.
complete_ = true;
}
// Binds policy with recommended printers (deprecated). This method calls
// indirectly RecalculateCurrentPrintersList() that prepares the first
// version of final list of printers.
BindPref(prefs::kRecommendedNativePrinters,
&EnterprisePrintersProviderImpl::UpdateUserRecommendedPrinters);
}
~EnterprisePrintersProviderImpl() override {
if (device_printers_)
device_printers_->RemoveObserver(this);
if (user_printers_)
user_printers_->RemoveObserver(this);
}
void AddObserver(EnterprisePrintersProvider::Observer* observer) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
observers_.AddObserver(observer);
observer->OnPrintersChanged(complete_, printers_);
}
void RemoveObserver(EnterprisePrintersProvider::Observer* observer) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
observers_.RemoveObserver(observer);
}
// BulkPrintersCalculator::Observer implementation
void OnPrintersChanged(const BulkPrintersCalculator* sender) override {
if (sender == device_printers_.get()) {
RecalculateCompleteFlagForDevicePrinters();
} else {
RecalculateCompleteFlagForUserPrinters();
}
RecalculateCurrentPrintersList();
}
private:
// This method process value from the deprecated policy with recommended
// printers. It is called when value of the policy changes.
void UpdateUserRecommendedPrinters() {
recommended_printers_.clear();
std::vector<std::string> data =
FromPrefs(prefs::kRecommendedNativePrinters);
for (const auto& printer_json : data) {
std::unique_ptr<base::DictionaryValue> printer_dictionary =
base::DictionaryValue::From(base::JSONReader::ReadDeprecated(
printer_json, base::JSON_ALLOW_TRAILING_COMMAS));
if (!printer_dictionary) {
LOG(WARNING) << "Ignoring invalid printer. Invalid JSON object: "
<< printer_json;
continue;
}
// Policy printers don't have id's but the ids only need to be locally
// unique so we'll hash the record. This will not collide with the
// UUIDs generated for user entries.
std::string id = base::MD5String(printer_json);
printer_dictionary->SetString(kPrinterId, id);
auto new_printer = RecommendedPrinterToPrinter(*printer_dictionary);
if (!new_printer) {
LOG(WARNING) << "Recommended printer is malformed.";
continue;
}
if (!recommended_printers_.insert({id, *new_printer}).second) {
// Printer is already in the list.
LOG(WARNING) << "Duplicate printer ignored: " << id;
continue;
}
}
RecalculateCurrentPrintersList();
}
// These three methods calculate resultant list of printers and complete flag.
void RecalculateCompleteFlagForUserPrinters() {
user_printers_is_complete_ =
user_printers_->IsComplete() &&
(user_printers_->IsDataPolicySet() ||
!PolicyWithDataIsSet(policy::key::kNativePrintersBulkConfiguration));
}
void RecalculateCompleteFlagForDevicePrinters() {
device_printers_is_complete_ =
device_printers_->IsComplete() &&
(device_printers_->IsDataPolicySet() ||
!PolicyWithDataIsSet(policy::key::kDeviceNativePrinters));
}
void RecalculateCurrentPrintersList() {
complete_ = true;
printers_ = recommended_printers_;
if (device_printers_) {
complete_ = complete_ && device_printers_is_complete_;
const auto& printers = device_printers_->GetPrinters();
printers_.insert(printers.begin(), printers.end());
}
if (user_printers_) {
complete_ = complete_ && user_printers_is_complete_;
const auto& printers = user_printers_->GetPrinters();
printers_.insert(printers.begin(), printers.end());
}
for (auto& observer : observers_) {
observer.OnPrintersChanged(complete_, printers_);
}
}
typedef void (EnterprisePrintersProviderImpl::*SimpleMethod)();
// Binds given user 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)();
}
// 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));
}
// Checks if given policy is set and if it is a dictionary
bool PolicyWithDataIsSet(const char* policy_name) {
policy::ProfilePolicyConnector* policy_connector =
policy::ProfilePolicyConnectorFactory::GetForBrowserContext(profile_);
if (!policy_connector) {
// something is wrong
return false;
}
const policy::PolicyNamespace policy_namespace =
policy::PolicyNamespace(policy::PolicyDomain::POLICY_DOMAIN_CHROME, "");
const policy::PolicyMap& policy_map =
policy_connector->policy_service()->GetPolicies(policy_namespace);
const base::Value* value = policy_map.GetValue(policy_name);
if (value && value->is_dict()) {
// policy is set and its value is a dictionary
return true;
}
return false;
}
// current partial results
std::unordered_map<std::string, Printer> recommended_printers_;
bool device_printers_is_complete_ = true;
bool user_printers_is_complete_ = true;
// current final results
bool complete_ = false;
std::unordered_map<std::string, Printer> printers_;
// Calculators for bulk printers from device and user policies. Unowned.
base::WeakPtr<BulkPrintersCalculator> device_printers_;
base::WeakPtr<BulkPrintersCalculator> user_printers_;
// Policies binder (bridge between policies and calculators). Owned.
std::unique_ptr<CalculatorsPoliciesBinder> policies_binder_;
// Profile (user) settings.
Profile* profile_;
PrefChangeRegistrar pref_change_registrar_;
base::ObserverList<EnterprisePrintersProvider::Observer>::Unchecked
observers_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(EnterprisePrintersProviderImpl);
};
} // namespace
// static
void EnterprisePrintersProvider::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterListPref(prefs::kRecommendedNativePrinters);
CalculatorsPoliciesBinder::RegisterProfilePrefs(registry);
}
// static
std::unique_ptr<EnterprisePrintersProvider> EnterprisePrintersProvider::Create(
CrosSettings* settings,
Profile* profile) {
return std::make_unique<EnterprisePrintersProviderImpl>(settings, profile);
}
} // namespace chromeos
// Copyright 2018 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.
#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_ENTERPRISE_PRINTERS_PROVIDER_H_
#define CHROME_BROWSER_CHROMEOS_PRINTING_ENTERPRISE_PRINTERS_PROVIDER_H_
#include <memory>
#include <string>
#include <unordered_map>
#include "base/macros.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/printing/printer_configuration.h"
#include "components/pref_registry/pref_registry_syncable.h"
namespace chromeos {
// Uses classes BulkPrintersCalculator and CalculatorsPoliciesBinder to track
// device settings & user profile modifications and to calculates resultant
// list of available enterprise printers. The final list of available enterprise
// printers is propagated to Observers.
// All methods must be called from the same sequence (UI) and all observers'
// notifications will be called from this sequence.
class EnterprisePrintersProvider {
public:
class Observer {
public:
// |complete| is true if all policies have been parsed and applied (even
// when parsing errors occurred), false means that a new list of available
// printers is being calculated. |printers| contains the current list of
// available printers: the map is indexed by printers ids. This
// notification is called when value of any of these two parameters changes.
virtual void OnPrintersChanged(
bool complete,
const std::unordered_map<std::string, Printer>& printers) = 0;
};
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// |settings| is the source of device policies. |profile| is a user profile.
static std::unique_ptr<EnterprisePrintersProvider> Create(
CrosSettings* settings,
Profile* profile);
virtual ~EnterprisePrintersProvider() = default;
// This method also calls directly OnPrintersChanged(...) from |observer|.
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
protected:
EnterprisePrintersProvider() = default;
private:
DISALLOW_COPY_AND_ASSIGN(EnterprisePrintersProvider);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_PRINTING_ENTERPRISE_PRINTERS_PROVIDER_H_
// Copyright 2017 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.
#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_H_
#define CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "chromeos/printing/printer_configuration.h"
namespace chromeos {
// Manages download and parsing of the external policy printer configuration and
// enforces restrictions.
class ExternalPrinters : public base::SupportsWeakPtr<ExternalPrinters> {
public:
// Choose the policy for printer access.
enum AccessMode {
UNSET = -1,
// Printers in the blacklist are disallowed. Others are allowed.
BLACKLIST_ONLY = 0,
// Only printers in the whitelist are allowed.
WHITELIST_ONLY = 1,
// All printers in the policy are allowed.
ALL_ACCESS = 2
};
// Observer is notified when the computed set of printers change. It is
// assumed that the observer is on the same sequence as the object it is
// observing.
class Observer {
public:
// Called when the printers have changed and should be queried. |valid| is
// true if |printers| is based on a valid policy. |printers| are the
// printers that should be available to the user.
virtual void OnPrintersChanged(
bool valid,
const std::map<const std::string, const Printer>& printers) = 0;
};
// Creates a handler for the external printer policies.
static std::unique_ptr<ExternalPrinters> Create();
virtual ~ExternalPrinters() = default;
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
// Parses |data| which is the contents of the bulk printes file and extracts
// printer information. The file format is assumed to be JSON.
virtual void SetData(std::unique_ptr<std::string> data) = 0;
// Removes all printer data and invalidates the configuration.
virtual void ClearData() = 0;
// Set the access mode which chooses the type of filtering that is performed.
virtual void SetAccessMode(AccessMode mode) = 0;
// Set the |blacklist| which excludes printers with the given id if access
// mode is BLACKLIST_ONLY.
virtual void SetBlacklist(const std::vector<std::string>& blacklist) = 0;
// Set the |whitelist| which is the complete list of printers that are show to
// the user. This is in effect if access mode is WHITELIST_ONLY.
virtual void SetWhitelist(const std::vector<std::string>& whitelist) = 0;
// Returns true if the printer map has been computed from a valid policy.
// Returns false otherwise. This is computed asynchronously. Observe
// OnPrintersChanged() to be notified when it is updated. This may never
// become true if a user does not have the appropriate printer policies.
virtual bool IsPolicySet() const = 0;
// Returns a refernce to a map of the computed set of printers. The map is
// empty if either the policy was empty or we are yet to receive the full
// policy. Use IsPolicySet() to differentiate betweeen the two.
virtual const std::map<const std::string, const Printer>& GetPrinters()
const = 0;
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_H_
// Copyright 2017 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.
#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_FACTORY_H_
#define CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_FACTORY_H_
#include <map>
#include <memory>
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "chrome/browser/chromeos/printing/external_printers.h"
#include "components/account_id/account_id.h"
class Profile;
namespace chromeos {
// Dispenses ExternalPrinters objects based on account id. Access to this
// object should be sequenced.
class ExternalPrintersFactory {
public:
static ExternalPrintersFactory* Get();
// Returns a WeakPtr to the ExternalPrinters registered for |account_id|. If
// an ExternalPrinters does not exist, one will be created for |account_id|.
// The returned object remains valid until RemoveForUserId or Shutdown is
// called.
base::WeakPtr<ExternalPrinters> GetForAccountId(const AccountId& account_id);
// Returns a WeakPtr to the ExternalPrinters registered for |profile| which
// could be null if |profile| does not map to a valid AccountId. The returned
// object remains valid until RemoveForUserId or Shutdown is called.
base::WeakPtr<ExternalPrinters> GetForProfile(Profile* profile);
// Deletes the ExternalPrinters registered for |account_id|.
void RemoveForUserId(const AccountId& account_id);
// Tear down all ExternalPrinters.
void Shutdown();
private:
friend struct base::LazyInstanceTraitsBase<ExternalPrintersFactory>;
ExternalPrintersFactory();
~ExternalPrintersFactory();
std::map<AccountId, std::unique_ptr<ExternalPrinters>> printers_by_user_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(ExternalPrintersFactory);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_FACTORY_H_
// Copyright 2018 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.
#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_POLICIES_H_
#define CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_POLICIES_H_
#include <string>
// A collection of preference names representing the external printer fields.
struct ExternalPrinterPolicies {
std::string access_mode;
std::string blacklist;
std::string whitelist;
};
#endif // CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_POLICIES_H_
// 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 "chrome/browser/chromeos/printing/external_printers_pref_bridge.h"
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/values.h"
#include "chrome/browser/chromeos/printing/external_printers.h"
#include "chrome/browser/chromeos/printing/external_printers_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/policy/policy_constants.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
namespace chromeos {
namespace {
// Extracts the list of strings named |policy_name| from |prefs| and returns it.
std::vector<std::string> FromPrefs(const PrefService* prefs,
const std::string& policy_name) {
std::vector<std::string> string_list;
const base::ListValue* list = prefs->GetList(policy_name);
for (const base::Value& value : *list) {
if (value.is_string()) {
string_list.push_back(value.GetString());
}
}
return string_list;
}
} // namespace
// static
void ExternalPrintersPrefBridge::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry,
const ExternalPrinterPolicies& policies) {
// Default value for access mode is AllAccess.
registry->RegisterIntegerPref(policies.access_mode,
ExternalPrinters::ALL_ACCESS);
registry->RegisterListPref(policies.blacklist);
registry->RegisterListPref(policies.whitelist);
}
ExternalPrintersPrefBridge::ExternalPrintersPrefBridge(
const ExternalPrinterPolicies& policies,
Profile* profile)
: profile_(profile), policies_(policies) {
pref_change_registrar_.Init(profile_->GetPrefs());
pref_change_registrar_.Add(
policies_.access_mode,
base::BindRepeating(&ExternalPrintersPrefBridge::AccessModeUpdated,
base::Unretained(this)));
pref_change_registrar_.Add(
policies_.blacklist,
base::BindRepeating(&ExternalPrintersPrefBridge::BlacklistUpdated,
base::Unretained(this)));
pref_change_registrar_.Add(
policies_.whitelist,
base::BindRepeating(&ExternalPrintersPrefBridge::WhitelistUpdated,
base::Unretained(this)));
Initialize();
}
void ExternalPrintersPrefBridge::Initialize() {
BlacklistUpdated();
WhitelistUpdated();
AccessModeUpdated();
}
void ExternalPrintersPrefBridge::AccessModeUpdated() {
const PrefService* prefs = profile_->GetPrefs();
ExternalPrinters::AccessMode mode = ExternalPrinters::UNSET;
int mode_val = prefs->GetInteger(policies_.access_mode);
if (mode_val >= ExternalPrinters::BLACKLIST_ONLY &&
mode_val <= ExternalPrinters::ALL_ACCESS) {
mode = static_cast<ExternalPrinters::AccessMode>(mode_val);
} else {
LOG(ERROR) << "Unrecognized access mode";
return;
}
base::WeakPtr<ExternalPrinters> printers =
ExternalPrintersFactory::Get()->GetForProfile(profile_);
if (printers)
printers->SetAccessMode(mode);
}
void ExternalPrintersPrefBridge::BlacklistUpdated() {
base::WeakPtr<ExternalPrinters> printers =
ExternalPrintersFactory::Get()->GetForProfile(profile_);
if (printers)
printers->SetBlacklist(
FromPrefs(profile_->GetPrefs(), policies_.blacklist));
}
void ExternalPrintersPrefBridge::WhitelistUpdated() {
base::WeakPtr<ExternalPrinters> printers =
ExternalPrintersFactory::Get()->GetForProfile(profile_);
if (printers)
printers->SetWhitelist(
FromPrefs(profile_->GetPrefs(), policies_.whitelist));
}
} // namespace chromeos
// Copyright 2017 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.
#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_PREF_BRIDGE_H_
#define CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_PREF_BRIDGE_H_
#include <string>
#include "base/macros.h"
#include "chrome/browser/chromeos/printing/external_printers_policies.h"
#include "components/prefs/pref_change_registrar.h"
class Profile;
namespace user_prefs {
class PrefRegistrySyncable;
}
namespace chromeos {
class ExternalPrinters;
// Observe preference changes and propogate changes to ExternalPrinters.
class ExternalPrintersPrefBridge {
public:
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
const ExternalPrinterPolicies& policies);
ExternalPrintersPrefBridge(const ExternalPrinterPolicies& policies,
Profile* profile);
private:
// Retrieve initial values for preferences.
void Initialize();
// Handle update for the access mode policy.
void AccessModeUpdated();
// Handle updates for the blacklist policy.
void BlacklistUpdated();
// Handle updates for the whitelist policy.
void WhitelistUpdated();
Profile* profile_;
const ExternalPrinterPolicies policies_;
PrefChangeRegistrar pref_change_registrar_;
DISALLOW_COPY_AND_ASSIGN(ExternalPrintersPrefBridge);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_PREF_BRIDGE_H_
......@@ -39,7 +39,8 @@ class SyncedPrintersManager : public KeyedService {
virtual void OnConfiguredPrintersChanged(
const std::vector<Printer>& printers) = 0;
virtual void OnEnterprisePrintersChanged(
const std::vector<Printer>& printers) = 0;
const std::vector<Printer>& printers,
bool enterprise_printers_are_ready) {}
};
static std::unique_ptr<SyncedPrintersManager> Create(
......@@ -53,8 +54,9 @@ class SyncedPrintersManager : public KeyedService {
// Returns the printers that are saved in preferences.
virtual std::vector<Printer> GetConfiguredPrinters() const = 0;
// Returns printers from enterprise policy.
virtual std::vector<Printer> GetEnterprisePrinters() const = 0;
// Replaces given vector with vector of printers from enterprise policy.
// Returns true if the enterprise policy was loaded and is valid.
virtual bool GetEnterprisePrinters(std::vector<Printer>& printers) const = 0;
// Returns the printer with id |printer_id|, or nullptr if no such printer
// exists. Searches both Configured and Enterprise printers.
......
......@@ -72,7 +72,8 @@ class LoggingObserver : public SyncedPrintersManager::Observer {
}
void OnEnterprisePrintersChanged(
const std::vector<Printer>& printer) override {
const std::vector<Printer>& printer,
bool enterprise_printers_are_ready) override {
enterprise_printers_ = printer;
}
......@@ -200,10 +201,12 @@ TEST_F(SyncedPrintersManagerTest, EnterprisePrinters) {
// TestingPrefSyncableService assumes ownership of |value|.
prefs->SetManagedPref(prefs::kRecommendedNativePrinters, std::move(value));
auto printers = manager_->GetEnterprisePrinters();
std::vector<Printer> printers;
manager_->GetEnterprisePrinters(printers);
ASSERT_EQ(2U, printers.size());
EXPECT_EQ("Color Laser", printers[0].display_name());
EXPECT_EQ("ipp://192.168.1.5", printers[1].uri());
// order not specified
// EXPECT_EQ("Color Laser", printers[0].display_name());
// EXPECT_EQ("ipp://192.168.1.5", printers[1].uri());
EXPECT_EQ(Printer::Source::SRC_POLICY, printers[1].source());
}
......@@ -217,7 +220,8 @@ TEST_F(SyncedPrintersManagerTest, GetEnterprisePrinter) {
// TestingPrefSyncableService assumes ownership of |value|.
prefs->SetManagedPref(prefs::kRecommendedNativePrinters, std::move(value));
auto printers = manager_->GetEnterprisePrinters();
std::vector<Printer> printers;
manager_->GetEnterprisePrinters(printers);
const Printer& from_list = printers.front();
std::unique_ptr<Printer> retrieved = manager_->GetPrinter(from_list.id());
......@@ -250,7 +254,9 @@ TEST_F(SyncedPrintersManagerTest, PrinterInstalledConfiguresPrinter) {
prefs->SetManagedPref(prefs::kRecommendedNativePrinters, std::move(value));
// Figure out the id of the enterprise printer that was just installed.
std::string enterprise_id = manager_->GetEnterprisePrinters().at(0).id();
std::vector<Printer> printers;
manager_->GetEnterprisePrinters(printers);
std::string enterprise_id = printers.at(0).id();
Printer configured(kTestPrinterId);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment