Revert of Remove OneClickSigninHelper since it is no longer used. (patchset #5 id...
[chromium-blink-merge.git] / remoting / host / remoting_me2me_host.cc
blobc426a655f96e0dc14c54b739ae08da1e1f36fca4
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.
4 //
5 // This file implements a standalone host process for Me2Me.
7 #include <string>
9 #include "base/at_exit.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/command_line.h"
13 #include "base/debug/alias.h"
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/threading/thread.h"
23 #include "build/build_config.h"
24 #include "crypto/nss_util.h"
25 #include "ipc/ipc_channel.h"
26 #include "ipc/ipc_channel_proxy.h"
27 #include "ipc/ipc_listener.h"
28 #include "media/base/media.h"
29 #include "net/base/network_change_notifier.h"
30 #include "net/socket/client_socket_factory.h"
31 #include "net/socket/ssl_server_socket.h"
32 #include "net/url_request/url_fetcher.h"
33 #include "policy/policy_constants.h"
34 #include "remoting/base/auto_thread_task_runner.h"
35 #include "remoting/base/breakpad.h"
36 #include "remoting/base/constants.h"
37 #include "remoting/base/logging.h"
38 #include "remoting/base/rsa_key_pair.h"
39 #include "remoting/base/service_urls.h"
40 #include "remoting/base/util.h"
41 #include "remoting/host/branding.h"
42 #include "remoting/host/chromoting_host.h"
43 #include "remoting/host/chromoting_host_context.h"
44 #include "remoting/host/chromoting_messages.h"
45 #include "remoting/host/config_file_watcher.h"
46 #include "remoting/host/config_watcher.h"
47 #include "remoting/host/desktop_environment.h"
48 #include "remoting/host/desktop_session_connector.h"
49 #include "remoting/host/host_change_notification_listener.h"
50 #include "remoting/host/host_config.h"
51 #include "remoting/host/host_event_logger.h"
52 #include "remoting/host/host_exit_codes.h"
53 #include "remoting/host/host_main.h"
54 #include "remoting/host/host_signaling_manager.h"
55 #include "remoting/host/host_status_logger.h"
56 #include "remoting/host/ipc_constants.h"
57 #include "remoting/host/ipc_desktop_environment.h"
58 #include "remoting/host/ipc_host_event_logger.h"
59 #include "remoting/host/logging.h"
60 #include "remoting/host/me2me_desktop_environment.h"
61 #include "remoting/host/pairing_registry_delegate.h"
62 #include "remoting/host/policy_watcher.h"
63 #include "remoting/host/session_manager_factory.h"
64 #include "remoting/host/shutdown_watchdog.h"
65 #include "remoting/host/signaling_connector.h"
66 #include "remoting/host/single_window_desktop_environment.h"
67 #include "remoting/host/third_party_auth_config.h"
68 #include "remoting/host/token_validator_factory_impl.h"
69 #include "remoting/host/usage_stats_consent.h"
70 #include "remoting/host/username.h"
71 #include "remoting/host/video_frame_recorder_host_extension.h"
72 #include "remoting/protocol/me2me_host_authenticator_factory.h"
73 #include "remoting/protocol/network_settings.h"
74 #include "remoting/protocol/pairing_registry.h"
75 #include "remoting/protocol/port_range.h"
76 #include "remoting/protocol/token_validator.h"
77 #include "remoting/signaling/xmpp_signal_strategy.h"
79 #if defined(OS_POSIX)
80 #include <signal.h>
81 #include <sys/types.h>
82 #include <unistd.h>
83 #include "base/file_descriptor_posix.h"
84 #include "remoting/host/pam_authorization_factory_posix.h"
85 #include "remoting/host/posix/signal_handler.h"
86 #endif // defined(OS_POSIX)
88 #if defined(OS_MACOSX)
89 #include "base/mac/scoped_cftyperef.h"
90 #endif // defined(OS_MACOSX)
92 #if defined(OS_LINUX)
93 #include <gtk/gtk.h>
94 #include <X11/Xlib.h>
95 #include "remoting/host/audio_capturer_linux.h"
96 #endif // defined(OS_LINUX)
98 #if defined(OS_WIN)
99 #include <commctrl.h>
100 #include "base/win/registry.h"
101 #include "base/win/scoped_handle.h"
102 #include "remoting/host/pairing_registry_delegate_win.h"
103 #include "remoting/host/win/session_desktop_environment.h"
104 #endif // defined(OS_WIN)
106 using remoting::protocol::PairingRegistry;
107 using remoting::protocol::NetworkSettings;
109 #if defined(USE_REMOTING_MACOSX_INTERNAL)
110 #include "remoting/tools/internal/internal_mac-inl.h"
111 #endif
113 namespace {
115 // This is used for tagging system event logs.
116 const char kApplicationName[] = "chromoting";
118 #if defined(OS_LINUX)
119 // The command line switch used to pass name of the pipe to capture audio on
120 // linux.
121 const char kAudioPipeSwitchName[] = "audio-pipe-name";
123 // The command line switch used to pass name of the unix domain socket used to
124 // listen for gnubby requests.
125 const char kAuthSocknameSwitchName[] = "ssh-auth-sockname";
126 #endif // defined(OS_LINUX)
128 // The command line switch used by the parent to request the host to signal it
129 // when it is successfully started.
130 const char kSignalParentSwitchName[] = "signal-parent";
132 // Command line switch used to enable VP9 encoding.
133 const char kEnableVp9SwitchName[] = "enable-vp9";
135 // Command line switch used to enable and configure the frame-recorder.
136 const char kFrameRecorderBufferKbName[] = "frame-recorder-buffer-kb";
138 // Value used for --host-config option to indicate that the path must be read
139 // from stdin.
140 const char kStdinConfigPath[] = "-";
142 const char kWindowIdSwitchName[] = "window-id";
144 // Maximum time to wait for clean shutdown to occur, before forcing termination
145 // of the process.
146 const int kShutdownTimeoutSeconds = 15;
148 // Maximum time to wait for reporting host-offline-reason to the service,
149 // before continuing normal process shutdown.
150 const int kHostOfflineReasonTimeoutSeconds = 10;
152 // Host offline reasons not associated with shutting down the host process
153 // and therefore not expressible through HostExitCodes enum.
154 const char kHostOfflineReasonPolicyReadError[] = "POLICY_READ_ERROR";
155 const char kHostOfflineReasonPolicyChangeRequiresRestart[] =
156 "POLICY_CHANGE_REQUIRES_RESTART";
158 } // namespace
160 namespace remoting {
162 class HostProcess : public ConfigWatcher::Delegate,
163 public HostSignalingManager::Listener,
164 public HostChangeNotificationListener::Listener,
165 public IPC::Listener,
166 public base::RefCountedThreadSafe<HostProcess> {
167 public:
168 // |shutdown_watchdog| is armed when shutdown is started, and should be kept
169 // alive as long as possible until the process exits (since destroying the
170 // watchdog disarms it).
171 HostProcess(scoped_ptr<ChromotingHostContext> context,
172 int* exit_code_out,
173 ShutdownWatchdog* shutdown_watchdog);
175 // ConfigWatcher::Delegate interface.
176 void OnConfigUpdated(const std::string& serialized_config) override;
177 void OnConfigWatcherError() override;
179 // IPC::Listener implementation.
180 bool OnMessageReceived(const IPC::Message& message) override;
181 void OnChannelError() override;
183 // HostChangeNotificationListener::Listener overrides.
184 void OnHostDeleted() override;
186 // Handler of the ChromotingDaemonNetworkMsg_InitializePairingRegistry IPC
187 // message.
188 void OnInitializePairingRegistry(
189 IPC::PlatformFileForTransit privileged_key,
190 IPC::PlatformFileForTransit unprivileged_key);
192 private:
193 // See SetState method for a list of allowed state transitions.
194 enum HostState {
195 // Waiting for valid config and policies to be read from the disk.
196 // Either the host process has just been started, or it is trying to start
197 // again after temporarily going offline due to policy change or error.
198 HOST_STARTING,
200 // Host is started and running.
201 HOST_STARTED,
203 // Host is sending offline reason, before trying to restart.
204 HOST_GOING_OFFLINE_TO_RESTART,
206 // Host is sending offline reason, before shutting down.
207 HOST_GOING_OFFLINE_TO_STOP,
209 // Host has been stopped (host process will end soon).
210 HOST_STOPPED,
213 enum PolicyState {
214 // Cannot start the host, because a valid policy has not been read yet.
215 POLICY_INITIALIZING,
217 // Policy was loaded successfully.
218 POLICY_LOADED,
220 // Policy error was detected, and we haven't yet sent out a
221 // host-offline-reason (i.e. because we haven't yet read the config).
222 POLICY_ERROR_REPORT_PENDING,
224 // Policy error was detected, and we have sent out a host-offline-reason.
225 POLICY_ERROR_REPORTED,
228 friend class base::RefCountedThreadSafe<HostProcess>;
229 ~HostProcess() override;
231 void SetState(HostState target_state);
233 void StartOnNetworkThread();
235 #if defined(OS_POSIX)
236 // Callback passed to RegisterSignalHandler() to handle SIGTERM events.
237 void SigTermHandler(int signal_number);
238 #endif
240 // Called to initialize resources on the UI thread.
241 void StartOnUiThread();
243 // Initializes IPC control channel and config file path from |cmd_line|.
244 // Called on the UI thread.
245 bool InitWithCommandLine(const base::CommandLine* cmd_line);
247 // Called on the UI thread to start monitoring the configuration file.
248 void StartWatchingConfigChanges();
250 // Called on the network thread to set the host's Authenticator factory.
251 void CreateAuthenticatorFactory();
253 // Tear down resources that run on the UI thread.
254 void ShutdownOnUiThread();
256 // Applies the host config, returning true if successful.
257 bool ApplyConfig(const base::DictionaryValue& config);
259 // Handles policy updates, by calling On*PolicyUpdate methods.
260 void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies);
261 void OnPolicyError();
262 void ReportPolicyErrorAndRestartHost();
263 void ApplyHostDomainPolicy();
264 void ApplyUsernamePolicy();
265 bool OnHostDomainPolicyUpdate(base::DictionaryValue* policies);
266 bool OnUsernamePolicyUpdate(base::DictionaryValue* policies);
267 bool OnNatPolicyUpdate(base::DictionaryValue* policies);
268 bool OnRelayPolicyUpdate(base::DictionaryValue* policies);
269 bool OnUdpPortPolicyUpdate(base::DictionaryValue* policies);
270 bool OnCurtainPolicyUpdate(base::DictionaryValue* policies);
271 bool OnHostTalkGadgetPrefixPolicyUpdate(base::DictionaryValue* policies);
272 bool OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies);
273 bool OnPairingPolicyUpdate(base::DictionaryValue* policies);
274 bool OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies);
276 scoped_ptr<HostSignalingManager> CreateHostSignalingManager();
278 void StartHostIfReady();
279 void StartHost();
281 // Overrides for HostSignalingManager::Listener interface.
282 void OnHeartbeatSuccessful() override;
283 void OnUnknownHostIdError() override;
284 void OnAuthFailed() override;
286 void RestartHost(const std::string& host_offline_reason);
287 void ShutdownHost(HostExitCodes exit_code);
289 // Helper methods doing the work needed by RestartHost and ShutdownHost.
290 void GoOffline(const std::string& host_offline_reason);
291 void OnHostOfflineReasonAck(bool success);
293 #if defined(OS_WIN)
294 // Initializes the pairing registry on Windows. This should be invoked on the
295 // network thread.
296 void InitializePairingRegistry(
297 IPC::PlatformFileForTransit privileged_key,
298 IPC::PlatformFileForTransit unprivileged_key);
299 #endif // defined(OS_WIN)
301 // Crashes the process in response to a daemon's request. The daemon passes
302 // the location of the code that detected the fatal error resulted in this
303 // request.
304 void OnCrash(const std::string& function_name,
305 const std::string& file_name,
306 const int& line_number);
308 scoped_ptr<ChromotingHostContext> context_;
310 // Accessed on the UI thread.
311 scoped_ptr<IPC::ChannelProxy> daemon_channel_;
313 // XMPP server/remoting bot configuration (initialized from the command line).
314 XmppSignalStrategy::XmppServerConfig xmpp_server_config_;
315 std::string directory_bot_jid_;
317 // Created on the UI thread but used from the network thread.
318 base::FilePath host_config_path_;
319 std::string host_config_;
320 scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
322 // Accessed on the network thread.
323 HostState state_;
325 scoped_ptr<ConfigWatcher> config_watcher_;
327 std::string host_id_;
328 protocol::SharedSecretHash host_secret_hash_;
329 scoped_refptr<RsaKeyPair> key_pair_;
330 std::string oauth_refresh_token_;
331 std::string serialized_config_;
332 std::string host_owner_;
333 std::string host_owner_email_;
334 bool use_service_account_;
335 bool enable_vp9_;
336 int64_t frame_recorder_buffer_size_;
338 scoped_ptr<PolicyWatcher> policy_watcher_;
339 PolicyState policy_state_;
340 std::string host_domain_;
341 bool host_username_match_required_;
342 bool allow_nat_traversal_;
343 bool allow_relay_;
344 PortRange udp_port_range_;
345 std::string talkgadget_prefix_;
346 bool allow_pairing_;
348 bool curtain_required_;
349 ThirdPartyAuthConfig third_party_auth_config_;
350 bool enable_gnubby_auth_;
352 // Boolean to change flow, where necessary, if we're
353 // capturing a window instead of the entire desktop.
354 bool enable_window_capture_;
356 // Used to specify which window to stream, if enabled.
357 webrtc::WindowId window_id_;
359 // Used to send heartbeats while running, and the reason for going offline
360 // when shutting down.
361 scoped_ptr<HostSignalingManager> host_signaling_manager_;
363 scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_;
364 scoped_ptr<HostStatusLogger> host_status_logger_;
365 scoped_ptr<HostEventLogger> host_event_logger_;
367 scoped_ptr<ChromotingHost> host_;
369 // Used to keep this HostProcess alive until it is shutdown.
370 scoped_refptr<HostProcess> self_;
372 #if defined(REMOTING_MULTI_PROCESS)
373 DesktopSessionConnector* desktop_session_connector_;
374 #endif // defined(REMOTING_MULTI_PROCESS)
376 int* exit_code_out_;
377 bool signal_parent_;
379 scoped_refptr<PairingRegistry> pairing_registry_;
381 ShutdownWatchdog* shutdown_watchdog_;
383 DISALLOW_COPY_AND_ASSIGN(HostProcess);
386 HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context,
387 int* exit_code_out,
388 ShutdownWatchdog* shutdown_watchdog)
389 : context_(context.Pass()),
390 state_(HOST_STARTING),
391 use_service_account_(false),
392 enable_vp9_(false),
393 frame_recorder_buffer_size_(0),
394 policy_state_(POLICY_INITIALIZING),
395 host_username_match_required_(false),
396 allow_nat_traversal_(true),
397 allow_relay_(true),
398 allow_pairing_(true),
399 curtain_required_(false),
400 enable_gnubby_auth_(false),
401 enable_window_capture_(false),
402 window_id_(0),
403 #if defined(REMOTING_MULTI_PROCESS)
404 desktop_session_connector_(nullptr),
405 #endif // defined(REMOTING_MULTI_PROCESS)
406 self_(this),
407 exit_code_out_(exit_code_out),
408 signal_parent_(false),
409 shutdown_watchdog_(shutdown_watchdog) {
410 StartOnUiThread();
413 HostProcess::~HostProcess() {
414 // Verify that UI components have been torn down.
415 DCHECK(!config_watcher_);
416 DCHECK(!daemon_channel_);
417 DCHECK(!desktop_environment_factory_);
419 // We might be getting deleted on one of the threads the |host_context| owns,
420 // so we need to post it back to the caller thread to safely join & delete the
421 // threads it contains. This will go away when we move to AutoThread.
422 // |context_release()| will null |context_| before the method is invoked, so
423 // we need to pull out the task-runner on which to call DeleteSoon first.
424 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
425 context_->ui_task_runner();
426 task_runner->DeleteSoon(FROM_HERE, context_.release());
429 bool HostProcess::InitWithCommandLine(const base::CommandLine* cmd_line) {
430 #if defined(REMOTING_MULTI_PROCESS)
431 // Parse the handle value and convert it to a handle/file descriptor.
432 std::string channel_name =
433 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
435 int pipe_handle = 0;
436 if (channel_name.empty() ||
437 !base::StringToInt(channel_name, &pipe_handle)) {
438 LOG(ERROR) << "Invalid '" << kDaemonPipeSwitchName
439 << "' value: " << channel_name;
440 return false;
443 #if defined(OS_WIN)
444 base::win::ScopedHandle pipe(reinterpret_cast<HANDLE>(pipe_handle));
445 IPC::ChannelHandle channel_handle(pipe.Get());
446 #elif defined(OS_POSIX)
447 base::FileDescriptor pipe(pipe_handle, true);
448 IPC::ChannelHandle channel_handle(channel_name, pipe);
449 #endif // defined(OS_POSIX)
451 // Connect to the daemon process.
452 daemon_channel_ = IPC::ChannelProxy::Create(channel_handle,
453 IPC::Channel::MODE_CLIENT,
454 this,
455 context_->network_task_runner());
456 #else // !defined(REMOTING_MULTI_PROCESS)
457 // Connect to the daemon process.
458 std::string channel_name =
459 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
460 if (!channel_name.empty()) {
461 daemon_channel_ =
462 IPC::ChannelProxy::Create(channel_name,
463 IPC::Channel::MODE_CLIENT,
464 this,
465 context_->network_task_runner().get());
468 if (cmd_line->HasSwitch(kHostConfigSwitchName)) {
469 host_config_path_ = cmd_line->GetSwitchValuePath(kHostConfigSwitchName);
471 // Read config from stdin if necessary.
472 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
473 char buf[4096];
474 size_t len;
475 while ((len = fread(buf, 1, sizeof(buf), stdin)) > 0) {
476 host_config_.append(buf, len);
479 } else {
480 base::FilePath default_config_dir = remoting::GetConfigDir();
481 host_config_path_ = default_config_dir.Append(kDefaultHostConfigFile);
484 if (host_config_path_ != base::FilePath(kStdinConfigPath) &&
485 !base::PathExists(host_config_path_)) {
486 LOG(ERROR) << "Can't find host config at " << host_config_path_.value();
487 return false;
489 #endif // !defined(REMOTING_MULTI_PROCESS)
491 // Ignore certificate requests - the host currently has no client certificate
492 // support, so ignoring certificate requests allows connecting to servers that
493 // request, but don't require, a certificate (optional client authentication).
494 net::URLFetcher::SetIgnoreCertificateRequests(true);
496 ServiceUrls* service_urls = ServiceUrls::GetInstance();
497 bool xmpp_server_valid = net::ParseHostAndPort(
498 service_urls->xmpp_server_address(),
499 &xmpp_server_config_.host, &xmpp_server_config_.port);
500 if (!xmpp_server_valid) {
501 LOG(ERROR) << "Invalid XMPP server: " <<
502 service_urls->xmpp_server_address();
503 return false;
505 xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls();
506 directory_bot_jid_ = service_urls->directory_bot_jid();
508 signal_parent_ = cmd_line->HasSwitch(kSignalParentSwitchName);
510 enable_window_capture_ = cmd_line->HasSwitch(kWindowIdSwitchName);
511 if (enable_window_capture_) {
513 #if defined(OS_LINUX) || defined(OS_WIN)
514 LOG(WARNING) << "Window capturing is not fully supported on Linux or "
515 "Windows.";
516 #endif // defined(OS_LINUX) || defined(OS_WIN)
518 // uint32_t is large enough to hold window IDs on all platforms.
519 uint32_t window_id;
520 if (base::StringToUint(
521 cmd_line->GetSwitchValueASCII(kWindowIdSwitchName),
522 &window_id)) {
523 window_id_ = static_cast<webrtc::WindowId>(window_id);
524 } else {
525 LOG(ERROR) << "Window with window id: " << window_id_
526 << " not found. Shutting down host.";
527 return false;
530 return true;
533 void HostProcess::OnConfigUpdated(
534 const std::string& serialized_config) {
535 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
536 context_->network_task_runner()->PostTask(FROM_HERE,
537 base::Bind(&HostProcess::OnConfigUpdated, this, serialized_config));
538 return;
541 // Filter out duplicates.
542 if (serialized_config_ == serialized_config)
543 return;
545 HOST_LOG << "Processing new host configuration.";
547 serialized_config_ = serialized_config;
548 scoped_ptr<base::DictionaryValue> config(
549 HostConfigFromJson(serialized_config));
550 if (!config) {
551 LOG(ERROR) << "Invalid configuration.";
552 ShutdownHost(kInvalidHostConfigurationExitCode);
553 return;
556 if (!ApplyConfig(*config)) {
557 LOG(ERROR) << "Failed to apply the configuration.";
558 ShutdownHost(kInvalidHostConfigurationExitCode);
559 return;
562 if (state_ == HOST_STARTING) {
563 StartHostIfReady();
564 } else if (state_ == HOST_STARTED) {
565 // Reapply policies that could be affected by a new config.
566 DCHECK_EQ(policy_state_, POLICY_LOADED);
567 ApplyHostDomainPolicy();
568 ApplyUsernamePolicy();
570 // TODO(sergeyu): Here we assume that PIN is the only part of the config
571 // that may change while the service is running. Change ApplyConfig() to
572 // detect other changes in the config and restart host if necessary here.
573 CreateAuthenticatorFactory();
577 void HostProcess::OnConfigWatcherError() {
578 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
579 ShutdownHost(kInvalidHostConfigurationExitCode);
582 // Allowed state transitions (enforced via DCHECKs in SetState method):
583 // STARTING->STARTED (once we have valid config + policy)
584 // STARTING->GOING_OFFLINE_TO_STOP
585 // STARTING->GOING_OFFLINE_TO_RESTART
586 // STARTED->GOING_OFFLINE_TO_STOP
587 // STARTED->GOING_OFFLINE_TO_RESTART
588 // GOING_OFFLINE_TO_RESTART->GOING_OFFLINE_TO_STOP
589 // GOING_OFFLINE_TO_RESTART->STARTING (after OnHostOfflineReasonAck)
590 // GOING_OFFLINE_TO_STOP->STOPPED (after OnHostOfflineReasonAck)
592 // |host_| must be not-null in STARTED state and nullptr in all other states
593 // (although this invariant can be temporarily violated when doing
594 // synchronous processing on the networking thread).
595 void HostProcess::SetState(HostState target_state) {
596 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
598 // DCHECKs below enforce state allowed transitions listed in HostState.
599 switch (state_) {
600 case HOST_STARTING:
601 DCHECK((target_state == HOST_STARTED) ||
602 (target_state == HOST_GOING_OFFLINE_TO_STOP) ||
603 (target_state == HOST_GOING_OFFLINE_TO_RESTART))
604 << state_ << " -> " << target_state;
605 break;
606 case HOST_STARTED:
607 DCHECK((target_state == HOST_GOING_OFFLINE_TO_STOP) ||
608 (target_state == HOST_GOING_OFFLINE_TO_RESTART))
609 << state_ << " -> " << target_state;
610 break;
611 case HOST_GOING_OFFLINE_TO_RESTART:
612 DCHECK((target_state == HOST_GOING_OFFLINE_TO_STOP) ||
613 (target_state == HOST_STARTING))
614 << state_ << " -> " << target_state;
615 break;
616 case HOST_GOING_OFFLINE_TO_STOP:
617 DCHECK_EQ(target_state, HOST_STOPPED);
618 break;
619 case HOST_STOPPED: // HOST_STOPPED is a terminal state.
620 default:
621 NOTREACHED() << state_ << " -> " << target_state;
622 break;
624 state_ = target_state;
627 void HostProcess::StartOnNetworkThread() {
628 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
630 #if !defined(REMOTING_MULTI_PROCESS)
631 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
632 // Process config we've read from stdin.
633 OnConfigUpdated(host_config_);
634 } else {
635 // Start watching the host configuration file.
636 config_watcher_.reset(new ConfigFileWatcher(context_->network_task_runner(),
637 context_->file_task_runner(),
638 host_config_path_));
639 config_watcher_->Watch(this);
641 #endif // !defined(REMOTING_MULTI_PROCESS)
643 #if defined(OS_POSIX)
644 remoting::RegisterSignalHandler(
645 SIGTERM,
646 base::Bind(&HostProcess::SigTermHandler, base::Unretained(this)));
647 #endif // defined(OS_POSIX)
650 #if defined(OS_POSIX)
651 void HostProcess::SigTermHandler(int signal_number) {
652 DCHECK(signal_number == SIGTERM);
653 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
654 HOST_LOG << "Caught SIGTERM: Shutting down...";
655 ShutdownHost(kSuccessExitCode);
657 #endif // OS_POSIX
659 void HostProcess::CreateAuthenticatorFactory() {
660 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
662 if (state_ != HOST_STARTED)
663 return;
665 std::string local_certificate = key_pair_->GenerateCertificate();
666 if (local_certificate.empty()) {
667 LOG(ERROR) << "Failed to generate host certificate.";
668 ShutdownHost(kInitializationFailed);
669 return;
672 scoped_ptr<protocol::AuthenticatorFactory> factory;
674 if (third_party_auth_config_.is_null()) {
675 scoped_refptr<PairingRegistry> pairing_registry;
676 if (allow_pairing_) {
677 // On Windows |pairing_registry_| is initialized in
678 // InitializePairingRegistry().
679 #if !defined(OS_WIN)
680 if (!pairing_registry_) {
681 scoped_ptr<PairingRegistry::Delegate> delegate =
682 CreatePairingRegistryDelegate();
684 if (delegate)
685 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
686 delegate.Pass());
688 #endif // defined(OS_WIN)
690 pairing_registry = pairing_registry_;
693 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
694 use_service_account_, host_owner_, local_certificate, key_pair_,
695 host_secret_hash_, pairing_registry);
697 host_->set_pairing_registry(pairing_registry);
698 } else {
699 DCHECK(third_party_auth_config_.token_url.is_valid());
700 DCHECK(third_party_auth_config_.token_validation_url.is_valid());
702 scoped_ptr<protocol::TokenValidatorFactory> token_validator_factory(
703 new TokenValidatorFactoryImpl(
704 third_party_auth_config_,
705 key_pair_, context_->url_request_context_getter()));
706 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
707 use_service_account_, host_owner_, local_certificate, key_pair_,
708 token_validator_factory.Pass());
711 #if defined(OS_POSIX)
712 // On Linux and Mac, perform a PAM authorization step after authentication.
713 factory.reset(new PamAuthorizationFactory(factory.Pass()));
714 #endif
715 host_->SetAuthenticatorFactory(factory.Pass());
718 // IPC::Listener implementation.
719 bool HostProcess::OnMessageReceived(const IPC::Message& message) {
720 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
722 #if defined(REMOTING_MULTI_PROCESS)
723 bool handled = true;
724 IPC_BEGIN_MESSAGE_MAP(HostProcess, message)
725 IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash)
726 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration,
727 OnConfigUpdated)
728 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_InitializePairingRegistry,
729 OnInitializePairingRegistry)
730 IPC_MESSAGE_FORWARD(
731 ChromotingDaemonNetworkMsg_DesktopAttached,
732 desktop_session_connector_,
733 DesktopSessionConnector::OnDesktopSessionAgentAttached)
734 IPC_MESSAGE_FORWARD(ChromotingDaemonNetworkMsg_TerminalDisconnected,
735 desktop_session_connector_,
736 DesktopSessionConnector::OnTerminalDisconnected)
737 IPC_MESSAGE_UNHANDLED(handled = false)
738 IPC_END_MESSAGE_MAP()
740 CHECK(handled) << "Received unexpected IPC type: " << message.type();
741 return handled;
743 #else // !defined(REMOTING_MULTI_PROCESS)
744 return false;
745 #endif // !defined(REMOTING_MULTI_PROCESS)
748 void HostProcess::OnChannelError() {
749 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
751 // Shutdown the host if the daemon process disconnects the IPC channel.
752 context_->network_task_runner()->PostTask(
753 FROM_HERE,
754 base::Bind(&HostProcess::ShutdownHost, this, kSuccessExitCode));
757 void HostProcess::StartOnUiThread() {
758 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
760 if (!InitWithCommandLine(base::CommandLine::ForCurrentProcess())) {
761 // Shutdown the host if the command line is invalid.
762 context_->network_task_runner()->PostTask(
763 FROM_HERE, base::Bind(&HostProcess::ShutdownHost, this,
764 kUsageExitCode));
765 return;
768 policy_watcher_ =
769 PolicyWatcher::Create(nullptr, context_->file_task_runner());
770 policy_watcher_->StartWatching(
771 base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)),
772 base::Bind(&HostProcess::OnPolicyError, base::Unretained(this)));
774 #if defined(OS_LINUX)
775 // If an audio pipe is specific on the command-line then initialize
776 // AudioCapturerLinux to capture from it.
777 base::FilePath audio_pipe_name = base::CommandLine::ForCurrentProcess()->
778 GetSwitchValuePath(kAudioPipeSwitchName);
779 if (!audio_pipe_name.empty()) {
780 remoting::AudioCapturerLinux::InitializePipeReader(
781 context_->audio_task_runner(), audio_pipe_name);
784 base::FilePath gnubby_socket_name = base::CommandLine::ForCurrentProcess()->
785 GetSwitchValuePath(kAuthSocknameSwitchName);
786 if (!gnubby_socket_name.empty())
787 remoting::GnubbyAuthHandler::SetGnubbySocketName(gnubby_socket_name);
788 #endif // defined(OS_LINUX)
790 // Create a desktop environment factory appropriate to the build type &
791 // platform.
792 #if defined(OS_WIN)
793 IpcDesktopEnvironmentFactory* desktop_environment_factory =
794 new IpcDesktopEnvironmentFactory(
795 context_->audio_task_runner(),
796 context_->network_task_runner(),
797 context_->video_capture_task_runner(),
798 context_->network_task_runner(),
799 daemon_channel_.get());
800 desktop_session_connector_ = desktop_environment_factory;
801 #else // !defined(OS_WIN)
802 DesktopEnvironmentFactory* desktop_environment_factory;
803 if (enable_window_capture_) {
804 desktop_environment_factory =
805 new SingleWindowDesktopEnvironmentFactory(
806 context_->network_task_runner(),
807 context_->input_task_runner(),
808 context_->ui_task_runner(),
809 window_id_);
810 } else {
811 desktop_environment_factory =
812 new Me2MeDesktopEnvironmentFactory(
813 context_->network_task_runner(),
814 context_->input_task_runner(),
815 context_->ui_task_runner());
817 #endif // !defined(OS_WIN)
819 desktop_environment_factory_.reset(desktop_environment_factory);
820 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
822 context_->network_task_runner()->PostTask(
823 FROM_HERE,
824 base::Bind(&HostProcess::StartOnNetworkThread, this));
827 void HostProcess::ShutdownOnUiThread() {
828 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
830 // Tear down resources that need to be torn down on the UI thread.
831 daemon_channel_.reset();
832 desktop_environment_factory_.reset();
833 policy_watcher_.reset();
835 // It is now safe for the HostProcess to be deleted.
836 self_ = nullptr;
838 #if defined(OS_LINUX)
839 // Cause the global AudioPipeReader to be freed, otherwise the audio
840 // thread will remain in-use and prevent the process from exiting.
841 // TODO(wez): DesktopEnvironmentFactory should own the pipe reader.
842 // See crbug.com/161373 and crbug.com/104544.
843 AudioCapturerLinux::InitializePipeReader(nullptr, base::FilePath());
844 #endif
847 void HostProcess::OnUnknownHostIdError() {
848 LOG(ERROR) << "Host ID not found.";
849 ShutdownHost(kInvalidHostIdExitCode);
852 void HostProcess::OnHeartbeatSuccessful() {
853 HOST_LOG << "Host ready to receive connections.";
854 #if defined(OS_POSIX)
855 if (signal_parent_) {
856 kill(getppid(), SIGUSR1);
857 signal_parent_ = false;
859 #endif
862 void HostProcess::OnHostDeleted() {
863 LOG(ERROR) << "Host was deleted from the directory.";
864 ShutdownHost(kInvalidHostIdExitCode);
867 void HostProcess::OnInitializePairingRegistry(
868 IPC::PlatformFileForTransit privileged_key,
869 IPC::PlatformFileForTransit unprivileged_key) {
870 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
872 #if defined(OS_WIN)
873 context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
874 &HostProcess::InitializePairingRegistry,
875 this, privileged_key, unprivileged_key));
876 #else // !defined(OS_WIN)
877 NOTREACHED();
878 #endif // !defined(OS_WIN)
881 #if defined(OS_WIN)
882 void HostProcess::InitializePairingRegistry(
883 IPC::PlatformFileForTransit privileged_key,
884 IPC::PlatformFileForTransit unprivileged_key) {
885 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
886 // |privileged_key| can be nullptr but not |unprivileged_key|.
887 DCHECK(unprivileged_key);
888 // |pairing_registry_| should only be initialized once.
889 DCHECK(!pairing_registry_);
891 HKEY privileged_hkey = reinterpret_cast<HKEY>(
892 IPC::PlatformFileForTransitToPlatformFile(privileged_key));
893 HKEY unprivileged_hkey = reinterpret_cast<HKEY>(
894 IPC::PlatformFileForTransitToPlatformFile(unprivileged_key));
896 scoped_ptr<PairingRegistryDelegateWin> delegate(
897 new PairingRegistryDelegateWin());
898 delegate->SetRootKeys(privileged_hkey, unprivileged_hkey);
900 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
901 delegate.Pass());
903 // (Re)Create the authenticator factory now that |pairing_registry_| has been
904 // initialized.
905 CreateAuthenticatorFactory();
907 #endif // !defined(OS_WIN)
909 // Applies the host config, returning true if successful.
910 bool HostProcess::ApplyConfig(const base::DictionaryValue& config) {
911 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
913 if (!config.GetString(kHostIdConfigPath, &host_id_)) {
914 LOG(ERROR) << "host_id is not defined in the config.";
915 return false;
918 std::string key_base64;
919 if (!config.GetString(kPrivateKeyConfigPath, &key_base64)) {
920 LOG(ERROR) << "Private key couldn't be read from the config file.";
921 return false;
924 key_pair_ = RsaKeyPair::FromString(key_base64);
925 if (!key_pair_.get()) {
926 LOG(ERROR) << "Invalid private key in the config file.";
927 return false;
930 std::string host_secret_hash_string;
931 if (!config.GetString(kHostSecretHashConfigPath,
932 &host_secret_hash_string)) {
933 host_secret_hash_string = "plain:";
936 if (!host_secret_hash_.Parse(host_secret_hash_string)) {
937 LOG(ERROR) << "Invalid host_secret_hash.";
938 return false;
941 // Use an XMPP connection to the Talk network for session signaling.
942 if (!config.GetString(kXmppLoginConfigPath, &xmpp_server_config_.username) ||
943 !config.GetString(kOAuthRefreshTokenConfigPath, &oauth_refresh_token_)) {
944 LOG(ERROR) << "XMPP credentials are not defined in the config.";
945 return false;
948 if (config.GetString(kHostOwnerConfigPath, &host_owner_)) {
949 // Service account configs have a host_owner, different from the xmpp_login.
950 use_service_account_ = true;
951 } else {
952 // User credential configs only have an xmpp_login, which is also the owner.
953 host_owner_ = xmpp_server_config_.username;
954 use_service_account_ = false;
957 // For non-Gmail Google accounts, the owner base JID differs from the email.
958 // host_owner_ contains the base JID (used for authenticating clients), while
959 // host_owner_email contains the account's email (used for UI and logs).
960 if (!config.GetString(kHostOwnerEmailConfigPath, &host_owner_email_)) {
961 host_owner_email_ = host_owner_;
964 // Allow offering of VP9 encoding to be overridden by the command-line.
965 if (base::CommandLine::ForCurrentProcess()->HasSwitch(kEnableVp9SwitchName)) {
966 enable_vp9_ = true;
967 } else {
968 config.GetBoolean(kEnableVp9ConfigPath, &enable_vp9_);
971 // Allow the command-line to override the size of the frame recorder buffer.
972 int frame_recorder_buffer_kb = 0;
973 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
974 kFrameRecorderBufferKbName)) {
975 std::string switch_value =
976 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
977 kFrameRecorderBufferKbName);
978 base::StringToInt(switch_value, &frame_recorder_buffer_kb);
979 } else {
980 config.GetInteger(kFrameRecorderBufferKbConfigPath,
981 &frame_recorder_buffer_kb);
983 if (frame_recorder_buffer_kb > 0) {
984 frame_recorder_buffer_size_ = 1024LL * frame_recorder_buffer_kb;
987 return true;
990 void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
991 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
992 context_->network_task_runner()->PostTask(
993 FROM_HERE, base::Bind(&HostProcess::OnPolicyUpdate, this,
994 base::Passed(&policies)));
995 return;
998 bool restart_required = false;
999 restart_required |= OnHostDomainPolicyUpdate(policies.get());
1000 restart_required |= OnCurtainPolicyUpdate(policies.get());
1001 // Note: UsernamePolicyUpdate must run after OnCurtainPolicyUpdate.
1002 restart_required |= OnUsernamePolicyUpdate(policies.get());
1003 restart_required |= OnNatPolicyUpdate(policies.get());
1004 restart_required |= OnRelayPolicyUpdate(policies.get());
1005 restart_required |= OnUdpPortPolicyUpdate(policies.get());
1006 restart_required |= OnHostTalkGadgetPrefixPolicyUpdate(policies.get());
1007 restart_required |= OnHostTokenUrlPolicyUpdate(policies.get());
1008 restart_required |= OnPairingPolicyUpdate(policies.get());
1009 restart_required |= OnGnubbyAuthPolicyUpdate(policies.get());
1011 policy_state_ = POLICY_LOADED;
1013 if (state_ == HOST_STARTING) {
1014 StartHostIfReady();
1015 } else if (state_ == HOST_STARTED) {
1016 if (restart_required)
1017 RestartHost(kHostOfflineReasonPolicyChangeRequiresRestart);
1021 void HostProcess::OnPolicyError() {
1022 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
1023 context_->network_task_runner()->PostTask(
1024 FROM_HERE, base::Bind(&HostProcess::OnPolicyError, this));
1025 return;
1028 if (policy_state_ != POLICY_ERROR_REPORTED) {
1029 policy_state_ = POLICY_ERROR_REPORT_PENDING;
1030 if ((state_ == HOST_STARTED) ||
1031 (state_ == HOST_STARTING && !serialized_config_.empty())) {
1032 ReportPolicyErrorAndRestartHost();
1037 void HostProcess::ReportPolicyErrorAndRestartHost() {
1038 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1039 DCHECK(!serialized_config_.empty());
1041 DCHECK_EQ(policy_state_, POLICY_ERROR_REPORT_PENDING);
1042 policy_state_ = POLICY_ERROR_REPORTED;
1044 LOG(INFO) << "Restarting the host due to policy errors.";
1045 RestartHost(kHostOfflineReasonPolicyReadError);
1048 void HostProcess::ApplyHostDomainPolicy() {
1049 if (state_ != HOST_STARTED)
1050 return;
1052 HOST_LOG << "Policy sets host domain: " << host_domain_;
1054 if (!host_domain_.empty()) {
1055 // If the user does not have a Google email, their client JID will not be
1056 // based on their email. In that case, the username/host domain policies
1057 // would be meaningless, since there is no way to check that the JID
1058 // trying to connect actually corresponds to the owner email in question.
1059 if (host_owner_ != host_owner_email_) {
1060 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1061 << "for accounts with a non-Google email.";
1062 ShutdownHost(kInvalidHostDomainExitCode);
1065 if (!EndsWith(host_owner_, std::string("@") + host_domain_, false)) {
1066 LOG(ERROR) << "The host domain does not match the policy.";
1067 ShutdownHost(kInvalidHostDomainExitCode);
1072 bool HostProcess::OnHostDomainPolicyUpdate(base::DictionaryValue* policies) {
1073 // Returns true if the host has to be restarted after this policy update.
1074 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1076 if (!policies->GetString(policy::key::kRemoteAccessHostDomain,
1077 &host_domain_)) {
1078 return false;
1081 ApplyHostDomainPolicy();
1082 return false;
1085 void HostProcess::ApplyUsernamePolicy() {
1086 if (state_ != HOST_STARTED)
1087 return;
1089 if (host_username_match_required_) {
1090 HOST_LOG << "Policy requires host username match.";
1092 // See comment in ApplyHostDomainPolicy.
1093 if (host_owner_ != host_owner_email_) {
1094 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1095 << "for accounts with a non-Google email.";
1096 ShutdownHost(kUsernameMismatchExitCode);
1099 std::string username = GetUsername();
1100 bool shutdown = username.empty() ||
1101 !StartsWithASCII(host_owner_, username + std::string("@"),
1102 false);
1104 #if defined(OS_MACOSX)
1105 // On Mac, we run as root at the login screen, so the username won't match.
1106 // However, there's no need to enforce the policy at the login screen, as
1107 // the client will have to reconnect if a login occurs.
1108 if (shutdown && getuid() == 0) {
1109 shutdown = false;
1111 #endif
1113 // Curtain-mode on Windows presents the standard OS login prompt to the user
1114 // for each connection, removing the need for an explicit user-name matching
1115 // check.
1116 #if defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1117 if (curtain_required_)
1118 return;
1119 #endif // defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1121 // Shutdown the host if the username does not match.
1122 if (shutdown) {
1123 LOG(ERROR) << "The host username does not match.";
1124 ShutdownHost(kUsernameMismatchExitCode);
1126 } else {
1127 HOST_LOG << "Policy does not require host username match.";
1131 bool HostProcess::OnUsernamePolicyUpdate(base::DictionaryValue* policies) {
1132 // Returns false: never restart the host after this policy update.
1133 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1135 if (!policies->GetBoolean(policy::key::kRemoteAccessHostMatchUsername,
1136 &host_username_match_required_)) {
1137 return false;
1140 ApplyUsernamePolicy();
1141 return false;
1144 bool HostProcess::OnNatPolicyUpdate(base::DictionaryValue* policies) {
1145 // Returns true if the host has to be restarted after this policy update.
1146 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1148 if (!policies->GetBoolean(policy::key::kRemoteAccessHostFirewallTraversal,
1149 &allow_nat_traversal_)) {
1150 return false;
1153 if (allow_nat_traversal_) {
1154 HOST_LOG << "Policy enables NAT traversal.";
1155 } else {
1156 HOST_LOG << "Policy disables NAT traversal.";
1158 return true;
1161 bool HostProcess::OnRelayPolicyUpdate(base::DictionaryValue* policies) {
1162 // Returns true if the host has to be restarted after this policy update.
1163 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1165 if (!policies->GetBoolean(
1166 policy::key::kRemoteAccessHostAllowRelayedConnection,
1167 &allow_relay_)) {
1168 return false;
1171 if (allow_relay_) {
1172 HOST_LOG << "Policy enables use of relay server.";
1173 } else {
1174 HOST_LOG << "Policy disables use of relay server.";
1176 return true;
1179 bool HostProcess::OnUdpPortPolicyUpdate(base::DictionaryValue* policies) {
1180 // Returns true if the host has to be restarted after this policy update.
1181 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1183 std::string string_value;
1184 if (!policies->GetString(policy::key::kRemoteAccessHostUdpPortRange,
1185 &string_value)) {
1186 return false;
1189 DCHECK(PortRange::Parse(string_value, &udp_port_range_));
1190 HOST_LOG << "Policy restricts UDP port range to: " << udp_port_range_;
1191 return true;
1194 bool HostProcess::OnCurtainPolicyUpdate(base::DictionaryValue* policies) {
1195 // Returns true if the host has to be restarted after this policy update.
1196 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1198 if (!policies->GetBoolean(policy::key::kRemoteAccessHostRequireCurtain,
1199 &curtain_required_)) {
1200 return false;
1203 #if defined(OS_MACOSX)
1204 if (curtain_required_) {
1205 // When curtain mode is in effect on Mac, the host process runs in the
1206 // user's switched-out session, but launchd will also run an instance at
1207 // the console login screen. Even if no user is currently logged-on, we
1208 // can't support remote-access to the login screen because the current host
1209 // process model disconnects the client during login, which would leave
1210 // the logged in session un-curtained on the console until they reconnect.
1212 // TODO(jamiewalch): Fix this once we have implemented the multi-process
1213 // daemon architecture (crbug.com/134894)
1214 if (getuid() == 0) {
1215 LOG(ERROR) << "Running the host in the console login session is yet not "
1216 "supported.";
1217 ShutdownHost(kLoginScreenNotSupportedExitCode);
1218 return false;
1221 #endif
1223 if (curtain_required_) {
1224 HOST_LOG << "Policy requires curtain-mode.";
1225 } else {
1226 HOST_LOG << "Policy does not require curtain-mode.";
1229 if (host_)
1230 host_->SetEnableCurtaining(curtain_required_);
1231 return false;
1234 bool HostProcess::OnHostTalkGadgetPrefixPolicyUpdate(
1235 base::DictionaryValue* policies) {
1236 // Returns true if the host has to be restarted after this policy update.
1237 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1239 if (!policies->GetString(policy::key::kRemoteAccessHostTalkGadgetPrefix,
1240 &talkgadget_prefix_)) {
1241 return false;
1244 HOST_LOG << "Policy sets talkgadget prefix: " << talkgadget_prefix_;
1245 return true;
1248 bool HostProcess::OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies) {
1249 switch (ThirdPartyAuthConfig::Parse(*policies, &third_party_auth_config_)) {
1250 case ThirdPartyAuthConfig::NoPolicy:
1251 return false;
1252 case ThirdPartyAuthConfig::ParsingSuccess:
1253 HOST_LOG << "Policy sets third-party token URLs: "
1254 << third_party_auth_config_;
1255 return true;
1256 case ThirdPartyAuthConfig::InvalidPolicy:
1257 default:
1258 NOTREACHED();
1259 return false;
1263 bool HostProcess::OnPairingPolicyUpdate(base::DictionaryValue* policies) {
1264 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1266 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowClientPairing,
1267 &allow_pairing_)) {
1268 return false;
1271 if (allow_pairing_) {
1272 HOST_LOG << "Policy enables client pairing.";
1273 } else {
1274 HOST_LOG << "Policy disables client pairing.";
1276 return true;
1279 bool HostProcess::OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies) {
1280 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1282 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowGnubbyAuth,
1283 &enable_gnubby_auth_)) {
1284 return false;
1287 if (enable_gnubby_auth_) {
1288 HOST_LOG << "Policy enables gnubby auth.";
1289 } else {
1290 HOST_LOG << "Policy disables gnubby auth.";
1293 if (desktop_environment_factory_)
1294 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
1296 return true;
1299 scoped_ptr<HostSignalingManager> HostProcess::CreateHostSignalingManager() {
1300 DCHECK(!host_id_.empty()); // |ApplyConfig| should already have been run.
1302 scoped_ptr<OAuthTokenGetter::OAuthCredentials> oauth_credentials(
1303 new OAuthTokenGetter::OAuthCredentials(xmpp_server_config_.username,
1304 oauth_refresh_token_,
1305 use_service_account_));
1307 return HostSignalingManager::Create(
1308 this, context_->url_request_context_getter(), xmpp_server_config_,
1309 talkgadget_prefix_, host_id_, key_pair_, directory_bot_jid_,
1310 oauth_credentials.Pass());
1313 void HostProcess::StartHostIfReady() {
1314 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1315 DCHECK_EQ(state_, HOST_STARTING);
1317 // Start the host if both the config and the policies are loaded.
1318 if (!serialized_config_.empty()) {
1319 if (policy_state_ == POLICY_LOADED) {
1320 StartHost();
1321 } else if (policy_state_ == POLICY_ERROR_REPORT_PENDING) {
1322 ReportPolicyErrorAndRestartHost();
1327 void HostProcess::StartHost() {
1328 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1329 DCHECK(!host_);
1330 DCHECK(!host_signaling_manager_);
1332 SetState(HOST_STARTED);
1334 host_signaling_manager_ = CreateHostSignalingManager();
1336 uint32 network_flags = 0;
1337 if (allow_nat_traversal_) {
1338 network_flags = NetworkSettings::NAT_TRAVERSAL_STUN |
1339 NetworkSettings::NAT_TRAVERSAL_OUTGOING;
1340 if (allow_relay_)
1341 network_flags |= NetworkSettings::NAT_TRAVERSAL_RELAY;
1344 NetworkSettings network_settings(network_flags);
1346 if (!udp_port_range_.is_null()) {
1347 network_settings.port_range = udp_port_range_;
1348 } else if (!allow_nat_traversal_) {
1349 // For legacy reasons we have to restrict the port range to a set of default
1350 // values when nat traversal is disabled, even if the port range was not
1351 // set in policy.
1352 network_settings.port_range.min_port = NetworkSettings::kDefaultMinPort;
1353 network_settings.port_range.max_port = NetworkSettings::kDefaultMaxPort;
1356 host_.reset(new ChromotingHost(
1357 host_signaling_manager_->signal_strategy(),
1358 desktop_environment_factory_.get(),
1359 CreateHostSessionManager(host_signaling_manager_->signal_strategy(),
1360 network_settings,
1361 context_->url_request_context_getter()),
1362 context_->audio_task_runner(), context_->input_task_runner(),
1363 context_->video_capture_task_runner(),
1364 context_->video_encode_task_runner(), context_->network_task_runner(),
1365 context_->ui_task_runner()));
1367 if (enable_vp9_) {
1368 scoped_ptr<protocol::CandidateSessionConfig> config =
1369 host_->protocol_config()->Clone();
1370 config->EnableVideoCodec(protocol::ChannelConfig::CODEC_VP9);
1371 host_->set_protocol_config(config.Pass());
1374 if (frame_recorder_buffer_size_ > 0) {
1375 scoped_ptr<VideoFrameRecorderHostExtension> frame_recorder_extension(
1376 new VideoFrameRecorderHostExtension());
1377 frame_recorder_extension->SetMaxContentBytes(frame_recorder_buffer_size_);
1378 host_->AddExtension(frame_recorder_extension.Pass());
1381 // TODO(simonmorris): Get the maximum session duration from a policy.
1382 #if defined(OS_LINUX)
1383 host_->SetMaximumSessionDuration(base::TimeDelta::FromHours(20));
1384 #endif
1386 host_change_notification_listener_.reset(new HostChangeNotificationListener(
1387 this, host_id_, host_signaling_manager_->signal_strategy(),
1388 directory_bot_jid_));
1390 host_status_logger_.reset(new HostStatusLogger(
1391 host_->AsWeakPtr(), ServerLogEntry::ME2ME,
1392 host_signaling_manager_->signal_strategy(), directory_bot_jid_));
1394 // Set up reporting the host status notifications.
1395 #if defined(REMOTING_MULTI_PROCESS)
1396 host_event_logger_.reset(
1397 new IpcHostEventLogger(host_->AsWeakPtr(), daemon_channel_.get()));
1398 #else // !defined(REMOTING_MULTI_PROCESS)
1399 host_event_logger_ =
1400 HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName);
1401 #endif // !defined(REMOTING_MULTI_PROCESS)
1403 host_->SetEnableCurtaining(curtain_required_);
1404 host_->Start(host_owner_email_);
1406 CreateAuthenticatorFactory();
1408 ApplyHostDomainPolicy();
1409 ApplyUsernamePolicy();
1412 void HostProcess::OnAuthFailed() {
1413 ShutdownHost(kInvalidOauthCredentialsExitCode);
1416 void HostProcess::RestartHost(const std::string& host_offline_reason) {
1417 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1418 DCHECK(!host_offline_reason.empty());
1420 SetState(HOST_GOING_OFFLINE_TO_RESTART);
1421 GoOffline(host_offline_reason);
1424 void HostProcess::ShutdownHost(HostExitCodes exit_code) {
1425 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1427 *exit_code_out_ = exit_code;
1429 switch (state_) {
1430 case HOST_STARTING:
1431 case HOST_STARTED:
1432 SetState(HOST_GOING_OFFLINE_TO_STOP);
1433 GoOffline(ExitCodeToString(exit_code));
1434 break;
1436 case HOST_GOING_OFFLINE_TO_RESTART:
1437 SetState(HOST_GOING_OFFLINE_TO_STOP);
1438 break;
1440 case HOST_GOING_OFFLINE_TO_STOP:
1441 case HOST_STOPPED:
1442 // Host is already stopped or being stopped. No action is required.
1443 break;
1447 void HostProcess::GoOffline(const std::string& host_offline_reason) {
1448 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1449 DCHECK(!host_offline_reason.empty());
1450 DCHECK((state_ == HOST_GOING_OFFLINE_TO_STOP) ||
1451 (state_ == HOST_GOING_OFFLINE_TO_RESTART));
1453 // Shut down everything except the HostSignalingManager.
1454 host_.reset();
1455 host_event_logger_.reset();
1456 host_status_logger_.reset();
1457 host_change_notification_listener_.reset();
1459 // Before shutting down HostSignalingManager, send the |host_offline_reason|
1460 // if possible (i.e. if we have the config).
1461 if (!serialized_config_.empty()) {
1462 if (!host_signaling_manager_) {
1463 host_signaling_manager_ = CreateHostSignalingManager();
1466 host_signaling_manager_->SendHostOfflineReason(
1467 host_offline_reason,
1468 base::TimeDelta::FromSeconds(kHostOfflineReasonTimeoutSeconds),
1469 base::Bind(&HostProcess::OnHostOfflineReasonAck, this));
1470 return; // Shutdown will resume after OnHostOfflineReasonAck.
1473 // Continue the shutdown without sending the host offline reason.
1474 HOST_LOG << "Can't send offline reason (" << host_offline_reason << ") "
1475 << "without a valid host config.";
1476 OnHostOfflineReasonAck(false);
1479 void HostProcess::OnHostOfflineReasonAck(bool success) {
1480 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1481 DCHECK(!host_); // Assert that the host is really offline at this point.
1483 HOST_LOG << "SendHostOfflineReason " << (success ? "succeeded." : "failed.");
1484 host_signaling_manager_.reset();
1486 if (state_ == HOST_GOING_OFFLINE_TO_RESTART) {
1487 SetState(HOST_STARTING);
1488 StartHostIfReady();
1489 } else if (state_ == HOST_GOING_OFFLINE_TO_STOP) {
1490 SetState(HOST_STOPPED);
1492 shutdown_watchdog_->SetExitCode(*exit_code_out_);
1493 shutdown_watchdog_->Arm();
1495 config_watcher_.reset();
1497 // Complete the rest of shutdown on the main thread.
1498 context_->ui_task_runner()->PostTask(
1499 FROM_HERE, base::Bind(&HostProcess::ShutdownOnUiThread, this));
1500 } else {
1501 NOTREACHED();
1505 void HostProcess::OnCrash(const std::string& function_name,
1506 const std::string& file_name,
1507 const int& line_number) {
1508 char message[1024];
1509 base::snprintf(message, sizeof(message),
1510 "Requested by %s at %s, line %d.",
1511 function_name.c_str(), file_name.c_str(), line_number);
1512 base::debug::Alias(message);
1514 // The daemon requested us to crash the process.
1515 CHECK(false) << message;
1518 int HostProcessMain() {
1519 #if defined(OS_LINUX)
1520 // Required in order for us to run multiple X11 threads.
1521 XInitThreads();
1523 // Required for any calls into GTK functions, such as the Disconnect and
1524 // Continue windows, though these should not be used for the Me2Me case
1525 // (crbug.com/104377).
1526 gtk_init(nullptr, nullptr);
1527 #endif
1529 // Enable support for SSL server sockets, which must be done while still
1530 // single-threaded.
1531 net::EnableSSLServerSockets();
1533 // Ensures runtime specific CPU features are initialized.
1534 media::InitializeCPUSpecificMediaFeatures();
1536 // Create the main message loop and start helper threads.
1537 base::MessageLoopForUI message_loop;
1538 scoped_ptr<ChromotingHostContext> context =
1539 ChromotingHostContext::Create(new AutoThreadTaskRunner(
1540 message_loop.message_loop_proxy(), base::MessageLoop::QuitClosure()));
1541 if (!context)
1542 return kInitializationFailed;
1544 // NetworkChangeNotifier must be initialized after MessageLoop.
1545 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier(
1546 net::NetworkChangeNotifier::Create());
1548 // BasicURLRequestContext holds references to threads, so it needs to be
1549 // dereferences on UI threads. Store the reference to the URLRequestGetter to
1550 // make sure it's not destroyed on other threads.
1551 // TODO(sergeyu): Consider fixing it in BasicURLRequestContext.
1552 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
1553 context->url_request_context_getter();
1555 // Create & start the HostProcess using these threads.
1556 // TODO(wez): The HostProcess holds a reference to itself until Shutdown().
1557 // Remove this hack as part of the multi-process refactoring.
1558 int exit_code = kSuccessExitCode;
1559 ShutdownWatchdog shutdown_watchdog(
1560 base::TimeDelta::FromSeconds(kShutdownTimeoutSeconds));
1561 new HostProcess(context.Pass(), &exit_code, &shutdown_watchdog);
1563 // Run the main (also UI) message loop until the host no longer needs it.
1564 message_loop.Run();
1566 return exit_code;
1569 } // namespace remoting