blob: 73ff1a1909dc90073c9563d67139b34717872910 [file]
// Copyright 2026 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/component_loader_prefs.h"
#include <optional>
#include <string>
#include <utility>
#include "base/files/file_path.h"
#include "base/values.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "extensions/common/extension_id.h"
namespace extensions::component_loader_prefs {
namespace {
// Local State preference storing a dictionary of staged component extensions,
// mapping ExtensionId to a dictionary containing the relative install path and
// parsed manifest dictionary.
constexpr char kComponentExtensionStagedUpdatesPref[] =
"extensions.staged_component_updates";
constexpr char kRelativePathPrefKey[] = "relative_path";
constexpr char kManifestPrefKey[] = "manifest";
} // namespace
void RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(kComponentExtensionStagedUpdatesPref);
}
void StageExtension(PrefService& local_state,
const ExtensionId& extension_id,
const base::FilePath& relative_path,
base::DictValue manifest) {
ScopedDictPrefUpdate update(&local_state,
kComponentExtensionStagedUpdatesPref);
base::DictValue entry;
entry.Set(kRelativePathPrefKey, relative_path.AsUTF8Unsafe());
entry.Set(kManifestPrefKey, std::move(manifest));
update->Set(extension_id, std::move(entry));
}
void ClearExtension(PrefService& local_state, const ExtensionId& extension_id) {
if (!local_state.GetDict(kComponentExtensionStagedUpdatesPref)
.contains(extension_id)) {
return;
}
ScopedDictPrefUpdate update(&local_state,
kComponentExtensionStagedUpdatesPref);
update->Remove(extension_id);
}
std::optional<StagedComponentExtensionInfo> GetExtension(
const PrefService& local_state,
const ExtensionId& extension_id) {
const base::DictValue* entry =
local_state.GetDict(kComponentExtensionStagedUpdatesPref)
.FindDict(extension_id);
if (!entry) {
return std::nullopt;
}
const std::string* path_str = entry->FindString(kRelativePathPrefKey);
const base::DictValue* manifest = entry->FindDict(kManifestPrefKey);
if (!path_str || !manifest) {
return std::nullopt;
}
base::FilePath relative_path = base::FilePath::FromUTF8Unsafe(*path_str);
if (relative_path.empty() || relative_path.IsAbsolute() ||
relative_path.ReferencesParent()) {
return std::nullopt;
}
return StagedComponentExtensionInfo{std::move(relative_path),
manifest->Clone()};
}
} // namespace extensions::component_loader_prefs