 e77d065875
			
		
	
	
	e77d065875
	
	
	
		
			
			Until one of the latest version of node, the definition of the DISALLOW_COPY_AND_ASSIGN macro in node was different than in chromium. That is no longer the case, so just undefining the macro in node_includes.h works.
		
			
				
	
	
		
			198 lines
		
	
	
	
		
			6.4 KiB
			
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
	
		
			6.4 KiB
			
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (c) 2018 GitHub, Inc.
 | |
| // Use of this source code is governed by the MIT license that can be
 | |
| // found in the LICENSE file.
 | |
| 
 | |
| #include "atom/browser/printing/print_preview_message_handler.h"
 | |
| 
 | |
| #include <memory>
 | |
| #include <utility>
 | |
| 
 | |
| #include "atom/common/node_includes.h"
 | |
| #include "base/bind.h"
 | |
| #include "base/memory/read_only_shared_memory_region.h"
 | |
| #include "base/memory/ref_counted.h"
 | |
| #include "base/memory/ref_counted_memory.h"
 | |
| #include "base/task/post_task.h"
 | |
| #include "chrome/browser/browser_process.h"
 | |
| #include "chrome/browser/printing/print_job_manager.h"
 | |
| #include "chrome/browser/printing/printer_query.h"
 | |
| #include "components/printing/browser/print_composite_client.h"
 | |
| #include "components/printing/browser/print_manager_utils.h"
 | |
| #include "components/printing/common/print_messages.h"
 | |
| #include "components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h"
 | |
| #include "content/public/browser/browser_task_traits.h"
 | |
| #include "content/public/browser/browser_thread.h"
 | |
| #include "content/public/browser/render_frame_host.h"
 | |
| #include "content/public/browser/web_contents.h"
 | |
| 
 | |
| using content::BrowserThread;
 | |
| 
 | |
| namespace atom {
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| void StopWorker(int document_cookie) {
 | |
|   if (document_cookie <= 0)
 | |
|     return;
 | |
|   scoped_refptr<printing::PrintQueriesQueue> queue =
 | |
|       g_browser_process->print_job_manager()->queue();
 | |
|   scoped_refptr<printing::PrinterQuery> printer_query =
 | |
|       queue->PopPrinterQuery(document_cookie);
 | |
|   if (printer_query.get()) {
 | |
|     base::PostTaskWithTraits(
 | |
|         FROM_HERE, {BrowserThread::IO},
 | |
|         base::BindOnce(&printing::PrinterQuery::StopWorker, printer_query));
 | |
|   }
 | |
| }
 | |
| 
 | |
| }  // namespace
 | |
| 
 | |
| PrintPreviewMessageHandler::PrintPreviewMessageHandler(
 | |
|     content::WebContents* web_contents)
 | |
|     : content::WebContentsObserver(web_contents), weak_ptr_factory_(this) {
 | |
|   DCHECK(web_contents);
 | |
| }
 | |
| 
 | |
| PrintPreviewMessageHandler::~PrintPreviewMessageHandler() = default;
 | |
| 
 | |
| bool PrintPreviewMessageHandler::OnMessageReceived(
 | |
|     const IPC::Message& message,
 | |
|     content::RenderFrameHost* render_frame_host) {
 | |
|   bool handled = true;
 | |
|   IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(PrintPreviewMessageHandler, message,
 | |
|                                    render_frame_host)
 | |
|     IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting,
 | |
|                         OnMetafileReadyForPrinting)
 | |
|     IPC_MESSAGE_UNHANDLED(handled = false)
 | |
|   IPC_END_MESSAGE_MAP()
 | |
|   if (handled)
 | |
|     return true;
 | |
| 
 | |
|   handled = true;
 | |
|   IPC_BEGIN_MESSAGE_MAP(PrintPreviewMessageHandler, message)
 | |
|     IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewFailed, OnPrintPreviewFailed)
 | |
|     IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewCancelled,
 | |
|                         OnPrintPreviewCancelled)
 | |
|     IPC_MESSAGE_UNHANDLED(handled = false)
 | |
|   IPC_END_MESSAGE_MAP()
 | |
|   return handled;
 | |
| }
 | |
| 
 | |
| void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
 | |
|     content::RenderFrameHost* render_frame_host,
 | |
|     const PrintHostMsg_DidPreviewDocument_Params& params,
 | |
|     const PrintHostMsg_PreviewIds& ids) {
 | |
|   // Always try to stop the worker.
 | |
|   StopWorker(params.document_cookie);
 | |
| 
 | |
|   const PrintHostMsg_DidPrintContent_Params& content = params.content;
 | |
|   if (!content.metafile_data_region.IsValid() ||
 | |
|       params.expected_pages_count <= 0) {
 | |
|     RejectPromise(ids.request_id);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (printing::IsOopifEnabled()) {
 | |
|     auto* client =
 | |
|         printing::PrintCompositeClient::FromWebContents(web_contents());
 | |
|     DCHECK(client);
 | |
|     client->DoCompositeDocumentToPdf(
 | |
|         params.document_cookie, render_frame_host, content,
 | |
|         base::BindOnce(&PrintPreviewMessageHandler::OnCompositePdfDocumentDone,
 | |
|                        weak_ptr_factory_.GetWeakPtr(), ids));
 | |
|   } else {
 | |
|     ResolvePromise(ids.request_id,
 | |
|                    base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(
 | |
|                        content.metafile_data_region));
 | |
|   }
 | |
| }
 | |
| 
 | |
| void PrintPreviewMessageHandler::OnCompositePdfDocumentDone(
 | |
|     const PrintHostMsg_PreviewIds& ids,
 | |
|     printing::mojom::PdfCompositor::Status status,
 | |
|     base::ReadOnlySharedMemoryRegion region) {
 | |
|   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 | |
| 
 | |
|   if (status != printing::mojom::PdfCompositor::Status::SUCCESS) {
 | |
|     DLOG(ERROR) << "Compositing pdf failed with error " << status;
 | |
|     RejectPromise(ids.request_id);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   ResolvePromise(
 | |
|       ids.request_id,
 | |
|       base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region));
 | |
| }
 | |
| 
 | |
| void PrintPreviewMessageHandler::OnPrintPreviewFailed(
 | |
|     int document_cookie,
 | |
|     const PrintHostMsg_PreviewIds& ids) {
 | |
|   StopWorker(document_cookie);
 | |
| 
 | |
|   RejectPromise(ids.request_id);
 | |
| }
 | |
| 
 | |
| void PrintPreviewMessageHandler::OnPrintPreviewCancelled(
 | |
|     int document_cookie,
 | |
|     const PrintHostMsg_PreviewIds& ids) {
 | |
|   StopWorker(document_cookie);
 | |
| 
 | |
|   RejectPromise(ids.request_id);
 | |
| }
 | |
| 
 | |
| void PrintPreviewMessageHandler::PrintToPDF(
 | |
|     const base::DictionaryValue& options,
 | |
|     atom::util::Promise promise) {
 | |
|   int request_id;
 | |
|   options.GetInteger(printing::kPreviewRequestID, &request_id);
 | |
|   promise_map_.emplace(request_id, std::move(promise));
 | |
| 
 | |
|   auto* focused_frame = web_contents()->GetFocusedFrame();
 | |
|   auto* rfh = focused_frame && focused_frame->HasSelection()
 | |
|                   ? focused_frame
 | |
|                   : web_contents()->GetMainFrame();
 | |
|   rfh->Send(new PrintMsg_PrintPreview(rfh->GetRoutingID(), options));
 | |
| }
 | |
| 
 | |
| util::Promise PrintPreviewMessageHandler::GetPromise(int request_id) {
 | |
|   auto it = promise_map_.find(request_id);
 | |
|   DCHECK(it != promise_map_.end());
 | |
| 
 | |
|   util::Promise promise = std::move(it->second);
 | |
|   promise_map_.erase(it);
 | |
| 
 | |
|   return promise;
 | |
| }
 | |
| 
 | |
| void PrintPreviewMessageHandler::ResolvePromise(
 | |
|     int request_id,
 | |
|     scoped_refptr<base::RefCountedMemory> data_bytes) {
 | |
|   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 | |
| 
 | |
|   util::Promise promise = GetPromise(request_id);
 | |
| 
 | |
|   v8::Isolate* isolate = promise.isolate();
 | |
|   mate::Locker locker(isolate);
 | |
|   v8::HandleScope handle_scope(isolate);
 | |
|   v8::Context::Scope context_scope(
 | |
|       v8::Local<v8::Context>::New(isolate, promise.GetContext()));
 | |
| 
 | |
|   v8::Local<v8::Value> buffer =
 | |
|       node::Buffer::Copy(isolate,
 | |
|                          reinterpret_cast<const char*>(data_bytes->front()),
 | |
|                          data_bytes->size())
 | |
|           .ToLocalChecked();
 | |
| 
 | |
|   promise.Resolve(buffer);
 | |
| }
 | |
| 
 | |
| void PrintPreviewMessageHandler::RejectPromise(int request_id) {
 | |
|   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 | |
| 
 | |
|   util::Promise promise = GetPromise(request_id);
 | |
|   promise.RejectWithErrorMessage("Failed to generate PDF");
 | |
| }
 | |
| 
 | |
| WEB_CONTENTS_USER_DATA_KEY_IMPL(PrintPreviewMessageHandler)
 | |
| 
 | |
| }  // namespace atom
 |