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