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