之前文章提到过浏览器启动会从[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Google\Chrome\Extensions\
注册表下自动搜索需要加载的扩展,那么如何禁用此功能呢?
直接看源码
chrome\browser\extensions\external_registry_loader_win.cc
chrome\browser\extensions\external_registry_loader_win.cc
// The Registry subkey that contains information about external extensions.
const wchar_t kRegistryExtensions[] = L"Software\\Google\\Chrome\\Extensions";
std::unique_ptr<base::DictionaryValue>
ExternalRegistryLoader::LoadPrefsOnBlockingThread() {
auto prefs = std::make_unique<base::DictionaryValue>();
//此函数会遍历[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Google\Chrome\Extensions\
// A map of IDs, to weed out duplicates between HKCU and HKLM.
std::set<std::wstring> keys;
base::win::RegistryKeyIterator iterator_machine_key(
HKEY_LOCAL_MACHINE,
kRegistryExtensions,
KEY_WOW64_32KEY);
for (; iterator_machine_key.Valid(); ++iterator_machine_key)
keys.insert(iterator_machine_key.Name());
base::win::RegistryKeyIterator iterator_user_key(
HKEY_CURRENT_USER, kRegistryExtensions);
for (; iterator_user_key.Valid(); ++iterator_user_key)
keys.insert(iterator_user_key.Name());
// Iterate over the keys found, first trying HKLM, then HKCU, as per Windows
// policy conventions. We only fall back to HKCU if the HKLM key cannot be
// opened, not if the data within the key is invalid, for example.
for (auto it = keys.begin(); it != keys.end(); ++it) {
base::win::RegKey key;
std::wstring key_path = kRegistryExtensions;
key_path.append(L"\\");
key_path.append(*it);
if (key.Open(HKEY_LOCAL_MACHINE,
key_path.c_str(),
KEY_READ | KEY_WOW64_32KEY) != ERROR_SUCCESS &&
key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ) !=
ERROR_SUCCESS) {
LOG(ERROR) << "Unable to read registry key at path (HKLM & HKCU): "
<< key_path << ".";
continue;
}
std::string id = base::ToLowerASCII(base::WideToASCII(*it));
if (!crx_file::id_util::IdIsValid(id)) {
LOG(ERROR) << "Invalid id value " << id
<< " for key " << key_path << ".";
continue;
}
std::wstring extension_dist_id;
if (key.ReadValue(kRegistryExtensionInstallParam, &extension_dist_id) ==
ERROR_SUCCESS) {
prefs->SetString(MakePrefName(id, ExternalProviderImpl::kInstallParam),
base::WideToASCII(extension_dist_id));
}
// If there is an update URL present, copy it to prefs and ignore
// path and version keys for this entry.
std::wstring extension_update_url;
if (key.ReadValue(kRegistryExtensionUpdateUrl, &extension_update_url)
== ERROR_SUCCESS) {
prefs->SetString(
MakePrefName(id, ExternalProviderImpl::kExternalUpdateUrl),
base::WideToASCII(extension_update_url));
continue;
}
std::wstring extension_path_str;
if (key.ReadValue(kRegistryExtensionPath, &extension_path_str)
!= ERROR_SUCCESS) {
// TODO(erikkay): find a way to get this into about:extensions
LOG(ERROR) << "Missing value " << kRegistryExtensionPath
<< " for key " << key_path << ".";
continue;
}
base::FilePath extension_path(extension_path_str);
if (!extension_path.IsAbsolute()) {
LOG(ERROR) << "File path " << extension_path_str
<< " needs to be absolute in key "
<< key_path;
continue;
}
if (!base::PathExists(extension_path)) {
LOG(ERROR) << "File " << extension_path_str
<< " for key " << key_path
<< " does not exist or is not readable.";
continue;
}
if (!CanOpenFileForReading(extension_path)) {
LOG(ERROR) << "File " << extension_path_str
<< " for key " << key_path << " can not be read. "
<< "Check that users who should have the extension "
<< "installed have permission to read it.";
continue;
}
std::wstring extension_version;
if (key.ReadValue(kRegistryExtensionVersion, &extension_version)
!= ERROR_SUCCESS) {
// TODO(erikkay): find a way to get this into about:extensions
LOG(ERROR) << "Missing value " << kRegistryExtensionVersion
<< " for key " << key_path << ".";
continue;
}
base::Version version(base::WideToASCII(extension_version));
if (!version.IsValid()) {
LOG(ERROR) << "Invalid version value " << extension_version
<< " for key " << key_path << ".";
continue;
}
prefs->SetString(MakePrefName(id, ExternalProviderImpl::kExternalVersion),
base::WideToASCII(extension_version));
prefs->SetString(MakePrefName(id, ExternalProviderImpl::kExternalCrx),
base::AsString16(extension_path_str));
prefs->SetBoolean(
MakePrefName(id, ExternalProviderImpl::kMayBeUntrusted),
true);
}
return prefs;
}
//加载
void ExternalRegistryLoader::LoadOnBlockingThread() {
DCHECK(task_runner_);
DCHECK(task_runner_->RunsTasksInCurrentSequence());
base::TimeTicks start_time = base::TimeTicks::Now();
std::unique_ptr<base::DictionaryValue> prefs = LoadPrefsOnBlockingThread();
LOCAL_HISTOGRAM_TIMES("Extensions.ExternalRegistryLoaderWin",
base::TimeTicks::Now() - start_time);
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
&ExternalRegistryLoader::CompleteLoadAndStartWatchingRegistry, this,
std::move(prefs)));
}
//更新
void ExternalRegistryLoader::UpatePrefsOnBlockingThread() {
DCHECK(task_runner_);
DCHECK(task_runner_->RunsTasksInCurrentSequence());
base::TimeTicks start_time = base::TimeTicks::Now();
std::unique_ptr<base::DictionaryValue> prefs = LoadPrefsOnBlockingThread();
LOCAL_HISTOGRAM_TIMES("Extensions.ExternalRegistryLoaderWinUpdate",
base::TimeTicks::Now() - start_time);
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&ExternalRegistryLoader::OnUpdated, this,
std::move(prefs)));
}
结论: LoadPrefsOnBlockingThread函数会在以上两个函数调用,所以直接将LoadPrefsOnBlockingThread函数返回值置成空即可。
std::unique_ptr<base::DictionaryValue>
ExternalRegistryLoader::LoadPrefsOnBlockingThread() {
auto prefs = std::make_unique<base::DictionaryValue>();
return prefs ;
}