aw_print_manager.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "android_webview/browser/aw_print_manager.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/file_descriptor_posix.h"
  8. #include "base/files/file_util.h"
  9. #include "base/memory/ptr_util.h"
  10. #include "base/memory/ref_counted_memory.h"
  11. #include "base/numerics/safe_conversions.h"
  12. #include "base/task/task_traits.h"
  13. #include "base/task/thread_pool.h"
  14. #include "components/printing/browser/print_manager_utils.h"
  15. #include "components/printing/common/print.mojom.h"
  16. #include "content/public/browser/browser_thread.h"
  17. #include "content/public/browser/render_frame_host.h"
  18. #include "printing/print_job_constants.h"
  19. namespace android_webview {
  20. namespace {
  21. uint32_t SaveDataToFd(int fd,
  22. uint32_t page_count,
  23. scoped_refptr<base::RefCountedSharedMemoryMapping> data) {
  24. bool result = fd > base::kInvalidFd &&
  25. base::IsValueInRangeForNumericType<int>(data->size());
  26. if (result)
  27. result = base::WriteFileDescriptor(fd, *data);
  28. return result ? page_count : 0;
  29. }
  30. } // namespace
  31. AwPrintManager::AwPrintManager(content::WebContents* contents)
  32. : PrintManager(contents),
  33. content::WebContentsUserData<AwPrintManager>(*contents) {}
  34. AwPrintManager::~AwPrintManager() = default;
  35. // static
  36. void AwPrintManager::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 = AwPrintManager::FromWebContents(web_contents);
  43. if (!print_manager)
  44. return;
  45. print_manager->BindReceiver(std::move(receiver), rfh);
  46. }
  47. void AwPrintManager::PdfWritingDone(int page_count) {
  48. pdf_writing_done_callback().Run(page_count);
  49. // Invalidate the file descriptor so it doesn't get reused.
  50. fd_ = -1;
  51. }
  52. bool AwPrintManager::PrintNow() {
  53. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  54. auto* rfh = web_contents()->GetPrimaryMainFrame();
  55. if (!rfh->IsRenderFrameLive())
  56. return false;
  57. GetPrintRenderFrame(rfh)->PrintRequestedPages();
  58. return true;
  59. }
  60. void AwPrintManager::GetDefaultPrintSettings(
  61. GetDefaultPrintSettingsCallback callback) {
  62. // Unlike PrintViewManagerBase, we do process this in UI thread.
  63. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  64. auto params = printing::mojom::PrintParams::New();
  65. printing::RenderParamsFromPrintSettings(*settings_, params.get());
  66. params->document_cookie = cookie();
  67. std::move(callback).Run(std::move(params));
  68. }
  69. void AwPrintManager::UpdateParam(
  70. std::unique_ptr<printing::PrintSettings> settings,
  71. int file_descriptor,
  72. PrintManager::PdfWritingDoneCallback callback) {
  73. DCHECK(settings);
  74. DCHECK(callback);
  75. settings_ = std::move(settings);
  76. fd_ = file_descriptor;
  77. set_pdf_writing_done_callback(std::move(callback));
  78. set_cookie(1); // Set a valid dummy cookie value.
  79. }
  80. void AwPrintManager::ScriptedPrint(
  81. printing::mojom::ScriptedPrintParamsPtr scripted_params,
  82. ScriptedPrintCallback callback) {
  83. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  84. auto params = printing::mojom::PrintPagesParams::New();
  85. params->params = printing::mojom::PrintParams::New();
  86. if (scripted_params->is_scripted &&
  87. GetCurrentTargetFrame()->IsNestedWithinFencedFrame()) {
  88. DLOG(ERROR) << "Unexpected message received. Script Print is not allowed"
  89. " in a fenced frame.";
  90. std::move(callback).Run(std::move(params));
  91. return;
  92. }
  93. printing::RenderParamsFromPrintSettings(*settings_, params->params.get());
  94. params->params->document_cookie = scripted_params->cookie;
  95. params->pages = settings_->ranges();
  96. std::move(callback).Run(std::move(params));
  97. }
  98. void AwPrintManager::DidPrintDocument(
  99. printing::mojom::DidPrintDocumentParamsPtr params,
  100. DidPrintDocumentCallback callback) {
  101. if (params->document_cookie != cookie()) {
  102. std::move(callback).Run(false);
  103. return;
  104. }
  105. const printing::mojom::DidPrintContentParams& content = *params->content;
  106. if (!content.metafile_data_region.IsValid()) {
  107. NOTREACHED() << "invalid memory handle";
  108. web_contents()->Stop();
  109. PdfWritingDone(0);
  110. std::move(callback).Run(false);
  111. return;
  112. }
  113. auto data = base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(
  114. content.metafile_data_region);
  115. if (!data) {
  116. NOTREACHED() << "couldn't map";
  117. web_contents()->Stop();
  118. PdfWritingDone(0);
  119. std::move(callback).Run(false);
  120. return;
  121. }
  122. if (number_pages() > printing::kMaxPageCount) {
  123. web_contents()->Stop();
  124. PdfWritingDone(0);
  125. std::move(callback).Run(false);
  126. return;
  127. }
  128. DCHECK(pdf_writing_done_callback());
  129. base::PostTaskAndReplyWithResult(
  130. base::ThreadPool::CreateTaskRunner(
  131. {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
  132. base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})
  133. .get(),
  134. FROM_HERE, base::BindOnce(&SaveDataToFd, fd_, number_pages(), data),
  135. base::BindOnce(&AwPrintManager::OnDidPrintDocumentWritingDone,
  136. pdf_writing_done_callback(), std::move(callback)));
  137. }
  138. // static
  139. void AwPrintManager::OnDidPrintDocumentWritingDone(
  140. const PdfWritingDoneCallback& callback,
  141. DidPrintDocumentCallback did_print_document_cb,
  142. uint32_t page_count) {
  143. DCHECK_LE(page_count, printing::kMaxPageCount);
  144. if (callback)
  145. callback.Run(base::checked_cast<int>(page_count));
  146. std::move(did_print_document_cb).Run(true);
  147. }
  148. WEB_CONTENTS_USER_DATA_KEY_IMPL(AwPrintManager);
  149. } // namespace android_webview