[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 1 | // 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 | |
avi | 126e93c | 2015-12-21 21:48:16 | [diff] [blame] | 7 | #include <stddef.h> |
| 8 | |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 9 | #include <algorithm> |
| 10 | #include <cmath> |
dcheng | 031a8f8 | 2016-09-08 21:04:33 | [diff] [blame] | 11 | #include <memory> |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 12 | #include <string> |
dcheng | 031a8f8 | 2016-09-08 21:04:33 | [diff] [blame] | 13 | #include <utility> |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 14 | |
| 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 Li | 02720a4 | 2017-10-25 22:06:48 | [diff] [blame] | 19 | #include "build/build_config.h" |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 20 | #include "printing/print_job_constants.h" |
| 21 | #include "printing/print_settings.h" |
| 22 | #include "printing/units.h" |
| 23 | |
| 24 | namespace printing { |
| 25 | |
| 26 | namespace { |
| 27 | |
Lei Zhang | c8553b4 | 2019-08-07 19:13:46 | [diff] [blame] | 28 | // Note: If this code crashes, then the caller has passed in invalid |settings|. |
| 29 | // Fix the caller, instead of trying to avoid the crash here. |
| 30 | PageMargins GetCustomMarginsFromJobSettings(const base::Value& settings) { |
| 31 | PageMargins margins_in_points; |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 32 | const base::Value* custom_margins = settings.FindKey(kSettingMarginsCustom); |
Lei Zhang | c8553b4 | 2019-08-07 19:13:46 | [diff] [blame] | 33 | margins_in_points.top = custom_margins->FindIntKey(kSettingMarginTop).value(); |
| 34 | margins_in_points.bottom = |
| 35 | custom_margins->FindIntKey(kSettingMarginBottom).value(); |
| 36 | margins_in_points.left = |
| 37 | custom_margins->FindIntKey(kSettingMarginLeft).value(); |
| 38 | margins_in_points.right = |
| 39 | custom_margins->FindIntKey(kSettingMarginRight).value(); |
| 40 | return margins_in_points; |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | void SetMarginsToJobSettings(const std::string& json_path, |
| 44 | const PageMargins& margins, |
| 45 | base::DictionaryValue* job_settings) { |
Gyuyoung Kim | b480aba | 2018-01-27 07:00:04 | [diff] [blame] | 46 | auto dict = std::make_unique<base::DictionaryValue>(); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 47 | dict->SetInteger(kSettingMarginTop, margins.top); |
| 48 | dict->SetInteger(kSettingMarginBottom, margins.bottom); |
| 49 | dict->SetInteger(kSettingMarginLeft, margins.left); |
| 50 | dict->SetInteger(kSettingMarginRight, margins.right); |
jdoerrie | cb205a5 | 2017-06-08 16:16:44 | [diff] [blame] | 51 | job_settings->Set(json_path, std::move(dict)); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 52 | } |
| 53 | |
| 54 | void SetSizeToJobSettings(const std::string& json_path, |
| 55 | const gfx::Size& size, |
| 56 | base::DictionaryValue* job_settings) { |
Gyuyoung Kim | b480aba | 2018-01-27 07:00:04 | [diff] [blame] | 57 | auto dict = std::make_unique<base::DictionaryValue>(); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 58 | dict->SetInteger("width", size.width()); |
| 59 | dict->SetInteger("height", size.height()); |
jdoerrie | cb205a5 | 2017-06-08 16:16:44 | [diff] [blame] | 60 | job_settings->Set(json_path, std::move(dict)); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | void SetRectToJobSettings(const std::string& json_path, |
| 64 | const gfx::Rect& rect, |
| 65 | base::DictionaryValue* job_settings) { |
Gyuyoung Kim | b480aba | 2018-01-27 07:00:04 | [diff] [blame] | 66 | auto dict = std::make_unique<base::DictionaryValue>(); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 67 | dict->SetInteger("x", rect.x()); |
| 68 | dict->SetInteger("y", rect.y()); |
| 69 | dict->SetInteger("width", rect.width()); |
| 70 | dict->SetInteger("height", rect.height()); |
jdoerrie | cb205a5 | 2017-06-08 16:16:44 | [diff] [blame] | 71 | job_settings->Set(json_path, std::move(dict)); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 72 | } |
| 73 | |
| 74 | } // namespace |
| 75 | |
Jesse Schettler | a092a99c | 2019-11-06 15:21:27 | [diff] [blame^] | 76 | PageRanges GetPageRangesFromJobSettings(const base::Value& job_settings) { |
| 77 | PageRanges page_ranges; |
| 78 | const base::Value* page_range_array = |
| 79 | job_settings.FindListKey(kSettingPageRange); |
| 80 | if (page_range_array) { |
| 81 | for (const base::Value& page_range : page_range_array->GetList()) { |
| 82 | if (!page_range.is_dict()) |
| 83 | continue; |
| 84 | |
| 85 | base::Optional<int> from = page_range.FindIntKey(kSettingPageRangeFrom); |
| 86 | base::Optional<int> to = page_range.FindIntKey(kSettingPageRangeTo); |
| 87 | if (!from.has_value() || !to.has_value()) |
| 88 | continue; |
| 89 | |
| 90 | // Page numbers are 1-based in the dictionary. |
| 91 | // Page numbers are 0-based for the printing context. |
| 92 | page_ranges.push_back(PageRange{from.value() - 1, to.value() - 1}); |
| 93 | } |
| 94 | } |
| 95 | return page_ranges; |
| 96 | } |
| 97 | |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 98 | bool PrintSettingsFromJobSettings(const base::Value& job_settings, |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 99 | PrintSettings* settings) { |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 100 | base::Optional<bool> display_header_footer = |
| 101 | job_settings.FindBoolKey(kSettingHeaderFooterEnabled); |
| 102 | if (!display_header_footer.has_value()) |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 103 | return false; |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 104 | |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 105 | settings->set_display_header_footer(display_header_footer.value()); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 106 | if (settings->display_header_footer()) { |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 107 | const std::string* title = |
| 108 | job_settings.FindStringKey(kSettingHeaderFooterTitle); |
| 109 | const std::string* url = |
| 110 | job_settings.FindStringKey(kSettingHeaderFooterURL); |
| 111 | if (!title || !url) |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 112 | return false; |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 113 | |
| 114 | settings->set_title(base::UTF8ToUTF16(*title)); |
| 115 | settings->set_url(base::UTF8ToUTF16(*url)); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 116 | } |
| 117 | |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 118 | base::Optional<bool> backgrounds = |
| 119 | job_settings.FindBoolKey(kSettingShouldPrintBackgrounds); |
| 120 | base::Optional<bool> selection_only = |
| 121 | job_settings.FindBoolKey(kSettingShouldPrintSelectionOnly); |
| 122 | if (!backgrounds.has_value() || !selection_only.has_value()) |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 123 | return false; |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 124 | |
| 125 | settings->set_should_print_backgrounds(backgrounds.value()); |
| 126 | settings->set_selection_only(selection_only.value()); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 127 | |
| 128 | PrintSettings::RequestedMedia requested_media; |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 129 | const base::Value* media_size_value = job_settings.FindKeyOfType( |
| 130 | kSettingMediaSize, base::Value::Type::DICTIONARY); |
| 131 | if (media_size_value) { |
| 132 | base::Optional<int> width_microns = |
| 133 | media_size_value->FindIntKey(kSettingMediaSizeWidthMicrons); |
| 134 | base::Optional<int> height_microns = |
| 135 | media_size_value->FindIntKey(kSettingMediaSizeHeightMicrons); |
| 136 | if (width_microns.has_value() && height_microns.has_value()) { |
| 137 | requested_media.size_microns = |
| 138 | gfx::Size(width_microns.value(), height_microns.value()); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 139 | } |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 140 | |
| 141 | const std::string* vendor_id = |
| 142 | media_size_value->FindStringKey(kSettingMediaSizeVendorId); |
| 143 | if (vendor_id && !vendor_id->empty()) |
| 144 | requested_media.vendor_id = *vendor_id; |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 145 | } |
| 146 | settings->set_requested_media(requested_media); |
| 147 | |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 148 | int margin_type = |
| 149 | job_settings.FindIntKey(kSettingMarginsType).value_or(DEFAULT_MARGINS); |
| 150 | if (margin_type != DEFAULT_MARGINS && margin_type != NO_MARGINS && |
| 151 | margin_type != CUSTOM_MARGINS && margin_type != PRINTABLE_AREA_MARGINS) { |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 152 | margin_type = DEFAULT_MARGINS; |
| 153 | } |
| 154 | settings->set_margin_type(static_cast<MarginType>(margin_type)); |
| 155 | |
Lei Zhang | c8553b4 | 2019-08-07 19:13:46 | [diff] [blame] | 156 | if (margin_type == CUSTOM_MARGINS) |
| 157 | settings->SetCustomMargins(GetCustomMarginsFromJobSettings(job_settings)); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 158 | |
Jesse Schettler | a092a99c | 2019-11-06 15:21:27 | [diff] [blame^] | 159 | settings->set_ranges(GetPageRangesFromJobSettings(job_settings)); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 160 | |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 161 | base::Optional<bool> collate = job_settings.FindBoolKey(kSettingCollate); |
| 162 | base::Optional<int> copies = job_settings.FindIntKey(kSettingCopies); |
| 163 | base::Optional<int> color = job_settings.FindIntKey(kSettingColor); |
| 164 | base::Optional<int> duplex_mode = job_settings.FindIntKey(kSettingDuplexMode); |
| 165 | base::Optional<bool> landscape = job_settings.FindBoolKey(kSettingLandscape); |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 166 | base::Optional<int> scale_factor = |
| 167 | job_settings.FindIntKey(kSettingScaleFactor); |
| 168 | base::Optional<bool> rasterize_pdf = |
| 169 | job_settings.FindBoolKey(kSettingRasterizePdf); |
| 170 | base::Optional<int> pages_per_sheet = |
| 171 | job_settings.FindIntKey(kSettingPagesPerSheet); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 172 | |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 173 | if (!collate.has_value() || !copies.has_value() || !color.has_value() || |
Lei Zhang | dfe53f9 | 2019-10-11 05:41:07 | [diff] [blame] | 174 | !duplex_mode.has_value() || !landscape.has_value() || |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 175 | !scale_factor.has_value() || !rasterize_pdf.has_value() || |
| 176 | !pages_per_sheet.has_value()) { |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 177 | return false; |
| 178 | } |
rbpotter | 116c2e1 | 2017-04-04 19:21:28 | [diff] [blame] | 179 | #if defined(OS_WIN) |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 180 | base::Optional<int> dpi_horizontal = |
| 181 | job_settings.FindIntKey(kSettingDpiHorizontal); |
| 182 | base::Optional<int> dpi_vertical = |
| 183 | job_settings.FindIntKey(kSettingDpiVertical); |
| 184 | if (!dpi_horizontal.has_value() || !dpi_vertical.has_value()) |
rbpotter | 116c2e1 | 2017-04-04 19:21:28 | [diff] [blame] | 185 | return false; |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 186 | |
| 187 | settings->set_dpi_xy(dpi_horizontal.value(), dpi_vertical.value()); |
rbpotter | 116c2e1 | 2017-04-04 19:21:28 | [diff] [blame] | 188 | #endif |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 189 | |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 190 | settings->set_collate(collate.value()); |
| 191 | settings->set_copies(copies.value()); |
| 192 | settings->SetOrientation(landscape.value()); |
Lei Zhang | dfe53f9 | 2019-10-11 05:41:07 | [diff] [blame] | 193 | settings->set_device_name( |
| 194 | base::UTF8ToUTF16(*job_settings.FindStringKey(kSettingDeviceName))); |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 195 | settings->set_duplex_mode(static_cast<DuplexMode>(duplex_mode.value())); |
| 196 | settings->set_color(static_cast<ColorModel>(color.value())); |
| 197 | settings->set_scale_factor(static_cast<double>(scale_factor.value()) / 100.0); |
| 198 | settings->set_rasterize_pdf(rasterize_pdf.value()); |
| 199 | settings->set_pages_per_sheet(pages_per_sheet.value()); |
| 200 | base::Optional<bool> is_modifiable = |
| 201 | job_settings.FindBoolKey(kSettingPreviewModifiable); |
| 202 | if (is_modifiable.has_value()) { |
| 203 | settings->set_is_modifiable(is_modifiable.value()); |
thestig | e85e6b6 | 2016-08-25 00:00:06 | [diff] [blame] | 204 | #if defined(OS_WIN) |
Vladislav Kuzkokov | 490ab0c | 2019-01-16 11:21:57 | [diff] [blame] | 205 | settings->set_print_text_with_gdi(is_modifiable.value()); |
thestig | e85e6b6 | 2016-08-25 00:00:06 | [diff] [blame] | 206 | #endif |
Wei Li | 02720a4 | 2017-10-25 22:06:48 | [diff] [blame] | 207 | } |
Vladislav Kuzkokov | 48b1500 | 2019-01-30 17:13:35 | [diff] [blame] | 208 | |
| 209 | #if defined(OS_CHROMEOS) |
| 210 | bool send_user_info = |
| 211 | job_settings.FindBoolKey(kSettingSendUserInfo).value_or(false); |
| 212 | settings->set_send_user_info(send_user_info); |
| 213 | if (send_user_info) { |
| 214 | const std::string* username = job_settings.FindStringKey(kSettingUsername); |
| 215 | if (username) |
| 216 | settings->set_username(*username); |
| 217 | } |
Nikita Podguzov | c1bf3f8 | 2019-03-19 15:23:23 | [diff] [blame] | 218 | |
| 219 | const std::string* pin_value = job_settings.FindStringKey(kSettingPinValue); |
| 220 | if (pin_value) |
| 221 | settings->set_pin_value(*pin_value); |
Vladislav Kuzkokov | d4e4ff3 | 2019-09-13 11:55:56 | [diff] [blame] | 222 | |
| 223 | const base::Value* advanced_settings = |
| 224 | job_settings.FindDictKey(kSettingAdvancedSettings); |
| 225 | if (advanced_settings) { |
| 226 | for (const auto& item : advanced_settings->DictItems()) |
| 227 | settings->advanced_settings().emplace(item.first, item.second.Clone()); |
| 228 | } |
Vladislav Kuzkokov | 48b1500 | 2019-01-30 17:13:35 | [diff] [blame] | 229 | #endif |
| 230 | |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 231 | return true; |
| 232 | } |
| 233 | |
| 234 | void PrintSettingsToJobSettingsDebug(const PrintSettings& settings, |
| 235 | base::DictionaryValue* job_settings) { |
| 236 | job_settings->SetBoolean(kSettingHeaderFooterEnabled, |
| 237 | settings.display_header_footer()); |
| 238 | job_settings->SetString(kSettingHeaderFooterTitle, settings.title()); |
| 239 | job_settings->SetString(kSettingHeaderFooterURL, settings.url()); |
| 240 | job_settings->SetBoolean(kSettingShouldPrintBackgrounds, |
| 241 | settings.should_print_backgrounds()); |
| 242 | job_settings->SetBoolean(kSettingShouldPrintSelectionOnly, |
| 243 | settings.selection_only()); |
| 244 | job_settings->SetInteger(kSettingMarginsType, settings.margin_type()); |
| 245 | if (!settings.ranges().empty()) { |
Gyuyoung Kim | b480aba | 2018-01-27 07:00:04 | [diff] [blame] | 246 | auto page_range_array = std::make_unique<base::ListValue>(); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 247 | for (size_t i = 0; i < settings.ranges().size(); ++i) { |
Gyuyoung Kim | b480aba | 2018-01-27 07:00:04 | [diff] [blame] | 248 | auto dict = std::make_unique<base::DictionaryValue>(); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 249 | dict->SetInteger(kSettingPageRangeFrom, settings.ranges()[i].from + 1); |
| 250 | dict->SetInteger(kSettingPageRangeTo, settings.ranges()[i].to + 1); |
dcheng | 031a8f8 | 2016-09-08 21:04:33 | [diff] [blame] | 251 | page_range_array->Append(std::move(dict)); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 252 | } |
jdoerrie | cb205a5 | 2017-06-08 16:16:44 | [diff] [blame] | 253 | job_settings->Set(kSettingPageRange, std::move(page_range_array)); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 254 | } |
| 255 | |
| 256 | job_settings->SetBoolean(kSettingCollate, settings.collate()); |
| 257 | job_settings->SetInteger(kSettingCopies, settings.copies()); |
| 258 | job_settings->SetInteger(kSettingColor, settings.color()); |
| 259 | job_settings->SetInteger(kSettingDuplexMode, settings.duplex_mode()); |
| 260 | job_settings->SetBoolean(kSettingLandscape, settings.landscape()); |
| 261 | job_settings->SetString(kSettingDeviceName, settings.device_name()); |
xlou | 6bd7c2d | 2018-07-10 01:35:40 | [diff] [blame] | 262 | job_settings->SetInteger(kSettingPagesPerSheet, settings.pages_per_sheet()); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 263 | |
| 264 | // Following values are not read form JSON by InitSettings, so do not have |
| 265 | // common public constants. So just serialize in "debug" section. |
Gyuyoung Kim | b480aba | 2018-01-27 07:00:04 | [diff] [blame] | 266 | auto debug = std::make_unique<base::DictionaryValue>(); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 267 | debug->SetInteger("dpi", settings.dpi()); |
| 268 | debug->SetInteger("deviceUnitsPerInch", settings.device_units_per_inch()); |
| 269 | debug->SetBoolean("support_alpha_blend", settings.should_print_backgrounds()); |
rbpotter | de17410 | 2017-04-03 20:47:03 | [diff] [blame] | 270 | debug->SetString("media_vendor_id", settings.requested_media().vendor_id); |
jdoerrie | cb205a5 | 2017-06-08 16:16:44 | [diff] [blame] | 271 | SetSizeToJobSettings("media_size", settings.requested_media().size_microns, |
| 272 | debug.get()); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 273 | SetMarginsToJobSettings("requested_custom_margins_in_points", |
| 274 | settings.requested_custom_margins_in_points(), |
jdoerrie | cb205a5 | 2017-06-08 16:16:44 | [diff] [blame] | 275 | debug.get()); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 276 | const PageSetup& page_setup = settings.page_setup_device_units(); |
jdoerrie | cb205a5 | 2017-06-08 16:16:44 | [diff] [blame] | 277 | SetMarginsToJobSettings("effective_margins", page_setup.effective_margins(), |
| 278 | debug.get()); |
| 279 | SetSizeToJobSettings("physical_size", page_setup.physical_size(), |
| 280 | debug.get()); |
| 281 | SetRectToJobSettings("overlay_area", page_setup.overlay_area(), debug.get()); |
| 282 | SetRectToJobSettings("content_area", page_setup.content_area(), debug.get()); |
| 283 | SetRectToJobSettings("printable_area", page_setup.printable_area(), |
| 284 | debug.get()); |
| 285 | job_settings->Set("debug", std::move(debug)); |
[email protected] | c95198b | 2014-06-12 16:56:55 | [diff] [blame] | 286 | } |
| 287 | |
| 288 | } // namespace printing |