This source file includes following definitions.
- FreeIEConfig
 
- StartWatching
 
- CreateRegKey
 
- watch_event
 
- AddObserver
 
- StartWatchingRegistryForChanges
 
- AddKeyToWatchList
 
- OnObjectSignaled
 
- GetCurrentProxyConfig
 
- SetFromIEConfig
 
#include "net/proxy/proxy_config_service_win.h"
#include <windows.h>
#include <winhttp.h>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "base/win/registry.h"
#include "net/base/net_errors.h"
#include "net/proxy/proxy_config.h"
#pragma comment(lib, "winhttp.lib")
namespace net {
namespace {
const int kPollIntervalSec = 10;
void FreeIEConfig(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* ie_config) {
  if (ie_config->lpszAutoConfigUrl)
    GlobalFree(ie_config->lpszAutoConfigUrl);
  if (ie_config->lpszProxy)
    GlobalFree(ie_config->lpszProxy);
  if (ie_config->lpszProxyBypass)
    GlobalFree(ie_config->lpszProxyBypass);
}
}  
class ProxyConfigServiceWin::KeyEntry {
 public:
  bool StartWatching(base::win::ObjectWatcher::Delegate* delegate) {
    
    
    if (key_.StartWatching() != ERROR_SUCCESS)
      return false;
    
    
    if (!watcher_.StartWatching(key_.watch_event(), delegate))
      return false;
    return true;
  }
  bool CreateRegKey(HKEY rootkey, const wchar_t* subkey) {
    return key_.Create(rootkey, subkey, KEY_NOTIFY) == ERROR_SUCCESS;
  }
  HANDLE watch_event() const {
    return key_.watch_event();
  }
 private:
  base::win::RegKey key_;
  base::win::ObjectWatcher watcher_;
};
ProxyConfigServiceWin::ProxyConfigServiceWin()
    : PollingProxyConfigService(
          base::TimeDelta::FromSeconds(kPollIntervalSec),
          &ProxyConfigServiceWin::GetCurrentProxyConfig) {
}
ProxyConfigServiceWin::~ProxyConfigServiceWin() {
  
  
  base::ThreadRestrictions::ScopedAllowIO allow_io;
  STLDeleteElements(&keys_to_watch_);
}
void ProxyConfigServiceWin::AddObserver(Observer* observer) {
  
  StartWatchingRegistryForChanges();
  
  PollingProxyConfigService::AddObserver(observer);
}
void ProxyConfigServiceWin::StartWatchingRegistryForChanges() {
  if (!keys_to_watch_.empty())
    return;  
  
  
  base::ThreadRestrictions::ScopedAllowIO allow_io;
  
  
  
  
  
  
  
  
  
  
  
  AddKeyToWatchList(
      HKEY_CURRENT_USER,
      L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
  AddKeyToWatchList(
      HKEY_LOCAL_MACHINE,
      L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
  AddKeyToWatchList(
      HKEY_LOCAL_MACHINE,
      L"SOFTWARE\\Policies\\Microsoft\\Windows\\CurrentVersion\\"
      L"Internet Settings");
}
bool ProxyConfigServiceWin::AddKeyToWatchList(HKEY rootkey,
                                              const wchar_t* subkey) {
  scoped_ptr<KeyEntry> entry(new KeyEntry);
  if (!entry->CreateRegKey(rootkey, subkey))
    return false;
  if (!entry->StartWatching(this))
    return false;
  keys_to_watch_.push_back(entry.release());
  return true;
}
void ProxyConfigServiceWin::OnObjectSignaled(HANDLE object) {
  
  KeyEntryList::iterator it;
  for (it = keys_to_watch_.begin(); it != keys_to_watch_.end(); ++it) {
    if ((*it)->watch_event() == object)
      break;
  }
  DCHECK(it != keys_to_watch_.end());
  
  if (!(*it)->StartWatching(this))
    keys_to_watch_.erase(it);
  
  CheckForChangesNow();
}
void ProxyConfigServiceWin::GetCurrentProxyConfig(ProxyConfig* config) {
  WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_config = {0};
  if (!WinHttpGetIEProxyConfigForCurrentUser(&ie_config)) {
    LOG(ERROR) << "WinHttpGetIEProxyConfigForCurrentUser failed: " <<
        GetLastError();
    *config = ProxyConfig::CreateDirect();
    config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED);
    return;
  }
  SetFromIEConfig(config, ie_config);
  FreeIEConfig(&ie_config);
}
void ProxyConfigServiceWin::SetFromIEConfig(
    ProxyConfig* config,
    const WINHTTP_CURRENT_USER_IE_PROXY_CONFIG& ie_config) {
  if (ie_config.fAutoDetect)
    config->set_auto_detect(true);
  if (ie_config.lpszProxy) {
    
    
    config->proxy_rules().ParseFromString(
        base::UTF16ToASCII(ie_config.lpszProxy));
  }
  if (ie_config.lpszProxyBypass) {
    std::string proxy_bypass = base::UTF16ToASCII(ie_config.lpszProxyBypass);
    base::StringTokenizer proxy_server_bypass_list(proxy_bypass, ";, \t\n\r");
    while (proxy_server_bypass_list.GetNext()) {
      std::string bypass_url_domain = proxy_server_bypass_list.token();
      config->proxy_rules().bypass_rules.AddRuleFromString(bypass_url_domain);
    }
  }
  if (ie_config.lpszAutoConfigUrl)
    config->set_pac_url(GURL(ie_config.lpszAutoConfigUrl));
  config->set_source(PROXY_CONFIG_SOURCE_SYSTEM);
}
}