blob: 49b11a35c927ae7ed40e8e7f7873cd754964b55d [file] [log] [blame]
[email protected]c95198b2014-06-12 16:56:551// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "printing/print_settings_conversion.h"
6
avi126e93c2015-12-21 21:48:167#include <stddef.h>
8
[email protected]c95198b2014-06-12 16:56:559#include <algorithm>
10#include <cmath>
dcheng031a8f82016-09-08 21:04:3311#include <memory>
[email protected]c95198b2014-06-12 16:56:5512#include <string>
dcheng031a8f82016-09-08 21:04:3313#include <utility>
[email protected]c95198b2014-06-12 16:56:5514
Daniel Hosseinianfc4d8252021-09-03 21:44:1615#include "base/containers/contains.h"
16#include "base/containers/fixed_flat_set.h"
[email protected]c95198b2014-06-12 16:56:5517#include "base/strings/string_number_conversions.h"
Daniel Hosseinianfc4d8252021-09-03 21:44:1618#include "base/strings/string_piece.h"
[email protected]c95198b2014-06-12 16:56:5519#include "base/strings/utf_string_conversions.h"
20#include "base/time/time.h"
21#include "base/values.h"
Wei Li02720a42017-10-25 22:06:4822#include "build/build_config.h"
Yuta Hijikata2f663892020-10-06 10:34:2223#include "build/chromeos_buildflags.h"
Julie Jeongeun Kime454f2602020-04-30 05:20:0724#include "printing/mojom/print.mojom.h"
[email protected]c95198b2014-06-12 16:56:5525#include "printing/print_job_constants.h"
26#include "printing/print_settings.h"
27#include "printing/units.h"
28
29namespace printing {
30
31namespace {
32
Daniel Hosseinian3553e272021-04-24 00:51:1833// Note: If this code crashes, then the caller has passed in invalid `settings`.
Lei Zhangc8553b42019-08-07 19:13:4634// Fix the caller, instead of trying to avoid the crash here.
35PageMargins GetCustomMarginsFromJobSettings(const base::Value& settings) {
36 PageMargins margins_in_points;
Vladislav Kuzkokov490ab0c2019-01-16 11:21:5737 const base::Value* custom_margins = settings.FindKey(kSettingMarginsCustom);
Lei Zhangc8553b42019-08-07 19:13:4638 margins_in_points.top = custom_margins->FindIntKey(kSettingMarginTop).value();
39 margins_in_points.bottom =
40 custom_margins->FindIntKey(kSettingMarginBottom).value();
41 margins_in_points.left =
42 custom_margins->FindIntKey(kSettingMarginLeft).value();
43 margins_in_points.right =
44 custom_margins->FindIntKey(kSettingMarginRight).value();
45 return margins_in_points;
[email protected]c95198b2014-06-12 16:56:5546}
47
48void SetMarginsToJobSettings(const std::string& json_path,
49 const PageMargins& margins,
Alan Screen3c25f8e2021-08-04 17:41:5150 base::Value& job_settings) {
51 base::Value dict(base::Value::Type::DICTIONARY);
52 dict.SetIntKey(kSettingMarginTop, margins.top);
53 dict.SetIntKey(kSettingMarginBottom, margins.bottom);
54 dict.SetIntKey(kSettingMarginLeft, margins.left);
55 dict.SetIntKey(kSettingMarginRight, margins.right);
56 job_settings.SetKey(json_path, std::move(dict));
[email protected]c95198b2014-06-12 16:56:5557}
58
59void SetSizeToJobSettings(const std::string& json_path,
60 const gfx::Size& size,
Alan Screen3c25f8e2021-08-04 17:41:5161 base::Value& job_settings) {
62 base::Value dict(base::Value::Type::DICTIONARY);
63 dict.SetIntKey("width", size.width());
64 dict.SetIntKey("height", size.height());
65 job_settings.SetKey(json_path, std::move(dict));
[email protected]c95198b2014-06-12 16:56:5566}
67
68void SetRectToJobSettings(const std::string& json_path,
69 const gfx::Rect& rect,
Alan Screen3c25f8e2021-08-04 17:41:5170 base::Value& job_settings) {
71 base::Value dict(base::Value::Type::DICTIONARY);
72 dict.SetIntKey("x", rect.x());
73 dict.SetIntKey("y", rect.y());
74 dict.SetIntKey("width", rect.width());
75 dict.SetIntKey("height", rect.height());
76 job_settings.SetKey(json_path, std::move(dict));
[email protected]c95198b2014-06-12 16:56:5577}
78
79} // namespace
80
Jesse Schettlera092a99c2019-11-06 15:21:2781PageRanges GetPageRangesFromJobSettings(const base::Value& job_settings) {
82 PageRanges page_ranges;
83 const base::Value* page_range_array =
84 job_settings.FindListKey(kSettingPageRange);
85 if (page_range_array) {
86 for (const base::Value& page_range : page_range_array->GetList()) {
87 if (!page_range.is_dict())
88 continue;
89
Anton Bikineev11eb7ff2021-05-15 18:21:2890 absl::optional<int> from = page_range.FindIntKey(kSettingPageRangeFrom);
91 absl::optional<int> to = page_range.FindIntKey(kSettingPageRangeTo);
Jesse Schettlera092a99c2019-11-06 15:21:2792 if (!from.has_value() || !to.has_value())
93 continue;
94
95 // Page numbers are 1-based in the dictionary.
96 // Page numbers are 0-based for the printing context.
Peter Kasting2bb51ca2021-06-09 06:51:3997 page_ranges.push_back(PageRange{static_cast<uint32_t>(from.value() - 1),
98 static_cast<uint32_t>(to.value() - 1)});
Jesse Schettlera092a99c2019-11-06 15:21:2799 }
100 }
101 return page_ranges;
102}
103
Pranav Batra636e2042020-09-03 03:35:05104std::unique_ptr<PrintSettings> PrintSettingsFromJobSettings(
105 const base::Value& job_settings) {
106 auto settings = std::make_unique<PrintSettings>();
Anton Bikineev11eb7ff2021-05-15 18:21:28107 absl::optional<bool> display_header_footer =
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57108 job_settings.FindBoolKey(kSettingHeaderFooterEnabled);
109 if (!display_header_footer.has_value())
Pranav Batra636e2042020-09-03 03:35:05110 return nullptr;
[email protected]c95198b2014-06-12 16:56:55111
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57112 settings->set_display_header_footer(display_header_footer.value());
[email protected]c95198b2014-06-12 16:56:55113 if (settings->display_header_footer()) {
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57114 const std::string* title =
115 job_settings.FindStringKey(kSettingHeaderFooterTitle);
116 const std::string* url =
117 job_settings.FindStringKey(kSettingHeaderFooterURL);
118 if (!title || !url)
Pranav Batra636e2042020-09-03 03:35:05119 return nullptr;
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57120
121 settings->set_title(base::UTF8ToUTF16(*title));
122 settings->set_url(base::UTF8ToUTF16(*url));
[email protected]c95198b2014-06-12 16:56:55123 }
124
Anton Bikineev11eb7ff2021-05-15 18:21:28125 absl::optional<bool> backgrounds =
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57126 job_settings.FindBoolKey(kSettingShouldPrintBackgrounds);
Anton Bikineev11eb7ff2021-05-15 18:21:28127 absl::optional<bool> selection_only =
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57128 job_settings.FindBoolKey(kSettingShouldPrintSelectionOnly);
129 if (!backgrounds.has_value() || !selection_only.has_value())
Pranav Batra636e2042020-09-03 03:35:05130 return nullptr;
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57131
132 settings->set_should_print_backgrounds(backgrounds.value());
133 settings->set_selection_only(selection_only.value());
[email protected]c95198b2014-06-12 16:56:55134
135 PrintSettings::RequestedMedia requested_media;
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57136 const base::Value* media_size_value = job_settings.FindKeyOfType(
137 kSettingMediaSize, base::Value::Type::DICTIONARY);
138 if (media_size_value) {
Anton Bikineev11eb7ff2021-05-15 18:21:28139 absl::optional<int> width_microns =
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57140 media_size_value->FindIntKey(kSettingMediaSizeWidthMicrons);
Anton Bikineev11eb7ff2021-05-15 18:21:28141 absl::optional<int> height_microns =
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57142 media_size_value->FindIntKey(kSettingMediaSizeHeightMicrons);
143 if (width_microns.has_value() && height_microns.has_value()) {
144 requested_media.size_microns =
145 gfx::Size(width_microns.value(), height_microns.value());
[email protected]c95198b2014-06-12 16:56:55146 }
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57147
148 const std::string* vendor_id =
149 media_size_value->FindStringKey(kSettingMediaSizeVendorId);
150 if (vendor_id && !vendor_id->empty())
151 requested_media.vendor_id = *vendor_id;
[email protected]c95198b2014-06-12 16:56:55152 }
153 settings->set_requested_media(requested_media);
154
Julie Jeongeun Kimcb00d1ab2020-08-14 07:43:32155 mojom::MarginType margin_type = static_cast<mojom::MarginType>(
156 job_settings.FindIntKey(kSettingMarginsType)
157 .value_or(static_cast<int>(mojom::MarginType::kDefaultMargins)));
158 if (margin_type != mojom::MarginType::kDefaultMargins &&
159 margin_type != mojom::MarginType::kNoMargins &&
160 margin_type != mojom::MarginType::kCustomMargins &&
161 margin_type != mojom::MarginType::kPrintableAreaMargins) {
162 margin_type = mojom::MarginType::kDefaultMargins;
[email protected]c95198b2014-06-12 16:56:55163 }
Julie Jeongeun Kimcb00d1ab2020-08-14 07:43:32164 settings->set_margin_type(margin_type);
[email protected]c95198b2014-06-12 16:56:55165
Julie Jeongeun Kimcb00d1ab2020-08-14 07:43:32166 if (margin_type == mojom::MarginType::kCustomMargins)
Lei Zhangc8553b42019-08-07 19:13:46167 settings->SetCustomMargins(GetCustomMarginsFromJobSettings(job_settings));
[email protected]c95198b2014-06-12 16:56:55168
Jesse Schettlera092a99c2019-11-06 15:21:27169 settings->set_ranges(GetPageRangesFromJobSettings(job_settings));
[email protected]c95198b2014-06-12 16:56:55170
Anton Bikineev11eb7ff2021-05-15 18:21:28171 absl::optional<bool> collate = job_settings.FindBoolKey(kSettingCollate);
172 absl::optional<int> copies = job_settings.FindIntKey(kSettingCopies);
173 absl::optional<int> color = job_settings.FindIntKey(kSettingColor);
174 absl::optional<int> duplex_mode = job_settings.FindIntKey(kSettingDuplexMode);
175 absl::optional<bool> landscape = job_settings.FindBoolKey(kSettingLandscape);
176 absl::optional<int> scale_factor =
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57177 job_settings.FindIntKey(kSettingScaleFactor);
Anton Bikineev11eb7ff2021-05-15 18:21:28178 absl::optional<bool> rasterize_pdf =
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57179 job_settings.FindBoolKey(kSettingRasterizePdf);
Anton Bikineev11eb7ff2021-05-15 18:21:28180 absl::optional<int> pages_per_sheet =
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57181 job_settings.FindIntKey(kSettingPagesPerSheet);
[email protected]c95198b2014-06-12 16:56:55182
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57183 if (!collate.has_value() || !copies.has_value() || !color.has_value() ||
Lei Zhangdfe53f92019-10-11 05:41:07184 !duplex_mode.has_value() || !landscape.has_value() ||
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57185 !scale_factor.has_value() || !rasterize_pdf.has_value() ||
186 !pages_per_sheet.has_value()) {
Pranav Batra636e2042020-09-03 03:35:05187 return nullptr;
[email protected]c95198b2014-06-12 16:56:55188 }
Pranav Batra636e2042020-09-03 03:35:05189
Anton Bikineev11eb7ff2021-05-15 18:21:28190 absl::optional<int> dpi_horizontal =
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57191 job_settings.FindIntKey(kSettingDpiHorizontal);
Anton Bikineev11eb7ff2021-05-15 18:21:28192 absl::optional<int> dpi_vertical =
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57193 job_settings.FindIntKey(kSettingDpiVertical);
194 if (!dpi_horizontal.has_value() || !dpi_vertical.has_value())
Pranav Batra636e2042020-09-03 03:35:05195 return nullptr;
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57196 settings->set_dpi_xy(dpi_horizontal.value(), dpi_vertical.value());
[email protected]c95198b2014-06-12 16:56:55197
Alan Screendce2e585b2021-08-12 21:10:47198 absl::optional<int> rasterize_pdf_dpi =
199 job_settings.FindIntKey(kSettingRasterizePdfDpi);
200 if (rasterize_pdf_dpi.has_value())
201 settings->set_rasterize_pdf_dpi(rasterize_pdf_dpi.value());
202
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57203 settings->set_collate(collate.value());
204 settings->set_copies(copies.value());
205 settings->SetOrientation(landscape.value());
Lei Zhangdfe53f92019-10-11 05:41:07206 settings->set_device_name(
207 base::UTF8ToUTF16(*job_settings.FindStringKey(kSettingDeviceName)));
Julie Jeongeun Kime454f2602020-04-30 05:20:07208 settings->set_duplex_mode(
209 static_cast<mojom::DuplexMode>(duplex_mode.value()));
Alan Screen3fb63bf2020-08-19 00:11:23210 settings->set_color(static_cast<mojom::ColorModel>(color.value()));
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57211 settings->set_scale_factor(static_cast<double>(scale_factor.value()) / 100.0);
212 settings->set_rasterize_pdf(rasterize_pdf.value());
213 settings->set_pages_per_sheet(pages_per_sheet.value());
Anton Bikineev11eb7ff2021-05-15 18:21:28214 absl::optional<bool> is_modifiable =
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57215 job_settings.FindBoolKey(kSettingPreviewModifiable);
216 if (is_modifiable.has_value()) {
217 settings->set_is_modifiable(is_modifiable.value());
thestige85e6b62016-08-25 00:00:06218#if defined(OS_WIN)
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57219 settings->set_print_text_with_gdi(is_modifiable.value());
thestige85e6b62016-08-25 00:00:06220#endif
Wei Li02720a42017-10-25 22:06:48221 }
Vladislav Kuzkokov48b15002019-01-30 17:13:35222
Pranav Batra32b98bfc2021-05-12 00:17:02223#if defined(OS_CHROMEOS) || (defined(OS_LINUX) && defined(USE_CUPS))
Daniel Hosseinianc3db7f4c2020-06-25 02:09:52224 const base::Value* advanced_settings =
225 job_settings.FindDictKey(kSettingAdvancedSettings);
226 if (advanced_settings) {
Daniel Hosseinianfc4d8252021-09-03 21:44:16227 for (const auto item : advanced_settings->DictItems()) {
228 static constexpr auto kNonJobAttributes =
229 base::MakeFixedFlatSet<base::StringPiece>(
230 {"printer-info", "printer-make-and-model", "system_driverinfo"});
231 if (!base::Contains(kNonJobAttributes, item.first))
232 settings->advanced_settings().emplace(item.first, item.second.Clone());
233 }
Daniel Hosseinianc3db7f4c2020-06-25 02:09:52234 }
Pranav Batra32b98bfc2021-05-12 00:17:02235#endif // defined(OS_CHROMEOS) || (defined(OS_LINUX) && defined(USE_CUPS))
Daniel Hosseinianc3db7f4c2020-06-25 02:09:52236
Pranav Batra32b98bfc2021-05-12 00:17:02237#if defined(OS_CHROMEOS)
Vladislav Kuzkokov48b15002019-01-30 17:13:35238 bool send_user_info =
239 job_settings.FindBoolKey(kSettingSendUserInfo).value_or(false);
240 settings->set_send_user_info(send_user_info);
241 if (send_user_info) {
242 const std::string* username = job_settings.FindStringKey(kSettingUsername);
243 if (username)
244 settings->set_username(*username);
245 }
Nikita Podguzovc1bf3f82019-03-19 15:23:23246
247 const std::string* pin_value = job_settings.FindStringKey(kSettingPinValue);
248 if (pin_value)
249 settings->set_pin_value(*pin_value);
Pranav Batra32b98bfc2021-05-12 00:17:02250#endif // defined(OS_CHROMEOS)
Vladislav Kuzkokov48b15002019-01-30 17:13:35251
Pranav Batra636e2042020-09-03 03:35:05252 return settings;
[email protected]c95198b2014-06-12 16:56:55253}
254
Alan Screen3c25f8e2021-08-04 17:41:51255base::Value PrintSettingsToJobSettingsDebug(const PrintSettings& settings) {
256 base::Value job_settings(base::Value::Type::DICTIONARY);
257
258 job_settings.SetBoolKey(kSettingHeaderFooterEnabled,
259 settings.display_header_footer());
260 job_settings.SetStringKey(kSettingHeaderFooterTitle, settings.title());
261 job_settings.SetStringKey(kSettingHeaderFooterURL, settings.url());
262 job_settings.SetBoolKey(kSettingShouldPrintBackgrounds,
263 settings.should_print_backgrounds());
264 job_settings.SetBoolKey(kSettingShouldPrintSelectionOnly,
265 settings.selection_only());
266 job_settings.SetIntKey(kSettingMarginsType,
267 static_cast<int>(settings.margin_type()));
[email protected]c95198b2014-06-12 16:56:55268 if (!settings.ranges().empty()) {
Song Fangzhen6ff811d2021-06-29 08:35:43269 base::ListValue page_range_array;
Alan Screen3c25f8e2021-08-04 17:41:51270 for (const auto& range : settings.ranges()) {
271 auto dict = std::make_unique<base::Value>(base::Value::Type::DICTIONARY);
272 dict->SetIntKey(kSettingPageRangeFrom, range.from + 1);
273 dict->SetIntKey(kSettingPageRangeTo, range.to + 1);
Song Fangzhen6ff811d2021-06-29 08:35:43274 page_range_array.Append(std::move(dict));
[email protected]c95198b2014-06-12 16:56:55275 }
Alan Screen3c25f8e2021-08-04 17:41:51276 job_settings.SetKey(kSettingPageRange, std::move(page_range_array));
[email protected]c95198b2014-06-12 16:56:55277 }
278
Alan Screen3c25f8e2021-08-04 17:41:51279 job_settings.SetBoolKey(kSettingCollate, settings.collate());
280 job_settings.SetIntKey(kSettingCopies, settings.copies());
281 job_settings.SetIntKey(kSettingColor, static_cast<int>(settings.color()));
282 job_settings.SetIntKey(kSettingDuplexMode,
283 static_cast<int>(settings.duplex_mode()));
284 job_settings.SetBoolKey(kSettingLandscape, settings.landscape());
285 job_settings.SetStringKey(kSettingDeviceName, settings.device_name());
286 job_settings.SetIntKey(kSettingDpiHorizontal, settings.dpi_horizontal());
287 job_settings.SetIntKey(kSettingDpiVertical, settings.dpi_vertical());
288 job_settings.SetIntKey(
289 kSettingScaleFactor,
290 static_cast<int>((settings.scale_factor() * 100.0) + 0.5));
291 job_settings.SetBoolKey(kSettingRasterizePdf, settings.rasterize_pdf());
292 job_settings.SetIntKey(kSettingPagesPerSheet, settings.pages_per_sheet());
[email protected]c95198b2014-06-12 16:56:55293
294 // Following values are not read form JSON by InitSettings, so do not have
295 // common public constants. So just serialize in "debug" section.
Alan Screen3c25f8e2021-08-04 17:41:51296 base::Value debug(base::Value::Type::DICTIONARY);
297 debug.SetIntKey("dpi", settings.dpi());
298 debug.SetIntKey("deviceUnitsPerInch", settings.device_units_per_inch());
299 debug.SetBoolKey("support_alpha_blend", settings.should_print_backgrounds());
300 debug.SetStringKey("media_vendor_id", settings.requested_media().vendor_id);
jdoerriecb205a52017-06-08 16:16:44301 SetSizeToJobSettings("media_size", settings.requested_media().size_microns,
Alan Screen3c25f8e2021-08-04 17:41:51302 debug);
[email protected]c95198b2014-06-12 16:56:55303 SetMarginsToJobSettings("requested_custom_margins_in_points",
Alan Screen3c25f8e2021-08-04 17:41:51304 settings.requested_custom_margins_in_points(), debug);
[email protected]c95198b2014-06-12 16:56:55305 const PageSetup& page_setup = settings.page_setup_device_units();
jdoerriecb205a52017-06-08 16:16:44306 SetMarginsToJobSettings("effective_margins", page_setup.effective_margins(),
Alan Screen3c25f8e2021-08-04 17:41:51307 debug);
308 SetSizeToJobSettings("physical_size", page_setup.physical_size(), debug);
309 SetRectToJobSettings("overlay_area", page_setup.overlay_area(), debug);
310 SetRectToJobSettings("content_area", page_setup.content_area(), debug);
311 SetRectToJobSettings("printable_area", page_setup.printable_area(), debug);
312 job_settings.SetKey("debug", std::move(debug));
313
314 return job_settings;
[email protected]c95198b2014-06-12 16:56:55315}
316
317} // namespace printing