// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/proxy/proxy_config_service_linux.h"

#include <errno.h>
#include <fcntl.h>
#if defined(USE_GCONF)
#include <gconf/gconf-client.h>
#endif  // defined(USE_GCONF)
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <unistd.h>

#include <map>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/environment.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/nix/xdg_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/timer/timer.h"
#include "net/base/net_errors.h"
#include "net/http/http_util.h"
#include "net/proxy/proxy_config.h"
#include "net/proxy/proxy_server.h"
#include "url/url_canon.h"

#if defined(USE_GIO)
#include "library_loaders/libgio.h"
#endif  // defined(USE_GIO)

namespace net {

namespace {

// Given a proxy hostname from a setting, returns that hostname with
// an appropriate proxy server scheme prefix.
// scheme indicates the desired proxy scheme: usually http, with
// socks 4 or 5 as special cases.
// TODO(arindam): Remove URI string manipulation by using MapUrlSchemeToProxy.
std::string FixupProxyHostScheme(ProxyServer::Scheme scheme,
                                 std::string host) {
  if (scheme == ProxyServer::SCHEME_SOCKS5 &&
      StartsWithASCII(host, "socks4://", false)) {
    // We default to socks 5, but if the user specifically set it to
    // socks4://, then use that.
    scheme = ProxyServer::SCHEME_SOCKS4;
  }
  // Strip the scheme if any.
  std::string::size_type colon = host.find("://");
  if (colon != std::string::npos)
    host = host.substr(colon + 3);
  // If a username and perhaps password are specified, give a warning.
  std::string::size_type at_sign = host.find("@");
  // Should this be supported?
  if (at_sign != std::string::npos) {
    // ProxyConfig does not support authentication parameters, but Chrome
    // will prompt for the password later. Disregard the
    // authentication parameters and continue with this hostname.
    LOG(WARNING) << "Proxy authentication parameters ignored, see bug 16709";
    host = host.substr(at_sign + 1);
  }
  // If this is a socks proxy, prepend a scheme so as to tell
  // ProxyServer. This also allows ProxyServer to choose the right
  // default port.
  if (scheme == ProxyServer::SCHEME_SOCKS4)
    host = "socks4://" + host;
  else if (scheme == ProxyServer::SCHEME_SOCKS5)
    host = "socks5://" + host;
  // If there is a trailing slash, remove it so |host| will parse correctly
  // even if it includes a port number (since the slash is not numeric).
  if (host.length() && host[host.length() - 1] == '/')
    host.resize(host.length() - 1);
  return host;
}

}  // namespace

ProxyConfigServiceLinux::Delegate::~Delegate() {
}

bool ProxyConfigServiceLinux::Delegate::GetProxyFromEnvVarForScheme(
    const char* variable, ProxyServer::Scheme scheme,
    ProxyServer* result_server) {
  std::string env_value;
  if (env_var_getter_->GetVar(variable, &env_value)) {
    if (!env_value.empty()) {
      env_value = FixupProxyHostScheme(scheme, env_value);
      ProxyServer proxy_server =
          ProxyServer::FromURI(env_value, ProxyServer::SCHEME_HTTP);
      if (proxy_server.is_valid() && !proxy_server.is_direct()) {
        *result_server = proxy_server;
        return true;
      } else {
        LOG(ERROR) << "Failed to parse environment variable " << variable;
      }
    }
  }
  return false;
}

bool ProxyConfigServiceLinux::Delegate::GetProxyFromEnvVar(
    const char* variable, ProxyServer* result_server) {
  return GetProxyFromEnvVarForScheme(variable, ProxyServer::SCHEME_HTTP,
                                     result_server);
}

bool ProxyConfigServiceLinux::Delegate::GetConfigFromEnv(ProxyConfig* config) {
  // Check for automatic configuration first, in
  // "auto_proxy". Possibly only the "environment_proxy" firefox
  // extension has ever used this, but it still sounds like a good
  // idea.
  std::string auto_proxy;
  if (env_var_getter_->GetVar("auto_proxy", &auto_proxy)) {
    if (auto_proxy.empty()) {
      // Defined and empty => autodetect
      config->set_auto_detect(true);
    } else {
      // specified autoconfig URL
      config->set_pac_url(GURL(auto_proxy));
    }
    return true;
  }
  // "all_proxy" is a shortcut to avoid defining {http,https,ftp}_proxy.
  ProxyServer proxy_server;
  if (GetProxyFromEnvVar("all_proxy", &proxy_server)) {
    config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
    config->proxy_rules().single_proxies.SetSingleProxyServer(proxy_server);
  } else {
    bool have_http = GetProxyFromEnvVar("http_proxy", &proxy_server);
    if (have_http)
      config->proxy_rules().proxies_for_http.SetSingleProxyServer(proxy_server);
    // It would be tempting to let http_proxy apply for all protocols
    // if https_proxy and ftp_proxy are not defined. Googling turns up
    // several documents that mention only http_proxy. But then the
    // user really might not want to proxy https. And it doesn't seem
    // like other apps do this. So we will refrain.
    bool have_https = GetProxyFromEnvVar("https_proxy", &proxy_server);
    if (have_https)
      config->proxy_rules().proxies_for_https.
          SetSingleProxyServer(proxy_server);
    bool have_ftp = GetProxyFromEnvVar("ftp_proxy", &proxy_server);
    if (have_ftp)
      config->proxy_rules().proxies_for_ftp.SetSingleProxyServer(proxy_server);
    if (have_http || have_https || have_ftp) {
      // mustn't change type unless some rules are actually set.
      config->proxy_rules().type =
          ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
    }
  }
  if (config->proxy_rules().empty()) {
    // If the above were not defined, try for socks.
    // For environment variables, we default to version 5, per the gnome
    // documentation: http://library.gnome.org/devel/gnet/stable/gnet-socks.html
    ProxyServer::Scheme scheme = ProxyServer::SCHEME_SOCKS5;
    std::string env_version;
    if (env_var_getter_->GetVar("SOCKS_VERSION", &env_version)
        && env_version == "4")
      scheme = ProxyServer::SCHEME_SOCKS4;
    if (GetProxyFromEnvVarForScheme("SOCKS_SERVER", scheme, &proxy_server)) {
      config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
      config->proxy_rules().single_proxies.SetSingleProxyServer(proxy_server);
    }
  }
  // Look for the proxy bypass list.
  std::string no_proxy;
  env_var_getter_->GetVar("no_proxy", &no_proxy);
  if (config->proxy_rules().empty()) {
    // Having only "no_proxy" set, presumably to "*", makes it
    // explicit that env vars do specify a configuration: having no
    // rules specified only means the user explicitly asks for direct
    // connections.
    return !no_proxy.empty();
  }
  // Note that this uses "suffix" matching. So a bypass of "google.com"
  // is understood to mean a bypass of "*google.com".
  config->proxy_rules().bypass_rules.ParseFromStringUsingSuffixMatching(
      no_proxy);
  return true;
}

namespace {

const int kDebounceTimeoutMilliseconds = 250;

#if defined(USE_GCONF)
// This setting getter uses gconf, as used in GNOME 2 and some GNOME 3 desktops.
class SettingGetterImplGConf : public ProxyConfigServiceLinux::SettingGetter {
 public:
  SettingGetterImplGConf()
      : client_(NULL), system_proxy_id_(0), system_http_proxy_id_(0),
        notify_delegate_(NULL) {
  }

  virtual ~SettingGetterImplGConf() {
    // client_ should have been released before now, from
    // Delegate::OnDestroy(), while running on the UI thread. However
    // on exiting the process, it may happen that Delegate::OnDestroy()
    // task is left pending on the glib loop after the loop was quit,
    // and pending tasks may then be deleted without being run.
    if (client_) {
      // gconf client was not cleaned up.
      if (task_runner_->BelongsToCurrentThread()) {
        // We are on the UI thread so we can clean it safely. This is
        // the case at least for ui_tests running under Valgrind in
        // bug 16076.
        VLOG(1) << "~SettingGetterImplGConf: releasing gconf client";
        ShutDown();
      } else {
        // This is very bad! We are deleting the setting getter but we're not on
        // the UI thread. This is not supposed to happen: the setting getter is
        // owned by the proxy config service's delegate, which is supposed to be
        // destroyed on the UI thread only. We will get change notifications to
        // a deleted object if we continue here, so fail now.
        LOG(FATAL) << "~SettingGetterImplGConf: deleting on wrong thread!";
      }
    }
    DCHECK(!client_);
  }

  virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner,
                    base::MessageLoopForIO* file_loop) OVERRIDE {
    DCHECK(glib_thread_task_runner->BelongsToCurrentThread());
    DCHECK(!client_);
    DCHECK(!task_runner_.get());
    task_runner_ = glib_thread_task_runner;
    client_ = gconf_client_get_default();
    if (!client_) {
      // It's not clear whether/when this can return NULL.
      LOG(ERROR) << "Unable to create a gconf client";
      task_runner_ = NULL;
      return false;
    }
    GError* error = NULL;
    bool added_system_proxy = false;
    // We need to add the directories for which we'll be asking
    // for notifications, and we might as well ask to preload them.
    // These need to be removed again in ShutDown(); we are careful
    // here to only leave client_ non-NULL if both have been added.
    gconf_client_add_dir(client_, "/system/proxy",
                         GCONF_CLIENT_PRELOAD_ONELEVEL, &error);
    if (error == NULL) {
      added_system_proxy = true;
      gconf_client_add_dir(client_, "/system/http_proxy",
                           GCONF_CLIENT_PRELOAD_ONELEVEL, &error);
    }
    if (error != NULL) {
      LOG(ERROR) << "Error requesting gconf directory: " << error->message;
      g_error_free(error);
      if (added_system_proxy)
        gconf_client_remove_dir(client_, "/system/proxy", NULL);
      g_object_unref(client_);
      client_ = NULL;
      task_runner_ = NULL;
      return false;
    }
    return true;
  }

  virtual void ShutDown() OVERRIDE {
    if (client_) {
      DCHECK(task_runner_->BelongsToCurrentThread());
      // We must explicitly disable gconf notifications here, because the gconf
      // client will be shared between all setting getters, and they do not all
      // have the same lifetimes. (For instance, incognito sessions get their
      // own, which is destroyed when the session ends.)
      gconf_client_notify_remove(client_, system_http_proxy_id_);
      gconf_client_notify_remove(client_, system_proxy_id_);
      gconf_client_remove_dir(client_, "/system/http_proxy", NULL);
      gconf_client_remove_dir(client_, "/system/proxy", NULL);
      g_object_unref(client_);
      client_ = NULL;
      task_runner_ = NULL;
    }
  }

  virtual bool SetUpNotifications(
      ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE {
    DCHECK(client_);
    DCHECK(task_runner_->BelongsToCurrentThread());
    GError* error = NULL;
    notify_delegate_ = delegate;
    // We have to keep track of the IDs returned by gconf_client_notify_add() so
    // that we can remove them in ShutDown(). (Otherwise, notifications will be
    // delivered to this object after it is deleted, which is bad, m'kay?)
    system_proxy_id_ = gconf_client_notify_add(
        client_, "/system/proxy",
        OnGConfChangeNotification, this,
        NULL, &error);
    if (error == NULL) {
      system_http_proxy_id_ = gconf_client_notify_add(
          client_, "/system/http_proxy",
          OnGConfChangeNotification, this,
          NULL, &error);
    }
    if (error != NULL) {
      LOG(ERROR) << "Error requesting gconf notifications: " << error->message;
      g_error_free(error);
      ShutDown();
      return false;
    }
    // Simulate a change to avoid possibly losing updates before this point.
    OnChangeNotification();
    return true;
  }

  virtual base::SingleThreadTaskRunner* GetNotificationTaskRunner() OVERRIDE {
    return task_runner_.get();
  }

  virtual ProxyConfigSource GetConfigSource() OVERRIDE {
    return PROXY_CONFIG_SOURCE_GCONF;
  }

  virtual bool GetString(StringSetting key, std::string* result) OVERRIDE {
    switch (key) {
      case PROXY_MODE:
        return GetStringByPath("/system/proxy/mode", result);
      case PROXY_AUTOCONF_URL:
        return GetStringByPath("/system/proxy/autoconfig_url", result);
      case PROXY_HTTP_HOST:
        return GetStringByPath("/system/http_proxy/host", result);
      case PROXY_HTTPS_HOST:
        return GetStringByPath("/system/proxy/secure_host", result);
      case PROXY_FTP_HOST:
        return GetStringByPath("/system/proxy/ftp_host", result);
      case PROXY_SOCKS_HOST:
        return GetStringByPath("/system/proxy/socks_host", result);
    }
    return false;  // Placate compiler.
  }
  virtual bool GetBool(BoolSetting key, bool* result) OVERRIDE {
    switch (key) {
      case PROXY_USE_HTTP_PROXY:
        return GetBoolByPath("/system/http_proxy/use_http_proxy", result);
      case PROXY_USE_SAME_PROXY:
        return GetBoolByPath("/system/http_proxy/use_same_proxy", result);
      case PROXY_USE_AUTHENTICATION:
        return GetBoolByPath("/system/http_proxy/use_authentication", result);
    }
    return false;  // Placate compiler.
  }
  virtual bool GetInt(IntSetting key, int* result) OVERRIDE {
    switch (key) {
      case PROXY_HTTP_PORT:
        return GetIntByPath("/system/http_proxy/port", result);
      case PROXY_HTTPS_PORT:
        return GetIntByPath("/system/proxy/secure_port", result);
      case PROXY_FTP_PORT:
        return GetIntByPath("/system/proxy/ftp_port", result);
      case PROXY_SOCKS_PORT:
        return GetIntByPath("/system/proxy/socks_port", result);
    }
    return false;  // Placate compiler.
  }
  virtual bool GetStringList(StringListSetting key,
                             std::vector<std::string>* result) OVERRIDE {
    switch (key) {
      case PROXY_IGNORE_HOSTS:
        return GetStringListByPath("/system/http_proxy/ignore_hosts", result);
    }
    return false;  // Placate compiler.
  }

  virtual bool BypassListIsReversed() OVERRIDE {
    // This is a KDE-specific setting.
    return false;
  }

  virtual bool MatchHostsUsingSuffixMatching() OVERRIDE {
    return false;
  }

 private:
  bool GetStringByPath(const char* key, std::string* result) {
    DCHECK(client_);
    DCHECK(task_runner_->BelongsToCurrentThread());
    GError* error = NULL;
    gchar* value = gconf_client_get_string(client_, key, &error);
    if (HandleGError(error, key))
      return false;
    if (!value)
      return false;
    *result = value;
    g_free(value);
    return true;
  }
  bool GetBoolByPath(const char* key, bool* result) {
    DCHECK(client_);
    DCHECK(task_runner_->BelongsToCurrentThread());
    GError* error = NULL;
    // We want to distinguish unset values from values defaulting to
    // false. For that we need to use the type-generic
    // gconf_client_get() rather than gconf_client_get_bool().
    GConfValue* gconf_value = gconf_client_get(client_, key, &error);
    if (HandleGError(error, key))
      return false;
    if (!gconf_value) {
      // Unset.
      return false;
    }
    if (gconf_value->type != GCONF_VALUE_BOOL) {
      gconf_value_free(gconf_value);
      return false;
    }
    gboolean bool_value = gconf_value_get_bool(gconf_value);
    *result = static_cast<bool>(bool_value);
    gconf_value_free(gconf_value);
    return true;
  }
  bool GetIntByPath(const char* key, int* result) {
    DCHECK(client_);
    DCHECK(task_runner_->BelongsToCurrentThread());
    GError* error = NULL;
    int value = gconf_client_get_int(client_, key, &error);
    if (HandleGError(error, key))
      return false;
    // We don't bother to distinguish an unset value because callers
    // don't care. 0 is returned if unset.
    *result = value;
    return true;
  }
  bool GetStringListByPath(const char* key, std::vector<std::string>* result) {
    DCHECK(client_);
    DCHECK(task_runner_->BelongsToCurrentThread());
    GError* error = NULL;
    GSList* list = gconf_client_get_list(client_, key,
                                         GCONF_VALUE_STRING, &error);
    if (HandleGError(error, key))
      return false;
    if (!list)
      return false;
    for (GSList *it = list; it; it = it->next) {
      result->push_back(static_cast<char*>(it->data));
      g_free(it->data);
    }
    g_slist_free(list);
    return true;
  }

  // Logs and frees a glib error. Returns false if there was no error
  // (error is NULL).
  bool HandleGError(GError* error, const char* key) {
    if (error != NULL) {
      LOG(ERROR) << "Error getting gconf value for " << key
                 << ": " << error->message;
      g_error_free(error);
      return true;
    }
    return false;
  }

  // This is the callback from the debounce timer.
  void OnDebouncedNotification() {
    DCHECK(task_runner_->BelongsToCurrentThread());
    CHECK(notify_delegate_);
    // Forward to a method on the proxy config service delegate object.
    notify_delegate_->OnCheckProxyConfigSettings();
  }

  void OnChangeNotification() {
    // 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(kDebounceTimeoutMilliseconds),
        this, &SettingGetterImplGConf::OnDebouncedNotification);
  }

  // gconf notification callback, dispatched on the default glib main loop.
  static void OnGConfChangeNotification(GConfClient* client, guint cnxn_id,
                                        GConfEntry* entry, gpointer user_data) {
    VLOG(1) << "gconf change notification for key "
            << gconf_entry_get_key(entry);
    // We don't track which key has changed, just that something did change.
    SettingGetterImplGConf* setting_getter =
        reinterpret_cast<SettingGetterImplGConf*>(user_data);
    setting_getter->OnChangeNotification();
  }

  GConfClient* client_;
  // These ids are the values returned from gconf_client_notify_add(), which we
  // will need in order to later call gconf_client_notify_remove().
  guint system_proxy_id_;
  guint system_http_proxy_id_;

  ProxyConfigServiceLinux::Delegate* notify_delegate_;
  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
  // thread. Only for assertions.
  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;

  DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGConf);
};
#endif  // defined(USE_GCONF)

#if defined(USE_GIO)
// This setting getter uses gsettings, as used in most GNOME 3 desktops.
class SettingGetterImplGSettings
    : public ProxyConfigServiceLinux::SettingGetter {
 public:
  SettingGetterImplGSettings() :
    client_(NULL),
    http_client_(NULL),
    https_client_(NULL),
    ftp_client_(NULL),
    socks_client_(NULL),
    notify_delegate_(NULL) {
  }

  virtual ~SettingGetterImplGSettings() {
    // client_ should have been released before now, from
    // Delegate::OnDestroy(), while running on the UI thread. However
    // on exiting the process, it may happen that
    // Delegate::OnDestroy() task is left pending on the glib loop
    // after the loop was quit, and pending tasks may then be deleted
    // without being run.
    if (client_) {
      // gconf client was not cleaned up.
      if (task_runner_->BelongsToCurrentThread()) {
        // We are on the UI thread so we can clean it safely. This is
        // the case at least for ui_tests running under Valgrind in
        // bug 16076.
        VLOG(1) << "~SettingGetterImplGSettings: releasing gsettings client";
        ShutDown();
      } else {
        LOG(WARNING) << "~SettingGetterImplGSettings: leaking gsettings client";
        client_ = NULL;
      }
    }
    DCHECK(!client_);
  }

  bool SchemaExists(const char* schema_name) {
    const gchar* const* schemas = libgio_loader_.g_settings_list_schemas();
    while (*schemas) {
      if (strcmp(schema_name, static_cast<const char*>(*schemas)) == 0)
        return true;
      schemas++;
    }
    return false;
  }

  // LoadAndCheckVersion() must be called *before* Init()!
  bool LoadAndCheckVersion(base::Environment* env);

  virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner,
                    base::MessageLoopForIO* file_loop) OVERRIDE {
    DCHECK(glib_thread_task_runner->BelongsToCurrentThread());
    DCHECK(!client_);
    DCHECK(!task_runner_.get());

    if (!SchemaExists("org.gnome.system.proxy") ||
        !(client_ = libgio_loader_.g_settings_new("org.gnome.system.proxy"))) {
      // It's not clear whether/when this can return NULL.
      LOG(ERROR) << "Unable to create a gsettings client";
      return false;
    }
    task_runner_ = glib_thread_task_runner;
    // We assume these all work if the above call worked.
    http_client_ = libgio_loader_.g_settings_get_child(client_, "http");
    https_client_ = libgio_loader_.g_settings_get_child(client_, "https");
    ftp_client_ = libgio_loader_.g_settings_get_child(client_, "ftp");
    socks_client_ = libgio_loader_.g_settings_get_child(client_, "socks");
    DCHECK(http_client_ && https_client_ && ftp_client_ && socks_client_);
    return true;
  }

  virtual void ShutDown() OVERRIDE {
    if (client_) {
      DCHECK(task_runner_->BelongsToCurrentThread());
      // This also disables gsettings notifications.
      g_object_unref(socks_client_);
      g_object_unref(ftp_client_);
      g_object_unref(https_client_);
      g_object_unref(http_client_);
      g_object_unref(client_);
      // We only need to null client_ because it's the only one that we check.
      client_ = NULL;
      task_runner_ = NULL;
    }
  }

  virtual bool SetUpNotifications(
      ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE {
    DCHECK(client_);
    DCHECK(task_runner_->BelongsToCurrentThread());
    notify_delegate_ = delegate;
    // We could watch for the change-event signal instead of changed, but
    // since we have to watch more than one object, we'd still have to
    // debounce change notifications. This is conceptually simpler.
    g_signal_connect(G_OBJECT(client_), "changed",
                     G_CALLBACK(OnGSettingsChangeNotification), this);
    g_signal_connect(G_OBJECT(http_client_), "changed",
                     G_CALLBACK(OnGSettingsChangeNotification), this);
    g_signal_connect(G_OBJECT(https_client_), "changed",
                     G_CALLBACK(OnGSettingsChangeNotification), this);
    g_signal_connect(G_OBJECT(ftp_client_), "changed",
                     G_CALLBACK(OnGSettingsChangeNotification), this);
    g_signal_connect(G_OBJECT(socks_client_), "changed",
                     G_CALLBACK(OnGSettingsChangeNotification), this);
    // Simulate a change to avoid possibly losing updates before this point.
    OnChangeNotification();
    return true;
  }

  virtual base::SingleThreadTaskRunner* GetNotificationTaskRunner() OVERRIDE {
    return task_runner_.get();
  }

  virtual ProxyConfigSource GetConfigSource() OVERRIDE {
    return PROXY_CONFIG_SOURCE_GSETTINGS;
  }

  virtual bool GetString(StringSetting key, std::string* result) OVERRIDE {
    DCHECK(client_);
    switch (key) {
      case PROXY_MODE:
        return GetStringByPath(client_, "mode", result);
      case PROXY_AUTOCONF_URL:
        return GetStringByPath(client_, "autoconfig-url", result);
      case PROXY_HTTP_HOST:
        return GetStringByPath(http_client_, "host", result);
      case PROXY_HTTPS_HOST:
        return GetStringByPath(https_client_, "host", result);
      case PROXY_FTP_HOST:
        return GetStringByPath(ftp_client_, "host", result);
      case PROXY_SOCKS_HOST:
        return GetStringByPath(socks_client_, "host", result);
    }
    return false;  // Placate compiler.
  }
  virtual bool GetBool(BoolSetting key, bool* result) OVERRIDE {
    DCHECK(client_);
    switch (key) {
      case PROXY_USE_HTTP_PROXY:
        // Although there is an "enabled" boolean in http_client_, it is not set
        // to true by the proxy config utility. We ignore it and return false.
        return false;
      case PROXY_USE_SAME_PROXY:
        // Similarly, although there is a "use-same-proxy" boolean in client_,
        // it is never set to false by the proxy config utility. We ignore it.
        return false;
      case PROXY_USE_AUTHENTICATION:
        // There is also no way to set this in the proxy config utility, but it
        // doesn't hurt us to get the actual setting (unlike the two above).
        return GetBoolByPath(http_client_, "use-authentication", result);
    }
    return false;  // Placate compiler.
  }
  virtual bool GetInt(IntSetting key, int* result) OVERRIDE {
    DCHECK(client_);
    switch (key) {
      case PROXY_HTTP_PORT:
        return GetIntByPath(http_client_, "port", result);
      case PROXY_HTTPS_PORT:
        return GetIntByPath(https_client_, "port", result);
      case PROXY_FTP_PORT:
        return GetIntByPath(ftp_client_, "port", result);
      case PROXY_SOCKS_PORT:
        return GetIntByPath(socks_client_, "port", result);
    }
    return false;  // Placate compiler.
  }
  virtual bool GetStringList(StringListSetting key,
                             std::vector<std::string>* result) OVERRIDE {
    DCHECK(client_);
    switch (key) {
      case PROXY_IGNORE_HOSTS:
        return GetStringListByPath(client_, "ignore-hosts", result);
    }
    return false;  // Placate compiler.
  }

  virtual bool BypassListIsReversed() OVERRIDE {
    // This is a KDE-specific setting.
    return false;
  }

  virtual bool MatchHostsUsingSuffixMatching() OVERRIDE {
    return false;
  }

 private:
  bool GetStringByPath(GSettings* client, const char* key,
                       std::string* result) {
    DCHECK(task_runner_->BelongsToCurrentThread());
    gchar* value = libgio_loader_.g_settings_get_string(client, key);
    if (!value)
      return false;
    *result = value;
    g_free(value);
    return true;
  }
  bool GetBoolByPath(GSettings* client, const char* key, bool* result) {
    DCHECK(task_runner_->BelongsToCurrentThread());
    *result = static_cast<bool>(
        libgio_loader_.g_settings_get_boolean(client, key));
    return true;
  }
  bool GetIntByPath(GSettings* client, const char* key, int* result) {
    DCHECK(task_runner_->BelongsToCurrentThread());
    *result = libgio_loader_.g_settings_get_int(client, key);
    return true;
  }
  bool GetStringListByPath(GSettings* client, const char* key,
                           std::vector<std::string>* result) {
    DCHECK(task_runner_->BelongsToCurrentThread());
    gchar** list = libgio_loader_.g_settings_get_strv(client, key);
    if (!list)
      return false;
    for (size_t i = 0; list[i]; ++i) {
      result->push_back(static_cast<char*>(list[i]));
      g_free(list[i]);
    }
    g_free(list);
    return true;
  }

  // This is the callback from the debounce timer.
  void OnDebouncedNotification() {
    DCHECK(task_runner_->BelongsToCurrentThread());
    CHECK(notify_delegate_);
    // Forward to a method on the proxy config service delegate object.
    notify_delegate_->OnCheckProxyConfigSettings();
  }

  void OnChangeNotification() {
    // 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(kDebounceTimeoutMilliseconds),
        this, &SettingGetterImplGSettings::OnDebouncedNotification);
  }

  // gsettings notification callback, dispatched on the default glib main loop.
  static void OnGSettingsChangeNotification(GSettings* client, gchar* key,
                                            gpointer user_data) {
    VLOG(1) << "gsettings change notification for key " << key;
    // We don't track which key has changed, just that something did change.
    SettingGetterImplGSettings* setting_getter =
        reinterpret_cast<SettingGetterImplGSettings*>(user_data);
    setting_getter->OnChangeNotification();
  }

  GSettings* client_;
  GSettings* http_client_;
  GSettings* https_client_;
  GSettings* ftp_client_;
  GSettings* socks_client_;
  ProxyConfigServiceLinux::Delegate* notify_delegate_;
  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
  // thread. Only for assertions.
  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;

  LibGioLoader libgio_loader_;

  DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGSettings);
};

bool SettingGetterImplGSettings::LoadAndCheckVersion(
    base::Environment* env) {
  // LoadAndCheckVersion() must be called *before* Init()!
  DCHECK(!client_);

  // The APIs to query gsettings were introduced after the minimum glib
  // version we target, so we can't link directly against them. We load them
  // dynamically at runtime, and if they don't exist, return false here. (We
  // support linking directly via gyp flags though.) Additionally, even when
  // they are present, we do two additional checks to make sure we should use
  // them and not gconf. First, we attempt to load the schema for proxy
  // settings. Second, we check for the program that was used in older
  // versions of GNOME to configure proxy settings, and return false if it
  // exists. Some distributions (e.g. Ubuntu 11.04) have the API and schema
  // but don't use gsettings for proxy settings, but they do have the old
  // binary, so we detect these systems that way.

  {
    // TODO(phajdan.jr): Redesign the code to load library on different thread.
    base::ThreadRestrictions::ScopedAllowIO allow_io;

    // Try also without .0 at the end; on some systems this may be required.
    if (!libgio_loader_.Load("libgio-2.0.so.0") &&
        !libgio_loader_.Load("libgio-2.0.so")) {
      VLOG(1) << "Cannot load gio library. Will fall back to gconf.";
      return false;
    }
  }

  GSettings* client;
  if (!SchemaExists("org.gnome.system.proxy") ||
      !(client = libgio_loader_.g_settings_new("org.gnome.system.proxy"))) {
    VLOG(1) << "Cannot create gsettings client. Will fall back to gconf.";
    return false;
  }
  g_object_unref(client);

  std::string path;
  if (!env->GetVar("PATH", &path)) {
    LOG(ERROR) << "No $PATH variable. Assuming no gnome-network-properties.";
  } else {
    // Yes, we're on the UI thread. Yes, we're accessing the file system.
    // Sadly, we don't have much choice. We need the proxy settings and we
    // need them now, and to figure out where to get them, we have to check
    // for this binary. See http://crbug.com/69057 for additional details.
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    std::vector<std::string> paths;
    Tokenize(path, ":", &paths);
    for (size_t i = 0; i < paths.size(); ++i) {
      base::FilePath file(paths[i]);
      if (base::PathExists(file.Append("gnome-network-properties"))) {
        VLOG(1) << "Found gnome-network-properties. Will fall back to gconf.";
        return false;
      }
    }
  }

  VLOG(1) << "All gsettings tests OK. Will get proxy config from gsettings.";
  return true;
}
#endif  // defined(USE_GIO)

// This is the KDE version that reads kioslaverc and simulates gconf.
// Doing this allows the main Delegate code, as well as the unit tests
// for it, to stay the same - and the settings map fairly well besides.
class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter,
                             public base::MessagePumpLibevent::Watcher {
 public:
  explicit SettingGetterImplKDE(base::Environment* env_var_getter)
      : inotify_fd_(-1), notify_delegate_(NULL), indirect_manual_(false),
        auto_no_pac_(false), reversed_bypass_list_(false),
        env_var_getter_(env_var_getter), file_loop_(NULL) {
    // This has to be called on the UI thread (http://crbug.com/69057).
    base::ThreadRestrictions::ScopedAllowIO allow_io;

    // Derive the location of the kde config dir from the environment.
    std::string home;
    if (env_var_getter->GetVar("KDEHOME", &home) && !home.empty()) {
      // $KDEHOME is set. Use it unconditionally.
      kde_config_dir_ = KDEHomeToConfigPath(base::FilePath(home));
    } else {
      // $KDEHOME is unset. Try to figure out what to use. This seems to be
      // the common case on most distributions.
      if (!env_var_getter->GetVar(base::env_vars::kHome, &home))
        // User has no $HOME? Give up. Later we'll report the failure.
        return;
      if (base::nix::GetDesktopEnvironment(env_var_getter) ==
          base::nix::DESKTOP_ENVIRONMENT_KDE3) {
        // KDE3 always uses .kde for its configuration.
        base::FilePath kde_path = base::FilePath(home).Append(".kde");
        kde_config_dir_ = KDEHomeToConfigPath(kde_path);
      } else {
        // Some distributions patch KDE4 to use .kde4 instead of .kde, so that
        // both can be installed side-by-side. Sadly they don't all do this, and
        // they don't always do this: some distributions have started switching
        // back as well. So if there is a .kde4 directory, check the timestamps
        // of the config directories within and use the newest one.
        // Note that we should currently be running in the UI thread, because in
        // the gconf version, that is the only thread that can access the proxy
        // settings (a gconf restriction). As noted below, the initial read of
        // the proxy settings will be done in this thread anyway, so we check
        // for .kde4 here in this thread as well.
        base::FilePath kde3_path = base::FilePath(home).Append(".kde");
        base::FilePath kde3_config = KDEHomeToConfigPath(kde3_path);
        base::FilePath kde4_path = base::FilePath(home).Append(".kde4");
        base::FilePath kde4_config = KDEHomeToConfigPath(kde4_path);
        bool use_kde4 = false;
        if (base::DirectoryExists(kde4_path)) {
          base::PlatformFileInfo kde3_info;
          base::PlatformFileInfo kde4_info;
          if (file_util::GetFileInfo(kde4_config, &kde4_info)) {
            if (file_util::GetFileInfo(kde3_config, &kde3_info)) {
              use_kde4 = kde4_info.last_modified >= kde3_info.last_modified;
            } else {
              use_kde4 = true;
            }
          }
        }
        if (use_kde4) {
          kde_config_dir_ = KDEHomeToConfigPath(kde4_path);
        } else {
          kde_config_dir_ = KDEHomeToConfigPath(kde3_path);
        }
      }
    }
  }

  virtual ~SettingGetterImplKDE() {
    // inotify_fd_ should have been closed before now, from
    // Delegate::OnDestroy(), while running on the file thread. However
    // on exiting the process, it may happen that Delegate::OnDestroy()
    // task is left pending on the file loop after the loop was quit,
    // and pending tasks may then be deleted without being run.
    // Here in the KDE version, we can safely close the file descriptor
    // anyway. (Not that it really matters; the process is exiting.)
    if (inotify_fd_ >= 0)
      ShutDown();
    DCHECK(inotify_fd_ < 0);
  }

  virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner,
                    base::MessageLoopForIO* file_loop) OVERRIDE {
    // This has to be called on the UI thread (http://crbug.com/69057).
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    DCHECK(inotify_fd_ < 0);
    inotify_fd_ = inotify_init();
    if (inotify_fd_ < 0) {
      PLOG(ERROR) << "inotify_init failed";
      return false;
    }
    int flags = fcntl(inotify_fd_, F_GETFL);
    if (fcntl(inotify_fd_, F_SETFL, flags | O_NONBLOCK) < 0) {
      PLOG(ERROR) << "fcntl failed";
      close(inotify_fd_);
      inotify_fd_ = -1;
      return false;
    }
    file_loop_ = file_loop;
    // The initial read is done on the current thread, not |file_loop_|,
    // since we will need to have it for SetUpAndFetchInitialConfig().
    UpdateCachedSettings();
    return true;
  }

  virtual void ShutDown() OVERRIDE {
    if (inotify_fd_ >= 0) {
      ResetCachedSettings();
      inotify_watcher_.StopWatchingFileDescriptor();
      close(inotify_fd_);
      inotify_fd_ = -1;
    }
  }

  virtual bool SetUpNotifications(
      ProxyConfigServiceLinux::Delegate* delegate) OVERRIDE {
    DCHECK(inotify_fd_ >= 0);
    DCHECK(base::MessageLoop::current() == file_loop_);
    // We can't just watch the kioslaverc file directly, since KDE will write
    // a new copy of it and then rename it whenever settings are changed and
    // inotify watches inodes (so we'll be watching the old deleted file after
    // the first change, and it will never change again). So, we watch the
    // directory instead. We then act only on changes to the kioslaverc entry.
    if (inotify_add_watch(inotify_fd_, kde_config_dir_.value().c_str(),
                          IN_MODIFY | IN_MOVED_TO) < 0)
      return false;
    notify_delegate_ = delegate;
    if (!file_loop_->WatchFileDescriptor(inotify_fd_,
                                         true,
                                         base::MessageLoopForIO::WATCH_READ,
                                         &inotify_watcher_,
                                         this))
      return false;
    // Simulate a change to avoid possibly losing updates before this point.
    OnChangeNotification();
    return true;
  }

  virtual base::SingleThreadTaskRunner* GetNotificationTaskRunner() OVERRIDE {
    return file_loop_ ? file_loop_->message_loop_proxy().get() : NULL;
  }

  // Implement base::MessagePumpLibevent::Watcher.
  virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {
    DCHECK_EQ(fd, inotify_fd_);
    DCHECK(base::MessageLoop::current() == file_loop_);
    OnChangeNotification();
  }
  virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {
    NOTREACHED();
  }

  virtual ProxyConfigSource GetConfigSource() OVERRIDE {
    return PROXY_CONFIG_SOURCE_KDE;
  }

  virtual bool GetString(StringSetting key, std::string* result) OVERRIDE {
    string_map_type::iterator it = string_table_.find(key);
    if (it == string_table_.end())
      return false;
    *result = it->second;
    return true;
  }
  virtual bool GetBool(BoolSetting key, bool* result) OVERRIDE {
    // We don't ever have any booleans.
    return false;
  }
  virtual bool GetInt(IntSetting key, int* result) OVERRIDE {
    // We don't ever have any integers. (See AddProxy() below about ports.)
    return false;
  }
  virtual bool GetStringList(StringListSetting key,
                             std::vector<std::string>* result) OVERRIDE {
    strings_map_type::iterator it = strings_table_.find(key);
    if (it == strings_table_.end())
      return false;
    *result = it->second;
    return true;
  }

  virtual bool BypassListIsReversed() OVERRIDE {
    return reversed_bypass_list_;
  }

  virtual bool MatchHostsUsingSuffixMatching() OVERRIDE {
    return true;
  }

 private:
  void ResetCachedSettings() {
    string_table_.clear();
    strings_table_.clear();
    indirect_manual_ = false;
    auto_no_pac_ = false;
    reversed_bypass_list_ = false;
  }

  base::FilePath KDEHomeToConfigPath(const base::FilePath& kde_home) {
    return kde_home.Append("share").Append("config");
  }

  void AddProxy(StringSetting host_key, const std::string& value) {
    if (value.empty() || value.substr(0, 3) == "//:")
      // No proxy.
      return;
    size_t space = value.find(' ');
    if (space != std::string::npos) {
      // Newer versions of KDE use a space rather than a colon to separate the
      // port number from the hostname. If we find this, we need to convert it.
      std::string fixed = value;
      fixed[space] = ':';
      string_table_[host_key] = fixed;
    } else {
      // We don't need to parse the port number out; GetProxyFromSettings()
      // would only append it right back again. So we just leave the port
      // number right in the host string.
      string_table_[host_key] = value;
    }
  }

  void AddHostList(StringListSetting key, const std::string& value) {
    std::vector<std::string> tokens;
    base::StringTokenizer tk(value, ", ");
    while (tk.GetNext()) {
      std::string token = tk.token();
      if (!token.empty())
        tokens.push_back(token);
    }
    strings_table_[key] = tokens;
  }

  void AddKDESetting(const std::string& key, const std::string& value) {
    if (key == "ProxyType") {
      const char* mode = "none";
      indirect_manual_ = false;
      auto_no_pac_ = false;
      int int_value;
      base::StringToInt(value, &int_value);
      switch (int_value) {
        case 0:  // No proxy, or maybe kioslaverc syntax error.
          break;
        case 1:  // Manual configuration.
          mode = "manual";
          break;
        case 2:  // PAC URL.
          mode = "auto";
          break;
        case 3:  // WPAD.
          mode = "auto";
          auto_no_pac_ = true;
          break;
        case 4:  // Indirect manual via environment variables.
          mode = "manual";
          indirect_manual_ = true;
          break;
      }
      string_table_[PROXY_MODE] = mode;
    } else if (key == "Proxy Config Script") {
      string_table_[PROXY_AUTOCONF_URL] = value;
    } else if (key == "httpProxy") {
      AddProxy(PROXY_HTTP_HOST, value);
    } else if (key == "httpsProxy") {
      AddProxy(PROXY_HTTPS_HOST, value);
    } else if (key == "ftpProxy") {
      AddProxy(PROXY_FTP_HOST, value);
    } else if (key == "socksProxy") {
      // Older versions of KDE configure SOCKS in a weird way involving
      // LD_PRELOAD and a library that intercepts network calls to SOCKSify
      // them. We don't support it. KDE 4.8 added a proper SOCKS setting.
      AddProxy(PROXY_SOCKS_HOST, value);
    } else if (key == "ReversedException") {
      // We count "true" or any nonzero number as true, otherwise false.
      // Note that if the value is not actually numeric StringToInt()
      // will return 0, which we count as false.
      int int_value;
      base::StringToInt(value, &int_value);
      reversed_bypass_list_ = (value == "true" || int_value);
    } else if (key == "NoProxyFor") {
      AddHostList(PROXY_IGNORE_HOSTS, value);
    } else if (key == "AuthMode") {
      // Check for authentication, just so we can warn.
      int mode;
      base::StringToInt(value, &mode);
      if (mode) {
        // ProxyConfig does not support authentication parameters, but
        // Chrome will prompt for the password later. So we ignore this.
        LOG(WARNING) <<
            "Proxy authentication parameters ignored, see bug 16709";
      }
    }
  }

  void ResolveIndirect(StringSetting key) {
    string_map_type::iterator it = string_table_.find(key);
    if (it != string_table_.end()) {
      std::string value;
      if (env_var_getter_->GetVar(it->second.c_str(), &value))
        it->second = value;
      else
        string_table_.erase(it);
    }
  }

  void ResolveIndirectList(StringListSetting key) {
    strings_map_type::iterator it = strings_table_.find(key);
    if (it != strings_table_.end()) {
      std::string value;
      if (!it->second.empty() &&
          env_var_getter_->GetVar(it->second[0].c_str(), &value))
        AddHostList(key, value);
      else
        strings_table_.erase(it);
    }
  }

  // The settings in kioslaverc could occur in any order, but some affect
  // others. Rather than read the whole file in and then query them in an
  // order that allows us to handle that, we read the settings in whatever
  // order they occur and do any necessary tweaking after we finish.
  void ResolveModeEffects() {
    if (indirect_manual_) {
      ResolveIndirect(PROXY_HTTP_HOST);
      ResolveIndirect(PROXY_HTTPS_HOST);
      ResolveIndirect(PROXY_FTP_HOST);
      ResolveIndirectList(PROXY_IGNORE_HOSTS);
    }
    if (auto_no_pac_) {
      // Remove the PAC URL; we're not supposed to use it.
      string_table_.erase(PROXY_AUTOCONF_URL);
    }
  }

  // Reads kioslaverc one line at a time and calls AddKDESetting() to add
  // each relevant name-value pair to the appropriate value table.
  void UpdateCachedSettings() {
    base::FilePath kioslaverc = kde_config_dir_.Append("kioslaverc");
    file_util::ScopedFILE input(file_util::OpenFile(kioslaverc, "r"));
    if (!input.get())
      return;
    ResetCachedSettings();
    bool in_proxy_settings = false;
    bool line_too_long = false;
    char line[BUFFER_SIZE];
    // fgets() will return NULL on EOF or error.
    while (fgets(line, sizeof(line), input.get())) {
      // fgets() guarantees the line will be properly terminated.
      size_t length = strlen(line);
      if (!length)
        continue;
      // This should be true even with CRLF endings.
      if (line[length - 1] != '\n') {
        line_too_long = true;
        continue;
      }
      if (line_too_long) {
        // The previous line had no line ending, but this done does. This is
        // the end of the line that was too long, so warn here and skip it.
        LOG(WARNING) << "skipped very long line in " << kioslaverc.value();
        line_too_long = false;
        continue;
      }
      // Remove the LF at the end, and the CR if there is one.
      line[--length] = '\0';
      if (length && line[length - 1] == '\r')
        line[--length] = '\0';
      // Now parse the line.
      if (line[0] == '[') {
        // Switching sections. All we care about is whether this is
        // the (a?) proxy settings section, for both KDE3 and KDE4.
        in_proxy_settings = !strncmp(line, "[Proxy Settings]", 16);
      } else if (in_proxy_settings) {
        // A regular line, in the (a?) proxy settings section.
        char* split = strchr(line, '=');
        // Skip this line if it does not contain an = sign.
        if (!split)
          continue;
        // Split the line on the = and advance |split|.
        *(split++) = 0;
        std::string key = line;
        std::string value = split;
        TrimWhitespaceASCII(key, TRIM_ALL, &key);
        TrimWhitespaceASCII(value, TRIM_ALL, &value);
        // Skip this line if the key name is empty.
        if (key.empty())
          continue;
        // Is the value name localized?
        if (key[key.length() - 1] == ']') {
          // Find the matching bracket.
          length = key.rfind('[');
          // Skip this line if the localization indicator is malformed.
          if (length == std::string::npos)
            continue;
          // Trim the localization indicator off.
          key.resize(length);
          // Remove any resulting trailing whitespace.
          TrimWhitespaceASCII(key, TRIM_TRAILING, &key);
          // Skip this line if the key name is now empty.
          if (key.empty())
            continue;
        }
        // Now fill in the tables.
        AddKDESetting(key, value);
      }
    }
    if (ferror(input.get()))
      LOG(ERROR) << "error reading " << kioslaverc.value();
    ResolveModeEffects();
  }

  // This is the callback from the debounce timer.
  void OnDebouncedNotification() {
    DCHECK(base::MessageLoop::current() == file_loop_);
    VLOG(1) << "inotify change notification for kioslaverc";
    UpdateCachedSettings();
    CHECK(notify_delegate_);
    // Forward to a method on the proxy config service delegate object.
    notify_delegate_->OnCheckProxyConfigSettings();
  }

  // Called by OnFileCanReadWithoutBlocking() on the file thread. Reads
  // from the inotify file descriptor and starts up a debounce timer if
  // an event for kioslaverc is seen.
  void OnChangeNotification() {
    DCHECK_GE(inotify_fd_,  0);
    DCHECK(base::MessageLoop::current() == file_loop_);
    char event_buf[(sizeof(inotify_event) + NAME_MAX + 1) * 4];
    bool kioslaverc_touched = false;
    ssize_t r;
    while ((r = read(inotify_fd_, event_buf, sizeof(event_buf))) > 0) {
      // inotify returns variable-length structures, which is why we have
      // this strange-looking loop instead of iterating through an array.
      char* event_ptr = event_buf;
      while (event_ptr < event_buf + r) {
        inotify_event* event = reinterpret_cast<inotify_event*>(event_ptr);
        // The kernel always feeds us whole events.
        CHECK_LE(event_ptr + sizeof(inotify_event), event_buf + r);
        CHECK_LE(event->name + event->len, event_buf + r);
        if (!strcmp(event->name, "kioslaverc"))
          kioslaverc_touched = true;
        // Advance the pointer just past the end of the filename.
        event_ptr = event->name + event->len;
      }
      // We keep reading even if |kioslaverc_touched| is true to drain the
      // inotify event queue.
    }
    if (!r)
      // Instead of returning -1 and setting errno to EINVAL if there is not
      // enough buffer space, older kernels (< 2.6.21) return 0. Simulate the
      // new behavior (EINVAL) so we can reuse the code below.
      errno = EINVAL;
    if (errno != EAGAIN) {
      PLOG(WARNING) << "error reading inotify file descriptor";
      if (errno == EINVAL) {
        // Our buffer is not large enough to read the next event. This should
        // not happen (because its size is calculated to always be sufficiently
        // large), but if it does we'd warn continuously since |inotify_fd_|
        // would be forever ready to read. Close it and stop watching instead.
        LOG(ERROR) << "inotify failure; no longer watching kioslaverc!";
        inotify_watcher_.StopWatchingFileDescriptor();
        close(inotify_fd_);
        inotify_fd_ = -1;
      }
    }
    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(
          kDebounceTimeoutMilliseconds), this,
          &SettingGetterImplKDE::OnDebouncedNotification);
    }
  }

  typedef std::map<StringSetting, std::string> string_map_type;
  typedef std::map<StringListSetting,
                   std::vector<std::string> > strings_map_type;

  int inotify_fd_;
  base::MessagePumpLibevent::FileDescriptorWatcher inotify_watcher_;
  ProxyConfigServiceLinux::Delegate* notify_delegate_;
  base::OneShotTimer<SettingGetterImplKDE> debounce_timer_;
  base::FilePath kde_config_dir_;
  bool indirect_manual_;
  bool auto_no_pac_;
  bool reversed_bypass_list_;
  // We don't own |env_var_getter_|.  It's safe to hold a pointer to it, since
  // both it and us are owned by ProxyConfigServiceLinux::Delegate, and have the
  // same lifetime.
  base::Environment* env_var_getter_;

  // We cache these settings whenever we re-read the kioslaverc file.
  string_map_type string_table_;
  strings_map_type strings_table_;

  // Message loop of the file thread, for reading kioslaverc. If NULL,
  // just read it directly (for testing). We also handle inotify events
  // on this thread.
  base::MessageLoopForIO* file_loop_;

  DISALLOW_COPY_AND_ASSIGN(SettingGetterImplKDE);
};

}  // namespace

bool ProxyConfigServiceLinux::Delegate::GetProxyFromSettings(
    SettingGetter::StringSetting host_key,
    ProxyServer* result_server) {
  std::string host;
  if (!setting_getter_->GetString(host_key, &host) || host.empty()) {
    // Unset or empty.
    return false;
  }
  // Check for an optional port.
  int port = 0;
  SettingGetter::IntSetting port_key =
      SettingGetter::HostSettingToPortSetting(host_key);
  setting_getter_->GetInt(port_key, &port);
  if (port != 0) {
    // If a port is set and non-zero:
    host += ":" + base::IntToString(port);
  }

  // gconf settings do not appear to distinguish between SOCKS version. We
  // default to version 5. For more information on this policy decision, see:
  // http://code.google.com/p/chromium/issues/detail?id=55912#c2
  ProxyServer::Scheme scheme = (host_key == SettingGetter::PROXY_SOCKS_HOST) ?
      ProxyServer::SCHEME_SOCKS5 : ProxyServer::SCHEME_HTTP;
  host = FixupProxyHostScheme(scheme, host);
  ProxyServer proxy_server = ProxyServer::FromURI(host,
                                                  ProxyServer::SCHEME_HTTP);
  if (proxy_server.is_valid()) {
    *result_server = proxy_server;
    return true;
  }
  return false;
}

bool ProxyConfigServiceLinux::Delegate::GetConfigFromSettings(
    ProxyConfig* config) {
  std::string mode;
  if (!setting_getter_->GetString(SettingGetter::PROXY_MODE, &mode)) {
    // We expect this to always be set, so if we don't see it then we
    // probably have a gconf/gsettings problem, and so we don't have a valid
    // proxy config.
    return false;
  }
  if (mode == "none") {
    // Specifically specifies no proxy.
    return true;
  }

  if (mode == "auto") {
    // Automatic proxy config.
    std::string pac_url_str;
    if (setting_getter_->GetString(SettingGetter::PROXY_AUTOCONF_URL,
                                   &pac_url_str)) {
      if (!pac_url_str.empty()) {
        // If the PAC URL is actually a file path, then put file:// in front.
        if (pac_url_str[0] == '/')
          pac_url_str = "file://" + pac_url_str;
        GURL pac_url(pac_url_str);
        if (!pac_url.is_valid())
          return false;
        config->set_pac_url(pac_url);
        return true;
      }
    }
    config->set_auto_detect(true);
    return true;
  }

  if (mode != "manual") {
    // Mode is unrecognized.
    return false;
  }
  bool use_http_proxy;
  if (setting_getter_->GetBool(SettingGetter::PROXY_USE_HTTP_PROXY,
                               &use_http_proxy)
      && !use_http_proxy) {
    // Another master switch for some reason. If set to false, then no
    // proxy. But we don't panic if the key doesn't exist.
    return true;
  }

  bool same_proxy = false;
  // Indicates to use the http proxy for all protocols. This one may
  // not exist (presumably on older versions); we assume false in that
  // case.
  setting_getter_->GetBool(SettingGetter::PROXY_USE_SAME_PROXY,
                           &same_proxy);

  ProxyServer proxy_for_http;
  ProxyServer proxy_for_https;
  ProxyServer proxy_for_ftp;
  ProxyServer socks_proxy;  // (socks)

  // This counts how many of the above ProxyServers were defined and valid.
  size_t num_proxies_specified = 0;

  // Extract the per-scheme proxies. If we failed to parse it, or no proxy was
  // specified for the scheme, then the resulting ProxyServer will be invalid.
  if (GetProxyFromSettings(SettingGetter::PROXY_HTTP_HOST, &proxy_for_http))
    num_proxies_specified++;
  if (GetProxyFromSettings(SettingGetter::PROXY_HTTPS_HOST, &proxy_for_https))
    num_proxies_specified++;
  if (GetProxyFromSettings(SettingGetter::PROXY_FTP_HOST, &proxy_for_ftp))
    num_proxies_specified++;
  if (GetProxyFromSettings(SettingGetter::PROXY_SOCKS_HOST, &socks_proxy))
    num_proxies_specified++;

  if (same_proxy) {
    if (proxy_for_http.is_valid()) {
      // Use the http proxy for all schemes.
      config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
      config->proxy_rules().single_proxies.SetSingleProxyServer(proxy_for_http);
    }
  } else if (num_proxies_specified > 0) {
    if (socks_proxy.is_valid() && num_proxies_specified == 1) {
      // If the only proxy specified was for SOCKS, use it for all schemes.
      config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
      config->proxy_rules().single_proxies.SetSingleProxyServer(socks_proxy);
    } else {
      // Otherwise use the indicated proxies per-scheme.
      config->proxy_rules().type =
          ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
      config->proxy_rules().proxies_for_http.
          SetSingleProxyServer(proxy_for_http);
      config->proxy_rules().proxies_for_https.
          SetSingleProxyServer(proxy_for_https);
      config->proxy_rules().proxies_for_ftp.SetSingleProxyServer(proxy_for_ftp);
      config->proxy_rules().fallback_proxies.SetSingleProxyServer(socks_proxy);
    }
  }

  if (config->proxy_rules().empty()) {
    // Manual mode but we couldn't parse any rules.
    return false;
  }

  // Check for authentication, just so we can warn.
  bool use_auth = false;
  setting_getter_->GetBool(SettingGetter::PROXY_USE_AUTHENTICATION,
                           &use_auth);
  if (use_auth) {
    // ProxyConfig does not support authentication parameters, but
    // Chrome will prompt for the password later. So we ignore
    // /system/http_proxy/*auth* settings.
    LOG(WARNING) << "Proxy authentication parameters ignored, see bug 16709";
  }

  // Now the bypass list.
  std::vector<std::string> ignore_hosts_list;
  config->proxy_rules().bypass_rules.Clear();
  if (setting_getter_->GetStringList(SettingGetter::PROXY_IGNORE_HOSTS,
                                     &ignore_hosts_list)) {
    std::vector<std::string>::const_iterator it(ignore_hosts_list.begin());
    for (; it != ignore_hosts_list.end(); ++it) {
      if (setting_getter_->MatchHostsUsingSuffixMatching()) {
        config->proxy_rules().bypass_rules.
            AddRuleFromStringUsingSuffixMatching(*it);
      } else {
        config->proxy_rules().bypass_rules.AddRuleFromString(*it);
      }
    }
  }
  // Note that there are no settings with semantics corresponding to
  // bypass of local names in GNOME. In KDE, "<local>" is supported
  // as a hostname rule.

  // KDE allows one to reverse the bypass rules.
  config->proxy_rules().reverse_bypass =
      setting_getter_->BypassListIsReversed();

  return true;
}

ProxyConfigServiceLinux::Delegate::Delegate(base::Environment* env_var_getter)
    : env_var_getter_(env_var_getter) {
  // Figure out which SettingGetterImpl to use, if any.
  switch (base::nix::GetDesktopEnvironment(env_var_getter)) {
    case base::nix::DESKTOP_ENVIRONMENT_GNOME:
    case base::nix::DESKTOP_ENVIRONMENT_UNITY:
#if defined(USE_GIO)
      {
        scoped_ptr<SettingGetterImplGSettings> gs_getter(
            new SettingGetterImplGSettings());
        // We have to load symbols and check the GNOME version in use to decide
        // if we should use the gsettings getter. See LoadAndCheckVersion().
        if (gs_getter->LoadAndCheckVersion(env_var_getter))
          setting_getter_.reset(gs_getter.release());
      }
#endif
#if defined(USE_GCONF)
      // Fall back on gconf if gsettings is unavailable or incorrect.
      if (!setting_getter_.get())
        setting_getter_.reset(new SettingGetterImplGConf());
#endif
      break;
    case base::nix::DESKTOP_ENVIRONMENT_KDE3:
    case base::nix::DESKTOP_ENVIRONMENT_KDE4:
      setting_getter_.reset(new SettingGetterImplKDE(env_var_getter));
      break;
    case base::nix::DESKTOP_ENVIRONMENT_XFCE:
    case base::nix::DESKTOP_ENVIRONMENT_OTHER:
      break;
  }
}

ProxyConfigServiceLinux::Delegate::Delegate(
    base::Environment* env_var_getter, SettingGetter* setting_getter)
    : env_var_getter_(env_var_getter), setting_getter_(setting_getter) {
}

void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig(
    base::SingleThreadTaskRunner* glib_thread_task_runner,
    base::SingleThreadTaskRunner* io_thread_task_runner,
    base::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());
  glib_thread_task_runner_ = glib_thread_task_runner;
  io_thread_task_runner_ = io_thread_task_runner;

  // 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
  // setups.
  if (!io_thread_task_runner_.get() || !file_loop)
    VLOG(1) << "Monitoring of proxy setting changes is disabled";

  // Fetch and cache the current proxy config. The config is left in
  // cached_config_, where GetLatestProxyConfig() running on the IO thread
  // will expect to find it. This is safe to do because we return
  // before this ProxyConfigServiceLinux is passed on to
  // the ProxyService.

  // Note: It would be nice to prioritize environment variables
  // and only fall back to gconf if env vars were unset. But
  // gnome-terminal "helpfully" sets http_proxy and no_proxy, and it
  // does so even if the proxy mode is set to auto, which would
  // mislead us.

  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());
    VLOG(1) << "Obtained proxy settings from "
            << ProxyConfigSourceToString(cached_config_.source());

    // If gconf proxy mode is "none", meaning direct, then we take
    // that to be a valid config and will not check environment
    // variables. The alternative would have been to look for a proxy
    // 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
    // setting up notifications has the side effect of simulating a change, so
    // 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) {
      scoped_refptr<base::SingleThreadTaskRunner> required_loop =
          setting_getter_->GetNotificationTaskRunner();
      if (!required_loop.get() || required_loop->BelongsToCurrentThread()) {
        // In this case we are already on an acceptable thread.
        SetUpNotifications();
      } else {
        // Post a task to set up notifications. We don't wait for success.
        required_loop->PostTask(FROM_HERE, base::Bind(
            &ProxyConfigServiceLinux::Delegate::SetUpNotifications, this));
      }
    }
  }

  if (!got_config) {
    // We fall back on environment variables.
    //
    // 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.
      VLOG(1) << "Obtained proxy settings from environment variables";
    }
  }
}

// Depending on the SettingGetter in use, this method will be called
// on either the UI thread (GConf) or the file thread (KDE).
void ProxyConfigServiceLinux::Delegate::SetUpNotifications() {
  scoped_refptr<base::SingleThreadTaskRunner> required_loop =
      setting_getter_->GetNotificationTaskRunner();
  DCHECK(!required_loop.get() || required_loop->BelongsToCurrentThread());
  if (!setting_getter_->SetUpNotifications(this))
    LOG(ERROR) << "Unable to set up proxy configuration change notifications";
}

void ProxyConfigServiceLinux::Delegate::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void ProxyConfigServiceLinux::Delegate::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

ProxyConfigService::ConfigAvailability
    ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig(
        ProxyConfig* config) {
  // This is called from the IO thread.
  DCHECK(!io_thread_task_runner_.get() ||
         io_thread_task_runner_->BelongsToCurrentThread());

  // Simply return the last proxy configuration that glib_default_loop
  // notified us of.
  if (cached_config_.is_valid()) {
    *config = cached_config_;
  } else {
    *config = ProxyConfig::CreateDirect();
    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.
  return CONFIG_VALID;
}

// Depending on the SettingGetter in use, this method will be called
// on either the UI thread (GConf) or the file thread (KDE).
void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() {
  scoped_refptr<base::SingleThreadTaskRunner> required_loop =
      setting_getter_->GetNotificationTaskRunner();
  DCHECK(!required_loop.get() || required_loop->BelongsToCurrentThread());
  ProxyConfig new_config;
  bool valid = GetConfigFromSettings(&new_config);
  if (valid)
    new_config.set_id(1);  // mark it as valid

  // See if it is different from what we had before.
  if (new_config.is_valid() != reference_config_.is_valid() ||
      !new_config.Equals(reference_config_)) {
    // 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, new_config));
    // Update the thread-private copy in |reference_config_| as well.
    reference_config_ = new_config;
  } else {
    VLOG(1) << "Detected no-op change to proxy settings. Doing nothing.";
  }
}

void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig(
    const ProxyConfig& new_config) {
  DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
  VLOG(1) << "Proxy configuration changed";
  cached_config_ = new_config;
  FOR_EACH_OBSERVER(
      Observer, observers_,
      OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID));
}

void ProxyConfigServiceLinux::Delegate::PostDestroyTask() {
  if (!setting_getter_.get())
    return;
  scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop =
      setting_getter_->GetNotificationTaskRunner();
  if (!shutdown_loop.get() || shutdown_loop->BelongsToCurrentThread()) {
    // Already on the right thread, call directly.
    // This is the case for the unittests.
    OnDestroy();
  } else {
    // Post to shutdown thread. Note that on browser shutdown, we may quit
    // this MessageLoop and exit the program before ever running this.
    shutdown_loop->PostTask(FROM_HERE, base::Bind(
        &ProxyConfigServiceLinux::Delegate::OnDestroy, this));
  }
}
void ProxyConfigServiceLinux::Delegate::OnDestroy() {
  scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop =
      setting_getter_->GetNotificationTaskRunner();
  DCHECK(!shutdown_loop.get() || shutdown_loop->BelongsToCurrentThread());
  setting_getter_->ShutDown();
}

ProxyConfigServiceLinux::ProxyConfigServiceLinux()
    : delegate_(new Delegate(base::Environment::Create())) {
}

ProxyConfigServiceLinux::~ProxyConfigServiceLinux() {
  delegate_->PostDestroyTask();
}

ProxyConfigServiceLinux::ProxyConfigServiceLinux(
    base::Environment* env_var_getter)
    : delegate_(new Delegate(env_var_getter)) {
}

ProxyConfigServiceLinux::ProxyConfigServiceLinux(
    base::Environment* env_var_getter, SettingGetter* setting_getter)
    : delegate_(new Delegate(env_var_getter, setting_getter)) {
}

void ProxyConfigServiceLinux::AddObserver(Observer* observer) {
  delegate_->AddObserver(observer);
}

void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) {
  delegate_->RemoveObserver(observer);
}

ProxyConfigService::ConfigAvailability
    ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) {
  return delegate_->GetLatestProxyConfig(config);
}

}  // namespace net
