Introduced IDR_SIGNIN_INTERNALS_INDEX_* strings to grit_whitelist.txt
[chromium-blink-merge.git] / remoting / host / daemon_process_win.cc
bloba365f3ed99c6f562c2ddc05c45209e94b4b33100
1 // Copyright (c) 2012 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 #include "remoting/host/daemon_process.h"
7 #include "base/base_switches.h"
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/process/process.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/time/time.h"
18 #include "base/timer/timer.h"
19 #include "base/win/scoped_handle.h"
20 #include "ipc/ipc_message.h"
21 #include "ipc/ipc_message_macros.h"
22 #include "remoting/base/auto_thread_task_runner.h"
23 #include "remoting/base/scoped_sc_handle_win.h"
24 #include "remoting/host/branding.h"
25 #include "remoting/host/chromoting_messages.h"
26 #include "remoting/host/desktop_session_win.h"
27 #include "remoting/host/host_exit_codes.h"
28 #include "remoting/host/host_main.h"
29 #include "remoting/host/ipc_constants.h"
30 #include "remoting/host/screen_resolution.h"
31 #include "remoting/host/win/launch_process_with_token.h"
32 #include "remoting/host/win/unprivileged_process_delegate.h"
33 #include "remoting/host/win/worker_process_launcher.h"
35 using base::win::ScopedHandle;
36 using base::TimeDelta;
38 namespace remoting {
40 class WtsTerminalMonitor;
42 // The command line parameters that should be copied from the service's command
43 // line to the host process.
44 const char* kCopiedSwitchNames[] = { switches::kV, switches::kVModule };
46 class DaemonProcessWin : public DaemonProcess {
47 public:
48 DaemonProcessWin(
49 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
50 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
51 const base::Closure& stopped_callback);
52 virtual ~DaemonProcessWin();
54 // WorkerProcessIpcDelegate implementation.
55 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
56 virtual void OnPermanentError(int exit_code) OVERRIDE;
58 // DaemonProcess overrides.
59 virtual void SendToNetwork(IPC::Message* message) OVERRIDE;
60 virtual bool OnDesktopSessionAgentAttached(
61 int terminal_id,
62 base::ProcessHandle desktop_process,
63 IPC::PlatformFileForTransit desktop_pipe) OVERRIDE;
65 protected:
66 // DaemonProcess implementation.
67 virtual scoped_ptr<DesktopSession> DoCreateDesktopSession(
68 int terminal_id,
69 const ScreenResolution& resolution,
70 bool virtual_terminal) OVERRIDE;
71 virtual void DoCrashNetworkProcess(
72 const tracked_objects::Location& location) OVERRIDE;
73 virtual void LaunchNetworkProcess() OVERRIDE;
75 // Changes the service start type to 'manual'.
76 void DisableAutoStart();
78 private:
79 scoped_ptr<WorkerProcessLauncher> network_launcher_;
81 // Handle of the network process.
82 ScopedHandle network_process_;
84 DISALLOW_COPY_AND_ASSIGN(DaemonProcessWin);
87 DaemonProcessWin::DaemonProcessWin(
88 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
89 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
90 const base::Closure& stopped_callback)
91 : DaemonProcess(caller_task_runner, io_task_runner, stopped_callback) {
94 DaemonProcessWin::~DaemonProcessWin() {
97 void DaemonProcessWin::OnChannelConnected(int32 peer_pid) {
98 // Obtain the handle of the network process.
99 network_process_.Set(OpenProcess(PROCESS_DUP_HANDLE, false, peer_pid));
100 if (!network_process_.IsValid()) {
101 CrashNetworkProcess(FROM_HERE);
102 return;
105 DaemonProcess::OnChannelConnected(peer_pid);
108 void DaemonProcessWin::OnPermanentError(int exit_code) {
109 // Change the service start type to 'manual' if the host has been deleted
110 // remotely. This way the host will not be started every time the machine
111 // boots until the user re-enable it again.
112 if (exit_code == kInvalidHostIdExitCode)
113 DisableAutoStart();
115 DaemonProcess::OnPermanentError(exit_code);
118 void DaemonProcessWin::SendToNetwork(IPC::Message* message) {
119 if (network_launcher_) {
120 network_launcher_->Send(message);
121 } else {
122 delete message;
126 bool DaemonProcessWin::OnDesktopSessionAgentAttached(
127 int terminal_id,
128 base::ProcessHandle desktop_process,
129 IPC::PlatformFileForTransit desktop_pipe) {
130 // Prepare |desktop_process| handle for sending over to the network process.
131 base::ProcessHandle desktop_process_for_transit;
132 if (!DuplicateHandle(GetCurrentProcess(),
133 desktop_process,
134 network_process_,
135 &desktop_process_for_transit,
137 FALSE,
138 DUPLICATE_SAME_ACCESS)) {
139 LOG_GETLASTERROR(ERROR) << "Failed to duplicate the desktop process handle";
140 return false;
143 // |desktop_pipe| is a handle in the desktop process. It will be duplicated
144 // by the network process directly from the desktop process.
145 SendToNetwork(new ChromotingDaemonNetworkMsg_DesktopAttached(
146 terminal_id, desktop_process_for_transit, desktop_pipe));
147 return true;
150 scoped_ptr<DesktopSession> DaemonProcessWin::DoCreateDesktopSession(
151 int terminal_id,
152 const ScreenResolution& resolution,
153 bool virtual_terminal) {
154 DCHECK(caller_task_runner()->BelongsToCurrentThread());
156 if (virtual_terminal) {
157 return DesktopSessionWin::CreateForVirtualTerminal(
158 caller_task_runner(), io_task_runner(), this, terminal_id, resolution);
159 } else {
160 return DesktopSessionWin::CreateForConsole(
161 caller_task_runner(), io_task_runner(), this, terminal_id, resolution);
165 void DaemonProcessWin::DoCrashNetworkProcess(
166 const tracked_objects::Location& location) {
167 DCHECK(caller_task_runner()->BelongsToCurrentThread());
169 network_launcher_->Crash(location);
172 void DaemonProcessWin::LaunchNetworkProcess() {
173 DCHECK(caller_task_runner()->BelongsToCurrentThread());
174 DCHECK(!network_launcher_);
176 // Construct the host binary name.
177 base::FilePath host_binary;
178 if (!GetInstalledBinaryPath(kHostBinaryName, &host_binary)) {
179 Stop();
180 return;
183 scoped_ptr<CommandLine> target(new CommandLine(host_binary));
184 target->AppendSwitchASCII(kProcessTypeSwitchName, kProcessTypeHost);
185 target->CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
186 kCopiedSwitchNames,
187 arraysize(kCopiedSwitchNames));
189 scoped_ptr<UnprivilegedProcessDelegate> delegate(
190 new UnprivilegedProcessDelegate(io_task_runner(), target.Pass()));
191 network_launcher_.reset(new WorkerProcessLauncher(delegate.Pass(), this));
194 scoped_ptr<DaemonProcess> DaemonProcess::Create(
195 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
196 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
197 const base::Closure& stopped_callback) {
198 scoped_ptr<DaemonProcessWin> daemon_process(
199 new DaemonProcessWin(caller_task_runner, io_task_runner,
200 stopped_callback));
201 daemon_process->Initialize();
202 return daemon_process.PassAs<DaemonProcess>();
205 void DaemonProcessWin::DisableAutoStart() {
206 ScopedScHandle scmanager(
207 OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE,
208 SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE));
209 if (!scmanager.IsValid()) {
210 LOG_GETLASTERROR(INFO)
211 << "Failed to connect to the service control manager";
212 return;
215 DWORD desired_access = SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS;
216 ScopedScHandle service(
217 OpenService(scmanager, kWindowsServiceName, desired_access));
218 if (!service.IsValid()) {
219 LOG_GETLASTERROR(INFO)
220 << "Failed to open to the '" << kWindowsServiceName << "' service";
221 return;
224 // Change the service start type to 'manual'. All |NULL| parameters below mean
225 // that there is no change to the corresponding service parameter.
226 if (!ChangeServiceConfig(service,
227 SERVICE_NO_CHANGE,
228 SERVICE_DEMAND_START,
229 SERVICE_NO_CHANGE,
230 NULL,
231 NULL,
232 NULL,
233 NULL,
234 NULL,
235 NULL,
236 NULL)) {
237 LOG_GETLASTERROR(INFO)
238 << "Failed to change the '" << kWindowsServiceName
239 << "'service start type to 'manual'";
243 } // namespace remoting