Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: remoting/host/remoting_me2me_host.cc

Issue 11416093: Add HostState enum to track host process status. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This file implements a standalone host process for Me2Me. 5 // This file implements a standalone host process for Me2Me.
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/at_exit.h" 9 #include "base/at_exit.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 public: 152 public:
153 explicit HostProcess(scoped_ptr<ChromotingHostContext> context); 153 explicit HostProcess(scoped_ptr<ChromotingHostContext> context);
154 154
155 // Initializes IPC control channel and config file path from |cmd_line|. 155 // Initializes IPC control channel and config file path from |cmd_line|.
156 bool InitWithCommandLine(const CommandLine* cmd_line); 156 bool InitWithCommandLine(const CommandLine* cmd_line);
157 157
158 // ConfigFileWatcher::Delegate interface. 158 // ConfigFileWatcher::Delegate interface.
159 virtual void OnConfigUpdated(const std::string& serialized_config) OVERRIDE; 159 virtual void OnConfigUpdated(const std::string& serialized_config) OVERRIDE;
160 virtual void OnConfigWatcherError() OVERRIDE; 160 virtual void OnConfigWatcherError() OVERRIDE;
161 161
162 void StartWatchingConfigChanges();
163 void CreateAuthenticatorFactory(); 162 void CreateAuthenticatorFactory();
164 163
165 // IPC::Listener implementation. 164 // IPC::Listener implementation.
166 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 165 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
167 virtual void OnChannelError() OVERRIDE; 166 virtual void OnChannelError() OVERRIDE;
168 167
169 // HeartbeatSender::Listener overrides. 168 // HeartbeatSender::Listener overrides.
170 virtual void OnUnknownHostIdError() OVERRIDE; 169 virtual void OnUnknownHostIdError() OVERRIDE;
171 170
172 void StartHostProcess(); 171 void StartHostProcess();
173 172
174 int get_exit_code() const; 173 int get_exit_code() const;
175 174
176 private: 175 private:
176 enum HostState {
177 // Host process has just been started. Waiting for config and policies to be
178 // read from the disk.
179 HOST_INITIALIZING,
180
181 // Host is started and running.
182 HOST_STARTED,
183
184 // Host is being stopped and will need to be started again.
185 HOST_STOPPING_TO_RESTART,
186
187 // Host is being stopped.
188 HOST_STOPPING,
189
190 // Host has been stopped.
191 HOST_STOPPED,
192
193 // Allowed state transitions:
194 // INITIALIZING->STARTED
195 // INITIALIZING->STOPPED
196 // STARTED->STOPPING_TO_RESTART
197 // STARTED->STOPPING
198 // STOPPING_TO_RESTART->STARTED
199 // STOPPING_TO_RESTART->STOPPING
200 // STOPPING->STOPPED
201 // STOPPED->STARTED
202 //
203 // |host_| must be NULL in INITIALIZING and STOPPED states and not-NULL in
204 // all other states.
205 };
206
207 void StartOnNetworkThread();
208
177 #if defined(OS_POSIX) 209 #if defined(OS_POSIX)
178 // Registers a SIGTERM handler on the network thread, to shutdown the host.
179 void ListenForShutdownSignal();
180
181 // Callback passed to RegisterSignalHandler() to handle SIGTERM events. 210 // Callback passed to RegisterSignalHandler() to handle SIGTERM events.
182 void SigTermHandler(int signal_number); 211 void SigTermHandler(int signal_number);
183 #endif 212 #endif
184 213
185 // Asks the daemon to inject Secure Attention Sequence to the console. 214 // Asks the daemon to inject Secure Attention Sequence to the console.
186 void SendSasToConsole(); 215 void SendSasToConsole();
187 216
188 void ShutdownHostProcess(); 217 void ShutdownHostProcess();
189 218
190 // Applies the host config, returning true if successful. 219 // Applies the host config, returning true if successful.
191 bool ApplyConfig(scoped_ptr<JsonHostConfig> config); 220 bool ApplyConfig(scoped_ptr<JsonHostConfig> config);
192 221
193 void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies); 222 void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies);
194 bool OnHostDomainPolicyUpdate(const std::string& host_domain); 223 bool OnHostDomainPolicyUpdate(const std::string& host_domain);
195 bool OnUsernamePolicyUpdate(bool username_match_required); 224 bool OnUsernamePolicyUpdate(bool username_match_required);
196 bool OnNatPolicyUpdate(bool nat_traversal_enabled); 225 bool OnNatPolicyUpdate(bool nat_traversal_enabled);
197 bool OnCurtainPolicyUpdate(bool curtain_required); 226 bool OnCurtainPolicyUpdate(bool curtain_required);
198 bool OnHostTalkGadgetPrefixPolicyUpdate(const std::string& talkgadget_prefix); 227 bool OnHostTalkGadgetPrefixPolicyUpdate(const std::string& talkgadget_prefix);
199 228
200 void StartHostStatusService();
201
202 void StartHost(); 229 void StartHost();
203 230
204 void OnAuthFailed(); 231 void OnAuthFailed();
205 232
206 void RejectAuthenticatingClient(); 233 void RejectAuthenticatingClient();
207 234
208 // Invoked when the user uses the Disconnect windows to terminate 235 // Invoked when the user uses the Disconnect windows to terminate
209 // the sessions, or when the local session is activated in curtain mode. 236 // the sessions, or when the local session is activated in curtain mode.
210 void OnDisconnectRequested(); 237 void OnDisconnectRequested();
211 238
212 void RestartHost(); 239 void RestartHost();
213 240
214 void RestartOnHostShutdown(); 241 // Stops the host and shuts down the process with the specified |exit_code|.
215 242 void ShutdownHost(int exit_code);
216 void Shutdown(int exit_code);
217 243
218 void OnShutdownFinished(); 244 void OnShutdownFinished();
219 245
220 void ResetHost();
221
222 // Crashes the process in response to a daemon's request. The daemon passes 246 // Crashes the process in response to a daemon's request. The daemon passes
223 // the location of the code that detected the fatal error resulted in this 247 // the location of the code that detected the fatal error resulted in this
224 // request. 248 // request.
225 void OnCrash(const std::string& function_name, 249 void OnCrash(const std::string& function_name,
226 const std::string& file_name, 250 const std::string& file_name,
227 const int& line_number); 251 const int& line_number);
228 252
229 scoped_ptr<ChromotingHostContext> context_; 253 scoped_ptr<ChromotingHostContext> context_;
230 scoped_ptr<IPC::ChannelProxy> daemon_channel_; 254 scoped_ptr<IPC::ChannelProxy> daemon_channel_;
231 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_; 255 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
232 256
233 FilePath host_config_path_; 257 FilePath host_config_path_;
234 scoped_ptr<ConfigFileWatcher> config_watcher_;
235 258
236 // Accessed on the network thread. 259 // Accessed on the network thread.
237 260
alexeypa (please no reviews) 2012/11/21 23:53:48 nit: remove the empty line?
Sergey Ulanov 2012/11/27 01:04:38 Done.
261 HostState state_;
262
263 scoped_ptr<ConfigFileWatcher> config_watcher_;
238 scoped_ptr<HostStatusService> status_service_; 264 scoped_ptr<HostStatusService> status_service_;
239 265
240 std::string host_id_; 266 std::string host_id_;
241 protocol::SharedSecretHash host_secret_hash_; 267 protocol::SharedSecretHash host_secret_hash_;
242 HostKeyPair key_pair_; 268 HostKeyPair key_pair_;
243 std::string oauth_refresh_token_; 269 std::string oauth_refresh_token_;
244 std::string serialized_config_; 270 std::string serialized_config_;
245 std::string xmpp_login_; 271 std::string xmpp_login_;
246 std::string xmpp_auth_token_; 272 std::string xmpp_auth_token_;
247 std::string xmpp_auth_service_; 273 std::string xmpp_auth_service_;
248 274
249 scoped_ptr<policy_hack::PolicyWatcher> policy_watcher_; 275 scoped_ptr<policy_hack::PolicyWatcher> policy_watcher_;
250 bool allow_nat_traversal_; 276 bool allow_nat_traversal_;
251 std::string talkgadget_prefix_; 277 std::string talkgadget_prefix_;
252 278
253 scoped_ptr<CurtainMode> curtain_; 279 scoped_ptr<CurtainMode> curtain_;
254 scoped_ptr<CurtainingHostObserver> curtaining_host_observer_; 280 scoped_ptr<CurtainingHostObserver> curtaining_host_observer_;
255 bool curtain_required_; 281 bool curtain_required_;
256 282
257 bool restarting_;
258 bool shutting_down_;
259
260 scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_; 283 scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
261 scoped_ptr<DesktopResizer> desktop_resizer_; 284 scoped_ptr<DesktopResizer> desktop_resizer_;
262 scoped_ptr<ResizingHostObserver> resizing_host_observer_; 285 scoped_ptr<ResizingHostObserver> resizing_host_observer_;
263 scoped_ptr<XmppSignalStrategy> signal_strategy_; 286 scoped_ptr<XmppSignalStrategy> signal_strategy_;
264 scoped_ptr<SignalingConnector> signaling_connector_; 287 scoped_ptr<SignalingConnector> signaling_connector_;
265 scoped_ptr<HeartbeatSender> heartbeat_sender_; 288 scoped_ptr<HeartbeatSender> heartbeat_sender_;
266 scoped_ptr<LogToServer> log_to_server_; 289 scoped_ptr<LogToServer> log_to_server_;
267 scoped_ptr<HostEventLogger> host_event_logger_; 290 scoped_ptr<HostEventLogger> host_event_logger_;
268 291
269 scoped_ptr<HostUserInterface> host_user_interface_; 292 scoped_ptr<HostUserInterface> host_user_interface_;
270 293
271 scoped_refptr<ChromotingHost> host_; 294 scoped_refptr<ChromotingHost> host_;
272 295
273 #if defined(REMOTING_MULTI_PROCESS) 296 #if defined(REMOTING_MULTI_PROCESS)
274 DesktopSessionConnector* desktop_session_connector_; 297 DesktopSessionConnector* desktop_session_connector_;
275 #endif // defined(REMOTING_MULTI_PROCESS) 298 #endif // defined(REMOTING_MULTI_PROCESS)
276 299
277 int exit_code_; 300 int exit_code_;
278 }; 301 };
279 302
280 HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context) 303 HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context)
281 : context_(context.Pass()), 304 : context_(context.Pass()),
305 state_(HOST_INITIALIZING),
282 allow_nat_traversal_(true), 306 allow_nat_traversal_(true),
283 curtain_required_(false), 307 curtain_required_(false),
284 restarting_(false),
285 shutting_down_(false),
286 desktop_resizer_(DesktopResizer::Create()), 308 desktop_resizer_(DesktopResizer::Create()),
287 #if defined(REMOTING_MULTI_PROCESS) 309 #if defined(REMOTING_MULTI_PROCESS)
288 desktop_session_connector_(NULL), 310 desktop_session_connector_(NULL),
289 #endif // defined(REMOTING_MULTI_PROCESS) 311 #endif // defined(REMOTING_MULTI_PROCESS)
290 exit_code_(kSuccessExitCode) { 312 exit_code_(kSuccessExitCode) {
291 network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); 313 network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
292 curtain_ = CurtainMode::Create( 314 curtain_ = CurtainMode::Create(
293 base::Bind(&HostProcess::OnDisconnectRequested, 315 base::Bind(&HostProcess::OnDisconnectRequested,
294 base::Unretained(this)), 316 base::Unretained(this)),
295 base::Bind(&HostProcess::RejectAuthenticatingClient, 317 base::Bind(&HostProcess::RejectAuthenticatingClient,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 // Filter out duplicates. 378 // Filter out duplicates.
357 if (serialized_config_ == serialized_config) 379 if (serialized_config_ == serialized_config)
358 return; 380 return;
359 381
360 LOG(INFO) << "Processing new host configuration."; 382 LOG(INFO) << "Processing new host configuration.";
361 383
362 serialized_config_ = serialized_config; 384 serialized_config_ = serialized_config;
363 scoped_ptr<JsonHostConfig> config(new JsonHostConfig(FilePath())); 385 scoped_ptr<JsonHostConfig> config(new JsonHostConfig(FilePath()));
364 if (!config->SetSerializedData(serialized_config)) { 386 if (!config->SetSerializedData(serialized_config)) {
365 LOG(ERROR) << "Invalid configuration."; 387 LOG(ERROR) << "Invalid configuration.";
366 Shutdown(kInvalidHostConfigurationExitCode); 388 ShutdownHost(kInvalidHostConfigurationExitCode);
367 return; 389 return;
368 } 390 }
369 391
370 if (!ApplyConfig(config.Pass())) { 392 if (!ApplyConfig(config.Pass())) {
371 LOG(ERROR) << "Failed to apply the configuration."; 393 LOG(ERROR) << "Failed to apply the configuration.";
372 Shutdown(kInvalidHostConfigurationExitCode); 394 ShutdownHost(kInvalidHostConfigurationExitCode);
373 return; 395 return;
374 } 396 }
375 397
376 // Start watching the policy (and eventually start the host) if this is 398 if (state_ == HOST_INITIALIZING) {
377 // the first configuration update. Otherwise, create new authenticator 399 // TODO(sergeyu): Currently OnPolicyUpdate() assumes that host config is
378 // factory in case PIN has changed. 400 // already loaded so PolicyWatcher has to be started here. Separate policy
379 if (!policy_watcher_) { 401 // loading from policy verifications and move |policy_watcher_|
402 // initialization to StartOnNetworkThread().
380 policy_watcher_.reset( 403 policy_watcher_.reset(
381 policy_hack::PolicyWatcher::Create(context_->file_task_runner())); 404 policy_hack::PolicyWatcher::Create(context_->file_task_runner()));
382 policy_watcher_->StartWatching( 405 policy_watcher_->StartWatching(
383 base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this))); 406 base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)));
384 } else { 407 } else if (state_ == HOST_STARTED) {
408 // TODO(sergeyu): Here we assume that PIN is the only part of the config
409 // that may change while the service is running. Change ApplyConfig() to
410 // detect other changes in the config and restart host if necessary here.
385 CreateAuthenticatorFactory(); 411 CreateAuthenticatorFactory();
386 } 412 }
387 } 413 }
388 414
389 void HostProcess::OnConfigWatcherError() { 415 void HostProcess::OnConfigWatcherError() {
390 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread()); 416 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
391 417 ShutdownHost(kInvalidHostConfigurationExitCode);
392 context_->network_task_runner()->PostTask(
393 FROM_HERE,
394 base::Bind(&HostProcess::Shutdown, base::Unretained(this),
395 kInvalidHostConfigurationExitCode));
396 } 418 }
397 419
398 void HostProcess::StartWatchingConfigChanges() { 420 void HostProcess::StartOnNetworkThread() {
421 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
422
423 if (CommandLine::ForCurrentProcess()->HasSwitch(
424 kEnableStatusServiceSwitchName)) {
425 status_service_.reset(new HostStatusService());
426 }
427
399 #if !defined(REMOTING_MULTI_PROCESS) 428 #if !defined(REMOTING_MULTI_PROCESS)
400 // Start watching the host configuration file. 429 // Start watching the host configuration file.
401 config_watcher_.reset(new ConfigFileWatcher(context_->ui_task_runner(), 430 config_watcher_.reset(new ConfigFileWatcher(context_->network_task_runner(),
402 context_->file_task_runner(), 431 context_->file_task_runner(),
403 this)); 432 this));
404 config_watcher_->Watch(host_config_path_); 433 config_watcher_->Watch(host_config_path_);
405 #endif // !defined(REMOTING_MULTI_PROCESS) 434 #endif // !defined(REMOTING_MULTI_PROCESS)
435
436 #if defined(OS_POSIX)
437 remoting::RegisterSignalHandler(
438 SIGTERM,
439 base::Bind(&HostProcess::SigTermHandler, base::Unretained(this)));
440 #endif // defined(OS_POSIX)
406 } 441 }
407 442
408 #if defined(OS_POSIX) 443 #if defined(OS_POSIX)
409 void HostProcess::ListenForShutdownSignal() {
410 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
411
412 remoting::RegisterSignalHandler(
413 SIGTERM,
414 base::Bind(&HostProcess::SigTermHandler, base::Unretained(this)));
415 }
416
417 void HostProcess::SigTermHandler(int signal_number) { 444 void HostProcess::SigTermHandler(int signal_number) {
418 DCHECK(signal_number == SIGTERM); 445 DCHECK(signal_number == SIGTERM);
419 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 446 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
420 LOG(INFO) << "Caught SIGTERM: Shutting down..."; 447 LOG(INFO) << "Caught SIGTERM: Shutting down...";
421 Shutdown(kSuccessExitCode); 448 ShutdownHost(kSuccessExitCode);
422 } 449 }
423 #endif // OS_POSIX 450 #endif // OS_POSIX
424 451
425 void HostProcess::CreateAuthenticatorFactory() { 452 void HostProcess::CreateAuthenticatorFactory() {
426 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 453 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
427 454
428 if (!host_ || shutting_down_) 455 if (state_ != HOST_STARTED)
429 return; 456 return;
430 457
431 std::string local_certificate = key_pair_.GenerateCertificate(); 458 std::string local_certificate = key_pair_.GenerateCertificate();
432 if (local_certificate.empty()) { 459 if (local_certificate.empty()) {
433 LOG(ERROR) << "Failed to generate host certificate."; 460 LOG(ERROR) << "Failed to generate host certificate.";
434 Shutdown(kInitializationFailed); 461 ShutdownHost(kInitializationFailed);
435 return; 462 return;
436 } 463 }
437 464
438 scoped_ptr<protocol::AuthenticatorFactory> factory( 465 scoped_ptr<protocol::AuthenticatorFactory> factory(
439 new protocol::Me2MeHostAuthenticatorFactory( 466 new protocol::Me2MeHostAuthenticatorFactory(
440 local_certificate, *key_pair_.private_key(), host_secret_hash_)); 467 local_certificate, *key_pair_.private_key(), host_secret_hash_));
441 #if defined(OS_LINUX) 468 #if defined(OS_LINUX)
442 // On Linux, perform a PAM authorization step after authentication. 469 // On Linux, perform a PAM authorization step after authentication.
443 factory.reset(new PamAuthorizationFactory(factory.Pass())); 470 factory.reset(new PamAuthorizationFactory(factory.Pass()));
444 #endif 471 #endif
(...skipping 25 matching lines...) Expand all
470 return false; 497 return false;
471 #endif // !defined(REMOTING_MULTI_PROCESS) 498 #endif // !defined(REMOTING_MULTI_PROCESS)
472 } 499 }
473 500
474 void HostProcess::OnChannelError() { 501 void HostProcess::OnChannelError() {
475 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread()); 502 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
476 503
477 // Shutdown the host if the daemon disconnected the channel. 504 // Shutdown the host if the daemon disconnected the channel.
478 context_->network_task_runner()->PostTask( 505 context_->network_task_runner()->PostTask(
479 FROM_HERE, 506 FROM_HERE,
480 base::Bind(&HostProcess::Shutdown, base::Unretained(this), 507 base::Bind(&HostProcess::ShutdownHost, base::Unretained(this),
481 kSuccessExitCode)); 508 kSuccessExitCode));
482 } 509 }
483 510
484 void HostProcess::StartHostProcess() { 511 void HostProcess::StartHostProcess() {
485 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread()); 512 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
486 513
487 if (!InitWithCommandLine(CommandLine::ForCurrentProcess())) { 514 if (!InitWithCommandLine(CommandLine::ForCurrentProcess())) {
488 OnConfigWatcherError(); 515 OnConfigWatcherError();
489 return; 516 return;
490 } 517 }
491 518
492 #if defined(OS_LINUX) 519 #if defined(OS_LINUX)
493 // TODO(sergeyu): Pass configuration parameters to the Linux-specific version 520 // TODO(sergeyu): Pass configuration parameters to the Linux-specific version
494 // of DesktopEnvironmentFactory when we have it. 521 // of DesktopEnvironmentFactory when we have it.
495 remoting::VideoFrameCapturer::EnableXDamage(true); 522 remoting::VideoFrameCapturer::EnableXDamage(true);
496 523
497 // If an audio pipe is specific on the command-line then initialize 524 // If an audio pipe is specific on the command-line then initialize
498 // AudioCapturerLinux to capture from it. 525 // AudioCapturerLinux to capture from it.
499 FilePath audio_pipe_name = CommandLine::ForCurrentProcess()-> 526 FilePath audio_pipe_name = CommandLine::ForCurrentProcess()->
500 GetSwitchValuePath(kAudioPipeSwitchName); 527 GetSwitchValuePath(kAudioPipeSwitchName);
501 if (!audio_pipe_name.empty()) { 528 if (!audio_pipe_name.empty()) {
502 remoting::AudioCapturerLinux::InitializePipeReader( 529 remoting::AudioCapturerLinux::InitializePipeReader(
503 context_->audio_task_runner(), audio_pipe_name); 530 context_->audio_task_runner(), audio_pipe_name);
504 } 531 }
505 #endif // defined(OS_LINUX) 532 #endif // defined(OS_LINUX)
506 533
507 if (CommandLine::ForCurrentProcess()->HasSwitch(
508 kEnableStatusServiceSwitchName)) {
509 context_->network_task_runner()->PostTask(
510 FROM_HERE,
511 base::Bind(&HostProcess::StartHostStatusService,
512 base::Unretained(this)));
513 }
514
515 // Create a desktop environment factory appropriate to the build type & 534 // Create a desktop environment factory appropriate to the build type &
516 // platform. 535 // platform.
517 #if defined(OS_WIN) 536 #if defined(OS_WIN)
518 537
519 #if defined(REMOTING_MULTI_PROCESS) 538 #if defined(REMOTING_MULTI_PROCESS)
520 IpcDesktopEnvironmentFactory* desktop_environment_factory = 539 IpcDesktopEnvironmentFactory* desktop_environment_factory =
521 new IpcDesktopEnvironmentFactory( 540 new IpcDesktopEnvironmentFactory(
522 daemon_channel_.get(), 541 daemon_channel_.get(),
523 context_->input_task_runner(), 542 context_->input_task_runner(),
524 context_->network_task_runner(), 543 context_->network_task_runner(),
525 context_->ui_task_runner()); 544 context_->ui_task_runner());
526 desktop_session_connector_ = desktop_environment_factory; 545 desktop_session_connector_ = desktop_environment_factory;
527 #else // !defined(REMOTING_MULTI_PROCESS) 546 #else // !defined(REMOTING_MULTI_PROCESS)
528 DesktopEnvironmentFactory* desktop_environment_factory = 547 DesktopEnvironmentFactory* desktop_environment_factory =
529 new SessionDesktopEnvironmentFactory( 548 new SessionDesktopEnvironmentFactory(
530 context_->input_task_runner(), context_->ui_task_runner(), 549 context_->input_task_runner(), context_->ui_task_runner(),
531 base::Bind(&HostProcess::SendSasToConsole, base::Unretained(this))); 550 base::Bind(&HostProcess::SendSasToConsole, base::Unretained(this)));
532 #endif // !defined(REMOTING_MULTI_PROCESS) 551 #endif // !defined(REMOTING_MULTI_PROCESS)
533 552
534 #else // !defined(OS_WIN) 553 #else // !defined(OS_WIN)
535 DesktopEnvironmentFactory* desktop_environment_factory = 554 DesktopEnvironmentFactory* desktop_environment_factory =
536 new DesktopEnvironmentFactory( 555 new DesktopEnvironmentFactory(
537 context_->input_task_runner(), context_->ui_task_runner()); 556 context_->input_task_runner(), context_->ui_task_runner());
538 #endif // !defined(OS_WIN) 557 #endif // !defined(OS_WIN)
539 558
540 desktop_environment_factory_.reset(desktop_environment_factory); 559 desktop_environment_factory_.reset(desktop_environment_factory);
541 560
542 #if defined(OS_POSIX)
543 context_->network_task_runner()->PostTask(
544 FROM_HERE,
545 base::Bind(&HostProcess::ListenForShutdownSignal,
546 base::Unretained(this)));
547 #endif // OS_POSIX
548
549 // The host UI should be created on the UI thread. 561 // The host UI should be created on the UI thread.
550 bool want_user_interface = true; 562 bool want_user_interface = true;
551 #if defined(OS_LINUX) 563 #if defined(OS_LINUX)
552 want_user_interface = false; 564 want_user_interface = false;
553 #elif defined(OS_MACOSX) 565 #elif defined(OS_MACOSX)
554 // Don't try to display any UI on top of the system's login screen as this 566 // Don't try to display any UI on top of the system's login screen as this
555 // is rejected by the Window Server on OS X 10.7.4, and prevents the 567 // is rejected by the Window Server on OS X 10.7.4, and prevents the
556 // capturer from working (http://crbug.com/140984). 568 // capturer from working (http://crbug.com/140984).
557 569
558 // TODO(lambroslambrou): Use a better technique of detecting whether we're 570 // TODO(lambroslambrou): Use a better technique of detecting whether we're
559 // running in the LoginWindow context, and refactor this into a separate 571 // running in the LoginWindow context, and refactor this into a separate
560 // function to be used here and in CurtainMode::ActivateCurtain(). 572 // function to be used here and in CurtainMode::ActivateCurtain().
561 want_user_interface = getuid() != 0; 573 want_user_interface = getuid() != 0;
562 #endif // OS_MACOSX 574 #endif // OS_MACOSX
563 575
564 if (want_user_interface) { 576 if (want_user_interface) {
565 host_user_interface_.reset( 577 host_user_interface_.reset(
566 new HostUserInterface(context_->network_task_runner(), 578 new HostUserInterface(context_->network_task_runner(),
567 context_->ui_task_runner())); 579 context_->ui_task_runner()));
568 host_user_interface_->Init(); 580 host_user_interface_->Init();
569 } 581 }
570 582
571 StartWatchingConfigChanges(); 583 context_->network_task_runner()->PostTask(
584 FROM_HERE,
585 base::Bind(&HostProcess::StartOnNetworkThread,
586 base::Unretained(this)));
572 } 587 }
573 588
574 int HostProcess::get_exit_code() const { 589 int HostProcess::get_exit_code() const {
575 return exit_code_; 590 return exit_code_;
576 } 591 }
577 592
578 void HostProcess::SendSasToConsole() { 593 void HostProcess::SendSasToConsole() {
579 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread()); 594 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
580 595
581 if (daemon_channel_) 596 if (daemon_channel_)
582 daemon_channel_->Send(new ChromotingNetworkDaemonMsg_SendSasToConsole()); 597 daemon_channel_->Send(new ChromotingNetworkDaemonMsg_SendSasToConsole());
583 } 598 }
584 599
585 void HostProcess::ShutdownHostProcess() { 600 void HostProcess::ShutdownHostProcess() {
586 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread()); 601 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
587 602
588 // Tear down resources that use ChromotingHostContext threads. 603 // Tear down resources that use ChromotingHostContext threads.
589 config_watcher_.reset();
590 daemon_channel_.reset(); 604 daemon_channel_.reset();
591 desktop_environment_factory_.reset(); 605 desktop_environment_factory_.reset();
592 host_user_interface_.reset(); 606 host_user_interface_.reset();
593 607
594 context_.reset(); 608 context_.reset();
595 } 609 }
596 610
597 // Overridden from HeartbeatSender::Listener 611 // Overridden from HeartbeatSender::Listener
598 void HostProcess::OnUnknownHostIdError() { 612 void HostProcess::OnUnknownHostIdError() {
599 LOG(ERROR) << "Host ID not found."; 613 LOG(ERROR) << "Host ID not found.";
600 Shutdown(kInvalidHostIdExitCode); 614 ShutdownHost(kInvalidHostIdExitCode);
601 } 615 }
602 616
603 // Applies the host config, returning true if successful. 617 // Applies the host config, returning true if successful.
604 bool HostProcess::ApplyConfig(scoped_ptr<JsonHostConfig> config) { 618 bool HostProcess::ApplyConfig(scoped_ptr<JsonHostConfig> config) {
605 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 619 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
606 620
607 if (!config->GetString(kHostIdConfigPath, &host_id_)) { 621 if (!config->GetString(kHostIdConfigPath, &host_id_)) {
608 LOG(ERROR) << "host_id is not defined in the config."; 622 LOG(ERROR) << "host_id is not defined in the config.";
609 return false; 623 return false;
610 } 624 }
(...skipping 30 matching lines...) Expand all
641 // For the me2me host, we default to ClientLogin token for chromiumsync 655 // For the me2me host, we default to ClientLogin token for chromiumsync
642 // because earlier versions of the host had no HTTP stack with which to 656 // because earlier versions of the host had no HTTP stack with which to
643 // request an OAuth2 access token. 657 // request an OAuth2 access token.
644 xmpp_auth_service_ = kChromotingTokenDefaultServiceName; 658 xmpp_auth_service_ = kChromotingTokenDefaultServiceName;
645 } 659 }
646 return true; 660 return true;
647 } 661 }
648 662
649 void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) { 663 void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
650 // TODO(rmsousa): Consolidate all On*PolicyUpdate methods into this one. 664 // TODO(rmsousa): Consolidate all On*PolicyUpdate methods into this one.
665 // TODO(sergeyu): Currently polices are verified only when they are loaded.
666 // Separate policy loading from policy verifications - this will allow to
667 // check policies again later, e.g. when host config changes.
668
651 if (!context_->network_task_runner()->BelongsToCurrentThread()) { 669 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
652 context_->network_task_runner()->PostTask(FROM_HERE, base::Bind( 670 context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
653 &HostProcess::OnPolicyUpdate, base::Unretained(this), 671 &HostProcess::OnPolicyUpdate, base::Unretained(this),
654 base::Passed(&policies))); 672 base::Passed(&policies)));
655 return; 673 return;
656 } 674 }
657 675
658 bool restart_required = false; 676 bool restart_required = false;
659 bool bool_value; 677 bool bool_value;
660 std::string string_value; 678 std::string string_value;
(...skipping 11 matching lines...) Expand all
672 restart_required |= OnNatPolicyUpdate(bool_value); 690 restart_required |= OnNatPolicyUpdate(bool_value);
673 } 691 }
674 if (policies->GetString( 692 if (policies->GetString(
675 policy_hack::PolicyWatcher::kHostTalkGadgetPrefixPolicyName, 693 policy_hack::PolicyWatcher::kHostTalkGadgetPrefixPolicyName,
676 &string_value)) { 694 &string_value)) {
677 restart_required |= OnHostTalkGadgetPrefixPolicyUpdate(string_value); 695 restart_required |= OnHostTalkGadgetPrefixPolicyUpdate(string_value);
678 } 696 }
679 if (policies->GetBoolean( 697 if (policies->GetBoolean(
680 policy_hack::PolicyWatcher::kHostRequireCurtainPolicyName, 698 policy_hack::PolicyWatcher::kHostRequireCurtainPolicyName,
681 &bool_value)) { 699 &bool_value)) {
682 restart_required |= OnCurtainPolicyUpdate(bool_value); 700 restart_required |= OnCurtainPolicyUpdate(bool_value);
683 } 701 }
684 if (!host_) { 702
703 if (state_ == HOST_INITIALIZING) {
685 StartHost(); 704 StartHost();
686 } else if (restart_required) { 705 } else if (state_ == HOST_STARTED && restart_required) {
687 RestartHost(); 706 RestartHost();
688 } 707 }
689 } 708 }
690 709
691 bool HostProcess::OnHostDomainPolicyUpdate(const std::string& host_domain) { 710 bool HostProcess::OnHostDomainPolicyUpdate(const std::string& host_domain) {
692 // Returns true if the host has to be restarted after this policy update. 711 // Returns true if the host has to be restarted after this policy update.
693 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 712 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
694 713
695 LOG(INFO) << "Policy sets host domain: " << host_domain; 714 LOG(INFO) << "Policy sets host domain: " << host_domain;
696 715
697 if (!host_domain.empty() && 716 if (!host_domain.empty() &&
698 !EndsWith(xmpp_login_, std::string("@") + host_domain, false)) { 717 !EndsWith(xmpp_login_, std::string("@") + host_domain, false)) {
699 Shutdown(kInvalidHostDomainExitCode); 718 ShutdownHost(kInvalidHostDomainExitCode);
700 } 719 }
701 return false; 720 return false;
702 } 721 }
703 722
704 bool HostProcess::OnUsernamePolicyUpdate(bool host_username_match_required) { 723 bool HostProcess::OnUsernamePolicyUpdate(bool host_username_match_required) {
705 // Returns false: never restart the host after this policy update. 724 // Returns false: never restart the host after this policy update.
706 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 725 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
707 726
708 if (host_username_match_required) { 727 if (host_username_match_required) {
709 LOG(INFO) << "Policy requires host username match."; 728 LOG(INFO) << "Policy requires host username match.";
710 if (!CanGetUsername() || 729 if (!CanGetUsername() ||
711 !StartsWithASCII(xmpp_login_, GetUsername() + std::string("@"), 730 !StartsWithASCII(xmpp_login_, GetUsername() + std::string("@"),
712 false)) { 731 false)) {
713 Shutdown(kUsernameMismatchExitCode); 732 ShutdownHost(kUsernameMismatchExitCode);
714 } 733 }
715 } else { 734 } else {
716 LOG(INFO) << "Policy does not require host username match."; 735 LOG(INFO) << "Policy does not require host username match.";
717 } 736 }
718 737
719 return false; 738 return false;
720 } 739 }
721 740
722 bool HostProcess::OnNatPolicyUpdate(bool nat_traversal_enabled) { 741 bool HostProcess::OnNatPolicyUpdate(bool nat_traversal_enabled) {
723 // Returns true if the host has to be restarted after this policy update. 742 // Returns true if the host has to be restarted after this policy update.
(...skipping 19 matching lines...) Expand all
743 // When curtain mode is in effect on Mac, the host process runs in the 762 // When curtain mode is in effect on Mac, the host process runs in the
744 // user's switched-out session, but launchd will also run an instance at 763 // user's switched-out session, but launchd will also run an instance at
745 // the console login screen. Even if no user is currently logged-on, we 764 // the console login screen. Even if no user is currently logged-on, we
746 // can't support remote-access to the login screen because the current host 765 // can't support remote-access to the login screen because the current host
747 // process model disconnects the client during login, which would leave 766 // process model disconnects the client during login, which would leave
748 // the logged in session un-curtained on the console until they reconnect. 767 // the logged in session un-curtained on the console until they reconnect.
749 // 768 //
750 // TODO(jamiewalch): Fix this once we have implemented the multi-process 769 // TODO(jamiewalch): Fix this once we have implemented the multi-process
751 // daemon architecture (crbug.com/134894) 770 // daemon architecture (crbug.com/134894)
752 if (getuid() == 0) { 771 if (getuid() == 0) {
753 Shutdown(kLoginScreenNotSupportedExitCode); 772 ShutdownHost(kLoginScreenNotSupportedExitCode);
754 return false; 773 return false;
755 } 774 }
756 } 775 }
757 #endif 776 #endif
758 777
759 if (curtain_required_ != curtain_required) { 778 if (curtain_required_ != curtain_required) {
760 if (curtain_required) 779 if (curtain_required)
761 LOG(ERROR) << "Policy requires curtain-mode."; 780 LOG(ERROR) << "Policy requires curtain-mode.";
762 else 781 else
763 LOG(ERROR) << "Policy does not require curtain-mode."; 782 LOG(ERROR) << "Policy does not require curtain-mode.";
(...skipping 11 matching lines...) Expand all
775 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 794 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
776 795
777 if (talkgadget_prefix != talkgadget_prefix_) { 796 if (talkgadget_prefix != talkgadget_prefix_) {
778 LOG(INFO) << "Policy sets talkgadget prefix: " << talkgadget_prefix; 797 LOG(INFO) << "Policy sets talkgadget prefix: " << talkgadget_prefix;
779 talkgadget_prefix_ = talkgadget_prefix; 798 talkgadget_prefix_ = talkgadget_prefix;
780 return true; 799 return true;
781 } 800 }
782 return false; 801 return false;
783 } 802 }
784 803
785 void HostProcess::StartHostStatusService() {
786 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
787 status_service_.reset(new HostStatusService());
788 }
789
790 void HostProcess::StartHost() { 804 void HostProcess::StartHost() {
791 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 805 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
792 DCHECK(!host_); 806 DCHECK(!host_);
793 DCHECK(!signal_strategy_.get()); 807 DCHECK(!signal_strategy_.get());
794 808 DCHECK(state_ == HOST_INITIALIZING || state_ == HOST_STOPPING_TO_RESTART ||
795 if (shutting_down_) 809 state_ == HOST_STOPPED) << state_;
796 return; 810 state_ = HOST_STARTED;
797 811
798 signal_strategy_.reset( 812 signal_strategy_.reset(
799 new XmppSignalStrategy(context_->url_request_context_getter(), 813 new XmppSignalStrategy(context_->url_request_context_getter(),
800 xmpp_login_, xmpp_auth_token_, 814 xmpp_login_, xmpp_auth_token_,
801 xmpp_auth_service_)); 815 xmpp_auth_service_));
802 816
803 scoped_ptr<DnsBlackholeChecker> dns_blackhole_checker( 817 scoped_ptr<DnsBlackholeChecker> dns_blackhole_checker(
804 new DnsBlackholeChecker(context_->url_request_context_getter(), 818 new DnsBlackholeChecker(context_->url_request_context_getter(),
805 talkgadget_prefix_)); 819 talkgadget_prefix_));
806 820
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 884
871 if (status_service_) 885 if (status_service_)
872 status_service_->SetHostIsUp(host_id_); 886 status_service_->SetHostIsUp(host_id_);
873 887
874 host_->Start(xmpp_login_); 888 host_->Start(xmpp_login_);
875 889
876 CreateAuthenticatorFactory(); 890 CreateAuthenticatorFactory();
877 } 891 }
878 892
879 void HostProcess::OnAuthFailed() { 893 void HostProcess::OnAuthFailed() {
880 Shutdown(kInvalidOauthCredentialsExitCode); 894 ShutdownHost(kInvalidOauthCredentialsExitCode);
881 } 895 }
882 896
883 void HostProcess::RejectAuthenticatingClient() { 897 void HostProcess::RejectAuthenticatingClient() {
884 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 898 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
885 DCHECK(host_); 899 DCHECK(host_);
886 host_->RejectAuthenticatingClient(); 900 host_->RejectAuthenticatingClient();
887 } 901 }
888 902
889 // Invoked when the user uses the Disconnect windows to terminate 903 // Invoked when the user uses the Disconnect windows to terminate
890 // the sessions, or when the local session is activated in curtain mode. 904 // the sessions, or when the local session is activated in curtain mode.
891 void HostProcess::OnDisconnectRequested() { 905 void HostProcess::OnDisconnectRequested() {
892 if (!context_->network_task_runner()->BelongsToCurrentThread()) { 906 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
893 context_->network_task_runner()->PostTask(FROM_HERE, base::Bind( 907 context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
894 &HostProcess::OnDisconnectRequested, base::Unretained(this))); 908 &HostProcess::OnDisconnectRequested, base::Unretained(this)));
895 return; 909 return;
896 } 910 }
897 if (host_) { 911 if (host_) {
898 host_->DisconnectAllClients(); 912 host_->DisconnectAllClients();
899 } 913 }
900 } 914 }
901 915
902 void HostProcess::RestartHost() { 916 void HostProcess::RestartHost() {
903 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 917 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
918 DCHECK_EQ(state_, HOST_STARTED);
904 919
905 if (restarting_ || shutting_down_) 920 state_ = HOST_STOPPING_TO_RESTART;
906 return;
907
908 restarting_ = true;
909 host_->Shutdown(base::Bind( 921 host_->Shutdown(base::Bind(
910 &HostProcess::RestartOnHostShutdown, base::Unretained(this))); 922 &HostProcess::OnShutdownFinished, base::Unretained(this)));
911 } 923 }
912 924
913 void HostProcess::RestartOnHostShutdown() { 925 void HostProcess::ShutdownHost(int exit_code) {
914 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 926 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
915 927
916 if (shutting_down_) 928 exit_code_ = exit_code;
917 return;
918 929
919 restarting_ = false; 930 switch (state_) {
920 host_ = NULL; 931 case HOST_INITIALIZING:
921 ResetHost(); 932 state_ = HOST_STOPPED;
933 OnShutdownFinished();
934 break;
922 935
923 StartHost(); 936 case HOST_STARTED:
924 } 937 if (status_service_)
938 status_service_->SetHostIsDown();
939 host_->Shutdown(base::Bind(
940 &HostProcess::OnShutdownFinished, base::Unretained(this)));
941 state_ = HOST_STOPPING;
942 break;
925 943
926 void HostProcess::Shutdown(int exit_code) { 944 case HOST_STOPPING_TO_RESTART:
927 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 945 state_ = HOST_STOPPING;
946 break;
928 947
929 if (shutting_down_) 948 case HOST_STOPPING:
930 return; 949 case HOST_STOPPED:
931 950 // Host is already stopped or being stopped. No action is required.
932 if (status_service_) 951 break;
933 status_service_->SetHostIsDown();
934
935 shutting_down_ = true;
936 exit_code_ = exit_code;
937 if (host_) {
938 host_->Shutdown(base::Bind(
939 &HostProcess::OnShutdownFinished, base::Unretained(this)));
940 } else {
941 OnShutdownFinished();
942 } 952 }
943 } 953 }
944 954
945 void HostProcess::OnShutdownFinished() { 955 void HostProcess::OnShutdownFinished() {
946 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 956 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
947 957
948 // Destroy networking objects while we are on the network thread.
949 host_ = NULL; 958 host_ = NULL;
950 ResetHost();
951
952 if (policy_watcher_.get()) {
953 base::WaitableEvent done_event(true, false);
954 policy_watcher_->StopWatching(&done_event);
955 done_event.Wait();
956 policy_watcher_.reset();
957 }
958
959 status_service_.reset();
960
961 // Complete the rest of shutdown on the main thread.
962 context_->ui_task_runner()->PostTask(
963 FROM_HERE,
964 base::Bind(&HostProcess::ShutdownHostProcess,
965 base::Unretained(this)));
966 }
967
968 void HostProcess::ResetHost() {
969 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
970
971 curtaining_host_observer_.reset(); 959 curtaining_host_observer_.reset();
972 host_event_logger_.reset(); 960 host_event_logger_.reset();
973 log_to_server_.reset(); 961 log_to_server_.reset();
974 heartbeat_sender_.reset(); 962 heartbeat_sender_.reset();
975 signaling_connector_.reset(); 963 signaling_connector_.reset();
976 signal_strategy_.reset(); 964 signal_strategy_.reset();
977 resizing_host_observer_.reset(); 965 resizing_host_observer_.reset();
966
967 if (state_ == HOST_STOPPING_TO_RESTART) {
968 StartHost();
969 } else if (state_ == HOST_STOPPING) {
970 state_ = HOST_STOPPED;
971
972 if (policy_watcher_.get()) {
973 base::WaitableEvent done_event(true, false);
974 policy_watcher_->StopWatching(&done_event);
975 done_event.Wait();
976 policy_watcher_.reset();
977 }
978
979 config_watcher_.reset();
980
alexeypa (please no reviews) 2012/11/21 23:53:48 nit: remove the empty line. Or two.
Sergey Ulanov 2012/11/27 01:04:38 Done.
981
982 status_service_.reset();
983
984 // Complete the rest of shutdown on the main thread.
985 context_->ui_task_runner()->PostTask(
986 FROM_HERE,
987 base::Bind(&HostProcess::ShutdownHostProcess,
988 base::Unretained(this)));
989 } else {
990 // This method is used as a callback for ChromotingHost::Shutdown() which is
991 // called only in STOPPING_TO_RESTART and STOPPING states.
992 NOTREACHED();
993 }
978 } 994 }
979 995
980 void HostProcess::OnCrash(const std::string& function_name, 996 void HostProcess::OnCrash(const std::string& function_name,
981 const std::string& file_name, 997 const std::string& file_name,
982 const int& line_number) { 998 const int& line_number) {
983 CHECK(false); 999 CHECK(false);
984 } 1000 }
985 1001
986 } // namespace remoting 1002 } // namespace remoting
987 1003
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 user32.GetFunctionPointer("SetProcessDPIAware")); 1084 user32.GetFunctionPointer("SetProcessDPIAware"));
1069 set_process_dpi_aware(); 1085 set_process_dpi_aware();
1070 } 1086 }
1071 1087
1072 // CommandLine::Init() ignores the passed |argc| and |argv| on Windows getting 1088 // CommandLine::Init() ignores the passed |argc| and |argv| on Windows getting
1073 // the command line from GetCommandLineW(), so we can safely pass NULL here. 1089 // the command line from GetCommandLineW(), so we can safely pass NULL here.
1074 return main(0, NULL); 1090 return main(0, NULL);
1075 } 1091 }
1076 1092
1077 #endif // defined(OS_WIN) 1093 #endif // defined(OS_WIN)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698