Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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 #ifdef MOZ_LOGGING
7 #define FORCE_PR_LOG 1 /* Allow logging in the release build */
8 #endif /* MOZ_LOGGING */
9 #include "prlog.h"
11 #include "plstr.h"
13 #include "nsDeviceContextSpecG.h"
15 #include "prenv.h" /* for PR_GetEnv */
17 #include "nsPrintfCString.h"
18 #include "nsReadableUtils.h"
19 #include "nsStringEnumerator.h"
20 #include "nsIServiceManager.h"
22 #include "nsPSPrinters.h"
23 #include "nsPaperPS.h" /* Paper size list */
25 #include "nsPrintSettingsGTK.h"
27 #include "nsIFileStreams.h"
28 #include "nsIFile.h"
29 #include "nsTArray.h"
31 #include "mozilla/Preferences.h"
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
37 using namespace mozilla;
39 #ifdef PR_LOGGING
40 static PRLogModuleInfo *
41 GetDeviceContextSpecGTKLog()
42 {
43 static PRLogModuleInfo *sLog;
44 if (!sLog)
45 sLog = PR_NewLogModule("DeviceContextSpecGTK");
46 return sLog;
47 }
48 #endif /* PR_LOGGING */
49 /* Macro to make lines shorter */
50 #define DO_PR_DEBUG_LOG(x) PR_LOG(GetDeviceContextSpecGTKLog(), PR_LOG_DEBUG, x)
52 //----------------------------------------------------------------------------------
53 // The printer data is shared between the PrinterEnumerator and the nsDeviceContextSpecGTK
54 // The PrinterEnumerator creates the printer info
55 // but the nsDeviceContextSpecGTK cleans it up
56 // If it gets created (via the Page Setup Dialog) but the user never prints anything
57 // then it will never be delete, so this class takes care of that.
58 class GlobalPrinters {
59 public:
60 static GlobalPrinters* GetInstance() { return &mGlobalPrinters; }
61 ~GlobalPrinters() { FreeGlobalPrinters(); }
63 void FreeGlobalPrinters();
64 nsresult InitializeGlobalPrinters();
66 bool PrintersAreAllocated() { return mGlobalPrinterList != nullptr; }
67 uint32_t GetNumPrinters()
68 { return mGlobalPrinterList ? mGlobalPrinterList->Length() : 0; }
69 nsString* GetStringAt(int32_t aInx) { return &mGlobalPrinterList->ElementAt(aInx); }
70 void GetDefaultPrinterName(char16_t **aDefaultPrinterName);
72 protected:
73 GlobalPrinters() {}
75 static GlobalPrinters mGlobalPrinters;
76 static nsTArray<nsString>* mGlobalPrinterList;
77 };
79 //---------------
80 // static members
81 GlobalPrinters GlobalPrinters::mGlobalPrinters;
82 nsTArray<nsString>* GlobalPrinters::mGlobalPrinterList = nullptr;
83 //---------------
85 nsDeviceContextSpecGTK::nsDeviceContextSpecGTK()
86 : mPrintJob(nullptr)
87 , mGtkPrinter(nullptr)
88 , mGtkPrintSettings(nullptr)
89 , mGtkPageSetup(nullptr)
90 {
91 DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::nsDeviceContextSpecGTK()\n"));
92 }
94 nsDeviceContextSpecGTK::~nsDeviceContextSpecGTK()
95 {
96 DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::~nsDeviceContextSpecGTK()\n"));
98 if (mGtkPageSetup) {
99 g_object_unref(mGtkPageSetup);
100 }
102 if (mGtkPrintSettings) {
103 g_object_unref(mGtkPrintSettings);
104 }
105 }
107 NS_IMPL_ISUPPORTS(nsDeviceContextSpecGTK,
108 nsIDeviceContextSpec)
110 #include "gfxPDFSurface.h"
111 #include "gfxPSSurface.h"
112 NS_IMETHODIMP nsDeviceContextSpecGTK::GetSurfaceForPrinter(gfxASurface **aSurface)
113 {
114 *aSurface = nullptr;
116 const char *path;
117 GetPath(&path);
119 double width, height;
120 mPrintSettings->GetEffectivePageSize(&width, &height);
122 // convert twips to points
123 width /= TWIPS_PER_POINT_FLOAT;
124 height /= TWIPS_PER_POINT_FLOAT;
126 DO_PR_DEBUG_LOG(("\"%s\", %f, %f\n", path, width, height));
127 nsresult rv;
129 // Spool file. Use Glib's temporary file function since we're
130 // already dependent on the gtk software stack.
131 gchar *buf;
132 gint fd = g_file_open_tmp("XXXXXX.tmp", &buf, nullptr);
133 if (-1 == fd)
134 return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE;
135 close(fd);
137 rv = NS_NewNativeLocalFile(nsDependentCString(buf), false,
138 getter_AddRefs(mSpoolFile));
139 if (NS_FAILED(rv)) {
140 unlink(buf);
141 return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE;
142 }
144 mSpoolName = buf;
145 g_free(buf);
147 mSpoolFile->SetPermissions(0600);
149 nsCOMPtr<nsIFileOutputStream> stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1");
150 rv = stream->Init(mSpoolFile, -1, -1, 0);
151 if (NS_FAILED(rv))
152 return rv;
154 int16_t format;
155 mPrintSettings->GetOutputFormat(&format);
157 nsRefPtr<gfxASurface> surface;
158 gfxSize surfaceSize(width, height);
160 // Determine the real format with some GTK magic
161 if (format == nsIPrintSettings::kOutputFormatNative) {
162 if (mIsPPreview) {
163 // There is nothing to detect on Print Preview, use PS.
164 format = nsIPrintSettings::kOutputFormatPS;
165 } else {
166 const gchar* fmtGTK = gtk_print_settings_get(mGtkPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT);
167 if (!fmtGTK && GTK_IS_PRINTER(mGtkPrinter)) {
168 // Likely not print-to-file, check printer's capabilities
170 // Prior to gtk 2.24, gtk_printer_accepts_pdf() and
171 // gtk_printer_accepts_ps() always returned true regardless of the
172 // printer's capability.
173 if (gtk_major_version > 2 ||
174 (gtk_major_version == 2 && gtk_minor_version >= 24)) {
175 format =
176 gtk_printer_accepts_pdf(mGtkPrinter) ?
177 static_cast<int16_t>(nsIPrintSettings::kOutputFormatPDF) :
178 static_cast<int16_t>(nsIPrintSettings::kOutputFormatPS);
179 } else {
180 format = nsIPrintSettings::kOutputFormatPS;
181 }
183 } else if (nsDependentCString(fmtGTK).EqualsIgnoreCase("pdf")) {
184 format = nsIPrintSettings::kOutputFormatPDF;
185 } else {
186 format = nsIPrintSettings::kOutputFormatPS;
187 }
188 }
189 }
191 if (format == nsIPrintSettings::kOutputFormatPDF) {
192 surface = new gfxPDFSurface(stream, surfaceSize);
193 } else {
194 int32_t orientation;
195 mPrintSettings->GetOrientation(&orientation);
196 if (nsIPrintSettings::kPortraitOrientation == orientation) {
197 surface = new gfxPSSurface(stream, surfaceSize, gfxPSSurface::PORTRAIT);
198 } else {
199 surface = new gfxPSSurface(stream, surfaceSize, gfxPSSurface::LANDSCAPE);
200 }
201 }
203 if (!surface)
204 return NS_ERROR_OUT_OF_MEMORY;
206 surface.swap(*aSurface);
208 return NS_OK;
209 }
211 /** -------------------------------------------------------
212 * Initialize the nsDeviceContextSpecGTK
213 * @update dc 2/15/98
214 * @update syd 3/2/99
215 */
216 NS_IMETHODIMP nsDeviceContextSpecGTK::Init(nsIWidget *aWidget,
217 nsIPrintSettings* aPS,
218 bool aIsPrintPreview)
219 {
220 DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::Init(aPS=%p)\n", aPS));
222 if (gtk_major_version < 2 ||
223 (gtk_major_version == 2 && gtk_minor_version < 10))
224 return NS_ERROR_NOT_AVAILABLE; // I'm so sorry bz
226 mPrintSettings = aPS;
227 mIsPPreview = aIsPrintPreview;
229 // This is only set by embedders
230 bool toFile;
231 aPS->GetPrintToFile(&toFile);
233 mToPrinter = !toFile && !aIsPrintPreview;
235 nsCOMPtr<nsPrintSettingsGTK> printSettingsGTK(do_QueryInterface(aPS));
236 if (!printSettingsGTK)
237 return NS_ERROR_NO_INTERFACE;
239 mGtkPrinter = printSettingsGTK->GetGtkPrinter();
240 mGtkPrintSettings = printSettingsGTK->GetGtkPrintSettings();
241 mGtkPageSetup = printSettingsGTK->GetGtkPageSetup();
243 // This is a horrible workaround for some printer driver bugs that treat custom page sizes different
244 // to standard ones. If our paper object matches one of a standard one, use a standard paper size
245 // object instead. See bug 414314 for more info.
246 GtkPaperSize* geckosHackishPaperSize = gtk_page_setup_get_paper_size(mGtkPageSetup);
247 GtkPaperSize* standardGtkPaperSize = gtk_paper_size_new(gtk_paper_size_get_name(geckosHackishPaperSize));
249 mGtkPageSetup = gtk_page_setup_copy(mGtkPageSetup);
250 mGtkPrintSettings = gtk_print_settings_copy(mGtkPrintSettings);
252 GtkPaperSize* properPaperSize;
253 if (gtk_paper_size_is_equal(geckosHackishPaperSize, standardGtkPaperSize)) {
254 properPaperSize = standardGtkPaperSize;
255 } else {
256 properPaperSize = geckosHackishPaperSize;
257 }
258 gtk_print_settings_set_paper_size(mGtkPrintSettings, properPaperSize);
259 gtk_page_setup_set_paper_size_and_default_margins(mGtkPageSetup, properPaperSize);
260 gtk_paper_size_free(standardGtkPaperSize);
262 return NS_OK;
263 }
265 NS_IMETHODIMP nsDeviceContextSpecGTK::GetPath(const char **aPath)
266 {
267 *aPath = mPath;
268 return NS_OK;
269 }
271 /* static !! */
272 nsresult nsDeviceContextSpecGTK::GetPrintMethod(const char *aPrinter, PrintMethod &aMethod)
273 {
274 aMethod = pmPostScript;
275 return NS_OK;
276 }
278 static void
279 #if (MOZ_WIDGET_GTK == 3)
280 print_callback(GtkPrintJob *aJob, gpointer aData, const GError *aError) {
281 #else
282 print_callback(GtkPrintJob *aJob, gpointer aData, GError *aError) {
283 #endif
284 g_object_unref(aJob);
285 ((nsIFile*) aData)->Remove(false);
286 }
288 static void
289 ns_release_macro(gpointer aData) {
290 nsIFile* spoolFile = (nsIFile*) aData;
291 NS_RELEASE(spoolFile);
292 }
294 NS_IMETHODIMP nsDeviceContextSpecGTK::BeginDocument(const nsAString& aTitle, char16_t * aPrintToFileName,
295 int32_t aStartPage, int32_t aEndPage)
296 {
297 if (mToPrinter) {
298 if (!GTK_IS_PRINTER(mGtkPrinter))
299 return NS_ERROR_FAILURE;
301 mPrintJob = gtk_print_job_new(NS_ConvertUTF16toUTF8(aTitle).get(), mGtkPrinter,
302 mGtkPrintSettings, mGtkPageSetup);
303 }
305 return NS_OK;
306 }
308 NS_IMETHODIMP nsDeviceContextSpecGTK::EndDocument()
309 {
310 if (mToPrinter) {
311 if (!mPrintJob)
312 return NS_OK; // The operation was aborted.
314 if (!gtk_print_job_set_source_file(mPrintJob, mSpoolName.get(), nullptr))
315 return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE;
317 NS_ADDREF(mSpoolFile.get());
318 gtk_print_job_send(mPrintJob, print_callback, mSpoolFile, ns_release_macro);
319 } else {
320 // Handle print-to-file ourselves for the benefit of embedders
321 nsXPIDLString targetPath;
322 nsCOMPtr<nsIFile> destFile;
323 mPrintSettings->GetToFileName(getter_Copies(targetPath));
325 nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(targetPath),
326 false, getter_AddRefs(destFile));
327 NS_ENSURE_SUCCESS(rv, rv);
329 nsAutoString destLeafName;
330 rv = destFile->GetLeafName(destLeafName);
331 NS_ENSURE_SUCCESS(rv, rv);
333 nsCOMPtr<nsIFile> destDir;
334 rv = destFile->GetParent(getter_AddRefs(destDir));
335 NS_ENSURE_SUCCESS(rv, rv);
337 rv = mSpoolFile->MoveTo(destDir, destLeafName);
338 NS_ENSURE_SUCCESS(rv, rv);
340 // This is the standard way to get the UNIX umask. Ugh.
341 mode_t mask = umask(0);
342 umask(mask);
343 // If you're not familiar with umasks, they contain the bits of what NOT to set in the permissions
344 // (thats because files and directories have different numbers of bits for their permissions)
345 destFile->SetPermissions(0666 & ~(mask));
346 }
347 return NS_OK;
348 }
350 /* Get prefs for printer
351 * Search order:
352 * - Get prefs per printer name and module name
353 * - Get prefs per printer name
354 * - Get prefs per module name
355 * - Get prefs
356 */
357 static
358 nsresult CopyPrinterCharPref(const char *modulename, const char *printername,
359 const char *prefname, nsCString &return_buf)
360 {
361 DO_PR_DEBUG_LOG(("CopyPrinterCharPref('%s', '%s', '%s')\n", modulename, printername, prefname));
363 nsresult rv = NS_ERROR_FAILURE;
365 if (printername && modulename) {
366 /* Get prefs per printer name and module name */
367 nsPrintfCString name("print.%s.printer_%s.%s", modulename, printername, prefname);
368 DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get()));
369 rv = Preferences::GetCString(name.get(), &return_buf);
370 }
372 if (NS_FAILED(rv)) {
373 if (printername) {
374 /* Get prefs per printer name */
375 nsPrintfCString name("print.printer_%s.%s", printername, prefname);
376 DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get()));
377 rv = Preferences::GetCString(name.get(), &return_buf);
378 }
380 if (NS_FAILED(rv)) {
381 if (modulename) {
382 /* Get prefs per module name */
383 nsPrintfCString name("print.%s.%s", modulename, prefname);
384 DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get()));
385 rv = Preferences::GetCString(name.get(), &return_buf);
386 }
388 if (NS_FAILED(rv)) {
389 /* Get prefs */
390 nsPrintfCString name("print.%s", prefname);
391 DO_PR_DEBUG_LOG(("trying to get '%s'\n", name.get()));
392 rv = Preferences::GetCString(name.get(), &return_buf);
393 }
394 }
395 }
397 #ifdef PR_LOG
398 if (NS_SUCCEEDED(rv)) {
399 DO_PR_DEBUG_LOG(("CopyPrinterCharPref returning '%s'.\n", return_buf.get()));
400 }
401 else
402 {
403 DO_PR_DEBUG_LOG(("CopyPrinterCharPref failure.\n"));
404 }
405 #endif /* PR_LOG */
407 return rv;
408 }
410 // Printer Enumerator
411 nsPrinterEnumeratorGTK::nsPrinterEnumeratorGTK()
412 {
413 }
415 NS_IMPL_ISUPPORTS(nsPrinterEnumeratorGTK, nsIPrinterEnumerator)
417 NS_IMETHODIMP nsPrinterEnumeratorGTK::GetPrinterNameList(nsIStringEnumerator **aPrinterNameList)
418 {
419 NS_ENSURE_ARG_POINTER(aPrinterNameList);
420 *aPrinterNameList = nullptr;
422 nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters();
423 if (NS_FAILED(rv)) {
424 return rv;
425 }
427 uint32_t numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters();
428 nsTArray<nsString> *printers = new nsTArray<nsString>(numPrinters);
429 if (!printers) {
430 GlobalPrinters::GetInstance()->FreeGlobalPrinters();
431 return NS_ERROR_OUT_OF_MEMORY;
432 }
434 uint32_t count = 0;
435 while( count < numPrinters )
436 {
437 printers->AppendElement(*GlobalPrinters::GetInstance()->GetStringAt(count++));
438 }
439 GlobalPrinters::GetInstance()->FreeGlobalPrinters();
441 return NS_NewAdoptingStringEnumerator(aPrinterNameList, printers);
442 }
444 /* readonly attribute wstring defaultPrinterName; */
445 NS_IMETHODIMP nsPrinterEnumeratorGTK::GetDefaultPrinterName(char16_t **aDefaultPrinterName)
446 {
447 DO_PR_DEBUG_LOG(("nsPrinterEnumeratorGTK::GetDefaultPrinterName()\n"));
448 NS_ENSURE_ARG_POINTER(aDefaultPrinterName);
450 GlobalPrinters::GetInstance()->GetDefaultPrinterName(aDefaultPrinterName);
452 DO_PR_DEBUG_LOG(("GetDefaultPrinterName(): default printer='%s'.\n", NS_ConvertUTF16toUTF8(*aDefaultPrinterName).get()));
453 return NS_OK;
454 }
456 /* void initPrintSettingsFromPrinter (in wstring aPrinterName, in nsIPrintSettings aPrintSettings); */
457 NS_IMETHODIMP nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter(const char16_t *aPrinterName, nsIPrintSettings *aPrintSettings)
458 {
459 DO_PR_DEBUG_LOG(("nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter()"));
460 nsresult rv;
462 NS_ENSURE_ARG_POINTER(aPrinterName);
463 NS_ENSURE_ARG_POINTER(aPrintSettings);
465 NS_ENSURE_TRUE(*aPrinterName, NS_ERROR_FAILURE);
466 NS_ENSURE_TRUE(aPrintSettings, NS_ERROR_FAILURE);
468 nsXPIDLCString fullPrinterName, /* Full name of printer incl. driver-specific prefix */
469 printerName; /* "Stripped" name of printer */
470 fullPrinterName.Assign(NS_ConvertUTF16toUTF8(aPrinterName));
471 printerName.Assign(NS_ConvertUTF16toUTF8(aPrinterName));
472 DO_PR_DEBUG_LOG(("printerName='%s'\n", printerName.get()));
474 PrintMethod type = pmInvalid;
475 rv = nsDeviceContextSpecGTK::GetPrintMethod(printerName, type);
476 if (NS_FAILED(rv))
477 return rv;
479 /* "Demangle" postscript printer name */
480 if (type == pmPostScript) {
481 /* Strip the printing method name from the printer,
482 * e.g. turn "PostScript/foobar" to "foobar" */
483 int32_t slash = printerName.FindChar('/');
484 if (kNotFound != slash)
485 printerName.Cut(0, slash + 1);
486 }
488 /* Set filename */
489 nsAutoCString filename;
490 if (NS_FAILED(CopyPrinterCharPref(nullptr, printerName, "filename", filename))) {
491 const char *path;
493 if (!(path = PR_GetEnv("PWD")))
494 path = PR_GetEnv("HOME");
496 if (path)
497 filename = nsPrintfCString("%s/mozilla.pdf", path);
498 else
499 filename.AssignLiteral("mozilla.pdf");
500 }
501 DO_PR_DEBUG_LOG(("Setting default filename to '%s'\n", filename.get()));
502 aPrintSettings->SetToFileName(NS_ConvertUTF8toUTF16(filename).get());
504 aPrintSettings->SetIsInitializedFromPrinter(true);
506 if (type == pmPostScript) {
507 DO_PR_DEBUG_LOG(("InitPrintSettingsFromPrinter() for PostScript printer\n"));
509 nsAutoCString orientation;
510 if (NS_SUCCEEDED(CopyPrinterCharPref("postscript", printerName,
511 "orientation", orientation))) {
512 if (orientation.LowerCaseEqualsLiteral("portrait")) {
513 DO_PR_DEBUG_LOG(("setting default orientation to 'portrait'\n"));
514 aPrintSettings->SetOrientation(nsIPrintSettings::kPortraitOrientation);
515 }
516 else if (orientation.LowerCaseEqualsLiteral("landscape")) {
517 DO_PR_DEBUG_LOG(("setting default orientation to 'landscape'\n"));
518 aPrintSettings->SetOrientation(nsIPrintSettings::kLandscapeOrientation);
519 }
520 else {
521 DO_PR_DEBUG_LOG(("Unknown default orientation '%s'\n", orientation.get()));
522 }
523 }
525 /* PostScript module does not support changing the plex mode... */
526 DO_PR_DEBUG_LOG(("setting default plex to '%s'\n", "default"));
527 aPrintSettings->SetPlexName(MOZ_UTF16("default"));
529 /* PostScript module does not support changing the resolution mode... */
530 DO_PR_DEBUG_LOG(("setting default resolution to '%s'\n", "default"));
531 aPrintSettings->SetResolutionName(MOZ_UTF16("default"));
533 /* PostScript module does not support changing the colorspace... */
534 DO_PR_DEBUG_LOG(("setting default colorspace to '%s'\n", "default"));
535 aPrintSettings->SetColorspace(MOZ_UTF16("default"));
537 nsAutoCString papername;
538 if (NS_SUCCEEDED(CopyPrinterCharPref("postscript", printerName,
539 "paper_size", papername))) {
540 nsPaperSizePS paper;
542 if (paper.Find(papername.get())) {
543 DO_PR_DEBUG_LOG(("setting default paper size to '%s' (%g mm/%g mm)\n",
544 paper.Name(), paper.Width_mm(), paper.Height_mm()));
545 aPrintSettings->SetPaperSizeUnit(nsIPrintSettings::kPaperSizeMillimeters);
546 aPrintSettings->SetPaperWidth(paper.Width_mm());
547 aPrintSettings->SetPaperHeight(paper.Height_mm());
548 aPrintSettings->SetPaperName(NS_ConvertASCIItoUTF16(paper.Name()).get());
549 }
550 else {
551 DO_PR_DEBUG_LOG(("Unknown paper size '%s' given.\n", papername.get()));
552 }
553 }
555 bool hasSpoolerCmd = (nsPSPrinterList::kTypePS ==
556 nsPSPrinterList::GetPrinterType(fullPrinterName));
558 if (hasSpoolerCmd) {
559 nsAutoCString command;
560 if (NS_SUCCEEDED(CopyPrinterCharPref("postscript",
561 printerName, "print_command", command))) {
562 DO_PR_DEBUG_LOG(("setting default print command to '%s'\n",
563 command.get()));
564 aPrintSettings->SetPrintCommand(NS_ConvertUTF8toUTF16(command).get());
565 }
566 }
568 return NS_OK;
569 }
571 return NS_ERROR_UNEXPECTED;
572 }
574 NS_IMETHODIMP nsPrinterEnumeratorGTK::DisplayPropertiesDlg(const char16_t *aPrinter, nsIPrintSettings *aPrintSettings)
575 {
576 return NS_OK;
577 }
579 //----------------------------------------------------------------------
580 nsresult GlobalPrinters::InitializeGlobalPrinters ()
581 {
582 if (PrintersAreAllocated()) {
583 return NS_OK;
584 }
586 mGlobalPrinterList = new nsTArray<nsString>();
588 nsPSPrinterList psMgr;
589 if (psMgr.Enabled()) {
590 /* Get the list of PostScript-module printers */
591 // XXX: this function is the only user of GetPrinterList
592 // So it may be interesting to convert the nsCStrings
593 // in this function, we would save one loop here
594 nsTArray<nsCString> printerList;
595 psMgr.GetPrinterList(printerList);
596 for (uint32_t i = 0; i < printerList.Length(); i++)
597 {
598 mGlobalPrinterList->AppendElement(NS_ConvertUTF8toUTF16(printerList[i]));
599 }
600 }
602 /* If there are no printers available after all checks, return an error */
603 if (!mGlobalPrinterList->Length())
604 {
605 /* Make sure we do not cache an empty printer list */
606 FreeGlobalPrinters();
608 return NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE;
609 }
611 return NS_OK;
612 }
614 //----------------------------------------------------------------------
615 void GlobalPrinters::FreeGlobalPrinters()
616 {
617 if (mGlobalPrinterList) {
618 delete mGlobalPrinterList;
619 mGlobalPrinterList = nullptr;
620 }
621 }
623 void
624 GlobalPrinters::GetDefaultPrinterName(char16_t **aDefaultPrinterName)
625 {
626 *aDefaultPrinterName = nullptr;
628 bool allocate = !GlobalPrinters::GetInstance()->PrintersAreAllocated();
630 if (allocate) {
631 nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters();
632 if (NS_FAILED(rv)) {
633 return;
634 }
635 }
636 NS_ASSERTION(GlobalPrinters::GetInstance()->PrintersAreAllocated(), "no GlobalPrinters");
638 if (GlobalPrinters::GetInstance()->GetNumPrinters() == 0)
639 return;
641 *aDefaultPrinterName = ToNewUnicode(*GlobalPrinters::GetInstance()->GetStringAt(0));
643 if (allocate) {
644 GlobalPrinters::GetInstance()->FreeGlobalPrinters();
645 }
646 }