// Copyright 2013 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 "components/wifi/wifi_service.h"

#include <iphlpapi.h>
#include <objbase.h>
#include <wlanapi.h>

#include <set>

#include "base/base_paths_win.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/registry.h"
#include "components/onc/onc_constants.h"
#include "components/wifi/network_properties.h"
#include "third_party/libxml/chromium/libxml_utils.h"

namespace {
const wchar_t kNwCategoryWizardRegKey[] =
    L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Network\\"
    L"NwCategoryWizard";
const wchar_t kNwCategoryWizardRegValue[] = L"Show";
const wchar_t kNwCategoryWizardSavedRegValue[] = L"ShowSaved";
const wchar_t kNwCategoryWizardDeleteRegValue[] = L"ShowDelete";
const wchar_t kWlanApiDll[] = L"wlanapi.dll";

// Created Profile Dictionary keys
const char kProfileXmlKey[] = "xml";
const char kProfileSharedKey[] = "shared";

// WlanApi function names
const char kWlanConnect[] = "WlanConnect";
const char kWlanCloseHandle[] = "WlanCloseHandle";
const char kWlanDeleteProfile[] = "WlanDeleteProfile";
const char kWlanDisconnect[] = "WlanDisconnect";
const char kWlanEnumInterfaces[] = "WlanEnumInterfaces";
const char kWlanFreeMemory[] = "WlanFreeMemory";
const char kWlanGetAvailableNetworkList[] = "WlanGetAvailableNetworkList";
const char kWlanGetNetworkBssList[] = "WlanGetNetworkBssList";
const char kWlanGetProfile[] = "WlanGetProfile";
const char kWlanOpenHandle[] = "WlanOpenHandle";
const char kWlanQueryInterface[] = "WlanQueryInterface";
const char kWlanRegisterNotification[] = "WlanRegisterNotification";
const char kWlanSaveTemporaryProfile[] = "WlanSaveTemporaryProfile";
const char kWlanScan[] = "WlanScan";
const char kWlanSetProfile[] = "WlanSetProfile";

// WlanApi function definitions
typedef DWORD(WINAPI* WlanConnectFunction)(
    HANDLE hClientHandle,
    CONST GUID* pInterfaceGuid,
    CONST PWLAN_CONNECTION_PARAMETERS pConnectionParameters,
    PVOID pReserved);

typedef DWORD (WINAPI* WlanCloseHandleFunction)(
    HANDLE hClientHandle,
    PVOID pReserved);

typedef DWORD(WINAPI* WlanDeleteProfileFunction)(HANDLE hClientHandle,
                                                 const GUID* pInterfaceGuid,
                                                 LPCWSTR strProfileName,
                                                 PVOID pReserved);

typedef DWORD(WINAPI* WlanDisconnectFunction)(HANDLE hClientHandle,
                                              CONST GUID* pInterfaceGuid,
                                              PVOID pReserved);

typedef DWORD(WINAPI* WlanEnumInterfacesFunction)(
    HANDLE hClientHandle,
    PVOID pReserved,
    PWLAN_INTERFACE_INFO_LIST* ppInterfaceList);

typedef VOID (WINAPI* WlanFreeMemoryFunction)(
    _In_ PVOID pMemory);

typedef DWORD(WINAPI* WlanGetAvailableNetworkListFunction)(
    HANDLE hClientHandle,
    CONST GUID* pInterfaceGuid,
    DWORD dwFlags,
    PVOID pReserved,
    PWLAN_AVAILABLE_NETWORK_LIST* ppAvailableNetworkList);

typedef DWORD (WINAPI* WlanGetNetworkBssListFunction)(
    HANDLE hClientHandle,
    const GUID* pInterfaceGuid,
    const  PDOT11_SSID pDot11Ssid,
    DOT11_BSS_TYPE dot11BssType,
    BOOL bSecurityEnabled,
    PVOID pReserved,
    PWLAN_BSS_LIST* ppWlanBssList);

typedef DWORD(WINAPI* WlanGetProfileFunction)(HANDLE hClientHandle,
                                              CONST GUID* pInterfaceGuid,
                                              LPCWSTR strProfileName,
                                              PVOID pReserved,
                                              LPWSTR* pstrProfileXml,
                                              DWORD* pdwFlags,
                                              DWORD* pdwGrantedAccess);

typedef DWORD (WINAPI* WlanOpenHandleFunction)(
    DWORD dwClientVersion,
    PVOID pReserved,
    PDWORD pdwNegotiatedVersion,
    PHANDLE phClientHandle);

typedef DWORD(WINAPI* WlanQueryInterfaceFunction)(
    HANDLE hClientHandle,
    const GUID* pInterfaceGuid,
    WLAN_INTF_OPCODE OpCode,
    PVOID pReserved,
    PDWORD pdwDataSize,
    PVOID* ppData,
    PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType);

typedef DWORD (WINAPI* WlanRegisterNotificationFunction)(
    HANDLE hClientHandle,
    DWORD dwNotifSource,
    BOOL bIgnoreDuplicate,
    WLAN_NOTIFICATION_CALLBACK funcCallback,
    PVOID pCallbackContext,
    PVOID pReserved,
    PDWORD pdwPrevNotifSource);

typedef DWORD (WINAPI* WlanSaveTemporaryProfileFunction)(
    HANDLE hClientHandle,
    CONST GUID* pInterfaceGuid,
    LPCWSTR strProfileName,
    LPCWSTR strAllUserProfileSecurity,
    DWORD dwFlags,
    BOOL bOverWrite,
    PVOID pReserved);

typedef DWORD(WINAPI* WlanScanFunction)(HANDLE hClientHandle,
                                        CONST GUID* pInterfaceGuid,
                                        CONST PDOT11_SSID pDot11Ssid,
                                        CONST PWLAN_RAW_DATA pIeData,
                                        PVOID pReserved);

typedef DWORD(WINAPI* WlanSetProfileFunction)(HANDLE hClientHandle,
                                              const GUID* pInterfaceGuid,
                                              DWORD dwFlags,
                                              LPCWSTR strProfileXml,
                                              LPCWSTR strAllUserProfileSecurity,
                                              BOOL bOverwrite,
                                              PVOID pReserved,
                                              DWORD* pdwReasonCode);

// Values for WLANProfile XML.
const char kAuthenticationOpen[] = "open";
const char kAuthenticationWepPsk[] = "WEP";
const char kAuthenticationWpaPsk[] = "WPAPSK";
const char kAuthenticationWpa2Psk[] = "WPA2PSK";
const char kEncryptionAES[] = "AES";
const char kEncryptionNone[] = "none";
const char kEncryptionTKIP[] = "TKIP";
const char kEncryptionWEP[] = "WEP";
const char kKeyTypeNetwork[] = "networkKey";
const char kKeyTypePassphrase[] = "passPhrase";

}  // namespace

namespace wifi {

// Implementation of WiFiService for Windows.
class WiFiServiceImpl : public WiFiService {
 public:
  WiFiServiceImpl();
  virtual ~WiFiServiceImpl();

  // WiFiService interface implementation.
  virtual void Initialize(
      scoped_refptr<base::SequencedTaskRunner> task_runner) override;

  virtual void UnInitialize() override;

  virtual void GetProperties(const std::string& network_guid,
                             base::DictionaryValue* properties,
                             std::string* error) override;

  virtual void GetManagedProperties(const std::string& network_guid,
                                    base::DictionaryValue* managed_properties,
                                    std::string* error) override;

  virtual void GetState(const std::string& network_guid,
                        base::DictionaryValue* properties,
                        std::string* error) override;

  virtual void SetProperties(const std::string& network_guid,
                             scoped_ptr<base::DictionaryValue> properties,
                             std::string* error) override;

  virtual void CreateNetwork(bool shared,
                             scoped_ptr<base::DictionaryValue> properties,
                             std::string* network_guid,
                             std::string* error) override;

  virtual void GetVisibleNetworks(const std::string& network_type,
                                  base::ListValue* network_list,
                                  bool include_details) override;

  virtual void RequestNetworkScan() override;

  virtual void StartConnect(const std::string& network_guid,
                            std::string* error) override;

  virtual void StartDisconnect(const std::string& network_guid,
                               std::string* error) override;

  virtual void GetKeyFromSystem(const std::string& network_guid,
                                std::string* key_data,
                                std::string* error) override;

  virtual void SetEventObservers(
      scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
      const NetworkGuidListCallback& networks_changed_observer,
      const NetworkGuidListCallback& network_list_changed_observer) override;

  virtual void RequestConnectedNetworkUpdate() override {}

 private:
  typedef int32 EncryptionType;
  enum EncryptionTypeEnum {
    kEncryptionTypeAny = 0,
    kEncryptionTypeAES = 1,
    kEncryptionTypeTKIP = 2
  };

  // Static callback for Windows WLAN_NOTIFICATION. Calls OnWlanNotification
  // on WiFiServiceImpl passed back as |context|.
  static void __stdcall OnWlanNotificationCallback(
      PWLAN_NOTIFICATION_DATA wlan_notification_data,
      PVOID context);

  // Callback for Windows WLAN_NOTIFICATION. Called on random thread from
  // OnWlanNotificationCallback. Handles network connectivity and scan complete
  // notification and posts tasks to main thread.
  void OnWlanNotification(PWLAN_NOTIFICATION_DATA wlan_notification_data);

  // Handles NetworkScanComplete notification on main thread. Sends
  // |NetworkListChanged| event with new list of visible networks.
  void OnNetworkScanCompleteOnMainThread();

  // Wait up to |kMaxAttempts| with |kAttemptDelayMs| delay for connection
  // to network with |network_guid|. Reset DHCP and Notify that |NetworkChanged|
  // upon success.
  void WaitForNetworkConnect(const std::string& network_guid, int attempt);

  // Check |error_code| and if is not |ERROR_SUCCESS|, then store |error_name|
  // into |error|.
  bool CheckError(DWORD error_code,
                  const std::string& error_name,
                  std::string* error) const;

  // Return |iterator| to network identified by |network_guid| in |networks|
  // list.
  NetworkList::iterator FindNetwork(NetworkList& networks,
                                    const std::string& network_guid);

  // Save currently connected network profile so it can be re-connected later.
  DWORD SaveCurrentConnectedNetwork(const NetworkProperties& properties);

  // Sort networks, so connected/connecting is up front, then by type:
  // Ethernet, WiFi, Cellular, VPN
  static void SortNetworks(NetworkList* networks);

  // Open a WLAN client handle, register for WLAN notifications.
  DWORD OpenClientHandle();

  // Reset DHCP on wireless network to work around an issue when Windows
  // takes forever to connect to the network, e.g. after Chromecast
  // device reset.
  DWORD ResetDHCP();

  // Find |adapter_index_map| by |interface_guid| for DHCP reset.
  DWORD FindAdapterIndexMapByGUID(const GUID& interface_guid,
                                  IP_ADAPTER_INDEX_MAP* adapter_index_map);

  // Avoid the network location wizard to pop up when network is connected.
  // Preserve current value in |saved_nw_category_wizard_|.
  DWORD DisableNwCategoryWizard();

  // Restore network location wizard to value saved by DisableNwCategoryWizard.
  DWORD RestoreNwCategoryWizard();

  // Ensure that |client_| handle is initialized.
  DWORD EnsureInitialized();

  // Close |client_| handle if it is open.
  DWORD CloseClientHandle();

  // Get |profile_name| from unique |network_guid|.
  base::string16 ProfileNameFromGUID(const std::string& network_guid) const {
    return base::UTF8ToUTF16(network_guid);
  }

  // Get |dot11_ssid| from unique |network_guid|.
  DOT11_SSID SSIDFromGUID(const std::string& network_guid) const;

  // Get unique |network_guid| string based on |dot11_ssid|.
  std::string GUIDFromSSID(const DOT11_SSID& dot11_ssid) const {
    return std::string(reinterpret_cast<const char*>(dot11_ssid.ucSSID),
                       dot11_ssid.uSSIDLength);
  }

  // Get network |ssid| string based on |wlan|.
  std::string SSIDFromWLAN(const WLAN_AVAILABLE_NETWORK& wlan) const {
    return GUIDFromSSID(wlan.dot11Ssid);
  }

  // Get unique |network_guid| string based on |wlan|.
  std::string GUIDFromWLAN(const WLAN_AVAILABLE_NETWORK& wlan) const {
    return SSIDFromWLAN(wlan);
  }

  // Deduce |onc::wifi| security from |alg|.
  std::string SecurityFromDot11AuthAlg(DOT11_AUTH_ALGORITHM alg) const;

  // Deduce |onc::connection_state| from |wlan_state|.
  std::string ConnectionStateFromInterfaceState(
      WLAN_INTERFACE_STATE wlan_state) const;

  // Convert |EncryptionType| into WPA(2) encryption type string.
  std::string WpaEncryptionFromEncryptionType(
      EncryptionType encryption_type) const;

  // Deduce WLANProfile |authEncryption| values from |onc::wifi| security.
  bool AuthEncryptionFromSecurity(const std::string& security,
                                  EncryptionType encryption_type,
                                  std::string* authentication,
                                  std::string* encryption,
                                  std::string* key_type) const;

  // Populate |properties| based on |wlan|.
  void NetworkPropertiesFromAvailableNetwork(const WLAN_AVAILABLE_NETWORK& wlan,
                                             NetworkProperties* properties);

  // Update |properties| based on bss info from |wlan_bss_list|. If |bssid| in
  // |properties| is not empty, then it is not changed and |frequency| is set
  // based on that bssid.
  void UpdateNetworkPropertiesFromBssList(const std::string& network_guid,
                                          const WLAN_BSS_LIST& wlan_bss_list,
                                          NetworkProperties* properties);

  // Get the list of visible wireless networks.
  DWORD GetVisibleNetworkList(NetworkList* network_list);

  // Get properties of the network currently used (connected or in transition)
  // by interface. Populate |current_properties| on success.
  DWORD GetCurrentProperties(NetworkProperties* current_properties);

  // Connect to network |network_guid| using previosly stored profile if exists,
  // or just network sid. If |frequency| is not |kFrequencyUnknown| then
  // connects only to BSS which uses that frequency and returns
  // |ERROR_NOT_FOUND| if such BSS cannot be found.
  DWORD Connect(const std::string& network_guid, Frequency frequency);

  // Disconnect from currently connected network if any.
  DWORD Disconnect();

  // Get desired connection freqency if it was set using |SetProperties|.
  // Default to |kFrequencyAny|.
  Frequency GetFrequencyToConnect(const std::string& network_guid) const;

  // Get DOT11_BSSID_LIST of desired BSSIDs to connect to |ssid| network on
  // given |frequency|.
  DWORD GetDesiredBssList(DOT11_SSID& ssid,
                          Frequency frequency,
                          scoped_ptr<DOT11_BSSID_LIST>* desired_list);

  // Normalizes |frequency_in_mhz| into one of |Frequency| values.
  Frequency GetNormalizedFrequency(int frequency_in_mhz) const;

  // Create |profile_xml| based on |network_properties|. If |encryption_type|
  // is |kEncryptionTypeAny| applies the type most suitable for parameters in
  // |network_properties|.
  bool CreateProfile(const NetworkProperties& network_properties,
                     EncryptionType encryption_type,
                     std::string* profile_xml);

  // Save temporary wireless profile for |network_guid|.
  DWORD SaveTempProfile(const std::string& network_guid);

  // Get previously stored |profile_xml| for |network_guid|.
  // If |get_plaintext_key| is true, and process has sufficient privileges, then
  // <sharedKey> data in |profile_xml| will be unprotected.
  DWORD GetProfile(const std::string& network_guid,
                   bool get_plaintext_key,
                   std::string* profile_xml);

  // Set |profile_xml| to current user or all users depending on |shared| flag.
  // If |overwrite| is false, then returns an error if profile exists.
  DWORD SetProfile(bool shared, const std::string& profile_xml, bool overwrite);

  // Return true if there is previously stored profile xml for |network_guid|.
  bool HaveProfile(const std::string& network_guid);

  // Delete profile that was created, but failed to connect.
  DWORD DeleteCreatedProfile(const std::string& network_guid);

  // Notify |network_list_changed_observer_| that list of visible networks has
  // changed to |networks|.
  void NotifyNetworkListChanged(const NetworkList& networks);

  // Notify |networks_changed_observer_| that network |network_guid| status has
  // changed.
  void NotifyNetworkChanged(const std::string& network_guid);

  // Load WlanApi.dll from SystemDirectory and get Api function pointers.
  DWORD LoadWlanLibrary();
  // Instance of WlanApi.dll.
  HINSTANCE wlan_api_library_;
  // WlanApi function pointers
  WlanConnectFunction WlanConnect_function_;
  WlanCloseHandleFunction WlanCloseHandle_function_;
  WlanDeleteProfileFunction WlanDeleteProfile_function_;
  WlanDisconnectFunction WlanDisconnect_function_;
  WlanEnumInterfacesFunction WlanEnumInterfaces_function_;
  WlanFreeMemoryFunction WlanFreeMemory_function_;
  WlanGetAvailableNetworkListFunction WlanGetAvailableNetworkList_function_;
  // WlanGetNetworkBssList function may not be avaiable on Windows XP.
  WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_;
  WlanGetProfileFunction WlanGetProfile_function_;
  WlanOpenHandleFunction WlanOpenHandle_function_;
  WlanQueryInterfaceFunction WlanQueryInterface_function_;
  WlanRegisterNotificationFunction WlanRegisterNotification_function_;
  WlanScanFunction WlanScan_function_;
  WlanSetProfileFunction WlanSetProfile_function_;
  // WlanSaveTemporaryProfile function may not be avaiable on Windows XP.
  WlanSaveTemporaryProfileFunction WlanSaveTemporaryProfile_function_;

  // WLAN service handle.
  HANDLE client_;
  // GUID of the currently connected interface, if any, otherwise the GUID of
  // one of the WLAN interfaces.
  GUID interface_guid_;
  // Temporary storage of network properties indexed by |network_guid|. Persist
  // only in memory.
  base::DictionaryValue connect_properties_;
  // Preserved WLAN profile xml.
  std::map<std::string, std::string> saved_profiles_xml_;
  // Created WLAN Profiles, indexed by |network_guid|. Contains xml with TKIP
  // encryption type saved by |CreateNetwork| if applicable. Profile has to be
  // deleted if connection fails. Implicitly created profiles have to be deleted
  // if connection succeeds. Persist only in memory.
  base::DictionaryValue created_profiles_;
  // Observer to get notified when network(s) have changed (e.g. connect).
  NetworkGuidListCallback networks_changed_observer_;
  // Observer to get notified when network list has changed (scan complete).
  NetworkGuidListCallback network_list_changed_observer_;
  // Saved value of network location wizard show value.
  scoped_ptr<DWORD> saved_nw_category_wizard_;
  // MessageLoopProxy to post events on UI thread.
  scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
  // Task runner for worker tasks.
  scoped_refptr<base::SequencedTaskRunner> task_runner_;
  // If |false|, then |networks_changed_observer_| is not notified.
  bool enable_notify_network_changed_;
  // Number of attempts to check that network has connected successfully.
  static const int kMaxAttempts = 100;
  // Delay between attempts to check that network has connected successfully.
  static const int kAttemptDelayMs = 100;
  DISALLOW_COPY_AND_ASSIGN(WiFiServiceImpl);
};

WiFiServiceImpl::WiFiServiceImpl()
    : wlan_api_library_(NULL),
      WlanConnect_function_(NULL),
      WlanCloseHandle_function_(NULL),
      WlanDeleteProfile_function_(NULL),
      WlanDisconnect_function_(NULL),
      WlanEnumInterfaces_function_(NULL),
      WlanFreeMemory_function_(NULL),
      WlanGetAvailableNetworkList_function_(NULL),
      WlanGetNetworkBssList_function_(NULL),
      WlanGetProfile_function_(NULL),
      WlanOpenHandle_function_(NULL),
      WlanRegisterNotification_function_(NULL),
      WlanSaveTemporaryProfile_function_(NULL),
      WlanScan_function_(NULL),
      WlanSetProfile_function_(NULL),
      client_(NULL),
      enable_notify_network_changed_(true) {}

WiFiServiceImpl::~WiFiServiceImpl() { UnInitialize(); }

void WiFiServiceImpl::Initialize(
    scoped_refptr<base::SequencedTaskRunner> task_runner) {
  DCHECK(!client_);
  task_runner_.swap(task_runner);
  // Restore NwCategoryWizard in case if we crashed during connect.
  RestoreNwCategoryWizard();
  OpenClientHandle();
}

void WiFiServiceImpl::UnInitialize() {
  CloseClientHandle();
}

void WiFiServiceImpl::GetProperties(const std::string& network_guid,
                                    base::DictionaryValue* properties,
                                    std::string* error) {
  DWORD error_code = EnsureInitialized();
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  NetworkProperties connected_properties;
  error_code = GetCurrentProperties(&connected_properties);
  if (error_code == ERROR_SUCCESS &&
      connected_properties.guid == network_guid) {
    properties->Swap(connected_properties.ToValue(false).get());
    return;
  }

  NetworkList network_list;
  error_code = GetVisibleNetworkList(&network_list);
  if (error_code == ERROR_SUCCESS) {
    NetworkList::const_iterator it = FindNetwork(network_list, network_guid);
    if (it != network_list.end()) {
      DVLOG(1) << "Get Properties: " << network_guid << ":"
                  << it->connection_state;
      properties->Swap(it->ToValue(false).get());
      return;
    }
    error_code = ERROR_NOT_FOUND;
  }

  CheckError(error_code, kErrorWiFiService, error);
}

void WiFiServiceImpl::GetManagedProperties(
    const std::string& network_guid,
    base::DictionaryValue* managed_properties,
    std::string* error) {
  CheckError(ERROR_CALL_NOT_IMPLEMENTED, kErrorWiFiService, error);
}

void WiFiServiceImpl::GetState(const std::string& network_guid,
                               base::DictionaryValue* properties,
                               std::string* error) {
  CheckError(ERROR_CALL_NOT_IMPLEMENTED, kErrorWiFiService, error);
}

void WiFiServiceImpl::SetProperties(
    const std::string& network_guid,
    scoped_ptr<base::DictionaryValue> properties,
    std::string* error) {
  // Temporary preserve WiFi properties (desired frequency, wifi password) to
  // use in StartConnect.
  DCHECK(properties.get());
  if (!properties->HasKey(onc::network_type::kWiFi)) {
    DVLOG(0) << "Missing WiFi properties:" << *properties;
    *error = kErrorWiFiService;
    return;
  }

  base::DictionaryValue* existing_properties;
  // If the network properties already exist, don't override previously set
  // properties, unless they are set in |properties|.
  if (connect_properties_.GetDictionaryWithoutPathExpansion(
          network_guid, &existing_properties)) {
    existing_properties->MergeDictionary(properties.get());
  } else {
    connect_properties_.SetWithoutPathExpansion(network_guid,
                                                properties.release());
  }
}

void WiFiServiceImpl::CreateNetwork(
    bool shared,
    scoped_ptr<base::DictionaryValue> properties,
    std::string* network_guid,
    std::string* error) {
  DWORD error_code = EnsureInitialized();
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  NetworkProperties network_properties;
  if (!network_properties.UpdateFromValue(*properties)) {
    CheckError(ERROR_INVALID_DATA, kErrorWiFiService, error);
    return;
  }

  network_properties.guid = network_properties.ssid;
  std::string profile_xml;
  if (!CreateProfile(network_properties, kEncryptionTypeAny, &profile_xml)) {
    CheckError(ERROR_INVALID_DATA, kErrorWiFiService, error);
    return;
  }

  error_code = SetProfile(shared, profile_xml, false);
  if (CheckError(error_code, kErrorWiFiService, error)) {
    DVLOG(0) << profile_xml;
    return;
  }

  // WAP and WAP2 networks could use either AES or TKIP encryption type.
  // Preserve alternative profile to use in case if connection with default
  // encryption type fails.
  std::string tkip_profile_xml;
  if (!CreateProfile(network_properties,
                     kEncryptionTypeTKIP,
                     &tkip_profile_xml)) {
    CheckError(ERROR_INVALID_DATA, kErrorWiFiService, error);
    return;
  }

  if (tkip_profile_xml != profile_xml) {
    scoped_ptr<base::DictionaryValue> tkip_profile(new base::DictionaryValue());
    tkip_profile->SetString(kProfileXmlKey, tkip_profile_xml);
    tkip_profile->SetBoolean(kProfileSharedKey, shared);
    created_profiles_.SetWithoutPathExpansion(network_properties.guid,
                                              tkip_profile.release());
  }

  *network_guid = network_properties.guid;
}

void WiFiServiceImpl::GetVisibleNetworks(const std::string& network_type,
                                         base::ListValue* network_list,
                                         bool include_details) {
  if (!network_type.empty() &&
      network_type != onc::network_type::kAllTypes &&
      network_type != onc::network_type::kWiFi) {
    return;
  }

  DWORD error = EnsureInitialized();
  if (error == ERROR_SUCCESS) {
    NetworkList networks;
    error = GetVisibleNetworkList(&networks);
    if (error == ERROR_SUCCESS && !networks.empty()) {
      SortNetworks(&networks);
      for (NetworkList::const_iterator it = networks.begin();
           it != networks.end();
           ++it) {
        scoped_ptr<base::DictionaryValue> network(
            it->ToValue(!include_details));
        network_list->Append(network.release());
      }
    }
  }
}

void WiFiServiceImpl::RequestNetworkScan() {
  DWORD error = EnsureInitialized();
  if (error == ERROR_SUCCESS) {
    WlanScan_function_(client_, &interface_guid_, NULL, NULL, NULL);
  }
}

void WiFiServiceImpl::StartConnect(const std::string& network_guid,
                                   std::string* error) {
  DVLOG(1) << "Start Connect: " << network_guid;
  DWORD error_code = EnsureInitialized();
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  // Check, if the network is already connected on desired frequency.
  Frequency frequency = GetFrequencyToConnect(network_guid);
  NetworkProperties properties;
  GetCurrentProperties(&properties);
  bool already_connected =
      network_guid == properties.guid &&
      properties.connection_state == onc::connection_state::kConnected &&
      (frequency == kFrequencyAny || frequency == properties.frequency);

  // Connect only if network |network_guid| is not connected already.
  if (!already_connected) {
    SaveCurrentConnectedNetwork(properties);
    error_code = Connect(network_guid, frequency);
  }
  if (error_code == ERROR_SUCCESS) {
    // Notify that previously connected network has changed.
    NotifyNetworkChanged(properties.guid);
    // Start waiting for network connection state change.
    if (!networks_changed_observer_.is_null()) {
      DisableNwCategoryWizard();
      // Disable automatic network change notifications as they get fired
      // when network is just connected, but not yet accessible (doesn't
      // have valid IP address).
      enable_notify_network_changed_ = false;
      WaitForNetworkConnect(network_guid, 0);
      return;
    }
  } else if (error_code == ERROR_ACCESS_DENIED) {
    CheckError(error_code, kErrorNotConfigured, error);
  } else {
    CheckError(error_code, kErrorWiFiService, error);
  }
}

void WiFiServiceImpl::StartDisconnect(const std::string& network_guid,
                                      std::string* error) {
  DVLOG(1) << "Start Disconnect: " << network_guid;
  DWORD error_code = EnsureInitialized();
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  // Check, if the network is currently connected.
  NetworkProperties properties;
  GetCurrentProperties(&properties);
  if (network_guid == properties.guid) {
    if (properties.connection_state == onc::connection_state::kConnected)
      SaveCurrentConnectedNetwork(properties);
    error_code = Disconnect();
    if (error_code == ERROR_SUCCESS) {
      NotifyNetworkChanged(network_guid);
      return;
    }
  }
  CheckError(error_code, kErrorWiFiService, error);
}

void WiFiServiceImpl::GetKeyFromSystem(const std::string& network_guid,
                                       std::string* key_data,
                                       std::string* error) {
  DWORD error_code = EnsureInitialized();
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  std::string profile_xml;
  error_code = GetProfile(network_guid, true, &profile_xml);
  if (CheckError(error_code, kErrorWiFiService, error))
    return;

  const char kSharedKeyElement[] = "sharedKey";
  const char kProtectedElement[] = "protected";
  const char kKeyMaterialElement[] = "keyMaterial";

  // Quick check to verify presence of <sharedKey> element.
  if (profile_xml.find(kSharedKeyElement) == std::string::npos) {
    *error = kErrorWiFiService;
    return;
  }

  XmlReader reader;
  if (reader.Load(profile_xml)) {
    while (reader.Read()) {
      reader.SkipToElement();
      if (reader.NodeName() == kSharedKeyElement) {
        while (reader.Read()) {
          reader.SkipToElement();
          if (reader.NodeName() == kKeyMaterialElement) {
            reader.ReadElementContent(key_data);
          } else if (reader.NodeName() == kProtectedElement) {
            std::string protected_data;
            reader.ReadElementContent(&protected_data);
            // Without UAC privilege escalation call to |GetProfile| with
            // |WLAN_PROFILE_GET_PLAINTEXT_KEY| flag returns success, but has
            // protected keyMaterial. Report an error in this case.
            if (protected_data != "false") {
              *error = kErrorWiFiService;
              break;
            }
          }
        }
        return;
      }
    }
  }

  // Did not find passphrase in the profile.
  *error = kErrorWiFiService;
}

void WiFiServiceImpl::SetEventObservers(
    scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
    const NetworkGuidListCallback& networks_changed_observer,
    const NetworkGuidListCallback& network_list_changed_observer) {
  DWORD error_code = EnsureInitialized();
  if (error_code != ERROR_SUCCESS)
    return;
  message_loop_proxy_.swap(message_loop_proxy);
  if (!networks_changed_observer_.is_null() ||
      !network_list_changed_observer_.is_null()) {
    // Stop listening to WLAN notifications.
    WlanRegisterNotification_function_(client_,
                                       WLAN_NOTIFICATION_SOURCE_NONE,
                                       FALSE,
                                       OnWlanNotificationCallback,
                                       this,
                                       NULL,
                                       NULL);
  }
  networks_changed_observer_ = networks_changed_observer;
  network_list_changed_observer_ = network_list_changed_observer;
  if (!networks_changed_observer_.is_null() ||
      !network_list_changed_observer_.is_null()) {
    // Start listening to WLAN notifications.
    WlanRegisterNotification_function_(client_,
                                       WLAN_NOTIFICATION_SOURCE_ALL,
                                       FALSE,
                                       OnWlanNotificationCallback,
                                       this,
                                       NULL,
                                       NULL);
  }
}

void WiFiServiceImpl::OnWlanNotificationCallback(
    PWLAN_NOTIFICATION_DATA wlan_notification_data,
    PVOID context) {
  WiFiServiceImpl* service = reinterpret_cast<WiFiServiceImpl*>(context);
  service->OnWlanNotification(wlan_notification_data);
}

void WiFiServiceImpl::OnWlanNotification(
    PWLAN_NOTIFICATION_DATA wlan_notification_data) {
  if (message_loop_proxy_ == NULL)
    return;
  switch (wlan_notification_data->NotificationCode) {
    case wlan_notification_acm_disconnected:
    case wlan_notification_acm_connection_complete:
    case wlan_notification_acm_connection_attempt_fail: {
      PWLAN_CONNECTION_NOTIFICATION_DATA wlan_connection_data =
          reinterpret_cast<PWLAN_CONNECTION_NOTIFICATION_DATA>(
              wlan_notification_data->pData);
      message_loop_proxy_->PostTask(
          FROM_HERE,
          base::Bind(&WiFiServiceImpl::NotifyNetworkChanged,
                     base::Unretained(this),
                     GUIDFromSSID(wlan_connection_data->dot11Ssid)));
      break;
    }
    case wlan_notification_acm_scan_complete:
    case wlan_notification_acm_interface_removal:
      message_loop_proxy_->PostTask(
          FROM_HERE,
          base::Bind(&WiFiServiceImpl::OnNetworkScanCompleteOnMainThread,
                     base::Unretained(this)));
      break;
  }
}

void WiFiServiceImpl::OnNetworkScanCompleteOnMainThread() {
  NetworkList networks;
  // Get current list of visible networks and notify that network list has
  // changed.
  DWORD error = GetVisibleNetworkList(&networks);
  if (error != ERROR_SUCCESS)
    networks.clear();
  NotifyNetworkListChanged(networks);
}

void WiFiServiceImpl::WaitForNetworkConnect(const std::string& network_guid,
                                            int attempt) {
  // If network didn't get connected in |kMaxAttempts|, then try to connect
  // using different profile if it was created recently.
  if (attempt > kMaxAttempts) {
    LOG(ERROR) << kMaxAttempts << " attempts exceeded waiting for connect to "
               << network_guid;

    base::DictionaryValue* created_profile = NULL;
    // Check, whether this connection is using newly created profile.
    if (created_profiles_.GetDictionaryWithoutPathExpansion(
        network_guid, &created_profile)) {
      std::string tkip_profile_xml;
      bool shared = false;
      // Check, if this connection there is alternative TKIP profile xml that
      // should be tried. If there is, then set it up and try to connect again.
      if (created_profile->GetString(kProfileXmlKey, &tkip_profile_xml) &&
          created_profile->GetBoolean(kProfileSharedKey, &shared)) {
        // Remove TKIP profile xml, so it will not be tried again.
        created_profile->Remove(kProfileXmlKey, NULL);
        created_profile->Remove(kProfileSharedKey, NULL);
        DWORD error_code = SetProfile(shared, tkip_profile_xml, true);
        if (error_code == ERROR_SUCCESS) {
          // Try to connect with new profile.
          error_code = Connect(network_guid,
                               GetFrequencyToConnect(network_guid));
          if (error_code == ERROR_SUCCESS) {
            // Start waiting again.
            WaitForNetworkConnect(network_guid, 0);
            return;
          } else {
            LOG(ERROR) << "Failed to set created profile for " << network_guid
                       << " error=" << error_code;
          }
        }
      } else {
        // Connection has failed, so delete bad created profile.
        DWORD error_code = DeleteCreatedProfile(network_guid);
        if (error_code != ERROR_SUCCESS) {
          LOG(ERROR) << "Failed to delete created profile for " << network_guid
                     << " error=" << error_code;
        }
      }
    }
    // Restore automatic network change notifications and stop waiting.
    enable_notify_network_changed_ = true;
    RestoreNwCategoryWizard();
    return;
  }
  NetworkProperties current_properties;
  DWORD error = GetCurrentProperties(&current_properties);
  if (network_guid == current_properties.guid &&
      current_properties.connection_state ==
          onc::connection_state::kConnected) {
    DVLOG(1) << "WiFi Connected, Reset DHCP: " << network_guid;
    // Even though wireless network is now connected, it may still be unusable,
    // e.g. after Chromecast device reset. Reset DHCP on wireless network to
    // work around this issue.
    error = ResetDHCP();
    if (error != ERROR_SUCCESS)
      LOG(ERROR) << error;
    // There is no need to keep created profile as network is connected.
    created_profiles_.RemoveWithoutPathExpansion(network_guid, NULL);
    // Restore previously suppressed notifications.
    enable_notify_network_changed_ = true;
    RestoreNwCategoryWizard();
    NotifyNetworkChanged(network_guid);
  } else {
    // Continue waiting for network connection state change.
    task_runner_->PostDelayedTask(
        FROM_HERE,
        base::Bind(&WiFiServiceImpl::WaitForNetworkConnect,
                   base::Unretained(this),
                   network_guid,
                   ++attempt),
        base::TimeDelta::FromMilliseconds(kAttemptDelayMs));
  }
}

bool WiFiServiceImpl::CheckError(DWORD error_code,
                                 const std::string& error_name,
                                 std::string* error) const {
  if (error_code != ERROR_SUCCESS) {
    DLOG(ERROR) << "WiFiService Error " << error_code << ": " << error_name;
    *error = error_name;
    return true;
  }
  return false;
}

NetworkList::iterator WiFiServiceImpl::FindNetwork(
    NetworkList& networks,
    const std::string& network_guid) {
  for (NetworkList::iterator it = networks.begin(); it != networks.end();
       ++it) {
    if (it->guid == network_guid)
      return it;
  }
  return networks.end();
}

DWORD WiFiServiceImpl::SaveCurrentConnectedNetwork(
    const NetworkProperties& current_properties) {
  DWORD error = ERROR_SUCCESS;
  // Save currently connected network.
  if (!current_properties.guid.empty() &&
      current_properties.connection_state ==
          onc::connection_state::kConnected) {
    error = SaveTempProfile(current_properties.guid);
  }
  return error;
}

void WiFiServiceImpl::SortNetworks(NetworkList* networks) {
  networks->sort(NetworkProperties::OrderByType);
}

DWORD WiFiServiceImpl::LoadWlanLibrary() {
  // Use an absolute path to load the DLL to avoid DLL preloading attacks.
  base::FilePath path;
  if (!PathService::Get(base::DIR_SYSTEM, &path)) {
    LOG(ERROR) << "Unable to get system path.";
    return ERROR_NOT_FOUND;
  }
  wlan_api_library_ = ::LoadLibraryEx(path.Append(kWlanApiDll).value().c_str(),
                                      NULL,
                                      LOAD_WITH_ALTERED_SEARCH_PATH);
  if (!wlan_api_library_) {
    LOG(ERROR) << "Unable to load WlanApi.dll.";
    return ERROR_NOT_FOUND;
  }

  // Initialize WlanApi function pointers
  WlanConnect_function_ =
      reinterpret_cast<WlanConnectFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanConnect));
  WlanCloseHandle_function_ =
      reinterpret_cast<WlanCloseHandleFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanCloseHandle));
  WlanDeleteProfile_function_ =
      reinterpret_cast<WlanDeleteProfileFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanDeleteProfile));
  WlanDisconnect_function_ =
      reinterpret_cast<WlanDisconnectFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanDisconnect));
  WlanEnumInterfaces_function_ =
      reinterpret_cast<WlanEnumInterfacesFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanEnumInterfaces));
  WlanFreeMemory_function_ =
      reinterpret_cast<WlanFreeMemoryFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanFreeMemory));
  WlanGetAvailableNetworkList_function_ =
      reinterpret_cast<WlanGetAvailableNetworkListFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanGetAvailableNetworkList));
  WlanGetNetworkBssList_function_ =
      reinterpret_cast<WlanGetNetworkBssListFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanGetNetworkBssList));
  WlanGetProfile_function_ =
      reinterpret_cast<WlanGetProfileFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanGetProfile));
  WlanOpenHandle_function_ =
      reinterpret_cast<WlanOpenHandleFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanOpenHandle));
  WlanQueryInterface_function_ =
      reinterpret_cast<WlanQueryInterfaceFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanQueryInterface));
  WlanRegisterNotification_function_ =
      reinterpret_cast<WlanRegisterNotificationFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanRegisterNotification));
  WlanSaveTemporaryProfile_function_ =
      reinterpret_cast<WlanSaveTemporaryProfileFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanSaveTemporaryProfile));
  WlanScan_function_ =
      reinterpret_cast<WlanScanFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanScan));
  WlanSetProfile_function_ =
      reinterpret_cast<WlanSetProfileFunction>(
          ::GetProcAddress(wlan_api_library_, kWlanSetProfile));

  if (!WlanConnect_function_ ||
      !WlanCloseHandle_function_ ||
      !WlanDeleteProfile_function_ ||
      !WlanDisconnect_function_ ||
      !WlanEnumInterfaces_function_ ||
      !WlanFreeMemory_function_ ||
      !WlanGetAvailableNetworkList_function_ ||
      !WlanGetProfile_function_ ||
      !WlanOpenHandle_function_ ||
      !WlanQueryInterface_function_ ||
      !WlanRegisterNotification_function_ ||
      !WlanScan_function_ ||
      !WlanSetProfile_function_) {
    LOG(ERROR) << "Unable to find required WlanApi function.";
    FreeLibrary(wlan_api_library_);
    wlan_api_library_ = NULL;
    return ERROR_NOT_FOUND;
  }

  // Some WlanApi functions may not be available on XP.
  if (!WlanGetNetworkBssList_function_ ||
      !WlanSaveTemporaryProfile_function_) {
    DVLOG(1) << "WlanApi function is not be available on XP.";
  }

  return ERROR_SUCCESS;
}

DWORD WiFiServiceImpl::OpenClientHandle() {
  DWORD error = LoadWlanLibrary();
  DWORD service_version = 0;

  if (error != ERROR_SUCCESS)
    return error;

  // Open a handle to the service.
  error = WlanOpenHandle_function_(1, NULL, &service_version, &client_);

  PWLAN_INTERFACE_INFO_LIST interface_list = NULL;
  if (error == ERROR_SUCCESS) {
    // Enumerate wireless interfaces.
    error = WlanEnumInterfaces_function_(client_, NULL, &interface_list);
    if (error == ERROR_SUCCESS) {
      if (interface_list != NULL && interface_list->dwNumberOfItems != 0) {
        // Remember first interface just in case if none are connected.
        interface_guid_ = interface_list->InterfaceInfo[0].InterfaceGuid;
        // Try to find a connected interface.
        for (DWORD itf = 0; itf < interface_list->dwNumberOfItems; ++itf) {
          if (interface_list->InterfaceInfo[itf].isState ==
              wlan_interface_state_connected) {
            // Found connected interface, remember it!
            interface_guid_ = interface_list->InterfaceInfo[itf].InterfaceGuid;
            break;
          }
        }
      } else {
        error = ERROR_NOINTERFACE;
      }
    }
    // Clean up..
    if (interface_list != NULL)
      WlanFreeMemory_function_(interface_list);
  }
  return error;
}

DWORD WiFiServiceImpl::ResetDHCP() {
  IP_ADAPTER_INDEX_MAP adapter_index_map = {0};
  DWORD error = FindAdapterIndexMapByGUID(interface_guid_, &adapter_index_map);
  if (error != ERROR_SUCCESS) {
    LOG(ERROR) << error;
    return error;
  }
  error = ::IpReleaseAddress(&adapter_index_map);
  if (error != ERROR_SUCCESS) {
    if (error != ERROR_ADDRESS_NOT_ASSOCIATED) {
      LOG(ERROR) << error;
      return error;
    }
    DVLOG(1) << "Ignoring IpReleaseAddress Error: " << error;
  }
  error = ::IpRenewAddress(&adapter_index_map);
  if (error != ERROR_SUCCESS)
    LOG(ERROR) << error;
  return error;
}

DWORD WiFiServiceImpl::FindAdapterIndexMapByGUID(
    const GUID& interface_guid,
    IP_ADAPTER_INDEX_MAP* adapter_index_map) {
  base::string16 guid_string;
  const int kGUIDSize = 39;
  ::StringFromGUID2(
      interface_guid, WriteInto(&guid_string, kGUIDSize), kGUIDSize);

  ULONG buffer_length = 0;
  DWORD error = ::GetInterfaceInfo(NULL, &buffer_length);
  if (error == ERROR_INSUFFICIENT_BUFFER) {
    scoped_ptr<unsigned char[]> buffer(new unsigned char[buffer_length]);
    IP_INTERFACE_INFO* interface_info =
        reinterpret_cast<IP_INTERFACE_INFO*>(buffer.get());
    error = GetInterfaceInfo(interface_info, &buffer_length);
    if (error == ERROR_SUCCESS) {
      for (int adapter = 0; adapter < interface_info->NumAdapters; ++adapter) {
        if (EndsWith(
                interface_info->Adapter[adapter].Name, guid_string, false)) {
          *adapter_index_map = interface_info->Adapter[adapter];
          break;
        }
      }
    }
  }
  return error;
}

DWORD WiFiServiceImpl::DisableNwCategoryWizard() {
  base::win::RegKey nw_category_wizard;
  DWORD error = nw_category_wizard.Open(HKEY_CURRENT_USER,
                                        kNwCategoryWizardRegKey,
                                        KEY_READ | KEY_SET_VALUE);
  if (error == ERROR_SUCCESS) {
    // Save current value if present.
    if (nw_category_wizard.HasValue(kNwCategoryWizardRegValue)) {
      DWORD saved = 0u;
      error = nw_category_wizard.ReadValueDW(kNwCategoryWizardRegValue,
                                             &saved);
      if (error == ERROR_SUCCESS) {
        error = nw_category_wizard.WriteValue(kNwCategoryWizardSavedRegValue,
                                              saved);
      }
    } else {
      // Mark that temporary value has to be deleted.
      error = nw_category_wizard.WriteValue(kNwCategoryWizardDeleteRegValue,
                                            1u);
    }

    // Disable network location wizard.
    error = nw_category_wizard.WriteValue(kNwCategoryWizardRegValue,
                                          static_cast<DWORD>(0));
  }

  return error;
}

DWORD WiFiServiceImpl::RestoreNwCategoryWizard() {
  base::win::RegKey nw_category_wizard;
  DWORD error = nw_category_wizard.Open(HKEY_CURRENT_USER,
                                        kNwCategoryWizardRegKey,
                                        KEY_SET_VALUE);
  if (error == ERROR_SUCCESS) {
    // Restore saved value if present.
    if (nw_category_wizard.HasValue(kNwCategoryWizardSavedRegValue)) {
      DWORD saved = 0u;
      error = nw_category_wizard.ReadValueDW(kNwCategoryWizardSavedRegValue,
                                             &saved);
      if (error == ERROR_SUCCESS) {
        error = nw_category_wizard.WriteValue(kNwCategoryWizardRegValue,
                                              saved);
        error = nw_category_wizard.DeleteValue(kNwCategoryWizardSavedRegValue);
      }
    } else if (nw_category_wizard.HasValue(kNwCategoryWizardDeleteRegValue)) {
      error = nw_category_wizard.DeleteValue(kNwCategoryWizardRegValue);
      error = nw_category_wizard.DeleteValue(kNwCategoryWizardDeleteRegValue);
    }
  }

  return error;
}

DWORD WiFiServiceImpl::EnsureInitialized() {
  if (client_ != NULL)
    return ERROR_SUCCESS;
  return ERROR_NOINTERFACE;
}

DWORD WiFiServiceImpl::CloseClientHandle() {
  DWORD error = ERROR_SUCCESS;
  if (client_ != NULL) {
    error = WlanCloseHandle_function_(client_, NULL);
    client_ = NULL;
  }
  if (wlan_api_library_ != NULL) {
    WlanConnect_function_ = NULL;
    WlanCloseHandle_function_ = NULL;
    WlanDeleteProfile_function_ = NULL;
    WlanDisconnect_function_ = NULL;
    WlanEnumInterfaces_function_ = NULL;
    WlanFreeMemory_function_ = NULL;
    WlanGetAvailableNetworkList_function_ = NULL;
    WlanGetNetworkBssList_function_ = NULL;
    WlanGetProfile_function_ = NULL;
    WlanOpenHandle_function_ = NULL;
    WlanRegisterNotification_function_ = NULL;
    WlanSaveTemporaryProfile_function_ = NULL;
    WlanScan_function_ = NULL;
    WlanSetProfile_function_ = NULL;
    ::FreeLibrary(wlan_api_library_);
    wlan_api_library_ = NULL;
  }
  return error;
}

DOT11_SSID WiFiServiceImpl::SSIDFromGUID(
    const std::string& network_guid) const {
  DOT11_SSID ssid = {0};
  if (network_guid.length() <= DOT11_SSID_MAX_LENGTH) {
    ssid.uSSIDLength = static_cast<ULONG>(network_guid.length());
    strncpy(reinterpret_cast<char*>(ssid.ucSSID),
            network_guid.c_str(),
            ssid.uSSIDLength);
  } else {
    NOTREACHED();
  }
  return ssid;
}

std::string WiFiServiceImpl::SecurityFromDot11AuthAlg(
    DOT11_AUTH_ALGORITHM alg) const {
  switch (alg) {
    case DOT11_AUTH_ALGO_RSNA:
      return onc::wifi::kWPA_EAP;
    case DOT11_AUTH_ALGO_RSNA_PSK:
      return onc::wifi::kWPA_PSK;
    case DOT11_AUTH_ALGO_80211_SHARED_KEY:
      return onc::wifi::kWEP_PSK;
    case DOT11_AUTH_ALGO_80211_OPEN:
      return onc::wifi::kSecurityNone;
    default:
      return onc::wifi::kWPA_EAP;
  }
}

std::string WiFiServiceImpl::ConnectionStateFromInterfaceState(
    WLAN_INTERFACE_STATE wlan_state) const {
  switch (wlan_state) {
    case wlan_interface_state_connected:
      // TODO(mef): Even if |wlan_state| is connected, the network may still
      // not be reachable, and should be resported as |kConnecting|.
      return onc::connection_state::kConnected;
    case wlan_interface_state_associating:
    case wlan_interface_state_discovering:
    case wlan_interface_state_authenticating:
      return onc::connection_state::kConnecting;
    default:
      return onc::connection_state::kNotConnected;
  }
}

void WiFiServiceImpl::NetworkPropertiesFromAvailableNetwork(
    const WLAN_AVAILABLE_NETWORK& wlan,
    NetworkProperties* properties) {
  // TODO(mef): It would be nice for the connection states in
  // getVisibleNetworks and getProperties results to be consistent.
  if (wlan.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) {
    properties->connection_state = onc::connection_state::kConnected;
  } else {
    properties->connection_state = onc::connection_state::kNotConnected;
  }

  properties->ssid = SSIDFromWLAN(wlan);
  properties->name = properties->ssid;
  properties->guid = GUIDFromWLAN(wlan);
  properties->type = onc::network_type::kWiFi;
  properties->security =
      SecurityFromDot11AuthAlg(wlan.dot11DefaultAuthAlgorithm);
  properties->signal_strength = wlan.wlanSignalQuality;
}

void WiFiServiceImpl::UpdateNetworkPropertiesFromBssList(
    const std::string& network_guid,
    const WLAN_BSS_LIST& wlan_bss_list,
    NetworkProperties* properties) {
  if (network_guid.empty())
    return;

  DOT11_SSID ssid = SSIDFromGUID(network_guid);
  for (size_t bss = 0; bss < wlan_bss_list.dwNumberOfItems; ++bss) {
    const WLAN_BSS_ENTRY& bss_entry(wlan_bss_list.wlanBssEntries[bss]);
    if (bss_entry.dot11Ssid.uSSIDLength == ssid.uSSIDLength &&
        0 == memcmp(bss_entry.dot11Ssid.ucSSID,
                    ssid.ucSSID,
                    bss_entry.dot11Ssid.uSSIDLength)) {
      std::string bssid = NetworkProperties::MacAddressAsString(
          bss_entry.dot11Bssid);
      Frequency frequency = GetNormalizedFrequency(
          bss_entry.ulChCenterFrequency / 1000);
      properties->frequency_set.insert(frequency);
      if (properties->bssid.empty() || properties->bssid == bssid) {
        properties->frequency = frequency;
        properties->bssid = bssid;
      }
    }
  }
}

// Get the list of visible wireless networks
DWORD WiFiServiceImpl::GetVisibleNetworkList(NetworkList* network_list) {
  if (client_ == NULL) {
    NOTREACHED();
    return ERROR_NOINTERFACE;
  }

  DWORD error = ERROR_SUCCESS;
  PWLAN_AVAILABLE_NETWORK_LIST available_network_list = NULL;
  PWLAN_BSS_LIST bss_list = NULL;

  error = WlanGetAvailableNetworkList_function_(
      client_,
      &interface_guid_,
      WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES,
      NULL,
      &available_network_list);

  std::set<std::string> network_guids;

  if (error == ERROR_SUCCESS &&
      available_network_list &&
      WlanGetNetworkBssList_function_) {
    // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
    // needed, then different method of getting BSS (e.g. OID query) will have
    // to be used.
    error = WlanGetNetworkBssList_function_(client_,
                                            &interface_guid_,
                                            NULL,
                                            dot11_BSS_type_any,
                                            FALSE,
                                            NULL,
                                            &bss_list);
    if (error == ERROR_SUCCESS && NULL != bss_list) {
      for (DWORD i = 0; i < available_network_list->dwNumberOfItems; ++i) {
        NetworkProperties network_properties;
        NetworkPropertiesFromAvailableNetwork(
            available_network_list->Network[i],
            &network_properties);
        UpdateNetworkPropertiesFromBssList(network_properties.guid,
                                           *bss_list,
                                           &network_properties);
        // Check for duplicate network guids.
        if (network_guids.count(network_properties.guid)) {
          // There should be no difference between properties except for
          // |connection_state|, so mark it as |kConnected| if either one is.
          if (network_properties.connection_state ==
              onc::connection_state::kConnected) {
            NetworkList::iterator previous_network_properties =
                FindNetwork(*network_list, network_properties.guid);
            DCHECK(previous_network_properties != network_list->end());
            previous_network_properties->connection_state =
                network_properties.connection_state;
          }
        } else {
          network_list->push_back(network_properties);
        }
        network_guids.insert(network_properties.guid);
      }
    }
  }

  // Clean up.
  if (available_network_list != NULL) {
    WlanFreeMemory_function_(available_network_list);
  }
  if (bss_list != NULL) {
    WlanFreeMemory_function_(bss_list);
  }
  return error;
}

DWORD WiFiServiceImpl::GetCurrentProperties(NetworkProperties* properties) {
  if (client_ == NULL) {
    NOTREACHED();
    return ERROR_NOINTERFACE;
  }

  // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
  // needed, then different method of getting BSS (e.g. OID query) will have
  // to be used.
  if (WlanGetNetworkBssList_function_ == NULL)
    return ERROR_NOINTERFACE;

  DWORD error = ERROR_SUCCESS;
  DWORD data_size = 0;
  PWLAN_CONNECTION_ATTRIBUTES wlan_connection_attributes = NULL;
  PWLAN_BSS_LIST bss_list = NULL;
  error = WlanQueryInterface_function_(
      client_,
      &interface_guid_,
      wlan_intf_opcode_current_connection,
      NULL,
      &data_size,
      reinterpret_cast<PVOID*>(&wlan_connection_attributes),
      NULL);
  if (error == ERROR_SUCCESS &&
      wlan_connection_attributes != NULL) {
    WLAN_ASSOCIATION_ATTRIBUTES& connected_wlan =
        wlan_connection_attributes->wlanAssociationAttributes;

    properties->connection_state = ConnectionStateFromInterfaceState(
        wlan_connection_attributes->isState);
    properties->ssid = GUIDFromSSID(connected_wlan.dot11Ssid);
    properties->name = properties->ssid;
    properties->guid = GUIDFromSSID(connected_wlan.dot11Ssid);
    properties->type = onc::network_type::kWiFi;
    properties->bssid = NetworkProperties::MacAddressAsString(
        connected_wlan.dot11Bssid);
    properties->security = SecurityFromDot11AuthAlg(
        wlan_connection_attributes->wlanSecurityAttributes.dot11AuthAlgorithm);
    properties->signal_strength = connected_wlan.wlanSignalQuality;

    error = WlanGetNetworkBssList_function_(client_,
                                            &interface_guid_,
                                            &connected_wlan.dot11Ssid,
                                            connected_wlan.dot11BssType,
                                            FALSE,
                                            NULL,
                                            &bss_list);
    if (error == ERROR_SUCCESS && NULL != bss_list) {
      UpdateNetworkPropertiesFromBssList(properties->guid,
                                         *bss_list,
                                         properties);
    }
  }

  // Clean up.
  if (wlan_connection_attributes != NULL)
    WlanFreeMemory_function_(wlan_connection_attributes);

  if (bss_list != NULL)
    WlanFreeMemory_function_(bss_list);

  return error;
}

Frequency WiFiServiceImpl::GetFrequencyToConnect(
    const std::string& network_guid) const {
  // Check whether desired frequency is set in |connect_properties_|.
  const base::DictionaryValue* properties;
  if (connect_properties_.GetDictionaryWithoutPathExpansion(network_guid,
                                                            &properties)) {
    const base::DictionaryValue* wifi;
    if (properties->GetDictionary(onc::network_type::kWiFi, &wifi)) {
      int frequency;
      if (wifi->GetInteger(onc::wifi::kFrequency, &frequency))
        return GetNormalizedFrequency(frequency);
    }
  }
  return kFrequencyAny;
}

DWORD WiFiServiceImpl::GetDesiredBssList(
    DOT11_SSID& ssid,
    Frequency frequency,
    scoped_ptr<DOT11_BSSID_LIST>* desired_list) {
  if (client_ == NULL) {
    NOTREACHED();
    return ERROR_NOINTERFACE;
  }

  desired_list->reset();

  if (frequency == kFrequencyAny)
    return ERROR_SUCCESS;

  // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
  // needed, then different method of getting BSS (e.g. OID query) will have
  // to be used.
  if (!WlanGetNetworkBssList_function_)
    return ERROR_NOT_SUPPORTED;

  DWORD error = ERROR_SUCCESS;
  PWLAN_BSS_LIST bss_list = NULL;

  error = WlanGetNetworkBssList_function_(client_,
                                          &interface_guid_,
                                          &ssid,
                                          dot11_BSS_type_infrastructure,
                                          FALSE,
                                          NULL,
                                          &bss_list);
  if (error == ERROR_SUCCESS && NULL != bss_list) {
    unsigned int best_quality = 0u;
    size_t best_index = 0;
    Frequency bss_frequency;

    // Go through bss_list and find best quality BSSID with matching frequency.
    for (size_t bss = 0; bss < bss_list->dwNumberOfItems; ++bss) {
      const WLAN_BSS_ENTRY& bss_entry(bss_list->wlanBssEntries[bss]);
      if (bss_entry.dot11Ssid.uSSIDLength != ssid.uSSIDLength ||
          0 != memcmp(bss_entry.dot11Ssid.ucSSID,
                      ssid.ucSSID,
                      bss_entry.dot11Ssid.uSSIDLength))
        continue;

      bss_frequency = GetNormalizedFrequency(
          bss_entry.ulChCenterFrequency / 1000);
      if (bss_frequency == frequency &&
          bss_entry.uLinkQuality > best_quality) {
        best_quality = bss_entry.uLinkQuality;
        best_index = bss;
      }
    }

    // If any matching BSS were found, prepare the header.
    if (best_quality > 0) {
      const WLAN_BSS_ENTRY& bss_entry(bss_list->wlanBssEntries[best_index]);
      scoped_ptr<DOT11_BSSID_LIST> selected_list(new DOT11_BSSID_LIST);

      selected_list->Header.Revision = DOT11_BSSID_LIST_REVISION_1;
      selected_list->Header.Size = sizeof(DOT11_BSSID_LIST);
      selected_list->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
      selected_list->uNumOfEntries = 1;
      selected_list->uTotalNumOfEntries = 1;
      std::copy(bss_entry.dot11Bssid,
                bss_entry.dot11Bssid+sizeof(bss_entry.dot11Bssid),
                selected_list->BSSIDs[0]);
      desired_list->swap(selected_list);
      DVLOG(1) << "Quality: " << best_quality << " BSS: "
          << NetworkProperties::MacAddressAsString(bss_entry.dot11Bssid);
    } else {
      error = ERROR_NOT_FOUND;
    }
  }

  // Clean up.
  if (bss_list != NULL) {
    WlanFreeMemory_function_(bss_list);
  }
  return error;
}

Frequency WiFiServiceImpl::GetNormalizedFrequency(int frequency_in_mhz) const {
  if (frequency_in_mhz == 0)
    return kFrequencyAny;
  if (frequency_in_mhz < 3000)
    return kFrequency2400;
  return kFrequency5000;
}

DWORD WiFiServiceImpl::Connect(const std::string& network_guid,
                               Frequency frequency) {
  if (client_ == NULL) {
    NOTREACHED();
    return ERROR_NOINTERFACE;
  }

  DWORD error = ERROR_SUCCESS;
  DOT11_SSID ssid = SSIDFromGUID(network_guid);
  scoped_ptr<DOT11_BSSID_LIST> desired_bss_list;
  error = GetDesiredBssList(ssid, frequency, &desired_bss_list);
  if (error == ERROR_SUCCESS) {
    if (HaveProfile(network_guid)) {
      base::string16 profile_name = ProfileNameFromGUID(network_guid);
      WLAN_CONNECTION_PARAMETERS wlan_params = {
          wlan_connection_mode_profile,
          profile_name.c_str(),
          NULL,
          desired_bss_list.get(),
          dot11_BSS_type_any,
          0};
      error = WlanConnect_function_(
          client_, &interface_guid_, &wlan_params, NULL);
    } else {
      // If network is available, but is not open security, then it cannot be
      // connected without profile, so return 'access denied' error.
      scoped_ptr<base::DictionaryValue> properties (new base::DictionaryValue);
      const base::DictionaryValue* wifi;
      std::string wifi_security;
      std::string error_string;
      GetProperties(network_guid, properties.get(), &error_string);
      if (error_string.empty() &&
          properties->GetDictionary(onc::network_type::kWiFi, &wifi) &&
          wifi->GetString(onc::wifi::kSecurity, &wifi_security) &&
          wifi_security != onc::wifi::kSecurityNone) {
        error = ERROR_ACCESS_DENIED;
        LOG(ERROR) << error;
        return error;
      }
      WLAN_CONNECTION_PARAMETERS wlan_params = {
          wlan_connection_mode_discovery_unsecure,
          NULL,
          &ssid,
          desired_bss_list.get(),
          dot11_BSS_type_infrastructure,
          0};
      error = WlanConnect_function_(
          client_, &interface_guid_, &wlan_params, NULL);
    }
  }

  return error;
}

DWORD WiFiServiceImpl::Disconnect() {
  if (client_ == NULL) {
    NOTREACHED();
    return ERROR_NOINTERFACE;
  }

  DWORD error = ERROR_SUCCESS;
  error = WlanDisconnect_function_(client_, &interface_guid_, NULL);
  return error;
}

DWORD WiFiServiceImpl::SaveTempProfile(const std::string& network_guid) {
  if (client_ == NULL) {
    NOTREACHED();
    return ERROR_NOINTERFACE;
  }

  DWORD error = ERROR_SUCCESS;
  base::string16 profile_name = ProfileNameFromGUID(network_guid);
  // TODO(mef): WlanSaveTemporaryProfile is not available on XP. If XP support
  // is needed, then different method of saving network profile will have to be
  // used.
  if (WlanSaveTemporaryProfile_function_) {
    error = WlanSaveTemporaryProfile_function_(client_,
                                               &interface_guid_,
                                               profile_name.c_str(),
                                               NULL,
                                               WLAN_PROFILE_USER,
                                               true,
                                               NULL);
  } else {
    error = ERROR_NOT_SUPPORTED;
  }
  return error;
}

DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid,
                                  bool get_plaintext_key,
                                  std::string* profile_xml) {
  if (client_ == NULL) {
    NOTREACHED();
    return ERROR_NOINTERFACE;
  }

  DWORD error = ERROR_SUCCESS;
  base::string16 profile_name = ProfileNameFromGUID(network_guid);
  DWORD flags = get_plaintext_key ? WLAN_PROFILE_GET_PLAINTEXT_KEY : 0;
  LPWSTR str_profile_xml = NULL;
  error = WlanGetProfile_function_(client_,
                                   &interface_guid_,
                                   profile_name.c_str(),
                                   NULL,
                                   &str_profile_xml,
                                   &flags,
                                   NULL);

  if (error == ERROR_SUCCESS && str_profile_xml != NULL) {
    *profile_xml = base::UTF16ToUTF8(str_profile_xml);
  }
  // Clean up.
  if (str_profile_xml != NULL) {
    WlanFreeMemory_function_(str_profile_xml);
  }

  return error;
}

DWORD WiFiServiceImpl::SetProfile(bool shared,
                                  const std::string& profile_xml,
                                  bool overwrite) {
  DWORD error_code = ERROR_SUCCESS;

  base::string16 profile_xml16(base::UTF8ToUTF16(profile_xml));
  DWORD reason_code = 0u;

  error_code = WlanSetProfile_function_(client_,
                                        &interface_guid_,
                                        shared ? 0 : WLAN_PROFILE_USER,
                                        profile_xml16.c_str(),
                                        NULL,
                                        overwrite,
                                        NULL,
                                        &reason_code);
  return error_code;
}

bool WiFiServiceImpl::HaveProfile(const std::string& network_guid) {
  std::string profile_xml;
  return GetProfile(network_guid, false, &profile_xml) == ERROR_SUCCESS;
}


DWORD WiFiServiceImpl::DeleteCreatedProfile(const std::string& network_guid) {
  base::DictionaryValue* created_profile = NULL;
  DWORD error_code = ERROR_SUCCESS;
  // Check, whether this connection is using new created profile, and remove it.
  if (created_profiles_.GetDictionaryWithoutPathExpansion(
      network_guid, &created_profile)) {
    // Connection has failed, so delete it.
    base::string16 profile_name = ProfileNameFromGUID(network_guid);
    error_code = WlanDeleteProfile_function_(client_,
                                              &interface_guid_,
                                              profile_name.c_str(),
                                              NULL);
    created_profiles_.RemoveWithoutPathExpansion(network_guid, NULL);
  }
  return error_code;
}

std::string WiFiServiceImpl::WpaEncryptionFromEncryptionType(
    EncryptionType encryption_type) const {
  if (encryption_type == kEncryptionTypeTKIP)
    return kEncryptionTKIP;
  return kEncryptionAES;
}

bool WiFiServiceImpl::AuthEncryptionFromSecurity(
    const std::string& security,
    EncryptionType encryption_type,
    std::string* authentication,
    std::string* encryption,
    std::string* key_type) const {
  if (security == onc::wifi::kSecurityNone) {
    *authentication = kAuthenticationOpen;
    *encryption = kEncryptionNone;
  } else if (security == onc::wifi::kWEP_PSK) {
    *authentication = kAuthenticationOpen;
    *encryption = kEncryptionWEP;
    *key_type = kKeyTypeNetwork;
  } else if (security == onc::wifi::kWPA_PSK) {
    *authentication = kAuthenticationWpaPsk;
    *encryption = WpaEncryptionFromEncryptionType(encryption_type);
    *key_type = kKeyTypePassphrase;
  } else if (security == onc::wifi::kWPA2_PSK) {
    *authentication = kAuthenticationWpa2Psk;
    *encryption = WpaEncryptionFromEncryptionType(encryption_type);
    *key_type = kKeyTypePassphrase;
  } else {
    return false;
  }
  return true;
}

bool WiFiServiceImpl::CreateProfile(
    const NetworkProperties& network_properties,
    EncryptionType encryption_type,
    std::string* profile_xml) {
  // Get authentication and encryption values from security.
  std::string authentication;
  std::string encryption;
  std::string key_type;
  bool valid = AuthEncryptionFromSecurity(network_properties.security,
                                          encryption_type,
                                          &authentication,
                                          &encryption,
                                          &key_type);
  if (!valid)
    return valid;

  // Generate profile XML.
  XmlWriter xml_writer;
  xml_writer.StartWriting();
  xml_writer.StartElement("WLANProfile");
  xml_writer.AddAttribute(
      "xmlns",
      "http://www.microsoft.com/networking/WLAN/profile/v1");
  xml_writer.WriteElement("name", network_properties.guid);
  xml_writer.StartElement("SSIDConfig");
  xml_writer.StartElement("SSID");
  xml_writer.WriteElement("name", network_properties.ssid);
  xml_writer.EndElement();  // Ends "SSID" element.
  xml_writer.EndElement();  // Ends "SSIDConfig" element.
  xml_writer.WriteElement("connectionType", "ESS");
  xml_writer.WriteElement("connectionMode", "manual");
  xml_writer.StartElement("MSM");
  xml_writer.StartElement("security");
  xml_writer.StartElement("authEncryption");
  xml_writer.WriteElement("authentication", authentication);
  xml_writer.WriteElement("encryption", encryption);
  xml_writer.WriteElement("useOneX", "false");
  xml_writer.EndElement();  // Ends "authEncryption" element.
  if (!key_type.empty()) {
    xml_writer.StartElement("sharedKey");
    xml_writer.WriteElement("keyType", key_type);
    xml_writer.WriteElement("protected", "false");
    xml_writer.WriteElement("keyMaterial", network_properties.password);
    xml_writer.EndElement();  // Ends "sharedKey" element.
  }
  xml_writer.EndElement();  // Ends "security" element.
  xml_writer.EndElement();  // Ends "MSM" element.
  xml_writer.EndElement();  // Ends "WLANProfile" element.
  xml_writer.StopWriting();
  *profile_xml = xml_writer.GetWrittenString();

  return true;
}

void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList& networks) {
  if (network_list_changed_observer_.is_null())
    return;

  NetworkGuidList current_networks;
  for (NetworkList::const_iterator it = networks.begin();
       it != networks.end();
       ++it) {
    current_networks.push_back(it->guid);
  }

  message_loop_proxy_->PostTask(
      FROM_HERE,
      base::Bind(network_list_changed_observer_, current_networks));
}

void WiFiServiceImpl::NotifyNetworkChanged(const std::string& network_guid) {
  if (enable_notify_network_changed_ && !networks_changed_observer_.is_null()) {
    DVLOG(1) << "NotifyNetworkChanged: " << network_guid;
    NetworkGuidList changed_networks(1, network_guid);
    message_loop_proxy_->PostTask(
        FROM_HERE,
        base::Bind(networks_changed_observer_, changed_networks));
  }
}

WiFiService* WiFiService::Create() { return new WiFiServiceImpl(); }

}  // namespace wifi
