This source file includes following definitions.
- GetMachineIDAsync
- render_process_id_
- Start
- RegisterProfilePrefs
- GetLegacyDeviceIDPath
- CheckPrefsOnUIThread
- ComputeOnUIThread
- LegacyComputeOnBlockingPool
- RunCallbackOnIOThread
#include "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
#include "base/file_util.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#if defined(OS_CHROMEOS)
#include "chromeos/cryptohome/system_salt_getter.h"
#endif
#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_ppapi_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "crypto/encryptor.h"
#include "crypto/random.h"
#include "crypto/sha2.h"
#include "ppapi/c/pp_errors.h"
#if defined(ENABLE_RLZ)
#include "rlz/lib/machine_id.h"
#endif
using content::BrowserPpapiHost;
using content::BrowserThread;
using content::RenderProcessHost;
namespace chrome {
namespace {
const char kDRMIdentifierFile[] = "Pepper DRM ID.0";
const uint32_t kSaltLength = 32;
void GetMachineIDAsync(
const base::Callback<void(const std::string&)>& callback) {
#if defined(OS_WIN) && defined(ENABLE_RLZ)
std::string result;
rlz_lib::GetMachineId(&result);
callback.Run(result);
#elif defined(OS_CHROMEOS)
chromeos::SystemSaltGetter::Get()->GetSystemSalt(callback);
#else
NOTREACHED();
callback.Run(std::string());
#endif
}
}
DeviceIDFetcher::DeviceIDFetcher(int render_process_id)
: in_progress_(false),
render_process_id_(render_process_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
DeviceIDFetcher::~DeviceIDFetcher() {
}
bool DeviceIDFetcher::Start(const IDCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (in_progress_)
return false;
in_progress_ = true;
callback_ = callback;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&DeviceIDFetcher::CheckPrefsOnUIThread, this));
return true;
}
void DeviceIDFetcher::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* prefs) {
prefs->RegisterBooleanPref(prefs::kEnableDRM,
true,
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
prefs->RegisterStringPref(
prefs::kDRMSalt,
"",
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}
base::FilePath DeviceIDFetcher::GetLegacyDeviceIDPath(
const base::FilePath& profile_path) {
return profile_path.AppendASCII(kDRMIdentifierFile);
}
void DeviceIDFetcher::CheckPrefsOnUIThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Profile* profile = NULL;
RenderProcessHost* render_process_host =
RenderProcessHost::FromID(render_process_id_);
if (render_process_host && render_process_host->GetBrowserContext()) {
profile = Profile::FromBrowserContext(
render_process_host->GetBrowserContext());
}
if (!profile ||
profile->IsOffTheRecord() ||
!profile->GetPrefs()->GetBoolean(prefs::kEnableDRM)) {
RunCallbackOnIOThread(std::string(), PP_ERROR_NOACCESS);
return;
}
std::string salt = profile->GetPrefs()->GetString(prefs::kDRMSalt);
if (salt.empty()) {
uint8_t salt_bytes[kSaltLength];
crypto::RandBytes(salt_bytes, arraysize(salt_bytes));
salt = base::HexEncode(salt_bytes, arraysize(salt_bytes));
profile->GetPrefs()->SetString(prefs::kDRMSalt, salt);
}
#if defined(OS_CHROMEOS)
BrowserThread::PostBlockingPoolTask(
FROM_HERE,
base::Bind(&DeviceIDFetcher::LegacyComputeOnBlockingPool,
this,
profile->GetPath(), salt));
#else
GetMachineIDAsync(base::Bind(&DeviceIDFetcher::ComputeOnUIThread,
this, salt));
#endif
}
void DeviceIDFetcher::ComputeOnUIThread(const std::string& salt,
const std::string& machine_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (machine_id.empty()) {
LOG(ERROR) << "Empty machine id";
RunCallbackOnIOThread(std::string(), PP_ERROR_FAILED);
return;
}
std::vector<uint8> salt_bytes;
if (!base::HexStringToBytes(salt, &salt_bytes))
salt_bytes.clear();
if (salt_bytes.size() != kSaltLength) {
LOG(ERROR) << "Unexpected salt bytes length: " << salt_bytes.size();
RunCallbackOnIOThread(std::string(), PP_ERROR_FAILED);
return;
}
char id_buf[256 / 8];
std::string input = machine_id;
input.append(kDRMIdentifierFile);
input.append(salt_bytes.begin(), salt_bytes.end());
crypto::SHA256HashString(input, &id_buf, sizeof(id_buf));
std::string id = StringToLowerASCII(
base::HexEncode(reinterpret_cast<const void*>(id_buf), sizeof(id_buf)));
input = machine_id;
input.append(kDRMIdentifierFile);
input.append(id);
crypto::SHA256HashString(input, &id_buf, sizeof(id_buf));
id = StringToLowerASCII(base::HexEncode(
reinterpret_cast<const void*>(id_buf),
sizeof(id_buf)));
RunCallbackOnIOThread(id, PP_OK);
}
void DeviceIDFetcher::LegacyComputeOnBlockingPool(
const base::FilePath& profile_path,
const std::string& salt) {
std::string id;
base::FilePath id_path = GetLegacyDeviceIDPath(profile_path);
if (base::PathExists(id_path)) {
if (base::ReadFileToString(id_path, &id) && !id.empty()) {
RunCallbackOnIOThread(id, PP_OK);
return;
}
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&GetMachineIDAsync,
base::Bind(&DeviceIDFetcher::ComputeOnUIThread,
this, salt)));
}
void DeviceIDFetcher::RunCallbackOnIOThread(const std::string& id,
int32_t result) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&DeviceIDFetcher::RunCallbackOnIOThread, this, id, result));
return;
}
in_progress_ = false;
callback_.Run(id, result);
}
}