[M120 Migration][VD] Remove accessing oom_score_adj in zygote process
[platform/framework/web/chromium-efl.git] / printing / print_settings_conversion.cc
1 // Copyright 2014 The Chromium Authors
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
7 #include <stddef.h>
8
9 #include <algorithm>
10 #include <cmath>
11 #include <memory>
12 #include <string>
13 #include <utility>
14
15 #include "base/containers/contains.h"
16 #include "base/containers/fixed_flat_set.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_piece.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/time/time.h"
21 #include "base/values.h"
22 #include "build/build_config.h"
23 #include "printing/buildflags/buildflags.h"
24 #include "printing/mojom/print.mojom.h"
25 #include "printing/print_job_constants.h"
26 #include "printing/print_settings.h"
27 #include "printing/units.h"
28 #include "third_party/abseil-cpp/absl/types/optional.h"
29 #include "ui/gfx/geometry/rect.h"
30 #include "ui/gfx/geometry/size.h"
31
32 #if BUILDFLAG(IS_CHROMEOS)
33 #include "chromeos/crosapi/mojom/local_printer.mojom.h"
34 #include "print_settings_conversion_chromeos.h"
35 #endif  // BUILDFLAG(IS_CHROMEOS)
36
37 namespace printing {
38
39 namespace {
40
41 // Note: If this code crashes, then the caller has passed in invalid `settings`.
42 // Fix the caller, instead of trying to avoid the crash here.
43 PageMargins GetCustomMarginsFromJobSettings(const base::Value::Dict& settings) {
44   PageMargins margins_in_points;
45   const base::Value::Dict* custom_margins =
46       settings.FindDict(kSettingMarginsCustom);
47   margins_in_points.top = custom_margins->FindInt(kSettingMarginTop).value();
48   margins_in_points.bottom =
49       custom_margins->FindInt(kSettingMarginBottom).value();
50   margins_in_points.left = custom_margins->FindInt(kSettingMarginLeft).value();
51   margins_in_points.right =
52       custom_margins->FindInt(kSettingMarginRight).value();
53   return margins_in_points;
54 }
55
56 void SetMarginsToJobSettings(const std::string& json_path,
57                              const PageMargins& margins,
58                              base::Value::Dict& job_settings) {
59   base::Value::Dict dict;
60   dict.Set(kSettingMarginTop, margins.top);
61   dict.Set(kSettingMarginBottom, margins.bottom);
62   dict.Set(kSettingMarginLeft, margins.left);
63   dict.Set(kSettingMarginRight, margins.right);
64   job_settings.Set(json_path, std::move(dict));
65 }
66
67 void SetSizeToJobSettings(const std::string& json_path,
68                           const gfx::Size& size,
69                           base::Value::Dict& job_settings) {
70   base::Value::Dict dict;
71   dict.Set("width", size.width());
72   dict.Set("height", size.height());
73   job_settings.Set(json_path, std::move(dict));
74 }
75
76 void SetRectToJobSettings(const std::string& json_path,
77                           const gfx::Rect& rect,
78                           base::Value::Dict& job_settings) {
79   base::Value::Dict dict;
80   dict.Set("x", rect.x());
81   dict.Set("y", rect.y());
82   dict.Set("width", rect.width());
83   dict.Set("height", rect.height());
84   job_settings.Set(json_path, std::move(dict));
85 }
86
87 void SetPrintableAreaIfValid(PrintSettings& settings,
88                              const gfx::Size& size_microns,
89                              const base::Value::Dict& media_size) {
90   absl::optional<int> left_microns =
91       media_size.FindInt(kSettingsImageableAreaLeftMicrons);
92   absl::optional<int> bottom_microns =
93       media_size.FindInt(kSettingsImageableAreaBottomMicrons);
94   absl::optional<int> right_microns =
95       media_size.FindInt(kSettingsImageableAreaRightMicrons);
96   absl::optional<int> top_microns =
97       media_size.FindInt(kSettingsImageableAreaTopMicrons);
98   if (!bottom_microns.has_value() || !left_microns.has_value() ||
99       !right_microns.has_value() || !top_microns.has_value()) {
100     return;
101   }
102
103   // Scale the page size and printable area to device units.
104   // Blink doesn't support different dpi settings in X and Y axis. Because of
105   // this, printers with non-square pixels still scale page size and printable
106   // area using device_units_per_inch() instead of their respective dimensions
107   // in device_units_per_inch_size().
108   float scale =
109       static_cast<float>(settings.device_units_per_inch()) / kMicronsPerInch;
110   gfx::Size page_size = gfx::ScaleToRoundedSize(size_microns, scale);
111   // Flip the y-axis since the imageable area origin is at the bottom-left,
112   // while the gfx::Rect origin is at the top-left.
113   gfx::Rect printable_area = gfx::ScaleToRoundedRect(
114       {left_microns.value(), size_microns.height() - top_microns.value(),
115        right_microns.value() - left_microns.value(),
116        top_microns.value() - bottom_microns.value()},
117       scale);
118   // Sanity check that the printable area makes sense.
119   if (printable_area.IsEmpty() ||
120       !gfx::Rect(page_size).Contains(printable_area)) {
121     return;
122   }
123   settings.SetPrinterPrintableArea(page_size, printable_area,
124                                    /*landscape_needs_flip=*/true);
125 }
126
127 }  // namespace
128
129 PageRanges GetPageRangesFromJobSettings(const base::Value::Dict& job_settings) {
130   PageRanges page_ranges;
131   const base::Value::List* page_range_array =
132       job_settings.FindList(kSettingPageRange);
133   if (!page_range_array) {
134     return page_ranges;
135   }
136
137   for (const base::Value& page_range : *page_range_array) {
138     if (!page_range.is_dict()) {
139       continue;
140     }
141
142     const auto& dict = page_range.GetDict();
143     absl::optional<int> from = dict.FindInt(kSettingPageRangeFrom);
144     absl::optional<int> to = dict.FindInt(kSettingPageRangeTo);
145     if (!from.has_value() || !to.has_value()) {
146       continue;
147     }
148
149     // Page numbers are 1-based in the dictionary.
150     // Page numbers are 0-based for the printing context.
151     page_ranges.push_back(PageRange{static_cast<uint32_t>(from.value() - 1),
152                                     static_cast<uint32_t>(to.value() - 1)});
153   }
154   return page_ranges;
155 }
156
157 std::unique_ptr<PrintSettings> PrintSettingsFromJobSettings(
158     const base::Value::Dict& job_settings) {
159   auto settings = std::make_unique<PrintSettings>();
160   absl::optional<bool> display_header_footer =
161       job_settings.FindBool(kSettingHeaderFooterEnabled);
162   if (!display_header_footer.has_value()) {
163     return nullptr;
164   }
165
166   settings->set_display_header_footer(display_header_footer.value());
167   if (settings->display_header_footer()) {
168     const std::string* title =
169         job_settings.FindString(kSettingHeaderFooterTitle);
170     const std::string* url = job_settings.FindString(kSettingHeaderFooterURL);
171     if (!title || !url) {
172       return nullptr;
173     }
174
175     settings->set_title(base::UTF8ToUTF16(*title));
176     settings->set_url(base::UTF8ToUTF16(*url));
177   }
178
179   absl::optional<bool> backgrounds =
180       job_settings.FindBool(kSettingShouldPrintBackgrounds);
181   absl::optional<bool> selection_only =
182       job_settings.FindBool(kSettingShouldPrintSelectionOnly);
183   if (!backgrounds.has_value() || !selection_only.has_value()) {
184     return nullptr;
185   }
186
187   settings->set_should_print_backgrounds(backgrounds.value());
188   settings->set_selection_only(selection_only.value());
189
190   absl::optional<bool> collate = job_settings.FindBool(kSettingCollate);
191   absl::optional<int> copies = job_settings.FindInt(kSettingCopies);
192   absl::optional<int> color = job_settings.FindInt(kSettingColor);
193   absl::optional<int> duplex_mode = job_settings.FindInt(kSettingDuplexMode);
194   absl::optional<bool> landscape = job_settings.FindBool(kSettingLandscape);
195   const std::string* device_name = job_settings.FindString(kSettingDeviceName);
196   absl::optional<int> scale_factor = job_settings.FindInt(kSettingScaleFactor);
197   absl::optional<bool> rasterize_pdf =
198       job_settings.FindBool(kSettingRasterizePdf);
199   absl::optional<int> pages_per_sheet =
200       job_settings.FindInt(kSettingPagesPerSheet);
201   if (!collate.has_value() || !copies.has_value() || !color.has_value() ||
202       !duplex_mode.has_value() || !landscape.has_value() || !device_name ||
203       !scale_factor.has_value() || !rasterize_pdf.has_value() ||
204       !pages_per_sheet.has_value()) {
205     return nullptr;
206   }
207   settings->set_collate(collate.value());
208   settings->set_copies(copies.value());
209   settings->SetOrientation(landscape.value());
210   settings->set_device_name(base::UTF8ToUTF16(*device_name));
211   settings->set_duplex_mode(
212       static_cast<mojom::DuplexMode>(duplex_mode.value()));
213   settings->set_color(static_cast<mojom::ColorModel>(color.value()));
214   settings->set_scale_factor(static_cast<double>(scale_factor.value()) / 100.0);
215   settings->set_rasterize_pdf(rasterize_pdf.value());
216   settings->set_pages_per_sheet(pages_per_sheet.value());
217
218   absl::optional<int> dpi_horizontal =
219       job_settings.FindInt(kSettingDpiHorizontal);
220   absl::optional<int> dpi_vertical = job_settings.FindInt(kSettingDpiVertical);
221   if (!dpi_horizontal.has_value() || !dpi_vertical.has_value()) {
222     return nullptr;
223   }
224
225   settings->set_dpi_xy(dpi_horizontal.value(), dpi_vertical.value());
226
227   absl::optional<int> rasterize_pdf_dpi =
228       job_settings.FindInt(kSettingRasterizePdfDpi);
229   if (rasterize_pdf_dpi.has_value()) {
230     settings->set_rasterize_pdf_dpi(rasterize_pdf_dpi.value());
231   }
232
233   // Set margin type before setting printable area. `SetPrintableAreaIfValid()`
234   // calls `PrintSettings::SetPrinterPrintableArea()`, which requires the margin
235   // type to be set first.
236   mojom::MarginType margin_type = static_cast<mojom::MarginType>(
237       job_settings.FindInt(kSettingMarginsType)
238           .value_or(static_cast<int>(mojom::MarginType::kDefaultMargins)));
239   if (margin_type < mojom::MarginType::kMinValue ||
240       margin_type > mojom::MarginType::kMaxValue) {
241     margin_type = mojom::MarginType::kDefaultMargins;
242   }
243   settings->set_margin_type(margin_type);
244
245   if (margin_type == mojom::MarginType::kCustomMargins) {
246     settings->SetCustomMargins(GetCustomMarginsFromJobSettings(job_settings));
247   }
248
249   PrintSettings::RequestedMedia requested_media;
250   const base::Value::Dict* media_size_value =
251       job_settings.FindDict(kSettingMediaSize);
252   if (media_size_value) {
253     absl::optional<int> width_microns =
254         media_size_value->FindInt(kSettingMediaSizeWidthMicrons);
255     absl::optional<int> height_microns =
256         media_size_value->FindInt(kSettingMediaSizeHeightMicrons);
257     if (width_microns.has_value() && height_microns.has_value()) {
258       requested_media.size_microns =
259           gfx::Size(width_microns.value(), height_microns.value());
260       SetPrintableAreaIfValid(*settings, requested_media.size_microns,
261                               *media_size_value);
262     }
263
264     const std::string* vendor_id =
265         media_size_value->FindString(kSettingMediaSizeVendorId);
266     if (vendor_id && !vendor_id->empty()) {
267       requested_media.vendor_id = *vendor_id;
268     }
269   }
270   settings->set_requested_media(requested_media);
271
272   absl::optional<bool> borderless = job_settings.FindBool(kSettingBorderless);
273   if (borderless.has_value()) {
274     settings->set_borderless(borderless.value());
275   }
276
277   const std::string* media_type = job_settings.FindString(kSettingMediaType);
278   if (media_type && !media_type->empty()) {
279     settings->set_media_type(*media_type);
280   }
281
282   settings->set_ranges(GetPageRangesFromJobSettings(job_settings));
283
284   absl::optional<bool> is_modifiable =
285       job_settings.FindBool(kSettingPreviewModifiable);
286   if (is_modifiable.has_value()) {
287     settings->set_is_modifiable(is_modifiable.value());
288   }
289
290 #if BUILDFLAG(IS_CHROMEOS) || (BUILDFLAG(IS_LINUX) && BUILDFLAG(USE_CUPS))
291   const base::Value::Dict* advanced_settings =
292       job_settings.FindDict(kSettingAdvancedSettings);
293   if (advanced_settings) {
294     for (const auto item : *advanced_settings) {
295       static constexpr auto kNonJobAttributes =
296           base::MakeFixedFlatSet<base::StringPiece>(
297               {"printer-info", "printer-make-and-model", "system_driverinfo"});
298       if (!base::Contains(kNonJobAttributes, item.first)) {
299         settings->advanced_settings().emplace(item.first, item.second.Clone());
300       }
301     }
302   }
303 #endif  // BUILDFLAG(IS_CHROMEOS) || (BUILDFLAG(IS_LINUX) &&
304         // BUILDFLAG(USE_CUPS))
305
306 #if BUILDFLAG(IS_CHROMEOS)
307   bool send_user_info =
308       job_settings.FindBool(kSettingSendUserInfo).value_or(false);
309   settings->set_send_user_info(send_user_info);
310   if (send_user_info) {
311     const std::string* username = job_settings.FindString(kSettingUsername);
312     if (username) {
313       settings->set_username(*username);
314     }
315   }
316
317   const std::string* oauth_token =
318       job_settings.FindString(kSettingChromeOSAccessOAuthToken);
319   if (oauth_token) {
320     settings->set_oauth_token(*oauth_token);
321   }
322
323   const std::string* pin_value = job_settings.FindString(kSettingPinValue);
324   if (pin_value) {
325     settings->set_pin_value(*pin_value);
326   }
327
328   const base::Value::List* client_info_list =
329       job_settings.FindList(kSettingIppClientInfo);
330   if (client_info_list) {
331     settings->set_client_infos(
332         ConvertJobSettingToClientInfo(*client_info_list));
333   }
334
335   settings->set_printer_manually_selected(
336       job_settings.FindBool(kSettingPrinterManuallySelected).value_or(false));
337
338   absl::optional<int> reason =
339       job_settings.FindInt(kSettingPrinterStatusReason);
340   if (reason.has_value()) {
341     settings->set_printer_status_reason(
342         static_cast<crosapi::mojom::StatusReason::Reason>(reason.value()));
343   }
344 #endif  // BUILDFLAG(IS_CHROMEOS)
345
346   return settings;
347 }
348
349 base::Value::Dict PrintSettingsToJobSettingsDebug(
350     const PrintSettings& settings) {
351   base::Value::Dict job_settings;
352
353   job_settings.Set(kSettingHeaderFooterEnabled,
354                    settings.display_header_footer());
355   job_settings.Set(kSettingHeaderFooterTitle, settings.title());
356   job_settings.Set(kSettingHeaderFooterURL, settings.url());
357   job_settings.Set(kSettingShouldPrintBackgrounds,
358                    settings.should_print_backgrounds());
359   job_settings.Set(kSettingShouldPrintSelectionOnly, settings.selection_only());
360   job_settings.Set(kSettingMarginsType,
361                    static_cast<int>(settings.margin_type()));
362   if (!settings.ranges().empty()) {
363     base::Value::List page_range_array;
364     for (const auto& range : settings.ranges()) {
365       base::Value::Dict dict;
366       dict.Set(kSettingPageRangeFrom, static_cast<int>(range.from + 1));
367       dict.Set(kSettingPageRangeTo, static_cast<int>(range.to + 1));
368       page_range_array.Append(std::move(dict));
369     }
370     job_settings.Set(kSettingPageRange, std::move(page_range_array));
371   }
372
373   job_settings.Set(kSettingCollate, settings.collate());
374   job_settings.Set(kSettingCopies, settings.copies());
375   job_settings.Set(kSettingColor, static_cast<int>(settings.color()));
376   job_settings.Set(kSettingDuplexMode,
377                    static_cast<int>(settings.duplex_mode()));
378   job_settings.Set(kSettingLandscape, settings.landscape());
379   job_settings.Set(kSettingDeviceName, settings.device_name());
380   job_settings.Set(kSettingDpiHorizontal, settings.dpi_horizontal());
381   job_settings.Set(kSettingDpiVertical, settings.dpi_vertical());
382   job_settings.Set(kSettingScaleFactor,
383                    static_cast<int>((settings.scale_factor() * 100.0) + 0.5));
384   job_settings.Set(kSettingRasterizePdf, settings.rasterize_pdf());
385   job_settings.Set(kSettingPagesPerSheet, settings.pages_per_sheet());
386
387   // Following values are not read form JSON by InitSettings, so do not have
388   // common public constants. So just serialize in "debug" section.
389   base::Value::Dict debug;
390   debug.Set("dpi", settings.dpi());
391   debug.Set("deviceUnitsPerInch", settings.device_units_per_inch());
392   debug.Set("support_alpha_blend", settings.should_print_backgrounds());
393   debug.Set("media_vendor_id", settings.requested_media().vendor_id);
394   SetSizeToJobSettings("media_size", settings.requested_media().size_microns,
395                        debug);
396   SetMarginsToJobSettings("requested_custom_margins_in_points",
397                           settings.requested_custom_margins_in_points(), debug);
398   const PageSetup& page_setup = settings.page_setup_device_units();
399   SetMarginsToJobSettings("effective_margins", page_setup.effective_margins(),
400                           debug);
401   SetSizeToJobSettings("physical_size", page_setup.physical_size(), debug);
402   SetRectToJobSettings("overlay_area", page_setup.overlay_area(), debug);
403   SetRectToJobSettings("content_area", page_setup.content_area(), debug);
404   SetRectToJobSettings("printable_area", page_setup.printable_area(), debug);
405   job_settings.Set("debug", std::move(debug));
406
407 #if BUILDFLAG(IS_CHROMEOS)
408   job_settings.Set(kSettingIppClientInfo,
409                    ConvertClientInfoToJobSetting(settings.client_infos()));
410 #endif  // BUILDFLAG(IS_CHROMEOS)
411
412   return job_settings;
413 }
414
415 }  // namespace printing