Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 #include <fstream> | 6 #include <fstream> |
| 7 #include <iostream> | 7 #include <iostream> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <string> | 10 #include <string> |
| 11 #include <utility> | 11 #include <utility> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/bind.h" | |
| 15 #include "base/callback.h" | |
| 14 #include "base/file_util.h" | 16 #include "base/file_util.h" |
| 15 #include "base/files/file.h" | 17 #include "base/files/file.h" |
| 16 #include "base/files/file_path.h" | 18 #include "base/files/file_path.h" |
| 17 #include "base/files/scoped_temp_dir.h" | 19 #include "base/files/scoped_temp_dir.h" |
| 18 #include "base/logging.h" | 20 #include "base/logging.h" |
| 19 #include "base/md5.h" | 21 #include "base/md5.h" |
| 20 #include "base/memory/scoped_ptr.h" | 22 #include "base/memory/scoped_ptr.h" |
| 21 #include "base/path_service.h" | 23 #include "base/path_service.h" |
| 22 #include "base/run_loop.h" | 24 #include "base/run_loop.h" |
| 23 #include "base/scoped_native_library.h" | 25 #include "base/scoped_native_library.h" |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 bool background_colors_and_images; | 102 bool background_colors_and_images; |
| 101 MarginType margins; | 103 MarginType margins; |
| 102 bool source_is_pdf; | 104 bool source_is_pdf; |
| 103 }; | 105 }; |
| 104 | 106 |
| 105 // Observes the print preview webpage. Once it observes the PreviewPageCount | 107 // Observes the print preview webpage. Once it observes the PreviewPageCount |
| 106 // message, will send a sequence of commands to the print preview dialog and | 108 // message, will send a sequence of commands to the print preview dialog and |
| 107 // change the settings of the preview dialog. | 109 // change the settings of the preview dialog. |
| 108 class PrintPreviewObserver : public WebContentsObserver { | 110 class PrintPreviewObserver : public WebContentsObserver { |
| 109 public: | 111 public: |
| 110 PrintPreviewObserver(Browser* browser, WebContents* dialog) | 112 PrintPreviewObserver(Browser* browser, |
| 113 WebContents* dialog, | |
| 114 const base::FilePath& pdf_file_save_path) | |
| 111 : WebContentsObserver(dialog), | 115 : WebContentsObserver(dialog), |
| 112 browser_(browser), | 116 browser_(browser), |
| 113 state_(kWaitingToSendSaveAsPdf), | 117 state_(kWaitingToSendSaveAsPdf), |
| 114 failed_setting_("None") {} | 118 failed_setting_("None"), |
| 119 pdf_file_save_path_(pdf_file_save_path) {} | |
| 115 | 120 |
| 116 virtual ~PrintPreviewObserver() {} | 121 virtual ~PrintPreviewObserver() {} |
| 117 | 122 |
| 118 // Sets closure for the observer so that it can end the loop. | 123 // Sets closure for the observer so that it can end the loop. |
| 119 void set_quit_closure(const base::Closure &closure) { | 124 void set_quit_closure(const base::Closure &closure) { |
| 120 quit_closure_ = closure; | 125 quit_closure_ = closure; |
| 121 } | 126 } |
| 122 | 127 |
| 123 // Actually stops the message loop so that the test can proceed. | 128 // Actually stops the message loop so that the test can proceed. |
| 124 void EndLoop() { | 129 void EndLoop() { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 } else if (state_ == kWaitingToSendBackgroundColorsAndImages) { | 182 } else if (state_ == kWaitingToSendBackgroundColorsAndImages) { |
| 178 script_argument.SetBoolean("backgroundColorsAndImages", | 183 script_argument.SetBoolean("backgroundColorsAndImages", |
| 179 settings_->background_colors_and_images); | 184 settings_->background_colors_and_images); |
| 180 state_ = kWaitingToSendMargins; | 185 state_ = kWaitingToSendMargins; |
| 181 failed_setting_ = "Background Colors and Images"; | 186 failed_setting_ = "Background Colors and Images"; |
| 182 } else if (state_ == kWaitingToSendMargins) { | 187 } else if (state_ == kWaitingToSendMargins) { |
| 183 script_argument.SetInteger("margins", settings_->margins); | 188 script_argument.SetInteger("margins", settings_->margins); |
| 184 state_ = kWaitingForFinalMessage; | 189 state_ = kWaitingForFinalMessage; |
| 185 failed_setting_ = "Margins"; | 190 failed_setting_ = "Margins"; |
| 186 } else if (state_ == kWaitingForFinalMessage) { | 191 } else if (state_ == kWaitingForFinalMessage) { |
| 187 EndLoop(); | 192 // Called by PrintPreviewMessageHandler when the PDF is saved. This ends |
| 193 // the message loop for |this|. | |
| 194 base::Closure end_loop_callback = | |
| 195 base::Bind(&PrintPreviewObserver::EndLoop, base::Unretained(this)); | |
| 196 GetUI()->SetPdfSavedCallbackForTesting(end_loop_callback); | |
| 197 GetUI()->SetSelectedFileForTesting(pdf_file_save_path_); | |
| 188 return; | 198 return; |
| 189 } | 199 } |
| 190 | 200 |
| 191 ASSERT_FALSE(script_argument.empty()); | 201 ASSERT_FALSE(script_argument.empty()); |
| 192 GetUI()->web_ui()->CallJavascriptFunction( | 202 GetUI()->web_ui()->CallJavascriptFunction( |
| 193 "onManipulateSettingsForTest", script_argument); | 203 "onManipulateSettingsForTest", script_argument); |
| 194 } | 204 } |
| 195 | 205 |
| 196 // Saves the print preview settings to be sent to the print preview dialog. | 206 // Saves the print preview settings to be sent to the print preview dialog. |
| 197 void SetPrintPreviewSettings(const PrintPreviewSettings& settings) { | 207 void SetPrintPreviewSettings(const PrintPreviewSettings& settings) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 265 ui->web_ui()->AddMessageHandler(new UIDoneLoadingMessageHandler(this)); | 275 ui->web_ui()->AddMessageHandler(new UIDoneLoadingMessageHandler(this)); |
| 266 ui->web_ui()->CallJavascriptFunction("onEnableManipulateSettingsForTest"); | 276 ui->web_ui()->CallJavascriptFunction("onEnableManipulateSettingsForTest"); |
| 267 } | 277 } |
| 268 | 278 |
| 269 virtual void DidCloneToNewWebContents( | 279 virtual void DidCloneToNewWebContents( |
| 270 WebContents* old_web_contents, | 280 WebContents* old_web_contents, |
| 271 WebContents* new_web_contents) OVERRIDE { | 281 WebContents* new_web_contents) OVERRIDE { |
| 272 Observe(new_web_contents); | 282 Observe(new_web_contents); |
| 273 } | 283 } |
| 274 | 284 |
| 275 virtual void WebContentsDestroyed() OVERRIDE { | |
| 276 EndLoop(); | |
| 277 } | |
| 278 | |
| 279 Browser* browser_; | 285 Browser* browser_; |
| 280 base::Closure quit_closure_; | 286 base::Closure quit_closure_; |
| 281 scoped_ptr<PrintPreviewSettings> settings_; | 287 scoped_ptr<PrintPreviewSettings> settings_; |
| 282 | 288 |
| 283 // State of the observer. The state indicates what message to send | 289 // State of the observer. The state indicates what message to send |
| 284 // next. The state advances whenever the message handler calls | 290 // next. The state advances whenever the message handler calls |
| 285 // ManipulatePreviewSettings() on the observer. | 291 // ManipulatePreviewSettings() on the observer. |
| 286 State state_; | 292 State state_; |
| 287 std::string failed_setting_; | 293 std::string failed_setting_; |
| 294 base::FilePath pdf_file_save_path_; | |
| 288 | 295 |
| 289 DISALLOW_COPY_AND_ASSIGN(PrintPreviewObserver); | 296 DISALLOW_COPY_AND_ASSIGN(PrintPreviewObserver); |
| 290 }; | 297 }; |
| 291 | 298 |
| 292 class PrintPreviewPdfGeneratedBrowserTest : public InProcessBrowserTest { | 299 class PrintPreviewPdfGeneratedBrowserTest : public InProcessBrowserTest { |
| 293 public: | 300 public: |
| 294 PrintPreviewPdfGeneratedBrowserTest() {} | 301 PrintPreviewPdfGeneratedBrowserTest() {} |
| 295 virtual ~PrintPreviewPdfGeneratedBrowserTest() {} | 302 virtual ~PrintPreviewPdfGeneratedBrowserTest() {} |
| 296 | 303 |
| 297 // Navigates to the given web page, then initiates print preview and waits | 304 // Navigates to the given web page, then initiates print preview and waits |
| 298 // for all the settings to be set. | 305 // for all the settings to be set, then the webpage is printed to a PDF. |
|
Lei Zhang
2014/07/22 03:04:39
... then save the preview to PDF.
ivandavid
2014/07/22 19:02:00
Done.
| |
| 299 void NavigateAndPreview(const base::FilePath::StringType& file_name, | 306 void NavigateAndPrint(const base::FilePath::StringType& file_name, |
| 300 const PrintPreviewSettings& settings) { | 307 const PrintPreviewSettings& settings) { |
| 301 print_preview_observer_->SetPrintPreviewSettings(settings); | 308 print_preview_observer_->SetPrintPreviewSettings(settings); |
| 302 base::FilePath path(file_name); | 309 base::FilePath path(file_name); |
| 303 GURL gurl = net::FilePathToFileURL(path); | 310 GURL gurl = net::FilePathToFileURL(path); |
| 304 | 311 |
| 305 ui_test_utils::NavigateToURL(browser(), gurl); | 312 ui_test_utils::NavigateToURL(browser(), gurl); |
| 306 | 313 |
| 307 base::RunLoop loop; | 314 base::RunLoop loop; |
| 308 print_preview_observer_->set_quit_closure(loop.QuitClosure()); | 315 print_preview_observer_->set_quit_closure(loop.QuitClosure()); |
| 309 chrome::Print(browser()); | 316 chrome::Print(browser()); |
| 310 loop.Run(); | 317 loop.Run(); |
| 311 } | 318 } |
| 312 | 319 |
| 313 // Prints the web page to a PDF. NavigateAndPreview must be called first. | |
| 314 void Print() { | |
| 315 ASSERT_FALSE(pdf_file_save_path_.empty()); | |
| 316 | |
| 317 base::RunLoop loop; | |
| 318 print_preview_observer_->set_quit_closure(loop.QuitClosure()); | |
| 319 print_preview_observer_->GetUI()->SetSelectedFileForTesting( | |
| 320 pdf_file_save_path_); | |
| 321 loop.Run(); | |
| 322 | |
| 323 // Checks to see if the file exists and is readable. If the file doesn't | |
| 324 // exist, the test will fail. If it exists, but isn't readable, the test | |
| 325 // will keep polling until the file becomes readable. This is due to a | |
| 326 // problem on Windows where the file exists, but isn't readable, causing | |
| 327 // other ASSERT statements in this test to fail. | |
| 328 // TODO(ivandavid): Come up with a better way to do this. | |
| 329 ASSERT_TRUE(base::PathExists(pdf_file_save_path_)); | |
| 330 while (true) { | |
| 331 base::File pdf_file( | |
| 332 pdf_file_save_path_, base::File::FLAG_OPEN | base::File::FLAG_READ); | |
| 333 if (pdf_file.IsValid()) | |
| 334 break; | |
| 335 } | |
| 336 } | |
| 337 | |
| 338 // Initializes function pointers from the PDF library. Called once when the | 320 // Initializes function pointers from the PDF library. Called once when the |
| 339 // test starts. The library is closed when the browser test ends. | 321 // test starts. The library is closed when the browser test ends. |
| 340 void InitPdfFunctions() { | 322 void InitPdfFunctions() { |
| 341 base::FilePath pdf_module_path; | 323 base::FilePath pdf_module_path; |
| 342 | 324 |
| 343 ASSERT_TRUE(PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_module_path)); | 325 ASSERT_TRUE(PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_module_path)); |
| 344 ASSERT_TRUE(base::PathExists(pdf_module_path)); | 326 ASSERT_TRUE(base::PathExists(pdf_module_path)); |
| 345 pdf_lib_.Reset(base::LoadNativeLibrary(pdf_module_path, NULL)); | 327 pdf_lib_.Reset(base::LoadNativeLibrary(pdf_module_path, NULL)); |
| 346 | 328 |
| 347 ASSERT_TRUE(pdf_lib_.is_valid()); | 329 ASSERT_TRUE(pdf_lib_.is_valid()); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 488 } | 470 } |
| 489 | 471 |
| 490 // Duplicates the tab that was created when the browser opened. This is done | 472 // Duplicates the tab that was created when the browser opened. This is done |
| 491 // so that the observer can listen to the duplicated tab as soon as possible | 473 // so that the observer can listen to the duplicated tab as soon as possible |
| 492 // and start listening for messages related to print preview. | 474 // and start listening for messages related to print preview. |
| 493 void DuplicateTab() { | 475 void DuplicateTab() { |
| 494 WebContents* tab = | 476 WebContents* tab = |
| 495 browser()->tab_strip_model()->GetActiveWebContents(); | 477 browser()->tab_strip_model()->GetActiveWebContents(); |
| 496 ASSERT_TRUE(tab); | 478 ASSERT_TRUE(tab); |
| 497 | 479 |
| 498 print_preview_observer_.reset(new PrintPreviewObserver(browser(), tab)); | 480 print_preview_observer_.reset( |
| 481 new PrintPreviewObserver(browser(), tab, pdf_file_save_path_)); | |
| 499 chrome::DuplicateTab(browser()); | 482 chrome::DuplicateTab(browser()); |
| 500 | 483 |
| 501 WebContents* initiator = | 484 WebContents* initiator = |
| 502 browser()->tab_strip_model()->GetActiveWebContents(); | 485 browser()->tab_strip_model()->GetActiveWebContents(); |
| 503 ASSERT_TRUE(initiator); | 486 ASSERT_TRUE(initiator); |
| 504 ASSERT_NE(tab, initiator); | 487 ASSERT_NE(tab, initiator); |
| 505 } | 488 } |
| 506 | 489 |
| 507 // Resets the test so that another web page can be printed. It also deletes | 490 // Resets the test so that another web page can be printed. It also deletes |
| 508 // the duplicated tab as it isn't needed anymore. | 491 // the duplicated tab as it isn't needed anymore. |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 537 | 520 |
| 538 // Redirects |std::cin| to the file |stdin_path|. |in| is not freed because | 521 // Redirects |std::cin| to the file |stdin_path|. |in| is not freed because |
| 539 // if it goes out of scope, |std::cin.rdbuf| will be freed, causing an | 522 // if it goes out of scope, |std::cin.rdbuf| will be freed, causing an |
| 540 // error. | 523 // error. |
| 541 std::ifstream* in = new std::ifstream(stdin_path.value().c_str()); | 524 std::ifstream* in = new std::ifstream(stdin_path.value().c_str()); |
| 542 ASSERT_TRUE(in->is_open()); | 525 ASSERT_TRUE(in->is_open()); |
| 543 std::cin.rdbuf(in->rdbuf()); | 526 std::cin.rdbuf(in->rdbuf()); |
| 544 | 527 |
| 545 pdf_file_save_path_ = | 528 pdf_file_save_path_ = |
| 546 tmp_dir_.path().Append(FILE_PATH_LITERAL("dummy.pdf")); | 529 tmp_dir_.path().Append(FILE_PATH_LITERAL("dummy.pdf")); |
| 530 ASSERT_FALSE(pdf_file_save_path_.empty()); | |
|
Lei Zhang
2014/07/22 03:04:39
This can't be false, you just appended to it one l
ivandavid
2014/07/22 19:02:00
Done.
ivandavid
2014/07/22 19:02:00
I moved this to ManipulatePreviewSettings() when |
| |
| 547 | 531 |
| 548 // Send the file path to the layout test framework so that it can | 532 // Send the file path to the layout test framework so that it can |
| 549 // communicate with this browser test. | 533 // communicate with this browser test. |
| 550 std::cout << "StdinPath: " << stdin_path.value() << "\n"; | 534 std::cout << "StdinPath: " << stdin_path.value() << "\n"; |
| 551 std::cout << "#EOF\n"; | 535 std::cout << "#EOF\n"; |
| 552 std::cout.flush(); | 536 std::cout.flush(); |
| 553 } | 537 } |
| 554 | 538 |
| 555 private: | 539 private: |
| 556 // Generates a png from bitmap data and stores it in |png_output_|. | 540 // Generates a png from bitmap data and stores it in |png_output_|. |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 691 cmd.find(file_extension) != base::FilePath::StringType::npos); | 675 cmd.find(file_extension) != base::FilePath::StringType::npos); |
| 692 | 676 |
| 693 // Splits the command sent by the layout test framework. The first command | 677 // Splits the command sent by the layout test framework. The first command |
| 694 // is always the file path to use for the test. The rest isn't relevant, | 678 // is always the file path to use for the test. The rest isn't relevant, |
| 695 // so it can be ignored. The separator for the commands is an apostrophe. | 679 // so it can be ignored. The separator for the commands is an apostrophe. |
| 696 std::vector<base::FilePath::StringType> cmd_arguments; | 680 std::vector<base::FilePath::StringType> cmd_arguments; |
| 697 base::SplitString(cmd, '\'', &cmd_arguments); | 681 base::SplitString(cmd, '\'', &cmd_arguments); |
| 698 | 682 |
| 699 ASSERT_GE(cmd_arguments.size(), 1U); | 683 ASSERT_GE(cmd_arguments.size(), 1U); |
| 700 base::FilePath::StringType test_name(cmd_arguments[0]); | 684 base::FilePath::StringType test_name(cmd_arguments[0]); |
| 701 NavigateAndPreview(test_name, settings); | 685 NavigateAndPrint(test_name, settings); |
| 702 Print(); | |
| 703 PdfToPng(); | 686 PdfToPng(); |
| 704 | 687 |
| 705 // Message to the layout test framework indicating that it should start | 688 // Message to the layout test framework indicating that it should start |
| 706 // waiting for the image data, as there is no more text data to be read. | 689 // waiting for the image data, as there is no more text data to be read. |
| 707 // There actually isn't any text data at all, however because the layout | 690 // There actually isn't any text data at all, however because the layout |
| 708 // test framework requires it, a message has to be sent to stop it from | 691 // test framework requires it, a message has to be sent to stop it from |
| 709 // waiting for this message and start waiting for the image data. | 692 // waiting for this message and start waiting for the image data. |
| 710 std::cout << "#EOF\n"; | 693 std::cout << "#EOF\n"; |
| 711 std::cout.flush(); | 694 std::cout.flush(); |
| 712 | 695 |
| 713 SendPng(); | 696 SendPng(); |
| 714 Reset(); | 697 Reset(); |
| 715 } | 698 } |
| 716 } | 699 } |
| 717 | 700 |
| 718 } // namespace printing | 701 } // namespace printing |
| OLD | NEW |