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