// Copyright (c) 2012 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/printing_message_filter.h" #include #include #include "base/bind.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_manager_utils.h" #include "components/printing/common/print_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/child_process_host.h" #if defined(OS_LINUX) #include "libcef/browser/printing/print_dialog_linux.h" #endif using content::BrowserThread; namespace printing { CefPrintingMessageFilter::CefPrintingMessageFilter(int render_process_id) : content::BrowserMessageFilter(PrintMsgStart), render_process_id_(render_process_id), queue_(g_browser_process->print_job_manager()->queue()) { DCHECK(queue_.get()); } CefPrintingMessageFilter::~CefPrintingMessageFilter() { } void CefPrintingMessageFilter::OverrideThreadForMessage( const IPC::Message& message, BrowserThread::ID* thread) { } bool CefPrintingMessageFilter::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(CefPrintingMessageFilter, message) IPC_MESSAGE_HANDLER(PrintHostMsg_IsPrintingEnabled, OnIsPrintingEnabled) IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings, OnGetDefaultPrintSettings) IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint) IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_UpdatePrintSettings, OnUpdatePrintSettings) IPC_MESSAGE_HANDLER(PrintHostMsg_CheckForCancel, OnCheckForCancel) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } void CefPrintingMessageFilter::OnIsPrintingEnabled(bool* is_enabled) { DCHECK_CURRENTLY_ON(BrowserThread::IO); *is_enabled = true; } void CefPrintingMessageFilter::OnGetDefaultPrintSettings( IPC::Message* reply_msg) { DCHECK_CURRENTLY_ON(BrowserThread::IO); #if defined(OS_LINUX) // Send notification to the client. CefPrintDialogLinux::OnPrintStart(render_process_id_, reply_msg->routing_id()); #endif scoped_refptr printer_query; printer_query = queue_->PopPrinterQuery(0); if (!printer_query.get()) { printer_query = queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id()); } // Loads default settings. This is asynchronous, only the IPC message sender // will hang until the settings are retrieved. printer_query->GetSettings( PrinterQuery::GetSettingsAskParam::DEFAULTS, 0, false, DEFAULT_MARGINS, false, false, base::Bind(&CefPrintingMessageFilter::OnGetDefaultPrintSettingsReply, this, printer_query, reply_msg)); } void CefPrintingMessageFilter::OnGetDefaultPrintSettingsReply( scoped_refptr printer_query, IPC::Message* reply_msg) { PrintMsg_Print_Params params; if (!printer_query.get() || printer_query->last_status() != PrintingContext::OK) { params.Reset(); } else { RenderParamsFromPrintSettings(printer_query->settings(), ¶ms); params.document_cookie = printer_query->cookie(); } PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, params); Send(reply_msg); // If printing was enabled. if (printer_query.get()) { // If user hasn't cancelled. if (printer_query->cookie() && printer_query->settings().dpi()) { queue_->QueuePrinterQuery(printer_query.get()); } else { printer_query->StopWorker(); } } } void CefPrintingMessageFilter::OnScriptedPrint( const PrintHostMsg_ScriptedPrint_Params& params, IPC::Message* reply_msg) { scoped_refptr printer_query = queue_->PopPrinterQuery(params.cookie); if (!printer_query.get()) { printer_query = queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id()); } printer_query->GetSettings( PrinterQuery::GetSettingsAskParam::ASK_USER, params.expected_pages_count, params.has_selection, params.margin_type, params.is_scripted, params.is_modifiable, base::Bind(&CefPrintingMessageFilter::OnScriptedPrintReply, this, printer_query, reply_msg)); } void CefPrintingMessageFilter::OnScriptedPrintReply( scoped_refptr printer_query, IPC::Message* reply_msg) { PrintMsg_PrintPages_Params params; #if defined(OS_ANDROID) // We need to save the routing ID here because Send method below deletes the // |reply_msg| before we can get the routing ID for the Android code. int routing_id = reply_msg->routing_id(); #endif if (printer_query->last_status() != PrintingContext::OK || !printer_query->settings().dpi()) { params.Reset(); } else { RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params); params.params.document_cookie = printer_query->cookie(); params.pages = PageRange::GetPages(printer_query->settings().ranges()); } PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params); Send(reply_msg); if (params.params.dpi && params.params.document_cookie) { #if defined(OS_ANDROID) int file_descriptor; const base::string16& device_name = printer_query->settings().device_name(); if (base::StringToInt(device_name, &file_descriptor)) { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&CefPrintingMessageFilter::UpdateFileDescriptor, this, routing_id, file_descriptor)); } #endif queue_->QueuePrinterQuery(printer_query.get()); } else { printer_query->StopWorker(); } } void CefPrintingMessageFilter::OnUpdatePrintSettings( int document_cookie, const base::DictionaryValue& job_settings, IPC::Message* reply_msg) { std::unique_ptr new_settings(job_settings.DeepCopy()); scoped_refptr printer_query; printer_query = queue_->PopPrinterQuery(document_cookie); if (!printer_query.get()) { int host_id = render_process_id_; int routing_id = reply_msg->routing_id(); if (!new_settings->GetInteger(printing::kPreviewInitiatorHostId, &host_id) || !new_settings->GetInteger(printing::kPreviewInitiatorRoutingId, &routing_id)) { host_id = content::ChildProcessHost::kInvalidUniqueID; routing_id = content::ChildProcessHost::kInvalidUniqueID; } printer_query = queue_->CreatePrinterQuery(host_id, routing_id); } printer_query->SetSettings( std::move(new_settings), base::Bind(&CefPrintingMessageFilter::OnUpdatePrintSettingsReply, this, printer_query, reply_msg)); } void CefPrintingMessageFilter::OnUpdatePrintSettingsReply( scoped_refptr printer_query, IPC::Message* reply_msg) { PrintMsg_PrintPages_Params params; if (!printer_query.get() || printer_query->last_status() != PrintingContext::OK) { params.Reset(); } else { RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params); params.params.document_cookie = printer_query->cookie(); params.pages = PageRange::GetPages(printer_query->settings().ranges()); } PrintHostMsg_UpdatePrintSettings::WriteReplyParams( reply_msg, params, printer_query.get() && (printer_query->last_status() == printing::PrintingContext::CANCEL)); Send(reply_msg); // If user hasn't cancelled. if (printer_query.get()) { if (printer_query->cookie() && printer_query->settings().dpi()) { queue_->QueuePrinterQuery(printer_query.get()); } else { printer_query->StopWorker(); } } } void CefPrintingMessageFilter::OnCheckForCancel(int32_t preview_ui_id, int preview_request_id, bool* cancel) { *cancel = false; } } // namespace printing