Chromium Code Reviews| Index: content/browser/renderer_host/printing_message_filter.cc |
| diff --git a/content/browser/renderer_host/printing_message_filter.cc b/content/browser/renderer_host/printing_message_filter.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8b9b9ef01619a65ad22b2cb5880765682e4b5fd7 |
| --- /dev/null |
| +++ b/content/browser/renderer_host/printing_message_filter.cc |
| @@ -0,0 +1,293 @@ |
| +// Copyright (c) 2011 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 "content/browser/renderer_host/printing_message_filter.h" |
| + |
| +#include <fcntl.h> |
| + |
| +#include "base/command_line.h" |
| +#include "base/file_util.h" |
| +#include "base/lazy_instance.h" |
| +#include "base/process_util.h" |
| +#include "chrome/browser/browser_process.h" |
| +#include "chrome/browser/printing/printer_query.h" |
| +#include "chrome/browser/printing/print_job_manager.h" |
| +#include "chrome/common/chrome_switches.h" |
| +#include "chrome/common/render_messages.h" |
| +#include "chrome/common/render_messages_params.h" |
| +#include "ipc/ipc_message_macros.h" |
|
jam
2011/02/22 20:29:41
i don't think this is needed
kmadhusu
2011/02/23 02:27:49
Removed.
|
| + |
| +#if defined(OS_CHROMEOS) |
| +#include "chrome/browser/printing/print_dialog_cloud.h" |
| +#endif |
| + |
| +namespace { |
| + |
| +typedef std::map<int, FilePath> SequenceToPathMap; |
| + |
| +struct PrintingSequencePathMap { |
|
Lei Zhang
2011/02/22 19:37:42
this and |g_printing_file_descriptor_map| are CrOS
jam
2011/02/22 20:29:41
also fcntl.h should only be included on gtk builds
kmadhusu
2011/02/23 02:27:49
Done.
kmadhusu
2011/02/23 02:27:49
Fixed. It is required only for CrOS builds.
|
| + SequenceToPathMap map; |
| + int sequence; |
| +}; |
| + |
| +// No locking, only access on the FILE thread. |
| +static base::LazyInstance<PrintingSequencePathMap> |
| + g_printing_file_descriptor_map(base::LINKER_INITIALIZED); |
| + |
| +void RenderParamsFromPrintSettings(const printing::PrintSettings& settings, |
| + ViewMsg_Print_Params* params) { |
| + DCHECK(params); |
| + params->page_size = settings.page_setup_device_units().physical_size(); |
| + params->printable_size.SetSize( |
| + settings.page_setup_device_units().content_area().width(), |
| + settings.page_setup_device_units().content_area().height()); |
| + params->margin_top = settings.page_setup_device_units().content_area().x(); |
| + params->margin_left = settings.page_setup_device_units().content_area().y(); |
| + params->dpi = settings.dpi(); |
| + // Currently hardcoded at 1.25. See PrintSettings' constructor. |
| + params->min_shrink = settings.min_shrink; |
| + // Currently hardcoded at 2.0. See PrintSettings' constructor. |
| + params->max_shrink = settings.max_shrink; |
| + // Currently hardcoded at 72dpi. See PrintSettings' constructor. |
| + params->desired_dpi = settings.desired_dpi; |
| + // Always use an invalid cookie. |
| + params->document_cookie = 0; |
| + params->selection_only = settings.selection_only; |
| + params->supports_alpha_blend = settings.supports_alpha_blend(); |
| +} |
| + |
| +} // namespace |
| + |
| +PrintingMessageFilter::PrintingMessageFilter() |
| + : print_job_manager_(g_browser_process->print_job_manager()) { |
| +#if defined(OS_CHROMEOS) |
| + cloud_print_enabled_ = true; |
| +#else |
| + cloud_print_enabled_ = CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kEnableCloudPrint); |
| +#endif |
| +} |
| + |
| +PrintingMessageFilter::~PrintingMessageFilter() {} |
| + |
| +bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message, |
| + bool* message_was_ok) { |
| + bool handled = true; |
| + IPC_BEGIN_MESSAGE_MAP_EX(PrintingMessageFilter, message, *message_was_ok) |
| +#if defined(OS_WIN) |
| + IPC_MESSAGE_HANDLER(ViewHostMsg_DuplicateSection, OnDuplicateSection) |
| +#endif |
| +#if defined(OS_POSIX) |
| + IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateSharedMemoryBuffer, |
| + OnAllocateSharedMemoryBuffer) |
| +#endif |
| +#if defined(OS_CHROMEOS) |
| + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_AllocateTempFileForPrinting, |
|
kmadhusu
2011/02/21 21:30:04
jam: Although we are dispatching on a different th
jam
2011/02/22 23:39:51
I'm not quite sure what this question is. But act
kmadhusu
2011/02/23 02:27:49
Fixed. Implemented OverrideThreadForMessage() func
|
| + OnAllocateTempFileForPrinting) |
| + IPC_MESSAGE_HANDLER(ViewHostMsg_TempFileForPrintingWritten, |
| + OnTempFileForPrintingWritten) |
| +#endif |
| + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDefaultPrintSettings, |
| + OnGetDefaultPrintSettings) |
| + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ScriptedPrint, OnScriptedPrint) |
| + IPC_MESSAGE_UNHANDLED(handled = false) |
| + IPC_END_MESSAGE_MAP() |
| + return handled; |
| +} |
| + |
| +#if defined(OS_POSIX) |
| +void PrintingMessageFilter::OnAllocateSharedMemoryBuffer( |
| + uint32 buffer_size, |
| + base::SharedMemoryHandle* handle) { |
| + base::SharedMemory shared_buf; |
| + if (!shared_buf.CreateAndMapAnonymous(buffer_size)) { |
| + *handle = base::SharedMemory::NULLHandle(); |
| + NOTREACHED() << "Cannot map shared memory buffer"; |
| + return; |
| + } |
| + shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), handle); |
| +} |
| +#endif |
| + |
| +#if defined(OS_WIN) |
| +void PrintingMessageFilter::OnDuplicateSection( |
| + base::SharedMemoryHandle renderer_handle, |
| + base::SharedMemoryHandle* browser_handle) { |
| + // Duplicate the handle in this process right now so the memory is kept alive |
| + // (even if it is not mapped) |
| + base::SharedMemory shared_buf(renderer_handle, true, peer_handle()); |
| + shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), browser_handle); |
| +} |
| +#endif |
| + |
| +#if defined(OS_CHROMEOS) |
| +void PrintingMessageFilter::OnAllocateTempFileForPrinting( |
| + IPC::Message* reply_msg) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + NewRunnableMethod( |
| + this, &PrintingMessageFilter::DoOnAllocateTempFileForPrinting, |
| + reply_msg)); |
| +} |
| + |
| +void PrintingMessageFilter::OnTempFileForPrintingWritten(int sequence_number) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + NewRunnableMethod( |
| + this, &PrintingMessageFilter::DoOnTempFileForPrintingWritten, |
| + sequence_number)); |
| +} |
| + |
| +void PrintingMessageFilter::DoOnAllocateTempFileForPrinting( |
| + IPC::Message* reply_msg) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + base::FileDescriptor temp_file_fd(-1, false); |
| + SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map; |
| + const int sequence_number = g_printing_file_descriptor_map.Get().sequence++; |
| + |
| + FilePath path; |
| + if (file_util::CreateTemporaryFile(&path)) { |
| + int fd = open(path.value().c_str(), O_WRONLY); |
| + if (fd >= 0) { |
| + SequenceToPathMap::iterator it = map->find(sequence_number); |
| + if (it != map->end()) { |
| + NOTREACHED() << "Sequence number already in use. seq=" << |
| + sequence_number; |
| + } else { |
| + (*map)[sequence_number] = path; |
| + temp_file_fd.fd = fd; |
| + temp_file_fd.auto_close = true; |
| + } |
| + } |
| + } |
| + |
| + ViewHostMsg_AllocateTempFileForPrinting::WriteReplyParams( |
| + reply_msg, temp_file_fd, sequence_number); |
| + Send(reply_msg); |
| +} |
| + |
| +void PrintingMessageFilter::DoOnTempFileForPrintingWritten( |
| + int sequence_number) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map; |
| + SequenceToPathMap::iterator it = map->find(sequence_number); |
| + if (it == map->end()) { |
| + NOTREACHED() << "Got a sequence that we didn't pass to the " |
| + "renderer: " << sequence_number; |
| + return; |
| + } |
| + |
| + if (cloud_print_enabled_) |
| + PrintDialogCloud::CreatePrintDialogForPdf(it->second, string16(), true); |
| + else |
| + NOTIMPLEMENTED(); |
| + |
| + // Erase the entry in the map. |
| + map->erase(it); |
| +} |
| +#endif // defined(OS_CHROMEOS) |
| + |
| +void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) { |
| + scoped_refptr<printing::PrinterQuery> printer_query; |
| + if (!print_job_manager_->printing_enabled()) { |
| + // Reply with NULL query. |
| + OnGetDefaultPrintSettingsReply(printer_query, reply_msg); |
| + return; |
| + } |
| + |
| + print_job_manager_->PopPrinterQuery(0, &printer_query); |
| + if (!printer_query.get()) { |
| + printer_query = new printing::PrinterQuery; |
| + } |
| + |
| + CancelableTask* task = NewRunnableMethod( |
| + this, |
| + &PrintingMessageFilter::OnGetDefaultPrintSettingsReply, |
| + printer_query, |
| + reply_msg); |
| + // Loads default settings. This is asynchronous, only the IPC message sender |
| + // will hang until the settings are retrieved. |
| + printer_query->GetSettings(printing::PrinterQuery::DEFAULTS, |
| + NULL, |
| + 0, |
| + false, |
| + true, |
| + task); |
| +} |
| + |
| +void PrintingMessageFilter::OnGetDefaultPrintSettingsReply( |
| + scoped_refptr<printing::PrinterQuery> printer_query, |
| + IPC::Message* reply_msg) { |
| + ViewMsg_Print_Params params; |
| + if (!printer_query.get() || |
| + printer_query->last_status() != printing::PrintingContext::OK) { |
| + memset(¶ms, 0, sizeof(params)); |
| + } else { |
| + RenderParamsFromPrintSettings(printer_query->settings(), ¶ms); |
| + params.document_cookie = printer_query->cookie(); |
| + } |
| + ViewHostMsg_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()) { |
| + print_job_manager_->QueuePrinterQuery(printer_query.get()); |
| + } else { |
| + printer_query->StopWorker(); |
| + } |
| + } |
| +} |
| + |
| +void PrintingMessageFilter::OnScriptedPrint( |
| + const ViewHostMsg_ScriptedPrint_Params& params, |
| + IPC::Message* reply_msg) { |
| + gfx::NativeView host_view = |
| + gfx::NativeViewFromIdInBrowser(params.host_window_id); |
| + |
| + scoped_refptr<printing::PrinterQuery> printer_query; |
| + print_job_manager_->PopPrinterQuery(params.cookie, &printer_query); |
| + if (!printer_query.get()) { |
| + printer_query = new printing::PrinterQuery; |
| + } |
| + |
| + CancelableTask* task = NewRunnableMethod( |
| + this, |
| + &PrintingMessageFilter::OnScriptedPrintReply, |
| + printer_query, |
| + params.routing_id, |
| + reply_msg); |
| + |
| + printer_query->GetSettings(printing::PrinterQuery::ASK_USER, |
| + host_view, |
| + params.expected_pages_count, |
| + params.has_selection, |
| + params.use_overlays, |
| + task); |
| +} |
| + |
| +void PrintingMessageFilter::OnScriptedPrintReply( |
| + scoped_refptr<printing::PrinterQuery> printer_query, |
| + int routing_id, |
| + IPC::Message* reply_msg) { |
| + ViewMsg_PrintPages_Params params; |
| + if (printer_query->last_status() != printing::PrintingContext::OK || |
| + !printer_query->settings().dpi()) { |
| + memset(¶ms, 0, sizeof(params)); |
| + } else { |
| + RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params); |
| + params.params.document_cookie = printer_query->cookie(); |
| + params.pages = |
| + printing::PageRange::GetPages(printer_query->settings().ranges); |
| + } |
| + ViewHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params); |
| + Send(reply_msg); |
| + if (params.params.dpi && params.params.document_cookie) { |
| + print_job_manager_->QueuePrinterQuery(printer_query.get()); |
| + } else { |
| + printer_query->StopWorker(); |
| + } |
| +} |