Chromium Code Reviews| Index: headless/app/headless_shell.cc |
| diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc |
| index d6d6adeb758a5ef06ce2821d3973911297b22c74..bf3f81823925abd963c5d94069def9f5d9c4f72a 100644 |
| --- a/headless/app/headless_shell.cc |
| +++ b/headless/app/headless_shell.cc |
| @@ -5,6 +5,7 @@ |
| #include <memory> |
| #include <sstream> |
| #include <string> |
| +#include <utility> |
| #include "base/base64.h" |
| #include "base/base_switches.h" |
| @@ -32,6 +33,8 @@ namespace { |
| const char kDevToolsHttpServerAddress[] = "127.0.0.1"; |
| // Default file name for screenshot. Can be overriden by "--screenshot" switch. |
| const char kDefaultScreenshotFileName[] = "screenshot.png"; |
| +// Default file name for pdf. Can be overriden by "--print-to-pdf" switch. |
| +const char kDefaultPDFFileName[] = "output.pdf"; |
| bool ParseWindowSize(std::string window_size, gfx::Size* parsed_window_size) { |
| int width, height = 0; |
| @@ -255,6 +258,9 @@ void HeadlessShell::OnPageReady() { |
| } else if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kScreenshot)) { |
| CaptureScreenshot(); |
| + } else if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kPrintToPDF)) { |
| + PrintToPDF(); |
| } else { |
| Shutdown(); |
| } |
| @@ -319,73 +325,89 @@ void HeadlessShell::CaptureScreenshot() { |
| void HeadlessShell::OnScreenshotCaptured( |
| std::unique_ptr<page::CaptureScreenshotResult> result) { |
| + WriteFile(switches::kScreenshot, kDefaultScreenshotFileName, |
| + result->GetData()); |
| +} |
| + |
| +void HeadlessShell::PrintToPDF() { |
| + devtools_client_->GetPage()->GetExperimental()->PrintToPDF( |
| + page::PrintToPDFParams::Builder().Build(), |
| + base::Bind(&HeadlessShell::OnPDFCreated, weak_factory_.GetWeakPtr())); |
| +} |
| + |
| +void HeadlessShell::OnPDFCreated( |
| + std::unique_ptr<page::PrintToPDFResult> result) { |
| + if (!result) { |
|
Eric Seckler
2017/03/29 11:21:19
For consistency, could you add the same check to O
jzfeng
2017/03/30 03:04:56
Done.
|
| + LOG(ERROR) << "Print to PDF failed"; |
| + Shutdown(); |
| + return; |
| + } |
| + WriteFile(switches::kPrintToPDF, kDefaultPDFFileName, result->GetData()); |
| +} |
| + |
| +void HeadlessShell::WriteFile(const std::string& switch_string, |
|
Eric Seckler
2017/03/29 11:21:19
nit: file_path_switch
jzfeng
2017/03/30 03:04:56
Done.
|
| + const std::string& default_file_name, |
| + const std::string& data) { |
|
Eric Seckler
2017/03/29 11:21:19
nit: base64_data
jzfeng
2017/03/30 03:04:56
Done.
|
| base::FilePath file_name = |
| - base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( |
| - switches::kScreenshot); |
| + base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(switch_string); |
| if (file_name.empty()) { |
| - file_name = base::FilePath().AppendASCII(kDefaultScreenshotFileName); |
| + file_name = base::FilePath().AppendASCII(default_file_name); |
| } |
| - screenshot_file_proxy_.reset( |
| - new base::FileProxy(browser_->BrowserFileThread().get())); |
| - if (!screenshot_file_proxy_->CreateOrOpen( |
| + file_proxy_.reset(new base::FileProxy(browser_->BrowserFileThread().get())); |
| + if (!file_proxy_->CreateOrOpen( |
| file_name, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE, |
| - base::Bind(&HeadlessShell::OnScreenshotFileOpened, |
| - weak_factory_.GetWeakPtr(), |
| - base::Passed(std::move(result)), file_name))) { |
| + base::Bind(&HeadlessShell::OnFileOpened, weak_factory_.GetWeakPtr(), |
| + data, file_name))) { |
| // Operation could not be started. |
| - OnScreenshotFileOpened(nullptr, file_name, base::File::FILE_ERROR_FAILED); |
| + OnFileOpened("", file_name, base::File::FILE_ERROR_FAILED); |
|
Lei Zhang
2017/03/29 05:30:15
Pass in a std::string() instead of "". There's a f
jzfeng
2017/03/30 03:04:56
Done.
|
| } |
| } |
| -void HeadlessShell::OnScreenshotFileOpened( |
| - std::unique_ptr<page::CaptureScreenshotResult> result, |
| - const base::FilePath file_name, |
| - base::File::Error error_code) { |
| - if (!screenshot_file_proxy_->IsValid()) { |
| - LOG(ERROR) << "Writing screenshot to file " << file_name.value() |
| +void HeadlessShell::OnFileOpened(const std::string& data, |
| + const base::FilePath file_name, |
| + base::File::Error error_code) { |
| + if (!file_proxy_->IsValid()) { |
| + LOG(ERROR) << "Writing to file " << file_name.value() |
| << " was unsuccessful, could not open file: " |
| << base::File::ErrorToString(error_code); |
| return; |
| } |
| - std::string decoded_png; |
| - base::Base64Decode(result->GetData(), &decoded_png); |
| + std::string decoded_data; |
| + base::Base64Decode(data, &decoded_data); |
|
Lei Zhang
2017/03/29 05:30:15
base::Base64Decode() can fail, BTW.
jzfeng
2017/03/30 03:04:56
Added error handling logic.
|
| scoped_refptr<net::IOBufferWithSize> buf = |
| - new net::IOBufferWithSize(decoded_png.size()); |
| - memcpy(buf->data(), decoded_png.data(), decoded_png.size()); |
| + new net::IOBufferWithSize(decoded_data.size()); |
| + memcpy(buf->data(), decoded_data.data(), decoded_data.size()); |
| - if (!screenshot_file_proxy_->Write( |
| + if (!file_proxy_->Write( |
| 0, buf->data(), buf->size(), |
| - base::Bind(&HeadlessShell::OnScreenshotFileWritten, |
| - weak_factory_.GetWeakPtr(), file_name, buf->size()))) { |
| + base::Bind(&HeadlessShell::OnFileWritten, weak_factory_.GetWeakPtr(), |
| + file_name, buf->size()))) { |
| // Operation may have completed successfully or failed. |
| - OnScreenshotFileWritten(file_name, buf->size(), |
| - base::File::FILE_ERROR_FAILED, 0); |
| + OnFileWritten(file_name, buf->size(), base::File::FILE_ERROR_FAILED, 0); |
| } |
| } |
| -void HeadlessShell::OnScreenshotFileWritten(const base::FilePath file_name, |
| - const int length, |
| - base::File::Error error_code, |
| - int write_result) { |
| +void HeadlessShell::OnFileWritten(const base::FilePath file_name, |
| + const int length, |
| + base::File::Error error_code, |
| + int write_result) { |
| if (write_result < length) { |
| // TODO(eseckler): Support recovering from partial writes. |
| - LOG(ERROR) << "Writing screenshot to file " << file_name.value() |
| + LOG(ERROR) << "Writing to file " << file_name.value() |
| << " was unsuccessful: " << net::ErrorToString(write_result); |
|
Eric Seckler
2017/03/29 11:21:19
ups, I think we should be using File::ErrorToStrin
jzfeng
2017/03/30 03:04:56
Done.
|
| } else { |
| - LOG(INFO) << "Screenshot written to file " << file_name.value() << "." |
| - << std::endl; |
| + LOG(INFO) << "Written to file " << file_name.value() << "."; |
| } |
| - if (!screenshot_file_proxy_->Close( |
| - base::Bind(&HeadlessShell::OnScreenshotFileClosed, |
| - weak_factory_.GetWeakPtr()))) { |
| + if (!file_proxy_->Close(base::Bind(&HeadlessShell::OnFileClosed, |
| + weak_factory_.GetWeakPtr()))) { |
| // Operation could not be started. |
| - OnScreenshotFileClosed(base::File::FILE_ERROR_FAILED); |
| + OnFileClosed(base::File::FILE_ERROR_FAILED); |
| } |
| } |
| -void HeadlessShell::OnScreenshotFileClosed(base::File::Error error_code) { |
| +void HeadlessShell::OnFileClosed(base::File::Error error_code) { |
| Shutdown(); |
| } |
| @@ -417,6 +439,11 @@ bool ValidateCommandLine(const base::CommandLine& command_line) { |
| << "when remote debugging is enabled."; |
| return false; |
| } |
| + if (command_line.HasSwitch(switches::kPrintToPDF)) { |
| + LOG(ERROR) << "Print to PDF is disabled " |
| + << "when remote debugging is enabled."; |
| + return false; |
| + } |
| if (command_line.HasSwitch(switches::kTimeout)) { |
| LOG(ERROR) << "Navigation timeout is disabled " |
| << "when remote debugging is enabled."; |