Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(639)

Side by Side Diff: chrome/browser/printing/print_preview_pdf_generated_browsertest.cc

Issue 335583004: Added a test that currently is able to print to pdf. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Browsertest modifies bitmap to fit in larger PNGs. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 <cstdio>
6 #include <iostream>
7 #include <iterator>
8 #include <limits>
9 #include <string>
10 #include <utility>
11 #include <vector>
12
13 #include "base/file_util.h"
14 #include "base/files/file.h"
15 #include "base/files/file_path.h"
16 #include "base/files/scoped_temp_dir.h"
17 #include "base/format_macros.h"
18 #include "base/logging.h"
19 #include "base/md5.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/numerics/safe_conversions.h"
22 #include "base/path_service.h"
23 #include "base/run_loop.h"
24 #include "base/scoped_native_library.h"
25 #include "base/strings/string16.h"
26 #include "base/strings/string_split.h"
27 #include "base/strings/string_util.h"
28 #include "base/strings/utf_string_conversions.h"
29 #include "chrome/app/chrome_command_ids.h"
30 #include "chrome/browser/net/referrer.h"
31 #include "chrome/browser/printing/print_preview_dialog_controller.h"
32 #include "chrome/browser/profiles/profile.h"
33 #include "chrome/browser/ui/browser.h"
34 #include "chrome/browser/ui/browser_commands.h"
35 #include "chrome/browser/ui/tabs/tab_strip_model.h"
36 #include "chrome/browser/ui/webui/print_preview/print_preview_handler.h"
37 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
38 #include "chrome/browser/ui/webui/print_preview/sticky_settings.h"
39 #include "chrome/common/chrome_paths.h"
40 #include "chrome/common/print_messages.h"
41 #include "chrome/common/url_constants.h"
42 #include "chrome/test/base/in_process_browser_test.h"
43 #include "chrome/test/base/ui_test_utils.h"
44 #include "content/public/browser/web_contents.h"
45 #include "content/public/browser/web_ui_message_handler.h"
46 #include "content/public/common/page_transition_types.h"
47 #include "content/public/test/browser_test_utils.h"
48 #include "content/public/test/test_navigation_observer.h"
49 #include "content/public/test/test_utils.h"
50 #include "net/base/filename_util.h"
51 #include "printing/pdf_render_settings.h"
52 #include "printing/units.h"
53 #include "ui/events/keycodes/keyboard_codes.h"
54 #include "ui/gfx/codec/png_codec.h"
55 #include "ui/gfx/geometry/rect.h"
56 #include "url/gurl.h"
57 #include "ipc/ipc_message_macros.h"
58
59 #if defined(OS_POSIX)
60 #define STDIN_STREAM std::cin
61 #elif defined(OS_WIN)
62 #define STDIN_STREAM std::wcin
63 #endif
64
65 using content::WebContents;
66 using content::WebContentsObserver;
67
68 //Number of color channels in a BGRA bitmap.
69 const int kColorChannels = 4;
70
71 // Message refers to the 'UILoaded' message from print_preview.js.
72 // It gets sent either from onPreviewGenerationDone or from
73 // onManipulateSettings_() in print_preview.js
74 enum State {
75 // Waiting for the first message so the program can select Save as PDF
76 kWaitingToSendSaveAsPdf = 0,
77 // Waiting for the second message so the test can set the layout
78 kWaitingToSendLayoutSettings = 1,
79 // Waiting for the third message so the test can set the page numbers
80 kWaitingToSendPageNumbers = 2,
81 // Waiting for the forth message so the test can set the headers checkbox
82 kWaitingToSendHeadersAndFooters = 3,
83 // Waiting for the fifth message so the test can set the background checkbox
84 kWaitingToSendBackgroundColorsAndImages = 4,
85 // Waiting for the sixth message so the test can set the margins combobox
86 kWaitingToSendMargins = 5,
87 // Waiting for the final message so the program can save to PDF.
88 kWaitingForFinalMessage = 6,
89 };
90
91 // Settings for print preview. It reflects the current options
92 // provided by print preview. If more options are added, more
93 // states should be added and there should be more settings
94 // added to this struct.
95 struct PrintPreviewSettings {
96 PrintPreviewSettings(bool is_portrait,
97 std::string page_numbers,
98 bool headers_and_footers,
99 bool background_colors_and_images,
100 printing::MarginType margins,
101 bool is_already_pdf)
102 : is_portrait(is_portrait),
103 page_numbers(page_numbers),
104 headers_and_footers(headers_and_footers),
105 background_colors_and_images(background_colors_and_images),
106 margins(margins),
107 is_already_pdf(is_already_pdf) {}
108
109 bool is_portrait;
110 std::string page_numbers;
111 bool headers_and_footers;
112 bool background_colors_and_images;
113 printing::MarginType margins;
114 bool is_already_pdf;
115 };
116
117 // Observes the print preview webpage. Once it observes the
118 // PreviewPageCount message, will send a sequence of commands
119 // to the print preview dialog and change the settings of the
120 // preview dialog.
121 class PrintPreviewObserver : public WebContentsObserver {
122 public:
123 PrintPreviewObserver(WebContents* dialog, Browser* browser)
124 : WebContentsObserver(dialog),
125 browser_(browser),
126 state_(kWaitingToSendSaveAsPdf) {}
127
128 virtual ~PrintPreviewObserver() {}
129
130 // Sets closure for the observer so that it can end the loop.
131 void set_quit_closure(const base::Closure &closure) {
132 closure_ = closure;
133 }
134
135 // Actually stops the message_loop so that the test can proceed.
136 void EndLoop() {
137 base::MessageLoop::current()->PostTask(FROM_HERE, closure_);
138 }
139
140 // This method must always return false. If it ever returns true,
141 // it will cause the test to hang. This is because the
142 // PrintPreviewMessageHandler should still handle all of the messages to
143 // progress the print preview process.
144 bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
Dan Beam 2014/07/09 02:08:31 bool handled = true;
145 IPC_BEGIN_MESSAGE_MAP(PrintPreviewObserver, message)
146 IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPreviewPageCount,
147 OnDidGetPreviewPageCount)
148 IPC_MESSAGE_UNHANDLED()
Dan Beam 2014/07/09 02:08:32 IPC_MESSAGE_UNHANDLED(handled = false)
ivandavid 2014/07/09 19:58:22 I just removed this line as it was never needed in
Dan Beam 2014/07/09 22:03:04 ah, ok, if we don't to handle -- great, this total
149 IPC_END_MESSAGE_MAP();
150 return false;
Dan Beam 2014/07/09 02:08:32 return handled;
151 }
152
153 // Gets the web contents for the print preview dialog so that
154 // the UI and other elements can be accessed.
155 WebContents* GetDialog() {
156 WebContents* tab = browser_->tab_strip_model()->GetActiveWebContents();
157 printing::PrintPreviewDialogController* dialog_controller =
158 printing::PrintPreviewDialogController::GetInstance();
159 WebContents* web_contents =
160 dialog_controller->GetPrintPreviewForContents(tab);
161 return web_contents;
162 }
163
164 // Gets the PrintPreviewUI so that certain elements can be accessed.
165 PrintPreviewUI* GetUI() {
166 return static_cast<PrintPreviewUI*>(
167 GetDialog()->GetWebUI()->GetController());
168 }
169
170 // Calls a javascript function that will change the print preview settings,
171 // such as the layout, the margins, page numbers, etc.
172 void ManipulatePreviewSettings() {
173 base::DictionaryValue script_argument;
174
175 if (state_ == kWaitingToSendSaveAsPdf) {
176 script_argument.SetBoolean("selectSaveAsPdfDestination", true);
177 state_ = settings_->is_already_pdf ?
178 kWaitingToSendPageNumbers :
179 kWaitingToSendLayoutSettings;
180 } else if (state_ == kWaitingToSendLayoutSettings) {
181 script_argument.SetBoolean("layoutSettings.portrait",
182 settings_->is_portrait);
183 state_ = kWaitingToSendPageNumbers;
184 } else if (state_ == kWaitingToSendPageNumbers) {
185 script_argument.SetString("pageRange", settings_->page_numbers);
186 state_ = settings_->is_already_pdf ?
187 kWaitingForFinalMessage :
188 kWaitingToSendHeadersAndFooters;
189 } else if (state_ == kWaitingToSendHeadersAndFooters) {
190 script_argument.SetBoolean("headersAndFooters",
191 settings_->headers_and_footers);
192 state_ = kWaitingToSendBackgroundColorsAndImages;
193 } else if (state_ == kWaitingToSendBackgroundColorsAndImages) {
194 script_argument.SetBoolean("backgroundColorsAndImages",
195 settings_->background_colors_and_images);
196 state_ = kWaitingToSendMargins;
197 } else if (state_ == kWaitingToSendMargins) {
198 script_argument.SetInteger("margins", settings_->margins);
199 state_ = kWaitingForFinalMessage;
200 } else if (state_ == kWaitingForFinalMessage) {
201 // Exit
202 EndLoop();
203 return;
204 }
205
206 ASSERT_TRUE(!script_argument.empty());
207 GetUI()->web_ui()->CallJavascriptFunction(
208 "onManipulateSettingsForTest", script_argument);
209 }
210
211 // Function to set the print preview settings and save them so they
212 // can be sent later. Currently only used in the constructor. Will be
213 // used when creating a test and take command line arguments.
214 // |page_numbers| is a comma separated page range.
215 // Example: "1-5,9" will print pages 1 through 5 and page 9.
216 // The pages specified must be less than or equal to the maximum
217 // page number. An empty string seems to be valid input, however
218 // further testing will be required to see if that is actually
219 // true.
220 void SetPrintPreviewSettings(const PrintPreviewSettings& settings) {
221 settings_.reset(new PrintPreviewSettings(settings));
222 }
223
224 private:
225 // Listens for messages from the print preview dialog. Specifically,
226 // it listens for 'UILoadedForTest' and 'UIFailedLoadingForTest.'
227 class UIDoneLoadingMessageHandler : public content::WebUIMessageHandler {
228 public:
229 explicit UIDoneLoadingMessageHandler(PrintPreviewObserver* observer)
230 : observer_(observer) {}
231
232 virtual ~UIDoneLoadingMessageHandler() {}
233
234 // When a setting has been set succesfully, this is called and
235 // the observer_ is told to send the next setting to be set.
236 void HandleDone(const base::ListValue* /* args */) {
237 ASSERT_TRUE(observer_);
238 observer_->ManipulatePreviewSettings();
239 }
240
241 // Ends the test because a setting was not set successfully,
242 // therefore, the test shouldn't continue.
243 // TODO(ivandavid): Print out error message to give context.
244 void HandleFailure(const base::ListValue* /* args */) {
245 FAIL();
246 }
247
248 // Sets up this class to listen for the UILoadedForTest and
249 // UIFailedLoadingForTest messages. These messages are sent
250 // by print_preview.js. On UILoadedForTest, a settings has
251 // been successfully set and its effects on the pdf have been finalized.
252 // On UIFaieldLoadingForTest a setting has not been successfully set
253 // and the test should fail.
254 void RegisterMessages() OVERRIDE {
255 web_ui()->RegisterMessageCallback(
256 "UILoadedForTest",
257 base::Bind(&UIDoneLoadingMessageHandler::HandleDone,
258 base::Unretained(this)));
259
260 web_ui()->RegisterMessageCallback(
261 "UIFailedLoadingForTest",
262 base::Bind(&UIDoneLoadingMessageHandler::HandleFailure,
263 base::Unretained(this)));
264 }
265
266 private:
267 PrintPreviewObserver* observer_;
268
269 DISALLOW_COPY_AND_ASSIGN(UIDoneLoadingMessageHandler);
270 };
271
272 // Called when the observer gets the IPC message stating that the
273 // page count is ready.
274 // Due to forward declaration problem, the definition of the function
275 // must be separated from the declaration.
276 void OnDidGetPreviewPageCount(
277 const PrintHostMsg_DidGetPreviewPageCount_Params &params) {
278 WebContents* web_contents = GetDialog();
279 PrintPreviewUI* ui = GetUI();
280 ASSERT_TRUE(ui);
281 ASSERT_TRUE(ui->web_ui());
282 Observe(web_contents);
283 ASSERT_TRUE(web_contents);
284
285 // The web ui deallocates the memory for the handler when
286 // the web ui is destroyed.
Dan Beam 2014/07/09 02:08:32 wrap as close to 80 cols as possible (everywhere)
ivandavid 2014/07/09 19:58:22 Done.
ivandavid 2014/07/09 19:58:22 I did my best to do this. Hopefully I caught most
287 ui->web_ui()->AddMessageHandler(new UIDoneLoadingMessageHandler(this));
288 ui->web_ui()->CallJavascriptFunction("onEnableManipulateSettingsForTest");
289 }
290
291 void DidCloneToNewWebContents(WebContents* old_web_contents,
292 WebContents* new_web_contents) OVERRIDE {
293 Observe(new_web_contents);
294 }
295
296 void WebContentsDestroyed() OVERRIDE {
297 EndLoop();
298 }
299
300 Browser* browser_;
301 base::Closure closure_;
302 scoped_ptr<PrintPreviewSettings> settings_;
303
304 // State of the observer. The state indicates what message it is
305 // to send next. The state advances whenever the message handler calls
306 // ManipulatePreviewSettings() on the observer.
307 State state_;
308
309 DISALLOW_COPY_AND_ASSIGN(PrintPreviewObserver);
310 };
311
312 class PrintPreviewPdfGeneratedBrowserTest : public InProcessBrowserTest {
313 public:
314 PrintPreviewPdfGeneratedBrowserTest() {}
315 virtual ~PrintPreviewPdfGeneratedBrowserTest() {}
316
317 // Navigates to the web page given, then initiates print preview
318 // and waits for all the settings to be set.
319 void NavigateAndPreview(const base::FilePath::StringType& file_name,
320 PrintPreviewSettings settings) {
321 print_preview_observer_->SetPrintPreviewSettings(settings);
322 base::FilePath path(file_name);
323 GURL gurl = net::FilePathToFileURL(path);
324
325 ui_test_utils::NavigateToURL(browser(), gurl);
326
327 base::RunLoop loop;
328 print_preview_observer_->set_quit_closure(loop.QuitClosure());
329 chrome::Print(browser());
330 loop.Run();
331 }
332
333 // Prints the webpage to pdf, after the settings have been set.
334 void Print() {
335 ASSERT_FALSE(pdf_file_save_path_.empty());
336 base::RunLoop loop;
337 print_preview_observer_->set_quit_closure(loop.QuitClosure());
338 print_preview_observer_->GetUI()->handler_->FileSelected(
339 pdf_file_save_path_, 0, NULL);
340 loop.Run();
341 }
342
343 // Initializes the pdf lib functions. Called once when browser test starts.
344 // Library is closed when the test ends.
345 void InitPdfFunctions() {
346 base::FilePath pdf_module_path;
347
348 ASSERT_TRUE(PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_module_path));
349 ASSERT_TRUE(base::PathExists(pdf_module_path));
350 pdf_lib_.Reset(base::LoadNativeLibrary(pdf_module_path, NULL));
351
352 ASSERT_TRUE(pdf_lib_.is_valid());
353 pdf_to_bitmap_func_ =
354 reinterpret_cast<PDFPageToBitmapProc>(
355 pdf_lib_.GetFunctionPointer("RenderPDFPageToBitmap"));
356
357 pdf_doc_info_func_ =
358 reinterpret_cast<GetPDFDocInfoProc>(
359 pdf_lib_.GetFunctionPointer("GetPDFDocInfo"));
360
361 pdf_page_size_func_ =
362 reinterpret_cast<GetPDFPageSizeByIndexProc>(
363 pdf_lib_.GetFunctionPointer("GetPDFPageSizeByIndex"));
364
365 ASSERT_TRUE(pdf_to_bitmap_func_);
366 ASSERT_TRUE(pdf_doc_info_func_);
367 ASSERT_TRUE(pdf_page_size_func_);
368 }
369
370 // Converts the pdf to a png file, so that the layout test can
371 // do an image diff on this image and a reference image.
372 void PdfToPng() {
373 std::string data;
374 int num_pages;
375 const int kDpi = 300;
376 double max_width = 0;
377 std::vector<uint8_t> bitmap_data;
378 double total_height = 0;
379
380 ASSERT_TRUE(base::ReadFileToString(pdf_file_save_path_, &data));
381 ASSERT_TRUE(pdf_doc_info_func_(data.data(),
382 data.size(),
383 &num_pages,
384 &max_width));
385
386 max_width = printing::ConvertPointsToPixelDouble(max_width);
387
388 for (int i = 0; i < num_pages; ++i) {
389 double width, height;
390 bool autorotate = false;
391 ASSERT_TRUE(pdf_page_size_func_(
392 data.data(), data.size(), i, &width, &height));
393
394 width = printing::ConvertPointsToPixelDouble(width);
395 height = printing::ConvertPointsToPixelDouble(height);
396
397 // The image needs to be rotated if the width is > to the
398 // height. This is because, when the image is printed to a
399 // pdf, if it is in landscape mode (or the document is just wide)
400 // if will be printed horizontally, not vertically. However,
401 // if it printed, it would have been rotated. Therefore, the image
402 // has to be automatically rotated here to reflect what is printed.
403 //
404 // TODO (ivandavid): See if this is a linux only problem or if
405 // its on every platform. It might not matter, since if its
406 // autorotated, width > height will always be false.
407
408 if (width > height) {
409 std::swap<double>(width, height);
410 autorotate = true;
411 }
412
413 total_height += height;
414 gfx::Rect rect(width, height);
415 printing::PdfRenderSettings settings(rect, kDpi, true);
416
417 // TODO(ivandavid): Implement correct overflow detection.
ivandavid 2014/07/08 23:24:22 I got rid of the old overflow detection because it
418 // Need to check for signed multiplication overflow.
419 // Can't use size_t or any unsigned stuff, b/c internally
420 // everything in PdfRenderSettings is signed it seems.
421
422 std::vector<uint8_t> page_bitmap_data(
423 kColorChannels * settings.area().size().GetArea());
424
425 ASSERT_TRUE(pdf_to_bitmap_func_(data.data(),
426 data.size(),
427 i,
428 page_bitmap_data.data(),
429 settings.area().size().width(),
430 settings.area().size().height(),
431 settings.dpi(),
432 settings.dpi(),
433 autorotate));
434
435 // Must multiply width & max_width by number of color channels because
436 // the bitmap stores individual bytes, not int32's.
437 FillPng(&page_bitmap_data, width * kColorChannels,
438 max_width * kColorChannels,
439 settings.area().size().height());
440 bitmap_data.insert(bitmap_data.end(),
441 page_bitmap_data.begin(),
442 page_bitmap_data.end());
443 }
444
445 CreatePng(bitmap_data, max_width, total_height);
446 }
447
448 // Fills out a bitmap with the color white to fit within a png
449 // that is wider than the bitmap. This prevents the image from
450 // being cutoff or split. The desired_width must be greater than
451 // the current width of the image.
452 void FillPng(std::vector<uint8_t>* bitmap,
453 int current_width,
454 int desired_width,
455 int height) {
456 // Need to seperate the iterator and index. We can't use an iterator only
457 // since the vector will most likely be resized and will render the
458 // iterator invalid. Might need to re-do to make it faster, but there
459 // don't seem to be any speed issues.
460 ASSERT_TRUE(bitmap);
461 ASSERT_LE(current_width, desired_width);
462 const uint8_t kColorByte = 255;
463 size_t index = 0;
464 for (int i = 0; i < height; ++i, index = i * desired_width) {
465 index += current_width - 1;
466 std::vector<uint8_t>::iterator iterator = bitmap->begin();
467 std::advance(iterator, index);
468 // 255,255,255,255 is white in BGRA
469 bitmap->insert(iterator, desired_width - current_width, kColorByte);
470 }
471 }
472
473 // Sends the png image to the layout test framework for comparison.
474 void SendPng() {
475 // Send image header & hash_ to the layout test framework.
476 printf("Content-Type: image/png\n");
477 printf("ActualHash: %s\n", base::MD5DigestToBase16(hash_).data());
478 printf("Content-Length: %" PRIuS "\n", output_.size());
479
480 for (size_t i = 0; i < output_.size(); ++i)
481 printf("%c", output_[i]);
482
483 printf("#EOF\n");
484 fflush(stdout);
485 fprintf(stderr, "#EOF\n");
486 fflush(stderr);
487 }
488
489 // Duplicates the tab that was created when the browser opened.
490 // This is done, so that the observer can listen to the duplicated
491 // tab as soon as possible and start listening for messages related to
492 // print preview.
493 void DuplicateTab() {
494 WebContents* tab =
495 browser()->tab_strip_model()->GetActiveWebContents();
496 ASSERT_TRUE(tab);
497
498 print_preview_observer_.reset(new PrintPreviewObserver(tab, browser()));
499 chrome::DuplicateTab(browser());
500
501 WebContents* initiator =
502 browser()->tab_strip_model()->GetActiveWebContents();
503 ASSERT_TRUE(initiator);
504 ASSERT_NE(tab, initiator);
505 }
506
507 // Resets the test so that another web page can be printing.
508 // Deletes the duplicate tab as it isn't needed anymore.
509 void Reset() {
510 output_.clear();
511 ASSERT_EQ(browser()->tab_strip_model()->count(), 2);
512 chrome::CloseTab(browser());
513 ASSERT_EQ(browser()->tab_strip_model()->count(), 1);
514 }
515
516 // Creates a temporary directory to store the file that will be used for
517 // stdin to accept input. Also sets up the path to save the pdf file
518 // that will be printed. Everything is cleaned up automatically once
519 // the test ends.
520 void SetupStdinAndSavePath() {
521 // Sends a message to the layout test framework indicating indicating
522 // that the browser test has completed setting itself up. The layout
523 // test will then expect the file path for stdin.
524 base::FilePath tmp_path;
525 printf("#READY\n");
526 fflush(stdout);
527
528 ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
529 ASSERT_TRUE(base::CreateTemporaryFileInDir(tmp_dir_.path(), &tmp_path));
530 ASSERT_TRUE(freopen(tmp_path.value().c_str(), "r", stdin));
531
532 pdf_file_save_path_ = tmp_dir_.path().AppendASCII("dummy.pdf");
533
534 // Send the file path to the layout test framework so that it can
535 // communicate with this browsertest.
536 printf("StdinPath: %s\n#EOF\n", tmp_path.value().c_str());
537 fflush(stdout);
538 }
539
540 private:
541 // Generates a png from bitmap data and stores it in output_.
542 void CreatePng(
543 const std::vector<uint8_t>& bitmap_data, int width, int height) {
544 std::string hash_input(bitmap_data.begin(), bitmap_data.end());
545 base::MD5Sum(static_cast<const void*>(hash_input.data()),
546 hash_input.size(),
547 &hash_);
548
549 gfx::Rect png_rect(width, height);
550
551 // tEXtchecksum looks funny, but that's what the layout test
552 // framework expects.
553 std::string comment_title("tEXtchecksum\x00");
554 gfx::PNGCodec::Comment hash_comment(
555 comment_title,
556 base::MD5DigestToBase16(hash_));
557
558 std::vector<gfx::PNGCodec::Comment> comments;
559 comments.push_back(hash_comment);
560
561 ASSERT_TRUE(
562 gfx::PNGCodec::Encode(
563 bitmap_data.data(),
564 gfx::PNGCodec::FORMAT_BGRA,
565 png_rect.size(),
566 png_rect.size().width() * kColorChannels,
567 false,
568 comments,
569 &output_));
570 }
571
572 scoped_ptr<PrintPreviewObserver> print_preview_observer_;
573 base::FilePath pdf_file_save_path_;
574
575 // These typedefs are function pointers to pdflib functions
576 // that give information about the pdf as a whole and
577 // about specific pages.
578
579 // Converts the pdf to a bitmap.
580 typedef bool (*PDFPageToBitmapProc)(const void* pdf_buffer,
581 int pdf_buffer_size,
582 int page_number,
583 void* bitmap_buffer,
584 int bitmap_width,
585 int bitmap_height,
586 int dpi_x,
587 int dpi_y,
588 bool autorotate);
589
590 // Gets the page count and maximum page width of the pdf
591 // in points.
592 typedef bool (*GetPDFDocInfoProc)(const void* pdf_buffer,
593 int buffer_size,
594 int* pages_count,
595 double* max_page_width);
596
597 // Gets the dimensions of a specific page.
598 typedef bool (*GetPDFPageSizeByIndexProc)(const void* pdf_buffer,
599 int buffer_size,
600 int index,
601 double* width,
602 double* height);
603
604 // Instantiations of the function pointers described above.
605 PDFPageToBitmapProc pdf_to_bitmap_func_;
606 GetPDFDocInfoProc pdf_doc_info_func_;
607 GetPDFPageSizeByIndexProc pdf_page_size_func_;
608
609 // Used to open up the library that contains the pdflib functions.
610 base::ScopedNativeLibrary pdf_lib_;
611
612 // Vector where the png is finally stored.
613 std::vector<unsigned char> output_;
614
615 // Image hash of the bitmap that is turned into a PNG. The
616 // hash is put into the PNG as a comment, as it is needed by the layout
617 // test framework.
618 base::MD5Digest hash_;
619
620 // Temporary directory for storing the pdf and the file for stdin.
621 base::ScopedTempDir tmp_dir_;
622
623 DISALLOW_COPY_AND_ASSIGN(PrintPreviewPdfGeneratedBrowserTest);
624 };
625
626 IN_PROC_BROWSER_TEST_F(PrintPreviewPdfGeneratedBrowserTest,
627 MANUAL_DummyTest) {
628 // What this code is supposed to do:
629 // -Setup communication with the layout test framework
630 // -Print webpage to a pdf
631 // -Convert pdf to a png
632 // -Send png to layout test framework, where it doesn an image diff
633 // on the image sent by this test and a reference image.
634 //
635 // Throughout this code, there will be printf statements.
636 // The layout test framework uses stdout to get data from the browser test
637 // and uses stdin to send data to the browser test.
638 // Calling printf("#EOF\n") indicates that whatever block of data that
639 // the test was expecting has been completely sent. Sometimes EOF is
640 // printed to stderr because the test will expect it from stderr
641 // in addition to stdout for certain blocks of data.
642 InitPdfFunctions();
643 SetupStdinAndSavePath();
644
645 // There is no way to determine how many tests are to be run
646 // ahead of time without a ton of modifications to the layout
647 // test framework. However, whenever it is done with a set of tests,
648 // it calls SIGKILL on the browser test that ran those set of tests.
649 // Thus, this while loop will end once the layout test framework
650 // decides to actually kill this process. For this to work,
651 // the test must be run with '--single_process'. There must be an
652 // underscore, not a dash, as that is something different.
653 while (true) {
654 base::FilePath::StringType cmd;
655 std::getline(STDIN_STREAM, cmd);
656 if (cmd.empty()) {
657 while (STDIN_STREAM.eof()) {
658 STDIN_STREAM.clear();
659 std::getline(STDIN_STREAM, cmd);
660 if (!cmd.empty()) {
661 break;
662 }
663 }
664 }
665
666 DuplicateTab();
667
668 // TODO(ivandavid): Get settings from file in resources.
669 PrintPreviewSettings settings(
670 true,
671 "",
672 false,
673 false,
674 printing::DEFAULT_MARGINS,
675 cmd.find(".pdf") != base::FilePath::StringType::npos);
676
677 // Splits the command sent by the layout test framework. The first
678 // first command is always the file path to use for the test. The rest
679 // isn't relevant, so it can be ignored. The separator for the
680 // commands is an apostrophe.
681 std::vector<base::FilePath::StringType> cmd_arguments;
682 base::SplitString(cmd, '\'', &cmd_arguments);
683 base::FilePath::StringType test_name(cmd_arguments[0]);
684 NavigateAndPreview(test_name, settings);
685 Print();
686 PdfToPng();
687
688 // Message to the layout test framework indicating that it should start
689 // waiting for the image data, as there is no more text data to be read.
690 // There actually isn't any text data at all, however because the layout
691 // test framework requires it, a message has to be sent to stop it from
692 // waiting for this message and start waiting for the image data.
693 printf("#EOF\n");
694 fflush(stdout);
695
696 SendPng();
697 Reset();
698 }
699 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698