// 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/renderer/mock_printer.h"
#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/memory/shared_memory.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/print_messages.h"
#include "ipc/ipc_message_utils.h"
#include "printing/metafile_impl.h"
#include "printing/units.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_MACOSX)
#include "printing/pdf_metafile_cg_mac.h"
#endif
namespace {
void UpdateMargins(int margins_type, int dpi, PrintMsg_Print_Params* params) {
if (margins_type == printing::NO_MARGINS) {
params->content_size.SetSize(static_cast<int>((8.5 * dpi)),
static_cast<int>((11.0 * dpi)));
params->margin_left = 0;
params->margin_top = 0;
} else if (margins_type == printing::PRINTABLE_AREA_MARGINS) {
params->content_size.SetSize(static_cast<int>((8.0 * dpi)),
static_cast<int>((10.5 * dpi)));
params->margin_left = static_cast<int>(0.25 * dpi);
params->margin_top = static_cast<int>(0.25 * dpi);
} else if (margins_type == printing::CUSTOM_MARGINS) {
params->content_size.SetSize(static_cast<int>((7.9 * dpi)),
static_cast<int>((10.4 * dpi)));
params->margin_left = static_cast<int>(0.30 * dpi);
params->margin_top = static_cast<int>(0.30 * dpi);
}
}
} // namespace
MockPrinterPage::MockPrinterPage(const void* source_data,
uint32 source_size,
const printing::Image& image)
: source_size_(source_size),
image_(image) {
// Create copies of the source data
source_data_.reset(new uint8[source_size]);
if (source_data_.get())
memcpy(source_data_.get(), source_data, source_size);
}
MockPrinterPage::~MockPrinterPage() {}
MockPrinter::MockPrinter()
: dpi_(printing::kPointsPerInch),
max_shrink_(2.0),
min_shrink_(1.25),
desired_dpi_(printing::kPointsPerInch),
selection_only_(false),
should_print_backgrounds_(false),
document_cookie_(-1),
current_document_cookie_(0),
printer_status_(PRINTER_READY),
number_pages_(0),
page_number_(0),
is_first_request_(true),
print_to_pdf_(false),
preview_request_id_(0),
print_scaling_option_(blink::WebPrintScalingOptionSourceSize),
display_header_footer_(false),
title_(ASCIIToUTF16("title")),
url_(ASCIIToUTF16("url")),
use_invalid_settings_(false) {
page_size_.SetSize(static_cast<int>(8.5 * dpi_),
static_cast<int>(11.0 * dpi_));
content_size_.SetSize(static_cast<int>((7.5 * dpi_)),
static_cast<int>((10.0 * dpi_)));
margin_left_ = margin_top_ = static_cast<int>(0.5 * dpi_);
printable_area_.SetRect(static_cast<int>(0.25 * dpi_),
static_cast<int>(0.25 *dpi_),
static_cast<int>(8 * dpi_),
static_cast<int>(10.5 * dpi_));
}
MockPrinter::~MockPrinter() {
}
void MockPrinter::ResetPrinter() {
printer_status_ = PRINTER_READY;
document_cookie_ = -1;
}
void MockPrinter::GetDefaultPrintSettings(PrintMsg_Print_Params* params) {
// Verify this printer is not processing a job.
// Sorry, this mock printer is very fragile.
EXPECT_EQ(-1, document_cookie_);
// Assign a unit document cookie and set the print settings.
document_cookie_ = CreateDocumentCookie();
params->Reset();
SetPrintParams(params);
}
void MockPrinter::SetDefaultPrintSettings(const PrintMsg_Print_Params& params) {
dpi_ = params.dpi;
max_shrink_ = params.max_shrink;
min_shrink_ = params.min_shrink;
desired_dpi_ = params.desired_dpi;
selection_only_ = params.selection_only;
should_print_backgrounds_ = params.should_print_backgrounds;
page_size_ = params.page_size;
content_size_ = params.content_size;
printable_area_ = params.printable_area;
margin_left_ = params.margin_left;
margin_top_ = params.margin_top;
display_header_footer_ = params.display_header_footer;
title_ = params.title;
url_ = params.url;
}
void MockPrinter::UseInvalidSettings() {
use_invalid_settings_ = true;
PrintMsg_Print_Params empty_param;
SetDefaultPrintSettings(empty_param);
}
void MockPrinter::UseInvalidPageSize() {
page_size_.SetSize(0, 0);
}
void MockPrinter::UseInvalidContentSize() {
content_size_.SetSize(0, 0);
}
void MockPrinter::ScriptedPrint(int cookie,
int expected_pages_count,
bool has_selection,
PrintMsg_PrintPages_Params* settings) {
// Verify the input parameters.
EXPECT_EQ(document_cookie_, cookie);
settings->Reset();
settings->params.dpi = dpi_;
settings->params.max_shrink = max_shrink_;
settings->params.min_shrink = min_shrink_;
settings->params.desired_dpi = desired_dpi_;
settings->params.selection_only = selection_only_;
settings->params.should_print_backgrounds = should_print_backgrounds_;
settings->params.document_cookie = document_cookie_;
settings->params.page_size = page_size_;
settings->params.content_size = content_size_;
settings->params.printable_area = printable_area_;
settings->params.is_first_request = is_first_request_;
settings->params.print_scaling_option = print_scaling_option_;
settings->params.print_to_pdf = print_to_pdf_;
settings->params.preview_request_id = preview_request_id_;
settings->params.display_header_footer = display_header_footer_;
settings->params.title = title_;
settings->params.url = url_;
printer_status_ = PRINTER_PRINTING;
}
void MockPrinter::UpdateSettings(int cookie,
PrintMsg_PrintPages_Params* params,
const std::vector<int>& pages,
int margins_type) {
if (document_cookie_ == -1) {
document_cookie_ = CreateDocumentCookie();
}
params->Reset();
params->pages = pages;
SetPrintParams(&(params->params));
UpdateMargins(margins_type, dpi_, &(params->params));
printer_status_ = PRINTER_PRINTING;
}
void MockPrinter::SetPrintedPagesCount(int cookie, int number_pages) {
// Verify the input parameter and update the printer status so that the
// RenderViewTest class can verify the this function finishes without errors.
EXPECT_EQ(document_cookie_, cookie);
EXPECT_EQ(PRINTER_PRINTING, printer_status_);
EXPECT_EQ(0, number_pages_);
EXPECT_EQ(0, page_number_);
// Initialize the job status.
number_pages_ = number_pages;
page_number_ = 0;
pages_.clear();
}
void MockPrinter::PrintPage(const PrintHostMsg_DidPrintPage_Params& params) {
// Verify the input parameter and update the printer status so that the
// RenderViewTest class can verify the this function finishes without errors.
EXPECT_EQ(PRINTER_PRINTING, printer_status_);
EXPECT_EQ(document_cookie_, params.document_cookie);
EXPECT_EQ(page_number_, params.page_number);
EXPECT_LE(params.page_number, number_pages_);
#if defined(OS_WIN) || defined(OS_MACOSX)
// Load the data sent from a RenderView object and create a PageData object.
// We duplicate the given file handle when creating a base::SharedMemory
// instance so that its destructor closes the copy.
EXPECT_GT(params.data_size, 0U);
#if defined(OS_WIN)
base::SharedMemory metafile_data(params.metafile_data_handle, true,
GetCurrentProcess());
#elif defined(OS_MACOSX)
base::SharedMemory metafile_data(params.metafile_data_handle, true);
#endif
metafile_data.Map(params.data_size);
#if defined(OS_MACOSX)
printing::PdfMetafileCg metafile;
#else
printing::NativeMetafile metafile;
#endif
metafile.InitFromData(metafile_data.memory(), params.data_size);
printing::Image image(metafile);
MockPrinterPage* page_data = new MockPrinterPage(metafile_data.memory(),
params.data_size,
image);
scoped_refptr<MockPrinterPage> page(page_data);
pages_.push_back(page);
#endif
// We finish printing a printing job.
// Reset the job status and the printer status.
++page_number_;
if (number_pages_ == page_number_)
ResetPrinter();
}
int MockPrinter::GetPrintedPages() const {
if (printer_status_ != PRINTER_READY)
return -1;
return page_number_;
}
const MockPrinterPage* MockPrinter::GetPrintedPage(unsigned int pageno) const {
if (pages_.size() > pageno)
return pages_[pageno].get();
else
return NULL;
}
int MockPrinter::GetWidth(unsigned int page) const {
if (printer_status_ != PRINTER_READY || page >= pages_.size())
return -1;
return pages_[page]->width();
}
int MockPrinter::GetHeight(unsigned int page) const {
if (printer_status_ != PRINTER_READY || page >= pages_.size())
return -1;
return pages_[page]->height();
}
bool MockPrinter::GetBitmapChecksum(
unsigned int page, std::string* checksum) const {
if (printer_status_ != PRINTER_READY || page >= pages_.size())
return false;
*checksum = pages_[page]->image().checksum();
return true;
}
bool MockPrinter::SaveSource(
unsigned int page, const base::FilePath& filepath) const {
if (printer_status_ != PRINTER_READY || page >= pages_.size())
return false;
const uint8* source_data = pages_[page]->source_data();
uint32 source_size = pages_[page]->source_size();
file_util::WriteFile(filepath, reinterpret_cast<const char*>(source_data),
source_size);
return true;
}
bool MockPrinter::SaveBitmap(
unsigned int page, const base::FilePath& filepath) const {
if (printer_status_ != PRINTER_READY || page >= pages_.size())
return false;
pages_[page]->image().SaveToPng(filepath);
return true;
}
int MockPrinter::CreateDocumentCookie() {
return use_invalid_settings_ ? 0 : ++current_document_cookie_;
}
void MockPrinter::SetPrintParams(PrintMsg_Print_Params* params) {
params->dpi = dpi_;
params->max_shrink = max_shrink_;
params->min_shrink = min_shrink_;
params->desired_dpi = desired_dpi_;
params->selection_only = selection_only_;
params->should_print_backgrounds = should_print_backgrounds_;
params->document_cookie = document_cookie_;
params->page_size = page_size_;
params->content_size = content_size_;
params->printable_area = printable_area_;
params->margin_left = margin_left_;
params->margin_top = margin_top_;
params->is_first_request = is_first_request_;
params->print_scaling_option = print_scaling_option_;
params->print_to_pdf = print_to_pdf_;
params->preview_request_id = preview_request_id_;
params->display_header_footer = display_header_footer_;
params->title = title_;
params->url = url_;
}