1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/command_line.h"
6 #include "chrome/common/chrome_switches.h"
7 #include "chrome/common/print_messages.h"
8 #include "chrome/renderer/mock_printer.h"
9 #include "chrome/renderer/printing/print_web_view_helper.h"
10 #include "chrome/test/base/chrome_render_view_test.h"
11 #include "content/public/renderer/render_view.h"
12 #include "printing/print_job_constants.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/WebKit/public/platform/WebString.h"
15 #include "third_party/WebKit/public/web/WebFrame.h"
16 #include "third_party/WebKit/public/web/WebRange.h"
17 #include "third_party/WebKit/public/web/WebView.h"
18
19 #if defined(OS_WIN) || defined(OS_MACOSX)
20 #include "base/file_util.h"
21 #include "printing/image.h"
22
23 using blink::WebFrame;
24 using blink::WebString;
25 #endif
26
27 namespace printing {
28
29 namespace {
30
31 // A simple web page.
32 const char kHelloWorldHTML[] = "<body><p>Hello World!</p></body>";
33
34 // A simple webpage with a button to print itself with.
35 const char kPrintOnUserAction[] =
36 "<body>"
37 " <button id=\"print\" onclick=\"window.print();\">Hello World!</button>"
38 "</body>";
39
40 #if !defined(OS_CHROMEOS)
41 // HTML with 3 pages.
42 const char kMultipageHTML[] =
43 "<html><head><style>"
44 ".break { page-break-after: always; }"
45 "</style></head>"
46 "<body>"
47 "<div class='break'>page1</div>"
48 "<div class='break'>page2</div>"
49 "<div>page3</div>"
50 "</body></html>";
51
52 // A simple web page with print page size css.
53 const char kHTMLWithPageSizeCss[] =
54 "<html><head><style>"
55 "@media print {"
56 " @page {"
57 " size: 4in 4in;"
58 " }"
59 "}"
60 "</style></head>"
61 "<body>Lorem Ipsum:"
62 "</body></html>";
63
64 // A simple web page with print page layout css.
65 const char kHTMLWithLandscapePageCss[] =
66 "<html><head><style>"
67 "@media print {"
68 " @page {"
69 " size: landscape;"
70 " }"
71 "}"
72 "</style></head>"
73 "<body>Lorem Ipsum:"
74 "</body></html>";
75
76 // A longer web page.
77 const char kLongPageHTML[] =
78 "<body><img src=\"\" width=10 height=10000 /></body>";
79
80 // A web page to simulate the print preview page.
81 const char kPrintPreviewHTML[] =
82 "<body><p id=\"pdf-viewer\">Hello World!</p></body>";
83
CreatePrintSettingsDictionary(base::DictionaryValue * dict)84 void CreatePrintSettingsDictionary(base::DictionaryValue* dict) {
85 dict->SetBoolean(kSettingLandscape, false);
86 dict->SetBoolean(kSettingCollate, false);
87 dict->SetInteger(kSettingColor, GRAY);
88 dict->SetBoolean(kSettingPrintToPDF, true);
89 dict->SetInteger(kSettingDuplexMode, SIMPLEX);
90 dict->SetInteger(kSettingCopies, 1);
91 dict->SetString(kSettingDeviceName, "dummy");
92 dict->SetInteger(kPreviewUIID, 4);
93 dict->SetInteger(kPreviewRequestID, 12345);
94 dict->SetBoolean(kIsFirstRequest, true);
95 dict->SetInteger(kSettingMarginsType, DEFAULT_MARGINS);
96 dict->SetBoolean(kSettingPreviewModifiable, false);
97 dict->SetBoolean(kSettingHeaderFooterEnabled, false);
98 dict->SetBoolean(kSettingGenerateDraftData, true);
99 dict->SetBoolean(kSettingShouldPrintBackgrounds, false);
100 dict->SetBoolean(kSettingShouldPrintSelectionOnly, false);
101 }
102 #endif // !defined(OS_CHROMEOS)
103
104 } // namespace
105
106 class PrintWebViewHelperTestBase : public ChromeRenderViewTest {
107 public:
PrintWebViewHelperTestBase()108 PrintWebViewHelperTestBase() {}
~PrintWebViewHelperTestBase()109 virtual ~PrintWebViewHelperTestBase() {}
110
111 protected:
PrintWithJavaScript()112 void PrintWithJavaScript() {
113 ExecuteJavaScript("window.print();");
114 ProcessPendingMessages();
115 }
116 // The renderer should be done calculating the number of rendered pages
117 // according to the specified settings defined in the mock render thread.
118 // Verify the page count is correct.
VerifyPageCount(int count)119 void VerifyPageCount(int count) {
120 #if defined(OS_CHROMEOS)
121 // The DidGetPrintedPagesCount message isn't sent on ChromeOS. Right now we
122 // always print all pages, and there are checks to that effect built into
123 // the print code.
124 #else
125 const IPC::Message* page_cnt_msg =
126 render_thread_->sink().GetUniqueMessageMatching(
127 PrintHostMsg_DidGetPrintedPagesCount::ID);
128 ASSERT_TRUE(page_cnt_msg);
129 PrintHostMsg_DidGetPrintedPagesCount::Param post_page_count_param;
130 PrintHostMsg_DidGetPrintedPagesCount::Read(page_cnt_msg,
131 &post_page_count_param);
132 EXPECT_EQ(count, post_page_count_param.b);
133 #endif // defined(OS_CHROMEOS)
134 }
135
136 // The renderer should be done calculating the number of rendered pages
137 // according to the specified settings defined in the mock render thread.
138 // Verify the page count is correct.
VerifyPreviewPageCount(int count)139 void VerifyPreviewPageCount(int count) {
140 const IPC::Message* page_cnt_msg =
141 render_thread_->sink().GetUniqueMessageMatching(
142 PrintHostMsg_DidGetPreviewPageCount::ID);
143 ASSERT_TRUE(page_cnt_msg);
144 PrintHostMsg_DidGetPreviewPageCount::Param post_page_count_param;
145 PrintHostMsg_DidGetPreviewPageCount::Read(page_cnt_msg,
146 &post_page_count_param);
147 EXPECT_EQ(count, post_page_count_param.a.page_count);
148 }
149
150 // Verifies whether the pages printed or not.
VerifyPagesPrinted(bool printed)151 void VerifyPagesPrinted(bool printed) {
152 #if defined(OS_CHROMEOS)
153 bool did_print_msg = (render_thread_->sink().GetUniqueMessageMatching(
154 PrintHostMsg_TempFileForPrintingWritten::ID) != NULL);
155 ASSERT_EQ(printed, did_print_msg);
156 #else
157 const IPC::Message* print_msg =
158 render_thread_->sink().GetUniqueMessageMatching(
159 PrintHostMsg_DidPrintPage::ID);
160 bool did_print_msg = (NULL != print_msg);
161 ASSERT_EQ(printed, did_print_msg);
162 if (printed) {
163 PrintHostMsg_DidPrintPage::Param post_did_print_page_param;
164 PrintHostMsg_DidPrintPage::Read(print_msg, &post_did_print_page_param);
165 EXPECT_EQ(0, post_did_print_page_param.a.page_number);
166 }
167 #endif // defined(OS_CHROMEOS)
168 }
OnPrintPages()169 void OnPrintPages() {
170 PrintWebViewHelper::Get(view_)->OnPrintPages();
171 ProcessPendingMessages();
172 }
173
OnPrintPreview(const base::DictionaryValue & dict)174 void OnPrintPreview(const base::DictionaryValue& dict) {
175 PrintWebViewHelper* print_web_view_helper = PrintWebViewHelper::Get(view_);
176 print_web_view_helper->OnInitiatePrintPreview(false);
177 print_web_view_helper->OnPrintPreview(dict);
178 ProcessPendingMessages();
179 }
180
OnPrintForPrintPreview(const base::DictionaryValue & dict)181 void OnPrintForPrintPreview(const base::DictionaryValue& dict) {
182 PrintWebViewHelper::Get(view_)->OnPrintForPrintPreview(dict);
183 ProcessPendingMessages();
184 }
185
186 DISALLOW_COPY_AND_ASSIGN(PrintWebViewHelperTestBase);
187 };
188
189 class PrintWebViewHelperTest : public PrintWebViewHelperTestBase {
190 public:
PrintWebViewHelperTest()191 PrintWebViewHelperTest() {}
~PrintWebViewHelperTest()192 virtual ~PrintWebViewHelperTest() {}
193
SetUp()194 virtual void SetUp() OVERRIDE {
195 ChromeRenderViewTest::SetUp();
196 }
197
198 protected:
199 DISALLOW_COPY_AND_ASSIGN(PrintWebViewHelperTest);
200 };
201
202 // Tests that printing pages work and sending and receiving messages through
203 // that channel all works.
TEST_F(PrintWebViewHelperTest,OnPrintPages)204 TEST_F(PrintWebViewHelperTest, OnPrintPages) {
205 LoadHTML(kHelloWorldHTML);
206 OnPrintPages();
207
208 VerifyPageCount(1);
209 VerifyPagesPrinted(true);
210 }
211
212 // Duplicate of OnPrintPagesTest only using javascript to print.
TEST_F(PrintWebViewHelperTest,PrintWithJavascript)213 TEST_F(PrintWebViewHelperTest, PrintWithJavascript) {
214 PrintWithJavaScript();
215
216 VerifyPageCount(1);
217 VerifyPagesPrinted(true);
218 }
219
220 // Tests that the renderer blocks window.print() calls if they occur too
221 // frequently.
TEST_F(PrintWebViewHelperTest,BlockScriptInitiatedPrinting)222 TEST_F(PrintWebViewHelperTest, BlockScriptInitiatedPrinting) {
223 // Pretend user will cancel printing.
224 chrome_render_thread_->set_print_dialog_user_response(false);
225 // Try to print with window.print() a few times.
226 PrintWithJavaScript();
227 PrintWithJavaScript();
228 PrintWithJavaScript();
229 VerifyPagesPrinted(false);
230
231 // Pretend user will print. (but printing is blocked.)
232 chrome_render_thread_->set_print_dialog_user_response(true);
233 PrintWithJavaScript();
234 VerifyPagesPrinted(false);
235
236 // Unblock script initiated printing and verify printing works.
237 PrintWebViewHelper::Get(view_)->ResetScriptedPrintCount();
238 chrome_render_thread_->printer()->ResetPrinter();
239 PrintWithJavaScript();
240 VerifyPageCount(1);
241 VerifyPagesPrinted(true);
242 }
243
244 // Tests that the renderer always allows window.print() calls if they are user
245 // initiated.
TEST_F(PrintWebViewHelperTest,AllowUserOriginatedPrinting)246 TEST_F(PrintWebViewHelperTest, AllowUserOriginatedPrinting) {
247 // Pretend user will cancel printing.
248 chrome_render_thread_->set_print_dialog_user_response(false);
249 // Try to print with window.print() a few times.
250 PrintWithJavaScript();
251 PrintWithJavaScript();
252 PrintWithJavaScript();
253 VerifyPagesPrinted(false);
254
255 // Pretend user will print. (but printing is blocked.)
256 chrome_render_thread_->set_print_dialog_user_response(true);
257 PrintWithJavaScript();
258 VerifyPagesPrinted(false);
259
260 // Try again as if user initiated, without resetting the print count.
261 chrome_render_thread_->printer()->ResetPrinter();
262 LoadHTML(kPrintOnUserAction);
263 gfx::Size new_size(200, 100);
264 Resize(new_size, gfx::Rect(), false);
265
266 gfx::Rect bounds = GetElementBounds("print");
267 EXPECT_FALSE(bounds.IsEmpty());
268 blink::WebMouseEvent mouse_event;
269 mouse_event.type = blink::WebInputEvent::MouseDown;
270 mouse_event.button = blink::WebMouseEvent::ButtonLeft;
271 mouse_event.x = bounds.CenterPoint().x();
272 mouse_event.y = bounds.CenterPoint().y();
273 mouse_event.clickCount = 1;
274 SendWebMouseEvent(mouse_event);
275 mouse_event.type = blink::WebInputEvent::MouseUp;
276 SendWebMouseEvent(mouse_event);
277 ProcessPendingMessages();
278
279 VerifyPageCount(1);
280 VerifyPagesPrinted(true);
281 }
282
TEST_F(PrintWebViewHelperTest,BlockScriptInitiatedPrintingFromPopup)283 TEST_F(PrintWebViewHelperTest, BlockScriptInitiatedPrintingFromPopup) {
284 PrintWebViewHelper* print_web_view_helper = PrintWebViewHelper::Get(view_);
285 print_web_view_helper->SetScriptedPrintBlocked(true);
286 PrintWithJavaScript();
287 VerifyPagesPrinted(false);
288
289 print_web_view_helper->SetScriptedPrintBlocked(false);
290 PrintWithJavaScript();
291 VerifyPageCount(1);
292 VerifyPagesPrinted(true);
293 }
294
295 #if defined(OS_WIN) || defined(OS_MACOSX)
296 // TODO(estade): I don't think this test is worth porting to Linux. We will have
297 // to rip out and replace most of the IPC code if we ever plan to improve
298 // printing, and the comment below by sverrir suggests that it doesn't do much
299 // for us anyway.
TEST_F(PrintWebViewHelperTest,PrintWithIframe)300 TEST_F(PrintWebViewHelperTest, PrintWithIframe) {
301 // Document that populates an iframe.
302 const char html[] =
303 "<html><body>Lorem Ipsum:"
304 "<iframe name=\"sub1\" id=\"sub1\"></iframe><script>"
305 " document.write(frames['sub1'].name);"
306 " frames['sub1'].document.write("
307 " '<p>Cras tempus ante eu felis semper luctus!</p>');"
308 "</script></body></html>";
309
310 LoadHTML(html);
311
312 // Find the frame and set it as the focused one. This should mean that that
313 // the printout should only contain the contents of that frame.
314 WebFrame* sub1_frame =
315 view_->GetWebView()->findFrameByName(WebString::fromUTF8("sub1"));
316 ASSERT_TRUE(sub1_frame);
317 view_->GetWebView()->setFocusedFrame(sub1_frame);
318 ASSERT_NE(view_->GetWebView()->focusedFrame(),
319 view_->GetWebView()->mainFrame());
320
321 // Initiate printing.
322 OnPrintPages();
323 VerifyPagesPrinted(true);
324
325 // Verify output through MockPrinter.
326 const MockPrinter* printer(chrome_render_thread_->printer());
327 ASSERT_EQ(1, printer->GetPrintedPages());
328 const Image& image1(printer->GetPrintedPage(0)->image());
329
330 // TODO(sverrir): Figure out a way to improve this test to actually print
331 // only the content of the iframe. Currently image1 will contain the full
332 // page.
333 EXPECT_NE(0, image1.size().width());
334 EXPECT_NE(0, image1.size().height());
335 }
336 #endif
337
338 // Tests if we can print a page and verify its results.
339 // This test prints HTML pages into a pseudo printer and check their outputs,
340 // i.e. a simplified version of the PrintingLayoutTextTest UI test.
341 namespace {
342 // Test cases used in this test.
343 struct TestPageData {
344 const char* page;
345 size_t printed_pages;
346 int width;
347 int height;
348 const char* checksum;
349 const wchar_t* file;
350 };
351
352 #if defined(OS_WIN) || defined(OS_MACOSX)
353 const TestPageData kTestPages[] = {
354 {"<html>"
355 "<head>"
356 "<meta"
357 " http-equiv=\"Content-Type\""
358 " content=\"text/html; charset=utf-8\"/>"
359 "<title>Test 1</title>"
360 "</head>"
361 "<body style=\"background-color: white;\">"
362 "<p style=\"font-family: arial;\">Hello World!</p>"
363 "</body>",
364 #if defined(OS_MACOSX)
365 // Mac printing code compensates for the WebKit scale factor while generating
366 // the metafile, so we expect smaller pages.
367 1, 600, 780,
368 #else
369 1, 675, 900,
370 #endif
371 NULL,
372 NULL,
373 },
374 };
375 #endif // defined(OS_WIN) || defined(OS_MACOSX)
376 } // namespace
377
378 // TODO(estade): need to port MockPrinter to get this on Linux. This involves
379 // hooking up Cairo to read a pdf stream, or accessing the cairo surface in the
380 // metafile directly.
381 #if defined(OS_WIN) || defined(OS_MACOSX)
TEST_F(PrintWebViewHelperTest,PrintLayoutTest)382 TEST_F(PrintWebViewHelperTest, PrintLayoutTest) {
383 bool baseline = false;
384
385 EXPECT_TRUE(chrome_render_thread_->printer() != NULL);
386 for (size_t i = 0; i < arraysize(kTestPages); ++i) {
387 // Load an HTML page and print it.
388 LoadHTML(kTestPages[i].page);
389 OnPrintPages();
390 VerifyPagesPrinted(true);
391
392 // MockRenderThread::Send() just calls MockRenderThread::OnReceived().
393 // So, all IPC messages sent in the above RenderView::OnPrintPages() call
394 // has been handled by the MockPrinter object, i.e. this printing job
395 // has been already finished.
396 // So, we can start checking the output pages of this printing job.
397 // Retrieve the number of pages actually printed.
398 size_t pages = chrome_render_thread_->printer()->GetPrintedPages();
399 EXPECT_EQ(kTestPages[i].printed_pages, pages);
400
401 // Retrieve the width and height of the output page.
402 int width = chrome_render_thread_->printer()->GetWidth(0);
403 int height = chrome_render_thread_->printer()->GetHeight(0);
404
405 // Check with margin for error. This has been failing with a one pixel
406 // offset on our buildbot.
407 const int kErrorMargin = 5; // 5%
408 EXPECT_GT(kTestPages[i].width * (100 + kErrorMargin) / 100, width);
409 EXPECT_LT(kTestPages[i].width * (100 - kErrorMargin) / 100, width);
410 EXPECT_GT(kTestPages[i].height * (100 + kErrorMargin) / 100, height);
411 EXPECT_LT(kTestPages[i].height* (100 - kErrorMargin) / 100, height);
412
413 // Retrieve the checksum of the bitmap data from the pseudo printer and
414 // compare it with the expected result.
415 std::string bitmap_actual;
416 EXPECT_TRUE(
417 chrome_render_thread_->printer()->GetBitmapChecksum(0, &bitmap_actual));
418 if (kTestPages[i].checksum)
419 EXPECT_EQ(kTestPages[i].checksum, bitmap_actual);
420
421 if (baseline) {
422 // Save the source data and the bitmap data into temporary files to
423 // create base-line results.
424 base::FilePath source_path;
425 base::CreateTemporaryFile(&source_path);
426 chrome_render_thread_->printer()->SaveSource(0, source_path);
427
428 base::FilePath bitmap_path;
429 base::CreateTemporaryFile(&bitmap_path);
430 chrome_render_thread_->printer()->SaveBitmap(0, bitmap_path);
431 }
432 }
433 }
434 #endif
435
436 // These print preview tests do not work on Chrome OS yet.
437 #if !defined(OS_CHROMEOS)
438 class PrintWebViewHelperPreviewTest : public PrintWebViewHelperTestBase {
439 public:
PrintWebViewHelperPreviewTest()440 PrintWebViewHelperPreviewTest() {}
~PrintWebViewHelperPreviewTest()441 virtual ~PrintWebViewHelperPreviewTest() {}
442
SetUp()443 virtual void SetUp() OVERRIDE {
444 // Append the print preview switch before creating the PrintWebViewHelper.
445 CommandLine::ForCurrentProcess()->AppendSwitch(
446 switches::kRendererPrintPreview);
447
448 ChromeRenderViewTest::SetUp();
449 }
450
451 protected:
VerifyPrintPreviewCancelled(bool did_cancel)452 void VerifyPrintPreviewCancelled(bool did_cancel) {
453 bool print_preview_cancelled =
454 (render_thread_->sink().GetUniqueMessageMatching(
455 PrintHostMsg_PrintPreviewCancelled::ID) != NULL);
456 EXPECT_EQ(did_cancel, print_preview_cancelled);
457 }
458
VerifyPrintPreviewFailed(bool did_fail)459 void VerifyPrintPreviewFailed(bool did_fail) {
460 bool print_preview_failed =
461 (render_thread_->sink().GetUniqueMessageMatching(
462 PrintHostMsg_PrintPreviewFailed::ID) != NULL);
463 EXPECT_EQ(did_fail, print_preview_failed);
464 }
465
VerifyPrintPreviewGenerated(bool generated_preview)466 void VerifyPrintPreviewGenerated(bool generated_preview) {
467 const IPC::Message* preview_msg =
468 render_thread_->sink().GetUniqueMessageMatching(
469 PrintHostMsg_MetafileReadyForPrinting::ID);
470 bool did_get_preview_msg = (NULL != preview_msg);
471 ASSERT_EQ(generated_preview, did_get_preview_msg);
472 if (did_get_preview_msg) {
473 PrintHostMsg_MetafileReadyForPrinting::Param preview_param;
474 PrintHostMsg_MetafileReadyForPrinting::Read(preview_msg, &preview_param);
475 EXPECT_NE(0, preview_param.a.document_cookie);
476 EXPECT_NE(0, preview_param.a.expected_pages_count);
477 EXPECT_NE(0U, preview_param.a.data_size);
478 }
479 }
480
VerifyPrintFailed(bool did_fail)481 void VerifyPrintFailed(bool did_fail) {
482 bool print_failed = (render_thread_->sink().GetUniqueMessageMatching(
483 PrintHostMsg_PrintingFailed::ID) != NULL);
484 EXPECT_EQ(did_fail, print_failed);
485 }
486
VerifyPrintPreviewInvalidPrinterSettings(bool settings_invalid)487 void VerifyPrintPreviewInvalidPrinterSettings(bool settings_invalid) {
488 bool print_preview_invalid_printer_settings =
489 (render_thread_->sink().GetUniqueMessageMatching(
490 PrintHostMsg_PrintPreviewInvalidPrinterSettings::ID) != NULL);
491 EXPECT_EQ(settings_invalid, print_preview_invalid_printer_settings);
492 }
493
494 // |page_number| is 0-based.
VerifyDidPreviewPage(bool generate_draft_pages,int page_number)495 void VerifyDidPreviewPage(bool generate_draft_pages, int page_number) {
496 bool msg_found = false;
497 size_t msg_count = render_thread_->sink().message_count();
498 for (size_t i = 0; i < msg_count; ++i) {
499 const IPC::Message* msg = render_thread_->sink().GetMessageAt(i);
500 if (msg->type() == PrintHostMsg_DidPreviewPage::ID) {
501 PrintHostMsg_DidPreviewPage::Param page_param;
502 PrintHostMsg_DidPreviewPage::Read(msg, &page_param);
503 if (page_param.a.page_number == page_number) {
504 msg_found = true;
505 if (generate_draft_pages)
506 EXPECT_NE(0U, page_param.a.data_size);
507 else
508 EXPECT_EQ(0U, page_param.a.data_size);
509 break;
510 }
511 }
512 }
513 ASSERT_EQ(generate_draft_pages, msg_found);
514 }
515
VerifyDefaultPageLayout(int content_width,int content_height,int margin_top,int margin_bottom,int margin_left,int margin_right,bool page_has_print_css)516 void VerifyDefaultPageLayout(int content_width, int content_height,
517 int margin_top, int margin_bottom,
518 int margin_left, int margin_right,
519 bool page_has_print_css) {
520 const IPC::Message* default_page_layout_msg =
521 render_thread_->sink().GetUniqueMessageMatching(
522 PrintHostMsg_DidGetDefaultPageLayout::ID);
523 bool did_get_default_page_layout_msg = (NULL != default_page_layout_msg);
524 if (did_get_default_page_layout_msg) {
525 PrintHostMsg_DidGetDefaultPageLayout::Param param;
526 PrintHostMsg_DidGetDefaultPageLayout::Read(default_page_layout_msg,
527 ¶m);
528 EXPECT_EQ(content_width, param.a.content_width);
529 EXPECT_EQ(content_height, param.a.content_height);
530 EXPECT_EQ(margin_top, param.a.margin_top);
531 EXPECT_EQ(margin_right, param.a.margin_right);
532 EXPECT_EQ(margin_left, param.a.margin_left);
533 EXPECT_EQ(margin_bottom, param.a.margin_bottom);
534 EXPECT_EQ(page_has_print_css, param.c);
535 }
536 }
537
538 DISALLOW_COPY_AND_ASSIGN(PrintWebViewHelperPreviewTest);
539 };
540
541 // Tests that print preview work and sending and receiving messages through
542 // that channel all works.
TEST_F(PrintWebViewHelperPreviewTest,OnPrintPreview)543 TEST_F(PrintWebViewHelperPreviewTest, OnPrintPreview) {
544 LoadHTML(kHelloWorldHTML);
545
546 // Fill in some dummy values.
547 base::DictionaryValue dict;
548 CreatePrintSettingsDictionary(&dict);
549 OnPrintPreview(dict);
550
551 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
552 VerifyDefaultPageLayout(540, 720, 36, 36, 36, 36, false);
553 VerifyPrintPreviewCancelled(false);
554 VerifyPrintPreviewFailed(false);
555 VerifyPrintPreviewGenerated(true);
556 VerifyPagesPrinted(false);
557 }
558
TEST_F(PrintWebViewHelperPreviewTest,PrintPreviewHTMLWithPageMarginsCss)559 TEST_F(PrintWebViewHelperPreviewTest, PrintPreviewHTMLWithPageMarginsCss) {
560 // A simple web page with print margins css.
561 const char kHTMLWithPageMarginsCss[] =
562 "<html><head><style>"
563 "@media print {"
564 " @page {"
565 " margin: 3in 1in 2in 0.3in;"
566 " }"
567 "}"
568 "</style></head>"
569 "<body>Lorem Ipsum:"
570 "</body></html>";
571 LoadHTML(kHTMLWithPageMarginsCss);
572
573 // Fill in some dummy values.
574 base::DictionaryValue dict;
575 CreatePrintSettingsDictionary(&dict);
576 dict.SetBoolean(kSettingPrintToPDF, false);
577 dict.SetInteger(kSettingMarginsType, DEFAULT_MARGINS);
578 OnPrintPreview(dict);
579
580 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
581 VerifyDefaultPageLayout(519, 432, 216, 144, 21, 72, false);
582 VerifyPrintPreviewCancelled(false);
583 VerifyPrintPreviewFailed(false);
584 VerifyPrintPreviewGenerated(true);
585 VerifyPagesPrinted(false);
586 }
587
588 // Test to verify that print preview ignores print media css when non-default
589 // margin is selected.
TEST_F(PrintWebViewHelperPreviewTest,NonDefaultMarginsSelectedIgnorePrintCss)590 TEST_F(PrintWebViewHelperPreviewTest, NonDefaultMarginsSelectedIgnorePrintCss) {
591 LoadHTML(kHTMLWithPageSizeCss);
592
593 // Fill in some dummy values.
594 base::DictionaryValue dict;
595 CreatePrintSettingsDictionary(&dict);
596 dict.SetBoolean(kSettingPrintToPDF, false);
597 dict.SetInteger(kSettingMarginsType, NO_MARGINS);
598 OnPrintPreview(dict);
599
600 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
601 VerifyDefaultPageLayout(612, 792, 0, 0, 0, 0, true);
602 VerifyPrintPreviewCancelled(false);
603 VerifyPrintPreviewFailed(false);
604 VerifyPrintPreviewGenerated(true);
605 VerifyPagesPrinted(false);
606 }
607
608 // Test to verify that print preview honor print media size css when
609 // PRINT_TO_PDF is selected and doesn't fit to printer default paper size.
TEST_F(PrintWebViewHelperPreviewTest,PrintToPDFSelectedHonorPrintCss)610 TEST_F(PrintWebViewHelperPreviewTest, PrintToPDFSelectedHonorPrintCss) {
611 LoadHTML(kHTMLWithPageSizeCss);
612
613 // Fill in some dummy values.
614 base::DictionaryValue dict;
615 CreatePrintSettingsDictionary(&dict);
616 dict.SetBoolean(kSettingPrintToPDF, true);
617 dict.SetInteger(kSettingMarginsType,
618 PRINTABLE_AREA_MARGINS);
619 OnPrintPreview(dict);
620
621 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
622 // Since PRINT_TO_PDF is selected, pdf page size is equal to print media page
623 // size.
624 VerifyDefaultPageLayout(252, 252, 18, 18, 18, 18, true);
625 VerifyPrintPreviewCancelled(false);
626 VerifyPrintPreviewFailed(false);
627 }
628
629 // Test to verify that print preview honor print margin css when PRINT_TO_PDF
630 // is selected and doesn't fit to printer default paper size.
TEST_F(PrintWebViewHelperPreviewTest,PrintToPDFSelectedHonorPageMarginsCss)631 TEST_F(PrintWebViewHelperPreviewTest, PrintToPDFSelectedHonorPageMarginsCss) {
632 // A simple web page with print margins css.
633 const char kHTMLWithPageCss[] =
634 "<html><head><style>"
635 "@media print {"
636 " @page {"
637 " margin: 3in 1in 2in 0.3in;"
638 " size: 14in 14in;"
639 " }"
640 "}"
641 "</style></head>"
642 "<body>Lorem Ipsum:"
643 "</body></html>";
644 LoadHTML(kHTMLWithPageCss);
645
646 // Fill in some dummy values.
647 base::DictionaryValue dict;
648 CreatePrintSettingsDictionary(&dict);
649 dict.SetBoolean(kSettingPrintToPDF, true);
650 dict.SetInteger(kSettingMarginsType, DEFAULT_MARGINS);
651 OnPrintPreview(dict);
652
653 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
654 // Since PRINT_TO_PDF is selected, pdf page size is equal to print media page
655 // size.
656 VerifyDefaultPageLayout(915, 648, 216, 144, 21, 72, true);
657 VerifyPrintPreviewCancelled(false);
658 VerifyPrintPreviewFailed(false);
659 }
660
661 // Test to verify that print preview workflow center the html page contents to
662 // fit the page size.
TEST_F(PrintWebViewHelperPreviewTest,PrintPreviewCenterToFitPage)663 TEST_F(PrintWebViewHelperPreviewTest, PrintPreviewCenterToFitPage) {
664 LoadHTML(kHTMLWithPageSizeCss);
665
666 // Fill in some dummy values.
667 base::DictionaryValue dict;
668 CreatePrintSettingsDictionary(&dict);
669 dict.SetBoolean(kSettingPrintToPDF, false);
670 dict.SetInteger(kSettingMarginsType, DEFAULT_MARGINS);
671 OnPrintPreview(dict);
672
673 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
674 VerifyDefaultPageLayout(216, 216, 288, 288, 198, 198, true);
675 VerifyPrintPreviewCancelled(false);
676 VerifyPrintPreviewFailed(false);
677 VerifyPrintPreviewGenerated(true);
678 }
679
680 // Test to verify that print preview workflow scale the html page contents to
681 // fit the page size.
TEST_F(PrintWebViewHelperPreviewTest,PrintPreviewShrinkToFitPage)682 TEST_F(PrintWebViewHelperPreviewTest, PrintPreviewShrinkToFitPage) {
683 // A simple web page with print margins css.
684 const char kHTMLWithPageCss[] =
685 "<html><head><style>"
686 "@media print {"
687 " @page {"
688 " size: 15in 17in;"
689 " }"
690 "}"
691 "</style></head>"
692 "<body>Lorem Ipsum:"
693 "</body></html>";
694 LoadHTML(kHTMLWithPageCss);
695
696 // Fill in some dummy values.
697 base::DictionaryValue dict;
698 CreatePrintSettingsDictionary(&dict);
699 dict.SetBoolean(kSettingPrintToPDF, false);
700 dict.SetInteger(kSettingMarginsType, DEFAULT_MARGINS);
701 OnPrintPreview(dict);
702
703 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
704 VerifyDefaultPageLayout(571, 652, 69, 71, 20, 21, true);
705 VerifyPrintPreviewCancelled(false);
706 VerifyPrintPreviewFailed(false);
707 }
708
709 // Test to verify that print preview workflow honor the orientation settings
710 // specified in css.
TEST_F(PrintWebViewHelperPreviewTest,PrintPreviewHonorsOrientationCss)711 TEST_F(PrintWebViewHelperPreviewTest, PrintPreviewHonorsOrientationCss) {
712 LoadHTML(kHTMLWithLandscapePageCss);
713
714 // Fill in some dummy values.
715 base::DictionaryValue dict;
716 CreatePrintSettingsDictionary(&dict);
717 dict.SetBoolean(kSettingPrintToPDF, false);
718 dict.SetInteger(kSettingMarginsType, NO_MARGINS);
719 OnPrintPreview(dict);
720
721 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
722 VerifyDefaultPageLayout(792, 612, 0, 0, 0, 0, true);
723 VerifyPrintPreviewCancelled(false);
724 VerifyPrintPreviewFailed(false);
725 }
726
727 // Test to verify that print preview workflow honors the orientation settings
728 // specified in css when PRINT_TO_PDF is selected.
TEST_F(PrintWebViewHelperPreviewTest,PrintToPDFSelectedHonorOrientationCss)729 TEST_F(PrintWebViewHelperPreviewTest, PrintToPDFSelectedHonorOrientationCss) {
730 LoadHTML(kHTMLWithLandscapePageCss);
731
732 // Fill in some dummy values.
733 base::DictionaryValue dict;
734 CreatePrintSettingsDictionary(&dict);
735 dict.SetBoolean(kSettingPrintToPDF, true);
736 dict.SetInteger(kSettingMarginsType, CUSTOM_MARGINS);
737 OnPrintPreview(dict);
738
739 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
740 VerifyDefaultPageLayout(748, 568, 21, 23, 21, 23, true);
741 VerifyPrintPreviewCancelled(false);
742 VerifyPrintPreviewFailed(false);
743 }
744
745 // Test to verify that complete metafile is generated for a subset of pages
746 // without creating draft pages.
TEST_F(PrintWebViewHelperPreviewTest,OnPrintPreviewForSelectedPages)747 TEST_F(PrintWebViewHelperPreviewTest, OnPrintPreviewForSelectedPages) {
748 LoadHTML(kMultipageHTML);
749
750 // Fill in some dummy values.
751 base::DictionaryValue dict;
752 CreatePrintSettingsDictionary(&dict);
753
754 // Set a page range and update the dictionary to generate only the complete
755 // metafile with the selected pages. Page numbers used in the dictionary
756 // are 1-based.
757 base::DictionaryValue* page_range = new base::DictionaryValue();
758 page_range->SetInteger(kSettingPageRangeFrom, 2);
759 page_range->SetInteger(kSettingPageRangeTo, 3);
760
761 base::ListValue* page_range_array = new base::ListValue();
762 page_range_array->Append(page_range);
763
764 dict.Set(kSettingPageRange, page_range_array);
765 dict.SetBoolean(kSettingGenerateDraftData, false);
766
767 OnPrintPreview(dict);
768
769 VerifyDidPreviewPage(false, 0);
770 VerifyDidPreviewPage(false, 1);
771 VerifyDidPreviewPage(false, 2);
772 VerifyPreviewPageCount(3);
773 VerifyPrintPreviewCancelled(false);
774 VerifyPrintPreviewFailed(false);
775 VerifyPrintPreviewGenerated(true);
776 VerifyPagesPrinted(false);
777 }
778
779 // Test to verify that preview generated only for one page.
TEST_F(PrintWebViewHelperPreviewTest,OnPrintPreviewForSelectedText)780 TEST_F(PrintWebViewHelperPreviewTest, OnPrintPreviewForSelectedText) {
781 LoadHTML(kMultipageHTML);
782 GetMainFrame()->selectRange(
783 blink::WebRange::fromDocumentRange(GetMainFrame(), 1, 3));
784
785 // Fill in some dummy values.
786 base::DictionaryValue dict;
787 CreatePrintSettingsDictionary(&dict);
788 dict.SetBoolean(kSettingShouldPrintSelectionOnly, true);
789
790 OnPrintPreview(dict);
791
792 VerifyPreviewPageCount(1);
793 VerifyPrintPreviewCancelled(false);
794 VerifyPrintPreviewFailed(false);
795 VerifyPrintPreviewGenerated(true);
796 VerifyPagesPrinted(false);
797 }
798
799 // Tests that print preview fails and receiving error messages through
800 // that channel all works.
TEST_F(PrintWebViewHelperPreviewTest,OnPrintPreviewFail)801 TEST_F(PrintWebViewHelperPreviewTest, OnPrintPreviewFail) {
802 LoadHTML(kHelloWorldHTML);
803
804 // An empty dictionary should fail.
805 base::DictionaryValue empty_dict;
806 OnPrintPreview(empty_dict);
807
808 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
809 VerifyPrintPreviewCancelled(false);
810 VerifyPrintPreviewFailed(true);
811 VerifyPrintPreviewGenerated(false);
812 VerifyPagesPrinted(false);
813 }
814
815 // Tests that cancelling print preview works.
TEST_F(PrintWebViewHelperPreviewTest,OnPrintPreviewCancel)816 TEST_F(PrintWebViewHelperPreviewTest, OnPrintPreviewCancel) {
817 LoadHTML(kLongPageHTML);
818
819 const int kCancelPage = 3;
820 chrome_render_thread_->set_print_preview_cancel_page_number(kCancelPage);
821 // Fill in some dummy values.
822 base::DictionaryValue dict;
823 CreatePrintSettingsDictionary(&dict);
824 OnPrintPreview(dict);
825
826 EXPECT_EQ(kCancelPage,
827 chrome_render_thread_->print_preview_pages_remaining());
828 VerifyPrintPreviewCancelled(true);
829 VerifyPrintPreviewFailed(false);
830 VerifyPrintPreviewGenerated(false);
831 VerifyPagesPrinted(false);
832 }
833
834 // Tests that printing from print preview works and sending and receiving
835 // messages through that channel all works.
TEST_F(PrintWebViewHelperPreviewTest,OnPrintForPrintPreview)836 TEST_F(PrintWebViewHelperPreviewTest, OnPrintForPrintPreview) {
837 LoadHTML(kPrintPreviewHTML);
838
839 // Fill in some dummy values.
840 base::DictionaryValue dict;
841 CreatePrintSettingsDictionary(&dict);
842 OnPrintForPrintPreview(dict);
843
844 VerifyPrintFailed(false);
845 VerifyPagesPrinted(true);
846 }
847
848 // Tests that printing from print preview fails and receiving error messages
849 // through that channel all works.
TEST_F(PrintWebViewHelperPreviewTest,OnPrintForPrintPreviewFail)850 TEST_F(PrintWebViewHelperPreviewTest, OnPrintForPrintPreviewFail) {
851 LoadHTML(kPrintPreviewHTML);
852
853 // An empty dictionary should fail.
854 base::DictionaryValue empty_dict;
855 OnPrintForPrintPreview(empty_dict);
856
857 VerifyPagesPrinted(false);
858 }
859
860 // Tests that when default printer has invalid printer settings, print preview
861 // receives error message.
TEST_F(PrintWebViewHelperPreviewTest,OnPrintPreviewUsingInvalidPrinterSettings)862 TEST_F(PrintWebViewHelperPreviewTest,
863 OnPrintPreviewUsingInvalidPrinterSettings) {
864 LoadHTML(kPrintPreviewHTML);
865
866 // Set mock printer to provide invalid settings.
867 chrome_render_thread_->printer()->UseInvalidSettings();
868
869 // Fill in some dummy values.
870 base::DictionaryValue dict;
871 CreatePrintSettingsDictionary(&dict);
872 OnPrintPreview(dict);
873
874 // We should have received invalid printer settings from |printer_|.
875 VerifyPrintPreviewInvalidPrinterSettings(true);
876 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
877
878 // It should receive the invalid printer settings message only.
879 VerifyPrintPreviewFailed(false);
880 VerifyPrintPreviewGenerated(false);
881 }
882
883 // Tests that when the selected printer has invalid page settings, print preview
884 // receives error message.
TEST_F(PrintWebViewHelperPreviewTest,OnPrintPreviewUsingInvalidPageSize)885 TEST_F(PrintWebViewHelperPreviewTest,
886 OnPrintPreviewUsingInvalidPageSize) {
887 LoadHTML(kPrintPreviewHTML);
888
889 chrome_render_thread_->printer()->UseInvalidPageSize();
890
891 base::DictionaryValue dict;
892 CreatePrintSettingsDictionary(&dict);
893 OnPrintPreview(dict);
894
895 VerifyPrintPreviewInvalidPrinterSettings(true);
896 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
897
898 // It should receive the invalid printer settings message only.
899 VerifyPrintPreviewFailed(false);
900 VerifyPrintPreviewGenerated(false);
901 }
902
903 // Tests that when the selected printer has invalid content settings, print
904 // preview receives error message.
TEST_F(PrintWebViewHelperPreviewTest,OnPrintPreviewUsingInvalidContentSize)905 TEST_F(PrintWebViewHelperPreviewTest,
906 OnPrintPreviewUsingInvalidContentSize) {
907 LoadHTML(kPrintPreviewHTML);
908
909 chrome_render_thread_->printer()->UseInvalidContentSize();
910
911 base::DictionaryValue dict;
912 CreatePrintSettingsDictionary(&dict);
913 OnPrintPreview(dict);
914
915 VerifyPrintPreviewInvalidPrinterSettings(true);
916 EXPECT_EQ(0, chrome_render_thread_->print_preview_pages_remaining());
917
918 // It should receive the invalid printer settings message only.
919 VerifyPrintPreviewFailed(false);
920 VerifyPrintPreviewGenerated(false);
921 }
922
TEST_F(PrintWebViewHelperPreviewTest,OnPrintForPrintPreviewUsingInvalidPrinterSettings)923 TEST_F(PrintWebViewHelperPreviewTest,
924 OnPrintForPrintPreviewUsingInvalidPrinterSettings) {
925 LoadHTML(kPrintPreviewHTML);
926
927 // Set mock printer to provide invalid settings.
928 chrome_render_thread_->printer()->UseInvalidSettings();
929
930 // Fill in some dummy values.
931 base::DictionaryValue dict;
932 CreatePrintSettingsDictionary(&dict);
933 OnPrintForPrintPreview(dict);
934
935 VerifyPrintFailed(true);
936 VerifyPagesPrinted(false);
937 }
938
939 #endif // !defined(OS_CHROMEOS)
940
941 class PrintWebViewHelperKioskTest : public PrintWebViewHelperTestBase {
942 public:
PrintWebViewHelperKioskTest()943 PrintWebViewHelperKioskTest() {}
~PrintWebViewHelperKioskTest()944 virtual ~PrintWebViewHelperKioskTest() {}
945
SetUp()946 virtual void SetUp() OVERRIDE {
947 // Append the throttling disable switch before creating the
948 // PrintWebViewHelper.
949 CommandLine::ForCurrentProcess()->AppendSwitch(
950 switches::kDisableScriptedPrintThrottling);
951
952 ChromeRenderViewTest::SetUp();
953 }
954
955 protected:
956 DISALLOW_COPY_AND_ASSIGN(PrintWebViewHelperKioskTest);
957 };
958
959 // Tests that the switch overrides the throttling that blocks window.print()
960 // calls if they occur too frequently. Compare with
961 // PrintWebViewHelperTest.BlockScriptInitiatedPrinting above.
TEST_F(PrintWebViewHelperKioskTest,DontBlockScriptInitiatedPrinting)962 TEST_F(PrintWebViewHelperKioskTest, DontBlockScriptInitiatedPrinting) {
963 // Pretend user will cancel printing.
964 chrome_render_thread_->set_print_dialog_user_response(false);
965 // Try to print with window.print() a few times.
966 PrintWithJavaScript();
967 chrome_render_thread_->printer()->ResetPrinter();
968 PrintWithJavaScript();
969 chrome_render_thread_->printer()->ResetPrinter();
970 PrintWithJavaScript();
971 chrome_render_thread_->printer()->ResetPrinter();
972 VerifyPagesPrinted(false);
973
974 // Pretend user will print, should not be throttled.
975 chrome_render_thread_->set_print_dialog_user_response(true);
976 PrintWithJavaScript();
977 VerifyPagesPrinted(true);
978 }
979
980 } // namespace printing
981