blob: 86ff8346a762d373a6b9b1ea163a3266d3348420 [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 "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/pdf/pdf_extension_test_base.h"
#include "chrome/browser/pdf/pdf_extension_test_util.h"
#include "chrome/browser/printing/print_error_dialog.h"
#include "chrome/browser/printing/print_view_manager_base.h"
#include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h"
#include "chrome/browser/ui/browser_commands.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "printing/buildflags/buildflags.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
#include "chrome/browser/printing/print_view_manager.h"
#include "ui/base/ui_base_types.h"
#else
#include "chrome/browser/printing/print_view_manager_basic.h"
#endif
using ::content::WebContents;
using ::extensions::MimeHandlerViewGuest;
using ::pdf_extension_test_util::SetInputFocusOnPlugin;
namespace {
class PrintObserver : public printing::PrintViewManagerBase::Observer {
public:
explicit PrintObserver(content::RenderFrameHost* rfh)
: print_view_manager_(PrintViewManagerImpl::FromWebContents(
content::WebContents::FromRenderFrameHost(rfh))),
rfh_(rfh) {
print_view_manager_->AddObserver(*this);
}
~PrintObserver() override { print_view_manager_->RemoveObserver(*this); }
// printing::PrintViewManagerBase::Observer:
void OnPrintNow(const content::RenderFrameHost* rfh) override {
EXPECT_FALSE(print_now_called_);
EXPECT_FALSE(print_preview_called_);
EXPECT_EQ(rfh, rfh_);
run_loop_.Quit();
print_now_called_ = true;
}
void OnPrintPreview(const content::RenderFrameHost* rfh) override {
EXPECT_FALSE(print_preview_called_);
EXPECT_FALSE(print_now_called_);
EXPECT_EQ(rfh, rfh_);
run_loop_.Quit();
print_preview_called_ = true;
}
void WaitForPrintNow() {
WaitIfNotAlreadyPrinted();
EXPECT_TRUE(print_now_called_);
EXPECT_FALSE(print_preview_called_);
}
void WaitForPrintPreview() {
WaitIfNotAlreadyPrinted();
EXPECT_TRUE(print_preview_called_);
EXPECT_FALSE(print_now_called_);
}
private:
void WaitIfNotAlreadyPrinted() {
if (!print_now_called_ && !print_preview_called_) {
run_loop_.Run();
}
}
bool print_now_called_ = false;
bool print_preview_called_ = false;
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
using PrintViewManagerImpl = printing::PrintViewManager;
#else
using PrintViewManagerImpl = printing::PrintViewManagerBasic;
#endif
const raw_ptr<PrintViewManagerImpl> print_view_manager_;
const raw_ptr<const content::RenderFrameHost, FlakyDanglingUntriaged> rfh_;
base::RunLoop run_loop_;
};
} // namespace
class PDFExtensionPrintingTest : public PDFExtensionTestBase {
public:
PDFExtensionPrintingTest() = default;
~PDFExtensionPrintingTest() override = default;
// PDFExtensionTestBase:
void SetUpOnMainThread() override {
// Avoid getting blocked by modal print error dialogs.
SetShowPrintErrorDialogForTest(base::DoNothing());
PDFExtensionTestBase::SetUpOnMainThread();
}
void TearDownOnMainThread() override {
SetShowPrintErrorDialogForTest(base::NullCallback());
PDFExtensionTestBase::TearDownOnMainThread();
}
};
// Flaky. See http://crbug.com/1415194
IN_PROC_BROWSER_TEST_F(PDFExtensionPrintingTest, DISABLED_BasicPrintCommand) {
MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
embedded_test_server()->GetURL("/pdf/test.pdf"));
content::RenderFrameHost* frame = GetPluginFrame(guest);
ASSERT_TRUE(frame);
PrintObserver print_observer(frame);
chrome::BasicPrint(browser());
print_observer.WaitForPrintNow();
}
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
IN_PROC_BROWSER_TEST_F(PDFExtensionPrintingTest, PrintCommand) {
MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
embedded_test_server()->GetURL("/pdf/test.pdf"));
content::RenderFrameHost* frame = GetPluginFrame(guest);
ASSERT_TRUE(frame);
PrintObserver print_observer(frame);
chrome::Print(browser());
print_observer.WaitForPrintPreview();
}
IN_PROC_BROWSER_TEST_F(PDFExtensionPrintingTest,
ContextMenuPrintCommandExtensionMainFrame) {
MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
embedded_test_server()->GetURL("/pdf/test.pdf"));
content::RenderFrameHost* plugin_frame = GetPluginFrame(guest);
ASSERT_TRUE(plugin_frame);
content::RenderFrameHost* guest_main_frame = guest->GetGuestMainFrame();
// Makes sure that the correct frame invoked the context menu.
content::ContextMenuInterceptor menu_interceptor(guest_main_frame);
// Executes the print command as soon as the context menu is shown.
ContextMenuNotificationObserver context_menu_observer(IDC_PRINT);
PrintObserver print_observer(plugin_frame);
guest_main_frame->GetRenderWidgetHost()->ShowContextMenuAtPoint(
{1, 1}, ui::MENU_SOURCE_MOUSE);
print_observer.WaitForPrintPreview();
menu_interceptor.Wait();
}
// TODO(crbug.com/1344508): Test is flaky on multiple platforms.
IN_PROC_BROWSER_TEST_F(
PDFExtensionPrintingTest,
DISABLED_ContextMenuPrintCommandEmbeddedExtensionMainFrame) {
MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
embedded_test_server()->GetURL("/pdf/pdf_embed.html"));
content::RenderFrameHost* plugin_frame = GetPluginFrame(guest);
ASSERT_TRUE(plugin_frame);
content::RenderFrameHost* guest_main_frame = guest->GetGuestMainFrame();
// Makes sure that the correct frame invoked the context menu.
content::ContextMenuInterceptor menu_interceptor(guest_main_frame);
// Executes the print command as soon as the context menu is shown.
ContextMenuNotificationObserver context_menu_observer(IDC_PRINT);
PrintObserver print_observer(plugin_frame);
SimulateMouseClickAt(guest, blink::WebInputEvent::kNoModifiers,
blink::WebMouseEvent::Button::kLeft, {1, 1});
guest_main_frame->GetRenderWidgetHost()->ShowContextMenuAtPoint(
{1, 1}, ui::MENU_SOURCE_MOUSE);
print_observer.WaitForPrintPreview();
menu_interceptor.Wait();
}
IN_PROC_BROWSER_TEST_F(PDFExtensionPrintingTest,
ContextMenuPrintCommandPluginFrame) {
MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
embedded_test_server()->GetURL("/pdf/test.pdf"));
content::RenderFrameHost* plugin_frame = GetPluginFrame(guest);
ASSERT_TRUE(plugin_frame);
// Makes sure that the correct frame invoked the context menu.
content::ContextMenuInterceptor menu_interceptor(plugin_frame);
// Executes the print command as soon as the context menu is shown.
ContextMenuNotificationObserver context_menu_observer(IDC_PRINT);
PrintObserver print_observer(plugin_frame);
SetInputFocusOnPlugin(guest);
plugin_frame->GetRenderWidgetHost()->ShowContextMenuAtPoint(
{1, 1}, ui::MENU_SOURCE_MOUSE);
print_observer.WaitForPrintPreview();
menu_interceptor.Wait();
}
// TODO(crbug.com/1330032): Fix flakiness.
IN_PROC_BROWSER_TEST_F(PDFExtensionPrintingTest,
DISABLED_ContextMenuPrintCommandEmbeddedPluginFrame) {
MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
embedded_test_server()->GetURL("/pdf/pdf_embed.html"));
content::RenderFrameHost* plugin_frame = GetPluginFrame(guest);
ASSERT_TRUE(plugin_frame);
// Makes sure that the correct frame invoked the context menu.
content::ContextMenuInterceptor menu_interceptor(plugin_frame);
// Executes the print command as soon as the context menu is shown.
ContextMenuNotificationObserver context_menu_observer(IDC_PRINT);
PrintObserver print_observer(plugin_frame);
SetInputFocusOnPlugin(guest);
plugin_frame->GetRenderWidgetHost()->ShowContextMenuAtPoint(
{1, 1}, ui::MENU_SOURCE_MOUSE);
print_observer.WaitForPrintPreview();
menu_interceptor.Wait();
}
IN_PROC_BROWSER_TEST_F(PDFExtensionPrintingTest, PrintButton) {
MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
embedded_test_server()->GetURL("/pdf/test.pdf"));
content::RenderFrameHost* frame = GetPluginFrame(guest);
ASSERT_TRUE(frame);
PrintObserver print_observer(frame);
constexpr char kClickPrintButtonScript[] = R"(
viewer.shadowRoot.querySelector('#toolbar')
.shadowRoot.querySelector('#print')
.click();
)";
EXPECT_TRUE(
ExecuteScript(guest->GetGuestMainFrame(), kClickPrintButtonScript));
print_observer.WaitForPrintPreview();
}
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)