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