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

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

Issue 10829467: [Chromoting] Introducing refcount-based life time management of the message loops in the service (d… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR feedback. Created 8 years, 3 months 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
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 10 matching lines...) Expand all
21 #include "base/synchronization/waitable_event.h" 21 #include "base/synchronization/waitable_event.h"
22 #include "base/threading/thread.h" 22 #include "base/threading/thread.h"
23 #include "base/utf_string_conversions.h" 23 #include "base/utf_string_conversions.h"
24 #include "base/win/windows_version.h" 24 #include "base/win/windows_version.h"
25 #include "build/build_config.h" 25 #include "build/build_config.h"
26 #include "crypto/nss_util.h" 26 #include "crypto/nss_util.h"
27 #include "ipc/ipc_channel.h" 27 #include "ipc/ipc_channel.h"
28 #include "ipc/ipc_channel_proxy.h" 28 #include "ipc/ipc_channel_proxy.h"
29 #include "net/base/network_change_notifier.h" 29 #include "net/base/network_change_notifier.h"
30 #include "net/socket/ssl_server_socket.h" 30 #include "net/socket/ssl_server_socket.h"
31 #include "remoting/base/auto_thread_task_runner.h"
31 #include "remoting/base/breakpad.h" 32 #include "remoting/base/breakpad.h"
32 #include "remoting/base/constants.h" 33 #include "remoting/base/constants.h"
33 #include "remoting/host/branding.h" 34 #include "remoting/host/branding.h"
34 #include "remoting/host/chromoting_host.h" 35 #include "remoting/host/chromoting_host.h"
35 #include "remoting/host/chromoting_host_context.h" 36 #include "remoting/host/chromoting_host_context.h"
36 #include "remoting/host/composite_host_config.h" 37 #include "remoting/host/composite_host_config.h"
37 #include "remoting/host/constants.h" 38 #include "remoting/host/constants.h"
38 #include "remoting/host/desktop_environment.h" 39 #include "remoting/host/desktop_environment.h"
39 #include "remoting/host/event_executor.h" 40 #include "remoting/host/event_executor.h"
40 #include "remoting/host/heartbeat_sender.h" 41 #include "remoting/host/heartbeat_sender.h"
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 const int kMaxPortNumber = 12409; 91 const int kMaxPortNumber = 12409;
91 92
92 const char kUnofficialOAuth2ClientId[] = 93 const char kUnofficialOAuth2ClientId[] =
93 "440925447803-2pi3v45bff6tp1rde2f7q6lgbor3o5uj.apps.googleusercontent.com"; 94 "440925447803-2pi3v45bff6tp1rde2f7q6lgbor3o5uj.apps.googleusercontent.com";
94 const char kUnofficialOAuth2ClientSecret[] = "W2ieEsG-R1gIA4MMurGrgMc_"; 95 const char kUnofficialOAuth2ClientSecret[] = "W2ieEsG-R1gIA4MMurGrgMc_";
95 96
96 const char kOfficialOAuth2ClientId[] = 97 const char kOfficialOAuth2ClientId[] =
97 "440925447803-avn2sj1kc099s0r7v62je5s339mu0am1.apps.googleusercontent.com"; 98 "440925447803-avn2sj1kc099s0r7v62je5s339mu0am1.apps.googleusercontent.com";
98 const char kOfficialOAuth2ClientSecret[] = "Bgur6DFiOMM1h8x-AQpuTQlK"; 99 const char kOfficialOAuth2ClientSecret[] = "Bgur6DFiOMM1h8x-AQpuTQlK";
99 100
101 void QuitMessageLoop(MessageLoop* message_loop) {
102 message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
103 }
104
100 } // namespace 105 } // namespace
101 106
102 namespace remoting { 107 namespace remoting {
103 108
104 class HostProcess 109 class HostProcess
105 : public HeartbeatSender::Listener, 110 : public HeartbeatSender::Listener,
106 public IPC::Listener { 111 public IPC::Listener {
107 public: 112 public:
108 HostProcess() 113 HostProcess(scoped_ptr<ChromotingHostContext> context)
109 : message_loop_(MessageLoop::TYPE_UI), 114 : context_(context.Pass()),
110 #ifdef OFFICIAL_BUILD 115 #ifdef OFFICIAL_BUILD
111 oauth_use_official_client_id_(true), 116 oauth_use_official_client_id_(true),
112 #else 117 #else
113 oauth_use_official_client_id_(false), 118 oauth_use_official_client_id_(false),
114 #endif 119 #endif
115 allow_nat_traversal_(true), 120 allow_nat_traversal_(true),
116 restarting_(false), 121 restarting_(false),
117 shutting_down_(false), 122 shutting_down_(false),
118 exit_code_(kSuccessExitCode) 123 exit_code_(kSuccessExitCode)
119 #if defined(OS_MACOSX) 124 #if defined(OS_MACOSX)
120 , curtain_(base::Bind(&HostProcess::OnDisconnectRequested, 125 , curtain_(base::Bind(&HostProcess::OnDisconnectRequested,
121 base::Unretained(this)), 126 base::Unretained(this)),
122 base::Bind(&HostProcess::OnDisconnectRequested, 127 base::Bind(&HostProcess::OnDisconnectRequested,
123 base::Unretained(this))) 128 base::Unretained(this)))
124 #endif 129 #endif
125 { 130 {
126 context_.reset(
127 new ChromotingHostContext(message_loop_.message_loop_proxy()));
128 context_->Start();
129 network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); 131 network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
130 config_updated_timer_.reset(new base::DelayTimer<HostProcess>( 132 config_updated_timer_.reset(new base::DelayTimer<HostProcess>(
131 FROM_HERE, base::TimeDelta::FromSeconds(2), this, 133 FROM_HERE, base::TimeDelta::FromSeconds(2), this,
132 &HostProcess::ConfigUpdatedDelayed)); 134 &HostProcess::ConfigUpdatedDelayed));
133 } 135 }
134 136
135 bool InitWithCommandLine(const CommandLine* cmd_line) { 137 bool InitWithCommandLine(const CommandLine* cmd_line) {
136 // Connect to the daemon process. 138 // Connect to the daemon process.
137 std::string channel_name = 139 std::string channel_name =
138 cmd_line->GetSwitchValueASCII(kDaemonIpcSwitchName); 140 cmd_line->GetSwitchValueASCII(kDaemonIpcSwitchName);
(...skipping 18 matching lines...) Expand all
157 host_config_path_ = default_config_dir.Append(kDefaultHostConfigFile); 159 host_config_path_ = default_config_dir.Append(kDefaultHostConfigFile);
158 if (cmd_line->HasSwitch(kHostConfigSwitchName)) { 160 if (cmd_line->HasSwitch(kHostConfigSwitchName)) {
159 host_config_path_ = cmd_line->GetSwitchValuePath(kHostConfigSwitchName); 161 host_config_path_ = cmd_line->GetSwitchValuePath(kHostConfigSwitchName);
160 } 162 }
161 config_.AddConfigPath(host_config_path_); 163 config_.AddConfigPath(host_config_path_);
162 164
163 return true; 165 return true;
164 } 166 }
165 167
166 void ConfigUpdated() { 168 void ConfigUpdated() {
167 DCHECK(message_loop_.message_loop_proxy()->BelongsToCurrentThread()); 169 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
168 170
169 // Call ConfigUpdatedDelayed after a short delay, so that this object won't 171 // Call ConfigUpdatedDelayed after a short delay, so that this object won't
170 // try to read the updated configuration file before it has been 172 // try to read the updated configuration file before it has been
171 // completely written. 173 // completely written.
172 // If the writer moves the new configuration file into place atomically, 174 // If the writer moves the new configuration file into place atomically,
173 // this delay may not be necessary. 175 // this delay may not be necessary.
174 config_updated_timer_->Reset(); 176 config_updated_timer_->Reset();
175 } 177 }
176 178
177 void ConfigUpdatedDelayed() { 179 void ConfigUpdatedDelayed() {
178 DCHECK(message_loop_.message_loop_proxy()->BelongsToCurrentThread()); 180 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
179 181
180 if (LoadConfig()) { 182 if (LoadConfig()) {
181 // PostTask to create new authenticator factory in case PIN has changed. 183 // PostTask to create new authenticator factory in case PIN has changed.
182 context_->network_task_runner()->PostTask( 184 context_->network_task_runner()->PostTask(
183 FROM_HERE, 185 FROM_HERE,
184 base::Bind(&HostProcess::CreateAuthenticatorFactory, 186 base::Bind(&HostProcess::CreateAuthenticatorFactory,
185 base::Unretained(this))); 187 base::Unretained(this)));
186 } else { 188 } else {
187 LOG(ERROR) << "Invalid configuration."; 189 LOG(ERROR) << "Invalid configuration.";
188 } 190 }
(...skipping 24 matching lines...) Expand all
213 }; 215 };
214 #endif // defined(OS_WIN) 216 #endif // defined(OS_WIN)
215 217
216 void ListenForConfigChanges() { 218 void ListenForConfigChanges() {
217 #if defined(OS_POSIX) 219 #if defined(OS_POSIX)
218 remoting::RegisterHupSignalHandler( 220 remoting::RegisterHupSignalHandler(
219 base::Bind(&HostProcess::ConfigUpdatedDelayed, base::Unretained(this))); 221 base::Bind(&HostProcess::ConfigUpdatedDelayed, base::Unretained(this)));
220 #elif defined(OS_WIN) 222 #elif defined(OS_WIN)
221 scoped_refptr<base::files::FilePathWatcher::Delegate> delegate( 223 scoped_refptr<base::files::FilePathWatcher::Delegate> delegate(
222 new ConfigChangedDelegate( 224 new ConfigChangedDelegate(
223 message_loop_.message_loop_proxy(), 225 context_->ui_task_runner(),
224 base::Bind(&HostProcess::ConfigUpdated, base::Unretained(this)))); 226 base::Bind(&HostProcess::ConfigUpdated, base::Unretained(this))));
225 config_watcher_.reset(new base::files::FilePathWatcher()); 227 config_watcher_.reset(new base::files::FilePathWatcher());
226 if (!config_watcher_->Watch(host_config_path_, delegate)) { 228 if (!config_watcher_->Watch(host_config_path_, delegate)) {
227 LOG(ERROR) << "Couldn't watch file " << host_config_path_.value(); 229 LOG(ERROR) << "Couldn't watch file " << host_config_path_.value();
228 } 230 }
229 #endif // defined (OS_WIN) 231 #endif // defined (OS_WIN)
230 } 232 }
231 233
232 void CreateAuthenticatorFactory() { 234 void CreateAuthenticatorFactory() {
233 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 235 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
234 scoped_ptr<protocol::AuthenticatorFactory> factory( 236 scoped_ptr<protocol::AuthenticatorFactory> factory(
235 new protocol::Me2MeHostAuthenticatorFactory( 237 new protocol::Me2MeHostAuthenticatorFactory(
236 key_pair_.GenerateCertificate(), 238 key_pair_.GenerateCertificate(),
237 *key_pair_.private_key(), host_secret_hash_)); 239 *key_pair_.private_key(), host_secret_hash_));
238 host_->SetAuthenticatorFactory(factory.Pass()); 240 host_->SetAuthenticatorFactory(factory.Pass());
239 } 241 }
240 242
241 // IPC::Listener implementation. 243 // IPC::Listener implementation.
242 virtual bool OnMessageReceived(const IPC::Message& message) { 244 virtual bool OnMessageReceived(const IPC::Message& message) {
243 return false; 245 return false;
244 } 246 }
245 247
246 int Run() { 248 void StartHostProcess() {
247 if (!LoadConfig()) { 249 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
248 return kInvalidHostConfigurationExitCode; 250
251 if (!InitWithCommandLine(CommandLine::ForCurrentProcess()) ||
252 !LoadConfig()) {
253 context_->network_task_runner()->PostTask(
254 FROM_HERE,
255 base::Bind(&HostProcess::Shutdown, base::Unretained(this),
256 kInvalidHostConfigurationExitCode));
257 return;
249 } 258 }
250 259
251 #if defined(OS_MACOSX) || defined(OS_WIN) 260 #if defined(OS_MACOSX) || defined(OS_WIN)
252 host_user_interface_.reset(new HostUserInterface(context_.get())); 261 host_user_interface_.reset(new HostUserInterface(context_.get()));
253 #endif 262 #endif
254 263
255 StartWatchingPolicy(); 264 StartWatchingPolicy();
256 265
257 #if defined(OS_MACOSX) || defined(OS_WIN) 266 #if defined(OS_MACOSX) || defined(OS_WIN)
258 context_->file_task_runner()->PostTask( 267 context_->file_task_runner()->PostTask(
259 FROM_HERE, 268 FROM_HERE,
260 base::Bind(&HostProcess::ListenForConfigChanges, 269 base::Bind(&HostProcess::ListenForConfigChanges,
261 base::Unretained(this))); 270 base::Unretained(this)));
262 #endif 271 #endif
263 message_loop_.Run(); 272 }
273
274 int get_exit_code() const { return exit_code_; }
275
276 private:
277 void ShutdownHostProcess() {
278 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
279
280 daemon_channel_.reset();
264 281
265 #if defined(OS_MACOSX) || defined(OS_WIN) 282 #if defined(OS_MACOSX) || defined(OS_WIN)
266 host_user_interface_.reset(); 283 host_user_interface_.reset();
267 #endif 284 #endif
268 285
269 daemon_channel_.reset(); 286 if (policy_watcher_.get()) {
270 base::WaitableEvent done_event(true, false); 287 base::WaitableEvent done_event(true, false);
271 policy_watcher_->StopWatching(&done_event); 288 policy_watcher_->StopWatching(&done_event);
272 done_event.Wait(); 289 done_event.Wait();
273 policy_watcher_.reset(); 290 policy_watcher_.reset();
291 }
274 292
275 return exit_code_; 293 context_.reset();
276 } 294 }
277 295
278 // Overridden from HeartbeatSender::Listener 296 // Overridden from HeartbeatSender::Listener
279 virtual void OnUnknownHostIdError() OVERRIDE { 297 virtual void OnUnknownHostIdError() OVERRIDE {
280 LOG(ERROR) << "Host ID not found."; 298 LOG(ERROR) << "Host ID not found.";
281 Shutdown(kInvalidHostIdExitCode); 299 Shutdown(kInvalidHostIdExitCode);
282 } 300 }
283 301
284 private:
285 void StartWatchingPolicy() { 302 void StartWatchingPolicy() {
286 policy_watcher_.reset( 303 policy_watcher_.reset(
287 policy_hack::PolicyWatcher::Create(context_->file_task_runner())); 304 policy_hack::PolicyWatcher::Create(context_->file_task_runner()));
288 policy_watcher_->StartWatching( 305 policy_watcher_->StartWatching(
289 base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this))); 306 base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)));
290 } 307 }
291 308
292 // Read host config, returning true if successful. 309 // Read host config, returning true if successful.
293 bool LoadConfig() { 310 bool LoadConfig() {
294 DCHECK(message_loop_.message_loop_proxy()->BelongsToCurrentThread()); 311 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
295 312
296 // TODO(sergeyu): There is a potential race condition: this function is 313 // TODO(sergeyu): There is a potential race condition: this function is
297 // called on the main thread while the class members it mutates are used on 314 // called on the main thread while the class members it mutates are used on
298 // the network thread. Fix it. http://crbug.com/140986 . 315 // the network thread. Fix it. http://crbug.com/140986 .
299 316
300 if (!config_.Read()) { 317 if (!config_.Read()) {
301 LOG(ERROR) << "Failed to read config file."; 318 LOG(ERROR) << "Failed to read config file.";
302 return false; 319 return false;
303 } 320 }
304 321
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 CreateAuthenticatorFactory(); 547 CreateAuthenticatorFactory();
531 } 548 }
532 549
533 void OnAuthFailed() { 550 void OnAuthFailed() {
534 Shutdown(kInvalidOauthCredentialsExitCode); 551 Shutdown(kInvalidOauthCredentialsExitCode);
535 } 552 }
536 553
537 // Invoked when the user uses the Disconnect windows to terminate 554 // Invoked when the user uses the Disconnect windows to terminate
538 // the sessions. 555 // the sessions.
539 void OnDisconnectRequested() { 556 void OnDisconnectRequested() {
540 DCHECK(message_loop_.message_loop_proxy()->BelongsToCurrentThread()); 557 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
541 558
542 host_->DisconnectAllClients(); 559 host_->DisconnectAllClients();
543 } 560 }
544 561
545 void RestartHost() { 562 void RestartHost() {
546 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 563 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
547 564
548 if (restarting_ || shutting_down_) 565 if (restarting_ || shutting_down_)
549 return; 566 return;
550 567
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 } else { 599 } else {
583 OnShutdownFinished(); 600 OnShutdownFinished();
584 } 601 }
585 } 602 }
586 603
587 void OnShutdownFinished() { 604 void OnShutdownFinished() {
588 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 605 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
589 606
590 // Destroy networking objects while we are on the network thread. 607 // Destroy networking objects while we are on the network thread.
591 host_ = NULL; 608 host_ = NULL;
609 desktop_environment_.reset();
592 host_event_logger_.reset(); 610 host_event_logger_.reset();
593 log_to_server_.reset(); 611 log_to_server_.reset();
594 heartbeat_sender_.reset(); 612 heartbeat_sender_.reset();
595 signaling_connector_.reset(); 613 signaling_connector_.reset();
596 signal_strategy_.reset(); 614 signal_strategy_.reset();
597 615
598 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure()); 616 // Complete the rest of shutdown on the main thread.
617 context_->ui_task_runner()->PostTask(
618 FROM_HERE,
619 base::Bind(&HostProcess::ShutdownHostProcess,
620 base::Unretained(this)));
599 } 621 }
600 622
601 MessageLoop message_loop_;
602 scoped_ptr<ChromotingHostContext> context_; 623 scoped_ptr<ChromotingHostContext> context_;
603 scoped_ptr<IPC::ChannelProxy> daemon_channel_; 624 scoped_ptr<IPC::ChannelProxy> daemon_channel_;
604 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_; 625 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
605 626
606 FilePath host_config_path_; 627 FilePath host_config_path_;
607 CompositeHostConfig config_; 628 CompositeHostConfig config_;
608 629
609 std::string host_id_; 630 std::string host_id_;
610 HostKeyPair key_pair_; 631 HostKeyPair key_pair_;
611 protocol::SharedSecretHash host_secret_hash_; 632 protocol::SharedSecretHash host_secret_hash_;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 InitLogging(debug_log.value().c_str(), 686 InitLogging(debug_log.value().c_str(),
666 #if defined(OS_WIN) 687 #if defined(OS_WIN)
667 logging::LOG_ONLY_TO_FILE, 688 logging::LOG_ONLY_TO_FILE,
668 #else 689 #else
669 logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, 690 logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
670 #endif 691 #endif
671 logging::DONT_LOCK_LOG_FILE, 692 logging::DONT_LOCK_LOG_FILE,
672 logging::APPEND_TO_OLD_LOG_FILE, 693 logging::APPEND_TO_OLD_LOG_FILE,
673 logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS); 694 logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
674 695
675 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
676
677 #if defined(TOOLKIT_GTK) 696 #if defined(TOOLKIT_GTK)
678 // Required for any calls into GTK functions, such as the Disconnect and 697 // Required for any calls into GTK functions, such as the Disconnect and
679 // Continue windows, though these should not be used for the Me2Me case 698 // Continue windows, though these should not be used for the Me2Me case
680 // (crbug.com/104377). 699 // (crbug.com/104377).
700 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
681 gfx::GtkInitFromCommandLine(*cmd_line); 701 gfx::GtkInitFromCommandLine(*cmd_line);
682 #endif // TOOLKIT_GTK 702 #endif // TOOLKIT_GTK
683 703
684 // Enable support for SSL server sockets, which must be done while still 704 // Enable support for SSL server sockets, which must be done while still
685 // single-threaded. 705 // single-threaded.
686 net::EnableSSLServerSockets(); 706 net::EnableSSLServerSockets();
687 707
688 #if defined(OS_LINUX) 708 #if defined(OS_LINUX)
689 remoting::VideoFrameCapturer::EnableXDamage(true); 709 remoting::VideoFrameCapturer::EnableXDamage(true);
690 #endif 710 #endif
691 711
692 remoting::HostProcess me2me_host; 712 // Create the main message loop and start helper threads.
693 if (!me2me_host.InitWithCommandLine(cmd_line)) { 713 MessageLoop message_loop(MessageLoop::TYPE_UI);
694 return remoting::kInvalidHostConfigurationExitCode; 714 base::Closure quit_message_loop = base::Bind(&QuitMessageLoop,
695 } 715 base::Unretained(&message_loop));
Sergey Ulanov 2012/08/31 01:25:18 Do you really need Unretained here given that Quit
alexeypa (please no reviews) 2012/08/31 19:57:36 Done.
716 scoped_ptr<remoting::ChromotingHostContext> context(
717 new remoting::ChromotingHostContext(
718 new remoting::AutoThreadTaskRunner(message_loop.message_loop_proxy(),
719 quit_message_loop)));
720 if (!context->Start())
721 return remoting::kHostInitializationFailed;
696 722
697 return me2me_host.Run(); 723 // Create the host process instance and run the rest of the initialization on
724 // the main message loop.
725 remoting::HostProcess me2me_host(context.Pass());
726 message_loop.PostTask(
727 FROM_HERE,
728 base::Bind(&remoting::HostProcess::StartHostProcess,
729 base::Unretained(&me2me_host)));
730 message_loop.Run();
731 return me2me_host.get_exit_code();
698 } 732 }
699 733
700 #if defined(OS_WIN) 734 #if defined(OS_WIN)
701 HMODULE g_hModule = NULL; 735 HMODULE g_hModule = NULL;
702 736
703 int CALLBACK WinMain(HINSTANCE instance, 737 int CALLBACK WinMain(HINSTANCE instance,
704 HINSTANCE previous_instance, 738 HINSTANCE previous_instance,
705 LPSTR command_line, 739 LPSTR command_line,
706 int show_command) { 740 int show_command) {
707 #ifdef OFFICIAL_BUILD 741 #ifdef OFFICIAL_BUILD
(...skipping 23 matching lines...) Expand all
731 user32.GetFunctionPointer("SetProcessDPIAware")); 765 user32.GetFunctionPointer("SetProcessDPIAware"));
732 set_process_dpi_aware(); 766 set_process_dpi_aware();
733 } 767 }
734 768
735 // CommandLine::Init() ignores the passed |argc| and |argv| on Windows getting 769 // CommandLine::Init() ignores the passed |argc| and |argv| on Windows getting
736 // the command line from GetCommandLineW(), so we can safely pass NULL here. 770 // the command line from GetCommandLineW(), so we can safely pass NULL here.
737 return main(0, NULL); 771 return main(0, NULL);
738 } 772 }
739 773
740 #endif // defined(OS_WIN) 774 #endif // defined(OS_WIN)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698