#include "chrome/browser/extensions/external_pref_loader.h"
#include <set>
#include <utility>
#include "base/containers/contains.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/json/json_file_value_serializer.h"
#include "base/json/json_string_value_serializer.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/ranges/algorithm.h"
#include "base/scoped_observation.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/value_iterators.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/apps/user_type_filter.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_file_task_runner.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/constants/ash_switches.h"
#include "chrome/browser/prefs/pref_service_syncable_util.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/sync/service/sync_service.h"
#include "components/sync/service/sync_service_observer.h"
#include "components/sync/service/sync_user_settings.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "components/sync_preferences/pref_service_syncable_observer.h"
#endif
BrowserThread;
namespace {
constexpr base::FilePath::CharType kExternalExtensionJson[] = …);
bool SkipInstallForChromeOSTablet(const base::FilePath& file_path) { … }
std::set<base::FilePath> GetPrefsCandidateFilesFromFolder(
const base::FilePath& external_extension_search_path) { … }
}
namespace extensions {
#if BUILDFLAG(IS_CHROMEOS_ASH)
class ExternalPrefLoader::PrioritySyncReadyWaiter
: public sync_preferences::PrefServiceSyncableObserver,
public syncer::SyncServiceObserver {
public:
explicit PrioritySyncReadyWaiter(Profile* profile) : profile_(profile) {
DCHECK(profile_);
}
PrioritySyncReadyWaiter(const PrioritySyncReadyWaiter&) = delete;
PrioritySyncReadyWaiter& operator=(const PrioritySyncReadyWaiter&) = delete;
~PrioritySyncReadyWaiter() override = default;
void Start(base::OnceClosure done_closure) {
if (IsPrioritySyncing()) {
std::move(done_closure).Run();
return;
}
DCHECK(!done_closure_);
done_closure_ = std::move(done_closure);
MaybeObserveSyncStart();
}
private:
void MaybeObserveSyncStart() {
syncer::SyncService* service = SyncServiceFactory::GetForProfile(profile_);
if (!service || !service->IsSyncFeatureEnabled()) {
Finish();
return;
}
AddObservers();
}
void OnIsSyncingChanged() override {
DCHECK(profile_);
if (!IsPrioritySyncing())
return;
Finish();
}
void OnStateChanged(syncer::SyncService* sync) override {
if (!sync->IsSyncFeatureEnabled()) {
Finish();
}
}
void OnSyncShutdown(syncer::SyncService* sync) override {
DCHECK(sync_service_observation_.IsObservingSource(sync));
sync_service_observation_.Reset();
}
bool IsPrioritySyncing() {
sync_preferences::PrefServiceSyncable* prefs =
PrefServiceSyncableFromProfile(profile_);
return prefs->AreOsPriorityPrefsSyncing();
}
void AddObservers() {
sync_preferences::PrefServiceSyncable* prefs =
PrefServiceSyncableFromProfile(profile_);
DCHECK(prefs);
syncable_pref_observation_.Observe(prefs);
syncer::SyncService* service = SyncServiceFactory::GetForProfile(profile_);
sync_service_observation_.Observe(service);
}
void Finish() { std::move(done_closure_).Run(); }
raw_ptr<Profile, LeakedDanglingUntriaged> profile_;
base::OnceClosure done_closure_;
base::ScopedObservation<sync_preferences::PrefServiceSyncable,
sync_preferences::PrefServiceSyncableObserver>
syncable_pref_observation_{this};
base::ScopedObservation<syncer::SyncService, syncer::SyncServiceObserver>
sync_service_observation_{this};
};
#endif
ExternalPrefLoader::ExternalPrefLoader(int base_path_id,
int options,
Profile* profile)
: … { … }
ExternalPrefLoader::~ExternalPrefLoader() { … }
const base::FilePath ExternalPrefLoader::GetBaseCrxFilePath() { … }
void ExternalPrefLoader::StartLoading() { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
void ExternalPrefLoader::OnPrioritySyncReady(
ExternalPrefLoader::PrioritySyncReadyWaiter* waiter) {
pending_waiter_list_.erase(
base::ranges::find(pending_waiter_list_, waiter,
&std::unique_ptr<PrioritySyncReadyWaiter>::get));
GetExtensionFileTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&ExternalPrefLoader::LoadOnFileThread, this));
}
#endif
base::Value::Dict ExternalPrefLoader::ExtractExtensionPrefs(
base::ValueDeserializer* deserializer,
const base::FilePath& path) { … }
void ExternalPrefLoader::LoadOnFileThread() { … }
void ExternalPrefLoader::ReadExternalExtensionPrefFile(
base::Value::Dict& prefs) { … }
void ExternalPrefLoader::ReadStandaloneExtensionPrefFiles(
base::Value::Dict& prefs) { … }
}