Commit 07a590fc authored by Daniel Hosseinian's avatar Daniel Hosseinian Committed by Commit Bot

Add a pref to blacklist certain printer types in print preview

Printer types that can be blacklisted include privet, PDF, local,
extension, and cloud printers.

If a certain printer type is on the blacklist, calls of 'getPrinters'
for that type would immediately resolve without dispatching any Web UI
events. Calls of 'getPrinterCapabilities' for a blacklisted printer
type would be rejected.

Because cloud printers are fetched separately, if cloud printers are on
the blacklist, the pref will have the same effect as setting the
"CloudPrintSubmitEnabled" policy to false.

This is the first CL to implement a policy disabling certain printer
types. A future CL will add the policy configurations.

Bug: 487875
Change-Id: I3bd4e1d3d3ecae3c2a6c379f3b3ae009b2c4921c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1881844
Commit-Queue: Daniel Hosseinian <dhoss@chromium.org>
Reviewed-by: default avatarRebekah Potter <rbpotter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712342}
parent 1cec8d44
......@@ -12,6 +12,7 @@ namespace printing {
// static
void PolicySettings::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterListPref(prefs::kPrinterTypeBlacklist);
registry->RegisterBooleanPref(prefs::kPrintHeaderFooter, true);
#if defined(OS_CHROMEOS)
registry->RegisterIntegerPref(prefs::kPrintingAllowedBackgroundGraphicsModes,
......
......@@ -557,6 +557,7 @@ void PrintPreviewHandler::OnJavascriptAllowed() {
print_preview_ui()->SetPreviewUIId();
// Now that the UI is initialized, any future account changes will require
// a printer list refresh.
ReadPrinterTypeBlacklistFromPrefs();
RegisterForGaiaCookieChanges();
}
......@@ -567,6 +568,7 @@ void PrintPreviewHandler::OnJavascriptDisallowed() {
print_preview_ui()->ClearPreviewUIId();
preview_callbacks_.clear();
preview_failures_.clear();
printer_type_blacklist_.clear();
UnregisterForGaiaCookieChanges();
}
......@@ -580,6 +582,33 @@ PrefService* PrintPreviewHandler::GetPrefs() const {
return prefs;
}
void PrintPreviewHandler::ReadPrinterTypeBlacklistFromPrefs() {
PrefService* prefs = GetPrefs();
if (!prefs->HasPrefPath(prefs::kPrinterTypeBlacklist))
return;
const base::Value* blacklist_types = prefs->Get(prefs::kPrinterTypeBlacklist);
if (!blacklist_types || !blacklist_types->is_list())
return;
for (const base::Value& blacklist_type : blacklist_types->GetList()) {
if (!blacklist_type.is_string())
continue;
const std::string& blacklist_str = blacklist_type.GetString();
if (blacklist_str == "privet")
printer_type_blacklist_.insert(kPrivetPrinter);
else if (blacklist_str == "extension")
printer_type_blacklist_.insert(kExtensionPrinter);
else if (blacklist_str == "pdf")
printer_type_blacklist_.insert(kPdfPrinter);
else if (blacklist_str == "local")
printer_type_blacklist_.insert(kLocalPrinter);
else if (blacklist_str == "cloud")
printer_type_blacklist_.insert(kCloudPrinter);
}
}
PrintPreviewUI* PrintPreviewHandler::print_preview_ui() const {
return static_cast<PrintPreviewUI*>(web_ui()->GetController());
}
......@@ -623,6 +652,13 @@ void PrintPreviewHandler::HandleGetPrinters(const base::ListValue* args) {
CHECK(args->GetInteger(1, &type));
PrinterType printer_type = static_cast<PrinterType>(type);
// Immediately resolve the callback without fetching printers if the printer
// type is blacklisted
if (base::Contains(printer_type_blacklist_, printer_type)) {
ResolveJavascriptCallback(base::Value(callback_id), base::Value());
return;
}
PrinterHandler* handler = GetPrinterHandler(printer_type);
if (!handler) {
RejectJavascriptCallback(base::Value(callback_id), base::Value());
......@@ -666,6 +702,12 @@ void PrintPreviewHandler::HandleGetPrinterCapabilities(
}
PrinterType printer_type = static_cast<PrinterType>(type);
// Reject the callback if the printer type is blacklisted
if (base::Contains(printer_type_blacklist_, printer_type)) {
RejectJavascriptCallback(base::Value(callback_id), base::Value());
return;
}
PrinterHandler* handler = GetPrinterHandler(printer_type);
if (!handler) {
RejectJavascriptCallback(base::Value(callback_id), base::Value());
......@@ -1361,6 +1403,7 @@ void PrintPreviewHandler::OnPrintResult(const std::string& callback_id,
void PrintPreviewHandler::RegisterForGaiaCookieChanges() {
DCHECK(!identity_manager_);
cloud_print_enabled_ =
!base::Contains(printer_type_blacklist_, kCloudPrinter) &&
GetPrefs()->GetBoolean(prefs::kCloudPrintSubmitEnabled);
if (!cloud_print_enabled_)
......
......@@ -22,6 +22,7 @@
#include "content/public/browser/web_ui_message_handler.h"
#include "printing/backend/print_backend.h"
#include "printing/buildflags/buildflags.h"
#include "printing/print_job_constants.h"
namespace base {
class DictionaryValue;
......@@ -135,7 +136,10 @@ class PrintPreviewHandler : public content::WebUIMessageHandler,
MANUAL_DummyTest);
friend class PrintPreviewHandlerTest;
FRIEND_TEST_ALL_PREFIXES(PrintPreviewHandlerTest, GetPrinters);
FRIEND_TEST_ALL_PREFIXES(PrintPreviewHandlerTest, GetNoBlacklistedPrinters);
FRIEND_TEST_ALL_PREFIXES(PrintPreviewHandlerTest, GetPrinterCapabilities);
FRIEND_TEST_ALL_PREFIXES(PrintPreviewHandlerTest,
GetNoBlacklistedPrinterCapabilities);
FRIEND_TEST_ALL_PREFIXES(PrintPreviewHandlerTest, Print);
FRIEND_TEST_ALL_PREFIXES(PrintPreviewHandlerTest, GetPreview);
FRIEND_TEST_ALL_PREFIXES(PrintPreviewHandlerTest, SendPreviewUpdates);
......@@ -153,6 +157,10 @@ class PrintPreviewHandler : public content::WebUIMessageHandler,
PrefService* GetPrefs() const;
// Checks policy preferences for a blacklist of printer types and initializes
// the set that stores them.
void ReadPrinterTypeBlacklistFromPrefs();
// Whether the the handler should be receiving messages from the renderer to
// forward to the Print Preview JS in response to preview request with id
// |request_id|. Kills the renderer if the handler should not be receiving
......@@ -350,6 +358,9 @@ class PrintPreviewHandler : public content::WebUIMessageHandler,
// Set of preview request ids for failed previews.
std::set<int> preview_failures_;
// Set of blacklisted printer types.
std::set<PrinterType> printer_type_blacklist_;
base::WeakPtrFactory<PrintPreviewHandler> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PrintPreviewHandler);
......
......@@ -586,6 +586,43 @@ TEST_F(PrintPreviewHandlerTest, GetPrinters) {
}
}
// Validates the 'printing.printer_type_blacklist' pref by blacklisting the
// extension and privet printer types. A 'getPrinters' Web UI message is then
// called for all three fetchable printer types; only local printers should be
// successfully fetched.
TEST_F(PrintPreviewHandlerTest, GetNoBlacklistedPrinters) {
base::Value::ListStorage blacklist;
blacklist.push_back(base::Value("extension"));
blacklist.push_back(base::Value("privet"));
prefs()->Set(prefs::kPrinterTypeBlacklist, base::Value(std::move(blacklist)));
Initialize();
size_t expected_callbacks = 1;
for (size_t i = 0; i < base::size(kFetchableTypes); i++) {
PrinterType type = kFetchableTypes[i];
std::string callback_id_in =
"test-callback-id-" + base::NumberToString(i + 1);
handler()->reset_calls();
SendGetPrinters(type, callback_id_in);
// Start with 1 call from initial settings, then add 2 more for each printer
// type that isn't blacklisted (one for printers-added, and one for the
// response), and only 1 more for each blacklisted type (just for response).
const bool is_allowed_type = type == kLocalPrinter;
EXPECT_EQ(is_allowed_type, handler()->CalledOnlyForType(type));
expected_callbacks += is_allowed_type ? 2 : 1;
ASSERT_EQ(expected_callbacks, web_ui()->call_data().size());
if (is_allowed_type) {
ValidatePrinterTypeAdded(type);
}
// Verify getPrinters promise was resolved successfully.
const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
CheckWebUIResponse(data, callback_id_in, true);
}
}
TEST_F(PrintPreviewHandlerTest, GetPrinterCapabilities) {
// Add an empty printer to the handler.
printers().push_back(GetEmptyPrinterInfo());
......@@ -632,6 +669,38 @@ TEST_F(PrintPreviewHandlerTest, GetPrinterCapabilities) {
}
}
// Validates the 'printing.printer_type_blacklist' pref by blacklisting the
// local and PDF printer types. A 'getPrinterCapabilities' Web UI message is
// then called for all supported printer types; only privet and extension
// printer capabilties should be successfully fetched.
TEST_F(PrintPreviewHandlerTest, GetNoBlacklistedPrinterCapabilities) {
base::Value::ListStorage blacklist;
blacklist.push_back(base::Value("local"));
blacklist.push_back(base::Value("pdf"));
prefs()->Set(prefs::kPrinterTypeBlacklist, base::Value(std::move(blacklist)));
Initialize();
// Check all four printer types that implement
// PrinterHandler::StartGetCapability().
for (size_t i = 0; i < base::size(kAllSupportedTypes); i++) {
PrinterType type = kAllSupportedTypes[i];
std::string callback_id_in =
"test-callback-id-" + base::NumberToString(i + 1);
handler()->reset_calls();
SendGetPrinterCapabilities(type, callback_id_in, kDummyPrinterName);
const bool is_allowed_type =
type == kPrivetPrinter || type == kExtensionPrinter;
EXPECT_EQ(is_allowed_type, handler()->CalledOnlyForType(type));
// Start with 1 call from initial settings, then add 1 more for each loop
// iteration.
ASSERT_EQ(1u + (i + 1), web_ui()->call_data().size());
ValidatePrinterCapabilities(callback_id_in, is_allowed_type);
}
}
TEST_F(PrintPreviewHandlerTest, Print) {
Initialize();
......
......@@ -1285,6 +1285,13 @@ const char kProfileAvatarTutorialShown[] =
// mode is on, recommending high-contrast extensions and themes.
const char kInvertNotificationShown[] = "invert_notification_version_2_shown";
// A pref holding the list of printer types to be disabled.
const char kPrinterTypeBlacklist[] = "printing.printer_type_blacklist";
// The default value for the 'Headers and footers' checkbox, in Print Preview.
// Takes priority over kPrintPreviewStickySettings if set.
const char kPrintHeaderFooter[] = "printing.print_header_footer";
// Boolean controlling whether printing is enabled.
const char kPrintingEnabled[] = "printing.enabled";
......@@ -1296,10 +1303,6 @@ const char kPrintPreviewDisabled[] = "printing.print_preview_disabled";
const char kPrintPreviewDefaultDestinationSelectionRules[] =
"printing.default_destination_selection_rules";
// The default value for the 'Headers and footers' checkbox, in Print Preview.
// Takes priority over kPrintPreviewStickySettings if set.
const char kPrintHeaderFooter[] = "printing.print_header_footer";
#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
// A pref that sets the default destination in Print Preview to always be the
// OS default printer instead of the most recently used destination.
......
......@@ -409,10 +409,11 @@ extern const char kProfileAvatarTutorialShown[];
extern const char kInvertNotificationShown[];
extern const char kPrinterTypeBlacklist[];
extern const char kPrintingEnabled[];
extern const char kPrintHeaderFooter[];
extern const char kPrintPreviewDisabled[];
extern const char kPrintPreviewDefaultDestinationSelectionRules[];
extern const char kPrintHeaderFooter[];
#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
extern const char kPrintPreviewUseSystemDefaultPrinter[];
......
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