Transfer system print dialog settings to Print Backend service
Linux and macOS platforms are not yet able to display the system print dialog from the Print Backend service. In these cases the dialog is still invoked from the browser process. This requires that the user settings specified must be collected and then transferred to the Print Backend service so that the rest of the print pipeline can still be performed out-of-process. The nature of such data is platform specific. Encapsulate the data in a dictionary value for transfer to the service. Mojom validation ensures that the data passes at least basic expectations for the number and type of entries in the dictionary. Test: System print (Print Preview and direct) for both Linux and macOS Low-Coverage-Reason: https://crbug.com/1451540, https://crbug.com/1463045 Bug: 1477394 Change-Id: Id09823f10362f9aa00867d3d5cc10fc9706d56e5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4827824 Reviewed-by: Jayson Adams <shrike@chromium.org> Commit-Queue: Alan Screen <awscreen@chromium.org> Reviewed-by: Thomas Anderson <thomasanderson@chromium.org> Reviewed-by: Andy Phan <andyphan@chromium.org> Reviewed-by: Nasko Oskov <nasko@chromium.org> Cr-Commit-Position: refs/heads/main@{#1191626}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
0bf2971a54
commit
2750f09051
chrome
browser
services
printing
printing
buildflags
mojom
BUILD.gnprinting_context.mojomprinting_context_mojom_traits.ccprinting_context_mojom_traits.hprinting_context_mojom_traits_unittest.cc
print_dialog_linux_interface.hprint_settings.ccprint_settings.hprinting_context.ccprinting_context.hprinting_context_linux.ccprinting_context_mac.mmtest_printing_context.ccui/gtk
@ -12,9 +12,14 @@
|
||||
#include "base/values.h"
|
||||
#include "chrome/browser/printing/print_view_manager_common.h"
|
||||
#include "chrome/browser/ui/webui/print_preview/print_preview_handler.h"
|
||||
#include "printing/buildflags/buildflags.h"
|
||||
#include "printing/mojom/print.mojom.h"
|
||||
#include "printing/print_job_constants.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
#include "printing/printing_features.h"
|
||||
#endif
|
||||
|
||||
namespace printing::test {
|
||||
|
||||
const char kPrinterName[] = "DefaultPrinter";
|
||||
@ -110,6 +115,32 @@ std::unique_ptr<PrintSettings> MakeUserModifiedPrintSettings(
|
||||
std::unique_ptr<PrintSettings> settings =
|
||||
MakeDefaultPrintSettings(printer_name);
|
||||
settings->set_copies(kPrintSettingsCopies + 1);
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
if (features::kEnableOopPrintDriversJobPrint.Get()) {
|
||||
// Supply fake data to mimic what might be collected from the system print
|
||||
// dialog. Platform-specific since the fake data still has to be able to
|
||||
// pass mojom data validation.
|
||||
base::Value::Dict data;
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
data.Set(kMacSystemPrintDialogDataDestinationType, 2);
|
||||
data.Set(kMacSystemPrintDialogDataPageFormat,
|
||||
base::Value::BlobStorage({0xF1}));
|
||||
data.Set(kMacSystemPrintDialogDataPrintSettings,
|
||||
base::Value::BlobStorage({0xB2}));
|
||||
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
data.Set(kLinuxSystemPrintDialogDataPrinter, printer_name);
|
||||
data.Set(kLinuxSystemPrintDialogDataPrintSettings, "print-settings");
|
||||
data.Set(kLinuxSystemPrintDialogDataPageSetup, "page-setup");
|
||||
|
||||
#else
|
||||
#error "Missing fake system print dialog data for this platform."
|
||||
#endif
|
||||
|
||||
settings->set_system_print_dialog_data(std::move(data));
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ void PrinterQueryOop::OnDidUseDefaultSettings(
|
||||
} else {
|
||||
VLOG(1) << "Use default settings from service complete";
|
||||
result = mojom::ResultCode::kSuccess;
|
||||
printing_context()->ApplyPrintSettings(print_settings->get_settings());
|
||||
printing_context()->SetPrintSettings(print_settings->get_settings());
|
||||
}
|
||||
|
||||
InvokeSettingsCallback(std::move(callback), result);
|
||||
@ -92,7 +92,7 @@ void PrinterQueryOop::OnDidAskUserForSettings(
|
||||
if (print_settings->is_settings()) {
|
||||
VLOG(1) << "Ask user for settings from service complete";
|
||||
result = mojom::ResultCode::kSuccess;
|
||||
printing_context()->ApplyPrintSettings(print_settings->get_settings());
|
||||
printing_context()->SetPrintSettings(print_settings->get_settings());
|
||||
|
||||
// Use the same PrintBackendService for querying and printing, so that the
|
||||
// same device context can be used with both.
|
||||
@ -256,7 +256,7 @@ void PrinterQueryOop::OnDidUpdatePrintSettings(
|
||||
} else {
|
||||
VLOG(1) << "Update print settings via service complete for " << device_name;
|
||||
result = mojom::ResultCode::kSuccess;
|
||||
printing_context()->ApplyPrintSettings(print_settings->get_settings());
|
||||
printing_context()->SetPrintSettings(print_settings->get_settings());
|
||||
|
||||
if (query_with_ui_client_id_.has_value()) {
|
||||
// Use the same PrintBackendService for querying and printing, so that the
|
||||
|
@ -1734,15 +1734,8 @@ IN_PROC_BROWSER_TEST_P(SystemAccessProcessPrintBrowserTest,
|
||||
EXPECT_EQ(render_printed_document_result(), mojom::ResultCode::kSuccess);
|
||||
#endif
|
||||
EXPECT_EQ(document_done_result(), mojom::ResultCode::kSuccess);
|
||||
#if BUILDFLAG(ENABLE_OOP_BASIC_PRINT_DIALOG)
|
||||
EXPECT_EQ(*test::MakeUserModifiedPrintSettings("printer1"),
|
||||
*document_print_settings());
|
||||
#else
|
||||
// TODO(crbug.com/1414968): Update the expectation once system print
|
||||
// settings are properly reflected at start of job print.
|
||||
EXPECT_NE(*test::MakeUserModifiedPrintSettings("printer1"),
|
||||
*document_print_settings());
|
||||
#endif
|
||||
}
|
||||
EXPECT_EQ(error_dialog_shown_count(), 0u);
|
||||
EXPECT_EQ(print_job_destruction_count(), 1);
|
||||
@ -1830,16 +1823,12 @@ IN_PROC_BROWSER_TEST_F(SystemAccessProcessSandboxedServicePrintBrowserTest,
|
||||
#if BUILDFLAG(ENABLE_OOP_BASIC_PRINT_DIALOG)
|
||||
EXPECT_EQ(use_default_settings_result(), mojom::ResultCode::kSuccess);
|
||||
EXPECT_EQ(ask_user_for_settings_result(), mojom::ResultCode::kSuccess);
|
||||
EXPECT_EQ(*test::MakeUserModifiedPrintSettings("printer1"),
|
||||
*document_print_settings());
|
||||
#else
|
||||
EXPECT_TRUE(did_use_default_settings());
|
||||
EXPECT_TRUE(did_get_settings_with_ui());
|
||||
// TODO(crbug.com/1414968): Update the expectation once system print
|
||||
// settings are properly reflected at start of job print.
|
||||
EXPECT_NE(*test::MakeUserModifiedPrintSettings("printer1"),
|
||||
*document_print_settings());
|
||||
#endif
|
||||
EXPECT_EQ(*test::MakeUserModifiedPrintSettings("printer1"),
|
||||
*document_print_settings());
|
||||
EXPECT_EQ(start_printing_result(), mojom::ResultCode::kSuccess);
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// TODO(crbug.com/1008222) Include Windows coverage of
|
||||
|
@ -749,7 +749,7 @@ void PrintBackendServiceImpl::StartPrinting(
|
||||
#if !BUILDFLAG(ENABLE_OOP_BASIC_PRINT_DIALOG)
|
||||
if (settings) {
|
||||
// Apply the settings from the in-browser system dialog to the context.
|
||||
context_container->context->ApplyPrintSettings(*settings);
|
||||
context_container->context->SetPrintSettings(*settings);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -18,6 +18,7 @@ buildflag_header("buildflags") {
|
||||
"ENABLE_BASIC_PRINT_DIALOG=$enable_basic_print_dialog",
|
||||
"ENABLE_CONCURRENT_BASIC_PRINT_DIALOGS=$enable_concurrent_basic_print_dialogs",
|
||||
"ENABLE_OOP_BASIC_PRINT_DIALOG=$enable_oop_basic_print_dialog",
|
||||
"ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG=$enable_oop_printing_no_oop_basic_print_dialog",
|
||||
"ENABLE_OOP_PRINTING=$enable_oop_printing",
|
||||
"ENABLE_PRINT_CONTENT_ANALYSIS=$enable_print_content_analysis",
|
||||
"USE_CUPS=$use_cups",
|
||||
|
@ -60,6 +60,12 @@ declare_args() {
|
||||
# TODO(crbug.com/809738) Determine if Linux Wayland can be made to have a
|
||||
# system dialog be modal against an application window in the browser process.
|
||||
enable_oop_basic_print_dialog = enable_oop_printing && is_win
|
||||
|
||||
# Enables out-of-process print handling for platforms which support a system
|
||||
# print dialog but are unable to invoke that dialog from the Print Backend
|
||||
# service.
|
||||
enable_oop_printing_no_oop_basic_print_dialog =
|
||||
enable_oop_printing && (is_linux || is_mac)
|
||||
}
|
||||
|
||||
declare_args() {
|
||||
|
@ -25,8 +25,9 @@ mojom("mojom") {
|
||||
|
||||
if (enable_oop_printing) {
|
||||
mojom("printing_context") {
|
||||
enabled_features = []
|
||||
if (is_linux || is_chromeos) {
|
||||
enabled_features = [ "is_linux_or_chromeos" ]
|
||||
enabled_features += [ "is_linux_or_chromeos" ]
|
||||
}
|
||||
|
||||
sources = [ "printing_context.mojom" ]
|
||||
@ -37,6 +38,10 @@ if (enable_oop_printing) {
|
||||
"//ui/gfx/geometry/mojom",
|
||||
]
|
||||
|
||||
if (enable_oop_printing_no_oop_basic_print_dialog) {
|
||||
enabled_features += [ "enable_oop_printing_no_oop_basic_print_dialog" ]
|
||||
}
|
||||
|
||||
cpp_typemaps = [
|
||||
{
|
||||
types = [
|
||||
@ -60,6 +65,7 @@ if (enable_oop_printing) {
|
||||
traits_sources = [ "printing_context_mojom_traits.cc" ]
|
||||
traits_headers = [ "printing_context_mojom_traits.h" ]
|
||||
traits_deps = [
|
||||
"//base",
|
||||
"//mojo/public/mojom/base",
|
||||
"//printing",
|
||||
"//ui/gfx/geometry",
|
||||
|
@ -77,4 +77,7 @@ struct PrintSettings {
|
||||
string username;
|
||||
[EnableIf=is_chromeos]
|
||||
string pin_value;
|
||||
|
||||
[EnableIf=enable_oop_printing_no_oop_basic_print_dialog]
|
||||
mojo_base.mojom.DictionaryValue system_print_dialog_data;
|
||||
};
|
||||
|
@ -15,6 +15,10 @@
|
||||
#include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||
#include "mojo/public/mojom/base/values.mojom.h"
|
||||
#endif
|
||||
@ -176,6 +180,96 @@ bool StructTraits<
|
||||
out->set_pin_value(pin_value);
|
||||
#endif // BUILDFLAG(IS_CHROMEOS)
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
base::Value::Dict system_print_dialog_data;
|
||||
if (!data.ReadSystemPrintDialogData(&system_print_dialog_data)) {
|
||||
return false;
|
||||
}
|
||||
// If doing system print then a dialog invoked in-browser needs to provide
|
||||
// the settings that were specified. Such data is platform-specific.
|
||||
if (!system_print_dialog_data.empty()) {
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
// The dictionary must contain the destination type, page format, and
|
||||
// print settings.
|
||||
absl::optional<int> destination_type = system_print_dialog_data.FindInt(
|
||||
printing::kMacSystemPrintDialogDataDestinationType);
|
||||
if (!destination_type.has_value()) {
|
||||
return false;
|
||||
}
|
||||
const base::Value::BlobStorage* page_format =
|
||||
system_print_dialog_data.FindBlob(
|
||||
printing::kMacSystemPrintDialogDataPageFormat);
|
||||
if (!page_format || page_format->empty()) {
|
||||
return false;
|
||||
}
|
||||
const base::Value::BlobStorage* print_settings =
|
||||
system_print_dialog_data.FindBlob(
|
||||
printing::kMacSystemPrintDialogDataPrintSettings);
|
||||
if (!print_settings || print_settings->empty()) {
|
||||
return false;
|
||||
}
|
||||
size_t dictionary_entries = 3;
|
||||
|
||||
// Destination type must be uint16.
|
||||
if (!base::IsValueInRangeForNumericType<uint16_t>(*destination_type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Destination format and location are optional. If present, they must be
|
||||
// strings.
|
||||
base::Value* destination_format = system_print_dialog_data.Find(
|
||||
printing::kMacSystemPrintDialogDataDestinationFormat);
|
||||
if (destination_format) {
|
||||
if (!destination_format->is_string()) {
|
||||
return false;
|
||||
}
|
||||
++dictionary_entries;
|
||||
}
|
||||
base::Value* destination_location = system_print_dialog_data.Find(
|
||||
printing::kMacSystemPrintDialogDataDestinationLocation);
|
||||
if (destination_location) {
|
||||
if (!destination_location->is_string()) {
|
||||
return false;
|
||||
}
|
||||
++dictionary_entries;
|
||||
}
|
||||
|
||||
// There should not be any other keys present.
|
||||
if (system_print_dialog_data.size() != dictionary_entries) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
// The dictionary must contain three strings.
|
||||
base::Value* value = system_print_dialog_data.Find(
|
||||
printing::kLinuxSystemPrintDialogDataPrinter);
|
||||
if (!value || !value->is_string()) {
|
||||
return false;
|
||||
}
|
||||
value = system_print_dialog_data.Find(
|
||||
printing::kLinuxSystemPrintDialogDataPrintSettings);
|
||||
if (!value || !value->is_string()) {
|
||||
return false;
|
||||
}
|
||||
value = system_print_dialog_data.Find(
|
||||
printing::kLinuxSystemPrintDialogDataPageSetup);
|
||||
if (!value || !value->is_string()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// There should not be any other keys present.
|
||||
if (system_print_dialog_data.size() != 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
#error "System print dialog support not implemented for this platform."
|
||||
#endif
|
||||
}
|
||||
|
||||
out->set_system_print_dialog_data(std::move(system_print_dialog_data));
|
||||
#endif // BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,11 @@
|
||||
#include "printing/print_settings.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
#include "base/values.h"
|
||||
#include "mojo/public/cpp/base/values_mojom_traits.h"
|
||||
#endif
|
||||
|
||||
namespace mojo {
|
||||
|
||||
template <>
|
||||
@ -180,6 +185,13 @@ struct StructTraits<printing::mojom::PrintSettingsDataView,
|
||||
}
|
||||
#endif // BUILDFLAG(IS_CHROMEOS)
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
static const base::Value::Dict& system_print_dialog_data(
|
||||
const printing::PrintSettings& s) {
|
||||
return s.system_print_dialog_data();
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool Read(printing::mojom::PrintSettingsDataView data,
|
||||
printing::PrintSettings* out);
|
||||
};
|
||||
|
@ -60,6 +60,38 @@ PrintSettings::RequestedMedia GenerateSampleRequestedMedia() {
|
||||
return media;
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
base::Value::Dict GenerateSampleSystemPrintDialogData(
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
bool include_optional_data
|
||||
#endif
|
||||
) {
|
||||
base::Value::Dict data;
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
data.Set(kMacSystemPrintDialogDataDestinationType, 4);
|
||||
data.Set(kMacSystemPrintDialogDataPageFormat,
|
||||
base::Value::BlobStorage({0xA0, 0xA1, 0xA2}));
|
||||
data.Set(kMacSystemPrintDialogDataPrintSettings,
|
||||
base::Value::BlobStorage({0x00, 0x01}));
|
||||
if (include_optional_data) {
|
||||
data.Set(kMacSystemPrintDialogDataDestinationFormat, "application/pdf");
|
||||
data.Set(kMacSystemPrintDialogDataDestinationLocation, "/foo/bar.pdf");
|
||||
}
|
||||
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
data.Set(kLinuxSystemPrintDialogDataPrinter, "printer-name");
|
||||
data.Set(kLinuxSystemPrintDialogDataPrintSettings, "print-settings-foo");
|
||||
data.Set(kLinuxSystemPrintDialogDataPageSetup, "page-setup-bar");
|
||||
|
||||
#else
|
||||
#error "System print dialog support not implemented for this platform."
|
||||
#endif
|
||||
|
||||
return data;
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
|
||||
// Support two possible sample `PrintSettings`, to ensure that certain fields
|
||||
// get definitively tested for coverage (e.g., booleans). Note that not all
|
||||
// fields need distinct values between the two. A key difference between them
|
||||
@ -621,4 +653,241 @@ TEST(PrintingContextMojomTraitsTest,
|
||||
}
|
||||
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
TEST(PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogData) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data, including all optional data.
|
||||
input.set_system_print_dialog_data(GenerateSampleSystemPrintDialogData(
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
/*include_optional_data=*/true
|
||||
#endif
|
||||
));
|
||||
|
||||
{
|
||||
PrintSettings output;
|
||||
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(
|
||||
input, output));
|
||||
|
||||
EXPECT_EQ(output.system_print_dialog_data(),
|
||||
input.system_print_dialog_data());
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
// Generate some system print dialog data, excluding optional data
|
||||
input.set_system_print_dialog_data(
|
||||
GenerateSampleSystemPrintDialogData(/*include_optional_data=*/false));
|
||||
|
||||
{
|
||||
PrintSettings output;
|
||||
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(
|
||||
input, output));
|
||||
|
||||
EXPECT_EQ(output.system_print_dialog_data(),
|
||||
input.system_print_dialog_data());
|
||||
}
|
||||
#endif // BUILDFLAG(IS_MAC)
|
||||
}
|
||||
|
||||
TEST(PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogDataInvalid) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data which is invalid.
|
||||
base::Value::Dict data;
|
||||
data.Set("foo", "bar");
|
||||
input.set_system_print_dialog_data(std::move(data));
|
||||
|
||||
PrintSettings output;
|
||||
EXPECT_FALSE(
|
||||
mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(input, output));
|
||||
}
|
||||
|
||||
TEST(PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogDataExtraKey) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data.
|
||||
base::Value::Dict data = GenerateSampleSystemPrintDialogData(
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
/*include_optional_data=*/true
|
||||
#endif
|
||||
);
|
||||
|
||||
// Erroneously include an extra key/value pair.
|
||||
data.Set("foo", "bar");
|
||||
input.set_system_print_dialog_data(std::move(data));
|
||||
|
||||
PrintSettings output;
|
||||
EXPECT_FALSE(
|
||||
mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(input, output));
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
TEST(
|
||||
PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogDataDestTypeOutOfRange) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data.
|
||||
base::Value::Dict data =
|
||||
GenerateSampleSystemPrintDialogData(/*include_optional_data=*/false);
|
||||
|
||||
// Override with out-of-range destination type.
|
||||
data.Set(kMacSystemPrintDialogDataDestinationType, 0x10000);
|
||||
input.set_system_print_dialog_data(std::move(data));
|
||||
|
||||
PrintSettings output;
|
||||
EXPECT_FALSE(
|
||||
mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(input, output));
|
||||
}
|
||||
|
||||
TEST(
|
||||
PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogDataDestTypeInvalidDataType) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data.
|
||||
base::Value::Dict data =
|
||||
GenerateSampleSystemPrintDialogData(/*include_optional_data=*/false);
|
||||
|
||||
// Override with invalid data type for destination type.
|
||||
data.Set(kMacSystemPrintDialogDataDestinationType, "supposed to be an int");
|
||||
input.set_system_print_dialog_data(std::move(data));
|
||||
|
||||
PrintSettings output;
|
||||
EXPECT_FALSE(
|
||||
mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(input, output));
|
||||
}
|
||||
|
||||
TEST(
|
||||
PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogPageFormatInvalidDataType) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data.
|
||||
base::Value::Dict data =
|
||||
GenerateSampleSystemPrintDialogData(/*include_optional_data=*/false);
|
||||
|
||||
// Override with invalid data type for page format.
|
||||
data.Set(kMacSystemPrintDialogDataPageFormat, "supposed to be a BlobStorage");
|
||||
input.set_system_print_dialog_data(std::move(data));
|
||||
|
||||
PrintSettings output;
|
||||
EXPECT_FALSE(
|
||||
mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(input, output));
|
||||
}
|
||||
|
||||
TEST(
|
||||
PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogPrintSettingsInvalidDataType) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data.
|
||||
base::Value::Dict data =
|
||||
GenerateSampleSystemPrintDialogData(/*include_optional_data=*/false);
|
||||
|
||||
// Override with invalid data type for print settings.
|
||||
data.Set(kMacSystemPrintDialogDataPrintSettings,
|
||||
"supposed to be a BlobStorage");
|
||||
input.set_system_print_dialog_data(std::move(data));
|
||||
|
||||
PrintSettings output;
|
||||
EXPECT_FALSE(
|
||||
mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(input, output));
|
||||
}
|
||||
|
||||
TEST(
|
||||
PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogDestinationFormatInvalidDataType) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data.
|
||||
base::Value::Dict data =
|
||||
GenerateSampleSystemPrintDialogData(/*include_optional_data=*/false);
|
||||
|
||||
// Override with invalid data type for destination format.
|
||||
data.Set(kMacSystemPrintDialogDataPageFormat, 0xBAD);
|
||||
input.set_system_print_dialog_data(std::move(data));
|
||||
|
||||
PrintSettings output;
|
||||
EXPECT_FALSE(
|
||||
mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(input, output));
|
||||
}
|
||||
|
||||
TEST(
|
||||
PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogDestinationLocationInvalidDataType) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data.
|
||||
base::Value::Dict data =
|
||||
GenerateSampleSystemPrintDialogData(/*include_optional_data=*/false);
|
||||
|
||||
// Override with invalid data type for destination location.
|
||||
data.Set(kMacSystemPrintDialogDataDestinationLocation, 0xBAD);
|
||||
input.set_system_print_dialog_data(std::move(data));
|
||||
|
||||
PrintSettings output;
|
||||
EXPECT_FALSE(
|
||||
mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(input, output));
|
||||
}
|
||||
#endif // BUILDFLAG(IS_MAC)
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
TEST(
|
||||
PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogPrinterInvalidDataType) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data.
|
||||
base::Value::Dict data = GenerateSampleSystemPrintDialogData();
|
||||
|
||||
// Override with invalid data type for printer.
|
||||
data.Set(kLinuxSystemPrintDialogDataPrinter, 0xBAD);
|
||||
input.set_system_print_dialog_data(std::move(data));
|
||||
|
||||
PrintSettings output;
|
||||
EXPECT_FALSE(
|
||||
mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(input, output));
|
||||
}
|
||||
|
||||
TEST(
|
||||
PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogPrintSettingsDataType) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data.
|
||||
base::Value::Dict data = GenerateSampleSystemPrintDialogData();
|
||||
|
||||
// Override with invalid data type for printer.
|
||||
data.Set(kLinuxSystemPrintDialogDataPrintSettings, 0xBAD);
|
||||
input.set_system_print_dialog_data(std::move(data));
|
||||
|
||||
PrintSettings output;
|
||||
EXPECT_FALSE(
|
||||
mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(input, output));
|
||||
}
|
||||
|
||||
TEST(
|
||||
PrintingContextMojomTraitsTest,
|
||||
TestSerializeAndDeserializePrintSettingsSystemPrintDialogPageSetupDataType) {
|
||||
PrintSettings input = GenerateSamplePrintSettingsDefaultMargins();
|
||||
|
||||
// Generate some system print dialog data.
|
||||
base::Value::Dict data = GenerateSampleSystemPrintDialogData();
|
||||
|
||||
// Override with invalid data type for printer.
|
||||
data.Set(kLinuxSystemPrintDialogDataPageSetup, 0xBAD);
|
||||
input.set_system_print_dialog_data(std::move(data));
|
||||
|
||||
PrintSettings output;
|
||||
EXPECT_FALSE(
|
||||
mojo::test::SerializeAndDeserialize<mojom::PrintSettings>(input, output));
|
||||
}
|
||||
#endif // BUILDFLAG(IS_LINUX)
|
||||
|
||||
#endif // BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
|
||||
} // namespace printing
|
||||
|
@ -28,6 +28,11 @@ class PrintDialogLinuxInterface {
|
||||
// system print dialog. E.g. for Print Preview.
|
||||
virtual void UpdateSettings(std::unique_ptr<PrintSettings> settings) = 0;
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
// Updates the dialog to use system print dialog settings saved in `settings`.
|
||||
virtual void LoadPrintSettings(const printing::PrintSettings& settings) = 0;
|
||||
#endif
|
||||
|
||||
// Shows the dialog and handles the response with `callback`. Only used when
|
||||
// printing with the native print dialog.
|
||||
virtual void ShowDialog(
|
||||
|
@ -331,6 +331,9 @@ PrintSettings& PrintSettings::operator=(const PrintSettings& settings) {
|
||||
pin_value_ = settings.pin_value_;
|
||||
client_infos_ = settings.client_infos_;
|
||||
#endif // BUILDFLAG(IS_CHROMEOS)
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
system_print_dialog_data_ = settings.system_print_dialog_data_.Clone();
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -421,6 +424,9 @@ void PrintSettings::Clear() {
|
||||
pin_value_.clear();
|
||||
client_infos_.clear();
|
||||
#endif // BUILDFLAG(IS_CHROMEOS)
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
system_print_dialog_data_.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
void PrintSettings::SetPrinterPrintableArea(
|
||||
|
@ -21,6 +21,10 @@
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
#include "base/values.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||
#include <map>
|
||||
|
||||
@ -33,6 +37,29 @@
|
||||
|
||||
namespace printing {
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
inline constexpr char kMacSystemPrintDialogDataDestinationType[] =
|
||||
"destination_type";
|
||||
inline constexpr char kMacSystemPrintDialogDataDestinationFormat[] =
|
||||
"destination_format";
|
||||
inline constexpr char kMacSystemPrintDialogDataDestinationLocation[] =
|
||||
"destination_location";
|
||||
inline constexpr char kMacSystemPrintDialogDataPageFormat[] = "page_format";
|
||||
inline constexpr char kMacSystemPrintDialogDataPrintSettings[] =
|
||||
"print_settings";
|
||||
#endif // BUILDFLAG(IS_MAC)
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
inline constexpr char kLinuxSystemPrintDialogDataPrinter[] = "printer_name";
|
||||
inline constexpr char kLinuxSystemPrintDialogDataPrintSettings[] =
|
||||
"print_settings";
|
||||
inline constexpr char kLinuxSystemPrintDialogDataPageSetup[] = "page_setup";
|
||||
#endif // BUILDFLAG(IS_LINUX)
|
||||
|
||||
#endif // BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
|
||||
// Convert from `color_mode` into a `color_model`. An invalid `color_mode`
|
||||
// will give a result of `mojom::ColorModel::kUnknownColorModel`.
|
||||
COMPONENT_EXPORT(PRINTING)
|
||||
@ -295,6 +322,14 @@ class COMPONENT_EXPORT(PRINTING) PrintSettings {
|
||||
}
|
||||
#endif // BUILDFLAG(IS_CHROMEOS)
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
void set_system_print_dialog_data(base::Value::Dict data) {
|
||||
system_print_dialog_data_ = std::move(data);
|
||||
}
|
||||
const base::Value::Dict& system_print_dialog_data() const {
|
||||
return system_print_dialog_data_;
|
||||
}
|
||||
#endif
|
||||
// Cookie generator. It is used to initialize `PrintedDocument` with its
|
||||
// associated `PrintSettings`, to be sure that each generated `PrintedPage`
|
||||
// is correctly associated with its corresponding `PrintedDocument`.
|
||||
@ -344,6 +379,13 @@ class COMPONENT_EXPORT(PRINTING) PrintSettings {
|
||||
// Printer device name as opened by the OS.
|
||||
std::u16string device_name_;
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
// Platform-specific print settings captured from a system print dialog.
|
||||
// The settings are captured in the browser process for transmission to
|
||||
// the Print Backend service for OOP printing.
|
||||
base::Value::Dict system_print_dialog_data_;
|
||||
#endif
|
||||
|
||||
// Media requested by the user.
|
||||
RequestedMedia requested_media_;
|
||||
|
||||
|
@ -205,19 +205,4 @@ void PrintingContext::SetPrintSettings(const PrintSettings& settings) {
|
||||
*settings_ = settings;
|
||||
}
|
||||
|
||||
void PrintingContext::ApplyPrintSettings(const PrintSettings& settings) {
|
||||
SetPrintSettings(settings);
|
||||
|
||||
#if !BUILDFLAG(ENABLE_OOP_BASIC_PRINT_DIALOG)
|
||||
if (skip_system_calls()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(crbug.com/1414968): System print dialog settings from the browser
|
||||
// require platform-specific handling to be applied to device context.
|
||||
NOTIMPLEMENTED()
|
||||
<< "Apply system dialog settings to device context not supported yet";
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
|
@ -112,10 +112,6 @@ class COMPONENT_EXPORT(PRINTING) PrintingContext {
|
||||
// Sets the print settings to `settings`.
|
||||
void SetPrintSettings(const PrintSettings& settings);
|
||||
|
||||
// Applies the print settings to this context. Intended to be used only by
|
||||
// the Print Backend service process.
|
||||
void ApplyPrintSettings(const PrintSettings& settings);
|
||||
|
||||
// Set the printable area in print settings to be the default printable area.
|
||||
// Intended to be used only for virtual printers.
|
||||
void SetDefaultPrintableAreaForVirtualPrinters();
|
||||
|
@ -18,6 +18,10 @@
|
||||
#include "printing/print_job_constants.h"
|
||||
#include "printing/units.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
#include "printing/printing_features.h"
|
||||
#endif
|
||||
|
||||
// Avoid using LinuxUi on Fuchsia.
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
#include "ui/linux/linux_ui.h"
|
||||
@ -127,11 +131,23 @@ mojom::ResultCode PrintingContextLinux::NewDocument(
|
||||
DCHECK(!in_print_job_);
|
||||
in_print_job_ = true;
|
||||
|
||||
// If this implementation is expanded to include system calls then such calls
|
||||
// should be gated upon `skip_system_calls()`.
|
||||
|
||||
document_name_ = document_name;
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
if (skip_system_calls()) {
|
||||
return mojom::ResultCode::kSuccess;
|
||||
}
|
||||
|
||||
if (features::kEnableOopPrintDriversJobPrint.Get() &&
|
||||
!settings_->system_print_dialog_data().empty()) {
|
||||
CHECK(ui::LinuxUi::instance());
|
||||
if (!print_dialog_) {
|
||||
print_dialog_ = ui::LinuxUi::instance()->CreatePrintDialog(this);
|
||||
}
|
||||
print_dialog_->LoadPrintSettings(*settings_);
|
||||
}
|
||||
#endif
|
||||
|
||||
return mojom::ResultCode::kSuccess;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "base/apple/bridging.h"
|
||||
#include "base/apple/foundation_util.h"
|
||||
#include "base/apple/scoped_cftyperef.h"
|
||||
#include "base/check.h"
|
||||
#include "base/check_op.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
@ -29,6 +29,11 @@
|
||||
#include "printing/printing_features.h"
|
||||
#include "printing/units.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "base/types/expected.h"
|
||||
#endif
|
||||
|
||||
namespace printing {
|
||||
|
||||
namespace {
|
||||
@ -85,6 +90,250 @@ bool IsIppColorModelColorful(mojom::ColorModel color_model) {
|
||||
return IsColorModelSelected(color_model).value();
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
|
||||
// The set of "capture" routines run in the browser process.
|
||||
// The set of "apply" routines run in the Print Backend service.
|
||||
|
||||
base::expected<std::vector<uint8_t>, mojom::ResultCode>
|
||||
CaptureSystemPrintSettings(PMPrintSettings& print_settings) {
|
||||
CFDataRef data_ref = nullptr;
|
||||
OSStatus status = PMPrintSettingsCreateDataRepresentation(
|
||||
print_settings, &data_ref, kPMDataFormatXMLDefault);
|
||||
if (status != noErr) {
|
||||
LOG(ERROR)
|
||||
<< "Failed to create data representation of print settings, error: "
|
||||
<< logging::SystemErrorCodeToString(status);
|
||||
return base::unexpected(mojom::ResultCode::kFailed);
|
||||
}
|
||||
|
||||
base::apple::ScopedCFTypeRef<CFDataRef> scoped_data_ref(data_ref);
|
||||
uint32_t data_size = CFDataGetLength(data_ref);
|
||||
std::vector<uint8_t> capture_data(data_size);
|
||||
CFDataGetBytes(data_ref, CFRangeMake(0, data_size),
|
||||
static_cast<UInt8*>(&capture_data.front()));
|
||||
return capture_data;
|
||||
}
|
||||
|
||||
base::expected<std::vector<uint8_t>, mojom::ResultCode> CaptureSystemPageFormat(
|
||||
PMPageFormat& page_format) {
|
||||
CFDataRef data_ref = nullptr;
|
||||
OSStatus status = PMPageFormatCreateDataRepresentation(
|
||||
page_format, &data_ref, kPMDataFormatXMLDefault);
|
||||
if (status != noErr) {
|
||||
LOG(ERROR) << "Failed to create data representation of page format, error: "
|
||||
<< status;
|
||||
return base::unexpected(mojom::ResultCode::kFailed);
|
||||
}
|
||||
|
||||
uint32_t data_size = CFDataGetLength(data_ref);
|
||||
std::vector<uint8_t> capture_data(data_size);
|
||||
CFDataGetBytes(data_ref, CFRangeMake(0, data_size),
|
||||
static_cast<UInt8*>(&capture_data.front()));
|
||||
return capture_data;
|
||||
}
|
||||
|
||||
base::expected<base::apple::ScopedCFTypeRef<CFStringRef>, mojom::ResultCode>
|
||||
CaptureSystemDestinationFormat(PMPrintSession& print_session,
|
||||
PMPrintSettings& print_settings) {
|
||||
CFStringRef destination_format_ref = nullptr;
|
||||
OSStatus status = PMSessionCopyDestinationFormat(
|
||||
print_session, print_settings, &destination_format_ref);
|
||||
if (status != noErr) {
|
||||
LOG(ERROR) << "Failed to get printing destination format, error: "
|
||||
<< status;
|
||||
return base::unexpected(mojom::ResultCode::kFailed);
|
||||
}
|
||||
return base::apple::ScopedCFTypeRef<CFStringRef>(destination_format_ref);
|
||||
}
|
||||
|
||||
base::expected<base::apple::ScopedCFTypeRef<CFURLRef>, mojom::ResultCode>
|
||||
CaptureSystemDestinationLocation(PMPrintSession& print_session,
|
||||
PMPrintSettings& print_settings) {
|
||||
CFURLRef destination_location_ref = nullptr;
|
||||
OSStatus status = PMSessionCopyDestinationLocation(
|
||||
print_session, print_settings, &destination_location_ref);
|
||||
if (status != noErr) {
|
||||
LOG(ERROR) << "Failed to get printing destination location, error: "
|
||||
<< status;
|
||||
return base::unexpected(mojom::ResultCode::kFailed);
|
||||
}
|
||||
return base::apple::ScopedCFTypeRef<CFURLRef>(destination_location_ref);
|
||||
}
|
||||
|
||||
mojom::ResultCode CaptureSystemPrintDialogData(NSPrintInfo* print_info,
|
||||
PrintSettings* settings) {
|
||||
PMPrintSettings print_settings =
|
||||
(PMPrintSettings)[print_info PMPrintSettings];
|
||||
|
||||
base::expected<std::vector<uint8_t>, mojom::ResultCode> print_settings_data =
|
||||
CaptureSystemPrintSettings(print_settings);
|
||||
if (!print_settings_data.has_value()) {
|
||||
return print_settings_data.error();
|
||||
}
|
||||
|
||||
PMPageFormat page_format =
|
||||
static_cast<PMPageFormat>([print_info PMPageFormat]);
|
||||
|
||||
base::expected<std::vector<uint8_t>, mojom::ResultCode> page_format_data =
|
||||
CaptureSystemPageFormat(page_format);
|
||||
if (!page_format_data.has_value()) {
|
||||
return page_format_data.error();
|
||||
}
|
||||
|
||||
PMPrintSession print_session =
|
||||
static_cast<PMPrintSession>([print_info PMPrintSession]);
|
||||
|
||||
PMDestinationType destination_type = kPMDestinationInvalid;
|
||||
PMSessionGetDestinationType(print_session, print_settings, &destination_type);
|
||||
|
||||
base::expected<base::apple::ScopedCFTypeRef<CFStringRef>, mojom::ResultCode>
|
||||
destination_format =
|
||||
CaptureSystemDestinationFormat(print_session, print_settings);
|
||||
if (!destination_format.has_value()) {
|
||||
return destination_format.error();
|
||||
}
|
||||
|
||||
base::expected<base::apple::ScopedCFTypeRef<CFURLRef>, mojom::ResultCode>
|
||||
destination_location =
|
||||
CaptureSystemDestinationLocation(print_session, print_settings);
|
||||
if (!destination_location.has_value()) {
|
||||
return destination_location.error();
|
||||
}
|
||||
|
||||
base::Value::Dict dialog_data;
|
||||
dialog_data.Set(kMacSystemPrintDialogDataPrintSettings,
|
||||
std::move(print_settings_data.value()));
|
||||
dialog_data.Set(kMacSystemPrintDialogDataPageFormat,
|
||||
std::move(page_format_data.value()));
|
||||
dialog_data.Set(kMacSystemPrintDialogDataDestinationType, destination_type);
|
||||
if (destination_format.value()) {
|
||||
dialog_data.Set(kMacSystemPrintDialogDataDestinationFormat,
|
||||
base::SysCFStringRefToUTF8(destination_format.value()));
|
||||
}
|
||||
if (destination_location.value()) {
|
||||
dialog_data.Set(kMacSystemPrintDialogDataDestinationLocation,
|
||||
base::SysCFStringRefToUTF8(
|
||||
CFURLGetString(destination_location.value())));
|
||||
}
|
||||
settings->set_system_print_dialog_data(std::move(dialog_data));
|
||||
return mojom::ResultCode::kSuccess;
|
||||
}
|
||||
|
||||
void ApplySystemPrintSettings(const base::Value::Dict& system_print_dialog_data,
|
||||
NSPrintInfo* print_info,
|
||||
PMPrintSession& print_session,
|
||||
PMPrintSettings& print_settings) {
|
||||
const base::Value::BlobStorage* data =
|
||||
system_print_dialog_data.FindBlob(kMacSystemPrintDialogDataPrintSettings);
|
||||
CHECK(data);
|
||||
uint32_t data_size = data->size();
|
||||
CHECK_GT(data_size, 0u);
|
||||
CFDataRef data_ref =
|
||||
CFDataCreate(kCFAllocatorDefault,
|
||||
static_cast<const UInt8*>(&data->front()), data_size);
|
||||
CHECK(data_ref);
|
||||
base::apple::ScopedCFTypeRef<CFDataRef> scoped_data_ref(data_ref);
|
||||
|
||||
PMPrintSettings new_print_settings = nullptr;
|
||||
OSStatus status = PMPrintSettingsCreateWithDataRepresentation(
|
||||
data_ref, &new_print_settings);
|
||||
CHECK_EQ(status, noErr) << logging::SystemErrorCodeToString(status);
|
||||
|
||||
status = PMSessionValidatePrintSettings(print_session, new_print_settings,
|
||||
kPMDontWantBoolean);
|
||||
CHECK_EQ(status, noErr) << logging::SystemErrorCodeToString(status);
|
||||
status = PMCopyPrintSettings(new_print_settings, print_settings);
|
||||
CHECK_EQ(status, noErr) << logging::SystemErrorCodeToString(status);
|
||||
|
||||
[print_info updateFromPMPrintSettings];
|
||||
PMRelease(new_print_settings);
|
||||
}
|
||||
|
||||
void ApplySystemPageFormat(const base::Value::Dict& system_print_dialog_data,
|
||||
NSPrintInfo* print_info,
|
||||
PMPrintSession& print_session,
|
||||
PMPageFormat& page_format) {
|
||||
const base::Value::BlobStorage* data =
|
||||
system_print_dialog_data.FindBlob(kMacSystemPrintDialogDataPageFormat);
|
||||
CHECK(data);
|
||||
uint32_t data_size = data->size();
|
||||
CHECK_GT(data_size, 0u);
|
||||
CFDataRef data_ref =
|
||||
CFDataCreate(kCFAllocatorDefault,
|
||||
static_cast<const UInt8*>(&data->front()), data_size);
|
||||
CHECK(data_ref);
|
||||
|
||||
PMPageFormat new_page_format = nullptr;
|
||||
OSStatus status =
|
||||
PMPageFormatCreateWithDataRepresentation(data_ref, &new_page_format);
|
||||
CHECK_EQ(status, noErr) << logging::SystemErrorCodeToString(status);
|
||||
status = PMSessionValidatePageFormat(print_session, page_format,
|
||||
kPMDontWantBoolean);
|
||||
status = PMCopyPageFormat(new_page_format, page_format);
|
||||
CHECK_EQ(status, noErr) << logging::SystemErrorCodeToString(status);
|
||||
|
||||
[print_info updateFromPMPageFormat];
|
||||
PMRelease(new_page_format);
|
||||
}
|
||||
|
||||
void ApplySystemDestination(const base::Value::Dict& system_print_dialog_data,
|
||||
PMPrintSession& print_session,
|
||||
PMPrintSettings& print_settings) {
|
||||
absl::optional<int> destination_type = system_print_dialog_data.FindInt(
|
||||
kMacSystemPrintDialogDataDestinationType);
|
||||
|
||||
CHECK(destination_type.has_value());
|
||||
CHECK(base::IsValueInRangeForNumericType<uint16_t>(*destination_type));
|
||||
|
||||
const std::string* destination_format_str =
|
||||
system_print_dialog_data.FindString(
|
||||
kMacSystemPrintDialogDataDestinationFormat);
|
||||
const std::string* destination_location_str =
|
||||
system_print_dialog_data.FindString(
|
||||
kMacSystemPrintDialogDataDestinationLocation);
|
||||
|
||||
base::apple::ScopedCFTypeRef<CFStringRef> destination_format;
|
||||
if (destination_format_str) {
|
||||
destination_format.reset(
|
||||
base::SysUTF8ToCFStringRef(*destination_format_str));
|
||||
}
|
||||
|
||||
base::apple::ScopedCFTypeRef<CFURLRef> destination_location;
|
||||
if (destination_location_str) {
|
||||
destination_location.reset(CFURLCreateWithFileSystemPath(
|
||||
kCFAllocatorDefault,
|
||||
base::SysUTF8ToCFStringRef(*destination_location_str),
|
||||
kCFURLPOSIXPathStyle,
|
||||
/*isDirectory=*/FALSE));
|
||||
}
|
||||
|
||||
OSStatus status = PMSessionSetDestination(
|
||||
print_session, print_settings,
|
||||
static_cast<PMDestinationType>(*destination_type),
|
||||
destination_format.get(), destination_location.get());
|
||||
CHECK_EQ(status, noErr) << logging::SystemErrorCodeToString(status);
|
||||
}
|
||||
|
||||
void ApplySystemPrintDialogData(
|
||||
const base::Value::Dict& system_print_dialog_data,
|
||||
NSPrintInfo* print_info) {
|
||||
PMPrintSession print_session =
|
||||
static_cast<PMPrintSession>([print_info PMPrintSession]);
|
||||
PMPrintSettings print_settings =
|
||||
static_cast<PMPrintSettings>([print_info PMPrintSettings]);
|
||||
PMPageFormat page_format =
|
||||
static_cast<PMPageFormat>([print_info PMPageFormat]);
|
||||
|
||||
ApplySystemPrintSettings(system_print_dialog_data, print_info, print_session,
|
||||
print_settings);
|
||||
ApplySystemPageFormat(system_print_dialog_data, print_info, print_session,
|
||||
page_format);
|
||||
ApplySystemDestination(system_print_dialog_data, print_session,
|
||||
print_settings);
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
@ -154,7 +403,13 @@ void PrintingContextMac::AskUserForSettings(int max_pages,
|
||||
print_info_ = [panel printInfo];
|
||||
settings_->set_ranges(GetPageRangesFromPrintInfo());
|
||||
InitPrintSettingsFromPrintInfo();
|
||||
std::move(block_callback).Run(mojom::ResultCode::kSuccess);
|
||||
mojom::ResultCode result = mojom::ResultCode::kSuccess;
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
if (features::kEnableOopPrintDriversJobPrint.Get()) {
|
||||
result = CaptureSystemPrintDialogData(print_info_, settings_.get());
|
||||
}
|
||||
#endif
|
||||
std::move(block_callback).Run(result);
|
||||
} else {
|
||||
std::move(block_callback).Run(mojom::ResultCode::kCanceled);
|
||||
}
|
||||
@ -493,6 +748,18 @@ mojom::ResultCode PrintingContextMac::NewDocument(
|
||||
if (skip_system_calls())
|
||||
return mojom::ResultCode::kSuccess;
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
if (features::kEnableOopPrintDriversJobPrint.Get() &&
|
||||
!settings_->system_print_dialog_data().empty()) {
|
||||
// NOTE: Reset `print_info_` with a copy of `sharedPrintInfo` so as to
|
||||
// start with a clean slate.
|
||||
print_info_ = [[NSPrintInfo sharedPrintInfo] copy];
|
||||
|
||||
ApplySystemPrintDialogData(settings_->system_print_dialog_data(),
|
||||
print_info_);
|
||||
}
|
||||
#endif
|
||||
|
||||
PMPrintSession print_session =
|
||||
static_cast<PMPrintSession>([print_info_ PMPrintSession]);
|
||||
PMPrintSettings print_settings =
|
||||
|
@ -20,6 +20,10 @@
|
||||
#include "printing/units.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
#include "printing/printing_features.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "printing/printed_page_win.h"
|
||||
#endif
|
||||
@ -180,6 +184,15 @@ mojom::ResultCode TestPrintingContext::NewDocument(
|
||||
const std::u16string& document_name) {
|
||||
DCHECK(!in_print_job_);
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
if (!skip_system_calls() && features::kEnableOopPrintDriversJobPrint.Get() &&
|
||||
!settings_->system_print_dialog_data().empty()) {
|
||||
// Mimic the update when system print dialog settings are provided to
|
||||
// Print Backend service from the browser process.
|
||||
applied_settings_ = *settings_;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (on_new_document_callback_) {
|
||||
on_new_document_callback_.Run(
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
|
@ -121,8 +121,10 @@ gdouble gtk_page_setup_get_paper_height(GtkPageSetup* setup, GtkUnit unit);
|
||||
GtkPaperSize* gtk_page_setup_get_paper_size(GtkPageSetup* setup);
|
||||
gdouble gtk_page_setup_get_paper_width(GtkPageSetup* setup, GtkUnit unit);
|
||||
gdouble gtk_page_setup_get_top_margin(GtkPageSetup* setup, GtkUnit unit);
|
||||
gboolean gtk_page_setup_load_key_file (GtkPageSetup* setup, GKeyFile* key_file, const char* group_name, GError** error);
|
||||
GtkPageSetup* gtk_page_setup_new(void);
|
||||
void gtk_page_setup_set_paper_size(GtkPageSetup* setup, GtkPaperSize* size);
|
||||
void gtk_page_setup_to_key_file (GtkPageSetup* setup, GKeyFile* key_file, const gchar* group_name);
|
||||
void gtk_paper_size_free(GtkPaperSize* size);
|
||||
gdouble gtk_paper_size_get_height(GtkPaperSize* size, GtkUnit unit);
|
||||
GList* gtk_paper_size_get_paper_sizes(gboolean include_custom);
|
||||
@ -141,6 +143,7 @@ GtkPageRange* gtk_print_settings_get_page_ranges(GtkPrintSettings* settings, gin
|
||||
const gchar* gtk_print_settings_get_printer(GtkPrintSettings* settings);
|
||||
GtkPrintPages gtk_print_settings_get_print_pages(GtkPrintSettings* settings);
|
||||
gint gtk_print_settings_get_resolution(GtkPrintSettings* settings);
|
||||
gboolean gtk_print_settings_load_key_file(GtkPrintSettings* settings, GKeyFile* key_file, const gchar* group_name, GError** error);
|
||||
GtkPrintSettings* gtk_print_settings_new(void);
|
||||
void gtk_print_settings_set(GtkPrintSettings* settings, const gchar* key, const gchar* value);
|
||||
void gtk_print_settings_set_collate(GtkPrintSettings* settings, gboolean collate);
|
||||
@ -149,6 +152,7 @@ void gtk_print_settings_set_orientation(GtkPrintSettings* settings, GtkPageOrien
|
||||
void gtk_print_settings_set_printer_lpi(GtkPrintSettings* settings, gdouble lpi);
|
||||
void gtk_print_settings_set_print_pages(GtkPrintSettings* settings, GtkPrintPages pages);
|
||||
void gtk_print_settings_set_resolution_xy(GtkPrintSettings* settings, gint resolution_x, gint resolution_y);
|
||||
void gtk_print_settings_to_key_file(GtkPrintSettings* settings, GKeyFile* key_file, const gchar* group_name);
|
||||
GtkPageSetup* gtk_print_unix_dialog_get_page_setup(GtkPrintUnixDialog* dialog);
|
||||
GtkPrinter* gtk_print_unix_dialog_get_selected_printer(GtkPrintUnixDialog* dialog);
|
||||
GtkPrintSettings* gtk_print_unix_dialog_get_settings(GtkPrintUnixDialog* dialog);
|
||||
|
@ -174,6 +174,21 @@ class GtkPrinterList {
|
||||
raw_ptr<GtkPrinter> default_printer_ = nullptr;
|
||||
};
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
ScopedGKeyFile GetGKeyFileFromDict(const base::Value::Dict& data,
|
||||
base::StringPiece key) {
|
||||
const std::string* data_string = data.FindString(key);
|
||||
CHECK(data_string);
|
||||
|
||||
ScopedGKeyFile key_file = ScopedGKeyFile(g_key_file_new());
|
||||
GError* error = nullptr;
|
||||
CHECK(g_key_file_load_from_data(key_file.get(), data_string->c_str(),
|
||||
data_string->size(), G_KEY_FILE_NONE, &error))
|
||||
<< error->message;
|
||||
return key_file;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
@ -365,6 +380,42 @@ void PrintDialogGtk::UpdateSettings(
|
||||
InitPrintSettings(std::move(settings));
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
void PrintDialogGtk::LoadPrintSettings(const PrintSettings& settings) {
|
||||
const std::string* printer_name =
|
||||
settings.system_print_dialog_data().FindString(
|
||||
printing::kLinuxSystemPrintDialogDataPrinter);
|
||||
CHECK(printer_name);
|
||||
|
||||
GError* error = nullptr;
|
||||
auto printer_list = std::make_unique<GtkPrinterList>();
|
||||
printer_ = printer_list->GetPrinterWithName(*printer_name);
|
||||
CHECK(printer_);
|
||||
g_object_ref(printer_);
|
||||
|
||||
if (!gtk_settings_) {
|
||||
gtk_settings_ = gtk_print_settings_copy(GetLastUsedSettings().settings());
|
||||
}
|
||||
if (!page_setup_) {
|
||||
page_setup_ = gtk_page_setup_new();
|
||||
}
|
||||
|
||||
ScopedGKeyFile settings_key_file =
|
||||
GetGKeyFileFromDict(settings.system_print_dialog_data(),
|
||||
printing::kLinuxSystemPrintDialogDataPrintSettings);
|
||||
CHECK(gtk_print_settings_load_key_file(gtk_settings_, settings_key_file.get(),
|
||||
/*group_name=*/nullptr, &error))
|
||||
<< error->message;
|
||||
|
||||
ScopedGKeyFile page_setup_key_file =
|
||||
GetGKeyFileFromDict(settings.system_print_dialog_data(),
|
||||
printing::kLinuxSystemPrintDialogDataPageSetup);
|
||||
CHECK(gtk_page_setup_load_key_file(page_setup_, page_setup_key_file.get(),
|
||||
/*group_name=*/nullptr, &error))
|
||||
<< error->message;
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
|
||||
void PrintDialogGtk::ShowDialog(
|
||||
gfx::NativeView parent_view,
|
||||
bool has_selection,
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/ref_counted_delete_on_sequence.h"
|
||||
#include "printing/buildflags/buildflags.h"
|
||||
#include "printing/print_dialog_linux_interface.h"
|
||||
#include "printing/printing_context_linux.h"
|
||||
#include "ui/aura/window_observer.h"
|
||||
@ -39,6 +40,9 @@ class PrintDialogGtk : public printing::PrintDialogLinuxInterface,
|
||||
void UseDefaultSettings() override;
|
||||
void UpdateSettings(
|
||||
std::unique_ptr<printing::PrintSettings> settings) override;
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
void LoadPrintSettings(const printing::PrintSettings& settings) override;
|
||||
#endif
|
||||
void ShowDialog(
|
||||
gfx::NativeView parent_view,
|
||||
bool has_selection,
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "printing/buildflags/buildflags.h"
|
||||
#include "printing/print_settings.h"
|
||||
#include "printing/printing_context_linux.h"
|
||||
#include "printing/units.h"
|
||||
@ -14,6 +15,12 @@
|
||||
#include "ui/gfx/geometry/size_f.h"
|
||||
#include "ui/gtk/gtk_compat.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
#include <utility>
|
||||
|
||||
#include "base/values.h"
|
||||
#endif
|
||||
|
||||
gfx::Size GetPdfPaperSizeDeviceUnitsGtk(
|
||||
printing::PrintingContextLinux* context) {
|
||||
GtkPageSetup* page_setup = gtk_page_setup_new();
|
||||
@ -71,4 +78,31 @@ void InitPrintSettingsGtk(GtkPrintSettings* settings,
|
||||
DCHECK_EQ(print_settings->device_units_per_inch(), dpi);
|
||||
print_settings->SetPrinterPrintableArea(physical_size_device_units,
|
||||
printable_area_device_units, true);
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
if (printer_name) {
|
||||
// Capture the system dialog settings for this printer, to be used by the
|
||||
// Print Backend service.
|
||||
base::Value::Dict dialog_data;
|
||||
|
||||
dialog_data.Set(printing::kLinuxSystemPrintDialogDataPrinter, printer_name);
|
||||
|
||||
ScopedGKeyFile print_settings_key_file(g_key_file_new());
|
||||
gtk_print_settings_to_key_file(settings, print_settings_key_file.get(),
|
||||
/*group_name=*/nullptr);
|
||||
|
||||
dialog_data.Set(printing::kLinuxSystemPrintDialogDataPrintSettings,
|
||||
g_key_file_to_data(print_settings_key_file.get(),
|
||||
/*length=*/nullptr, /*error=*/nullptr));
|
||||
|
||||
ScopedGKeyFile page_setup_key_file(g_key_file_new());
|
||||
gtk_page_setup_to_key_file(page_setup, page_setup_key_file.get(),
|
||||
/*group_name=*/nullptr);
|
||||
dialog_data.Set(printing::kLinuxSystemPrintDialogDataPageSetup,
|
||||
g_key_file_to_data(page_setup_key_file.get(),
|
||||
/*length=*/nullptr, /*error=*/nullptr));
|
||||
|
||||
print_settings->set_system_print_dialog_data(std::move(dialog_data));
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
}
|
||||
|
@ -5,8 +5,14 @@
|
||||
#ifndef UI_GTK_PRINTING_PRINTING_GTK_UTIL_H_
|
||||
#define UI_GTK_PRINTING_PRINTING_GTK_UTIL_H_
|
||||
|
||||
#include "printing/buildflags/buildflags.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "ui/gtk/gtk_compat.h"
|
||||
#endif
|
||||
|
||||
namespace printing {
|
||||
class PrintingContextLinux;
|
||||
class PrintSettings;
|
||||
@ -24,4 +30,21 @@ void InitPrintSettingsGtk(GtkPrintSettings* settings,
|
||||
GtkPageSetup* page_setup,
|
||||
printing::PrintSettings* print_settings);
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
class ScopedGKeyFile {
|
||||
public:
|
||||
explicit ScopedGKeyFile(GKeyFile* key_file) : key_file_(key_file) {}
|
||||
~ScopedGKeyFile() {
|
||||
if (key_file_) {
|
||||
g_key_file_free(key_file_);
|
||||
}
|
||||
}
|
||||
|
||||
GKeyFile* get() { return key_file_; }
|
||||
|
||||
private:
|
||||
raw_ptr<GKeyFile> key_file_;
|
||||
};
|
||||
#endif // BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
|
||||
|
||||
#endif // UI_GTK_PRINTING_PRINTING_GTK_UTIL_H_
|
||||
|
Reference in New Issue
Block a user