mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	- Building on Windows now requires the Windows 10.0.10586 SDK. - Remove CefParseCSSColor which was implemented using Blink code in the browser process. This is longer advisable now that the Oilpan GC is enabled. - Avoid potential renderer process crashes by disabling script actions on the CefV8Context passed to CefRenderProcessHandler::OnContextReleased.
		
			
				
	
	
		
			219 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			219 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (c) 2013 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 "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
 | |
| 
 | |
| #include "base/files/file_util.h"
 | |
| #include "base/macros.h"
 | |
| #include "base/strings/string_number_conversions.h"
 | |
| #include "build/build_config.h"
 | |
| #include "chrome/common/pref_names.h"
 | |
| #if defined(OS_CHROMEOS)
 | |
| #include "chromeos/cryptohome/system_salt_getter.h"
 | |
| #endif
 | |
| #include "components/prefs/pref_service.h"
 | |
| #include "components/pref_registry/pref_registry_syncable.h"
 | |
| #include "components/user_prefs/user_prefs.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
 | |
|   // Not implemented for other platforms.
 | |
|   NOTREACHED();
 | |
|   callback.Run(std::string());
 | |
| #endif
 | |
| }
 | |
| 
 | |
| }  // namespace
 | |
| 
 | |
| DeviceIDFetcher::DeviceIDFetcher(int render_process_id)
 | |
|     : in_progress_(false), render_process_id_(render_process_id) {
 | |
|   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 | |
| }
 | |
| 
 | |
| DeviceIDFetcher::~DeviceIDFetcher() {}
 | |
| 
 | |
| bool DeviceIDFetcher::Start(const IDCallback& callback) {
 | |
|   DCHECK_CURRENTLY_ON(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;
 | |
| }
 | |
| 
 | |
| // static
 | |
| void DeviceIDFetcher::RegisterProfilePrefs(
 | |
|     user_prefs::PrefRegistrySyncable* prefs) {
 | |
|   prefs->RegisterBooleanPref(prefs::kEnableDRM, true);
 | |
|   prefs->RegisterStringPref(prefs::kDRMSalt, "");
 | |
| }
 | |
| 
 | |
| // static
 | |
| base::FilePath DeviceIDFetcher::GetLegacyDeviceIDPath(
 | |
|     const base::FilePath& profile_path) {
 | |
|   return profile_path.AppendASCII(kDRMIdentifierFile);
 | |
| }
 | |
| 
 | |
| void DeviceIDFetcher::CheckPrefsOnUIThread() {
 | |
|   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 | |
| 
 | |
|   RenderProcessHost* render_process_host =
 | |
|       RenderProcessHost::FromID(render_process_id_);
 | |
|   content::BrowserContext* browser_context = NULL;
 | |
|   if (render_process_host)
 | |
|     browser_context = render_process_host->GetBrowserContext();
 | |
| 
 | |
|   PrefService* prefs = NULL;
 | |
|   if (browser_context) {
 | |
|     prefs = user_prefs::UserPrefs::Get(browser_context);
 | |
|     DCHECK(prefs);
 | |
|   }
 | |
| 
 | |
|   if (!browser_context || browser_context->IsOffTheRecord() ||
 | |
|       !prefs->GetBoolean(prefs::kEnableDRM)) {
 | |
|     RunCallbackOnIOThread(std::string(), PP_ERROR_NOACCESS);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Check if the salt pref is set. If it isn't, set it.
 | |
|   std::string salt = prefs->GetString(prefs::kDRMSalt);
 | |
|   if (salt.empty()) {
 | |
|     uint8_t salt_bytes[kSaltLength];
 | |
|     crypto::RandBytes(salt_bytes, arraysize(salt_bytes));
 | |
|     // Since it will be stored in a string pref, convert it to hex.
 | |
|     salt = base::HexEncode(salt_bytes, arraysize(salt_bytes));
 | |
|     prefs->SetString(prefs::kDRMSalt, salt);
 | |
|   }
 | |
| 
 | |
| #if defined(OS_CHROMEOS)
 | |
|   // Try the legacy path first for ChromeOS. We pass the new salt in as well
 | |
|   // in case the legacy id doesn't exist.
 | |
|   BrowserThread::PostBlockingPoolTask(
 | |
|       FROM_HERE,
 | |
|       base::Bind(&DeviceIDFetcher::LegacyComputeOnBlockingPool,
 | |
|                  this,
 | |
|                  profile->GetPath(),
 | |
|                  salt));
 | |
| #else
 | |
|   // Get the machine ID and call ComputeOnUIThread with salt + machine_id.
 | |
|   GetMachineIDAsync(
 | |
|       base::Bind(&DeviceIDFetcher::ComputeOnUIThread, this, salt));
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void DeviceIDFetcher::ComputeOnUIThread(const std::string& salt,
 | |
|                                         const std::string& machine_id) {
 | |
|   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 | |
| 
 | |
|   if (machine_id.empty()) {
 | |
|     LOG(ERROR) << "Empty machine id";
 | |
|     RunCallbackOnIOThread(std::string(), PP_ERROR_FAILED);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Build the identifier as follows:
 | |
|   // SHA256(machine-id||service||SHA256(machine-id||service||salt))
 | |
|   std::vector<uint8_t> 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];  // 256-bits for SHA256
 | |
|   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 = base::ToLowerASCII(
 | |
|       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 = base::ToLowerASCII(
 | |
|       base::HexEncode(reinterpret_cast<const void*>(id_buf), sizeof(id_buf)));
 | |
| 
 | |
|   RunCallbackOnIOThread(id, PP_OK);
 | |
| }
 | |
| 
 | |
| // TODO(raymes): This is temporary code to migrate ChromeOS devices to the new
 | |
| // scheme for generating device IDs. Delete this once we are sure most ChromeOS
 | |
| // devices have been migrated.
 | |
| void DeviceIDFetcher::LegacyComputeOnBlockingPool(
 | |
|     const base::FilePath& profile_path,
 | |
|     const std::string& salt) {
 | |
|   std::string id;
 | |
|   // First check if the legacy device ID file exists on ChromeOS. If it does, we
 | |
|   // should just return that.
 | |
|   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;
 | |
|     }
 | |
|   }
 | |
|   // If we didn't find an ID, get the machine ID and call the new code path to
 | |
|   // generate an ID.
 | |
|   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);
 | |
| }
 | |
| 
 | |
| }  // namespace chrome
 |