Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/renderer_host/pepper/device_id_fetcher.h" | 5 #include "chrome/browser/renderer_host/pepper/device_id_fetcher.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/prefs/pref_service.h" | 8 #include "base/prefs/pref_service.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "chrome/browser/profiles/profile.h" | 10 #include "chrome/browser/profiles/profile.h" |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 using content::RenderProcessHost; | 29 using content::RenderProcessHost; |
| 30 | 30 |
| 31 namespace chrome { | 31 namespace chrome { |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 const char kDRMIdentifierFile[] = "Pepper DRM ID.0"; | 35 const char kDRMIdentifierFile[] = "Pepper DRM ID.0"; |
| 36 | 36 |
| 37 const uint32_t kSaltLength = 32; | 37 const uint32_t kSaltLength = 32; |
| 38 | 38 |
| 39 void GetMachineIdAsync(const DeviceIDFetcher::IDCallback& callback) { | |
| 40 std::string result; | |
| 41 #if defined(OS_WIN) && defined(ENABLE_RLZ) | |
| 42 rlz_lib::GetMachineId(&result); | |
| 43 #elif defined(OS_CHROMEOS) | |
| 44 result = chromeos::CryptohomeLibrary::Get()->GetSystemSalt(); | |
| 45 if (result.empty()) { | |
| 46 // cryptohome must not be running; re-request after a delay. | |
| 47 const int64 kRequestStstemSaltDelayMs = 500; | |
|
hashimoto
2013/09/18 05:53:19
nit: s/Ststem/System/?
stevenjb
2013/09/18 19:23:36
Done.
| |
| 48 base::MessageLoop::current()->PostDelayedTask( | |
| 49 FROM_HERE, | |
| 50 base::Bind(&GetMachineIdAsync, callback), | |
| 51 base::TimeDelta::FromMilliseconds(kRequestStstemSaltDelayMs)); | |
| 52 return; | |
| 53 } | |
| 54 #else | |
| 55 // Not implemented for other platforms. | |
| 56 NOTREACHED(); | |
| 57 #endif | |
| 58 callback.Run(result); | |
| 59 } | |
| 60 | |
| 39 } // namespace | 61 } // namespace |
| 40 | 62 |
| 41 DeviceIDFetcher::DeviceIDFetcher(int render_process_id) | 63 DeviceIDFetcher::DeviceIDFetcher(int render_process_id) |
| 42 : in_progress_(false), | 64 : in_progress_(false), |
| 43 render_process_id_(render_process_id) { | 65 render_process_id_(render_process_id), |
| 66 weak_ptr_factory_(this) { | |
|
hashimoto
2013/09/18 05:53:19
DeviceIDFetcher is ref counted. Is threre any reas
stevenjb
2013/09/18 19:23:36
Facepalm. Thanks. I don't know how I missed that.
| |
| 44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 45 } | 68 } |
| 46 | 69 |
| 47 DeviceIDFetcher::~DeviceIDFetcher() { | 70 DeviceIDFetcher::~DeviceIDFetcher() { |
| 48 } | 71 } |
| 49 | 72 |
| 50 bool DeviceIDFetcher::Start(const IDCallback& callback) { | 73 bool DeviceIDFetcher::Start(const IDCallback& callback) { |
| 51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 52 | 75 |
| 53 if (in_progress_) | 76 if (in_progress_) |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 73 "", | 96 "", |
| 74 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 97 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 75 } | 98 } |
| 76 | 99 |
| 77 // static | 100 // static |
| 78 base::FilePath DeviceIDFetcher::GetLegacyDeviceIDPath( | 101 base::FilePath DeviceIDFetcher::GetLegacyDeviceIDPath( |
| 79 const base::FilePath& profile_path) { | 102 const base::FilePath& profile_path) { |
| 80 return profile_path.AppendASCII(kDRMIdentifierFile); | 103 return profile_path.AppendASCII(kDRMIdentifierFile); |
| 81 } | 104 } |
| 82 | 105 |
| 83 // TODO(raymes): Change this to just return the device id salt and call it with | |
| 84 // PostTaskAndReply once the legacy ChromeOS codepath is removed. | |
| 85 void DeviceIDFetcher::CheckPrefsOnUIThread() { | 106 void DeviceIDFetcher::CheckPrefsOnUIThread() { |
| 86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 87 | 108 |
| 88 Profile* profile = NULL; | 109 Profile* profile = NULL; |
| 89 RenderProcessHost* render_process_host = | 110 RenderProcessHost* render_process_host = |
| 90 RenderProcessHost::FromID(render_process_id_); | 111 RenderProcessHost::FromID(render_process_id_); |
| 91 if (render_process_host && render_process_host->GetBrowserContext()) { | 112 if (render_process_host && render_process_host->GetBrowserContext()) { |
| 92 profile = Profile::FromBrowserContext( | 113 profile = Profile::FromBrowserContext( |
| 93 render_process_host->GetBrowserContext()); | 114 render_process_host->GetBrowserContext()); |
| 94 } | 115 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 106 uint8_t salt_bytes[kSaltLength]; | 127 uint8_t salt_bytes[kSaltLength]; |
| 107 crypto::RandBytes(salt_bytes, arraysize(salt_bytes)); | 128 crypto::RandBytes(salt_bytes, arraysize(salt_bytes)); |
| 108 // Since it will be stored in a string pref, convert it to hex. | 129 // Since it will be stored in a string pref, convert it to hex. |
| 109 salt = base::HexEncode(salt_bytes, arraysize(salt_bytes)); | 130 salt = base::HexEncode(salt_bytes, arraysize(salt_bytes)); |
| 110 profile->GetPrefs()->SetString(prefs::kDRMSalt, salt); | 131 profile->GetPrefs()->SetString(prefs::kDRMSalt, salt); |
| 111 } | 132 } |
| 112 | 133 |
| 113 #if defined(OS_CHROMEOS) | 134 #if defined(OS_CHROMEOS) |
| 114 // Try the legacy path first for ChromeOS. We pass the new salt in as well | 135 // Try the legacy path first for ChromeOS. We pass the new salt in as well |
| 115 // in case the legacy id doesn't exist. | 136 // in case the legacy id doesn't exist. |
| 116 BrowserThread::PostBlockingPoolTask(FROM_HERE, | 137 BrowserThread::PostBlockingPoolTask( |
| 117 base::Bind(&DeviceIDFetcher::ComputeOnBlockingPool, this, | 138 FROM_HERE, |
| 139 base::Bind(&DeviceIDFetcher::LegacyComputeOnBlockingPool, | |
| 140 weak_ptr_factory_.GetWeakPtr(), | |
| 118 profile->GetPath(), salt)); | 141 profile->GetPath(), salt)); |
| 119 #else | 142 #else |
| 120 BrowserThread::PostTask( | 143 // Get the machine ID and call ComputeOnUIThread with salt + machine_id. |
| 121 BrowserThread::IO, FROM_HERE, | 144 GetMachineIdAsync(base::Bind(&DeviceIDFetcher::ComputeOnUIThread, |
| 122 base::Bind(&DeviceIDFetcher::ComputeOnIOThread, this, salt)); | 145 weak_ptr_factory_.GetWeakPtr(), |
| 146 salt)); | |
| 123 #endif | 147 #endif |
| 124 } | 148 } |
| 125 | 149 |
| 150 void DeviceIDFetcher::ComputeOnUIThread(const std::string& salt, | |
| 151 const std::string& machine_id) { | |
| 152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 126 | 153 |
| 127 void DeviceIDFetcher::ComputeOnIOThread(const std::string& salt) { | 154 if (machine_id.empty()) { |
| 155 LOG(ERROR) << "Empty machine id"; | |
| 156 RunCallbackOnIOThread(std::string()); | |
| 157 return; | |
| 158 } | |
| 159 | |
| 160 // Build the identifier as follows: | |
| 161 // SHA256(machine-id||service||SHA256(machine-id||service||salt)) | |
| 128 std::vector<uint8> salt_bytes; | 162 std::vector<uint8> salt_bytes; |
| 129 if (!base::HexStringToBytes(salt, &salt_bytes)) | 163 if (!base::HexStringToBytes(salt, &salt_bytes)) |
| 130 salt_bytes.clear(); | 164 salt_bytes.clear(); |
| 131 | 165 if (salt_bytes.size() != kSaltLength) { |
| 132 // Build the identifier as follows: | 166 LOG(ERROR) << "Unexpected salt bytes length: " << salt_bytes.size(); |
| 133 // SHA256(machine-id||service||SHA256(machine-id||service||salt)) | |
| 134 std::string machine_id = GetMachineID(); | |
| 135 if (machine_id.empty() || salt_bytes.size() != kSaltLength) { | |
| 136 NOTREACHED(); | |
| 137 RunCallbackOnIOThread(std::string()); | 167 RunCallbackOnIOThread(std::string()); |
| 138 return; | 168 return; |
| 139 } | 169 } |
| 140 | 170 |
| 141 char id_buf[256 / 8]; // 256-bits for SHA256 | 171 char id_buf[256 / 8]; // 256-bits for SHA256 |
| 142 std::string input = machine_id; | 172 std::string input = machine_id; |
| 143 input.append(kDRMIdentifierFile); | 173 input.append(kDRMIdentifierFile); |
| 144 input.append(salt_bytes.begin(), salt_bytes.end()); | 174 input.append(salt_bytes.begin(), salt_bytes.end()); |
| 145 crypto::SHA256HashString(input, &id_buf, sizeof(id_buf)); | 175 crypto::SHA256HashString(input, &id_buf, sizeof(id_buf)); |
| 146 std::string id = StringToLowerASCII( | 176 std::string id = StringToLowerASCII( |
| 147 base::HexEncode(reinterpret_cast<const void*>(id_buf), sizeof(id_buf))); | 177 base::HexEncode(reinterpret_cast<const void*>(id_buf), sizeof(id_buf))); |
| 148 input = machine_id; | 178 input = machine_id; |
| 149 input.append(kDRMIdentifierFile); | 179 input.append(kDRMIdentifierFile); |
| 150 input.append(id); | 180 input.append(id); |
| 151 crypto::SHA256HashString(input, &id_buf, sizeof(id_buf)); | 181 crypto::SHA256HashString(input, &id_buf, sizeof(id_buf)); |
| 152 id = StringToLowerASCII(base::HexEncode( | 182 id = StringToLowerASCII(base::HexEncode( |
| 153 reinterpret_cast<const void*>(id_buf), | 183 reinterpret_cast<const void*>(id_buf), |
| 154 sizeof(id_buf))); | 184 sizeof(id_buf))); |
| 155 | 185 |
| 156 RunCallbackOnIOThread(id); | 186 RunCallbackOnIOThread(id); |
| 157 } | 187 } |
| 158 | 188 |
| 159 // TODO(raymes): This is temporary code to migrate ChromeOS devices to the new | 189 // TODO(raymes): This is temporary code to migrate ChromeOS devices to the new |
| 160 // scheme for generating device IDs. Delete this once we are sure most ChromeOS | 190 // scheme for generating device IDs. Delete this once we are sure most ChromeOS |
| 161 // devices have been migrated. | 191 // devices have been migrated. |
| 162 void DeviceIDFetcher::ComputeOnBlockingPool(const base::FilePath& profile_path, | 192 // static |
| 163 const std::string& salt) { | 193 void DeviceIDFetcher::LegacyComputeOnBlockingPool( |
| 194 base::WeakPtr<DeviceIDFetcher> fetcher, | |
| 195 const base::FilePath& profile_path, | |
| 196 const std::string& salt) { | |
| 164 std::string id; | 197 std::string id; |
| 165 // First check if the legacy device ID file exists on ChromeOS. If it does, we | 198 // First check if the legacy device ID file exists on ChromeOS. If it does, we |
| 166 // should just return that. | 199 // should just return that. |
| 167 base::FilePath id_path = GetLegacyDeviceIDPath(profile_path); | 200 base::FilePath id_path = |
| 168 if (base::PathExists(id_path)) { | 201 DeviceIDFetcher::GetLegacyDeviceIDPath(profile_path); |
| 169 if (base::ReadFileToString(id_path, &id) && !id.empty()) { | 202 if (base::PathExists(id_path) && |
| 170 RunCallbackOnIOThread(id); | 203 base::ReadFileToString(id_path, &id) && |
| 171 return; | 204 !id.empty()) { |
| 172 } | 205 BrowserThread::PostTask( |
| 206 BrowserThread::UI, FROM_HERE, | |
| 207 base::Bind(&DeviceIDFetcher::RunCallbackOnIOThread, | |
| 208 fetcher, | |
| 209 id)); | |
| 210 return; | |
| 173 } | 211 } |
| 174 // If we didn't find an ID, go back to the new code path to generate an ID. | 212 // If we didn't find an ID, get the machine Id and call the new code path to |
| 213 // generate an ID. | |
| 175 BrowserThread::PostTask( | 214 BrowserThread::PostTask( |
| 176 BrowserThread::IO, FROM_HERE, | 215 BrowserThread::UI, FROM_HERE, |
| 177 base::Bind(&DeviceIDFetcher::ComputeOnIOThread, this, salt)); | 216 base::Bind(&GetMachineIdAsync, |
| 217 base::Bind(&DeviceIDFetcher::ComputeOnUIThread, | |
| 218 fetcher, | |
| 219 salt))); | |
| 178 } | 220 } |
| 179 | 221 |
| 180 | |
| 181 void DeviceIDFetcher::RunCallbackOnIOThread(const std::string& id) { | 222 void DeviceIDFetcher::RunCallbackOnIOThread(const std::string& id) { |
| 182 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 223 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 183 BrowserThread::PostTask( | 224 BrowserThread::PostTask( |
| 184 BrowserThread::IO, FROM_HERE, | 225 BrowserThread::IO, FROM_HERE, |
| 185 base::Bind(&DeviceIDFetcher::RunCallbackOnIOThread, this, id)); | 226 base::Bind(&DeviceIDFetcher::RunCallbackOnIOThread, this, id)); |
| 186 return; | 227 return; |
| 187 } | 228 } |
| 188 in_progress_ = false; | 229 in_progress_ = false; |
| 189 callback_.Run(id); | 230 callback_.Run(id); |
| 190 } | 231 } |
| 191 | 232 |
| 192 std::string DeviceIDFetcher::GetMachineID() { | |
| 193 #if defined(OS_WIN) && defined(ENABLE_RLZ) | |
| 194 std::string result; | |
| 195 rlz_lib::GetMachineId(&result); | |
| 196 return result; | |
| 197 #elif defined(OS_CHROMEOS) | |
| 198 chromeos::CryptohomeLibrary* c_home = chromeos::CryptohomeLibrary::Get(); | |
| 199 return c_home->GetSystemSalt(); | |
| 200 #else | |
| 201 // Not implemented for other platforms. | |
| 202 NOTREACHED(); | |
| 203 return ""; | |
| 204 #endif | |
| 205 } | |
| 206 | |
| 207 } // namespace chrome | 233 } // namespace chrome |
| OLD | NEW |