Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / remoting / host / host_main.cc
blob9d17d786643bd51c6e795410beb7cdf0df64bbf7
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.
4 //
5 // This file implements the common entry point shared by all Chromoting Host
6 // processes.
8 #include "remoting/host/host_main.h"
10 #include <string>
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/base/resources.h"
23 #include "remoting/host/host_exit_codes.h"
24 #include "remoting/host/logging.h"
25 #include "remoting/host/setup/me2me_native_messaging_host.h"
26 #include "remoting/host/usage_stats_consent.h"
28 #if defined(OS_MACOSX)
29 #include "base/mac/scoped_nsautorelease_pool.h"
30 #endif // defined(OS_MACOSX)
32 #if defined(OS_WIN)
33 #include <commctrl.h>
34 #include <shellapi.h>
35 #endif // defined(OS_WIN)
37 namespace remoting {
39 // Known entry points.
40 int HostProcessMain();
41 #if defined(OS_WIN)
42 int DaemonProcessMain();
43 int DesktopProcessMain();
44 int RdpDesktopSessionMain();
45 #endif // defined(OS_WIN)
47 const char kElevateSwitchName[] = "elevate";
48 const char kProcessTypeSwitchName[] = "type";
50 const char kProcessTypeDaemon[] = "daemon";
51 const char kProcessTypeDesktop[] = "desktop";
52 const char kProcessTypeHost[] = "host";
53 const char kProcessTypeRdpDesktopSession[] = "rdp_desktop_session";
55 namespace {
57 typedef int (*MainRoutineFn)();
59 // "--help" or "--?" prints the usage message.
60 const char kHelpSwitchName[] = "help";
61 const char kQuestionSwitchName[] = "?";
63 // The command line switch used to get version of the daemon.
64 const char kVersionSwitchName[] = "version";
66 const char kUsageMessage[] =
67 "Usage: %s [options]\n"
68 "\n"
69 "Options:\n"
70 " --audio-pipe-name=<pipe> - Sets the pipe name to capture audio on Linux.\n"
71 " --console - Runs the daemon interactively.\n"
72 " --daemon-pipe=<pipe> - Specifies the pipe to connect to the daemon.\n"
73 " --elevate=<binary> - Runs <binary> elevated.\n"
74 " --host-config=<config> - Specifies the host configuration.\n"
75 " --help, -? - Print this message.\n"
76 " --type - Specifies process type.\n"
77 " --version - Prints the host version and exits.\n"
78 " --window-id=<id> - Specifies a window to remote,"
79 " instead of the whole desktop.\n";
81 void Usage(const base::FilePath& program_name) {
82 printf(kUsageMessage, program_name.MaybeAsASCII().c_str());
85 #if defined(OS_WIN)
87 // Runs the binary specified by the command line, elevated.
88 int RunElevated() {
89 const base::CommandLine::SwitchMap& switches =
90 base::CommandLine::ForCurrentProcess()->GetSwitches();
91 base::CommandLine::StringVector args =
92 base::CommandLine::ForCurrentProcess()->GetArgs();
94 // Create the child process command line by copying switches from the current
95 // command line.
96 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
97 for (base::CommandLine::SwitchMap::const_iterator i = switches.begin();
98 i != switches.end(); ++i) {
99 if (i->first != kElevateSwitchName)
100 command_line.AppendSwitchNative(i->first, i->second);
102 for (base::CommandLine::StringVector::const_iterator i = args.begin();
103 i != args.end(); ++i) {
104 command_line.AppendArgNative(*i);
107 // Get the name of the binary to launch.
108 base::FilePath binary =
109 base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
110 kElevateSwitchName);
111 base::CommandLine::StringType parameters =
112 command_line.GetCommandLineString();
114 // Launch the child process requesting elevation.
115 SHELLEXECUTEINFO info;
116 memset(&info, 0, sizeof(info));
117 info.cbSize = sizeof(info);
118 info.lpVerb = L"runas";
119 info.lpFile = binary.value().c_str();
120 info.lpParameters = parameters.c_str();
121 info.nShow = SW_SHOWNORMAL;
123 if (!ShellExecuteEx(&info)) {
124 DWORD exit_code = GetLastError();
125 PLOG(ERROR) << "Unable to launch '" << binary.value() << "'";
126 return exit_code;
129 return kSuccessExitCode;
132 #endif // !defined(OS_WIN)
134 // Select the entry point corresponding to the process type.
135 MainRoutineFn SelectMainRoutine(const std::string& process_type) {
136 MainRoutineFn main_routine = nullptr;
138 if (process_type == kProcessTypeHost) {
139 main_routine = &HostProcessMain;
140 #if defined(OS_WIN)
141 } else if (process_type == kProcessTypeDaemon) {
142 main_routine = &DaemonProcessMain;
143 } else if (process_type == kProcessTypeDesktop) {
144 main_routine = &DesktopProcessMain;
145 } else if (process_type == kProcessTypeRdpDesktopSession) {
146 main_routine = &RdpDesktopSessionMain;
147 #endif // defined(OS_WIN)
150 return main_routine;
153 } // namespace
155 int HostMain(int argc, char** argv) {
156 #if defined(OS_MACOSX)
157 // Needed so we don't leak objects when threads are created.
158 base::mac::ScopedNSAutoreleasePool pool;
159 #endif
161 base::CommandLine::Init(argc, argv);
163 // Initialize Breakpad as early as possible. On Mac the command-line needs to
164 // be initialized first, so that the preference for crash-reporting can be
165 // looked up in the config file.
166 #if defined(REMOTING_ENABLE_BREAKPAD)
167 if (IsUsageStatsAllowed()) {
168 InitializeCrashReporting();
170 #endif // defined(REMOTING_ENABLE_BREAKPAD)
172 // This object instance is required by Chrome code (for example,
173 // LazyInstance, MessageLoop).
174 base::AtExitManager exit_manager;
176 // Enable debug logs.
177 InitHostLogging();
179 // Register and initialize common controls.
180 #if defined(OS_WIN)
181 INITCOMMONCONTROLSEX info;
182 info.dwSize = sizeof(info);
183 info.dwICC = ICC_STANDARD_CLASSES;
184 InitCommonControlsEx(&info);
185 #endif // defined(OS_WIN)
187 // Parse the command line.
188 const base::CommandLine* command_line =
189 base::CommandLine::ForCurrentProcess();
190 if (command_line->HasSwitch(kHelpSwitchName) ||
191 command_line->HasSwitch(kQuestionSwitchName)) {
192 Usage(command_line->GetProgram());
193 return kSuccessExitCode;
196 if (command_line->HasSwitch(kVersionSwitchName)) {
197 printf("%s\n", STRINGIZE(VERSION));
198 return kSuccessExitCode;
201 #if defined(OS_WIN)
202 if (command_line->HasSwitch(kElevateSwitchName)) {
203 return RunElevated();
205 #endif // defined(OS_WIN)
207 // Assume the host process by default.
208 std::string process_type = kProcessTypeHost;
209 if (command_line->HasSwitch(kProcessTypeSwitchName)) {
210 process_type = command_line->GetSwitchValueASCII(kProcessTypeSwitchName);
213 MainRoutineFn main_routine = SelectMainRoutine(process_type);
214 if (!main_routine) {
215 fprintf(stderr, "Unknown process type '%s' specified.",
216 process_type.c_str());
217 Usage(command_line->GetProgram());
218 return kUsageExitCode;
221 // Required to find the ICU data file, used by some file_util routines.
222 base::i18n::InitializeICU();
224 remoting::LoadResources("");
226 // Invoke the entry point.
227 int exit_code = main_routine();
228 if (exit_code == kUsageExitCode) {
229 Usage(command_line->GetProgram());
232 remoting::UnloadResources();
234 return exit_code;
237 } // namespace remoting
239 #if !defined(OS_WIN)
240 int main(int argc, char** argv) {
241 return remoting::HostMain(argc, argv);
243 #endif // !defined(OS_WIN)