Skip to content

Commit

Permalink
Relocate test PrintPreviewObserver into separate file
Browse files Browse the repository at this point in the history
Extract the PrintPreviewObserver class from print_browsertest.cc and
put it in its own file.  This is so that it can be shared by multiple
test files, in preparation of splitting the tests in
print_browsertest.cc into multiple files.

Rename the class to have a "Test" prefix, to clearly indicate that
this class is intended only for testing.

Bug: 1418833
Change-Id: I5075a1e3db0a1e0a2280ea405ff59cd6af1370bb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4326976
Reviewed-by: Andy Phan <andyphan@chromium.org>
Commit-Queue: Alan Screen <awscreen@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1115991}
  • Loading branch information
Alan Screen authored and Chromium LUCI CQ committed Mar 11, 2023
1 parent 19431b4 commit c000f43
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 110 deletions.
122 changes: 12 additions & 110 deletions chrome/browser/printing/print_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
#include "chrome/browser/printing/print_view_manager.h"
#include "chrome/browser/printing/print_view_manager_common.h"
#include "chrome/browser/printing/printer_query.h"
#include "chrome/browser/printing/test_print_preview_observer.h"
#include "chrome/browser/printing/test_print_view_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
Expand Down Expand Up @@ -316,104 +316,6 @@ class BrowserPrintingContextFactoryForTest
absl::optional<PrintSettings> document_print_settings_;
};

class PrintPreviewObserver : PrintPreviewUI::TestDelegate {
public:
explicit PrintPreviewObserver(bool wait_for_loaded)
: PrintPreviewObserver(wait_for_loaded, /*pages_per_sheet=*/1) {}

PrintPreviewObserver(bool wait_for_loaded, int pages_per_sheet)
: pages_per_sheet_(pages_per_sheet), wait_for_loaded_(wait_for_loaded) {
PrintPreviewUI::SetDelegateForTesting(this);
}

PrintPreviewObserver(const PrintPreviewObserver&) = delete;
PrintPreviewObserver& operator=(const PrintPreviewObserver&) = delete;

~PrintPreviewObserver() override {
PrintPreviewUI::SetDelegateForTesting(nullptr);
}

// Tests that use PrintPreviewObserver must call
// WaitUntilPreviewIsReady*() exactly once.
[[nodiscard]] content::WebContents*
WaitUntilPreviewIsReadyAndReturnPreviewDialog() {
if (rendered_page_count_ < expected_rendered_page_count_) {
base::RunLoop run_loop;
base::AutoReset<base::RunLoop*> auto_reset(&run_loop_, &run_loop);
run_loop.Run();

if (queue_.has_value()) {
std::string message;
EXPECT_TRUE(queue_->WaitForMessage(&message));
EXPECT_EQ("\"success\"", message);
}
}

// Grab and reset `preview_dialog_` to avoid potential dangling pointers.
content::WebContents* dialog = preview_dialog_;
preview_dialog_ = nullptr;
return dialog;
}

// Wrapper for WaitUntilPreviewIsReadyAndReturnPreviewDialog() provided for
// convenience for callers that do not need the returned result.
void WaitUntilPreviewIsReady() {
std::ignore = WaitUntilPreviewIsReadyAndReturnPreviewDialog();
}

uint32_t rendered_page_count() const { return rendered_page_count_; }

private:
// PrintPreviewUI::TestDelegate:
void DidGetPreviewPageCount(uint32_t page_count) override {
// `page_count` is the number of pages to be generated but doesn't take
// N-up into consideration. Since `DidRenderPreviewPage()` is called after
// any N-up processing is performed, determine the number of times that
// function is expected to be called.
expected_rendered_page_count_ =
(page_count + pages_per_sheet_ - 1) / pages_per_sheet_;
}

// PrintPreviewUI::TestDelegate:
void DidRenderPreviewPage(content::WebContents* preview_dialog) override {
++rendered_page_count_;
DVLOG(2) << "Rendered preview page " << rendered_page_count_
<< " of a total expected " << expected_rendered_page_count_;
CHECK_LE(rendered_page_count_, expected_rendered_page_count_);
if (rendered_page_count_ == expected_rendered_page_count_ && run_loop_) {
run_loop_->Quit();
preview_dialog_ = preview_dialog;

if (wait_for_loaded_) {
// Instantiate `queue_` to listen for messages in `preview_dialog_`.
queue_.emplace(preview_dialog_);
content::ExecuteScriptAsync(
preview_dialog_.get(),
"window.addEventListener('message', event => {"
" if (event.data.type === 'documentLoaded') {"
" domAutomationController.send(event.data.load_state);"
" }"
"});");
}
}
}

absl::optional<content::DOMMessageQueue> queue_;

// Rendered pages are provided after N-up processing, which will be different
// from the count provided to `DidGetPreviewPageCount()` when
// `pages_per_sheet_` is larger than one.
const int pages_per_sheet_;
uint32_t expected_rendered_page_count_ = 1;
uint32_t rendered_page_count_ = 0;

const bool wait_for_loaded_;
raw_ptr<content::WebContents> preview_dialog_ = nullptr;
// This field is not a raw_ptr<> because it was filtered by the rewriter for:
// #addr-of
RAW_PTR_EXCLUSION base::RunLoop* run_loop_ = nullptr;
};

class TestPrintRenderFrame
: public mojom::PrintRenderFrameInterceptorForTesting {
public:
Expand Down Expand Up @@ -912,8 +814,8 @@ class PrintBrowserTest : public InProcessBrowserTest {
}

void PrintAndWaitUntilPreviewIsReady(const PrintParams& params) {
PrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/false,
params.pages_per_sheet);
TestPrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/false,
params.pages_per_sheet);

StartPrint(browser()->tab_strip_model()->GetActiveWebContents(),
/*print_renderer=*/mojo::NullAssociatedRemote(),
Expand All @@ -930,8 +832,8 @@ class PrintBrowserTest : public InProcessBrowserTest {
}

void PrintAndWaitUntilPreviewIsReadyAndLoaded(const PrintParams& params) {
PrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/true,
params.pages_per_sheet);
TestPrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/true,
params.pages_per_sheet);

StartPrint(browser()->tab_strip_model()->GetActiveWebContents(),
/*print_renderer=*/mojo::NullAssociatedRemote(),
Expand Down Expand Up @@ -1139,7 +1041,7 @@ class PrintExtensionBrowserTest : public extensions::ExtensionBrowserTest {
~PrintExtensionBrowserTest() override = default;

void PrintAndWaitUntilPreviewIsReady() {
PrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/false);
TestPrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/false);

StartPrint(browser()->tab_strip_model()->GetActiveWebContents(),
/*print_renderer=*/mojo::NullAssociatedRemote(),
Expand Down Expand Up @@ -1656,7 +1558,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessPrintBrowserTest,
subframe_rph, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);

// Adds the observer to get the status for the preview.
PrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/false);
TestPrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/false);
StartPrint(browser()->tab_strip_model()->GetActiveWebContents(),
/*print_renderer=*/mojo::NullAssociatedRemote(),
/*print_preview_disabled=*/false, /*has_selection*/ false);
Expand Down Expand Up @@ -1984,7 +1886,7 @@ IN_PROC_BROWSER_TEST_F(PrintBrowserTest,
GURL url(embedded_test_server()->GetURL("/printing/multipage.html"));
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));

PrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/true);
TestPrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/true);
StartPrint(browser()->tab_strip_model()->GetActiveWebContents(),
/*print_renderer=*/mojo::NullAssociatedRemote(),
/*print_preview_disabled=*/false, /*has_selection=*/false);
Expand Down Expand Up @@ -2033,7 +1935,7 @@ IN_PROC_BROWSER_TEST_F(PrintBrowserTest, WindowDotPrint) {
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();

PrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/false);
TestPrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/false);
content::ExecuteScriptAsync(web_contents->GetPrimaryMainFrame(),
"window.print();");
print_preview_observer.WaitUntilPreviewIsReady();
Expand All @@ -2056,7 +1958,7 @@ IN_PROC_BROWSER_TEST_F(PrintBrowserTest,
PrintPreviewDoneObserver done_observer(rfh, GetPrintRenderFrame(rfh).get());

// Load Print Preview and make sure the beforeprint event fired.
PrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/false);
TestPrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/false);
content::ExecuteScriptAsync(rfh, "window.print();");
print_preview_observer.WaitUntilPreviewIsReady();
EXPECT_EQ(true, content::EvalJs(rfh, "firedBeforePrint"));
Expand Down Expand Up @@ -2574,7 +2476,7 @@ class SystemAccessProcessPrintBrowserTestBase

void PrintAfterPreviewIsReadyAndLoaded() {
// First invoke the Print Preview dialog with `StartPrint()`.
PrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/true);
TestPrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/true);
StartPrint(browser()->tab_strip_model()->GetActiveWebContents(),
/*print_renderer=*/mojo::NullAssociatedRemote(),
/*print_preview_disabled=*/false,
Expand All @@ -2600,7 +2502,7 @@ class SystemAccessProcessPrintBrowserTestBase
#if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG)
void SystemPrintFromPreviewOnceReadyAndLoaded(bool wait_for_callback) {
// First invoke the Print Preview dialog with `StartPrint()`.
PrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/true);
TestPrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/true);
StartPrint(browser()->tab_strip_model()->GetActiveWebContents(),
/*print_renderer=*/mojo::NullAssociatedRemote(),
/*print_preview_disabled=*/false,
Expand Down
90 changes: 90 additions & 0 deletions chrome/browser/printing/test_print_preview_observer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/printing/test_print_preview_observer.h"

#include <tuple>

#include "base/check_op.h"
#include "base/logging.h"
#include "base/run_loop.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"

namespace printing {

TestPrintPreviewObserver::TestPrintPreviewObserver(bool wait_for_loaded)
: TestPrintPreviewObserver(wait_for_loaded, /*pages_per_sheet=*/1) {}

TestPrintPreviewObserver::TestPrintPreviewObserver(bool wait_for_loaded,
int pages_per_sheet)
: pages_per_sheet_(pages_per_sheet), wait_for_loaded_(wait_for_loaded) {
PrintPreviewUI::SetDelegateForTesting(this);
}

TestPrintPreviewObserver::~TestPrintPreviewObserver() {
PrintPreviewUI::SetDelegateForTesting(nullptr);
}

[[nodiscard]] content::WebContents*
TestPrintPreviewObserver::WaitUntilPreviewIsReadyAndReturnPreviewDialog() {
if (rendered_page_count_ < expected_rendered_page_count_) {
base::RunLoop run_loop;
base::AutoReset<base::RunLoop*> auto_reset(&run_loop_, &run_loop);
run_loop.Run();

if (queue_.has_value()) {
std::string message;
EXPECT_TRUE(queue_->WaitForMessage(&message));
EXPECT_EQ("\"success\"", message);
}
}

// Grab and reset `preview_dialog_` to avoid potential dangling pointers.
content::WebContents* dialog = preview_dialog_;
preview_dialog_ = nullptr;
return dialog;
}

// Wrapper for WaitUntilPreviewIsReadyAndReturnPreviewDialog() provided for
// convenience for callers that do not need the returned result.
void TestPrintPreviewObserver::WaitUntilPreviewIsReady() {
std::ignore = WaitUntilPreviewIsReadyAndReturnPreviewDialog();
}

void TestPrintPreviewObserver::DidGetPreviewPageCount(uint32_t page_count) {
// `page_count` is the number of pages to be generated but doesn't take
// N-up into consideration. Since `DidRenderPreviewPage()` is called after
// any N-up processing is performed, determine the number of times that
// function is expected to be called.
expected_rendered_page_count_ =
(page_count + pages_per_sheet_ - 1) / pages_per_sheet_;
}

void TestPrintPreviewObserver::DidRenderPreviewPage(
content::WebContents* preview_dialog) {
++rendered_page_count_;
DVLOG(2) << "Rendered preview page " << rendered_page_count_
<< " of a total expected " << expected_rendered_page_count_;
CHECK_LE(rendered_page_count_, expected_rendered_page_count_);
if (rendered_page_count_ == expected_rendered_page_count_ && run_loop_) {
run_loop_->Quit();
preview_dialog_ = preview_dialog;

if (wait_for_loaded_) {
// Instantiate `queue_` to listen for messages in `preview_dialog_`.
queue_.emplace(preview_dialog_);
content::ExecuteScriptAsync(
preview_dialog_.get(),
"window.addEventListener('message', event => {"
" if (event.data.type === 'documentLoaded') {"
" domAutomationController.send(event.data.load_state);"
" }"
"});");
}
}
}

} // namespace printing
67 changes: 67 additions & 0 deletions chrome/browser/printing/test_print_preview_observer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_PRINTING_TEST_PRINT_PREVIEW_OBSERVER_H_
#define CHROME_BROWSER_PRINTING_TEST_PRINT_PREVIEW_OBSERVER_H_

#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
#include "content/public/test/browser_test_utils.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace base {
class RunLoop;
}
namespace content {
class WebContents;
}

namespace printing {

class TestPrintPreviewObserver : PrintPreviewUI::TestDelegate {
public:
explicit TestPrintPreviewObserver(bool wait_for_loaded);
TestPrintPreviewObserver(bool wait_for_loaded, int pages_per_sheet);
TestPrintPreviewObserver(const TestPrintPreviewObserver&) = delete;
TestPrintPreviewObserver& operator=(const TestPrintPreviewObserver&) = delete;
~TestPrintPreviewObserver() override;

// Tests that use PrintPreviewObserver must call
// WaitUntilPreviewIsReady*() exactly once.
[[nodiscard]] content::WebContents*
WaitUntilPreviewIsReadyAndReturnPreviewDialog();

// Wrapper for WaitUntilPreviewIsReadyAndReturnPreviewDialog() provided for
// convenience for callers that do not need the returned result.
void WaitUntilPreviewIsReady();

uint32_t rendered_page_count() const { return rendered_page_count_; }

private:
// PrintPreviewUI::TestDelegate:
void DidGetPreviewPageCount(uint32_t page_count) override;

// PrintPreviewUI::TestDelegate:
void DidRenderPreviewPage(content::WebContents* preview_dialog) override;

absl::optional<content::DOMMessageQueue> queue_;

// Rendered pages are provided after N-up processing, which will be different
// from the count provided to `DidGetPreviewPageCount()` when
// `pages_per_sheet_` is larger than one.
const int pages_per_sheet_;
uint32_t expected_rendered_page_count_ = 1;
uint32_t rendered_page_count_ = 0;

const bool wait_for_loaded_;
raw_ptr<content::WebContents> preview_dialog_ = nullptr;
// This field is not a raw_ptr<> because it was filtered by the rewriter for:
// #addr-of
RAW_PTR_EXCLUSION base::RunLoop* run_loop_ = nullptr;
};

} // namespace printing

#endif // CHROME_BROWSER_PRINTING_TEST_PRINT_PREVIEW_OBSERVER_H_
2 changes: 2 additions & 0 deletions chrome/test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -4642,6 +4642,8 @@ if (!is_android) {
"../browser/printing/pwg_raster_converter_browsertest.cc",
"../browser/printing/test_print_preview_dialog_cloned_observer.cc",
"../browser/printing/test_print_preview_dialog_cloned_observer.h",
"../browser/printing/test_print_preview_observer.cc",
"../browser/printing/test_print_preview_observer.h",
"../browser/printing/test_print_view_manager.cc",
"../browser/printing/test_print_view_manager.h",
"../browser/printing/test_print_view_manager_for_request_preview.cc",
Expand Down

0 comments on commit c000f43

Please sign in to comment.