xref: /aosp_15_r20/external/cronet/base/ios/device_util.mm (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker// Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker// found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker#include "base/ios/device_util.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker#include <CommonCrypto/CommonDigest.h>
8*6777b538SAndroid Build Coastguard Worker#import <UIKit/UIKit.h>
9*6777b538SAndroid Build Coastguard Worker#include <ifaddrs.h>
10*6777b538SAndroid Build Coastguard Worker#include <net/if_dl.h>
11*6777b538SAndroid Build Coastguard Worker#include <stddef.h>
12*6777b538SAndroid Build Coastguard Worker#include <string.h>
13*6777b538SAndroid Build Coastguard Worker#include <sys/socket.h>
14*6777b538SAndroid Build Coastguard Worker#include <sys/sysctl.h>
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker#include <memory>
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker#include "base/apple/scoped_cftyperef.h"
19*6777b538SAndroid Build Coastguard Worker#include "base/check.h"
20*6777b538SAndroid Build Coastguard Worker#include "base/numerics/safe_conversions.h"
21*6777b538SAndroid Build Coastguard Worker#include "base/posix/sysctl.h"
22*6777b538SAndroid Build Coastguard Worker#include "base/strings/stringprintf.h"
23*6777b538SAndroid Build Coastguard Worker#include "base/strings/sys_string_conversions.h"
24*6777b538SAndroid Build Coastguard Worker#include "base/system/sys_info.h"
25*6777b538SAndroid Build Coastguard Worker
26*6777b538SAndroid Build Coastguard Workernamespace {
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker// Client ID key in the user preferences.
29*6777b538SAndroid Build Coastguard WorkerNSString* const kLegacyClientIdPreferenceKey = @"ChromiumClientID";
30*6777b538SAndroid Build Coastguard WorkerNSString* const kClientIdPreferenceKey = @"ChromeClientID";
31*6777b538SAndroid Build Coastguard Worker// Current hardware type. This is used to detect that a device has been backed
32*6777b538SAndroid Build Coastguard Worker// up and restored to another device, and allows regenerating a new device id.
33*6777b538SAndroid Build Coastguard WorkerNSString* const kHardwareTypePreferenceKey = @"ClientIDGenerationHardwareType";
34*6777b538SAndroid Build Coastguard Worker// Default salt for device ids.
35*6777b538SAndroid Build Coastguard Workerconst char kDefaultSalt[] = "Salt";
36*6777b538SAndroid Build Coastguard Worker// Zero UUID returned on buggy iOS devices.
37*6777b538SAndroid Build Coastguard WorkerNSString* const kZeroUUID = @"00000000-0000-0000-0000-000000000000";
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard WorkerNSString* GenerateClientId() {
40*6777b538SAndroid Build Coastguard Worker  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker  // Try to migrate from legacy client id.
43*6777b538SAndroid Build Coastguard Worker  NSString* client_id = [defaults stringForKey:kLegacyClientIdPreferenceKey];
44*6777b538SAndroid Build Coastguard Worker
45*6777b538SAndroid Build Coastguard Worker  // Some iOS6 devices return a buggy identifierForVendor:
46*6777b538SAndroid Build Coastguard Worker  // https://openradar.appspot.com/12377282. If this is the case, revert to
47*6777b538SAndroid Build Coastguard Worker  // generating a new one.
48*6777b538SAndroid Build Coastguard Worker  if (!client_id || [client_id isEqualToString:kZeroUUID]) {
49*6777b538SAndroid Build Coastguard Worker    client_id = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
50*6777b538SAndroid Build Coastguard Worker    if ([client_id isEqualToString:kZeroUUID])
51*6777b538SAndroid Build Coastguard Worker      client_id = base::SysUTF8ToNSString(ios::device_util::GetRandomId());
52*6777b538SAndroid Build Coastguard Worker  }
53*6777b538SAndroid Build Coastguard Worker  return client_id;
54*6777b538SAndroid Build Coastguard Worker}
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker}  // namespace
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Workernamespace ios::device_util {
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Workerbool RamIsAtLeast512Mb() {
61*6777b538SAndroid Build Coastguard Worker  // 512MB devices report anywhere from 502-504 MB, use 450 MB just to be safe.
62*6777b538SAndroid Build Coastguard Worker  return RamIsAtLeast(450);
63*6777b538SAndroid Build Coastguard Worker}
64*6777b538SAndroid Build Coastguard Worker
65*6777b538SAndroid Build Coastguard Workerbool RamIsAtLeast1024Mb() {
66*6777b538SAndroid Build Coastguard Worker  // 1GB devices report anywhere from 975-999 MB, use 900 MB just to be safe.
67*6777b538SAndroid Build Coastguard Worker  return RamIsAtLeast(900);
68*6777b538SAndroid Build Coastguard Worker}
69*6777b538SAndroid Build Coastguard Worker
70*6777b538SAndroid Build Coastguard Workerbool RamIsAtLeast(uint64_t ram_in_mb) {
71*6777b538SAndroid Build Coastguard Worker  uint64_t memory_size = 0;
72*6777b538SAndroid Build Coastguard Worker  size_t size = sizeof(memory_size);
73*6777b538SAndroid Build Coastguard Worker  if (sysctlbyname("hw.memsize", &memory_size, &size, NULL, 0) == 0) {
74*6777b538SAndroid Build Coastguard Worker    // Anything >= 500M, call high ram.
75*6777b538SAndroid Build Coastguard Worker    return memory_size >= ram_in_mb * 1024 * 1024;
76*6777b538SAndroid Build Coastguard Worker  }
77*6777b538SAndroid Build Coastguard Worker  return false;
78*6777b538SAndroid Build Coastguard Worker}
79*6777b538SAndroid Build Coastguard Worker
80*6777b538SAndroid Build Coastguard Workerbool IsSingleCoreDevice() {
81*6777b538SAndroid Build Coastguard Worker  uint64_t cpu_number = 0;
82*6777b538SAndroid Build Coastguard Worker  size_t sizes = sizeof(cpu_number);
83*6777b538SAndroid Build Coastguard Worker  sysctlbyname("hw.physicalcpu", &cpu_number, &sizes, NULL, 0);
84*6777b538SAndroid Build Coastguard Worker  return cpu_number == 1;
85*6777b538SAndroid Build Coastguard Worker}
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Workerstd::string GetMacAddress(const std::string& interface_name) {
88*6777b538SAndroid Build Coastguard Worker  std::string mac_string;
89*6777b538SAndroid Build Coastguard Worker  struct ifaddrs* addresses;
90*6777b538SAndroid Build Coastguard Worker  if (getifaddrs(&addresses) == 0) {
91*6777b538SAndroid Build Coastguard Worker    for (struct ifaddrs* address = addresses; address;
92*6777b538SAndroid Build Coastguard Worker         address = address->ifa_next) {
93*6777b538SAndroid Build Coastguard Worker      if ((address->ifa_addr->sa_family == AF_LINK) &&
94*6777b538SAndroid Build Coastguard Worker          strcmp(interface_name.c_str(), address->ifa_name) == 0) {
95*6777b538SAndroid Build Coastguard Worker        const struct sockaddr_dl* found_address_struct =
96*6777b538SAndroid Build Coastguard Worker            reinterpret_cast<const struct sockaddr_dl*>(address->ifa_addr);
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Worker        // |found_address_struct->sdl_data| contains the interface name followed
99*6777b538SAndroid Build Coastguard Worker        // by the interface address. The address part can be accessed based on
100*6777b538SAndroid Build Coastguard Worker        // the length of the name, that is, |found_address_struct->sdl_nlen|.
101*6777b538SAndroid Build Coastguard Worker        const unsigned char* found_address =
102*6777b538SAndroid Build Coastguard Worker            reinterpret_cast<const unsigned char*>(
103*6777b538SAndroid Build Coastguard Worker                &found_address_struct->sdl_data[
104*6777b538SAndroid Build Coastguard Worker                    found_address_struct->sdl_nlen]);
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker        int found_address_length = found_address_struct->sdl_alen;
107*6777b538SAndroid Build Coastguard Worker        for (int i = 0; i < found_address_length; ++i) {
108*6777b538SAndroid Build Coastguard Worker          if (i != 0)
109*6777b538SAndroid Build Coastguard Worker            mac_string.push_back(':');
110*6777b538SAndroid Build Coastguard Worker          base::StringAppendF(&mac_string, "%02X", found_address[i]);
111*6777b538SAndroid Build Coastguard Worker        }
112*6777b538SAndroid Build Coastguard Worker        break;
113*6777b538SAndroid Build Coastguard Worker      }
114*6777b538SAndroid Build Coastguard Worker    }
115*6777b538SAndroid Build Coastguard Worker    freeifaddrs(addresses);
116*6777b538SAndroid Build Coastguard Worker  }
117*6777b538SAndroid Build Coastguard Worker  return mac_string;
118*6777b538SAndroid Build Coastguard Worker}
119*6777b538SAndroid Build Coastguard Worker
120*6777b538SAndroid Build Coastguard Workerstd::string GetRandomId() {
121*6777b538SAndroid Build Coastguard Worker  base::apple::ScopedCFTypeRef<CFUUIDRef> uuid_object(
122*6777b538SAndroid Build Coastguard Worker      CFUUIDCreate(kCFAllocatorDefault));
123*6777b538SAndroid Build Coastguard Worker  base::apple::ScopedCFTypeRef<CFStringRef> uuid_string(
124*6777b538SAndroid Build Coastguard Worker      CFUUIDCreateString(kCFAllocatorDefault, uuid_object.get()));
125*6777b538SAndroid Build Coastguard Worker  return base::SysCFStringRefToUTF8(uuid_string.get());
126*6777b538SAndroid Build Coastguard Worker}
127*6777b538SAndroid Build Coastguard Worker
128*6777b538SAndroid Build Coastguard Workerstd::string GetDeviceIdentifier(const char* salt) {
129*6777b538SAndroid Build Coastguard Worker  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker  NSString* last_seen_hardware =
132*6777b538SAndroid Build Coastguard Worker      [defaults stringForKey:kHardwareTypePreferenceKey];
133*6777b538SAndroid Build Coastguard Worker  NSString* current_hardware =
134*6777b538SAndroid Build Coastguard Worker      base::SysUTF8ToNSString(base::SysInfo::HardwareModelName());
135*6777b538SAndroid Build Coastguard Worker  if (!last_seen_hardware) {
136*6777b538SAndroid Build Coastguard Worker    last_seen_hardware = current_hardware;
137*6777b538SAndroid Build Coastguard Worker    [defaults setObject:current_hardware forKey:kHardwareTypePreferenceKey];
138*6777b538SAndroid Build Coastguard Worker    [defaults synchronize];
139*6777b538SAndroid Build Coastguard Worker  }
140*6777b538SAndroid Build Coastguard Worker
141*6777b538SAndroid Build Coastguard Worker  NSString* client_id = [defaults stringForKey:kClientIdPreferenceKey];
142*6777b538SAndroid Build Coastguard Worker
143*6777b538SAndroid Build Coastguard Worker  if (!client_id || ![last_seen_hardware isEqualToString:current_hardware]) {
144*6777b538SAndroid Build Coastguard Worker    client_id = GenerateClientId();
145*6777b538SAndroid Build Coastguard Worker    [defaults setObject:client_id forKey:kClientIdPreferenceKey];
146*6777b538SAndroid Build Coastguard Worker    [defaults setObject:current_hardware forKey:kHardwareTypePreferenceKey];
147*6777b538SAndroid Build Coastguard Worker    [defaults synchronize];
148*6777b538SAndroid Build Coastguard Worker  }
149*6777b538SAndroid Build Coastguard Worker
150*6777b538SAndroid Build Coastguard Worker  return GetSaltedString(base::SysNSStringToUTF8(client_id),
151*6777b538SAndroid Build Coastguard Worker                         salt ? salt : kDefaultSalt);
152*6777b538SAndroid Build Coastguard Worker}
153*6777b538SAndroid Build Coastguard Worker
154*6777b538SAndroid Build Coastguard Workerstd::string GetVendorId() {
155*6777b538SAndroid Build Coastguard Worker  return base::SysNSStringToUTF8(
156*6777b538SAndroid Build Coastguard Worker      [[[UIDevice currentDevice] identifierForVendor] UUIDString]);
157*6777b538SAndroid Build Coastguard Worker}
158*6777b538SAndroid Build Coastguard Worker
159*6777b538SAndroid Build Coastguard Workerstd::string GetSaltedString(const std::string& in_string,
160*6777b538SAndroid Build Coastguard Worker                            const std::string& salt) {
161*6777b538SAndroid Build Coastguard Worker  DCHECK(salt.length());
162*6777b538SAndroid Build Coastguard Worker  NSData* hash_data = [base::SysUTF8ToNSString(in_string + salt)
163*6777b538SAndroid Build Coastguard Worker      dataUsingEncoding:NSUTF8StringEncoding];
164*6777b538SAndroid Build Coastguard Worker
165*6777b538SAndroid Build Coastguard Worker  unsigned char hash[CC_SHA256_DIGEST_LENGTH];
166*6777b538SAndroid Build Coastguard Worker  CC_SHA256([hash_data bytes], base::checked_cast<CC_LONG>([hash_data length]),
167*6777b538SAndroid Build Coastguard Worker            hash);
168*6777b538SAndroid Build Coastguard Worker  CFUUIDBytes* uuid_bytes = reinterpret_cast<CFUUIDBytes*>(hash);
169*6777b538SAndroid Build Coastguard Worker
170*6777b538SAndroid Build Coastguard Worker  base::apple::ScopedCFTypeRef<CFUUIDRef> uuid_object(
171*6777b538SAndroid Build Coastguard Worker      CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, *uuid_bytes));
172*6777b538SAndroid Build Coastguard Worker  base::apple::ScopedCFTypeRef<CFStringRef> device_id(
173*6777b538SAndroid Build Coastguard Worker      CFUUIDCreateString(kCFAllocatorDefault, uuid_object.get()));
174*6777b538SAndroid Build Coastguard Worker  return base::SysCFStringRefToUTF8(device_id.get());
175*6777b538SAndroid Build Coastguard Worker}
176*6777b538SAndroid Build Coastguard Worker
177*6777b538SAndroid Build Coastguard Worker}  // namespace ios::device_util
178