Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / remoting / host / remoting_me2me_host.cc
blob943d1d8e2e2dd54e9fae0158b32cf81da4227794
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/heartbeat_sender.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_status_logger.h"
55 #include "remoting/host/ipc_constants.h"
56 #include "remoting/host/ipc_desktop_environment.h"
57 #include "remoting/host/ipc_host_event_logger.h"
58 #include "remoting/host/logging.h"
59 #include "remoting/host/me2me_desktop_environment.h"
60 #include "remoting/host/oauth_token_getter_impl.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 HostChangeNotificationListener::Listener,
164 public IPC::Listener,
165 public base::RefCountedThreadSafe<HostProcess> {
166 public:
167 // |shutdown_watchdog| is armed when shutdown is started, and should be kept
168 // alive as long as possible until the process exits (since destroying the
169 // watchdog disarms it).
170 HostProcess(scoped_ptr<ChromotingHostContext> context,
171 int* exit_code_out,
172 ShutdownWatchdog* shutdown_watchdog);
174 // ConfigWatcher::Delegate interface.
175 void OnConfigUpdated(const std::string& serialized_config) override;
176 void OnConfigWatcherError() override;
178 // IPC::Listener implementation.
179 bool OnMessageReceived(const IPC::Message& message) override;
180 void OnChannelError() override;
182 // HostChangeNotificationListener::Listener overrides.
183 void OnHostDeleted() override;
185 // Handler of the ChromotingDaemonNetworkMsg_InitializePairingRegistry IPC
186 // message.
187 void OnInitializePairingRegistry(
188 IPC::PlatformFileForTransit privileged_key,
189 IPC::PlatformFileForTransit unprivileged_key);
191 private:
192 // See SetState method for a list of allowed state transitions.
193 enum HostState {
194 // Waiting for valid config and policies to be read from the disk.
195 // Either the host process has just been started, or it is trying to start
196 // again after temporarily going offline due to policy change or error.
197 HOST_STARTING,
199 // Host is started and running.
200 HOST_STARTED,
202 // Host is sending offline reason, before trying to restart.
203 HOST_GOING_OFFLINE_TO_RESTART,
205 // Host is sending offline reason, before shutting down.
206 HOST_GOING_OFFLINE_TO_STOP,
208 // Host has been stopped (host process will end soon).
209 HOST_STOPPED,
212 enum PolicyState {
213 // Cannot start the host, because a valid policy has not been read yet.
214 POLICY_INITIALIZING,
216 // Policy was loaded successfully.
217 POLICY_LOADED,
219 // Policy error was detected, and we haven't yet sent out a
220 // host-offline-reason (i.e. because we haven't yet read the config).
221 POLICY_ERROR_REPORT_PENDING,
223 // Policy error was detected, and we have sent out a host-offline-reason.
224 POLICY_ERROR_REPORTED,
227 friend class base::RefCountedThreadSafe<HostProcess>;
228 ~HostProcess() override;
230 void SetState(HostState target_state);
232 void StartOnNetworkThread();
234 #if defined(OS_POSIX)
235 // Callback passed to RegisterSignalHandler() to handle SIGTERM events.
236 void SigTermHandler(int signal_number);
237 #endif
239 // Called to initialize resources on the UI thread.
240 void StartOnUiThread();
242 // Initializes IPC control channel and config file path from |cmd_line|.
243 // Called on the UI thread.
244 bool InitWithCommandLine(const base::CommandLine* cmd_line);
246 // Called on the UI thread to start monitoring the configuration file.
247 void StartWatchingConfigChanges();
249 // Called on the network thread to set the host's Authenticator factory.
250 void CreateAuthenticatorFactory();
252 // Tear down resources that run on the UI thread.
253 void ShutdownOnUiThread();
255 // Applies the host config, returning true if successful.
256 bool ApplyConfig(const base::DictionaryValue& config);
258 // Handles policy updates, by calling On*PolicyUpdate methods.
259 void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies);
260 void OnPolicyError();
261 void ReportPolicyErrorAndRestartHost();
262 void ApplyHostDomainPolicy();
263 void ApplyUsernamePolicy();
264 bool OnHostDomainPolicyUpdate(base::DictionaryValue* policies);
265 bool OnUsernamePolicyUpdate(base::DictionaryValue* policies);
266 bool OnNatPolicyUpdate(base::DictionaryValue* policies);
267 bool OnRelayPolicyUpdate(base::DictionaryValue* policies);
268 bool OnUdpPortPolicyUpdate(base::DictionaryValue* policies);
269 bool OnCurtainPolicyUpdate(base::DictionaryValue* policies);
270 bool OnHostTalkGadgetPrefixPolicyUpdate(base::DictionaryValue* policies);
271 bool OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies);
272 bool OnPairingPolicyUpdate(base::DictionaryValue* policies);
273 bool OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies);
275 void InitializeSignaling();
277 void StartHostIfReady();
278 void StartHost();
280 // Error handler for HeartbeatSender.
281 void OnHeartbeatSuccessful();
282 void OnUnknownHostIdError();
284 // Error handler for SignalingConnector.
285 void OnAuthFailed();
287 void RestartHost(const std::string& host_offline_reason);
288 void ShutdownHost(HostExitCodes exit_code);
290 // Helper methods doing the work needed by RestartHost and ShutdownHost.
291 void GoOffline(const std::string& host_offline_reason);
292 void OnHostOfflineReasonAck(bool success);
294 #if defined(OS_WIN)
295 // Initializes the pairing registry on Windows. This should be invoked on the
296 // network thread.
297 void InitializePairingRegistry(
298 IPC::PlatformFileForTransit privileged_key,
299 IPC::PlatformFileForTransit unprivileged_key);
300 #endif // defined(OS_WIN)
302 // Crashes the process in response to a daemon's request. The daemon passes
303 // the location of the code that detected the fatal error resulted in this
304 // request.
305 void OnCrash(const std::string& function_name,
306 const std::string& file_name,
307 const int& line_number);
309 scoped_ptr<ChromotingHostContext> context_;
311 // Accessed on the UI thread.
312 scoped_ptr<IPC::ChannelProxy> daemon_channel_;
314 // XMPP server/remoting bot configuration (initialized from the command line).
315 XmppSignalStrategy::XmppServerConfig xmpp_server_config_;
316 std::string directory_bot_jid_;
318 // Created on the UI thread but used from the network thread.
319 base::FilePath host_config_path_;
320 std::string host_config_;
321 scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
323 // Accessed on the network thread.
324 HostState state_;
326 scoped_ptr<ConfigWatcher> config_watcher_;
328 std::string host_id_;
329 protocol::SharedSecretHash host_secret_hash_;
330 scoped_refptr<RsaKeyPair> key_pair_;
331 std::string oauth_refresh_token_;
332 std::string serialized_config_;
333 std::string host_owner_;
334 std::string host_owner_email_;
335 bool use_service_account_;
336 bool enable_vp9_;
337 int64_t frame_recorder_buffer_size_;
338 std::string gcd_device_id_;
340 scoped_ptr<PolicyWatcher> policy_watcher_;
341 PolicyState policy_state_;
342 std::string host_domain_;
343 bool host_username_match_required_;
344 bool allow_nat_traversal_;
345 bool allow_relay_;
346 PortRange udp_port_range_;
347 std::string talkgadget_prefix_;
348 bool allow_pairing_;
350 bool curtain_required_;
351 ThirdPartyAuthConfig third_party_auth_config_;
352 bool enable_gnubby_auth_;
354 // Boolean to change flow, where necessary, if we're
355 // capturing a window instead of the entire desktop.
356 bool enable_window_capture_;
358 // Used to specify which window to stream, if enabled.
359 webrtc::WindowId window_id_;
361 // |heartbeat_sender_| and |signaling_connector_| have to be destroyed before
362 // |signal_strategy_| because their destructors need to call
363 // signal_strategy_->RemoveListener(this)
364 scoped_ptr<SignalStrategy> signal_strategy_;
365 scoped_ptr<SignalingConnector> signaling_connector_;
366 scoped_ptr<HeartbeatSender> heartbeat_sender_;
368 scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_;
369 scoped_ptr<HostStatusLogger> host_status_logger_;
370 scoped_ptr<HostEventLogger> host_event_logger_;
372 scoped_ptr<ChromotingHost> host_;
374 // Used to keep this HostProcess alive until it is shutdown.
375 scoped_refptr<HostProcess> self_;
377 #if defined(REMOTING_MULTI_PROCESS)
378 DesktopSessionConnector* desktop_session_connector_;
379 #endif // defined(REMOTING_MULTI_PROCESS)
381 int* exit_code_out_;
382 bool signal_parent_;
384 scoped_refptr<PairingRegistry> pairing_registry_;
386 ShutdownWatchdog* shutdown_watchdog_;
388 DISALLOW_COPY_AND_ASSIGN(HostProcess);
391 HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context,
392 int* exit_code_out,
393 ShutdownWatchdog* shutdown_watchdog)
394 : context_(context.Pass()),
395 state_(HOST_STARTING),
396 use_service_account_(false),
397 enable_vp9_(false),
398 frame_recorder_buffer_size_(0),
399 policy_state_(POLICY_INITIALIZING),
400 host_username_match_required_(false),
401 allow_nat_traversal_(true),
402 allow_relay_(true),
403 allow_pairing_(true),
404 curtain_required_(false),
405 enable_gnubby_auth_(false),
406 enable_window_capture_(false),
407 window_id_(0),
408 #if defined(REMOTING_MULTI_PROCESS)
409 desktop_session_connector_(nullptr),
410 #endif // defined(REMOTING_MULTI_PROCESS)
411 self_(this),
412 exit_code_out_(exit_code_out),
413 signal_parent_(false),
414 shutdown_watchdog_(shutdown_watchdog) {
415 StartOnUiThread();
418 HostProcess::~HostProcess() {
419 // Verify that UI components have been torn down.
420 DCHECK(!config_watcher_);
421 DCHECK(!daemon_channel_);
422 DCHECK(!desktop_environment_factory_);
424 // We might be getting deleted on one of the threads the |host_context| owns,
425 // so we need to post it back to the caller thread to safely join & delete the
426 // threads it contains. This will go away when we move to AutoThread.
427 // |context_release()| will null |context_| before the method is invoked, so
428 // we need to pull out the task-runner on which to call DeleteSoon first.
429 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
430 context_->ui_task_runner();
431 task_runner->DeleteSoon(FROM_HERE, context_.release());
434 bool HostProcess::InitWithCommandLine(const base::CommandLine* cmd_line) {
435 #if defined(REMOTING_MULTI_PROCESS)
436 // Parse the handle value and convert it to a handle/file descriptor.
437 std::string channel_name =
438 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
440 int pipe_handle = 0;
441 if (channel_name.empty() ||
442 !base::StringToInt(channel_name, &pipe_handle)) {
443 LOG(ERROR) << "Invalid '" << kDaemonPipeSwitchName
444 << "' value: " << channel_name;
445 return false;
448 #if defined(OS_WIN)
449 base::win::ScopedHandle pipe(reinterpret_cast<HANDLE>(pipe_handle));
450 IPC::ChannelHandle channel_handle(pipe.Get());
451 #elif defined(OS_POSIX)
452 base::FileDescriptor pipe(pipe_handle, true);
453 IPC::ChannelHandle channel_handle(channel_name, pipe);
454 #endif // defined(OS_POSIX)
456 // Connect to the daemon process.
457 daemon_channel_ = IPC::ChannelProxy::Create(channel_handle,
458 IPC::Channel::MODE_CLIENT,
459 this,
460 context_->network_task_runner());
461 #else // !defined(REMOTING_MULTI_PROCESS)
462 // Connect to the daemon process.
463 std::string channel_name =
464 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
465 if (!channel_name.empty()) {
466 daemon_channel_ =
467 IPC::ChannelProxy::Create(channel_name,
468 IPC::Channel::MODE_CLIENT,
469 this,
470 context_->network_task_runner().get());
473 if (cmd_line->HasSwitch(kHostConfigSwitchName)) {
474 host_config_path_ = cmd_line->GetSwitchValuePath(kHostConfigSwitchName);
476 // Read config from stdin if necessary.
477 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
478 char buf[4096];
479 size_t len;
480 while ((len = fread(buf, 1, sizeof(buf), stdin)) > 0) {
481 host_config_.append(buf, len);
484 } else {
485 base::FilePath default_config_dir = remoting::GetConfigDir();
486 host_config_path_ = default_config_dir.Append(kDefaultHostConfigFile);
489 if (host_config_path_ != base::FilePath(kStdinConfigPath) &&
490 !base::PathExists(host_config_path_)) {
491 LOG(ERROR) << "Can't find host config at " << host_config_path_.value();
492 return false;
494 #endif // !defined(REMOTING_MULTI_PROCESS)
496 // Ignore certificate requests - the host currently has no client certificate
497 // support, so ignoring certificate requests allows connecting to servers that
498 // request, but don't require, a certificate (optional client authentication).
499 net::URLFetcher::SetIgnoreCertificateRequests(true);
501 ServiceUrls* service_urls = ServiceUrls::GetInstance();
503 const std::string& xmpp_server =
504 service_urls->xmpp_server_address_for_me2me_host();
505 if (!net::ParseHostAndPort(xmpp_server, &xmpp_server_config_.host,
506 &xmpp_server_config_.port)) {
507 LOG(ERROR) << "Invalid XMPP server: " << xmpp_server;
508 return false;
510 xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls();
511 directory_bot_jid_ = service_urls->directory_bot_jid();
513 signal_parent_ = cmd_line->HasSwitch(kSignalParentSwitchName);
515 enable_window_capture_ = cmd_line->HasSwitch(kWindowIdSwitchName);
516 if (enable_window_capture_) {
518 #if defined(OS_LINUX) || defined(OS_WIN)
519 LOG(WARNING) << "Window capturing is not fully supported on Linux or "
520 "Windows.";
521 #endif // defined(OS_LINUX) || defined(OS_WIN)
523 // uint32_t is large enough to hold window IDs on all platforms.
524 uint32_t window_id;
525 if (base::StringToUint(
526 cmd_line->GetSwitchValueASCII(kWindowIdSwitchName),
527 &window_id)) {
528 window_id_ = static_cast<webrtc::WindowId>(window_id);
529 } else {
530 LOG(ERROR) << "Window with window id: " << window_id_
531 << " not found. Shutting down host.";
532 return false;
535 return true;
538 void HostProcess::OnConfigUpdated(
539 const std::string& serialized_config) {
540 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
541 context_->network_task_runner()->PostTask(FROM_HERE,
542 base::Bind(&HostProcess::OnConfigUpdated, this, serialized_config));
543 return;
546 // Filter out duplicates.
547 if (serialized_config_ == serialized_config)
548 return;
550 HOST_LOG << "Processing new host configuration.";
552 serialized_config_ = serialized_config;
553 scoped_ptr<base::DictionaryValue> config(
554 HostConfigFromJson(serialized_config));
555 if (!config) {
556 LOG(ERROR) << "Invalid configuration.";
557 ShutdownHost(kInvalidHostConfigurationExitCode);
558 return;
561 if (!ApplyConfig(*config)) {
562 LOG(ERROR) << "Failed to apply the configuration.";
563 ShutdownHost(kInvalidHostConfigurationExitCode);
564 return;
567 if (state_ == HOST_STARTING) {
568 StartHostIfReady();
569 } else if (state_ == HOST_STARTED) {
570 // Reapply policies that could be affected by a new config.
571 DCHECK_EQ(policy_state_, POLICY_LOADED);
572 ApplyHostDomainPolicy();
573 ApplyUsernamePolicy();
575 // TODO(sergeyu): Here we assume that PIN is the only part of the config
576 // that may change while the service is running. Change ApplyConfig() to
577 // detect other changes in the config and restart host if necessary here.
578 CreateAuthenticatorFactory();
582 void HostProcess::OnConfigWatcherError() {
583 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
584 ShutdownHost(kInvalidHostConfigurationExitCode);
587 // Allowed state transitions (enforced via DCHECKs in SetState method):
588 // STARTING->STARTED (once we have valid config + policy)
589 // STARTING->GOING_OFFLINE_TO_STOP
590 // STARTING->GOING_OFFLINE_TO_RESTART
591 // STARTED->GOING_OFFLINE_TO_STOP
592 // STARTED->GOING_OFFLINE_TO_RESTART
593 // GOING_OFFLINE_TO_RESTART->GOING_OFFLINE_TO_STOP
594 // GOING_OFFLINE_TO_RESTART->STARTING (after OnHostOfflineReasonAck)
595 // GOING_OFFLINE_TO_STOP->STOPPED (after OnHostOfflineReasonAck)
597 // |host_| must be not-null in STARTED state and nullptr in all other states
598 // (although this invariant can be temporarily violated when doing
599 // synchronous processing on the networking thread).
600 void HostProcess::SetState(HostState target_state) {
601 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
603 // DCHECKs below enforce state allowed transitions listed in HostState.
604 switch (state_) {
605 case HOST_STARTING:
606 DCHECK((target_state == HOST_STARTED) ||
607 (target_state == HOST_GOING_OFFLINE_TO_STOP) ||
608 (target_state == HOST_GOING_OFFLINE_TO_RESTART))
609 << state_ << " -> " << target_state;
610 break;
611 case HOST_STARTED:
612 DCHECK((target_state == HOST_GOING_OFFLINE_TO_STOP) ||
613 (target_state == HOST_GOING_OFFLINE_TO_RESTART))
614 << state_ << " -> " << target_state;
615 break;
616 case HOST_GOING_OFFLINE_TO_RESTART:
617 DCHECK((target_state == HOST_GOING_OFFLINE_TO_STOP) ||
618 (target_state == HOST_STARTING))
619 << state_ << " -> " << target_state;
620 break;
621 case HOST_GOING_OFFLINE_TO_STOP:
622 DCHECK_EQ(target_state, HOST_STOPPED);
623 break;
624 case HOST_STOPPED: // HOST_STOPPED is a terminal state.
625 default:
626 NOTREACHED() << state_ << " -> " << target_state;
627 break;
629 state_ = target_state;
632 void HostProcess::StartOnNetworkThread() {
633 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
635 #if !defined(REMOTING_MULTI_PROCESS)
636 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
637 // Process config we've read from stdin.
638 OnConfigUpdated(host_config_);
639 } else {
640 // Start watching the host configuration file.
641 config_watcher_.reset(new ConfigFileWatcher(context_->network_task_runner(),
642 context_->file_task_runner(),
643 host_config_path_));
644 config_watcher_->Watch(this);
646 #endif // !defined(REMOTING_MULTI_PROCESS)
648 #if defined(OS_POSIX)
649 remoting::RegisterSignalHandler(
650 SIGTERM,
651 base::Bind(&HostProcess::SigTermHandler, base::Unretained(this)));
652 #endif // defined(OS_POSIX)
655 #if defined(OS_POSIX)
656 void HostProcess::SigTermHandler(int signal_number) {
657 DCHECK(signal_number == SIGTERM);
658 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
659 HOST_LOG << "Caught SIGTERM: Shutting down...";
660 ShutdownHost(kSuccessExitCode);
662 #endif // OS_POSIX
664 void HostProcess::CreateAuthenticatorFactory() {
665 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
667 if (state_ != HOST_STARTED)
668 return;
670 std::string local_certificate = key_pair_->GenerateCertificate();
671 if (local_certificate.empty()) {
672 LOG(ERROR) << "Failed to generate host certificate.";
673 ShutdownHost(kInitializationFailed);
674 return;
677 scoped_ptr<protocol::AuthenticatorFactory> factory;
679 if (third_party_auth_config_.is_null()) {
680 scoped_refptr<PairingRegistry> pairing_registry;
681 if (allow_pairing_) {
682 // On Windows |pairing_registry_| is initialized in
683 // InitializePairingRegistry().
684 #if !defined(OS_WIN)
685 if (!pairing_registry_) {
686 scoped_ptr<PairingRegistry::Delegate> delegate =
687 CreatePairingRegistryDelegate();
689 if (delegate)
690 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
691 delegate.Pass());
693 #endif // defined(OS_WIN)
695 pairing_registry = pairing_registry_;
698 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
699 use_service_account_, host_owner_, local_certificate, key_pair_,
700 host_secret_hash_, pairing_registry);
702 host_->set_pairing_registry(pairing_registry);
703 } else {
704 DCHECK(third_party_auth_config_.token_url.is_valid());
705 DCHECK(third_party_auth_config_.token_validation_url.is_valid());
707 scoped_ptr<protocol::TokenValidatorFactory> token_validator_factory(
708 new TokenValidatorFactoryImpl(
709 third_party_auth_config_,
710 key_pair_, context_->url_request_context_getter()));
711 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
712 use_service_account_, host_owner_, local_certificate, key_pair_,
713 token_validator_factory.Pass());
716 #if defined(OS_POSIX)
717 // On Linux and Mac, perform a PAM authorization step after authentication.
718 factory.reset(new PamAuthorizationFactory(factory.Pass()));
719 #endif
720 host_->SetAuthenticatorFactory(factory.Pass());
723 // IPC::Listener implementation.
724 bool HostProcess::OnMessageReceived(const IPC::Message& message) {
725 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
727 #if defined(REMOTING_MULTI_PROCESS)
728 bool handled = true;
729 IPC_BEGIN_MESSAGE_MAP(HostProcess, message)
730 IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash)
731 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration,
732 OnConfigUpdated)
733 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_InitializePairingRegistry,
734 OnInitializePairingRegistry)
735 IPC_MESSAGE_FORWARD(
736 ChromotingDaemonNetworkMsg_DesktopAttached,
737 desktop_session_connector_,
738 DesktopSessionConnector::OnDesktopSessionAgentAttached)
739 IPC_MESSAGE_FORWARD(ChromotingDaemonNetworkMsg_TerminalDisconnected,
740 desktop_session_connector_,
741 DesktopSessionConnector::OnTerminalDisconnected)
742 IPC_MESSAGE_UNHANDLED(handled = false)
743 IPC_END_MESSAGE_MAP()
745 CHECK(handled) << "Received unexpected IPC type: " << message.type();
746 return handled;
748 #else // !defined(REMOTING_MULTI_PROCESS)
749 return false;
750 #endif // !defined(REMOTING_MULTI_PROCESS)
753 void HostProcess::OnChannelError() {
754 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
756 // Shutdown the host if the daemon process disconnects the IPC channel.
757 context_->network_task_runner()->PostTask(
758 FROM_HERE,
759 base::Bind(&HostProcess::ShutdownHost, this, kSuccessExitCode));
762 void HostProcess::StartOnUiThread() {
763 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
765 if (!InitWithCommandLine(base::CommandLine::ForCurrentProcess())) {
766 // Shutdown the host if the command line is invalid.
767 context_->network_task_runner()->PostTask(
768 FROM_HERE, base::Bind(&HostProcess::ShutdownHost, this,
769 kUsageExitCode));
770 return;
773 policy_watcher_ =
774 PolicyWatcher::Create(nullptr, context_->file_task_runner());
775 policy_watcher_->StartWatching(
776 base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)),
777 base::Bind(&HostProcess::OnPolicyError, base::Unretained(this)));
779 #if defined(OS_LINUX)
780 // If an audio pipe is specific on the command-line then initialize
781 // AudioCapturerLinux to capture from it.
782 base::FilePath audio_pipe_name = base::CommandLine::ForCurrentProcess()->
783 GetSwitchValuePath(kAudioPipeSwitchName);
784 if (!audio_pipe_name.empty()) {
785 remoting::AudioCapturerLinux::InitializePipeReader(
786 context_->audio_task_runner(), audio_pipe_name);
789 base::FilePath gnubby_socket_name = base::CommandLine::ForCurrentProcess()->
790 GetSwitchValuePath(kAuthSocknameSwitchName);
791 if (!gnubby_socket_name.empty())
792 remoting::GnubbyAuthHandler::SetGnubbySocketName(gnubby_socket_name);
793 #endif // defined(OS_LINUX)
795 // Create a desktop environment factory appropriate to the build type &
796 // platform.
797 #if defined(OS_WIN)
798 IpcDesktopEnvironmentFactory* desktop_environment_factory =
799 new IpcDesktopEnvironmentFactory(
800 context_->audio_task_runner(),
801 context_->network_task_runner(),
802 context_->video_capture_task_runner(),
803 context_->network_task_runner(),
804 daemon_channel_.get());
805 desktop_session_connector_ = desktop_environment_factory;
806 #else // !defined(OS_WIN)
807 DesktopEnvironmentFactory* desktop_environment_factory;
808 if (enable_window_capture_) {
809 desktop_environment_factory =
810 new SingleWindowDesktopEnvironmentFactory(
811 context_->network_task_runner(),
812 context_->input_task_runner(),
813 context_->ui_task_runner(),
814 window_id_);
815 } else {
816 desktop_environment_factory =
817 new Me2MeDesktopEnvironmentFactory(
818 context_->network_task_runner(),
819 context_->input_task_runner(),
820 context_->ui_task_runner());
822 #endif // !defined(OS_WIN)
824 desktop_environment_factory_.reset(desktop_environment_factory);
825 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
827 context_->network_task_runner()->PostTask(
828 FROM_HERE,
829 base::Bind(&HostProcess::StartOnNetworkThread, this));
832 void HostProcess::ShutdownOnUiThread() {
833 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
835 // Tear down resources that need to be torn down on the UI thread.
836 daemon_channel_.reset();
837 desktop_environment_factory_.reset();
838 policy_watcher_.reset();
840 // It is now safe for the HostProcess to be deleted.
841 self_ = nullptr;
843 #if defined(OS_LINUX)
844 // Cause the global AudioPipeReader to be freed, otherwise the audio
845 // thread will remain in-use and prevent the process from exiting.
846 // TODO(wez): DesktopEnvironmentFactory should own the pipe reader.
847 // See crbug.com/161373 and crbug.com/104544.
848 AudioCapturerLinux::InitializePipeReader(nullptr, base::FilePath());
849 #endif
852 void HostProcess::OnUnknownHostIdError() {
853 LOG(ERROR) << "Host ID not found.";
854 ShutdownHost(kInvalidHostIdExitCode);
857 void HostProcess::OnHeartbeatSuccessful() {
858 HOST_LOG << "Host ready to receive connections.";
859 #if defined(OS_POSIX)
860 if (signal_parent_) {
861 kill(getppid(), SIGUSR1);
862 signal_parent_ = false;
864 #endif
867 void HostProcess::OnHostDeleted() {
868 LOG(ERROR) << "Host was deleted from the directory.";
869 ShutdownHost(kInvalidHostIdExitCode);
872 void HostProcess::OnInitializePairingRegistry(
873 IPC::PlatformFileForTransit privileged_key,
874 IPC::PlatformFileForTransit unprivileged_key) {
875 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
877 #if defined(OS_WIN)
878 context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
879 &HostProcess::InitializePairingRegistry,
880 this, privileged_key, unprivileged_key));
881 #else // !defined(OS_WIN)
882 NOTREACHED();
883 #endif // !defined(OS_WIN)
886 #if defined(OS_WIN)
887 void HostProcess::InitializePairingRegistry(
888 IPC::PlatformFileForTransit privileged_key,
889 IPC::PlatformFileForTransit unprivileged_key) {
890 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
891 // |privileged_key| can be nullptr but not |unprivileged_key|.
892 DCHECK(unprivileged_key);
893 // |pairing_registry_| should only be initialized once.
894 DCHECK(!pairing_registry_);
896 HKEY privileged_hkey = reinterpret_cast<HKEY>(
897 IPC::PlatformFileForTransitToPlatformFile(privileged_key));
898 HKEY unprivileged_hkey = reinterpret_cast<HKEY>(
899 IPC::PlatformFileForTransitToPlatformFile(unprivileged_key));
901 scoped_ptr<PairingRegistryDelegateWin> delegate(
902 new PairingRegistryDelegateWin());
903 delegate->SetRootKeys(privileged_hkey, unprivileged_hkey);
905 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
906 delegate.Pass());
908 // (Re)Create the authenticator factory now that |pairing_registry_| has been
909 // initialized.
910 CreateAuthenticatorFactory();
912 #endif // !defined(OS_WIN)
914 // Applies the host config, returning true if successful.
915 bool HostProcess::ApplyConfig(const base::DictionaryValue& config) {
916 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
918 if (!config.GetString(kHostIdConfigPath, &host_id_)) {
919 LOG(ERROR) << "host_id is not defined in the config.";
920 return false;
923 std::string key_base64;
924 if (!config.GetString(kPrivateKeyConfigPath, &key_base64)) {
925 LOG(ERROR) << "Private key couldn't be read from the config file.";
926 return false;
929 key_pair_ = RsaKeyPair::FromString(key_base64);
930 if (!key_pair_.get()) {
931 LOG(ERROR) << "Invalid private key in the config file.";
932 return false;
935 std::string host_secret_hash_string;
936 if (!config.GetString(kHostSecretHashConfigPath,
937 &host_secret_hash_string)) {
938 host_secret_hash_string = "plain:";
941 if (!host_secret_hash_.Parse(host_secret_hash_string)) {
942 LOG(ERROR) << "Invalid host_secret_hash.";
943 return false;
946 // Use an XMPP connection to the Talk network for session signaling.
947 if (!config.GetString(kXmppLoginConfigPath, &xmpp_server_config_.username) ||
948 !config.GetString(kOAuthRefreshTokenConfigPath, &oauth_refresh_token_)) {
949 LOG(ERROR) << "XMPP credentials are not defined in the config.";
950 return false;
953 if (config.GetString(kHostOwnerConfigPath, &host_owner_)) {
954 // Service account configs have a host_owner, different from the xmpp_login.
955 use_service_account_ = true;
956 } else {
957 // User credential configs only have an xmpp_login, which is also the owner.
958 host_owner_ = xmpp_server_config_.username;
959 use_service_account_ = false;
962 // For non-Gmail Google accounts, the owner base JID differs from the email.
963 // host_owner_ contains the base JID (used for authenticating clients), while
964 // host_owner_email contains the account's email (used for UI and logs).
965 if (!config.GetString(kHostOwnerEmailConfigPath, &host_owner_email_)) {
966 host_owner_email_ = host_owner_;
969 // Allow offering of VP9 encoding to be overridden by the command-line.
970 if (base::CommandLine::ForCurrentProcess()->HasSwitch(kEnableVp9SwitchName)) {
971 enable_vp9_ = true;
972 } else {
973 config.GetBoolean(kEnableVp9ConfigPath, &enable_vp9_);
976 // Allow the command-line to override the size of the frame recorder buffer.
977 int frame_recorder_buffer_kb = 0;
978 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
979 kFrameRecorderBufferKbName)) {
980 std::string switch_value =
981 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
982 kFrameRecorderBufferKbName);
983 base::StringToInt(switch_value, &frame_recorder_buffer_kb);
984 } else {
985 config.GetInteger(kFrameRecorderBufferKbConfigPath,
986 &frame_recorder_buffer_kb);
988 if (frame_recorder_buffer_kb > 0) {
989 frame_recorder_buffer_size_ = 1024LL * frame_recorder_buffer_kb;
992 if (!config.GetString(kGcdDeviceIdConfigPath, &gcd_device_id_)) {
993 gcd_device_id_.clear();
996 return true;
999 void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
1000 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
1001 context_->network_task_runner()->PostTask(
1002 FROM_HERE, base::Bind(&HostProcess::OnPolicyUpdate, this,
1003 base::Passed(&policies)));
1004 return;
1007 bool restart_required = false;
1008 restart_required |= OnHostDomainPolicyUpdate(policies.get());
1009 restart_required |= OnCurtainPolicyUpdate(policies.get());
1010 // Note: UsernamePolicyUpdate must run after OnCurtainPolicyUpdate.
1011 restart_required |= OnUsernamePolicyUpdate(policies.get());
1012 restart_required |= OnNatPolicyUpdate(policies.get());
1013 restart_required |= OnRelayPolicyUpdate(policies.get());
1014 restart_required |= OnUdpPortPolicyUpdate(policies.get());
1015 restart_required |= OnHostTalkGadgetPrefixPolicyUpdate(policies.get());
1016 restart_required |= OnHostTokenUrlPolicyUpdate(policies.get());
1017 restart_required |= OnPairingPolicyUpdate(policies.get());
1018 restart_required |= OnGnubbyAuthPolicyUpdate(policies.get());
1020 policy_state_ = POLICY_LOADED;
1022 if (state_ == HOST_STARTING) {
1023 StartHostIfReady();
1024 } else if (state_ == HOST_STARTED) {
1025 if (restart_required)
1026 RestartHost(kHostOfflineReasonPolicyChangeRequiresRestart);
1030 void HostProcess::OnPolicyError() {
1031 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
1032 context_->network_task_runner()->PostTask(
1033 FROM_HERE, base::Bind(&HostProcess::OnPolicyError, this));
1034 return;
1037 if (policy_state_ != POLICY_ERROR_REPORTED) {
1038 policy_state_ = POLICY_ERROR_REPORT_PENDING;
1039 if ((state_ == HOST_STARTED) ||
1040 (state_ == HOST_STARTING && !serialized_config_.empty())) {
1041 ReportPolicyErrorAndRestartHost();
1046 void HostProcess::ReportPolicyErrorAndRestartHost() {
1047 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1048 DCHECK(!serialized_config_.empty());
1050 DCHECK_EQ(policy_state_, POLICY_ERROR_REPORT_PENDING);
1051 policy_state_ = POLICY_ERROR_REPORTED;
1053 LOG(INFO) << "Restarting the host due to policy errors.";
1054 RestartHost(kHostOfflineReasonPolicyReadError);
1057 void HostProcess::ApplyHostDomainPolicy() {
1058 if (state_ != HOST_STARTED)
1059 return;
1061 HOST_LOG << "Policy sets host domain: " << host_domain_;
1063 if (!host_domain_.empty()) {
1064 // If the user does not have a Google email, their client JID will not be
1065 // based on their email. In that case, the username/host domain policies
1066 // would be meaningless, since there is no way to check that the JID
1067 // trying to connect actually corresponds to the owner email in question.
1068 if (host_owner_ != host_owner_email_) {
1069 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1070 << "for accounts with a non-Google email.";
1071 ShutdownHost(kInvalidHostDomainExitCode);
1074 if (!EndsWith(host_owner_, std::string("@") + host_domain_, false)) {
1075 LOG(ERROR) << "The host domain does not match the policy.";
1076 ShutdownHost(kInvalidHostDomainExitCode);
1081 bool HostProcess::OnHostDomainPolicyUpdate(base::DictionaryValue* policies) {
1082 // Returns true if the host has to be restarted after this policy update.
1083 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1085 if (!policies->GetString(policy::key::kRemoteAccessHostDomain,
1086 &host_domain_)) {
1087 return false;
1090 ApplyHostDomainPolicy();
1091 return false;
1094 void HostProcess::ApplyUsernamePolicy() {
1095 if (state_ != HOST_STARTED)
1096 return;
1098 if (host_username_match_required_) {
1099 HOST_LOG << "Policy requires host username match.";
1101 // See comment in ApplyHostDomainPolicy.
1102 if (host_owner_ != host_owner_email_) {
1103 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1104 << "for accounts with a non-Google email.";
1105 ShutdownHost(kUsernameMismatchExitCode);
1108 std::string username = GetUsername();
1109 bool shutdown = username.empty() ||
1110 !StartsWithASCII(host_owner_, username + std::string("@"),
1111 false);
1113 #if defined(OS_MACOSX)
1114 // On Mac, we run as root at the login screen, so the username won't match.
1115 // However, there's no need to enforce the policy at the login screen, as
1116 // the client will have to reconnect if a login occurs.
1117 if (shutdown && getuid() == 0) {
1118 shutdown = false;
1120 #endif
1122 // Curtain-mode on Windows presents the standard OS login prompt to the user
1123 // for each connection, removing the need for an explicit user-name matching
1124 // check.
1125 #if defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1126 if (curtain_required_)
1127 return;
1128 #endif // defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1130 // Shutdown the host if the username does not match.
1131 if (shutdown) {
1132 LOG(ERROR) << "The host username does not match.";
1133 ShutdownHost(kUsernameMismatchExitCode);
1135 } else {
1136 HOST_LOG << "Policy does not require host username match.";
1140 bool HostProcess::OnUsernamePolicyUpdate(base::DictionaryValue* policies) {
1141 // Returns false: never restart the host after this policy update.
1142 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1144 if (!policies->GetBoolean(policy::key::kRemoteAccessHostMatchUsername,
1145 &host_username_match_required_)) {
1146 return false;
1149 ApplyUsernamePolicy();
1150 return false;
1153 bool HostProcess::OnNatPolicyUpdate(base::DictionaryValue* policies) {
1154 // Returns true if the host has to be restarted after this policy update.
1155 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1157 if (!policies->GetBoolean(policy::key::kRemoteAccessHostFirewallTraversal,
1158 &allow_nat_traversal_)) {
1159 return false;
1162 if (allow_nat_traversal_) {
1163 HOST_LOG << "Policy enables NAT traversal.";
1164 } else {
1165 HOST_LOG << "Policy disables NAT traversal.";
1167 return true;
1170 bool HostProcess::OnRelayPolicyUpdate(base::DictionaryValue* policies) {
1171 // Returns true if the host has to be restarted after this policy update.
1172 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1174 if (!policies->GetBoolean(
1175 policy::key::kRemoteAccessHostAllowRelayedConnection,
1176 &allow_relay_)) {
1177 return false;
1180 if (allow_relay_) {
1181 HOST_LOG << "Policy enables use of relay server.";
1182 } else {
1183 HOST_LOG << "Policy disables use of relay server.";
1185 return true;
1188 bool HostProcess::OnUdpPortPolicyUpdate(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 std::string string_value;
1193 if (!policies->GetString(policy::key::kRemoteAccessHostUdpPortRange,
1194 &string_value)) {
1195 return false;
1198 DCHECK(PortRange::Parse(string_value, &udp_port_range_));
1199 HOST_LOG << "Policy restricts UDP port range to: " << udp_port_range_;
1200 return true;
1203 bool HostProcess::OnCurtainPolicyUpdate(base::DictionaryValue* policies) {
1204 // Returns true if the host has to be restarted after this policy update.
1205 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1207 if (!policies->GetBoolean(policy::key::kRemoteAccessHostRequireCurtain,
1208 &curtain_required_)) {
1209 return false;
1212 #if defined(OS_MACOSX)
1213 if (curtain_required_) {
1214 // When curtain mode is in effect on Mac, the host process runs in the
1215 // user's switched-out session, but launchd will also run an instance at
1216 // the console login screen. Even if no user is currently logged-on, we
1217 // can't support remote-access to the login screen because the current host
1218 // process model disconnects the client during login, which would leave
1219 // the logged in session un-curtained on the console until they reconnect.
1221 // TODO(jamiewalch): Fix this once we have implemented the multi-process
1222 // daemon architecture (crbug.com/134894)
1223 if (getuid() == 0) {
1224 LOG(ERROR) << "Running the host in the console login session is yet not "
1225 "supported.";
1226 ShutdownHost(kLoginScreenNotSupportedExitCode);
1227 return false;
1230 #endif
1232 if (curtain_required_) {
1233 HOST_LOG << "Policy requires curtain-mode.";
1234 } else {
1235 HOST_LOG << "Policy does not require curtain-mode.";
1238 if (host_)
1239 host_->SetEnableCurtaining(curtain_required_);
1240 return false;
1243 bool HostProcess::OnHostTalkGadgetPrefixPolicyUpdate(
1244 base::DictionaryValue* policies) {
1245 // Returns true if the host has to be restarted after this policy update.
1246 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1248 if (!policies->GetString(policy::key::kRemoteAccessHostTalkGadgetPrefix,
1249 &talkgadget_prefix_)) {
1250 return false;
1253 HOST_LOG << "Policy sets talkgadget prefix: " << talkgadget_prefix_;
1254 return true;
1257 bool HostProcess::OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies) {
1258 switch (ThirdPartyAuthConfig::Parse(*policies, &third_party_auth_config_)) {
1259 case ThirdPartyAuthConfig::NoPolicy:
1260 return false;
1261 case ThirdPartyAuthConfig::ParsingSuccess:
1262 HOST_LOG << "Policy sets third-party token URLs: "
1263 << third_party_auth_config_;
1264 return true;
1265 case ThirdPartyAuthConfig::InvalidPolicy:
1266 default:
1267 NOTREACHED();
1268 return false;
1272 bool HostProcess::OnPairingPolicyUpdate(base::DictionaryValue* policies) {
1273 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1275 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowClientPairing,
1276 &allow_pairing_)) {
1277 return false;
1280 if (allow_pairing_) {
1281 HOST_LOG << "Policy enables client pairing.";
1282 } else {
1283 HOST_LOG << "Policy disables client pairing.";
1285 return true;
1288 bool HostProcess::OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies) {
1289 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1291 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowGnubbyAuth,
1292 &enable_gnubby_auth_)) {
1293 return false;
1296 if (enable_gnubby_auth_) {
1297 HOST_LOG << "Policy enables gnubby auth.";
1298 } else {
1299 HOST_LOG << "Policy disables gnubby auth.";
1302 if (desktop_environment_factory_)
1303 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
1305 return true;
1308 void HostProcess::InitializeSignaling() {
1309 DCHECK(!host_id_.empty()); // |ApplyConfig| should already have been run.
1310 DCHECK(!signal_strategy_);
1312 // Create SignalStrategy.
1313 XmppSignalStrategy* xmpp_signal_strategy = new XmppSignalStrategy(
1314 net::ClientSocketFactory::GetDefaultFactory(),
1315 context_->url_request_context_getter(), xmpp_server_config_);
1316 signal_strategy_.reset(xmpp_signal_strategy);
1318 // Create SignalingConnector.
1319 scoped_ptr<DnsBlackholeChecker> dns_blackhole_checker(new DnsBlackholeChecker(
1320 context_->url_request_context_getter(), talkgadget_prefix_));
1321 scoped_ptr<OAuthTokenGetter::OAuthCredentials> oauth_credentials(
1322 new OAuthTokenGetter::OAuthCredentials(xmpp_server_config_.username,
1323 oauth_refresh_token_,
1324 use_service_account_));
1325 scoped_ptr<OAuthTokenGetter> oauth_token_getter(new OAuthTokenGetterImpl(
1326 oauth_credentials.Pass(), context_->url_request_context_getter(), false,
1327 gcd_device_id_.empty()));
1328 signaling_connector_.reset(new SignalingConnector(
1329 xmpp_signal_strategy, dns_blackhole_checker.Pass(),
1330 oauth_token_getter.Pass(),
1331 base::Bind(&HostProcess::OnAuthFailed, base::Unretained(this))));
1333 // Create HeartbeatSender.
1334 heartbeat_sender_.reset(new HeartbeatSender(
1335 base::Bind(&HostProcess::OnHeartbeatSuccessful, base::Unretained(this)),
1336 base::Bind(&HostProcess::OnUnknownHostIdError, base::Unretained(this)),
1337 host_id_, xmpp_signal_strategy, key_pair_, directory_bot_jid_));
1340 void HostProcess::StartHostIfReady() {
1341 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1342 DCHECK_EQ(state_, HOST_STARTING);
1344 // Start the host if both the config and the policies are loaded.
1345 if (!serialized_config_.empty()) {
1346 if (policy_state_ == POLICY_LOADED) {
1347 StartHost();
1348 } else if (policy_state_ == POLICY_ERROR_REPORT_PENDING) {
1349 ReportPolicyErrorAndRestartHost();
1354 void HostProcess::StartHost() {
1355 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1356 DCHECK(!host_);
1358 SetState(HOST_STARTED);
1360 InitializeSignaling();
1362 uint32 network_flags = 0;
1363 if (allow_nat_traversal_) {
1364 network_flags = NetworkSettings::NAT_TRAVERSAL_STUN |
1365 NetworkSettings::NAT_TRAVERSAL_OUTGOING;
1366 if (allow_relay_)
1367 network_flags |= NetworkSettings::NAT_TRAVERSAL_RELAY;
1370 NetworkSettings network_settings(network_flags);
1372 if (!udp_port_range_.is_null()) {
1373 network_settings.port_range = udp_port_range_;
1374 } else if (!allow_nat_traversal_) {
1375 // For legacy reasons we have to restrict the port range to a set of default
1376 // values when nat traversal is disabled, even if the port range was not
1377 // set in policy.
1378 network_settings.port_range.min_port = NetworkSettings::kDefaultMinPort;
1379 network_settings.port_range.max_port = NetworkSettings::kDefaultMaxPort;
1382 host_.reset(new ChromotingHost(
1383 signal_strategy_.get(), desktop_environment_factory_.get(),
1384 CreateHostSessionManager(signal_strategy_.get(), network_settings,
1385 context_->url_request_context_getter()),
1386 context_->audio_task_runner(), context_->input_task_runner(),
1387 context_->video_capture_task_runner(),
1388 context_->video_encode_task_runner(), context_->network_task_runner(),
1389 context_->ui_task_runner()));
1391 if (enable_vp9_) {
1392 scoped_ptr<protocol::CandidateSessionConfig> config =
1393 host_->protocol_config()->Clone();
1394 config->EnableVideoCodec(protocol::ChannelConfig::CODEC_VP9);
1395 host_->set_protocol_config(config.Pass());
1398 if (frame_recorder_buffer_size_ > 0) {
1399 scoped_ptr<VideoFrameRecorderHostExtension> frame_recorder_extension(
1400 new VideoFrameRecorderHostExtension());
1401 frame_recorder_extension->SetMaxContentBytes(frame_recorder_buffer_size_);
1402 host_->AddExtension(frame_recorder_extension.Pass());
1405 // TODO(simonmorris): Get the maximum session duration from a policy.
1406 #if defined(OS_LINUX)
1407 host_->SetMaximumSessionDuration(base::TimeDelta::FromHours(20));
1408 #endif
1410 host_change_notification_listener_.reset(new HostChangeNotificationListener(
1411 this, host_id_, signal_strategy_.get(), directory_bot_jid_));
1413 host_status_logger_.reset(
1414 new HostStatusLogger(host_->AsWeakPtr(), ServerLogEntry::ME2ME,
1415 signal_strategy_.get(), directory_bot_jid_));
1417 // Set up reporting the host status notifications.
1418 #if defined(REMOTING_MULTI_PROCESS)
1419 host_event_logger_.reset(
1420 new IpcHostEventLogger(host_->AsWeakPtr(), daemon_channel_.get()));
1421 #else // !defined(REMOTING_MULTI_PROCESS)
1422 host_event_logger_ =
1423 HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName);
1424 #endif // !defined(REMOTING_MULTI_PROCESS)
1426 host_->SetEnableCurtaining(curtain_required_);
1427 host_->Start(host_owner_email_);
1429 CreateAuthenticatorFactory();
1431 ApplyHostDomainPolicy();
1432 ApplyUsernamePolicy();
1435 void HostProcess::OnAuthFailed() {
1436 ShutdownHost(kInvalidOauthCredentialsExitCode);
1439 void HostProcess::RestartHost(const std::string& host_offline_reason) {
1440 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1441 DCHECK(!host_offline_reason.empty());
1443 SetState(HOST_GOING_OFFLINE_TO_RESTART);
1444 GoOffline(host_offline_reason);
1447 void HostProcess::ShutdownHost(HostExitCodes exit_code) {
1448 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1450 *exit_code_out_ = exit_code;
1452 switch (state_) {
1453 case HOST_STARTING:
1454 case HOST_STARTED:
1455 SetState(HOST_GOING_OFFLINE_TO_STOP);
1456 GoOffline(ExitCodeToString(exit_code));
1457 break;
1459 case HOST_GOING_OFFLINE_TO_RESTART:
1460 SetState(HOST_GOING_OFFLINE_TO_STOP);
1461 break;
1463 case HOST_GOING_OFFLINE_TO_STOP:
1464 case HOST_STOPPED:
1465 // Host is already stopped or being stopped. No action is required.
1466 break;
1470 void HostProcess::GoOffline(const std::string& host_offline_reason) {
1471 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1472 DCHECK(!host_offline_reason.empty());
1473 DCHECK((state_ == HOST_GOING_OFFLINE_TO_STOP) ||
1474 (state_ == HOST_GOING_OFFLINE_TO_RESTART));
1476 // Shut down everything except the HostSignalingManager.
1477 host_.reset();
1478 host_event_logger_.reset();
1479 host_status_logger_.reset();
1480 host_change_notification_listener_.reset();
1482 // Before shutting down HostSignalingManager, send the |host_offline_reason|
1483 // if possible (i.e. if we have the config).
1484 if (!serialized_config_.empty()) {
1485 if (!signal_strategy_)
1486 InitializeSignaling();
1488 HOST_LOG << "SendHostOfflineReason: sending " << host_offline_reason << ".";
1489 heartbeat_sender_->SetHostOfflineReason(
1490 host_offline_reason,
1491 base::TimeDelta::FromSeconds(kHostOfflineReasonTimeoutSeconds),
1492 base::Bind(&HostProcess::OnHostOfflineReasonAck, this));
1493 return; // Shutdown will resume after OnHostOfflineReasonAck.
1496 // Continue the shutdown without sending the host offline reason.
1497 HOST_LOG << "Can't send offline reason (" << host_offline_reason << ") "
1498 << "without a valid host config.";
1499 OnHostOfflineReasonAck(false);
1502 void HostProcess::OnHostOfflineReasonAck(bool success) {
1503 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1504 DCHECK(!host_); // Assert that the host is really offline at this point.
1506 HOST_LOG << "SendHostOfflineReason " << (success ? "succeeded." : "failed.");
1507 heartbeat_sender_.reset();
1508 signaling_connector_.reset();
1509 signal_strategy_.reset();
1511 if (state_ == HOST_GOING_OFFLINE_TO_RESTART) {
1512 SetState(HOST_STARTING);
1513 StartHostIfReady();
1514 } else if (state_ == HOST_GOING_OFFLINE_TO_STOP) {
1515 SetState(HOST_STOPPED);
1517 shutdown_watchdog_->SetExitCode(*exit_code_out_);
1518 shutdown_watchdog_->Arm();
1520 config_watcher_.reset();
1522 // Complete the rest of shutdown on the main thread.
1523 context_->ui_task_runner()->PostTask(
1524 FROM_HERE, base::Bind(&HostProcess::ShutdownOnUiThread, this));
1525 } else {
1526 NOTREACHED();
1530 void HostProcess::OnCrash(const std::string& function_name,
1531 const std::string& file_name,
1532 const int& line_number) {
1533 char message[1024];
1534 base::snprintf(message, sizeof(message),
1535 "Requested by %s at %s, line %d.",
1536 function_name.c_str(), file_name.c_str(), line_number);
1537 base::debug::Alias(message);
1539 // The daemon requested us to crash the process.
1540 CHECK(false) << message;
1543 int HostProcessMain() {
1544 #if defined(OS_LINUX)
1545 // Required in order for us to run multiple X11 threads.
1546 XInitThreads();
1548 // Required for any calls into GTK functions, such as the Disconnect and
1549 // Continue windows, though these should not be used for the Me2Me case
1550 // (crbug.com/104377).
1551 gtk_init(nullptr, nullptr);
1552 #endif
1554 // Enable support for SSL server sockets, which must be done while still
1555 // single-threaded.
1556 net::EnableSSLServerSockets();
1558 // Ensures runtime specific CPU features are initialized.
1559 media::InitializeCPUSpecificMediaFeatures();
1561 // Create the main message loop and start helper threads.
1562 base::MessageLoopForUI message_loop;
1563 scoped_ptr<ChromotingHostContext> context =
1564 ChromotingHostContext::Create(new AutoThreadTaskRunner(
1565 message_loop.message_loop_proxy(), base::MessageLoop::QuitClosure()));
1566 if (!context)
1567 return kInitializationFailed;
1569 // NetworkChangeNotifier must be initialized after MessageLoop.
1570 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier(
1571 net::NetworkChangeNotifier::Create());
1573 // Create & start the HostProcess using these threads.
1574 // TODO(wez): The HostProcess holds a reference to itself until Shutdown().
1575 // Remove this hack as part of the multi-process refactoring.
1576 int exit_code = kSuccessExitCode;
1577 ShutdownWatchdog shutdown_watchdog(
1578 base::TimeDelta::FromSeconds(kShutdownTimeoutSeconds));
1579 new HostProcess(context.Pass(), &exit_code, &shutdown_watchdog);
1581 // Run the main (also UI) message loop until the host no longer needs it.
1582 message_loop.Run();
1584 return exit_code;
1587 } // namespace remoting