This source file includes following definitions.
- KillProcess
- command_
- WaitForPageToLoad
- GetAutomationExtension
- GetAsDesktop
- GetOperatingSystemName
- QuitImpl
- command
#include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/process/kill.h"
#include "base/sys_info.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "chrome/test/chromedriver/chrome/automation_extension.h"
#include "chrome/test/chromedriver/chrome/devtools_client.h"
#include "chrome/test/chromedriver/chrome/devtools_http_client.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/chrome/web_view_impl.h"
#include "chrome/test/chromedriver/net/port_server.h"
#if defined(OS_POSIX)
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#endif
namespace {
bool KillProcess(base::ProcessHandle process_id) {
#if defined(OS_POSIX)
kill(process_id, SIGKILL);
base::TimeTicks deadline =
base::TimeTicks::Now() + base::TimeDelta::FromSeconds(30);
while (base::TimeTicks::Now() < deadline) {
pid_t pid = HANDLE_EINTR(waitpid(process_id, NULL, WNOHANG));
if (pid == process_id)
return true;
if (pid == -1) {
if (errno == ECHILD) {
return true;
}
LOG(WARNING) << "Error waiting for process " << process_id;
}
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
}
return false;
#endif
#if defined(OS_WIN)
if (!base::KillProcess(process_id, 0, true)) {
int exit_code;
return base::GetTerminationStatus(process_id, &exit_code) !=
base::TERMINATION_STATUS_STILL_RUNNING;
}
return true;
#endif
}
}
ChromeDesktopImpl::ChromeDesktopImpl(
scoped_ptr<DevToolsHttpClient> client,
ScopedVector<DevToolsEventListener>& devtools_event_listeners,
scoped_ptr<PortReservation> port_reservation,
base::ProcessHandle process,
const CommandLine& command,
base::ScopedTempDir* user_data_dir,
base::ScopedTempDir* extension_dir)
: ChromeImpl(client.Pass(),
devtools_event_listeners,
port_reservation.Pass()),
process_(process),
command_(command) {
if (user_data_dir->IsValid())
CHECK(user_data_dir_.Set(user_data_dir->Take()));
if (extension_dir->IsValid())
CHECK(extension_dir_.Set(extension_dir->Take()));
}
ChromeDesktopImpl::~ChromeDesktopImpl() {
if (!quit_) {
base::FilePath user_data_dir = user_data_dir_.Take();
base::FilePath extension_dir = extension_dir_.Take();
LOG(WARNING) << "chrome detaches, user should take care of directory:"
<< user_data_dir.value() << " and " << extension_dir.value();
}
base::CloseProcessHandle(process_);
}
Status ChromeDesktopImpl::WaitForPageToLoad(const std::string& url,
const base::TimeDelta& timeout,
scoped_ptr<WebView>* web_view) {
base::TimeTicks deadline = base::TimeTicks::Now() + timeout;
std::string id;
while (base::TimeTicks::Now() < deadline) {
WebViewsInfo views_info;
Status status = devtools_http_client_->GetWebViewsInfo(&views_info);
if (status.IsError())
return status;
for (size_t i = 0; i < views_info.GetSize(); ++i) {
if (views_info.Get(i).url.find(url) == 0) {
id = views_info.Get(i).id;
break;
}
}
if (!id.empty())
break;
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
}
if (id.empty())
return Status(kUnknownError, "page could not be found: " + url);
scoped_ptr<WebView> web_view_tmp(new WebViewImpl(
id, GetBuildNo(), devtools_http_client_->CreateClient(id)));
Status status = web_view_tmp->ConnectIfNecessary();
if (status.IsError())
return status;
status = web_view_tmp->WaitForPendingNavigations(
std::string(), deadline - base::TimeTicks::Now(), false);
if (status.IsOk())
*web_view = web_view_tmp.Pass();
return status;
}
Status ChromeDesktopImpl::GetAutomationExtension(
AutomationExtension** extension) {
if (!automation_extension_) {
scoped_ptr<WebView> web_view;
Status status = WaitForPageToLoad(
"chrome-extension://aapnijgdinlhnhlmodcfapnahmbfebeb/"
"_generated_background_page.html",
base::TimeDelta::FromSeconds(10),
&web_view);
if (status.IsError())
return Status(kUnknownError, "cannot get automation extension", status);
automation_extension_.reset(new AutomationExtension(web_view.Pass()));
}
*extension = automation_extension_.get();
return Status(kOk);
}
ChromeDesktopImpl* ChromeDesktopImpl::GetAsDesktop() {
return this;
}
std::string ChromeDesktopImpl::GetOperatingSystemName() {
return base::SysInfo::OperatingSystemName();
}
Status ChromeDesktopImpl::QuitImpl() {
if (!KillProcess(process_))
return Status(kUnknownError, "cannot kill Chrome");
return Status(kOk);
}
const CommandLine& ChromeDesktopImpl::command() const {
return command_;
}