Home | History | Annotate | Download | only in printing
      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 
     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:
    108   PrintWebViewHelperTestBase() {}
    109   virtual ~PrintWebViewHelperTestBase() {}
    110 
    111  protected:
    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.
    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.
    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.
    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   }
    169   void OnPrintPages() {
    170     PrintWebViewHelper::Get(view_)->OnPrintPages();
    171     ProcessPendingMessages();
    172   }
    173 
    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 
    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:
    191   PrintWebViewHelperTest() {}
    192   virtual ~PrintWebViewHelperTest() {}
    193 
    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.
    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.
    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.
    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.
    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 
    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.
    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)
    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:
    440   PrintWebViewHelperPreviewTest() {}
    441   virtual ~PrintWebViewHelperPreviewTest() {}
    442 
    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:
    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 
    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 
    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 
    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 
    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.
    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 
    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                                                  &param);
    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.
    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 
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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 
    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:
    943   PrintWebViewHelperKioskTest() {}
    944   virtual ~PrintWebViewHelperKioskTest() {}
    945 
    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.
    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