mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	- Configuration of OSR VSync interval is currently missing (issue #2517) - Rename VERSION to VERSION.in to fix libc++ compile error (issue #2518)
		
			
				
	
	
		
			556 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			556 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2013 The Chromium Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style license that can be
 | |
| // found in the LICENSE file.
 | |
| 
 | |
| #include "libcef/browser/printing/print_view_manager_base.h"
 | |
| 
 | |
| #include <memory>
 | |
| #include <utility>
 | |
| 
 | |
| #include "base/auto_reset.h"
 | |
| #include "base/bind.h"
 | |
| #include "base/location.h"
 | |
| #include "base/memory/ref_counted_memory.h"
 | |
| #include "base/memory/shared_memory.h"
 | |
| #include "base/message_loop/message_loop_current.h"
 | |
| #include "base/run_loop.h"
 | |
| #include "base/single_thread_task_runner.h"
 | |
| #include "base/strings/utf_string_conversions.h"
 | |
| #include "base/task/post_task.h"
 | |
| #include "base/threading/thread_task_runner_handle.h"
 | |
| #include "base/timer/timer.h"
 | |
| #include "build/build_config.h"
 | |
| #include "chrome/browser/browser_process.h"
 | |
| #include "chrome/browser/chrome_notification_types.h"
 | |
| #include "chrome/browser/printing/print_job.h"
 | |
| #include "chrome/browser/printing/print_job_manager.h"
 | |
| #include "chrome/browser/printing/printer_query.h"
 | |
| #include "chrome/browser/profiles/profile.h"
 | |
| #include "chrome/common/pref_names.h"
 | |
| #include "chrome/grit/generated_resources.h"
 | |
| #include "components/prefs/pref_service.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/notification_details.h"
 | |
| #include "content/public/browser/notification_service.h"
 | |
| #include "content/public/browser/notification_source.h"
 | |
| #include "content/public/browser/render_frame_host.h"
 | |
| #include "content/public/browser/render_process_host.h"
 | |
| #include "content/public/browser/render_view_host.h"
 | |
| #include "content/public/browser/web_contents.h"
 | |
| #include "mojo/public/cpp/system/buffer.h"
 | |
| #include "printing/buildflags/buildflags.h"
 | |
| #include "printing/metafile_skia.h"
 | |
| #include "printing/print_settings.h"
 | |
| #include "printing/printed_document.h"
 | |
| #include "ui/base/l10n/l10n_util.h"
 | |
| 
 | |
| #if defined(OS_WIN)
 | |
| #include "base/command_line.h"
 | |
| #include "chrome/common/chrome_features.h"
 | |
| #endif
 | |
| 
 | |
| using base::TimeDelta;
 | |
| using content::BrowserThread;
 | |
| 
 | |
| namespace printing {
 | |
| 
 | |
| CefPrintViewManagerBase::CefPrintViewManagerBase(
 | |
|     content::WebContents* web_contents)
 | |
|     : PrintManager(web_contents),
 | |
|       printing_rfh_(nullptr),
 | |
|       printing_succeeded_(false),
 | |
|       inside_inner_message_loop_(false),
 | |
|       queue_(g_browser_process->print_job_manager()->queue()),
 | |
|       weak_ptr_factory_(this) {
 | |
|   DCHECK(queue_);
 | |
|   Profile* profile =
 | |
|       Profile::FromBrowserContext(web_contents->GetBrowserContext());
 | |
|   printing_enabled_.Init(
 | |
|       prefs::kPrintingEnabled, profile->GetPrefs(),
 | |
|       base::Bind(&CefPrintViewManagerBase::UpdatePrintingEnabled,
 | |
|                  weak_ptr_factory_.GetWeakPtr()));
 | |
| }
 | |
| 
 | |
| CefPrintViewManagerBase::~CefPrintViewManagerBase() {
 | |
|   ReleasePrinterQuery();
 | |
|   DisconnectFromCurrentPrintJob();
 | |
| }
 | |
| 
 | |
| bool CefPrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh) {
 | |
|   DisconnectFromCurrentPrintJob();
 | |
| 
 | |
|   SetPrintingRFH(rfh);
 | |
|   int32_t id = rfh->GetRoutingID();
 | |
|   return PrintNowInternal(rfh, std::make_unique<PrintMsg_PrintPages>(id));
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::PrintDocument(
 | |
|     const scoped_refptr<base::RefCountedMemory>& print_data,
 | |
|     const gfx::Size& page_size,
 | |
|     const gfx::Rect& content_area,
 | |
|     const gfx::Point& offsets) {
 | |
| #if defined(OS_WIN)
 | |
|   print_job_->StartConversionToNativeFormat(print_data, page_size, content_area,
 | |
|                                             offsets);
 | |
| #else
 | |
|   std::unique_ptr<MetafileSkia> metafile = std::make_unique<MetafileSkia>();
 | |
|   CHECK(metafile->InitFromData(print_data->front(), print_data->size()));
 | |
| 
 | |
|   // Update the rendered document. It will send notifications to the listener.
 | |
|   PrintedDocument* document = print_job_->document();
 | |
|   document->SetDocument(std::move(metafile), page_size, content_area);
 | |
|   ShouldQuitFromInnerMessageLoop();
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::UpdatePrintingEnabled() {
 | |
|   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 | |
|   // The Unretained() is safe because ForEachFrame() is synchronous.
 | |
|   web_contents()->ForEachFrame(base::BindRepeating(
 | |
|       &CefPrintViewManagerBase::SendPrintingEnabled, base::Unretained(this),
 | |
|       printing_enabled_.GetValue()));
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::NavigationStopped() {
 | |
|   // Cancel the current job, wait for the worker to finish.
 | |
|   TerminatePrintJob(true);
 | |
| }
 | |
| 
 | |
| base::string16 CefPrintViewManagerBase::RenderSourceName() {
 | |
|   base::string16 name(web_contents()->GetTitle());
 | |
|   if (name.empty())
 | |
|     name = l10n_util::GetStringUTF16(IDS_DEFAULT_PRINT_DOCUMENT_TITLE);
 | |
|   return name;
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::OnDidGetPrintedPagesCount(int cookie,
 | |
|                                                         int number_pages) {
 | |
|   PrintManager::OnDidGetPrintedPagesCount(cookie, number_pages);
 | |
|   OpportunisticallyCreatePrintJob(cookie);
 | |
| }
 | |
| 
 | |
| bool CefPrintViewManagerBase::PrintJobHasDocument(int cookie) {
 | |
|   if (!OpportunisticallyCreatePrintJob(cookie))
 | |
|     return false;
 | |
| 
 | |
|   // These checks may fail since we are completely asynchronous. Old spurious
 | |
|   // messages can be received if one of the processes is overloaded.
 | |
|   PrintedDocument* document = print_job_->document();
 | |
|   return document && document->cookie() == cookie;
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::OnComposePdfDone(
 | |
|     const gfx::Size& page_size,
 | |
|     const gfx::Rect& content_area,
 | |
|     const gfx::Point& physical_offsets,
 | |
|     mojom::PdfCompositor::Status status,
 | |
|     base::ReadOnlySharedMemoryRegion region) {
 | |
|   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 | |
|   if (status != mojom::PdfCompositor::Status::SUCCESS) {
 | |
|     DLOG(ERROR) << "Compositing pdf failed with error " << status;
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (!print_job_->document())
 | |
|     return;
 | |
| 
 | |
|   scoped_refptr<base::RefCountedSharedMemoryMapping> data =
 | |
|       base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region);
 | |
|   if (!data)
 | |
|     return;
 | |
| 
 | |
|   PrintDocument(data, page_size, content_area, physical_offsets);
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::OnDidPrintDocument(
 | |
|     content::RenderFrameHost* render_frame_host,
 | |
|     const PrintHostMsg_DidPrintDocument_Params& params) {
 | |
|   if (!PrintJobHasDocument(params.document_cookie))
 | |
|     return;
 | |
| 
 | |
|   const PrintHostMsg_DidPrintContent_Params& content = params.content;
 | |
|   if (!content.metafile_data_region.IsValid()) {
 | |
|     NOTREACHED() << "invalid memory handle";
 | |
|     web_contents()->Stop();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   auto* client = PrintCompositeClient::FromWebContents(web_contents());
 | |
|   if (IsOopifEnabled() && print_job_->document()->settings().is_modifiable()) {
 | |
|     client->DoCompositeDocumentToPdf(
 | |
|         params.document_cookie, render_frame_host, content,
 | |
|         base::BindOnce(&CefPrintViewManagerBase::OnComposePdfDone,
 | |
|                        weak_ptr_factory_.GetWeakPtr(), params.page_size,
 | |
|                        params.content_area, params.physical_offsets));
 | |
|     return;
 | |
|   }
 | |
|   auto data = base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(
 | |
|       content.metafile_data_region);
 | |
|   if (!data) {
 | |
|     NOTREACHED() << "couldn't map";
 | |
|     web_contents()->Stop();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   PrintDocument(data, params.page_size, params.content_area,
 | |
|                 params.physical_offsets);
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::OnPrintingFailed(int cookie) {
 | |
|   PrintManager::OnPrintingFailed(cookie);
 | |
| 
 | |
|   ReleasePrinterQuery();
 | |
| 
 | |
|   content::NotificationService::current()->Notify(
 | |
|       chrome::NOTIFICATION_PRINT_JOB_RELEASED,
 | |
|       content::Source<content::WebContents>(web_contents()),
 | |
|       content::NotificationService::NoDetails());
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::OnShowInvalidPrinterSettingsError() {}
 | |
| 
 | |
| void CefPrintViewManagerBase::DidStartLoading() {
 | |
|   UpdatePrintingEnabled();
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::RenderFrameDeleted(
 | |
|     content::RenderFrameHost* render_frame_host) {
 | |
|   // Terminates or cancels the print job if one was pending.
 | |
|   if (render_frame_host != printing_rfh_)
 | |
|     return;
 | |
| 
 | |
|   printing_rfh_ = nullptr;
 | |
| 
 | |
|   PrintManager::PrintingRenderFrameDeleted();
 | |
|   ReleasePrinterQuery();
 | |
| 
 | |
|   if (!print_job_)
 | |
|     return;
 | |
| 
 | |
|   scoped_refptr<PrintedDocument> document(print_job_->document());
 | |
|   if (document) {
 | |
|     // If IsComplete() returns false, the document isn't completely rendered.
 | |
|     // Since our renderer is gone, there's nothing to do, cancel it. Otherwise,
 | |
|     // the print job may finish without problem.
 | |
|     TerminatePrintJob(!document->IsComplete());
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool CefPrintViewManagerBase::OnMessageReceived(
 | |
|     const IPC::Message& message,
 | |
|     content::RenderFrameHost* render_frame_host) {
 | |
|   bool handled = true;
 | |
|   IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(CefPrintViewManagerBase, message,
 | |
|                                    render_frame_host)
 | |
|     IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintDocument, OnDidPrintDocument)
 | |
|     IPC_MESSAGE_UNHANDLED(handled = false)
 | |
|   IPC_END_MESSAGE_MAP()
 | |
|   if (handled)
 | |
|     return true;
 | |
| 
 | |
|   handled = true;
 | |
|   IPC_BEGIN_MESSAGE_MAP(CefPrintViewManagerBase, message)
 | |
|     IPC_MESSAGE_HANDLER(PrintHostMsg_ShowInvalidPrinterSettingsError,
 | |
|                         OnShowInvalidPrinterSettingsError)
 | |
|     IPC_MESSAGE_UNHANDLED(handled = false)
 | |
|   IPC_END_MESSAGE_MAP()
 | |
|   return handled || PrintManager::OnMessageReceived(message, render_frame_host);
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::Observe(
 | |
|     int type,
 | |
|     const content::NotificationSource& source,
 | |
|     const content::NotificationDetails& details) {
 | |
|   DCHECK_EQ(chrome::NOTIFICATION_PRINT_JOB_EVENT, type);
 | |
|   OnNotifyPrintJobEvent(*content::Details<JobEventDetails>(details).ptr());
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::OnNotifyPrintJobEvent(
 | |
|     const JobEventDetails& event_details) {
 | |
|   switch (event_details.type()) {
 | |
|     case JobEventDetails::FAILED: {
 | |
|       TerminatePrintJob(true);
 | |
| 
 | |
|       content::NotificationService::current()->Notify(
 | |
|           chrome::NOTIFICATION_PRINT_JOB_RELEASED,
 | |
|           content::Source<content::WebContents>(web_contents()),
 | |
|           content::NotificationService::NoDetails());
 | |
|       break;
 | |
|     }
 | |
|     case JobEventDetails::USER_INIT_DONE:
 | |
|     case JobEventDetails::DEFAULT_INIT_DONE:
 | |
|     case JobEventDetails::USER_INIT_CANCELED: {
 | |
|       NOTREACHED();
 | |
|       break;
 | |
|     }
 | |
|     case JobEventDetails::ALL_PAGES_REQUESTED: {
 | |
|       ShouldQuitFromInnerMessageLoop();
 | |
|       break;
 | |
|     }
 | |
|     case JobEventDetails::NEW_DOC:
 | |
| #if defined(OS_WIN)
 | |
|     case JobEventDetails::PAGE_DONE:
 | |
| #endif
 | |
|     case JobEventDetails::DOC_DONE: {
 | |
|       // Don't care about the actual printing process.
 | |
|       break;
 | |
|     }
 | |
|     case JobEventDetails::JOB_DONE: {
 | |
|       // Printing is done, we don't need it anymore.
 | |
|       // print_job_->is_job_pending() may still be true, depending on the order
 | |
|       // of object registration.
 | |
|       printing_succeeded_ = true;
 | |
|       ReleasePrintJob();
 | |
| 
 | |
|       content::NotificationService::current()->Notify(
 | |
|           chrome::NOTIFICATION_PRINT_JOB_RELEASED,
 | |
|           content::Source<content::WebContents>(web_contents()),
 | |
|           content::NotificationService::NoDetails());
 | |
|       break;
 | |
|     }
 | |
|     default: {
 | |
|       NOTREACHED();
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool CefPrintViewManagerBase::RenderAllMissingPagesNow() {
 | |
|   if (!print_job_ || !print_job_->is_job_pending())
 | |
|     return false;
 | |
| 
 | |
|   // Is the document already complete?
 | |
|   if (print_job_->document() && print_job_->document()->IsComplete()) {
 | |
|     printing_succeeded_ = true;
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   // We can't print if there is no renderer.
 | |
|   if (!web_contents() || !web_contents()->GetRenderViewHost() ||
 | |
|       !web_contents()->GetRenderViewHost()->IsRenderViewLive()) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // WebContents is either dying or a second consecutive request to print
 | |
|   // happened before the first had time to finish. We need to render all the
 | |
|   // pages in an hurry if a print_job_ is still pending. No need to wait for it
 | |
|   // to actually spool the pages, only to have the renderer generate them. Run
 | |
|   // a message loop until we get our signal that the print job is satisfied.
 | |
|   // PrintJob will send a ALL_PAGES_REQUESTED after having received all the
 | |
|   // pages it needs. RunLoop::QuitCurrentWhenIdleDeprecated() will be called as
 | |
|   // soon as print_job_->document()->IsComplete() is true on either
 | |
|   // ALL_PAGES_REQUESTED or in DidPrintDocument(). The check is done in
 | |
|   // ShouldQuitFromInnerMessageLoop().
 | |
|   // BLOCKS until all the pages are received. (Need to enable recursive task)
 | |
|   if (!RunInnerMessageLoop()) {
 | |
|     // This function is always called from DisconnectFromCurrentPrintJob() so we
 | |
|     // know that the job will be stopped/canceled in any case.
 | |
|     return false;
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::ShouldQuitFromInnerMessageLoop() {
 | |
|   // Look at the reason.
 | |
|   DCHECK(print_job_->document());
 | |
|   if (print_job_->document() && print_job_->document()->IsComplete() &&
 | |
|       inside_inner_message_loop_) {
 | |
|     // We are in a message loop created by RenderAllMissingPagesNow. Quit from
 | |
|     // it.
 | |
|     base::RunLoop::QuitCurrentWhenIdleDeprecated();
 | |
|     inside_inner_message_loop_ = false;
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool CefPrintViewManagerBase::CreateNewPrintJob(PrinterQuery* query) {
 | |
|   DCHECK(!inside_inner_message_loop_);
 | |
|   DCHECK(query);
 | |
| 
 | |
|   // Disconnect the current |print_job_|.
 | |
|   DisconnectFromCurrentPrintJob();
 | |
| 
 | |
|   // We can't print if there is no renderer.
 | |
|   if (!web_contents()->GetRenderViewHost() ||
 | |
|       !web_contents()->GetRenderViewHost()->IsRenderViewLive()) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   DCHECK(!print_job_);
 | |
|   print_job_ = base::MakeRefCounted<PrintJob>();
 | |
|   print_job_->Initialize(query, RenderSourceName(), number_pages_);
 | |
|   registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
 | |
|                  content::Source<PrintJob>(print_job_.get()));
 | |
|   printing_succeeded_ = false;
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::DisconnectFromCurrentPrintJob() {
 | |
|   // Make sure all the necessary rendered page are done. Don't bother with the
 | |
|   // return value.
 | |
|   bool result = RenderAllMissingPagesNow();
 | |
| 
 | |
|   // Verify that assertion.
 | |
|   if (print_job_ && print_job_->document() &&
 | |
|       !print_job_->document()->IsComplete()) {
 | |
|     DCHECK(!result);
 | |
|     // That failed.
 | |
|     TerminatePrintJob(true);
 | |
|   } else {
 | |
|     // DO NOT wait for the job to finish.
 | |
|     ReleasePrintJob();
 | |
|   }
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::TerminatePrintJob(bool cancel) {
 | |
|   if (!print_job_)
 | |
|     return;
 | |
| 
 | |
|   if (cancel) {
 | |
|     // We don't need the metafile data anymore because the printing is canceled.
 | |
|     print_job_->Cancel();
 | |
|     inside_inner_message_loop_ = false;
 | |
|   } else {
 | |
|     DCHECK(!inside_inner_message_loop_);
 | |
|     DCHECK(!print_job_->document() || print_job_->document()->IsComplete());
 | |
| 
 | |
|     // WebContents is either dying or navigating elsewhere. We need to render
 | |
|     // all the pages in an hurry if a print job is still pending. This does the
 | |
|     // trick since it runs a blocking message loop:
 | |
|     print_job_->Stop();
 | |
|   }
 | |
|   ReleasePrintJob();
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::ReleasePrintJob() {
 | |
|   content::RenderFrameHost* rfh = printing_rfh_;
 | |
|   printing_rfh_ = nullptr;
 | |
| 
 | |
|   if (!print_job_)
 | |
|     return;
 | |
| 
 | |
|   if (rfh) {
 | |
|     auto msg = std::make_unique<PrintMsg_PrintingDone>(rfh->GetRoutingID(),
 | |
|                                                        printing_succeeded_);
 | |
|     rfh->Send(msg.release());
 | |
|   }
 | |
| 
 | |
|   registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
 | |
|                     content::Source<PrintJob>(print_job_.get()));
 | |
|   // Don't close the worker thread.
 | |
|   print_job_ = nullptr;
 | |
| }
 | |
| 
 | |
| bool CefPrintViewManagerBase::RunInnerMessageLoop() {
 | |
|   // This value may actually be too low:
 | |
|   //
 | |
|   // - If we're looping because of printer settings initialization, the premise
 | |
|   // here is that some poor users have their print server away on a VPN over a
 | |
|   // slow connection. In this situation, the simple fact of opening the printer
 | |
|   // can be dead slow. On the other side, we don't want to die infinitely for a
 | |
|   // real network error. Give the printer 60 seconds to comply.
 | |
|   //
 | |
|   // - If we're looping because of renderer page generation, the renderer could
 | |
|   // be CPU bound, the page overly complex/large or the system just
 | |
|   // memory-bound.
 | |
|   static const int kPrinterSettingsTimeout = 60000;
 | |
|   base::OneShotTimer quit_timer;
 | |
|   base::RunLoop run_loop;
 | |
|   quit_timer.Start(FROM_HERE,
 | |
|                    TimeDelta::FromMilliseconds(kPrinterSettingsTimeout),
 | |
|                    run_loop.QuitWhenIdleClosure());
 | |
| 
 | |
|   inside_inner_message_loop_ = true;
 | |
| 
 | |
|   // Need to enable recursive task.
 | |
|   {
 | |
|     base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
 | |
|     run_loop.Run();
 | |
|   }
 | |
| 
 | |
|   bool success = true;
 | |
|   if (inside_inner_message_loop_) {
 | |
|     // Ok we timed out. That's sad.
 | |
|     inside_inner_message_loop_ = false;
 | |
|     success = false;
 | |
|   }
 | |
| 
 | |
|   return success;
 | |
| }
 | |
| 
 | |
| bool CefPrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) {
 | |
|   if (print_job_)
 | |
|     return true;
 | |
| 
 | |
|   if (!cookie) {
 | |
|     // Out of sync. It may happens since we are completely asynchronous. Old
 | |
|     // spurious message can happen if one of the processes is overloaded.
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // The job was initiated by a script. Time to get the corresponding worker
 | |
|   // thread.
 | |
|   scoped_refptr<PrinterQuery> queued_query = queue_->PopPrinterQuery(cookie);
 | |
|   if (!queued_query) {
 | |
|     NOTREACHED();
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   if (!CreateNewPrintJob(queued_query.get())) {
 | |
|     // Don't kill anything.
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // Settings are already loaded. Go ahead. This will set
 | |
|   // print_job_->is_job_pending() to true.
 | |
|   print_job_->StartPrinting();
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool CefPrintViewManagerBase::PrintNowInternal(
 | |
|     content::RenderFrameHost* rfh,
 | |
|     std::unique_ptr<IPC::Message> message) {
 | |
|   // Don't print / print preview interstitials or crashed tabs.
 | |
|   if (web_contents()->ShowingInterstitialPage() || web_contents()->IsCrashed())
 | |
|     return false;
 | |
|   return rfh->Send(message.release());
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::SetPrintingRFH(content::RenderFrameHost* rfh) {
 | |
|   DCHECK(!printing_rfh_);
 | |
|   printing_rfh_ = rfh;
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::ReleasePrinterQuery() {
 | |
|   if (!cookie_)
 | |
|     return;
 | |
| 
 | |
|   int cookie = cookie_;
 | |
|   cookie_ = 0;
 | |
| 
 | |
|   PrintJobManager* print_job_manager = g_browser_process->print_job_manager();
 | |
|   // May be NULL in tests.
 | |
|   if (!print_job_manager)
 | |
|     return;
 | |
| 
 | |
|   scoped_refptr<PrinterQuery> printer_query;
 | |
|   printer_query = queue_->PopPrinterQuery(cookie);
 | |
|   if (!printer_query)
 | |
|     return;
 | |
|   base::PostTaskWithTraits(
 | |
|       FROM_HERE, {content::BrowserThread::IO},
 | |
|       base::BindOnce(&PrinterQuery::StopWorker, printer_query));
 | |
| }
 | |
| 
 | |
| void CefPrintViewManagerBase::SendPrintingEnabled(
 | |
|     bool enabled,
 | |
|     content::RenderFrameHost* rfh) {
 | |
|   rfh->Send(new PrintMsg_SetPrintingEnabled(rfh->GetRoutingID(), enabled));
 | |
| }
 | |
| 
 | |
| }  // namespace printing
 |