1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This file implements a standalone host process for Me2Me.
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/stringize_macros.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "build/build_config.h"
23 #include "ipc/ipc_channel.h"
24 #include "ipc/ipc_channel_proxy.h"
25 #include "ipc/ipc_listener.h"
26 #include "net/base/net_util.h"
27 #include "net/base/network_change_notifier.h"
28 #include "net/socket/client_socket_factory.h"
29 #include "net/socket/ssl_server_socket.h"
30 #include "net/url_request/url_fetcher.h"
31 #include "policy/policy_constants.h"
32 #include "remoting/base/auto_thread_task_runner.h"
33 #include "remoting/base/breakpad.h"
34 #include "remoting/base/constants.h"
35 #include "remoting/base/logging.h"
36 #include "remoting/base/rsa_key_pair.h"
37 #include "remoting/base/service_urls.h"
38 #include "remoting/base/util.h"
39 #include "remoting/host/branding.h"
40 #include "remoting/host/chromoting_host.h"
41 #include "remoting/host/chromoting_host_context.h"
42 #include "remoting/host/chromoting_messages.h"
43 #include "remoting/host/config_file_watcher.h"
44 #include "remoting/host/config_watcher.h"
45 #include "remoting/host/desktop_environment.h"
46 #include "remoting/host/desktop_session_connector.h"
47 #include "remoting/host/dns_blackhole_checker.h"
48 #include "remoting/host/gcd_rest_client.h"
49 #include "remoting/host/gcd_state_updater.h"
50 #include "remoting/host/heartbeat_sender.h"
51 #include "remoting/host/host_change_notification_listener.h"
52 #include "remoting/host/host_config.h"
53 #include "remoting/host/host_event_logger.h"
54 #include "remoting/host/host_exit_codes.h"
55 #include "remoting/host/host_main.h"
56 #include "remoting/host/host_status_logger.h"
57 #include "remoting/host/input_injector.h"
58 #include "remoting/host/ipc_desktop_environment.h"
59 #include "remoting/host/ipc_host_event_logger.h"
60 #include "remoting/host/logging.h"
61 #include "remoting/host/me2me_desktop_environment.h"
62 #include "remoting/host/oauth_token_getter_impl.h"
63 #include "remoting/host/pairing_registry_delegate.h"
64 #include "remoting/host/policy_watcher.h"
65 #include "remoting/host/session_manager_factory.h"
66 #include "remoting/host/shutdown_watchdog.h"
67 #include "remoting/host/signaling_connector.h"
68 #include "remoting/host/single_window_desktop_environment.h"
69 #include "remoting/host/switches.h"
70 #include "remoting/host/third_party_auth_config.h"
71 #include "remoting/host/token_validator_factory_impl.h"
72 #include "remoting/host/usage_stats_consent.h"
73 #include "remoting/host/username.h"
74 #include "remoting/host/video_frame_recorder_host_extension.h"
75 #include "remoting/protocol/me2me_host_authenticator_factory.h"
76 #include "remoting/protocol/network_settings.h"
77 #include "remoting/protocol/pairing_registry.h"
78 #include "remoting/protocol/port_range.h"
79 #include "remoting/protocol/token_validator.h"
80 #include "remoting/signaling/push_notification_subscriber.h"
81 #include "remoting/signaling/xmpp_signal_strategy.h"
85 #include <sys/types.h>
87 #include "base/file_descriptor_posix.h"
88 #include "remoting/host/pam_authorization_factory_posix.h"
89 #include "remoting/host/posix/signal_handler.h"
90 #endif // defined(OS_POSIX)
92 #if defined(OS_MACOSX)
93 #include "base/mac/scoped_cftyperef.h"
94 #endif // defined(OS_MACOSX)
99 #include "remoting/host/audio_capturer_linux.h"
100 #endif // defined(OS_LINUX)
103 #include <commctrl.h>
104 #include "base/win/registry.h"
105 #include "base/win/scoped_handle.h"
106 #include "remoting/host/pairing_registry_delegate_win.h"
107 #include "remoting/host/win/session_desktop_environment.h"
108 #endif // defined(OS_WIN)
110 using remoting::protocol::PairingRegistry
;
111 using remoting::protocol::NetworkSettings
;
113 #if defined(USE_REMOTING_MACOSX_INTERNAL)
114 #include "remoting/tools/internal/internal_mac-inl.h"
119 #if !defined(REMOTING_MULTI_PROCESS)
120 // This is used for tagging system event logs.
121 const char kApplicationName
[] = "chromoting";
123 // Value used for --host-config option to indicate that the path must be read
125 const char kStdinConfigPath
[] = "-";
126 #endif // !defined(REMOTING_MULTI_PROCESS)
128 #if defined(OS_LINUX)
129 // The command line switch used to pass name of the pipe to capture audio on
131 const char kAudioPipeSwitchName
[] = "audio-pipe-name";
133 // The command line switch used to pass name of the unix domain socket used to
134 // listen for gnubby requests.
135 const char kAuthSocknameSwitchName
[] = "ssh-auth-sockname";
136 #endif // defined(OS_LINUX)
138 // The command line switch used by the parent to request the host to signal it
139 // when it is successfully started.
140 const char kSignalParentSwitchName
[] = "signal-parent";
142 // Command line switch used to enable VP9 encoding.
143 const char kEnableVp9SwitchName
[] = "enable-vp9";
145 // Command line switch used to enable and configure the frame-recorder.
146 const char kFrameRecorderBufferKbName
[] = "frame-recorder-buffer-kb";
148 const char kWindowIdSwitchName
[] = "window-id";
150 // Maximum time to wait for clean shutdown to occur, before forcing termination
152 const int kShutdownTimeoutSeconds
= 15;
154 // Maximum time to wait for reporting host-offline-reason to the service,
155 // before continuing normal process shutdown.
156 const int kHostOfflineReasonTimeoutSeconds
= 10;
158 // Host offline reasons not associated with shutting down the host process
159 // and therefore not expressible through HostExitCodes enum.
160 const char kHostOfflineReasonPolicyReadError
[] = "POLICY_READ_ERROR";
161 const char kHostOfflineReasonPolicyChangeRequiresRestart
[] =
162 "POLICY_CHANGE_REQUIRES_RESTART";
168 class HostProcess
: public ConfigWatcher::Delegate
,
169 public HostChangeNotificationListener::Listener
,
170 public IPC::Listener
,
171 public base::RefCountedThreadSafe
<HostProcess
> {
173 // |shutdown_watchdog| is armed when shutdown is started, and should be kept
174 // alive as long as possible until the process exits (since destroying the
175 // watchdog disarms it).
176 HostProcess(scoped_ptr
<ChromotingHostContext
> context
,
178 ShutdownWatchdog
* shutdown_watchdog
);
180 // ConfigWatcher::Delegate interface.
181 void OnConfigUpdated(const std::string
& serialized_config
) override
;
182 void OnConfigWatcherError() override
;
184 // IPC::Listener implementation.
185 bool OnMessageReceived(const IPC::Message
& message
) override
;
186 void OnChannelError() override
;
188 // HostChangeNotificationListener::Listener overrides.
189 void OnHostDeleted() override
;
191 // Handler of the ChromotingDaemonNetworkMsg_InitializePairingRegistry IPC
193 void OnInitializePairingRegistry(
194 IPC::PlatformFileForTransit privileged_key
,
195 IPC::PlatformFileForTransit unprivileged_key
);
198 // See SetState method for a list of allowed state transitions.
200 // Waiting for valid config and policies to be read from the disk.
201 // Either the host process has just been started, or it is trying to start
202 // again after temporarily going offline due to policy change or error.
205 // Host is started and running.
208 // Host is sending offline reason, before trying to restart.
209 HOST_GOING_OFFLINE_TO_RESTART
,
211 // Host is sending offline reason, before shutting down.
212 HOST_GOING_OFFLINE_TO_STOP
,
214 // Host has been stopped (host process will end soon).
219 // Cannot start the host, because a valid policy has not been read yet.
222 // Policy was loaded successfully.
225 // Policy error was detected, and we haven't yet sent out a
226 // host-offline-reason (i.e. because we haven't yet read the config).
227 POLICY_ERROR_REPORT_PENDING
,
229 // Policy error was detected, and we have sent out a host-offline-reason.
230 POLICY_ERROR_REPORTED
,
233 friend class base::RefCountedThreadSafe
<HostProcess
>;
234 ~HostProcess() override
;
236 void SetState(HostState target_state
);
238 void StartOnNetworkThread();
240 #if defined(OS_POSIX)
241 // Callback passed to RegisterSignalHandler() to handle SIGTERM events.
242 void SigTermHandler(int signal_number
);
245 // Called to initialize resources on the UI thread.
246 void StartOnUiThread();
248 // Initializes IPC control channel and config file path from |cmd_line|.
249 // Called on the UI thread.
250 bool InitWithCommandLine(const base::CommandLine
* cmd_line
);
252 // Called on the UI thread to start monitoring the configuration file.
253 void StartWatchingConfigChanges();
255 // Called on the network thread to set the host's Authenticator factory.
256 void CreateAuthenticatorFactory();
258 // Tear down resources that run on the UI thread.
259 void ShutdownOnUiThread();
261 // Applies the host config, returning true if successful.
262 bool ApplyConfig(const base::DictionaryValue
& config
);
264 // Handles policy updates, by calling On*PolicyUpdate methods.
265 void OnPolicyUpdate(scoped_ptr
<base::DictionaryValue
> policies
);
266 void OnPolicyError();
267 void ReportPolicyErrorAndRestartHost();
268 void ApplyHostDomainPolicy();
269 void ApplyUsernamePolicy();
270 bool OnHostDomainPolicyUpdate(base::DictionaryValue
* policies
);
271 bool OnUsernamePolicyUpdate(base::DictionaryValue
* policies
);
272 bool OnNatPolicyUpdate(base::DictionaryValue
* policies
);
273 bool OnRelayPolicyUpdate(base::DictionaryValue
* policies
);
274 bool OnUdpPortPolicyUpdate(base::DictionaryValue
* policies
);
275 bool OnCurtainPolicyUpdate(base::DictionaryValue
* policies
);
276 bool OnHostTalkGadgetPrefixPolicyUpdate(base::DictionaryValue
* policies
);
277 bool OnHostTokenUrlPolicyUpdate(base::DictionaryValue
* policies
);
278 bool OnPairingPolicyUpdate(base::DictionaryValue
* policies
);
279 bool OnGnubbyAuthPolicyUpdate(base::DictionaryValue
* policies
);
281 void InitializeSignaling();
283 void StartHostIfReady();
286 // Error handler for HeartbeatSender.
287 void OnHeartbeatSuccessful();
288 void OnUnknownHostIdError();
290 // Error handler for SignalingConnector.
293 void RestartHost(const std::string
& host_offline_reason
);
294 void ShutdownHost(HostExitCodes exit_code
);
296 // Helper methods doing the work needed by RestartHost and ShutdownHost.
297 void GoOffline(const std::string
& host_offline_reason
);
298 void OnHostOfflineReasonAck(bool success
);
301 // Initializes the pairing registry on Windows. This should be invoked on the
303 void InitializePairingRegistry(
304 IPC::PlatformFileForTransit privileged_key
,
305 IPC::PlatformFileForTransit unprivileged_key
);
306 #endif // defined(OS_WIN)
308 // Crashes the process in response to a daemon's request. The daemon passes
309 // the location of the code that detected the fatal error resulted in this
311 void OnCrash(const std::string
& function_name
,
312 const std::string
& file_name
,
313 const int& line_number
);
315 scoped_ptr
<ChromotingHostContext
> context_
;
317 // Accessed on the UI thread.
318 scoped_ptr
<IPC::ChannelProxy
> daemon_channel_
;
320 // XMPP server/remoting bot configuration (initialized from the command line).
321 XmppSignalStrategy::XmppServerConfig xmpp_server_config_
;
322 std::string directory_bot_jid_
;
324 // Created on the UI thread but used from the network thread.
325 base::FilePath host_config_path_
;
326 std::string host_config_
;
327 scoped_ptr
<DesktopEnvironmentFactory
> desktop_environment_factory_
;
329 // Accessed on the network thread.
332 scoped_ptr
<ConfigWatcher
> config_watcher_
;
334 std::string host_id_
;
335 protocol::SharedSecretHash host_secret_hash_
;
336 scoped_refptr
<RsaKeyPair
> key_pair_
;
337 std::string oauth_refresh_token_
;
338 std::string serialized_config_
;
339 std::string host_owner_
;
340 std::string host_owner_email_
;
341 bool use_service_account_
;
343 int64_t frame_recorder_buffer_size_
;
345 scoped_ptr
<PolicyWatcher
> policy_watcher_
;
346 PolicyState policy_state_
;
347 std::string host_domain_
;
348 bool host_username_match_required_
;
349 bool allow_nat_traversal_
;
351 PortRange udp_port_range_
;
352 std::string talkgadget_prefix_
;
355 bool curtain_required_
;
356 ThirdPartyAuthConfig third_party_auth_config_
;
357 bool enable_gnubby_auth_
;
359 // Boolean to change flow, where necessary, if we're
360 // capturing a window instead of the entire desktop.
361 bool enable_window_capture_
;
363 // Used to specify which window to stream, if enabled.
364 webrtc::WindowId window_id_
;
366 // Must outlive |gcd_state_updater_| and |signaling_connector_|.
367 scoped_ptr
<OAuthTokenGetter
> oauth_token_getter_
;
369 // Must outlive |signaling_connector_|, |gcd_subscriber_|, and
370 // |heartbeat_sender_|.
371 scoped_ptr
<SignalStrategy
> signal_strategy_
;
373 scoped_ptr
<SignalingConnector
> signaling_connector_
;
374 scoped_ptr
<HeartbeatSender
> heartbeat_sender_
;
376 scoped_ptr
<GcdStateUpdater
> gcd_state_updater_
;
377 scoped_ptr
<PushNotificationSubscriber
> gcd_subscriber_
;
378 #endif // defined(USE_GCD)
380 scoped_ptr
<HostChangeNotificationListener
> host_change_notification_listener_
;
381 scoped_ptr
<HostStatusLogger
> host_status_logger_
;
382 scoped_ptr
<HostEventLogger
> host_event_logger_
;
384 scoped_ptr
<ChromotingHost
> host_
;
386 // Used to keep this HostProcess alive until it is shutdown.
387 scoped_refptr
<HostProcess
> self_
;
389 #if defined(REMOTING_MULTI_PROCESS)
390 DesktopSessionConnector
* desktop_session_connector_
;
391 #endif // defined(REMOTING_MULTI_PROCESS)
396 scoped_refptr
<PairingRegistry
> pairing_registry_
;
398 ShutdownWatchdog
* shutdown_watchdog_
;
400 DISALLOW_COPY_AND_ASSIGN(HostProcess
);
403 HostProcess::HostProcess(scoped_ptr
<ChromotingHostContext
> context
,
405 ShutdownWatchdog
* shutdown_watchdog
)
406 : context_(context
.Pass()),
407 state_(HOST_STARTING
),
408 use_service_account_(false),
410 frame_recorder_buffer_size_(0),
411 policy_state_(POLICY_INITIALIZING
),
412 host_username_match_required_(false),
413 allow_nat_traversal_(true),
415 allow_pairing_(true),
416 curtain_required_(false),
417 enable_gnubby_auth_(false),
418 enable_window_capture_(false),
421 #if defined(REMOTING_MULTI_PROCESS)
422 desktop_session_connector_(nullptr),
423 #endif // defined(REMOTING_MULTI_PROCESS)
424 exit_code_out_(exit_code_out
),
425 signal_parent_(false),
426 shutdown_watchdog_(shutdown_watchdog
) {
430 HostProcess::~HostProcess() {
431 // Verify that UI components have been torn down.
432 DCHECK(!config_watcher_
);
433 DCHECK(!daemon_channel_
);
434 DCHECK(!desktop_environment_factory_
);
436 // We might be getting deleted on one of the threads the |host_context| owns,
437 // so we need to post it back to the caller thread to safely join & delete the
438 // threads it contains. This will go away when we move to AutoThread.
439 // |context_release()| will null |context_| before the method is invoked, so
440 // we need to pull out the task-runner on which to call DeleteSoon first.
441 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
=
442 context_
->ui_task_runner();
443 task_runner
->DeleteSoon(FROM_HERE
, context_
.release());
446 bool HostProcess::InitWithCommandLine(const base::CommandLine
* cmd_line
) {
447 #if defined(REMOTING_MULTI_PROCESS)
448 // Parse the handle value and convert it to a handle/file descriptor.
449 std::string channel_name
=
450 cmd_line
->GetSwitchValueASCII(kDaemonPipeSwitchName
);
453 if (channel_name
.empty() ||
454 !base::StringToInt(channel_name
, &pipe_handle
)) {
455 LOG(ERROR
) << "Invalid '" << kDaemonPipeSwitchName
456 << "' value: " << channel_name
;
461 base::win::ScopedHandle
pipe(reinterpret_cast<HANDLE
>(pipe_handle
));
462 IPC::ChannelHandle
channel_handle(pipe
.Get());
463 #elif defined(OS_POSIX)
464 base::FileDescriptor
pipe(pipe_handle
, true);
465 IPC::ChannelHandle
channel_handle(channel_name
, pipe
);
466 #endif // defined(OS_POSIX)
468 // Connect to the daemon process.
469 daemon_channel_
= IPC::ChannelProxy::Create(channel_handle
,
470 IPC::Channel::MODE_CLIENT
,
472 context_
->network_task_runner(),
474 #else // !defined(REMOTING_MULTI_PROCESS)
475 // Connect to the daemon process.
476 std::string channel_name
=
477 cmd_line
->GetSwitchValueASCII(kDaemonPipeSwitchName
);
478 if (!channel_name
.empty()) {
480 IPC::ChannelProxy::Create(channel_name
,
481 IPC::Channel::MODE_CLIENT
,
483 context_
->network_task_runner().get(),
487 if (cmd_line
->HasSwitch(kHostConfigSwitchName
)) {
488 host_config_path_
= cmd_line
->GetSwitchValuePath(kHostConfigSwitchName
);
490 // Read config from stdin if necessary.
491 if (host_config_path_
== base::FilePath(kStdinConfigPath
)) {
492 const size_t kBufferSize
= 4096;
493 scoped_ptr
<char[]> buf(new char[kBufferSize
]);
495 while ((len
= fread(buf
.get(), 1, kBufferSize
, stdin
)) > 0) {
496 host_config_
.append(buf
.get(), len
);
500 base::FilePath default_config_dir
= remoting::GetConfigDir();
501 host_config_path_
= default_config_dir
.Append(kDefaultHostConfigFile
);
504 if (host_config_path_
!= base::FilePath(kStdinConfigPath
) &&
505 !base::PathExists(host_config_path_
)) {
506 LOG(ERROR
) << "Can't find host config at " << host_config_path_
.value();
509 #endif // !defined(REMOTING_MULTI_PROCESS)
511 // Ignore certificate requests - the host currently has no client certificate
512 // support, so ignoring certificate requests allows connecting to servers that
513 // request, but don't require, a certificate (optional client authentication).
514 net::URLFetcher::SetIgnoreCertificateRequests(true);
516 ServiceUrls
* service_urls
= ServiceUrls::GetInstance();
518 const std::string
& xmpp_server
=
519 service_urls
->xmpp_server_address_for_me2me_host();
520 if (!net::ParseHostAndPort(xmpp_server
, &xmpp_server_config_
.host
,
521 &xmpp_server_config_
.port
)) {
522 LOG(ERROR
) << "Invalid XMPP server: " << xmpp_server
;
525 xmpp_server_config_
.use_tls
= service_urls
->xmpp_server_use_tls();
526 directory_bot_jid_
= service_urls
->directory_bot_jid();
528 signal_parent_
= cmd_line
->HasSwitch(kSignalParentSwitchName
);
530 enable_window_capture_
= cmd_line
->HasSwitch(kWindowIdSwitchName
);
531 if (enable_window_capture_
) {
533 #if defined(OS_LINUX) || defined(OS_WIN)
534 LOG(WARNING
) << "Window capturing is not fully supported on Linux or "
536 #endif // defined(OS_LINUX) || defined(OS_WIN)
538 // uint32_t is large enough to hold window IDs on all platforms.
540 if (base::StringToUint(
541 cmd_line
->GetSwitchValueASCII(kWindowIdSwitchName
),
543 window_id_
= static_cast<webrtc::WindowId
>(window_id
);
545 LOG(ERROR
) << "Window with window id: " << window_id_
546 << " not found. Shutting down host.";
553 void HostProcess::OnConfigUpdated(
554 const std::string
& serialized_config
) {
555 if (!context_
->network_task_runner()->BelongsToCurrentThread()) {
556 context_
->network_task_runner()->PostTask(FROM_HERE
,
557 base::Bind(&HostProcess::OnConfigUpdated
, this, serialized_config
));
561 // Filter out duplicates.
562 if (serialized_config_
== serialized_config
)
565 HOST_LOG
<< "Processing new host configuration.";
567 serialized_config_
= serialized_config
;
568 scoped_ptr
<base::DictionaryValue
> config(
569 HostConfigFromJson(serialized_config
));
571 LOG(ERROR
) << "Invalid configuration.";
572 ShutdownHost(kInvalidHostConfigurationExitCode
);
576 if (!ApplyConfig(*config
)) {
577 LOG(ERROR
) << "Failed to apply the configuration.";
578 ShutdownHost(kInvalidHostConfigurationExitCode
);
582 if (state_
== HOST_STARTING
) {
584 } else if (state_
== HOST_STARTED
) {
585 // Reapply policies that could be affected by a new config.
586 DCHECK_EQ(policy_state_
, POLICY_LOADED
);
587 ApplyHostDomainPolicy();
588 ApplyUsernamePolicy();
590 // TODO(sergeyu): Here we assume that PIN is the only part of the config
591 // that may change while the service is running. Change ApplyConfig() to
592 // detect other changes in the config and restart host if necessary here.
593 CreateAuthenticatorFactory();
597 void HostProcess::OnConfigWatcherError() {
598 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
599 ShutdownHost(kInvalidHostConfigurationExitCode
);
602 // Allowed state transitions (enforced via DCHECKs in SetState method):
603 // STARTING->STARTED (once we have valid config + policy)
604 // STARTING->GOING_OFFLINE_TO_STOP
605 // STARTING->GOING_OFFLINE_TO_RESTART
606 // STARTED->GOING_OFFLINE_TO_STOP
607 // STARTED->GOING_OFFLINE_TO_RESTART
608 // GOING_OFFLINE_TO_RESTART->GOING_OFFLINE_TO_STOP
609 // GOING_OFFLINE_TO_RESTART->STARTING (after OnHostOfflineReasonAck)
610 // GOING_OFFLINE_TO_STOP->STOPPED (after OnHostOfflineReasonAck)
612 // |host_| must be not-null in STARTED state and nullptr in all other states
613 // (although this invariant can be temporarily violated when doing
614 // synchronous processing on the networking thread).
615 void HostProcess::SetState(HostState target_state
) {
616 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
618 // DCHECKs below enforce state allowed transitions listed in HostState.
621 DCHECK((target_state
== HOST_STARTED
) ||
622 (target_state
== HOST_GOING_OFFLINE_TO_STOP
) ||
623 (target_state
== HOST_GOING_OFFLINE_TO_RESTART
))
624 << state_
<< " -> " << target_state
;
627 DCHECK((target_state
== HOST_GOING_OFFLINE_TO_STOP
) ||
628 (target_state
== HOST_GOING_OFFLINE_TO_RESTART
))
629 << state_
<< " -> " << target_state
;
631 case HOST_GOING_OFFLINE_TO_RESTART
:
632 DCHECK((target_state
== HOST_GOING_OFFLINE_TO_STOP
) ||
633 (target_state
== HOST_STARTING
))
634 << state_
<< " -> " << target_state
;
636 case HOST_GOING_OFFLINE_TO_STOP
:
637 DCHECK_EQ(target_state
, HOST_STOPPED
);
639 case HOST_STOPPED
: // HOST_STOPPED is a terminal state.
641 NOTREACHED() << state_
<< " -> " << target_state
;
644 state_
= target_state
;
647 void HostProcess::StartOnNetworkThread() {
648 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
650 if (state_
!= HOST_STARTING
) {
651 // Host was shutdown before the task had a chance to run.
655 #if !defined(REMOTING_MULTI_PROCESS)
656 if (host_config_path_
== base::FilePath(kStdinConfigPath
)) {
657 // Process config we've read from stdin.
658 OnConfigUpdated(host_config_
);
660 // Start watching the host configuration file.
661 config_watcher_
.reset(new ConfigFileWatcher(context_
->network_task_runner(),
662 context_
->file_task_runner(),
664 config_watcher_
->Watch(this);
666 #endif // !defined(REMOTING_MULTI_PROCESS)
668 #if defined(OS_POSIX)
669 remoting::RegisterSignalHandler(
671 base::Bind(&HostProcess::SigTermHandler
, base::Unretained(this)));
672 #endif // defined(OS_POSIX)
675 #if defined(OS_POSIX)
676 void HostProcess::SigTermHandler(int signal_number
) {
677 DCHECK(signal_number
== SIGTERM
);
678 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
679 HOST_LOG
<< "Caught SIGTERM: Shutting down...";
680 ShutdownHost(kSuccessExitCode
);
684 void HostProcess::CreateAuthenticatorFactory() {
685 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
687 if (state_
!= HOST_STARTED
)
690 std::string local_certificate
= key_pair_
->GenerateCertificate();
691 if (local_certificate
.empty()) {
692 LOG(ERROR
) << "Failed to generate host certificate.";
693 ShutdownHost(kInitializationFailed
);
697 scoped_ptr
<protocol::AuthenticatorFactory
> factory
;
699 if (third_party_auth_config_
.is_null()) {
700 scoped_refptr
<PairingRegistry
> pairing_registry
;
701 if (allow_pairing_
) {
702 // On Windows |pairing_registry_| is initialized in
703 // InitializePairingRegistry().
705 if (!pairing_registry_
) {
706 scoped_ptr
<PairingRegistry::Delegate
> delegate
=
707 CreatePairingRegistryDelegate();
710 pairing_registry_
= new PairingRegistry(context_
->file_task_runner(),
713 #endif // defined(OS_WIN)
715 pairing_registry
= pairing_registry_
;
718 factory
= protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
719 use_service_account_
, host_owner_
, local_certificate
, key_pair_
,
720 host_secret_hash_
, pairing_registry
);
722 host_
->set_pairing_registry(pairing_registry
);
724 DCHECK(third_party_auth_config_
.token_url
.is_valid());
725 DCHECK(third_party_auth_config_
.token_validation_url
.is_valid());
727 scoped_ptr
<protocol::TokenValidatorFactory
> token_validator_factory(
728 new TokenValidatorFactoryImpl(
729 third_party_auth_config_
,
730 key_pair_
, context_
->url_request_context_getter()));
731 factory
= protocol::Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
732 use_service_account_
, host_owner_
, local_certificate
, key_pair_
,
733 token_validator_factory
.Pass());
736 #if defined(OS_POSIX)
737 // On Linux and Mac, perform a PAM authorization step after authentication.
738 factory
.reset(new PamAuthorizationFactory(factory
.Pass()));
740 host_
->SetAuthenticatorFactory(factory
.Pass());
743 // IPC::Listener implementation.
744 bool HostProcess::OnMessageReceived(const IPC::Message
& message
) {
745 DCHECK(context_
->ui_task_runner()->BelongsToCurrentThread());
747 #if defined(REMOTING_MULTI_PROCESS)
749 IPC_BEGIN_MESSAGE_MAP(HostProcess
, message
)
750 IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash
, OnCrash
)
751 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration
,
753 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_InitializePairingRegistry
,
754 OnInitializePairingRegistry
)
756 ChromotingDaemonNetworkMsg_DesktopAttached
,
757 desktop_session_connector_
,
758 DesktopSessionConnector::OnDesktopSessionAgentAttached
)
759 IPC_MESSAGE_FORWARD(ChromotingDaemonNetworkMsg_TerminalDisconnected
,
760 desktop_session_connector_
,
761 DesktopSessionConnector::OnTerminalDisconnected
)
762 IPC_MESSAGE_UNHANDLED(handled
= false)
763 IPC_END_MESSAGE_MAP()
765 CHECK(handled
) << "Received unexpected IPC type: " << message
.type();
768 #else // !defined(REMOTING_MULTI_PROCESS)
770 #endif // !defined(REMOTING_MULTI_PROCESS)
773 void HostProcess::OnChannelError() {
774 DCHECK(context_
->ui_task_runner()->BelongsToCurrentThread());
776 // Shutdown the host if the daemon process disconnects the IPC channel.
777 context_
->network_task_runner()->PostTask(
779 base::Bind(&HostProcess::ShutdownHost
, this, kSuccessExitCode
));
782 void HostProcess::StartOnUiThread() {
783 DCHECK(context_
->ui_task_runner()->BelongsToCurrentThread());
785 if (!InitWithCommandLine(base::CommandLine::ForCurrentProcess())) {
786 // Shutdown the host if the command line is invalid.
787 context_
->network_task_runner()->PostTask(
788 FROM_HERE
, base::Bind(&HostProcess::ShutdownHost
, this,
794 PolicyWatcher::Create(nullptr, context_
->file_task_runner());
795 policy_watcher_
->StartWatching(
796 base::Bind(&HostProcess::OnPolicyUpdate
, base::Unretained(this)),
797 base::Bind(&HostProcess::OnPolicyError
, base::Unretained(this)));
799 #if defined(OS_LINUX)
800 // If an audio pipe is specific on the command-line then initialize
801 // AudioCapturerLinux to capture from it.
802 base::FilePath audio_pipe_name
= base::CommandLine::ForCurrentProcess()->
803 GetSwitchValuePath(kAudioPipeSwitchName
);
804 if (!audio_pipe_name
.empty()) {
805 remoting::AudioCapturerLinux::InitializePipeReader(
806 context_
->audio_task_runner(), audio_pipe_name
);
809 base::FilePath gnubby_socket_name
= base::CommandLine::ForCurrentProcess()->
810 GetSwitchValuePath(kAuthSocknameSwitchName
);
811 if (!gnubby_socket_name
.empty())
812 remoting::GnubbyAuthHandler::SetGnubbySocketName(gnubby_socket_name
);
813 #endif // defined(OS_LINUX)
815 // Create a desktop environment factory appropriate to the build type &
818 IpcDesktopEnvironmentFactory
* desktop_environment_factory
=
819 new IpcDesktopEnvironmentFactory(
820 context_
->audio_task_runner(),
821 context_
->network_task_runner(),
822 context_
->video_capture_task_runner(),
823 context_
->network_task_runner(),
824 daemon_channel_
.get());
825 desktop_session_connector_
= desktop_environment_factory
;
826 #else // !defined(OS_WIN)
827 BasicDesktopEnvironmentFactory
* desktop_environment_factory
;
828 if (enable_window_capture_
) {
829 desktop_environment_factory
=
830 new SingleWindowDesktopEnvironmentFactory(
831 context_
->network_task_runner(),
832 context_
->input_task_runner(),
833 context_
->ui_task_runner(),
836 desktop_environment_factory
=
837 new Me2MeDesktopEnvironmentFactory(
838 context_
->network_task_runner(),
839 context_
->input_task_runner(),
840 context_
->ui_task_runner());
842 #endif // !defined(OS_WIN)
843 desktop_environment_factory
->set_supports_touch_events(
844 InputInjector::SupportsTouchEvents());
846 desktop_environment_factory_
.reset(desktop_environment_factory
);
847 desktop_environment_factory_
->SetEnableGnubbyAuth(enable_gnubby_auth_
);
849 context_
->network_task_runner()->PostTask(
851 base::Bind(&HostProcess::StartOnNetworkThread
, this));
854 void HostProcess::ShutdownOnUiThread() {
855 DCHECK(context_
->ui_task_runner()->BelongsToCurrentThread());
857 // Tear down resources that need to be torn down on the UI thread.
858 daemon_channel_
.reset();
859 desktop_environment_factory_
.reset();
860 policy_watcher_
.reset();
862 // It is now safe for the HostProcess to be deleted.
865 #if defined(OS_LINUX)
866 // Cause the global AudioPipeReader to be freed, otherwise the audio
867 // thread will remain in-use and prevent the process from exiting.
868 // TODO(wez): DesktopEnvironmentFactory should own the pipe reader.
869 // See crbug.com/161373 and crbug.com/104544.
870 AudioCapturerLinux::InitializePipeReader(nullptr, base::FilePath());
874 void HostProcess::OnUnknownHostIdError() {
875 LOG(ERROR
) << "Host ID not found.";
876 ShutdownHost(kInvalidHostIdExitCode
);
879 void HostProcess::OnHeartbeatSuccessful() {
880 HOST_LOG
<< "Host ready to receive connections.";
881 #if defined(OS_POSIX)
882 if (signal_parent_
) {
883 kill(getppid(), SIGUSR1
);
884 signal_parent_
= false;
889 void HostProcess::OnHostDeleted() {
890 LOG(ERROR
) << "Host was deleted from the directory.";
891 ShutdownHost(kInvalidHostIdExitCode
);
894 void HostProcess::OnInitializePairingRegistry(
895 IPC::PlatformFileForTransit privileged_key
,
896 IPC::PlatformFileForTransit unprivileged_key
) {
897 DCHECK(context_
->ui_task_runner()->BelongsToCurrentThread());
900 context_
->network_task_runner()->PostTask(FROM_HERE
, base::Bind(
901 &HostProcess::InitializePairingRegistry
,
902 this, privileged_key
, unprivileged_key
));
903 #else // !defined(OS_WIN)
905 #endif // !defined(OS_WIN)
909 void HostProcess::InitializePairingRegistry(
910 IPC::PlatformFileForTransit privileged_key
,
911 IPC::PlatformFileForTransit unprivileged_key
) {
912 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
913 // |privileged_key| can be nullptr but not |unprivileged_key|.
914 DCHECK(unprivileged_key
);
915 // |pairing_registry_| should only be initialized once.
916 DCHECK(!pairing_registry_
);
918 HKEY privileged_hkey
= reinterpret_cast<HKEY
>(
919 IPC::PlatformFileForTransitToPlatformFile(privileged_key
));
920 HKEY unprivileged_hkey
= reinterpret_cast<HKEY
>(
921 IPC::PlatformFileForTransitToPlatformFile(unprivileged_key
));
923 scoped_ptr
<PairingRegistryDelegateWin
> delegate(
924 new PairingRegistryDelegateWin());
925 delegate
->SetRootKeys(privileged_hkey
, unprivileged_hkey
);
927 pairing_registry_
= new PairingRegistry(context_
->file_task_runner(),
930 // (Re)Create the authenticator factory now that |pairing_registry_| has been
932 CreateAuthenticatorFactory();
934 #endif // !defined(OS_WIN)
936 // Applies the host config, returning true if successful.
937 bool HostProcess::ApplyConfig(const base::DictionaryValue
& config
) {
938 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
940 if (!config
.GetString(kHostIdConfigPath
, &host_id_
)) {
941 LOG(ERROR
) << "Config does not define " << kHostIdConfigPath
<< ".";
945 std::string key_base64
;
946 if (!config
.GetString(kPrivateKeyConfigPath
, &key_base64
)) {
947 LOG(ERROR
) << "Private key couldn't be read from the config file.";
951 key_pair_
= RsaKeyPair::FromString(key_base64
);
952 if (!key_pair_
.get()) {
953 LOG(ERROR
) << "Invalid private key in the config file.";
957 std::string host_secret_hash_string
;
958 if (!config
.GetString(kHostSecretHashConfigPath
,
959 &host_secret_hash_string
)) {
960 host_secret_hash_string
= "plain:";
963 if (!host_secret_hash_
.Parse(host_secret_hash_string
)) {
964 LOG(ERROR
) << "Invalid host_secret_hash.";
968 // Use an XMPP connection to the Talk network for session signaling.
969 if (!config
.GetString(kXmppLoginConfigPath
, &xmpp_server_config_
.username
) ||
970 !config
.GetString(kOAuthRefreshTokenConfigPath
, &oauth_refresh_token_
)) {
971 LOG(ERROR
) << "XMPP credentials are not defined in the config.";
975 if (config
.GetString(kHostOwnerConfigPath
, &host_owner_
)) {
976 // Service account configs have a host_owner, different from the xmpp_login.
977 use_service_account_
= true;
979 // User credential configs only have an xmpp_login, which is also the owner.
980 host_owner_
= xmpp_server_config_
.username
;
981 use_service_account_
= false;
984 // For non-Gmail Google accounts, the owner base JID differs from the email.
985 // host_owner_ contains the base JID (used for authenticating clients), while
986 // host_owner_email contains the account's email (used for UI and logs).
987 if (!config
.GetString(kHostOwnerEmailConfigPath
, &host_owner_email_
)) {
988 host_owner_email_
= host_owner_
;
991 // Allow offering of VP9 encoding to be overridden by the command-line.
992 if (base::CommandLine::ForCurrentProcess()->HasSwitch(kEnableVp9SwitchName
)) {
995 config
.GetBoolean(kEnableVp9ConfigPath
, &enable_vp9_
);
998 // Allow the command-line to override the size of the frame recorder buffer.
999 int frame_recorder_buffer_kb
= 0;
1000 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1001 kFrameRecorderBufferKbName
)) {
1002 std::string switch_value
=
1003 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
1004 kFrameRecorderBufferKbName
);
1005 base::StringToInt(switch_value
, &frame_recorder_buffer_kb
);
1007 config
.GetInteger(kFrameRecorderBufferKbConfigPath
,
1008 &frame_recorder_buffer_kb
);
1010 if (frame_recorder_buffer_kb
> 0) {
1011 frame_recorder_buffer_size_
= 1024LL * frame_recorder_buffer_kb
;
1017 void HostProcess::OnPolicyUpdate(scoped_ptr
<base::DictionaryValue
> policies
) {
1018 if (!context_
->network_task_runner()->BelongsToCurrentThread()) {
1019 context_
->network_task_runner()->PostTask(
1020 FROM_HERE
, base::Bind(&HostProcess::OnPolicyUpdate
, this,
1021 base::Passed(&policies
)));
1025 bool restart_required
= false;
1026 restart_required
|= OnHostDomainPolicyUpdate(policies
.get());
1027 restart_required
|= OnCurtainPolicyUpdate(policies
.get());
1028 // Note: UsernamePolicyUpdate must run after OnCurtainPolicyUpdate.
1029 restart_required
|= OnUsernamePolicyUpdate(policies
.get());
1030 restart_required
|= OnNatPolicyUpdate(policies
.get());
1031 restart_required
|= OnRelayPolicyUpdate(policies
.get());
1032 restart_required
|= OnUdpPortPolicyUpdate(policies
.get());
1033 restart_required
|= OnHostTalkGadgetPrefixPolicyUpdate(policies
.get());
1034 restart_required
|= OnHostTokenUrlPolicyUpdate(policies
.get());
1035 restart_required
|= OnPairingPolicyUpdate(policies
.get());
1036 restart_required
|= OnGnubbyAuthPolicyUpdate(policies
.get());
1038 policy_state_
= POLICY_LOADED
;
1040 if (state_
== HOST_STARTING
) {
1042 } else if (state_
== HOST_STARTED
) {
1043 if (restart_required
)
1044 RestartHost(kHostOfflineReasonPolicyChangeRequiresRestart
);
1048 void HostProcess::OnPolicyError() {
1049 if (!context_
->network_task_runner()->BelongsToCurrentThread()) {
1050 context_
->network_task_runner()->PostTask(
1051 FROM_HERE
, base::Bind(&HostProcess::OnPolicyError
, this));
1055 if (policy_state_
!= POLICY_ERROR_REPORTED
) {
1056 policy_state_
= POLICY_ERROR_REPORT_PENDING
;
1057 if ((state_
== HOST_STARTED
) ||
1058 (state_
== HOST_STARTING
&& !serialized_config_
.empty())) {
1059 ReportPolicyErrorAndRestartHost();
1064 void HostProcess::ReportPolicyErrorAndRestartHost() {
1065 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1066 DCHECK(!serialized_config_
.empty());
1068 DCHECK_EQ(policy_state_
, POLICY_ERROR_REPORT_PENDING
);
1069 policy_state_
= POLICY_ERROR_REPORTED
;
1071 HOST_LOG
<< "Restarting the host due to policy errors.";
1072 RestartHost(kHostOfflineReasonPolicyReadError
);
1075 void HostProcess::ApplyHostDomainPolicy() {
1076 if (state_
!= HOST_STARTED
)
1079 HOST_LOG
<< "Policy sets host domain: " << host_domain_
;
1081 if (!host_domain_
.empty()) {
1082 // If the user does not have a Google email, their client JID will not be
1083 // based on their email. In that case, the username/host domain policies
1084 // would be meaningless, since there is no way to check that the JID
1085 // trying to connect actually corresponds to the owner email in question.
1086 if (host_owner_
!= host_owner_email_
) {
1087 LOG(ERROR
) << "The username and host domain policies cannot be enabled "
1088 << "for accounts with a non-Google email.";
1089 ShutdownHost(kInvalidHostDomainExitCode
);
1092 if (!base::EndsWith(host_owner_
, std::string("@") + host_domain_
,
1093 base::CompareCase::INSENSITIVE_ASCII
)) {
1094 LOG(ERROR
) << "The host domain does not match the policy.";
1095 ShutdownHost(kInvalidHostDomainExitCode
);
1100 bool HostProcess::OnHostDomainPolicyUpdate(base::DictionaryValue
* policies
) {
1101 // Returns true if the host has to be restarted after this policy update.
1102 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1104 if (!policies
->GetString(policy::key::kRemoteAccessHostDomain
,
1109 ApplyHostDomainPolicy();
1113 void HostProcess::ApplyUsernamePolicy() {
1114 if (state_
!= HOST_STARTED
)
1117 if (host_username_match_required_
) {
1118 HOST_LOG
<< "Policy requires host username match.";
1120 // See comment in ApplyHostDomainPolicy.
1121 if (host_owner_
!= host_owner_email_
) {
1122 LOG(ERROR
) << "The username and host domain policies cannot be enabled "
1123 << "for accounts with a non-Google email.";
1124 ShutdownHost(kUsernameMismatchExitCode
);
1127 std::string username
= GetUsername();
1130 !base::StartsWith(host_owner_
, username
+ std::string("@"),
1131 base::CompareCase::INSENSITIVE_ASCII
);
1133 #if defined(OS_MACOSX)
1134 // On Mac, we run as root at the login screen, so the username won't match.
1135 // However, there's no need to enforce the policy at the login screen, as
1136 // the client will have to reconnect if a login occurs.
1137 if (shutdown
&& getuid() == 0) {
1142 // Curtain-mode on Windows presents the standard OS login prompt to the user
1143 // for each connection, removing the need for an explicit user-name matching
1145 #if defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1146 if (curtain_required_
)
1148 #endif // defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1150 // Shutdown the host if the username does not match.
1152 LOG(ERROR
) << "The host username does not match.";
1153 ShutdownHost(kUsernameMismatchExitCode
);
1156 HOST_LOG
<< "Policy does not require host username match.";
1160 bool HostProcess::OnUsernamePolicyUpdate(base::DictionaryValue
* policies
) {
1161 // Returns false: never restart the host after this policy update.
1162 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1164 if (!policies
->GetBoolean(policy::key::kRemoteAccessHostMatchUsername
,
1165 &host_username_match_required_
)) {
1169 ApplyUsernamePolicy();
1173 bool HostProcess::OnNatPolicyUpdate(base::DictionaryValue
* policies
) {
1174 // Returns true if the host has to be restarted after this policy update.
1175 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1177 if (!policies
->GetBoolean(policy::key::kRemoteAccessHostFirewallTraversal
,
1178 &allow_nat_traversal_
)) {
1182 if (allow_nat_traversal_
) {
1183 HOST_LOG
<< "Policy enables NAT traversal.";
1185 HOST_LOG
<< "Policy disables NAT traversal.";
1190 bool HostProcess::OnRelayPolicyUpdate(base::DictionaryValue
* policies
) {
1191 // Returns true if the host has to be restarted after this policy update.
1192 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1194 if (!policies
->GetBoolean(
1195 policy::key::kRemoteAccessHostAllowRelayedConnection
,
1201 HOST_LOG
<< "Policy enables use of relay server.";
1203 HOST_LOG
<< "Policy disables use of relay server.";
1208 bool HostProcess::OnUdpPortPolicyUpdate(base::DictionaryValue
* policies
) {
1209 // Returns true if the host has to be restarted after this policy update.
1210 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1212 std::string string_value
;
1213 if (!policies
->GetString(policy::key::kRemoteAccessHostUdpPortRange
,
1218 if (!PortRange::Parse(string_value
, &udp_port_range_
)) {
1219 // PolicyWatcher verifies that the value is formatted correctly.
1220 LOG(FATAL
) << "Invalid port range: " << string_value
;
1222 HOST_LOG
<< "Policy restricts UDP port range to: " << udp_port_range_
;
1226 bool HostProcess::OnCurtainPolicyUpdate(base::DictionaryValue
* policies
) {
1227 // Returns true if the host has to be restarted after this policy update.
1228 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1230 if (!policies
->GetBoolean(policy::key::kRemoteAccessHostRequireCurtain
,
1231 &curtain_required_
)) {
1235 #if defined(OS_MACOSX)
1236 if (curtain_required_
) {
1237 // When curtain mode is in effect on Mac, the host process runs in the
1238 // user's switched-out session, but launchd will also run an instance at
1239 // the console login screen. Even if no user is currently logged-on, we
1240 // can't support remote-access to the login screen because the current host
1241 // process model disconnects the client during login, which would leave
1242 // the logged in session un-curtained on the console until they reconnect.
1244 // TODO(jamiewalch): Fix this once we have implemented the multi-process
1245 // daemon architecture (crbug.com/134894)
1246 if (getuid() == 0) {
1247 LOG(ERROR
) << "Running the host in the console login session is yet not "
1249 ShutdownHost(kLoginScreenNotSupportedExitCode
);
1255 if (curtain_required_
) {
1256 HOST_LOG
<< "Policy requires curtain-mode.";
1258 HOST_LOG
<< "Policy does not require curtain-mode.";
1262 host_
->SetEnableCurtaining(curtain_required_
);
1266 bool HostProcess::OnHostTalkGadgetPrefixPolicyUpdate(
1267 base::DictionaryValue
* policies
) {
1268 // Returns true if the host has to be restarted after this policy update.
1269 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1271 if (!policies
->GetString(policy::key::kRemoteAccessHostTalkGadgetPrefix
,
1272 &talkgadget_prefix_
)) {
1276 HOST_LOG
<< "Policy sets talkgadget prefix: " << talkgadget_prefix_
;
1280 bool HostProcess::OnHostTokenUrlPolicyUpdate(base::DictionaryValue
* policies
) {
1281 switch (ThirdPartyAuthConfig::Parse(*policies
, &third_party_auth_config_
)) {
1282 case ThirdPartyAuthConfig::NoPolicy
:
1284 case ThirdPartyAuthConfig::ParsingSuccess
:
1285 HOST_LOG
<< "Policy sets third-party token URLs: "
1286 << third_party_auth_config_
;
1288 case ThirdPartyAuthConfig::InvalidPolicy
:
1295 bool HostProcess::OnPairingPolicyUpdate(base::DictionaryValue
* policies
) {
1296 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1298 if (!policies
->GetBoolean(policy::key::kRemoteAccessHostAllowClientPairing
,
1303 if (allow_pairing_
) {
1304 HOST_LOG
<< "Policy enables client pairing.";
1306 HOST_LOG
<< "Policy disables client pairing.";
1311 bool HostProcess::OnGnubbyAuthPolicyUpdate(base::DictionaryValue
* policies
) {
1312 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1314 if (!policies
->GetBoolean(policy::key::kRemoteAccessHostAllowGnubbyAuth
,
1315 &enable_gnubby_auth_
)) {
1319 if (enable_gnubby_auth_
) {
1320 HOST_LOG
<< "Policy enables gnubby auth.";
1322 HOST_LOG
<< "Policy disables gnubby auth.";
1325 if (desktop_environment_factory_
)
1326 desktop_environment_factory_
->SetEnableGnubbyAuth(enable_gnubby_auth_
);
1331 void HostProcess::InitializeSignaling() {
1332 DCHECK(!host_id_
.empty()); // ApplyConfig() should already have been run.
1334 DCHECK(!signal_strategy_
);
1335 DCHECK(!oauth_token_getter_
);
1336 DCHECK(!signaling_connector_
);
1337 #if defined(USE_GCD)
1338 DCHECK(!gcd_state_updater_
);
1339 DCHECK(!gcd_subscriber_
);
1340 #endif // defined(USE_GCD)
1341 DCHECK(!heartbeat_sender_
);
1343 // Create SignalStrategy.
1344 XmppSignalStrategy
* xmpp_signal_strategy
= new XmppSignalStrategy(
1345 net::ClientSocketFactory::GetDefaultFactory(),
1346 context_
->url_request_context_getter(), xmpp_server_config_
);
1347 signal_strategy_
.reset(xmpp_signal_strategy
);
1349 // Create SignalingConnector.
1350 scoped_ptr
<DnsBlackholeChecker
> dns_blackhole_checker(new DnsBlackholeChecker(
1351 context_
->url_request_context_getter(), talkgadget_prefix_
));
1352 scoped_ptr
<OAuthTokenGetter::OAuthCredentials
> oauth_credentials(
1353 new OAuthTokenGetter::OAuthCredentials(xmpp_server_config_
.username
,
1354 oauth_refresh_token_
,
1355 use_service_account_
));
1356 oauth_token_getter_
.reset(new OAuthTokenGetterImpl(
1357 oauth_credentials
.Pass(), context_
->url_request_context_getter(), false));
1358 signaling_connector_
.reset(new SignalingConnector(
1359 xmpp_signal_strategy
, dns_blackhole_checker
.Pass(),
1360 oauth_token_getter_
.get(),
1361 base::Bind(&HostProcess::OnAuthFailed
, base::Unretained(this))));
1363 #if defined(USE_GCD)
1364 // Create objects to manage GCD state.
1365 ServiceUrls
* service_urls
= ServiceUrls::GetInstance();
1366 scoped_ptr
<GcdRestClient
> gcd_rest_client(new GcdRestClient(
1367 service_urls
->gcd_base_url(), host_id_
,
1368 context_
->url_request_context_getter(), oauth_token_getter_
.get()));
1369 gcd_state_updater_
.reset(
1370 new GcdStateUpdater(base::Bind(&HostProcess::OnHeartbeatSuccessful
,
1371 base::Unretained(this)),
1372 base::Bind(&HostProcess::OnUnknownHostIdError
,
1373 base::Unretained(this)),
1374 signal_strategy_
.get(), gcd_rest_client
.Pass()));
1375 PushNotificationSubscriber::Subscription sub
;
1376 sub
.channel
= "cloud_devices";
1377 PushNotificationSubscriber::SubscriptionList subs
;
1378 subs
.push_back(sub
);
1379 gcd_subscriber_
.reset(
1380 new PushNotificationSubscriber(signal_strategy_
.get(), subs
));
1381 #endif // defined(USE_GCD)
1383 // Create HeartbeatSender.
1384 heartbeat_sender_
.reset(new HeartbeatSender(
1385 base::Bind(&HostProcess::OnHeartbeatSuccessful
, base::Unretained(this)),
1386 base::Bind(&HostProcess::OnUnknownHostIdError
, base::Unretained(this)),
1387 host_id_
, signal_strategy_
.get(), key_pair_
, directory_bot_jid_
));
1390 void HostProcess::StartHostIfReady() {
1391 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1392 DCHECK_EQ(state_
, HOST_STARTING
);
1394 // Start the host if both the config and the policies are loaded.
1395 if (!serialized_config_
.empty()) {
1396 if (policy_state_
== POLICY_LOADED
) {
1398 } else if (policy_state_
== POLICY_ERROR_REPORT_PENDING
) {
1399 ReportPolicyErrorAndRestartHost();
1404 void HostProcess::StartHost() {
1405 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1408 SetState(HOST_STARTED
);
1410 InitializeSignaling();
1412 uint32 network_flags
= 0;
1413 if (allow_nat_traversal_
) {
1414 network_flags
= NetworkSettings::NAT_TRAVERSAL_STUN
|
1415 NetworkSettings::NAT_TRAVERSAL_OUTGOING
;
1417 network_flags
|= NetworkSettings::NAT_TRAVERSAL_RELAY
;
1420 NetworkSettings
network_settings(network_flags
);
1422 if (!udp_port_range_
.is_null()) {
1423 network_settings
.port_range
= udp_port_range_
;
1424 } else if (!allow_nat_traversal_
) {
1425 // For legacy reasons we have to restrict the port range to a set of default
1426 // values when nat traversal is disabled, even if the port range was not
1428 network_settings
.port_range
.min_port
= NetworkSettings::kDefaultMinPort
;
1429 network_settings
.port_range
.max_port
= NetworkSettings::kDefaultMaxPort
;
1432 scoped_ptr
<protocol::SessionManager
> session_manager
=
1433 CreateHostSessionManager(signal_strategy_
.get(), network_settings
,
1434 context_
->url_request_context_getter());
1436 scoped_ptr
<protocol::CandidateSessionConfig
> protocol_config
=
1437 protocol::CandidateSessionConfig::CreateDefault();
1438 if (!desktop_environment_factory_
->SupportsAudioCapture())
1439 protocol_config
->DisableAudioChannel();
1441 protocol_config
->set_vp9_experiment_enabled(true);
1442 session_manager
->set_protocol_config(protocol_config
.Pass());
1444 host_
.reset(new ChromotingHost(
1445 signal_strategy_
.get(), desktop_environment_factory_
.get(),
1446 session_manager
.Pass(), context_
->audio_task_runner(),
1447 context_
->input_task_runner(), context_
->video_capture_task_runner(),
1448 context_
->video_encode_task_runner(), context_
->network_task_runner(),
1449 context_
->ui_task_runner()));
1451 if (frame_recorder_buffer_size_
> 0) {
1452 scoped_ptr
<VideoFrameRecorderHostExtension
> frame_recorder_extension(
1453 new VideoFrameRecorderHostExtension());
1454 frame_recorder_extension
->SetMaxContentBytes(frame_recorder_buffer_size_
);
1455 host_
->AddExtension(frame_recorder_extension
.Pass());
1458 // TODO(simonmorris): Get the maximum session duration from a policy.
1459 #if defined(OS_LINUX)
1460 host_
->SetMaximumSessionDuration(base::TimeDelta::FromHours(20));
1463 host_change_notification_listener_
.reset(new HostChangeNotificationListener(
1464 this, host_id_
, signal_strategy_
.get(), directory_bot_jid_
));
1466 host_status_logger_
.reset(new HostStatusLogger(
1467 host_
->AsWeakPtr(), ServerLogEntry::ME2ME
,
1468 signal_strategy_
.get(), directory_bot_jid_
));
1470 // Set up reporting the host status notifications.
1471 #if defined(REMOTING_MULTI_PROCESS)
1472 host_event_logger_
.reset(
1473 new IpcHostEventLogger(host_
->AsWeakPtr(), daemon_channel_
.get()));
1474 #else // !defined(REMOTING_MULTI_PROCESS)
1475 host_event_logger_
=
1476 HostEventLogger::Create(host_
->AsWeakPtr(), kApplicationName
);
1477 #endif // !defined(REMOTING_MULTI_PROCESS)
1479 host_
->SetEnableCurtaining(curtain_required_
);
1480 host_
->Start(host_owner_email_
);
1482 CreateAuthenticatorFactory();
1484 ApplyHostDomainPolicy();
1485 ApplyUsernamePolicy();
1488 void HostProcess::OnAuthFailed() {
1489 ShutdownHost(kInvalidOauthCredentialsExitCode
);
1492 void HostProcess::RestartHost(const std::string
& host_offline_reason
) {
1493 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1494 DCHECK(!host_offline_reason
.empty());
1496 SetState(HOST_GOING_OFFLINE_TO_RESTART
);
1497 GoOffline(host_offline_reason
);
1500 void HostProcess::ShutdownHost(HostExitCodes exit_code
) {
1501 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1503 *exit_code_out_
= exit_code
;
1508 SetState(HOST_GOING_OFFLINE_TO_STOP
);
1509 GoOffline(ExitCodeToString(exit_code
));
1512 case HOST_GOING_OFFLINE_TO_RESTART
:
1513 SetState(HOST_GOING_OFFLINE_TO_STOP
);
1516 case HOST_GOING_OFFLINE_TO_STOP
:
1518 // Host is already stopped or being stopped. No action is required.
1523 void HostProcess::GoOffline(const std::string
& host_offline_reason
) {
1524 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1525 DCHECK(!host_offline_reason
.empty());
1526 DCHECK((state_
== HOST_GOING_OFFLINE_TO_STOP
) ||
1527 (state_
== HOST_GOING_OFFLINE_TO_RESTART
));
1529 // Shut down everything except the HostSignalingManager.
1531 host_event_logger_
.reset();
1532 host_status_logger_
.reset();
1533 host_change_notification_listener_
.reset();
1535 // Before shutting down HostSignalingManager, send the |host_offline_reason|
1536 // if possible (i.e. if we have the config).
1537 if (!serialized_config_
.empty()) {
1538 if (!signal_strategy_
)
1539 InitializeSignaling();
1541 HOST_LOG
<< "SendHostOfflineReason: sending " << host_offline_reason
<< ".";
1542 if (heartbeat_sender_
) {
1543 heartbeat_sender_
->SetHostOfflineReason(
1544 host_offline_reason
,
1545 base::TimeDelta::FromSeconds(kHostOfflineReasonTimeoutSeconds
),
1546 base::Bind(&HostProcess::OnHostOfflineReasonAck
, this));
1548 #if defined(USE_GCD)
1549 if (gcd_state_updater_
) {
1550 gcd_state_updater_
->SetHostOfflineReason(
1551 host_offline_reason
,
1552 base::TimeDelta::FromSeconds(kHostOfflineReasonTimeoutSeconds
),
1553 base::Bind(&HostProcess::OnHostOfflineReasonAck
, this));
1555 #endif // defined(USE_GCD)
1556 return; // Shutdown will resume after OnHostOfflineReasonAck.
1559 // Continue the shutdown without sending the host offline reason.
1560 HOST_LOG
<< "Can't send offline reason (" << host_offline_reason
<< ") "
1561 << "without a valid host config.";
1562 OnHostOfflineReasonAck(false);
1565 void HostProcess::OnHostOfflineReasonAck(bool success
) {
1566 DCHECK(context_
->network_task_runner()->BelongsToCurrentThread());
1567 DCHECK(!host_
); // Assert that the host is really offline at this point.
1569 HOST_LOG
<< "SendHostOfflineReason " << (success
? "succeeded." : "failed.");
1570 heartbeat_sender_
.reset();
1571 oauth_token_getter_
.reset();
1572 signaling_connector_
.reset();
1573 signal_strategy_
.reset();
1574 #if defined(USE_GCD)
1575 gcd_state_updater_
.reset();
1576 gcd_subscriber_
.reset();
1577 #endif // defined(USE_GCD)
1579 if (state_
== HOST_GOING_OFFLINE_TO_RESTART
) {
1580 SetState(HOST_STARTING
);
1582 } else if (state_
== HOST_GOING_OFFLINE_TO_STOP
) {
1583 SetState(HOST_STOPPED
);
1585 shutdown_watchdog_
->SetExitCode(*exit_code_out_
);
1586 shutdown_watchdog_
->Arm();
1588 config_watcher_
.reset();
1590 // Complete the rest of shutdown on the main thread.
1591 context_
->ui_task_runner()->PostTask(
1592 FROM_HERE
, base::Bind(&HostProcess::ShutdownOnUiThread
, this));
1598 void HostProcess::OnCrash(const std::string
& function_name
,
1599 const std::string
& file_name
,
1600 const int& line_number
) {
1602 base::snprintf(message
, sizeof(message
),
1603 "Requested by %s at %s, line %d.",
1604 function_name
.c_str(), file_name
.c_str(), line_number
);
1605 base::debug::Alias(message
);
1607 // The daemon requested us to crash the process.
1608 CHECK(false) << message
;
1611 int HostProcessMain() {
1612 HOST_LOG
<< "Starting host process: version " << STRINGIZE(VERSION
);
1614 #if defined(OS_LINUX)
1615 // Required in order for us to run multiple X11 threads.
1618 // Required for any calls into GTK functions, such as the Disconnect and
1619 // Continue windows, though these should not be used for the Me2Me case
1620 // (crbug.com/104377).
1621 gtk_init(nullptr, nullptr);
1624 // Enable support for SSL server sockets, which must be done while still
1626 net::EnableSSLServerSockets();
1628 // Create the main message loop and start helper threads.
1629 base::MessageLoopForUI message_loop
;
1630 scoped_ptr
<ChromotingHostContext
> context
=
1631 ChromotingHostContext::Create(new AutoThreadTaskRunner(
1632 message_loop
.task_runner(), base::MessageLoop::QuitClosure()));
1634 return kInitializationFailed
;
1636 // NetworkChangeNotifier must be initialized after MessageLoop.
1637 scoped_ptr
<net::NetworkChangeNotifier
> network_change_notifier(
1638 net::NetworkChangeNotifier::Create());
1640 // Create & start the HostProcess using these threads.
1641 // TODO(wez): The HostProcess holds a reference to itself until Shutdown().
1642 // Remove this hack as part of the multi-process refactoring.
1643 int exit_code
= kSuccessExitCode
;
1644 ShutdownWatchdog
shutdown_watchdog(
1645 base::TimeDelta::FromSeconds(kShutdownTimeoutSeconds
));
1646 new HostProcess(context
.Pass(), &exit_code
, &shutdown_watchdog
);
1648 // Run the main (also UI) message loop until the host no longer needs it.
1654 } // namespace remoting