summaryrefslogtreecommitdiffstats
path: root/net/proxy
diff options
context:
space:
mode:
authoreroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-30 06:09:40 +0000
committereroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-30 06:09:40 +0000
commit9328443b6546402da992f1c37ee97d94667a709e (patch)
tree1531485bbbfa635479652a1eca7df85754251a6c /net/proxy
parent39b16c2480c50d79459bc79eaf82d51efdd619c1 (diff)
downloadchromium_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.cc101
-rw-r--r--net/proxy/proxy_config_service_mac.h48
-rw-r--r--net/proxy/proxy_service.cc2
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();