// 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_resolution/proxy_config_service_mac.h"

#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>

#include "base/bind.h"
#include "base/logging.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/sys_string_conversions.h"
#include "net/base/net_errors.h"
#include "net/base/proxy_server.h"
#include "net/proxy_resolution/proxy_info.h"
#include "starboard/types.h"

namespace net {

namespace {

// Utility function to pull out a boolean value from a dictionary and return it,
// returning a default value if the key is not present.
bool GetBoolFromDictionary(CFDictionaryRef dict,
                           CFStringRef key,
                           bool default_value) {
  CFNumberRef number = base::mac::GetValueFromDictionary<CFNumberRef>(dict,
                                                                      key);
  if (!number)
    return default_value;

  int int_value;
  if (CFNumberGetValue(number, kCFNumberIntType, &int_value))
    return int_value;
  else
    return default_value;
}

void GetCurrentProxyConfig(const NetworkTrafficAnnotationTag traffic_annotation,
                           ProxyConfigWithAnnotation* config) {
  base::ScopedCFTypeRef<CFDictionaryRef> config_dict(
      SCDynamicStoreCopyProxies(NULL));
  DCHECK(config_dict);
  ProxyConfig proxy_config;

  // auto-detect

  // There appears to be no UI for this configuration option, and we're not sure
  // if Apple's proxy code even takes it into account. But the constant is in
  // the header file so we'll use it.
  proxy_config.set_auto_detect(GetBoolFromDictionary(
      config_dict.get(), kSCPropNetProxiesProxyAutoDiscoveryEnable, false));

  // PAC file

  if (GetBoolFromDictionary(config_dict.get(),
                            kSCPropNetProxiesProxyAutoConfigEnable,
                            false)) {
    CFStringRef pac_url_ref = base::mac::GetValueFromDictionary<CFStringRef>(
        config_dict.get(), kSCPropNetProxiesProxyAutoConfigURLString);
    if (pac_url_ref)
      proxy_config.set_pac_url(GURL(base::SysCFStringRefToUTF8(pac_url_ref)));
  }

  // proxies (for now ftp, http, https, and SOCKS)

  if (GetBoolFromDictionary(config_dict.get(),
                            kSCPropNetProxiesFTPEnable,
                            false)) {
    ProxyServer proxy_server =
        ProxyServer::FromDictionary(ProxyServer::SCHEME_HTTP,
                                    config_dict.get(),
                                    kSCPropNetProxiesFTPProxy,
                                    kSCPropNetProxiesFTPPort);
    if (proxy_server.is_valid()) {
      proxy_config.proxy_rules().type =
          ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
      proxy_config.proxy_rules().proxies_for_ftp.SetSingleProxyServer(
          proxy_server);
    }
  }
  if (GetBoolFromDictionary(config_dict.get(),
                            kSCPropNetProxiesHTTPEnable,
                            false)) {
    ProxyServer proxy_server =
        ProxyServer::FromDictionary(ProxyServer::SCHEME_HTTP,
                                    config_dict.get(),
                                    kSCPropNetProxiesHTTPProxy,
                                    kSCPropNetProxiesHTTPPort);
    if (proxy_server.is_valid()) {
      proxy_config.proxy_rules().type =
          ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
      proxy_config.proxy_rules().proxies_for_http.SetSingleProxyServer(
          proxy_server);
    }
  }
  if (GetBoolFromDictionary(config_dict.get(),
                            kSCPropNetProxiesHTTPSEnable,
                            false)) {
    ProxyServer proxy_server =
        ProxyServer::FromDictionary(ProxyServer::SCHEME_HTTP,
                                    config_dict.get(),
                                    kSCPropNetProxiesHTTPSProxy,
                                    kSCPropNetProxiesHTTPSPort);
    if (proxy_server.is_valid()) {
      proxy_config.proxy_rules().type =
          ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
      proxy_config.proxy_rules().proxies_for_https.SetSingleProxyServer(
          proxy_server);
    }
  }
  if (GetBoolFromDictionary(config_dict.get(),
                            kSCPropNetProxiesSOCKSEnable,
                            false)) {
    ProxyServer proxy_server =
        ProxyServer::FromDictionary(ProxyServer::SCHEME_SOCKS5,
                                    config_dict.get(),
                                    kSCPropNetProxiesSOCKSProxy,
                                    kSCPropNetProxiesSOCKSPort);
    if (proxy_server.is_valid()) {
      proxy_config.proxy_rules().type =
          ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
      proxy_config.proxy_rules().fallback_proxies.SetSingleProxyServer(
          proxy_server);
    }
  }

  // proxy bypass list

  CFArrayRef bypass_array_ref = base::mac::GetValueFromDictionary<CFArrayRef>(
      config_dict.get(), kSCPropNetProxiesExceptionsList);
  if (bypass_array_ref) {
    CFIndex bypass_array_count = CFArrayGetCount(bypass_array_ref);
    for (CFIndex i = 0; i < bypass_array_count; ++i) {
      CFStringRef bypass_item_ref = base::mac::CFCast<CFStringRef>(
          CFArrayGetValueAtIndex(bypass_array_ref, i));
      if (!bypass_item_ref) {
        LOG(WARNING) << "Expected value for item " << i
                     << " in the kSCPropNetProxiesExceptionsList"
                        " to be a CFStringRef but it was not";

      } else {
        proxy_config.proxy_rules().bypass_rules.AddRuleFromString(
            base::SysCFStringRefToUTF8(bypass_item_ref));
      }
    }
  }

  // proxy bypass boolean

  if (GetBoolFromDictionary(config_dict.get(),
                            kSCPropNetProxiesExcludeSimpleHostnames,
                            false)) {
    proxy_config.proxy_rules().bypass_rules.AddRuleToBypassLocal();
  }

  *config = ProxyConfigWithAnnotation(proxy_config, traffic_annotation);
}

}  // namespace

// 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 ProxyConfigWithAnnotation& new_config) {
    if (parent_)
      parent_->OnProxyConfigChanged(new_config);
  }

 private:
  friend class base::RefCountedThreadSafe<Helper>;
  ~Helper() {}

  ProxyConfigServiceMac* parent_;
};

void ProxyConfigServiceMac::Forwarder::SetDynamicStoreNotificationKeys(
    SCDynamicStoreRef store) {
  proxy_config_service_->SetDynamicStoreNotificationKeys(store);
}

void ProxyConfigServiceMac::Forwarder::OnNetworkConfigChange(
    CFArrayRef changed_keys) {
  proxy_config_service_->OnNetworkConfigChange(changed_keys);
}

ProxyConfigServiceMac::ProxyConfigServiceMac(
    const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner,
    const NetworkTrafficAnnotationTag& traffic_annotation)
    : forwarder_(this),
      has_fetched_config_(false),
      helper_(new Helper(this)),
      sequenced_task_runner_(sequenced_task_runner),
      traffic_annotation_(traffic_annotation) {
  DCHECK(sequenced_task_runner_.get());
  config_watcher_.reset(new NetworkConfigWatcherMac(&forwarder_));
}

ProxyConfigServiceMac::~ProxyConfigServiceMac() {
  DCHECK(sequenced_task_runner_->RunsTasksInCurrentSequence());
  // Delete the config_watcher_ to ensure the notifier thread finishes before
  // this object is destroyed.
  config_watcher_.reset();
  helper_->Orphan();
}

void ProxyConfigServiceMac::AddObserver(Observer* observer) {
  DCHECK(sequenced_task_runner_->RunsTasksInCurrentSequence());
  observers_.AddObserver(observer);
}

void ProxyConfigServiceMac::RemoveObserver(Observer* observer) {
  DCHECK(sequenced_task_runner_->RunsTasksInCurrentSequence());
  observers_.RemoveObserver(observer);
}

ProxyConfigService::ConfigAvailability
ProxyConfigServiceMac::GetLatestProxyConfig(ProxyConfigWithAnnotation* config) {
  DCHECK(sequenced_task_runner_->RunsTasksInCurrentSequence());

  // Lazy-initialize by fetching the proxy setting from this thread.
  if (!has_fetched_config_) {
    GetCurrentProxyConfig(traffic_annotation_, &last_config_fetched_);
    has_fetched_config_ = true;
  }

  *config = last_config_fetched_;
  return has_fetched_config_ ? CONFIG_VALID : CONFIG_PENDING;
}

void ProxyConfigServiceMac::SetDynamicStoreNotificationKeys(
    SCDynamicStoreRef store) {
  // Called on notifier thread.

  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.
  ProxyConfigWithAnnotation new_config;
  GetCurrentProxyConfig(traffic_annotation_, &new_config);

  // Call OnProxyConfigChanged() on the TakeRunner to notify our observers.
  sequenced_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&Helper::OnProxyConfigChanged, helper_.get(), new_config));
}

void ProxyConfigServiceMac::OnProxyConfigChanged(
    const ProxyConfigWithAnnotation& new_config) {
  DCHECK(sequenced_task_runner_->RunsTasksInCurrentSequence());

  // Keep track of the last value we have seen.
  has_fetched_config_ = true;
  last_config_fetched_ = new_config;

  // Notify all the observers.
  for (auto& observer : observers_)
    observer.OnProxyConfigChanged(new_config, CONFIG_VALID);
}

}  // namespace net
