Commit 3a6935e1 authored by Matt Menard's avatar Matt Menard Committed by Chromium LUCI CQ

Add print servers to PrintPreviewHandlerChromeOS

Bug: b:168650771
Change-Id: Ic4c5d025ae0e5ebea8b81d6182fed34bbfe8be62
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2583218
Commit-Queue: Matt Menard <mattme@google.com>
Reviewed-by: default avatarSean Kau <skau@chromium.org>
Reviewed-by: default avatarRebekah Potter <rbpotter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836905}
parent f6146e18
......@@ -397,6 +397,10 @@ class CupsPrintersManagerImpl
nearby_zeroconf_printers_count);
}
PrintServersManager* GetPrintServersManager() const override {
return print_servers_manager_.get();
}
// Callback for FetchPrinterStatus
void OnPrinterInfoFetched(const std::string& printer_id,
PrinterStatusCallback cb,
......
......@@ -124,6 +124,8 @@ class CupsPrintersManager : public PrinterInstallationManager,
// Records the total number of detected network printers and the
// number of detected network printers that have not been saved.
virtual void RecordNearbyNetworkPrinterCounts() const = 0;
virtual PrintServersManager* GetPrintServersManager() const = 0;
};
} // namespace chromeos
......
......@@ -20,4 +20,8 @@ base::Optional<Printer> StubCupsPrintersManager::GetPrinter(
return {};
}
PrintServersManager* StubCupsPrintersManager::GetPrintServersManager() const {
return nullptr;
}
} // namespace chromeos
......@@ -23,6 +23,7 @@ class StubCupsPrintersManager : public CupsPrintersManager {
std::vector<Printer> GetPrinters(PrinterClass printer_class) const override;
bool IsPrinterInstalled(const Printer& printer) const override;
base::Optional<Printer> GetPrinter(const std::string& id) const override;
PrintServersManager* GetPrintServersManager() const override;
void SavePrinter(const Printer& printer) override {}
void RemoveSavedPrinter(const std::string& printer_id) override {}
......
......@@ -19,8 +19,11 @@
#include "build/chromeos_buildflags.h"
#include "chrome/browser/chromeos/account_manager/account_manager_util.h"
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
#include "chrome/browser/chromeos/printing/cups_printers_manager.h"
#include "chrome/browser/chromeos/printing/cups_printers_manager_factory.h"
#include "chrome/browser/device_identity/device_oauth2_token_service.h"
#include "chrome/browser/device_identity/device_oauth2_token_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_handler.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
#include "chrome/browser/ui/webui/print_preview/printer_handler.h"
......@@ -33,6 +36,31 @@
namespace printing {
namespace {
using chromeos::CupsPrintersManager;
using chromeos::CupsPrintersManagerFactory;
base::Value ConvertPrintServersConfig(
const chromeos::PrintServersConfig& config) {
base::Value ui_print_servers(base::Value::Type::LIST);
for (const auto& print_server : config.print_servers) {
base::Value ui_print_server(base::Value::Type::DICTIONARY);
ui_print_server.SetStringKey("id", print_server.GetId());
ui_print_server.SetStringKey("name", print_server.GetName());
ui_print_servers.Append(std::move(ui_print_server));
}
base::Value ui_print_servers_config(base::Value::Type::DICTIONARY);
ui_print_servers_config.SetKey("printServers", std::move(ui_print_servers));
ui_print_servers_config.SetBoolKey(
"isSingleServerFetchingMode",
config.fetching_mode ==
chromeos::ServerPrintersFetchingMode::kSingleServerOnly);
return ui_print_servers_config;
}
} // namespace
class PrintPreviewHandlerChromeOS::AccessTokenService
: public OAuth2AccessTokenManager::Consumer {
public:
......@@ -102,12 +130,37 @@ void PrintPreviewHandlerChromeOS::RegisterMessages() {
base::BindRepeating(
&PrintPreviewHandlerChromeOS::HandleRequestPrinterStatusUpdate,
base::Unretained(this)));
if (base::FeatureList::IsEnabled(chromeos::features::kPrintServerScaling)) {
web_ui()->RegisterMessageCallback(
"choosePrintServer",
base::BindRepeating(
&PrintPreviewHandlerChromeOS::HandleChoosePrintServer,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"getPrintServersConfig",
base::BindRepeating(
&PrintPreviewHandlerChromeOS::HandleGetPrintServersConfig,
base::Unretained(this)));
}
}
void PrintPreviewHandlerChromeOS::OnJavascriptAllowed() {
if (base::FeatureList::IsEnabled(chromeos::features::kPrintServerScaling)) {
Profile* profile = Profile::FromWebUI(web_ui());
print_servers_manager_ =
CupsPrintersManagerFactory::GetForBrowserContext(profile)
->GetPrintServersManager();
print_servers_manager_->AddObserver(this);
}
}
void PrintPreviewHandlerChromeOS::OnJavascriptDisallowed() {
// Normally the handler and print preview will be destroyed together, but
// this is necessary for refresh or navigation from the chrome://print page.
weak_factory_.InvalidateWeakPtrs();
if (base::FeatureList::IsEnabled(chromeos::features::kPrintServerScaling)) {
print_servers_manager_->RemoveObserver(this);
}
}
void PrintPreviewHandlerChromeOS::HandleGrantExtensionPrinterAccess(
......@@ -268,4 +321,48 @@ void PrintPreviewHandlerChromeOS::OnPrinterStatusUpdated(
ResolveJavascriptCallback(base::Value(callback_id), cups_printer_status);
}
void PrintPreviewHandlerChromeOS::HandleChoosePrintServer(
const base::ListValue* args) {
CHECK_EQ(1U, args->GetSize());
const base::Value& val = args->GetList()[0];
std::vector<std::string> print_server_ids;
for (const auto& id : val.GetList()) {
print_server_ids.push_back(id.GetString());
}
MaybeAllowJavascript();
FireWebUIListener("server-printers-loading", base::Value(true));
print_servers_manager_->ChoosePrintServer(print_server_ids);
}
void PrintPreviewHandlerChromeOS::HandleGetPrintServersConfig(
const base::ListValue* args) {
std::string callback_id;
CHECK(args->GetString(0, &callback_id));
CHECK(!callback_id.empty());
const chromeos::PrintServersConfig print_servers_config =
print_servers_manager_->GetPrintServersConfig();
base::Value ui_print_servers_config =
ConvertPrintServersConfig(print_servers_config);
ResolveJavascriptCallback(base::Value(callback_id), ui_print_servers_config);
}
void PrintPreviewHandlerChromeOS::OnPrintServersChanged(
const chromeos::PrintServersConfig& config) {
if (base::FeatureList::IsEnabled(chromeos::features::kPrintServerScaling)) {
base::Value ui_print_servers_config = ConvertPrintServersConfig(config);
MaybeAllowJavascript();
FireWebUIListener("print-servers-config-changed", ui_print_servers_config);
}
}
void PrintPreviewHandlerChromeOS::OnServerPrintersChanged(
const std::vector<chromeos::PrinterDetector::DetectedPrinter>& printers) {
if (base::FeatureList::IsEnabled(chromeos::features::kPrintServerScaling)) {
MaybeAllowJavascript();
FireWebUIListener("server-printers-loading", base::Value(false));
}
}
} // namespace printing
......@@ -14,6 +14,7 @@
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/chromeos/printing/print_servers_manager.h"
#include "chrome/common/buildflags.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/identity_manager/identity_manager.h"
......@@ -32,7 +33,9 @@ class PrinterHandler;
class PrintPreviewHandler;
// The handler for Javascript messages related to the print preview dialog.
class PrintPreviewHandlerChromeOS : public content::WebUIMessageHandler {
class PrintPreviewHandlerChromeOS
: public content::WebUIMessageHandler,
public chromeos::PrintServersManager::Observer {
public:
PrintPreviewHandlerChromeOS();
~PrintPreviewHandlerChromeOS() override;
......@@ -40,6 +43,7 @@ class PrintPreviewHandlerChromeOS : public content::WebUIMessageHandler {
// WebUIMessageHandler implementation.
void RegisterMessages() override;
void OnJavascriptDisallowed() override;
void OnJavascriptAllowed() override;
protected:
// Protected so unit tests can override.
......@@ -92,9 +96,25 @@ class PrintPreviewHandlerChromeOS : public content::WebUIMessageHandler {
void OnPrinterStatusUpdated(const std::string& callback_id,
const base::Value& cups_printer_status);
// PrintServersManager::Observer implementation
void OnPrintServersChanged(
const chromeos::PrintServersConfig& config) override;
void OnServerPrintersChanged(
const std::vector<chromeos::PrinterDetector::DetectedPrinter>& printers)
override;
// Loads printers corresponding to the print server(s). First element of
// |args| is the print server IDs.
void HandleChoosePrintServer(const base::ListValue* args);
// Gets the list of print servers and fetching mode.
void HandleGetPrintServersConfig(const base::ListValue* args);
// Holds token service to get OAuth2 access tokens.
std::unique_ptr<AccessTokenService> token_service_;
chromeos::PrintServersManager* print_servers_manager_;
base::WeakPtrFactory<PrintPreviewHandlerChromeOS> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PrintPreviewHandlerChromeOS);
......
// 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/ui/webui/print_preview/print_preview_handler_chromeos.h"
#include <vector>
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "chrome/browser/chromeos/printing/cups_printers_manager.h"
#include "chrome/browser/chromeos/printing/cups_printers_manager_factory.h"
#include "chrome/browser/chromeos/printing/printing_stubs.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_handler.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/constants/chromeos_features.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_web_ui.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace printing {
const char kSelectedPrintServerId[] = "selected-print-server-id";
const char kSelectedPrintServerName[] = "Print Server Name";
class TestPrintServersManager : public chromeos::PrintServersManager {
public:
void AddObserver(Observer* observer) override { observer_ = observer; }
void RemoveObserver(Observer* observer) override { observer_ = nullptr; }
void ChoosePrintServer(
const std::vector<std::string>& selected_print_server_ids) override {
selected_print_server_ids_ = selected_print_server_ids;
}
chromeos::PrintServersConfig GetPrintServersConfig() const override {
return print_servers_config_;
}
void ChangePrintServersConfig(const chromeos::PrintServersConfig& config) {
print_servers_config_ = config;
observer_->OnPrintServersChanged(config);
}
virtual void ChangeServerPrinters(
const std::vector<chromeos::PrinterDetector::DetectedPrinter>& printers) {
observer_->OnServerPrintersChanged(printers);
}
std::vector<std::string> selected_print_server_ids() {
return selected_print_server_ids_;
}
Observer* observer_;
std::vector<std::string> selected_print_server_ids_;
chromeos::PrintServersConfig print_servers_config_;
};
class TestCupsPrintersManager : public chromeos::StubCupsPrintersManager {
public:
explicit TestCupsPrintersManager(
chromeos::PrintServersManager* print_servers_manager)
: print_servers_manager_(print_servers_manager) {}
chromeos::PrintServersManager* GetPrintServersManager() const override {
return print_servers_manager_;
}
private:
chromeos::PrintServersManager* print_servers_manager_;
};
class FakePrintPreviewUI : public PrintPreviewUI {
public:
FakePrintPreviewUI(content::WebUI* web_ui,
std::unique_ptr<PrintPreviewHandler> handler)
: PrintPreviewUI(web_ui, std::move(handler)) {}
~FakePrintPreviewUI() override = default;
private:
DISALLOW_COPY_AND_ASSIGN(FakePrintPreviewUI);
};
class PrintPreviewHandlerChromeOSTest : public testing::Test {
public:
PrintPreviewHandlerChromeOSTest() = default;
~PrintPreviewHandlerChromeOSTest() override = default;
void SetUp() override {
scoped_feature_list_.InitWithFeatures(
{chromeos::features::kPrintServerScaling}, {});
TestingProfile::Builder builder;
profile_ = builder.Build();
chromeos::CupsPrintersManagerFactory::GetInstance()
->SetTestingFactoryAndUse(
profile_.get(),
base::BindLambdaForTesting([this](content::BrowserContext* context)
-> std::unique_ptr<KeyedService> {
print_servers_manager_ =
std::make_unique<TestPrintServersManager>();
return std::make_unique<TestCupsPrintersManager>(
print_servers_manager_.get());
}));
preview_web_contents_ = content::WebContents::Create(
content::WebContents::CreateParams(profile_.get()));
web_ui_ = std::make_unique<content::TestWebUI>();
web_ui_->set_web_contents(preview_web_contents_.get());
auto preview_handler = std::make_unique<PrintPreviewHandlerChromeOS>();
handler_ = preview_handler.get();
web_ui()->AddMessageHandler(std::move(preview_handler));
handler_->AllowJavascriptForTesting();
auto preview_ui = std::make_unique<FakePrintPreviewUI>(
web_ui(), std::make_unique<PrintPreviewHandler>());
web_ui()->SetController(std::move(preview_ui));
}
void AssertWebUIEventFired(const content::TestWebUI::CallData& data,
const std::string& event_id) {
EXPECT_EQ("cr.webUIListenerCallback", data.function_name());
std::string event_fired;
ASSERT_TRUE(data.arg1()->GetAsString(&event_fired));
EXPECT_EQ(event_id, event_fired);
}
content::TestWebUI* web_ui() { return web_ui_.get(); }
TestPrintServersManager* print_servers_manager() {
return print_servers_manager_.get();
}
private:
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestingProfile> profile_;
std::unique_ptr<content::TestWebUI> web_ui_;
std::unique_ptr<content::WebContents> preview_web_contents_;
PrintPreviewHandlerChromeOS* handler_;
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<TestPrintServersManager> print_servers_manager_;
DISALLOW_COPY_AND_ASSIGN(PrintPreviewHandlerChromeOSTest);
};
TEST_F(PrintPreviewHandlerChromeOSTest, ChoosePrintServer) {
base::Value selected_args(base::Value::Type::LIST);
base::Value selected_ids_js(base::Value::Type::LIST);
selected_ids_js.Append(kSelectedPrintServerId);
selected_args.Append(std::move(selected_ids_js));
base::Value none_selected_args(base::Value::Type::LIST);
base::Value none_selected_js(base::Value::Type::LIST);
none_selected_args.Append(std::move(none_selected_js));
web_ui()->HandleReceivedMessage("choosePrintServer",
&base::Value::AsListValue(selected_args));
EXPECT_THAT(print_servers_manager()->selected_print_server_ids(),
testing::ElementsAre(std::string(kSelectedPrintServerId)));
web_ui()->HandleReceivedMessage(
"choosePrintServer", &base::Value::AsListValue(none_selected_args));
EXPECT_THAT(print_servers_manager()->selected_print_server_ids(),
testing::IsEmpty());
AssertWebUIEventFired(*web_ui()->call_data().back(),
"server-printers-loading");
EXPECT_EQ(web_ui()->call_data().back()->arg2()->GetBool(), true);
}
TEST_F(PrintPreviewHandlerChromeOSTest, OnPrintServersChanged) {
std::vector<chromeos::PrintServer> servers;
servers.emplace_back(kSelectedPrintServerId, GURL("http://print-server.com"),
kSelectedPrintServerName);
chromeos::PrintServersConfig config;
config.print_servers = servers;
config.fetching_mode = chromeos::ServerPrintersFetchingMode::kStandard;
print_servers_manager()->ChangePrintServersConfig(config);
auto* call_data = web_ui()->call_data().back().get();
AssertWebUIEventFired(*call_data, "print-servers-config-changed");
base::Value::ConstListView printer_list =
call_data->arg2()->FindListKey("printServers")->GetList();
bool is_single_server_fetching_mode =
call_data->arg2()->FindBoolKey("isSingleServerFetchingMode").value();
ASSERT_EQ(printer_list.size(), 1u);
const base::Value& first_printer = printer_list.front();
EXPECT_EQ(*first_printer.FindStringKey("id"), kSelectedPrintServerId);
EXPECT_EQ(*first_printer.FindStringKey("name"), kSelectedPrintServerName);
EXPECT_EQ(is_single_server_fetching_mode, false);
}
TEST_F(PrintPreviewHandlerChromeOSTest, OnServerPrintersUpdated) {
std::vector<chromeos::PrinterDetector::DetectedPrinter> printers;
print_servers_manager()->ChangeServerPrinters(printers);
AssertWebUIEventFired(*web_ui()->call_data().back(),
"server-printers-loading");
EXPECT_EQ(web_ui()->call_data().back()->arg2()->GetBool(), false);
}
} // namespace printing
......@@ -5814,6 +5814,7 @@ test("unit_tests") {
} else {
sources += [
"../browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc",
"../browser/ui/webui/print_preview/print_preview_handler_chromeos_unittest.cc",
"../browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc",
"../browser/ui/webui/settings/chromeos/server_printer_url_util_unittest.cc",
]
......
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