Fix mouse warp with 2x displays
[chromium-blink-merge.git] / remoting / host / remoting_me2me_host.cc
blob1029cff9b6446dac3c612cfa33c0852ea2bfcfaf
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/bind.h"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "base/debug/alias.h"
13 #include "base/files/file_path.h"
14 #include "base/files/file_util.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "build/build_config.h"
22 #include "ipc/ipc_channel.h"
23 #include "ipc/ipc_channel_proxy.h"
24 #include "ipc/ipc_listener.h"
25 #include "media/base/media.h"
26 #include "net/base/net_util.h"
27 #include "net/base/network_change_notifier.h"
28 #include "net/socket/client_socket_factory.h"
29 #include "net/socket/ssl_server_socket.h"
30 #include "net/url_request/url_fetcher.h"
31 #include "policy/policy_constants.h"
32 #include "remoting/base/auto_thread_task_runner.h"
33 #include "remoting/base/breakpad.h"
34 #include "remoting/base/constants.h"
35 #include "remoting/base/logging.h"
36 #include "remoting/base/rsa_key_pair.h"
37 #include "remoting/base/service_urls.h"
38 #include "remoting/base/util.h"
39 #include "remoting/host/branding.h"
40 #include "remoting/host/chromoting_host.h"
41 #include "remoting/host/chromoting_host_context.h"
42 #include "remoting/host/chromoting_messages.h"
43 #include "remoting/host/config_file_watcher.h"
44 #include "remoting/host/config_watcher.h"
45 #include "remoting/host/desktop_environment.h"
46 #include "remoting/host/desktop_session_connector.h"
47 #include "remoting/host/dns_blackhole_checker.h"
48 #include "remoting/host/gcd_rest_client.h"
49 #include "remoting/host/gcd_state_updater.h"
50 #include "remoting/host/heartbeat_sender.h"
51 #include "remoting/host/host_change_notification_listener.h"
52 #include "remoting/host/host_config.h"
53 #include "remoting/host/host_event_logger.h"
54 #include "remoting/host/host_exit_codes.h"
55 #include "remoting/host/host_main.h"
56 #include "remoting/host/host_status_logger.h"
57 #include "remoting/host/input_injector.h"
58 #include "remoting/host/ipc_constants.h"
59 #include "remoting/host/ipc_desktop_environment.h"
60 #include "remoting/host/ipc_host_event_logger.h"
61 #include "remoting/host/logging.h"
62 #include "remoting/host/me2me_desktop_environment.h"
63 #include "remoting/host/oauth_token_getter_impl.h"
64 #include "remoting/host/pairing_registry_delegate.h"
65 #include "remoting/host/policy_watcher.h"
66 #include "remoting/host/session_manager_factory.h"
67 #include "remoting/host/shutdown_watchdog.h"
68 #include "remoting/host/signaling_connector.h"
69 #include "remoting/host/single_window_desktop_environment.h"
70 #include "remoting/host/third_party_auth_config.h"
71 #include "remoting/host/token_validator_factory_impl.h"
72 #include "remoting/host/usage_stats_consent.h"
73 #include "remoting/host/username.h"
74 #include "remoting/host/video_frame_recorder_host_extension.h"
75 #include "remoting/protocol/me2me_host_authenticator_factory.h"
76 #include "remoting/protocol/network_settings.h"
77 #include "remoting/protocol/pairing_registry.h"
78 #include "remoting/protocol/port_range.h"
79 #include "remoting/protocol/token_validator.h"
80 #include "remoting/signaling/push_notification_subscriber.h"
81 #include "remoting/signaling/xmpp_signal_strategy.h"
83 #if defined(OS_POSIX)
84 #include <signal.h>
85 #include <sys/types.h>
86 #include <unistd.h>
87 #include "base/file_descriptor_posix.h"
88 #include "remoting/host/pam_authorization_factory_posix.h"
89 #include "remoting/host/posix/signal_handler.h"
90 #endif // defined(OS_POSIX)
92 #if defined(OS_MACOSX)
93 #include "base/mac/scoped_cftyperef.h"
94 #endif // defined(OS_MACOSX)
96 #if defined(OS_LINUX)
97 #include <gtk/gtk.h>
98 #include <X11/Xlib.h>
99 #include "remoting/host/audio_capturer_linux.h"
100 #endif // defined(OS_LINUX)
102 #if defined(OS_WIN)
103 #include <commctrl.h>
104 #include "base/win/registry.h"
105 #include "base/win/scoped_handle.h"
106 #include "remoting/host/pairing_registry_delegate_win.h"
107 #include "remoting/host/win/session_desktop_environment.h"
108 #endif // defined(OS_WIN)
110 using remoting::protocol::PairingRegistry;
111 using remoting::protocol::NetworkSettings;
113 #if defined(USE_REMOTING_MACOSX_INTERNAL)
114 #include "remoting/tools/internal/internal_mac-inl.h"
115 #endif
117 namespace {
119 #if !defined(REMOTING_MULTI_PROCESS)
120 // This is used for tagging system event logs.
121 const char kApplicationName[] = "chromoting";
123 // Value used for --host-config option to indicate that the path must be read
124 // from stdin.
125 const char kStdinConfigPath[] = "-";
126 #endif // !defined(REMOTING_MULTI_PROCESS)
128 #if defined(OS_LINUX)
129 // The command line switch used to pass name of the pipe to capture audio on
130 // linux.
131 const char kAudioPipeSwitchName[] = "audio-pipe-name";
133 // The command line switch used to pass name of the unix domain socket used to
134 // listen for gnubby requests.
135 const char kAuthSocknameSwitchName[] = "ssh-auth-sockname";
136 #endif // defined(OS_LINUX)
138 // The command line switch used by the parent to request the host to signal it
139 // when it is successfully started.
140 const char kSignalParentSwitchName[] = "signal-parent";
142 // Command line switch used to enable VP9 encoding.
143 const char kEnableVp9SwitchName[] = "enable-vp9";
145 // Command line switch used to enable and configure the frame-recorder.
146 const char kFrameRecorderBufferKbName[] = "frame-recorder-buffer-kb";
148 const char kWindowIdSwitchName[] = "window-id";
150 // Maximum time to wait for clean shutdown to occur, before forcing termination
151 // of the process.
152 const int kShutdownTimeoutSeconds = 15;
154 // Maximum time to wait for reporting host-offline-reason to the service,
155 // before continuing normal process shutdown.
156 const int kHostOfflineReasonTimeoutSeconds = 10;
158 // Host offline reasons not associated with shutting down the host process
159 // and therefore not expressible through HostExitCodes enum.
160 const char kHostOfflineReasonPolicyReadError[] = "POLICY_READ_ERROR";
161 const char kHostOfflineReasonPolicyChangeRequiresRestart[] =
162 "POLICY_CHANGE_REQUIRES_RESTART";
164 } // namespace
166 namespace remoting {
168 class HostProcess : public ConfigWatcher::Delegate,
169 public HostChangeNotificationListener::Listener,
170 public IPC::Listener,
171 public base::RefCountedThreadSafe<HostProcess> {
172 public:
173 // |shutdown_watchdog| is armed when shutdown is started, and should be kept
174 // alive as long as possible until the process exits (since destroying the
175 // watchdog disarms it).
176 HostProcess(scoped_ptr<ChromotingHostContext> context,
177 int* exit_code_out,
178 ShutdownWatchdog* shutdown_watchdog);
180 // ConfigWatcher::Delegate interface.
181 void OnConfigUpdated(const std::string& serialized_config) override;
182 void OnConfigWatcherError() override;
184 // IPC::Listener implementation.
185 bool OnMessageReceived(const IPC::Message& message) override;
186 void OnChannelError() override;
188 // HostChangeNotificationListener::Listener overrides.
189 void OnHostDeleted() override;
191 // Handler of the ChromotingDaemonNetworkMsg_InitializePairingRegistry IPC
192 // message.
193 void OnInitializePairingRegistry(
194 IPC::PlatformFileForTransit privileged_key,
195 IPC::PlatformFileForTransit unprivileged_key);
197 private:
198 // See SetState method for a list of allowed state transitions.
199 enum HostState {
200 // Waiting for valid config and policies to be read from the disk.
201 // Either the host process has just been started, or it is trying to start
202 // again after temporarily going offline due to policy change or error.
203 HOST_STARTING,
205 // Host is started and running.
206 HOST_STARTED,
208 // Host is sending offline reason, before trying to restart.
209 HOST_GOING_OFFLINE_TO_RESTART,
211 // Host is sending offline reason, before shutting down.
212 HOST_GOING_OFFLINE_TO_STOP,
214 // Host has been stopped (host process will end soon).
215 HOST_STOPPED,
218 enum PolicyState {
219 // Cannot start the host, because a valid policy has not been read yet.
220 POLICY_INITIALIZING,
222 // Policy was loaded successfully.
223 POLICY_LOADED,
225 // Policy error was detected, and we haven't yet sent out a
226 // host-offline-reason (i.e. because we haven't yet read the config).
227 POLICY_ERROR_REPORT_PENDING,
229 // Policy error was detected, and we have sent out a host-offline-reason.
230 POLICY_ERROR_REPORTED,
233 friend class base::RefCountedThreadSafe<HostProcess>;
234 ~HostProcess() override;
236 void SetState(HostState target_state);
238 void StartOnNetworkThread();
240 #if defined(OS_POSIX)
241 // Callback passed to RegisterSignalHandler() to handle SIGTERM events.
242 void SigTermHandler(int signal_number);
243 #endif
245 // Called to initialize resources on the UI thread.
246 void StartOnUiThread();
248 // Initializes IPC control channel and config file path from |cmd_line|.
249 // Called on the UI thread.
250 bool InitWithCommandLine(const base::CommandLine* cmd_line);
252 // Called on the UI thread to start monitoring the configuration file.
253 void StartWatchingConfigChanges();
255 // Called on the network thread to set the host's Authenticator factory.
256 void CreateAuthenticatorFactory();
258 // Tear down resources that run on the UI thread.
259 void ShutdownOnUiThread();
261 // Applies the host config, returning true if successful.
262 bool ApplyConfig(const base::DictionaryValue& config);
264 // Handles policy updates, by calling On*PolicyUpdate methods.
265 void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies);
266 void OnPolicyError();
267 void ReportPolicyErrorAndRestartHost();
268 void ApplyHostDomainPolicy();
269 void ApplyUsernamePolicy();
270 bool OnHostDomainPolicyUpdate(base::DictionaryValue* policies);
271 bool OnUsernamePolicyUpdate(base::DictionaryValue* policies);
272 bool OnNatPolicyUpdate(base::DictionaryValue* policies);
273 bool OnRelayPolicyUpdate(base::DictionaryValue* policies);
274 bool OnUdpPortPolicyUpdate(base::DictionaryValue* policies);
275 bool OnCurtainPolicyUpdate(base::DictionaryValue* policies);
276 bool OnHostTalkGadgetPrefixPolicyUpdate(base::DictionaryValue* policies);
277 bool OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies);
278 bool OnPairingPolicyUpdate(base::DictionaryValue* policies);
279 bool OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies);
281 void InitializeSignaling();
283 void StartHostIfReady();
284 void StartHost();
286 // Error handler for HeartbeatSender.
287 void OnHeartbeatSuccessful();
288 void OnUnknownHostIdError();
290 // Error handler for SignalingConnector.
291 void OnAuthFailed();
293 void RestartHost(const std::string& host_offline_reason);
294 void ShutdownHost(HostExitCodes exit_code);
296 // Helper methods doing the work needed by RestartHost and ShutdownHost.
297 void GoOffline(const std::string& host_offline_reason);
298 void OnHostOfflineReasonAck(bool success);
300 #if defined(OS_WIN)
301 // Initializes the pairing registry on Windows. This should be invoked on the
302 // network thread.
303 void InitializePairingRegistry(
304 IPC::PlatformFileForTransit privileged_key,
305 IPC::PlatformFileForTransit unprivileged_key);
306 #endif // defined(OS_WIN)
308 // Crashes the process in response to a daemon's request. The daemon passes
309 // the location of the code that detected the fatal error resulted in this
310 // request.
311 void OnCrash(const std::string& function_name,
312 const std::string& file_name,
313 const int& line_number);
315 scoped_ptr<ChromotingHostContext> context_;
317 // Accessed on the UI thread.
318 scoped_ptr<IPC::ChannelProxy> daemon_channel_;
320 // XMPP server/remoting bot configuration (initialized from the command line).
321 XmppSignalStrategy::XmppServerConfig xmpp_server_config_;
322 std::string directory_bot_jid_;
324 // Created on the UI thread but used from the network thread.
325 base::FilePath host_config_path_;
326 std::string host_config_;
327 scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
329 // Accessed on the network thread.
330 HostState state_;
332 scoped_ptr<ConfigWatcher> config_watcher_;
334 std::string host_id_;
335 protocol::SharedSecretHash host_secret_hash_;
336 scoped_refptr<RsaKeyPair> key_pair_;
337 std::string oauth_refresh_token_;
338 std::string serialized_config_;
339 std::string host_owner_;
340 std::string host_owner_email_;
341 bool use_service_account_;
342 bool enable_vp9_;
343 int64_t frame_recorder_buffer_size_;
345 scoped_ptr<PolicyWatcher> policy_watcher_;
346 PolicyState policy_state_;
347 std::string host_domain_;
348 bool host_username_match_required_;
349 bool allow_nat_traversal_;
350 bool allow_relay_;
351 PortRange udp_port_range_;
352 std::string talkgadget_prefix_;
353 bool allow_pairing_;
355 bool curtain_required_;
356 ThirdPartyAuthConfig third_party_auth_config_;
357 bool enable_gnubby_auth_;
359 // Boolean to change flow, where necessary, if we're
360 // capturing a window instead of the entire desktop.
361 bool enable_window_capture_;
363 // Used to specify which window to stream, if enabled.
364 webrtc::WindowId window_id_;
366 // Must outlive |gcd_state_updater_| and |signaling_connector_|.
367 scoped_ptr<OAuthTokenGetter> oauth_token_getter_;
369 // Must outlive |signaling_connector_|, |gcd_subscriber_|, and
370 // |heartbeat_sender_|.
371 scoped_ptr<SignalStrategy> signal_strategy_;
373 scoped_ptr<SignalingConnector> signaling_connector_;
374 scoped_ptr<HeartbeatSender> heartbeat_sender_;
375 #if defined(USE_GCD)
376 scoped_ptr<GcdStateUpdater> gcd_state_updater_;
377 scoped_ptr<PushNotificationSubscriber> gcd_subscriber_;
378 #endif // defined(USE_GCD)
380 scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_;
381 scoped_ptr<HostStatusLogger> host_status_logger_;
382 scoped_ptr<HostEventLogger> host_event_logger_;
384 scoped_ptr<ChromotingHost> host_;
386 // Used to keep this HostProcess alive until it is shutdown.
387 scoped_refptr<HostProcess> self_;
389 #if defined(REMOTING_MULTI_PROCESS)
390 DesktopSessionConnector* desktop_session_connector_;
391 #endif // defined(REMOTING_MULTI_PROCESS)
393 int* exit_code_out_;
394 bool signal_parent_;
396 scoped_refptr<PairingRegistry> pairing_registry_;
398 ShutdownWatchdog* shutdown_watchdog_;
400 DISALLOW_COPY_AND_ASSIGN(HostProcess);
403 HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context,
404 int* exit_code_out,
405 ShutdownWatchdog* shutdown_watchdog)
406 : context_(context.Pass()),
407 state_(HOST_STARTING),
408 use_service_account_(false),
409 enable_vp9_(false),
410 frame_recorder_buffer_size_(0),
411 policy_state_(POLICY_INITIALIZING),
412 host_username_match_required_(false),
413 allow_nat_traversal_(true),
414 allow_relay_(true),
415 allow_pairing_(true),
416 curtain_required_(false),
417 enable_gnubby_auth_(false),
418 enable_window_capture_(false),
419 window_id_(0),
420 self_(this),
421 #if defined(REMOTING_MULTI_PROCESS)
422 desktop_session_connector_(nullptr),
423 #endif // defined(REMOTING_MULTI_PROCESS)
424 exit_code_out_(exit_code_out),
425 signal_parent_(false),
426 shutdown_watchdog_(shutdown_watchdog) {
427 StartOnUiThread();
430 HostProcess::~HostProcess() {
431 // Verify that UI components have been torn down.
432 DCHECK(!config_watcher_);
433 DCHECK(!daemon_channel_);
434 DCHECK(!desktop_environment_factory_);
436 // We might be getting deleted on one of the threads the |host_context| owns,
437 // so we need to post it back to the caller thread to safely join & delete the
438 // threads it contains. This will go away when we move to AutoThread.
439 // |context_release()| will null |context_| before the method is invoked, so
440 // we need to pull out the task-runner on which to call DeleteSoon first.
441 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
442 context_->ui_task_runner();
443 task_runner->DeleteSoon(FROM_HERE, context_.release());
446 bool HostProcess::InitWithCommandLine(const base::CommandLine* cmd_line) {
447 #if defined(REMOTING_MULTI_PROCESS)
448 // Parse the handle value and convert it to a handle/file descriptor.
449 std::string channel_name =
450 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
452 int pipe_handle = 0;
453 if (channel_name.empty() ||
454 !base::StringToInt(channel_name, &pipe_handle)) {
455 LOG(ERROR) << "Invalid '" << kDaemonPipeSwitchName
456 << "' value: " << channel_name;
457 return false;
460 #if defined(OS_WIN)
461 base::win::ScopedHandle pipe(reinterpret_cast<HANDLE>(pipe_handle));
462 IPC::ChannelHandle channel_handle(pipe.Get());
463 #elif defined(OS_POSIX)
464 base::FileDescriptor pipe(pipe_handle, true);
465 IPC::ChannelHandle channel_handle(channel_name, pipe);
466 #endif // defined(OS_POSIX)
468 // Connect to the daemon process.
469 daemon_channel_ = IPC::ChannelProxy::Create(channel_handle,
470 IPC::Channel::MODE_CLIENT,
471 this,
472 context_->network_task_runner());
473 #else // !defined(REMOTING_MULTI_PROCESS)
474 // Connect to the daemon process.
475 std::string channel_name =
476 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
477 if (!channel_name.empty()) {
478 daemon_channel_ =
479 IPC::ChannelProxy::Create(channel_name,
480 IPC::Channel::MODE_CLIENT,
481 this,
482 context_->network_task_runner().get());
485 if (cmd_line->HasSwitch(kHostConfigSwitchName)) {
486 host_config_path_ = cmd_line->GetSwitchValuePath(kHostConfigSwitchName);
488 // Read config from stdin if necessary.
489 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
490 const size_t kBufferSize = 4096;
491 scoped_ptr<char[]> buf(new char[kBufferSize]);
492 size_t len;
493 while ((len = fread(buf.get(), 1, kBufferSize, stdin)) > 0) {
494 host_config_.append(buf.get(), len);
497 } else {
498 base::FilePath default_config_dir = remoting::GetConfigDir();
499 host_config_path_ = default_config_dir.Append(kDefaultHostConfigFile);
502 if (host_config_path_ != base::FilePath(kStdinConfigPath) &&
503 !base::PathExists(host_config_path_)) {
504 LOG(ERROR) << "Can't find host config at " << host_config_path_.value();
505 return false;
507 #endif // !defined(REMOTING_MULTI_PROCESS)
509 // Ignore certificate requests - the host currently has no client certificate
510 // support, so ignoring certificate requests allows connecting to servers that
511 // request, but don't require, a certificate (optional client authentication).
512 net::URLFetcher::SetIgnoreCertificateRequests(true);
514 ServiceUrls* service_urls = ServiceUrls::GetInstance();
516 const std::string& xmpp_server =
517 service_urls->xmpp_server_address_for_me2me_host();
518 if (!net::ParseHostAndPort(xmpp_server, &xmpp_server_config_.host,
519 &xmpp_server_config_.port)) {
520 LOG(ERROR) << "Invalid XMPP server: " << xmpp_server;
521 return false;
523 xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls();
524 directory_bot_jid_ = service_urls->directory_bot_jid();
526 signal_parent_ = cmd_line->HasSwitch(kSignalParentSwitchName);
528 enable_window_capture_ = cmd_line->HasSwitch(kWindowIdSwitchName);
529 if (enable_window_capture_) {
531 #if defined(OS_LINUX) || defined(OS_WIN)
532 LOG(WARNING) << "Window capturing is not fully supported on Linux or "
533 "Windows.";
534 #endif // defined(OS_LINUX) || defined(OS_WIN)
536 // uint32_t is large enough to hold window IDs on all platforms.
537 uint32_t window_id;
538 if (base::StringToUint(
539 cmd_line->GetSwitchValueASCII(kWindowIdSwitchName),
540 &window_id)) {
541 window_id_ = static_cast<webrtc::WindowId>(window_id);
542 } else {
543 LOG(ERROR) << "Window with window id: " << window_id_
544 << " not found. Shutting down host.";
545 return false;
548 return true;
551 void HostProcess::OnConfigUpdated(
552 const std::string& serialized_config) {
553 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
554 context_->network_task_runner()->PostTask(FROM_HERE,
555 base::Bind(&HostProcess::OnConfigUpdated, this, serialized_config));
556 return;
559 // Filter out duplicates.
560 if (serialized_config_ == serialized_config)
561 return;
563 HOST_LOG << "Processing new host configuration.";
565 serialized_config_ = serialized_config;
566 scoped_ptr<base::DictionaryValue> config(
567 HostConfigFromJson(serialized_config));
568 if (!config) {
569 LOG(ERROR) << "Invalid configuration.";
570 ShutdownHost(kInvalidHostConfigurationExitCode);
571 return;
574 if (!ApplyConfig(*config)) {
575 LOG(ERROR) << "Failed to apply the configuration.";
576 ShutdownHost(kInvalidHostConfigurationExitCode);
577 return;
580 if (state_ == HOST_STARTING) {
581 StartHostIfReady();
582 } else if (state_ == HOST_STARTED) {
583 // Reapply policies that could be affected by a new config.
584 DCHECK_EQ(policy_state_, POLICY_LOADED);
585 ApplyHostDomainPolicy();
586 ApplyUsernamePolicy();
588 // TODO(sergeyu): Here we assume that PIN is the only part of the config
589 // that may change while the service is running. Change ApplyConfig() to
590 // detect other changes in the config and restart host if necessary here.
591 CreateAuthenticatorFactory();
595 void HostProcess::OnConfigWatcherError() {
596 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
597 ShutdownHost(kInvalidHostConfigurationExitCode);
600 // Allowed state transitions (enforced via DCHECKs in SetState method):
601 // STARTING->STARTED (once we have valid config + policy)
602 // STARTING->GOING_OFFLINE_TO_STOP
603 // STARTING->GOING_OFFLINE_TO_RESTART
604 // STARTED->GOING_OFFLINE_TO_STOP
605 // STARTED->GOING_OFFLINE_TO_RESTART
606 // GOING_OFFLINE_TO_RESTART->GOING_OFFLINE_TO_STOP
607 // GOING_OFFLINE_TO_RESTART->STARTING (after OnHostOfflineReasonAck)
608 // GOING_OFFLINE_TO_STOP->STOPPED (after OnHostOfflineReasonAck)
610 // |host_| must be not-null in STARTED state and nullptr in all other states
611 // (although this invariant can be temporarily violated when doing
612 // synchronous processing on the networking thread).
613 void HostProcess::SetState(HostState target_state) {
614 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
616 // DCHECKs below enforce state allowed transitions listed in HostState.
617 switch (state_) {
618 case HOST_STARTING:
619 DCHECK((target_state == HOST_STARTED) ||
620 (target_state == HOST_GOING_OFFLINE_TO_STOP) ||
621 (target_state == HOST_GOING_OFFLINE_TO_RESTART))
622 << state_ << " -> " << target_state;
623 break;
624 case HOST_STARTED:
625 DCHECK((target_state == HOST_GOING_OFFLINE_TO_STOP) ||
626 (target_state == HOST_GOING_OFFLINE_TO_RESTART))
627 << state_ << " -> " << target_state;
628 break;
629 case HOST_GOING_OFFLINE_TO_RESTART:
630 DCHECK((target_state == HOST_GOING_OFFLINE_TO_STOP) ||
631 (target_state == HOST_STARTING))
632 << state_ << " -> " << target_state;
633 break;
634 case HOST_GOING_OFFLINE_TO_STOP:
635 DCHECK_EQ(target_state, HOST_STOPPED);
636 break;
637 case HOST_STOPPED: // HOST_STOPPED is a terminal state.
638 default:
639 NOTREACHED() << state_ << " -> " << target_state;
640 break;
642 state_ = target_state;
645 void HostProcess::StartOnNetworkThread() {
646 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
648 if (state_ != HOST_STARTING) {
649 // Host was shutdown before the task had a chance to run.
650 return;
653 #if !defined(REMOTING_MULTI_PROCESS)
654 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
655 // Process config we've read from stdin.
656 OnConfigUpdated(host_config_);
657 } else {
658 // Start watching the host configuration file.
659 config_watcher_.reset(new ConfigFileWatcher(context_->network_task_runner(),
660 context_->file_task_runner(),
661 host_config_path_));
662 config_watcher_->Watch(this);
664 #endif // !defined(REMOTING_MULTI_PROCESS)
666 #if defined(OS_POSIX)
667 remoting::RegisterSignalHandler(
668 SIGTERM,
669 base::Bind(&HostProcess::SigTermHandler, base::Unretained(this)));
670 #endif // defined(OS_POSIX)
673 #if defined(OS_POSIX)
674 void HostProcess::SigTermHandler(int signal_number) {
675 DCHECK(signal_number == SIGTERM);
676 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
677 HOST_LOG << "Caught SIGTERM: Shutting down...";
678 ShutdownHost(kSuccessExitCode);
680 #endif // OS_POSIX
682 void HostProcess::CreateAuthenticatorFactory() {
683 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
685 if (state_ != HOST_STARTED)
686 return;
688 std::string local_certificate = key_pair_->GenerateCertificate();
689 if (local_certificate.empty()) {
690 LOG(ERROR) << "Failed to generate host certificate.";
691 ShutdownHost(kInitializationFailed);
692 return;
695 scoped_ptr<protocol::AuthenticatorFactory> factory;
697 if (third_party_auth_config_.is_null()) {
698 scoped_refptr<PairingRegistry> pairing_registry;
699 if (allow_pairing_) {
700 // On Windows |pairing_registry_| is initialized in
701 // InitializePairingRegistry().
702 #if !defined(OS_WIN)
703 if (!pairing_registry_) {
704 scoped_ptr<PairingRegistry::Delegate> delegate =
705 CreatePairingRegistryDelegate();
707 if (delegate)
708 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
709 delegate.Pass());
711 #endif // defined(OS_WIN)
713 pairing_registry = pairing_registry_;
716 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
717 use_service_account_, host_owner_, local_certificate, key_pair_,
718 host_secret_hash_, pairing_registry);
720 host_->set_pairing_registry(pairing_registry);
721 } else {
722 DCHECK(third_party_auth_config_.token_url.is_valid());
723 DCHECK(third_party_auth_config_.token_validation_url.is_valid());
725 scoped_ptr<protocol::TokenValidatorFactory> token_validator_factory(
726 new TokenValidatorFactoryImpl(
727 third_party_auth_config_,
728 key_pair_, context_->url_request_context_getter()));
729 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
730 use_service_account_, host_owner_, local_certificate, key_pair_,
731 token_validator_factory.Pass());
734 #if defined(OS_POSIX)
735 // On Linux and Mac, perform a PAM authorization step after authentication.
736 factory.reset(new PamAuthorizationFactory(factory.Pass()));
737 #endif
738 host_->SetAuthenticatorFactory(factory.Pass());
741 // IPC::Listener implementation.
742 bool HostProcess::OnMessageReceived(const IPC::Message& message) {
743 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
745 #if defined(REMOTING_MULTI_PROCESS)
746 bool handled = true;
747 IPC_BEGIN_MESSAGE_MAP(HostProcess, message)
748 IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash)
749 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration,
750 OnConfigUpdated)
751 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_InitializePairingRegistry,
752 OnInitializePairingRegistry)
753 IPC_MESSAGE_FORWARD(
754 ChromotingDaemonNetworkMsg_DesktopAttached,
755 desktop_session_connector_,
756 DesktopSessionConnector::OnDesktopSessionAgentAttached)
757 IPC_MESSAGE_FORWARD(ChromotingDaemonNetworkMsg_TerminalDisconnected,
758 desktop_session_connector_,
759 DesktopSessionConnector::OnTerminalDisconnected)
760 IPC_MESSAGE_UNHANDLED(handled = false)
761 IPC_END_MESSAGE_MAP()
763 CHECK(handled) << "Received unexpected IPC type: " << message.type();
764 return handled;
766 #else // !defined(REMOTING_MULTI_PROCESS)
767 return false;
768 #endif // !defined(REMOTING_MULTI_PROCESS)
771 void HostProcess::OnChannelError() {
772 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
774 // Shutdown the host if the daemon process disconnects the IPC channel.
775 context_->network_task_runner()->PostTask(
776 FROM_HERE,
777 base::Bind(&HostProcess::ShutdownHost, this, kSuccessExitCode));
780 void HostProcess::StartOnUiThread() {
781 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
783 if (!InitWithCommandLine(base::CommandLine::ForCurrentProcess())) {
784 // Shutdown the host if the command line is invalid.
785 context_->network_task_runner()->PostTask(
786 FROM_HERE, base::Bind(&HostProcess::ShutdownHost, this,
787 kUsageExitCode));
788 return;
791 policy_watcher_ =
792 PolicyWatcher::Create(nullptr, context_->file_task_runner());
793 policy_watcher_->StartWatching(
794 base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)),
795 base::Bind(&HostProcess::OnPolicyError, base::Unretained(this)));
797 #if defined(OS_LINUX)
798 // If an audio pipe is specific on the command-line then initialize
799 // AudioCapturerLinux to capture from it.
800 base::FilePath audio_pipe_name = base::CommandLine::ForCurrentProcess()->
801 GetSwitchValuePath(kAudioPipeSwitchName);
802 if (!audio_pipe_name.empty()) {
803 remoting::AudioCapturerLinux::InitializePipeReader(
804 context_->audio_task_runner(), audio_pipe_name);
807 base::FilePath gnubby_socket_name = base::CommandLine::ForCurrentProcess()->
808 GetSwitchValuePath(kAuthSocknameSwitchName);
809 if (!gnubby_socket_name.empty())
810 remoting::GnubbyAuthHandler::SetGnubbySocketName(gnubby_socket_name);
811 #endif // defined(OS_LINUX)
813 // Create a desktop environment factory appropriate to the build type &
814 // platform.
815 #if defined(OS_WIN)
816 IpcDesktopEnvironmentFactory* desktop_environment_factory =
817 new IpcDesktopEnvironmentFactory(
818 context_->audio_task_runner(),
819 context_->network_task_runner(),
820 context_->video_capture_task_runner(),
821 context_->network_task_runner(),
822 daemon_channel_.get());
823 desktop_session_connector_ = desktop_environment_factory;
824 #else // !defined(OS_WIN)
825 BasicDesktopEnvironmentFactory* desktop_environment_factory;
826 if (enable_window_capture_) {
827 desktop_environment_factory =
828 new SingleWindowDesktopEnvironmentFactory(
829 context_->network_task_runner(),
830 context_->input_task_runner(),
831 context_->ui_task_runner(),
832 window_id_);
833 } else {
834 desktop_environment_factory =
835 new Me2MeDesktopEnvironmentFactory(
836 context_->network_task_runner(),
837 context_->input_task_runner(),
838 context_->ui_task_runner());
840 #endif // !defined(OS_WIN)
841 desktop_environment_factory->set_supports_touch_events(
842 InputInjector::SupportsTouchEvents());
844 desktop_environment_factory_.reset(desktop_environment_factory);
845 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
847 context_->network_task_runner()->PostTask(
848 FROM_HERE,
849 base::Bind(&HostProcess::StartOnNetworkThread, this));
852 void HostProcess::ShutdownOnUiThread() {
853 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
855 // Tear down resources that need to be torn down on the UI thread.
856 daemon_channel_.reset();
857 desktop_environment_factory_.reset();
858 policy_watcher_.reset();
860 // It is now safe for the HostProcess to be deleted.
861 self_ = nullptr;
863 #if defined(OS_LINUX)
864 // Cause the global AudioPipeReader to be freed, otherwise the audio
865 // thread will remain in-use and prevent the process from exiting.
866 // TODO(wez): DesktopEnvironmentFactory should own the pipe reader.
867 // See crbug.com/161373 and crbug.com/104544.
868 AudioCapturerLinux::InitializePipeReader(nullptr, base::FilePath());
869 #endif
872 void HostProcess::OnUnknownHostIdError() {
873 LOG(ERROR) << "Host ID not found.";
874 ShutdownHost(kInvalidHostIdExitCode);
877 void HostProcess::OnHeartbeatSuccessful() {
878 HOST_LOG << "Host ready to receive connections.";
879 #if defined(OS_POSIX)
880 if (signal_parent_) {
881 kill(getppid(), SIGUSR1);
882 signal_parent_ = false;
884 #endif
887 void HostProcess::OnHostDeleted() {
888 LOG(ERROR) << "Host was deleted from the directory.";
889 ShutdownHost(kInvalidHostIdExitCode);
892 void HostProcess::OnInitializePairingRegistry(
893 IPC::PlatformFileForTransit privileged_key,
894 IPC::PlatformFileForTransit unprivileged_key) {
895 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
897 #if defined(OS_WIN)
898 context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
899 &HostProcess::InitializePairingRegistry,
900 this, privileged_key, unprivileged_key));
901 #else // !defined(OS_WIN)
902 NOTREACHED();
903 #endif // !defined(OS_WIN)
906 #if defined(OS_WIN)
907 void HostProcess::InitializePairingRegistry(
908 IPC::PlatformFileForTransit privileged_key,
909 IPC::PlatformFileForTransit unprivileged_key) {
910 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
911 // |privileged_key| can be nullptr but not |unprivileged_key|.
912 DCHECK(unprivileged_key);
913 // |pairing_registry_| should only be initialized once.
914 DCHECK(!pairing_registry_);
916 HKEY privileged_hkey = reinterpret_cast<HKEY>(
917 IPC::PlatformFileForTransitToPlatformFile(privileged_key));
918 HKEY unprivileged_hkey = reinterpret_cast<HKEY>(
919 IPC::PlatformFileForTransitToPlatformFile(unprivileged_key));
921 scoped_ptr<PairingRegistryDelegateWin> delegate(
922 new PairingRegistryDelegateWin());
923 delegate->SetRootKeys(privileged_hkey, unprivileged_hkey);
925 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
926 delegate.Pass());
928 // (Re)Create the authenticator factory now that |pairing_registry_| has been
929 // initialized.
930 CreateAuthenticatorFactory();
932 #endif // !defined(OS_WIN)
934 // Applies the host config, returning true if successful.
935 bool HostProcess::ApplyConfig(const base::DictionaryValue& config) {
936 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
938 if (!config.GetString(kHostIdConfigPath, &host_id_)) {
939 LOG(ERROR) << "Config does not define " << kHostIdConfigPath << ".";
940 return false;
943 std::string key_base64;
944 if (!config.GetString(kPrivateKeyConfigPath, &key_base64)) {
945 LOG(ERROR) << "Private key couldn't be read from the config file.";
946 return false;
949 key_pair_ = RsaKeyPair::FromString(key_base64);
950 if (!key_pair_.get()) {
951 LOG(ERROR) << "Invalid private key in the config file.";
952 return false;
955 std::string host_secret_hash_string;
956 if (!config.GetString(kHostSecretHashConfigPath,
957 &host_secret_hash_string)) {
958 host_secret_hash_string = "plain:";
961 if (!host_secret_hash_.Parse(host_secret_hash_string)) {
962 LOG(ERROR) << "Invalid host_secret_hash.";
963 return false;
966 // Use an XMPP connection to the Talk network for session signaling.
967 if (!config.GetString(kXmppLoginConfigPath, &xmpp_server_config_.username) ||
968 !config.GetString(kOAuthRefreshTokenConfigPath, &oauth_refresh_token_)) {
969 LOG(ERROR) << "XMPP credentials are not defined in the config.";
970 return false;
973 if (config.GetString(kHostOwnerConfigPath, &host_owner_)) {
974 // Service account configs have a host_owner, different from the xmpp_login.
975 use_service_account_ = true;
976 } else {
977 // User credential configs only have an xmpp_login, which is also the owner.
978 host_owner_ = xmpp_server_config_.username;
979 use_service_account_ = false;
982 // For non-Gmail Google accounts, the owner base JID differs from the email.
983 // host_owner_ contains the base JID (used for authenticating clients), while
984 // host_owner_email contains the account's email (used for UI and logs).
985 if (!config.GetString(kHostOwnerEmailConfigPath, &host_owner_email_)) {
986 host_owner_email_ = host_owner_;
989 // Allow offering of VP9 encoding to be overridden by the command-line.
990 if (base::CommandLine::ForCurrentProcess()->HasSwitch(kEnableVp9SwitchName)) {
991 enable_vp9_ = true;
992 } else {
993 config.GetBoolean(kEnableVp9ConfigPath, &enable_vp9_);
996 // Allow the command-line to override the size of the frame recorder buffer.
997 int frame_recorder_buffer_kb = 0;
998 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
999 kFrameRecorderBufferKbName)) {
1000 std::string switch_value =
1001 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
1002 kFrameRecorderBufferKbName);
1003 base::StringToInt(switch_value, &frame_recorder_buffer_kb);
1004 } else {
1005 config.GetInteger(kFrameRecorderBufferKbConfigPath,
1006 &frame_recorder_buffer_kb);
1008 if (frame_recorder_buffer_kb > 0) {
1009 frame_recorder_buffer_size_ = 1024LL * frame_recorder_buffer_kb;
1012 return true;
1015 void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
1016 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
1017 context_->network_task_runner()->PostTask(
1018 FROM_HERE, base::Bind(&HostProcess::OnPolicyUpdate, this,
1019 base::Passed(&policies)));
1020 return;
1023 bool restart_required = false;
1024 restart_required |= OnHostDomainPolicyUpdate(policies.get());
1025 restart_required |= OnCurtainPolicyUpdate(policies.get());
1026 // Note: UsernamePolicyUpdate must run after OnCurtainPolicyUpdate.
1027 restart_required |= OnUsernamePolicyUpdate(policies.get());
1028 restart_required |= OnNatPolicyUpdate(policies.get());
1029 restart_required |= OnRelayPolicyUpdate(policies.get());
1030 restart_required |= OnUdpPortPolicyUpdate(policies.get());
1031 restart_required |= OnHostTalkGadgetPrefixPolicyUpdate(policies.get());
1032 restart_required |= OnHostTokenUrlPolicyUpdate(policies.get());
1033 restart_required |= OnPairingPolicyUpdate(policies.get());
1034 restart_required |= OnGnubbyAuthPolicyUpdate(policies.get());
1036 policy_state_ = POLICY_LOADED;
1038 if (state_ == HOST_STARTING) {
1039 StartHostIfReady();
1040 } else if (state_ == HOST_STARTED) {
1041 if (restart_required)
1042 RestartHost(kHostOfflineReasonPolicyChangeRequiresRestart);
1046 void HostProcess::OnPolicyError() {
1047 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
1048 context_->network_task_runner()->PostTask(
1049 FROM_HERE, base::Bind(&HostProcess::OnPolicyError, this));
1050 return;
1053 if (policy_state_ != POLICY_ERROR_REPORTED) {
1054 policy_state_ = POLICY_ERROR_REPORT_PENDING;
1055 if ((state_ == HOST_STARTED) ||
1056 (state_ == HOST_STARTING && !serialized_config_.empty())) {
1057 ReportPolicyErrorAndRestartHost();
1062 void HostProcess::ReportPolicyErrorAndRestartHost() {
1063 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1064 DCHECK(!serialized_config_.empty());
1066 DCHECK_EQ(policy_state_, POLICY_ERROR_REPORT_PENDING);
1067 policy_state_ = POLICY_ERROR_REPORTED;
1069 LOG(INFO) << "Restarting the host due to policy errors.";
1070 RestartHost(kHostOfflineReasonPolicyReadError);
1073 void HostProcess::ApplyHostDomainPolicy() {
1074 if (state_ != HOST_STARTED)
1075 return;
1077 HOST_LOG << "Policy sets host domain: " << host_domain_;
1079 if (!host_domain_.empty()) {
1080 // If the user does not have a Google email, their client JID will not be
1081 // based on their email. In that case, the username/host domain policies
1082 // would be meaningless, since there is no way to check that the JID
1083 // trying to connect actually corresponds to the owner email in question.
1084 if (host_owner_ != host_owner_email_) {
1085 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1086 << "for accounts with a non-Google email.";
1087 ShutdownHost(kInvalidHostDomainExitCode);
1090 if (!base::EndsWith(host_owner_, std::string("@") + host_domain_,
1091 base::CompareCase::INSENSITIVE_ASCII)) {
1092 LOG(ERROR) << "The host domain does not match the policy.";
1093 ShutdownHost(kInvalidHostDomainExitCode);
1098 bool HostProcess::OnHostDomainPolicyUpdate(base::DictionaryValue* policies) {
1099 // Returns true if the host has to be restarted after this policy update.
1100 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1102 if (!policies->GetString(policy::key::kRemoteAccessHostDomain,
1103 &host_domain_)) {
1104 return false;
1107 ApplyHostDomainPolicy();
1108 return false;
1111 void HostProcess::ApplyUsernamePolicy() {
1112 if (state_ != HOST_STARTED)
1113 return;
1115 if (host_username_match_required_) {
1116 HOST_LOG << "Policy requires host username match.";
1118 // See comment in ApplyHostDomainPolicy.
1119 if (host_owner_ != host_owner_email_) {
1120 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1121 << "for accounts with a non-Google email.";
1122 ShutdownHost(kUsernameMismatchExitCode);
1125 std::string username = GetUsername();
1126 bool shutdown =
1127 username.empty() ||
1128 !base::StartsWith(host_owner_, username + std::string("@"),
1129 base::CompareCase::INSENSITIVE_ASCII);
1131 #if defined(OS_MACOSX)
1132 // On Mac, we run as root at the login screen, so the username won't match.
1133 // However, there's no need to enforce the policy at the login screen, as
1134 // the client will have to reconnect if a login occurs.
1135 if (shutdown && getuid() == 0) {
1136 shutdown = false;
1138 #endif
1140 // Curtain-mode on Windows presents the standard OS login prompt to the user
1141 // for each connection, removing the need for an explicit user-name matching
1142 // check.
1143 #if defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1144 if (curtain_required_)
1145 return;
1146 #endif // defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1148 // Shutdown the host if the username does not match.
1149 if (shutdown) {
1150 LOG(ERROR) << "The host username does not match.";
1151 ShutdownHost(kUsernameMismatchExitCode);
1153 } else {
1154 HOST_LOG << "Policy does not require host username match.";
1158 bool HostProcess::OnUsernamePolicyUpdate(base::DictionaryValue* policies) {
1159 // Returns false: never restart the host after this policy update.
1160 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1162 if (!policies->GetBoolean(policy::key::kRemoteAccessHostMatchUsername,
1163 &host_username_match_required_)) {
1164 return false;
1167 ApplyUsernamePolicy();
1168 return false;
1171 bool HostProcess::OnNatPolicyUpdate(base::DictionaryValue* policies) {
1172 // Returns true if the host has to be restarted after this policy update.
1173 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1175 if (!policies->GetBoolean(policy::key::kRemoteAccessHostFirewallTraversal,
1176 &allow_nat_traversal_)) {
1177 return false;
1180 if (allow_nat_traversal_) {
1181 HOST_LOG << "Policy enables NAT traversal.";
1182 } else {
1183 HOST_LOG << "Policy disables NAT traversal.";
1185 return true;
1188 bool HostProcess::OnRelayPolicyUpdate(base::DictionaryValue* policies) {
1189 // Returns true if the host has to be restarted after this policy update.
1190 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1192 if (!policies->GetBoolean(
1193 policy::key::kRemoteAccessHostAllowRelayedConnection,
1194 &allow_relay_)) {
1195 return false;
1198 if (allow_relay_) {
1199 HOST_LOG << "Policy enables use of relay server.";
1200 } else {
1201 HOST_LOG << "Policy disables use of relay server.";
1203 return true;
1206 bool HostProcess::OnUdpPortPolicyUpdate(base::DictionaryValue* policies) {
1207 // Returns true if the host has to be restarted after this policy update.
1208 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1210 std::string string_value;
1211 if (!policies->GetString(policy::key::kRemoteAccessHostUdpPortRange,
1212 &string_value)) {
1213 return false;
1216 if (!PortRange::Parse(string_value, &udp_port_range_)) {
1217 // PolicyWatcher verifies that the value is formatted correctly.
1218 LOG(FATAL) << "Invalid port range: " << string_value;
1220 HOST_LOG << "Policy restricts UDP port range to: " << udp_port_range_;
1221 return true;
1224 bool HostProcess::OnCurtainPolicyUpdate(base::DictionaryValue* policies) {
1225 // Returns true if the host has to be restarted after this policy update.
1226 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1228 if (!policies->GetBoolean(policy::key::kRemoteAccessHostRequireCurtain,
1229 &curtain_required_)) {
1230 return false;
1233 #if defined(OS_MACOSX)
1234 if (curtain_required_) {
1235 // When curtain mode is in effect on Mac, the host process runs in the
1236 // user's switched-out session, but launchd will also run an instance at
1237 // the console login screen. Even if no user is currently logged-on, we
1238 // can't support remote-access to the login screen because the current host
1239 // process model disconnects the client during login, which would leave
1240 // the logged in session un-curtained on the console until they reconnect.
1242 // TODO(jamiewalch): Fix this once we have implemented the multi-process
1243 // daemon architecture (crbug.com/134894)
1244 if (getuid() == 0) {
1245 LOG(ERROR) << "Running the host in the console login session is yet not "
1246 "supported.";
1247 ShutdownHost(kLoginScreenNotSupportedExitCode);
1248 return false;
1251 #endif
1253 if (curtain_required_) {
1254 HOST_LOG << "Policy requires curtain-mode.";
1255 } else {
1256 HOST_LOG << "Policy does not require curtain-mode.";
1259 if (host_)
1260 host_->SetEnableCurtaining(curtain_required_);
1261 return false;
1264 bool HostProcess::OnHostTalkGadgetPrefixPolicyUpdate(
1265 base::DictionaryValue* policies) {
1266 // Returns true if the host has to be restarted after this policy update.
1267 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1269 if (!policies->GetString(policy::key::kRemoteAccessHostTalkGadgetPrefix,
1270 &talkgadget_prefix_)) {
1271 return false;
1274 HOST_LOG << "Policy sets talkgadget prefix: " << talkgadget_prefix_;
1275 return true;
1278 bool HostProcess::OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies) {
1279 switch (ThirdPartyAuthConfig::Parse(*policies, &third_party_auth_config_)) {
1280 case ThirdPartyAuthConfig::NoPolicy:
1281 return false;
1282 case ThirdPartyAuthConfig::ParsingSuccess:
1283 HOST_LOG << "Policy sets third-party token URLs: "
1284 << third_party_auth_config_;
1285 return true;
1286 case ThirdPartyAuthConfig::InvalidPolicy:
1287 default:
1288 NOTREACHED();
1289 return false;
1293 bool HostProcess::OnPairingPolicyUpdate(base::DictionaryValue* policies) {
1294 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1296 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowClientPairing,
1297 &allow_pairing_)) {
1298 return false;
1301 if (allow_pairing_) {
1302 HOST_LOG << "Policy enables client pairing.";
1303 } else {
1304 HOST_LOG << "Policy disables client pairing.";
1306 return true;
1309 bool HostProcess::OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies) {
1310 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1312 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowGnubbyAuth,
1313 &enable_gnubby_auth_)) {
1314 return false;
1317 if (enable_gnubby_auth_) {
1318 HOST_LOG << "Policy enables gnubby auth.";
1319 } else {
1320 HOST_LOG << "Policy disables gnubby auth.";
1323 if (desktop_environment_factory_)
1324 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
1326 return true;
1329 void HostProcess::InitializeSignaling() {
1330 DCHECK(!host_id_.empty()); // ApplyConfig() should already have been run.
1332 DCHECK(!signal_strategy_);
1333 DCHECK(!oauth_token_getter_);
1334 DCHECK(!signaling_connector_);
1335 #if defined(USE_GCD)
1336 DCHECK(!gcd_state_updater_);
1337 DCHECK(!gcd_subscriber_);
1338 #endif // defined(USE_GCD)
1339 DCHECK(!heartbeat_sender_);
1341 // Create SignalStrategy.
1342 XmppSignalStrategy* xmpp_signal_strategy = new XmppSignalStrategy(
1343 net::ClientSocketFactory::GetDefaultFactory(),
1344 context_->url_request_context_getter(), xmpp_server_config_);
1345 signal_strategy_.reset(xmpp_signal_strategy);
1347 // Create SignalingConnector.
1348 scoped_ptr<DnsBlackholeChecker> dns_blackhole_checker(new DnsBlackholeChecker(
1349 context_->url_request_context_getter(), talkgadget_prefix_));
1350 scoped_ptr<OAuthTokenGetter::OAuthCredentials> oauth_credentials(
1351 new OAuthTokenGetter::OAuthCredentials(xmpp_server_config_.username,
1352 oauth_refresh_token_,
1353 use_service_account_));
1354 oauth_token_getter_.reset(new OAuthTokenGetterImpl(
1355 oauth_credentials.Pass(), context_->url_request_context_getter(), false));
1356 signaling_connector_.reset(new SignalingConnector(
1357 xmpp_signal_strategy, dns_blackhole_checker.Pass(),
1358 oauth_token_getter_.get(),
1359 base::Bind(&HostProcess::OnAuthFailed, base::Unretained(this))));
1361 #if defined(USE_GCD)
1362 // Create objects to manage GCD state.
1363 ServiceUrls* service_urls = ServiceUrls::GetInstance();
1364 scoped_ptr<GcdRestClient> gcd_rest_client(new GcdRestClient(
1365 service_urls->gcd_base_url(), host_id_,
1366 context_->url_request_context_getter(), oauth_token_getter_.get()));
1367 gcd_state_updater_.reset(
1368 new GcdStateUpdater(base::Bind(&HostProcess::OnHeartbeatSuccessful,
1369 base::Unretained(this)),
1370 base::Bind(&HostProcess::OnUnknownHostIdError,
1371 base::Unretained(this)),
1372 signal_strategy_.get(), gcd_rest_client.Pass()));
1373 PushNotificationSubscriber::Subscription sub;
1374 sub.channel = "cloud_devices";
1375 PushNotificationSubscriber::SubscriptionList subs;
1376 subs.push_back(sub);
1377 gcd_subscriber_.reset(
1378 new PushNotificationSubscriber(signal_strategy_.get(), subs));
1379 #endif // defined(USE_GCD)
1381 // Create HeartbeatSender.
1382 heartbeat_sender_.reset(new HeartbeatSender(
1383 base::Bind(&HostProcess::OnHeartbeatSuccessful, base::Unretained(this)),
1384 base::Bind(&HostProcess::OnUnknownHostIdError, base::Unretained(this)),
1385 host_id_, signal_strategy_.get(), key_pair_, directory_bot_jid_));
1388 void HostProcess::StartHostIfReady() {
1389 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1390 DCHECK_EQ(state_, HOST_STARTING);
1392 // Start the host if both the config and the policies are loaded.
1393 if (!serialized_config_.empty()) {
1394 if (policy_state_ == POLICY_LOADED) {
1395 StartHost();
1396 } else if (policy_state_ == POLICY_ERROR_REPORT_PENDING) {
1397 ReportPolicyErrorAndRestartHost();
1402 void HostProcess::StartHost() {
1403 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1404 DCHECK(!host_);
1406 SetState(HOST_STARTED);
1408 InitializeSignaling();
1410 uint32 network_flags = 0;
1411 if (allow_nat_traversal_) {
1412 network_flags = NetworkSettings::NAT_TRAVERSAL_STUN |
1413 NetworkSettings::NAT_TRAVERSAL_OUTGOING;
1414 if (allow_relay_)
1415 network_flags |= NetworkSettings::NAT_TRAVERSAL_RELAY;
1418 NetworkSettings network_settings(network_flags);
1420 if (!udp_port_range_.is_null()) {
1421 network_settings.port_range = udp_port_range_;
1422 } else if (!allow_nat_traversal_) {
1423 // For legacy reasons we have to restrict the port range to a set of default
1424 // values when nat traversal is disabled, even if the port range was not
1425 // set in policy.
1426 network_settings.port_range.min_port = NetworkSettings::kDefaultMinPort;
1427 network_settings.port_range.max_port = NetworkSettings::kDefaultMaxPort;
1430 scoped_ptr<protocol::SessionManager> session_manager =
1431 CreateHostSessionManager(signal_strategy_.get(), network_settings,
1432 context_->url_request_context_getter());
1434 scoped_ptr<protocol::CandidateSessionConfig> protocol_config =
1435 protocol::CandidateSessionConfig::CreateDefault();
1436 if (!desktop_environment_factory_->SupportsAudioCapture())
1437 protocol_config->DisableAudioChannel();
1438 if (enable_vp9_)
1439 protocol_config->EnableVideoCodec(protocol::ChannelConfig::CODEC_VP9);
1440 session_manager->set_protocol_config(protocol_config.Pass());
1442 host_.reset(new ChromotingHost(
1443 signal_strategy_.get(), desktop_environment_factory_.get(),
1444 session_manager.Pass(), context_->audio_task_runner(),
1445 context_->input_task_runner(), context_->video_capture_task_runner(),
1446 context_->video_encode_task_runner(), context_->network_task_runner(),
1447 context_->ui_task_runner()));
1449 if (frame_recorder_buffer_size_ > 0) {
1450 scoped_ptr<VideoFrameRecorderHostExtension> frame_recorder_extension(
1451 new VideoFrameRecorderHostExtension());
1452 frame_recorder_extension->SetMaxContentBytes(frame_recorder_buffer_size_);
1453 host_->AddExtension(frame_recorder_extension.Pass());
1456 // TODO(simonmorris): Get the maximum session duration from a policy.
1457 #if defined(OS_LINUX)
1458 host_->SetMaximumSessionDuration(base::TimeDelta::FromHours(20));
1459 #endif
1461 host_change_notification_listener_.reset(new HostChangeNotificationListener(
1462 this, host_id_, signal_strategy_.get(), directory_bot_jid_));
1464 host_status_logger_.reset(new HostStatusLogger(
1465 host_->AsWeakPtr(), ServerLogEntry::ME2ME,
1466 signal_strategy_.get(), directory_bot_jid_));
1468 // Set up reporting the host status notifications.
1469 #if defined(REMOTING_MULTI_PROCESS)
1470 host_event_logger_.reset(
1471 new IpcHostEventLogger(host_->AsWeakPtr(), daemon_channel_.get()));
1472 #else // !defined(REMOTING_MULTI_PROCESS)
1473 host_event_logger_ =
1474 HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName);
1475 #endif // !defined(REMOTING_MULTI_PROCESS)
1477 host_->SetEnableCurtaining(curtain_required_);
1478 host_->Start(host_owner_email_);
1480 CreateAuthenticatorFactory();
1482 ApplyHostDomainPolicy();
1483 ApplyUsernamePolicy();
1486 void HostProcess::OnAuthFailed() {
1487 ShutdownHost(kInvalidOauthCredentialsExitCode);
1490 void HostProcess::RestartHost(const std::string& host_offline_reason) {
1491 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1492 DCHECK(!host_offline_reason.empty());
1494 SetState(HOST_GOING_OFFLINE_TO_RESTART);
1495 GoOffline(host_offline_reason);
1498 void HostProcess::ShutdownHost(HostExitCodes exit_code) {
1499 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1501 *exit_code_out_ = exit_code;
1503 switch (state_) {
1504 case HOST_STARTING:
1505 case HOST_STARTED:
1506 SetState(HOST_GOING_OFFLINE_TO_STOP);
1507 GoOffline(ExitCodeToString(exit_code));
1508 break;
1510 case HOST_GOING_OFFLINE_TO_RESTART:
1511 SetState(HOST_GOING_OFFLINE_TO_STOP);
1512 break;
1514 case HOST_GOING_OFFLINE_TO_STOP:
1515 case HOST_STOPPED:
1516 // Host is already stopped or being stopped. No action is required.
1517 break;
1521 void HostProcess::GoOffline(const std::string& host_offline_reason) {
1522 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1523 DCHECK(!host_offline_reason.empty());
1524 DCHECK((state_ == HOST_GOING_OFFLINE_TO_STOP) ||
1525 (state_ == HOST_GOING_OFFLINE_TO_RESTART));
1527 // Shut down everything except the HostSignalingManager.
1528 host_.reset();
1529 host_event_logger_.reset();
1530 host_status_logger_.reset();
1531 host_change_notification_listener_.reset();
1533 // Before shutting down HostSignalingManager, send the |host_offline_reason|
1534 // if possible (i.e. if we have the config).
1535 if (!serialized_config_.empty()) {
1536 if (!signal_strategy_)
1537 InitializeSignaling();
1539 HOST_LOG << "SendHostOfflineReason: sending " << host_offline_reason << ".";
1540 if (heartbeat_sender_) {
1541 heartbeat_sender_->SetHostOfflineReason(
1542 host_offline_reason,
1543 base::TimeDelta::FromSeconds(kHostOfflineReasonTimeoutSeconds),
1544 base::Bind(&HostProcess::OnHostOfflineReasonAck, this));
1546 #if defined(USE_GCD)
1547 if (gcd_state_updater_) {
1548 gcd_state_updater_->SetHostOfflineReason(
1549 host_offline_reason,
1550 base::TimeDelta::FromSeconds(kHostOfflineReasonTimeoutSeconds),
1551 base::Bind(&HostProcess::OnHostOfflineReasonAck, this));
1553 #endif // defined(USE_GCD)
1554 return; // Shutdown will resume after OnHostOfflineReasonAck.
1557 // Continue the shutdown without sending the host offline reason.
1558 HOST_LOG << "Can't send offline reason (" << host_offline_reason << ") "
1559 << "without a valid host config.";
1560 OnHostOfflineReasonAck(false);
1563 void HostProcess::OnHostOfflineReasonAck(bool success) {
1564 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1565 DCHECK(!host_); // Assert that the host is really offline at this point.
1567 HOST_LOG << "SendHostOfflineReason " << (success ? "succeeded." : "failed.");
1568 heartbeat_sender_.reset();
1569 oauth_token_getter_.reset();
1570 signaling_connector_.reset();
1571 signal_strategy_.reset();
1572 #if defined(USE_GCD)
1573 gcd_state_updater_.reset();
1574 gcd_subscriber_.reset();
1575 #endif // defined(USE_GCD)
1577 if (state_ == HOST_GOING_OFFLINE_TO_RESTART) {
1578 SetState(HOST_STARTING);
1579 StartHostIfReady();
1580 } else if (state_ == HOST_GOING_OFFLINE_TO_STOP) {
1581 SetState(HOST_STOPPED);
1583 shutdown_watchdog_->SetExitCode(*exit_code_out_);
1584 shutdown_watchdog_->Arm();
1586 config_watcher_.reset();
1588 // Complete the rest of shutdown on the main thread.
1589 context_->ui_task_runner()->PostTask(
1590 FROM_HERE, base::Bind(&HostProcess::ShutdownOnUiThread, this));
1591 } else {
1592 NOTREACHED();
1596 void HostProcess::OnCrash(const std::string& function_name,
1597 const std::string& file_name,
1598 const int& line_number) {
1599 char message[1024];
1600 base::snprintf(message, sizeof(message),
1601 "Requested by %s at %s, line %d.",
1602 function_name.c_str(), file_name.c_str(), line_number);
1603 base::debug::Alias(message);
1605 // The daemon requested us to crash the process.
1606 CHECK(false) << message;
1609 int HostProcessMain() {
1610 #if defined(OS_LINUX)
1611 // Required in order for us to run multiple X11 threads.
1612 XInitThreads();
1614 // Required for any calls into GTK functions, such as the Disconnect and
1615 // Continue windows, though these should not be used for the Me2Me case
1616 // (crbug.com/104377).
1617 gtk_init(nullptr, nullptr);
1618 #endif
1620 // Enable support for SSL server sockets, which must be done while still
1621 // single-threaded.
1622 net::EnableSSLServerSockets();
1624 // Ensures that media library and specific CPU features are initialized.
1625 media::InitializeMediaLibrary();
1627 // Create the main message loop and start helper threads.
1628 base::MessageLoopForUI message_loop;
1629 scoped_ptr<ChromotingHostContext> context =
1630 ChromotingHostContext::Create(new AutoThreadTaskRunner(
1631 message_loop.task_runner(), base::MessageLoop::QuitClosure()));
1632 if (!context)
1633 return kInitializationFailed;
1635 // NetworkChangeNotifier must be initialized after MessageLoop.
1636 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier(
1637 net::NetworkChangeNotifier::Create());
1639 // Create & start the HostProcess using these threads.
1640 // TODO(wez): The HostProcess holds a reference to itself until Shutdown().
1641 // Remove this hack as part of the multi-process refactoring.
1642 int exit_code = kSuccessExitCode;
1643 ShutdownWatchdog shutdown_watchdog(
1644 base::TimeDelta::FromSeconds(kShutdownTimeoutSeconds));
1645 new HostProcess(context.Pass(), &exit_code, &shutdown_watchdog);
1647 // Run the main (also UI) message loop until the host no longer needs it.
1648 message_loop.Run();
1650 return exit_code;
1653 } // namespace remoting