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