| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 <memory> | 5 #include <memory> |
| 6 #include <sstream> | 6 #include <sstream> |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 browser_->SetDefaultBrowserContext(browser_context_); | 80 browser_->SetDefaultBrowserContext(browser_context_); |
| 81 | 81 |
| 82 HeadlessWebContents::Builder builder( | 82 HeadlessWebContents::Builder builder( |
| 83 browser_context_->CreateWebContentsBuilder()); | 83 browser_context_->CreateWebContentsBuilder()); |
| 84 base::CommandLine::StringVector args = | 84 base::CommandLine::StringVector args = |
| 85 base::CommandLine::ForCurrentProcess()->GetArgs(); | 85 base::CommandLine::ForCurrentProcess()->GetArgs(); |
| 86 | 86 |
| 87 // TODO(alexclarke): Should we navigate to about:blank first if using | 87 // TODO(alexclarke): Should we navigate to about:blank first if using |
| 88 // virtual time? | 88 // virtual time? |
| 89 if (args.empty()) | 89 if (args.empty()) |
| 90 #if defined(OS_WIN) |
| 91 args.push_back(L"about:blank"); |
| 92 #else |
| 90 args.push_back("about:blank"); | 93 args.push_back("about:blank"); |
| 94 #endif |
| 91 for (auto it = args.rbegin(); it != args.rend(); ++it) { | 95 for (auto it = args.rbegin(); it != args.rend(); ++it) { |
| 92 GURL url(*it); | 96 GURL url(*it); |
| 93 HeadlessWebContents* web_contents = builder.SetInitialURL(url).Build(); | 97 HeadlessWebContents* web_contents = builder.SetInitialURL(url).Build(); |
| 94 if (!web_contents) { | 98 if (!web_contents) { |
| 95 LOG(ERROR) << "Navigation to " << url << " failed"; | 99 LOG(ERROR) << "Navigation to " << url << " failed"; |
| 96 browser_->Shutdown(); | 100 browser_->Shutdown(); |
| 97 return; | 101 return; |
| 98 } | 102 } |
| 99 if (!web_contents_ && !RemoteDebuggingEnabled()) { | 103 if (!web_contents_ && !RemoteDebuggingEnabled()) { |
| 100 // TODO(jzfeng): Support observing multiple targets. | 104 // TODO(jzfeng): Support observing multiple targets. |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 | 318 |
| 315 void HeadlessShell::OnScreenshotCaptured( | 319 void HeadlessShell::OnScreenshotCaptured( |
| 316 std::unique_ptr<page::CaptureScreenshotResult> result) { | 320 std::unique_ptr<page::CaptureScreenshotResult> result) { |
| 317 base::FilePath file_name = | 321 base::FilePath file_name = |
| 318 base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( | 322 base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( |
| 319 switches::kScreenshot); | 323 switches::kScreenshot); |
| 320 if (file_name.empty()) { | 324 if (file_name.empty()) { |
| 321 file_name = base::FilePath().AppendASCII(kDefaultScreenshotFileName); | 325 file_name = base::FilePath().AppendASCII(kDefaultScreenshotFileName); |
| 322 } | 326 } |
| 323 | 327 |
| 324 screenshot_file_stream_.reset( | 328 screenshot_file_proxy_.reset( |
| 325 new net::FileStream(browser_->BrowserFileThread())); | 329 new base::FileProxy(browser_->BrowserFileThread().get())); |
| 326 const int open_result = screenshot_file_stream_->Open( | 330 if (!screenshot_file_proxy_->CreateOrOpen( |
| 327 file_name, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | | 331 file_name, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE, |
| 328 base::File::FLAG_ASYNC, | 332 base::Bind(&HeadlessShell::OnScreenshotFileOpened, |
| 329 base::Bind(&HeadlessShell::OnScreenshotFileOpened, | 333 weak_factory_.GetWeakPtr(), |
| 330 weak_factory_.GetWeakPtr(), base::Passed(std::move(result)), | 334 base::Passed(std::move(result)), file_name))) { |
| 331 file_name)); | |
| 332 if (open_result != net::ERR_IO_PENDING) { | |
| 333 // Operation could not be started. | 335 // Operation could not be started. |
| 334 OnScreenshotFileOpened(nullptr, file_name, open_result); | 336 OnScreenshotFileOpened(nullptr, file_name, base::File::FILE_ERROR_FAILED); |
| 335 } | 337 } |
| 336 } | 338 } |
| 337 | 339 |
| 338 void HeadlessShell::OnScreenshotFileOpened( | 340 void HeadlessShell::OnScreenshotFileOpened( |
| 339 std::unique_ptr<page::CaptureScreenshotResult> result, | 341 std::unique_ptr<page::CaptureScreenshotResult> result, |
| 340 const base::FilePath file_name, | 342 const base::FilePath file_name, |
| 341 const int open_result) { | 343 base::File::Error error_code) { |
| 342 if (open_result != net::OK) { | 344 if (!screenshot_file_proxy_->IsValid()) { |
| 343 LOG(ERROR) << "Writing screenshot to file " << file_name.value() | 345 LOG(ERROR) << "Writing screenshot to file " << file_name.value() |
| 344 << " was unsuccessful, could not open file: " | 346 << " was unsuccessful, could not open file: " |
| 345 << net::ErrorToString(open_result); | 347 << base::File::ErrorToString(error_code); |
| 346 return; | 348 return; |
| 347 } | 349 } |
| 348 | 350 |
| 349 std::string decoded_png; | 351 std::string decoded_png; |
| 350 base::Base64Decode(result->GetData(), &decoded_png); | 352 base::Base64Decode(result->GetData(), &decoded_png); |
| 351 scoped_refptr<net::IOBufferWithSize> buf = | 353 scoped_refptr<net::IOBufferWithSize> buf = |
| 352 new net::IOBufferWithSize(decoded_png.size()); | 354 new net::IOBufferWithSize(decoded_png.size()); |
| 353 memcpy(buf->data(), decoded_png.data(), decoded_png.size()); | 355 memcpy(buf->data(), decoded_png.data(), decoded_png.size()); |
| 354 const int write_result = screenshot_file_stream_->Write( | 356 |
| 355 buf.get(), buf->size(), | 357 if (!screenshot_file_proxy_->Write( |
| 356 base::Bind(&HeadlessShell::OnScreenshotFileWritten, | 358 0, buf->data(), buf->size(), |
| 357 weak_factory_.GetWeakPtr(), file_name, buf->size())); | 359 base::Bind(&HeadlessShell::OnScreenshotFileWritten, |
| 358 if (write_result != net::ERR_IO_PENDING) { | 360 weak_factory_.GetWeakPtr(), file_name, buf->size()))) { |
| 359 // Operation may have completed successfully or failed. | 361 // Operation may have completed successfully or failed. |
| 360 OnScreenshotFileWritten(file_name, buf->size(), write_result); | 362 OnScreenshotFileWritten(file_name, buf->size(), |
| 363 base::File::FILE_ERROR_FAILED, 0); |
| 361 } | 364 } |
| 362 } | 365 } |
| 363 | 366 |
| 364 void HeadlessShell::OnScreenshotFileWritten(const base::FilePath file_name, | 367 void HeadlessShell::OnScreenshotFileWritten(const base::FilePath file_name, |
| 365 const int length, | 368 const int length, |
| 366 const int write_result) { | 369 base::File::Error error_code, |
| 370 int write_result) { |
| 367 if (write_result < length) { | 371 if (write_result < length) { |
| 368 // TODO(eseckler): Support recovering from partial writes. | 372 // TODO(eseckler): Support recovering from partial writes. |
| 369 LOG(ERROR) << "Writing screenshot to file " << file_name.value() | 373 LOG(ERROR) << "Writing screenshot to file " << file_name.value() |
| 370 << " was unsuccessful: " << net::ErrorToString(write_result); | 374 << " was unsuccessful: " << net::ErrorToString(write_result); |
| 371 } else { | 375 } else { |
| 372 LOG(INFO) << "Screenshot written to file " << file_name.value() << "." | 376 LOG(INFO) << "Screenshot written to file " << file_name.value() << "." |
| 373 << std::endl; | 377 << std::endl; |
| 374 } | 378 } |
| 375 int close_result = screenshot_file_stream_->Close(base::Bind( | 379 if (!screenshot_file_proxy_->Close( |
| 376 &HeadlessShell::OnScreenshotFileClosed, weak_factory_.GetWeakPtr())); | 380 base::Bind(&HeadlessShell::OnScreenshotFileClosed, |
| 377 if (close_result != net::ERR_IO_PENDING) { | 381 weak_factory_.GetWeakPtr()))) { |
| 378 // Operation could not be started. | 382 // Operation could not be started. |
| 379 OnScreenshotFileClosed(close_result); | 383 OnScreenshotFileClosed(base::File::FILE_ERROR_FAILED); |
| 380 } | 384 } |
| 381 } | 385 } |
| 382 | 386 |
| 383 void HeadlessShell::OnScreenshotFileClosed(const int close_result) { | 387 void HeadlessShell::OnScreenshotFileClosed(base::File::Error error_code) { |
| 384 Shutdown(); | 388 Shutdown(); |
| 385 } | 389 } |
| 386 | 390 |
| 387 bool HeadlessShell::RemoteDebuggingEnabled() const { | 391 bool HeadlessShell::RemoteDebuggingEnabled() const { |
| 388 const base::CommandLine& command_line = | 392 const base::CommandLine& command_line = |
| 389 *base::CommandLine::ForCurrentProcess(); | 393 *base::CommandLine::ForCurrentProcess(); |
| 390 return command_line.HasSwitch(switches::kRemoteDebuggingPort); | 394 return command_line.HasSwitch(switches::kRemoteDebuggingPort); |
| 391 } | 395 } |
| 392 | 396 |
| 393 bool ValidateCommandLine(const base::CommandLine& command_line) { | 397 bool ValidateCommandLine(const base::CommandLine& command_line) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 419 } | 423 } |
| 420 if (command_line.HasSwitch(switches::kVirtualTimeBudget)) { | 424 if (command_line.HasSwitch(switches::kVirtualTimeBudget)) { |
| 421 LOG(ERROR) << "Virtual time budget is disabled " | 425 LOG(ERROR) << "Virtual time budget is disabled " |
| 422 << "when remote debugging is enabled."; | 426 << "when remote debugging is enabled."; |
| 423 return false; | 427 return false; |
| 424 } | 428 } |
| 425 return true; | 429 return true; |
| 426 } | 430 } |
| 427 | 431 |
| 428 int HeadlessShellMain(int argc, const char** argv) { | 432 int HeadlessShellMain(int argc, const char** argv) { |
| 433 base::CommandLine::Init(argc, argv); |
| 429 RunChildProcessIfNeeded(argc, argv); | 434 RunChildProcessIfNeeded(argc, argv); |
| 430 HeadlessShell shell; | 435 HeadlessShell shell; |
| 431 HeadlessBrowser::Options::Builder builder(argc, argv); | 436 HeadlessBrowser::Options::Builder builder(argc, argv); |
| 432 | 437 |
| 433 // Enable devtools if requested. | 438 // Enable devtools if requested. |
| 434 base::CommandLine::Init(argc, argv); | |
| 435 const base::CommandLine& command_line( | 439 const base::CommandLine& command_line( |
| 436 *base::CommandLine::ForCurrentProcess()); | 440 *base::CommandLine::ForCurrentProcess()); |
| 437 if (!ValidateCommandLine(command_line)) | 441 if (!ValidateCommandLine(command_line)) |
| 438 return EXIT_FAILURE; | 442 return EXIT_FAILURE; |
| 439 | 443 |
| 440 if (command_line.HasSwitch(::switches::kRemoteDebuggingPort)) { | 444 if (command_line.HasSwitch(::switches::kRemoteDebuggingPort)) { |
| 441 std::string address = kDevToolsHttpServerAddress; | 445 std::string address = kDevToolsHttpServerAddress; |
| 442 if (command_line.HasSwitch(switches::kRemoteDebuggingAddress)) { | 446 if (command_line.HasSwitch(switches::kRemoteDebuggingAddress)) { |
| 443 address = | 447 address = |
| 444 command_line.GetSwitchValueASCII(switches::kRemoteDebuggingAddress); | 448 command_line.GetSwitchValueASCII(switches::kRemoteDebuggingAddress); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 builder.SetOverrideWebPreferencesCallback(base::Bind([]( | 510 builder.SetOverrideWebPreferencesCallback(base::Bind([]( |
| 507 WebPreferences* preferences) { preferences->hide_scrollbars = true; })); | 511 WebPreferences* preferences) { preferences->hide_scrollbars = true; })); |
| 508 } | 512 } |
| 509 | 513 |
| 510 return HeadlessBrowserMain( | 514 return HeadlessBrowserMain( |
| 511 builder.Build(), | 515 builder.Build(), |
| 512 base::Bind(&HeadlessShell::OnStart, base::Unretained(&shell))); | 516 base::Bind(&HeadlessShell::OnStart, base::Unretained(&shell))); |
| 513 } | 517 } |
| 514 | 518 |
| 515 } // namespace headless | 519 } // namespace headless |
| OLD | NEW |