blob: 458de22d6a187decad7ab43b650fe38a9e9943e4 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/evaluate_capability.h"
#include <iostream>
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "build/build_config.h"
#include "remoting/host/host_exit_codes.h"
#include "remoting/host/ipc_constants.h"
#include "remoting/host/switches.h"
#if defined(OS_WIN)
#include "remoting/host/win/evaluate_3d_display_mode.h"
#include "remoting/host/win/evaluate_d3d.h"
#endif
namespace remoting {
namespace {
// Returns the full path of the binary file we should use to evaluate the
// capability. According to the platform and executing environment, return of
// this function may vary. But in one process, the return value is guaranteed to
// be the same.
// This function uses capability_test_stub in unittest, or tries to use current
// binary if supported, otherwise it falls back to use the default binary.
base::FilePath BuildHostBinaryPath() {
base::FilePath path;
bool result = base::PathService::Get(base::FILE_EXE, &path);
DCHECK(result);
base::FilePath directory;
result = base::PathService::Get(base::DIR_EXE, &directory);
DCHECK(result);
#if defined(OS_WIN)
if (path.BaseName().value() == FILE_PATH_LITERAL("remoting_unittests.exe")) {
return directory.Append(FILE_PATH_LITERAL("capability_test_stub.exe"));
}
#else
if (path.BaseName().value() == FILE_PATH_LITERAL("remoting_unittests")) {
return directory.Append(FILE_PATH_LITERAL("capability_test_stub"));
}
#endif
#if defined(OS_LINUX)
if (path.BaseName().value() ==
FILE_PATH_LITERAL("chrome-remote-desktop-host")) {
return path;
}
if (path.BaseName().value() == FILE_PATH_LITERAL("remoting_me2me_host")) {
return path;
}
return directory.Append(FILE_PATH_LITERAL("remoting_me2me_host"));
#elif defined(OS_MACOSX)
if (path.BaseName().value() == FILE_PATH_LITERAL("remoting_me2me_host")) {
return path;
}
return directory.Append(FILE_PATH_LITERAL(
"remoting_me2me_host.app/Contents/MacOS/remoting_me2me_host"));
#elif defined(OS_WIN)
if (path.BaseName().value() == FILE_PATH_LITERAL("remoting_console.exe")) {
return path;
}
if (path.BaseName().value() == FILE_PATH_LITERAL("remoting_desktop.exe")) {
return path;
}
if (path.BaseName().value() == FILE_PATH_LITERAL("remoting_host.exe")) {
return path;
}
return directory.Append(FILE_PATH_LITERAL("remoting_host.exe"));
#else
#error "BuildHostBinaryPath is not implemented for current platform."
#endif
}
} // namespace
int EvaluateCapabilityLocally(const std::string& type) {
#if defined(OS_WIN)
if (type == kEvaluateD3D) {
return EvaluateD3D();
}
if (type == kEvaluate3dDisplayMode) {
return Evaluate3dDisplayMode();
}
#endif
return kInvalidCommandLineExitCode;
}
int EvaluateCapability(const std::string& type,
std::string* output /* = nullptr */) {
base::CommandLine command(BuildHostBinaryPath());
command.AppendSwitchASCII(kProcessTypeSwitchName,
kProcessTypeEvaluateCapability);
command.AppendSwitchASCII(kEvaluateCapabilitySwitchName, type);
int exit_code;
std::string dummy_output;
if (!output) {
output = &dummy_output;
}
bool result = base::GetAppOutputWithExitCode(command, output, &exit_code);
#if defined(OS_WIN)
// On Windows, base::GetAppOutputWithExitCode() usually returns false when
// receiving "unknown" exit code. See
// https://cs.chromium.org/chromium/src/base/process/launch_win.cc?rcl=39ec40095376e8d977decbdc5d7ca28ba7d39cf2&l=130
// But we forward the |exit_code| through return value, so the return value of
// base::GetAppOutputWithExitCode() should be ignored.
result = true;
#endif
if (!result) {
LOG(ERROR) << "Failed to execute process "
<< command.GetCommandLineString()
<< ", exit code "
<< exit_code;
// This should not happen.
NOTREACHED();
}
return exit_code;
}
} // namespace remoting