diff options
author | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-30 06:09:40 +0000 |
---|---|---|
committer | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-30 06:09:40 +0000 |
commit | 9328443b6546402da992f1c37ee97d94667a709e (patch) | |
tree | 1531485bbbfa635479652a1eca7df85754251a6c /net/proxy | |
parent | 39b16c2480c50d79459bc79eaf82d51efdd619c1 (diff) | |
download | chromium_src-9328443b6546402da992f1c37ee97d94667a709e.zip chromium_src-9328443b6546402da992f1c37ee97d94667a709e.tar.gz chromium_src-9328443b6546402da992f1c37ee97d94667a709e.tar.bz2 |
Use notification-based API for getting system proxy settings on Mac rather than polling.
BUG=50587
Review URL: http://codereview.chromium.org/3078009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54288 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/proxy')
-rw-r--r-- | net/proxy/proxy_config_service_mac.cc | 101 | ||||
-rw-r--r-- | net/proxy/proxy_config_service_mac.h | 48 | ||||
-rw-r--r-- | net/proxy/proxy_service.cc | 2 |
3 files changed, 142 insertions, 9 deletions
diff --git a/net/proxy/proxy_config_service_mac.cc b/net/proxy/proxy_config_service_mac.cc index 27a0426..38237a56 100644 --- a/net/proxy/proxy_config_service_mac.cc +++ b/net/proxy/proxy_config_service_mac.cc @@ -161,9 +161,104 @@ void GetCurrentProxyConfig(ProxyConfig* config) { } // namespace -ProxyConfigServiceMac::ProxyConfigServiceMac() - : PollingProxyConfigService(base::TimeDelta::FromSeconds(kPollIntervalSec), - &GetCurrentProxyConfig) { +// Reference-counted helper for posting a task to +// ProxyConfigServiceMac::OnProxyConfigChanged between the notifier and IO +// thread. This helper object may outlive the ProxyConfigServiceMac. +class ProxyConfigServiceMac::Helper + : public base::RefCountedThreadSafe<ProxyConfigServiceMac::Helper> { + public: + explicit Helper(ProxyConfigServiceMac* parent) : parent_(parent) { + DCHECK(parent); + } + + // Called when the parent is destroyed. + void Orphan() { + parent_ = NULL; + } + + void OnProxyConfigChanged(const ProxyConfig& new_config) { + if (parent_) + parent_->OnProxyConfigChanged(new_config); + } + + private: + ProxyConfigServiceMac* parent_; +}; + +ProxyConfigServiceMac::ProxyConfigServiceMac(MessageLoop* io_loop) + : has_fetched_config_(false), + helper_(new Helper(this)), + io_loop_(io_loop) { + DCHECK(io_loop); +} + +ProxyConfigServiceMac::~ProxyConfigServiceMac() { + DCHECK_EQ(io_loop_, MessageLoop::current()); + helper_->Orphan(); + io_loop_ = NULL; +} + +void ProxyConfigServiceMac::AddObserver(Observer* observer) { + DCHECK_EQ(io_loop_, MessageLoop::current()); + observers_.AddObserver(observer); +} + +void ProxyConfigServiceMac::RemoveObserver(Observer* observer) { + DCHECK_EQ(io_loop_, MessageLoop::current()); + observers_.RemoveObserver(observer); +} + +bool ProxyConfigServiceMac::GetLatestProxyConfig(ProxyConfig* config) { + DCHECK_EQ(io_loop_, MessageLoop::current()); + + // Lazy-initialize by fetching the proxy setting from this thread. + if (!has_fetched_config_) { + GetCurrentProxyConfig(&last_config_fetched_); + has_fetched_config_ = true; + } + + *config = last_config_fetched_; + return has_fetched_config_; +} + +void ProxyConfigServiceMac::SetDynamicStoreNotificationKeys( + SCDynamicStoreRef store) { + CFStringRef proxies_key = SCDynamicStoreKeyCreateProxies(NULL); + CFArrayRef key_array = CFArrayCreate( + NULL, (const void **)(&proxies_key), 1, &kCFTypeArrayCallBacks); + + bool ret = SCDynamicStoreSetNotificationKeys(store, key_array, NULL); + // TODO(willchan): Figure out a proper way to handle this rather than crash. + CHECK(ret); + + CFRelease(key_array); + CFRelease(proxies_key); +} + +void ProxyConfigServiceMac::OnNetworkConfigChange(CFArrayRef changed_keys) { + // Called on notifier thread. + + // Fetch the new system proxy configuration. + ProxyConfig new_config; + GetCurrentProxyConfig(&new_config); + + // Call OnProxyConfigChanged() on the IO thread to notify our observers. + io_loop_->PostTask( + FROM_HERE, + NewRunnableMethod( + helper_.get(), &Helper::OnProxyConfigChanged, new_config)); +} + +void ProxyConfigServiceMac::OnProxyConfigChanged( + const ProxyConfig& new_config) { + DCHECK_EQ(io_loop_, MessageLoop::current()); + + // Keep track of the last value we have seen. + has_fetched_config_ = true; + last_config_fetched_ = new_config; + + // Notify all the observers. + FOR_EACH_OBSERVER(Observer, observers_, OnProxyConfigChanged(new_config)); } } // namespace net diff --git a/net/proxy/proxy_config_service_mac.h b/net/proxy/proxy_config_service_mac.h index 3602313..fd2d524 100644 --- a/net/proxy/proxy_config_service_mac.h +++ b/net/proxy/proxy_config_service_mac.h @@ -6,15 +6,53 @@ #define NET_PROXY_PROXY_CONFIG_SERVICE_MAC_H_ #pragma once -#include "net/proxy/polling_proxy_config_service.h" +#include "base/basictypes.h" +#include "base/observer_list.h" +#include "base/ref_counted.h" +#include "net/base/network_config_watcher_mac.h" +#include "net/proxy/proxy_config.h" +#include "net/proxy/proxy_config_service.h" namespace net { -// TODO(eroman): Use notification-based system APIs instead of polling for -// changes. -class ProxyConfigServiceMac : public PollingProxyConfigService { +class ProxyConfigServiceMac : public ProxyConfigService, + public NetworkConfigWatcherMac { public: - ProxyConfigServiceMac(); + // Constructs a ProxyConfigService that watches the Mac OS system settings. + // This instance is expected to be operated and deleted on |io_loop| + // (however it may be constructed from a different thread). + explicit ProxyConfigServiceMac(MessageLoop* io_loop); + virtual ~ProxyConfigServiceMac(); + + public: + // ProxyConfigService implementation: + virtual void AddObserver(Observer* observer); + virtual void RemoveObserver(Observer* observer); + virtual bool GetLatestProxyConfig(ProxyConfig* config); + + protected: + // NetworkConfigWatcherMac implementation: + virtual void SetDynamicStoreNotificationKeys(SCDynamicStoreRef store); + virtual void OnNetworkConfigChange(CFArrayRef changed_keys); + + private: + class Helper; + + // Called when the proxy configuration has changed, to notify the observers. + void OnProxyConfigChanged(const ProxyConfig& new_config); + + ObserverList<Observer> observers_; + + // Holds the last system proxy settings that we fetched. + bool has_fetched_config_; + ProxyConfig last_config_fetched_; + + scoped_refptr<Helper> helper_; + + // The thread that we expect to be operated on. + MessageLoop* io_loop_; + + DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceMac); }; } // namespace net diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index d13b1f1..7358f1c 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc @@ -614,7 +614,7 @@ ProxyConfigService* ProxyService::CreateSystemProxyConfigService( #if defined(OS_WIN) return new ProxyConfigServiceWin(); #elif defined(OS_MACOSX) - return new ProxyConfigServiceMac(); + return new ProxyConfigServiceMac(io_loop); #elif defined(OS_LINUX) ProxyConfigServiceLinux* linux_config_service = new ProxyConfigServiceLinux(); |