| Index: net/proxy/proxy_config_service_linux.cc
|
| diff --git a/net/proxy/proxy_config_service_linux.cc b/net/proxy/proxy_config_service_linux.cc
|
| index 1c8e5a367d84f5de9c47ea42f7d72cde7c0f5a6a..831ffbefd4903f5f8725fa9a0dae8446ffaee173 100644
|
| --- a/net/proxy/proxy_config_service_linux.cc
|
| +++ b/net/proxy/proxy_config_service_linux.cc
|
| @@ -285,6 +285,7 @@ class SettingGetterImplGConf : public ProxyConfigServiceLinux::SettingGetter {
|
| client_ = NULL;
|
| task_runner_ = NULL;
|
| }
|
| + debounce_timer_.reset();
|
| }
|
|
|
| virtual bool SetUpNotifications(
|
| @@ -472,10 +473,12 @@ class SettingGetterImplGConf : public ProxyConfigServiceLinux::SettingGetter {
|
| }
|
|
|
| void OnChangeNotification() {
|
| + if (!debounce_timer_.get())
|
| + debounce_timer_.reset(new base::OneShotTimer<SettingGetterImplGConf>());
|
| // We don't use Reset() because the timer may not yet be running.
|
| // (In that case Stop() is a no-op.)
|
| - debounce_timer_.Stop();
|
| - debounce_timer_.Start(FROM_HERE,
|
| + debounce_timer_->Stop();
|
| + debounce_timer_->Start(FROM_HERE,
|
| base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds),
|
| this, &SettingGetterImplGConf::OnDebouncedNotification);
|
| }
|
| @@ -498,7 +501,7 @@ class SettingGetterImplGConf : public ProxyConfigServiceLinux::SettingGetter {
|
| guint system_http_proxy_id_;
|
|
|
| ProxyConfigServiceLinux::Delegate* notify_delegate_;
|
| - base::OneShotTimer<SettingGetterImplGConf> debounce_timer_;
|
| + scoped_ptr<base::OneShotTimer<SettingGetterImplGConf> > debounce_timer_;
|
|
|
| // Task runner for the thread that we make gconf calls on. It should
|
| // be the UI thread and all our methods should be called on this
|
| @@ -610,6 +613,7 @@ class SettingGetterImplGSettings
|
| client_ = NULL;
|
| task_runner_ = NULL;
|
| }
|
| + debounce_timer_.reset();
|
| }
|
|
|
| virtual bool SetUpNotifications(
|
| @@ -787,10 +791,13 @@ class SettingGetterImplGSettings
|
| }
|
|
|
| void OnChangeNotification() {
|
| + if (!debounce_timer_.get())
|
| + debounce_timer_.reset(
|
| + new base::OneShotTimer<SettingGetterImplGSettings>());
|
| // We don't use Reset() because the timer may not yet be running.
|
| // (In that case Stop() is a no-op.)
|
| - debounce_timer_.Stop();
|
| - debounce_timer_.Start(FROM_HERE,
|
| + debounce_timer_->Stop();
|
| + debounce_timer_->Start(FROM_HERE,
|
| base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds),
|
| this, &SettingGetterImplGSettings::OnDebouncedNotification);
|
| }
|
| @@ -811,7 +818,7 @@ class SettingGetterImplGSettings
|
| GSettings* ftp_client_;
|
| GSettings* socks_client_;
|
| ProxyConfigServiceLinux::Delegate* notify_delegate_;
|
| - base::OneShotTimer<SettingGetterImplGSettings> debounce_timer_;
|
| + scoped_ptr<base::OneShotTimer<SettingGetterImplGSettings> > debounce_timer_;
|
|
|
| // Task runner for the thread that we make gsettings calls on. It should
|
| // be the UI thread and all our methods should be called on this
|
| @@ -1011,6 +1018,7 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter,
|
| close(inotify_fd_);
|
| inotify_fd_ = -1;
|
| }
|
| + debounce_timer_.reset();
|
| }
|
|
|
| virtual bool SetUpNotifications(
|
| @@ -1362,8 +1370,10 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter,
|
| if (kioslaverc_touched) {
|
| // We don't use Reset() because the timer may not yet be running.
|
| // (In that case Stop() is a no-op.)
|
| - debounce_timer_.Stop();
|
| - debounce_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(
|
| + if (!debounce_timer_.get())
|
| + debounce_timer_.reset(new base::OneShotTimer<SettingGetterImplKDE>());
|
| + debounce_timer_->Stop();
|
| + debounce_timer_->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(
|
| kDebounceTimeoutMilliseconds), this,
|
| &SettingGetterImplKDE::OnDebouncedNotification);
|
| }
|
| @@ -1376,7 +1386,7 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter,
|
| int inotify_fd_;
|
| base::MessagePumpLibevent::FileDescriptorWatcher inotify_watcher_;
|
| ProxyConfigServiceLinux::Delegate* notify_delegate_;
|
| - base::OneShotTimer<SettingGetterImplKDE> debounce_timer_;
|
| + scoped_ptr<base::OneShotTimer<SettingGetterImplKDE> > debounce_timer_;
|
| FilePath kde_config_dir_;
|
| bool indirect_manual_;
|
| bool auto_no_pac_;
|
| @@ -1604,19 +1614,31 @@ ProxyConfigServiceLinux::Delegate::Delegate(base::Environment* env_var_getter)
|
|
|
| ProxyConfigServiceLinux::Delegate::Delegate(
|
| base::Environment* env_var_getter, SettingGetter* setting_getter)
|
| - : env_var_getter_(env_var_getter), setting_getter_(setting_getter) {
|
| + : env_var_getter_(env_var_getter), setting_getter_(setting_getter),
|
| + finished_initialization_(false) {
|
| }
|
|
|
| void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig(
|
| base::SingleThreadTaskRunner* glib_thread_task_runner,
|
| base::SingleThreadTaskRunner* io_thread_task_runner,
|
| MessageLoopForIO* file_loop) {
|
| - // We should be running on the default glib main loop thread right
|
| - // now. gconf can only be accessed from this thread.
|
| - DCHECK(glib_thread_task_runner->BelongsToCurrentThread());
|
| + DCHECK(io_thread_task_runner->BelongsToCurrentThread());
|
| +
|
| glib_thread_task_runner_ = glib_thread_task_runner;
|
| io_thread_task_runner_ = io_thread_task_runner;
|
|
|
| + glib_thread_task_runner->PostTask(FROM_HERE, base::Bind(
|
| + &Delegate::SetUpAndFetchInitialConfigOnUIThread,
|
| + this,
|
| + file_loop));
|
| +}
|
| +
|
| +void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfigOnUIThread(
|
| + MessageLoopForIO* file_loop) {
|
| + // We should be running on the default glib main loop thread right
|
| + // now. gconf can only be accessed from this thread.
|
| + DCHECK(glib_thread_task_runner_->BelongsToCurrentThread());
|
| +
|
| // If we are passed a NULL |io_thread_task_runner| or |file_loop|,
|
| // then we don't set up proxy setting change notifications. This
|
| // should not be the usual case but is intended to simplify test
|
| @@ -1638,12 +1660,12 @@ void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig(
|
|
|
| bool got_config = false;
|
| if (setting_getter_.get() &&
|
| - setting_getter_->Init(glib_thread_task_runner, file_loop) &&
|
| - GetConfigFromSettings(&cached_config_)) {
|
| - cached_config_.set_id(1); // Mark it as valid.
|
| - cached_config_.set_source(setting_getter_->GetConfigSource());
|
| + setting_getter_->Init(glib_thread_task_runner_, file_loop) &&
|
| + GetConfigFromSettings(&reference_config_)) {
|
| + reference_config_.set_id(1); // Mark it as valid.
|
| + reference_config_.set_source(setting_getter_->GetConfigSource());
|
| VLOG(1) << "Obtained proxy settings from "
|
| - << ProxyConfigSourceToString(cached_config_.source());
|
| + << ProxyConfigSourceToString(reference_config_.source());
|
|
|
| // If gconf proxy mode is "none", meaning direct, then we take
|
| // that to be a valid config and will not check environment
|
| @@ -1651,11 +1673,6 @@ void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig(
|
| // whereever we can find one.
|
| got_config = true;
|
|
|
| - // Keep a copy of the config for use from this thread for
|
| - // comparison with updated settings when we get notifications.
|
| - reference_config_ = cached_config_;
|
| - reference_config_.set_id(1); // Mark it as valid.
|
| -
|
| // We only set up notifications if we have IO and file loops available.
|
| // We do this after getting the initial configuration so that we don't have
|
| // to worry about cancelling it if the initial fetch above fails. Note that
|
| @@ -1663,7 +1680,7 @@ void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig(
|
| // that we won't lose any updates that may have happened after the initial
|
| // fetch and before setting up notifications. We'll detect the common case
|
| // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it.
|
| - if (io_thread_task_runner && file_loop) {
|
| + if (io_thread_task_runner_ && file_loop) {
|
| scoped_refptr<base::SingleThreadTaskRunner> required_loop =
|
| setting_getter_->GetNotificationTaskRunner();
|
| if (!required_loop || required_loop->BelongsToCurrentThread()) {
|
| @@ -1682,12 +1699,18 @@ void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig(
|
| //
|
| // Consulting environment variables doesn't need to be done from the
|
| // default glib main loop, but it's a tiny enough amount of work.
|
| - if (GetConfigFromEnv(&cached_config_)) {
|
| - cached_config_.set_source(PROXY_CONFIG_SOURCE_ENV);
|
| - cached_config_.set_id(1); // Mark it as valid.
|
| + if (GetConfigFromEnv(&reference_config_)) {
|
| + reference_config_.set_source(PROXY_CONFIG_SOURCE_ENV);
|
| + reference_config_.set_id(1); // Mark it as valid.
|
| VLOG(1) << "Obtained proxy settings from environment variables";
|
| }
|
| }
|
| +
|
| + // Post a task to the IO thread with the new configuration, so it can
|
| + // update |cached_config_|.
|
| + io_thread_task_runner_->PostTask(FROM_HERE, base::Bind(
|
| + &ProxyConfigServiceLinux::Delegate::SetNewProxyConfig,
|
| + this, reference_config_));
|
| }
|
|
|
| // Depending on the SettingGetter in use, this method will be called
|
| @@ -1715,6 +1738,9 @@ ProxyConfigService::ConfigAvailability
|
| DCHECK(!io_thread_task_runner_ ||
|
| io_thread_task_runner_->BelongsToCurrentThread());
|
|
|
| + if (!finished_initialization_)
|
| + return CONFIG_PENDING;
|
| +
|
| // Simply return the last proxy configuration that glib_default_loop
|
| // notified us of.
|
| if (cached_config_.is_valid()) {
|
| @@ -1724,11 +1750,7 @@ ProxyConfigService::ConfigAvailability
|
| config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED);
|
| }
|
|
|
| - // We return CONFIG_VALID to indicate that *config was filled in. It is always
|
| - // going to be available since we initialized eagerly on the UI thread.
|
| - // TODO(eroman): do lazy initialization instead, so we no longer need
|
| - // to construct ProxyConfigServiceLinux on the UI thread.
|
| - // In which case, we may return false here.
|
| + // We return CONFIG_VALID to indicate that *config was filled in.
|
| return CONFIG_VALID;
|
| }
|
|
|
| @@ -1763,6 +1785,7 @@ void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig(
|
| DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
|
| VLOG(1) << "Proxy configuration changed";
|
| cached_config_ = new_config;
|
| + finished_initialization_ = true;
|
| FOR_EACH_OBSERVER(
|
| Observer, observers_,
|
| OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID));
|
| @@ -1784,6 +1807,7 @@ void ProxyConfigServiceLinux::Delegate::PostDestroyTask() {
|
| &ProxyConfigServiceLinux::Delegate::OnDestroy, this));
|
| }
|
| }
|
| +
|
| void ProxyConfigServiceLinux::Delegate::OnDestroy() {
|
| scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop =
|
| setting_getter_->GetNotificationTaskRunner();
|
| @@ -1791,11 +1815,21 @@ void ProxyConfigServiceLinux::Delegate::OnDestroy() {
|
| setting_getter_->ShutDown();
|
| }
|
|
|
| -ProxyConfigServiceLinux::ProxyConfigServiceLinux()
|
| +
|
| +ProxyConfigServiceLinux::ProxyConfigServiceLinux(
|
| + base::SingleThreadTaskRunner* glib_thread_task_runner,
|
| + base::SingleThreadTaskRunner* io_thread_task_runner,
|
| + MessageLoopForIO* file_loop)
|
| : delegate_(new Delegate(base::Environment::Create())) {
|
| + SetupAndFetchInitialConfig(glib_thread_task_runner,
|
| + io_thread_task_runner,
|
| + file_loop);
|
| }
|
|
|
| ProxyConfigServiceLinux::~ProxyConfigServiceLinux() {
|
| +}
|
| +
|
| +void ProxyConfigServiceLinux::StartTearDown() {
|
| delegate_->PostDestroyTask();
|
| }
|
|
|
|
|