// 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 "chrome/browser/extensions/api/music_manager_private/device_id.h"

// Note: The order of header includes is important, as we want both pre-Vista
// and post-Vista data structures to be defined, specifically
// PIP_ADAPTER_ADDRESSES and PMIB_IF_ROW2.
#include <winsock2.h>
#include <ws2def.h>
#include <ws2ipdef.h>
#include <iphlpapi.h>

#include <string>

#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/scoped_native_library.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/win/windows_version.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/net_util.h"

#if defined(ENABLE_RLZ)
#include "rlz/lib/machine_id.h"
#endif

namespace {

using extensions::api::DeviceId;

typedef base::Callback<bool(const void* bytes, size_t size)>
    IsValidMacAddressCallback;

class MacAddressProcessor {
 public:
  MacAddressProcessor(const IsValidMacAddressCallback& is_valid_mac_address)
    : is_valid_mac_address_(is_valid_mac_address),
      found_index_(ULONG_MAX) {
  }

  // Iterate through the interfaces, looking for the valid MAC address with the
  // lowest IfIndex.
  void ProcessAdapterAddress(PIP_ADAPTER_ADDRESSES address) {
    if (address->IfType == IF_TYPE_TUNNEL)
      return;

    ProcessPhysicalAddress(address->IfIndex,
                           address->PhysicalAddress,
                           address->PhysicalAddressLength);
  }

  void ProcessInterfaceRow(const PMIB_IF_ROW2 row) {
    if (row->Type == IF_TYPE_TUNNEL ||
        !row->InterfaceAndOperStatusFlags.HardwareInterface) {
      return;
    }

    ProcessPhysicalAddress(row->InterfaceIndex,
                           row->PhysicalAddress,
                           row->PhysicalAddressLength);
  }

  std::string mac_address() const { return found_mac_address_; }

 private:
  void ProcessPhysicalAddress(NET_IFINDEX index,
                              const void* bytes,
                              size_t size) {
    if (index >= found_index_ || size == 0)
      return;

    if (!is_valid_mac_address_.Run(bytes, size))
      return;

    found_mac_address_ = StringToLowerASCII(base::HexEncode(bytes, size));
    found_index_ = index;
  }

  const IsValidMacAddressCallback& is_valid_mac_address_;
  std::string found_mac_address_;
  NET_IFINDEX found_index_;
};

std::string GetMacAddressFromGetAdaptersAddresses(
    const IsValidMacAddressCallback& is_valid_mac_address) {
  base::ThreadRestrictions::AssertIOAllowed();

  // MS recommends a default size of 15k.
  ULONG bufferSize = 15 * 1024;
  // Disable as much as we can, since all we want is MAC addresses.
  ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER |
                GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_MULTICAST |
                GAA_FLAG_SKIP_UNICAST;
  std::vector<unsigned char> buffer(bufferSize);
  PIP_ADAPTER_ADDRESSES adapterAddresses =
      reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer.front());

  DWORD result = GetAdaptersAddresses(AF_UNSPEC, flags, 0,
                                      adapterAddresses, &bufferSize);
  if (result == ERROR_BUFFER_OVERFLOW) {
    buffer.resize(bufferSize);
    adapterAddresses =
        reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer.front());
    result = GetAdaptersAddresses(AF_UNSPEC, flags, 0,
                                  adapterAddresses, &bufferSize);
  }

  if (result != NO_ERROR) {
    VLOG(ERROR) << "GetAdapatersAddresses failed with error " << result;
    return "";
  }

  MacAddressProcessor processor(is_valid_mac_address);
  for (; adapterAddresses != NULL; adapterAddresses = adapterAddresses->Next) {
    processor.ProcessAdapterAddress(adapterAddresses);
  }
  return processor.mac_address();
}

std::string GetMacAddressFromGetIfTable2(
    const IsValidMacAddressCallback& is_valid_mac_address) {
  base::ThreadRestrictions::AssertIOAllowed();

  // This is available on Vista+ only.
  base::ScopedNativeLibrary library(base::FilePath(L"Iphlpapi.dll"));

  typedef DWORD (NETIOAPI_API_ *GetIfTablePtr)(PMIB_IF_TABLE2*);
  typedef void (NETIOAPI_API_ *FreeMibTablePtr)(PMIB_IF_TABLE2);

  GetIfTablePtr getIfTable = reinterpret_cast<GetIfTablePtr>(
      library.GetFunctionPointer("GetIfTable2"));
  FreeMibTablePtr freeMibTablePtr = reinterpret_cast<FreeMibTablePtr>(
      library.GetFunctionPointer("FreeMibTable"));
  if (getIfTable == NULL || freeMibTablePtr == NULL) {
    VLOG(ERROR) << "Could not get proc addresses for machine identifier.";
    return "";
  }

  PMIB_IF_TABLE2  ifTable = NULL;
  DWORD result = getIfTable(&ifTable);
  if (result != NO_ERROR || ifTable == NULL) {
    VLOG(ERROR) << "GetIfTable failed with error " << result;
    return "";
  }

  MacAddressProcessor processor(is_valid_mac_address);
  for (size_t i = 0; i < ifTable->NumEntries; i++) {
    processor.ProcessInterfaceRow(&(ifTable->Table[i]));
  }

  if (ifTable != NULL) {
    freeMibTablePtr(ifTable);
    ifTable = NULL;
  }
  return processor.mac_address();
}

void GetMacAddress(const IsValidMacAddressCallback& is_valid_mac_address,
                   const DeviceId::IdCallback& callback) {
  base::ThreadRestrictions::AssertIOAllowed();

  std::string mac_address =
      GetMacAddressFromGetAdaptersAddresses(is_valid_mac_address);
  if (mac_address.empty())
    mac_address = GetMacAddressFromGetIfTable2(is_valid_mac_address);

  static bool error_logged = false;
  if (mac_address.empty() && !error_logged) {
    error_logged = true;
    LOG(ERROR) << "Could not find appropriate MAC address.";
  }

  content::BrowserThread::PostTask(
      content::BrowserThread::UI,
      FROM_HERE,
      base::Bind(callback, mac_address));
}

std::string GetRlzMachineId() {
#if defined(ENABLE_RLZ)
  std::string machine_id;
  if (!rlz_lib::GetMachineId(&machine_id))
    return "";
  return machine_id;
#else
  return "";
#endif
}

void GetMacAddressCallback(const DeviceId::IdCallback& callback,
                           const std::string& mac_address) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  std::string machine_id = GetRlzMachineId();
  if (mac_address.empty() || machine_id.empty()) {
    callback.Run("");
    return;
  }
  callback.Run(mac_address + machine_id);
}

}  // namespace

namespace extensions {
namespace api {

// static
void DeviceId::GetRawDeviceId(const IdCallback& callback) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  content::BrowserThread::PostTask(
      content::BrowserThread::FILE,
      FROM_HERE,
      base::Bind(GetMacAddress,
        base::Bind(DeviceId::IsValidMacAddress),
        base::Bind(GetMacAddressCallback, callback)));
}

}  // namespace api
}  // namespace extensions
