OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |