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

Side by Side Diff: net/proxy/proxy_config_service_linux.cc

Issue 10912132: Move ProxyConfigService construction onto the IO thread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Adjust comments Created 8 years, 2 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 #include "net/proxy/proxy_config_service_linux.h" 5 #include "net/proxy/proxy_config_service_linux.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #if defined(USE_GCONF) 9 #if defined(USE_GCONF)
10 #include <gconf/gconf-client.h> 10 #include <gconf/gconf-client.h>
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 // This setting getter uses gconf, as used in GNOME 2 and some GNOME 3 desktops. 200 // This setting getter uses gconf, as used in GNOME 2 and some GNOME 3 desktops.
201 class SettingGetterImplGConf : public ProxyConfigServiceLinux::SettingGetter { 201 class SettingGetterImplGConf : public ProxyConfigServiceLinux::SettingGetter {
202 public: 202 public:
203 SettingGetterImplGConf() 203 SettingGetterImplGConf()
204 : client_(NULL), system_proxy_id_(0), system_http_proxy_id_(0), 204 : client_(NULL), system_proxy_id_(0), system_http_proxy_id_(0),
205 notify_delegate_(NULL) { 205 notify_delegate_(NULL) {
206 } 206 }
207 207
208 virtual ~SettingGetterImplGConf() { 208 virtual ~SettingGetterImplGConf() {
209 // client_ should have been released before now, from 209 // client_ should have been released before now, from
210 // Delegate::OnDestroy(), while running on the UI thread. However 210 // Delegate::OnDestroy(), while running on the UI thread.
211 // on exiting the process, it may happen that Delegate::OnDestroy()
212 // task is left pending on the glib loop after the loop was quit,
213 // and pending tasks may then be deleted without being run.
214 if (client_) { 211 if (client_) {
215 // gconf client was not cleaned up. 212 // gconf client was not cleaned up.
216 if (task_runner_->BelongsToCurrentThread()) { 213 if (task_runner_->BelongsToCurrentThread()) {
217 // We are on the UI thread so we can clean it safely. This is 214 // We are on the UI thread so we can clean it safely. This is
218 // the case at least for ui_tests running under Valgrind in 215 // the case at least for ui_tests running under Valgrind in
219 // bug 16076. 216 // bug 16076.
220 VLOG(1) << "~SettingGetterImplGConf: releasing gconf client"; 217 VLOG(1) << "~SettingGetterImplGConf: releasing gconf client";
221 ShutDown(); 218 ShutDown();
222 } else { 219 } else {
223 // This is very bad! We are deleting the setting getter but we're not on 220 // This is very bad! We are deleting the setting getter but we're not on
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 // have the same lifetimes. (For instance, incognito sessions get their 275 // have the same lifetimes. (For instance, incognito sessions get their
279 // own, which is destroyed when the session ends.) 276 // own, which is destroyed when the session ends.)
280 gconf_client_notify_remove(client_, system_http_proxy_id_); 277 gconf_client_notify_remove(client_, system_http_proxy_id_);
281 gconf_client_notify_remove(client_, system_proxy_id_); 278 gconf_client_notify_remove(client_, system_proxy_id_);
282 gconf_client_remove_dir(client_, "/system/http_proxy", NULL); 279 gconf_client_remove_dir(client_, "/system/http_proxy", NULL);
283 gconf_client_remove_dir(client_, "/system/proxy", NULL); 280 gconf_client_remove_dir(client_, "/system/proxy", NULL);
284 g_object_unref(client_); 281 g_object_unref(client_);
285 client_ = NULL; 282 client_ = NULL;
286 task_runner_ = NULL; 283 task_runner_ = NULL;
287 } 284 }
285 debounce_timer_.reset();
288 } 286 }
289 287
290 virtual bool SetUpNotifications( 288 virtual bool SetUpNotifications(
291 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE { 289 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE {
292 DCHECK(client_); 290 DCHECK(client_);
293 DCHECK(task_runner_->BelongsToCurrentThread()); 291 DCHECK(task_runner_->BelongsToCurrentThread());
294 GError* error = NULL; 292 GError* error = NULL;
295 notify_delegate_ = delegate; 293 notify_delegate_ = delegate;
294 debounce_timer_.reset(new base::OneShotTimer<SettingGetterImplGConf>());
296 // We have to keep track of the IDs returned by gconf_client_notify_add() so 295 // We have to keep track of the IDs returned by gconf_client_notify_add() so
297 // that we can remove them in ShutDown(). (Otherwise, notifications will be 296 // that we can remove them in ShutDown(). (Otherwise, notifications will be
298 // delivered to this object after it is deleted, which is bad, m'kay?) 297 // delivered to this object after it is deleted, which is bad, m'kay?)
299 system_proxy_id_ = gconf_client_notify_add( 298 system_proxy_id_ = gconf_client_notify_add(
300 client_, "/system/proxy", 299 client_, "/system/proxy",
301 OnGConfChangeNotification, this, 300 OnGConfChangeNotification, this,
302 NULL, &error); 301 NULL, &error);
303 if (error == NULL) { 302 if (error == NULL) {
304 system_http_proxy_id_ = gconf_client_notify_add( 303 system_http_proxy_id_ = gconf_client_notify_add(
305 client_, "/system/http_proxy", 304 client_, "/system/http_proxy",
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 void OnDebouncedNotification() { 466 void OnDebouncedNotification() {
468 DCHECK(task_runner_->BelongsToCurrentThread()); 467 DCHECK(task_runner_->BelongsToCurrentThread());
469 CHECK(notify_delegate_); 468 CHECK(notify_delegate_);
470 // Forward to a method on the proxy config service delegate object. 469 // Forward to a method on the proxy config service delegate object.
471 notify_delegate_->OnCheckProxyConfigSettings(); 470 notify_delegate_->OnCheckProxyConfigSettings();
472 } 471 }
473 472
474 void OnChangeNotification() { 473 void OnChangeNotification() {
475 // We don't use Reset() because the timer may not yet be running. 474 // We don't use Reset() because the timer may not yet be running.
476 // (In that case Stop() is a no-op.) 475 // (In that case Stop() is a no-op.)
477 debounce_timer_.Stop(); 476 debounce_timer_->Stop();
478 debounce_timer_.Start(FROM_HERE, 477 debounce_timer_->Start(FROM_HERE,
479 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), 478 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds),
480 this, &SettingGetterImplGConf::OnDebouncedNotification); 479 this, &SettingGetterImplGConf::OnDebouncedNotification);
481 } 480 }
482 481
483 // gconf notification callback, dispatched on the default glib main loop. 482 // gconf notification callback, dispatched on the default glib main loop.
484 static void OnGConfChangeNotification(GConfClient* client, guint cnxn_id, 483 static void OnGConfChangeNotification(GConfClient* client, guint cnxn_id,
485 GConfEntry* entry, gpointer user_data) { 484 GConfEntry* entry, gpointer user_data) {
486 VLOG(1) << "gconf change notification for key " 485 VLOG(1) << "gconf change notification for key "
487 << gconf_entry_get_key(entry); 486 << gconf_entry_get_key(entry);
488 // We don't track which key has changed, just that something did change. 487 // We don't track which key has changed, just that something did change.
489 SettingGetterImplGConf* setting_getter = 488 SettingGetterImplGConf* setting_getter =
490 reinterpret_cast<SettingGetterImplGConf*>(user_data); 489 reinterpret_cast<SettingGetterImplGConf*>(user_data);
491 setting_getter->OnChangeNotification(); 490 setting_getter->OnChangeNotification();
492 } 491 }
493 492
494 GConfClient* client_; 493 GConfClient* client_;
495 // These ids are the values returned from gconf_client_notify_add(), which we 494 // These ids are the values returned from gconf_client_notify_add(), which we
496 // will need in order to later call gconf_client_notify_remove(). 495 // will need in order to later call gconf_client_notify_remove().
497 guint system_proxy_id_; 496 guint system_proxy_id_;
498 guint system_http_proxy_id_; 497 guint system_http_proxy_id_;
499 498
500 ProxyConfigServiceLinux::Delegate* notify_delegate_; 499 ProxyConfigServiceLinux::Delegate* notify_delegate_;
501 base::OneShotTimer<SettingGetterImplGConf> debounce_timer_; 500 scoped_ptr<base::OneShotTimer<SettingGetterImplGConf> > debounce_timer_;
502 501
503 // Task runner for the thread that we make gconf calls on. It should 502 // Task runner for the thread that we make gconf calls on. It should
504 // be the UI thread and all our methods should be called on this 503 // be the UI thread and all our methods should be called on this
505 // thread. Only for assertions. 504 // thread. Only for assertions.
506 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 505 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
507 506
508 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGConf); 507 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGConf);
509 }; 508 };
510 #endif // defined(USE_GCONF) 509 #endif // defined(USE_GCONF)
511 510
(...skipping 16 matching lines...) Expand all
528 client_(NULL), 527 client_(NULL),
529 http_client_(NULL), 528 http_client_(NULL),
530 https_client_(NULL), 529 https_client_(NULL),
531 ftp_client_(NULL), 530 ftp_client_(NULL),
532 socks_client_(NULL), 531 socks_client_(NULL),
533 notify_delegate_(NULL) { 532 notify_delegate_(NULL) {
534 } 533 }
535 534
536 virtual ~SettingGetterImplGSettings() { 535 virtual ~SettingGetterImplGSettings() {
537 // client_ should have been released before now, from 536 // client_ should have been released before now, from
538 // Delegate::OnDestroy(), while running on the UI thread. However 537 // Delegate::OnDestroy(), while running on the UI thread.
539 // on exiting the process, it may happen that
540 // Delegate::OnDestroy() task is left pending on the glib loop
541 // after the loop was quit, and pending tasks may then be deleted
542 // without being run.
543 if (client_) { 538 if (client_) {
544 // gconf client was not cleaned up. 539 // gconf client was not cleaned up.
545 if (task_runner_->BelongsToCurrentThread()) { 540 if (task_runner_->BelongsToCurrentThread()) {
546 // We are on the UI thread so we can clean it safely. This is 541 // We are on the UI thread so we can clean it safely. This is
547 // the case at least for ui_tests running under Valgrind in 542 // the case at least for ui_tests running under Valgrind in
548 // bug 16076. 543 // bug 16076.
549 VLOG(1) << "~SettingGetterImplGSettings: releasing gsettings client"; 544 VLOG(1) << "~SettingGetterImplGSettings: releasing gsettings client";
550 ShutDown(); 545 ShutDown();
551 } else { 546 } else {
552 LOG(WARNING) << "~SettingGetterImplGSettings: leaking gsettings client"; 547 LOG(WARNING) << "~SettingGetterImplGSettings: leaking gsettings client";
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 // This also disables gsettings notifications. 598 // This also disables gsettings notifications.
604 g_object_unref(socks_client_); 599 g_object_unref(socks_client_);
605 g_object_unref(ftp_client_); 600 g_object_unref(ftp_client_);
606 g_object_unref(https_client_); 601 g_object_unref(https_client_);
607 g_object_unref(http_client_); 602 g_object_unref(http_client_);
608 g_object_unref(client_); 603 g_object_unref(client_);
609 // We only need to null client_ because it's the only one that we check. 604 // We only need to null client_ because it's the only one that we check.
610 client_ = NULL; 605 client_ = NULL;
611 task_runner_ = NULL; 606 task_runner_ = NULL;
612 } 607 }
608 debounce_timer_.reset();
613 } 609 }
614 610
615 virtual bool SetUpNotifications( 611 virtual bool SetUpNotifications(
616 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE { 612 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE {
617 DCHECK(client_); 613 DCHECK(client_);
618 DCHECK(task_runner_->BelongsToCurrentThread()); 614 DCHECK(task_runner_->BelongsToCurrentThread());
619 notify_delegate_ = delegate; 615 notify_delegate_ = delegate;
616 debounce_timer_.reset(
617 new base::OneShotTimer<SettingGetterImplGSettings>());
620 // We could watch for the change-event signal instead of changed, but 618 // We could watch for the change-event signal instead of changed, but
621 // since we have to watch more than one object, we'd still have to 619 // since we have to watch more than one object, we'd still have to
622 // debounce change notifications. This is conceptually simpler. 620 // debounce change notifications. This is conceptually simpler.
623 g_signal_connect(G_OBJECT(client_), "changed", 621 g_signal_connect(G_OBJECT(client_), "changed",
624 G_CALLBACK(OnGSettingsChangeNotification), this); 622 G_CALLBACK(OnGSettingsChangeNotification), this);
625 g_signal_connect(G_OBJECT(http_client_), "changed", 623 g_signal_connect(G_OBJECT(http_client_), "changed",
626 G_CALLBACK(OnGSettingsChangeNotification), this); 624 G_CALLBACK(OnGSettingsChangeNotification), this);
627 g_signal_connect(G_OBJECT(https_client_), "changed", 625 g_signal_connect(G_OBJECT(https_client_), "changed",
628 G_CALLBACK(OnGSettingsChangeNotification), this); 626 G_CALLBACK(OnGSettingsChangeNotification), this);
629 g_signal_connect(G_OBJECT(ftp_client_), "changed", 627 g_signal_connect(G_OBJECT(ftp_client_), "changed",
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 void OnDebouncedNotification() { 780 void OnDebouncedNotification() {
783 DCHECK(task_runner_->BelongsToCurrentThread()); 781 DCHECK(task_runner_->BelongsToCurrentThread());
784 CHECK(notify_delegate_); 782 CHECK(notify_delegate_);
785 // Forward to a method on the proxy config service delegate object. 783 // Forward to a method on the proxy config service delegate object.
786 notify_delegate_->OnCheckProxyConfigSettings(); 784 notify_delegate_->OnCheckProxyConfigSettings();
787 } 785 }
788 786
789 void OnChangeNotification() { 787 void OnChangeNotification() {
790 // We don't use Reset() because the timer may not yet be running. 788 // We don't use Reset() because the timer may not yet be running.
791 // (In that case Stop() is a no-op.) 789 // (In that case Stop() is a no-op.)
792 debounce_timer_.Stop(); 790 debounce_timer_->Stop();
793 debounce_timer_.Start(FROM_HERE, 791 debounce_timer_->Start(FROM_HERE,
794 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), 792 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds),
795 this, &SettingGetterImplGSettings::OnDebouncedNotification); 793 this, &SettingGetterImplGSettings::OnDebouncedNotification);
796 } 794 }
797 795
798 // gsettings notification callback, dispatched on the default glib main loop. 796 // gsettings notification callback, dispatched on the default glib main loop.
799 static void OnGSettingsChangeNotification(GSettings* client, gchar* key, 797 static void OnGSettingsChangeNotification(GSettings* client, gchar* key,
800 gpointer user_data) { 798 gpointer user_data) {
801 VLOG(1) << "gsettings change notification for key " << key; 799 VLOG(1) << "gsettings change notification for key " << key;
802 // We don't track which key has changed, just that something did change. 800 // We don't track which key has changed, just that something did change.
803 SettingGetterImplGSettings* setting_getter = 801 SettingGetterImplGSettings* setting_getter =
804 reinterpret_cast<SettingGetterImplGSettings*>(user_data); 802 reinterpret_cast<SettingGetterImplGSettings*>(user_data);
805 setting_getter->OnChangeNotification(); 803 setting_getter->OnChangeNotification();
806 } 804 }
807 805
808 GSettings* client_; 806 GSettings* client_;
809 GSettings* http_client_; 807 GSettings* http_client_;
810 GSettings* https_client_; 808 GSettings* https_client_;
811 GSettings* ftp_client_; 809 GSettings* ftp_client_;
812 GSettings* socks_client_; 810 GSettings* socks_client_;
813 ProxyConfigServiceLinux::Delegate* notify_delegate_; 811 ProxyConfigServiceLinux::Delegate* notify_delegate_;
814 base::OneShotTimer<SettingGetterImplGSettings> debounce_timer_; 812 scoped_ptr<base::OneShotTimer<SettingGetterImplGSettings> > debounce_timer_;
815 813
816 // Task runner for the thread that we make gsettings calls on. It should 814 // Task runner for the thread that we make gsettings calls on. It should
817 // be the UI thread and all our methods should be called on this 815 // be the UI thread and all our methods should be called on this
818 // thread. Only for assertions. 816 // thread. Only for assertions.
819 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 817 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
820 818
821 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGSettings); 819 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGSettings);
822 }; 820 };
823 821
824 bool SettingGetterImplGSettings::LoadAndCheckVersion( 822 bool SettingGetterImplGSettings::LoadAndCheckVersion(
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 kde_config_dir_ = KDEHomeToConfigPath(kde4_path); 960 kde_config_dir_ = KDEHomeToConfigPath(kde4_path);
963 } else { 961 } else {
964 kde_config_dir_ = KDEHomeToConfigPath(kde3_path); 962 kde_config_dir_ = KDEHomeToConfigPath(kde3_path);
965 } 963 }
966 } 964 }
967 } 965 }
968 } 966 }
969 967
970 virtual ~SettingGetterImplKDE() { 968 virtual ~SettingGetterImplKDE() {
971 // inotify_fd_ should have been closed before now, from 969 // inotify_fd_ should have been closed before now, from
972 // Delegate::OnDestroy(), while running on the file thread. However 970 // Delegate::OnDestroy(), while running on the file thread.
973 // on exiting the process, it may happen that Delegate::OnDestroy()
974 // task is left pending on the file loop after the loop was quit,
975 // and pending tasks may then be deleted without being run.
976 // Here in the KDE version, we can safely close the file descriptor
977 // anyway. (Not that it really matters; the process is exiting.)
978 if (inotify_fd_ >= 0) 971 if (inotify_fd_ >= 0)
979 ShutDown(); 972 ShutDown();
980 DCHECK(inotify_fd_ < 0); 973 DCHECK(inotify_fd_ < 0);
981 } 974 }
982 975
983 virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner, 976 virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner,
984 MessageLoopForIO* file_loop) OVERRIDE { 977 MessageLoopForIO* file_loop) OVERRIDE {
985 // This has to be called on the UI thread (http://crbug.com/69057). 978 // This has to be called on the UI thread (http://crbug.com/69057).
986 base::ThreadRestrictions::ScopedAllowIO allow_io; 979 base::ThreadRestrictions::ScopedAllowIO allow_io;
987 DCHECK(inotify_fd_ < 0); 980 DCHECK(inotify_fd_ < 0);
(...skipping 16 matching lines...) Expand all
1004 return true; 997 return true;
1005 } 998 }
1006 999
1007 virtual void ShutDown() OVERRIDE { 1000 virtual void ShutDown() OVERRIDE {
1008 if (inotify_fd_ >= 0) { 1001 if (inotify_fd_ >= 0) {
1009 ResetCachedSettings(); 1002 ResetCachedSettings();
1010 inotify_watcher_.StopWatchingFileDescriptor(); 1003 inotify_watcher_.StopWatchingFileDescriptor();
1011 close(inotify_fd_); 1004 close(inotify_fd_);
1012 inotify_fd_ = -1; 1005 inotify_fd_ = -1;
1013 } 1006 }
1007 debounce_timer_.reset();
1014 } 1008 }
1015 1009
1016 virtual bool SetUpNotifications( 1010 virtual bool SetUpNotifications(
1017 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE { 1011 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE {
1018 DCHECK(inotify_fd_ >= 0); 1012 DCHECK(inotify_fd_ >= 0);
1019 DCHECK(MessageLoop::current() == file_loop_); 1013 DCHECK(MessageLoop::current() == file_loop_);
1014 debounce_timer_.reset(new base::OneShotTimer<SettingGetterImplKDE>());
1020 // We can't just watch the kioslaverc file directly, since KDE will write 1015 // We can't just watch the kioslaverc file directly, since KDE will write
1021 // a new copy of it and then rename it whenever settings are changed and 1016 // a new copy of it and then rename it whenever settings are changed and
1022 // inotify watches inodes (so we'll be watching the old deleted file after 1017 // inotify watches inodes (so we'll be watching the old deleted file after
1023 // the first change, and it will never change again). So, we watch the 1018 // the first change, and it will never change again). So, we watch the
1024 // directory instead. We then act only on changes to the kioslaverc entry. 1019 // directory instead. We then act only on changes to the kioslaverc entry.
1025 if (inotify_add_watch(inotify_fd_, kde_config_dir_.value().c_str(), 1020 if (inotify_add_watch(inotify_fd_, kde_config_dir_.value().c_str(),
1026 IN_MODIFY | IN_MOVED_TO) < 0) 1021 IN_MODIFY | IN_MOVED_TO) < 0)
1027 return false; 1022 return false;
1028 notify_delegate_ = delegate; 1023 notify_delegate_ = delegate;
1029 if (!file_loop_->WatchFileDescriptor(inotify_fd_, true, 1024 if (!file_loop_->WatchFileDescriptor(inotify_fd_, true,
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 // would be forever ready to read. Close it and stop watching instead. 1350 // would be forever ready to read. Close it and stop watching instead.
1356 LOG(ERROR) << "inotify failure; no longer watching kioslaverc!"; 1351 LOG(ERROR) << "inotify failure; no longer watching kioslaverc!";
1357 inotify_watcher_.StopWatchingFileDescriptor(); 1352 inotify_watcher_.StopWatchingFileDescriptor();
1358 close(inotify_fd_); 1353 close(inotify_fd_);
1359 inotify_fd_ = -1; 1354 inotify_fd_ = -1;
1360 } 1355 }
1361 } 1356 }
1362 if (kioslaverc_touched) { 1357 if (kioslaverc_touched) {
1363 // We don't use Reset() because the timer may not yet be running. 1358 // We don't use Reset() because the timer may not yet be running.
1364 // (In that case Stop() is a no-op.) 1359 // (In that case Stop() is a no-op.)
1365 debounce_timer_.Stop(); 1360 debounce_timer_->Stop();
1366 debounce_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds( 1361 debounce_timer_->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(
1367 kDebounceTimeoutMilliseconds), this, 1362 kDebounceTimeoutMilliseconds), this,
1368 &SettingGetterImplKDE::OnDebouncedNotification); 1363 &SettingGetterImplKDE::OnDebouncedNotification);
1369 } 1364 }
1370 } 1365 }
1371 1366
1372 typedef std::map<StringSetting, std::string> string_map_type; 1367 typedef std::map<StringSetting, std::string> string_map_type;
1373 typedef std::map<StringListSetting, 1368 typedef std::map<StringListSetting,
1374 std::vector<std::string> > strings_map_type; 1369 std::vector<std::string> > strings_map_type;
1375 1370
1376 int inotify_fd_; 1371 int inotify_fd_;
1377 base::MessagePumpLibevent::FileDescriptorWatcher inotify_watcher_; 1372 base::MessagePumpLibevent::FileDescriptorWatcher inotify_watcher_;
1378 ProxyConfigServiceLinux::Delegate* notify_delegate_; 1373 ProxyConfigServiceLinux::Delegate* notify_delegate_;
1379 base::OneShotTimer<SettingGetterImplKDE> debounce_timer_; 1374 scoped_ptr<base::OneShotTimer<SettingGetterImplKDE> > debounce_timer_;
1380 FilePath kde_config_dir_; 1375 FilePath kde_config_dir_;
1381 bool indirect_manual_; 1376 bool indirect_manual_;
1382 bool auto_no_pac_; 1377 bool auto_no_pac_;
1383 bool reversed_bypass_list_; 1378 bool reversed_bypass_list_;
1384 // We don't own |env_var_getter_|. It's safe to hold a pointer to it, since 1379 // We don't own |env_var_getter_|. It's safe to hold a pointer to it, since
1385 // both it and us are owned by ProxyConfigServiceLinux::Delegate, and have the 1380 // both it and us are owned by ProxyConfigServiceLinux::Delegate, and have the
1386 // same lifetime. 1381 // same lifetime.
1387 base::Environment* env_var_getter_; 1382 base::Environment* env_var_getter_;
1388 1383
1389 // We cache these settings whenever we re-read the kioslaverc file. 1384 // We cache these settings whenever we re-read the kioslaverc file.
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
1597 setting_getter_.reset(new SettingGetterImplKDE(env_var_getter)); 1592 setting_getter_.reset(new SettingGetterImplKDE(env_var_getter));
1598 break; 1593 break;
1599 case base::nix::DESKTOP_ENVIRONMENT_XFCE: 1594 case base::nix::DESKTOP_ENVIRONMENT_XFCE:
1600 case base::nix::DESKTOP_ENVIRONMENT_OTHER: 1595 case base::nix::DESKTOP_ENVIRONMENT_OTHER:
1601 break; 1596 break;
1602 } 1597 }
1603 } 1598 }
1604 1599
1605 ProxyConfigServiceLinux::Delegate::Delegate( 1600 ProxyConfigServiceLinux::Delegate::Delegate(
1606 base::Environment* env_var_getter, SettingGetter* setting_getter) 1601 base::Environment* env_var_getter, SettingGetter* setting_getter)
1607 : env_var_getter_(env_var_getter), setting_getter_(setting_getter) { 1602 : env_var_getter_(env_var_getter), setting_getter_(setting_getter),
1603 finished_initialization_(false) {
1608 } 1604 }
1609 1605
1610 void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig( 1606 void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig(
1611 base::SingleThreadTaskRunner* glib_thread_task_runner, 1607 base::SingleThreadTaskRunner* glib_thread_task_runner,
1612 base::SingleThreadTaskRunner* io_thread_task_runner, 1608 base::SingleThreadTaskRunner* io_thread_task_runner,
1613 MessageLoopForIO* file_loop) { 1609 MessageLoopForIO* file_loop) {
1610 DCHECK(io_thread_task_runner->BelongsToCurrentThread());
1611
1612 glib_thread_task_runner_ = glib_thread_task_runner;
1613 io_thread_task_runner_ = io_thread_task_runner;
1614
1615 glib_thread_task_runner->PostTask(FROM_HERE, base::Bind(
1616 &Delegate::SetUpAndFetchInitialConfigOnUIThread,
1617 this,
1618 file_loop));
1619 }
1620
1621 void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfigOnUIThread(
1622 MessageLoopForIO* file_loop) {
1614 // We should be running on the default glib main loop thread right 1623 // We should be running on the default glib main loop thread right
1615 // now. gconf can only be accessed from this thread. 1624 // now. gconf can only be accessed from this thread.
1616 DCHECK(glib_thread_task_runner->BelongsToCurrentThread()); 1625 DCHECK(glib_thread_task_runner_->BelongsToCurrentThread());
1617 glib_thread_task_runner_ = glib_thread_task_runner;
1618 io_thread_task_runner_ = io_thread_task_runner;
1619 1626
1620 // If we are passed a NULL |io_thread_task_runner| or |file_loop|, 1627 // If we are passed a NULL |io_thread_task_runner| or |file_loop|,
1621 // then we don't set up proxy setting change notifications. This 1628 // then we don't set up proxy setting change notifications. This
1622 // should not be the usual case but is intended to simplify test 1629 // should not be the usual case but is intended to simplify test
1623 // setups. 1630 // setups.
1624 if (!io_thread_task_runner_ || !file_loop) 1631 if (!io_thread_task_runner_ || !file_loop)
1625 VLOG(1) << "Monitoring of proxy setting changes is disabled"; 1632 VLOG(1) << "Monitoring of proxy setting changes is disabled";
1626 1633
1627 // Fetch and cache the current proxy config. The config is left in 1634 // Fetch and cache the current proxy config. The config is left in
1628 // cached_config_, where GetLatestProxyConfig() running on the IO thread 1635 // cached_config_, where GetLatestProxyConfig() running on the IO thread
1629 // will expect to find it. This is safe to do because we return 1636 // will expect to find it. This is safe to do because we return
1630 // before this ProxyConfigServiceLinux is passed on to 1637 // before this ProxyConfigServiceLinux is passed on to
1631 // the ProxyService. 1638 // the ProxyService.
1632 1639
1633 // Note: It would be nice to prioritize environment variables 1640 // Note: It would be nice to prioritize environment variables
1634 // and only fall back to gconf if env vars were unset. But 1641 // and only fall back to gconf if env vars were unset. But
1635 // gnome-terminal "helpfully" sets http_proxy and no_proxy, and it 1642 // gnome-terminal "helpfully" sets http_proxy and no_proxy, and it
1636 // does so even if the proxy mode is set to auto, which would 1643 // does so even if the proxy mode is set to auto, which would
1637 // mislead us. 1644 // mislead us.
1638 1645
1639 bool got_config = false; 1646 bool got_config = false;
1640 if (setting_getter_.get() && 1647 if (setting_getter_.get() &&
1641 setting_getter_->Init(glib_thread_task_runner, file_loop) && 1648 setting_getter_->Init(glib_thread_task_runner_, file_loop) &&
1642 GetConfigFromSettings(&cached_config_)) { 1649 GetConfigFromSettings(&reference_config_)) {
1643 cached_config_.set_id(1); // Mark it as valid. 1650 reference_config_.set_id(1); // Mark it as valid.
1644 cached_config_.set_source(setting_getter_->GetConfigSource()); 1651 reference_config_.set_source(setting_getter_->GetConfigSource());
1645 VLOG(1) << "Obtained proxy settings from " 1652 VLOG(1) << "Obtained proxy settings from "
1646 << ProxyConfigSourceToString(cached_config_.source()); 1653 << ProxyConfigSourceToString(reference_config_.source());
1647 1654
1648 // If gconf proxy mode is "none", meaning direct, then we take 1655 // If gconf proxy mode is "none", meaning direct, then we take
1649 // that to be a valid config and will not check environment 1656 // that to be a valid config and will not check environment
1650 // variables. The alternative would have been to look for a proxy 1657 // variables. The alternative would have been to look for a proxy
1651 // whereever we can find one. 1658 // whereever we can find one.
1652 got_config = true; 1659 got_config = true;
1653 1660
1654 // Keep a copy of the config for use from this thread for
1655 // comparison with updated settings when we get notifications.
1656 reference_config_ = cached_config_;
1657 reference_config_.set_id(1); // Mark it as valid.
1658
1659 // We only set up notifications if we have IO and file loops available. 1661 // We only set up notifications if we have IO and file loops available.
1660 // We do this after getting the initial configuration so that we don't have 1662 // We do this after getting the initial configuration so that we don't have
1661 // to worry about cancelling it if the initial fetch above fails. Note that 1663 // to worry about cancelling it if the initial fetch above fails. Note that
1662 // setting up notifications has the side effect of simulating a change, so 1664 // setting up notifications has the side effect of simulating a change, so
1663 // that we won't lose any updates that may have happened after the initial 1665 // that we won't lose any updates that may have happened after the initial
1664 // fetch and before setting up notifications. We'll detect the common case 1666 // fetch and before setting up notifications. We'll detect the common case
1665 // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it. 1667 // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it.
1666 if (io_thread_task_runner && file_loop) { 1668 if (io_thread_task_runner_ && file_loop) {
1667 scoped_refptr<base::SingleThreadTaskRunner> required_loop = 1669 scoped_refptr<base::SingleThreadTaskRunner> required_loop =
1668 setting_getter_->GetNotificationTaskRunner(); 1670 setting_getter_->GetNotificationTaskRunner();
1669 if (!required_loop || required_loop->BelongsToCurrentThread()) { 1671 if (!required_loop || required_loop->BelongsToCurrentThread()) {
1670 // In this case we are already on an acceptable thread. 1672 // In this case we are already on an acceptable thread.
1671 SetUpNotifications(); 1673 SetUpNotifications();
1672 } else { 1674 } else {
1673 // Post a task to set up notifications. We don't wait for success. 1675 // Post a task to set up notifications. We don't wait for success.
1674 required_loop->PostTask(FROM_HERE, base::Bind( 1676 required_loop->PostTask(FROM_HERE, base::Bind(
1675 &ProxyConfigServiceLinux::Delegate::SetUpNotifications, this)); 1677 &ProxyConfigServiceLinux::Delegate::SetUpNotifications, this));
1676 } 1678 }
1677 } 1679 }
1678 } 1680 }
1679 1681
1680 if (!got_config) { 1682 if (!got_config) {
1681 // We fall back on environment variables. 1683 // We fall back on environment variables.
1682 // 1684 //
1683 // Consulting environment variables doesn't need to be done from the 1685 // Consulting environment variables doesn't need to be done from the
1684 // default glib main loop, but it's a tiny enough amount of work. 1686 // default glib main loop, but it's a tiny enough amount of work.
1685 if (GetConfigFromEnv(&cached_config_)) { 1687 if (GetConfigFromEnv(&reference_config_)) {
1686 cached_config_.set_source(PROXY_CONFIG_SOURCE_ENV); 1688 reference_config_.set_source(PROXY_CONFIG_SOURCE_ENV);
1687 cached_config_.set_id(1); // Mark it as valid. 1689 reference_config_.set_id(1); // Mark it as valid.
1688 VLOG(1) << "Obtained proxy settings from environment variables"; 1690 VLOG(1) << "Obtained proxy settings from environment variables";
1689 } 1691 }
1690 } 1692 }
1693
1694 // Post a task to the IO thread with the new configuration, so it can
1695 // update |cached_config_|.
1696 io_thread_task_runner_->PostTask(FROM_HERE, base::Bind(
1697 &ProxyConfigServiceLinux::Delegate::SetNewProxyConfig,
1698 this, reference_config_));
1691 } 1699 }
1692 1700
1693 // Depending on the SettingGetter in use, this method will be called 1701 // Depending on the SettingGetter in use, this method will be called
1694 // on either the UI thread (GConf) or the file thread (KDE). 1702 // on either the UI thread (GConf) or the file thread (KDE).
1695 void ProxyConfigServiceLinux::Delegate::SetUpNotifications() { 1703 void ProxyConfigServiceLinux::Delegate::SetUpNotifications() {
1696 scoped_refptr<base::SingleThreadTaskRunner> required_loop = 1704 scoped_refptr<base::SingleThreadTaskRunner> required_loop =
1697 setting_getter_->GetNotificationTaskRunner(); 1705 setting_getter_->GetNotificationTaskRunner();
1698 DCHECK(!required_loop || required_loop->BelongsToCurrentThread()); 1706 DCHECK(!required_loop || required_loop->BelongsToCurrentThread());
1699 if (!setting_getter_->SetUpNotifications(this)) 1707 if (!setting_getter_->SetUpNotifications(this))
1700 LOG(ERROR) << "Unable to set up proxy configuration change notifications"; 1708 LOG(ERROR) << "Unable to set up proxy configuration change notifications";
1701 } 1709 }
1702 1710
1703 void ProxyConfigServiceLinux::Delegate::AddObserver(Observer* observer) { 1711 void ProxyConfigServiceLinux::Delegate::AddObserver(Observer* observer) {
1704 observers_.AddObserver(observer); 1712 observers_.AddObserver(observer);
1705 } 1713 }
1706 1714
1707 void ProxyConfigServiceLinux::Delegate::RemoveObserver(Observer* observer) { 1715 void ProxyConfigServiceLinux::Delegate::RemoveObserver(Observer* observer) {
1708 observers_.RemoveObserver(observer); 1716 observers_.RemoveObserver(observer);
1709 } 1717 }
1710 1718
1711 ProxyConfigService::ConfigAvailability 1719 ProxyConfigService::ConfigAvailability
1712 ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig( 1720 ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig(
1713 ProxyConfig* config) { 1721 ProxyConfig* config) {
1714 // This is called from the IO thread. 1722 // This is called from the IO thread.
1715 DCHECK(!io_thread_task_runner_ || 1723 DCHECK(!io_thread_task_runner_ ||
1716 io_thread_task_runner_->BelongsToCurrentThread()); 1724 io_thread_task_runner_->BelongsToCurrentThread());
1717 1725
1726 if (!finished_initialization_)
1727 return CONFIG_PENDING;
1728
1718 // Simply return the last proxy configuration that glib_default_loop 1729 // Simply return the last proxy configuration that glib_default_loop
1719 // notified us of. 1730 // notified us of.
1720 if (cached_config_.is_valid()) { 1731 if (cached_config_.is_valid()) {
1721 *config = cached_config_; 1732 *config = cached_config_;
1722 } else { 1733 } else {
1723 *config = ProxyConfig::CreateDirect(); 1734 *config = ProxyConfig::CreateDirect();
1724 config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED); 1735 config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED);
1725 } 1736 }
1726 1737
1727 // We return CONFIG_VALID to indicate that *config was filled in. It is always 1738 // We return CONFIG_VALID to indicate that *config was filled in.
1728 // going to be available since we initialized eagerly on the UI thread.
1729 // TODO(eroman): do lazy initialization instead, so we no longer need
1730 // to construct ProxyConfigServiceLinux on the UI thread.
1731 // In which case, we may return false here.
1732 return CONFIG_VALID; 1739 return CONFIG_VALID;
1733 } 1740 }
1734 1741
1735 // Depending on the SettingGetter in use, this method will be called 1742 // Depending on the SettingGetter in use, this method will be called
1736 // on either the UI thread (GConf) or the file thread (KDE). 1743 // on either the UI thread (GConf) or the file thread (KDE).
1737 void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() { 1744 void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() {
1738 scoped_refptr<base::SingleThreadTaskRunner> required_loop = 1745 scoped_refptr<base::SingleThreadTaskRunner> required_loop =
1739 setting_getter_->GetNotificationTaskRunner(); 1746 setting_getter_->GetNotificationTaskRunner();
1740 DCHECK(!required_loop || required_loop->BelongsToCurrentThread()); 1747 DCHECK(!required_loop || required_loop->BelongsToCurrentThread());
1741 ProxyConfig new_config; 1748 ProxyConfig new_config;
(...skipping 14 matching lines...) Expand all
1756 } else { 1763 } else {
1757 VLOG(1) << "Detected no-op change to proxy settings. Doing nothing."; 1764 VLOG(1) << "Detected no-op change to proxy settings. Doing nothing.";
1758 } 1765 }
1759 } 1766 }
1760 1767
1761 void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig( 1768 void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig(
1762 const ProxyConfig& new_config) { 1769 const ProxyConfig& new_config) {
1763 DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); 1770 DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
1764 VLOG(1) << "Proxy configuration changed"; 1771 VLOG(1) << "Proxy configuration changed";
1765 cached_config_ = new_config; 1772 cached_config_ = new_config;
1773 finished_initialization_ = true;
1766 FOR_EACH_OBSERVER( 1774 FOR_EACH_OBSERVER(
1767 Observer, observers_, 1775 Observer, observers_,
1768 OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID)); 1776 OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID));
1769 } 1777 }
1770 1778
1771 void ProxyConfigServiceLinux::Delegate::PostDestroyTask() { 1779 void ProxyConfigServiceLinux::Delegate::PostDestroyTask() {
1772 if (!setting_getter_.get()) 1780 if (!setting_getter_.get())
1773 return; 1781 return;
1774 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop = 1782 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop =
1775 setting_getter_->GetNotificationTaskRunner(); 1783 setting_getter_->GetNotificationTaskRunner();
1776 if (!shutdown_loop || shutdown_loop->BelongsToCurrentThread()) { 1784 if (!shutdown_loop || shutdown_loop->BelongsToCurrentThread()) {
1777 // Already on the right thread, call directly. 1785 // Already on the right thread, call directly.
1778 // This is the case for the unittests. 1786 // This is the case for the unittests.
1787 // The browser's UI thread will not execute any more tasks at this point
1788 // so its necessary to call directly.
1779 OnDestroy(); 1789 OnDestroy();
1780 } else { 1790 } else {
1781 // Post to shutdown thread. Note that on browser shutdown, we may quit 1791 // Post to shutdown thread. Note that on browser shutdown, we may quit
1782 // this MessageLoop and exit the program before ever running this. 1792 // this MessageLoop and exit the program before ever running this.
1783 shutdown_loop->PostTask(FROM_HERE, base::Bind( 1793 shutdown_loop->PostTask(FROM_HERE, base::Bind(
1784 &ProxyConfigServiceLinux::Delegate::OnDestroy, this)); 1794 &ProxyConfigServiceLinux::Delegate::OnDestroy, this));
1785 } 1795 }
1786 } 1796 }
1787 void ProxyConfigServiceLinux::Delegate::OnDestroy() { 1797 void ProxyConfigServiceLinux::Delegate::OnDestroy() {
1788 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop = 1798 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop =
1789 setting_getter_->GetNotificationTaskRunner(); 1799 setting_getter_->GetNotificationTaskRunner();
1790 DCHECK(!shutdown_loop || shutdown_loop->BelongsToCurrentThread()); 1800 DCHECK(!shutdown_loop || shutdown_loop->BelongsToCurrentThread());
1791 setting_getter_->ShutDown(); 1801 setting_getter_->ShutDown();
1792 } 1802 }
1793 1803
1794 ProxyConfigServiceLinux::ProxyConfigServiceLinux() 1804 ProxyConfigServiceLinux::ProxyConfigServiceLinux(
1805 base::SingleThreadTaskRunner* glib_thread_task_runner,
1806 base::SingleThreadTaskRunner* io_thread_task_runner,
1807 MessageLoopForIO* file_loop)
1795 : delegate_(new Delegate(base::Environment::Create())) { 1808 : delegate_(new Delegate(base::Environment::Create())) {
1809 SetupAndFetchInitialConfig(glib_thread_task_runner,
1810 io_thread_task_runner,
1811 file_loop);
1796 } 1812 }
1797 1813
1798 ProxyConfigServiceLinux::~ProxyConfigServiceLinux() { 1814 ProxyConfigServiceLinux::~ProxyConfigServiceLinux() {
1815 }
1816
1817 void ProxyConfigServiceLinux::StartTearDown() {
1818 // This must be done prior to destruction. Destruction occurs as the threads
1819 // are dying which is too late to post tasks. Previously this code relied on
1820 // ~Delegate() being called when the unexecuted Delegate::OnDestroy() task
1821 // was purged from the UI thread's MessageLoop as we shutdown. This didn't
1822 // work very well as things like BelongsToCurrentThread() don't operate
1823 // properly at this late a stage.
1799 delegate_->PostDestroyTask(); 1824 delegate_->PostDestroyTask();
1800 } 1825 }
1801 1826
1802 ProxyConfigServiceLinux::ProxyConfigServiceLinux( 1827 ProxyConfigServiceLinux::ProxyConfigServiceLinux(
1803 base::Environment* env_var_getter) 1828 base::Environment* env_var_getter)
1804 : delegate_(new Delegate(env_var_getter)) { 1829 : delegate_(new Delegate(env_var_getter)) {
1805 } 1830 }
1806 1831
1807 ProxyConfigServiceLinux::ProxyConfigServiceLinux( 1832 ProxyConfigServiceLinux::ProxyConfigServiceLinux(
1808 base::Environment* env_var_getter, SettingGetter* setting_getter) 1833 base::Environment* env_var_getter, SettingGetter* setting_getter)
1809 : delegate_(new Delegate(env_var_getter, setting_getter)) { 1834 : delegate_(new Delegate(env_var_getter, setting_getter)) {
1810 } 1835 }
1811 1836
1812 void ProxyConfigServiceLinux::AddObserver(Observer* observer) { 1837 void ProxyConfigServiceLinux::AddObserver(Observer* observer) {
1813 delegate_->AddObserver(observer); 1838 delegate_->AddObserver(observer);
1814 } 1839 }
1815 1840
1816 void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) { 1841 void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) {
1817 delegate_->RemoveObserver(observer); 1842 delegate_->RemoveObserver(observer);
1818 } 1843 }
1819 1844
1820 ProxyConfigService::ConfigAvailability 1845 ProxyConfigService::ConfigAvailability
1821 ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) { 1846 ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) {
1822 return delegate_->GetLatestProxyConfig(config); 1847 return delegate_->GetLatestProxyConfig(config);
1823 } 1848 }
1824 1849
1825 } // namespace net 1850 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698