blob: 79fd93355957c28f0e814504db2c5784dbee210c [file] [log] [blame]
// Copyright 2017 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 <memory>
#include <utility>
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/printing/print_test_utils.h"
#include "chrome/browser/printing/print_view_manager.h"
#include "chrome/browser/printing/print_view_manager_base.h"
#include "chrome/browser/printing/test_print_job.h"
#include "chrome/browser/printing/test_printer_query.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "components/printing/common/print_messages.h"
#include "content/public/test/test_renderer_host.h"
namespace printing {
using PrintViewManagerTest = BrowserWithTestWindowTest;
class TestPrintViewManager : public PrintViewManagerBase {
public:
explicit TestPrintViewManager(content::WebContents* web_contents)
: PrintViewManagerBase(web_contents) {}
~TestPrintViewManager() override {
// Set this null here. Otherwise, the PrintViewManagerBase destructor will
// try to de-register for notifications that were not registered for in
// CreateNewPrintJob().
print_job_ = nullptr;
}
// Mostly copied from PrintViewManager::PrintPreviewNow(). We can't override
// PrintViewManager since it is a user data class.
bool PrintPreviewNow(content::RenderFrameHost* rfh, bool has_selection) {
auto msg = std::make_unique<PrintMsg_InitiatePrintPreview>(
rfh->GetRoutingID(), has_selection);
return PrintNowInternal(rfh, std::move(msg));
}
// Getters for validating arguments to StartPdf...Conversion functions
const gfx::Size& page_size() { return test_job()->page_size(); }
const gfx::Rect& content_area() { return test_job()->content_area(); }
const gfx::Point& physical_offsets() {
return test_job()->physical_offsets();
}
#if defined(OS_WIN)
PrintSettings::PrinterType type() { return test_job()->type(); }
#endif
// Ends the run loop.
void FakePrintCallback(const base::Value& error) {
DCHECK(run_loop_);
run_loop_->Quit();
}
// Starts a run loop that quits when the print callback is called to indicate
// printing is complete.
void WaitForCallback() {
base::RunLoop run_loop;
base::AutoReset<base::RunLoop*> auto_reset(&run_loop_, &run_loop);
run_loop.Run();
}
protected:
// Override to create a TestPrintJob instead of a real one.
bool CreateNewPrintJob(PrinterQuery* query) override {
print_job_ = base::MakeRefCounted<TestPrintJob>();
print_job_->Initialize(query, RenderSourceName(), number_pages_);
return true;
}
private:
TestPrintJob* test_job() {
return reinterpret_cast<TestPrintJob*>(print_job_.get());
}
base::RunLoop* run_loop_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(TestPrintViewManager);
};
TEST_F(PrintViewManagerTest, PrintSubFrameAndDestroy) {
chrome::NewTab(browser());
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(web_contents);
content::RenderFrameHost* sub_frame =
content::RenderFrameHostTester::For(web_contents->GetMainFrame())
->AppendChild("child");
PrintViewManager* print_view_manager =
PrintViewManager::FromWebContents(web_contents);
ASSERT_TRUE(print_view_manager);
EXPECT_FALSE(print_view_manager->print_preview_rfh());
print_view_manager->PrintPreviewNow(sub_frame, false);
EXPECT_TRUE(print_view_manager->print_preview_rfh());
content::RenderFrameHostTester::For(sub_frame)->Detach();
EXPECT_FALSE(print_view_manager->print_preview_rfh());
}
#if defined(OS_WIN)
// Verifies that StartPdfToPostScriptConversion is called with the correct
// printable area offsets. See crbug.com/821485.
TEST_F(PrintViewManagerTest, PostScriptHasCorrectOffsets) {
scoped_refptr<TestPrintQueriesQueue> queue =
base::MakeRefCounted<TestPrintQueriesQueue>();
// Setup PostScript printer with printable area offsets of 0.1in.
queue->SetupPrinterType(PrintSettings::PrinterType::TYPE_POSTSCRIPT_LEVEL2);
int offset_in_pixels = static_cast<int>(kTestPrinterDpi * 0.1f);
queue->SetupPrinterOffsets(offset_in_pixels, offset_in_pixels);
g_browser_process->print_job_manager()->SetQueueForTest(queue);
chrome::NewTab(browser());
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(web_contents);
std::unique_ptr<TestPrintViewManager> print_view_manager =
std::make_unique<TestPrintViewManager>(web_contents);
print_view_manager->PrintPreviewNow(web_contents->GetMainFrame(), false);
base::Value print_ticket = GetPrintTicket(printing::kLocalPrinter, false);
const char kTestData[] = "abc";
auto print_data = base::MakeRefCounted<base::RefCountedStaticMemory>(
kTestData, sizeof(kTestData));
PrinterHandler::PrintCallback callback =
base::BindOnce(&TestPrintViewManager::FakePrintCallback,
base::Unretained(print_view_manager.get()));
print_view_manager->PrintForPrintPreview(std::move(print_ticket), print_data,
web_contents->GetMainFrame(),
std::move(callback));
print_view_manager->WaitForCallback();
EXPECT_EQ(gfx::Point(60, 60), print_view_manager->physical_offsets());
EXPECT_EQ(gfx::Rect(0, 0, 5100, 6600), print_view_manager->content_area());
EXPECT_EQ(PrintSettings::PrinterType::TYPE_POSTSCRIPT_LEVEL2,
print_view_manager->type());
}
#endif
} // namespace printing