| // Copyright 2025 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/extensions/initial_external_extension_loader.h" |
| |
| #include <string> |
| |
| #include "base/strings/strcat.h" |
| #include "base/types/to_address.h" |
| #include "base/values.h" |
| #include "chrome/browser/extensions/external_provider_impl.h" |
| #include "components/crx_file/id_util.h" |
| #include "components/prefs/pref_service.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "extensions/browser/pref_names.h" |
| #include "extensions/common/extension_urls.h" |
| |
| namespace extensions { |
| |
| namespace { |
| |
| std::string MakePrefName(const std::string& extension_id, |
| const std::string& pref_name) { |
| return base::StrCat({extension_id, ".", pref_name}); |
| } |
| |
| // Generates a dictionary of preferences for the given extension IDs. |
| // For each valid extension ID in `extensions_ids`, its creates |
| // preferences to set the update URL to the Chrome Web Store and to mark the |
| // extension as trusted (i.e., not untrusted). |
| base::Value::Dict GenerateExtensionPrefs( |
| const base::Value::List& extensions_ids) { |
| base::Value::Dict prefs; |
| const std::string web_store_update_url = |
| extension_urls::GetWebstoreUpdateUrl().spec(); |
| for (const auto& extension_id : extensions_ids) { |
| const std::string* id = extension_id.GetIfString(); |
| if (!id || !crx_file::id_util::IdIsValid(*id)) { |
| continue; |
| } |
| |
| prefs.SetByDottedPath( |
| MakePrefName(*id, ExternalProviderImpl::kExternalUpdateUrl), |
| web_store_update_url); |
| prefs.SetByDottedPath( |
| MakePrefName(*id, ExternalProviderImpl::kMayBeUntrusted), false); |
| } |
| return prefs; |
| } |
| |
| } // namespace |
| |
| InitialExternalExtensionLoader::InitialExternalExtensionLoader( |
| PrefService& prefs) |
| : prefs_(prefs) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| |
| pref_registrar_.Init(base::to_address(prefs_)); |
| |
| // base::Unretained() is safe because `pref_registrar_` is owned by `this`. |
| // |
| // `pref_names::kInitialInstallList` may not be populated at this time. |
| // Therefore, future changes should be monitored so that the extension ids |
| // will be taken into consideration. |
| pref_registrar_.Add( |
| pref_names::kInitialInstallList, |
| base::BindRepeating( |
| &InitialExternalExtensionLoader::OnExtensionsPrefChanged, |
| base::Unretained(this))); |
| } |
| |
| InitialExternalExtensionLoader::~InitialExternalExtensionLoader() = default; |
| |
| void InitialExternalExtensionLoader::StartLoading() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| const base::Value::List& ids = |
| prefs_->GetList(pref_names::kInitialInstallList); |
| LoadFinished(GenerateExtensionPrefs(ids)); |
| } |
| |
| void InitialExternalExtensionLoader::OnExtensionsPrefChanged() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| const base::Value::List& ids = |
| prefs_->GetList(pref_names::kInitialInstallList); |
| OnUpdated(GenerateExtensionPrefs(ids)); |
| } |
| |
| } // namespace extensions |