[Sync] Test Android passphrase creation UI
[chromium-blink-merge.git] / remoting / host / remoting_me2me_host.cc
blob3573414d075f307f6b1629097c2886d3f5603ddb
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/network_change_notifier.h"
27 #include "net/socket/client_socket_factory.h"
28 #include "net/socket/ssl_server_socket.h"
29 #include "net/url_request/url_fetcher.h"
30 #include "policy/policy_constants.h"
31 #include "remoting/base/auto_thread_task_runner.h"
32 #include "remoting/base/breakpad.h"
33 #include "remoting/base/constants.h"
34 #include "remoting/base/logging.h"
35 #include "remoting/base/rsa_key_pair.h"
36 #include "remoting/base/service_urls.h"
37 #include "remoting/base/util.h"
38 #include "remoting/host/branding.h"
39 #include "remoting/host/chromoting_host.h"
40 #include "remoting/host/chromoting_host_context.h"
41 #include "remoting/host/chromoting_messages.h"
42 #include "remoting/host/config_file_watcher.h"
43 #include "remoting/host/config_watcher.h"
44 #include "remoting/host/desktop_environment.h"
45 #include "remoting/host/desktop_session_connector.h"
46 #include "remoting/host/dns_blackhole_checker.h"
47 #include "remoting/host/heartbeat_sender.h"
48 #include "remoting/host/host_change_notification_listener.h"
49 #include "remoting/host/host_config.h"
50 #include "remoting/host/host_event_logger.h"
51 #include "remoting/host/host_exit_codes.h"
52 #include "remoting/host/host_main.h"
53 #include "remoting/host/host_status_logger.h"
54 #include "remoting/host/ipc_constants.h"
55 #include "remoting/host/ipc_desktop_environment.h"
56 #include "remoting/host/ipc_host_event_logger.h"
57 #include "remoting/host/logging.h"
58 #include "remoting/host/me2me_desktop_environment.h"
59 #include "remoting/host/pairing_registry_delegate.h"
60 #include "remoting/host/policy_watcher.h"
61 #include "remoting/host/session_manager_factory.h"
62 #include "remoting/host/shutdown_watchdog.h"
63 #include "remoting/host/signaling_connector.h"
64 #include "remoting/host/single_window_desktop_environment.h"
65 #include "remoting/host/third_party_auth_config.h"
66 #include "remoting/host/token_validator_factory_impl.h"
67 #include "remoting/host/usage_stats_consent.h"
68 #include "remoting/host/username.h"
69 #include "remoting/host/video_frame_recorder_host_extension.h"
70 #include "remoting/protocol/me2me_host_authenticator_factory.h"
71 #include "remoting/protocol/network_settings.h"
72 #include "remoting/protocol/pairing_registry.h"
73 #include "remoting/protocol/port_range.h"
74 #include "remoting/protocol/token_validator.h"
75 #include "remoting/signaling/xmpp_signal_strategy.h"
77 #if defined(OS_POSIX)
78 #include <signal.h>
79 #include <sys/types.h>
80 #include <unistd.h>
81 #include "base/file_descriptor_posix.h"
82 #include "remoting/host/pam_authorization_factory_posix.h"
83 #include "remoting/host/posix/signal_handler.h"
84 #endif // defined(OS_POSIX)
86 #if defined(OS_MACOSX)
87 #include "base/mac/scoped_cftyperef.h"
88 #endif // defined(OS_MACOSX)
90 #if defined(OS_LINUX)
91 #include <gtk/gtk.h>
92 #include <X11/Xlib.h>
93 #include "remoting/host/audio_capturer_linux.h"
94 #endif // defined(OS_LINUX)
96 #if defined(OS_WIN)
97 #include <commctrl.h>
98 #include "base/win/registry.h"
99 #include "base/win/scoped_handle.h"
100 #include "remoting/host/pairing_registry_delegate_win.h"
101 #include "remoting/host/win/session_desktop_environment.h"
102 #endif // defined(OS_WIN)
104 using remoting::protocol::PairingRegistry;
105 using remoting::protocol::NetworkSettings;
107 #if defined(USE_REMOTING_MACOSX_INTERNAL)
108 #include "remoting/tools/internal/internal_mac-inl.h"
109 #endif
111 namespace {
113 // This is used for tagging system event logs.
114 const char kApplicationName[] = "chromoting";
116 #if defined(OS_LINUX)
117 // The command line switch used to pass name of the pipe to capture audio on
118 // linux.
119 const char kAudioPipeSwitchName[] = "audio-pipe-name";
121 // The command line switch used to pass name of the unix domain socket used to
122 // listen for gnubby requests.
123 const char kAuthSocknameSwitchName[] = "ssh-auth-sockname";
124 #endif // defined(OS_LINUX)
126 // The command line switch used by the parent to request the host to signal it
127 // when it is successfully started.
128 const char kSignalParentSwitchName[] = "signal-parent";
130 // Command line switch used to enable VP9 encoding.
131 const char kEnableVp9SwitchName[] = "enable-vp9";
133 // Command line switch used to enable and configure the frame-recorder.
134 const char kFrameRecorderBufferKbName[] = "frame-recorder-buffer-kb";
136 // Value used for --host-config option to indicate that the path must be read
137 // from stdin.
138 const char kStdinConfigPath[] = "-";
140 const char kWindowIdSwitchName[] = "window-id";
142 // Maximum time to wait for clean shutdown to occur, before forcing termination
143 // of the process.
144 const int kShutdownTimeoutSeconds = 15;
146 // Maximum time to wait for reporting host-offline-reason to the service,
147 // before continuing normal process shutdown.
148 const int kHostOfflineReasonTimeoutSeconds = 10;
150 // Host offline reasons not associated with shutting down the host process
151 // and therefore not expressible through HostExitCodes enum.
152 const char kHostOfflineReasonPolicyReadError[] = "POLICY_READ_ERROR";
153 const char kHostOfflineReasonPolicyChangeRequiresRestart[] =
154 "POLICY_CHANGE_REQUIRES_RESTART";
156 } // namespace
158 namespace remoting {
160 class HostProcess : public ConfigWatcher::Delegate,
161 public HostChangeNotificationListener::Listener,
162 public IPC::Listener,
163 public base::RefCountedThreadSafe<HostProcess> {
164 public:
165 // |shutdown_watchdog| is armed when shutdown is started, and should be kept
166 // alive as long as possible until the process exits (since destroying the
167 // watchdog disarms it).
168 HostProcess(scoped_ptr<ChromotingHostContext> context,
169 int* exit_code_out,
170 ShutdownWatchdog* shutdown_watchdog);
172 // ConfigWatcher::Delegate interface.
173 void OnConfigUpdated(const std::string& serialized_config) override;
174 void OnConfigWatcherError() override;
176 // IPC::Listener implementation.
177 bool OnMessageReceived(const IPC::Message& message) override;
178 void OnChannelError() override;
180 // HostChangeNotificationListener::Listener overrides.
181 void OnHostDeleted() override;
183 // Handler of the ChromotingDaemonNetworkMsg_InitializePairingRegistry IPC
184 // message.
185 void OnInitializePairingRegistry(
186 IPC::PlatformFileForTransit privileged_key,
187 IPC::PlatformFileForTransit unprivileged_key);
189 private:
190 // See SetState method for a list of allowed state transitions.
191 enum HostState {
192 // Waiting for valid config and policies to be read from the disk.
193 // Either the host process has just been started, or it is trying to start
194 // again after temporarily going offline due to policy change or error.
195 HOST_STARTING,
197 // Host is started and running.
198 HOST_STARTED,
200 // Host is sending offline reason, before trying to restart.
201 HOST_GOING_OFFLINE_TO_RESTART,
203 // Host is sending offline reason, before shutting down.
204 HOST_GOING_OFFLINE_TO_STOP,
206 // Host has been stopped (host process will end soon).
207 HOST_STOPPED,
210 enum PolicyState {
211 // Cannot start the host, because a valid policy has not been read yet.
212 POLICY_INITIALIZING,
214 // Policy was loaded successfully.
215 POLICY_LOADED,
217 // Policy error was detected, and we haven't yet sent out a
218 // host-offline-reason (i.e. because we haven't yet read the config).
219 POLICY_ERROR_REPORT_PENDING,
221 // Policy error was detected, and we have sent out a host-offline-reason.
222 POLICY_ERROR_REPORTED,
225 friend class base::RefCountedThreadSafe<HostProcess>;
226 ~HostProcess() override;
228 void SetState(HostState target_state);
230 void StartOnNetworkThread();
232 #if defined(OS_POSIX)
233 // Callback passed to RegisterSignalHandler() to handle SIGTERM events.
234 void SigTermHandler(int signal_number);
235 #endif
237 // Called to initialize resources on the UI thread.
238 void StartOnUiThread();
240 // Initializes IPC control channel and config file path from |cmd_line|.
241 // Called on the UI thread.
242 bool InitWithCommandLine(const base::CommandLine* cmd_line);
244 // Called on the UI thread to start monitoring the configuration file.
245 void StartWatchingConfigChanges();
247 // Called on the network thread to set the host's Authenticator factory.
248 void CreateAuthenticatorFactory();
250 // Tear down resources that run on the UI thread.
251 void ShutdownOnUiThread();
253 // Applies the host config, returning true if successful.
254 bool ApplyConfig(const base::DictionaryValue& config);
256 // Handles policy updates, by calling On*PolicyUpdate methods.
257 void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies);
258 void OnPolicyError();
259 void ReportPolicyErrorAndRestartHost();
260 void ApplyHostDomainPolicy();
261 void ApplyUsernamePolicy();
262 bool OnHostDomainPolicyUpdate(base::DictionaryValue* policies);
263 bool OnUsernamePolicyUpdate(base::DictionaryValue* policies);
264 bool OnNatPolicyUpdate(base::DictionaryValue* policies);
265 bool OnRelayPolicyUpdate(base::DictionaryValue* policies);
266 bool OnUdpPortPolicyUpdate(base::DictionaryValue* policies);
267 bool OnCurtainPolicyUpdate(base::DictionaryValue* policies);
268 bool OnHostTalkGadgetPrefixPolicyUpdate(base::DictionaryValue* policies);
269 bool OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies);
270 bool OnPairingPolicyUpdate(base::DictionaryValue* policies);
271 bool OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies);
273 void InitializeSignaling();
275 void StartHostIfReady();
276 void StartHost();
278 // Error handler for HeartbeatSender.
279 void OnHeartbeatSuccessful();
280 void OnUnknownHostIdError();
282 // Error handler for SignalingConnector.
283 void OnAuthFailed();
285 void RestartHost(const std::string& host_offline_reason);
286 void ShutdownHost(HostExitCodes exit_code);
288 // Helper methods doing the work needed by RestartHost and ShutdownHost.
289 void GoOffline(const std::string& host_offline_reason);
290 void OnHostOfflineReasonAck(bool success);
292 #if defined(OS_WIN)
293 // Initializes the pairing registry on Windows. This should be invoked on the
294 // network thread.
295 void InitializePairingRegistry(
296 IPC::PlatformFileForTransit privileged_key,
297 IPC::PlatformFileForTransit unprivileged_key);
298 #endif // defined(OS_WIN)
300 // Crashes the process in response to a daemon's request. The daemon passes
301 // the location of the code that detected the fatal error resulted in this
302 // request.
303 void OnCrash(const std::string& function_name,
304 const std::string& file_name,
305 const int& line_number);
307 scoped_ptr<ChromotingHostContext> context_;
309 // Accessed on the UI thread.
310 scoped_ptr<IPC::ChannelProxy> daemon_channel_;
312 // XMPP server/remoting bot configuration (initialized from the command line).
313 XmppSignalStrategy::XmppServerConfig xmpp_server_config_;
314 std::string directory_bot_jid_;
316 // Created on the UI thread but used from the network thread.
317 base::FilePath host_config_path_;
318 std::string host_config_;
319 scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
321 // Accessed on the network thread.
322 HostState state_;
324 scoped_ptr<ConfigWatcher> config_watcher_;
326 std::string host_id_;
327 protocol::SharedSecretHash host_secret_hash_;
328 scoped_refptr<RsaKeyPair> key_pair_;
329 std::string oauth_refresh_token_;
330 std::string serialized_config_;
331 std::string host_owner_;
332 std::string host_owner_email_;
333 bool use_service_account_;
334 bool enable_vp9_;
335 int64_t frame_recorder_buffer_size_;
336 std::string gcd_device_id_;
338 scoped_ptr<PolicyWatcher> policy_watcher_;
339 PolicyState policy_state_;
340 std::string host_domain_;
341 bool host_username_match_required_;
342 bool allow_nat_traversal_;
343 bool allow_relay_;
344 PortRange udp_port_range_;
345 std::string talkgadget_prefix_;
346 bool allow_pairing_;
348 bool curtain_required_;
349 ThirdPartyAuthConfig third_party_auth_config_;
350 bool enable_gnubby_auth_;
352 // Boolean to change flow, where necessary, if we're
353 // capturing a window instead of the entire desktop.
354 bool enable_window_capture_;
356 // Used to specify which window to stream, if enabled.
357 webrtc::WindowId window_id_;
359 // |heartbeat_sender_| and |signaling_connector_| have to be destroyed before
360 // |signal_strategy_| because their destructors need to call
361 // signal_strategy_->RemoveListener(this)
362 scoped_ptr<SignalStrategy> signal_strategy_;
363 scoped_ptr<SignalingConnector> signaling_connector_;
364 scoped_ptr<HeartbeatSender> heartbeat_sender_;
366 scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_;
367 scoped_ptr<HostStatusLogger> host_status_logger_;
368 scoped_ptr<HostEventLogger> host_event_logger_;
370 scoped_ptr<ChromotingHost> host_;
372 // Used to keep this HostProcess alive until it is shutdown.
373 scoped_refptr<HostProcess> self_;
375 #if defined(REMOTING_MULTI_PROCESS)
376 DesktopSessionConnector* desktop_session_connector_;
377 #endif // defined(REMOTING_MULTI_PROCESS)
379 int* exit_code_out_;
380 bool signal_parent_;
382 scoped_refptr<PairingRegistry> pairing_registry_;
384 ShutdownWatchdog* shutdown_watchdog_;
386 DISALLOW_COPY_AND_ASSIGN(HostProcess);
389 HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context,
390 int* exit_code_out,
391 ShutdownWatchdog* shutdown_watchdog)
392 : context_(context.Pass()),
393 state_(HOST_STARTING),
394 use_service_account_(false),
395 enable_vp9_(false),
396 frame_recorder_buffer_size_(0),
397 policy_state_(POLICY_INITIALIZING),
398 host_username_match_required_(false),
399 allow_nat_traversal_(true),
400 allow_relay_(true),
401 allow_pairing_(true),
402 curtain_required_(false),
403 enable_gnubby_auth_(false),
404 enable_window_capture_(false),
405 window_id_(0),
406 #if defined(REMOTING_MULTI_PROCESS)
407 desktop_session_connector_(nullptr),
408 #endif // defined(REMOTING_MULTI_PROCESS)
409 self_(this),
410 exit_code_out_(exit_code_out),
411 signal_parent_(false),
412 shutdown_watchdog_(shutdown_watchdog) {
413 StartOnUiThread();
416 HostProcess::~HostProcess() {
417 // Verify that UI components have been torn down.
418 DCHECK(!config_watcher_);
419 DCHECK(!daemon_channel_);
420 DCHECK(!desktop_environment_factory_);
422 // We might be getting deleted on one of the threads the |host_context| owns,
423 // so we need to post it back to the caller thread to safely join & delete the
424 // threads it contains. This will go away when we move to AutoThread.
425 // |context_release()| will null |context_| before the method is invoked, so
426 // we need to pull out the task-runner on which to call DeleteSoon first.
427 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
428 context_->ui_task_runner();
429 task_runner->DeleteSoon(FROM_HERE, context_.release());
432 bool HostProcess::InitWithCommandLine(const base::CommandLine* cmd_line) {
433 #if defined(REMOTING_MULTI_PROCESS)
434 // Parse the handle value and convert it to a handle/file descriptor.
435 std::string channel_name =
436 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
438 int pipe_handle = 0;
439 if (channel_name.empty() ||
440 !base::StringToInt(channel_name, &pipe_handle)) {
441 LOG(ERROR) << "Invalid '" << kDaemonPipeSwitchName
442 << "' value: " << channel_name;
443 return false;
446 #if defined(OS_WIN)
447 base::win::ScopedHandle pipe(reinterpret_cast<HANDLE>(pipe_handle));
448 IPC::ChannelHandle channel_handle(pipe.Get());
449 #elif defined(OS_POSIX)
450 base::FileDescriptor pipe(pipe_handle, true);
451 IPC::ChannelHandle channel_handle(channel_name, pipe);
452 #endif // defined(OS_POSIX)
454 // Connect to the daemon process.
455 daemon_channel_ = IPC::ChannelProxy::Create(channel_handle,
456 IPC::Channel::MODE_CLIENT,
457 this,
458 context_->network_task_runner());
459 #else // !defined(REMOTING_MULTI_PROCESS)
460 // Connect to the daemon process.
461 std::string channel_name =
462 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
463 if (!channel_name.empty()) {
464 daemon_channel_ =
465 IPC::ChannelProxy::Create(channel_name,
466 IPC::Channel::MODE_CLIENT,
467 this,
468 context_->network_task_runner().get());
471 if (cmd_line->HasSwitch(kHostConfigSwitchName)) {
472 host_config_path_ = cmd_line->GetSwitchValuePath(kHostConfigSwitchName);
474 // Read config from stdin if necessary.
475 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
476 char buf[4096];
477 size_t len;
478 while ((len = fread(buf, 1, sizeof(buf), stdin)) > 0) {
479 host_config_.append(buf, len);
482 } else {
483 base::FilePath default_config_dir = remoting::GetConfigDir();
484 host_config_path_ = default_config_dir.Append(kDefaultHostConfigFile);
487 if (host_config_path_ != base::FilePath(kStdinConfigPath) &&
488 !base::PathExists(host_config_path_)) {
489 LOG(ERROR) << "Can't find host config at " << host_config_path_.value();
490 return false;
492 #endif // !defined(REMOTING_MULTI_PROCESS)
494 // Ignore certificate requests - the host currently has no client certificate
495 // support, so ignoring certificate requests allows connecting to servers that
496 // request, but don't require, a certificate (optional client authentication).
497 net::URLFetcher::SetIgnoreCertificateRequests(true);
499 ServiceUrls* service_urls = ServiceUrls::GetInstance();
501 const std::string& xmpp_server =
502 service_urls->xmpp_server_address_for_me2me_host();
503 if (!net::ParseHostAndPort(xmpp_server, &xmpp_server_config_.host,
504 &xmpp_server_config_.port)) {
505 LOG(ERROR) << "Invalid XMPP server: " << xmpp_server;
506 return false;
508 xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls();
509 directory_bot_jid_ = service_urls->directory_bot_jid();
511 signal_parent_ = cmd_line->HasSwitch(kSignalParentSwitchName);
513 enable_window_capture_ = cmd_line->HasSwitch(kWindowIdSwitchName);
514 if (enable_window_capture_) {
516 #if defined(OS_LINUX) || defined(OS_WIN)
517 LOG(WARNING) << "Window capturing is not fully supported on Linux or "
518 "Windows.";
519 #endif // defined(OS_LINUX) || defined(OS_WIN)
521 // uint32_t is large enough to hold window IDs on all platforms.
522 uint32_t window_id;
523 if (base::StringToUint(
524 cmd_line->GetSwitchValueASCII(kWindowIdSwitchName),
525 &window_id)) {
526 window_id_ = static_cast<webrtc::WindowId>(window_id);
527 } else {
528 LOG(ERROR) << "Window with window id: " << window_id_
529 << " not found. Shutting down host.";
530 return false;
533 return true;
536 void HostProcess::OnConfigUpdated(
537 const std::string& serialized_config) {
538 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
539 context_->network_task_runner()->PostTask(FROM_HERE,
540 base::Bind(&HostProcess::OnConfigUpdated, this, serialized_config));
541 return;
544 // Filter out duplicates.
545 if (serialized_config_ == serialized_config)
546 return;
548 HOST_LOG << "Processing new host configuration.";
550 serialized_config_ = serialized_config;
551 scoped_ptr<base::DictionaryValue> config(
552 HostConfigFromJson(serialized_config));
553 if (!config) {
554 LOG(ERROR) << "Invalid configuration.";
555 ShutdownHost(kInvalidHostConfigurationExitCode);
556 return;
559 if (!ApplyConfig(*config)) {
560 LOG(ERROR) << "Failed to apply the configuration.";
561 ShutdownHost(kInvalidHostConfigurationExitCode);
562 return;
565 if (state_ == HOST_STARTING) {
566 StartHostIfReady();
567 } else if (state_ == HOST_STARTED) {
568 // Reapply policies that could be affected by a new config.
569 DCHECK_EQ(policy_state_, POLICY_LOADED);
570 ApplyHostDomainPolicy();
571 ApplyUsernamePolicy();
573 // TODO(sergeyu): Here we assume that PIN is the only part of the config
574 // that may change while the service is running. Change ApplyConfig() to
575 // detect other changes in the config and restart host if necessary here.
576 CreateAuthenticatorFactory();
580 void HostProcess::OnConfigWatcherError() {
581 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
582 ShutdownHost(kInvalidHostConfigurationExitCode);
585 // Allowed state transitions (enforced via DCHECKs in SetState method):
586 // STARTING->STARTED (once we have valid config + policy)
587 // STARTING->GOING_OFFLINE_TO_STOP
588 // STARTING->GOING_OFFLINE_TO_RESTART
589 // STARTED->GOING_OFFLINE_TO_STOP
590 // STARTED->GOING_OFFLINE_TO_RESTART
591 // GOING_OFFLINE_TO_RESTART->GOING_OFFLINE_TO_STOP
592 // GOING_OFFLINE_TO_RESTART->STARTING (after OnHostOfflineReasonAck)
593 // GOING_OFFLINE_TO_STOP->STOPPED (after OnHostOfflineReasonAck)
595 // |host_| must be not-null in STARTED state and nullptr in all other states
596 // (although this invariant can be temporarily violated when doing
597 // synchronous processing on the networking thread).
598 void HostProcess::SetState(HostState target_state) {
599 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
601 // DCHECKs below enforce state allowed transitions listed in HostState.
602 switch (state_) {
603 case HOST_STARTING:
604 DCHECK((target_state == HOST_STARTED) ||
605 (target_state == HOST_GOING_OFFLINE_TO_STOP) ||
606 (target_state == HOST_GOING_OFFLINE_TO_RESTART))
607 << state_ << " -> " << target_state;
608 break;
609 case HOST_STARTED:
610 DCHECK((target_state == HOST_GOING_OFFLINE_TO_STOP) ||
611 (target_state == HOST_GOING_OFFLINE_TO_RESTART))
612 << state_ << " -> " << target_state;
613 break;
614 case HOST_GOING_OFFLINE_TO_RESTART:
615 DCHECK((target_state == HOST_GOING_OFFLINE_TO_STOP) ||
616 (target_state == HOST_STARTING))
617 << state_ << " -> " << target_state;
618 break;
619 case HOST_GOING_OFFLINE_TO_STOP:
620 DCHECK_EQ(target_state, HOST_STOPPED);
621 break;
622 case HOST_STOPPED: // HOST_STOPPED is a terminal state.
623 default:
624 NOTREACHED() << state_ << " -> " << target_state;
625 break;
627 state_ = target_state;
630 void HostProcess::StartOnNetworkThread() {
631 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
633 #if !defined(REMOTING_MULTI_PROCESS)
634 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
635 // Process config we've read from stdin.
636 OnConfigUpdated(host_config_);
637 } else {
638 // Start watching the host configuration file.
639 config_watcher_.reset(new ConfigFileWatcher(context_->network_task_runner(),
640 context_->file_task_runner(),
641 host_config_path_));
642 config_watcher_->Watch(this);
644 #endif // !defined(REMOTING_MULTI_PROCESS)
646 #if defined(OS_POSIX)
647 remoting::RegisterSignalHandler(
648 SIGTERM,
649 base::Bind(&HostProcess::SigTermHandler, base::Unretained(this)));
650 #endif // defined(OS_POSIX)
653 #if defined(OS_POSIX)
654 void HostProcess::SigTermHandler(int signal_number) {
655 DCHECK(signal_number == SIGTERM);
656 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
657 HOST_LOG << "Caught SIGTERM: Shutting down...";
658 ShutdownHost(kSuccessExitCode);
660 #endif // OS_POSIX
662 void HostProcess::CreateAuthenticatorFactory() {
663 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
665 if (state_ != HOST_STARTED)
666 return;
668 std::string local_certificate = key_pair_->GenerateCertificate();
669 if (local_certificate.empty()) {
670 LOG(ERROR) << "Failed to generate host certificate.";
671 ShutdownHost(kInitializationFailed);
672 return;
675 scoped_ptr<protocol::AuthenticatorFactory> factory;
677 if (third_party_auth_config_.is_null()) {
678 scoped_refptr<PairingRegistry> pairing_registry;
679 if (allow_pairing_) {
680 // On Windows |pairing_registry_| is initialized in
681 // InitializePairingRegistry().
682 #if !defined(OS_WIN)
683 if (!pairing_registry_) {
684 scoped_ptr<PairingRegistry::Delegate> delegate =
685 CreatePairingRegistryDelegate();
687 if (delegate)
688 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
689 delegate.Pass());
691 #endif // defined(OS_WIN)
693 pairing_registry = pairing_registry_;
696 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
697 use_service_account_, host_owner_, local_certificate, key_pair_,
698 host_secret_hash_, pairing_registry);
700 host_->set_pairing_registry(pairing_registry);
701 } else {
702 DCHECK(third_party_auth_config_.token_url.is_valid());
703 DCHECK(third_party_auth_config_.token_validation_url.is_valid());
705 scoped_ptr<protocol::TokenValidatorFactory> token_validator_factory(
706 new TokenValidatorFactoryImpl(
707 third_party_auth_config_,
708 key_pair_, context_->url_request_context_getter()));
709 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
710 use_service_account_, host_owner_, local_certificate, key_pair_,
711 token_validator_factory.Pass());
714 #if defined(OS_POSIX)
715 // On Linux and Mac, perform a PAM authorization step after authentication.
716 factory.reset(new PamAuthorizationFactory(factory.Pass()));
717 #endif
718 host_->SetAuthenticatorFactory(factory.Pass());
721 // IPC::Listener implementation.
722 bool HostProcess::OnMessageReceived(const IPC::Message& message) {
723 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
725 #if defined(REMOTING_MULTI_PROCESS)
726 bool handled = true;
727 IPC_BEGIN_MESSAGE_MAP(HostProcess, message)
728 IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash)
729 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration,
730 OnConfigUpdated)
731 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_InitializePairingRegistry,
732 OnInitializePairingRegistry)
733 IPC_MESSAGE_FORWARD(
734 ChromotingDaemonNetworkMsg_DesktopAttached,
735 desktop_session_connector_,
736 DesktopSessionConnector::OnDesktopSessionAgentAttached)
737 IPC_MESSAGE_FORWARD(ChromotingDaemonNetworkMsg_TerminalDisconnected,
738 desktop_session_connector_,
739 DesktopSessionConnector::OnTerminalDisconnected)
740 IPC_MESSAGE_UNHANDLED(handled = false)
741 IPC_END_MESSAGE_MAP()
743 CHECK(handled) << "Received unexpected IPC type: " << message.type();
744 return handled;
746 #else // !defined(REMOTING_MULTI_PROCESS)
747 return false;
748 #endif // !defined(REMOTING_MULTI_PROCESS)
751 void HostProcess::OnChannelError() {
752 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
754 // Shutdown the host if the daemon process disconnects the IPC channel.
755 context_->network_task_runner()->PostTask(
756 FROM_HERE,
757 base::Bind(&HostProcess::ShutdownHost, this, kSuccessExitCode));
760 void HostProcess::StartOnUiThread() {
761 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
763 if (!InitWithCommandLine(base::CommandLine::ForCurrentProcess())) {
764 // Shutdown the host if the command line is invalid.
765 context_->network_task_runner()->PostTask(
766 FROM_HERE, base::Bind(&HostProcess::ShutdownHost, this,
767 kUsageExitCode));
768 return;
771 policy_watcher_ =
772 PolicyWatcher::Create(nullptr, context_->file_task_runner());
773 policy_watcher_->StartWatching(
774 base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)),
775 base::Bind(&HostProcess::OnPolicyError, base::Unretained(this)));
777 #if defined(OS_LINUX)
778 // If an audio pipe is specific on the command-line then initialize
779 // AudioCapturerLinux to capture from it.
780 base::FilePath audio_pipe_name = base::CommandLine::ForCurrentProcess()->
781 GetSwitchValuePath(kAudioPipeSwitchName);
782 if (!audio_pipe_name.empty()) {
783 remoting::AudioCapturerLinux::InitializePipeReader(
784 context_->audio_task_runner(), audio_pipe_name);
787 base::FilePath gnubby_socket_name = base::CommandLine::ForCurrentProcess()->
788 GetSwitchValuePath(kAuthSocknameSwitchName);
789 if (!gnubby_socket_name.empty())
790 remoting::GnubbyAuthHandler::SetGnubbySocketName(gnubby_socket_name);
791 #endif // defined(OS_LINUX)
793 // Create a desktop environment factory appropriate to the build type &
794 // platform.
795 #if defined(OS_WIN)
796 IpcDesktopEnvironmentFactory* desktop_environment_factory =
797 new IpcDesktopEnvironmentFactory(
798 context_->audio_task_runner(),
799 context_->network_task_runner(),
800 context_->video_capture_task_runner(),
801 context_->network_task_runner(),
802 daemon_channel_.get());
803 desktop_session_connector_ = desktop_environment_factory;
804 #else // !defined(OS_WIN)
805 DesktopEnvironmentFactory* desktop_environment_factory;
806 if (enable_window_capture_) {
807 desktop_environment_factory =
808 new SingleWindowDesktopEnvironmentFactory(
809 context_->network_task_runner(),
810 context_->input_task_runner(),
811 context_->ui_task_runner(),
812 window_id_);
813 } else {
814 desktop_environment_factory =
815 new Me2MeDesktopEnvironmentFactory(
816 context_->network_task_runner(),
817 context_->input_task_runner(),
818 context_->ui_task_runner());
820 #endif // !defined(OS_WIN)
822 desktop_environment_factory_.reset(desktop_environment_factory);
823 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
825 context_->network_task_runner()->PostTask(
826 FROM_HERE,
827 base::Bind(&HostProcess::StartOnNetworkThread, this));
830 void HostProcess::ShutdownOnUiThread() {
831 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
833 // Tear down resources that need to be torn down on the UI thread.
834 daemon_channel_.reset();
835 desktop_environment_factory_.reset();
836 policy_watcher_.reset();
838 // It is now safe for the HostProcess to be deleted.
839 self_ = nullptr;
841 #if defined(OS_LINUX)
842 // Cause the global AudioPipeReader to be freed, otherwise the audio
843 // thread will remain in-use and prevent the process from exiting.
844 // TODO(wez): DesktopEnvironmentFactory should own the pipe reader.
845 // See crbug.com/161373 and crbug.com/104544.
846 AudioCapturerLinux::InitializePipeReader(nullptr, base::FilePath());
847 #endif
850 void HostProcess::OnUnknownHostIdError() {
851 LOG(ERROR) << "Host ID not found.";
852 ShutdownHost(kInvalidHostIdExitCode);
855 void HostProcess::OnHeartbeatSuccessful() {
856 HOST_LOG << "Host ready to receive connections.";
857 #if defined(OS_POSIX)
858 if (signal_parent_) {
859 kill(getppid(), SIGUSR1);
860 signal_parent_ = false;
862 #endif
865 void HostProcess::OnHostDeleted() {
866 LOG(ERROR) << "Host was deleted from the directory.";
867 ShutdownHost(kInvalidHostIdExitCode);
870 void HostProcess::OnInitializePairingRegistry(
871 IPC::PlatformFileForTransit privileged_key,
872 IPC::PlatformFileForTransit unprivileged_key) {
873 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
875 #if defined(OS_WIN)
876 context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
877 &HostProcess::InitializePairingRegistry,
878 this, privileged_key, unprivileged_key));
879 #else // !defined(OS_WIN)
880 NOTREACHED();
881 #endif // !defined(OS_WIN)
884 #if defined(OS_WIN)
885 void HostProcess::InitializePairingRegistry(
886 IPC::PlatformFileForTransit privileged_key,
887 IPC::PlatformFileForTransit unprivileged_key) {
888 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
889 // |privileged_key| can be nullptr but not |unprivileged_key|.
890 DCHECK(unprivileged_key);
891 // |pairing_registry_| should only be initialized once.
892 DCHECK(!pairing_registry_);
894 HKEY privileged_hkey = reinterpret_cast<HKEY>(
895 IPC::PlatformFileForTransitToPlatformFile(privileged_key));
896 HKEY unprivileged_hkey = reinterpret_cast<HKEY>(
897 IPC::PlatformFileForTransitToPlatformFile(unprivileged_key));
899 scoped_ptr<PairingRegistryDelegateWin> delegate(
900 new PairingRegistryDelegateWin());
901 delegate->SetRootKeys(privileged_hkey, unprivileged_hkey);
903 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
904 delegate.Pass());
906 // (Re)Create the authenticator factory now that |pairing_registry_| has been
907 // initialized.
908 CreateAuthenticatorFactory();
910 #endif // !defined(OS_WIN)
912 // Applies the host config, returning true if successful.
913 bool HostProcess::ApplyConfig(const base::DictionaryValue& config) {
914 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
916 if (!config.GetString(kHostIdConfigPath, &host_id_)) {
917 LOG(ERROR) << "host_id is not defined in the config.";
918 return false;
921 std::string key_base64;
922 if (!config.GetString(kPrivateKeyConfigPath, &key_base64)) {
923 LOG(ERROR) << "Private key couldn't be read from the config file.";
924 return false;
927 key_pair_ = RsaKeyPair::FromString(key_base64);
928 if (!key_pair_.get()) {
929 LOG(ERROR) << "Invalid private key in the config file.";
930 return false;
933 std::string host_secret_hash_string;
934 if (!config.GetString(kHostSecretHashConfigPath,
935 &host_secret_hash_string)) {
936 host_secret_hash_string = "plain:";
939 if (!host_secret_hash_.Parse(host_secret_hash_string)) {
940 LOG(ERROR) << "Invalid host_secret_hash.";
941 return false;
944 // Use an XMPP connection to the Talk network for session signaling.
945 if (!config.GetString(kXmppLoginConfigPath, &xmpp_server_config_.username) ||
946 !config.GetString(kOAuthRefreshTokenConfigPath, &oauth_refresh_token_)) {
947 LOG(ERROR) << "XMPP credentials are not defined in the config.";
948 return false;
951 if (config.GetString(kHostOwnerConfigPath, &host_owner_)) {
952 // Service account configs have a host_owner, different from the xmpp_login.
953 use_service_account_ = true;
954 } else {
955 // User credential configs only have an xmpp_login, which is also the owner.
956 host_owner_ = xmpp_server_config_.username;
957 use_service_account_ = false;
960 // For non-Gmail Google accounts, the owner base JID differs from the email.
961 // host_owner_ contains the base JID (used for authenticating clients), while
962 // host_owner_email contains the account's email (used for UI and logs).
963 if (!config.GetString(kHostOwnerEmailConfigPath, &host_owner_email_)) {
964 host_owner_email_ = host_owner_;
967 // Allow offering of VP9 encoding to be overridden by the command-line.
968 if (base::CommandLine::ForCurrentProcess()->HasSwitch(kEnableVp9SwitchName)) {
969 enable_vp9_ = true;
970 } else {
971 config.GetBoolean(kEnableVp9ConfigPath, &enable_vp9_);
974 // Allow the command-line to override the size of the frame recorder buffer.
975 int frame_recorder_buffer_kb = 0;
976 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
977 kFrameRecorderBufferKbName)) {
978 std::string switch_value =
979 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
980 kFrameRecorderBufferKbName);
981 base::StringToInt(switch_value, &frame_recorder_buffer_kb);
982 } else {
983 config.GetInteger(kFrameRecorderBufferKbConfigPath,
984 &frame_recorder_buffer_kb);
986 if (frame_recorder_buffer_kb > 0) {
987 frame_recorder_buffer_size_ = 1024LL * frame_recorder_buffer_kb;
990 if (!config.GetString(kGcdDeviceIdConfigPath, &gcd_device_id_)) {
991 gcd_device_id_.clear();
994 return true;
997 void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
998 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
999 context_->network_task_runner()->PostTask(
1000 FROM_HERE, base::Bind(&HostProcess::OnPolicyUpdate, this,
1001 base::Passed(&policies)));
1002 return;
1005 bool restart_required = false;
1006 restart_required |= OnHostDomainPolicyUpdate(policies.get());
1007 restart_required |= OnCurtainPolicyUpdate(policies.get());
1008 // Note: UsernamePolicyUpdate must run after OnCurtainPolicyUpdate.
1009 restart_required |= OnUsernamePolicyUpdate(policies.get());
1010 restart_required |= OnNatPolicyUpdate(policies.get());
1011 restart_required |= OnRelayPolicyUpdate(policies.get());
1012 restart_required |= OnUdpPortPolicyUpdate(policies.get());
1013 restart_required |= OnHostTalkGadgetPrefixPolicyUpdate(policies.get());
1014 restart_required |= OnHostTokenUrlPolicyUpdate(policies.get());
1015 restart_required |= OnPairingPolicyUpdate(policies.get());
1016 restart_required |= OnGnubbyAuthPolicyUpdate(policies.get());
1018 policy_state_ = POLICY_LOADED;
1020 if (state_ == HOST_STARTING) {
1021 StartHostIfReady();
1022 } else if (state_ == HOST_STARTED) {
1023 if (restart_required)
1024 RestartHost(kHostOfflineReasonPolicyChangeRequiresRestart);
1028 void HostProcess::OnPolicyError() {
1029 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
1030 context_->network_task_runner()->PostTask(
1031 FROM_HERE, base::Bind(&HostProcess::OnPolicyError, this));
1032 return;
1035 if (policy_state_ != POLICY_ERROR_REPORTED) {
1036 policy_state_ = POLICY_ERROR_REPORT_PENDING;
1037 if ((state_ == HOST_STARTED) ||
1038 (state_ == HOST_STARTING && !serialized_config_.empty())) {
1039 ReportPolicyErrorAndRestartHost();
1044 void HostProcess::ReportPolicyErrorAndRestartHost() {
1045 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1046 DCHECK(!serialized_config_.empty());
1048 DCHECK_EQ(policy_state_, POLICY_ERROR_REPORT_PENDING);
1049 policy_state_ = POLICY_ERROR_REPORTED;
1051 LOG(INFO) << "Restarting the host due to policy errors.";
1052 RestartHost(kHostOfflineReasonPolicyReadError);
1055 void HostProcess::ApplyHostDomainPolicy() {
1056 if (state_ != HOST_STARTED)
1057 return;
1059 HOST_LOG << "Policy sets host domain: " << host_domain_;
1061 if (!host_domain_.empty()) {
1062 // If the user does not have a Google email, their client JID will not be
1063 // based on their email. In that case, the username/host domain policies
1064 // would be meaningless, since there is no way to check that the JID
1065 // trying to connect actually corresponds to the owner email in question.
1066 if (host_owner_ != host_owner_email_) {
1067 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1068 << "for accounts with a non-Google email.";
1069 ShutdownHost(kInvalidHostDomainExitCode);
1072 if (!EndsWith(host_owner_, std::string("@") + host_domain_, false)) {
1073 LOG(ERROR) << "The host domain does not match the policy.";
1074 ShutdownHost(kInvalidHostDomainExitCode);
1079 bool HostProcess::OnHostDomainPolicyUpdate(base::DictionaryValue* policies) {
1080 // Returns true if the host has to be restarted after this policy update.
1081 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1083 if (!policies->GetString(policy::key::kRemoteAccessHostDomain,
1084 &host_domain_)) {
1085 return false;
1088 ApplyHostDomainPolicy();
1089 return false;
1092 void HostProcess::ApplyUsernamePolicy() {
1093 if (state_ != HOST_STARTED)
1094 return;
1096 if (host_username_match_required_) {
1097 HOST_LOG << "Policy requires host username match.";
1099 // See comment in ApplyHostDomainPolicy.
1100 if (host_owner_ != host_owner_email_) {
1101 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1102 << "for accounts with a non-Google email.";
1103 ShutdownHost(kUsernameMismatchExitCode);
1106 std::string username = GetUsername();
1107 bool shutdown = username.empty() ||
1108 !StartsWithASCII(host_owner_, username + std::string("@"),
1109 false);
1111 #if defined(OS_MACOSX)
1112 // On Mac, we run as root at the login screen, so the username won't match.
1113 // However, there's no need to enforce the policy at the login screen, as
1114 // the client will have to reconnect if a login occurs.
1115 if (shutdown && getuid() == 0) {
1116 shutdown = false;
1118 #endif
1120 // Curtain-mode on Windows presents the standard OS login prompt to the user
1121 // for each connection, removing the need for an explicit user-name matching
1122 // check.
1123 #if defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1124 if (curtain_required_)
1125 return;
1126 #endif // defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1128 // Shutdown the host if the username does not match.
1129 if (shutdown) {
1130 LOG(ERROR) << "The host username does not match.";
1131 ShutdownHost(kUsernameMismatchExitCode);
1133 } else {
1134 HOST_LOG << "Policy does not require host username match.";
1138 bool HostProcess::OnUsernamePolicyUpdate(base::DictionaryValue* policies) {
1139 // Returns false: never restart the host after this policy update.
1140 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1142 if (!policies->GetBoolean(policy::key::kRemoteAccessHostMatchUsername,
1143 &host_username_match_required_)) {
1144 return false;
1147 ApplyUsernamePolicy();
1148 return false;
1151 bool HostProcess::OnNatPolicyUpdate(base::DictionaryValue* policies) {
1152 // Returns true if the host has to be restarted after this policy update.
1153 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1155 if (!policies->GetBoolean(policy::key::kRemoteAccessHostFirewallTraversal,
1156 &allow_nat_traversal_)) {
1157 return false;
1160 if (allow_nat_traversal_) {
1161 HOST_LOG << "Policy enables NAT traversal.";
1162 } else {
1163 HOST_LOG << "Policy disables NAT traversal.";
1165 return true;
1168 bool HostProcess::OnRelayPolicyUpdate(base::DictionaryValue* policies) {
1169 // Returns true if the host has to be restarted after this policy update.
1170 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1172 if (!policies->GetBoolean(
1173 policy::key::kRemoteAccessHostAllowRelayedConnection,
1174 &allow_relay_)) {
1175 return false;
1178 if (allow_relay_) {
1179 HOST_LOG << "Policy enables use of relay server.";
1180 } else {
1181 HOST_LOG << "Policy disables use of relay server.";
1183 return true;
1186 bool HostProcess::OnUdpPortPolicyUpdate(base::DictionaryValue* policies) {
1187 // Returns true if the host has to be restarted after this policy update.
1188 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1190 std::string string_value;
1191 if (!policies->GetString(policy::key::kRemoteAccessHostUdpPortRange,
1192 &string_value)) {
1193 return false;
1196 DCHECK(PortRange::Parse(string_value, &udp_port_range_));
1197 HOST_LOG << "Policy restricts UDP port range to: " << udp_port_range_;
1198 return true;
1201 bool HostProcess::OnCurtainPolicyUpdate(base::DictionaryValue* policies) {
1202 // Returns true if the host has to be restarted after this policy update.
1203 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1205 if (!policies->GetBoolean(policy::key::kRemoteAccessHostRequireCurtain,
1206 &curtain_required_)) {
1207 return false;
1210 #if defined(OS_MACOSX)
1211 if (curtain_required_) {
1212 // When curtain mode is in effect on Mac, the host process runs in the
1213 // user's switched-out session, but launchd will also run an instance at
1214 // the console login screen. Even if no user is currently logged-on, we
1215 // can't support remote-access to the login screen because the current host
1216 // process model disconnects the client during login, which would leave
1217 // the logged in session un-curtained on the console until they reconnect.
1219 // TODO(jamiewalch): Fix this once we have implemented the multi-process
1220 // daemon architecture (crbug.com/134894)
1221 if (getuid() == 0) {
1222 LOG(ERROR) << "Running the host in the console login session is yet not "
1223 "supported.";
1224 ShutdownHost(kLoginScreenNotSupportedExitCode);
1225 return false;
1228 #endif
1230 if (curtain_required_) {
1231 HOST_LOG << "Policy requires curtain-mode.";
1232 } else {
1233 HOST_LOG << "Policy does not require curtain-mode.";
1236 if (host_)
1237 host_->SetEnableCurtaining(curtain_required_);
1238 return false;
1241 bool HostProcess::OnHostTalkGadgetPrefixPolicyUpdate(
1242 base::DictionaryValue* policies) {
1243 // Returns true if the host has to be restarted after this policy update.
1244 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1246 if (!policies->GetString(policy::key::kRemoteAccessHostTalkGadgetPrefix,
1247 &talkgadget_prefix_)) {
1248 return false;
1251 HOST_LOG << "Policy sets talkgadget prefix: " << talkgadget_prefix_;
1252 return true;
1255 bool HostProcess::OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies) {
1256 switch (ThirdPartyAuthConfig::Parse(*policies, &third_party_auth_config_)) {
1257 case ThirdPartyAuthConfig::NoPolicy:
1258 return false;
1259 case ThirdPartyAuthConfig::ParsingSuccess:
1260 HOST_LOG << "Policy sets third-party token URLs: "
1261 << third_party_auth_config_;
1262 return true;
1263 case ThirdPartyAuthConfig::InvalidPolicy:
1264 default:
1265 NOTREACHED();
1266 return false;
1270 bool HostProcess::OnPairingPolicyUpdate(base::DictionaryValue* policies) {
1271 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1273 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowClientPairing,
1274 &allow_pairing_)) {
1275 return false;
1278 if (allow_pairing_) {
1279 HOST_LOG << "Policy enables client pairing.";
1280 } else {
1281 HOST_LOG << "Policy disables client pairing.";
1283 return true;
1286 bool HostProcess::OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies) {
1287 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1289 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowGnubbyAuth,
1290 &enable_gnubby_auth_)) {
1291 return false;
1294 if (enable_gnubby_auth_) {
1295 HOST_LOG << "Policy enables gnubby auth.";
1296 } else {
1297 HOST_LOG << "Policy disables gnubby auth.";
1300 if (desktop_environment_factory_)
1301 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
1303 return true;
1306 void HostProcess::InitializeSignaling() {
1307 DCHECK(!host_id_.empty()); // |ApplyConfig| should already have been run.
1308 DCHECK(!signal_strategy_);
1310 // Create SignalStrategy.
1311 XmppSignalStrategy* xmpp_signal_strategy = new XmppSignalStrategy(
1312 net::ClientSocketFactory::GetDefaultFactory(),
1313 context_->url_request_context_getter(), xmpp_server_config_);
1314 signal_strategy_.reset(xmpp_signal_strategy);
1316 // Create SignalingConnector.
1317 scoped_ptr<DnsBlackholeChecker> dns_blackhole_checker(new DnsBlackholeChecker(
1318 context_->url_request_context_getter(), talkgadget_prefix_));
1319 scoped_ptr<OAuthTokenGetter::OAuthCredentials> oauth_credentials(
1320 new OAuthTokenGetter::OAuthCredentials(xmpp_server_config_.username,
1321 oauth_refresh_token_,
1322 use_service_account_));
1323 scoped_ptr<OAuthTokenGetter> oauth_token_getter(new OAuthTokenGetter(
1324 oauth_credentials.Pass(), context_->url_request_context_getter(), false,
1325 gcd_device_id_.empty()));
1326 signaling_connector_.reset(new SignalingConnector(
1327 xmpp_signal_strategy, dns_blackhole_checker.Pass(),
1328 oauth_token_getter.Pass(),
1329 base::Bind(&HostProcess::OnAuthFailed, base::Unretained(this))));
1331 // Create HeartbeatSender.
1332 heartbeat_sender_.reset(new HeartbeatSender(
1333 base::Bind(&HostProcess::OnHeartbeatSuccessful, base::Unretained(this)),
1334 base::Bind(&HostProcess::OnUnknownHostIdError, base::Unretained(this)),
1335 host_id_, xmpp_signal_strategy, key_pair_, directory_bot_jid_));
1338 void HostProcess::StartHostIfReady() {
1339 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1340 DCHECK_EQ(state_, HOST_STARTING);
1342 // Start the host if both the config and the policies are loaded.
1343 if (!serialized_config_.empty()) {
1344 if (policy_state_ == POLICY_LOADED) {
1345 StartHost();
1346 } else if (policy_state_ == POLICY_ERROR_REPORT_PENDING) {
1347 ReportPolicyErrorAndRestartHost();
1352 void HostProcess::StartHost() {
1353 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1354 DCHECK(!host_);
1356 SetState(HOST_STARTED);
1358 InitializeSignaling();
1360 uint32 network_flags = 0;
1361 if (allow_nat_traversal_) {
1362 network_flags = NetworkSettings::NAT_TRAVERSAL_STUN |
1363 NetworkSettings::NAT_TRAVERSAL_OUTGOING;
1364 if (allow_relay_)
1365 network_flags |= NetworkSettings::NAT_TRAVERSAL_RELAY;
1368 NetworkSettings network_settings(network_flags);
1370 if (!udp_port_range_.is_null()) {
1371 network_settings.port_range = udp_port_range_;
1372 } else if (!allow_nat_traversal_) {
1373 // For legacy reasons we have to restrict the port range to a set of default
1374 // values when nat traversal is disabled, even if the port range was not
1375 // set in policy.
1376 network_settings.port_range.min_port = NetworkSettings::kDefaultMinPort;
1377 network_settings.port_range.max_port = NetworkSettings::kDefaultMaxPort;
1380 host_.reset(new ChromotingHost(
1381 signal_strategy_.get(), desktop_environment_factory_.get(),
1382 CreateHostSessionManager(signal_strategy_.get(), network_settings,
1383 context_->url_request_context_getter()),
1384 context_->audio_task_runner(), context_->input_task_runner(),
1385 context_->video_capture_task_runner(),
1386 context_->video_encode_task_runner(), context_->network_task_runner(),
1387 context_->ui_task_runner()));
1389 if (enable_vp9_) {
1390 scoped_ptr<protocol::CandidateSessionConfig> config =
1391 host_->protocol_config()->Clone();
1392 config->EnableVideoCodec(protocol::ChannelConfig::CODEC_VP9);
1393 host_->set_protocol_config(config.Pass());
1396 if (frame_recorder_buffer_size_ > 0) {
1397 scoped_ptr<VideoFrameRecorderHostExtension> frame_recorder_extension(
1398 new VideoFrameRecorderHostExtension());
1399 frame_recorder_extension->SetMaxContentBytes(frame_recorder_buffer_size_);
1400 host_->AddExtension(frame_recorder_extension.Pass());
1403 // TODO(simonmorris): Get the maximum session duration from a policy.
1404 #if defined(OS_LINUX)
1405 host_->SetMaximumSessionDuration(base::TimeDelta::FromHours(20));
1406 #endif
1408 host_change_notification_listener_.reset(new HostChangeNotificationListener(
1409 this, host_id_, signal_strategy_.get(), directory_bot_jid_));
1411 host_status_logger_.reset(
1412 new HostStatusLogger(host_->AsWeakPtr(), ServerLogEntry::ME2ME,
1413 signal_strategy_.get(), directory_bot_jid_));
1415 // Set up reporting the host status notifications.
1416 #if defined(REMOTING_MULTI_PROCESS)
1417 host_event_logger_.reset(
1418 new IpcHostEventLogger(host_->AsWeakPtr(), daemon_channel_.get()));
1419 #else // !defined(REMOTING_MULTI_PROCESS)
1420 host_event_logger_ =
1421 HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName);
1422 #endif // !defined(REMOTING_MULTI_PROCESS)
1424 host_->SetEnableCurtaining(curtain_required_);
1425 host_->Start(host_owner_email_);
1427 CreateAuthenticatorFactory();
1429 ApplyHostDomainPolicy();
1430 ApplyUsernamePolicy();
1433 void HostProcess::OnAuthFailed() {
1434 ShutdownHost(kInvalidOauthCredentialsExitCode);
1437 void HostProcess::RestartHost(const std::string& host_offline_reason) {
1438 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1439 DCHECK(!host_offline_reason.empty());
1441 SetState(HOST_GOING_OFFLINE_TO_RESTART);
1442 GoOffline(host_offline_reason);
1445 void HostProcess::ShutdownHost(HostExitCodes exit_code) {
1446 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1448 *exit_code_out_ = exit_code;
1450 switch (state_) {
1451 case HOST_STARTING:
1452 case HOST_STARTED:
1453 SetState(HOST_GOING_OFFLINE_TO_STOP);
1454 GoOffline(ExitCodeToString(exit_code));
1455 break;
1457 case HOST_GOING_OFFLINE_TO_RESTART:
1458 SetState(HOST_GOING_OFFLINE_TO_STOP);
1459 break;
1461 case HOST_GOING_OFFLINE_TO_STOP:
1462 case HOST_STOPPED:
1463 // Host is already stopped or being stopped. No action is required.
1464 break;
1468 void HostProcess::GoOffline(const std::string& host_offline_reason) {
1469 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1470 DCHECK(!host_offline_reason.empty());
1471 DCHECK((state_ == HOST_GOING_OFFLINE_TO_STOP) ||
1472 (state_ == HOST_GOING_OFFLINE_TO_RESTART));
1474 // Shut down everything except the HostSignalingManager.
1475 host_.reset();
1476 host_event_logger_.reset();
1477 host_status_logger_.reset();
1478 host_change_notification_listener_.reset();
1480 // Before shutting down HostSignalingManager, send the |host_offline_reason|
1481 // if possible (i.e. if we have the config).
1482 if (!serialized_config_.empty()) {
1483 if (!signal_strategy_)
1484 InitializeSignaling();
1486 HOST_LOG << "SendHostOfflineReason: sending " << host_offline_reason << ".";
1487 heartbeat_sender_->SetHostOfflineReason(
1488 host_offline_reason,
1489 base::TimeDelta::FromSeconds(kHostOfflineReasonTimeoutSeconds),
1490 base::Bind(&HostProcess::OnHostOfflineReasonAck, this));
1491 return; // Shutdown will resume after OnHostOfflineReasonAck.
1494 // Continue the shutdown without sending the host offline reason.
1495 HOST_LOG << "Can't send offline reason (" << host_offline_reason << ") "
1496 << "without a valid host config.";
1497 OnHostOfflineReasonAck(false);
1500 void HostProcess::OnHostOfflineReasonAck(bool success) {
1501 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1502 DCHECK(!host_); // Assert that the host is really offline at this point.
1504 HOST_LOG << "SendHostOfflineReason " << (success ? "succeeded." : "failed.");
1505 heartbeat_sender_.reset();
1506 signaling_connector_.reset();
1507 signal_strategy_.reset();
1509 if (state_ == HOST_GOING_OFFLINE_TO_RESTART) {
1510 SetState(HOST_STARTING);
1511 StartHostIfReady();
1512 } else if (state_ == HOST_GOING_OFFLINE_TO_STOP) {
1513 SetState(HOST_STOPPED);
1515 shutdown_watchdog_->SetExitCode(*exit_code_out_);
1516 shutdown_watchdog_->Arm();
1518 config_watcher_.reset();
1520 // Complete the rest of shutdown on the main thread.
1521 context_->ui_task_runner()->PostTask(
1522 FROM_HERE, base::Bind(&HostProcess::ShutdownOnUiThread, this));
1523 } else {
1524 NOTREACHED();
1528 void HostProcess::OnCrash(const std::string& function_name,
1529 const std::string& file_name,
1530 const int& line_number) {
1531 char message[1024];
1532 base::snprintf(message, sizeof(message),
1533 "Requested by %s at %s, line %d.",
1534 function_name.c_str(), file_name.c_str(), line_number);
1535 base::debug::Alias(message);
1537 // The daemon requested us to crash the process.
1538 CHECK(false) << message;
1541 int HostProcessMain() {
1542 #if defined(OS_LINUX)
1543 // Required in order for us to run multiple X11 threads.
1544 XInitThreads();
1546 // Required for any calls into GTK functions, such as the Disconnect and
1547 // Continue windows, though these should not be used for the Me2Me case
1548 // (crbug.com/104377).
1549 gtk_init(nullptr, nullptr);
1550 #endif
1552 // Enable support for SSL server sockets, which must be done while still
1553 // single-threaded.
1554 net::EnableSSLServerSockets();
1556 // Ensures runtime specific CPU features are initialized.
1557 media::InitializeCPUSpecificMediaFeatures();
1559 // Create the main message loop and start helper threads.
1560 base::MessageLoopForUI message_loop;
1561 scoped_ptr<ChromotingHostContext> context =
1562 ChromotingHostContext::Create(new AutoThreadTaskRunner(
1563 message_loop.message_loop_proxy(), base::MessageLoop::QuitClosure()));
1564 if (!context)
1565 return kInitializationFailed;
1567 // NetworkChangeNotifier must be initialized after MessageLoop.
1568 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier(
1569 net::NetworkChangeNotifier::Create());
1571 // Create & start the HostProcess using these threads.
1572 // TODO(wez): The HostProcess holds a reference to itself until Shutdown().
1573 // Remove this hack as part of the multi-process refactoring.
1574 int exit_code = kSuccessExitCode;
1575 ShutdownWatchdog shutdown_watchdog(
1576 base::TimeDelta::FromSeconds(kShutdownTimeoutSeconds));
1577 new HostProcess(context.Pass(), &exit_code, &shutdown_watchdog);
1579 // Run the main (also UI) message loop until the host no longer needs it.
1580 message_loop.Run();
1582 return exit_code;
1585 } // namespace remoting