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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 LOG(FATAL) << "~SettingGetterImplGConf: deleting on wrong thread!"; | 227 LOG(FATAL) << "~SettingGetterImplGConf: deleting on wrong thread!"; |
228 } | 228 } |
229 } | 229 } |
230 DCHECK(!client_); | 230 DCHECK(!client_); |
231 } | 231 } |
232 | 232 |
233 virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner, | 233 virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner, |
234 base::MessageLoopForIO* file_loop) OVERRIDE { | 234 base::MessageLoopForIO* file_loop) OVERRIDE { |
235 DCHECK(glib_thread_task_runner->BelongsToCurrentThread()); | 235 DCHECK(glib_thread_task_runner->BelongsToCurrentThread()); |
236 DCHECK(!client_); | 236 DCHECK(!client_); |
237 DCHECK(!task_runner_); | 237 DCHECK(!task_runner_.get()); |
238 task_runner_ = glib_thread_task_runner; | 238 task_runner_ = glib_thread_task_runner; |
239 client_ = gconf_client_get_default(); | 239 client_ = gconf_client_get_default(); |
240 if (!client_) { | 240 if (!client_) { |
241 // It's not clear whether/when this can return NULL. | 241 // It's not clear whether/when this can return NULL. |
242 LOG(ERROR) << "Unable to create a gconf client"; | 242 LOG(ERROR) << "Unable to create a gconf client"; |
243 task_runner_ = NULL; | 243 task_runner_ = NULL; |
244 return false; | 244 return false; |
245 } | 245 } |
246 GError* error = NULL; | 246 GError* error = NULL; |
247 bool added_system_proxy = false; | 247 bool added_system_proxy = false; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 g_error_free(error); | 310 g_error_free(error); |
311 ShutDown(); | 311 ShutDown(); |
312 return false; | 312 return false; |
313 } | 313 } |
314 // Simulate a change to avoid possibly losing updates before this point. | 314 // Simulate a change to avoid possibly losing updates before this point. |
315 OnChangeNotification(); | 315 OnChangeNotification(); |
316 return true; | 316 return true; |
317 } | 317 } |
318 | 318 |
319 virtual base::SingleThreadTaskRunner* GetNotificationTaskRunner() OVERRIDE { | 319 virtual base::SingleThreadTaskRunner* GetNotificationTaskRunner() OVERRIDE { |
320 return task_runner_; | 320 return task_runner_.get(); |
321 } | 321 } |
322 | 322 |
323 virtual ProxyConfigSource GetConfigSource() OVERRIDE { | 323 virtual ProxyConfigSource GetConfigSource() OVERRIDE { |
324 return PROXY_CONFIG_SOURCE_GCONF; | 324 return PROXY_CONFIG_SOURCE_GCONF; |
325 } | 325 } |
326 | 326 |
327 virtual bool GetString(StringSetting key, std::string* result) OVERRIDE { | 327 virtual bool GetString(StringSetting key, std::string* result) OVERRIDE { |
328 switch (key) { | 328 switch (key) { |
329 case PROXY_MODE: | 329 case PROXY_MODE: |
330 return GetStringByPath("/system/proxy/mode", result); | 330 return GetStringByPath("/system/proxy/mode", result); |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 return false; | 555 return false; |
556 } | 556 } |
557 | 557 |
558 // LoadAndCheckVersion() must be called *before* Init()! | 558 // LoadAndCheckVersion() must be called *before* Init()! |
559 bool LoadAndCheckVersion(base::Environment* env); | 559 bool LoadAndCheckVersion(base::Environment* env); |
560 | 560 |
561 virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner, | 561 virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner, |
562 base::MessageLoopForIO* file_loop) OVERRIDE { | 562 base::MessageLoopForIO* file_loop) OVERRIDE { |
563 DCHECK(glib_thread_task_runner->BelongsToCurrentThread()); | 563 DCHECK(glib_thread_task_runner->BelongsToCurrentThread()); |
564 DCHECK(!client_); | 564 DCHECK(!client_); |
565 DCHECK(!task_runner_); | 565 DCHECK(!task_runner_.get()); |
566 | 566 |
567 if (!SchemaExists("org.gnome.system.proxy") || | 567 if (!SchemaExists("org.gnome.system.proxy") || |
568 !(client_ = libgio_loader_.g_settings_new("org.gnome.system.proxy"))) { | 568 !(client_ = libgio_loader_.g_settings_new("org.gnome.system.proxy"))) { |
569 // It's not clear whether/when this can return NULL. | 569 // It's not clear whether/when this can return NULL. |
570 LOG(ERROR) << "Unable to create a gsettings client"; | 570 LOG(ERROR) << "Unable to create a gsettings client"; |
571 return false; | 571 return false; |
572 } | 572 } |
573 task_runner_ = glib_thread_task_runner; | 573 task_runner_ = glib_thread_task_runner; |
574 // We assume these all work if the above call worked. | 574 // We assume these all work if the above call worked. |
575 http_client_ = libgio_loader_.g_settings_get_child(client_, "http"); | 575 http_client_ = libgio_loader_.g_settings_get_child(client_, "http"); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 g_signal_connect(G_OBJECT(ftp_client_), "changed", | 612 g_signal_connect(G_OBJECT(ftp_client_), "changed", |
613 G_CALLBACK(OnGSettingsChangeNotification), this); | 613 G_CALLBACK(OnGSettingsChangeNotification), this); |
614 g_signal_connect(G_OBJECT(socks_client_), "changed", | 614 g_signal_connect(G_OBJECT(socks_client_), "changed", |
615 G_CALLBACK(OnGSettingsChangeNotification), this); | 615 G_CALLBACK(OnGSettingsChangeNotification), this); |
616 // Simulate a change to avoid possibly losing updates before this point. | 616 // Simulate a change to avoid possibly losing updates before this point. |
617 OnChangeNotification(); | 617 OnChangeNotification(); |
618 return true; | 618 return true; |
619 } | 619 } |
620 | 620 |
621 virtual base::SingleThreadTaskRunner* GetNotificationTaskRunner() OVERRIDE { | 621 virtual base::SingleThreadTaskRunner* GetNotificationTaskRunner() OVERRIDE { |
622 return task_runner_; | 622 return task_runner_.get(); |
623 } | 623 } |
624 | 624 |
625 virtual ProxyConfigSource GetConfigSource() OVERRIDE { | 625 virtual ProxyConfigSource GetConfigSource() OVERRIDE { |
626 return PROXY_CONFIG_SOURCE_GSETTINGS; | 626 return PROXY_CONFIG_SOURCE_GSETTINGS; |
627 } | 627 } |
628 | 628 |
629 virtual bool GetString(StringSetting key, std::string* result) OVERRIDE { | 629 virtual bool GetString(StringSetting key, std::string* result) OVERRIDE { |
630 DCHECK(client_); | 630 DCHECK(client_); |
631 switch (key) { | 631 switch (key) { |
632 case PROXY_MODE: | 632 case PROXY_MODE: |
(...skipping 922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1555 // We should be running on the default glib main loop thread right | 1555 // We should be running on the default glib main loop thread right |
1556 // now. gconf can only be accessed from this thread. | 1556 // now. gconf can only be accessed from this thread. |
1557 DCHECK(glib_thread_task_runner->BelongsToCurrentThread()); | 1557 DCHECK(glib_thread_task_runner->BelongsToCurrentThread()); |
1558 glib_thread_task_runner_ = glib_thread_task_runner; | 1558 glib_thread_task_runner_ = glib_thread_task_runner; |
1559 io_thread_task_runner_ = io_thread_task_runner; | 1559 io_thread_task_runner_ = io_thread_task_runner; |
1560 | 1560 |
1561 // If we are passed a NULL |io_thread_task_runner| or |file_loop|, | 1561 // If we are passed a NULL |io_thread_task_runner| or |file_loop|, |
1562 // then we don't set up proxy setting change notifications. This | 1562 // then we don't set up proxy setting change notifications. This |
1563 // should not be the usual case but is intended to simplify test | 1563 // should not be the usual case but is intended to simplify test |
1564 // setups. | 1564 // setups. |
1565 if (!io_thread_task_runner_ || !file_loop) | 1565 if (!io_thread_task_runner_.get() || !file_loop) |
1566 VLOG(1) << "Monitoring of proxy setting changes is disabled"; | 1566 VLOG(1) << "Monitoring of proxy setting changes is disabled"; |
1567 | 1567 |
1568 // Fetch and cache the current proxy config. The config is left in | 1568 // Fetch and cache the current proxy config. The config is left in |
1569 // cached_config_, where GetLatestProxyConfig() running on the IO thread | 1569 // cached_config_, where GetLatestProxyConfig() running on the IO thread |
1570 // will expect to find it. This is safe to do because we return | 1570 // will expect to find it. This is safe to do because we return |
1571 // before this ProxyConfigServiceLinux is passed on to | 1571 // before this ProxyConfigServiceLinux is passed on to |
1572 // the ProxyService. | 1572 // the ProxyService. |
1573 | 1573 |
1574 // Note: It would be nice to prioritize environment variables | 1574 // Note: It would be nice to prioritize environment variables |
1575 // and only fall back to gconf if env vars were unset. But | 1575 // and only fall back to gconf if env vars were unset. But |
(...skipping 24 matching lines...) Expand all Loading... |
1600 // We only set up notifications if we have IO and file loops available. | 1600 // We only set up notifications if we have IO and file loops available. |
1601 // We do this after getting the initial configuration so that we don't have | 1601 // We do this after getting the initial configuration so that we don't have |
1602 // to worry about cancelling it if the initial fetch above fails. Note that | 1602 // to worry about cancelling it if the initial fetch above fails. Note that |
1603 // setting up notifications has the side effect of simulating a change, so | 1603 // setting up notifications has the side effect of simulating a change, so |
1604 // that we won't lose any updates that may have happened after the initial | 1604 // that we won't lose any updates that may have happened after the initial |
1605 // fetch and before setting up notifications. We'll detect the common case | 1605 // fetch and before setting up notifications. We'll detect the common case |
1606 // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it. | 1606 // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it. |
1607 if (io_thread_task_runner && file_loop) { | 1607 if (io_thread_task_runner && file_loop) { |
1608 scoped_refptr<base::SingleThreadTaskRunner> required_loop = | 1608 scoped_refptr<base::SingleThreadTaskRunner> required_loop = |
1609 setting_getter_->GetNotificationTaskRunner(); | 1609 setting_getter_->GetNotificationTaskRunner(); |
1610 if (!required_loop || required_loop->BelongsToCurrentThread()) { | 1610 if (!required_loop.get() || required_loop->BelongsToCurrentThread()) { |
1611 // In this case we are already on an acceptable thread. | 1611 // In this case we are already on an acceptable thread. |
1612 SetUpNotifications(); | 1612 SetUpNotifications(); |
1613 } else { | 1613 } else { |
1614 // Post a task to set up notifications. We don't wait for success. | 1614 // Post a task to set up notifications. We don't wait for success. |
1615 required_loop->PostTask(FROM_HERE, base::Bind( | 1615 required_loop->PostTask(FROM_HERE, base::Bind( |
1616 &ProxyConfigServiceLinux::Delegate::SetUpNotifications, this)); | 1616 &ProxyConfigServiceLinux::Delegate::SetUpNotifications, this)); |
1617 } | 1617 } |
1618 } | 1618 } |
1619 } | 1619 } |
1620 | 1620 |
1621 if (!got_config) { | 1621 if (!got_config) { |
1622 // We fall back on environment variables. | 1622 // We fall back on environment variables. |
1623 // | 1623 // |
1624 // Consulting environment variables doesn't need to be done from the | 1624 // Consulting environment variables doesn't need to be done from the |
1625 // default glib main loop, but it's a tiny enough amount of work. | 1625 // default glib main loop, but it's a tiny enough amount of work. |
1626 if (GetConfigFromEnv(&cached_config_)) { | 1626 if (GetConfigFromEnv(&cached_config_)) { |
1627 cached_config_.set_source(PROXY_CONFIG_SOURCE_ENV); | 1627 cached_config_.set_source(PROXY_CONFIG_SOURCE_ENV); |
1628 cached_config_.set_id(1); // Mark it as valid. | 1628 cached_config_.set_id(1); // Mark it as valid. |
1629 VLOG(1) << "Obtained proxy settings from environment variables"; | 1629 VLOG(1) << "Obtained proxy settings from environment variables"; |
1630 } | 1630 } |
1631 } | 1631 } |
1632 } | 1632 } |
1633 | 1633 |
1634 // Depending on the SettingGetter in use, this method will be called | 1634 // Depending on the SettingGetter in use, this method will be called |
1635 // on either the UI thread (GConf) or the file thread (KDE). | 1635 // on either the UI thread (GConf) or the file thread (KDE). |
1636 void ProxyConfigServiceLinux::Delegate::SetUpNotifications() { | 1636 void ProxyConfigServiceLinux::Delegate::SetUpNotifications() { |
1637 scoped_refptr<base::SingleThreadTaskRunner> required_loop = | 1637 scoped_refptr<base::SingleThreadTaskRunner> required_loop = |
1638 setting_getter_->GetNotificationTaskRunner(); | 1638 setting_getter_->GetNotificationTaskRunner(); |
1639 DCHECK(!required_loop || required_loop->BelongsToCurrentThread()); | 1639 DCHECK(!required_loop.get() || required_loop->BelongsToCurrentThread()); |
1640 if (!setting_getter_->SetUpNotifications(this)) | 1640 if (!setting_getter_->SetUpNotifications(this)) |
1641 LOG(ERROR) << "Unable to set up proxy configuration change notifications"; | 1641 LOG(ERROR) << "Unable to set up proxy configuration change notifications"; |
1642 } | 1642 } |
1643 | 1643 |
1644 void ProxyConfigServiceLinux::Delegate::AddObserver(Observer* observer) { | 1644 void ProxyConfigServiceLinux::Delegate::AddObserver(Observer* observer) { |
1645 observers_.AddObserver(observer); | 1645 observers_.AddObserver(observer); |
1646 } | 1646 } |
1647 | 1647 |
1648 void ProxyConfigServiceLinux::Delegate::RemoveObserver(Observer* observer) { | 1648 void ProxyConfigServiceLinux::Delegate::RemoveObserver(Observer* observer) { |
1649 observers_.RemoveObserver(observer); | 1649 observers_.RemoveObserver(observer); |
1650 } | 1650 } |
1651 | 1651 |
1652 ProxyConfigService::ConfigAvailability | 1652 ProxyConfigService::ConfigAvailability |
1653 ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig( | 1653 ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig( |
1654 ProxyConfig* config) { | 1654 ProxyConfig* config) { |
1655 // This is called from the IO thread. | 1655 // This is called from the IO thread. |
1656 DCHECK(!io_thread_task_runner_ || | 1656 DCHECK(!io_thread_task_runner_.get() || |
1657 io_thread_task_runner_->BelongsToCurrentThread()); | 1657 io_thread_task_runner_->BelongsToCurrentThread()); |
1658 | 1658 |
1659 // Simply return the last proxy configuration that glib_default_loop | 1659 // Simply return the last proxy configuration that glib_default_loop |
1660 // notified us of. | 1660 // notified us of. |
1661 if (cached_config_.is_valid()) { | 1661 if (cached_config_.is_valid()) { |
1662 *config = cached_config_; | 1662 *config = cached_config_; |
1663 } else { | 1663 } else { |
1664 *config = ProxyConfig::CreateDirect(); | 1664 *config = ProxyConfig::CreateDirect(); |
1665 config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED); | 1665 config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED); |
1666 } | 1666 } |
1667 | 1667 |
1668 // We return CONFIG_VALID to indicate that *config was filled in. It is always | 1668 // We return CONFIG_VALID to indicate that *config was filled in. It is always |
1669 // going to be available since we initialized eagerly on the UI thread. | 1669 // going to be available since we initialized eagerly on the UI thread. |
1670 // TODO(eroman): do lazy initialization instead, so we no longer need | 1670 // TODO(eroman): do lazy initialization instead, so we no longer need |
1671 // to construct ProxyConfigServiceLinux on the UI thread. | 1671 // to construct ProxyConfigServiceLinux on the UI thread. |
1672 // In which case, we may return false here. | 1672 // In which case, we may return false here. |
1673 return CONFIG_VALID; | 1673 return CONFIG_VALID; |
1674 } | 1674 } |
1675 | 1675 |
1676 // Depending on the SettingGetter in use, this method will be called | 1676 // Depending on the SettingGetter in use, this method will be called |
1677 // on either the UI thread (GConf) or the file thread (KDE). | 1677 // on either the UI thread (GConf) or the file thread (KDE). |
1678 void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() { | 1678 void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() { |
1679 scoped_refptr<base::SingleThreadTaskRunner> required_loop = | 1679 scoped_refptr<base::SingleThreadTaskRunner> required_loop = |
1680 setting_getter_->GetNotificationTaskRunner(); | 1680 setting_getter_->GetNotificationTaskRunner(); |
1681 DCHECK(!required_loop || required_loop->BelongsToCurrentThread()); | 1681 DCHECK(!required_loop.get() || required_loop->BelongsToCurrentThread()); |
1682 ProxyConfig new_config; | 1682 ProxyConfig new_config; |
1683 bool valid = GetConfigFromSettings(&new_config); | 1683 bool valid = GetConfigFromSettings(&new_config); |
1684 if (valid) | 1684 if (valid) |
1685 new_config.set_id(1); // mark it as valid | 1685 new_config.set_id(1); // mark it as valid |
1686 | 1686 |
1687 // See if it is different from what we had before. | 1687 // See if it is different from what we had before. |
1688 if (new_config.is_valid() != reference_config_.is_valid() || | 1688 if (new_config.is_valid() != reference_config_.is_valid() || |
1689 !new_config.Equals(reference_config_)) { | 1689 !new_config.Equals(reference_config_)) { |
1690 // Post a task to the IO thread with the new configuration, so it can | 1690 // Post a task to the IO thread with the new configuration, so it can |
1691 // update |cached_config_|. | 1691 // update |cached_config_|. |
(...skipping 15 matching lines...) Expand all Loading... |
1707 FOR_EACH_OBSERVER( | 1707 FOR_EACH_OBSERVER( |
1708 Observer, observers_, | 1708 Observer, observers_, |
1709 OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID)); | 1709 OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID)); |
1710 } | 1710 } |
1711 | 1711 |
1712 void ProxyConfigServiceLinux::Delegate::PostDestroyTask() { | 1712 void ProxyConfigServiceLinux::Delegate::PostDestroyTask() { |
1713 if (!setting_getter_.get()) | 1713 if (!setting_getter_.get()) |
1714 return; | 1714 return; |
1715 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop = | 1715 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop = |
1716 setting_getter_->GetNotificationTaskRunner(); | 1716 setting_getter_->GetNotificationTaskRunner(); |
1717 if (!shutdown_loop || shutdown_loop->BelongsToCurrentThread()) { | 1717 if (!shutdown_loop.get() || shutdown_loop->BelongsToCurrentThread()) { |
1718 // Already on the right thread, call directly. | 1718 // Already on the right thread, call directly. |
1719 // This is the case for the unittests. | 1719 // This is the case for the unittests. |
1720 OnDestroy(); | 1720 OnDestroy(); |
1721 } else { | 1721 } else { |
1722 // Post to shutdown thread. Note that on browser shutdown, we may quit | 1722 // Post to shutdown thread. Note that on browser shutdown, we may quit |
1723 // this MessageLoop and exit the program before ever running this. | 1723 // this MessageLoop and exit the program before ever running this. |
1724 shutdown_loop->PostTask(FROM_HERE, base::Bind( | 1724 shutdown_loop->PostTask(FROM_HERE, base::Bind( |
1725 &ProxyConfigServiceLinux::Delegate::OnDestroy, this)); | 1725 &ProxyConfigServiceLinux::Delegate::OnDestroy, this)); |
1726 } | 1726 } |
1727 } | 1727 } |
1728 void ProxyConfigServiceLinux::Delegate::OnDestroy() { | 1728 void ProxyConfigServiceLinux::Delegate::OnDestroy() { |
1729 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop = | 1729 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop = |
1730 setting_getter_->GetNotificationTaskRunner(); | 1730 setting_getter_->GetNotificationTaskRunner(); |
1731 DCHECK(!shutdown_loop || shutdown_loop->BelongsToCurrentThread()); | 1731 DCHECK(!shutdown_loop.get() || shutdown_loop->BelongsToCurrentThread()); |
1732 setting_getter_->ShutDown(); | 1732 setting_getter_->ShutDown(); |
1733 } | 1733 } |
1734 | 1734 |
1735 ProxyConfigServiceLinux::ProxyConfigServiceLinux() | 1735 ProxyConfigServiceLinux::ProxyConfigServiceLinux() |
1736 : delegate_(new Delegate(base::Environment::Create())) { | 1736 : delegate_(new Delegate(base::Environment::Create())) { |
1737 } | 1737 } |
1738 | 1738 |
1739 ProxyConfigServiceLinux::~ProxyConfigServiceLinux() { | 1739 ProxyConfigServiceLinux::~ProxyConfigServiceLinux() { |
1740 delegate_->PostDestroyTask(); | 1740 delegate_->PostDestroyTask(); |
1741 } | 1741 } |
(...skipping 15 matching lines...) Expand all Loading... |
1757 void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) { | 1757 void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) { |
1758 delegate_->RemoveObserver(observer); | 1758 delegate_->RemoveObserver(observer); |
1759 } | 1759 } |
1760 | 1760 |
1761 ProxyConfigService::ConfigAvailability | 1761 ProxyConfigService::ConfigAvailability |
1762 ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) { | 1762 ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) { |
1763 return delegate_->GetLatestProxyConfig(config); | 1763 return delegate_->GetLatestProxyConfig(config); |
1764 } | 1764 } |
1765 | 1765 |
1766 } // namespace net | 1766 } // namespace net |
OLD | NEW |