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 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                                                  &param);
    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