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
25using blink::WebFrame;
26using blink::WebLocalFrame;
27using blink::WebString;
28#endif
29
30namespace printing {
31
32namespace {
33
34// A simple web page.
35const 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.
40const char kPrintOnUserAction[] =
41    "<body>"
42    "  <button id=\"print\" onclick=\"window.print();\">Hello World!</button>"
43    "</body>";
44
45// HTML with 3 pages.
46const 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.
57const 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.
69const 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.
81const char kLongPageHTML[] =
82    "<body><img src=\"\" width=10 height=10000 /></body>";
83
84// A web page to simulate the print preview page.
85const char kPrintPreviewHTML[] =
86    "<body><p id=\"pdf-viewer\">Hello World!</p></body>";
87
88void 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
108class 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
128class 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
226class 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.
243TEST_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.
267TEST_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.
305TEST_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.
316TEST_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.
330TEST_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.
372namespace {
373// Test cases used in this test.
374struct 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)
384const 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)
414TEST_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)
470class 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                                                 &param);
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)
566TEST_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
578TEST_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.
601TEST_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
617TEST_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.
648TEST_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.
668TEST_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.
689TEST_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.
721TEST_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.
740TEST_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.
769TEST_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.
787TEST_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.
805TEST_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.
838TEST_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.
859TEST_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.
874TEST_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.
894TEST_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.
908TEST_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.
920TEST_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.
943TEST_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.
963TEST_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
981TEST_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