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

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: Tiny fix for get_server_time 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 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 // have the same lifetimes. (For instance, incognito sessions get their 278 // have the same lifetimes. (For instance, incognito sessions get their
279 // own, which is destroyed when the session ends.) 279 // own, which is destroyed when the session ends.)
280 gconf_client_notify_remove(client_, system_http_proxy_id_); 280 gconf_client_notify_remove(client_, system_http_proxy_id_);
281 gconf_client_notify_remove(client_, system_proxy_id_); 281 gconf_client_notify_remove(client_, system_proxy_id_);
282 gconf_client_remove_dir(client_, "/system/http_proxy", NULL); 282 gconf_client_remove_dir(client_, "/system/http_proxy", NULL);
283 gconf_client_remove_dir(client_, "/system/proxy", NULL); 283 gconf_client_remove_dir(client_, "/system/proxy", NULL);
284 g_object_unref(client_); 284 g_object_unref(client_);
285 client_ = NULL; 285 client_ = NULL;
286 task_runner_ = NULL; 286 task_runner_ = NULL;
287 } 287 }
288 debounce_timer_.reset();
288 } 289 }
289 290
290 virtual bool SetUpNotifications( 291 virtual bool SetUpNotifications(
291 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE { 292 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE {
292 DCHECK(client_); 293 DCHECK(client_);
293 DCHECK(task_runner_->BelongsToCurrentThread()); 294 DCHECK(task_runner_->BelongsToCurrentThread());
294 GError* error = NULL; 295 GError* error = NULL;
295 notify_delegate_ = delegate; 296 notify_delegate_ = delegate;
296 // We have to keep track of the IDs returned by gconf_client_notify_add() so 297 // 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 298 // that we can remove them in ShutDown(). (Otherwise, notifications will be
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 466
466 // This is the callback from the debounce timer. 467 // This is the callback from the debounce timer.
467 void OnDebouncedNotification() { 468 void OnDebouncedNotification() {
468 DCHECK(task_runner_->BelongsToCurrentThread()); 469 DCHECK(task_runner_->BelongsToCurrentThread());
469 CHECK(notify_delegate_); 470 CHECK(notify_delegate_);
470 // Forward to a method on the proxy config service delegate object. 471 // Forward to a method on the proxy config service delegate object.
471 notify_delegate_->OnCheckProxyConfigSettings(); 472 notify_delegate_->OnCheckProxyConfigSettings();
472 } 473 }
473 474
474 void OnChangeNotification() { 475 void OnChangeNotification() {
476 if (!debounce_timer_.get())
477 debounce_timer_.reset(new base::OneShotTimer<SettingGetterImplGConf>());
475 // We don't use Reset() because the timer may not yet be running. 478 // We don't use Reset() because the timer may not yet be running.
476 // (In that case Stop() is a no-op.) 479 // (In that case Stop() is a no-op.)
477 debounce_timer_.Stop(); 480 debounce_timer_->Stop();
478 debounce_timer_.Start(FROM_HERE, 481 debounce_timer_->Start(FROM_HERE,
479 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), 482 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds),
480 this, &SettingGetterImplGConf::OnDebouncedNotification); 483 this, &SettingGetterImplGConf::OnDebouncedNotification);
481 } 484 }
482 485
483 // gconf notification callback, dispatched on the default glib main loop. 486 // gconf notification callback, dispatched on the default glib main loop.
484 static void OnGConfChangeNotification(GConfClient* client, guint cnxn_id, 487 static void OnGConfChangeNotification(GConfClient* client, guint cnxn_id,
485 GConfEntry* entry, gpointer user_data) { 488 GConfEntry* entry, gpointer user_data) {
486 VLOG(1) << "gconf change notification for key " 489 VLOG(1) << "gconf change notification for key "
487 << gconf_entry_get_key(entry); 490 << gconf_entry_get_key(entry);
488 // We don't track which key has changed, just that something did change. 491 // We don't track which key has changed, just that something did change.
489 SettingGetterImplGConf* setting_getter = 492 SettingGetterImplGConf* setting_getter =
490 reinterpret_cast<SettingGetterImplGConf*>(user_data); 493 reinterpret_cast<SettingGetterImplGConf*>(user_data);
491 setting_getter->OnChangeNotification(); 494 setting_getter->OnChangeNotification();
492 } 495 }
493 496
494 GConfClient* client_; 497 GConfClient* client_;
495 // These ids are the values returned from gconf_client_notify_add(), which we 498 // 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(). 499 // will need in order to later call gconf_client_notify_remove().
497 guint system_proxy_id_; 500 guint system_proxy_id_;
498 guint system_http_proxy_id_; 501 guint system_http_proxy_id_;
499 502
500 ProxyConfigServiceLinux::Delegate* notify_delegate_; 503 ProxyConfigServiceLinux::Delegate* notify_delegate_;
501 base::OneShotTimer<SettingGetterImplGConf> debounce_timer_; 504 scoped_ptr<base::OneShotTimer<SettingGetterImplGConf> > debounce_timer_;
502 505
503 // Task runner for the thread that we make gconf calls on. It should 506 // 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 507 // be the UI thread and all our methods should be called on this
505 // thread. Only for assertions. 508 // thread. Only for assertions.
506 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 509 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
507 510
508 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGConf); 511 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGConf);
509 }; 512 };
510 #endif // defined(USE_GCONF) 513 #endif // defined(USE_GCONF)
511 514
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 // This also disables gsettings notifications. 606 // This also disables gsettings notifications.
604 g_object_unref(socks_client_); 607 g_object_unref(socks_client_);
605 g_object_unref(ftp_client_); 608 g_object_unref(ftp_client_);
606 g_object_unref(https_client_); 609 g_object_unref(https_client_);
607 g_object_unref(http_client_); 610 g_object_unref(http_client_);
608 g_object_unref(client_); 611 g_object_unref(client_);
609 // We only need to null client_ because it's the only one that we check. 612 // We only need to null client_ because it's the only one that we check.
610 client_ = NULL; 613 client_ = NULL;
611 task_runner_ = NULL; 614 task_runner_ = NULL;
612 } 615 }
616 debounce_timer_.reset();
613 } 617 }
614 618
615 virtual bool SetUpNotifications( 619 virtual bool SetUpNotifications(
616 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE { 620 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE {
617 DCHECK(client_); 621 DCHECK(client_);
618 DCHECK(task_runner_->BelongsToCurrentThread()); 622 DCHECK(task_runner_->BelongsToCurrentThread());
619 notify_delegate_ = delegate; 623 notify_delegate_ = delegate;
620 // We could watch for the change-event signal instead of changed, but 624 // 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 625 // since we have to watch more than one object, we'd still have to
622 // debounce change notifications. This is conceptually simpler. 626 // debounce change notifications. This is conceptually simpler.
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 784
781 // This is the callback from the debounce timer. 785 // This is the callback from the debounce timer.
782 void OnDebouncedNotification() { 786 void OnDebouncedNotification() {
783 DCHECK(task_runner_->BelongsToCurrentThread()); 787 DCHECK(task_runner_->BelongsToCurrentThread());
784 CHECK(notify_delegate_); 788 CHECK(notify_delegate_);
785 // Forward to a method on the proxy config service delegate object. 789 // Forward to a method on the proxy config service delegate object.
786 notify_delegate_->OnCheckProxyConfigSettings(); 790 notify_delegate_->OnCheckProxyConfigSettings();
787 } 791 }
788 792
789 void OnChangeNotification() { 793 void OnChangeNotification() {
794 if (!debounce_timer_.get())
795 debounce_timer_.reset(
796 new base::OneShotTimer<SettingGetterImplGSettings>());
790 // We don't use Reset() because the timer may not yet be running. 797 // We don't use Reset() because the timer may not yet be running.
791 // (In that case Stop() is a no-op.) 798 // (In that case Stop() is a no-op.)
792 debounce_timer_.Stop(); 799 debounce_timer_->Stop();
793 debounce_timer_.Start(FROM_HERE, 800 debounce_timer_->Start(FROM_HERE,
794 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), 801 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds),
795 this, &SettingGetterImplGSettings::OnDebouncedNotification); 802 this, &SettingGetterImplGSettings::OnDebouncedNotification);
796 } 803 }
797 804
798 // gsettings notification callback, dispatched on the default glib main loop. 805 // gsettings notification callback, dispatched on the default glib main loop.
799 static void OnGSettingsChangeNotification(GSettings* client, gchar* key, 806 static void OnGSettingsChangeNotification(GSettings* client, gchar* key,
800 gpointer user_data) { 807 gpointer user_data) {
801 VLOG(1) << "gsettings change notification for key " << key; 808 VLOG(1) << "gsettings change notification for key " << key;
802 // We don't track which key has changed, just that something did change. 809 // We don't track which key has changed, just that something did change.
803 SettingGetterImplGSettings* setting_getter = 810 SettingGetterImplGSettings* setting_getter =
804 reinterpret_cast<SettingGetterImplGSettings*>(user_data); 811 reinterpret_cast<SettingGetterImplGSettings*>(user_data);
805 setting_getter->OnChangeNotification(); 812 setting_getter->OnChangeNotification();
806 } 813 }
807 814
808 GSettings* client_; 815 GSettings* client_;
809 GSettings* http_client_; 816 GSettings* http_client_;
810 GSettings* https_client_; 817 GSettings* https_client_;
811 GSettings* ftp_client_; 818 GSettings* ftp_client_;
812 GSettings* socks_client_; 819 GSettings* socks_client_;
813 ProxyConfigServiceLinux::Delegate* notify_delegate_; 820 ProxyConfigServiceLinux::Delegate* notify_delegate_;
814 base::OneShotTimer<SettingGetterImplGSettings> debounce_timer_; 821 scoped_ptr<base::OneShotTimer<SettingGetterImplGSettings> > debounce_timer_;
815 822
816 // Task runner for the thread that we make gsettings calls on. It should 823 // 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 824 // be the UI thread and all our methods should be called on this
818 // thread. Only for assertions. 825 // thread. Only for assertions.
819 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 826 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
820 827
821 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGSettings); 828 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGSettings);
822 }; 829 };
823 830
824 bool SettingGetterImplGSettings::LoadAndCheckVersion( 831 bool SettingGetterImplGSettings::LoadAndCheckVersion(
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 return true; 1011 return true;
1005 } 1012 }
1006 1013
1007 virtual void ShutDown() OVERRIDE { 1014 virtual void ShutDown() OVERRIDE {
1008 if (inotify_fd_ >= 0) { 1015 if (inotify_fd_ >= 0) {
1009 ResetCachedSettings(); 1016 ResetCachedSettings();
1010 inotify_watcher_.StopWatchingFileDescriptor(); 1017 inotify_watcher_.StopWatchingFileDescriptor();
1011 close(inotify_fd_); 1018 close(inotify_fd_);
1012 inotify_fd_ = -1; 1019 inotify_fd_ = -1;
1013 } 1020 }
1021 debounce_timer_.reset();
1014 } 1022 }
1015 1023
1016 virtual bool SetUpNotifications( 1024 virtual bool SetUpNotifications(
1017 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE { 1025 ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE {
1018 DCHECK(inotify_fd_ >= 0); 1026 DCHECK(inotify_fd_ >= 0);
1019 DCHECK(MessageLoop::current() == file_loop_); 1027 DCHECK(MessageLoop::current() == file_loop_);
1020 // We can't just watch the kioslaverc file directly, since KDE will write 1028 // 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 1029 // 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 1030 // 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 1031 // the first change, and it will never change again). So, we watch the
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 // would be forever ready to read. Close it and stop watching instead. 1363 // would be forever ready to read. Close it and stop watching instead.
1356 LOG(ERROR) << "inotify failure; no longer watching kioslaverc!"; 1364 LOG(ERROR) << "inotify failure; no longer watching kioslaverc!";
1357 inotify_watcher_.StopWatchingFileDescriptor(); 1365 inotify_watcher_.StopWatchingFileDescriptor();
1358 close(inotify_fd_); 1366 close(inotify_fd_);
1359 inotify_fd_ = -1; 1367 inotify_fd_ = -1;
1360 } 1368 }
1361 } 1369 }
1362 if (kioslaverc_touched) { 1370 if (kioslaverc_touched) {
1363 // We don't use Reset() because the timer may not yet be running. 1371 // We don't use Reset() because the timer may not yet be running.
1364 // (In that case Stop() is a no-op.) 1372 // (In that case Stop() is a no-op.)
1365 debounce_timer_.Stop(); 1373 if (!debounce_timer_.get())
1366 debounce_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds( 1374 debounce_timer_.reset(new base::OneShotTimer<SettingGetterImplKDE>());
1375 debounce_timer_->Stop();
1376 debounce_timer_->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(
1367 kDebounceTimeoutMilliseconds), this, 1377 kDebounceTimeoutMilliseconds), this,
1368 &SettingGetterImplKDE::OnDebouncedNotification); 1378 &SettingGetterImplKDE::OnDebouncedNotification);
1369 } 1379 }
1370 } 1380 }
1371 1381
1372 typedef std::map<StringSetting, std::string> string_map_type; 1382 typedef std::map<StringSetting, std::string> string_map_type;
1373 typedef std::map<StringListSetting, 1383 typedef std::map<StringListSetting,
1374 std::vector<std::string> > strings_map_type; 1384 std::vector<std::string> > strings_map_type;
1375 1385
1376 int inotify_fd_; 1386 int inotify_fd_;
1377 base::MessagePumpLibevent::FileDescriptorWatcher inotify_watcher_; 1387 base::MessagePumpLibevent::FileDescriptorWatcher inotify_watcher_;
1378 ProxyConfigServiceLinux::Delegate* notify_delegate_; 1388 ProxyConfigServiceLinux::Delegate* notify_delegate_;
1379 base::OneShotTimer<SettingGetterImplKDE> debounce_timer_; 1389 scoped_ptr<base::OneShotTimer<SettingGetterImplKDE> > debounce_timer_;
1380 FilePath kde_config_dir_; 1390 FilePath kde_config_dir_;
1381 bool indirect_manual_; 1391 bool indirect_manual_;
1382 bool auto_no_pac_; 1392 bool auto_no_pac_;
1383 bool reversed_bypass_list_; 1393 bool reversed_bypass_list_;
1384 // We don't own |env_var_getter_|. It's safe to hold a pointer to it, since 1394 // 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 1395 // both it and us are owned by ProxyConfigServiceLinux::Delegate, and have the
1386 // same lifetime. 1396 // same lifetime.
1387 base::Environment* env_var_getter_; 1397 base::Environment* env_var_getter_;
1388 1398
1389 // We cache these settings whenever we re-read the kioslaverc file. 1399 // 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)); 1607 setting_getter_.reset(new SettingGetterImplKDE(env_var_getter));
1598 break; 1608 break;
1599 case base::nix::DESKTOP_ENVIRONMENT_XFCE: 1609 case base::nix::DESKTOP_ENVIRONMENT_XFCE:
1600 case base::nix::DESKTOP_ENVIRONMENT_OTHER: 1610 case base::nix::DESKTOP_ENVIRONMENT_OTHER:
1601 break; 1611 break;
1602 } 1612 }
1603 } 1613 }
1604 1614
1605 ProxyConfigServiceLinux::Delegate::Delegate( 1615 ProxyConfigServiceLinux::Delegate::Delegate(
1606 base::Environment* env_var_getter, SettingGetter* setting_getter) 1616 base::Environment* env_var_getter, SettingGetter* setting_getter)
1607 : env_var_getter_(env_var_getter), setting_getter_(setting_getter) { 1617 : env_var_getter_(env_var_getter), setting_getter_(setting_getter),
1618 finished_initialization_(false) {
1608 } 1619 }
1609 1620
1610 void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig( 1621 void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig(
1611 base::SingleThreadTaskRunner* glib_thread_task_runner, 1622 base::SingleThreadTaskRunner* glib_thread_task_runner,
1612 base::SingleThreadTaskRunner* io_thread_task_runner, 1623 base::SingleThreadTaskRunner* io_thread_task_runner,
1613 MessageLoopForIO* file_loop) { 1624 MessageLoopForIO* file_loop) {
1625 DCHECK(io_thread_task_runner->BelongsToCurrentThread());
1626
1627 glib_thread_task_runner_ = glib_thread_task_runner;
1628 io_thread_task_runner_ = io_thread_task_runner;
1629
1630 glib_thread_task_runner->PostTask(FROM_HERE, base::Bind(
1631 &Delegate::SetUpAndFetchInitialConfigOnUIThread,
1632 this,
1633 file_loop));
1634 }
1635
1636 void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfigOnUIThread(
1637 MessageLoopForIO* file_loop) {
1614 // We should be running on the default glib main loop thread right 1638 // We should be running on the default glib main loop thread right
1615 // now. gconf can only be accessed from this thread. 1639 // now. gconf can only be accessed from this thread.
1616 DCHECK(glib_thread_task_runner->BelongsToCurrentThread()); 1640 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 1641
1620 // If we are passed a NULL |io_thread_task_runner| or |file_loop|, 1642 // 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 1643 // then we don't set up proxy setting change notifications. This
1622 // should not be the usual case but is intended to simplify test 1644 // should not be the usual case but is intended to simplify test
1623 // setups. 1645 // setups.
1624 if (!io_thread_task_runner_ || !file_loop) 1646 if (!io_thread_task_runner_ || !file_loop)
1625 VLOG(1) << "Monitoring of proxy setting changes is disabled"; 1647 VLOG(1) << "Monitoring of proxy setting changes is disabled";
1626 1648
1627 // Fetch and cache the current proxy config. The config is left in 1649 // Fetch and cache the current proxy config. The config is left in
1628 // cached_config_, where GetLatestProxyConfig() running on the IO thread 1650 // cached_config_, where GetLatestProxyConfig() running on the IO thread
1629 // will expect to find it. This is safe to do because we return 1651 // will expect to find it. This is safe to do because we return
1630 // before this ProxyConfigServiceLinux is passed on to 1652 // before this ProxyConfigServiceLinux is passed on to
1631 // the ProxyService. 1653 // the ProxyService.
1632 1654
1633 // Note: It would be nice to prioritize environment variables 1655 // Note: It would be nice to prioritize environment variables
1634 // and only fall back to gconf if env vars were unset. But 1656 // and only fall back to gconf if env vars were unset. But
1635 // gnome-terminal "helpfully" sets http_proxy and no_proxy, and it 1657 // 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 1658 // does so even if the proxy mode is set to auto, which would
1637 // mislead us. 1659 // mislead us.
1638 1660
1639 bool got_config = false; 1661 bool got_config = false;
1640 if (setting_getter_.get() && 1662 if (setting_getter_.get() &&
1641 setting_getter_->Init(glib_thread_task_runner, file_loop) && 1663 setting_getter_->Init(glib_thread_task_runner_, file_loop) &&
1642 GetConfigFromSettings(&cached_config_)) { 1664 GetConfigFromSettings(&reference_config_)) {
1643 cached_config_.set_id(1); // Mark it as valid. 1665 reference_config_.set_id(1); // Mark it as valid.
1644 cached_config_.set_source(setting_getter_->GetConfigSource()); 1666 reference_config_.set_source(setting_getter_->GetConfigSource());
1645 VLOG(1) << "Obtained proxy settings from " 1667 VLOG(1) << "Obtained proxy settings from "
1646 << ProxyConfigSourceToString(cached_config_.source()); 1668 << ProxyConfigSourceToString(reference_config_.source());
1647 1669
1648 // If gconf proxy mode is "none", meaning direct, then we take 1670 // If gconf proxy mode is "none", meaning direct, then we take
1649 // that to be a valid config and will not check environment 1671 // that to be a valid config and will not check environment
1650 // variables. The alternative would have been to look for a proxy 1672 // variables. The alternative would have been to look for a proxy
1651 // whereever we can find one. 1673 // whereever we can find one.
1652 got_config = true; 1674 got_config = true;
1653 1675
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. 1676 // 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 1677 // 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 1678 // 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 1679 // 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 1680 // 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 1681 // fetch and before setting up notifications. We'll detect the common case
1665 // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it. 1682 // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it.
1666 if (io_thread_task_runner && file_loop) { 1683 if (io_thread_task_runner_ && file_loop) {
1667 scoped_refptr<base::SingleThreadTaskRunner> required_loop = 1684 scoped_refptr<base::SingleThreadTaskRunner> required_loop =
1668 setting_getter_->GetNotificationTaskRunner(); 1685 setting_getter_->GetNotificationTaskRunner();
1669 if (!required_loop || required_loop->BelongsToCurrentThread()) { 1686 if (!required_loop || required_loop->BelongsToCurrentThread()) {
1670 // In this case we are already on an acceptable thread. 1687 // In this case we are already on an acceptable thread.
1671 SetUpNotifications(); 1688 SetUpNotifications();
1672 } else { 1689 } else {
1673 // Post a task to set up notifications. We don't wait for success. 1690 // Post a task to set up notifications. We don't wait for success.
1674 required_loop->PostTask(FROM_HERE, base::Bind( 1691 required_loop->PostTask(FROM_HERE, base::Bind(
1675 &ProxyConfigServiceLinux::Delegate::SetUpNotifications, this)); 1692 &ProxyConfigServiceLinux::Delegate::SetUpNotifications, this));
1676 } 1693 }
1677 } 1694 }
1678 } 1695 }
1679 1696
1680 if (!got_config) { 1697 if (!got_config) {
1681 // We fall back on environment variables. 1698 // We fall back on environment variables.
1682 // 1699 //
1683 // Consulting environment variables doesn't need to be done from the 1700 // 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. 1701 // default glib main loop, but it's a tiny enough amount of work.
1685 if (GetConfigFromEnv(&cached_config_)) { 1702 if (GetConfigFromEnv(&reference_config_)) {
1686 cached_config_.set_source(PROXY_CONFIG_SOURCE_ENV); 1703 reference_config_.set_source(PROXY_CONFIG_SOURCE_ENV);
1687 cached_config_.set_id(1); // Mark it as valid. 1704 reference_config_.set_id(1); // Mark it as valid.
1688 VLOG(1) << "Obtained proxy settings from environment variables"; 1705 VLOG(1) << "Obtained proxy settings from environment variables";
1689 } 1706 }
1690 } 1707 }
1708
1709 // Post a task to the IO thread with the new configuration, so it can
1710 // update |cached_config_|.
1711 io_thread_task_runner_->PostTask(FROM_HERE, base::Bind(
1712 &ProxyConfigServiceLinux::Delegate::SetNewProxyConfig,
1713 this, reference_config_));
1691 } 1714 }
1692 1715
1693 // Depending on the SettingGetter in use, this method will be called 1716 // Depending on the SettingGetter in use, this method will be called
1694 // on either the UI thread (GConf) or the file thread (KDE). 1717 // on either the UI thread (GConf) or the file thread (KDE).
1695 void ProxyConfigServiceLinux::Delegate::SetUpNotifications() { 1718 void ProxyConfigServiceLinux::Delegate::SetUpNotifications() {
1696 scoped_refptr<base::SingleThreadTaskRunner> required_loop = 1719 scoped_refptr<base::SingleThreadTaskRunner> required_loop =
1697 setting_getter_->GetNotificationTaskRunner(); 1720 setting_getter_->GetNotificationTaskRunner();
1698 DCHECK(!required_loop || required_loop->BelongsToCurrentThread()); 1721 DCHECK(!required_loop || required_loop->BelongsToCurrentThread());
1699 if (!setting_getter_->SetUpNotifications(this)) 1722 if (!setting_getter_->SetUpNotifications(this))
1700 LOG(ERROR) << "Unable to set up proxy configuration change notifications"; 1723 LOG(ERROR) << "Unable to set up proxy configuration change notifications";
1701 } 1724 }
1702 1725
1703 void ProxyConfigServiceLinux::Delegate::AddObserver(Observer* observer) { 1726 void ProxyConfigServiceLinux::Delegate::AddObserver(Observer* observer) {
1704 observers_.AddObserver(observer); 1727 observers_.AddObserver(observer);
1705 } 1728 }
1706 1729
1707 void ProxyConfigServiceLinux::Delegate::RemoveObserver(Observer* observer) { 1730 void ProxyConfigServiceLinux::Delegate::RemoveObserver(Observer* observer) {
1708 observers_.RemoveObserver(observer); 1731 observers_.RemoveObserver(observer);
1709 } 1732 }
1710 1733
1711 ProxyConfigService::ConfigAvailability 1734 ProxyConfigService::ConfigAvailability
1712 ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig( 1735 ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig(
1713 ProxyConfig* config) { 1736 ProxyConfig* config) {
1714 // This is called from the IO thread. 1737 // This is called from the IO thread.
1715 DCHECK(!io_thread_task_runner_ || 1738 DCHECK(!io_thread_task_runner_ ||
1716 io_thread_task_runner_->BelongsToCurrentThread()); 1739 io_thread_task_runner_->BelongsToCurrentThread());
1717 1740
1741 if (!finished_initialization_)
1742 return CONFIG_PENDING;
1743
1718 // Simply return the last proxy configuration that glib_default_loop 1744 // Simply return the last proxy configuration that glib_default_loop
1719 // notified us of. 1745 // notified us of.
1720 if (cached_config_.is_valid()) { 1746 if (cached_config_.is_valid()) {
1721 *config = cached_config_; 1747 *config = cached_config_;
1722 } else { 1748 } else {
1723 *config = ProxyConfig::CreateDirect(); 1749 *config = ProxyConfig::CreateDirect();
1724 config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED); 1750 config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED);
1725 } 1751 }
1726 1752
1727 // We return CONFIG_VALID to indicate that *config was filled in. It is always 1753 // 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; 1754 return CONFIG_VALID;
1733 } 1755 }
1734 1756
1735 // Depending on the SettingGetter in use, this method will be called 1757 // Depending on the SettingGetter in use, this method will be called
1736 // on either the UI thread (GConf) or the file thread (KDE). 1758 // on either the UI thread (GConf) or the file thread (KDE).
1737 void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() { 1759 void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() {
1738 scoped_refptr<base::SingleThreadTaskRunner> required_loop = 1760 scoped_refptr<base::SingleThreadTaskRunner> required_loop =
1739 setting_getter_->GetNotificationTaskRunner(); 1761 setting_getter_->GetNotificationTaskRunner();
1740 DCHECK(!required_loop || required_loop->BelongsToCurrentThread()); 1762 DCHECK(!required_loop || required_loop->BelongsToCurrentThread());
1741 ProxyConfig new_config; 1763 ProxyConfig new_config;
(...skipping 14 matching lines...) Expand all
1756 } else { 1778 } else {
1757 VLOG(1) << "Detected no-op change to proxy settings. Doing nothing."; 1779 VLOG(1) << "Detected no-op change to proxy settings. Doing nothing.";
1758 } 1780 }
1759 } 1781 }
1760 1782
1761 void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig( 1783 void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig(
1762 const ProxyConfig& new_config) { 1784 const ProxyConfig& new_config) {
1763 DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); 1785 DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
1764 VLOG(1) << "Proxy configuration changed"; 1786 VLOG(1) << "Proxy configuration changed";
1765 cached_config_ = new_config; 1787 cached_config_ = new_config;
1788 finished_initialization_ = true;
1766 FOR_EACH_OBSERVER( 1789 FOR_EACH_OBSERVER(
1767 Observer, observers_, 1790 Observer, observers_,
1768 OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID)); 1791 OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID));
1769 } 1792 }
1770 1793
1771 void ProxyConfigServiceLinux::Delegate::PostDestroyTask() { 1794 void ProxyConfigServiceLinux::Delegate::PostDestroyTask() {
1772 if (!setting_getter_.get()) 1795 if (!setting_getter_.get())
1773 return; 1796 return;
1774 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop = 1797 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop =
1775 setting_getter_->GetNotificationTaskRunner(); 1798 setting_getter_->GetNotificationTaskRunner();
1776 if (!shutdown_loop || shutdown_loop->BelongsToCurrentThread()) { 1799 if (!shutdown_loop || shutdown_loop->BelongsToCurrentThread()) {
1777 // Already on the right thread, call directly. 1800 // Already on the right thread, call directly.
1778 // This is the case for the unittests. 1801 // This is the case for the unittests.
1779 OnDestroy(); 1802 OnDestroy();
1780 } else { 1803 } else {
1781 // Post to shutdown thread. Note that on browser shutdown, we may quit 1804 // Post to shutdown thread. Note that on browser shutdown, we may quit
1782 // this MessageLoop and exit the program before ever running this. 1805 // this MessageLoop and exit the program before ever running this.
1783 shutdown_loop->PostTask(FROM_HERE, base::Bind( 1806 shutdown_loop->PostTask(FROM_HERE, base::Bind(
1784 &ProxyConfigServiceLinux::Delegate::OnDestroy, this)); 1807 &ProxyConfigServiceLinux::Delegate::OnDestroy, this));
1785 } 1808 }
1786 } 1809 }
1810
1787 void ProxyConfigServiceLinux::Delegate::OnDestroy() { 1811 void ProxyConfigServiceLinux::Delegate::OnDestroy() {
1788 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop = 1812 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop =
1789 setting_getter_->GetNotificationTaskRunner(); 1813 setting_getter_->GetNotificationTaskRunner();
1790 DCHECK(!shutdown_loop || shutdown_loop->BelongsToCurrentThread()); 1814 DCHECK(!shutdown_loop || shutdown_loop->BelongsToCurrentThread());
1791 setting_getter_->ShutDown(); 1815 setting_getter_->ShutDown();
1792 } 1816 }
1793 1817
1794 ProxyConfigServiceLinux::ProxyConfigServiceLinux() 1818
1819 ProxyConfigServiceLinux::ProxyConfigServiceLinux(
1820 base::SingleThreadTaskRunner* glib_thread_task_runner,
1821 base::SingleThreadTaskRunner* io_thread_task_runner,
1822 MessageLoopForIO* file_loop)
1795 : delegate_(new Delegate(base::Environment::Create())) { 1823 : delegate_(new Delegate(base::Environment::Create())) {
1824 SetupAndFetchInitialConfig(glib_thread_task_runner,
1825 io_thread_task_runner,
1826 file_loop);
1796 } 1827 }
1797 1828
1798 ProxyConfigServiceLinux::~ProxyConfigServiceLinux() { 1829 ProxyConfigServiceLinux::~ProxyConfigServiceLinux() {
1830 }
1831
1832 void ProxyConfigServiceLinux::StartTearDown() {
1799 delegate_->PostDestroyTask(); 1833 delegate_->PostDestroyTask();
1800 } 1834 }
1801 1835
1802 ProxyConfigServiceLinux::ProxyConfigServiceLinux( 1836 ProxyConfigServiceLinux::ProxyConfigServiceLinux(
1803 base::Environment* env_var_getter) 1837 base::Environment* env_var_getter)
1804 : delegate_(new Delegate(env_var_getter)) { 1838 : delegate_(new Delegate(env_var_getter)) {
1805 } 1839 }
1806 1840
1807 ProxyConfigServiceLinux::ProxyConfigServiceLinux( 1841 ProxyConfigServiceLinux::ProxyConfigServiceLinux(
1808 base::Environment* env_var_getter, SettingGetter* setting_getter) 1842 base::Environment* env_var_getter, SettingGetter* setting_getter)
1809 : delegate_(new Delegate(env_var_getter, setting_getter)) { 1843 : delegate_(new Delegate(env_var_getter, setting_getter)) {
1810 } 1844 }
1811 1845
1812 void ProxyConfigServiceLinux::AddObserver(Observer* observer) { 1846 void ProxyConfigServiceLinux::AddObserver(Observer* observer) {
1813 delegate_->AddObserver(observer); 1847 delegate_->AddObserver(observer);
1814 } 1848 }
1815 1849
1816 void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) { 1850 void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) {
1817 delegate_->RemoveObserver(observer); 1851 delegate_->RemoveObserver(observer);
1818 } 1852 }
1819 1853
1820 ProxyConfigService::ConfigAvailability 1854 ProxyConfigService::ConfigAvailability
1821 ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) { 1855 ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) {
1822 return delegate_->GetLatestProxyConfig(config); 1856 return delegate_->GetLatestProxyConfig(config);
1823 } 1857 }
1824 1858
1825 } // namespace net 1859 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698