[M120 Migration][VD] Remove accessing oom_score_adj in zygote process
[platform/framework/web/chromium-efl.git] / printing / printing_context_system_dialog_win.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/printing_context_system_dialog_win.h"
6
7 #include <utility>
8
9 #include "base/auto_reset.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/task/current_thread.h"
12 #include "printing/backend/win_helper.h"
13 #include "printing/buildflags/buildflags.h"
14 #include "printing/mojom/print.mojom.h"
15 #include "printing/print_settings_initializer_win.h"
16 #include "skia/ext/skia_utils_win.h"
17
18 #if BUILDFLAG(ENABLE_OOP_PRINTING)
19 #include "printing/printing_features.h"
20 #endif
21
22 namespace printing {
23
24 HWND PrintingContextSystemDialogWin::GetWindow() {
25 #if BUILDFLAG(ENABLE_OOP_PRINTING)
26   if (features::ShouldPrintJobOop()) {
27     // Delving through the view tree to get to root window happens separately
28     // in the browser process (i.e., not in `PrintingContextSystemDialogWin`)
29     // before sending the identified window owner to the Print Backend service.
30     // This means that this call is happening in the service, and thus should
31     // just use the parent view as-is instead of looking for the root window.
32     // TODO(crbug.com/809738)  Pursue having a service-level instantiation of
33     // `PrintingContextSystemDialogWin` for this behavior.  That would ensure
34     // this logic would be compile-time driven and only invoked by the service.
35     return reinterpret_cast<HWND>(delegate_->GetParentView());
36   }
37 #endif
38   return GetRootWindow(delegate_->GetParentView());
39 }
40
41 PrintingContextSystemDialogWin::PrintingContextSystemDialogWin(
42     Delegate* delegate)
43     : PrintingContextWin(delegate) {}
44
45 PrintingContextSystemDialogWin::~PrintingContextSystemDialogWin() {}
46
47 void PrintingContextSystemDialogWin::AskUserForSettings(
48     int max_pages,
49     bool has_selection,
50     bool is_scripted,
51     PrintSettingsCallback callback) {
52   DCHECK(!in_print_job_);
53
54   HWND window = GetWindow();
55   DCHECK(window);
56
57   // Show the OS-dependent dialog box.
58   // If the user press
59   // - OK, the settings are reset and reinitialized with the new settings. OK is
60   //   returned.
61   // - Apply then Cancel, the settings are reset and reinitialized with the new
62   //   settings. CANCEL is returned.
63   // - Cancel, the settings are not changed, the previous setting, if it was
64   //   initialized before, are kept. CANCEL is returned.
65   // On failure, the settings are reset and FAILED is returned.
66   PRINTDLGEX dialog_options = {sizeof(PRINTDLGEX)};
67   dialog_options.hwndOwner = window;
68   // Disable options we don't support currently.
69   // TODO(maruel):  Reuse the previously loaded settings!
70   dialog_options.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE |
71                          PD_NOCURRENTPAGE | PD_HIDEPRINTTOFILE;
72   if (!has_selection)
73     dialog_options.Flags |= PD_NOSELECTION;
74
75   PRINTPAGERANGE ranges[32];
76   dialog_options.nStartPage = START_PAGE_GENERAL;
77   if (max_pages) {
78     // Default initialize to print all the pages.
79     memset(ranges, 0, sizeof(ranges));
80     ranges[0].nFromPage = 1;
81     ranges[0].nToPage = max_pages;
82     dialog_options.nPageRanges = 1;
83     dialog_options.nMaxPageRanges = std::size(ranges);
84     dialog_options.nMinPage = 1;
85     dialog_options.nMaxPage = max_pages;
86     dialog_options.lpPageRanges = ranges;
87   } else {
88     // No need to bother, we don't know how many pages are available.
89     dialog_options.Flags |= PD_NOPAGENUMS;
90   }
91
92   if (ShowPrintDialog(&dialog_options) != S_OK) {
93     ResetSettings();
94     std::move(callback).Run(mojom::ResultCode::kFailed);
95     return;
96   }
97
98   // TODO(maruel):  Support PD_PRINTTOFILE.
99   std::move(callback).Run(ParseDialogResultEx(dialog_options));
100 }
101
102 HRESULT PrintingContextSystemDialogWin::ShowPrintDialog(PRINTDLGEX* options) {
103   // Runs always on the UI thread.
104   static bool is_dialog_shown = false;
105   if (is_dialog_shown)
106     return E_FAIL;
107   // Block opening dialog from nested task. It crashes PrintDlgEx.
108   base::AutoReset<bool> auto_reset(&is_dialog_shown, true);
109
110   // Note that this cannot use ui::BaseShellDialog as the print dialog is
111   // system modal: opening it from a background thread can cause Windows to
112   // get the wrong Z-order which will make the print dialog appear behind the
113   // browser frame (but still being modal) so neither the browser frame nor
114   // the print dialog will get any input. See http://crbug.com/342697
115   // http://crbug.com/180997 for details.
116   base::CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop allow;
117
118   return PrintDlgEx(options);
119 }
120
121 bool PrintingContextSystemDialogWin::InitializeSettingsWithRanges(
122     const DEVMODE& dev_mode,
123     const std::wstring& new_device_name,
124     const PRINTPAGERANGE* ranges,
125     int number_ranges,
126     bool selection_only) {
127   DCHECK(GetDeviceCaps(context(), CLIPCAPS));
128   DCHECK(GetDeviceCaps(context(), RASTERCAPS) & RC_STRETCHDIB);
129   DCHECK(GetDeviceCaps(context(), RASTERCAPS) & RC_BITMAP64);
130   // Some printers don't advertise these.
131   // DCHECK(GetDeviceCaps(context(), RASTERCAPS) & RC_SCALING);
132   // DCHECK(GetDeviceCaps(context(), SHADEBLENDCAPS) & SB_CONST_ALPHA);
133   // DCHECK(GetDeviceCaps(context(), SHADEBLENDCAPS) & SB_PIXEL_ALPHA);
134
135   // StretchDIBits() support is needed for printing.
136   if (!(GetDeviceCaps(context(), RASTERCAPS) & RC_STRETCHDIB) ||
137       !(GetDeviceCaps(context(), RASTERCAPS) & RC_BITMAP64)) {
138     NOTREACHED();
139     ResetSettings();
140     return false;
141   }
142
143   DCHECK(!in_print_job_);
144   DCHECK(context());
145   PageRanges ranges_vector;
146   if (!selection_only) {
147     // Convert the PRINTPAGERANGE array to a PrintSettings::PageRanges vector.
148     ranges_vector.reserve(number_ranges);
149     for (int i = 0; i < number_ranges; ++i) {
150       PageRange range;
151       // Transfer from 1-based to 0-based.
152       range.from = ranges[i].nFromPage - 1;
153       range.to = ranges[i].nToPage - 1;
154       ranges_vector.push_back(range);
155     }
156   }
157
158   settings_->set_ranges(ranges_vector);
159   settings_->set_device_name(base::WideToUTF16(new_device_name));
160   settings_->set_selection_only(selection_only);
161   PrintSettingsInitializerWin::InitPrintSettings(context(), dev_mode,
162                                                  settings_.get());
163
164   return true;
165 }
166
167 mojom::ResultCode PrintingContextSystemDialogWin::ParseDialogResultEx(
168     const PRINTDLGEX& dialog_options) {
169   // If the user clicked OK or Apply then Cancel, but not only Cancel.
170   if (dialog_options.dwResultAction != PD_RESULT_CANCEL) {
171     // Start fresh, but preserve is_modifiable print setting.
172     bool is_modifiable = settings_->is_modifiable();
173     ResetSettings();
174     settings_->set_is_modifiable(is_modifiable);
175
176     DEVMODE* dev_mode = NULL;
177     if (dialog_options.hDevMode) {
178       dev_mode =
179           reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode));
180       DCHECK(dev_mode);
181     }
182
183     std::wstring device_name;
184     if (dialog_options.hDevNames) {
185       DEVNAMES* dev_names =
186           reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames));
187       DCHECK(dev_names);
188       if (dev_names) {
189         device_name = reinterpret_cast<const wchar_t*>(dev_names) +
190                       dev_names->wDeviceOffset;
191         GlobalUnlock(dialog_options.hDevNames);
192       }
193     }
194
195     bool success = false;
196     if (dev_mode && !device_name.empty()) {
197       set_context(dialog_options.hDC);
198       PRINTPAGERANGE* page_ranges = NULL;
199       DWORD num_page_ranges = 0;
200       bool print_selection_only = false;
201       if (dialog_options.Flags & PD_PAGENUMS) {
202         page_ranges = dialog_options.lpPageRanges;
203         num_page_ranges = dialog_options.nPageRanges;
204       }
205       if (dialog_options.Flags & PD_SELECTION) {
206         print_selection_only = true;
207       }
208       success =
209           InitializeSettingsWithRanges(*dev_mode, device_name, page_ranges,
210                                        num_page_ranges, print_selection_only);
211     }
212
213     if (!success && dialog_options.hDC) {
214       DeleteDC(dialog_options.hDC);
215       set_context(NULL);
216     }
217
218     if (dev_mode) {
219       GlobalUnlock(dialog_options.hDevMode);
220     }
221   } else {
222     if (dialog_options.hDC) {
223       DeleteDC(dialog_options.hDC);
224     }
225   }
226
227   if (dialog_options.hDevMode != NULL)
228     GlobalFree(dialog_options.hDevMode);
229   if (dialog_options.hDevNames != NULL)
230     GlobalFree(dialog_options.hDevNames);
231
232   switch (dialog_options.dwResultAction) {
233     case PD_RESULT_PRINT:
234       return context() ? mojom::ResultCode::kSuccess
235                        : mojom::ResultCode::kFailed;
236     case PD_RESULT_APPLY:
237       return context() ? mojom::ResultCode::kCanceled
238                        : mojom::ResultCode::kFailed;
239     case PD_RESULT_CANCEL:
240       return mojom::ResultCode::kCanceled;
241     default:
242       return mojom::ResultCode::kFailed;
243   }
244 }
245
246 }  // namespace printing