print_view_manager_electron.cc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Copyright 2020 Microsoft, Inc. All rights reserved.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/printing/print_view_manager_electron.h"
  5. #include <utility>
  6. #include "build/build_config.h"
  7. #include "components/printing/browser/print_to_pdf/pdf_print_utils.h"
  8. #include "printing/mojom/print.mojom.h"
  9. #include "printing/page_range.h"
  10. #include "third_party/abseil-cpp/absl/types/variant.h"
  11. #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
  12. #include "mojo/public/cpp/bindings/message.h"
  13. #endif
  14. namespace electron {
  15. namespace {
  16. #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
  17. constexpr char kInvalidUpdatePrintSettingsCall[] =
  18. "Invalid UpdatePrintSettings Call";
  19. constexpr char kInvalidSetupScriptedPrintPreviewCall[] =
  20. "Invalid SetupScriptedPrintPreview Call";
  21. constexpr char kInvalidShowScriptedPrintPreviewCall[] =
  22. "Invalid ShowScriptedPrintPreview Call";
  23. constexpr char kInvalidRequestPrintPreviewCall[] =
  24. "Invalid RequestPrintPreview Call";
  25. #endif
  26. } // namespace
  27. // This file subclasses printing::PrintViewManagerBase
  28. // but the implementations are duplicated from
  29. // components/printing/browser/print_to_pdf/pdf_print_manager.cc.
  30. PrintViewManagerElectron::PrintViewManagerElectron(
  31. content::WebContents* web_contents)
  32. : printing::PrintViewManagerBase(web_contents),
  33. content::WebContentsUserData<PrintViewManagerElectron>(*web_contents) {}
  34. PrintViewManagerElectron::~PrintViewManagerElectron() = default;
  35. // static
  36. void PrintViewManagerElectron::BindPrintManagerHost(
  37. mojo::PendingAssociatedReceiver<printing::mojom::PrintManagerHost> receiver,
  38. content::RenderFrameHost* rfh) {
  39. auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
  40. if (!web_contents)
  41. return;
  42. auto* print_manager = PrintViewManagerElectron::FromWebContents(web_contents);
  43. if (!print_manager)
  44. return;
  45. print_manager->BindReceiver(std::move(receiver), rfh);
  46. }
  47. // static
  48. std::string PrintViewManagerElectron::PrintResultToString(PrintResult result) {
  49. switch (result) {
  50. case PRINT_SUCCESS:
  51. return std::string(); // no error message
  52. case PRINTING_FAILED:
  53. return "Printing failed";
  54. case INVALID_PRINTER_SETTINGS:
  55. return "Show invalid printer settings error";
  56. case INVALID_MEMORY_HANDLE:
  57. return "Invalid memory handle";
  58. case METAFILE_MAP_ERROR:
  59. return "Map to shared memory error";
  60. case METAFILE_INVALID_HEADER:
  61. return "Invalid metafile header";
  62. case METAFILE_GET_DATA_ERROR:
  63. return "Get data from metafile error";
  64. case SIMULTANEOUS_PRINT_ACTIVE:
  65. return "The previous printing job hasn't finished";
  66. case PAGE_RANGE_SYNTAX_ERROR:
  67. return "Page range syntax error";
  68. case PAGE_RANGE_INVALID_RANGE:
  69. return "Page range is invalid (start > end)";
  70. case PAGE_COUNT_EXCEEDED:
  71. return "Page range exceeds page count";
  72. default:
  73. NOTREACHED();
  74. return "Unknown PrintResult";
  75. }
  76. }
  77. void PrintViewManagerElectron::PrintToPdf(
  78. content::RenderFrameHost* rfh,
  79. const std::string& page_ranges,
  80. printing::mojom::PrintPagesParamsPtr print_pages_params,
  81. PrintToPDFCallback callback) {
  82. DCHECK(callback);
  83. if (callback_) {
  84. std::move(callback).Run(SIMULTANEOUS_PRINT_ACTIVE,
  85. base::MakeRefCounted<base::RefCountedString>());
  86. return;
  87. }
  88. if (!rfh->IsRenderFrameLive()) {
  89. std::move(callback).Run(PRINTING_FAILED,
  90. base::MakeRefCounted<base::RefCountedString>());
  91. return;
  92. }
  93. absl::variant<printing::PageRanges, print_to_pdf::PageRangeError>
  94. parsed_ranges = print_to_pdf::TextPageRangesToPageRanges(page_ranges);
  95. if (absl::holds_alternative<print_to_pdf::PageRangeError>(parsed_ranges)) {
  96. PrintResult print_result;
  97. switch (absl::get<print_to_pdf::PageRangeError>(parsed_ranges)) {
  98. case print_to_pdf::PageRangeError::kSyntaxError:
  99. print_result = PAGE_RANGE_SYNTAX_ERROR;
  100. break;
  101. case print_to_pdf::PageRangeError::kInvalidRange:
  102. print_result = PAGE_RANGE_INVALID_RANGE;
  103. break;
  104. }
  105. std::move(callback).Run(print_result,
  106. base::MakeRefCounted<base::RefCountedString>());
  107. return;
  108. }
  109. printing_rfh_ = rfh;
  110. print_pages_params->pages = absl::get<printing::PageRanges>(parsed_ranges);
  111. auto cookie = print_pages_params->params->document_cookie;
  112. set_cookie(cookie);
  113. headless_jobs_.emplace_back(cookie);
  114. callback_ = std::move(callback);
  115. GetPrintRenderFrame(rfh)->PrintWithParams(std::move(print_pages_params));
  116. }
  117. void PrintViewManagerElectron::GetDefaultPrintSettings(
  118. GetDefaultPrintSettingsCallback callback) {
  119. if (printing_rfh_) {
  120. LOG(ERROR) << "Scripted print is not supported";
  121. std::move(callback).Run(printing::mojom::PrintParams::New());
  122. } else {
  123. PrintViewManagerBase::GetDefaultPrintSettings(std::move(callback));
  124. }
  125. }
  126. void PrintViewManagerElectron::ScriptedPrint(
  127. printing::mojom::ScriptedPrintParamsPtr params,
  128. ScriptedPrintCallback callback) {
  129. auto entry =
  130. std::find(headless_jobs_.begin(), headless_jobs_.end(), params->cookie);
  131. if (entry == headless_jobs_.end()) {
  132. PrintViewManagerBase::ScriptedPrint(std::move(params), std::move(callback));
  133. return;
  134. }
  135. auto default_param = printing::mojom::PrintPagesParams::New();
  136. default_param->params = printing::mojom::PrintParams::New();
  137. LOG(ERROR) << "Scripted print is not supported";
  138. std::move(callback).Run(std::move(default_param), /*cancelled*/ false);
  139. }
  140. void PrintViewManagerElectron::ShowInvalidPrinterSettingsError() {
  141. ReleaseJob(INVALID_PRINTER_SETTINGS);
  142. }
  143. void PrintViewManagerElectron::PrintingFailed(
  144. int32_t cookie,
  145. printing::mojom::PrintFailureReason reason) {
  146. ReleaseJob(reason == printing::mojom::PrintFailureReason::kInvalidPageRange
  147. ? PAGE_COUNT_EXCEEDED
  148. : PRINTING_FAILED);
  149. }
  150. #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
  151. void PrintViewManagerElectron::UpdatePrintSettings(
  152. int32_t cookie,
  153. base::Value::Dict job_settings,
  154. UpdatePrintSettingsCallback callback) {
  155. auto entry = std::find(headless_jobs_.begin(), headless_jobs_.end(), cookie);
  156. if (entry == headless_jobs_.end()) {
  157. PrintViewManagerBase::UpdatePrintSettings(cookie, std::move(job_settings),
  158. std::move(callback));
  159. return;
  160. }
  161. mojo::ReportBadMessage(kInvalidUpdatePrintSettingsCall);
  162. }
  163. void PrintViewManagerElectron::SetupScriptedPrintPreview(
  164. SetupScriptedPrintPreviewCallback callback) {
  165. mojo::ReportBadMessage(kInvalidSetupScriptedPrintPreviewCall);
  166. }
  167. void PrintViewManagerElectron::ShowScriptedPrintPreview(
  168. bool source_is_modifiable) {
  169. mojo::ReportBadMessage(kInvalidShowScriptedPrintPreviewCall);
  170. }
  171. void PrintViewManagerElectron::RequestPrintPreview(
  172. printing::mojom::RequestPrintPreviewParamsPtr params) {
  173. mojo::ReportBadMessage(kInvalidRequestPrintPreviewCall);
  174. }
  175. void PrintViewManagerElectron::CheckForCancel(int32_t preview_ui_id,
  176. int32_t request_id,
  177. CheckForCancelCallback callback) {
  178. std::move(callback).Run(false);
  179. }
  180. #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
  181. void PrintViewManagerElectron::RenderFrameDeleted(
  182. content::RenderFrameHost* render_frame_host) {
  183. PrintViewManagerBase::RenderFrameDeleted(render_frame_host);
  184. if (printing_rfh_ != render_frame_host)
  185. return;
  186. if (callback_) {
  187. std::move(callback_).Run(PRINTING_FAILED,
  188. base::MakeRefCounted<base::RefCountedString>());
  189. }
  190. Reset();
  191. }
  192. void PrintViewManagerElectron::DidGetPrintedPagesCount(int32_t cookie,
  193. uint32_t number_pages) {
  194. auto entry = std::find(headless_jobs_.begin(), headless_jobs_.end(), cookie);
  195. if (entry == headless_jobs_.end()) {
  196. PrintViewManagerBase::DidGetPrintedPagesCount(cookie, number_pages);
  197. }
  198. }
  199. void PrintViewManagerElectron::DidPrintDocument(
  200. printing::mojom::DidPrintDocumentParamsPtr params,
  201. DidPrintDocumentCallback callback) {
  202. auto entry = std::find(headless_jobs_.begin(), headless_jobs_.end(),
  203. params->document_cookie);
  204. if (entry == headless_jobs_.end()) {
  205. PrintViewManagerBase::DidPrintDocument(std::move(params),
  206. std::move(callback));
  207. return;
  208. }
  209. auto& content = *params->content;
  210. if (!content.metafile_data_region.IsValid()) {
  211. ReleaseJob(INVALID_MEMORY_HANDLE);
  212. std::move(callback).Run(false);
  213. return;
  214. }
  215. base::ReadOnlySharedMemoryMapping map = content.metafile_data_region.Map();
  216. if (!map.IsValid()) {
  217. ReleaseJob(METAFILE_MAP_ERROR);
  218. std::move(callback).Run(false);
  219. return;
  220. }
  221. data_ = std::string(static_cast<const char*>(map.memory()), map.size());
  222. headless_jobs_.erase(entry);
  223. std::move(callback).Run(true);
  224. ReleaseJob(PRINT_SUCCESS);
  225. }
  226. void PrintViewManagerElectron::Reset() {
  227. printing_rfh_ = nullptr;
  228. callback_.Reset();
  229. data_.clear();
  230. }
  231. void PrintViewManagerElectron::ReleaseJob(PrintResult result) {
  232. if (callback_) {
  233. DCHECK(result == PRINT_SUCCESS || data_.empty());
  234. std::move(callback_).Run(result,
  235. base::RefCountedString::TakeString(&data_));
  236. if (printing_rfh_ && printing_rfh_->IsRenderFrameLive()) {
  237. GetPrintRenderFrame(printing_rfh_)->PrintingDone(result == PRINT_SUCCESS);
  238. }
  239. Reset();
  240. }
  241. }
  242. WEB_CONTENTS_USER_DATA_KEY_IMPL(PrintViewManagerElectron);
  243. } // namespace electron