| // 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 "components/printing/renderer/print_render_frame_helper.h" |
| |
| #include <stddef.h> |
| |
| #include <memory> |
| #include <tuple> |
| #include <utility> |
| |
| #include "base/command_line.h" |
| #include "base/run_loop.h" |
| #include "base/stl_util.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_messages.h" |
| #include "components/printing/test/mock_printer.h" |
| #include "components/printing/test/print_mock_render_thread.h" |
| #include "components/printing/test/print_test_content_renderer_client.h" |
| #include "content/public/renderer/render_frame.h" |
| #include "content/public/renderer/render_view.h" |
| #include "content/public/test/render_view_test.h" |
| #include "ipc/ipc_listener.h" |
| #include "printing/buildflags/buildflags.h" |
| #include "printing/mojom/print.mojom.h" |
| #include "printing/page_range.h" |
| #include "printing/print_job_constants.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 defined(OS_WIN) || defined(OS_APPLE) |
| #include "base/files/file_util.h" |
| #include "printing/image.h" |
| |
| using blink::WebFrame; |
| using blink::WebLocalFrame; |
| using blink::WebString; |
| #endif |
| |
| 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.onbeforeprint = () => { ++beforePrintCount; };" |
| "window.onafterprint = () => { ++afterPrintCount; };" |
| "</script>" |
| "<button id=\"print\" onclick=\"window.print();\">Hello 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\" onclick=\"window.print();\">Hello 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>"; |
| |
| void CreatePrintSettingsDictionary(base::DictionaryValue* dict) { |
| dict->SetBoolean(kSettingLandscape, false); |
| dict->SetBoolean(kSettingCollate, false); |
| dict->SetInteger(kSettingColor, static_cast<int>(mojom::ColorModel::kGray)); |
| dict->SetInteger(kSettingPrinterType, static_cast<int>(PrinterType::kPdf)); |
| dict->SetInteger(kSettingDuplexMode, |
| static_cast<int>(mojom::DuplexMode::kSimplex)); |
| dict->SetInteger(kSettingCopies, 1); |
| dict->SetString(kSettingDeviceName, "dummy"); |
| dict->SetInteger(kPreviewUIID, 4); |
| dict->SetInteger(kPreviewRequestID, 12345); |
| dict->SetBoolean(kIsFirstRequest, true); |
| dict->SetInteger(kSettingMarginsType, |
| static_cast<int>(mojom::MarginType::kDefaultMargins)); |
| dict->SetBoolean(kSettingPreviewModifiable, true); |
| dict->SetBoolean(kSettingPreviewIsFromArc, false); |
| dict->SetBoolean(kSettingPreviewIsPdf, false); |
| dict->SetBoolean(kSettingHeaderFooterEnabled, false); |
| dict->SetBoolean(kSettingShouldPrintBackgrounds, false); |
| dict->SetBoolean(kSettingShouldPrintSelectionOnly, false); |
| } |
| #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| #endif // !BUILDFLAG(IS_CHROMEOS_ASH) |
| |
| #if BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| // TODO(https://crbug.com/1008939): Remove DidPreviewPageListener once all IPC |
| // messages are moved to mojo. |
| class DidPreviewPageListener : public IPC::Listener { |
| public: |
| explicit DidPreviewPageListener(base::RunLoop* run_loop) |
| : run_loop_(run_loop) {} |
| DidPreviewPageListener(const DidPreviewPageListener&) = delete; |
| DidPreviewPageListener& operator=(const DidPreviewPageListener&) = delete; |
| |
| bool OnMessageReceived(const IPC::Message& message) override { |
| if (message.type() == PrintHostMsg_MetafileReadyForPrinting::ID) |
| run_loop_->Quit(); |
| return false; |
| } |
| |
| private: |
| base::RunLoop* const run_loop_; |
| }; |
| |
| class FakePrintPreviewUI : public mojom::PrintPreviewUI { |
| public: |
| FakePrintPreviewUI() = default; |
| ~FakePrintPreviewUI() override = default; |
| |
| mojo::PendingAssociatedRemote<mojom::PrintPreviewUI> BindReceiver() { |
| return receiver_.BindNewEndpointAndPassDedicatedRemote(); |
| } |
| void SetQuitClosure(base::OnceClosure quit_closure) { |
| quit_closure_ = std::move(quit_closure); |
| } |
| |
| bool preview_failed() const { return preview_failed_; } |
| bool preview_cancelled() const { return preview_cancelled_; } |
| bool invalid_printer_setting() const { return invalid_printer_setting_; } |
| |
| // mojom::PrintPreviewUI: |
| void SetOptionsFromDocument(const mojom::OptionsFromDocumentParamsPtr params, |
| int32_t request_id) override {} |
| void PrintPreviewFailed(int32_t document_cookie, |
| int32_t request_id) override { |
| preview_failed_ = true; |
| RunQuitClosure(); |
| } |
| void PrintPreviewCancelled(int32_t document_cookie, |
| int32_t request_id) override { |
| preview_cancelled_ = true; |
| RunQuitClosure(); |
| } |
| void PrinterSettingsInvalid(int32_t document_cookie, |
| int32_t request_id) override { |
| invalid_printer_setting_ = true; |
| RunQuitClosure(); |
| } |
| |
| private: |
| void RunQuitClosure() { |
| if (!quit_closure_) |
| return; |
| std::move(quit_closure_).Run(); |
| } |
| |
| bool preview_failed_ = false; |
| bool preview_cancelled_ = false; |
| bool invalid_printer_setting_ = false; |
| base::OnceClosure quit_closure_; |
| |
| mojo::AssociatedReceiver<mojom::PrintPreviewUI> receiver_{this}; |
| }; |
| #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| |
| class TestPrintManagerHost |
| : public mojom::PrintManagerHostInterceptorForTesting { |
| public: |
| TestPrintManagerHost(content::RenderFrame* frame, |
| PrintMockRenderThread* thread) |
| : printer_(thread->GetPrinter()) |
| #if BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| , |
| thread_(thread) |
| #endif |
| { |
| 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 DidGetDocumentCookie(int32_t cookie) override {} |
| void DidPrintDocument(mojom::DidPrintDocumentParamsPtr params, |
| DidPrintDocumentCallback callback) override { |
| base::RunLoop().RunUntilIdle(); |
| printer_->PrintPage(std::move(params)); |
| std::move(callback).Run(true); |
| is_printed_ = true; |
| } |
| void GetDefaultPrintSettings( |
| GetDefaultPrintSettingsCallback callback) override { |
| printing::mojom::PrintParamsPtr params = |
| printer_->GetDefaultPrintSettings(); |
| std::move(callback).Run(std::move(params)); |
| } |
| void UpdatePrintSettings(int32_t cookie, |
| base::Value job_settings, |
| UpdatePrintSettingsCallback callback) override { |
| auto params = printing::mojom::PrintPagesParams::New(); |
| params->params = printing::mojom::PrintParams::New(); |
| bool canceled = false; |
| |
| // Check and make sure the required settings are all there. |
| // We don't actually care about the values. |
| base::Optional<int> margins_type = |
| job_settings.FindIntKey(printing::kSettingMarginsType); |
| if (!margins_type.has_value() || |
| !job_settings.FindBoolKey(printing::kSettingLandscape) || |
| !job_settings.FindBoolKey(printing::kSettingCollate) || |
| !job_settings.FindIntKey(printing::kSettingColor) || |
| !job_settings.FindIntKey(printing::kSettingPrinterType) || |
| !job_settings.FindBoolKey(printing::kIsFirstRequest) || |
| !job_settings.FindStringKey(printing::kSettingDeviceName) || |
| !job_settings.FindIntKey(printing::kSettingDuplexMode) || |
| !job_settings.FindIntKey(printing::kSettingCopies) || |
| !job_settings.FindIntKey(printing::kPreviewUIID) || |
| !job_settings.FindIntKey(printing::kPreviewRequestID)) { |
| std::move(callback).Run(std::move(params), canceled); |
| return; |
| } |
| |
| // Just return the default settings. |
| const base::Value* page_range = |
| job_settings.FindListKey(printing::kSettingPageRange); |
| printing::PageRanges new_ranges; |
| if (page_range) { |
| for (const base::Value& dict : page_range->GetList()) { |
| if (!dict.is_dict()) |
| continue; |
| |
| base::Optional<int> range_from = |
| dict.FindIntKey(printing::kSettingPageRangeFrom); |
| base::Optional<int> range_to = |
| dict.FindIntKey(printing::kSettingPageRangeTo); |
| if (!range_from || !range_to) |
| continue; |
| |
| // Page numbers are 1-based in the dictionary. |
| // Page numbers are 0-based for the printing context. |
| printing::PageRange range; |
| range.from = range_from.value() - 1; |
| range.to = range_to.value() - 1; |
| new_ranges.push_back(range); |
| } |
| } |
| |
| // Get media size |
| const base::Value* media_size_value = |
| job_settings.FindDictKey(printing::kSettingMediaSize); |
| gfx::Size page_size; |
| if (media_size_value) { |
| base::Optional<int> width_microns = |
| media_size_value->FindIntKey(printing::kSettingMediaSizeWidthMicrons); |
| base::Optional<int> height_microns = media_size_value->FindIntKey( |
| printing::kSettingMediaSizeHeightMicrons); |
| |
| if (width_microns && height_microns) { |
| float device_microns_per_unit = |
| static_cast<float>(printing::kMicronsPerInch) / |
| printing::kDefaultPdfDpi; |
| page_size = gfx::Size(width_microns.value() / device_microns_per_unit, |
| height_microns.value() / device_microns_per_unit); |
| } |
| } |
| |
| // Get scaling |
| base::Optional<int> setting_scale_factor = |
| job_settings.FindIntKey(printing::kSettingScaleFactor); |
| int scale_factor = setting_scale_factor.value_or(100); |
| |
| std::vector<uint32_t> pages(printing::PageRange::GetPages(new_ranges)); |
| printer_->UpdateSettings(cookie, params.get(), pages, margins_type.value(), |
| page_size, scale_factor); |
| base::Optional<bool> selection_only = |
| job_settings.FindBoolKey(printing::kSettingShouldPrintSelectionOnly); |
| base::Optional<bool> should_print_backgrounds = |
| job_settings.FindBoolKey(printing::kSettingShouldPrintBackgrounds); |
| params->params->selection_only = selection_only.value(); |
| params->params->should_print_backgrounds = should_print_backgrounds.value(); |
| std::move(callback).Run(std::move(params), canceled); |
| } |
| void DidShowPrintDialog() override {} |
| void ScriptedPrint(printing::mojom::ScriptedPrintParamsPtr params, |
| ScriptedPrintCallback callback) override { |
| auto settings = printing::mojom::PrintPagesParams::New(); |
| settings->params = printing::mojom::PrintParams::New(); |
| if (print_dialog_user_response_) { |
| printer_->ScriptedPrint(params->cookie, params->expected_pages_count, |
| params->has_selection, settings.get()); |
| } |
| std::move(callback).Run(std::move(settings)); |
| } |
| #if BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| 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 { |
| std::move(callback).Run(thread_->ShouldCancelRequest()); |
| } |
| #endif |
| |
| 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(); |
| } |
| |
| // 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; |
| } |
| |
| 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; |
| MockPrinter* printer_; |
| #if BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| PrintMockRenderThread* thread_; |
| #endif |
| base::OnceClosure quit_closure_; |
| // True to simulate user clicking print. False to cancel. |
| bool print_dialog_user_response_ = true; |
| 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(); |
| } |
| |
| void SetUp() override { |
| render_thread_ = std::make_unique<PrintMockRenderThread>(); |
| print_render_thread_ = |
| static_cast<PrintMockRenderThread*>(render_thread_.get()); |
| |
| content::RenderViewTest::SetUp(); |
| 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, print_render_thread_); |
| 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(); |
| } |
| |
| #if BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| void BindToFakePrintPreviewUI() { |
| PrintRenderFrameHelper* frame_helper = GetPrintRenderFrameHelper(); |
| frame_helper->SetPrintPreviewUI(preview_ui_.BindReceiver()); |
| } |
| |
| void WaitMojoMessages(base::RunLoop* run_loop) { |
| preview_ui()->SetQuitClosure(run_loop->QuitClosure()); |
| } |
| |
| // 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) { |
| const IPC::Message* preview_started_message = |
| render_thread_->sink().GetUniqueMessageMatching( |
| PrintHostMsg_DidStartPreview::ID); |
| ASSERT_TRUE(preview_started_message); |
| PrintHostMsg_DidStartPreview::Param param; |
| PrintHostMsg_DidStartPreview::Read(preview_started_message, ¶m); |
| EXPECT_EQ(expected_count, std::get<0>(param).page_count); |
| } |
| #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| |
| // 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(); |
| } |
| |
| #if BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| void VerifyPreviewRequest(bool expect_request) { |
| EXPECT_EQ(expect_request, print_manager()->IsSetupScriptedPrintPreview()); |
| } |
| |
| void OnPrintPreview(const base::DictionaryValue& dict) { |
| PrintRenderFrameHelper* print_render_frame_helper = |
| GetPrintRenderFrameHelper(); |
| print_render_frame_helper->InitiatePrintPreview( |
| mojo::NullAssociatedRemote(), false); |
| base::RunLoop run_loop; |
| DidPreviewPageListener filter(&run_loop); |
| render_thread_->sink().AddFilter(&filter); |
| print_render_frame_helper->PrintPreview(dict.Clone()); |
| WaitMojoMessages(&run_loop); |
| run_loop.Run(); |
| render_thread_->sink().RemoveFilter(&filter); |
| } |
| |
| void OnClosePrintPreviewDialog() { |
| GetPrintRenderFrameHelper()->OnPrintPreviewDialogClosed(); |
| } |
| #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| |
| 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( |
| base::ASCIIToUTF16("beforePrintCount"), &result)); |
| EXPECT_EQ(0, result) << "beforeprint event should not be dispatched."; |
| ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue( |
| base::ASCIIToUTF16("afterPrintCount"), &result)); |
| EXPECT_EQ(0, result) << "afterprint event should not be dispatched."; |
| } |
| |
| void ExpectOneBeforeNoAfterPrintEvent() { |
| int result; |
| ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue( |
| base::ASCIIToUTF16("beforePrintCount"), &result)); |
| EXPECT_EQ(1, result) << "beforeprint event should be dispatched once."; |
| ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue( |
| base::ASCIIToUTF16("afterPrintCount"), &result)); |
| EXPECT_EQ(0, result) << "afterprint event should not be dispatched."; |
| } |
| |
| void ExpectOneBeforeOneAfterPrintEvent() { |
| int result; |
| ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue( |
| base::ASCIIToUTF16("beforePrintCount"), &result)); |
| EXPECT_EQ(1, result) << "beforeprint event should be dispatched once."; |
| ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue( |
| base::ASCIIToUTF16("afterPrintCount"), &result)); |
| EXPECT_EQ(1, result) << "afterprint event should be dispatched once."; |
| } |
| |
| PrintMockRenderThread* print_render_thread() { return print_render_thread_; } |
| 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(); |
| } |
| #if BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| FakePrintPreviewUI* preview_ui() { return &preview_ui_; } |
| #endif |
| |
| private: |
| #if BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| FakePrintPreviewUI preview_ui_; |
| #endif |
| // Naked pointer as ownership is with |
| // |content::RenderViewTest::render_thread_|. |
| PrintMockRenderThread* print_render_thread_ = nullptr; |
| std::map<content::RenderFrame*, std::unique_ptr<TestPrintManagerHost>> |
| frame_to_print_manager_map_; |
| }; |
| |
| // RenderViewTest-based tests crash on Android |
| // http://crbug.com/187500 |
| #if defined(OS_ANDROID) |
| #define MAYBE_PrintRenderFrameHelperTest DISABLED_PrintRenderFrameHelperTest |
| #else |
| #define MAYBE_PrintRenderFrameHelperTest PrintRenderFrameHelperTest |
| #endif // defined(OS_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(); |
| print_render_thread()->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. |
| print_render_thread()->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.onbeforeprint = () => { 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.onafterprint = () => { 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); |
| } |
| |
| #if defined(OS_APPLE) |
| // TODO(estade): I don't think this test is worth porting to Linux. We will have |
| // to rip out and replace most of the IPC code if we ever plan to improve |
| // printing, and the comment below by sverrir suggests that it doesn't do much |
| // for us anyway. |
| 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>"; |
| |
| 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. |
| auto* web_view = view_->GetWebView(); |
| 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* printer(print_render_thread()->printer()); |
| ASSERT_EQ(1, printer->GetPrintedPages()); |
| const Image& image1(printer->GetPrintedPage(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 // defined(OS_APPLE) |
| |
| // Tests if we can print a page and verify its results. |
| // This test prints HTML pages into a pseudo printer and check their outputs, |
| // i.e. a simplified version of the PrintingLayoutTextTest UI test. |
| namespace { |
| // Test cases used in this test. |
| struct TestPageData { |
| const char* page; |
| size_t printed_pages; |
| int width; |
| int height; |
| const char* checksum; |
| const wchar_t* file; |
| }; |
| |
| #if defined(OS_APPLE) |
| const TestPageData kTestPages[] = { |
| { |
| "<html>" |
| "<head>" |
| "<meta" |
| " http-equiv=\"Content-Type\"" |
| " content=\"text/html; charset=utf-8\"/>" |
| "<title>Test 1</title>" |
| "</head>" |
| "<body style=\"background-color: white;\">" |
| "<p style=\"font-family: arial;\">Hello World!</p>" |
| "</body>", |
| 1, |
| // Mac printing code compensates for the WebKit scale factor while |
| // generating the metafile, so we expect smaller pages. (On non-Mac |
| // platforms, this would be 675x900). |
| 600, 780, nullptr, nullptr, |
| }, |
| }; |
| #endif // defined(OS_APPLE) |
| } // namespace |
| |
| // TODO(estade): need to port MockPrinter to get this on Linux. This involves |
| // hooking up Cairo to read a pdf stream, or accessing the cairo surface in the |
| // metafile directly. |
| // Same for printing via PDF on Windows. |
| #if defined(OS_APPLE) |
| TEST_F(MAYBE_PrintRenderFrameHelperTest, PrintLayoutTest) { |
| bool baseline = false; |
| |
| EXPECT_TRUE(print_render_thread()->printer()); |
| for (size_t i = 0; i < base::size(kTestPages); ++i) { |
| // Load an HTML page and print it. |
| LoadHTML(kTestPages[i].page); |
| OnPrintPages(); |
| VerifyPagesPrinted(true); |
| |
| // MockRenderThread::Send() just calls MockRenderThread::OnReceived(). |
| // So, all IPC messages sent in the above RenderView::OnPrintPages() call |
| // has been handled by the MockPrinter object, i.e. this printing job |
| // has been already finished. |
| // So, we can start checking the output pages of this printing job. |
| // Retrieve the number of pages actually printed. |
| size_t pages = print_render_thread()->printer()->GetPrintedPages(); |
| EXPECT_EQ(kTestPages[i].printed_pages, pages); |
| |
| // Retrieve the width and height of the output page. |
| int width = print_render_thread()->printer()->GetWidth(0); |
| int height = print_render_thread()->printer()->GetHeight(0); |
| |
| // Check with margin for error. This has been failing with a one pixel |
| // offset on our buildbot. |
| const int kErrorMargin = 5; // 5% |
| EXPECT_GT(kTestPages[i].width * (100 + kErrorMargin) / 100, width); |
| EXPECT_LT(kTestPages[i].width * (100 - kErrorMargin) / 100, width); |
| EXPECT_GT(kTestPages[i].height * (100 + kErrorMargin) / 100, height); |
| EXPECT_LT(kTestPages[i].height * (100 - kErrorMargin) / 100, height); |
| |
| // Retrieve the checksum of the bitmap data from the pseudo printer and |
| // compare it with the expected result. |
| std::string bitmap_actual; |
| EXPECT_TRUE( |
| print_render_thread()->printer()->GetBitmapChecksum(0, &bitmap_actual)); |
| if (kTestPages[i].checksum) |
| EXPECT_EQ(kTestPages[i].checksum, bitmap_actual); |
| |
| if (baseline) { |
| // Save the source data and the bitmap data into temporary files to |
| // create base-line results. |
| base::FilePath source_path; |
| base::CreateTemporaryFile(&source_path); |
| print_render_thread()->printer()->SaveSource(0, source_path); |
| |
| base::FilePath bitmap_path; |
| base::CreateTemporaryFile(&bitmap_path); |
| print_render_thread()->printer()->SaveBitmap(0, bitmap_path); |
| } |
| } |
| } |
| #endif // defined(OS_APPLE) |
| |
| // These print preview tests do not work on Chrome OS yet. |
| #if !BUILDFLAG(IS_CHROMEOS_ASH) |
| |
| // RenderViewTest-based tests crash on Android |
| // http://crbug.com/187500 |
| #if defined(OS_ANDROID) |
| #define MAYBE_PrintRenderFrameHelperPreviewTest \ |
| DISABLED_PrintRenderFrameHelperPreviewTest |
| #else |
| #define MAYBE_PrintRenderFrameHelperPreviewTest \ |
| PrintRenderFrameHelperPreviewTest |
| #endif // defined(OS_ANDROID) |
| |
| #if BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| class MAYBE_PrintRenderFrameHelperPreviewTest |
| : public PrintRenderFrameHelperTestBase { |
| public: |
| MAYBE_PrintRenderFrameHelperPreviewTest() = default; |
| MAYBE_PrintRenderFrameHelperPreviewTest( |
| const MAYBE_PrintRenderFrameHelperPreviewTest&) = delete; |
| MAYBE_PrintRenderFrameHelperPreviewTest& operator=( |
| const MAYBE_PrintRenderFrameHelperPreviewTest&) = delete; |
| ~MAYBE_PrintRenderFrameHelperPreviewTest() override = default; |
| |
| void SetUp() override { |
| PrintRenderFrameHelperTestBase::SetUp(); |
| BindToFakePrintPreviewUI(); |
| } |
| |
| protected: |
| void VerifyPrintPreviewCancelled(bool expect_cancel) { |
| EXPECT_EQ(expect_cancel, preview_ui()->preview_cancelled()); |
| } |
| |
| void VerifyPrintPreviewFailed(bool expect_fail) { |
| EXPECT_EQ(expect_fail, preview_ui()->preview_failed()); |
| } |
| |
| void VerifyPrintPreviewGenerated(bool expect_generated) { |
| const IPC::Message* preview_msg = |
| render_thread_->sink().GetUniqueMessageMatching( |
| PrintHostMsg_MetafileReadyForPrinting::ID); |
| bool got_preview_msg = !!preview_msg; |
| ASSERT_EQ(expect_generated, got_preview_msg); |
| if (got_preview_msg) { |
| PrintHostMsg_MetafileReadyForPrinting::Param preview_param; |
| PrintHostMsg_MetafileReadyForPrinting::Read(preview_msg, &preview_param); |
| const auto& param = std::get<0>(preview_param); |
| EXPECT_NE(0, param.document_cookie); |
| EXPECT_NE(0U, param.expected_pages_count); |
| EXPECT_NE(0U, param.content->metafile_data_region.GetSize()); |
| } |
| } |
| |
| void VerifyPrintPreviewInvalidPrinterSettings(bool expect_invalid_settings) { |
| EXPECT_EQ(expect_invalid_settings, preview_ui()->invalid_printer_setting()); |
| } |
| |
| // |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 : print_render_thread()->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_page_has_print_css) { |
| const IPC::Message* default_page_layout_msg = |
| render_thread_->sink().GetUniqueMessageMatching( |
| PrintHostMsg_DidGetDefaultPageLayout::ID); |
| bool did_get_default_page_layout_msg = !!default_page_layout_msg; |
| EXPECT_TRUE(did_get_default_page_layout_msg); |
| if (!did_get_default_page_layout_msg) |
| return; |
| |
| PrintHostMsg_DidGetDefaultPageLayout::Param param; |
| PrintHostMsg_DidGetDefaultPageLayout::Read(default_page_layout_msg, ¶m); |
| EXPECT_EQ(expected_content_width, std::get<0>(param).content_width); |
| EXPECT_EQ(expected_content_height, std::get<0>(param).content_height); |
| EXPECT_EQ(expected_margin_top, std::get<0>(param).margin_top); |
| EXPECT_EQ(expected_margin_right, std::get<0>(param).margin_right); |
| EXPECT_EQ(expected_margin_left, std::get<0>(param).margin_left); |
| EXPECT_EQ(expected_margin_bottom, std::get<0>(param).margin_bottom); |
| EXPECT_EQ(expected_page_has_print_css, std::get<2>(param)); |
| } |
| }; |
| |
| TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, BlockScriptInitiatedPrinting) { |
| LoadHTML(kHelloWorldHTML); |
| PrintRenderFrameHelper* print_render_frame_helper = |
| GetPrintRenderFrameHelper(); |
| print_render_frame_helper->SetPrintingEnabled(false); |
| PrintWithJavaScript(); |
| VerifyPreviewRequest(false); |
| |
| print_render_frame_helper->SetPrintingEnabled(true); |
| PrintWithJavaScript(); |
| VerifyPreviewRequest(true); |
| |
| OnClosePrintPreviewDialog(); |
| } |
| |
| TEST_F(MAYBE_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(MAYBE_PrintRenderFrameHelperPreviewTest, OnPrintPreview) { |
| LoadHTML(kHelloWorldHTML); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->print_preview_pages_remaining()); |
| VerifyDidPreviewPage(true, 0); |
| VerifyPreviewPageCount(1); |
| VerifyDefaultPageLayout(540, 720, 36, 36, 36, 36, false); |
| VerifyPrintPreviewCancelled(false); |
| VerifyPrintPreviewFailed(false); |
| VerifyPrintPreviewGenerated(true); |
| VerifyPagesPrinted(false); |
| |
| OnClosePrintPreviewDialog(); |
| } |
| |
| TEST_F(MAYBE_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); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| dict.SetInteger(kSettingPrinterType, static_cast<int>(PrinterType::kLocal)); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->print_preview_pages_remaining()); |
| VerifyDefaultPageLayout(519, 432, 216, 144, 21, 72, 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(MAYBE_PrintRenderFrameHelperPreviewTest, |
| NonDefaultMarginsSelectedIgnorePrintCss) { |
| LoadHTML(kHTMLWithPageSizeCss); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| dict.SetInteger(kSettingPrinterType, static_cast<int>(PrinterType::kLocal)); |
| dict.SetInteger(kSettingMarginsType, |
| static_cast<int>(mojom::MarginType::kNoMargins)); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->print_preview_pages_remaining()); |
| VerifyDefaultPageLayout(612, 792, 0, 0, 0, 0, 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(MAYBE_PrintRenderFrameHelperPreviewTest, |
| PrintToPDFSelectedHonorPrintCss) { |
| LoadHTML(kHTMLWithPageSizeCss); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| dict.SetInteger(kSettingMarginsType, |
| static_cast<int>(mojom::MarginType::kPrintableAreaMargins)); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->print_preview_pages_remaining()); |
| // Since PRINT_TO_PDF is selected, pdf page size is equal to print media page |
| // size. |
| VerifyDefaultPageLayout(252, 252, 18, 18, 18, 18, true); |
| VerifyDidPreviewPage(true, 0); |
| VerifyPreviewPageCount(1); |
| VerifyPrintPreviewCancelled(false); |
| VerifyPrintPreviewFailed(false); |
| VerifyPrintPreviewGenerated(true); |
| VerifyPagesPrinted(false); |
| |
| OnClosePrintPreviewDialog(); |
| } |
| |
| TEST_F(MAYBE_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); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| dict.SetInteger(kSettingPrinterType, static_cast<int>(PrinterType::kLocal)); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->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(MAYBE_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); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->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); |
| 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(MAYBE_PrintRenderFrameHelperPreviewTest, PrintPreviewCenterToFitPage) { |
| LoadHTML(kHTMLWithPageSizeCss); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| dict.SetInteger(kSettingPrinterType, static_cast<int>(PrinterType::kLocal)); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->print_preview_pages_remaining()); |
| VerifyDefaultPageLayout(216, 216, 288, 288, 198, 198, 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(MAYBE_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); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| dict.SetInteger(kSettingPrinterType, static_cast<int>(PrinterType::kLocal)); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->print_preview_pages_remaining()); |
| VerifyDefaultPageLayout(571, 652, 69, 71, 20, 21, 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(MAYBE_PrintRenderFrameHelperPreviewTest, |
| PrintPreviewHonorsOrientationCss) { |
| LoadHTML(kHTMLWithLandscapePageCss); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| dict.SetInteger(kSettingPrinterType, static_cast<int>(PrinterType::kLocal)); |
| dict.SetInteger(kSettingMarginsType, |
| static_cast<int>(mojom::MarginType::kNoMargins)); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->print_preview_pages_remaining()); |
| VerifyDefaultPageLayout(792, 612, 0, 0, 0, 0, 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(MAYBE_PrintRenderFrameHelperPreviewTest, |
| PrintToPDFSelectedHonorOrientationCss) { |
| LoadHTML(kHTMLWithLandscapePageCss); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| dict.SetInteger(kSettingMarginsType, |
| static_cast<int>(mojom::MarginType::kCustomMargins)); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->print_preview_pages_remaining()); |
| VerifyDefaultPageLayout(748, 568, 21, 23, 21, 23, true); |
| VerifyDidPreviewPage(true, 0); |
| VerifyPreviewPageCount(1); |
| VerifyPrintPreviewCancelled(false); |
| VerifyPrintPreviewFailed(false); |
| VerifyPrintPreviewGenerated(true); |
| VerifyPagesPrinted(false); |
| |
| OnClosePrintPreviewDialog(); |
| } |
| |
| TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, PrintPreviewForMultiplePages) { |
| LoadHTML(kMultipageHTML); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->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(MAYBE_PrintRenderFrameHelperPreviewTest, PrintPreviewForSelectedPages) { |
| LoadHTML(kMultipageHTML); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| |
| // 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 page_range(base::Value::Type::DICTIONARY); |
| page_range.SetKey(kSettingPageRangeFrom, base::Value(2)); |
| page_range.SetKey(kSettingPageRangeTo, base::Value(3)); |
| base::Value page_range_array(base::Value::Type::LIST); |
| page_range_array.Append(std::move(page_range)); |
| dict.SetKey(kSettingPageRange, std::move(page_range_array)); |
| |
| OnPrintPreview(dict); |
| |
| // 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, print_render_thread()->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 to verify that preview generated only for one page. |
| TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, PrintPreviewForSelectedText) { |
| LoadHTML(kMultipageHTML); |
| GetMainFrame()->SelectRange(blink::WebRange(1, 3), |
| blink::WebLocalFrame::kHideSelectionHandle, |
| blink::mojom::SelectionMenuBehavior::kHide); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| dict.SetBoolean(kSettingShouldPrintSelectionOnly, true); |
| |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->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(MAYBE_PrintRenderFrameHelperPreviewTest, PrintPreviewForSelectedText2) { |
| LoadHTML(kMultipageHTML); |
| GetMainFrame()->SelectRange(blink::WebRange(1, 8), |
| blink::WebLocalFrame::kHideSelectionHandle, |
| blink::mojom::SelectionMenuBehavior::kHide); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| dict.SetBoolean(kSettingShouldPrintSelectionOnly, true); |
| |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->print_preview_pages_remaining()); |
| VerifyDidPreviewPage(true, 0); |
| VerifyPreviewPageCount(2); |
| VerifyPrintPreviewCancelled(false); |
| VerifyPrintPreviewFailed(false); |
| VerifyPrintPreviewGenerated(true); |
| VerifyPagesPrinted(false); |
| |
| OnClosePrintPreviewDialog(); |
| } |
| |
| // Tests that cancelling print preview works. |
| TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, PrintPreviewCancel) { |
| LoadHTML(kLongPageHTML); |
| |
| const uint32_t kCancelPage = 3; |
| print_render_thread()->set_print_preview_cancel_page_number(kCancelPage); |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(kCancelPage, |
| print_render_thread()->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(MAYBE_PrintRenderFrameHelperPreviewTest, |
| OnPrintPreviewUsingInvalidPrinterSettings) { |
| LoadHTML(kPrintPreviewHTML); |
| |
| // Set mock printer to provide invalid settings. |
| print_render_thread()->printer()->UseInvalidSettings(); |
| |
| // Fill in some dummy values. |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| OnPrintPreview(dict); |
| |
| // We should have received invalid printer settings from |printer_|. |
| VerifyPrintPreviewInvalidPrinterSettings(true); |
| EXPECT_EQ(0u, print_render_thread()->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 invalid page settings, print preview |
| // receives error message. |
| TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, |
| OnPrintPreviewUsingInvalidPageSize) { |
| LoadHTML(kPrintPreviewHTML); |
| |
| print_render_thread()->printer()->UseInvalidPageSize(); |
| |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| OnPrintPreview(dict); |
| |
| VerifyPrintPreviewInvalidPrinterSettings(true); |
| EXPECT_EQ(0u, print_render_thread()->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 invalid content settings, print |
| // preview receives error message. |
| TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, |
| OnPrintPreviewUsingInvalidContentSize) { |
| LoadHTML(kPrintPreviewHTML); |
| |
| print_render_thread()->printer()->UseInvalidContentSize(); |
| |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| OnPrintPreview(dict); |
| |
| VerifyPrintPreviewInvalidPrinterSettings(true); |
| EXPECT_EQ(0u, print_render_thread()->print_preview_pages_remaining()); |
| |
| // It should receive the invalid printer settings message only. |
| VerifyPrintPreviewFailed(false); |
| VerifyPrintPreviewGenerated(false); |
| |
| OnClosePrintPreviewDialog(); |
| } |
| |
| TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, BasicBeforePrintAfterPrint) { |
| LoadHTML(kBeforeAfterPrintHtml); |
| ExpectNoBeforeNoAfterPrintEvent(); |
| |
| base::DictionaryValue dict; |
| CreatePrintSettingsDictionary(&dict); |
| OnPrintPreview(dict); |
| |
| EXPECT_EQ(0u, print_render_thread()->print_preview_pages_remaining()); |
| VerifyDidPreviewPage(true, 0); |
| VerifyPreviewPageCount(1); |
| VerifyDefaultPageLayout(540, 720, 36, 36, 36, 36, false); |
| VerifyPrintPreviewCancelled(false); |
| VerifyPrintPreviewFailed(false); |
| VerifyPrintPreviewGenerated(true); |
| VerifyPagesPrinted(false); |
| ExpectOneBeforeNoAfterPrintEvent(); |
| |
| OnClosePrintPreviewDialog(); |
| ExpectOneBeforeOneAfterPrintEvent(); |
| } |
| |
| // Regression test for https://crbug.com/912966 |
| TEST_F(MAYBE_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(); |
| } |
| |
| #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) |
| |
| #endif // !BUILDFLAG(IS_CHROMEOS_ASH) |
| |
| } // namespace printing |