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