blob: 4488344d10edf6aac7733b975054a3545aad9a61 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
[email protected]e16e8732012-08-07 11:03:112// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/ios/device_util.h"
6
7#include <CommonCrypto/CommonDigest.h>
[email protected]aebcd0dd2012-10-05 17:48:588#import <UIKit/UIKit.h>
[email protected]e16e8732012-08-07 11:03:119#include <ifaddrs.h>
10#include <net/if_dl.h>
avi9b6f42932015-12-26 22:15:1411#include <stddef.h>
[email protected]e16e8732012-08-07 11:03:1112#include <string.h>
13#include <sys/socket.h>
14#include <sys/sysctl.h>
15
dcheng093de9b2016-04-04 21:25:5116#include <memory>
17
Avi Drissmana09d7dd2023-08-17 16:26:5818#include "base/apple/scoped_cftyperef.h"
Hans Wennborga47ddf82020-05-05 18:08:0719#include "base/check.h"
Peter Kasting2f61c8b2022-07-19 23:43:4620#include "base/numerics/safe_conversions.h"
[email protected]d1a5a2f2013-06-10 21:17:4021#include "base/strings/string_util.h"
22#include "base/strings/stringprintf.h"
[email protected]9fe1a5b2013-02-07 19:18:0323#include "base/strings/sys_string_conversions.h"
[email protected]e16e8732012-08-07 11:03:1124
[email protected]e16e8732012-08-07 11:03:1125namespace {
26
27// Client ID key in the user preferences.
[email protected]d724b552012-12-13 17:39:4728NSString* const kLegacyClientIdPreferenceKey = @"ChromiumClientID";
29NSString* const kClientIdPreferenceKey = @"ChromeClientID";
[email protected]af6a8c92012-12-20 16:41:3330// Current hardware type. This is used to detect that a device has been backed
31// up and restored to another device, and allows regenerating a new device id.
32NSString* const kHardwareTypePreferenceKey = @"ClientIDGenerationHardwareType";
[email protected]e16e8732012-08-07 11:03:1133// Default salt for device ids.
34const char kDefaultSalt[] = "Salt";
[email protected]d724b552012-12-13 17:39:4735// Zero UUID returned on buggy iOS devices.
36NSString* const kZeroUUID = @"00000000-0000-0000-0000-000000000000";
37
38NSString* GenerateClientId() {
39 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
40
41 // Try to migrate from legacy client id.
42 NSString* client_id = [defaults stringForKey:kLegacyClientIdPreferenceKey];
43
44 // Some iOS6 devices return a buggy identifierForVendor:
Avi Drissmanb34db7a2023-01-04 21:50:1545 // https://openradar.appspot.com/12377282. If this is the case, revert to
[email protected]d724b552012-12-13 17:39:4746 // generating a new one.
47 if (!client_id || [client_id isEqualToString:kZeroUUID]) {
[email protected]d01f3112014-06-19 22:49:5548 client_id = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
49 if ([client_id isEqualToString:kZeroUUID])
[email protected]d724b552012-12-13 17:39:4750 client_id = base::SysUTF8ToNSString(ios::device_util::GetRandomId());
[email protected]d724b552012-12-13 17:39:4751 }
52 return client_id;
53}
[email protected]e16e8732012-08-07 11:03:1154
55} // namespace
56
Avi Drissman354864c2023-06-01 20:06:0357namespace ios::device_util {
[email protected]e16e8732012-08-07 11:03:1158
59std::string GetPlatform() {
Justin Cohen518b7442022-09-17 21:26:4960#if TARGET_OS_SIMULATOR
61 return getenv("SIMULATOR_MODEL_IDENTIFIER");
62#elif TARGET_OS_IPHONE
[email protected]e16e8732012-08-07 11:03:1163 std::string platform;
64 size_t size = 0;
65 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
Brett Wilsone3c4d1a2015-07-07 23:38:0966 sysctlbyname("hw.machine", base::WriteInto(&platform, size), &size, NULL, 0);
[email protected]e16e8732012-08-07 11:03:1167 return platform;
Justin Cohen518b7442022-09-17 21:26:4968#endif
[email protected]e16e8732012-08-07 11:03:1169}
70
[email protected]4f150ec72014-03-18 21:54:4271bool RamIsAtLeast512Mb() {
72 // 512MB devices report anywhere from 502-504 MB, use 450 MB just to be safe.
73 return RamIsAtLeast(450);
74}
75
76bool RamIsAtLeast1024Mb() {
77 // 1GB devices report anywhere from 975-999 MB, use 900 MB just to be safe.
78 return RamIsAtLeast(900);
79}
80
81bool RamIsAtLeast(uint64_t ram_in_mb) {
[email protected]e16e8732012-08-07 11:03:1182 uint64_t memory_size = 0;
83 size_t size = sizeof(memory_size);
84 if (sysctlbyname("hw.memsize", &memory_size, &size, NULL, 0) == 0) {
[email protected]9317c2492013-12-11 22:18:4185 // Anything >= 500M, call high ram.
[email protected]4f150ec72014-03-18 21:54:4286 return memory_size >= ram_in_mb * 1024 * 1024;
[email protected]e16e8732012-08-07 11:03:1187 }
88 return false;
89}
90
91bool IsSingleCoreDevice() {
92 uint64_t cpu_number = 0;
93 size_t sizes = sizeof(cpu_number);
94 sysctlbyname("hw.physicalcpu", &cpu_number, &sizes, NULL, 0);
95 return cpu_number == 1;
96}
97
98std::string GetMacAddress(const std::string& interface_name) {
99 std::string mac_string;
100 struct ifaddrs* addresses;
101 if (getifaddrs(&addresses) == 0) {
102 for (struct ifaddrs* address = addresses; address;
103 address = address->ifa_next) {
104 if ((address->ifa_addr->sa_family == AF_LINK) &&
105 strcmp(interface_name.c_str(), address->ifa_name) == 0) {
106 const struct sockaddr_dl* found_address_struct =
107 reinterpret_cast<const struct sockaddr_dl*>(address->ifa_addr);
108
109 // |found_address_struct->sdl_data| contains the interface name followed
110 // by the interface address. The address part can be accessed based on
111 // the length of the name, that is, |found_address_struct->sdl_nlen|.
112 const unsigned char* found_address =
113 reinterpret_cast<const unsigned char*>(
114 &found_address_struct->sdl_data[
115 found_address_struct->sdl_nlen]);
116
117 int found_address_length = found_address_struct->sdl_alen;
118 for (int i = 0; i < found_address_length; ++i) {
119 if (i != 0)
120 mac_string.push_back(':');
121 base::StringAppendF(&mac_string, "%02X", found_address[i]);
122 }
123 break;
124 }
125 }
126 freeifaddrs(addresses);
127 }
128 return mac_string;
129}
130
131std::string GetRandomId() {
[email protected]3df79f42013-06-24 18:49:05132 base::ScopedCFTypeRef<CFUUIDRef> uuid_object(
133 CFUUIDCreate(kCFAllocatorDefault));
134 base::ScopedCFTypeRef<CFStringRef> uuid_string(
[email protected]e16e8732012-08-07 11:03:11135 CFUUIDCreateString(kCFAllocatorDefault, uuid_object));
136 return base::SysCFStringRefToUTF8(uuid_string);
137}
138
139std::string GetDeviceIdentifier(const char* salt) {
140 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[email protected]af6a8c92012-12-20 16:41:33141
142 NSString* last_seen_hardware =
143 [defaults stringForKey:kHardwareTypePreferenceKey];
144 NSString* current_hardware = base::SysUTF8ToNSString(GetPlatform());
145 if (!last_seen_hardware) {
146 last_seen_hardware = current_hardware;
147 [defaults setObject:current_hardware forKey:kHardwareTypePreferenceKey];
148 [defaults synchronize];
149 }
150
[email protected]e16e8732012-08-07 11:03:11151 NSString* client_id = [defaults stringForKey:kClientIdPreferenceKey];
152
[email protected]af6a8c92012-12-20 16:41:33153 if (!client_id || ![last_seen_hardware isEqualToString:current_hardware]) {
[email protected]d724b552012-12-13 17:39:47154 client_id = GenerateClientId();
[email protected]e16e8732012-08-07 11:03:11155 [defaults setObject:client_id forKey:kClientIdPreferenceKey];
[email protected]af6a8c92012-12-20 16:41:33156 [defaults setObject:current_hardware forKey:kHardwareTypePreferenceKey];
[email protected]e16e8732012-08-07 11:03:11157 [defaults synchronize];
158 }
159
[email protected]0644db72014-06-05 20:05:43160 return GetSaltedString(base::SysNSStringToUTF8(client_id),
161 salt ? salt : kDefaultSalt);
[email protected]940b67d2014-06-03 14:27:18162}
163
Guillaume Jenkins74049b12020-12-01 18:53:46164std::string GetVendorId() {
165 return base::SysNSStringToUTF8(
166 [[[UIDevice currentDevice] identifierForVendor] UUIDString]);
167}
168
[email protected]940b67d2014-06-03 14:27:18169std::string GetSaltedString(const std::string& in_string,
170 const std::string& salt) {
[email protected]940b67d2014-06-03 14:27:18171 DCHECK(salt.length());
[email protected]0644db72014-06-05 20:05:43172 NSData* hash_data = [base::SysUTF8ToNSString(in_string + salt)
173 dataUsingEncoding:NSUTF8StringEncoding];
[email protected]e16e8732012-08-07 11:03:11174
175 unsigned char hash[CC_SHA256_DIGEST_LENGTH];
Peter Kasting2f61c8b2022-07-19 23:43:46176 CC_SHA256([hash_data bytes], base::checked_cast<CC_LONG>([hash_data length]),
177 hash);
[email protected]e16e8732012-08-07 11:03:11178 CFUUIDBytes* uuid_bytes = reinterpret_cast<CFUUIDBytes*>(hash);
179
[email protected]3df79f42013-06-24 18:49:05180 base::ScopedCFTypeRef<CFUUIDRef> uuid_object(
181 CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, *uuid_bytes));
182 base::ScopedCFTypeRef<CFStringRef> device_id(
[email protected]e16e8732012-08-07 11:03:11183 CFUUIDCreateString(kCFAllocatorDefault, uuid_object));
184 return base::SysCFStringRefToUTF8(device_id);
185}
186
Avi Drissman354864c2023-06-01 20:06:03187} // namespace ios::device_util