1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsPrintSettingsService.h"
8 #include "mozilla/embedding/PPrintingTypes.h"
9 #include "mozilla/layout/RemotePrintJobChild.h"
10 #include "mozilla/RefPtr.h"
12 #include "nsIPrinterList.h"
13 #include "nsReadableUtils.h"
14 #include "nsPrintSettingsImpl.h"
15 #include "nsServiceManagerUtils.h"
20 #include "nsXULAppAPI.h"
22 #include "nsIStringEnumerator.h"
24 #include "mozilla/StaticPrefs_print.h"
25 #include "mozilla/Preferences.h"
26 #include "nsPrintfCString.h"
28 using namespace mozilla
;
29 using namespace mozilla::embedding
;
31 typedef mozilla::layout::RemotePrintJobChild RemotePrintJobChild
;
33 NS_IMPL_ISUPPORTS(nsPrintSettingsService
, nsIPrintSettingsService
)
36 static const char kMarginTop
[] = "print_margin_top";
37 static const char kMarginLeft
[] = "print_margin_left";
38 static const char kMarginBottom
[] = "print_margin_bottom";
39 static const char kMarginRight
[] = "print_margin_right";
40 static const char kEdgeTop
[] = "print_edge_top";
41 static const char kEdgeLeft
[] = "print_edge_left";
42 static const char kEdgeBottom
[] = "print_edge_bottom";
43 static const char kEdgeRight
[] = "print_edge_right";
45 static const char kIgnoreUnwriteableMargins
[] =
46 "print_ignore_unwriteable_margins";
48 static const char kUnwriteableMarginTopTwips
[] =
49 "print_unwriteable_margin_top_twips";
50 static const char kUnwriteableMarginLeftTwips
[] =
51 "print_unwriteable_margin_left_twips";
52 static const char kUnwriteableMarginBottomTwips
[] =
53 "print_unwriteable_margin_bottom_twips";
54 static const char kUnwriteableMarginRightTwips
[] =
55 "print_unwriteable_margin_right_twips";
57 // These are legacy versions of the above UnwriteableMargin prefs. The new ones,
58 // which are in twips, were introduced to more accurately record the values.
59 static const char kUnwriteableMarginTop
[] = "print_unwriteable_margin_top";
60 static const char kUnwriteableMarginLeft
[] = "print_unwriteable_margin_left";
61 static const char kUnwriteableMarginBottom
[] =
62 "print_unwriteable_margin_bottom";
63 static const char kUnwriteableMarginRight
[] = "print_unwriteable_margin_right";
65 // Prefs for Print Options
66 static const char kPrintHeaderStrLeft
[] = "print_headerleft";
67 static const char kPrintHeaderStrCenter
[] = "print_headercenter";
68 static const char kPrintHeaderStrRight
[] = "print_headerright";
69 static const char kPrintFooterStrLeft
[] = "print_footerleft";
70 static const char kPrintFooterStrCenter
[] = "print_footercenter";
71 static const char kPrintFooterStrRight
[] = "print_footerright";
74 static const char kPrintReversed
[] = "print_reversed";
75 static const char kPrintInColor
[] = "print_in_color";
76 static const char kPrintPaperId
[] = "print_paper_id";
77 static const char kPrintPaperSizeUnit
[] = "print_paper_size_unit";
78 static const char kPrintPaperWidth
[] = "print_paper_width";
79 static const char kPrintPaperHeight
[] = "print_paper_height";
80 static const char kPrintOrientation
[] = "print_orientation";
81 static const char kPrinterName
[] = "print_printer";
82 static const char kPrintToFile
[] = "print_to_file";
83 static const char kPrintToFileName
[] = "print_to_filename";
84 static const char kPrintPageDelay
[] = "print_page_delay";
85 static const char kPrintBGColors
[] = "print_bgcolor";
86 static const char kPrintBGImages
[] = "print_bgimages";
87 static const char kPrintShrinkToFit
[] = "print_shrink_to_fit";
88 static const char kPrintScaling
[] = "print_scaling";
89 static const char kPrintDuplex
[] = "print_duplex";
91 static const char kJustLeft
[] = "left";
92 static const char kJustCenter
[] = "center";
93 static const char kJustRight
[] = "right";
95 #define NS_PRINTER_LIST_CONTRACTID "@mozilla.org/gfx/printerlist;1"
97 nsresult
nsPrintSettingsService::Init() { return NS_OK
; }
100 nsPrintSettingsService::SerializeToPrintData(nsIPrintSettings
* aSettings
,
102 aSettings
->GetPageRanges(data
->pageRanges());
104 aSettings
->GetEdgeTop(&data
->edgeTop());
105 aSettings
->GetEdgeLeft(&data
->edgeLeft());
106 aSettings
->GetEdgeBottom(&data
->edgeBottom());
107 aSettings
->GetEdgeRight(&data
->edgeRight());
109 aSettings
->GetMarginTop(&data
->marginTop());
110 aSettings
->GetMarginLeft(&data
->marginLeft());
111 aSettings
->GetMarginBottom(&data
->marginBottom());
112 aSettings
->GetMarginRight(&data
->marginRight());
113 aSettings
->GetUnwriteableMarginTop(&data
->unwriteableMarginTop());
114 aSettings
->GetUnwriteableMarginLeft(&data
->unwriteableMarginLeft());
115 aSettings
->GetUnwriteableMarginBottom(&data
->unwriteableMarginBottom());
116 aSettings
->GetUnwriteableMarginRight(&data
->unwriteableMarginRight());
118 aSettings
->GetScaling(&data
->scaling());
120 data
->printBGColors() = aSettings
->GetPrintBGColors();
121 data
->printBGImages() = aSettings
->GetPrintBGImages();
123 data
->ignoreUnwriteableMargins() = aSettings
->GetIgnoreUnwriteableMargins();
124 data
->honorPageRuleMargins() = aSettings
->GetHonorPageRuleMargins();
125 data
->usePageRuleSizeAsPaperSize() =
126 aSettings
->GetUsePageRuleSizeAsPaperSize();
127 data
->showMarginGuides() = aSettings
->GetShowMarginGuides();
128 data
->printSelectionOnly() = aSettings
->GetPrintSelectionOnly();
130 aSettings
->GetTitle(data
->title());
131 aSettings
->GetDocURL(data
->docURL());
133 aSettings
->GetHeaderStrLeft(data
->headerStrLeft());
134 aSettings
->GetHeaderStrCenter(data
->headerStrCenter());
135 aSettings
->GetHeaderStrRight(data
->headerStrRight());
137 aSettings
->GetFooterStrLeft(data
->footerStrLeft());
138 aSettings
->GetFooterStrCenter(data
->footerStrCenter());
139 aSettings
->GetFooterStrRight(data
->footerStrRight());
141 aSettings
->GetPrintSilent(&data
->printSilent());
142 aSettings
->GetShrinkToFit(&data
->shrinkToFit());
144 aSettings
->GetPaperId(data
->paperId());
145 aSettings
->GetPaperWidth(&data
->paperWidth());
146 aSettings
->GetPaperHeight(&data
->paperHeight());
147 aSettings
->GetPaperSizeUnit(&data
->paperSizeUnit());
149 aSettings
->GetPrintReversed(&data
->printReversed());
150 aSettings
->GetPrintInColor(&data
->printInColor());
151 aSettings
->GetOrientation(&data
->orientation());
153 aSettings
->GetNumCopies(&data
->numCopies());
154 aSettings
->GetNumPagesPerSheet(&data
->numPagesPerSheet());
156 data
->outputDestination() = aSettings
->GetOutputDestination();
158 data
->outputFormat() = aSettings
->GetOutputFormat();
159 data
->printPageDelay() = aSettings
->GetPrintPageDelay();
160 data
->resolution() = aSettings
->GetResolution();
161 data
->duplex() = aSettings
->GetDuplex();
163 aSettings
->GetIsInitializedFromPrinter(&data
->isInitializedFromPrinter());
164 aSettings
->GetIsInitializedFromPrefs(&data
->isInitializedFromPrefs());
166 // Initialize the platform-specific values that don't
167 // default-initialize, so that we don't send uninitialized data over
168 // IPC (which leads to valgrind warnings, and, for bools, fatal
170 // data->driverName() default-initializes
171 // data->deviceName() default-initializes
172 // data->GTKPrintSettings() default-initializes
178 nsPrintSettingsService::DeserializeToPrintSettings(const PrintData
& data
,
179 nsIPrintSettings
* settings
) {
180 settings
->SetPageRanges(data
.pageRanges());
182 settings
->SetEdgeTop(data
.edgeTop());
183 settings
->SetEdgeLeft(data
.edgeLeft());
184 settings
->SetEdgeBottom(data
.edgeBottom());
185 settings
->SetEdgeRight(data
.edgeRight());
187 settings
->SetMarginTop(data
.marginTop());
188 settings
->SetMarginLeft(data
.marginLeft());
189 settings
->SetMarginBottom(data
.marginBottom());
190 settings
->SetMarginRight(data
.marginRight());
191 settings
->SetUnwriteableMarginTop(data
.unwriteableMarginTop());
192 settings
->SetUnwriteableMarginLeft(data
.unwriteableMarginLeft());
193 settings
->SetUnwriteableMarginBottom(data
.unwriteableMarginBottom());
194 settings
->SetUnwriteableMarginRight(data
.unwriteableMarginRight());
196 settings
->SetScaling(data
.scaling());
198 settings
->SetPrintBGColors(data
.printBGColors());
199 settings
->SetPrintBGImages(data
.printBGImages());
200 settings
->SetHonorPageRuleMargins(data
.honorPageRuleMargins());
201 settings
->SetUsePageRuleSizeAsPaperSize(data
.usePageRuleSizeAsPaperSize());
202 settings
->SetIgnoreUnwriteableMargins(data
.ignoreUnwriteableMargins());
203 settings
->SetShowMarginGuides(data
.showMarginGuides());
204 settings
->SetPrintSelectionOnly(data
.printSelectionOnly());
206 settings
->SetTitle(data
.title());
207 settings
->SetDocURL(data
.docURL());
210 settings
->SetHeaderStrLeft(data
.headerStrLeft());
211 settings
->SetHeaderStrCenter(data
.headerStrCenter());
212 settings
->SetHeaderStrRight(data
.headerStrRight());
215 settings
->SetFooterStrLeft(data
.footerStrLeft());
216 settings
->SetFooterStrCenter(data
.footerStrCenter());
217 settings
->SetFooterStrRight(data
.footerStrRight());
219 settings
->SetPrintSilent(data
.printSilent());
220 settings
->SetShrinkToFit(data
.shrinkToFit());
222 settings
->SetPaperId(data
.paperId());
224 settings
->SetPaperWidth(data
.paperWidth());
225 settings
->SetPaperHeight(data
.paperHeight());
226 settings
->SetPaperSizeUnit(data
.paperSizeUnit());
228 settings
->SetPrintReversed(data
.printReversed());
229 settings
->SetPrintInColor(data
.printInColor());
230 settings
->SetOrientation(data
.orientation());
232 settings
->SetNumCopies(data
.numCopies());
233 settings
->SetNumPagesPerSheet(data
.numPagesPerSheet());
235 settings
->SetOutputDestination(
236 nsIPrintSettings::OutputDestinationType(data
.outputDestination()));
237 // Output stream intentionally unset, child processes shouldn't care about it.
239 settings
->SetOutputFormat(data
.outputFormat());
240 settings
->SetPrintPageDelay(data
.printPageDelay());
241 settings
->SetResolution(data
.resolution());
242 settings
->SetDuplex(data
.duplex());
243 settings
->SetIsInitializedFromPrinter(data
.isInitializedFromPrinter());
244 settings
->SetIsInitializedFromPrefs(data
.isInitializedFromPrefs());
249 /** ---------------------------------------------------
250 * Helper function - Creates the "prefix" for the pref
251 * It is either "print."
252 * or "print.printer_<print name>."
254 const char* nsPrintSettingsService::GetPrefName(const char* aPrefName
,
255 const nsAString
& aPrinterName
) {
256 if (!aPrefName
|| !*aPrefName
) {
257 NS_ERROR("Must have a valid pref name!");
261 mPrefName
.AssignLiteral("print.");
263 if (aPrinterName
.Length()) {
264 mPrefName
.AppendLiteral("printer_");
265 AppendUTF16toUTF8(aPrinterName
, mPrefName
);
266 mPrefName
.Append('.');
268 mPrefName
+= aPrefName
;
270 return mPrefName
.get();
274 * This will either read in the generic prefs (not specific to a printer)
275 * or read the prefs in using the printer name to qualify.
276 * It is either "print.attr_name" or "print.printer_HPLasr5.attr_name"
278 nsresult
nsPrintSettingsService::ReadPrefs(nsIPrintSettings
* aPS
,
279 const nsAString
& aPrinterName
,
281 NS_ENSURE_ARG_POINTER(aPS
);
283 bool noValidPrefsFound
= true;
289 #define GETBOOLPREF(_prefname, _retval) \
291 Preferences::GetBool(GetPrefName(_prefname, aPrinterName), _retval))
293 #define GETSTRPREF(_prefname, _retval) \
295 Preferences::GetString(GetPrefName(_prefname, aPrinterName), _retval))
297 #define GETINTPREF(_prefname, _retval) \
299 Preferences::GetInt(GetPrefName(_prefname, aPrinterName), _retval))
301 #define GETDBLPREF(_prefname, _retval) \
302 NS_SUCCEEDED(ReadPrefDouble(GetPrefName(_prefname, aPrinterName), _retval))
304 bool gotPaperSizeFromPrefs
= false;
305 int16_t paperSizeUnit
;
306 double paperWidth
, paperHeight
;
308 // Paper size prefs are read as a group
309 if (aFlags
& nsIPrintSettings::kInitSavePaperSize
) {
310 gotPaperSizeFromPrefs
= GETINTPREF(kPrintPaperSizeUnit
, &iVal
) &&
311 GETDBLPREF(kPrintPaperWidth
, paperWidth
) &&
312 GETDBLPREF(kPrintPaperHeight
, paperHeight
) &&
313 GETSTRPREF(kPrintPaperId
, str
);
314 paperSizeUnit
= (int16_t)iVal
;
316 if (gotPaperSizeFromPrefs
&&
317 paperSizeUnit
!= nsIPrintSettings::kPaperSizeInches
&&
318 paperSizeUnit
!= nsIPrintSettings::kPaperSizeMillimeters
) {
319 gotPaperSizeFromPrefs
= false;
322 if (gotPaperSizeFromPrefs
) {
323 // Bug 315687: Sanity check paper size to avoid paper size values in
324 // mm when the size unit flag is inches. The value 100 is arbitrary
325 // and can be changed.
326 gotPaperSizeFromPrefs
=
327 (paperSizeUnit
!= nsIPrintSettings::kPaperSizeInches
) ||
328 (paperWidth
< 100.0) || (paperHeight
< 100.0);
331 if (gotPaperSizeFromPrefs
) {
332 aPS
->SetPaperSizeUnit(paperSizeUnit
);
333 aPS
->SetPaperWidth(paperWidth
);
334 aPS
->SetPaperHeight(paperHeight
);
335 aPS
->SetPaperId(str
);
336 noValidPrefsFound
= false;
340 nsIntSize pageSizeInTwips
; // to sanity check margins
341 if (!gotPaperSizeFromPrefs
) {
342 aPS
->GetPaperSizeUnit(&paperSizeUnit
);
343 aPS
->GetPaperWidth(&paperWidth
);
344 aPS
->GetPaperHeight(&paperHeight
);
346 if (paperSizeUnit
== nsIPrintSettings::kPaperSizeMillimeters
) {
347 pageSizeInTwips
= nsIntSize((int)NS_MILLIMETERS_TO_TWIPS(paperWidth
),
348 (int)NS_MILLIMETERS_TO_TWIPS(paperHeight
));
350 pageSizeInTwips
= nsIntSize((int)NS_INCHES_TO_TWIPS(paperWidth
),
351 (int)NS_INCHES_TO_TWIPS(paperHeight
));
354 auto MarginIsOK
= [&pageSizeInTwips
](const nsIntMargin
& aMargin
) {
355 return aMargin
.top
>= 0 && aMargin
.right
>= 0 && aMargin
.bottom
>= 0 &&
356 aMargin
.left
>= 0 && aMargin
.LeftRight() < pageSizeInTwips
.width
&&
357 aMargin
.TopBottom() < pageSizeInTwips
.height
;
360 if (aFlags
& nsIPrintSettings::kInitSaveUnwriteableMargins
) {
363 GETINTPREF(kUnwriteableMarginTopTwips
, &margin
.top
.value
) &&
364 GETINTPREF(kUnwriteableMarginRightTwips
, &margin
.right
.value
) &&
365 GETINTPREF(kUnwriteableMarginBottomTwips
, &margin
.bottom
.value
) &&
366 GETINTPREF(kUnwriteableMarginLeftTwips
, &margin
.left
.value
);
368 // We failed to read the new unwritable margin twips prefs. Try to read
369 // the old ones in case they exist.
370 allPrefsRead
= ReadInchesIntToTwipsPref(
371 GetPrefName(kUnwriteableMarginTop
, aPrinterName
),
373 ReadInchesIntToTwipsPref(
374 GetPrefName(kUnwriteableMarginLeft
, aPrinterName
),
375 margin
.left
.value
) &&
376 ReadInchesIntToTwipsPref(
377 GetPrefName(kUnwriteableMarginBottom
, aPrinterName
),
378 margin
.bottom
.value
) &&
379 ReadInchesIntToTwipsPref(
380 GetPrefName(kUnwriteableMarginRight
, aPrinterName
),
383 // SetUnwriteableMarginInTwips does its own validation and drops negative
384 // values individually. We still want to block overly large values though,
385 // so we do that part of MarginIsOK manually.
386 if (allPrefsRead
&& margin
.LeftRight() < pageSizeInTwips
.width
&&
387 margin
.TopBottom() < pageSizeInTwips
.height
) {
388 aPS
->SetUnwriteableMarginInTwips(margin
);
389 noValidPrefsFound
= false;
393 if (aFlags
& nsIPrintSettings::kInitSaveMargins
) {
394 int32_t halfInch
= NS_INCHES_TO_INT_TWIPS(0.5);
395 nsIntMargin
margin(halfInch
, halfInch
, halfInch
, halfInch
);
396 bool prefRead
= ReadInchesToTwipsPref(GetPrefName(kMarginTop
, aPrinterName
),
398 prefRead
= ReadInchesToTwipsPref(GetPrefName(kMarginLeft
, aPrinterName
),
399 margin
.left
.value
) ||
401 prefRead
= ReadInchesToTwipsPref(GetPrefName(kMarginBottom
, aPrinterName
),
402 margin
.bottom
.value
) ||
405 prefRead
= ReadInchesToTwipsPref(GetPrefName(kMarginRight
, aPrinterName
),
406 margin
.right
.value
) ||
408 if (prefRead
&& MarginIsOK(margin
)) {
409 aPS
->SetMarginInTwips(margin
);
410 noValidPrefsFound
= false;
412 prefRead
= GETBOOLPREF(kIgnoreUnwriteableMargins
, &b
);
414 aPS
->SetIgnoreUnwriteableMargins(b
);
419 if (aFlags
& nsIPrintSettings::kInitSaveEdges
) {
420 nsIntMargin
margin(0, 0, 0, 0);
421 bool prefRead
= ReadInchesIntToTwipsPref(
422 GetPrefName(kEdgeTop
, aPrinterName
), margin
.top
.value
);
423 prefRead
= ReadInchesIntToTwipsPref(GetPrefName(kEdgeLeft
, aPrinterName
),
424 margin
.left
.value
) ||
427 prefRead
= ReadInchesIntToTwipsPref(GetPrefName(kEdgeBottom
, aPrinterName
),
428 margin
.bottom
.value
) ||
431 prefRead
= ReadInchesIntToTwipsPref(GetPrefName(kEdgeRight
, aPrinterName
),
432 margin
.right
.value
) ||
435 if (prefRead
&& MarginIsOK(margin
)) {
436 aPS
->SetEdgeInTwips(margin
);
437 noValidPrefsFound
= false;
441 if (aFlags
& nsIPrintSettings::kInitSaveHeaderLeft
) {
442 if (GETSTRPREF(kPrintHeaderStrLeft
, str
)) {
443 aPS
->SetHeaderStrLeft(str
);
444 noValidPrefsFound
= false;
448 if (aFlags
& nsIPrintSettings::kInitSaveHeaderCenter
) {
449 if (GETSTRPREF(kPrintHeaderStrCenter
, str
)) {
450 aPS
->SetHeaderStrCenter(str
);
451 noValidPrefsFound
= false;
455 if (aFlags
& nsIPrintSettings::kInitSaveHeaderRight
) {
456 if (GETSTRPREF(kPrintHeaderStrRight
, str
)) {
457 aPS
->SetHeaderStrRight(str
);
458 noValidPrefsFound
= false;
462 if (aFlags
& nsIPrintSettings::kInitSaveFooterLeft
) {
463 if (GETSTRPREF(kPrintFooterStrLeft
, str
)) {
464 aPS
->SetFooterStrLeft(str
);
465 noValidPrefsFound
= false;
469 if (aFlags
& nsIPrintSettings::kInitSaveFooterCenter
) {
470 if (GETSTRPREF(kPrintFooterStrCenter
, str
)) {
471 aPS
->SetFooterStrCenter(str
);
472 noValidPrefsFound
= false;
476 if (aFlags
& nsIPrintSettings::kInitSaveFooterRight
) {
477 if (GETSTRPREF(kPrintFooterStrRight
, str
)) {
478 aPS
->SetFooterStrRight(str
);
479 noValidPrefsFound
= false;
483 if (aFlags
& nsIPrintSettings::kInitSaveBGColors
) {
484 if (GETBOOLPREF(kPrintBGColors
, &b
)) {
485 aPS
->SetPrintBGColors(b
);
486 noValidPrefsFound
= false;
490 if (aFlags
& nsIPrintSettings::kInitSaveBGImages
) {
491 if (GETBOOLPREF(kPrintBGImages
, &b
)) {
492 aPS
->SetPrintBGImages(b
);
493 noValidPrefsFound
= false;
497 if (aFlags
& nsIPrintSettings::kInitSaveReversed
) {
498 if (GETBOOLPREF(kPrintReversed
, &b
)) {
499 aPS
->SetPrintReversed(b
);
500 noValidPrefsFound
= false;
504 if (aFlags
& nsIPrintSettings::kInitSaveInColor
) {
505 if (GETBOOLPREF(kPrintInColor
, &b
)) {
506 aPS
->SetPrintInColor(b
);
507 noValidPrefsFound
= false;
511 if (aFlags
& nsIPrintSettings::kInitSaveOrientation
) {
512 if (GETINTPREF(kPrintOrientation
, &iVal
) &&
513 (iVal
== nsIPrintSettings::kPortraitOrientation
||
514 iVal
== nsIPrintSettings::kLandscapeOrientation
)) {
515 aPS
->SetOrientation(iVal
);
516 noValidPrefsFound
= false;
520 if (aFlags
& nsIPrintSettings::kInitSavePrintToFile
) {
521 if (GETBOOLPREF(kPrintToFile
, &b
)) {
522 aPS
->SetOutputDestination(
523 b
? nsIPrintSettings::kOutputDestinationFile
524 : nsIPrintSettings::kOutputDestinationPrinter
);
525 noValidPrefsFound
= false;
529 if (aFlags
& nsIPrintSettings::kInitSaveToFileName
) {
530 if (GETSTRPREF(kPrintToFileName
, str
)) {
531 if (StringEndsWith(str
, u
".ps"_ns
)) {
532 // We only support PDF since bug 1425188 landed. Users may still have
533 // prefs with .ps filenames if they last saved a file as Postscript
534 // though, so we fix that up here. (The pref values will be
535 // overwritten the next time they save to file as a PDF.)
536 str
.Truncate(str
.Length() - 2);
537 str
.AppendLiteral("pdf");
539 aPS
->SetToFileName(str
);
540 noValidPrefsFound
= false;
544 if (aFlags
& nsIPrintSettings::kInitSavePageDelay
) {
546 if (GETINTPREF(kPrintPageDelay
, &iVal
) && iVal
>= 0 && iVal
<= 1000) {
547 aPS
->SetPrintPageDelay(iVal
);
548 noValidPrefsFound
= false;
552 if (aFlags
& nsIPrintSettings::kInitSaveShrinkToFit
) {
553 if (GETBOOLPREF(kPrintShrinkToFit
, &b
)) {
554 aPS
->SetShrinkToFit(b
);
555 noValidPrefsFound
= false;
559 if (aFlags
& nsIPrintSettings::kInitSaveScaling
) {
560 // The limits imposed here are fairly arbitrary and mainly intended to
561 // purge bad values which tend to be negative and/or very large. If we
562 // get complaints from users that settings outside these values "aren't
563 // saved" then we can consider increasing them.
564 if (GETDBLPREF(kPrintScaling
, dbl
) && dbl
>= 0.05 && dbl
<= 20) {
565 aPS
->SetScaling(dbl
);
566 noValidPrefsFound
= false;
570 if (aFlags
& nsIPrintSettings::kInitSaveDuplex
) {
571 if (GETINTPREF(kPrintDuplex
, &iVal
)) {
572 aPS
->SetDuplex(iVal
);
573 noValidPrefsFound
= false;
581 return noValidPrefsFound
? NS_ERROR_NOT_AVAILABLE
: NS_OK
;
584 nsresult
nsPrintSettingsService::WritePrefs(nsIPrintSettings
* aPS
,
585 const nsAString
& aPrinterName
,
587 NS_ENSURE_ARG_POINTER(aPS
);
589 if (aFlags
& nsIPrintSettings::kInitSaveMargins
) {
590 nsIntMargin margin
= aPS
->GetMarginInTwips();
591 WriteInchesFromTwipsPref(GetPrefName(kMarginTop
, aPrinterName
), margin
.top
);
592 WriteInchesFromTwipsPref(GetPrefName(kMarginLeft
, aPrinterName
),
594 WriteInchesFromTwipsPref(GetPrefName(kMarginBottom
, aPrinterName
),
596 WriteInchesFromTwipsPref(GetPrefName(kMarginRight
, aPrinterName
),
598 Preferences::SetBool(GetPrefName(kIgnoreUnwriteableMargins
, aPrinterName
),
599 aPS
->GetIgnoreUnwriteableMargins());
602 if (aFlags
& nsIPrintSettings::kInitSaveEdges
) {
603 nsIntMargin edge
= aPS
->GetEdgeInTwips();
604 WriteInchesIntFromTwipsPref(GetPrefName(kEdgeTop
, aPrinterName
), edge
.top
);
605 WriteInchesIntFromTwipsPref(GetPrefName(kEdgeLeft
, aPrinterName
),
607 WriteInchesIntFromTwipsPref(GetPrefName(kEdgeBottom
, aPrinterName
),
609 WriteInchesIntFromTwipsPref(GetPrefName(kEdgeRight
, aPrinterName
),
613 if (aFlags
& nsIPrintSettings::kInitSaveUnwriteableMargins
) {
614 nsIntMargin unwriteableMargin
= aPS
->GetUnwriteableMarginInTwips();
615 Preferences::SetInt(GetPrefName(kUnwriteableMarginTopTwips
, aPrinterName
),
616 unwriteableMargin
.top
);
617 Preferences::SetInt(GetPrefName(kUnwriteableMarginLeftTwips
, aPrinterName
),
618 unwriteableMargin
.left
);
620 GetPrefName(kUnwriteableMarginBottomTwips
, aPrinterName
),
621 unwriteableMargin
.bottom
);
622 Preferences::SetInt(GetPrefName(kUnwriteableMarginRightTwips
, aPrinterName
),
623 unwriteableMargin
.right
);
625 // Remove the old unwriteableMargin prefs.
626 Preferences::ClearUser(GetPrefName(kUnwriteableMarginTop
, aPrinterName
));
627 Preferences::ClearUser(GetPrefName(kUnwriteableMarginRight
, aPrinterName
));
628 Preferences::ClearUser(GetPrefName(kUnwriteableMarginBottom
, aPrinterName
));
629 Preferences::ClearUser(GetPrefName(kUnwriteableMarginLeft
, aPrinterName
));
632 // Paper size prefs are saved as a group
633 if (aFlags
& nsIPrintSettings::kInitSavePaperSize
) {
635 double width
, height
;
638 if (NS_SUCCEEDED(aPS
->GetPaperSizeUnit(&sizeUnit
)) &&
639 NS_SUCCEEDED(aPS
->GetPaperWidth(&width
)) &&
640 NS_SUCCEEDED(aPS
->GetPaperHeight(&height
)) &&
641 NS_SUCCEEDED(aPS
->GetPaperId(name
))) {
642 Preferences::SetInt(GetPrefName(kPrintPaperSizeUnit
, aPrinterName
),
644 WritePrefDouble(GetPrefName(kPrintPaperWidth
, aPrinterName
), width
);
645 WritePrefDouble(GetPrefName(kPrintPaperHeight
, aPrinterName
), height
);
646 Preferences::SetString(GetPrefName(kPrintPaperId
, aPrinterName
), name
);
655 if (aFlags
& nsIPrintSettings::kInitSaveHeaderLeft
) {
656 if (NS_SUCCEEDED(aPS
->GetHeaderStrLeft(uStr
))) {
657 Preferences::SetString(GetPrefName(kPrintHeaderStrLeft
, aPrinterName
),
662 if (aFlags
& nsIPrintSettings::kInitSaveHeaderCenter
) {
663 if (NS_SUCCEEDED(aPS
->GetHeaderStrCenter(uStr
))) {
664 Preferences::SetString(GetPrefName(kPrintHeaderStrCenter
, aPrinterName
),
669 if (aFlags
& nsIPrintSettings::kInitSaveHeaderRight
) {
670 if (NS_SUCCEEDED(aPS
->GetHeaderStrRight(uStr
))) {
671 Preferences::SetString(GetPrefName(kPrintHeaderStrRight
, aPrinterName
),
676 if (aFlags
& nsIPrintSettings::kInitSaveFooterLeft
) {
677 if (NS_SUCCEEDED(aPS
->GetFooterStrLeft(uStr
))) {
678 Preferences::SetString(GetPrefName(kPrintFooterStrLeft
, aPrinterName
),
683 if (aFlags
& nsIPrintSettings::kInitSaveFooterCenter
) {
684 if (NS_SUCCEEDED(aPS
->GetFooterStrCenter(uStr
))) {
685 Preferences::SetString(GetPrefName(kPrintFooterStrCenter
, aPrinterName
),
690 if (aFlags
& nsIPrintSettings::kInitSaveFooterRight
) {
691 if (NS_SUCCEEDED(aPS
->GetFooterStrRight(uStr
))) {
692 Preferences::SetString(GetPrefName(kPrintFooterStrRight
, aPrinterName
),
697 if (aFlags
& nsIPrintSettings::kInitSaveBGColors
) {
698 b
= aPS
->GetPrintBGColors();
699 Preferences::SetBool(GetPrefName(kPrintBGColors
, aPrinterName
), b
);
702 if (aFlags
& nsIPrintSettings::kInitSaveBGImages
) {
703 b
= aPS
->GetPrintBGImages();
704 Preferences::SetBool(GetPrefName(kPrintBGImages
, aPrinterName
), b
);
707 if (aFlags
& nsIPrintSettings::kInitSaveReversed
) {
708 if (NS_SUCCEEDED(aPS
->GetPrintReversed(&b
))) {
709 Preferences::SetBool(GetPrefName(kPrintReversed
, aPrinterName
), b
);
713 if (aFlags
& nsIPrintSettings::kInitSaveInColor
) {
714 if (NS_SUCCEEDED(aPS
->GetPrintInColor(&b
))) {
715 Preferences::SetBool(GetPrefName(kPrintInColor
, aPrinterName
), b
);
719 if (aFlags
& nsIPrintSettings::kInitSaveOrientation
) {
720 if (NS_SUCCEEDED(aPS
->GetOrientation(&iVal
))) {
721 Preferences::SetInt(GetPrefName(kPrintOrientation
, aPrinterName
), iVal
);
725 // Only the general version of this pref is saved
726 if ((aFlags
& nsIPrintSettings::kInitSavePrinterName
) &&
727 aPrinterName
.IsEmpty()) {
728 if (NS_SUCCEEDED(aPS
->GetPrinterName(uStr
))) {
729 Preferences::SetString(kPrinterName
, uStr
);
733 if (aFlags
& nsIPrintSettings::kInitSavePrintToFile
) {
734 Preferences::SetBool(GetPrefName(kPrintToFile
, aPrinterName
),
735 aPS
->GetOutputDestination() ==
736 nsIPrintSettings::kOutputDestinationFile
);
739 if (aFlags
& nsIPrintSettings::kInitSaveToFileName
) {
740 if (NS_SUCCEEDED(aPS
->GetToFileName(uStr
))) {
741 Preferences::SetString(GetPrefName(kPrintToFileName
, aPrinterName
), uStr
);
745 if (aFlags
& nsIPrintSettings::kInitSavePageDelay
) {
746 if (NS_SUCCEEDED(aPS
->GetPrintPageDelay(&iVal
))) {
747 Preferences::SetInt(GetPrefName(kPrintPageDelay
, aPrinterName
), iVal
);
751 if (aFlags
& nsIPrintSettings::kInitSaveShrinkToFit
) {
752 if (NS_SUCCEEDED(aPS
->GetShrinkToFit(&b
))) {
753 Preferences::SetBool(GetPrefName(kPrintShrinkToFit
, aPrinterName
), b
);
757 if (aFlags
& nsIPrintSettings::kInitSaveScaling
) {
758 if (NS_SUCCEEDED(aPS
->GetScaling(&dbl
))) {
759 WritePrefDouble(GetPrefName(kPrintScaling
, aPrinterName
), dbl
);
763 if (aFlags
& nsIPrintSettings::kInitSaveDuplex
) {
764 if (NS_SUCCEEDED(aPS
->GetDuplex(&iVal
))) {
765 Preferences::SetInt(GetPrefName(kPrintDuplex
, aPrinterName
), iVal
);
777 nsPrintSettingsService::GetDefaultPrintSettingsForPrinting(
778 nsIPrintSettings
** aPrintSettings
) {
779 nsresult rv
= CreateNewPrintSettings(aPrintSettings
);
780 NS_ENSURE_SUCCESS(rv
, rv
);
782 nsIPrintSettings
* settings
= *aPrintSettings
;
784 // For security reasons, we don't pass the printer name to content processes.
785 // Once bug 1776169 is fixed, we can just assert that this is the parent
787 bool usePrinterName
= XRE_IsParentProcess();
789 if (usePrinterName
) {
790 nsAutoString printerName
;
791 settings
->GetPrinterName(printerName
);
792 if (printerName
.IsEmpty()) {
793 GetLastUsedPrinterName(printerName
);
794 settings
->SetPrinterName(printerName
);
796 InitPrintSettingsFromPrinter(printerName
, settings
);
799 InitPrintSettingsFromPrefs(settings
, usePrinterName
,
800 nsIPrintSettings::kInitSaveAll
);
806 nsPrintSettingsService::CreateNewPrintSettings(
807 nsIPrintSettings
** aNewPrintSettings
) {
808 return _CreatePrintSettings(aNewPrintSettings
);
812 nsPrintSettingsService::GetLastUsedPrinterName(
813 nsAString
& aLastUsedPrinterName
) {
814 MOZ_ASSERT(XRE_IsParentProcess());
816 aLastUsedPrinterName
.Truncate();
817 Preferences::GetString(kPrinterName
, aLastUsedPrinterName
);
822 nsPrintSettingsService::InitPrintSettingsFromPrinter(
823 const nsAString
& aPrinterName
, nsIPrintSettings
* aPrintSettings
) {
824 // Don't get print settings from the printer in the child when printing via
825 // parent, these will be retrieved in the parent later in the print process.
826 if (XRE_IsContentProcess()) {
830 NS_ENSURE_ARG_POINTER(aPrintSettings
);
833 nsString printerName
;
834 aPrintSettings
->GetPrinterName(printerName
);
835 if (!printerName
.Equals(aPrinterName
)) {
836 NS_WARNING("Printer names should match!");
841 aPrintSettings
->GetIsInitializedFromPrinter(&isInitialized
);
842 if (isInitialized
) return NS_OK
;
845 nsCOMPtr
<nsIPrinterList
> printerList
=
846 do_GetService(NS_PRINTER_LIST_CONTRACTID
, &rv
);
847 NS_ENSURE_SUCCESS(rv
, rv
);
849 rv
= printerList
->InitPrintSettingsFromPrinter(aPrinterName
, aPrintSettings
);
850 NS_ENSURE_SUCCESS(rv
, rv
);
852 aPrintSettings
->SetIsInitializedFromPrinter(true);
856 /** ---------------------------------------------------
857 * Helper function - Returns either the name or sets the length to zero
859 static nsresult
GetAdjustedPrinterName(nsIPrintSettings
* aPS
, bool aUsePNP
,
860 nsAString
& aPrinterName
) {
861 NS_ENSURE_ARG_POINTER(aPS
);
863 aPrinterName
.Truncate();
864 if (!aUsePNP
) return NS_OK
;
866 // Get the Printer Name from the PrintSettings
867 // to use as a prefix for Pref Names
868 nsresult rv
= aPS
->GetPrinterName(aPrinterName
);
869 NS_ENSURE_SUCCESS(rv
, rv
);
871 // Convert any whitespaces, carriage returns or newlines to _
872 // The below algorithm is supposedly faster than using iterators
873 constexpr auto replSubstr
= u
"_"_ns
;
874 const char* replaceStr
= " \n\r";
877 for (x
= 0; x
< (int32_t)strlen(replaceStr
); x
++) {
878 char16_t uChar
= replaceStr
[x
];
881 while ((i
= aPrinterName
.FindChar(uChar
, i
)) != kNotFound
) {
882 aPrinterName
.Replace(i
, 1, replSubstr
);
890 nsPrintSettingsService::InitPrintSettingsFromPrefs(nsIPrintSettings
* aPS
,
893 NS_ENSURE_ARG_POINTER(aPS
);
896 aPS
->GetIsInitializedFromPrefs(&isInitialized
);
902 auto globalPrintSettings
= aFlags
;
903 #ifndef MOZ_WIDGET_ANDROID
904 globalPrintSettings
&= nsIPrintSettings::kGlobalSettings
;
907 nsAutoString prtName
;
908 // read any non printer specific prefs
909 // with empty printer name
910 nsresult rv
= ReadPrefs(aPS
, prtName
, globalPrintSettings
);
911 if (NS_FAILED(rv
) && rv
!= NS_ERROR_NOT_AVAILABLE
) {
912 NS_WARNING("ReadPrefs failed");
915 // Get the Printer Name from the PrintSettings to use as a prefix for Pref
917 rv
= GetAdjustedPrinterName(aPS
, aUsePNP
, prtName
);
918 NS_ENSURE_SUCCESS(rv
, rv
);
920 if (prtName
.IsEmpty()) {
921 NS_WARNING("Caller should supply a printer name.");
925 // Now read any printer specific prefs
926 rv
= ReadPrefs(aPS
, prtName
, aFlags
);
927 if (NS_SUCCEEDED(rv
)) {
928 aPS
->SetIsInitializedFromPrefs(true);
935 * Save all of the printer settings; if we can find a printer name, save
936 * printer-specific preferences. Otherwise, save generic ones.
938 nsresult
nsPrintSettingsService::MaybeSavePrintSettingsToPrefs(
939 nsIPrintSettings
* aPS
, uint32_t aFlags
) {
940 NS_ENSURE_ARG_POINTER(aPS
);
941 MOZ_DIAGNOSTIC_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default
);
942 MOZ_ASSERT(!(aFlags
& nsIPrintSettings::kInitSavePrinterName
),
943 "Use SaveLastUsedPrintNameToPrefs");
945 if (!Preferences::GetBool("print.save_print_settings", false)) {
949 // Get the printer name from the PrinterSettings for an optional prefix.
950 nsAutoString prtName
;
951 nsresult rv
= GetAdjustedPrinterName(aPS
, true, prtName
);
952 NS_ENSURE_SUCCESS(rv
, rv
);
954 #ifndef MOZ_WIDGET_ANDROID
955 // On most platforms we should always use a prefix when saving print settings
956 // to prefs. Saving without a prefix risks breaking printing for users
957 // without a good way for us to fix things for them (unprefixed prefs act as
958 // defaults and can result in values being inappropriately propagated to
960 if (prtName
.IsEmpty()) {
961 MOZ_DIAGNOSTIC_ASSERT(false, "Print settings must be saved with a prefix");
962 return NS_ERROR_FAILURE
;
966 return WritePrefs(aPS
, prtName
, aFlags
);
969 nsresult
nsPrintSettingsService::MaybeSaveLastUsedPrinterNameToPrefs(
970 const nsAString
& aPrinterName
) {
971 MOZ_DIAGNOSTIC_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default
);
973 if (!Preferences::GetBool("print.save_print_settings", false)) {
977 if (!aPrinterName
.IsEmpty()) {
978 Preferences::SetString(kPrinterName
, aPrinterName
);
983 //-----------------------------------------------------
984 //-- Protected Methods --------------------------------
985 //-----------------------------------------------------
986 nsresult
nsPrintSettingsService::ReadPrefDouble(const char* aPrefId
,
988 NS_ENSURE_ARG_POINTER(aPrefId
);
991 nsresult rv
= Preferences::GetCString(aPrefId
, str
);
992 if (NS_FAILED(rv
) || str
.IsEmpty()) {
993 return NS_ERROR_NOT_AVAILABLE
;
996 double value
= str
.ToDouble(&rv
);
1005 nsresult
nsPrintSettingsService::WritePrefDouble(const char* aPrefId
,
1007 NS_ENSURE_ARG_POINTER(aPrefId
);
1010 str
.AppendFloat(aVal
);
1011 return Preferences::SetCString(aPrefId
, str
);
1014 bool nsPrintSettingsService::ReadInchesToTwipsPref(const char* aPrefId
,
1017 nsresult rv
= Preferences::GetString(aPrefId
, str
);
1018 if (NS_FAILED(rv
) || str
.IsEmpty()) {
1022 float inches
= str
.ToFloat(&rv
);
1023 if (NS_FAILED(rv
)) {
1027 aTwips
= NS_INCHES_TO_INT_TWIPS(inches
);
1031 void nsPrintSettingsService::WriteInchesFromTwipsPref(const char* aPrefId
,
1033 double inches
= NS_TWIPS_TO_INCHES(aTwips
);
1034 nsAutoCString inchesStr
;
1035 inchesStr
.AppendFloat(inches
);
1037 Preferences::SetCString(aPrefId
, inchesStr
);
1040 bool nsPrintSettingsService::ReadInchesIntToTwipsPref(const char* aPrefId
,
1043 nsresult rv
= Preferences::GetInt(aPrefId
, &value
);
1044 if (NS_FAILED(rv
)) {
1048 aTwips
= NS_INCHES_TO_INT_TWIPS(float(value
) / 100.0f
);
1052 void nsPrintSettingsService::WriteInchesIntFromTwipsPref(const char* aPrefId
,
1054 Preferences::SetInt(aPrefId
,
1055 int32_t(NS_TWIPS_TO_INCHES(aTwips
) * 100.0f
+ 0.5f
));
1058 void nsPrintSettingsService::ReadJustification(const char* aPrefId
,
1060 int16_t aInitValue
) {
1062 nsAutoString justStr
;
1063 if (NS_SUCCEEDED(Preferences::GetString(aPrefId
, justStr
))) {
1064 if (justStr
.EqualsASCII(kJustRight
)) {
1065 aJust
= nsIPrintSettings::kJustRight
;
1066 } else if (justStr
.EqualsASCII(kJustCenter
)) {
1067 aJust
= nsIPrintSettings::kJustCenter
;
1069 aJust
= nsIPrintSettings::kJustLeft
;
1074 //---------------------------------------------------
1075 void nsPrintSettingsService::WriteJustification(const char* aPrefId
,
1078 case nsIPrintSettings::kJustLeft
:
1079 Preferences::SetCString(aPrefId
, kJustLeft
);
1082 case nsIPrintSettings::kJustCenter
:
1083 Preferences::SetCString(aPrefId
, kJustCenter
);
1086 case nsIPrintSettings::kJustRight
:
1087 Preferences::SetCString(aPrefId
, kJustRight
);