Index: headless/app/headless_shell.cc |
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc |
index d6d6adeb758a5ef06ce2821d3973911297b22c74..b1376f83d0ed5e7b338d860d2a67c1a99f712a3a 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,101 @@ void HeadlessShell::CaptureScreenshot() { |
void HeadlessShell::OnScreenshotCaptured( |
std::unique_ptr<page::CaptureScreenshotResult> result) { |
+ if (!result) { |
+ LOG(ERROR) << "Capture screenshot failed"; |
+ Shutdown(); |
+ return; |
+ } |
+ 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) { |
+ LOG(ERROR) << "Print to PDF failed"; |
+ Shutdown(); |
+ return; |
+ } |
+ WriteFile(switches::kPrintToPDF, kDefaultPDFFileName, result->GetData()); |
+} |
+ |
+void HeadlessShell::WriteFile(const std::string& file_path_switch, |
+ const std::string& default_file_name, |
+ const std::string& base64_data) { |
base::FilePath file_name = |
base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( |
- switches::kScreenshot); |
- if (file_name.empty()) { |
- file_name = base::FilePath().AppendASCII(kDefaultScreenshotFileName); |
- } |
+ file_path_switch); |
+ if (file_name.empty()) |
+ 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(), |
+ base64_data, file_name))) { |
// Operation could not be started. |
- OnScreenshotFileOpened(nullptr, file_name, base::File::FILE_ERROR_FAILED); |
+ OnFileOpened(std::string(), file_name, base::File::FILE_ERROR_FAILED); |
} |
} |
-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& base64_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; |
+ if (!base::Base64Decode(base64_data, &decoded_data)) { |
+ LOG(ERROR) << "Failed to decode base64 data"; |
+ OnFileWritten(file_name, base64_data.size(), base::File::FILE_ERROR_FAILED, |
+ 0); |
+ return; |
+ } |
+ |
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() |
- << " was unsuccessful: " << net::ErrorToString(write_result); |
+ LOG(ERROR) << "Writing to file " << file_name.value() |
+ << " was unsuccessful: " |
+ << base::File::ErrorToString(error_code); |
} 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 +451,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."; |