PrintingParent.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  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. #include "mozilla/dom/Element.h"
  6. #include "mozilla/dom/TabParent.h"
  7. #include "mozilla/Preferences.h"
  8. #include "mozilla/Unused.h"
  9. #include "nsIContent.h"
  10. #include "nsIDocument.h"
  11. #include "nsIDOMWindow.h"
  12. #include "nsIPrintingPromptService.h"
  13. #include "nsIPrintProgressParams.h"
  14. #include "nsIPrintSettingsService.h"
  15. #include "nsIServiceManager.h"
  16. #include "nsServiceManagerUtils.h"
  17. #include "nsIWebProgressListener.h"
  18. #include "PrintingParent.h"
  19. #include "PrintDataUtils.h"
  20. #include "PrintProgressDialogParent.h"
  21. #include "PrintSettingsDialogParent.h"
  22. #include "mozilla/layout/RemotePrintJobParent.h"
  23. using namespace mozilla;
  24. using namespace mozilla::dom;
  25. using namespace mozilla::layout;
  26. namespace mozilla {
  27. namespace embedding {
  28. bool
  29. PrintingParent::RecvShowProgress(PBrowserParent* parent,
  30. PPrintProgressDialogParent* printProgressDialog,
  31. PRemotePrintJobParent* remotePrintJob,
  32. const bool& isForPrinting,
  33. bool* notifyOnOpen,
  34. nsresult* result)
  35. {
  36. *result = NS_ERROR_FAILURE;
  37. *notifyOnOpen = false;
  38. nsCOMPtr<nsPIDOMWindowOuter> parentWin = DOMWindowFromBrowserParent(parent);
  39. if (!parentWin) {
  40. return true;
  41. }
  42. nsCOMPtr<nsIPrintingPromptService> pps(do_GetService("@mozilla.org/embedcomp/printingprompt-service;1"));
  43. if (!pps) {
  44. return true;
  45. }
  46. PrintProgressDialogParent* dialogParent =
  47. static_cast<PrintProgressDialogParent*>(printProgressDialog);
  48. nsCOMPtr<nsIObserver> observer = do_QueryInterface(dialogParent);
  49. nsCOMPtr<nsIWebProgressListener> printProgressListener;
  50. nsCOMPtr<nsIPrintProgressParams> printProgressParams;
  51. *result = pps->ShowProgress(parentWin, nullptr, nullptr, observer,
  52. isForPrinting,
  53. getter_AddRefs(printProgressListener),
  54. getter_AddRefs(printProgressParams),
  55. notifyOnOpen);
  56. NS_ENSURE_SUCCESS(*result, true);
  57. if (remotePrintJob) {
  58. // If we have a RemotePrintJob use that as a more general forwarder for
  59. // print progress listeners.
  60. static_cast<RemotePrintJobParent*>(remotePrintJob)
  61. ->RegisterListener(printProgressListener);
  62. } else {
  63. dialogParent->SetWebProgressListener(printProgressListener);
  64. }
  65. dialogParent->SetPrintProgressParams(printProgressParams);
  66. return true;
  67. }
  68. nsresult
  69. PrintingParent::ShowPrintDialog(PBrowserParent* aParent,
  70. const PrintData& aData,
  71. PrintData* aResult)
  72. {
  73. // If aParent is null this call is just being used to get print settings from
  74. // the printer for print preview.
  75. bool isPrintPreview = !aParent;
  76. nsCOMPtr<nsPIDOMWindowOuter> parentWin;
  77. if (aParent) {
  78. parentWin = DOMWindowFromBrowserParent(aParent);
  79. if (!parentWin) {
  80. return NS_ERROR_FAILURE;
  81. }
  82. }
  83. nsCOMPtr<nsIPrintingPromptService> pps(do_GetService("@mozilla.org/embedcomp/printingprompt-service;1"));
  84. if (!pps) {
  85. return NS_ERROR_FAILURE;
  86. }
  87. // The initSettings we got can be wrapped using
  88. // PrintDataUtils' MockWebBrowserPrint, which implements enough of
  89. // nsIWebBrowserPrint to keep the dialogs happy.
  90. nsCOMPtr<nsIWebBrowserPrint> wbp = new MockWebBrowserPrint(aData);
  91. // Use the existing RemotePrintJob and its settings, if we have one, to make
  92. // sure they stay current.
  93. RemotePrintJobParent* remotePrintJob =
  94. static_cast<RemotePrintJobParent*>(aData.remotePrintJobParent());
  95. nsCOMPtr<nsIPrintSettings> settings;
  96. nsresult rv;
  97. if (remotePrintJob) {
  98. settings = remotePrintJob->GetPrintSettings();
  99. } else {
  100. rv = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(settings));
  101. NS_ENSURE_SUCCESS(rv, rv);
  102. }
  103. // We only want to use the print silently setting from the parent.
  104. bool printSilently;
  105. rv = settings->GetPrintSilent(&printSilently);
  106. NS_ENSURE_SUCCESS(rv, rv);
  107. rv = mPrintSettingsSvc->DeserializeToPrintSettings(aData, settings);
  108. NS_ENSURE_SUCCESS(rv, rv);
  109. rv = settings->SetPrintSilent(printSilently);
  110. NS_ENSURE_SUCCESS(rv, rv);
  111. // If this is for print preview or we are printing silently then we just need
  112. // to initialize the print settings with anything specific from the printer.
  113. if (isPrintPreview || printSilently ||
  114. Preferences::GetBool("print.always_print_silent", printSilently)) {
  115. nsXPIDLString printerName;
  116. rv = settings->GetPrinterName(getter_Copies(printerName));
  117. NS_ENSURE_SUCCESS(rv, rv);
  118. settings->SetIsInitializedFromPrinter(false);
  119. mPrintSettingsSvc->InitPrintSettingsFromPrinter(printerName, settings);
  120. } else {
  121. rv = pps->ShowPrintDialog(parentWin, wbp, settings);
  122. NS_ENSURE_SUCCESS(rv, rv);
  123. }
  124. if (isPrintPreview) {
  125. // For print preview we don't want a RemotePrintJob just the settings.
  126. rv = mPrintSettingsSvc->SerializeToPrintData(settings, nullptr, aResult);
  127. } else {
  128. rv = SerializeAndEnsureRemotePrintJob(settings, nullptr, remotePrintJob,
  129. aResult);
  130. }
  131. return rv;
  132. }
  133. bool
  134. PrintingParent::RecvShowPrintDialog(PPrintSettingsDialogParent* aDialog,
  135. PBrowserParent* aParent,
  136. const PrintData& aData)
  137. {
  138. PrintData resultData;
  139. nsresult rv = ShowPrintDialog(aParent, aData, &resultData);
  140. // The child has been spinning an event loop while waiting
  141. // to hear about the print settings. We return the results
  142. // with an async message which frees the child process from
  143. // its nested event loop.
  144. if (NS_FAILED(rv)) {
  145. mozilla::Unused << aDialog->Send__delete__(aDialog, rv);
  146. } else {
  147. mozilla::Unused << aDialog->Send__delete__(aDialog, resultData);
  148. }
  149. return true;
  150. }
  151. bool
  152. PrintingParent::RecvSavePrintSettings(const PrintData& aData,
  153. const bool& aUsePrinterNamePrefix,
  154. const uint32_t& aFlags,
  155. nsresult* aResult)
  156. {
  157. nsCOMPtr<nsIPrintSettings> settings;
  158. *aResult = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(settings));
  159. NS_ENSURE_SUCCESS(*aResult, true);
  160. *aResult = mPrintSettingsSvc->DeserializeToPrintSettings(aData, settings);
  161. NS_ENSURE_SUCCESS(*aResult, true);
  162. *aResult = mPrintSettingsSvc->SavePrintSettingsToPrefs(settings,
  163. aUsePrinterNamePrefix,
  164. aFlags);
  165. return true;
  166. }
  167. PPrintProgressDialogParent*
  168. PrintingParent::AllocPPrintProgressDialogParent()
  169. {
  170. PrintProgressDialogParent* actor = new PrintProgressDialogParent();
  171. NS_ADDREF(actor); // De-ref'd in the __delete__ handler for
  172. // PrintProgressDialogParent.
  173. return actor;
  174. }
  175. bool
  176. PrintingParent::DeallocPPrintProgressDialogParent(PPrintProgressDialogParent* doomed)
  177. {
  178. // We can't just delete the PrintProgressDialogParent since somebody might
  179. // still be holding a reference to it as nsIObserver, so just decrement the
  180. // refcount instead.
  181. PrintProgressDialogParent* actor = static_cast<PrintProgressDialogParent*>(doomed);
  182. NS_RELEASE(actor);
  183. return true;
  184. }
  185. PPrintSettingsDialogParent*
  186. PrintingParent::AllocPPrintSettingsDialogParent()
  187. {
  188. return new PrintSettingsDialogParent();
  189. }
  190. bool
  191. PrintingParent::DeallocPPrintSettingsDialogParent(PPrintSettingsDialogParent* aDoomed)
  192. {
  193. delete aDoomed;
  194. return true;
  195. }
  196. PRemotePrintJobParent*
  197. PrintingParent::AllocPRemotePrintJobParent()
  198. {
  199. MOZ_ASSERT_UNREACHABLE("No default constructors for implementations.");
  200. return nullptr;
  201. }
  202. bool
  203. PrintingParent::DeallocPRemotePrintJobParent(PRemotePrintJobParent* aDoomed)
  204. {
  205. delete aDoomed;
  206. return true;
  207. }
  208. void
  209. PrintingParent::ActorDestroy(ActorDestroyReason aWhy)
  210. {
  211. }
  212. nsPIDOMWindowOuter*
  213. PrintingParent::DOMWindowFromBrowserParent(PBrowserParent* parent)
  214. {
  215. if (!parent) {
  216. return nullptr;
  217. }
  218. TabParent* tabParent = TabParent::GetFrom(parent);
  219. if (!tabParent) {
  220. return nullptr;
  221. }
  222. nsCOMPtr<Element> frameElement = tabParent->GetOwnerElement();
  223. if (!frameElement) {
  224. return nullptr;
  225. }
  226. nsCOMPtr<nsIContent> frame(do_QueryInterface(frameElement));
  227. if (!frame) {
  228. return nullptr;
  229. }
  230. nsCOMPtr<nsPIDOMWindowOuter> parentWin = frame->OwnerDoc()->GetWindow();
  231. if (!parentWin) {
  232. return nullptr;
  233. }
  234. return parentWin;
  235. }
  236. nsresult
  237. PrintingParent::SerializeAndEnsureRemotePrintJob(
  238. nsIPrintSettings* aPrintSettings, nsIWebProgressListener* aListener,
  239. layout::RemotePrintJobParent* aRemotePrintJob, PrintData* aPrintData)
  240. {
  241. MOZ_ASSERT(aPrintData);
  242. nsresult rv;
  243. nsCOMPtr<nsIPrintSettings> printSettings;
  244. if (aPrintSettings) {
  245. printSettings = aPrintSettings;
  246. } else {
  247. rv = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(printSettings));
  248. if (NS_WARN_IF(NS_FAILED(rv))) {
  249. return rv;
  250. }
  251. }
  252. rv = mPrintSettingsSvc->SerializeToPrintData(printSettings, nullptr,
  253. aPrintData);
  254. if (NS_WARN_IF(NS_FAILED(rv))) {
  255. return rv;
  256. }
  257. RemotePrintJobParent* remotePrintJob;
  258. if (aRemotePrintJob) {
  259. remotePrintJob = aRemotePrintJob;
  260. aPrintData->remotePrintJobParent() = remotePrintJob;
  261. } else {
  262. remotePrintJob = new RemotePrintJobParent(aPrintSettings);
  263. aPrintData->remotePrintJobParent() =
  264. SendPRemotePrintJobConstructor(remotePrintJob);
  265. }
  266. if (aListener) {
  267. remotePrintJob->RegisterListener(aListener);
  268. }
  269. return NS_OK;
  270. }
  271. PrintingParent::PrintingParent()
  272. {
  273. MOZ_COUNT_CTOR(PrintingParent);
  274. mPrintSettingsSvc =
  275. do_GetService("@mozilla.org/gfx/printsettings-service;1");
  276. MOZ_ASSERT(mPrintSettingsSvc);
  277. }
  278. PrintingParent::~PrintingParent()
  279. {
  280. MOZ_COUNT_DTOR(PrintingParent);
  281. }
  282. } // namespace embedding
  283. } // namespace mozilla