blob: 5cedfa68eaeb03be5f8915f4cbf3774c77aeaf58 [file] [log] [blame]
// 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;
quit_closure_ = run_loop.QuitClosure();
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::EnsureWaitForLoaded() {
if (queue_.has_value()) {
// Have already added event listener.
return;
}
// 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);"
" }"
"});");
}
void TestPrintPreviewObserver::DidGetPreviewPageCount(uint32_t page_count) {
rendered_page_count_ = 0;
// `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_ && quit_closure_) {
std::move(quit_closure_).Run();
preview_dialog_ = preview_dialog;
if (wait_for_loaded_) {
EnsureWaitForLoaded();
}
}
}
void TestPrintPreviewObserver::PreviewDocumentReady(
content::WebContents* preview_dialog,
base::span<const uint8_t> data) {
#if BUILDFLAG(IS_WIN)
last_document_composite_data_type_ = DetermineDocumentDataType(data);
#endif
// This runs after `DidGetPreviewPageCount()` for modifiable content, but is
// otherwise the only notification.
if (quit_closure_) {
std::move(quit_closure_).Run();
preview_dialog_ = preview_dialog;
if (wait_for_loaded_) {
EnsureWaitForLoaded();
}
}
}
} // namespace printing