/src/mozilla-central/widget/gtk/nsDeviceContextSpecG.cpp
Line | Count | Source (jump to first uncovered line) |
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/. */ |
5 | | |
6 | | #include "nsDeviceContextSpecG.h" |
7 | | |
8 | | #include "mozilla/gfx/PrintTargetPDF.h" |
9 | | #include "mozilla/gfx/PrintTargetPS.h" |
10 | | #include "mozilla/Logging.h" |
11 | | |
12 | | #include "plstr.h" |
13 | | #include "prenv.h" /* for PR_GetEnv */ |
14 | | |
15 | | #include "nsPrintfCString.h" |
16 | | #include "nsReadableUtils.h" |
17 | | #include "nsStringEnumerator.h" |
18 | | #include "nsIServiceManager.h" |
19 | | #include "nsThreadUtils.h" |
20 | | |
21 | | #include "nsPSPrinters.h" |
22 | | |
23 | | #include "nsPrintSettingsGTK.h" |
24 | | |
25 | | #include "nsIFileStreams.h" |
26 | | #include "nsIFile.h" |
27 | | #include "nsTArray.h" |
28 | | #include "nsThreadUtils.h" |
29 | | |
30 | | #include "mozilla/Preferences.h" |
31 | | |
32 | | #include <unistd.h> |
33 | | #include <sys/types.h> |
34 | | #include <sys/stat.h> |
35 | | |
36 | | // To check if we need to use flatpak portal for printing |
37 | | #include "nsIGIOService.h" |
38 | | |
39 | | using namespace mozilla; |
40 | | |
41 | | using mozilla::gfx::IntSize; |
42 | | using mozilla::gfx::PrintTarget; |
43 | | using mozilla::gfx::PrintTargetPDF; |
44 | | using mozilla::gfx::PrintTargetPS; |
45 | | |
46 | | static LazyLogModule sDeviceContextSpecGTKLog("DeviceContextSpecGTK"); |
47 | | /* Macro to make lines shorter */ |
48 | 0 | #define DO_PR_DEBUG_LOG(x) MOZ_LOG(sDeviceContextSpecGTKLog, mozilla::LogLevel::Debug, x) |
49 | | |
50 | | //---------------------------------------------------------------------------------- |
51 | | // The printer data is shared between the PrinterEnumerator and the nsDeviceContextSpecGTK |
52 | | // The PrinterEnumerator creates the printer info |
53 | | // but the nsDeviceContextSpecGTK cleans it up |
54 | | // If it gets created (via the Page Setup Dialog) but the user never prints anything |
55 | | // then it will never be delete, so this class takes care of that. |
56 | | class GlobalPrinters { |
57 | | public: |
58 | 0 | static GlobalPrinters* GetInstance() { return &mGlobalPrinters; } |
59 | 0 | ~GlobalPrinters() { FreeGlobalPrinters(); } |
60 | | |
61 | | void FreeGlobalPrinters(); |
62 | | nsresult InitializeGlobalPrinters(); |
63 | | |
64 | 0 | bool PrintersAreAllocated() { return mGlobalPrinterList != nullptr; } |
65 | | uint32_t GetNumPrinters() |
66 | 0 | { return mGlobalPrinterList ? mGlobalPrinterList->Length() : 0; } |
67 | 0 | nsString* GetStringAt(int32_t aInx) { return &mGlobalPrinterList->ElementAt(aInx); } |
68 | | void GetDefaultPrinterName(nsAString& aDefaultPrinterName); |
69 | | |
70 | | protected: |
71 | 3 | GlobalPrinters() {} |
72 | | |
73 | | static GlobalPrinters mGlobalPrinters; |
74 | | static nsTArray<nsString>* mGlobalPrinterList; |
75 | | }; |
76 | | |
77 | | //--------------- |
78 | | // static members |
79 | | GlobalPrinters GlobalPrinters::mGlobalPrinters; |
80 | | nsTArray<nsString>* GlobalPrinters::mGlobalPrinterList = nullptr; |
81 | | //--------------- |
82 | | |
83 | | nsDeviceContextSpecGTK::nsDeviceContextSpecGTK() |
84 | | : mGtkPrintSettings(nullptr) |
85 | | , mGtkPageSetup(nullptr) |
86 | 0 | { |
87 | 0 | DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::nsDeviceContextSpecGTK()\n")); |
88 | 0 | } |
89 | | |
90 | | nsDeviceContextSpecGTK::~nsDeviceContextSpecGTK() |
91 | 0 | { |
92 | 0 | DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::~nsDeviceContextSpecGTK()\n")); |
93 | 0 |
|
94 | 0 | if (mGtkPageSetup) { |
95 | 0 | g_object_unref(mGtkPageSetup); |
96 | 0 | } |
97 | 0 |
|
98 | 0 | if (mGtkPrintSettings) { |
99 | 0 | g_object_unref(mGtkPrintSettings); |
100 | 0 | } |
101 | 0 | } |
102 | | |
103 | | NS_IMPL_ISUPPORTS(nsDeviceContextSpecGTK, |
104 | | nsIDeviceContextSpec) |
105 | | |
106 | | already_AddRefed<PrintTarget> nsDeviceContextSpecGTK::MakePrintTarget() |
107 | 0 | { |
108 | 0 | double width, height; |
109 | 0 | mPrintSettings->GetEffectivePageSize(&width, &height); |
110 | 0 |
|
111 | 0 | // convert twips to points |
112 | 0 | width /= TWIPS_PER_POINT_FLOAT; |
113 | 0 | height /= TWIPS_PER_POINT_FLOAT; |
114 | 0 |
|
115 | 0 | DO_PR_DEBUG_LOG(("Making PrintTarget: width = %f, height = %f\n", width, height)); |
116 | 0 | nsresult rv; |
117 | 0 |
|
118 | 0 | // We shouldn't be attempting to get a surface if we've already got a spool |
119 | 0 | // file. |
120 | 0 | MOZ_ASSERT(!mSpoolFile); |
121 | 0 |
|
122 | 0 | // Spool file. Use Glib's temporary file function since we're |
123 | 0 | // already dependent on the gtk software stack. |
124 | 0 | gchar *buf; |
125 | 0 | gint fd = g_file_open_tmp("XXXXXX.tmp", &buf, nullptr); |
126 | 0 | if (-1 == fd) |
127 | 0 | return nullptr; |
128 | 0 | close(fd); |
129 | 0 |
|
130 | 0 | rv = NS_NewNativeLocalFile(nsDependentCString(buf), false, |
131 | 0 | getter_AddRefs(mSpoolFile)); |
132 | 0 | if (NS_FAILED(rv)) { |
133 | 0 | unlink(buf); |
134 | 0 | return nullptr; |
135 | 0 | } |
136 | 0 | |
137 | 0 | mSpoolName = buf; |
138 | 0 | g_free(buf); |
139 | 0 |
|
140 | 0 | mSpoolFile->SetPermissions(0600); |
141 | 0 |
|
142 | 0 | nsCOMPtr<nsIFileOutputStream> stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1"); |
143 | 0 | rv = stream->Init(mSpoolFile, -1, -1, 0); |
144 | 0 | if (NS_FAILED(rv)) |
145 | 0 | return nullptr; |
146 | 0 | |
147 | 0 | int16_t format; |
148 | 0 | mPrintSettings->GetOutputFormat(&format); |
149 | 0 |
|
150 | 0 | // Determine the real format with some GTK magic |
151 | 0 | if (format == nsIPrintSettings::kOutputFormatNative) { |
152 | 0 | if (mIsPPreview) { |
153 | 0 | // There is nothing to detect on Print Preview, use PDF. |
154 | 0 | format = nsIPrintSettings::kOutputFormatPDF; |
155 | 0 | } else { |
156 | 0 | return nullptr; |
157 | 0 | } |
158 | 0 | } |
159 | 0 | |
160 | 0 | IntSize size = IntSize::Truncate(width, height); |
161 | 0 |
|
162 | 0 | if (format == nsIPrintSettings::kOutputFormatPDF) { |
163 | 0 | return PrintTargetPDF::CreateOrNull(stream, size); |
164 | 0 | } |
165 | 0 | |
166 | 0 | int32_t orientation; |
167 | 0 | mPrintSettings->GetOrientation(&orientation); |
168 | 0 | return PrintTargetPS::CreateOrNull(stream, |
169 | 0 | size, |
170 | 0 | orientation == nsIPrintSettings::kPortraitOrientation |
171 | 0 | ? PrintTargetPS::PORTRAIT |
172 | 0 | : PrintTargetPS::LANDSCAPE); |
173 | 0 | } |
174 | | |
175 | | /** ------------------------------------------------------- |
176 | | * Initialize the nsDeviceContextSpecGTK |
177 | | * @update dc 2/15/98 |
178 | | * @update syd 3/2/99 |
179 | | */ |
180 | | NS_IMETHODIMP nsDeviceContextSpecGTK::Init(nsIWidget *aWidget, |
181 | | nsIPrintSettings* aPS, |
182 | | bool aIsPrintPreview) |
183 | 0 | { |
184 | 0 | DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::Init(aPS=%p)\n", aPS)); |
185 | 0 |
|
186 | 0 | if (gtk_major_version < 2 || |
187 | 0 | (gtk_major_version == 2 && gtk_minor_version < 10)) |
188 | 0 | return NS_ERROR_NOT_AVAILABLE; // I'm so sorry bz |
189 | 0 | |
190 | 0 | mPrintSettings = do_QueryInterface(aPS); |
191 | 0 | if (!mPrintSettings) |
192 | 0 | return NS_ERROR_NO_INTERFACE; |
193 | 0 | |
194 | 0 | mIsPPreview = aIsPrintPreview; |
195 | 0 |
|
196 | 0 | // This is only set by embedders |
197 | 0 | bool toFile; |
198 | 0 | aPS->GetPrintToFile(&toFile); |
199 | 0 |
|
200 | 0 | mToPrinter = !toFile && !aIsPrintPreview; |
201 | 0 |
|
202 | 0 | mGtkPrintSettings = mPrintSettings->GetGtkPrintSettings(); |
203 | 0 | mGtkPageSetup = mPrintSettings->GetGtkPageSetup(); |
204 | 0 |
|
205 | 0 | // This is a horrible workaround for some printer driver bugs that treat custom page sizes different |
206 | 0 | // to standard ones. If our paper object matches one of a standard one, use a standard paper size |
207 | 0 | // object instead. See bug 414314 for more info. |
208 | 0 | GtkPaperSize* geckosHackishPaperSize = gtk_page_setup_get_paper_size(mGtkPageSetup); |
209 | 0 | GtkPaperSize* standardGtkPaperSize = gtk_paper_size_new(gtk_paper_size_get_name(geckosHackishPaperSize)); |
210 | 0 |
|
211 | 0 | mGtkPageSetup = gtk_page_setup_copy(mGtkPageSetup); |
212 | 0 | mGtkPrintSettings = gtk_print_settings_copy(mGtkPrintSettings); |
213 | 0 |
|
214 | 0 | GtkPaperSize* properPaperSize; |
215 | 0 | if (gtk_paper_size_is_equal(geckosHackishPaperSize, standardGtkPaperSize)) { |
216 | 0 | properPaperSize = standardGtkPaperSize; |
217 | 0 | } else { |
218 | 0 | properPaperSize = geckosHackishPaperSize; |
219 | 0 | } |
220 | 0 | gtk_print_settings_set_paper_size(mGtkPrintSettings, properPaperSize); |
221 | 0 | gtk_page_setup_set_paper_size_and_default_margins(mGtkPageSetup, properPaperSize); |
222 | 0 | gtk_paper_size_free(standardGtkPaperSize); |
223 | 0 |
|
224 | 0 | return NS_OK; |
225 | 0 | } |
226 | | |
227 | | static void |
228 | | #ifdef MOZ_WIDGET_GTK |
229 | 0 | print_callback(GtkPrintJob *aJob, gpointer aData, const GError *aError) { |
230 | | #else |
231 | | print_callback(GtkPrintJob *aJob, gpointer aData, GError *aError) { |
232 | | #endif |
233 | | g_object_unref(aJob); |
234 | 0 | ((nsIFile*) aData)->Remove(false); |
235 | 0 | } |
236 | | |
237 | | static void |
238 | 0 | ns_release_macro(gpointer aData) { |
239 | 0 | nsIFile* spoolFile = (nsIFile*) aData; |
240 | 0 | NS_RELEASE(spoolFile); |
241 | 0 | } |
242 | | |
243 | | /* static */ |
244 | | gboolean nsDeviceContextSpecGTK::PrinterEnumerator(GtkPrinter *aPrinter, |
245 | 0 | gpointer aData) { |
246 | 0 | nsDeviceContextSpecGTK *spec = (nsDeviceContextSpecGTK*)aData; |
247 | 0 |
|
248 | 0 | // Find the printer whose name matches the one inside the settings. |
249 | 0 | nsString printerName; |
250 | 0 | nsresult rv = |
251 | 0 | spec->mPrintSettings->GetPrinterName(printerName); |
252 | 0 | if (NS_SUCCEEDED(rv) && !printerName.IsVoid()) { |
253 | 0 | NS_ConvertUTF16toUTF8 requestedName(printerName); |
254 | 0 | const char* currentName = gtk_printer_get_name(aPrinter); |
255 | 0 | if (requestedName.Equals(currentName)) { |
256 | 0 | spec->mPrintSettings->SetGtkPrinter(aPrinter); |
257 | 0 |
|
258 | 0 | // Bug 1145916 - attempting to kick off a print job for this printer |
259 | 0 | // during this tick of the event loop will result in the printer backend |
260 | 0 | // misunderstanding what the capabilities of the printer are due to a |
261 | 0 | // GTK bug (https://bugzilla.gnome.org/show_bug.cgi?id=753041). We |
262 | 0 | // sidestep this by deferring the print to the next tick. |
263 | 0 | NS_DispatchToCurrentThread( |
264 | 0 | NewRunnableMethod("nsDeviceContextSpecGTK::StartPrintJob", |
265 | 0 | spec, |
266 | 0 | &nsDeviceContextSpecGTK::StartPrintJob)); |
267 | 0 | return TRUE; |
268 | 0 | } |
269 | 0 | } |
270 | 0 | |
271 | 0 | // We haven't found it yet - keep searching... |
272 | 0 | return FALSE; |
273 | 0 | } |
274 | | |
275 | 0 | void nsDeviceContextSpecGTK::StartPrintJob() { |
276 | 0 | GtkPrintJob* job = gtk_print_job_new(mTitle.get(), |
277 | 0 | mPrintSettings->GetGtkPrinter(), |
278 | 0 | mGtkPrintSettings, |
279 | 0 | mGtkPageSetup); |
280 | 0 |
|
281 | 0 | if (!gtk_print_job_set_source_file(job, mSpoolName.get(), nullptr)) |
282 | 0 | return; |
283 | 0 | |
284 | 0 | NS_ADDREF(mSpoolFile.get()); |
285 | 0 | gtk_print_job_send(job, print_callback, mSpoolFile, ns_release_macro); |
286 | 0 | } |
287 | | |
288 | | void |
289 | | nsDeviceContextSpecGTK::EnumeratePrinters() |
290 | 0 | { |
291 | 0 | gtk_enumerate_printers(&nsDeviceContextSpecGTK::PrinterEnumerator, this, |
292 | 0 | nullptr, TRUE); |
293 | 0 | } |
294 | | |
295 | | NS_IMETHODIMP |
296 | | nsDeviceContextSpecGTK::BeginDocument(const nsAString& aTitle, |
297 | | const nsAString& aPrintToFileName, |
298 | | int32_t aStartPage, int32_t aEndPage) |
299 | 0 | { |
300 | 0 | // Print job names exceeding 255 bytes are safe with GTK version 3.18.2 or |
301 | 0 | // newer. This is a workaround for old GTK. |
302 | 0 | if (gtk_check_version(3,18,2) != nullptr) { |
303 | 0 | PrintTarget::AdjustPrintJobNameForIPP(aTitle, mTitle); |
304 | 0 | } else { |
305 | 0 | CopyUTF16toUTF8(aTitle, mTitle); |
306 | 0 | } |
307 | 0 |
|
308 | 0 | return NS_OK; |
309 | 0 | } |
310 | | |
311 | | NS_IMETHODIMP nsDeviceContextSpecGTK::EndDocument() |
312 | 0 | { |
313 | 0 | if (mToPrinter) { |
314 | 0 | // At this point, we might have a GtkPrinter set up in nsPrintSettingsGTK, |
315 | 0 | // or we might not. In the single-process case, we probably will, as this |
316 | 0 | // is populated by the print settings dialog, or set to the default |
317 | 0 | // printer. |
318 | 0 | // In the multi-process case, we proxy the print settings dialog over to |
319 | 0 | // the parent process, and only get the name of the printer back on the |
320 | 0 | // content process side. In that case, we need to enumerate the printers |
321 | 0 | // on the content side, and find a printer with a matching name. |
322 | 0 |
|
323 | 0 | GtkPrinter* printer = mPrintSettings->GetGtkPrinter(); |
324 | 0 | if (printer) { |
325 | 0 | // We have a printer, so we can print right away. |
326 | 0 | StartPrintJob(); |
327 | 0 | } else { |
328 | 0 | // We don't have a printer. We have to enumerate the printers and find |
329 | 0 | // one with a matching name. |
330 | 0 | NS_DispatchToCurrentThread( |
331 | 0 | NewRunnableMethod("nsDeviceContextSpecGTK::EnumeratePrinters", |
332 | 0 | this, |
333 | 0 | &nsDeviceContextSpecGTK::EnumeratePrinters)); |
334 | 0 | } |
335 | 0 | } else { |
336 | 0 | // Handle print-to-file ourselves for the benefit of embedders |
337 | 0 | nsString targetPath; |
338 | 0 | nsCOMPtr<nsIFile> destFile; |
339 | 0 | mPrintSettings->GetToFileName(targetPath); |
340 | 0 |
|
341 | 0 | nsresult rv = NS_NewLocalFile(targetPath, false, getter_AddRefs(destFile)); |
342 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
343 | 0 |
|
344 | 0 | nsAutoString destLeafName; |
345 | 0 | rv = destFile->GetLeafName(destLeafName); |
346 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
347 | 0 |
|
348 | 0 | nsCOMPtr<nsIFile> destDir; |
349 | 0 | rv = destFile->GetParent(getter_AddRefs(destDir)); |
350 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
351 | 0 |
|
352 | 0 | rv = mSpoolFile->MoveTo(destDir, destLeafName); |
353 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
354 | 0 |
|
355 | 0 | // This is the standard way to get the UNIX umask. Ugh. |
356 | 0 | mode_t mask = umask(0); |
357 | 0 | umask(mask); |
358 | 0 | // If you're not familiar with umasks, they contain the bits of what NOT to set in the permissions |
359 | 0 | // (thats because files and directories have different numbers of bits for their permissions) |
360 | 0 | destFile->SetPermissions(0666 & ~(mask)); |
361 | 0 |
|
362 | 0 | // Notify flatpak printing portal that file is completely written |
363 | 0 | nsCOMPtr<nsIGIOService> giovfs = |
364 | 0 | do_GetService(NS_GIOSERVICE_CONTRACTID); |
365 | 0 | bool shouldUsePortal; |
366 | 0 | if (giovfs) { |
367 | 0 | giovfs->ShouldUseFlatpakPortal(&shouldUsePortal); |
368 | 0 | if (shouldUsePortal) { |
369 | 0 | // Use the name of the file for printing to match with nsFlatpakPrintPortal |
370 | 0 | nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); |
371 | 0 | // Pass filename to be sure that observer process the right data |
372 | 0 | os->NotifyObservers(nullptr, "print-to-file-finished", targetPath.get()); |
373 | 0 | } |
374 | 0 | } |
375 | 0 | } |
376 | 0 | return NS_OK; |
377 | 0 | } |
378 | | |
379 | | // Printer Enumerator |
380 | | nsPrinterEnumeratorGTK::nsPrinterEnumeratorGTK() |
381 | 0 | { |
382 | 0 | } |
383 | | |
384 | | NS_IMPL_ISUPPORTS(nsPrinterEnumeratorGTK, nsIPrinterEnumerator) |
385 | | |
386 | | NS_IMETHODIMP nsPrinterEnumeratorGTK::GetPrinterNameList(nsIStringEnumerator **aPrinterNameList) |
387 | 0 | { |
388 | 0 | NS_ENSURE_ARG_POINTER(aPrinterNameList); |
389 | 0 | *aPrinterNameList = nullptr; |
390 | 0 |
|
391 | 0 | nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters(); |
392 | 0 | if (NS_FAILED(rv)) { |
393 | 0 | return rv; |
394 | 0 | } |
395 | 0 | |
396 | 0 | uint32_t numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters(); |
397 | 0 | nsTArray<nsString> *printers = new nsTArray<nsString>(numPrinters); |
398 | 0 | if (!printers) { |
399 | 0 | GlobalPrinters::GetInstance()->FreeGlobalPrinters(); |
400 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
401 | 0 | } |
402 | 0 | |
403 | 0 | uint32_t count = 0; |
404 | 0 | while( count < numPrinters ) |
405 | 0 | { |
406 | 0 | printers->AppendElement(*GlobalPrinters::GetInstance()->GetStringAt(count++)); |
407 | 0 | } |
408 | 0 | GlobalPrinters::GetInstance()->FreeGlobalPrinters(); |
409 | 0 |
|
410 | 0 | return NS_NewAdoptingStringEnumerator(aPrinterNameList, printers); |
411 | 0 | } |
412 | | |
413 | | NS_IMETHODIMP nsPrinterEnumeratorGTK::GetDefaultPrinterName(nsAString& aDefaultPrinterName) |
414 | 0 | { |
415 | 0 | DO_PR_DEBUG_LOG(("nsPrinterEnumeratorGTK::GetDefaultPrinterName()\n")); |
416 | 0 |
|
417 | 0 | GlobalPrinters::GetInstance()->GetDefaultPrinterName(aDefaultPrinterName); |
418 | 0 |
|
419 | 0 | DO_PR_DEBUG_LOG(("GetDefaultPrinterName(): default printer='%s'.\n", NS_ConvertUTF16toUTF8(aDefaultPrinterName).get())); |
420 | 0 | return NS_OK; |
421 | 0 | } |
422 | | |
423 | | NS_IMETHODIMP |
424 | | nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter(const nsAString& aPrinterName, |
425 | | nsIPrintSettings *aPrintSettings) |
426 | 0 | { |
427 | 0 | DO_PR_DEBUG_LOG(("nsPrinterEnumeratorGTK::InitPrintSettingsFromPrinter()")); |
428 | 0 |
|
429 | 0 | NS_ENSURE_ARG_POINTER(aPrintSettings); |
430 | 0 |
|
431 | 0 | // Set a default file name. |
432 | 0 | nsAutoString filename; |
433 | 0 | nsresult rv = aPrintSettings->GetToFileName(filename); |
434 | 0 | if (NS_FAILED(rv) || filename.IsEmpty()) { |
435 | 0 | const char* path = PR_GetEnv("PWD"); |
436 | 0 | if (!path) { |
437 | 0 | path = PR_GetEnv("HOME"); |
438 | 0 | } |
439 | 0 |
|
440 | 0 | if (path) { |
441 | 0 | CopyUTF8toUTF16(MakeStringSpan(path), filename); |
442 | 0 | filename.AppendLiteral("/mozilla.pdf"); |
443 | 0 | } else { |
444 | 0 | filename.AssignLiteral("mozilla.pdf"); |
445 | 0 | } |
446 | 0 |
|
447 | 0 | DO_PR_DEBUG_LOG(("Setting default filename to '%s'\n", |
448 | 0 | NS_ConvertUTF16toUTF8(filename).get())); |
449 | 0 | aPrintSettings->SetToFileName(filename); |
450 | 0 | } |
451 | 0 |
|
452 | 0 | aPrintSettings->SetIsInitializedFromPrinter(true); |
453 | 0 |
|
454 | 0 | return NS_OK; |
455 | 0 | } |
456 | | |
457 | | //---------------------------------------------------------------------- |
458 | | nsresult GlobalPrinters::InitializeGlobalPrinters () |
459 | 0 | { |
460 | 0 | if (PrintersAreAllocated()) { |
461 | 0 | return NS_OK; |
462 | 0 | } |
463 | 0 | |
464 | 0 | mGlobalPrinterList = new nsTArray<nsString>(); |
465 | 0 |
|
466 | 0 | nsPSPrinterList psMgr; |
467 | 0 | if (psMgr.Enabled()) { |
468 | 0 | /* Get the list of PostScript-module printers */ |
469 | 0 | // XXX: this function is the only user of GetPrinterList |
470 | 0 | // So it may be interesting to convert the nsCStrings |
471 | 0 | // in this function, we would save one loop here |
472 | 0 | nsTArray<nsCString> printerList; |
473 | 0 | psMgr.GetPrinterList(printerList); |
474 | 0 | for (uint32_t i = 0; i < printerList.Length(); i++) |
475 | 0 | { |
476 | 0 | mGlobalPrinterList->AppendElement(NS_ConvertUTF8toUTF16(printerList[i])); |
477 | 0 | } |
478 | 0 | } |
479 | 0 |
|
480 | 0 | /* If there are no printers available after all checks, return an error */ |
481 | 0 | if (!mGlobalPrinterList->Length()) |
482 | 0 | { |
483 | 0 | /* Make sure we do not cache an empty printer list */ |
484 | 0 | FreeGlobalPrinters(); |
485 | 0 |
|
486 | 0 | return NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE; |
487 | 0 | } |
488 | 0 | |
489 | 0 | return NS_OK; |
490 | 0 | } |
491 | | |
492 | | //---------------------------------------------------------------------- |
493 | | void GlobalPrinters::FreeGlobalPrinters() |
494 | 0 | { |
495 | 0 | if (mGlobalPrinterList) { |
496 | 0 | delete mGlobalPrinterList; |
497 | 0 | mGlobalPrinterList = nullptr; |
498 | 0 | } |
499 | 0 | } |
500 | | |
501 | | void |
502 | | GlobalPrinters::GetDefaultPrinterName(nsAString& aDefaultPrinterName) |
503 | 0 | { |
504 | 0 | aDefaultPrinterName.Truncate(); |
505 | 0 |
|
506 | 0 | bool allocate = !GlobalPrinters::GetInstance()->PrintersAreAllocated(); |
507 | 0 |
|
508 | 0 | if (allocate) { |
509 | 0 | nsresult rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters(); |
510 | 0 | if (NS_FAILED(rv)) { |
511 | 0 | return; |
512 | 0 | } |
513 | 0 | } |
514 | 0 | NS_ASSERTION(GlobalPrinters::GetInstance()->PrintersAreAllocated(), "no GlobalPrinters"); |
515 | 0 |
|
516 | 0 | if (GlobalPrinters::GetInstance()->GetNumPrinters() == 0) |
517 | 0 | return; |
518 | 0 | |
519 | 0 | aDefaultPrinterName = *GlobalPrinters::GetInstance()->GetStringAt(0); |
520 | 0 |
|
521 | 0 | if (allocate) { |
522 | 0 | GlobalPrinters::GetInstance()->FreeGlobalPrinters(); |
523 | 0 | } |
524 | 0 | } |
525 | | |