diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-05-20 09:47:09 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-06-07 11:15:42 +0000 |
commit | 189d4fd8fad9e3c776873be51938cd31a42b6177 (patch) | |
tree | 6497caeff5e383937996768766ab3bb2081a40b2 /chromium/chrome/browser/ui/webui/print_preview | |
parent | 8bc75099d364490b22f43a7ce366b366c08f4164 (diff) |
BASELINE: Update Chromium to 90.0.4430.221
Change-Id: Iff4d9d18d2fcf1a576f3b1f453010f744a232920
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/chrome/browser/ui/webui/print_preview')
25 files changed, 1807 insertions, 576 deletions
diff --git a/chromium/chrome/browser/ui/webui/print_preview/DEPS b/chromium/chrome/browser/ui/webui/print_preview/DEPS new file mode 100644 index 00000000000..89e0648e41a --- /dev/null +++ b/chromium/chrome/browser/ui/webui/print_preview/DEPS @@ -0,0 +1,5 @@ +specific_include_rules = { + "local_printer_handler_.*_unittest.cc": [ + "+chrome/services/printing/print_backend_service_test_impl.h", + ], +} diff --git a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc index 26768770d2b..41845b698b3 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc @@ -15,6 +15,7 @@ #include "base/metrics/histogram_functions.h" #include "base/task/thread_pool.h" #include "base/values.h" +#include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/printing/cups_print_job_manager.h" #include "chrome/browser/chromeos/printing/cups_print_job_manager_factory.h" @@ -22,20 +23,21 @@ #include "chrome/browser/chromeos/printing/cups_printers_manager_factory.h" #include "chrome/browser/chromeos/printing/ppd_provider_factory.h" #include "chrome/browser/chromeos/printing/printer_configurer.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/printing/print_backend_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/print_preview/print_preview_utils.h" #include "chrome/common/pref_names.h" +#include "chrome/common/printing/printer_capabilities.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/printing/printer_configuration.h" #include "chromeos/printing/printer_translator.h" #include "components/prefs/pref_service.h" -#include "components/printing/browser/printer_capabilities.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "printing/backend/print_backend_consts.h" #include "printing/backend/printing_restrictions.h" +#include "printing/printing_features.h" #include "url/gurl.h" namespace printing { @@ -63,10 +65,9 @@ PrinterBasicInfo ToBasicInfo(const chromeos::Printer& printer) { } void AddPrintersToList(const std::vector<chromeos::Printer>& printers, - PrinterList* list) { - for (const auto& printer : printers) { - list->push_back(ToBasicInfo(printer)); - } + PrinterList& list) { + for (const auto& printer : printers) + list.push_back(ToBasicInfo(printer)); } base::Value FetchCapabilitiesAsync(const std::string& device_name, @@ -86,6 +87,30 @@ void CapabilitiesFetched(base::Value policies, std::move(cb).Run(std::move(printer_info)); } +void CapabilitiesFetchedFromService( + const std::string& device_name, + const PrinterBasicInfo& basic_info, + bool has_secure_protocol, + base::Value policies, + LocalPrinterHandlerChromeos::GetCapabilityCallback cb, + const base::Optional<PrinterSemanticCapsAndDefaults>& printer_caps) { + std::unique_ptr<PrinterSemanticCapsAndDefaults> caps; + if (printer_caps.has_value()) { + VLOG(1) << "Successfully received printer capabilities from service for " + << device_name; + caps = + std::make_unique<PrinterSemanticCapsAndDefaults>(printer_caps.value()); + } else { + LOG(WARNING) << "Failure fetching printer capabilities from service for " + << device_name; + } + CapabilitiesFetched( + std::move(policies), std::move(cb), + AssemblePrinterSettings(device_name, basic_info, + PrinterSemanticCapsAndDefaults::Papers(), + has_secure_protocol, caps.get())); +} + void FetchCapabilities(const chromeos::Printer& printer, base::Value policies, LocalPrinterHandlerChromeos::GetCapabilityCallback cb) { @@ -93,13 +118,26 @@ void FetchCapabilities(const chromeos::Printer& printer, PrinterBasicInfo basic_info = ToBasicInfo(printer); - // USER_VISIBLE because the result is displayed in the print preview dialog. - base::ThreadPool::PostTaskAndReplyWithResult( - FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, - base::BindOnce(&FetchCapabilitiesAsync, printer.id(), basic_info, - printer.HasSecureProtocol(), - g_browser_process->GetApplicationLocale()), - base::BindOnce(&CapabilitiesFetched, std::move(policies), std::move(cb))); + if (base::FeatureList::IsEnabled(features::kEnableOopPrintDrivers)) { + VLOG(1) << "Fetching printer capabilities via service"; + GetPrintBackendService(g_browser_process->GetApplicationLocale(), + printer.id()) + ->GetPrinterSemanticCapsAndDefaults( + printer.id(), + base::BindOnce(&CapabilitiesFetchedFromService, printer.id(), + std::move(basic_info), printer.HasSecureProtocol(), + std::move(policies), std::move(cb))); + } else { + VLOG(1) << "Fetching printer capabilities in-process"; + // USER_VISIBLE because the result is displayed in the print preview dialog. + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&FetchCapabilitiesAsync, printer.id(), basic_info, + printer.HasSecureProtocol(), + g_browser_process->GetApplicationLocale()), + base::BindOnce(&CapabilitiesFetched, std::move(policies), + std::move(cb))); + } } } // namespace @@ -115,7 +153,7 @@ LocalPrinterHandlerChromeos::LocalPrinterHandlerChromeos( printers_manager_(printers_manager), printer_configurer_(std::move(printer_configurer)), ppd_provider_(std::move(ppd_provider)) { - // Construct the CupsPrintJobManager to listen for printing events. + // Construct the `CupsPrintJobManager` to listen for printing events. chromeos::CupsPrintJobManagerFactory::GetForBrowserContext(profile); } @@ -168,7 +206,7 @@ void LocalPrinterHandlerChromeos::GetDefaultPrinter(DefaultPrinterCallback cb) { void LocalPrinterHandlerChromeos::StartGetPrinters( AddedPrintersCallback added_printers_callback, GetPrintersDoneCallback done_callback) { - // SyncedPrintersManager is not thread safe and must be called from the UI + // `SyncedPrintersManager` is not thread safe and must be called from the UI // thread. DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -177,11 +215,11 @@ void LocalPrinterHandlerChromeos::StartGetPrinters( PrinterList printer_list; AddPrintersToList(printers_manager_->GetPrinters(PrinterClass::kSaved), - &printer_list); + printer_list); AddPrintersToList(printers_manager_->GetPrinters(PrinterClass::kEnterprise), - &printer_list); + printer_list); AddPrintersToList(printers_manager_->GetPrinters(PrinterClass::kAutomatic), - &printer_list); + printer_list); ConvertPrinterListForCallback(std::move(added_printers_callback), std::move(done_callback), printer_list); @@ -298,7 +336,7 @@ void LocalPrinterHandlerChromeos::HandlePrinterSetup( chromeos::PrinterConfigurer::RecordUsbPrinterSetupSource( chromeos::UsbPrinterSetupSource::kPrintPreview); } - // fetch settings on the blocking pool and invoke callback. + // Fetch settings off of the UI thread and invoke callback. FetchCapabilities(printer, GetNativePrinterPolicies(), std::move(cb)); return; } diff --git a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc index 065fc3e4015..c5598f54172 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc @@ -5,6 +5,7 @@ #include "chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h" #include <algorithm> +#include <functional> #include <memory> #include <string> #include <vector> @@ -16,17 +17,20 @@ #include "base/values.h" #include "chrome/browser/chromeos/printing/test_cups_printers_manager.h" #include "chrome/browser/chromeos/printing/test_printer_configurer.h" +#include "chrome/browser/printing/print_backend_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" +#include "chrome/common/printing/printer_capabilities.h" +#include "chrome/services/printing/print_backend_service_test_impl.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/printing/ppd_provider.h" -#include "components/printing/browser/printer_capabilities.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/test/browser_task_environment.h" #include "printing/backend/print_backend.h" #include "printing/backend/printing_restrictions.h" #include "printing/backend/test_print_backend.h" #include "printing/print_job_constants.h" +#include "printing/printing_features.h" #include "testing/gtest/include/gtest/gtest.h" namespace printing { @@ -40,29 +44,31 @@ using chromeos::PrinterConfigurer; using chromeos::PrinterSetupCallback; using chromeos::PrinterSetupResult; -// Used as a callback to StartGetPrinters in tests. -// Increases |*call_count| and records values returned by StartGetPrinters. -void RecordPrinterList(size_t* call_count, - std::unique_ptr<base::ListValue>* printers_out, +// Used as a callback to `StartGetPrinters` in tests. +// Increases `call_count` and records values returned by `StartGetPrinters`. +void RecordPrinterList(size_t& call_count, + std::unique_ptr<base::ListValue>& printers_out, const base::ListValue& printers) { - ++(*call_count); - printers_out->reset(printers.DeepCopy()); + ++call_count; + printers_out.reset(printers.DeepCopy()); } // Used as a callback to StartGetPrinters in tests. // Records that the test is done. -void RecordPrintersDone(bool* is_done_out) { - *is_done_out = true; +void RecordPrintersDone(bool& is_done_out) { + is_done_out = true; } -void RecordGetCapability(std::unique_ptr<base::Value>* capabilities_out, +void RecordGetCapability(bool& capabilities_set, + base::Value& capabilities_out, base::Value capability) { - capabilities_out->reset(capability.DeepCopy()); + capabilities_out = capability.Clone(); + capabilities_set = true; } -void RecordGetEulaUrl(std::string* fetched_eula_url, +void RecordGetEulaUrl(std::string& fetched_eula_url, const std::string& eula_url) { - *fetched_eula_url = eula_url; + fetched_eula_url = eula_url; } Printer CreateTestPrinter(const std::string& id, @@ -95,20 +101,20 @@ Printer CreateEnterprisePrinter(const std::string& id, } // Converts JSON string to base::ListValue object. -// On failure, returns NULL and fills |*error| string. +// On failure, returns NULL and fills `error` string. std::unique_ptr<base::ListValue> GetJSONAsListValue(const std::string& json, - std::string* error) { + std::string& error) { auto ret = base::ListValue::From( - JSONStringValueDeserializer(json).Deserialize(nullptr, error)); + JSONStringValueDeserializer(json).Deserialize(nullptr, &error)); if (!ret) - *error = "Value is not a list."; + error = "Value is not a list."; return ret; } -// Fake PpdProvider backend. This fake PpdProvider is used to fake fetching the -// PPD EULA license of a destination. If |effective_make_and_model| is empty, it -// will return with NOT_FOUND and an empty string. Otherwise, it will return -// SUCCESS with |effective_make_and_model| as the PPD license. +// Fake `PpdProvider` backend. This fake `PpdProvider` is used to fake fetching +// the PPD EULA license of a destination. If `effective_make_and_model` is +// empty, it will return with NOT_FOUND and an empty string. Otherwise, it will +// return SUCCESS with `effective_make_and_model` as the PPD license. class FakePpdProvider : public chromeos::PpdProvider { public: FakePpdProvider() = default; @@ -123,7 +129,7 @@ class FakePpdProvider : public chromeos::PpdProvider { effective_make_and_model.as_string())); } - // These methods are not used by CupsPrintersManager. + // These methods are not used by `CupsPrintersManager`. void ResolvePpd(const Printer::PpdReference& reference, ResolvePpdCallback cb) override {} void ResolvePpdReference(const chromeos::PrinterSearchData& search_data, @@ -143,6 +149,10 @@ class FakePpdProvider : public chromeos::PpdProvider { class LocalPrinterHandlerChromeosTest : public testing::Test { public: LocalPrinterHandlerChromeosTest() = default; + LocalPrinterHandlerChromeosTest(const LocalPrinterHandlerChromeosTest&) = + delete; + LocalPrinterHandlerChromeosTest& operator=( + const LocalPrinterHandlerChromeosTest&) = delete; ~LocalPrinterHandlerChromeosTest() override = default; void SetUp() override { @@ -155,19 +165,65 @@ class LocalPrinterHandlerChromeosTest : public testing::Test { } protected: - // Must outlive |profile_|. + void AddPrinter(const std::string& id, + const std::string& display_name, + const std::string& description, + bool is_default) { + auto caps = std::make_unique<PrinterSemanticCapsAndDefaults>(); + caps->papers.push_back({"bar", "vendor", {600, 600}}); + auto basic_info = std::make_unique<PrinterBasicInfo>( + id, display_name, description, /*printer_status=*/0, is_default, + PrinterBasicInfoOptions{}); + test_backend_->AddValidPrinter("printer1", std::move(caps), + std::move(basic_info)); + } + + // Must outlive `profile_`. content::BrowserTaskEnvironment task_environment_; - // Must outlive |printers_manager_|. + // Must outlive `printers_manager_`. TestingProfile profile_; scoped_refptr<TestPrintBackend> test_backend_; chromeos::TestCupsPrintersManager printers_manager_; scoped_refptr<FakePpdProvider> ppd_provider_; std::unique_ptr<LocalPrinterHandlerChromeos> local_printer_handler_; +}; - private: - DISALLOW_COPY_AND_ASSIGN(LocalPrinterHandlerChromeosTest); +// `LocalPrinterHandlerChromeosProcessScopeTest` performs test which make use +// of the print backend and can utilize that in different process scopes, be +// that in-process via a local task runner or out-of-process through a service. +class LocalPrinterHandlerChromeosProcessScopeTest + : public LocalPrinterHandlerChromeosTest, + public testing::WithParamInterface<bool> { + public: + LocalPrinterHandlerChromeosProcessScopeTest() = default; + LocalPrinterHandlerChromeosProcessScopeTest( + const LocalPrinterHandlerChromeosProcessScopeTest&) = delete; + LocalPrinterHandlerChromeosProcessScopeTest& operator=( + const LocalPrinterHandlerChromeosProcessScopeTest&) = delete; + ~LocalPrinterHandlerChromeosProcessScopeTest() override = default; + + void SetUp() override { + // Choose between running with local test runner or via a service. + LocalPrinterHandlerChromeosTest::SetUp(); + const bool use_backend_service = GetParam(); + if (use_backend_service) { + feature_list_.InitAndEnableFeature(features::kEnableOopPrintDrivers); + print_backend_service_ = PrintBackendServiceTestImpl::LaunchForTesting( + test_remote_, test_backend_); + } + } + + protected: + // Support for testing via a service instead of with a local task runner. + base::test::ScopedFeatureList feature_list_; + mojo::Remote<mojom::PrintBackendService> test_remote_; + std::unique_ptr<PrintBackendServiceTestImpl> print_backend_service_; }; +INSTANTIATE_TEST_SUITE_P(All, + LocalPrinterHandlerChromeosProcessScopeTest, + testing::Bool()); + TEST_F(LocalPrinterHandlerChromeosTest, GetPrinters) { size_t call_count = 0; std::unique_ptr<base::ListValue> printers; @@ -185,8 +241,9 @@ TEST_F(LocalPrinterHandlerChromeosTest, GetPrinters) { printers_manager_.AddPrinter(automatic_printer, PrinterClass::kAutomatic); local_printer_handler_->StartGetPrinters( - base::BindRepeating(&RecordPrinterList, &call_count, &printers), - base::BindOnce(&RecordPrintersDone, &is_done)); + base::BindRepeating(&RecordPrinterList, std::ref(call_count), + std::ref(printers)), + base::BindOnce(&RecordPrintersDone, std::ref(is_done))); EXPECT_EQ(call_count, 1u); EXPECT_TRUE(is_done); @@ -225,77 +282,78 @@ TEST_F(LocalPrinterHandlerChromeosTest, GetPrinters) { )"; std::string error; std::unique_ptr<base::ListValue> expected_printers( - GetJSONAsListValue(expected_list, &error)); + GetJSONAsListValue(expected_list, std::ref(error))); ASSERT_TRUE(expected_printers) << "Error deserializing printers: " << error; EXPECT_EQ(*printers, *expected_printers); } // Tests that fetching capabilities for an existing installed printer is // successful. -TEST_F(LocalPrinterHandlerChromeosTest, StartGetCapabilityValidPrinter) { +TEST_P(LocalPrinterHandlerChromeosProcessScopeTest, + StartGetCapabilityValidPrinter) { Printer saved_printer = CreateTestPrinter("printer1", "saved", "description1"); printers_manager_.AddPrinter(saved_printer, PrinterClass::kSaved); printers_manager_.InstallPrinter("printer1"); - // Add printer capabilities to |test_backend_|. - PrinterSemanticCapsAndDefaults caps; - test_backend_->AddValidPrinter( - "printer1", std::make_unique<PrinterSemanticCapsAndDefaults>(caps), - std::make_unique<printing::PrinterBasicInfo>()); + // Add printer capabilities to `test_backend_`. + AddPrinter("printer1", "saved", "description1", true); - std::unique_ptr<base::Value> fetched_caps; + bool did_fetch_caps = false; + base::Value fetched_caps; local_printer_handler_->StartGetCapability( - "printer1", base::BindOnce(&RecordGetCapability, &fetched_caps)); + "printer1", base::BindOnce(&RecordGetCapability, std::ref(did_fetch_caps), + std::ref(fetched_caps))); task_environment_.RunUntilIdle(); - ASSERT_TRUE(fetched_caps); - base::DictionaryValue* dict; - ASSERT_TRUE(fetched_caps->GetAsDictionary(&dict)); - ASSERT_TRUE(dict->HasKey(kSettingCapabilities)); - ASSERT_TRUE(dict->HasKey(kPrinter)); + ASSERT_TRUE(did_fetch_caps); + ASSERT_TRUE(fetched_caps.is_dict()); + EXPECT_TRUE(fetched_caps.FindKey(kSettingCapabilities)); + EXPECT_TRUE(fetched_caps.FindKey(kPrinter)); } // Test that printers which have not yet been installed are installed with -// SetUpPrinter before their capabilities are fetched. -TEST_F(LocalPrinterHandlerChromeosTest, StartGetCapabilityPrinterNotInstalled) { +// `SetUpPrinter` before their capabilities are fetched. +TEST_P(LocalPrinterHandlerChromeosProcessScopeTest, + StartGetCapabilityPrinterNotInstalled) { Printer discovered_printer = CreateTestPrinter("printer1", "discovered", "description1"); - // NOTE: The printer |discovered_printer| is not installed using - // InstallPrinter. + // NOTE: The printer `discovered_printer` is not installed using + // `InstallPrinter`. printers_manager_.AddPrinter(discovered_printer, PrinterClass::kDiscovered); - // Add printer capabilities to |test_backend_|. - PrinterSemanticCapsAndDefaults caps; - test_backend_->AddValidPrinter( - "printer1", std::make_unique<PrinterSemanticCapsAndDefaults>(caps), - std::make_unique<printing::PrinterBasicInfo>()); + // Add printer capabilities to `test_backend_`. + AddPrinter("printer1", "discovered", "description1", true); - std::unique_ptr<base::Value> fetched_caps; + bool did_fetch_caps = false; + base::Value fetched_caps; local_printer_handler_->StartGetCapability( - "printer1", base::BindOnce(&RecordGetCapability, &fetched_caps)); + "printer1", base::BindOnce(&RecordGetCapability, std::ref(did_fetch_caps), + std::ref(fetched_caps))); task_environment_.RunUntilIdle(); - ASSERT_TRUE(fetched_caps); - base::DictionaryValue* dict; - ASSERT_TRUE(fetched_caps->GetAsDictionary(&dict)); - ASSERT_TRUE(dict->HasKey(kSettingCapabilities)); - ASSERT_TRUE(dict->HasKey(kPrinter)); + ASSERT_TRUE(did_fetch_caps); + ASSERT_TRUE(fetched_caps.is_dict()); + EXPECT_TRUE(fetched_caps.FindKey(kSettingCapabilities)); + EXPECT_TRUE(fetched_caps.FindKey(kPrinter)); } -// In this test we expect the StartGetCapability to bail early because the -// provided printer can't be found in the CupsPrintersManager. +// In this test we expect the `StartGetCapability` to bail early because the +// provided printer can't be found in the `CupsPrintersManager`. TEST_F(LocalPrinterHandlerChromeosTest, StartGetCapabilityInvalidPrinter) { - std::unique_ptr<base::Value> fetched_caps; + bool did_fetch_caps = false; + base::Value fetched_caps; local_printer_handler_->StartGetCapability( - "invalid printer", base::BindOnce(&RecordGetCapability, &fetched_caps)); + "invalid printer", + base::BindOnce(&RecordGetCapability, std::ref(did_fetch_caps), + std::ref(fetched_caps))); task_environment_.RunUntilIdle(); - ASSERT_TRUE(fetched_caps); - EXPECT_TRUE(fetched_caps->is_none()); + ASSERT_TRUE(did_fetch_caps); + EXPECT_TRUE(fetched_caps.is_none()); } TEST_F(LocalPrinterHandlerChromeosTest, GetNativePrinterPolicies) { @@ -333,7 +391,7 @@ TEST_F(LocalPrinterHandlerChromeosTest, StartFetchValidEulaUrl) { Printer::PpdReference ref; ref.effective_make_and_model = "expected_make_model"; - // Printers with a PpdReference will return a license + // Printers with a `PpdReference` will return a license Printer saved_printer = CreateTestPrinterWithPpdReference( "printer1", "saved", "description1", ref); printers_manager_.AddPrinter(saved_printer, PrinterClass::kSaved); @@ -341,7 +399,8 @@ TEST_F(LocalPrinterHandlerChromeosTest, StartFetchValidEulaUrl) { std::string fetched_eula_url; local_printer_handler_->StartGetEulaUrl( - "printer1", base::BindOnce(&RecordGetEulaUrl, &fetched_eula_url)); + "printer1", + base::BindOnce(&RecordGetEulaUrl, std::ref(fetched_eula_url))); task_environment_.RunUntilIdle(); @@ -350,7 +409,7 @@ TEST_F(LocalPrinterHandlerChromeosTest, StartFetchValidEulaUrl) { // Test that a printer with no PPD license will return an empty string. TEST_F(LocalPrinterHandlerChromeosTest, StartFetchNotFoundEulaUrl) { - // A printer without a PpdReference will simulate an PPD without a license. + // A printer without a `PpdReference` will simulate an PPD without a license. Printer saved_printer = CreateTestPrinter("printer1", "saved", "description1"); printers_manager_.AddPrinter(saved_printer, PrinterClass::kSaved); @@ -358,7 +417,8 @@ TEST_F(LocalPrinterHandlerChromeosTest, StartFetchNotFoundEulaUrl) { std::string fetched_eula_url; local_printer_handler_->StartGetEulaUrl( - "printer1", base::BindOnce(&RecordGetEulaUrl, &fetched_eula_url)); + "printer1", + base::BindOnce(&RecordGetEulaUrl, std::ref(fetched_eula_url))); task_environment_.RunUntilIdle(); @@ -366,14 +426,15 @@ TEST_F(LocalPrinterHandlerChromeosTest, StartFetchNotFoundEulaUrl) { } // Test that fetching a PPD license will exit early if the printer is not found -// in CupsPrintersManager. +// in `CupsPrintersManager`. TEST_F(LocalPrinterHandlerChromeosTest, StartFetchEulaUrlOnNonExistantPrinter) { Printer saved_printer = CreateTestPrinter("printer1", "saved", "description1"); std::string fetched_eula_url; local_printer_handler_->StartGetEulaUrl( - "printer1", base::BindOnce(&RecordGetEulaUrl, &fetched_eula_url)); + "printer1", + base::BindOnce(&RecordGetEulaUrl, std::ref(fetched_eula_url))); task_environment_.RunUntilIdle(); diff --git a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc index bf325ecd6bc..be75cd7188a 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc @@ -16,13 +16,15 @@ #include "base/task/thread_pool.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/printing/print_backend_service.h" #include "chrome/browser/ui/webui/print_preview/print_preview_utils.h" -#include "components/printing/browser/printer_capabilities.h" +#include "chrome/common/printing/printer_capabilities.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" +#include "printing/printing_features.h" #if defined(OS_MAC) -#include "components/printing/browser/printer_capabilities_mac.h" +#include "chrome/common/printing/printer_capabilities_mac.h" #endif #if defined(OS_WIN) @@ -54,6 +56,45 @@ scoped_refptr<base::TaskRunner> CreatePrinterHandlerTaskRunner() { #endif } +void OnDidEnumeratePrinters( + PrinterHandler::AddedPrintersCallback added_printers_callback, + PrinterHandler::GetPrintersDoneCallback done_callback, + const base::Optional<PrinterList>& printer_list) { + const bool have_printers = printer_list.has_value(); + if (!have_printers) + LOG(WARNING) << "Failure enumerating local printers."; + + ConvertPrinterListForCallback( + std::move(added_printers_callback), std::move(done_callback), + have_printers ? printer_list.value() : PrinterList()); +} + +void OnDidFetchCapabilities( + const std::string& device_name, + bool has_secure_protocol, + PrinterHandler::GetCapabilityCallback callback, + const base::Optional<PrinterBasicInfo>& printer_info, + const base::Optional<PrinterSemanticCapsAndDefaults::Papers>& + user_defined_papers, + const base::Optional<PrinterSemanticCapsAndDefaults>& caps_and_defaults) { + const bool has_values = printer_info.has_value() && + user_defined_papers.has_value() && + caps_and_defaults.has_value(); + if (!has_values) { + LOG(WARNING) << "Failure fetching printer capabilities for " + << device_name; + std::move(callback).Run(base::Value()); + return; + } + + VLOG(1) << "Received printer info & capabilities for " << device_name; + PrinterSemanticCapsAndDefaults caps = caps_and_defaults.value(); + base::Value settings = AssemblePrinterSettings( + device_name, std::move(printer_info.value()), + std::move(user_defined_papers.value()), has_secure_protocol, &caps); + std::move(callback).Run(std::move(settings)); +} + } // namespace // static @@ -143,15 +184,24 @@ void LocalPrinterHandlerDefault::GetDefaultPrinter(DefaultPrinterCallback cb) { void LocalPrinterHandlerDefault::StartGetPrinters( AddedPrintersCallback callback, GetPrintersDoneCallback done_callback) { - VLOG(1) << "Enumerate printers start"; DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - base::PostTaskAndReplyWithResult( - task_runner_.get(), FROM_HERE, - base::BindOnce(&EnumeratePrintersAsync, - g_browser_process->GetApplicationLocale()), - base::BindOnce(&ConvertPrinterListForCallback, std::move(callback), - std::move(done_callback))); + if (base::FeatureList::IsEnabled(features::kEnableOopPrintDrivers)) { + VLOG(1) << "Enumerate printers start via service"; + GetPrintBackendService(g_browser_process->GetApplicationLocale(), + /*printer_name=*/std::string()) + ->EnumeratePrinters(base::BindOnce(&OnDidEnumeratePrinters, + std::move(callback), + std::move(done_callback))); + } else { + VLOG(1) << "Enumerate printers start in-process"; + base::PostTaskAndReplyWithResult( + task_runner_.get(), FROM_HERE, + base::BindOnce(&EnumeratePrintersAsync, + g_browser_process->GetApplicationLocale()), + base::BindOnce(&ConvertPrinterListForCallback, std::move(callback), + std::move(done_callback))); + } } void LocalPrinterHandlerDefault::StartGetCapability( @@ -159,11 +209,22 @@ void LocalPrinterHandlerDefault::StartGetCapability( GetCapabilityCallback cb) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - base::PostTaskAndReplyWithResult( - task_runner_.get(), FROM_HERE, - base::BindOnce(&FetchCapabilitiesAsync, device_name, - g_browser_process->GetApplicationLocale()), - std::move(cb)); + if (base::FeatureList::IsEnabled(features::kEnableOopPrintDrivers)) { + VLOG(1) << "Getting printer capabilities via service for " << device_name; + GetPrintBackendService(g_browser_process->GetApplicationLocale(), + device_name) + ->FetchCapabilities( + device_name, + base::BindOnce(&OnDidFetchCapabilities, device_name, + /*has_secure_protocol=*/false, std::move(cb))); + } else { + VLOG(1) << "Getting printer capabilities in-process for " << device_name; + base::PostTaskAndReplyWithResult( + task_runner_.get(), FROM_HERE, + base::BindOnce(&FetchCapabilitiesAsync, device_name, + g_browser_process->GetApplicationLocale()), + std::move(cb)); + } } void LocalPrinterHandlerDefault::StartPrint( diff --git a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default_unittest.cc b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default_unittest.cc new file mode 100644 index 00000000000..25549620856 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default_unittest.cc @@ -0,0 +1,232 @@ +// Copyright 2021 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/local_printer_handler_default.h" + +#include <functional> +#include <memory> + +#include "base/json/json_string_value_serializer.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" +#include "base/strings/string_piece.h" +#include "base/values.h" +#include "chrome/browser/printing/print_backend_service.h" +#include "chrome/common/printing/printer_capabilities.h" +#include "chrome/services/printing/print_backend_service_test_impl.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_task_environment.h" +#include "printing/backend/print_backend.h" +#include "printing/backend/test_print_backend.h" +#include "printing/printing_features.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace printing { + +namespace { + +// Used as a callback to `StartGetPrinters` in tests. +// Increases `call_count` and records values returned by `StartGetPrinters`. +// TODO(crbug.com/1171579) Get rid of use of base::ListValue. +void RecordPrinterList(size_t& call_count, + std::unique_ptr<base::ListValue>& printers_out, + const base::ListValue& printers) { + ++call_count; + printers_out.reset(printers.DeepCopy()); +} + +// Used as a callback to StartGetPrinters in tests. +// Records that the test is done. +void RecordPrintersDone(bool& is_done_out) { + is_done_out = true; +} + +void RecordGetCapability(bool& capabilities_set, + base::Value& capabilities_out, + base::Value capability) { + capabilities_out = capability.Clone(); + capabilities_set = true; +} + +// Converts JSON string to base::ListValue object. +// On failure, returns NULL and fills `error` string. +std::unique_ptr<base::ListValue> GetJSONAsListValue( + const base::StringPiece& json, + std::string& error) { + auto ret = base::ListValue::From( + JSONStringValueDeserializer(json).Deserialize(nullptr, &error)); + if (!ret) + error = "Value is not a list."; + return ret; +} + +} // namespace + +class LocalPrinterHandlerDefaultTest : public testing::TestWithParam<bool> { + public: + LocalPrinterHandlerDefaultTest() = default; + LocalPrinterHandlerDefaultTest(const LocalPrinterHandlerDefaultTest&) = + delete; + LocalPrinterHandlerDefaultTest& operator=( + const LocalPrinterHandlerDefaultTest&) = delete; + ~LocalPrinterHandlerDefaultTest() override = default; + + TestPrintBackend* print_backend() { return test_backend_.get(); } + + void SetUp() override { + // Choose between running with local test runner or via a service. + const bool use_backend_service = GetParam(); + feature_list_.InitWithFeatureState(features::kEnableOopPrintDrivers, + use_backend_service); + + TestingProfile::Builder builder; + profile_ = builder.Build(); + initiator_web_contents_ = content::WebContents::Create( + content::WebContents::CreateParams(profile_.get())); + content::WebContents* initiator = initiator_web_contents_.get(); + test_backend_ = base::MakeRefCounted<TestPrintBackend>(); + PrintBackend::SetPrintBackendForTesting(test_backend_.get()); + local_printer_handler_ = + std::make_unique<LocalPrinterHandlerDefault>(initiator); + + if (use_backend_service) { + print_backend_service_ = PrintBackendServiceTestImpl::LaunchForTesting( + test_remote_, test_backend_); + } + } + + void AddPrinter(const std::string& id, + const std::string& display_name, + const std::string& description, + bool is_default) { + auto caps = std::make_unique<PrinterSemanticCapsAndDefaults>(); + caps->papers.emplace_back( + PrinterSemanticCapsAndDefaults::Paper{"bar", "vendor", {600, 600}}); + auto basic_info = std::make_unique<PrinterBasicInfo>( + id, display_name, description, + /*printer_status=*/0, is_default, PrinterBasicInfoOptions{}); + + print_backend()->AddValidPrinter(id, std::move(caps), + std::move(basic_info)); + } + + protected: + content::BrowserTaskEnvironment task_environment_; + std::unique_ptr<TestingProfile> profile_; + std::unique_ptr<content::WebContents> initiator_web_contents_; + scoped_refptr<TestPrintBackend> test_backend_; + std::unique_ptr<LocalPrinterHandlerDefault> local_printer_handler_; + + // Support for testing via a service instead of with a local task runner. + base::test::ScopedFeatureList feature_list_; + mojo::Remote<mojom::PrintBackendService> test_remote_; + std::unique_ptr<PrintBackendServiceTestImpl> print_backend_service_; +}; + +INSTANTIATE_TEST_SUITE_P(All, LocalPrinterHandlerDefaultTest, testing::Bool()); + +TEST_P(LocalPrinterHandlerDefaultTest, GetPrinters) { + AddPrinter("printer1", "default1", "description1", true); + AddPrinter("printer2", "non-default2", "description2", false); + AddPrinter("printer3", "non-default3", "description3", false); + + size_t call_count = 0; + std::unique_ptr<base::ListValue> printers; + bool is_done = false; + + local_printer_handler_->StartGetPrinters( + base::BindRepeating(&RecordPrinterList, std::ref(call_count), + std::ref(printers)), + base::BindOnce(&RecordPrintersDone, std::ref(is_done))); + + task_environment_.RunUntilIdle(); + + EXPECT_EQ(call_count, 1u); + EXPECT_TRUE(is_done); + ASSERT_TRUE(printers); + + constexpr base::StringPiece expected_list = R"( + [ + { + "deviceName": "printer1", + "printerDescription": "description1", + "printerName": "default1", + "printerOptions": {} + }, + { + "deviceName": "printer2", + "printerDescription": "description2", + "printerName": "non-default2", + "printerOptions": {} + }, + { + "deviceName": "printer3", + "printerDescription": "description3", + "printerName": "non-default3", + "printerOptions": {} + } + ] + )"; + std::string error; + std::unique_ptr<base::ListValue> expected_printers( + GetJSONAsListValue(expected_list, error)); + ASSERT_TRUE(expected_printers) << "Error deserializing printers: " << error; + EXPECT_EQ(*printers, *expected_printers); +} + +TEST_P(LocalPrinterHandlerDefaultTest, GetPrintersNoneRegistered) { + size_t call_count = 0; + std::unique_ptr<base::ListValue> printers; + bool is_done = false; + + // Do not add any printers before attempt to get printer list. + local_printer_handler_->StartGetPrinters( + base::BindRepeating(&RecordPrinterList, std::ref(call_count), + std::ref(printers)), + base::BindOnce(&RecordPrintersDone, std::ref(is_done))); + + task_environment_.RunUntilIdle(); + + EXPECT_EQ(call_count, 0u); + EXPECT_TRUE(is_done); + EXPECT_FALSE(printers); +} + +// Tests that fetching capabilities for an existing installed printer is +// successful. +TEST_P(LocalPrinterHandlerDefaultTest, StartGetCapabilityValidPrinter) { + AddPrinter("printer1", "default1", "description1", true); + + bool did_fetch_caps = false; + base::Value fetched_caps; + local_printer_handler_->StartGetCapability( + "printer1", base::BindOnce(&RecordGetCapability, std::ref(did_fetch_caps), + std::ref(fetched_caps))); + + task_environment_.RunUntilIdle(); + + ASSERT_TRUE(did_fetch_caps); + ASSERT_TRUE(fetched_caps.is_dict()); + EXPECT_TRUE(fetched_caps.FindKey(kSettingCapabilities)); + EXPECT_TRUE(fetched_caps.FindKey(kPrinter)); +} + +// Tests that fetching capabilities bails early when the provided printer +// can't be found. +TEST_P(LocalPrinterHandlerDefaultTest, StartGetCapabilityInvalidPrinter) { + bool did_fetch_caps = false; + base::Value fetched_caps; + local_printer_handler_->StartGetCapability( + /*destination_id=*/"invalid printer", + base::BindOnce(&RecordGetCapability, std::ref(did_fetch_caps), + std::ref(fetched_caps))); + + task_environment_.RunUntilIdle(); + + ASSERT_TRUE(did_fetch_caps); + EXPECT_TRUE(fetched_caps.is_none()); +} + +} // namespace printing diff --git a/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc b/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc index c48314e52e8..e64ac255c18 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc @@ -9,17 +9,19 @@ #include "base/bind.h" #include "base/callback.h" #include "base/command_line.h" +#include "base/containers/contains.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/i18n/file_util_icu.h" -#include "base/stl_util.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/values.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "chrome/browser/app_mode/app_mode_utils.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/download/download_prefs.h" @@ -46,10 +48,10 @@ #include "url/gurl.h" #if defined(OS_MAC) -#include "components/printing/browser/printer_capabilities_mac.h" +#include "chrome/common/printing/printer_capabilities_mac.h" #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) #include "chrome/browser/chromeos/drive/drive_integration_service.h" #endif @@ -254,7 +256,7 @@ void PdfPrinterHandler::StartPrint( base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); bool prompt_user = !cmdline->HasSwitch(switches::kKioskModePrinting); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) use_drive_mount_ = settings.FindBoolKey(kSettingPrintToGoogleDrive).value_or(false); #endif @@ -287,7 +289,7 @@ base::FilePath PdfPrinterHandler::GetFileNameForPrintJobTitle( const base::string16& job_title) { DCHECK(!job_title.empty()); #if defined(OS_WIN) - base::FilePath::StringType print_job_title(job_title); + base::FilePath::StringType print_job_title(base::AsWString(job_title)); #elif defined(OS_POSIX) base::FilePath::StringType print_job_title = base::UTF16ToUTF8(job_title); #endif @@ -430,7 +432,7 @@ void PdfPrinterHandler::OnDirectorySelected(const base::FilePath& filename, } base::FilePath PdfPrinterHandler::GetSaveLocation() const { -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) drive::DriveIntegrationService* drive_service = drive::DriveIntegrationServiceFactory::GetForProfile(profile_); if (use_drive_mount_ && drive_service && drive_service->IsMounted()) { diff --git a/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h b/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h index 26954aeae08..d796486f6b7 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h +++ b/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h @@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" +#include "build/chromeos_buildflags.h" #include "chrome/browser/ui/webui/print_preview/printer_handler.h" #include "ui/shell_dialogs/select_file_dialog.h" @@ -108,7 +109,7 @@ class PdfPrinterHandler : public PrinterHandler, // The callback to call when complete. PrintCallback print_callback_; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) // Determines if the local Drive mount is sent to the file picker as the // default save location. Set to true for Save to Drive print jobs. bool use_drive_mount_ = false; diff --git a/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler_unittest.cc b/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler_unittest.cc index 23cc4711f79..c5b9d0242be 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler_unittest.cc @@ -17,7 +17,7 @@ #include "url/gurl.h" #if defined(OS_MAC) -#include "components/printing/browser/printer_capabilities_mac.h" +#include "chrome/common/printing/printer_capabilities_mac.h" #include "printing/backend/print_backend.h" #include "ui/gfx/geometry/size.h" #endif diff --git a/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc b/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc index 77de5f8fd34..1616bb22b6a 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc @@ -32,7 +32,7 @@ void ExecuteCancelledSelectFileDialog( const base::FilePath& default_path, const std::vector<ui::FileFilterSpec>& filter, int file_type_index, - const base::string16& default_extension, + const std::wstring& default_extension, HWND owner, ui::OnSelectFileExecutedCallback on_select_file_executed_callback) { // Send an empty result to simulate a cancelled dialog. @@ -117,17 +117,17 @@ class PdfPrinterHandlerWinTest : public BrowserWithTestWindowTest { }; TEST_F(PdfPrinterHandlerWinTest, TestSaveAsPdf) { - pdf_printer_->StartPrintToPdf(L"111111111111111111111.html"); + pdf_printer_->StartPrintToPdf(STRING16_LITERAL("111111111111111111111.html")); EXPECT_TRUE(pdf_printer_->save_failed()); } TEST_F(PdfPrinterHandlerWinTest, TestSaveAsPdfLongFileName) { - pdf_printer_->StartPrintToPdf( - L"11111111111111111111111111111111111111111111111111111111111111111111111" - L"11111111111111111111111111111111111111111111111111111111111111111111111" - L"11111111111111111111111111111111111111111111111111111111111111111111111" - L"11111111111111111111111111111111111111111111111111111111111111111111111" - L"1111111111111111111111111111111111111111111111111.html"); + pdf_printer_->StartPrintToPdf(STRING16_LITERAL( + "111111111111111111111111111111111111111111111111111111111111111111111111" + "111111111111111111111111111111111111111111111111111111111111111111111111" + "111111111111111111111111111111111111111111111111111111111111111111111111" + "111111111111111111111111111111111111111111111111111111111111111111111111" + "111111111111111111111111111111111111111111111.html")); EXPECT_TRUE(pdf_printer_->save_failed()); } diff --git a/chromium/chrome/browser/ui/webui/print_preview/policy_settings.cc b/chromium/chrome/browser/ui/webui/print_preview/policy_settings.cc index 28088a6be76..ce617f0a28c 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/policy_settings.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/policy_settings.cc @@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/print_preview/policy_settings.h" +#include "build/chromeos_buildflags.h" #include "chrome/common/pref_names.h" #include "components/pref_registry/pref_registry_syncable.h" @@ -12,13 +13,14 @@ namespace printing { // static void PolicySettings::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterBooleanPref(prefs::kForceEnablePrivetPrinting, false); registry->RegisterListPref(prefs::kPrinterTypeDenyList); registry->RegisterBooleanPref(prefs::kPrintHeaderFooter, true); registry->RegisterIntegerPref(prefs::kPrintingAllowedBackgroundGraphicsModes, 0); registry->RegisterIntegerPref(prefs::kPrintingBackgroundGraphicsDefault, 0); registry->RegisterDictionaryPref(prefs::kPrintingPaperSizeDefault); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) registry->RegisterIntegerPref(prefs::kPrintingAllowedColorModes, 0); registry->RegisterIntegerPref(prefs::kPrintingAllowedDuplexModes, 0); registry->RegisterIntegerPref(prefs::kPrintingAllowedPinModes, 0); diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index 4064cb61edd..5beb6ac1f57 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc @@ -24,6 +24,8 @@ #include "base/memory/ref_counted_memory.h" #include "base/values.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" +#include "chrome/browser/account_manager_facade_factory.h" #include "chrome/browser/app_mode/app_mode_utils.h" #include "chrome/browser/bad_message.h" #include "chrome/browser/browser_process.h" @@ -53,12 +55,12 @@ #include "chrome/common/cloud_print/cloud_print_constants.h" #include "chrome/common/crash_keys.h" #include "chrome/common/pref_names.h" +#include "chrome/common/printing/printer_capabilities.h" #include "chrome/common/webui_url_constants.h" #include "components/cloud_devices/common/cloud_device_description.h" #include "components/cloud_devices/common/cloud_devices_urls.h" #include "components/cloud_devices/common/printer_description.h" #include "components/prefs/pref_service.h" -#include "components/printing/browser/printer_capabilities.h" #include "components/printing/common/cloud_print_cdd_conversion.h" #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h" #include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h" @@ -78,17 +80,14 @@ #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/icu/source/i18n/unicode/ulocdata.h" -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/account_manager/account_manager_util.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/constants/ash_features.h" +#include "chrome/browser/ash/account_manager/account_manager_util.h" #include "chrome/browser/chromeos/drive/drive_integration_service.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/ui/settings_window_manager_chromeos.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h" #include "chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.h" -#include "chromeos/constants/chromeos_features.h" -#include "chromeos/printing/printer_configuration.h" -#include "components/signin/public/identity_manager/scope_set.h" +#include "components/account_manager_core/account_manager_facade.h" #endif using content::RenderFrameHost; @@ -177,12 +176,12 @@ const char kCssBackground[] = "cssBackground"; // Name of a dictionary pref holding the policy value for the paper size // setting. const char kMediaSize[] = "mediaSize"; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) // Name of a dictionary field holding policy value for the setting. const char kValue[] = "value"; // Name of a dictionary pref holding the policy value for the sheets number. const char kSheets[] = "sheets"; -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_CHROMEOS_ASH) // Name of a dictionary field indicating whether the 'Save to PDF' destination // is disabled. const char kPdfPrinterDisabled[] = "pdfPrinterDisabled"; @@ -197,11 +196,11 @@ const char kUserAccounts[] = "userAccounts"; // Print Preview will always send a request to the Google Cloud Print server on // load, to check the user's sign in state. const char kSyncAvailable[] = "syncAvailable"; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) // Name of a dictionary field indicating whether the user's Drive directory is // mounted. const char kIsDriveMounted[] = "isDriveMounted"; -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_CHROMEOS_ASH) // Get the print job settings dictionary from |json_str|. // Returns |base::Value()| on failure. @@ -226,7 +225,7 @@ UserActionBuckets DetermineUserAction(const base::Value& settings) { return UserActionBuckets::kOpenInMacPreview; #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) if (base::FeatureList::IsEnabled(chromeos::features::kPrintSaveToDrive) && settings.FindBoolKey(kSettingPrintToGoogleDrive).value_or(false)) { return UserActionBuckets::kPrintToGoogleDriveCros; @@ -324,64 +323,20 @@ base::Value GetPolicies(const PrefService& prefs) { if (!paper_size_policy.DictEmpty()) policies.SetKey(kMediaSize, std::move(paper_size_policy)); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) if (prefs.HasPrefPath(prefs::kPrintingMaxSheetsAllowed)) { base::Value sheets_policy(base::Value::Type::DICTIONARY); sheets_policy.SetIntKey(kValue, prefs.GetInteger(prefs::kPrintingMaxSheetsAllowed)); policies.SetKey(kSheets, std::move(sheets_policy)); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_CHROMEOS_ASH) return policies; } } // namespace -#if defined(OS_CHROMEOS) -class PrintPreviewHandler::AccessTokenService - : public OAuth2AccessTokenManager::Consumer { - public: - AccessTokenService() : OAuth2AccessTokenManager::Consumer("print_preview") {} - - void RequestToken(base::OnceCallback<void(const std::string&)> callback) { - // There can only be one pending request at a time. See - // cloud_print_interface_js.js. - const signin::ScopeSet scopes{cloud_devices::kCloudPrintAuthScope}; - DCHECK(!device_request_callback_); - - DeviceOAuth2TokenService* token_service = - DeviceOAuth2TokenServiceFactory::Get(); - device_request_ = token_service->StartAccessTokenRequest(scopes, this); - device_request_callback_ = std::move(callback); - } - - void OnGetTokenSuccess( - const OAuth2AccessTokenManager::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) override { - OnServiceResponse(request, token_response.access_token); - } - - void OnGetTokenFailure(const OAuth2AccessTokenManager::Request* request, - const GoogleServiceAuthError& error) override { - OnServiceResponse(request, std::string()); - } - - private: - void OnServiceResponse(const OAuth2AccessTokenManager::Request* request, - const std::string& access_token) { - DCHECK_EQ(request, device_request_.get()); - std::move(device_request_callback_).Run(access_token); - device_request_.reset(); - } - - std::unique_ptr<OAuth2AccessTokenManager::Request> device_request_; - base::OnceCallback<void(const std::string&)> device_request_callback_; - - DISALLOW_COPY_AND_ASSIGN(AccessTokenService); -}; -#endif // defined(OS_CHROMEOS) - PrintPreviewHandler::PrintPreviewHandler() { ReportUserActionHistogram(UserActionBuckets::kPreviewStarted); } @@ -405,10 +360,6 @@ void PrintPreviewHandler::RegisterMessages() { "getPrinterCapabilities", base::BindRepeating(&PrintPreviewHandler::HandleGetPrinterCapabilities, base::Unretained(this))); - web_ui()->RegisterMessageCallback( - "setupPrinter", - base::BindRepeating(&PrintPreviewHandler::HandlePrinterSetup, - base::Unretained(this))); #if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) web_ui()->RegisterMessageCallback( "showSystemDialog", @@ -418,12 +369,6 @@ void PrintPreviewHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( "signIn", base::BindRepeating(&PrintPreviewHandler::HandleSignin, base::Unretained(this))); -#if defined(OS_CHROMEOS) - web_ui()->RegisterMessageCallback( - "getAccessToken", - base::BindRepeating(&PrintPreviewHandler::HandleGetAccessToken, - base::Unretained(this))); -#endif web_ui()->RegisterMessageCallback( "closePrintPreviewDialog", base::BindRepeating(&PrintPreviewHandler::HandleClosePreviewDialog, @@ -445,25 +390,9 @@ void PrintPreviewHandler::RegisterMessages() { base::BindRepeating(&PrintPreviewHandler::HandleGetInitialSettings, base::Unretained(this))); web_ui()->RegisterMessageCallback( - "grantExtensionPrinterAccess", - base::BindRepeating( - &PrintPreviewHandler::HandleGrantExtensionPrinterAccess, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( "managePrinters", base::BindRepeating(&PrintPreviewHandler::HandleManagePrinters, base::Unretained(this))); - -#if defined(OS_CHROMEOS) - web_ui()->RegisterMessageCallback( - "getEulaUrl", base::BindRepeating(&PrintPreviewHandler::HandleGetEulaUrl, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( - "requestPrinterStatus", - base::BindRepeating( - &PrintPreviewHandler::HandleRequestPrinterStatusUpdate, - base::Unretained(this))); -#endif } void PrintPreviewHandler::OnJavascriptAllowed() { @@ -589,21 +518,6 @@ void PrintPreviewHandler::HandleGetPrinters(const base::ListValue* args) { weak_factory_.GetWeakPtr(), callback_id)); } -void PrintPreviewHandler::HandleGrantExtensionPrinterAccess( - const base::ListValue* args) { - std::string callback_id; - std::string printer_id; - bool ok = args->GetString(0, &callback_id) && - args->GetString(1, &printer_id) && !callback_id.empty(); - DCHECK(ok); - - PrinterHandler* handler = GetPrinterHandler(PrinterType::kExtension); - handler->StartGrantPrinterAccess( - printer_id, - base::BindOnce(&PrintPreviewHandler::OnGotExtensionPrinterInfo, - weak_factory_.GetWeakPtr(), callback_id)); -} - void PrintPreviewHandler::HandleGetPrinterCapabilities( const base::ListValue* args) { std::string callback_id; @@ -794,36 +708,18 @@ void PrintPreviewHandler::HandleSaveAppState(const base::ListValue* args) { sticky_settings->SaveInPrefs(GetPrefs()); } -// |args| is expected to contain a string with representing the callback id -// followed by a list of arguments the first of which should be the printer id. -void PrintPreviewHandler::HandlePrinterSetup(const base::ListValue* args) { - std::string callback_id; - std::string printer_name; - if (!args->GetString(0, &callback_id) || !args->GetString(1, &printer_name) || - callback_id.empty() || printer_name.empty()) { - RejectJavascriptCallback(base::Value(callback_id), - base::Value(printer_name)); - return; - } - - PrinterHandler* handler = GetPrinterHandler(PrinterType::kLocal); - handler->StartGetCapability( - printer_name, - base::BindOnce(&PrintPreviewHandler::SendPrinterSetup, - weak_factory_.GetWeakPtr(), callback_id, printer_name)); -} - void PrintPreviewHandler::HandleSignin(const base::ListValue* /*args*/) { Profile* profile = Profile::FromWebUI(web_ui()); DCHECK(profile); -#if defined(OS_CHROMEOS) - if (chromeos::IsAccountManagerAvailable(profile)) { +#if BUILDFLAG(IS_CHROMEOS_ASH) + if (ash::IsAccountManagerAvailable(profile)) { // Chrome OS Account Manager is enabled on this Profile and hence, all // account management flows will go through native UIs and not through a // tabbed browser window. - chromeos::InlineLoginDialogChromeOS::Show( - chromeos::InlineLoginDialogChromeOS::Source::kPrintPreviewDialog); + ::GetAccountManagerFacade(profile->GetPath().value()) + ->ShowAddAccountDialog(account_manager::AccountManagerFacade:: + AccountAdditionSource::kPrintPreviewDialog); return; } #endif @@ -844,21 +740,6 @@ void PrintPreviewHandler::OnSignInTabClosed() { FireWebUIListener("check-for-account-update"); } -#if defined(OS_CHROMEOS) -void PrintPreviewHandler::HandleGetAccessToken(const base::ListValue* args) { - std::string callback_id; - - bool ok = args->GetString(0, &callback_id) && !callback_id.empty(); - DCHECK(ok); - - if (!token_service_) - token_service_ = std::make_unique<AccessTokenService>(); - token_service_->RequestToken( - base::BindOnce(&PrintPreviewHandler::SendAccessToken, - weak_factory_.GetWeakPtr(), callback_id)); -} -#endif - #if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) void PrintPreviewHandler::HandleShowSystemDialog( const base::ListValue* /*args*/) { @@ -886,20 +767,6 @@ void PrintPreviewHandler::HandleClosePreviewDialog( regenerate_preview_request_count_); } -#if defined(OS_CHROMEOS) -void PrintPreviewHandler::HandleGetEulaUrl(const base::ListValue* args) { - CHECK_EQ(2U, args->GetSize()); - - const std::string& callback_id = args->GetList()[0].GetString(); - const std::string& destination_id = args->GetList()[1].GetString(); - - PrinterHandler* handler = GetPrinterHandler(PrinterType::kLocal); - handler->StartGetEulaUrl( - destination_id, base::BindOnce(&PrintPreviewHandler::SendEulaUrl, - weak_factory_.GetWeakPtr(), callback_id)); -} -#endif - void PrintPreviewHandler::GetLocaleInformation(base::Value* settings) { // Getting the measurement system based on the locale. UErrorCode errorCode = U_ZERO_ERROR; @@ -1020,7 +887,7 @@ void PrintPreviewHandler::SendInitialSettings( GetUserAccountList(&initial_settings); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) if (base::FeatureList::IsEnabled(chromeos::features::kPrintSaveToDrive)) { drive::DriveIntegrationService* drive_service = drive::DriveIntegrationServiceFactory::GetForProfile( @@ -1028,7 +895,7 @@ void PrintPreviewHandler::SendInitialSettings( initial_settings.SetBoolKey(kIsDriveMounted, drive_service && drive_service->IsMounted()); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_CHROMEOS_ASH) ResolveJavascriptCallback(base::Value(callback_id), initial_settings); } @@ -1037,21 +904,6 @@ void PrintPreviewHandler::ClosePreviewDialog() { print_preview_ui()->OnClosePrintPreviewDialog(); } -#if defined(OS_CHROMEOS) -void PrintPreviewHandler::SendAccessToken(const std::string& callback_id, - const std::string& access_token) { - VLOG(1) << "Get getAccessToken finished"; - ResolveJavascriptCallback(base::Value(callback_id), - base::Value(access_token)); -} - -void PrintPreviewHandler::SendEulaUrl(const std::string& callback_id, - const std::string& eula_url) { - VLOG(1) << "Get PPD license finished"; - ResolveJavascriptCallback(base::Value(callback_id), base::Value(eula_url)); -} -#endif - void PrintPreviewHandler::SendPrinterCapabilities( const std::string& callback_id, base::Value settings_info) { @@ -1068,35 +920,6 @@ void PrintPreviewHandler::SendPrinterCapabilities( RejectJavascriptCallback(base::Value(callback_id), base::Value()); } -void PrintPreviewHandler::SendPrinterSetup(const std::string& callback_id, - const std::string& printer_name, - base::Value destination_info) { - base::Value response(base::Value::Type::DICTIONARY); - base::Value* caps_value = - destination_info.is_dict() - ? destination_info.FindKeyOfType(kSettingCapabilities, - base::Value::Type::DICTIONARY) - : nullptr; - response.SetKey("printerId", base::Value(printer_name)); - response.SetKey("success", base::Value(!!caps_value)); - response.SetKey("capabilities", - caps_value ? std::move(*caps_value) - : base::Value(base::Value::Type::DICTIONARY)); - if (caps_value) { - base::Value* printer = - destination_info.FindKeyOfType(kPrinter, base::Value::Type::DICTIONARY); - if (printer) { - base::Value* policies_value = printer->FindKeyOfType( - kSettingPolicies, base::Value::Type::DICTIONARY); - if (policies_value) - response.SetKey("policies", std::move(*policies_value)); - } - } else { - LOG(WARNING) << "Printer setup failed"; - } - ResolveJavascriptCallback(base::Value(callback_id), response); -} - void PrintPreviewHandler::SendCloudPrintJob( const std::string& callback_id, const base::RefCountedMemory* data) { @@ -1259,7 +1082,8 @@ PrinterHandler* PrintPreviewHandler::GetPrinterHandler( return extension_printer_handler_.get(); } #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) - if (printer_type == PrinterType::kPrivet) { + if (printer_type == PrinterType::kPrivet && + GetPrefs()->GetBoolean(prefs::kForceEnablePrivetPrinting)) { if (!privet_printer_handler_) { privet_printer_handler_ = PrinterHandler::CreateForPrivetPrinters(Profile::FromWebUI(web_ui())); @@ -1309,16 +1133,6 @@ void PrintPreviewHandler::OnGetPrintersDone(const std::string& callback_id) { ResolveJavascriptCallback(base::Value(callback_id), base::Value()); } -void PrintPreviewHandler::OnGotExtensionPrinterInfo( - const std::string& callback_id, - const base::DictionaryValue& printer_info) { - if (printer_info.empty()) { - RejectJavascriptCallback(base::Value(callback_id), base::Value()); - return; - } - ResolveJavascriptCallback(base::Value(callback_id), printer_info); -} - void PrintPreviewHandler::OnPrintResult(const std::string& callback_id, const base::Value& error) { if (error.is_none()) @@ -1395,29 +1209,8 @@ void PrintPreviewHandler::SendManipulateSettingsForTest( FireWebUIListener("manipulate-settings-for-test", settings); } -#if defined(OS_CHROMEOS) -void PrintPreviewHandler::HandleRequestPrinterStatusUpdate( - const base::ListValue* args) { - CHECK_EQ(2U, args->GetSize()); - - const std::string& callback_id = args->GetList()[0].GetString(); - const std::string& printer_id = args->GetList()[1].GetString(); - - PrinterHandler* handler = GetPrinterHandler(PrinterType::kLocal); - handler->StartPrinterStatusRequest( - printer_id, base::BindOnce(&PrintPreviewHandler::OnPrinterStatusUpdated, - weak_factory_.GetWeakPtr(), callback_id)); -} - -void PrintPreviewHandler::OnPrinterStatusUpdated( - const std::string& callback_id, - const base::Value& cups_printer_status) { - ResolveJavascriptCallback(base::Value(callback_id), cups_printer_status); -} -#endif - void PrintPreviewHandler::HandleManagePrinters(const base::ListValue* args) { -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) chrome::SettingsWindowManager::GetInstance()->ShowOSSettings( Profile::FromWebUI(web_ui()), chromeos::settings::mojom::kPrintingDetailsSubpagePath); diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h index dd538d6c784..93d41f6e69b 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h @@ -16,6 +16,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" +#include "build/chromeos_buildflags.h" #include "chrome/common/buildflags.h" #include "components/prefs/pref_service.h" #include "components/printing/common/print.mojom.h" @@ -112,9 +113,10 @@ class PrintPreviewHandler : public content::WebUIMessageHandler, // Fires the 'manipulate-settings-for-test' WebUI event with |settings|. void SendManipulateSettingsForTest(const base::DictionaryValue& settings); + virtual PrinterHandler* GetPrinterHandler(PrinterType printer_type); + protected: // Protected so unit tests can override. - virtual PrinterHandler* GetPrinterHandler(PrinterType printer_type); virtual bool IsCloudPrintEnabled(); // Shuts down the initiator renderer. Called when a bad IPC message is @@ -146,10 +148,6 @@ class PrintPreviewHandler : public content::WebUIMessageHandler, FRIEND_TEST_ALL_PREFIXES(PrintPreviewHandlerFailingTest, GetPrinterCapabilities); -#if defined(OS_CHROMEOS) - class AccessTokenService; -#endif - content::WebContents* preview_web_contents() const; PrintPreviewUI* print_preview_ui() const; @@ -176,10 +174,6 @@ class PrintPreviewHandler : public content::WebUIMessageHandler, // callback, second element of |args| is the printer type to fetch. void HandleGetPrinters(const base::ListValue* args); - // Grants an extension access to a provisional printer. First element of - // |args| is the provisional printer ID. - void HandleGrantExtensionPrinterAccess(const base::ListValue* args); - // Asks the initiator renderer to generate a preview. First element of |args| // is a job settings JSON string. void HandleGetPreview(const base::ListValue* args); @@ -205,9 +199,6 @@ class PrintPreviewHandler : public content::WebUIMessageHandler, // printer whose capabilities are requested. void HandleGetPrinterCapabilities(const base::ListValue* args); - // Performs printer setup. First element of |args| is the printer name. - void HandlePrinterSetup(const base::ListValue* args); - #if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) // Asks the initiator renderer to show the native print system dialog. |args| // is unused. @@ -221,11 +212,6 @@ class PrintPreviewHandler : public content::WebUIMessageHandler, // Called when the tab opened by HandleSignIn() is closed. void OnSignInTabClosed(); -#if defined(OS_CHROMEOS) - // Generates new token and sends back to UI. - void HandleGetAccessToken(const base::ListValue* args); -#endif - // Gathers UMA stats when the print preview dialog is about to close. // |args| is unused. void HandleClosePreviewDialog(const base::ListValue* args); @@ -238,35 +224,15 @@ class PrintPreviewHandler : public content::WebUIMessageHandler, // dialog. |args| is unused. void HandleManagePrinters(const base::ListValue* args); -#if defined(OS_CHROMEOS) - // Gets the EULA URL. - void HandleGetEulaUrl(const base::ListValue* args); -#endif - void SendInitialSettings(const std::string& callback_id, const std::string& default_printer); -#if defined(OS_CHROMEOS) - // Send OAuth2 access token. - void SendAccessToken(const std::string& callback_id, - const std::string& access_token); - - // Send the EULA URL; - void SendEulaUrl(const std::string& callback_id, const std::string& eula_url); -#endif - // Sends the printer capabilities to the Web UI. |settings_info| contains // printer capabilities information. If |settings_info| is empty, sends // error notification to the Web UI instead. void SendPrinterCapabilities(const std::string& callback_id, base::Value settings_info); - // Send the result of performing printer setup. |settings_info| contains - // printer capabilities. - void SendPrinterSetup(const std::string& callback_id, - const std::string& printer_name, - base::Value settings_info); - // Send the PDF data to Print Preview so that it can be sent to the cloud // print server to print. void SendCloudPrintJob(const std::string& callback_id, @@ -297,13 +263,6 @@ class PrintPreviewHandler : public content::WebUIMessageHandler, // |callback_id|: The javascript callback to call. void OnGetPrintersDone(const std::string& callback_id); - // Called when an extension reports information requested for a provisional - // printer. - // |callback_id|: The javascript callback to resolve or reject. - // |printer_info|: The data reported by the extension. - void OnGotExtensionPrinterInfo(const std::string& callback_id, - const base::DictionaryValue& printer_info); - // Called when an extension or privet print job is completed. // |callback_id|: The javascript callback to run. // |error|: The returned print job error. Useful for reporting a specific @@ -311,15 +270,6 @@ class PrintPreviewHandler : public content::WebUIMessageHandler, void OnPrintResult(const std::string& callback_id, const base::Value& error); -#if defined(OS_CHROMEOS) - // Called to initiate a status request for a printer. - void HandleRequestPrinterStatusUpdate(const base::ListValue* args); - - // Resolves callback with printer status. - void OnPrinterStatusUpdated(const std::string& callback_id, - const base::Value& cups_printer_status); -#endif - // A count of how many requests received to regenerate preview data. // Initialized to 0 then incremented and emitted to a histogram. int regenerate_preview_request_count_ = 0; @@ -336,11 +286,6 @@ class PrintPreviewHandler : public content::WebUIMessageHandler, // The settings used for the most recent preview request. base::Value last_preview_settings_; -#if defined(OS_CHROMEOS) - // Holds token service to get OAuth2 access tokens. - std::unique_ptr<AccessTokenService> token_service_; -#endif - // Pointer to the identity manager service so that print preview can listen // for GAIA cookie changes. signin::IdentityManager* identity_manager_ = nullptr; diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos.cc new file mode 100644 index 00000000000..bdaa69da7be --- /dev/null +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos.cc @@ -0,0 +1,379 @@ +// 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 <ctype.h> +#include <stddef.h> + +#include <memory> +#include <string> +#include <utility> + +#include "ash/constants/ash_features.h" +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/lazy_instance.h" +#include "base/values.h" +#include "build/build_config.h" +#include "build/chromeos_buildflags.h" +#include "chrome/browser/ash/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" +#include "chrome/common/printing/printer_capabilities.h" +#include "chromeos/printing/printer_configuration.h" +#include "components/cloud_devices/common/cloud_devices_urls.h" +#include "components/signin/public/identity_manager/scope_set.h" +#include "content/public/browser/web_ui.h" + +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: + AccessTokenService() : OAuth2AccessTokenManager::Consumer("print_preview") {} + + void RequestToken(base::OnceCallback<void(const std::string&)> callback) { + // There can only be one pending request at a time. See + // cloud_print_interface_js.js. + const signin::ScopeSet scopes{cloud_devices::kCloudPrintAuthScope}; + DCHECK(!device_request_callback_); + + DeviceOAuth2TokenService* token_service = + DeviceOAuth2TokenServiceFactory::Get(); + device_request_ = token_service->StartAccessTokenRequest(scopes, this); + device_request_callback_ = std::move(callback); + } + + void OnGetTokenSuccess( + const OAuth2AccessTokenManager::Request* request, + const OAuth2AccessTokenConsumer::TokenResponse& token_response) override { + OnServiceResponse(request, token_response.access_token); + } + + void OnGetTokenFailure(const OAuth2AccessTokenManager::Request* request, + const GoogleServiceAuthError& error) override { + OnServiceResponse(request, std::string()); + } + + private: + void OnServiceResponse(const OAuth2AccessTokenManager::Request* request, + const std::string& access_token) { + DCHECK_EQ(request, device_request_.get()); + std::move(device_request_callback_).Run(access_token); + device_request_.reset(); + } + + std::unique_ptr<OAuth2AccessTokenManager::Request> device_request_; + base::OnceCallback<void(const std::string&)> device_request_callback_; + + DISALLOW_COPY_AND_ASSIGN(AccessTokenService); +}; + +PrintPreviewHandlerChromeOS::PrintPreviewHandlerChromeOS() {} + +PrintPreviewHandlerChromeOS::~PrintPreviewHandlerChromeOS() { + if (!base::FeatureList::IsEnabled(chromeos::features::kPrintServerScaling)) { + return; + } + Profile* profile = Profile::FromWebUI(web_ui()); + auto* cups_manager = + CupsPrintersManagerFactory::GetForBrowserContext(profile); + if (cups_manager) { + auto* print_servers_manager = cups_manager->GetPrintServersManager(); + print_servers_manager->RemoveObserver(this); + } +} + +void PrintPreviewHandlerChromeOS::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "setupPrinter", + base::BindRepeating(&PrintPreviewHandlerChromeOS::HandlePrinterSetup, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getAccessToken", + base::BindRepeating(&PrintPreviewHandlerChromeOS::HandleGetAccessToken, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "grantExtensionPrinterAccess", + base::BindRepeating( + &PrintPreviewHandlerChromeOS::HandleGrantExtensionPrinterAccess, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getEulaUrl", + base::BindRepeating(&PrintPreviewHandlerChromeOS::HandleGetEulaUrl, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "requestPrinterStatus", + base::BindRepeating( + &PrintPreviewHandlerChromeOS::HandleRequestPrinterStatusUpdate, + base::Unretained(this))); + if (base::FeatureList::IsEnabled(chromeos::features::kPrintServerScaling)) { + web_ui()->RegisterMessageCallback( + "choosePrintServers", + base::BindRepeating( + &PrintPreviewHandlerChromeOS::HandleChoosePrintServers, + 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( + const base::ListValue* args) { + std::string callback_id; + std::string printer_id; + bool ok = args->GetString(0, &callback_id) && + args->GetString(1, &printer_id) && !callback_id.empty(); + DCHECK(ok); + MaybeAllowJavascript(); + + PrinterHandler* handler = GetPrinterHandler(PrinterType::kExtension); + handler->StartGrantPrinterAccess( + printer_id, + base::BindOnce(&PrintPreviewHandlerChromeOS::OnGotExtensionPrinterInfo, + weak_factory_.GetWeakPtr(), callback_id)); +} + +// |args| is expected to contain a string with representing the callback id +// followed by a list of arguments the first of which should be the printer id. +void PrintPreviewHandlerChromeOS::HandlePrinterSetup( + const base::ListValue* args) { + std::string callback_id; + std::string printer_name; + MaybeAllowJavascript(); + if (!args->GetString(0, &callback_id) || !args->GetString(1, &printer_name) || + callback_id.empty() || printer_name.empty()) { + RejectJavascriptCallback(base::Value(callback_id), + base::Value(printer_name)); + return; + } + + PrinterHandler* handler = GetPrinterHandler(PrinterType::kLocal); + handler->StartGetCapability( + printer_name, + base::BindOnce(&PrintPreviewHandlerChromeOS::SendPrinterSetup, + weak_factory_.GetWeakPtr(), callback_id, printer_name)); +} + +void PrintPreviewHandlerChromeOS::HandleGetAccessToken( + const base::ListValue* args) { + std::string callback_id; + + bool ok = args->GetString(0, &callback_id) && !callback_id.empty(); + DCHECK(ok); + MaybeAllowJavascript(); + + if (!token_service_) + token_service_ = std::make_unique<AccessTokenService>(); + token_service_->RequestToken( + base::BindOnce(&PrintPreviewHandlerChromeOS::SendAccessToken, + weak_factory_.GetWeakPtr(), callback_id)); +} + +void PrintPreviewHandlerChromeOS::HandleGetEulaUrl( + const base::ListValue* args) { + CHECK_EQ(2U, args->GetSize()); + MaybeAllowJavascript(); + + const std::string& callback_id = args->GetList()[0].GetString(); + const std::string& destination_id = args->GetList()[1].GetString(); + + PrinterHandler* handler = GetPrinterHandler(PrinterType::kLocal); + handler->StartGetEulaUrl( + destination_id, base::BindOnce(&PrintPreviewHandlerChromeOS::SendEulaUrl, + weak_factory_.GetWeakPtr(), callback_id)); +} + +void PrintPreviewHandlerChromeOS::SendAccessToken( + const std::string& callback_id, + const std::string& access_token) { + VLOG(1) << "Get getAccessToken finished"; + ResolveJavascriptCallback(base::Value(callback_id), + base::Value(access_token)); +} + +void PrintPreviewHandlerChromeOS::SendEulaUrl(const std::string& callback_id, + const std::string& eula_url) { + VLOG(1) << "Get PPD license finished"; + ResolveJavascriptCallback(base::Value(callback_id), base::Value(eula_url)); +} + +void PrintPreviewHandlerChromeOS::SendPrinterSetup( + const std::string& callback_id, + const std::string& printer_name, + base::Value destination_info) { + base::Value response(base::Value::Type::DICTIONARY); + base::Value* caps_value = + destination_info.is_dict() + ? destination_info.FindKeyOfType(kSettingCapabilities, + base::Value::Type::DICTIONARY) + : nullptr; + response.SetKey("printerId", base::Value(printer_name)); + response.SetKey("success", base::Value(!!caps_value)); + response.SetKey("capabilities", + caps_value ? std::move(*caps_value) + : base::Value(base::Value::Type::DICTIONARY)); + if (caps_value) { + base::Value* printer = + destination_info.FindKeyOfType(kPrinter, base::Value::Type::DICTIONARY); + if (printer) { + base::Value* policies_value = printer->FindKeyOfType( + kSettingPolicies, base::Value::Type::DICTIONARY); + if (policies_value) + response.SetKey("policies", std::move(*policies_value)); + } + } else { + LOG(WARNING) << "Printer setup failed"; + } + ResolveJavascriptCallback(base::Value(callback_id), response); +} + +PrintPreviewHandler* PrintPreviewHandlerChromeOS::GetPrintPreviewHandler() { + PrintPreviewUI* ui = static_cast<PrintPreviewUI*>(web_ui()->GetController()); + return ui->handler(); +} + +PrinterHandler* PrintPreviewHandlerChromeOS::GetPrinterHandler( + PrinterType printer_type) { + return GetPrintPreviewHandler()->GetPrinterHandler(printer_type); +} + +void PrintPreviewHandlerChromeOS::MaybeAllowJavascript() { + if (!IsJavascriptAllowed() && + GetPrintPreviewHandler()->IsJavascriptAllowed()) { + AllowJavascript(); + } +} + +void PrintPreviewHandlerChromeOS::OnGotExtensionPrinterInfo( + const std::string& callback_id, + const base::DictionaryValue& printer_info) { + if (printer_info.empty()) { + RejectJavascriptCallback(base::Value(callback_id), base::Value()); + return; + } + ResolveJavascriptCallback(base::Value(callback_id), printer_info); +} + +void PrintPreviewHandlerChromeOS::HandleRequestPrinterStatusUpdate( + const base::ListValue* args) { + CHECK_EQ(2U, args->GetSize()); + + const std::string& callback_id = args->GetList()[0].GetString(); + const std::string& printer_id = args->GetList()[1].GetString(); + + MaybeAllowJavascript(); + PrinterHandler* handler = GetPrinterHandler(PrinterType::kLocal); + handler->StartPrinterStatusRequest( + printer_id, + base::BindOnce(&PrintPreviewHandlerChromeOS::OnPrinterStatusUpdated, + weak_factory_.GetWeakPtr(), callback_id)); +} + +void PrintPreviewHandlerChromeOS::OnPrinterStatusUpdated( + const std::string& callback_id, + const base::Value& cups_printer_status) { + ResolveJavascriptCallback(base::Value(callback_id), cups_printer_status); +} + +void PrintPreviewHandlerChromeOS::HandleChoosePrintServers( + 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 diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos.h b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos.h new file mode 100644 index 00000000000..1482994a0a5 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos.h @@ -0,0 +1,125 @@ +// 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. + +#ifndef CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_PRINT_PREVIEW_HANDLER_CHROMEOS_H_ +#define CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_PRINT_PREVIEW_HANDLER_CHROMEOS_H_ + +#include <memory> +#include <string> + +#include "base/gtest_prod_util.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#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" +#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; +} + +namespace printing { + +class PrinterHandler; +class PrintPreviewHandler; + +// The handler for Javascript messages related to the print preview dialog. +class PrintPreviewHandlerChromeOS + : public content::WebUIMessageHandler, + public chromeos::PrintServersManager::Observer { + public: + PrintPreviewHandlerChromeOS(); + ~PrintPreviewHandlerChromeOS() override; + + // WebUIMessageHandler implementation. + void RegisterMessages() override; + void OnJavascriptDisallowed() override; + void OnJavascriptAllowed() override; + + protected: + // Protected so unit tests can override. + virtual PrinterHandler* GetPrinterHandler(PrinterType printer_type); + + private: + class AccessTokenService; + + PrintPreviewHandler* GetPrintPreviewHandler(); + + void MaybeAllowJavascript(); + + // Grants an extension access to a provisional printer. First element of + // |args| is the provisional printer ID. + void HandleGrantExtensionPrinterAccess(const base::ListValue* args); + + // Performs printer setup. First element of |args| is the printer name. + void HandlePrinterSetup(const base::ListValue* args); + + // Generates new token and sends back to UI. + void HandleGetAccessToken(const base::ListValue* args); + + // Gets the EULA URL. + void HandleGetEulaUrl(const base::ListValue* args); + + // Send OAuth2 access token. + void SendAccessToken(const std::string& callback_id, + const std::string& access_token); + + // Send the EULA URL; + void SendEulaUrl(const std::string& callback_id, const std::string& eula_url); + + // Send the result of performing printer setup. |settings_info| contains + // printer capabilities. + void SendPrinterSetup(const std::string& callback_id, + const std::string& printer_name, + base::Value settings_info); + + // Called when an extension reports information requested for a provisional + // printer. + // |callback_id|: The javascript callback to resolve or reject. + // |printer_info|: The data reported by the extension. + void OnGotExtensionPrinterInfo(const std::string& callback_id, + const base::DictionaryValue& printer_info); + + // Called to initiate a status request for a printer. + void HandleRequestPrinterStatusUpdate(const base::ListValue* args); + + // Resolves callback with printer status. + 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 HandleChoosePrintServers(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); +}; + +} // namespace printing + +#endif // CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_PRINT_PREVIEW_HANDLER_CHROMEOS_H_ diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos_unittest.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos_unittest.cc new file mode 100644 index 00000000000..a7769525583 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos_unittest.cc @@ -0,0 +1,212 @@ +// 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 "ash/constants/ash_features.h" +#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 "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_; + base::test::ScopedFeatureList scoped_feature_list_; + std::unique_ptr<TestingProfile> profile_; + std::unique_ptr<TestPrintServersManager> print_servers_manager_; + std::unique_ptr<content::WebContents> preview_web_contents_; + std::unique_ptr<content::TestWebUI> web_ui_; + PrintPreviewHandlerChromeOS* handler_; + + DISALLOW_COPY_AND_ASSIGN(PrintPreviewHandlerChromeOSTest); +}; + +TEST_F(PrintPreviewHandlerChromeOSTest, ChoosePrintServers) { + 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("choosePrintServers", + &base::Value::AsListValue(selected_args)); + EXPECT_THAT(print_servers_manager()->selected_print_server_ids(), + testing::ElementsAre(std::string(kSelectedPrintServerId))); + + web_ui()->HandleReceivedMessage( + "choosePrintServers", &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 diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc index c38d276926e..0b94314edab 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc @@ -22,6 +22,7 @@ #include "base/test/icu_test_util.h" #include "base/test/metrics/histogram_tester.h" #include "base/values.h" +#include "build/chromeos_buildflags.h" #include "chrome/browser/printing/print_test_utils.h" #include "chrome/browser/printing/print_view_manager.h" #include "chrome/browser/ui/webui/print_preview/fake_print_render_frame.h" @@ -803,14 +804,14 @@ TEST_F(PrintPreviewHandlerTest, InitialSettingsDefaultPaperSizeCustomSize) { std::move(expected_initial_settings_policy)); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) TEST_F(PrintPreviewHandlerTest, InitialSettingsMaxSheetsAllowedPolicy) { prefs()->SetInteger(prefs::kPrintingMaxSheetsAllowed, 2); Initialize(); ValidateInitialSettingsValuePolicy(*web_ui()->call_data().back(), "sheets", base::Value(2)); } -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_CHROMEOS_ASH) TEST_F(PrintPreviewHandlerTest, GetPrinters) { Initialize(); diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_metrics.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_metrics.cc index d00cef7992d..303f21d35bf 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_metrics.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_metrics.cc @@ -11,6 +11,7 @@ #include "base/optional.h" #include "base/values.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "printing/mojom/print.mojom.h" #include "printing/print_job_constants.h" #include "printing/print_settings.h" @@ -171,10 +172,10 @@ void ReportPrintSettingsStats(const base::Value& print_settings, } } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) if (print_settings.FindStringKey(kSettingPinValue)) ReportPrintSettingHistogram(PrintSettingsBuckets::kPin); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_CHROMEOS_ASH) } void ReportRegeneratePreviewRequestCountBeforeCancel(size_t count) { diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index 1e583ad19d2..0351787fc0e 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc @@ -8,6 +8,7 @@ #include <utility> #include <vector> +#include "ash/constants/ash_features.h" #include "base/base_paths.h" #include "base/bind.h" #include "base/containers/flat_map.h" @@ -28,11 +29,15 @@ #include "base/synchronization/lock.h" #include "base/values.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/pdf/pdf_extension_util.h" #include "chrome/browser/printing/background_printing_manager.h" +#include "chrome/browser/printing/pdf_nup_converter_client.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/printing/print_preview_data_service.h" +#include "chrome/browser/printing/print_preview_dialog_controller.h" +#include "chrome/browser/printing/print_view_manager.h" #include "chrome/browser/printing/printer_query.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/chrome_pages.h" @@ -47,13 +52,12 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/chromium_strings.h" -#include "chrome/grit/component_extension_resources.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/print_preview_resources.h" #include "chrome/grit/print_preview_resources_map.h" -#include "chromeos/constants/chromeos_features.h" #include "components/prefs/pref_service.h" -#include "components/printing/common/print_messages.h" +#include "components/printing/browser/print_composite_client.h" +#include "components/printing/browser/print_manager_utils.h" #include "components/strings/grit/components_strings.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/browser_task_traits.h" @@ -62,7 +66,9 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui_data_source.h" #include "extensions/common/constants.h" +#include "mojo/public/cpp/bindings/callback_helpers.h" #include "printing/mojom/print.mojom.h" +#include "printing/nup_parameters.h" #include "printing/print_job_constants.h" #include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" @@ -71,6 +77,10 @@ #include "ui/web_dialogs/web_dialog_delegate.h" #include "ui/web_dialogs/web_dialog_ui.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos.h" +#endif + #if !BUILDFLAG(OPTIMIZE_WEBUI) #include "chrome/browser/ui/webui/managed_ui_handler.h" #endif @@ -84,10 +94,17 @@ namespace { #if defined(OS_MAC) // U+0028 U+21E7 U+2318 U+0050 U+0029 in UTF8 const char kBasicPrintShortcut[] = "\x28\xE2\x8c\xA5\xE2\x8C\x98\x50\x29"; -#elif !defined(OS_CHROMEOS) +#elif !BUILDFLAG(IS_CHROMEOS_ASH) const char kBasicPrintShortcut[] = "(Ctrl+Shift+P)"; #endif +constexpr char kInvalidArgsForDidStartPreview[] = + "Invalid arguments for DidStartPreview"; +constexpr char kInvalidPageNumberForDidPreviewPage[] = + "Invalid page number for DidPreviewPage"; +constexpr char kInvalidPageCountForMetafileReadyForPrinting[] = + "Invalid page count for MetafileReadyForPrinting"; + PrintPreviewUI::TestDelegate* g_test_delegate = nullptr; void StopWorker(int document_cookie) { @@ -104,6 +121,22 @@ void StopWorker(int document_cookie) { } } +bool IsValidPageNumber(uint32_t page_number, uint32_t page_count) { + return page_number < page_count; +} + +bool ShouldUseCompositor(PrintPreviewUI* print_preview_ui) { + return IsOopifEnabled() && print_preview_ui->source_is_modifiable(); +} + +WebContents* GetInitiator(content::WebUI* web_ui) { + PrintPreviewDialogController* dialog_controller = + PrintPreviewDialogController::GetInstance(); + if (!dialog_controller) + return nullptr; + return dialog_controller->GetInitiator(web_ui->GetWebContents()); +} + // Thread-safe wrapper around a base::flat_map to keep track of mappings from // PrintPreviewUI IDs to most recent print preview request IDs. class PrintPreviewRequestIdMapWithLock { @@ -308,10 +341,14 @@ void AddPrintPreviewStrings(content::WebUIDataSource* source) { {"selectButton", IDS_PRINT_PREVIEW_BUTTON_SELECT}, {"seeMore", IDS_PRINT_PREVIEW_SEE_MORE}, {"seeMoreDestinationsLabel", IDS_PRINT_PREVIEW_SEE_MORE_DESTINATIONS_LABEL}, +#if BUILDFLAG(IS_CHROMEOS_ASH) + {"serverSearchBoxPlaceholder", + IDS_PRINT_PREVIEW_SERVER_SEARCH_BOX_PLACEHOLDER}, +#endif {"title", IDS_PRINT_PREVIEW_TITLE}, {"top", IDS_PRINT_PREVIEW_TOP_MARGIN_LABEL}, {"unsupportedCloudPrinter", IDS_PRINT_PREVIEW_UNSUPPORTED_CLOUD_PRINTER}, -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) {"configuringFailedText", IDS_PRINT_CONFIGURING_FAILED_TEXT}, {"configuringInProgressText", IDS_PRINT_CONFIGURING_IN_PROGRESS_TEXT}, {"optionPin", IDS_PRINT_PREVIEW_OPTION_PIN}, @@ -341,12 +378,12 @@ void AddPrintPreviewStrings(content::WebUIDataSource* source) { {"openingPDFInPreview", IDS_PRINT_PREVIEW_OPENING_PDF_IN_PREVIEW_APP}, #endif }; - AddLocalizedStringsBulk(source, kLocalizedStrings); + source->AddLocalizedStrings(kLocalizedStrings); source->AddString("gcpCertificateErrorLearnMoreURL", chrome::kCloudPrintCertificateErrorLearnMoreURL); -#if !defined(OS_CHROMEOS) +#if !BUILDFLAG(IS_CHROMEOS_ASH) const base::string16 shortcut_text(base::UTF8ToUTF16(kBasicPrintShortcut)); source->AddString("systemDialogOption", l10n_util::GetStringFUTF16( @@ -362,7 +399,7 @@ void AddPrintPreviewStrings(content::WebUIDataSource* source) { } void AddPrintPreviewFlags(content::WebUIDataSource* source, Profile* profile) { -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) source->AddBoolean("useSystemDefaultPrinter", false); #else bool system_default_printer = profile->GetPrefs()->GetBoolean( @@ -372,18 +409,14 @@ void AddPrintPreviewFlags(content::WebUIDataSource* source, Profile* profile) { source->AddBoolean("isEnterpriseManaged", webui::IsEnterpriseManaged()); - bool cloud_print_deprecation_warnings_suppressed = true; - source->AddBoolean("cloudPrintDeprecationWarningsSuppressed", - cloud_print_deprecation_warnings_suppressed); - #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) source->AddBoolean( "forceEnablePrivetPrinting", - cloud_print_deprecation_warnings_suppressed || + profile->GetPrefs()->GetBoolean(prefs::kForceEnablePrivetPrinting) || base::FeatureList::IsEnabled(features::kForceEnablePrivetPrinting)); #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) source->AddBoolean( "showPrinterStatus", base::FeatureList::IsEnabled(chromeos::features::kPrinterStatus)); @@ -393,35 +426,13 @@ void AddPrintPreviewFlags(content::WebUIDataSource* source, Profile* profile) { source->AddBoolean( "printSaveToDrive", base::FeatureList::IsEnabled(chromeos::features::kPrintSaveToDrive)); + source->AddBoolean( + "printServerScaling", + base::FeatureList::IsEnabled(chromeos::features::kPrintServerScaling)); #endif } void SetupPrintPreviewPlugin(content::WebUIDataSource* source) { - static constexpr webui::ResourcePath kPdfResources[] = { - {"pdf/browser_api.js", IDR_PDF_BROWSER_API_JS}, - {"pdf/constants.js", IDR_PDF_CONSTANTS_JS}, - {"pdf/controller.js", IDR_PDF_CONTROLLER_JS}, - {"pdf/elements/icons.js", IDR_PDF_ICONS_JS}, - {"pdf/elements/shared-vars.js", IDR_PDF_SHARED_VARS_JS}, - {"pdf/elements/viewer-error-screen.js", IDR_PDF_VIEWER_ERROR_SCREEN_JS}, - {"pdf/elements/viewer-zoom-button.js", IDR_PDF_VIEWER_ZOOM_BUTTON_JS}, - {"pdf/elements/viewer-zoom-toolbar.js", IDR_PDF_VIEWER_ZOOM_SELECTOR_JS}, - {"pdf/gesture_detector.js", IDR_PDF_GESTURE_DETECTOR_JS}, - {"pdf/index.css", IDR_PDF_INDEX_CSS}, - {"pdf/main.js", IDR_PDF_MAIN_JS}, - {"pdf/metrics.js", IDR_PDF_METRICS_JS}, - {"pdf/open_pdf_params_parser.js", IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS}, - {"pdf/pdf_scripting_api.js", IDR_PDF_PDF_SCRIPTING_API_JS}, - {"pdf/pdf_viewer_base.js", IDR_PDF_PDF_VIEWER_BASE_JS}, - {"pdf/pdf_viewer_shared_style.js", IDR_PDF_PDF_VIEWER_SHARED_STYLE_JS}, - {"pdf/pdf_viewer_utils.js", IDR_PDF_PDF_VIEWER_UTILS_JS}, - {"pdf/toolbar_manager.js", IDR_PDF_TOOLBAR_MANAGER_JS}, - {"pdf/viewport.js", IDR_PDF_VIEWPORT_JS}, - {"pdf/viewport_scroller.js", IDR_PDF_VIEWPORT_SCROLLER_JS}, - {"pdf/zoom_manager.js", IDR_PDF_ZOOM_MANAGER_JS}, - }; - webui::AddResourcePathsBulk(source, kPdfResources); - source->SetRequestFilter(base::BindRepeating(&ShouldHandleRequestCallback), base::BindRepeating(&HandleRequestCallback)); source->OverrideContentSecurityPolicy( @@ -436,7 +447,7 @@ content::WebUIDataSource* CreatePrintPreviewUISource(Profile* profile) { content::WebUIDataSource::Create(chrome::kChromeUIPrintHost); webui::SetupWebUIDataSource( source, - base::make_span(kPrintPreviewResources, kPrintPreviewResourcesSize), "", + base::make_span(kPrintPreviewResources, kPrintPreviewResourcesSize), IDR_PRINT_PREVIEW_PRINT_PREVIEW_HTML); AddPrintPreviewStrings(source); SetupPrintPreviewPlugin(source); @@ -447,6 +458,9 @@ content::WebUIDataSource* CreatePrintPreviewUISource(Profile* profile) { PrintPreviewHandler* CreatePrintPreviewHandlers(content::WebUI* web_ui) { auto handler = std::make_unique<PrintPreviewHandler>(); PrintPreviewHandler* handler_ptr = handler.get(); +#if BUILDFLAG(IS_CHROMEOS_ASH) + web_ui->AddMessageHandler(std::make_unique<PrintPreviewHandlerChromeOS>()); +#endif web_ui->AddMessageHandler(std::move(handler)); web_ui->AddMessageHandler(std::make_unique<MetricsHandler>()); @@ -456,7 +470,7 @@ PrintPreviewHandler* CreatePrintPreviewHandlers(content::WebUI* web_ui) { "printPreviewPageSummaryLabel", IDS_PRINT_PREVIEW_PAGE_SUMMARY_LABEL); plural_string_handler->AddLocalizedString( "printPreviewSheetSummaryLabel", IDS_PRINT_PREVIEW_SHEET_SUMMARY_LABEL); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) plural_string_handler->AddLocalizedString( "sheetsLimitErrorMessage", IDS_PRINT_PREVIEW_SHEETS_LIMIT_ERROR_MESSAGE); #endif @@ -564,8 +578,197 @@ void PrintPreviewUI::ClearAllPreviewData() { PrintPreviewDataService::GetInstance()->RemoveEntry(*id_); } -void PrintPreviewUI::SetInitiatorTitle( - const base::string16& job_title) { +void PrintPreviewUI::NotifyUIPreviewPageReady( + uint32_t page_number, + int request_id, + scoped_refptr<base::RefCountedMemory> data_bytes) { + if (!data_bytes || !data_bytes->size()) + return; + + // Don't bother notifying the UI if this request has been cancelled already. + if (ShouldCancelRequest(id_, request_id)) + return; + + DCHECK_NE(page_number, kInvalidPageIndex); + SetPrintPreviewDataForIndex(base::checked_cast<int>(page_number), + std::move(data_bytes)); + + if (g_test_delegate) + g_test_delegate->DidRenderPreviewPage(web_ui()->GetWebContents()); + handler_->SendPagePreviewReady(base::checked_cast<int>(page_number), *id_, + request_id); +} + +void PrintPreviewUI::NotifyUIPreviewDocumentReady( + int request_id, + scoped_refptr<base::RefCountedMemory> data_bytes) { + if (!data_bytes || !data_bytes->size()) + return; + + // Don't bother notifying the UI if this request has been cancelled already. + if (ShouldCancelRequest(id_, request_id)) + return; + + if (!initial_preview_start_time_.is_null()) { + base::UmaHistogramTimes( + "PrintPreview.InitialDisplayTime", + base::TimeTicks::Now() - initial_preview_start_time_); + initial_preview_start_time_ = base::TimeTicks(); + } + + SetPrintPreviewDataForIndex(COMPLETE_PREVIEW_DOCUMENT_INDEX, + std::move(data_bytes)); + handler_->OnPrintPreviewReady(*id_, request_id); +} + +void PrintPreviewUI::OnCompositePdfPageDone( + uint32_t page_number, + int document_cookie, + int32_t request_id, + mojom::PrintCompositor::Status status, + base::ReadOnlySharedMemoryRegion region) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + if (ShouldCancelRequest(id_, request_id)) + return; + + if (status != mojom::PrintCompositor::Status::kSuccess) { + DLOG(ERROR) << "Compositing pdf failed with error " << status; + OnPrintPreviewFailed(request_id); + return; + } + + if (pages_per_sheet_ == 1) { + NotifyUIPreviewPageReady( + page_number, request_id, + base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region)); + } else { + AddPdfPageForNupConversion(std::move(region)); + uint32_t current_page_index = GetPageToNupConvertIndex(page_number); + if (current_page_index == kInvalidPageIndex) + return; + + if (((current_page_index + 1) % pages_per_sheet_) == 0 || + LastPageComposited(page_number)) { + uint32_t new_page_number = + base::checked_cast<uint32_t>(current_page_index / pages_per_sheet_); + DCHECK_NE(new_page_number, kInvalidPageIndex); + std::vector<base::ReadOnlySharedMemoryRegion> pdf_page_regions = + TakePagesForNupConvert(); + + gfx::Rect printable_rect = + PageSetup::GetSymmetricalPrintableArea(page_size(), printable_area()); + if (printable_rect.IsEmpty()) + return; + + WebContents* web_contents = GetInitiator(web_ui()); + if (!web_contents) + return; + + auto* client = PdfNupConverterClient::FromWebContents(web_contents); + DCHECK(client); + client->DoNupPdfConvert( + document_cookie, pages_per_sheet_, page_size(), printable_rect, + std::move(pdf_page_regions), + mojo::WrapCallbackWithDefaultInvokeIfNotRun( + base::BindOnce(&PrintPreviewUI::OnNupPdfConvertDone, + weak_ptr_factory_.GetWeakPtr(), new_page_number, + request_id), + mojom::PdfNupConverter::Status::CONVERSION_FAILURE, + base::ReadOnlySharedMemoryRegion())); + } + } +} + +void PrintPreviewUI::OnNupPdfConvertDone( + uint32_t page_number, + int32_t request_id, + mojom::PdfNupConverter::Status status, + base::ReadOnlySharedMemoryRegion region) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (status != mojom::PdfNupConverter::Status::SUCCESS) { + DLOG(ERROR) << "Nup pdf page conversion failed with error " << status; + OnPrintPreviewFailed(request_id); + return; + } + + NotifyUIPreviewPageReady( + page_number, request_id, + base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region)); +} + +void PrintPreviewUI::OnCompositeToPdfDone( + int document_cookie, + int32_t request_id, + mojom::PrintCompositor::Status status, + base::ReadOnlySharedMemoryRegion region) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + if (ShouldCancelRequest(id_, request_id)) + return; + + if (status != mojom::PrintCompositor::Status::kSuccess) { + DLOG(ERROR) << "Completion of document to pdf failed with error " << status; + OnPrintPreviewFailed(request_id); + return; + } + + if (pages_per_sheet_ == 1) { + NotifyUIPreviewDocumentReady( + request_id, + base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region)); + } else { + WebContents* web_contents = GetInitiator(web_ui()); + if (!web_contents) + return; + + auto* client = PdfNupConverterClient::FromWebContents(web_contents); + DCHECK(client); + + gfx::Rect printable_rect = + PageSetup::GetSymmetricalPrintableArea(page_size_, printable_area_); + if (printable_rect.IsEmpty()) + return; + + client->DoNupPdfDocumentConvert( + document_cookie, pages_per_sheet_, page_size_, printable_rect, + std::move(region), + mojo::WrapCallbackWithDefaultInvokeIfNotRun( + base::BindOnce(&PrintPreviewUI::OnNupPdfDocumentConvertDone, + weak_ptr_factory_.GetWeakPtr(), request_id), + mojom::PdfNupConverter::Status::CONVERSION_FAILURE, + base::ReadOnlySharedMemoryRegion())); + } +} + +void PrintPreviewUI::OnPrepareForDocumentToPdfDone( + int32_t request_id, + mojom::PrintCompositor::Status status) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + if (ShouldCancelRequest(id_, request_id)) + return; + + if (status != mojom::PrintCompositor::Status::kSuccess) + OnPrintPreviewFailed(request_id); +} + +void PrintPreviewUI::OnNupPdfDocumentConvertDone( + int32_t request_id, + mojom::PdfNupConverter::Status status, + base::ReadOnlySharedMemoryRegion region) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (status != mojom::PdfNupConverter::Status::SUCCESS) { + DLOG(ERROR) << "Nup pdf document convert failed with error " << status; + OnPrintPreviewFailed(request_id); + return; + } + NotifyUIPreviewDocumentReady( + request_id, + base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region)); +} + +void PrintPreviewUI::SetInitiatorTitle(const base::string16& job_title) { initiator_title_ = job_title; } @@ -597,7 +800,7 @@ void PrintPreviewUI::AddPdfPageForNupConversion( // static void PrintPreviewUI::SetInitialParams( content::WebContents* print_preview_dialog, - const PrintHostMsg_RequestPrintPreview_Params& params) { + const mojom::RequestPrintPreviewParams& params) { if (!print_preview_dialog || !print_preview_dialog->GetWebUI()) return; PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>( @@ -610,11 +813,15 @@ void PrintPreviewUI::SetInitialParams( } // static -bool PrintPreviewUI::ShouldCancelRequest(const mojom::PreviewIds& ids) { +bool PrintPreviewUI::ShouldCancelRequest( + const base::Optional<int32_t>& preview_ui_id, + int request_id) { + if (!preview_ui_id) + return true; int current_id = -1; - if (!g_print_preview_request_id_map.Get().Get(ids.ui_id, ¤t_id)) + if (!g_print_preview_request_id_map.Get().Get(*preview_ui_id, ¤t_id)) return true; - return ids.request_id != current_id; + return request_id != current_id; } base::Optional<int32_t> PrintPreviewUI::GetIDForPrintPreviewUI() const { @@ -656,51 +863,80 @@ void PrintPreviewUI::OnPrintPreviewRequest(int request_id) { g_print_preview_request_id_map.Get().Set(*id_, request_id); } -void PrintPreviewUI::OnDidStartPreview( - const mojom::DidStartPreviewParams& params, - int request_id) { - DCHECK_GT(params.page_count, 0u); - DCHECK_LE(params.page_count, kMaxPageCount); - DCHECK(!params.pages_to_render.empty()); +void PrintPreviewUI::DidStartPreview(mojom::DidStartPreviewParamsPtr params, + int32_t request_id) { + if (params->page_count == 0 || params->page_count > kMaxPageCount || + params->pages_to_render.empty()) { + receiver_.ReportBadMessage(kInvalidArgsForDidStartPreview); + return; + } - pages_to_render_ = params.pages_to_render; + for (uint32_t page_number : params->pages_to_render) { + if (!IsValidPageNumber(page_number, params->page_count)) { + receiver_.ReportBadMessage(kInvalidArgsForDidStartPreview); + return; + } + } + + if (!printing::NupParameters::IsSupported(params->pages_per_sheet)) { + receiver_.ReportBadMessage(kInvalidArgsForDidStartPreview); + return; + } + + if (params->page_size.IsEmpty()) { + receiver_.ReportBadMessage(kInvalidArgsForDidStartPreview); + return; + } + + pages_to_render_ = params->pages_to_render; pages_to_render_index_ = 0; - pages_per_sheet_ = params.pages_per_sheet; - page_size_ = params.page_size; + pages_per_sheet_ = params->pages_per_sheet; + page_size_ = params->page_size; ClearAllPreviewData(); if (g_test_delegate) - g_test_delegate->DidGetPreviewPageCount(params.page_count); - handler_->SendPageCountReady(base::checked_cast<int>(params.page_count), - params.fit_to_page_scaling, request_id); + g_test_delegate->DidGetPreviewPageCount(params->page_count); + handler_->SendPageCountReady(base::checked_cast<int>(params->page_count), + params->fit_to_page_scaling, request_id); } -void PrintPreviewUI::OnDidGetDefaultPageLayout( - const mojom::PageSizeMargins& page_layout, - const gfx::Rect& printable_area, +void PrintPreviewUI::DidGetDefaultPageLayout( + mojom::PageSizeMarginsPtr page_layout_in_points, + const gfx::Rect& printable_area_in_points, bool has_custom_page_size_style, - int request_id) { - if (page_layout.margin_top < 0 || page_layout.margin_left < 0 || - page_layout.margin_bottom < 0 || page_layout.margin_right < 0 || - page_layout.content_width < 0 || page_layout.content_height < 0 || - printable_area.width() <= 0 || printable_area.height() <= 0) { + int32_t request_id) { + if (printable_area_in_points.width() <= 0 || + printable_area_in_points.height() <= 0) { NOTREACHED(); return; } - // Save printable_area information for N-up conversion. - printable_area_ = printable_area; + // Save printable_area_in_points information for N-up conversion. + printable_area_ = printable_area_in_points; + + if (page_layout_in_points->margin_top < 0 || + page_layout_in_points->margin_left < 0 || + page_layout_in_points->margin_bottom < 0 || + page_layout_in_points->margin_right < 0 || + page_layout_in_points->content_width < 0 || + page_layout_in_points->content_height < 0) { + // Even though it early returns here, it doesn't block printing the page. + return; + } base::DictionaryValue layout; - layout.SetDouble(kSettingMarginTop, page_layout.margin_top); - layout.SetDouble(kSettingMarginLeft, page_layout.margin_left); - layout.SetDouble(kSettingMarginBottom, page_layout.margin_bottom); - layout.SetDouble(kSettingMarginRight, page_layout.margin_right); - layout.SetDouble(kSettingContentWidth, page_layout.content_width); - layout.SetDouble(kSettingContentHeight, page_layout.content_height); - layout.SetInteger(kSettingPrintableAreaX, printable_area.x()); - layout.SetInteger(kSettingPrintableAreaY, printable_area.y()); - layout.SetInteger(kSettingPrintableAreaWidth, printable_area.width()); - layout.SetInteger(kSettingPrintableAreaHeight, printable_area.height()); + layout.SetDouble(kSettingMarginTop, page_layout_in_points->margin_top); + layout.SetDouble(kSettingMarginLeft, page_layout_in_points->margin_left); + layout.SetDouble(kSettingMarginBottom, page_layout_in_points->margin_bottom); + layout.SetDouble(kSettingMarginRight, page_layout_in_points->margin_right); + layout.SetDouble(kSettingContentWidth, page_layout_in_points->content_width); + layout.SetDouble(kSettingContentHeight, + page_layout_in_points->content_height); + layout.SetInteger(kSettingPrintableAreaX, printable_area_in_points.x()); + layout.SetInteger(kSettingPrintableAreaY, printable_area_in_points.y()); + layout.SetInteger(kSettingPrintableAreaWidth, + printable_area_in_points.width()); + layout.SetInteger(kSettingPrintableAreaHeight, + printable_area_in_points.height()); handler_->SendPageLayoutReady(layout, has_custom_page_size_style, request_id); } @@ -713,36 +949,6 @@ bool PrintPreviewUI::OnPendingPreviewPage(uint32_t page_number) { return matched; } -void PrintPreviewUI::OnDidPreviewPage( - uint32_t page_number, - scoped_refptr<base::RefCountedMemory> data, - int preview_request_id) { - DCHECK_NE(page_number, kInvalidPageIndex); - - SetPrintPreviewDataForIndex(base::checked_cast<int>(page_number), - std::move(data)); - - if (g_test_delegate) - g_test_delegate->DidRenderPreviewPage(web_ui()->GetWebContents()); - handler_->SendPagePreviewReady(base::checked_cast<int>(page_number), *id_, - preview_request_id); -} - -void PrintPreviewUI::OnPreviewDataIsAvailable( - scoped_refptr<base::RefCountedMemory> data, - int preview_request_id) { - if (!initial_preview_start_time_.is_null()) { - base::UmaHistogramTimes( - "PrintPreview.InitialDisplayTime", - base::TimeTicks::Now() - initial_preview_start_time_); - initial_preview_start_time_ = base::TimeTicks(); - } - - SetPrintPreviewDataForIndex(COMPLETE_PREVIEW_DOCUMENT_INDEX, std::move(data)); - - handler_->OnPrintPreviewReady(*id_, preview_request_id); -} - void PrintPreviewUI::OnCancelPendingPreviewRequest() { g_print_preview_request_id_map.Get().Set(*id_, -1); } @@ -770,7 +976,6 @@ void PrintPreviewUI::OnHidePreviewDialog() { } void PrintPreviewUI::OnClosePrintPreviewDialog() { - receiver_.reset(); if (dialog_closed_) return; dialog_closed_ = true; @@ -790,6 +995,143 @@ void PrintPreviewUI::SetOptionsFromDocument( params->duplex, request_id); } +void PrintPreviewUI::DidPrepareDocumentForPreview(int32_t document_cookie, + int32_t request_id) { + // Determine if document composition from individual pages with the print + // compositor is the desired configuration. Issue a preparation call to the + // PrintCompositeClient if that hasn't been done yet. Otherwise, return early. + if (!ShouldUseCompositor(this)) + return; + + WebContents* web_contents = GetInitiator(web_ui()); + if (!web_contents) + return; + + // For case of print preview, page metafile is used to composite into + // the document PDF at same time. Need to indicate that this scenario + // is at play for the compositor. + auto* client = PrintCompositeClient::FromWebContents(web_contents); + DCHECK(client); + if (client->GetIsDocumentConcurrentlyComposited(document_cookie)) + return; + + content::RenderFrameHost* render_frame_host = + PrintViewManager::FromWebContents(web_contents)->print_preview_rfh(); + // |render_frame_host| could be null when the print preview dialog is closed. + if (!render_frame_host) + return; + + client->DoPrepareForDocumentToPdf( + document_cookie, render_frame_host, + mojo::WrapCallbackWithDefaultInvokeIfNotRun( + base::BindOnce(&PrintPreviewUI::OnPrepareForDocumentToPdfDone, + weak_ptr_factory_.GetWeakPtr(), request_id), + mojom::PrintCompositor::Status::kCompositingFailure)); +} + +void PrintPreviewUI::DidPreviewPage(mojom::DidPreviewPageParamsPtr params, + int32_t request_id) { + uint32_t page_number = params->page_number; + const mojom::DidPrintContentParams& content = *params->content; + if (page_number == kInvalidPageIndex || + !content.metafile_data_region.IsValid()) { + return; + } + + if (!OnPendingPreviewPage(page_number)) { + receiver_.ReportBadMessage(kInvalidPageNumberForDidPreviewPage); + return; + } + + if (ShouldUseCompositor(this)) { + // Don't bother compositing if this request has been cancelled already. + if (ShouldCancelRequest(id_, request_id)) + return; + + WebContents* web_contents = GetInitiator(web_ui()); + if (!web_contents) + return; + + auto* client = PrintCompositeClient::FromWebContents(web_contents); + DCHECK(client); + + content::RenderFrameHost* render_frame_host = + PrintViewManager::FromWebContents(web_contents)->print_preview_rfh(); + // |render_frame_host| could be null when the print preview dialog is + // closed. + if (!render_frame_host) + return; + + // Use utility process to convert skia metafile to pdf. + client->DoCompositePageToPdf( + params->document_cookie, render_frame_host, content, + mojo::WrapCallbackWithDefaultInvokeIfNotRun( + base::BindOnce(&PrintPreviewUI::OnCompositePdfPageDone, + weak_ptr_factory_.GetWeakPtr(), page_number, + params->document_cookie, request_id), + mojom::PrintCompositor::Status::kCompositingFailure, + base::ReadOnlySharedMemoryRegion())); + } else { + NotifyUIPreviewPageReady( + page_number, request_id, + base::RefCountedSharedMemoryMapping::CreateFromWholeRegion( + content.metafile_data_region)); + } +} + +void PrintPreviewUI::MetafileReadyForPrinting( + mojom::DidPreviewDocumentParamsPtr params, + int32_t request_id) { + // Always try to stop the worker. + StopWorker(params->document_cookie); + + const bool composite_document_using_individual_pages = + ShouldUseCompositor(this); + const base::ReadOnlySharedMemoryRegion& metafile = + params->content->metafile_data_region; + + // When the Print Compositor is active, the print document is composed from + // the individual pages, so |metafile| should be invalid. + // When it is inactive, the print document is composed from |metafile|. + // So if this comparison succeeds, that means the renderer sent bad data. + if (composite_document_using_individual_pages == metafile.IsValid()) + return; + + if (params->expected_pages_count == 0) { + receiver_.ReportBadMessage(kInvalidPageCountForMetafileReadyForPrinting); + return; + } + + if (composite_document_using_individual_pages) { + // Don't bother compositing if this request has been cancelled already. + if (ShouldCancelRequest(id_, request_id)) + return; + + auto callback = base::BindOnce(&PrintPreviewUI::OnCompositeToPdfDone, + weak_ptr_factory_.GetWeakPtr(), + params->document_cookie, request_id); + + WebContents* web_contents = GetInitiator(web_ui()); + if (!web_contents) + return; + + // Page metafile is used to composite into the document at same time. + // Need to provide particulars of how many pages are required before + // document will be completed. + auto* client = PrintCompositeClient::FromWebContents(web_contents); + client->DoCompleteDocumentToPdf( + params->document_cookie, params->expected_pages_count, + mojo::WrapCallbackWithDefaultInvokeIfNotRun( + std::move(callback), + mojom::PrintCompositor::Status::kCompositingFailure, + base::ReadOnlySharedMemoryRegion())); + } else { + NotifyUIPreviewDocumentReady( + request_id, + base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(metafile)); + } +} + void PrintPreviewUI::PrintPreviewFailed(int32_t document_cookie, int32_t request_id) { StopWorker(document_cookie); diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h index d0e9b1fc8b1..a131d53bad6 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h @@ -16,27 +16,24 @@ #include "base/macros.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/time/time.h" #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" +#include "chrome/services/printing/public/mojom/pdf_nup_converter.mojom.h" #include "components/printing/common/print.mojom.h" +#include "components/services/print_compositor/public/mojom/print_compositor.mojom.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "printing/mojom/print.mojom-forward.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" -struct PrintHostMsg_RequestPrintPreview_Params; - namespace base { class DictionaryValue; class FilePath; class RefCountedMemory; } -namespace gfx { -class Rect; -} - namespace printing { class PrintPreviewHandler; @@ -59,11 +56,23 @@ class PrintPreviewUI : public ConstrainedWebDialogUI, // printing::mojo::PrintPreviewUI: void SetOptionsFromDocument(const mojom::OptionsFromDocumentParamsPtr params, int32_t request_id) override; + void DidPrepareDocumentForPreview(int32_t document_cookie, + int32_t request_id) override; + void DidPreviewPage(mojom::DidPreviewPageParamsPtr params, + int32_t request_id) override; + void MetafileReadyForPrinting(mojom::DidPreviewDocumentParamsPtr params, + int32_t request_id) override; void PrintPreviewFailed(int32_t document_cookie, int32_t request_id) override; void PrintPreviewCancelled(int32_t document_cookie, int32_t request_id) override; void PrinterSettingsInvalid(int32_t document_cookie, int32_t request_id) override; + void DidGetDefaultPageLayout(mojom::PageSizeMarginsPtr page_layout_in_points, + const gfx::Rect& printable_area_in_points, + bool has_custom_page_size_style, + int32_t request_id) override; + void DidStartPreview(mojom::DidStartPreviewParamsPtr params, + int32_t request_id) override; bool IsBound() const; @@ -88,6 +97,8 @@ class PrintPreviewUI : public ConstrainedWebDialogUI, const gfx::Size& page_size() const { return page_size_; } + PrintPreviewHandler* handler() const { return handler_; } + // Returns true if |page_number| is the last page in |pages_to_render_|. // |page_number| is a 0-based number. bool LastPageComposited(uint32_t page_number) const; @@ -124,14 +135,14 @@ class PrintPreviewUI : public ConstrainedWebDialogUI, int* page_index); // Set initial settings for PrintPreviewUI. - static void SetInitialParams( - content::WebContents* print_preview_dialog, - const PrintHostMsg_RequestPrintPreview_Params& params); + static void SetInitialParams(content::WebContents* print_preview_dialog, + const mojom::RequestPrintPreviewParams& params); // Determines whether to cancel a print preview request based on the request - // and UI ids in |ids|. + // id. // Can be called from any thread. - static bool ShouldCancelRequest(const mojom::PreviewIds& ids); + static bool ShouldCancelRequest(const base::Optional<int32_t>& preview_ui_id, + int request_id); // Returns an id to uniquely identify this PrintPreviewUI. base::Optional<int32_t> GetIDForPrintPreviewUI() const; @@ -139,33 +150,11 @@ class PrintPreviewUI : public ConstrainedWebDialogUI, // Notifies the Web UI of a print preview request with |request_id|. virtual void OnPrintPreviewRequest(int request_id); - // Notifies the Web UI about the properties of the request preview. - void OnDidStartPreview(const mojom::DidStartPreviewParams& params, - int request_id); - - // Notifies the Web UI of the default page layout according to the currently - // selected printer and page size. - void OnDidGetDefaultPageLayout(const mojom::PageSizeMargins& page_layout, - const gfx::Rect& printable_area, - bool has_custom_page_size_style, - int request_id); - // Notifies the Web UI that the 0-based page |page_number| rendering is being // processed and an OnPendingPreviewPage() call is imminent. Returns whether // |page_number| is the expected page. bool OnPendingPreviewPage(uint32_t page_number); - // Notifies the Web UI that the 0-based page |page_number| has been rendered. - // |preview_request_id| indicates which request resulted in this response. - void OnDidPreviewPage(uint32_t page_number, - scoped_refptr<base::RefCountedMemory> data, - int preview_request_id); - - // Notifies the Web UI renderer that preview data is available. - // |preview_request_id| indicates which request resulted in this response. - void OnPreviewDataIsAvailable(scoped_refptr<base::RefCountedMemory> data, - int preview_request_id); - // Notifies the Web UI that the print preview failed to render for the request // with id = |request_id|. void OnPrintPreviewFailed(int request_id); @@ -247,6 +236,39 @@ class PrintPreviewUI : public ConstrainedWebDialogUI, // Clear the existing print preview data. void ClearAllPreviewData(); + // Notifies the Web UI that the 0-based page |page_number| has been rendered. + // |request_id| indicates which request resulted in this response. + void NotifyUIPreviewPageReady( + uint32_t page_number, + int request_id, + scoped_refptr<base::RefCountedMemory> data_bytes); + + // Notifies the Web UI renderer that preview data is available. |request_id| + // indicates which request resulted in this response. + void NotifyUIPreviewDocumentReady( + int request_id, + scoped_refptr<base::RefCountedMemory> data_bytes); + + // Callbacks for print compositor client. + void OnPrepareForDocumentToPdfDone(int32_t request_id, + mojom::PrintCompositor::Status status); + void OnCompositePdfPageDone(uint32_t page_number, + int32_t document_cookie, + int32_t request_id, + mojom::PrintCompositor::Status status, + base::ReadOnlySharedMemoryRegion region); + void OnNupPdfConvertDone(uint32_t page_number, + int32_t request_id, + mojom::PdfNupConverter::Status status, + base::ReadOnlySharedMemoryRegion region); + void OnNupPdfDocumentConvertDone(int32_t request_id, + mojom::PdfNupConverter::Status status, + base::ReadOnlySharedMemoryRegion region); + void OnCompositeToPdfDone(int document_cookie, + int32_t request_id, + mojom::PrintCompositor::Status status, + base::ReadOnlySharedMemoryRegion region); + base::TimeTicks initial_preview_start_time_; // The unique ID for this class instance. Stored here to avoid calling @@ -298,6 +320,8 @@ class PrintPreviewUI : public ConstrainedWebDialogUI, mojo::AssociatedReceiver<mojom::PrintPreviewUI> receiver_{this}; + base::WeakPtrFactory<PrintPreviewUI> weak_ptr_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(PrintPreviewUI); }; diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_browsertest.cc index 78e8255f3e7..1052355c78e 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_browsertest.cc @@ -4,6 +4,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/task_manager/task_manager_browsertest_util.h" @@ -58,7 +59,7 @@ IN_PROC_BROWSER_TEST_F(PrintPreviewBrowserTest, PrintCommands) { ASSERT_TRUE(chrome::IsCommandEnabled(browser(), IDC_PRINT)); -#if BUILDFLAG(ENABLE_PRINTING) && !defined(OS_CHROMEOS) +#if BUILDFLAG(ENABLE_PRINTING) && !BUILDFLAG(IS_CHROMEOS_ASH) // This is analagous to ENABLE_BASIC_PRINT_DIALOG but helps to verify // that it is defined as expected. bool is_basic_print_expected = true; diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc index d09c6609e5c..48c70b6b802 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc @@ -17,7 +17,6 @@ #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "components/prefs/pref_service.h" -#include "components/printing/common/print_messages.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" #include "content/public/browser/plugin_service.h" #include "content/public/browser/site_instance.h" @@ -190,23 +189,26 @@ TEST_F(PrintPreviewUIUnitTest, ShouldCancelRequest) { ASSERT_TRUE(preview_ui); preview_ui->SetPreviewUIId(); - // Test with invalid UI ID. - const int32_t kInvalidId = -5; - EXPECT_TRUE(preview_ui->ShouldCancelRequest({0, kInvalidId})); + // Test the initial state. + EXPECT_TRUE(PrintPreviewUI::ShouldCancelRequest( + *preview_ui->GetIDForPrintPreviewUI(), 0)); const int kFirstRequestId = 1000; const int kSecondRequestId = 1001; - const int32_t preview_id = preview_ui->GetIDForPrintPreviewUI().value(); // Test with kFirstRequestId. preview_ui->OnPrintPreviewRequest(kFirstRequestId); - EXPECT_FALSE(preview_ui->ShouldCancelRequest({kFirstRequestId, preview_id})); - EXPECT_TRUE(preview_ui->ShouldCancelRequest({kSecondRequestId, preview_id})); + EXPECT_FALSE(PrintPreviewUI::ShouldCancelRequest( + *preview_ui->GetIDForPrintPreviewUI(), kFirstRequestId)); + EXPECT_TRUE(PrintPreviewUI::ShouldCancelRequest( + *preview_ui->GetIDForPrintPreviewUI(), kSecondRequestId)); // Test with kSecondRequestId. preview_ui->OnPrintPreviewRequest(kSecondRequestId); - EXPECT_TRUE(preview_ui->ShouldCancelRequest({kFirstRequestId, preview_id})); - EXPECT_FALSE(preview_ui->ShouldCancelRequest({kSecondRequestId, preview_id})); + EXPECT_TRUE(PrintPreviewUI::ShouldCancelRequest( + *preview_ui->GetIDForPrintPreviewUI(), kFirstRequestId)); + EXPECT_FALSE(PrintPreviewUI::ShouldCancelRequest( + *preview_ui->GetIDForPrintPreviewUI(), kSecondRequestId)); } TEST_F(PrintPreviewUIUnitTest, ParseDataPath) { diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_utils.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_utils.cc index c0bed875af9..24485b73494 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_utils.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_utils.cc @@ -10,19 +10,20 @@ #include <vector> #include "base/bind.h" +#include "base/containers/contains.h" #include "base/json/json_reader.h" #include "base/logging.h" #include "base/memory/ref_counted_memory.h" -#include "base/stl_util.h" #include "base/strings/string_piece.h" #include "base/threading/thread_restrictions.h" #include "base/values.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "chrome/browser/printing/print_preview_dialog_controller.h" #include "chrome/browser/printing/print_view_manager.h" #include "chrome/browser/ui/webui/print_preview/printer_handler.h" +#include "chrome/common/printing/printer_capabilities.h" #include "components/crash/core/common/crash_keys.h" -#include "components/printing/browser/printer_capabilities.h" #include "content/public/browser/render_frame_host.h" #include "printing/backend/print_backend_consts.h" #include "printing/page_range.h" @@ -56,12 +57,12 @@ void PrintersToValues(const PrinterList& printer_list, for (const auto& opt_it : printer.options) options->SetString(opt_it.first, opt_it.second); -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) printer_info->SetBoolean( kCUPSEnterprisePrinter, base::Contains(printer.options, kCUPSEnterprisePrinter) && printer.options.at(kCUPSEnterprisePrinter) == kValueTrue); -#endif // defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_CHROMEOS_ASH) printer_info->Set(kSettingPrinterOptions, std::move(options)); diff --git a/chromium/chrome/browser/ui/webui/print_preview/printer_handler.cc b/chromium/chrome/browser/ui/webui/print_preview/printer_handler.cc index 2b2a95282ee..e29f23e2e04 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/printer_handler.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/printer_handler.cc @@ -5,6 +5,7 @@ #include "chrome/browser/ui/webui/print_preview/printer_handler.h" #include "build/buildflag.h" +#include "build/chromeos_buildflags.h" #include "chrome/browser/ui/webui/print_preview/extension_printer_handler.h" #include "chrome/browser/ui/webui/print_preview/pdf_printer_handler.h" #include "chrome/common/buildflags.h" @@ -13,7 +14,7 @@ #include "chrome/browser/ui/webui/print_preview/privet_printer_handler.h" #endif -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) #include "chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h" #else #include "chrome/browser/ui/webui/print_preview/local_printer_handler_default.h" @@ -31,7 +32,7 @@ std::unique_ptr<PrinterHandler> PrinterHandler::CreateForExtensionPrinters( std::unique_ptr<PrinterHandler> PrinterHandler::CreateForLocalPrinters( content::WebContents* preview_web_contents, Profile* profile) { -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) return LocalPrinterHandlerChromeos::CreateDefault(profile, preview_web_contents); #else @@ -65,7 +66,7 @@ void PrinterHandler::StartGrantPrinterAccess(const std::string& printer_id, NOTREACHED(); } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) void PrinterHandler::StartGetEulaUrl(const std::string& destination_id, GetEulaUrlCallback callback) { NOTREACHED(); diff --git a/chromium/chrome/browser/ui/webui/print_preview/printer_handler.h b/chromium/chrome/browser/ui/webui/print_preview/printer_handler.h index 6fa82c3a521..f9a02da5d0e 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/printer_handler.h +++ b/chromium/chrome/browser/ui/webui/print_preview/printer_handler.h @@ -13,6 +13,7 @@ #include "base/memory/ref_counted_memory.h" #include "base/strings/string16.h" #include "base/values.h" +#include "build/chromeos_buildflags.h" #include "chrome/common/buildflags.h" namespace content { @@ -49,7 +50,7 @@ class PrinterHandler { using PrintCallback = base::OnceCallback<void(const base::Value& error)>; using GetPrinterInfoCallback = base::OnceCallback<void(const base::DictionaryValue& printer_info)>; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) using GetEulaUrlCallback = base::OnceCallback<void(const std::string& license)>; using PrinterStatusRequestCallback = @@ -117,7 +118,7 @@ class PrinterHandler { scoped_refptr<base::RefCountedMemory> print_data, PrintCallback callback) = 0; -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) // Starts getting the printer's PPD EULA URL with the provided destination ID. // |destination_id|: The ID of the printer. // |callback| should be called in response to the request. diff --git a/chromium/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc b/chromium/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc index 88a2448b5b4..d9f2085e753 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc @@ -253,7 +253,8 @@ void PrivetPrinterHandler::StartPrint( IdentityManagerFactory::GetForProfileIfExists(profile_); if (identity_manager) { privet_local_print_operation_->SetUsername( - identity_manager->GetPrimaryAccountInfo().email); + identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync) + .email); } privet_local_print_operation_->Start(); |