blob: 8e9a07ce81c789a2aed52c85179cc2454be1c374 [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
15#include "base/strings/string_number_conversions.h"
16#include "base/strings/utf_string_conversions.h"
17#include "base/time/time.h"
18#include "base/values.h"
Wei Li02720a42017-10-25 22:06:4819#include "build/build_config.h"
Yuta Hijikata2f663892020-10-06 10:34:2220#include "build/chromeos_buildflags.h"
Julie Jeongeun Kime454f2602020-04-30 05:20:0721#include "printing/mojom/print.mojom.h"
[email protected]c95198b2014-06-12 16:56:5522#include "printing/print_job_constants.h"
23#include "printing/print_settings.h"
24#include "printing/units.h"
25
26namespace printing {
27
28namespace {
29
Lei Zhangc8553b42019-08-07 19:13:4630// Note: If this code crashes, then the caller has passed in invalid |settings|.
31// Fix the caller, instead of trying to avoid the crash here.
32PageMargins GetCustomMarginsFromJobSettings(const base::Value& settings) {
33 PageMargins margins_in_points;
Vladislav Kuzkokov490ab0c2019-01-16 11:21:5734 const base::Value* custom_margins = settings.FindKey(kSettingMarginsCustom);
Lei Zhangc8553b42019-08-07 19:13:4635 margins_in_points.top = custom_margins->FindIntKey(kSettingMarginTop).value();
36 margins_in_points.bottom =
37 custom_margins->FindIntKey(kSettingMarginBottom).value();
38 margins_in_points.left =
39 custom_margins->FindIntKey(kSettingMarginLeft).value();
40 margins_in_points.right =
41 custom_margins->FindIntKey(kSettingMarginRight).value();
42 return margins_in_points;
[email protected]c95198b2014-06-12 16:56:5543}
44
45void SetMarginsToJobSettings(const std::string& json_path,
46 const PageMargins& margins,
47 base::DictionaryValue* job_settings) {
Gyuyoung Kimb480aba2018-01-27 07:00:0448 auto dict = std::make_unique<base::DictionaryValue>();
[email protected]c95198b2014-06-12 16:56:5549 dict->SetInteger(kSettingMarginTop, margins.top);
50 dict->SetInteger(kSettingMarginBottom, margins.bottom);
51 dict->SetInteger(kSettingMarginLeft, margins.left);
52 dict->SetInteger(kSettingMarginRight, margins.right);
jdoerriecb205a52017-06-08 16:16:4453 job_settings->Set(json_path, std::move(dict));
[email protected]c95198b2014-06-12 16:56:5554}
55
56void SetSizeToJobSettings(const std::string& json_path,
57 const gfx::Size& size,
58 base::DictionaryValue* job_settings) {
Gyuyoung Kimb480aba2018-01-27 07:00:0459 auto dict = std::make_unique<base::DictionaryValue>();
[email protected]c95198b2014-06-12 16:56:5560 dict->SetInteger("width", size.width());
61 dict->SetInteger("height", size.height());
jdoerriecb205a52017-06-08 16:16:4462 job_settings->Set(json_path, std::move(dict));
[email protected]c95198b2014-06-12 16:56:5563}
64
65void SetRectToJobSettings(const std::string& json_path,
66 const gfx::Rect& rect,
67 base::DictionaryValue* job_settings) {
Gyuyoung Kimb480aba2018-01-27 07:00:0468 auto dict = std::make_unique<base::DictionaryValue>();
[email protected]c95198b2014-06-12 16:56:5569 dict->SetInteger("x", rect.x());
70 dict->SetInteger("y", rect.y());
71 dict->SetInteger("width", rect.width());
72 dict->SetInteger("height", rect.height());
jdoerriecb205a52017-06-08 16:16:4473 job_settings->Set(json_path, std::move(dict));
[email protected]c95198b2014-06-12 16:56:5574}
75
76} // namespace
77
Jesse Schettlera092a99c2019-11-06 15:21:2778PageRanges GetPageRangesFromJobSettings(const base::Value& job_settings) {
79 PageRanges page_ranges;
80 const base::Value* page_range_array =
81 job_settings.FindListKey(kSettingPageRange);
82 if (page_range_array) {
83 for (const base::Value& page_range : page_range_array->GetList()) {
84 if (!page_range.is_dict())
85 continue;
86
87 base::Optional<int> from = page_range.FindIntKey(kSettingPageRangeFrom);
88 base::Optional<int> to = page_range.FindIntKey(kSettingPageRangeTo);
89 if (!from.has_value() || !to.has_value())
90 continue;
91
92 // Page numbers are 1-based in the dictionary.
93 // Page numbers are 0-based for the printing context.
94 page_ranges.push_back(PageRange{from.value() - 1, to.value() - 1});
95 }
96 }
97 return page_ranges;
98}
99
Pranav Batra636e2042020-09-03 03:35:05100std::unique_ptr<PrintSettings> PrintSettingsFromJobSettings(
101 const base::Value& job_settings) {
102 auto settings = std::make_unique<PrintSettings>();
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57103 base::Optional<bool> display_header_footer =
104 job_settings.FindBoolKey(kSettingHeaderFooterEnabled);
105 if (!display_header_footer.has_value())
Pranav Batra636e2042020-09-03 03:35:05106 return nullptr;
[email protected]c95198b2014-06-12 16:56:55107
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57108 settings->set_display_header_footer(display_header_footer.value());
[email protected]c95198b2014-06-12 16:56:55109 if (settings->display_header_footer()) {
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57110 const std::string* title =
111 job_settings.FindStringKey(kSettingHeaderFooterTitle);
112 const std::string* url =
113 job_settings.FindStringKey(kSettingHeaderFooterURL);
114 if (!title || !url)
Pranav Batra636e2042020-09-03 03:35:05115 return nullptr;
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57116
117 settings->set_title(base::UTF8ToUTF16(*title));
118 settings->set_url(base::UTF8ToUTF16(*url));
[email protected]c95198b2014-06-12 16:56:55119 }
120
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57121 base::Optional<bool> backgrounds =
122 job_settings.FindBoolKey(kSettingShouldPrintBackgrounds);
123 base::Optional<bool> selection_only =
124 job_settings.FindBoolKey(kSettingShouldPrintSelectionOnly);
125 if (!backgrounds.has_value() || !selection_only.has_value())
Pranav Batra636e2042020-09-03 03:35:05126 return nullptr;
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57127
128 settings->set_should_print_backgrounds(backgrounds.value());
129 settings->set_selection_only(selection_only.value());
[email protected]c95198b2014-06-12 16:56:55130
131 PrintSettings::RequestedMedia requested_media;
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57132 const base::Value* media_size_value = job_settings.FindKeyOfType(
133 kSettingMediaSize, base::Value::Type::DICTIONARY);
134 if (media_size_value) {
135 base::Optional<int> width_microns =
136 media_size_value->FindIntKey(kSettingMediaSizeWidthMicrons);
137 base::Optional<int> height_microns =
138 media_size_value->FindIntKey(kSettingMediaSizeHeightMicrons);
139 if (width_microns.has_value() && height_microns.has_value()) {
140 requested_media.size_microns =
141 gfx::Size(width_microns.value(), height_microns.value());
[email protected]c95198b2014-06-12 16:56:55142 }
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57143
144 const std::string* vendor_id =
145 media_size_value->FindStringKey(kSettingMediaSizeVendorId);
146 if (vendor_id && !vendor_id->empty())
147 requested_media.vendor_id = *vendor_id;
[email protected]c95198b2014-06-12 16:56:55148 }
149 settings->set_requested_media(requested_media);
150
Julie Jeongeun Kimcb00d1ab2020-08-14 07:43:32151 mojom::MarginType margin_type = static_cast<mojom::MarginType>(
152 job_settings.FindIntKey(kSettingMarginsType)
153 .value_or(static_cast<int>(mojom::MarginType::kDefaultMargins)));
154 if (margin_type != mojom::MarginType::kDefaultMargins &&
155 margin_type != mojom::MarginType::kNoMargins &&
156 margin_type != mojom::MarginType::kCustomMargins &&
157 margin_type != mojom::MarginType::kPrintableAreaMargins) {
158 margin_type = mojom::MarginType::kDefaultMargins;
[email protected]c95198b2014-06-12 16:56:55159 }
Julie Jeongeun Kimcb00d1ab2020-08-14 07:43:32160 settings->set_margin_type(margin_type);
[email protected]c95198b2014-06-12 16:56:55161
Julie Jeongeun Kimcb00d1ab2020-08-14 07:43:32162 if (margin_type == mojom::MarginType::kCustomMargins)
Lei Zhangc8553b42019-08-07 19:13:46163 settings->SetCustomMargins(GetCustomMarginsFromJobSettings(job_settings));
[email protected]c95198b2014-06-12 16:56:55164
Jesse Schettlera092a99c2019-11-06 15:21:27165 settings->set_ranges(GetPageRangesFromJobSettings(job_settings));
[email protected]c95198b2014-06-12 16:56:55166
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57167 base::Optional<bool> collate = job_settings.FindBoolKey(kSettingCollate);
168 base::Optional<int> copies = job_settings.FindIntKey(kSettingCopies);
169 base::Optional<int> color = job_settings.FindIntKey(kSettingColor);
170 base::Optional<int> duplex_mode = job_settings.FindIntKey(kSettingDuplexMode);
171 base::Optional<bool> landscape = job_settings.FindBoolKey(kSettingLandscape);
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57172 base::Optional<int> scale_factor =
173 job_settings.FindIntKey(kSettingScaleFactor);
174 base::Optional<bool> rasterize_pdf =
175 job_settings.FindBoolKey(kSettingRasterizePdf);
176 base::Optional<int> pages_per_sheet =
177 job_settings.FindIntKey(kSettingPagesPerSheet);
[email protected]c95198b2014-06-12 16:56:55178
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57179 if (!collate.has_value() || !copies.has_value() || !color.has_value() ||
Lei Zhangdfe53f92019-10-11 05:41:07180 !duplex_mode.has_value() || !landscape.has_value() ||
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57181 !scale_factor.has_value() || !rasterize_pdf.has_value() ||
182 !pages_per_sheet.has_value()) {
Pranav Batra636e2042020-09-03 03:35:05183 return nullptr;
[email protected]c95198b2014-06-12 16:56:55184 }
Pranav Batra636e2042020-09-03 03:35:05185
Sean McAllister496972ab2020-08-24 19:17:35186#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS)
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57187 base::Optional<int> dpi_horizontal =
188 job_settings.FindIntKey(kSettingDpiHorizontal);
189 base::Optional<int> dpi_vertical =
190 job_settings.FindIntKey(kSettingDpiVertical);
191 if (!dpi_horizontal.has_value() || !dpi_vertical.has_value())
Pranav Batra636e2042020-09-03 03:35:05192 return nullptr;
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57193 settings->set_dpi_xy(dpi_horizontal.value(), dpi_vertical.value());
rbpotter116c2e12017-04-04 19:21:28194#endif
[email protected]c95198b2014-06-12 16:56:55195
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57196 settings->set_collate(collate.value());
197 settings->set_copies(copies.value());
198 settings->SetOrientation(landscape.value());
Lei Zhangdfe53f92019-10-11 05:41:07199 settings->set_device_name(
200 base::UTF8ToUTF16(*job_settings.FindStringKey(kSettingDeviceName)));
Julie Jeongeun Kime454f2602020-04-30 05:20:07201 settings->set_duplex_mode(
202 static_cast<mojom::DuplexMode>(duplex_mode.value()));
Alan Screen3fb63bf2020-08-19 00:11:23203 settings->set_color(static_cast<mojom::ColorModel>(color.value()));
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57204 settings->set_scale_factor(static_cast<double>(scale_factor.value()) / 100.0);
205 settings->set_rasterize_pdf(rasterize_pdf.value());
206 settings->set_pages_per_sheet(pages_per_sheet.value());
207 base::Optional<bool> is_modifiable =
208 job_settings.FindBoolKey(kSettingPreviewModifiable);
209 if (is_modifiable.has_value()) {
210 settings->set_is_modifiable(is_modifiable.value());
thestige85e6b62016-08-25 00:00:06211#if defined(OS_WIN)
Vladislav Kuzkokov490ab0c2019-01-16 11:21:57212 settings->set_print_text_with_gdi(is_modifiable.value());
thestige85e6b62016-08-25 00:00:06213#endif
Wei Li02720a42017-10-25 22:06:48214 }
Vladislav Kuzkokov48b15002019-01-30 17:13:35215
Daniel Hosseinianc3db7f4c2020-06-25 02:09:52216#if defined(OS_CHROMEOS) || (defined(OS_LINUX) && defined(USE_CUPS))
217 const base::Value* advanced_settings =
218 job_settings.FindDictKey(kSettingAdvancedSettings);
219 if (advanced_settings) {
220 for (const auto& item : advanced_settings->DictItems())
221 settings->advanced_settings().emplace(item.first, item.second.Clone());
222 }
223#endif // defined(OS_CHROMEOS) || (defined(OS_LINUX) && defined(USE_CUPS))
224
Yuta Hijikata2f663892020-10-06 10:34:22225#if BUILDFLAG(IS_ASH)
Vladislav Kuzkokov48b15002019-01-30 17:13:35226 bool send_user_info =
227 job_settings.FindBoolKey(kSettingSendUserInfo).value_or(false);
228 settings->set_send_user_info(send_user_info);
229 if (send_user_info) {
230 const std::string* username = job_settings.FindStringKey(kSettingUsername);
231 if (username)
232 settings->set_username(*username);
233 }
Nikita Podguzovc1bf3f82019-03-19 15:23:23234
235 const std::string* pin_value = job_settings.FindStringKey(kSettingPinValue);
236 if (pin_value)
237 settings->set_pin_value(*pin_value);
Yuta Hijikata2f663892020-10-06 10:34:22238#endif // BUILDFLAG(IS_ASH)
Vladislav Kuzkokov48b15002019-01-30 17:13:35239
Pranav Batra636e2042020-09-03 03:35:05240 return settings;
[email protected]c95198b2014-06-12 16:56:55241}
242
243void PrintSettingsToJobSettingsDebug(const PrintSettings& settings,
244 base::DictionaryValue* job_settings) {
245 job_settings->SetBoolean(kSettingHeaderFooterEnabled,
246 settings.display_header_footer());
247 job_settings->SetString(kSettingHeaderFooterTitle, settings.title());
248 job_settings->SetString(kSettingHeaderFooterURL, settings.url());
249 job_settings->SetBoolean(kSettingShouldPrintBackgrounds,
250 settings.should_print_backgrounds());
251 job_settings->SetBoolean(kSettingShouldPrintSelectionOnly,
252 settings.selection_only());
Julie Jeongeun Kimcb00d1ab2020-08-14 07:43:32253 job_settings->SetInteger(kSettingMarginsType,
254 static_cast<int>(settings.margin_type()));
[email protected]c95198b2014-06-12 16:56:55255 if (!settings.ranges().empty()) {
Gyuyoung Kimb480aba2018-01-27 07:00:04256 auto page_range_array = std::make_unique<base::ListValue>();
[email protected]c95198b2014-06-12 16:56:55257 for (size_t i = 0; i < settings.ranges().size(); ++i) {
Gyuyoung Kimb480aba2018-01-27 07:00:04258 auto dict = std::make_unique<base::DictionaryValue>();
[email protected]c95198b2014-06-12 16:56:55259 dict->SetInteger(kSettingPageRangeFrom, settings.ranges()[i].from + 1);
260 dict->SetInteger(kSettingPageRangeTo, settings.ranges()[i].to + 1);
dcheng031a8f82016-09-08 21:04:33261 page_range_array->Append(std::move(dict));
[email protected]c95198b2014-06-12 16:56:55262 }
jdoerriecb205a52017-06-08 16:16:44263 job_settings->Set(kSettingPageRange, std::move(page_range_array));
[email protected]c95198b2014-06-12 16:56:55264 }
265
266 job_settings->SetBoolean(kSettingCollate, settings.collate());
267 job_settings->SetInteger(kSettingCopies, settings.copies());
Alan Screen3fb63bf2020-08-19 00:11:23268 job_settings->SetInteger(kSettingColor, static_cast<int>(settings.color()));
Julie Jeongeun Kime454f2602020-04-30 05:20:07269 job_settings->SetInteger(kSettingDuplexMode,
270 static_cast<int>(settings.duplex_mode()));
[email protected]c95198b2014-06-12 16:56:55271 job_settings->SetBoolean(kSettingLandscape, settings.landscape());
272 job_settings->SetString(kSettingDeviceName, settings.device_name());
xlou6bd7c2d2018-07-10 01:35:40273 job_settings->SetInteger(kSettingPagesPerSheet, settings.pages_per_sheet());
[email protected]c95198b2014-06-12 16:56:55274
275 // Following values are not read form JSON by InitSettings, so do not have
276 // common public constants. So just serialize in "debug" section.
Gyuyoung Kimb480aba2018-01-27 07:00:04277 auto debug = std::make_unique<base::DictionaryValue>();
[email protected]c95198b2014-06-12 16:56:55278 debug->SetInteger("dpi", settings.dpi());
279 debug->SetInteger("deviceUnitsPerInch", settings.device_units_per_inch());
280 debug->SetBoolean("support_alpha_blend", settings.should_print_backgrounds());
rbpotterde174102017-04-03 20:47:03281 debug->SetString("media_vendor_id", settings.requested_media().vendor_id);
jdoerriecb205a52017-06-08 16:16:44282 SetSizeToJobSettings("media_size", settings.requested_media().size_microns,
283 debug.get());
[email protected]c95198b2014-06-12 16:56:55284 SetMarginsToJobSettings("requested_custom_margins_in_points",
285 settings.requested_custom_margins_in_points(),
jdoerriecb205a52017-06-08 16:16:44286 debug.get());
[email protected]c95198b2014-06-12 16:56:55287 const PageSetup& page_setup = settings.page_setup_device_units();
jdoerriecb205a52017-06-08 16:16:44288 SetMarginsToJobSettings("effective_margins", page_setup.effective_margins(),
289 debug.get());
290 SetSizeToJobSettings("physical_size", page_setup.physical_size(),
291 debug.get());
292 SetRectToJobSettings("overlay_area", page_setup.overlay_area(), debug.get());
293 SetRectToJobSettings("content_area", page_setup.content_area(), debug.get());
294 SetRectToJobSettings("printable_area", page_setup.printable_area(),
295 debug.get());
296 job_settings->Set("debug", std::move(debug));
[email protected]c95198b2014-06-12 16:56:55297}
298
299} // namespace printing