1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This file implements the common entry point shared by all Chromoting Host
8 #include "remoting/host/host_main.h"
12 #include "base/at_exit.h"
13 #include "base/command_line.h"
14 #include "base/files/file_path.h"
15 #include "base/i18n/icu_util.h"
16 #include "base/logging.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/stringize_macros.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "remoting/base/breakpad.h"
22 #include "remoting/host/host_exit_codes.h"
23 #include "remoting/host/logging.h"
24 #include "remoting/host/resources.h"
25 #include "remoting/host/setup/me2me_native_messaging_host.h"
26 #include "remoting/host/switches.h"
27 #include "remoting/host/usage_stats_consent.h"
29 #if defined(OS_MACOSX)
30 #include "base/mac/scoped_nsautorelease_pool.h"
31 #endif // defined(OS_MACOSX)
36 #endif // defined(OS_WIN)
40 // Known entry points.
41 int HostProcessMain();
43 int DaemonProcessMain();
44 int DesktopProcessMain();
45 int RdpDesktopSessionMain();
46 #endif // defined(OS_WIN)
50 typedef int (*MainRoutineFn
)();
52 const char kUsageMessage
[] =
53 "Usage: %s [options]\n"
56 " --audio-pipe-name=<pipe> - Sets the pipe name to capture audio on Linux.\n"
57 " --console - Runs the daemon interactively.\n"
58 " --daemon-pipe=<pipe> - Specifies the pipe to connect to the daemon.\n"
59 " --elevate=<binary> - Runs <binary> elevated.\n"
60 " --host-config=<config> - Specifies the host configuration.\n"
61 " --help, -? - Print this message.\n"
62 " --type - Specifies process type.\n"
63 " --version - Prints the host version and exits.\n"
64 " --window-id=<id> - Specifies a window to remote,"
65 " instead of the whole desktop.\n";
67 void Usage(const base::FilePath
& program_name
) {
68 printf(kUsageMessage
, program_name
.MaybeAsASCII().c_str());
73 // Runs the binary specified by the command line, elevated.
75 const base::CommandLine::SwitchMap
& switches
=
76 base::CommandLine::ForCurrentProcess()->GetSwitches();
77 base::CommandLine::StringVector args
=
78 base::CommandLine::ForCurrentProcess()->GetArgs();
80 // Create the child process command line by copying switches from the current
82 base::CommandLine
command_line(base::CommandLine::NO_PROGRAM
);
83 for (base::CommandLine::SwitchMap::const_iterator i
= switches
.begin();
84 i
!= switches
.end(); ++i
) {
85 if (i
->first
!= kElevateSwitchName
)
86 command_line
.AppendSwitchNative(i
->first
, i
->second
);
88 for (base::CommandLine::StringVector::const_iterator i
= args
.begin();
89 i
!= args
.end(); ++i
) {
90 command_line
.AppendArgNative(*i
);
93 // Get the name of the binary to launch.
94 base::FilePath binary
=
95 base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
97 base::CommandLine::StringType parameters
=
98 command_line
.GetCommandLineString();
100 // Launch the child process requesting elevation.
101 SHELLEXECUTEINFO info
;
102 memset(&info
, 0, sizeof(info
));
103 info
.cbSize
= sizeof(info
);
104 info
.lpVerb
= L
"runas";
105 info
.lpFile
= binary
.value().c_str();
106 info
.lpParameters
= parameters
.c_str();
107 info
.nShow
= SW_SHOWNORMAL
;
109 if (!ShellExecuteEx(&info
)) {
110 DWORD exit_code
= GetLastError();
111 PLOG(ERROR
) << "Unable to launch '" << binary
.value() << "'";
115 return kSuccessExitCode
;
118 #endif // !defined(OS_WIN)
120 // Select the entry point corresponding to the process type.
121 MainRoutineFn
SelectMainRoutine(const std::string
& process_type
) {
122 MainRoutineFn main_routine
= nullptr;
124 if (process_type
== kProcessTypeHost
) {
125 main_routine
= &HostProcessMain
;
127 } else if (process_type
== kProcessTypeDaemon
) {
128 main_routine
= &DaemonProcessMain
;
129 } else if (process_type
== kProcessTypeDesktop
) {
130 main_routine
= &DesktopProcessMain
;
131 } else if (process_type
== kProcessTypeRdpDesktopSession
) {
132 main_routine
= &RdpDesktopSessionMain
;
133 #endif // defined(OS_WIN)
141 int HostMain(int argc
, char** argv
) {
142 #if defined(OS_MACOSX)
143 // Needed so we don't leak objects when threads are created.
144 base::mac::ScopedNSAutoreleasePool pool
;
147 base::CommandLine::Init(argc
, argv
);
149 // Initialize Breakpad as early as possible. On Mac the command-line needs to
150 // be initialized first, so that the preference for crash-reporting can be
151 // looked up in the config file.
152 #if defined(REMOTING_ENABLE_BREAKPAD)
153 if (IsUsageStatsAllowed()) {
154 InitializeCrashReporting();
156 #endif // defined(REMOTING_ENABLE_BREAKPAD)
158 // This object instance is required by Chrome code (for example,
159 // LazyInstance, MessageLoop).
160 base::AtExitManager exit_manager
;
162 // Enable debug logs.
165 // Register and initialize common controls.
167 INITCOMMONCONTROLSEX info
;
168 info
.dwSize
= sizeof(info
);
169 info
.dwICC
= ICC_STANDARD_CLASSES
;
170 InitCommonControlsEx(&info
);
171 #endif // defined(OS_WIN)
173 // Parse the command line.
174 const base::CommandLine
* command_line
=
175 base::CommandLine::ForCurrentProcess();
176 if (command_line
->HasSwitch(kHelpSwitchName
) ||
177 command_line
->HasSwitch(kQuestionSwitchName
)) {
178 Usage(command_line
->GetProgram());
179 return kSuccessExitCode
;
182 if (command_line
->HasSwitch(kVersionSwitchName
)) {
183 printf("%s\n", STRINGIZE(VERSION
));
184 return kSuccessExitCode
;
188 if (command_line
->HasSwitch(kElevateSwitchName
)) {
189 return RunElevated();
191 #endif // defined(OS_WIN)
193 // Assume the host process by default.
194 std::string process_type
= kProcessTypeHost
;
195 if (command_line
->HasSwitch(kProcessTypeSwitchName
)) {
196 process_type
= command_line
->GetSwitchValueASCII(kProcessTypeSwitchName
);
199 MainRoutineFn main_routine
= SelectMainRoutine(process_type
);
201 fprintf(stderr
, "Unknown process type '%s' specified.",
202 process_type
.c_str());
203 Usage(command_line
->GetProgram());
204 return kUsageExitCode
;
207 // Required to find the ICU data file, used by some file_util routines.
208 base::i18n::InitializeICU();
210 remoting::LoadResources("");
212 // Invoke the entry point.
213 int exit_code
= main_routine();
214 if (exit_code
== kUsageExitCode
) {
215 Usage(command_line
->GetProgram());
218 remoting::UnloadResources();
223 } // namespace remoting
226 int main(int argc
, char** argv
) {
227 return remoting::HostMain(argc
, argv
);
229 #endif // !defined(OS_WIN)