[go: nahoru, domu]

blob: 0dad41cc9c25637a033ada2efd5657c62b625a79 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/printing/renderer/print_render_frame_helper.h"
#include <stddef.h>
#include <memory>
#include <tuple>
#include <utility>
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/printing/common/print.mojom-test-utils.h"
#include "components/printing/common/print.mojom.h"
#include "components/printing/common/print_params.h"
#include "components/printing/test/mock_printer.h"
#include "components/printing/test/print_test_content_renderer_client.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/test/mock_render_thread.h"
#include "content/public/test/render_view_test.h"
#include "ipc/ipc_listener.h"
#include "printing/buildflags/buildflags.h"
#include "printing/image.h"
#include "printing/mojom/print.mojom.h"
#include "printing/page_range.h"
#include "printing/print_job_constants.h"
#include "printing/printing_utils.h"
#include "printing/units.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_range.h"
#include "third_party/blink/public/web/web_view.h"
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
#include "components/printing/browser/print_manager_utils.h"
#include "printing/print_settings.h"
#include "printing/print_settings_conversion.h"
#endif
using blink::WebFrame;
using blink::WebLocalFrame;
using blink::WebString;
namespace printing {
namespace {
// A simple web page.
const char kHelloWorldHTML[] = "<body><p>Hello World!</p></body>";
// Web page used for testing onbeforeprint/onafterprint.
const char kBeforeAfterPrintHtml[] =
"<body>"
"<script>"
"var beforePrintCount = 0;"
"var afterPrintCount = 0;"
"window. => { ++beforePrintCount; };"
"window. => { ++afterPrintCount; };"
"</script>"
"<button id=\"print\" World!</button>"
"</body>";
#if !BUILDFLAG(IS_CHROMEOS_ASH)
// A simple webpage with a button to print itself with.
const char kPrintOnUserAction[] =
"<body>"
" <button id=\"print\" World!</button>"
"</body>";
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
// HTML with 3 pages.
const char kMultipageHTML[] =
"<html><head><style>"
".break { page-break-after: always; }"
"</style></head>"
"<body>"
"<div class='break'>page1</div>"
"<div class='break'>page2</div>"
"<div>page3</div>"
"</body></html>";
// A simple web page with print page size css.
const char kHTMLWithPageSizeCss[] =
"<html><head><style>"
"@media print {"
" @page {"
" size: 4in 4in;"
" }"
"}"
"</style></head>"
"<body>Lorem Ipsum:"
"</body></html>";
// A simple web page with print page layout css.
const char kHTMLWithLandscapePageCss[] =
"<html><head><style>"
"@media print {"
" @page {"
" size: landscape;"
" }"
"}"
"</style></head>"
"<body>Lorem Ipsum:"
"</body></html>";
// A longer web page.
const char kLongPageHTML[] =
"<body><img src=\"\" width=10 height=10000 /></body>";
// A web page to simulate the print preview page.
const char kPrintPreviewHTML[] =
"<body><p id=\"pdf-viewer\">Hello World!</p></body>";
const char kHTMLWithManyLinesOfText[] =
"<html><head><style>"
"p { font-size: 24px; }"
"</style></head><body>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"<p>The quick brown fox jumped over the lazy dog.</p>"
"</body></html>";
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
class FakePrintPreviewUI : public mojom::PrintPreviewUI {
public:
FakePrintPreviewUI() = default;
~FakePrintPreviewUI() override = default;
mojo::PendingAssociatedRemote<mojom::PrintPreviewUI> BindReceiver() {
return receiver_.BindNewEndpointAndPassDedicatedRemote();
}
void ResetPreviewStatus() {
// Make sure there is no active request.
DCHECK(!quit_closure_);
preview_status_ = PreviewStatus::kNone;
}
// Waits until the preview request is failed, canceled, invalid, or done.
void WaitUntilPreviewUpdate() {
// If |preview_status_| is updated, it doesn't need to wait.
if (preview_status_ != PreviewStatus::kNone)
return;
base::RunLoop run_loop;
quit_closure_ = run_loop.QuitClosure();
run_loop.Run();
}
// Sets the page number to be cancelled.
void set_print_preview_cancel_page_number(uint32_t page) {
print_preview_cancel_page_number_ = page;
}
bool PreviewFailed() const {
return preview_status_ == PreviewStatus::kFailed;
}
bool PreviewCancelled() const {
return preview_status_ == PreviewStatus::kCancelled;
}
bool InvalidPrinterSetting() const {
return preview_status_ == PreviewStatus::kInvalidSetting;
}
bool IsMetafileReadyForPrinting() const {
return preview_status_ == PreviewStatus::kMetafileReadyForPrinting;
}
uint32_t page_count() const { return page_count_; }
mojom::PageSizeMargins* page_layout() const {
return page_layout_ ? page_layout_.get() : nullptr;
}
uint32_t print_preview_pages_remaining() const {
return print_preview_pages_remaining_;
}
mojom::DidPreviewDocumentParams* did_preview_document_params() const {
return did_preview_document_params_ ? did_preview_document_params_.get()
: nullptr;
}
const std::vector<std::pair<uint32_t, uint32_t>>& print_preview_pages()
const {
return print_preview_pages_;
}
bool all_pages_have_custom_size() const {
return all_pages_have_custom_size_;
}
bool all_pages_have_custom_orientation() const {
return all_pages_have_custom_orientation_;
}
// mojom::PrintPreviewUI:
void SetOptionsFromDocument(const mojom::OptionsFromDocumentParamsPtr params,
int32_t request_id) override {}
void DidPrepareDocumentForPreview(int32_t document_cookie,
int32_t request_id) override {}
void DidPreviewPage(mojom::DidPreviewPageParamsPtr params,
int32_t request_id) override {
uint32_t page_number = params->page_number;
DCHECK_NE(page_number, kInvalidPageIndex);
print_preview_pages_remaining_--;
print_preview_pages_.emplace_back(
params->page_number, params->content->metafile_data_region.GetSize());
}
void MetafileReadyForPrinting(mojom::DidPreviewDocumentParamsPtr params,
int32_t request_id) override {
DCHECK_EQ(preview_status_, PreviewStatus::kNone);
preview_status_ = PreviewStatus::kMetafileReadyForPrinting;
did_preview_document_params_ = std::move(params);
RunQuitClosure();
}
void PrintPreviewFailed(int32_t document_cookie,
int32_t request_id) override {
DCHECK_EQ(preview_status_, PreviewStatus::kNone);
preview_status_ = PreviewStatus::kFailed;
RunQuitClosure();
}
void PrintPreviewCancelled(int32_t document_cookie,
int32_t request_id) override {
DCHECK_EQ(preview_status_, PreviewStatus::kNone);
preview_status_ = PreviewStatus::kCancelled;
RunQuitClosure();
}
void PrinterSettingsInvalid(int32_t document_cookie,
int32_t request_id) override {
DCHECK_EQ(preview_status_, PreviewStatus::kNone);
preview_status_ = PreviewStatus::kInvalidSetting;
RunQuitClosure();
}
void DidGetDefaultPageLayout(mojom::PageSizeMarginsPtr page_layout_in_points,
const gfx::RectF& printable_area_in_points,
bool all_pages_have_custom_size,
bool all_pages_have_custom_orientation,
int32_t request_id) override {
page_layout_ = std::move(page_layout_in_points);
all_pages_have_custom_size_ = all_pages_have_custom_size;
all_pages_have_custom_orientation_ = all_pages_have_custom_orientation;
}
void DidStartPreview(mojom::DidStartPreviewParamsPtr params,
int32_t request_id) override {
page_count_ = params->page_count;
print_preview_pages_remaining_ = params->page_count;
}
// Determines whether to cancel a print preview request.
bool ShouldCancelRequest() const {
return print_preview_pages_remaining_ == print_preview_cancel_page_number_;
}
private:
void RunQuitClosure() {
if (!quit_closure_)
return;
std::move(quit_closure_).Run();
}
enum class PreviewStatus {
kNone = 0,
kFailed,
kCancelled,
kInvalidSetting,
kMetafileReadyForPrinting,
};
PreviewStatus preview_status_ = PreviewStatus::kNone;
uint32_t page_count_ = 0;
bool all_pages_have_custom_size_ = false;
bool all_pages_have_custom_orientation_ = false;
// Simulates cancelling print preview if |print_preview_pages_remaining_|
// equals this.
uint32_t print_preview_cancel_page_number_ = kInvalidPageIndex;
mojom::PageSizeMarginsPtr page_layout_;
mojom::DidPreviewDocumentParamsPtr did_preview_document_params_;
// Number of pages to generate for print preview.
uint32_t print_preview_pages_remaining_ = 0;
// Vector of <page_number, content_data_size> that were previewed.
std::vector<std::pair<uint32_t, uint32_t>> print_preview_pages_;
base::OnceClosure quit_closure_;
base::OnceClosure quit_closure_for_preview_started_;
mojo::AssociatedReceiver<mojom::PrintPreviewUI> receiver_{this};
};
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
class TestPrintManagerHost
: public mojom::PrintManagerHostInterceptorForTesting {
public:
TestPrintManagerHost(content::RenderFrame* frame, MockPrinter* printer)
: printer_(printer) {
Init(frame);
}
~TestPrintManagerHost() override = default;
// mojom::PrintManagerHostInterceptorForTesting
mojom::PrintManagerHost* GetForwardingInterface() override { return nullptr; }
void DidGetPrintedPagesCount(int32_t cookie, uint32_t number_pages) override {
if (number_pages_ > 0)
EXPECT_EQ(number_pages, number_pages_);
printer_->SetPrintedPagesCount(cookie, number_pages);
}
void DidPrintDocument(mojom::DidPrintDocumentParamsPtr params,
DidPrintDocumentCallback callback) override {
base::RunLoop().RunUntilIdle();
printer_->OnDocumentPrinted(std::move(params));
std::move(callback).Run(true);
is_printed_ = true;
}
void IsPrintingEnabled(IsPrintingEnabledCallback callback) override {
std::move(callback).Run(is_printing_enabled_);
}
void GetDefaultPrintSettings(
GetDefaultPrintSettingsCallback callback) override {
printing::mojom::PrintParamsPtr params =
printer_->GetDefaultPrintSettings();
std::move(callback).Run(std::move(params));
}
void DidShowPrintDialog() override {}
void ScriptedPrint(printing::mojom::ScriptedPrintParamsPtr params,
ScriptedPrintCallback callback) override {
if (!print_dialog_user_response_) {
std::move(callback).Run(nullptr);
return;
}
auto settings = printing::mojom::PrintPagesParams::New();
settings->params = printing::mojom::PrintParams::New();
printer_->ScriptedPrint(params->cookie, params->expected_pages_count,
params->has_selection, settings.get());
if (!PrintMsgPrintParamsIsValid(*settings->params)) {
std::move(callback).Run(nullptr);
return;
}
std::move(callback).Run(std::move(settings));
}
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
void UpdatePrintSettings(base::Value::Dict job_settings,
UpdatePrintSettingsCallback callback) override {
// Check and make sure the required settings are all there.
absl::optional<int> margins_type =
job_settings.FindInt(kSettingMarginsType);
if (!margins_type.has_value() ||
!job_settings.FindBool(kSettingLandscape) ||
!job_settings.FindBool(kSettingCollate) ||
!job_settings.FindInt(kSettingColor) ||
!job_settings.FindInt(kSettingPrinterType) ||
!job_settings.FindBool(kIsFirstRequest) ||
!job_settings.FindString(kSettingDeviceName) ||
!job_settings.FindInt(kSettingDuplexMode) ||
!job_settings.FindInt(kSettingCopies) ||
!job_settings.FindInt(kPreviewUIID) ||
!job_settings.FindInt(kPreviewRequestID)) {
std::move(callback).Run(nullptr);
return;
}
std::unique_ptr<PrintSettings> print_settings =
PrintSettingsFromJobSettings(job_settings);
if (!print_settings) {
std::move(callback).Run(nullptr);
return;
}
mojom::PrintPagesParamsPtr settings = mojom::PrintPagesParams::New();
settings->pages = GetPageRangesFromJobSettings(job_settings);
settings->params = mojom::PrintParams::New();
RenderParamsFromPrintSettings(*print_settings, settings->params.get());
settings->params->document_cookie = PrintSettings::NewCookie();
if (!PrintMsgPrintParamsIsValid(*settings->params)) {
std::move(callback).Run(nullptr);
return;
}
std::move(callback).Run(std::move(settings));
}
void SetupScriptedPrintPreview(
SetupScriptedPrintPreviewCallback callback) override {
is_setup_scripted_print_preview_ = true;
std::move(callback).Run();
}
void ShowScriptedPrintPreview(bool source_is_modifiable) override {}
void RequestPrintPreview(
mojom::RequestPrintPreviewParamsPtr params) override {}
void CheckForCancel(int32_t preview_ui_id,
int32_t request_id,
CheckForCancelCallback callback) override {
// Waits until other mojo messages are handled before checking if
// the print preview is canceled.
base::RunLoop().RunUntilIdle();
std::move(callback).Run(preview_ui_->ShouldCancelRequest());
}
void SetAccessibilityTree(
int32_t cookie,
const ui::AXTreeUpdate& accessibility_tree) override {
++accessibility_tree_set_count_;
}
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
bool IsSetupScriptedPrintPreview() {
return is_setup_scripted_print_preview_;
}
void ResetSetupScriptedPrintPreview() {
is_setup_scripted_print_preview_ = false;
}
bool IsPrinted() { return is_printed_; }
void SetExpectedPagesCount(uint32_t number_pages) {
number_pages_ = number_pages;
}
void WaitUntilBinding() {
if (receiver_.is_bound())
return;
base::RunLoop run_loop;
quit_closure_ = run_loop.QuitClosure();
run_loop.Run();
}
void SetPrintingEnabled(bool enabled) { is_printing_enabled_ = enabled; }
// Call with |response| set to true if the user wants to print.
// False if the user decides to cancel.
void SetPrintDialogUserResponse(bool response) {
print_dialog_user_response_ = response;
}
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
void set_preview_ui(FakePrintPreviewUI* preview_ui) {
preview_ui_ = preview_ui;
}
#endif
int accessibility_tree_set_count() const {
return accessibility_tree_set_count_;
}
private:
void Init(content::RenderFrame* frame) {
frame->GetRemoteAssociatedInterfaces()->OverrideBinderForTesting(
mojom::PrintManagerHost::Name_,
base::BindRepeating(&TestPrintManagerHost::BindPrintManagerReceiver,
base::Unretained(this)));
}
void BindPrintManagerReceiver(mojo::ScopedInterfaceEndpointHandle handle) {
receiver_.Bind(mojo::PendingAssociatedReceiver<mojom::PrintManagerHost>(
std::move(handle)));
if (!quit_closure_)
return;
std::move(quit_closure_).Run();
}
uint32_t number_pages_ = 0;
bool is_setup_scripted_print_preview_ = false;
bool is_printed_ = false;
raw_ptr<MockPrinter> printer_;
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
raw_ptr<FakePrintPreviewUI> preview_ui_;
#endif
base::OnceClosure quit_closure_;
bool is_printing_enabled_ = true;
// True to simulate user clicking print. False to cancel.
bool print_dialog_user_response_ = true;
int accessibility_tree_set_count_ = 0;
mojo::AssociatedReceiver<mojom::PrintManagerHost> receiver_{this};
};
} // namespace
class PrintRenderFrameHelperTestBase : public content::RenderViewTest {
public:
PrintRenderFrameHelperTestBase() = default;
PrintRenderFrameHelperTestBase(const PrintRenderFrameHelperTestBase&) =
delete;
PrintRenderFrameHelperTestBase& operator=(
const PrintRenderFrameHelperTestBase&) = delete;
~PrintRenderFrameHelperTestBase() override = default;
protected:
// content::RenderViewTest:
content::ContentRendererClient* CreateContentRendererClient() override {
return new PrintTestContentRendererClient(/*generate_tagged_pdfs=*/false);
}
void SetUp() override {
render_thread_ = std::make_unique<content::MockRenderThread>();
printer_ = std::make_unique<MockPrinter>();
content::RenderViewTest::SetUp();
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
preview_ui_ = std::make_unique<FakePrintPreviewUI>();
#endif
BindPrintManagerHost(content::RenderFrame::FromWebFrame(GetMainFrame()));
}
void TearDown() override {
#if defined(LEAK_SANITIZER)
// Do this before shutting down V8 in RenderViewTest::TearDown().
// http://crbug.com/328552
__lsan_do_leak_check();
#endif
content::RenderViewTest::TearDown();
}
void BindPrintManagerHost(content::RenderFrame* frame) {
auto print_manager =
std::make_unique<TestPrintManagerHost>(frame, printer());
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
print_manager->set_preview_ui(preview_ui_.get());
#endif
GetPrintRenderFrameHelperForFrame(frame)->GetPrintManagerHost();
print_manager->WaitUntilBinding();
frame_to_print_manager_map_.emplace(frame, std::move(print_manager));
}
void ClearPrintManagerHost() { frame_to_print_manager_map_.clear(); }
void PrintWithJavaScript() {
print_manager()->ResetSetupScriptedPrintPreview();
ExecuteJavaScriptForTests("window.print();");
base::RunLoop().RunUntilIdle();
}
// Verifies whether the pages printed or not.
void VerifyPagesPrinted(bool expect_printed,
content::RenderFrame* render_frame = nullptr) {
if (!render_frame)
render_frame = content::RenderFrame::FromWebFrame(GetMainFrame());
ASSERT_EQ(expect_printed, print_manager(render_frame)->IsPrinted());
}
void OnPrintPages() {
GetPrintRenderFrameHelper()->PrintRequestedPages();
base::RunLoop().RunUntilIdle();
}
void OnPrintPagesInFrame(base::StringPiece frame_name) {
blink::WebFrame* frame = GetMainFrame()->FindFrameByName(
blink::WebString::FromUTF8(frame_name.data(), frame_name.size()));
ASSERT_TRUE(frame);
content::RenderFrame* render_frame =
content::RenderFrame::FromWebFrame(frame->ToWebLocalFrame());
BindPrintManagerHost(render_frame);
PrintRenderFrameHelper* helper =
GetPrintRenderFrameHelperForFrame(render_frame);
ASSERT_TRUE(helper);
helper->PrintRequestedPages();
base::RunLoop().RunUntilIdle();
}
PrintRenderFrameHelper* GetPrintRenderFrameHelper() {
return PrintRenderFrameHelper::Get(
content::RenderFrame::FromWebFrame(GetMainFrame()));
}
PrintRenderFrameHelper* GetPrintRenderFrameHelperForFrame(
content::RenderFrame* frame) {
return PrintRenderFrameHelper::Get(frame);
}
void ClickMouseButton(const gfx::Rect& bounds) {
EXPECT_FALSE(bounds.IsEmpty());
blink::WebMouseEvent mouse_event(
blink::WebInputEvent::Type::kMouseDown,
blink::WebInputEvent::kNoModifiers,
blink::WebInputEvent::GetStaticTimeStampForTests());
mouse_event.button = blink::WebMouseEvent::Button::kLeft;
mouse_event.SetPositionInWidget(bounds.CenterPoint().x(),
bounds.CenterPoint().y());
mouse_event.click_count = 1;
SendWebMouseEvent(mouse_event);
mouse_event.SetType(blink::WebInputEvent::Type::kMouseUp);
SendWebMouseEvent(mouse_event);
}
void ExpectNoBeforeNoAfterPrintEvent() {
int result;
ASSERT_TRUE(
ExecuteJavaScriptAndReturnIntValue(u"beforePrintCount", &result));
EXPECT_EQ(0, result) << "beforeprint event should not be dispatched.";
ASSERT_TRUE(
ExecuteJavaScriptAndReturnIntValue(u"afterPrintCount", &result));
EXPECT_EQ(0, result) << "afterprint event should not be dispatched.";
}
void ExpectOneBeforeNoAfterPrintEvent() {
int result;
ASSERT_TRUE(
ExecuteJavaScriptAndReturnIntValue(u"beforePrintCount", &result));
EXPECT_EQ(1, result) << "beforeprint event should be dispatched once.";
ASSERT_TRUE(
ExecuteJavaScriptAndReturnIntValue(u"afterPrintCount", &result));
EXPECT_EQ(0, result) << "afterprint event should not be dispatched.";
}
void ExpectOneBeforeOneAfterPrintEvent() {
int result;
ASSERT_TRUE(
ExecuteJavaScriptAndReturnIntValue(u"beforePrintCount", &result));
EXPECT_EQ(1, result) << "beforeprint event should be dispatched once.";
ASSERT_TRUE(
ExecuteJavaScriptAndReturnIntValue(u"afterPrintCount", &result));
EXPECT_EQ(1, result) << "afterprint event should be dispatched once.";
}
TestPrintManagerHost* print_manager(content::RenderFrame* frame = nullptr) {
if (!frame)
frame = content::RenderFrame::FromWebFrame(GetMainFrame());
auto it = frame_to_print_manager_map_.find(frame);
return it->second.get();
}
MockPrinter* printer() { return printer_.get(); }
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
FakePrintPreviewUI* preview_ui() { return preview_ui_.get(); }
#endif
private:
// A mock printer device used for printing tests.
std::unique_ptr<MockPrinter> printer_;
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
std::unique_ptr<FakePrintPreviewUI> preview_ui_;
#endif
std::map<content::RenderFrame*, std::unique_ptr<TestPrintManagerHost>>
frame_to_print_manager_map_;
};
// RenderViewTest-based tests crash on Android
// http://crbug.com/187500
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_PrintRenderFrameHelperTest DISABLED_PrintRenderFrameHelperTest
#else
#define MAYBE_PrintRenderFrameHelperTest PrintRenderFrameHelperTest
#endif // BUILDFLAG(IS_ANDROID)
class MAYBE_PrintRenderFrameHelperTest : public PrintRenderFrameHelperTestBase {
public:
MAYBE_PrintRenderFrameHelperTest() = default;
MAYBE_PrintRenderFrameHelperTest(const MAYBE_PrintRenderFrameHelperTest&) =
delete;
MAYBE_PrintRenderFrameHelperTest& operator=(
const MAYBE_PrintRenderFrameHelperTest&) = delete;
~MAYBE_PrintRenderFrameHelperTest() override = default;
};
// This tests only for platforms without print preview.
#if !BUILDFLAG(ENABLE_PRINT_PREVIEW)
// Tests that the renderer blocks window.print() calls if they occur too
// frequently.
TEST_F(MAYBE_PrintRenderFrameHelperTest, BlockScriptInitiatedPrinting) {
// Pretend user will cancel printing.
print_manager()->SetPrintDialogUserResponse(false);
// Try to print with window.print() a few times.
PrintWithJavaScript();
PrintWithJavaScript();
PrintWithJavaScript();
VerifyPagesPrinted(false);
// Pretend user will print. (but printing is blocked.)
print_manager()->SetPrintDialogUserResponse(true);
PrintWithJavaScript();
VerifyPagesPrinted(false);
// Unblock script initiated printing and verify printing works.
GetPrintRenderFrameHelper()->scripting_throttler_.Reset();
printer()->ResetPrinter();
print_manager()->SetExpectedPagesCount(1);
PrintWithJavaScript();
VerifyPagesPrinted(true);
}
// Tests that the renderer always allows window.print() calls if they are user
// initiated.
TEST_F(MAYBE_PrintRenderFrameHelperTest, AllowUserOriginatedPrinting) {
// Pretend user will cancel printing.
print_manager()->SetPrintDialogUserResponse(false);
// Try to print with window.print() a few times.
PrintWithJavaScript();
PrintWithJavaScript();
PrintWithJavaScript();
VerifyPagesPrinted(false);
// Pretend user will print. (but printing is blocked.)
print_manager()->SetPrintDialogUserResponse(true);
PrintWithJavaScript();
VerifyPagesPrinted(false);
// Try again as if user initiated, without resetting the print count.
printer()->ResetPrinter();
LoadHTML(kPrintOnUserAction);
gfx::Size new_size(200, 100);
Resize(new_size, false);
print_manager()->SetExpectedPagesCount(1);
gfx::Rect bounds = GetElementBounds("print");
ClickMouseButton(bounds);
base::RunLoop().RunUntilIdle();
VerifyPagesPrinted(true);
}
// Duplicate of OnPrintPagesTest only using javascript to print.
TEST_F(MAYBE_PrintRenderFrameHelperTest, PrintWithJavascript) {
print_manager()->SetExpectedPagesCount(1);
PrintWithJavaScript();
VerifyPagesPrinted(true);
}
// Regression test for https://crbug.com/912966
TEST_F(MAYBE_PrintRenderFrameHelperTest, WindowPrintBeforePrintAfterPrint) {
LoadHTML(kBeforeAfterPrintHtml);
ExpectNoBeforeNoAfterPrintEvent();
print_manager()->SetExpectedPagesCount(1);
PrintWithJavaScript();
VerifyPagesPrinted(true);
ExpectOneBeforeOneAfterPrintEvent();
}
#endif // !BUILDFLAG(ENABLE_PRINT_PREVIEW)
// Tests that printing pages work and sending and receiving messages through
// that channel all works.
TEST_F(MAYBE_PrintRenderFrameHelperTest, OnPrintPages) {
LoadHTML(kHelloWorldHTML);
print_manager()->SetExpectedPagesCount(1);
OnPrintPages();
VerifyPagesPrinted(true);
}
TEST_F(MAYBE_PrintRenderFrameHelperTest, BasicBeforePrintAfterPrint) {
LoadHTML(kBeforeAfterPrintHtml);
ExpectNoBeforeNoAfterPrintEvent();
print_manager()->SetExpectedPagesCount(1);
OnPrintPages();
VerifyPagesPrinted(true);
ExpectOneBeforeOneAfterPrintEvent();
}
TEST_F(MAYBE_PrintRenderFrameHelperTest, BasicBeforePrintAfterPrintSubFrame) {
static const char kCloseOnBeforeHtml[] =
"<body>Hello"
"<iframe name=sub srcdoc='<script>"
"window. => { window.frameElement.remove(); };"
"</script>'></iframe>"
"</body>";
LoadHTML(kCloseOnBeforeHtml);
content::RenderFrame* sub_render_frame = content::RenderFrame::FromWebFrame(
GetMainFrame()->FindFrameByName("sub")->ToWebLocalFrame());
OnPrintPagesInFrame("sub");
EXPECT_EQ(nullptr, GetMainFrame()->FindFrameByName("sub"));
VerifyPagesPrinted(false, sub_render_frame);
ClearPrintManagerHost();
static const char kCloseOnAfterHtml[] =
"<body>Hello"
"<iframe name=sub srcdoc='<script>"
"window. => { window.frameElement.remove(); };"
"</script>'></iframe>"
"</body>";
LoadHTML(kCloseOnAfterHtml);
sub_render_frame = content::RenderFrame::FromWebFrame(
GetMainFrame()->FindFrameByName("sub")->ToWebLocalFrame());
OnPrintPagesInFrame("sub");
EXPECT_EQ(nullptr, GetMainFrame()->FindFrameByName("sub"));
VerifyPagesPrinted(true, sub_render_frame);
}
// https://crbug.com/1372396
//
// There used to be a Blink bug when entering print preview with a monolithic
// absolutely positioned box that extended into a page where the parent had no
// representation. It could only be reproduced when entering print preview,
// because print preview apparently enters print mode, runs a rendering
// lifecycle update, leaves print mode *without* running a rendering lifecycle
// update, then enter print mode a second time. When running a rendering
// lifecycle update this time, we'd fail a DCHECK, because when leaving print
// mode the first time, we'd mark for paint invalidation. Not handling it at
// that point (no lifecycle update) is fine in principle, but it used to cause
// some bad ancestry node marking when we got to the lifecycle update when
// entering print mode for the second time.
TEST_F(MAYBE_PrintRenderFrameHelperTest, MonolithicAbsposOverflowingParent) {
LoadHTML(R"HTML(
<style>
#trouble {
contain: size;
position: absolute;
top: 5000px;
width: 100px;
height: 100px;
background: lime;
}
</style>
<div style="position:relative; height:10000px;">
<div>
<div id="trouble"></div>
</div>
</div>
)HTML");
OnPrintPages();
}
#if defined(MOCK_PRINTER_SUPPORTS_PAGE_IMAGES)
TEST_F(MAYBE_PrintRenderFrameHelperTest, Pixels) {
// This test should generate two pages. The first should be 16x16 CSS pixels
// large, and the second should be 24x24. The pixels and page size information
// are going on a ride through the machineries, so use size values carefully,
// to avoid subpixel issues. At some point on the journey, everything will be
// changed to 300 DPI, and the page sizes involved will be rounded to integers
// (so we need something that ends up with integers after having been
// multiplied by 300/72 and back). See crbug.com/1466995 . Furthermore, the
// final output will be in points, not CSS pixels, which is why the
// expectation is to get 12x12 and 18x18 pages instead of 16x16 and 24x24 (and
// a 4px border becomes a 3pt border).
LoadHTML(R"HTML(
<style>
@page {
size: 24px;
margin: 0;
}
@page:first {
size: 16px;
}
body {
margin: 0;
}
div {
box-sizing: border-box;
border: 4px solid;
}
</style>
<div style="width:16px; height:16px; border-color:#00ff00;"></div>
<div style="width:24px; height:24px; border-color:#0000ff;"></div>
)HTML");
printer()->set_should_print_backgrounds(true);
printer()->set_should_generate_page_images(true);
OnPrintPages();
// First page:
const MockPrinterPage* page = printer()->GetPrinterPage(0);
ASSERT_TRUE(page);
const Image& first_image = page->image();
ASSERT_EQ(first_image.size(), gfx::Size(12, 12));
// Top left corner:
EXPECT_EQ(first_image.pixel_at(0, 0), 0x00ff00U);
EXPECT_EQ(first_image.pixel_at(2, 2), 0x00ff00U);
EXPECT_EQ(first_image.pixel_at(3, 3), 0xffffffU);
// Top right corner:
EXPECT_EQ(first_image.pixel_at(11, 0), 0x00ff00U);
EXPECT_EQ(first_image.pixel_at(9, 2), 0x00ff00U);
EXPECT_EQ(first_image.pixel_at(8, 3), 0xffffffU);
// Bottom right corner:
EXPECT_EQ(first_image.pixel_at(11, 11), 0x00ff00U);
EXPECT_EQ(first_image.pixel_at(9, 9), 0x00ff00U);
EXPECT_EQ(first_image.pixel_at(8, 8), 0xffffffU);
// Bottom left corner:
EXPECT_EQ(first_image.pixel_at(0, 11), 0x00ff00U);
EXPECT_EQ(first_image.pixel_at(2, 9), 0x00ff00U);
EXPECT_EQ(first_image.pixel_at(3, 8), 0xffffffU);
// Second page:
page = printer()->GetPrinterPage(1);
ASSERT_TRUE(page);
const Image& second_image = page->image();
ASSERT_EQ(second_image.size(), gfx::Size(18, 18));
// Top left corner:
EXPECT_EQ(second_image.pixel_at(0, 0), 0x0000ffU);
EXPECT_EQ(second_image.pixel_at(2, 2), 0x0000ffU);
EXPECT_EQ(second_image.pixel_at(3, 3), 0xffffffU);
// Top right corner:
EXPECT_EQ(second_image.pixel_at(0, 17), 0x0000ffU);
EXPECT_EQ(second_image.pixel_at(2, 15), 0x0000ffU);
EXPECT_EQ(second_image.pixel_at(3, 14), 0xffffffU);
// Bottom right corner:
EXPECT_EQ(second_image.pixel_at(17, 17), 0x0000ffU);
EXPECT_EQ(second_image.pixel_at(15, 15), 0x0000ffU);
EXPECT_EQ(second_image.pixel_at(14, 14), 0xffffffU);
// Bottom left corner:
EXPECT_EQ(second_image.pixel_at(0, 17), 0x0000ffU);
EXPECT_EQ(second_image.pixel_at(2, 15), 0x0000ffU);
EXPECT_EQ(second_image.pixel_at(3, 14), 0xffffffU);
}
#endif // MOCK_PRINTER_SUPPORTS_PAGE_IMAGES
TEST_F(MAYBE_PrintRenderFrameHelperTest, SpecifiedPageSize1) {
LoadHTML(R"HTML(
<style>
@page {
size: 400px 123px;
margin: 0;
}
body {
margin: 0;
}
</style>
<div style="width:400px; height:123px;"></div>
)HTML");
print_manager()->SetExpectedPagesCount(1);
OnPrintPages();
VerifyPagesPrinted(true);
}
// TODO(crbug.com/1444579): Fix the remaining issues, and enable this test.
TEST_F(MAYBE_PrintRenderFrameHelperTest, DISABLED_SpecifiedPageSize2) {
LoadHTML(R"HTML(
<style>
@page {
size: 400px 123.1px;
margin: 0;
}
body {
margin: 0;
}
</style>
<div style="width:400px; height:123.1px;"></div>
)HTML");
print_manager()->SetExpectedPagesCount(1);
OnPrintPages();
VerifyPagesPrinted(true);
}
// TODO(crbug.com/1444579): Fix the remaining issues, and enable this test.
TEST_F(MAYBE_PrintRenderFrameHelperTest, DISABLED_SpecifiedPageSize3) {
LoadHTML(R"HTML(
<style>
@page {
size: 400px 123.9px;
margin: 0;
}
body {
margin: 0;
}
</style>
<div style="width:400px; height:123.9px;"></div>
)HTML");
print_manager()->SetExpectedPagesCount(1);
OnPrintPages();
VerifyPagesPrinted(true);
}
TEST_F(MAYBE_PrintRenderFrameHelperTest, MediaQueryNoCSSPageMargins) {
// The default page size in these tests is US Letter.
LoadHTML(R"HTML(
<style>
@page {
margin: 0;
}
@media (width: 8.5in) and (height: 11in) {
div { break-before: page; }
}
</style>
First page
<div>Second page</div>
)HTML");
print_manager()->SetExpectedPagesCount(2);
OnPrintPages();
VerifyPagesPrinted(true);
}
#if defined(MOCK_PRINTER_SUPPORTS_PAGE_IMAGES)
TEST_F(MAYBE_PrintRenderFrameHelperTest, PrintWithIframe) {
// Document that populates an iframe.
static const char html[] =
"<html><body>Lorem Ipsum:"
"<iframe name=\"sub1\" id=\"sub1\"></iframe><script>"
" document.write(frames['sub1'].name);"
" frames['sub1'].document.write("
" '<p>Cras tempus ante eu felis semper luctus!</p>');"
" frames['sub1'].document.close();"
"</script></body></html>";
printer()->set_should_generate_page_images(true);
LoadHTML(html);
// Find the frame and set it as the focused one. This should mean that that
// the printout should only contain the contents of that frame.
WebFrame* sub1_frame =
web_view_->MainFrame()->ToWebLocalFrame()->FindFrameByName(
WebString::FromUTF8("sub1"));
ASSERT_TRUE(sub1_frame);
web_view_->SetFocusedFrame(sub1_frame);
ASSERT_NE(web_view_->FocusedFrame(), web_view_->MainFrame());
// Initiate printing.
OnPrintPages();
VerifyPagesPrinted(true);
// Verify output through MockPrinter.
const MockPrinter* mock_printer(printer());
ASSERT_EQ(1, mock_printer->GetPageCount());
const Image& image1(mock_printer->GetPrinterPage(0)->image());
// TODO(sverrir): Figure out a way to improve this test to actually print
// only the content of the iframe. Currently image1 will contain the full
// page.
EXPECT_NE(0, image1.size().width());
EXPECT_NE(0, image1.size().height());
}
#endif // MOCK_PRINTER_SUPPORTS_PAGE_IMAGES
// These print preview tests do not work on Chrome OS yet.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
class PrintRenderFrameHelperPreviewTest
: public PrintRenderFrameHelperTestBase {
public:
PrintRenderFrameHelperPreviewTest() = default;
PrintRenderFrameHelperPreviewTest(const PrintRenderFrameHelperPreviewTest&) =
delete;
PrintRenderFrameHelperPreviewTest& operator=(
const PrintRenderFrameHelperPreviewTest&) = delete;
~PrintRenderFrameHelperPreviewTest() override = default;
void SetUp() override {
PrintRenderFrameHelperTestBase::SetUp();
BindToFakePrintPreviewUI();
CreatePrintSettingsDictionary();
}
protected:
void BindToFakePrintPreviewUI() {
PrintRenderFrameHelper* frame_helper = GetPrintRenderFrameHelper();
frame_helper->SetPrintPreviewUI(preview_ui()->BindReceiver());
}
void OnPrintPreview() {
PrintRenderFrameHelper* print_render_frame_helper =
GetPrintRenderFrameHelper();
print_render_frame_helper->InitiatePrintPreview(
#if BUILDFLAG(IS_CHROMEOS_ASH)
mojo::NullAssociatedRemote(),
#endif
/*has_selection=*/false);
print_render_frame_helper->PrintPreview(print_settings_.Clone());
preview_ui()->WaitUntilPreviewUpdate();
}
void OnPrintPreviewRerender() {
preview_ui()->ResetPreviewStatus();
GetPrintRenderFrameHelper()->PrintPreview(print_settings_.Clone());
preview_ui()->WaitUntilPreviewUpdate();
}
void OnClosePrintPreviewDialog() {
GetPrintRenderFrameHelper()->OnPrintPreviewDialogClosed();
}
void OnPrintForSystemDialog() {
GetPrintRenderFrameHelper()->PrintForSystemDialog();
}
void VerifyPreviewRequest(bool expect_request) {
EXPECT_EQ(expect_request, print_manager()->IsSetupScriptedPrintPreview());
}
// The renderer should be done calculating the number of rendered pages
// according to the specified settings defined in the mock render thread.
// Verify the page count is correct.
void VerifyPreviewPageCount(uint32_t expected_count) {
EXPECT_EQ(expected_count, preview_ui()->page_count());
}
void VerifyPrintPreviewCancelled(bool expect_cancel) {
EXPECT_EQ(expect_cancel, preview_ui()->PreviewCancelled());
}
void VerifyPrintPreviewFailed(bool expect_fail) {
EXPECT_EQ(expect_fail, preview_ui()->PreviewFailed());
}
void VerifyPrintPreviewGenerated(bool expect_generated) {
ASSERT_EQ(expect_generated, preview_ui()->IsMetafileReadyForPrinting());
if (preview_ui()->IsMetafileReadyForPrinting()) {
ASSERT_TRUE(preview_ui()->did_preview_document_params());
const auto& param = *preview_ui()->did_preview_document_params();
EXPECT_NE(0, param.document_cookie);
EXPECT_NE(0U, param.expected_pages_count);
auto mapped = param.content->metafile_data_region.Map();
ASSERT_TRUE(mapped.IsValid());
EXPECT_TRUE(LooksLikePdf(mapped.GetMemoryAsSpan<const char>()));
}
}
void VerifyPrintPreviewInvalidPrinterSettings(bool expect_invalid_settings) {
EXPECT_EQ(expect_invalid_settings, preview_ui()->InvalidPrinterSetting());
}
// |page_number| is 0-based.
void VerifyDidPreviewPage(bool expect_generated, uint32_t page_number) {
bool msg_found = false;
uint32_t data_size = 0;
for (const auto& preview : preview_ui()->print_preview_pages()) {
if (preview.first == page_number) {
msg_found = true;
data_size = preview.second;
break;
}
}
EXPECT_EQ(expect_generated, msg_found) << "For page " << page_number;
if (expect_generated)
EXPECT_NE(0U, data_size) << "For page " << page_number;
}
void VerifyDefaultPageLayout(
int expected_content_width,
int expected_content_height,
int expected_margin_top,
int expected_margin_bottom,
int expected_margin_left,
int expected_margin_right,
bool expected_all_pages_have_custom_size,
bool expected_all_pages_have_custom_orientation) {
const mojom::PageSizeMargins* page_layout = preview_ui()->page_layout();
ASSERT_TRUE(page_layout);
EXPECT_EQ(expected_content_width, page_layout->content_width);
EXPECT_EQ(expected_content_height, page_layout->content_height);
EXPECT_EQ(expected_margin_top, page_layout->margin_top);
EXPECT_EQ(expected_margin_right, page_layout->margin_right);
EXPECT_EQ(expected_margin_left, page_layout->margin_left);
EXPECT_EQ(expected_margin_bottom, page_layout->margin_bottom);
EXPECT_EQ(expected_all_pages_have_custom_size,
preview_ui()->all_pages_have_custom_size());
EXPECT_EQ(expected_all_pages_have_custom_orientation,
preview_ui()->all_pages_have_custom_orientation());
}
base::Value::Dict& print_settings() { return print_settings_; }
private:
void CreatePrintSettingsDictionary() {
print_settings_ =
base::Value::Dict()
.Set(kSettingLandscape, false)
.Set(kSettingCollate, false)
.Set(kSettingColor, static_cast<int>(mojom::ColorModel::kGray))
.Set(kSettingPrinterType,
static_cast<int>(mojom::PrinterType::kPdf))
.Set(kSettingDuplexMode,
static_cast<int>(mojom::DuplexMode::kSimplex))
.Set(kSettingCopies, 1)
.Set(kSettingDeviceName, "dummy")
.Set(kSettingDpiHorizontal, 72)
.Set(kSettingDpiVertical, 72)
.Set(kPreviewUIID, 4)
.Set(kSettingRasterizePdf, false)
.Set(kPreviewRequestID, 12345)
.Set(kSettingScaleFactor, 100)
.Set(kIsFirstRequest, true)
.Set(kSettingMarginsType,
static_cast<int>(mojom::MarginType::kDefaultMargins))
.Set(kSettingPagesPerSheet, 1)
.Set(kSettingPreviewModifiable, true)
.Set(kSettingPreviewIsFromArc, false)
.Set(kSettingHeaderFooterEnabled, false)
.Set(kSettingShouldPrintBackgrounds, false)
.Set(kSettingShouldPrintSelectionOnly, false);
// Using a media size with realistic dimensions for a Letter paper.
auto media_size = base::Value::Dict()
.Set(kSettingMediaSizeWidthMicrons, 215900)
.Set(kSettingMediaSizeHeightMicrons, 279400)
.Set(kSettingsImageableAreaLeftMicrons, 12700)
.Set(kSettingsImageableAreaBottomMicrons, 0)
.Set(kSettingsImageableAreaRightMicrons, 209550)
.Set(kSettingsImageableAreaTopMicrons, 254000);
print_settings_.Set(kSettingMediaSize, std::move(media_size));
}
base::Value::Dict print_settings_;
};
TEST_F(PrintRenderFrameHelperPreviewTest, BlockScriptInitiatedPrinting) {
LoadHTML(kHelloWorldHTML);
print_manager()->SetPrintingEnabled(false);
PrintWithJavaScript();
VerifyPreviewRequest(false);
print_manager()->SetPrintingEnabled(true);
PrintWithJavaScript();
VerifyPreviewRequest(true);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest, PrintWithJavaScript) {
LoadHTML(kPrintOnUserAction);
gfx::Size new_size(200, 100);
Resize(new_size, false);
gfx::Rect bounds = GetElementBounds("print");
ClickMouseButton(bounds);
VerifyPreviewRequest(true);
OnClosePrintPreviewDialog();
}
// Tests that print preview work and sending and receiving messages through
// that channel all works.
TEST_F(PrintRenderFrameHelperPreviewTest, OnPrintPreview) {
LoadHTML(kHelloWorldHTML);
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyDefaultPageLayout(548, 692, 72, 28, 36, 28, false, false);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest, PrintPreviewHTMLWithPageMarginsCss) {
// A simple web page with print margins css.
static const char kHTMLWithPageMarginsCss[] =
"<html><head><style>"
"@media print {"
" @page {"
" margin: 3in 1in 2in 0.3in;"
" }"
"}"
"</style></head>"
"<body>Lorem Ipsum:"
"</body></html>";
LoadHTML(kHTMLWithPageMarginsCss);
print_settings().Set(kSettingPrinterType,
static_cast<int>(mojom::PrinterType::kLocal));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDefaultPageLayout(519, 432, 216, 144, 21, 72, false, false);
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
// Test to verify that print preview ignores print media css when non-default
// margin is selected.
TEST_F(PrintRenderFrameHelperPreviewTest,
NonDefaultMarginsSelectedIgnorePrintCss) {
LoadHTML(kHTMLWithPageSizeCss);
print_settings().Set(kSettingPrinterType,
static_cast<int>(mojom::PrinterType::kLocal));
print_settings().Set(kSettingMarginsType,
static_cast<int>(mojom::MarginType::kNoMargins));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDefaultPageLayout(612, 792, 0, 0, 0, 0, true, true);
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
// Test to verify that print preview honor print media size css when
// PRINT_TO_PDF is selected and doesn't fit to printer default paper size.
TEST_F(PrintRenderFrameHelperPreviewTest, PrintToPDFSelectedHonorPrintCss) {
LoadHTML(kHTMLWithPageSizeCss);
print_settings().Set(
kSettingMarginsType,
static_cast<int>(mojom::MarginType::kPrintableAreaMargins));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
// Since PRINT_TO_PDF is selected, pdf page size is equal to print media page
// size.
VerifyDefaultPageLayout(234, 216, 72, 0, 36, 18, true, true);
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest, PreviewLayoutTriggeredByResize) {
// A simple web page with print margins css.
static const char kHTMLWithPageCss[] =
"<!DOCTYPE html>"
"<style>"
"@media (min-width: 540px) {"
" #container {"
" width: 540px;"
" }"
"}"
".testlist {"
" list-style-type: none;"
"}"
"</style>"
"<div id='container'>"
" <ul class='testlist'>"
" <li>"
" <p>"
" 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
" ccccccccccccccccccccccccccccccccccccccc"
" ddddddddddddddddddddddddddddddddddddddd"
" eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
" fffffffffffffffffffffffffffffffffffffff"
" ggggggggggggggggggggggggggggggggggggggg"
" hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
" iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"
" jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"
" kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"
" lllllllllllllllllllllllllllllllllllllll"
" mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm':"
" </p>"
" </li>"
" <li>"
" <p>"
" 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
" ccccccccccccccccccccccccccccccccccccccc"
" ddddddddddddddddddddddddddddddddddddddd"
" eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
" fffffffffffffffffffffffffffffffffffffff"
" ggggggggggggggggggggggggggggggggggggggg"
" hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
" iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"
" jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"
" kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"
" lllllllllllllllllllllllllllllllllllllll"
" mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm'"
" </p>"
" </li>"
" <li>"
" <p>"
" 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
" ccccccccccccccccccccccccccccccccccccccc"
" ddddddddddddddddddddddddddddddddddddddd"
" eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
" fffffffffffffffffffffffffffffffffffffff"
" ggggggggggggggggggggggggggggggggggggggg"
" hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
" iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"
" jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"
" kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"
" lllllllllllllllllllllllllllllllllllllll"
" mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm'"
" </p>"
" </li>"
" <li>"
" <p>"
" 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
" ccccccccccccccccccccccccccccccccccccccc"
" ddddddddddddddddddddddddddddddddddddddd"
" eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
" fffffffffffffffffffffffffffffffffffffff"
" ggggggggggggggggggggggggggggggggggggggg"
" hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
" iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"
" jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"
" kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"
" lllllllllllllllllllllllllllllllllllllll"
" mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm'"
" </p>"
" </li>"
" <li>"
" <p>"
" 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
" ccccccccccccccccccccccccccccccccccccccc"
" ddddddddddddddddddddddddddddddddddddddd"
" eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
" fffffffffffffffffffffffffffffffffffffff"
" ggggggggggggggggggggggggggggggggggggggg"
" hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
" iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"
" jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"
" kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"
" lllllllllllllllllllllllllllllllllllllll"
" mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm'"
" </p>"
" </li>"
" </ul>"
"</div>";
LoadHTML(kHTMLWithPageCss);
print_settings().Set(kSettingPrinterType,
static_cast<int>(mojom::PrinterType::kLocal));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(true, 0);
VerifyDidPreviewPage(true, 1);
VerifyPreviewPageCount(2);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
// Test to verify that print preview honor print margin css when PRINT_TO_PDF
// is selected and doesn't fit to printer default paper size.
TEST_F(PrintRenderFrameHelperPreviewTest,
PrintToPDFSelectedHonorPageMarginsCss) {
// A simple web page with print margins css.
static const char kHTMLWithPageCss[] =
"<html><head><style>"
"@media print {"
" @page {"
" margin: 3in 1in 2in 0.3in;"
" size: 14in 14in;"
" }"
"}"
"</style></head>"
"<body>Lorem Ipsum:"
"</body></html>";
LoadHTML(kHTMLWithPageCss);
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
// Since PRINT_TO_PDF is selected, pdf page size is equal to print media page
// size.
VerifyDefaultPageLayout(915, 648, 216, 144, 21, 72, true, true);
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
// Test to verify that print preview workflow center the html page contents to
// fit the page size.
TEST_F(PrintRenderFrameHelperPreviewTest, PrintPreviewCenterToFitPage) {
LoadHTML(kHTMLWithPageSizeCss);
print_settings().Set(kSettingPrinterType,
static_cast<int>(mojom::PrinterType::kLocal));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDefaultPageLayout(224, 188, 324, 280, 198, 190, true, true);
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
// Test to verify that print preview workflow scale the html page contents to
// fit the page size.
TEST_F(PrintRenderFrameHelperPreviewTest, PrintPreviewShrinkToFitPage) {
// A simple web page with print margins css.
static const char kHTMLWithPageCss[] =
"<html><head><style>"
"@media print {"
" @page {"
" size: 15in 17in;"
" }"
"}"
"</style></head>"
"<body>Lorem Ipsum:"
"</body></html>";
LoadHTML(kHTMLWithPageCss);
print_settings().Set(kSettingPrinterType,
static_cast<int>(mojom::PrinterType::kLocal));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDefaultPageLayout(576, 637, 89, 66, 20, 16, true, true);
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
// Test to verify that print preview workflow honor the orientation settings
// specified in css.
TEST_F(PrintRenderFrameHelperPreviewTest, PrintPreviewHonorsOrientationCss) {
LoadHTML(kHTMLWithLandscapePageCss);
print_settings().Set(kSettingPrinterType,
static_cast<int>(mojom::PrinterType::kLocal));
print_settings().Set(kSettingMarginsType,
static_cast<int>(mojom::MarginType::kNoMargins));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDefaultPageLayout(792, 612, 0, 0, 0, 0, false, true);
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
// Test to verify that print preview workflow honors the orientation settings
// specified in css when PRINT_TO_PDF is selected.
TEST_F(PrintRenderFrameHelperPreviewTest,
PrintToPDFSelectedHonorOrientationCss) {
LoadHTML(kHTMLWithLandscapePageCss);
base::Value::Dict custom_margins;
custom_margins.Set(kSettingMarginTop, 21);
custom_margins.Set(kSettingMarginBottom, 23);
custom_margins.Set(kSettingMarginLeft, 21);
custom_margins.Set(kSettingMarginRight, 23);
print_settings().Set(kSettingMarginsType,
static_cast<int>(mojom::MarginType::kCustomMargins));
print_settings().Set(kSettingMarginsCustom, std::move(custom_margins));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDefaultPageLayout(748, 568, 21, 23, 21, 23, false, true);
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest, PrintPreviewForMultiplePages) {
LoadHTML(kMultipageHTML);
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(true, 0);
VerifyDidPreviewPage(true, 1);
VerifyDidPreviewPage(true, 2);
VerifyPreviewPageCount(3);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest, PrintPreviewForSelectedPages) {
LoadHTML(kMultipageHTML);
// Set a page range and update the dictionary to generate only the complete
// metafile with the selected pages. Page numbers used in the dictionary
// are 1-based.
base::Value::Dict page_range;
page_range.Set(kSettingPageRangeFrom, base::Value(2));
page_range.Set(kSettingPageRangeTo, base::Value(3));
base::Value::List page_range_array;
page_range_array.Append(std::move(page_range));
print_settings().Set(kSettingPageRange, std::move(page_range_array));
OnPrintPreview();
// The expected page count below is 3 because the total number of pages in the
// document, without the page range, is 3. Since only 2 pages have been
// generated, the print_preview_pages_remaining() result is 1.
// TODO(thestig): Fix this on the browser side to accept the number of actual
// pages generated instead, or to take both page counts.
EXPECT_EQ(1u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(false, 0);
VerifyDidPreviewPage(true, 1);
VerifyDidPreviewPage(true, 2);
VerifyPreviewPageCount(3);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest, PrintPreviewInvalidPageRange) {
LoadHTML(kHelloWorldHTML);
// Request a page beyond the end of document and assure we get the entire
// document back.
base::Value::Dict page_range;
page_range.Set(kSettingPageRangeFrom, 2);
page_range.Set(kSettingPageRangeTo, 2);
base::Value::List page_range_array;
page_range_array.Append(std::move(page_range));
print_settings().Set(kSettingPageRange, std::move(page_range_array));
OnPrintPreview();
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
OnClosePrintPreviewDialog();
}
// Test to verify that preview generated only for one page.
TEST_F(PrintRenderFrameHelperPreviewTest, PrintPreviewForSelectedText) {
LoadHTML(kMultipageHTML);
GetMainFrame()->SelectRange(blink::WebRange(1, 3),
blink::WebLocalFrame::kHideSelectionHandle,
blink::mojom::SelectionMenuBehavior::kHide);
print_settings().Set(kSettingShouldPrintSelectionOnly, true);
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
// Test to verify that preview generated only for two pages.
TEST_F(PrintRenderFrameHelperPreviewTest, PrintPreviewForSelectedText2) {
LoadHTML(kMultipageHTML);
GetMainFrame()->SelectRange(blink::WebRange(1, 8),
blink::WebLocalFrame::kHideSelectionHandle,
blink::mojom::SelectionMenuBehavior::kHide);
print_settings().Set(kSettingShouldPrintSelectionOnly, true);
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(2);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest, PrintPreviewForManyLinesOfText) {
LoadHTML(kHTMLWithManyLinesOfText);
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest,
PrintPreviewForManyLinesOfTextWithScaling) {
LoadHTML(kHTMLWithManyLinesOfText);
print_settings().Set(kSettingScaleFactor, 200);
OnPrintPreview();
constexpr int kExpectedPageCount = 3;
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
for (int i = 0; i < kExpectedPageCount; ++i)
VerifyDidPreviewPage(true, i);
VerifyPreviewPageCount(kExpectedPageCount);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest,
PrintPreviewForManyLinesOfTextWithTextSelection) {
LoadHTML(kHTMLWithManyLinesOfText);
GetMainFrame()->ExecuteCommand("SelectAll");
print_settings().Set(kSettingShouldPrintSelectionOnly, true);
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest,
PrintPreviewForManyLinesOfTextWithTextSelectionAndScaling) {
LoadHTML(kHTMLWithManyLinesOfText);
GetMainFrame()->ExecuteCommand("SelectAll");
print_settings().Set(kSettingShouldPrintSelectionOnly, true);
print_settings().Set(kSettingScaleFactor, 200);
OnPrintPreview();
constexpr int kExpectedPageCount = 3;
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
for (int i = 0; i < kExpectedPageCount; ++i)
VerifyDidPreviewPage(true, i);
VerifyPreviewPageCount(kExpectedPageCount);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
// Tests that cancelling print preview works.
TEST_F(PrintRenderFrameHelperPreviewTest, PrintPreviewCancel) {
LoadHTML(kLongPageHTML);
const uint32_t kCancelPage = 3;
preview_ui()->set_print_preview_cancel_page_number(kCancelPage);
OnPrintPreview();
EXPECT_EQ(kCancelPage, preview_ui()->print_preview_pages_remaining());
VerifyPrintPreviewCancelled(true);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(false);
VerifyPagesPrinted(false);
OnClosePrintPreviewDialog();
}
// Tests that when default printer has invalid printer settings, print preview
// receives error message.
TEST_F(PrintRenderFrameHelperPreviewTest,
OnPrintPreviewUsingInvalidPrinterSettings) {
LoadHTML(kPrintPreviewHTML);
// Set mock printer to provide invalid settings.
// A missing color entry is invalid.
print_settings().Remove(kSettingColor);
OnPrintPreview();
// We should have received invalid printer settings from |printer_|.
VerifyPrintPreviewInvalidPrinterSettings(true);
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
// It should receive the invalid printer settings message only.
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(false);
OnClosePrintPreviewDialog();
}
// Tests that when the selected printer has an invalid media size, print preview
// receives error message.
TEST_F(PrintRenderFrameHelperPreviewTest, OnPrintPreviewUsingInvalidMediaSize) {
LoadHTML(kPrintPreviewHTML);
print_settings().Set(kSettingMediaSize, base::Value::Dict());
OnPrintPreview();
VerifyPrintPreviewInvalidPrinterSettings(true);
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
// It should receive the invalid printer settings message only.
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(false);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest, BasicBeforePrintAfterPrint) {
LoadHTML(kBeforeAfterPrintHtml);
ExpectNoBeforeNoAfterPrintEvent();
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyDefaultPageLayout(548, 692, 72, 28, 36, 28, false, false);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
ExpectOneBeforeNoAfterPrintEvent();
OnClosePrintPreviewDialog();
ExpectOneBeforeOneAfterPrintEvent();
}
// Regression test for https://crbug.com/912966
TEST_F(PrintRenderFrameHelperPreviewTest, WindowPrintBeforePrintAfterPrint) {
LoadHTML(kBeforeAfterPrintHtml);
gfx::Size new_size(200, 100);
Resize(new_size, false);
ExpectNoBeforeNoAfterPrintEvent();
gfx::Rect bounds = GetElementBounds("print");
ClickMouseButton(bounds);
VerifyPreviewRequest(true);
ExpectOneBeforeNoAfterPrintEvent();
OnClosePrintPreviewDialog();
ExpectOneBeforeOneAfterPrintEvent();
}
TEST_F(PrintRenderFrameHelperPreviewTest, OnlySomePagesWithCustomSize) {
// A specified page size will set both size and orientation (not just for any
// given fixed size, but also for well-known page sizes, such as B5). In this
// test, however, only the first page will match the @page rule, whereas the
// size and orientation of the second page may be freely controlled by UI
// settings.
LoadHTML(R"HTML(
<style>
@page custom { size:B5; }
</style>
<div style="page:custom;">Custom page</div>
Default page
)HTML");
print_settings().Set(kSettingPrinterType,
static_cast<int>(mojom::PrinterType::kLocal));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
EXPECT_FALSE(preview_ui()->all_pages_have_custom_size());
EXPECT_FALSE(preview_ui()->all_pages_have_custom_orientation());
VerifyPreviewPageCount(2);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest, SingleNamedPageWithCustomSize) {
// There's only one page, and that page is named, and it matches the @page
// rule, which specifies a page size. There are no pages that can be
// controlled by UI options, so the options should be hidden.
LoadHTML(R"HTML(
<style>
@page custom { size:B5; }
</style>
<div style="page:custom;">Custom page</div>
)HTML");
print_settings().Set(kSettingPrinterType,
static_cast<int>(mojom::PrinterType::kLocal));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
EXPECT_TRUE(preview_ui()->all_pages_have_custom_size());
EXPECT_TRUE(preview_ui()->all_pages_have_custom_orientation());
VerifyPreviewPageCount(1);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest, OnlySomePagesWithCustomOrientation) {
LoadHTML(R"HTML(
<style>
@page custom { size:portrait; }
</style>
<div style="page:custom;">Custom page</div>
Default page
)HTML");
print_settings().Set(kSettingPrinterType,
static_cast<int>(mojom::PrinterType::kLocal));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
EXPECT_FALSE(preview_ui()->all_pages_have_custom_size());
EXPECT_FALSE(preview_ui()->all_pages_have_custom_orientation());
VerifyPreviewPageCount(2);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest,
SingleNamedPageWithCustomOrientation) {
LoadHTML(R"HTML(
<style>
@page custom { size:portrait; }
</style>
<div style="page:custom;">Custom page</div>
)HTML");
print_settings().Set(kSettingPrinterType,
static_cast<int>(mojom::PrinterType::kLocal));
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
EXPECT_FALSE(preview_ui()->all_pages_have_custom_size());
EXPECT_TRUE(preview_ui()->all_pages_have_custom_orientation());
VerifyPreviewPageCount(1);
OnClosePrintPreviewDialog();
}
TEST_F(PrintRenderFrameHelperPreviewTest, PrintForSystemDialog) {
LoadHTML(kHelloWorldHTML);
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
VerifyPreviewPageCount(1);
// No need to call OnClosePrintPreviewDialog(), as OnPrintForSystemDialog()
// takes care of the Print Preview to system print dialog transition.
OnPrintForSystemDialog();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(true);
}
class PrintRenderFrameHelperTaggedPreviewTest
: public PrintRenderFrameHelperPreviewTest,
public testing::WithParamInterface<bool> {
public:
PrintRenderFrameHelperTaggedPreviewTest() = default;
PrintRenderFrameHelperTaggedPreviewTest(
const PrintRenderFrameHelperTaggedPreviewTest&) = delete;
PrintRenderFrameHelperTaggedPreviewTest& operator=(
const PrintRenderFrameHelperTaggedPreviewTest&) = delete;
~PrintRenderFrameHelperTaggedPreviewTest() override = default;
// content::RenderViewTest:
content::ContentRendererClient* CreateContentRendererClient() override {
return new PrintTestContentRendererClient(GenerateTaggedPDFs());
}
bool GenerateTaggedPDFs() const { return GetParam(); }
bool ExpectsSetAccessibilityTreeCalls() const { return GenerateTaggedPDFs(); }
};
TEST_P(PrintRenderFrameHelperTaggedPreviewTest,
PrintPreviewRerenderGeneratesTaggedPDF) {
LoadHTML(kHelloWorldHTML);
OnPrintPreview();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyDefaultPageLayout(548, 692, 72, 28, 36, 28, false, false);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
int expected_accessibility_tree_set_count =
ExpectsSetAccessibilityTreeCalls() ? 1 : 0;
EXPECT_EQ(expected_accessibility_tree_set_count,
print_manager()->accessibility_tree_set_count());
print_settings().Set(kSettingScaleFactor, 200);
OnPrintPreviewRerender();
EXPECT_EQ(0u, preview_ui()->print_preview_pages_remaining());
VerifyDidPreviewPage(true, 0);
VerifyPreviewPageCount(1);
VerifyDefaultPageLayout(548, 692, 72, 28, 36, 28, false, false);
VerifyPrintPreviewCancelled(false);
VerifyPrintPreviewFailed(false);
VerifyPrintPreviewGenerated(true);
VerifyPagesPrinted(false);
expected_accessibility_tree_set_count =
ExpectsSetAccessibilityTreeCalls() ? 2 : 0;
EXPECT_EQ(expected_accessibility_tree_set_count,
print_manager()->accessibility_tree_set_count());
}
INSTANTIATE_TEST_SUITE_P(All,
PrintRenderFrameHelperTaggedPreviewTest,
testing::Bool());
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
} // namespace printing