1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
// Copyright 2017 The Chromium Authors
// 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/check.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/notreached.h"
#include "base/path_service.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "remoting/host/base/host_exit_codes.h"
#include "remoting/host/base/switches.h"
#include "remoting/host/ipc_constants.h"
#if BUILDFLAG(IS_WIN)
#include "remoting/host/win/evaluate_3d_display_mode.h"
#include "remoting/host/win/evaluate_d3d.h"
#endif
namespace remoting {
// TODO(crbug.com/40155401): Do not perform blocking operations on the IO
// thread.
class ScopedBypassIOThreadRestrictions : public base::ScopedAllowBlocking {};
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 BUILDFLAG(IS_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 BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
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 BUILDFLAG(IS_APPLE)
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 BUILDFLAG(IS_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 BUILDFLAG(IS_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;
}
// TODO(crbug.com/40155401): Do not perform blocking operations on the IO
// thread.
ScopedBypassIOThreadRestrictions bypass;
#if DCHECK_IS_ON() && !BUILDFLAG(IS_WIN)
const bool result =
#endif
base::GetAppOutputWithExitCode(command, output, &exit_code);
// 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
#if DCHECK_IS_ON() && !BUILDFLAG(IS_WIN)
DCHECK(result) << "Failed to execute process "
<< command.GetCommandLineString() << ", exit code "
<< exit_code;
#endif
return exit_code;
}
} // namespace remoting
|