Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / remoting / host / remoting_me2me_host.cc
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.
6
7 #include <string>
8
9 #include "base/at_exit.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/command_line.h"
13 #include "base/debug/alias.h"
14 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/synchronization/waitable_event.h"
23 #include "base/threading/thread.h"
24 #include "build/build_config.h"
25 #include "crypto/nss_util.h"
26 #include "ipc/ipc_channel.h"
27 #include "ipc/ipc_channel_proxy.h"
28 #include "ipc/ipc_listener.h"
29 #include "media/base/media.h"
30 #include "net/base/network_change_notifier.h"
31 #include "net/socket/client_socket_factory.h"
32 #include "net/socket/ssl_server_socket.h"
33 #include "net/url_request/url_fetcher.h"
34 #include "remoting/base/auto_thread_task_runner.h"
35 #include "remoting/base/breakpad.h"
36 #include "remoting/base/constants.h"
37 #include "remoting/base/logging.h"
38 #include "remoting/base/rsa_key_pair.h"
39 #include "remoting/base/service_urls.h"
40 #include "remoting/base/util.h"
41 #include "remoting/host/branding.h"
42 #include "remoting/host/chromoting_host.h"
43 #include "remoting/host/chromoting_host_context.h"
44 #include "remoting/host/chromoting_messages.h"
45 #include "remoting/host/config_file_watcher.h"
46 #include "remoting/host/config_watcher.h"
47 #include "remoting/host/desktop_environment.h"
48 #include "remoting/host/desktop_session_connector.h"
49 #include "remoting/host/dns_blackhole_checker.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/host_status_sender.h"
58 #include "remoting/host/ipc_constants.h"
59 #include "remoting/host/ipc_desktop_environment.h"
60 #include "remoting/host/ipc_host_event_logger.h"
61 #include "remoting/host/json_host_config.h"
62 #include "remoting/host/logging.h"
63 #include "remoting/host/me2me_desktop_environment.h"
64 #include "remoting/host/pairing_registry_delegate.h"
65 #include "remoting/host/policy_hack/policy_watcher.h"
66 #include "remoting/host/session_manager_factory.h"
67 #include "remoting/host/signaling_connector.h"
68 #include "remoting/host/single_window_desktop_environment.h"
69 #include "remoting/host/token_validator_factory_impl.h"
70 #include "remoting/host/usage_stats_consent.h"
71 #include "remoting/host/username.h"
72 #include "remoting/host/video_frame_recorder_host_extension.h"
73 #include "remoting/protocol/me2me_host_authenticator_factory.h"
74 #include "remoting/protocol/network_settings.h"
75 #include "remoting/protocol/pairing_registry.h"
76 #include "remoting/protocol/token_validator.h"
77 #include "remoting/signaling/xmpp_signal_strategy.h"
78
79 #if defined(OS_POSIX)
80 #include <signal.h>
81 #include <sys/types.h>
82 #include <unistd.h>
83 #include "base/file_descriptor_posix.h"
84 #include "remoting/host/pam_authorization_factory_posix.h"
85 #include "remoting/host/posix/signal_handler.h"
86 #endif  // defined(OS_POSIX)
87
88 #if defined(OS_MACOSX)
89 #include "base/mac/scoped_cftyperef.h"
90 #endif  // defined(OS_MACOSX)
91
92 #if defined(OS_LINUX)
93 #include <gtk/gtk.h>
94 #include "remoting/host/audio_capturer_linux.h"
95 #endif  // defined(OS_LINUX)
96
97 #if defined(OS_WIN)
98 #include <commctrl.h>
99 #include "base/win/registry.h"
100 #include "base/win/scoped_handle.h"
101 #include "remoting/host/pairing_registry_delegate_win.h"
102 #include "remoting/host/win/session_desktop_environment.h"
103 #endif  // defined(OS_WIN)
104
105 using remoting::protocol::PairingRegistry;
106 using remoting::protocol::NetworkSettings;
107
108 namespace {
109
110 // This is used for tagging system event logs.
111 const char kApplicationName[] = "chromoting";
112
113 #if defined(OS_LINUX)
114 // The command line switch used to pass name of the pipe to capture audio on
115 // linux.
116 const char kAudioPipeSwitchName[] = "audio-pipe-name";
117
118 // The command line switch used to pass name of the unix domain socket used to
119 // listen for gnubby requests.
120 const char kAuthSocknameSwitchName[] = "ssh-auth-sockname";
121 #endif  // defined(OS_LINUX)
122
123 // The command line switch used by the parent to request the host to signal it
124 // when it is successfully started.
125 const char kSignalParentSwitchName[] = "signal-parent";
126
127 // Command line switch used to enable VP9 encoding.
128 const char kEnableVp9SwitchName[] = "enable-vp9";
129
130 // Command line switch used to enable and configure the frame-recorder.
131 const char kFrameRecorderBufferKbName[] = "frame-recorder-buffer-kb";
132
133 // Value used for --host-config option to indicate that the path must be read
134 // from stdin.
135 const char kStdinConfigPath[] = "-";
136
137 const char kWindowIdSwitchName[] = "window-id";
138
139 }  // namespace
140
141 namespace remoting {
142
143 class HostProcess
144     : public ConfigWatcher::Delegate,
145       public HeartbeatSender::Listener,
146       public HostChangeNotificationListener::Listener,
147       public IPC::Listener,
148       public base::RefCountedThreadSafe<HostProcess> {
149  public:
150   HostProcess(scoped_ptr<ChromotingHostContext> context,
151               int* exit_code_out);
152
153   // ConfigWatcher::Delegate interface.
154   virtual void OnConfigUpdated(const std::string& serialized_config) OVERRIDE;
155   virtual void OnConfigWatcherError() OVERRIDE;
156
157   // IPC::Listener implementation.
158   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
159   virtual void OnChannelError() OVERRIDE;
160
161   // HeartbeatSender::Listener overrides.
162   virtual void OnHeartbeatSuccessful() OVERRIDE;
163   virtual void OnUnknownHostIdError() OVERRIDE;
164
165   // HostChangeNotificationListener::Listener overrides.
166   virtual void OnHostDeleted() OVERRIDE;
167
168   // Initializes the pairing registry on Windows.
169   void OnInitializePairingRegistry(
170       IPC::PlatformFileForTransit privileged_key,
171       IPC::PlatformFileForTransit unprivileged_key);
172
173  private:
174   enum HostState {
175     // Host process has just been started. Waiting for config and policies to be
176     // read from the disk.
177     HOST_INITIALIZING,
178
179     // Host is started and running.
180     HOST_STARTED,
181
182     // Host is being stopped and will need to be started again.
183     HOST_STOPPING_TO_RESTART,
184
185     // Host is being stopped.
186     HOST_STOPPING,
187
188     // Host has been stopped.
189     HOST_STOPPED,
190
191     // Allowed state transitions:
192     //   INITIALIZING->STARTED
193     //   INITIALIZING->STOPPED
194     //   STARTED->STOPPING_TO_RESTART
195     //   STARTED->STOPPING
196     //   STOPPING_TO_RESTART->STARTED
197     //   STOPPING_TO_RESTART->STOPPING
198     //   STOPPING->STOPPED
199     //   STOPPED->STARTED
200     //
201     // |host_| must be NULL in INITIALIZING and STOPPED states and not-NULL in
202     // all other states.
203   };
204
205   friend class base::RefCountedThreadSafe<HostProcess>;
206   virtual ~HostProcess();
207
208   void StartOnNetworkThread();
209
210 #if defined(OS_POSIX)
211   // Callback passed to RegisterSignalHandler() to handle SIGTERM events.
212   void SigTermHandler(int signal_number);
213 #endif
214
215   // Called to initialize resources on the UI thread.
216   void StartOnUiThread();
217
218   // Initializes IPC control channel and config file path from |cmd_line|.
219   // Called on the UI thread.
220   bool InitWithCommandLine(const base::CommandLine* cmd_line);
221
222   // Called on the UI thread to start monitoring the configuration file.
223   void StartWatchingConfigChanges();
224
225   // Called on the network thread to set the host's Authenticator factory.
226   void CreateAuthenticatorFactory();
227
228   // Tear down resources that run on the UI thread.
229   void ShutdownOnUiThread();
230
231   // Applies the host config, returning true if successful.
232   bool ApplyConfig(scoped_ptr<JsonHostConfig> config);
233
234   // Handles policy updates, by calling On*PolicyUpdate methods.
235   void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies);
236   void ApplyHostDomainPolicy();
237   void ApplyUsernamePolicy();
238   bool OnHostDomainPolicyUpdate(base::DictionaryValue* policies);
239   bool OnUsernamePolicyUpdate(base::DictionaryValue* policies);
240   bool OnNatPolicyUpdate(base::DictionaryValue* policies);
241   bool OnRelayPolicyUpdate(base::DictionaryValue* policies);
242   bool OnUdpPortPolicyUpdate(base::DictionaryValue* policies);
243   bool OnCurtainPolicyUpdate(base::DictionaryValue* policies);
244   bool OnHostTalkGadgetPrefixPolicyUpdate(base::DictionaryValue* policies);
245   bool OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies);
246   bool OnPairingPolicyUpdate(base::DictionaryValue* policies);
247   bool OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies);
248
249   void StartHost();
250
251   void OnAuthFailed();
252
253   void RestartHost();
254
255   // Stops the host and shuts down the process with the specified |exit_code|.
256   void ShutdownHost(HostExitCodes exit_code);
257
258   void ScheduleHostShutdown();
259
260   void ShutdownOnNetworkThread();
261
262   // Crashes the process in response to a daemon's request. The daemon passes
263   // the location of the code that detected the fatal error resulted in this
264   // request.
265   void OnCrash(const std::string& function_name,
266                const std::string& file_name,
267                const int& line_number);
268
269   scoped_ptr<ChromotingHostContext> context_;
270
271   // Created on the UI thread but used from the network thread.
272   scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
273
274   // Accessed on the UI thread.
275   scoped_ptr<IPC::ChannelProxy> daemon_channel_;
276
277   // XMPP server/remoting bot configuration (initialized from the command line).
278   XmppSignalStrategy::XmppServerConfig xmpp_server_config_;
279   std::string directory_bot_jid_;
280
281   // Created on the UI thread but used from the network thread.
282   base::FilePath host_config_path_;
283   std::string host_config_;
284   scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
285
286   // Accessed on the network thread.
287   HostState state_;
288
289   scoped_ptr<ConfigWatcher> config_watcher_;
290
291   std::string host_id_;
292   protocol::SharedSecretHash host_secret_hash_;
293   scoped_refptr<RsaKeyPair> key_pair_;
294   std::string oauth_refresh_token_;
295   std::string serialized_config_;
296   std::string host_owner_;
297   bool use_service_account_;
298   bool enable_vp9_;
299   int64_t frame_recorder_buffer_size_;
300
301   scoped_ptr<policy_hack::PolicyWatcher> policy_watcher_;
302   std::string host_domain_;
303   bool host_username_match_required_;
304   bool allow_nat_traversal_;
305   bool allow_relay_;
306   int min_udp_port_;
307   int max_udp_port_;
308   std::string talkgadget_prefix_;
309   bool allow_pairing_;
310
311   bool curtain_required_;
312   ThirdPartyAuthConfig third_party_auth_config_;
313   bool enable_gnubby_auth_;
314
315   // Boolean to change flow, where ncessary, if we're
316   // capturing a window instead of the entire desktop.
317   bool enable_window_capture_;
318
319   // Used to specify which window to stream, if enabled.
320   webrtc::WindowId window_id_;
321
322   scoped_ptr<OAuthTokenGetter> oauth_token_getter_;
323   scoped_ptr<XmppSignalStrategy> signal_strategy_;
324   scoped_ptr<SignalingConnector> signaling_connector_;
325   scoped_ptr<HeartbeatSender> heartbeat_sender_;
326   scoped_ptr<HostStatusSender> host_status_sender_;
327   scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_;
328   scoped_ptr<HostStatusLogger> host_status_logger_;
329   scoped_ptr<HostEventLogger> host_event_logger_;
330
331   scoped_ptr<ChromotingHost> host_;
332
333   // Used to keep this HostProcess alive until it is shutdown.
334   scoped_refptr<HostProcess> self_;
335
336 #if defined(REMOTING_MULTI_PROCESS)
337   DesktopSessionConnector* desktop_session_connector_;
338 #endif  // defined(REMOTING_MULTI_PROCESS)
339
340   int* exit_code_out_;
341   bool signal_parent_;
342
343   scoped_ptr<PairingRegistry::Delegate> pairing_registry_delegate_;
344 };
345
346 HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context,
347                          int* exit_code_out)
348     : context_(context.Pass()),
349       state_(HOST_INITIALIZING),
350       use_service_account_(false),
351       enable_vp9_(false),
352       frame_recorder_buffer_size_(0),
353       host_username_match_required_(false),
354       allow_nat_traversal_(true),
355       allow_relay_(true),
356       min_udp_port_(0),
357       max_udp_port_(0),
358       allow_pairing_(true),
359       curtain_required_(false),
360       enable_gnubby_auth_(false),
361       enable_window_capture_(false),
362       window_id_(0),
363 #if defined(REMOTING_MULTI_PROCESS)
364       desktop_session_connector_(NULL),
365 #endif  // defined(REMOTING_MULTI_PROCESS)
366       self_(this),
367       exit_code_out_(exit_code_out),
368       signal_parent_(false) {
369   StartOnUiThread();
370 }
371
372 HostProcess::~HostProcess() {
373   // Verify that UI components have been torn down.
374   DCHECK(!config_watcher_);
375   DCHECK(!daemon_channel_);
376   DCHECK(!desktop_environment_factory_);
377
378   // We might be getting deleted on one of the threads the |host_context| owns,
379   // so we need to post it back to the caller thread to safely join & delete the
380   // threads it contains.  This will go away when we move to AutoThread.
381   // |context_release()| will null |context_| before the method is invoked, so
382   // we need to pull out the task-runner on which to call DeleteSoon first.
383   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
384       context_->ui_task_runner();
385   task_runner->DeleteSoon(FROM_HERE, context_.release());
386 }
387
388 bool HostProcess::InitWithCommandLine(const base::CommandLine* cmd_line) {
389 #if defined(REMOTING_MULTI_PROCESS)
390   // Parse the handle value and convert it to a handle/file descriptor.
391   std::string channel_name =
392       cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
393
394   int pipe_handle = 0;
395   if (channel_name.empty() ||
396       !base::StringToInt(channel_name, &pipe_handle)) {
397     LOG(ERROR) << "Invalid '" << kDaemonPipeSwitchName
398                << "' value: " << channel_name;
399     return false;
400   }
401
402 #if defined(OS_WIN)
403   base::win::ScopedHandle pipe(reinterpret_cast<HANDLE>(pipe_handle));
404   IPC::ChannelHandle channel_handle(pipe);
405 #elif defined(OS_POSIX)
406   base::FileDescriptor pipe(pipe_handle, true);
407   IPC::ChannelHandle channel_handle(channel_name, pipe);
408 #endif  // defined(OS_POSIX)
409
410   // Connect to the daemon process.
411   daemon_channel_ = IPC::ChannelProxy::Create(channel_handle,
412                                               IPC::Channel::MODE_CLIENT,
413                                               this,
414                                               context_->network_task_runner());
415 #else  // !defined(REMOTING_MULTI_PROCESS)
416   // Connect to the daemon process.
417   std::string channel_name =
418       cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
419   if (!channel_name.empty()) {
420     daemon_channel_ =
421         IPC::ChannelProxy::Create(channel_name,
422                                   IPC::Channel::MODE_CLIENT,
423                                   this,
424                                   context_->network_task_runner().get());
425   }
426
427   if (cmd_line->HasSwitch(kHostConfigSwitchName)) {
428     host_config_path_ = cmd_line->GetSwitchValuePath(kHostConfigSwitchName);
429
430     // Read config from stdin if necessary.
431     if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
432       char buf[4096];
433       size_t len;
434       while ((len = fread(buf, 1, sizeof(buf), stdin)) > 0) {
435         host_config_.append(buf, len);
436       }
437     }
438   } else {
439     base::FilePath default_config_dir = remoting::GetConfigDir();
440     host_config_path_ = default_config_dir.Append(kDefaultHostConfigFile);
441   }
442
443   if (host_config_path_ != base::FilePath(kStdinConfigPath) &&
444       !base::PathExists(host_config_path_)) {
445     LOG(ERROR) << "Can't find host config at " << host_config_path_.value();
446     return false;
447   }
448 #endif  // !defined(REMOTING_MULTI_PROCESS)
449
450   // Ignore certificate requests - the host currently has no client certificate
451   // support, so ignoring certificate requests allows connecting to servers that
452   // request, but don't require, a certificate (optional client authentication).
453   net::URLFetcher::SetIgnoreCertificateRequests(true);
454
455   ServiceUrls* service_urls = ServiceUrls::GetInstance();
456   bool xmpp_server_valid = net::ParseHostAndPort(
457       service_urls->xmpp_server_address(),
458       &xmpp_server_config_.host, &xmpp_server_config_.port);
459   if (!xmpp_server_valid) {
460     LOG(ERROR) << "Invalid XMPP server: " <<
461         service_urls->xmpp_server_address();
462     return false;
463   }
464   xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls();
465   directory_bot_jid_ = service_urls->directory_bot_jid();
466
467   signal_parent_ = cmd_line->HasSwitch(kSignalParentSwitchName);
468
469   enable_window_capture_ = cmd_line->HasSwitch(kWindowIdSwitchName);
470   if (enable_window_capture_) {
471
472 #if defined(OS_LINUX) || defined(OS_WIN)
473     LOG(WARNING) << "Window capturing is not fully supported on Linux or "
474                     "Windows.";
475 #endif  // defined(OS_LINUX) || defined(OS_WIN)
476
477     // uint32_t is large enough to hold window IDs on all platforms.
478     uint32_t window_id;
479     if (base::StringToUint(
480             cmd_line->GetSwitchValueASCII(kWindowIdSwitchName),
481             &window_id)) {
482       window_id_ = static_cast<webrtc::WindowId>(window_id);
483     } else {
484       LOG(ERROR) << "Window with window id: " << window_id_
485                  << " not found. Shutting down host.";
486       return false;
487     }
488   }
489   return true;
490 }
491
492 void HostProcess::OnConfigUpdated(
493     const std::string& serialized_config) {
494   if (!context_->network_task_runner()->BelongsToCurrentThread()) {
495     context_->network_task_runner()->PostTask(FROM_HERE,
496         base::Bind(&HostProcess::OnConfigUpdated, this, serialized_config));
497     return;
498   }
499
500   // Filter out duplicates.
501   if (serialized_config_ == serialized_config)
502     return;
503
504   HOST_LOG << "Processing new host configuration.";
505
506   serialized_config_ = serialized_config;
507   scoped_ptr<JsonHostConfig> config(new JsonHostConfig(base::FilePath()));
508   if (!config->SetSerializedData(serialized_config)) {
509     LOG(ERROR) << "Invalid configuration.";
510     ShutdownHost(kInvalidHostConfigurationExitCode);
511     return;
512   }
513
514   if (!ApplyConfig(config.Pass())) {
515     LOG(ERROR) << "Failed to apply the configuration.";
516     ShutdownHost(kInvalidHostConfigurationExitCode);
517     return;
518   }
519
520   if (state_ == HOST_INITIALIZING) {
521     // TODO(sergeyu): Currently OnPolicyUpdate() assumes that host config is
522     // already loaded so PolicyWatcher has to be started here. Separate policy
523     // loading from policy verifications and move |policy_watcher_|
524     // initialization to StartOnNetworkThread().
525     policy_watcher_.reset(
526         policy_hack::PolicyWatcher::Create(context_->file_task_runner()));
527     policy_watcher_->StartWatching(
528         base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)));
529   } else {
530     // Reapply policies that could be affected by a new config.
531     ApplyHostDomainPolicy();
532     ApplyUsernamePolicy();
533
534     if (state_ == HOST_STARTED) {
535       // TODO(sergeyu): Here we assume that PIN is the only part of the config
536       // that may change while the service is running. Change ApplyConfig() to
537       // detect other changes in the config and restart host if necessary here.
538       CreateAuthenticatorFactory();
539     }
540   }
541 }
542
543 void HostProcess::OnConfigWatcherError() {
544   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
545   ShutdownHost(kInvalidHostConfigurationExitCode);
546 }
547
548 void HostProcess::StartOnNetworkThread() {
549   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
550
551 #if !defined(REMOTING_MULTI_PROCESS)
552   if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
553     // Process config we've read from stdin.
554     OnConfigUpdated(host_config_);
555   } else {
556     // Start watching the host configuration file.
557     config_watcher_.reset(new ConfigFileWatcher(context_->network_task_runner(),
558                                                 context_->file_task_runner(),
559                                                 host_config_path_));
560     config_watcher_->Watch(this);
561   }
562 #endif  // !defined(REMOTING_MULTI_PROCESS)
563
564 #if defined(OS_POSIX)
565   remoting::RegisterSignalHandler(
566       SIGTERM,
567       base::Bind(&HostProcess::SigTermHandler, base::Unretained(this)));
568 #endif  // defined(OS_POSIX)
569 }
570
571 #if defined(OS_POSIX)
572 void HostProcess::SigTermHandler(int signal_number) {
573   DCHECK(signal_number == SIGTERM);
574   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
575   HOST_LOG << "Caught SIGTERM: Shutting down...";
576   ShutdownHost(kSuccessExitCode);
577 }
578 #endif  // OS_POSIX
579
580 void HostProcess::CreateAuthenticatorFactory() {
581   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
582
583   if (state_ != HOST_STARTED)
584     return;
585
586   std::string local_certificate = key_pair_->GenerateCertificate();
587   if (local_certificate.empty()) {
588     LOG(ERROR) << "Failed to generate host certificate.";
589     ShutdownHost(kInitializationFailed);
590     return;
591   }
592
593   scoped_refptr<PairingRegistry> pairing_registry = NULL;
594   if (allow_pairing_) {
595     if (!pairing_registry_delegate_)
596       pairing_registry_delegate_ = CreatePairingRegistryDelegate();
597
598     if (pairing_registry_delegate_) {
599       pairing_registry = new PairingRegistry(context_->file_task_runner(),
600                                              pairing_registry_delegate_.Pass());
601     }
602   }
603
604   scoped_ptr<protocol::AuthenticatorFactory> factory;
605
606   if (third_party_auth_config_.is_empty()) {
607     factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
608         use_service_account_, host_owner_, local_certificate, key_pair_,
609         host_secret_hash_, pairing_registry);
610
611   } else if (third_party_auth_config_.is_valid()) {
612     scoped_ptr<protocol::TokenValidatorFactory> token_validator_factory(
613         new TokenValidatorFactoryImpl(
614             third_party_auth_config_,
615             key_pair_, context_->url_request_context_getter()));
616     factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
617         use_service_account_, host_owner_, local_certificate, key_pair_,
618         token_validator_factory.Pass());
619
620   } else {
621     // TODO(rmsousa): If the policy is bad the host should not go online. It
622     // should keep running, but not connected, until the policies are fixed.
623     // Having it show up as online and then reject all clients is misleading.
624     LOG(ERROR) << "One of the third-party token URLs is empty or invalid. "
625                << "Host will reject all clients until policies are corrected. "
626                << "TokenUrl: " << third_party_auth_config_.token_url << ", "
627                << "TokenValidationUrl: "
628                << third_party_auth_config_.token_validation_url;
629     factory = protocol::Me2MeHostAuthenticatorFactory::CreateRejecting();
630   }
631
632 #if defined(OS_POSIX)
633   // On Linux and Mac, perform a PAM authorization step after authentication.
634   factory.reset(new PamAuthorizationFactory(factory.Pass()));
635 #endif
636   host_->SetAuthenticatorFactory(factory.Pass());
637
638   host_->set_pairing_registry(pairing_registry);
639 }
640
641 // IPC::Listener implementation.
642 bool HostProcess::OnMessageReceived(const IPC::Message& message) {
643   DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
644
645 #if defined(REMOTING_MULTI_PROCESS)
646   bool handled = true;
647   IPC_BEGIN_MESSAGE_MAP(HostProcess, message)
648     IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash)
649     IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration,
650                         OnConfigUpdated)
651     IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_InitializePairingRegistry,
652                         OnInitializePairingRegistry)
653     IPC_MESSAGE_FORWARD(
654         ChromotingDaemonNetworkMsg_DesktopAttached,
655         desktop_session_connector_,
656         DesktopSessionConnector::OnDesktopSessionAgentAttached)
657     IPC_MESSAGE_FORWARD(ChromotingDaemonNetworkMsg_TerminalDisconnected,
658                         desktop_session_connector_,
659                         DesktopSessionConnector::OnTerminalDisconnected)
660     IPC_MESSAGE_UNHANDLED(handled = false)
661   IPC_END_MESSAGE_MAP()
662
663   CHECK(handled) << "Received unexpected IPC type: " << message.type();
664   return handled;
665
666 #else  // !defined(REMOTING_MULTI_PROCESS)
667   return false;
668 #endif  // !defined(REMOTING_MULTI_PROCESS)
669 }
670
671 void HostProcess::OnChannelError() {
672   DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
673
674   // Shutdown the host if the daemon process disconnects the IPC channel.
675   context_->network_task_runner()->PostTask(
676       FROM_HERE,
677       base::Bind(&HostProcess::ShutdownHost, this, kSuccessExitCode));
678 }
679
680 void HostProcess::StartOnUiThread() {
681   DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
682
683   if (!InitWithCommandLine(base::CommandLine::ForCurrentProcess())) {
684     // Shutdown the host if the command line is invalid.
685     context_->network_task_runner()->PostTask(
686         FROM_HERE, base::Bind(&HostProcess::ShutdownHost, this,
687                               kUsageExitCode));
688     return;
689   }
690
691 #if defined(OS_LINUX)
692   // If an audio pipe is specific on the command-line then initialize
693   // AudioCapturerLinux to capture from it.
694   base::FilePath audio_pipe_name = base::CommandLine::ForCurrentProcess()->
695       GetSwitchValuePath(kAudioPipeSwitchName);
696   if (!audio_pipe_name.empty()) {
697     remoting::AudioCapturerLinux::InitializePipeReader(
698         context_->audio_task_runner(), audio_pipe_name);
699   }
700
701   base::FilePath gnubby_socket_name = base::CommandLine::ForCurrentProcess()->
702       GetSwitchValuePath(kAuthSocknameSwitchName);
703   if (!gnubby_socket_name.empty())
704     remoting::GnubbyAuthHandler::SetGnubbySocketName(gnubby_socket_name);
705 #endif  // defined(OS_LINUX)
706
707   // Create a desktop environment factory appropriate to the build type &
708   // platform.
709 #if defined(OS_WIN)
710   IpcDesktopEnvironmentFactory* desktop_environment_factory =
711       new IpcDesktopEnvironmentFactory(
712           context_->audio_task_runner(),
713           context_->network_task_runner(),
714           context_->video_capture_task_runner(),
715           context_->network_task_runner(),
716           daemon_channel_.get());
717   desktop_session_connector_ = desktop_environment_factory;
718 #else  // !defined(OS_WIN)
719   DesktopEnvironmentFactory* desktop_environment_factory;
720   if (enable_window_capture_) {
721     desktop_environment_factory =
722       new SingleWindowDesktopEnvironmentFactory(
723           context_->network_task_runner(),
724           context_->input_task_runner(),
725           context_->ui_task_runner(),
726           window_id_);
727   } else {
728     desktop_environment_factory =
729       new Me2MeDesktopEnvironmentFactory(
730           context_->network_task_runner(),
731           context_->input_task_runner(),
732           context_->ui_task_runner());
733   }
734 #endif  // !defined(OS_WIN)
735
736   desktop_environment_factory_.reset(desktop_environment_factory);
737   desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
738
739   context_->network_task_runner()->PostTask(
740       FROM_HERE,
741       base::Bind(&HostProcess::StartOnNetworkThread, this));
742 }
743
744 void HostProcess::ShutdownOnUiThread() {
745   DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
746
747   // Tear down resources that need to be torn down on the UI thread.
748   network_change_notifier_.reset();
749   daemon_channel_.reset();
750   desktop_environment_factory_.reset();
751
752   // It is now safe for the HostProcess to be deleted.
753   self_ = NULL;
754
755 #if defined(OS_LINUX)
756   // Cause the global AudioPipeReader to be freed, otherwise the audio
757   // thread will remain in-use and prevent the process from exiting.
758   // TODO(wez): DesktopEnvironmentFactory should own the pipe reader.
759   // See crbug.com/161373 and crbug.com/104544.
760   AudioCapturerLinux::InitializePipeReader(NULL, base::FilePath());
761 #endif
762 }
763
764 // Overridden from HeartbeatSender::Listener
765 void HostProcess::OnUnknownHostIdError() {
766   LOG(ERROR) << "Host ID not found.";
767   ShutdownHost(kInvalidHostIdExitCode);
768 }
769
770 void HostProcess::OnHeartbeatSuccessful() {
771   HOST_LOG << "Host ready to receive connections.";
772 #if defined(OS_POSIX)
773   if (signal_parent_) {
774     kill(getppid(), SIGUSR1);
775     signal_parent_ = false;
776   }
777 #endif
778 }
779
780 void HostProcess::OnHostDeleted() {
781   LOG(ERROR) << "Host was deleted from the directory.";
782   ShutdownHost(kInvalidHostIdExitCode);
783 }
784
785 void HostProcess::OnInitializePairingRegistry(
786     IPC::PlatformFileForTransit privileged_key,
787     IPC::PlatformFileForTransit unprivileged_key) {
788   DCHECK(!pairing_registry_delegate_);
789
790 #if defined(OS_WIN)
791   // Initialize the pairing registry delegate.
792   scoped_ptr<PairingRegistryDelegateWin> delegate(
793       new PairingRegistryDelegateWin());
794   bool result = delegate->SetRootKeys(
795       reinterpret_cast<HKEY>(
796           IPC::PlatformFileForTransitToPlatformFile(privileged_key)),
797       reinterpret_cast<HKEY>(
798           IPC::PlatformFileForTransitToPlatformFile(unprivileged_key)));
799   if (!result)
800     return;
801
802   pairing_registry_delegate_ = delegate.PassAs<PairingRegistry::Delegate>();
803 #else  // !defined(OS_WIN)
804   NOTREACHED();
805 #endif  // !defined(OS_WIN)
806 }
807
808 // Applies the host config, returning true if successful.
809 bool HostProcess::ApplyConfig(scoped_ptr<JsonHostConfig> config) {
810   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
811
812   if (!config->GetString(kHostIdConfigPath, &host_id_)) {
813     LOG(ERROR) << "host_id is not defined in the config.";
814     return false;
815   }
816
817   std::string key_base64;
818   if (!config->GetString(kPrivateKeyConfigPath, &key_base64)) {
819     LOG(ERROR) << "Private key couldn't be read from the config file.";
820     return false;
821   }
822
823   key_pair_ = RsaKeyPair::FromString(key_base64);
824   if (!key_pair_.get()) {
825     LOG(ERROR) << "Invalid private key in the config file.";
826     return false;
827   }
828
829   std::string host_secret_hash_string;
830   if (!config->GetString(kHostSecretHashConfigPath,
831                          &host_secret_hash_string)) {
832     host_secret_hash_string = "plain:";
833   }
834
835   if (!host_secret_hash_.Parse(host_secret_hash_string)) {
836     LOG(ERROR) << "Invalid host_secret_hash.";
837     return false;
838   }
839
840   // Use an XMPP connection to the Talk network for session signalling.
841   if (!config->GetString(kXmppLoginConfigPath, &xmpp_server_config_.username) ||
842       !(config->GetString(kXmppAuthTokenConfigPath,
843                           &xmpp_server_config_.auth_token) ||
844         config->GetString(kOAuthRefreshTokenConfigPath,
845                           &oauth_refresh_token_))) {
846     LOG(ERROR) << "XMPP credentials are not defined in the config.";
847     return false;
848   }
849
850   if (!oauth_refresh_token_.empty()) {
851     // SignalingConnector is responsible for getting OAuth token.
852     xmpp_server_config_.auth_token = "";
853     xmpp_server_config_.auth_service = "oauth2";
854   } else if (!config->GetString(kXmppAuthServiceConfigPath,
855                                 &xmpp_server_config_.auth_service)) {
856     // For the me2me host, we default to ClientLogin token for chromiumsync
857     // because earlier versions of the host had no HTTP stack with which to
858     // request an OAuth2 access token.
859     xmpp_server_config_.auth_service = kChromotingTokenDefaultServiceName;
860   }
861
862   if (config->GetString(kHostOwnerConfigPath, &host_owner_)) {
863     // Service account configs have a host_owner, different from the xmpp_login.
864     use_service_account_ = true;
865   } else {
866     // User credential configs only have an xmpp_login, which is also the owner.
867     host_owner_ = xmpp_server_config_.username;
868     use_service_account_ = false;
869   }
870
871   // Allow offering of VP9 encoding to be overridden by the command-line.
872   if (CommandLine::ForCurrentProcess()->HasSwitch(kEnableVp9SwitchName)) {
873     enable_vp9_ = true;
874   } else {
875     config->GetBoolean(kEnableVp9ConfigPath, &enable_vp9_);
876   }
877
878   // Allow the command-line to override the size of the frame recorder buffer.
879   std::string frame_recorder_buffer_kb;
880   if (CommandLine::ForCurrentProcess()->HasSwitch(
881           kFrameRecorderBufferKbName)) {
882     frame_recorder_buffer_kb =
883         CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
884             kFrameRecorderBufferKbName);
885   } else {
886     config->GetString(kFrameRecorderBufferKbConfigPath,
887                       &frame_recorder_buffer_kb);
888   }
889   if (!frame_recorder_buffer_kb.empty()) {
890     int buffer_kb = 0;
891     if (base::StringToInt(frame_recorder_buffer_kb, &buffer_kb)) {
892       frame_recorder_buffer_size_ = 1024LL * buffer_kb;
893     }
894   }
895
896   return true;
897 }
898
899 void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
900   if (!context_->network_task_runner()->BelongsToCurrentThread()) {
901     context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
902         &HostProcess::OnPolicyUpdate, this, base::Passed(&policies)));
903     return;
904   }
905
906   bool restart_required = false;
907   restart_required |= OnHostDomainPolicyUpdate(policies.get());
908   restart_required |= OnCurtainPolicyUpdate(policies.get());
909   // Note: UsernamePolicyUpdate must run after OnCurtainPolicyUpdate.
910   restart_required |= OnUsernamePolicyUpdate(policies.get());
911   restart_required |= OnNatPolicyUpdate(policies.get());
912   restart_required |= OnRelayPolicyUpdate(policies.get());
913   restart_required |= OnUdpPortPolicyUpdate(policies.get());
914   restart_required |= OnHostTalkGadgetPrefixPolicyUpdate(policies.get());
915   restart_required |= OnHostTokenUrlPolicyUpdate(policies.get());
916   restart_required |= OnPairingPolicyUpdate(policies.get());
917   restart_required |= OnGnubbyAuthPolicyUpdate(policies.get());
918
919   if (state_ == HOST_INITIALIZING) {
920     StartHost();
921   } else if (state_ == HOST_STARTED && restart_required) {
922     RestartHost();
923   }
924 }
925
926 void HostProcess::ApplyHostDomainPolicy() {
927   HOST_LOG << "Policy sets host domain: " << host_domain_;
928   if (!host_domain_.empty() &&
929       !EndsWith(host_owner_, std::string("@") + host_domain_, false)) {
930     LOG(ERROR) << "The host domain does not match the policy.";
931     ShutdownHost(kInvalidHostDomainExitCode);
932   }
933 }
934
935 bool HostProcess::OnHostDomainPolicyUpdate(base::DictionaryValue* policies) {
936   // Returns true if the host has to be restarted after this policy update.
937   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
938
939   if (!policies->GetString(policy_hack::PolicyWatcher::kHostDomainPolicyName,
940                           &host_domain_)) {
941     return false;
942   }
943
944   ApplyHostDomainPolicy();
945   return false;
946 }
947
948 void HostProcess::ApplyUsernamePolicy() {
949   if (host_username_match_required_) {
950     HOST_LOG << "Policy requires host username match.";
951     std::string username = GetUsername();
952     bool shutdown = username.empty() ||
953         !StartsWithASCII(host_owner_, username + std::string("@"),
954                          false);
955
956 #if defined(OS_MACOSX)
957     // On Mac, we run as root at the login screen, so the username won't match.
958     // However, there's no need to enforce the policy at the login screen, as
959     // the client will have to reconnect if a login occurs.
960     if (shutdown && getuid() == 0) {
961       shutdown = false;
962     }
963 #endif
964
965     // Curtain-mode on Windows presents the standard OS login prompt to the user
966     // for each connection, removing the need for an explicit user-name matching
967     // check.
968 #if defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
969     if (curtain_required_)
970       return;
971 #endif  // defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
972
973     // Shutdown the host if the username does not match.
974     if (shutdown) {
975       LOG(ERROR) << "The host username does not match.";
976       ShutdownHost(kUsernameMismatchExitCode);
977     }
978   } else {
979     HOST_LOG << "Policy does not require host username match.";
980   }
981 }
982
983 bool HostProcess::OnUsernamePolicyUpdate(base::DictionaryValue* policies) {
984   // Returns false: never restart the host after this policy update.
985   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
986
987   if (!policies->GetBoolean(
988       policy_hack::PolicyWatcher::kHostMatchUsernamePolicyName,
989       &host_username_match_required_)) {
990     return false;
991   }
992
993   ApplyUsernamePolicy();
994   return false;
995 }
996
997 bool HostProcess::OnNatPolicyUpdate(base::DictionaryValue* policies) {
998   // Returns true if the host has to be restarted after this policy update.
999   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1000
1001   if (!policies->GetBoolean(policy_hack::PolicyWatcher::kNatPolicyName,
1002                            &allow_nat_traversal_)) {
1003     return false;
1004   }
1005
1006   if (allow_nat_traversal_) {
1007     HOST_LOG << "Policy enables NAT traversal.";
1008   } else {
1009     HOST_LOG << "Policy disables NAT traversal.";
1010   }
1011   return true;
1012 }
1013
1014 bool HostProcess::OnRelayPolicyUpdate(base::DictionaryValue* policies) {
1015   // Returns true if the host has to be restarted after this policy update.
1016   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1017
1018   if (!policies->GetBoolean(policy_hack::PolicyWatcher::kRelayPolicyName,
1019                            &allow_relay_)) {
1020     return false;
1021   }
1022
1023   if (allow_relay_) {
1024     HOST_LOG << "Policy enables use of relay server.";
1025   } else {
1026     HOST_LOG << "Policy disables use of relay server.";
1027   }
1028   return true;
1029 }
1030
1031 bool HostProcess::OnUdpPortPolicyUpdate(base::DictionaryValue* policies) {
1032   // Returns true if the host has to be restarted after this policy update.
1033   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1034
1035   std::string udp_port_range;
1036   if (!policies->GetString(policy_hack::PolicyWatcher::kUdpPortRangePolicyName,
1037                            &udp_port_range)) {
1038     return false;
1039   }
1040
1041   // Use default values if policy setting is empty or invalid.
1042   int min_udp_port = 0;
1043   int max_udp_port = 0;
1044   if (!udp_port_range.empty() &&
1045       !NetworkSettings::ParsePortRange(udp_port_range, &min_udp_port,
1046                                        &max_udp_port)) {
1047     LOG(WARNING) << "Invalid port range policy: \"" << udp_port_range
1048                  << "\". Using default values.";
1049   }
1050
1051   if (min_udp_port_ != min_udp_port || max_udp_port_ != max_udp_port) {
1052     if (min_udp_port != 0 && max_udp_port != 0) {
1053       HOST_LOG << "Policy restricts UDP port range to [" << min_udp_port
1054                << ", " << max_udp_port << "]";
1055     } else {
1056       HOST_LOG << "Policy does not restrict UDP port range.";
1057     }
1058     min_udp_port_ = min_udp_port;
1059     max_udp_port_ = max_udp_port;
1060     return true;
1061   }
1062   return false;
1063 }
1064
1065 bool HostProcess::OnCurtainPolicyUpdate(base::DictionaryValue* policies) {
1066   // Returns true if the host has to be restarted after this policy update.
1067   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1068
1069   if (!policies->GetBoolean(
1070           policy_hack::PolicyWatcher::kHostRequireCurtainPolicyName,
1071           &curtain_required_)) {
1072     return false;
1073   }
1074
1075 #if defined(OS_MACOSX)
1076   if (curtain_required_) {
1077     // When curtain mode is in effect on Mac, the host process runs in the
1078     // user's switched-out session, but launchd will also run an instance at
1079     // the console login screen.  Even if no user is currently logged-on, we
1080     // can't support remote-access to the login screen because the current host
1081     // process model disconnects the client during login, which would leave
1082     // the logged in session un-curtained on the console until they reconnect.
1083     //
1084     // TODO(jamiewalch): Fix this once we have implemented the multi-process
1085     // daemon architecture (crbug.com/134894)
1086     if (getuid() == 0) {
1087       LOG(ERROR) << "Running the host in the console login session is yet not "
1088                     "supported.";
1089       ShutdownHost(kLoginScreenNotSupportedExitCode);
1090       return false;
1091     }
1092   }
1093 #endif
1094
1095   if (curtain_required_) {
1096     HOST_LOG << "Policy requires curtain-mode.";
1097   } else {
1098     HOST_LOG << "Policy does not require curtain-mode.";
1099   }
1100
1101   if (host_)
1102     host_->SetEnableCurtaining(curtain_required_);
1103   return false;
1104 }
1105
1106 bool HostProcess::OnHostTalkGadgetPrefixPolicyUpdate(
1107     base::DictionaryValue* policies) {
1108   // Returns true if the host has to be restarted after this policy update.
1109   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1110
1111   if (!policies->GetString(
1112           policy_hack::PolicyWatcher::kHostTalkGadgetPrefixPolicyName,
1113           &talkgadget_prefix_)) {
1114     return false;
1115   }
1116
1117   HOST_LOG << "Policy sets talkgadget prefix: " << talkgadget_prefix_;
1118   return true;
1119 }
1120
1121 bool HostProcess::OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies) {
1122   // Returns true if the host has to be restarted after this policy update.
1123   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1124
1125   bool token_policy_changed = false;
1126   std::string token_url_string;
1127   if (policies->GetString(
1128           policy_hack::PolicyWatcher::kHostTokenUrlPolicyName,
1129           &token_url_string)) {
1130     token_policy_changed = true;
1131     third_party_auth_config_.token_url = GURL(token_url_string);
1132   }
1133   std::string token_validation_url_string;
1134   if (policies->GetString(
1135           policy_hack::PolicyWatcher::kHostTokenValidationUrlPolicyName,
1136           &token_validation_url_string)) {
1137     token_policy_changed = true;
1138     third_party_auth_config_.token_validation_url =
1139         GURL(token_validation_url_string);
1140   }
1141   if (policies->GetString(
1142           policy_hack::PolicyWatcher::kHostTokenValidationCertIssuerPolicyName,
1143           &third_party_auth_config_.token_validation_cert_issuer)) {
1144     token_policy_changed = true;
1145   }
1146
1147   if (token_policy_changed) {
1148     HOST_LOG << "Policy sets third-party token URLs: "
1149              << "TokenUrl: "
1150              << third_party_auth_config_.token_url << ", "
1151              << "TokenValidationUrl: "
1152              << third_party_auth_config_.token_validation_url << ", "
1153              << "TokenValidationCertificateIssuer: "
1154              << third_party_auth_config_.token_validation_cert_issuer;
1155   }
1156   return token_policy_changed;
1157 }
1158
1159 bool HostProcess::OnPairingPolicyUpdate(base::DictionaryValue* policies) {
1160   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1161
1162   if (!policies->GetBoolean(
1163           policy_hack::PolicyWatcher::kHostAllowClientPairing,
1164           &allow_pairing_)) {
1165     return false;
1166   }
1167
1168   if (allow_pairing_) {
1169     HOST_LOG << "Policy enables client pairing.";
1170   } else {
1171     HOST_LOG << "Policy disables client pairing.";
1172   }
1173   return true;
1174 }
1175
1176 bool HostProcess::OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies) {
1177   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1178
1179   if (!policies->GetBoolean(
1180           policy_hack::PolicyWatcher::kHostAllowGnubbyAuthPolicyName,
1181           &enable_gnubby_auth_)) {
1182     return false;
1183   }
1184
1185   if (enable_gnubby_auth_) {
1186     HOST_LOG << "Policy enables gnubby auth.";
1187   } else {
1188     HOST_LOG << "Policy disables gnubby auth.";
1189   }
1190
1191   if (desktop_environment_factory_)
1192     desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
1193
1194   return true;
1195 }
1196
1197 void HostProcess::StartHost() {
1198   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1199   DCHECK(!host_);
1200   DCHECK(!signal_strategy_.get());
1201   DCHECK(state_ == HOST_INITIALIZING || state_ == HOST_STOPPING_TO_RESTART ||
1202          state_ == HOST_STOPPED) << state_;
1203   state_ = HOST_STARTED;
1204
1205   signal_strategy_.reset(
1206       new XmppSignalStrategy(net::ClientSocketFactory::GetDefaultFactory(),
1207                              context_->url_request_context_getter(),
1208                              xmpp_server_config_));
1209
1210   scoped_ptr<DnsBlackholeChecker> dns_blackhole_checker(
1211       new DnsBlackholeChecker(context_->url_request_context_getter(),
1212                               talkgadget_prefix_));
1213
1214   // Create a NetworkChangeNotifier for use by the signaling connector.
1215   network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
1216
1217   signaling_connector_.reset(new SignalingConnector(
1218       signal_strategy_.get(),
1219       dns_blackhole_checker.Pass(),
1220       base::Bind(&HostProcess::OnAuthFailed, this)));
1221
1222   if (!oauth_refresh_token_.empty()) {
1223     scoped_ptr<OAuthTokenGetter::OAuthCredentials> oauth_credentials;
1224     oauth_credentials.reset(
1225         new OAuthTokenGetter::OAuthCredentials(
1226             xmpp_server_config_.username, oauth_refresh_token_,
1227             use_service_account_));
1228
1229     oauth_token_getter_.reset(new OAuthTokenGetter(
1230         oauth_credentials.Pass(), context_->url_request_context_getter(),
1231         false));
1232
1233     signaling_connector_->EnableOAuth(oauth_token_getter_.get());
1234   }
1235
1236   uint32 network_flags = 0;
1237   if (allow_nat_traversal_) {
1238     network_flags = NetworkSettings::NAT_TRAVERSAL_STUN |
1239                     NetworkSettings::NAT_TRAVERSAL_OUTGOING;
1240     if (allow_relay_)
1241       network_flags |= NetworkSettings::NAT_TRAVERSAL_RELAY;
1242   }
1243
1244   NetworkSettings network_settings(network_flags);
1245
1246   if (min_udp_port_ && max_udp_port_) {
1247     network_settings.min_port = min_udp_port_;
1248     network_settings.max_port = max_udp_port_;
1249   } else if (!allow_nat_traversal_) {
1250     // For legacy reasons we have to restrict the port range to a set of default
1251     // values when nat traversal is disabled, even if the port range was not
1252     // set in policy.
1253     network_settings.min_port = NetworkSettings::kDefaultMinPort;
1254     network_settings.max_port = NetworkSettings::kDefaultMaxPort;
1255   }
1256
1257   host_.reset(new ChromotingHost(
1258       signal_strategy_.get(),
1259       desktop_environment_factory_.get(),
1260       CreateHostSessionManager(signal_strategy_.get(), network_settings,
1261                                context_->url_request_context_getter()),
1262       context_->audio_task_runner(),
1263       context_->input_task_runner(),
1264       context_->video_capture_task_runner(),
1265       context_->video_encode_task_runner(),
1266       context_->network_task_runner(),
1267       context_->ui_task_runner()));
1268
1269   if (enable_vp9_) {
1270     scoped_ptr<protocol::CandidateSessionConfig> config =
1271         host_->protocol_config()->Clone();
1272     config->EnableVideoCodec(protocol::ChannelConfig::CODEC_VP9);
1273     host_->set_protocol_config(config.Pass());
1274   }
1275
1276   if (frame_recorder_buffer_size_ > 0) {
1277     scoped_ptr<VideoFrameRecorderHostExtension> frame_recorder_extension(
1278         new VideoFrameRecorderHostExtension());
1279     frame_recorder_extension->SetMaxContentBytes(frame_recorder_buffer_size_);
1280     host_->AddExtension(frame_recorder_extension.PassAs<HostExtension>());
1281   }
1282
1283   // TODO(simonmorris): Get the maximum session duration from a policy.
1284 #if defined(OS_LINUX)
1285   host_->SetMaximumSessionDuration(base::TimeDelta::FromHours(20));
1286 #endif
1287
1288   heartbeat_sender_.reset(new HeartbeatSender(
1289       this, host_id_, signal_strategy_.get(), key_pair_,
1290       directory_bot_jid_));
1291
1292   host_status_sender_.reset(new HostStatusSender(
1293       host_id_, signal_strategy_.get(), key_pair_, directory_bot_jid_));
1294
1295   host_change_notification_listener_.reset(new HostChangeNotificationListener(
1296       this, host_id_, signal_strategy_.get(), directory_bot_jid_));
1297
1298   host_status_logger_.reset(
1299       new HostStatusLogger(host_->AsWeakPtr(), ServerLogEntry::ME2ME,
1300                            signal_strategy_.get(), directory_bot_jid_));
1301
1302   // Set up reporting the host status notifications.
1303 #if defined(REMOTING_MULTI_PROCESS)
1304   host_event_logger_.reset(
1305       new IpcHostEventLogger(host_->AsWeakPtr(), daemon_channel_.get()));
1306 #else  // !defined(REMOTING_MULTI_PROCESS)
1307   host_event_logger_ =
1308       HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName);
1309 #endif  // !defined(REMOTING_MULTI_PROCESS)
1310
1311   host_->SetEnableCurtaining(curtain_required_);
1312   host_->Start(host_owner_);
1313
1314   CreateAuthenticatorFactory();
1315 }
1316
1317 void HostProcess::OnAuthFailed() {
1318   ShutdownHost(kInvalidOauthCredentialsExitCode);
1319 }
1320
1321 void HostProcess::RestartHost() {
1322   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1323   DCHECK_EQ(state_, HOST_STARTED);
1324
1325   state_ = HOST_STOPPING_TO_RESTART;
1326   ShutdownOnNetworkThread();
1327 }
1328
1329 void HostProcess::ShutdownHost(HostExitCodes exit_code) {
1330   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1331
1332   *exit_code_out_ = exit_code;
1333
1334   switch (state_) {
1335     case HOST_INITIALIZING:
1336       state_ = HOST_STOPPING;
1337       ShutdownOnNetworkThread();
1338       break;
1339
1340     case HOST_STARTED:
1341       state_ = HOST_STOPPING;
1342       host_status_sender_->SendOfflineStatus(exit_code);
1343       ScheduleHostShutdown();
1344       break;
1345
1346     case HOST_STOPPING_TO_RESTART:
1347       state_ = HOST_STOPPING;
1348       break;
1349
1350     case HOST_STOPPING:
1351     case HOST_STOPPED:
1352       // Host is already stopped or being stopped. No action is required.
1353       break;
1354   }
1355 }
1356
1357 // TODO(weitaosu): shut down the host once we get an ACK for the offline status
1358 //                  XMPP message.
1359 void HostProcess::ScheduleHostShutdown() {
1360   // Delay the shutdown by 2 second to allow SendOfflineStatus to complete.
1361   context_->network_task_runner()->PostDelayedTask(
1362       FROM_HERE,
1363       base::Bind(&HostProcess::ShutdownOnNetworkThread, base::Unretained(this)),
1364       base::TimeDelta::FromSeconds(2));
1365 }
1366
1367 void HostProcess::ShutdownOnNetworkThread() {
1368   DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1369
1370   host_.reset();
1371   host_event_logger_.reset();
1372   host_status_logger_.reset();
1373   heartbeat_sender_.reset();
1374   host_status_sender_.reset();
1375   host_change_notification_listener_.reset();
1376   signaling_connector_.reset();
1377   oauth_token_getter_.reset();
1378   signal_strategy_.reset();
1379   network_change_notifier_.reset();
1380
1381   if (state_ == HOST_STOPPING_TO_RESTART) {
1382     StartHost();
1383   } else if (state_ == HOST_STOPPING) {
1384     state_ = HOST_STOPPED;
1385
1386     if (policy_watcher_.get()) {
1387       base::WaitableEvent done_event(true, false);
1388       policy_watcher_->StopWatching(&done_event);
1389       done_event.Wait();
1390       policy_watcher_.reset();
1391     }
1392
1393     config_watcher_.reset();
1394
1395     // Complete the rest of shutdown on the main thread.
1396     context_->ui_task_runner()->PostTask(
1397         FROM_HERE,
1398         base::Bind(&HostProcess::ShutdownOnUiThread, this));
1399   } else {
1400     // This method is only called in STOPPING_TO_RESTART and STOPPING states.
1401     NOTREACHED();
1402   }
1403 }
1404
1405 void HostProcess::OnCrash(const std::string& function_name,
1406                           const std::string& file_name,
1407                           const int& line_number) {
1408   char message[1024];
1409   base::snprintf(message, sizeof(message),
1410                  "Requested by %s at %s, line %d.",
1411                  function_name.c_str(), file_name.c_str(), line_number);
1412   base::debug::Alias(message);
1413
1414   // The daemon requested us to crash the process.
1415   CHECK(false) << message;
1416 }
1417
1418 int HostProcessMain() {
1419 #if defined(OS_LINUX)
1420   // Required for any calls into GTK functions, such as the Disconnect and
1421   // Continue windows, though these should not be used for the Me2Me case
1422   // (crbug.com/104377).
1423   gtk_init(NULL, NULL);
1424 #endif
1425
1426   // Enable support for SSL server sockets, which must be done while still
1427   // single-threaded.
1428   net::EnableSSLServerSockets();
1429
1430   // Ensures runtime specific CPU features are initialized.
1431   media::InitializeCPUSpecificMediaFeatures();
1432
1433   // Create the main message loop and start helper threads.
1434   base::MessageLoopForUI message_loop;
1435   scoped_ptr<ChromotingHostContext> context =
1436       ChromotingHostContext::Create(new AutoThreadTaskRunner(
1437           message_loop.message_loop_proxy(), base::MessageLoop::QuitClosure()));
1438   if (!context)
1439     return kInitializationFailed;
1440
1441   // Create & start the HostProcess using these threads.
1442   // TODO(wez): The HostProcess holds a reference to itself until Shutdown().
1443   // Remove this hack as part of the multi-process refactoring.
1444   int exit_code = kSuccessExitCode;
1445   new HostProcess(context.Pass(), &exit_code);
1446
1447   // Run the main (also UI) message loop until the host no longer needs it.
1448   message_loop.Run();
1449
1450   return exit_code;
1451 }
1452
1453 }  // namespace remoting