之前文章提到过浏览器启动会从[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:extensionsLOG(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:extensionsLOG(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 ;
}