一、先说结论 User Data 路径优先级如下:
1、注册表中策略配置的路径。
计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Chromium
UserDataDir="xx_path"
2、命令行中的路径。
--user-data-dir="xx_path"
3、默认用户路径
%LOCALAPPDATA%/Chromium/User Data
二、接下来上源码分析过程
一、chrome\app\chrome_crash_reporter_client_win.cc
//1、开始初始化user data目录
std::wstring user_data_dir;
if (process_type.empty())
install_static::GetUserDataDirectory(&user_data_dir, nullptr);
// static
void ChromeCrashReporterClient::InitializeCrashReportingForProcess() {
static ChromeCrashReporterClient* instance = nullptr;
if (instance)
return;
instance = new ChromeCrashReporterClient();
ANNOTATE_LEAKING_OBJECT_PTR(instance);
std::wstring process_type = install_static::GetSwitchValueFromCommandLine(
::GetCommandLine(), install_static::kProcessType);
// Don't set up Crashpad crash reporting in the Crashpad handler itself, nor
// in the fallback crash handler for the Crashpad handler process.
if (process_type != install_static::kCrashpadHandler &&
process_type != install_static::kFallbackHandler) {
crash_reporter::SetCrashReporterClient(instance);
//1、开始初始化user data目录
std::wstring user_data_dir;
if (process_type.empty())
install_static::GetUserDataDirectory(&user_data_dir, nullptr);
// TODO(wfh): Add a DCHECK for success. See https://crbug.com/1329269.
std::ignore = crash_reporter::InitializeCrashpadWithEmbeddedHandler(
/*initial_client=*/process_type.empty(),
install_static::WideToUTF8(process_type),
install_static::WideToUTF8(user_data_dir), base::FilePath());
}
}
二、第二步看install_static::GetUserDataDirectory(&user_data_dir, nullptr);实现
在chrome\install_static\user_data_dir.cc中
namespace install_static {
namespace {
std::wstring* g_user_data_dir;
std::wstring* g_invalid_user_data_dir;
// Retrieves a registry policy for the user data directory from the registry, if
// one is set. If there's none set in either HKLM or HKCU, |user_data_dir| will
// be unmodified.
void GetUserDataDirFromRegistryPolicyIfSet(const InstallConstants& mode,
std::wstring* user_data_dir) {
assert(user_data_dir);
std::wstring policies_path = L"SOFTWARE\\Policies\\";
AppendChromeInstallSubDirectory(mode, false /* !include_suffix */,
&policies_path);
std::wstring value;
constexpr wchar_t kUserDataDirRegistryKeyName[] = L"UserDataDir";
// First, try HKLM.
if (nt::QueryRegValueSZ(nt::HKLM, nt::NONE, policies_path.c_str(),
kUserDataDirRegistryKeyName, &value)) {
*user_data_dir = ExpandPathVariables(value);
return;
}
// Second, try HKCU.
if (nt::QueryRegValueSZ(nt::HKCU, nt::NONE, policies_path.c_str(),
kUserDataDirRegistryKeyName, &value)) {
*user_data_dir = ExpandPathVariables(value);
return;
}
}
std::wstring MakeAbsoluteFilePath(const std::wstring& input) {
wchar_t file_path[MAX_PATH];
if (!_wfullpath(file_path, input.c_str(), _countof(file_path)))
return std::wstring();
return file_path;
}
// The same as GetUserDataDirectory(), but directly queries the global command
// line object for the --user-data-dir flag. This is the more commonly used
// function, where GetUserDataDirectory() is used primiarily for testing.
bool GetUserDataDirectoryUsingProcessCommandLine(
const InstallConstants& mode,
std::wstring* result,
std::wstring* invalid_supplied_directory) {
return GetUserDataDirectoryImpl(
GetSwitchValueFromCommandLine(::GetCommandLine(), kUserDataDirSwitch),
mode, result, invalid_supplied_directory);
}
// Populates |result| with the default User Data directory for the current
// user. Returns false if all attempts at locating a User Data directory fail.
// TODO(ananta)
// http://crbug.com/604923
// Unify this with the Browser Distribution code.
bool GetDefaultUserDataDirectory(const InstallConstants& mode,
std::wstring* result) {
// This environment variable should be set on Windows Vista and later
// (https://msdn.microsoft.com/library/windows/desktop/dd378457.aspx).
std::wstring user_data_dir = GetEnvironmentString(L"LOCALAPPDATA");
if (user_data_dir.empty()) {
// LOCALAPPDATA was not set; fallback to the temporary files path.
DWORD size = ::GetTempPath(0, nullptr);
if (!size)
return false;
user_data_dir.resize(size + 1);
size = ::GetTempPath(size + 1, &user_data_dir[0]);
if (!size || size >= user_data_dir.size())
return false;
user_data_dir.resize(size);
}
result->swap(user_data_dir);
if ((*result)[result->length() - 1] != L'\\')
result->push_back(L'\\');
AppendChromeInstallSubDirectory(mode, true /* include_suffix */, result);
result->push_back(L'\\');
result->append(L"User Data");
return true;
}
} // namespace
bool GetUserDataDirectoryImpl(
const std::wstring& user_data_dir_from_command_line,
const InstallConstants& mode,
std::wstring* result,
std::wstring* invalid_supplied_directory) {
std::wstring user_data_dir = user_data_dir_from_command_line;
//从注册表中读取路径
GetUserDataDirFromRegistryPolicyIfSet(mode, &user_data_dir);
// On Windows, trailing separators leave Chrome in a bad state. See
// crbug.com/464616.
while (!user_data_dir.empty() &&
(user_data_dir.back() == '\\' || user_data_dir.back() == '/')) {
user_data_dir.pop_back();
}
bool got_valid_directory =
!user_data_dir.empty() && RecursiveDirectoryCreate(user_data_dir);
if (!got_valid_directory) {
*invalid_supplied_directory = user_data_dir;
//从%LOCALAPPDATA%/Chromium/User Data 中读取
got_valid_directory = GetDefaultUserDataDirectory(mode, &user_data_dir);
}
// The Chrome implementation CHECKs() here in the browser process. We
// don't as this function is used to initialize crash reporting, so
// we would get no report of this failure.
assert(got_valid_directory);
if (!got_valid_directory)
return false;
*result = MakeAbsoluteFilePath(user_data_dir);
return true;
}
bool GetUserDataDirectory(std::wstring* user_data_dir,
std::wstring* invalid_user_data_dir) {
if (!g_user_data_dir) {
g_user_data_dir = new std::wstring();
g_invalid_user_data_dir = new std::wstring();
//从命令行中解析路径
if (!GetUserDataDirectoryUsingProcessCommandLine(
InstallDetails::Get().mode(), g_user_data_dir,
g_invalid_user_data_dir)) {
return false;
}
assert(!g_user_data_dir->empty());
}
*user_data_dir = *g_user_data_dir;
if (invalid_user_data_dir)
*invalid_user_data_dir = *g_invalid_user_data_dir;
return true;
}
} // namespace install_static
调用堆栈:
GetUserDataDirectory->GetUserDataDirectoryUsingProcessCommandLine->
GetUserDataDirectoryImpl->GetSwitchValueFromCommandLine->GetUserDataDirFromRegistryPolicyIfSet->GetDefaultUserDataDirectory
三、最后将初始化的g_user_data_dir路径设置到
chrome\app\chrome_main_delegate.cc
CHECK(base::PathService::OverrideAndCreateIfNeeded(
chrome::DIR_USER_DATA, user_data_dir, false, true));中,
// Initializes the user data dir. Must be called before InitializeLocalState().
void InitializeUserDataDir(base::CommandLine* command_line) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
// In debug builds of Lacros, we keep track of when the user data dir
// is initialized, to ensure the cryptohome is not accessed before login
// when prelaunching at login screen.
chromeos::lacros_paths::SetInitializedUserDataDir();
#endif
#if BUILDFLAG(IS_WIN)
// Reach out to chrome_elf for the truth on the user data directory.
// Note that in tests, this links to chrome_elf_test_stubs.
wchar_t user_data_dir_buf[MAX_PATH], invalid_user_data_dir_buf[MAX_PATH];
// In tests this may return false, implying the user data dir should be unset.
if (GetUserDataDirectoryThunk(user_data_dir_buf, std::size(user_data_dir_buf),
invalid_user_data_dir_buf,
std::size(invalid_user_data_dir_buf))) {
base::FilePath user_data_dir(user_data_dir_buf);
if (invalid_user_data_dir_buf[0] != 0) {
chrome::SetInvalidSpecifiedUserDataDir(
base::FilePath(invalid_user_data_dir_buf));
command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
}
//将user data路径存储到path缓存中
CHECK(base::PathService::OverrideAndCreateIfNeeded(
chrome::DIR_USER_DATA, user_data_dir, false, true));
}
这样
base::FilePath user_data_dir;
base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
就可以读取其中的路径了。