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