1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/extensions/api/music_manager_private/device_id.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Note: The order of header includes is important, as we want both pre-Vista
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// and post-Vista data structures to be defined, specifically
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// PIP_ADAPTER_ADDRESSES and PMIB_IF_ROW2.
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <winsock2.h>
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <ws2def.h>
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <ws2ipdef.h>
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <iphlpapi.h>
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string>
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/files/file_path.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/scoped_native_library.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/windows_version.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/net_util.h"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(ENABLE_RLZ)
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "rlz/lib/machine_id.h"
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using extensions::api::DeviceId;
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef base::Callback<bool(const void* bytes, size_t size)>
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IsValidMacAddressCallback;
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MacAddressProcessor {
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MacAddressProcessor(const IsValidMacAddressCallback& is_valid_mac_address)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : is_valid_mac_address_(is_valid_mac_address),
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      found_index_(ULONG_MAX) {
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Iterate through the interfaces, looking for the valid MAC address with the
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // lowest IfIndex.
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ProcessAdapterAddress(PIP_ADAPTER_ADDRESSES address) {
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (address->IfType == IF_TYPE_TUNNEL)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ProcessPhysicalAddress(address->IfIndex,
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           address->PhysicalAddress,
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           address->PhysicalAddressLength);
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ProcessInterfaceRow(const PMIB_IF_ROW2 row) {
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (row->Type == IF_TYPE_TUNNEL ||
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        !row->InterfaceAndOperStatusFlags.HardwareInterface) {
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ProcessPhysicalAddress(row->InterfaceIndex,
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           row->PhysicalAddress,
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           row->PhysicalAddressLength);
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string mac_address() const { return found_mac_address_; }
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ProcessPhysicalAddress(NET_IFINDEX index,
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              const void* bytes,
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              size_t size) {
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (index >= found_index_ || size == 0)
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!is_valid_mac_address_.Run(bytes, size))
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    found_mac_address_ = base::StringToLowerASCII(base::HexEncode(bytes, size));
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    found_index_ = index;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const IsValidMacAddressCallback& is_valid_mac_address_;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string found_mac_address_;
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NET_IFINDEX found_index_;
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string GetMacAddressFromGetAdaptersAddresses(
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const IsValidMacAddressCallback& is_valid_mac_address) {
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ThreadRestrictions::AssertIOAllowed();
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // MS recommends a default size of 15k.
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ULONG bufferSize = 15 * 1024;
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Disable as much as we can, since all we want is MAC addresses.
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER |
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_MULTICAST |
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                GAA_FLAG_SKIP_UNICAST;
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<unsigned char> buffer(bufferSize);
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PIP_ADAPTER_ADDRESSES adapterAddresses =
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer.front());
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DWORD result = GetAdaptersAddresses(AF_UNSPEC, flags, 0,
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      adapterAddresses, &bufferSize);
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result == ERROR_BUFFER_OVERFLOW) {
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    buffer.resize(bufferSize);
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    adapterAddresses =
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer.front());
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result = GetAdaptersAddresses(AF_UNSPEC, flags, 0,
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  adapterAddresses, &bufferSize);
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result != NO_ERROR) {
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VLOG(ERROR) << "GetAdapatersAddresses failed with error " << result;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return "";
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MacAddressProcessor processor(is_valid_mac_address);
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (; adapterAddresses != NULL; adapterAddresses = adapterAddresses->Next) {
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    processor.ProcessAdapterAddress(adapterAddresses);
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return processor.mac_address();
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string GetMacAddressFromGetIfTable2(
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const IsValidMacAddressCallback& is_valid_mac_address) {
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ThreadRestrictions::AssertIOAllowed();
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This is available on Vista+ only.
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ScopedNativeLibrary library(base::FilePath(L"Iphlpapi.dll"));
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  typedef DWORD (NETIOAPI_API_ *GetIfTablePtr)(PMIB_IF_TABLE2*);
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  typedef void (NETIOAPI_API_ *FreeMibTablePtr)(PMIB_IF_TABLE2);
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetIfTablePtr getIfTable = reinterpret_cast<GetIfTablePtr>(
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      library.GetFunctionPointer("GetIfTable2"));
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FreeMibTablePtr freeMibTablePtr = reinterpret_cast<FreeMibTablePtr>(
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      library.GetFunctionPointer("FreeMibTable"));
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (getIfTable == NULL || freeMibTablePtr == NULL) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VLOG(ERROR) << "Could not get proc addresses for machine identifier.";
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return "";
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PMIB_IF_TABLE2  ifTable = NULL;
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DWORD result = getIfTable(&ifTable);
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result != NO_ERROR || ifTable == NULL) {
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VLOG(ERROR) << "GetIfTable failed with error " << result;
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return "";
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MacAddressProcessor processor(is_valid_mac_address);
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < ifTable->NumEntries; i++) {
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    processor.ProcessInterfaceRow(&(ifTable->Table[i]));
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ifTable != NULL) {
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    freeMibTablePtr(ifTable);
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ifTable = NULL;
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return processor.mac_address();
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GetMacAddress(const IsValidMacAddressCallback& is_valid_mac_address,
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   const DeviceId::IdCallback& callback) {
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ThreadRestrictions::AssertIOAllowed();
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string mac_address =
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetMacAddressFromGetAdaptersAddresses(is_valid_mac_address);
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (mac_address.empty())
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    mac_address = GetMacAddressFromGetIfTable2(is_valid_mac_address);
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static bool error_logged = false;
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (mac_address.empty() && !error_logged) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error_logged = true;
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(ERROR) << "Could not find appropriate MAC address.";
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::BrowserThread::PostTask(
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      content::BrowserThread::UI,
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(callback, mac_address));
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string GetRlzMachineId() {
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(ENABLE_RLZ)
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string machine_id;
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!rlz_lib::GetMachineId(&machine_id))
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return "";
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return machine_id;
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#else
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return "";
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GetMacAddressCallback(const DeviceId::IdCallback& callback,
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           const std::string& mac_address) {
196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string machine_id = GetRlzMachineId();
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (mac_address.empty() || machine_id.empty()) {
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run("");
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(mac_address + machine_id);
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace extensions {
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace api {
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DeviceId::GetRawDeviceId(const IdCallback& callback) {
213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::BrowserThread::PostTask(
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      content::BrowserThread::FILE,
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(GetMacAddress,
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(DeviceId::IsValidMacAddress),
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(GetMacAddressCallback, callback)));
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace api
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace extensions
225