// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/ios/device_util.h"

#include <CommonCrypto/CommonDigest.h>
#import <UIKit/UIKit.h>

#include <ifaddrs.h>
#include <net/if_dl.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/sysctl.h>

#include "base/ios/ios_util.h"
#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"

namespace {

// Client ID key in the user preferences.
NSString* const kLegacyClientIdPreferenceKey = @"ChromiumClientID";
NSString* const kClientIdPreferenceKey = @"ChromeClientID";
// Current hardware type. This is used to detect that a device has been backed
// up and restored to another device, and allows regenerating a new device id.
NSString* const kHardwareTypePreferenceKey = @"ClientIDGenerationHardwareType";
// Default salt for device ids.
const char kDefaultSalt[] = "Salt";
// Zero UUID returned on buggy iOS devices.
NSString* const kZeroUUID = @"00000000-0000-0000-0000-000000000000";

NSString* GenerateClientId() {
  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];

  // Try to migrate from legacy client id.
  NSString* client_id = [defaults stringForKey:kLegacyClientIdPreferenceKey];

  // Some iOS6 devices return a buggy identifierForVendor:
  // http://openradar.appspot.com/12377282. If this is the case, revert to
  // generating a new one.
  if (!client_id || [client_id isEqualToString:kZeroUUID]) {
    if (base::ios::IsRunningOnIOS6OrLater()) {
      client_id = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
      if ([client_id isEqualToString:kZeroUUID])
        client_id = base::SysUTF8ToNSString(ios::device_util::GetRandomId());
    } else {
      client_id = base::SysUTF8ToNSString(ios::device_util::GetRandomId());
    }
  }
  return client_id;
}

}  // namespace

namespace ios {
namespace device_util {

std::string GetPlatform() {
  std::string platform;
  size_t size = 0;
  sysctlbyname("hw.machine", NULL, &size, NULL, 0);
  sysctlbyname("hw.machine", WriteInto(&platform, size), &size, NULL, 0);
  return platform;
}

bool RamIsAtLeast512Mb() {
  // 512MB devices report anywhere from 502-504 MB, use 450 MB just to be safe.
  return RamIsAtLeast(450);
}

bool RamIsAtLeast1024Mb() {
  // 1GB devices report anywhere from 975-999 MB, use 900 MB just to be safe.
  return RamIsAtLeast(900);
}

bool RamIsAtLeast(uint64_t ram_in_mb) {
  uint64_t memory_size = 0;
  size_t size = sizeof(memory_size);
  if (sysctlbyname("hw.memsize", &memory_size, &size, NULL, 0) == 0) {
    // Anything >= 500M, call high ram.
    return memory_size >= ram_in_mb * 1024 * 1024;
  }
  return false;
}

bool IsSingleCoreDevice() {
  uint64_t cpu_number = 0;
  size_t sizes = sizeof(cpu_number);
  sysctlbyname("hw.physicalcpu", &cpu_number, &sizes, NULL, 0);
  return cpu_number == 1;
}

std::string GetMacAddress(const std::string& interface_name) {
  std::string mac_string;
  struct ifaddrs* addresses;
  if (getifaddrs(&addresses) == 0) {
    for (struct ifaddrs* address = addresses; address;
         address = address->ifa_next) {
      if ((address->ifa_addr->sa_family == AF_LINK) &&
          strcmp(interface_name.c_str(), address->ifa_name) == 0) {
        const struct sockaddr_dl* found_address_struct =
            reinterpret_cast<const struct sockaddr_dl*>(address->ifa_addr);

        // |found_address_struct->sdl_data| contains the interface name followed
        // by the interface address. The address part can be accessed based on
        // the length of the name, that is, |found_address_struct->sdl_nlen|.
        const unsigned char* found_address =
            reinterpret_cast<const unsigned char*>(
                &found_address_struct->sdl_data[
                    found_address_struct->sdl_nlen]);

        int found_address_length = found_address_struct->sdl_alen;
        for (int i = 0; i < found_address_length; ++i) {
          if (i != 0)
            mac_string.push_back(':');
          base::StringAppendF(&mac_string, "%02X", found_address[i]);
        }
        break;
      }
    }
    freeifaddrs(addresses);
  }
  return mac_string;
}

std::string GetRandomId() {
  base::ScopedCFTypeRef<CFUUIDRef> uuid_object(
      CFUUIDCreate(kCFAllocatorDefault));
  base::ScopedCFTypeRef<CFStringRef> uuid_string(
      CFUUIDCreateString(kCFAllocatorDefault, uuid_object));
  return base::SysCFStringRefToUTF8(uuid_string);
}

std::string GetDeviceIdentifier(const char* salt) {
  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];

  NSString* last_seen_hardware =
      [defaults stringForKey:kHardwareTypePreferenceKey];
  NSString* current_hardware = base::SysUTF8ToNSString(GetPlatform());
  if (!last_seen_hardware) {
    last_seen_hardware = current_hardware;
    [defaults setObject:current_hardware forKey:kHardwareTypePreferenceKey];
    [defaults synchronize];
  }

  NSString* client_id = [defaults stringForKey:kClientIdPreferenceKey];

  if (!client_id || ![last_seen_hardware isEqualToString:current_hardware]) {
    client_id = GenerateClientId();
    [defaults setObject:client_id forKey:kClientIdPreferenceKey];
    [defaults setObject:current_hardware forKey:kHardwareTypePreferenceKey];
    [defaults synchronize];
  }

  NSData* hash_data = [[NSString stringWithFormat:@"%@%s", client_id,
      salt ? salt : kDefaultSalt] dataUsingEncoding:NSUTF8StringEncoding];

  unsigned char hash[CC_SHA256_DIGEST_LENGTH];
  CC_SHA256([hash_data bytes], [hash_data length], hash);
  CFUUIDBytes* uuid_bytes = reinterpret_cast<CFUUIDBytes*>(hash);

  base::ScopedCFTypeRef<CFUUIDRef> uuid_object(
      CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, *uuid_bytes));
  base::ScopedCFTypeRef<CFStringRef> device_id(
      CFUUIDCreateString(kCFAllocatorDefault, uuid_object));
  return base::SysCFStringRefToUTF8(device_id);
}

}  // namespace device_util
}  // namespace ios
