Add printToPDF Implementation.
This commit is contained in:
parent
b360f7d86a
commit
7ffa7042b1
10 changed files with 1112 additions and 2 deletions
|
@ -0,0 +1,237 @@
|
|||
// 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 "chrome/browser/printing/print_preview_message_handler.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/ui/file_dialog.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/memory/ref_counted_memory.h"
|
||||
#include "base/memory/shared_memory.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/browser/printing/print_job_manager.h"
|
||||
#include "chrome/browser/printing/printer_query.h"
|
||||
#include "chrome/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/browser/web_ui.h"
|
||||
#include "printing/page_size_margins.h"
|
||||
#include "printing/print_job_constants.h"
|
||||
#include "printing/pdf_metafile_skia.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
using content::WebContents;
|
||||
|
||||
DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintPreviewMessageHandler);
|
||||
|
||||
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()) {
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&printing::PrinterQuery::StopWorker,
|
||||
printer_query));
|
||||
}
|
||||
}
|
||||
|
||||
base::RefCountedBytes* GetDataFromHandle(base::SharedMemoryHandle handle,
|
||||
uint32 data_size) {
|
||||
scoped_ptr<base::SharedMemory> shared_buf(
|
||||
new base::SharedMemory(handle, true));
|
||||
if (!shared_buf->Map(data_size)) {
|
||||
NOTREACHED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned char* data_begin = static_cast<unsigned char*>(shared_buf->memory());
|
||||
std::vector<unsigned char> data(data_begin, data_begin + data_size);
|
||||
return base::RefCountedBytes::TakeVector(&data);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace printing {
|
||||
|
||||
PrintPreviewMessageHandler::PrintPreviewMessageHandler(
|
||||
WebContents* web_contents)
|
||||
: content::WebContentsObserver(web_contents) {
|
||||
DCHECK(web_contents);
|
||||
}
|
||||
|
||||
PrintPreviewMessageHandler::~PrintPreviewMessageHandler() {
|
||||
}
|
||||
|
||||
void PrintPreviewMessageHandler::OnDidGetPreviewPageCount(
|
||||
const PrintHostMsg_DidGetPreviewPageCount_Params& params) {
|
||||
if (params.page_count <= 0) {
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(ERROR) << "OnDidGetPreviewPageCount: " << params.page_count;
|
||||
}
|
||||
|
||||
void PrintPreviewMessageHandler::OnDidPreviewPage(
|
||||
const PrintHostMsg_DidPreviewPage_Params& params) {
|
||||
int page_number = params.page_number;
|
||||
if (page_number < FIRST_PAGE_INDEX || !params.data_size)
|
||||
return;
|
||||
LOG(ERROR) << "OnDidPreviewPage: " << params.data_size;
|
||||
}
|
||||
|
||||
void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
|
||||
const PrintHostMsg_DidPreviewDocument_Params& params) {
|
||||
// Always try to stop the worker.
|
||||
StopWorker(params.document_cookie);
|
||||
|
||||
if (params.expected_pages_count <= 0) {
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(joth): This seems like a good match for using RefCountedStaticMemory
|
||||
// to avoid the memory copy, but the SetPrintPreviewData call chain below
|
||||
// needs updating to accept the RefCountedMemory* base class.
|
||||
scoped_refptr<base::RefCountedBytes> data(
|
||||
GetDataFromHandle(params.metafile_data_handle, params.data_size));
|
||||
if (!data || !data->size())
|
||||
return;
|
||||
|
||||
LOG(ERROR) << params.preview_request_id;
|
||||
atom::NativeWindow* window = atom::NativeWindow::FromWebContents(
|
||||
web_contents());
|
||||
base::FilePath save_path;
|
||||
file_dialog::ShowSaveDialog(window, "Save As",
|
||||
base::FilePath(FILE_PATH_LITERAL("print.pdf")),
|
||||
file_dialog::Filters(), &save_path);
|
||||
printing::PdfMetafileSkia metafile;
|
||||
metafile.InitFromData(static_cast<const void*>(data->front()), data->size());
|
||||
base::File file(save_path,
|
||||
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
|
||||
metafile.SaveTo(&file);
|
||||
}
|
||||
|
||||
//void PrintPreviewMessageHandler::OnPrintPreviewFailed(int document_cookie) {
|
||||
//StopWorker(document_cookie);
|
||||
|
||||
////PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
|
||||
////if (!print_preview_ui)
|
||||
////return;
|
||||
////print_preview_ui->OnPrintPreviewFailed();
|
||||
//}
|
||||
|
||||
//void PrintPreviewMessageHandler::OnDidGetDefaultPageLayout(
|
||||
//const PageSizeMargins& page_layout_in_points,
|
||||
//const gfx::Rect& printable_area_in_points,
|
||||
//bool has_custom_page_size_style) {
|
||||
////PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
|
||||
////if (!print_preview_ui)
|
||||
////return;
|
||||
////print_preview_ui->OnDidGetDefaultPageLayout(page_layout_in_points,
|
||||
////printable_area_in_points,
|
||||
////has_custom_page_size_style);
|
||||
//}
|
||||
|
||||
//void PrintPreviewMessageHandler::OnPrintPreviewCancelled(int document_cookie) {
|
||||
//// Always need to stop the worker.
|
||||
//StopWorker(document_cookie);
|
||||
//}
|
||||
|
||||
//void PrintPreviewMessageHandler::OnInvalidPrinterSettings(int document_cookie) {
|
||||
//StopWorker(document_cookie);
|
||||
////PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
|
||||
////if (!print_preview_ui)
|
||||
////return;
|
||||
////print_preview_ui->OnInvalidPrinterSettings();
|
||||
//}
|
||||
|
||||
//void PrintPreviewMessageHandler::OnSetOptionsFromDocument(
|
||||
//const PrintHostMsg_SetOptionsFromDocument_Params& params) {
|
||||
////PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
|
||||
////if (!print_preview_ui)
|
||||
////return;
|
||||
////print_preview_ui->OnSetOptionsFromDocument(params);
|
||||
//}
|
||||
|
||||
bool PrintPreviewMessageHandler::OnMessageReceived(
|
||||
const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(PrintPreviewMessageHandler, message)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPreviewPageCount,
|
||||
OnDidGetPreviewPageCount)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_DidPreviewPage,
|
||||
OnDidPreviewPage)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting,
|
||||
OnMetafileReadyForPrinting)
|
||||
//IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewFailed,
|
||||
//OnPrintPreviewFailed)
|
||||
//IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDefaultPageLayout,
|
||||
//OnDidGetDefaultPageLayout)
|
||||
//IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewCancelled,
|
||||
//OnPrintPreviewCancelled)
|
||||
//IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewInvalidPrinterSettings,
|
||||
//OnInvalidPrinterSettings)
|
||||
//IPC_MESSAGE_HANDLER(PrintHostMsg_SetOptionsFromDocument,
|
||||
//OnSetOptionsFromDocument)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
}
|
||||
|
||||
void PrintPreviewMessageHandler::HandleGetPreview(const base::ListValue* args) {
|
||||
static int request_id = 0;
|
||||
request_id++;
|
||||
// A simulated Chromium print preivew setting.
|
||||
const std::string setting_json_str = "{ \
|
||||
\"pageRage\":[], \
|
||||
\"mediaSize\":{ \
|
||||
\"height_microns\":297000, \
|
||||
\"is_default\":true, \
|
||||
\"name\":\"ISO_A4\", \
|
||||
\"width_microns\":210000, \
|
||||
\"custom_display_name\":\"A4\" \
|
||||
}, \
|
||||
\"landscape\":true, \
|
||||
\"color\":2, \
|
||||
\"headerFooterEnabled\":false, \
|
||||
\"marginsType\":0, \
|
||||
\"isFirstRequest\":false, \
|
||||
\"requestID\":1, \
|
||||
\"previewModifiable\":true, \
|
||||
\"printToPDF\":true, \
|
||||
\"printWithCloudPrint\":false, \
|
||||
\"printWithPrivet\":false, \
|
||||
\"printWithExtension\":false, \
|
||||
\"deviceName\":\"Save as PDF\", \
|
||||
\"generateDraftData\":true, \
|
||||
\"fitToPageEnabled\":false, \
|
||||
\"duplex\":0, \
|
||||
\"copies\":1, \
|
||||
\"collate\":true, \
|
||||
\"shouldPrintBackgrounds\":true, \
|
||||
\"shouldPrintSelectionOnly\":false \
|
||||
}";
|
||||
|
||||
scoped_ptr<base::DictionaryValue> settings(
|
||||
static_cast<base::DictionaryValue*>(
|
||||
base::JSONReader::Read(setting_json_str)));
|
||||
settings->SetInteger(printing::kPreviewRequestID, request_id);
|
||||
|
||||
LOG(ERROR) << "Print preview request start";
|
||||
content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
|
||||
rvh->Send(new PrintMsg_PrintPreview(rvh->GetRoutingID(), *settings));
|
||||
}
|
||||
|
||||
} // namespace printing
|
|
@ -0,0 +1,70 @@
|
|||
// 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.
|
||||
|
||||
#ifndef CHROME_BROWSER_PRINTING_PRINT_PREVIEW_MESSAGE_HANDLER_H_
|
||||
#define CHROME_BROWSER_PRINTING_PRINT_PREVIEW_MESSAGE_HANDLER_H_
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
|
||||
struct PrintHostMsg_DidGetPreviewPageCount_Params;
|
||||
struct PrintHostMsg_DidPreviewDocument_Params;
|
||||
struct PrintHostMsg_DidPreviewPage_Params;
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace gfx {
|
||||
class Rect;
|
||||
}
|
||||
|
||||
namespace printing {
|
||||
|
||||
struct PageSizeMargins;
|
||||
|
||||
// Manages the print preview handling for a WebContents.
|
||||
class PrintPreviewMessageHandler
|
||||
: public content::WebContentsObserver,
|
||||
public content::WebContentsUserData<PrintPreviewMessageHandler> {
|
||||
public:
|
||||
~PrintPreviewMessageHandler() override;
|
||||
|
||||
// content::WebContentsObserver implementation.
|
||||
bool OnMessageReceived(const IPC::Message& message) override;
|
||||
|
||||
// Asks the initiator renderer to generate a preview. First element of |args|
|
||||
// is a job settings JSON string.
|
||||
void HandleGetPreview(const base::ListValue* args);
|
||||
|
||||
private:
|
||||
explicit PrintPreviewMessageHandler(content::WebContents* web_contents);
|
||||
friend class content::WebContentsUserData<PrintPreviewMessageHandler>;
|
||||
|
||||
|
||||
// Message handlers.
|
||||
//void OnRequestPrintPreview(
|
||||
//const PrintHostMsg_RequestPrintPreview_Params& params);
|
||||
//void OnDidGetDefaultPageLayout(
|
||||
//const printing::PageSizeMargins& page_layout_in_points,
|
||||
//const gfx::Rect& printable_area_in_points,
|
||||
//bool has_custom_page_size_style);
|
||||
void OnDidGetPreviewPageCount(
|
||||
const PrintHostMsg_DidGetPreviewPageCount_Params& params);
|
||||
void OnDidPreviewPage(const PrintHostMsg_DidPreviewPage_Params& params);
|
||||
void OnMetafileReadyForPrinting(
|
||||
const PrintHostMsg_DidPreviewDocument_Params& params);
|
||||
//void OnPrintPreviewFailed(int document_cookie);
|
||||
//void OnPrintPreviewCancelled(int document_cookie);
|
||||
//void OnInvalidPrinterSettings(int document_cookie);
|
||||
//void OnSetOptionsFromDocument(
|
||||
//const PrintHostMsg_SetOptionsFromDocument_Params& params);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintPreviewMessageHandler);
|
||||
};
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // CHROME_BROWSER_PRINTING_PRINT_PREVIEW_MESSAGE_HANDLER_H_
|
|
@ -128,6 +128,8 @@ bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message) {
|
|||
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings,
|
||||
OnGetDefaultPrintSettings)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_UpdatePrintSettings,
|
||||
OnUpdatePrintSettings)
|
||||
#if defined(ENABLE_FULL_PRINTING)
|
||||
IPC_MESSAGE_HANDLER(PrintHostMsg_CheckForCancel, OnCheckForCancel)
|
||||
#endif
|
||||
|
@ -372,4 +374,57 @@ void PrintingMessageFilter::UpdateFileDescriptor(int render_view_id, int fd) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void PrintingMessageFilter::OnUpdatePrintSettings(
|
||||
int document_cookie, const base::DictionaryValue& job_settings,
|
||||
IPC::Message* reply_msg) {
|
||||
scoped_ptr<base::DictionaryValue> new_settings(job_settings.DeepCopy());
|
||||
|
||||
scoped_refptr<PrinterQuery> 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(
|
||||
new_settings.Pass(),
|
||||
base::Bind(&PrintingMessageFilter::OnUpdatePrintSettingsReply, this,
|
||||
printer_query, reply_msg));
|
||||
}
|
||||
|
||||
void PrintingMessageFilter::OnUpdatePrintSettingsReply(
|
||||
scoped_refptr<PrinterQuery> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
|
|
|
@ -96,6 +96,15 @@ class PrintingMessageFilter : public content::BrowserMessageFilter {
|
|||
void OnScriptedPrintReply(scoped_refptr<PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg);
|
||||
|
||||
// Modify the current print settings based on |job_settings|. The task is
|
||||
// handled by the print worker thread and the UI thread. The reply occurs on
|
||||
// the IO thread.
|
||||
void OnUpdatePrintSettings(int document_cookie,
|
||||
const base::DictionaryValue& job_settings,
|
||||
IPC::Message* reply_msg);
|
||||
void OnUpdatePrintSettingsReply(scoped_refptr<PrinterQuery> printer_query,
|
||||
IPC::Message* reply_msg);
|
||||
|
||||
#if defined(ENABLE_FULL_PRINTING)
|
||||
// Check to see if print preview has been cancelled.
|
||||
void OnCheckForCancel(int32 preview_ui_id,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue