| // 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 |