1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
// Copyright 2021 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/devtools/devtools_settings.h"
#include "base/strings/to_string.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/scoped_user_pref_update.h"
const char DevToolsSettings::kSyncDevToolsPreferencesFrontendName[] =
"sync-preferences";
const bool DevToolsSettings::kSyncDevToolsPreferencesDefault = false;
DevToolsSettings::DevToolsSettings(Profile* profile) : profile_(profile) {
pref_change_registrar_.Init(profile_->GetPrefs());
pref_change_registrar_.Add(
prefs::kDevToolsSyncPreferences,
base::BindRepeating(&DevToolsSettings::DevToolsSyncPreferencesChanged,
base::Unretained(this)));
}
DevToolsSettings::~DevToolsSettings() = default;
void DevToolsSettings::Register(const std::string& name,
const RegisterOptions& options) {
// kSyncDevToolsPreferenceFrontendName is not stored in any of the relevant
// dictionaries. Skip registration.
if (name == kSyncDevToolsPreferencesFrontendName)
return;
if (options.sync_mode == RegisterOptions::SyncMode::kSync) {
synced_setting_names_.insert(name);
}
// Setting might have had a different sync status in the past. Move the
// setting to the correct dictionary.
PrefService* prefs = profile_->GetPrefs();
const char* dictionary_to_remove_from =
options.sync_mode == RegisterOptions::SyncMode::kSync
? prefs::kDevToolsPreferences
: GetDictionaryNameForSyncedPrefs();
const std::string* settings_value =
prefs->GetDict(dictionary_to_remove_from).FindString(name);
if (!settings_value) {
return;
}
const char* dictionary_to_insert_into =
GetDictionaryNameForSettingsName(name);
// Settings already moved to the synced dictionary on a different device have
// precedence.
const std::string* already_synced_value =
prefs->GetDict(dictionary_to_insert_into).FindString(name);
if (dictionary_to_insert_into == prefs::kDevToolsPreferences ||
!already_synced_value) {
ScopedDictPrefUpdate insert_update(profile_->GetPrefs(),
dictionary_to_insert_into);
insert_update->Set(name, *settings_value);
}
ScopedDictPrefUpdate remove_update(profile_->GetPrefs(),
dictionary_to_remove_from);
remove_update->Remove(name);
}
base::Value::Dict DevToolsSettings::Get() {
base::Value::Dict settings;
PrefService* prefs = profile_->GetPrefs();
// DevTools expects any kind of preference to be a string. Parsing is
// happening on the frontend.
settings.Set(
kSyncDevToolsPreferencesFrontendName,
base::ToString(prefs->GetBoolean(prefs::kDevToolsSyncPreferences)));
settings.Merge(prefs->GetDict(prefs::kDevToolsPreferences).Clone());
settings.Merge(prefs->GetDict(GetDictionaryNameForSyncedPrefs()).Clone());
return settings;
}
std::optional<base::Value> DevToolsSettings::Get(const std::string& name) {
PrefService* prefs = profile_->GetPrefs();
if (name == kSyncDevToolsPreferencesFrontendName) {
// DevTools expects any kind of preference to be a string. Parsing is
// happening on the frontend.
bool result = prefs->GetBoolean(prefs::kDevToolsSyncPreferences);
return base::Value(base::ToString(result));
}
const char* dict_name = GetDictionaryNameForSettingsName(name);
const base::Value::Dict& dict = prefs->GetDict(dict_name);
const base::Value* value = dict.Find(name);
return value ? std::optional<base::Value>(value->Clone()) : std::nullopt;
}
void DevToolsSettings::Set(const std::string& name, const std::string& value) {
if (name == kSyncDevToolsPreferencesFrontendName) {
profile_->GetPrefs()->SetBoolean(prefs::kDevToolsSyncPreferences,
value == "true");
return;
}
ScopedDictPrefUpdate update(profile_->GetPrefs(),
GetDictionaryNameForSettingsName(name));
update->Set(name, value);
}
void DevToolsSettings::Remove(const std::string& name) {
if (name == kSyncDevToolsPreferencesFrontendName) {
profile_->GetPrefs()->SetBoolean(prefs::kDevToolsSyncPreferences,
kSyncDevToolsPreferencesDefault);
return;
}
PrefService* prefs = profile_->GetPrefs();
for (auto* dict_name :
{GetDictionaryNameForSyncedPrefs(), prefs::kDevToolsPreferences}) {
const base::Value::Dict& dict = prefs->GetDict(dict_name);
if (dict.Find(name)) {
ScopedDictPrefUpdate update(profile_->GetPrefs(), dict_name);
update->Remove(name);
}
}
}
void DevToolsSettings::Clear() {
profile_->GetPrefs()->SetBoolean(prefs::kDevToolsSyncPreferences,
kSyncDevToolsPreferencesDefault);
profile_->GetPrefs()->SetDict(prefs::kDevToolsPreferences,
base::Value::Dict());
profile_->GetPrefs()->SetDict(prefs::kDevToolsSyncedPreferencesSyncEnabled,
base::Value::Dict());
profile_->GetPrefs()->SetDict(prefs::kDevToolsSyncedPreferencesSyncDisabled,
base::Value::Dict());
}
const char* DevToolsSettings::GetDictionaryNameForSettingsName(
const std::string& name) const {
return synced_setting_names_.contains(name)
? GetDictionaryNameForSyncedPrefs()
: prefs::kDevToolsPreferences;
}
const char* DevToolsSettings::GetDictionaryNameForSyncedPrefs() const {
const bool isDevToolsSyncEnabled =
profile_->GetPrefs()->GetBoolean(prefs::kDevToolsSyncPreferences);
return isDevToolsSyncEnabled ? prefs::kDevToolsSyncedPreferencesSyncEnabled
: prefs::kDevToolsSyncedPreferencesSyncDisabled;
}
void DevToolsSettings::DevToolsSyncPreferencesChanged() {
// There are two cases to handle:
//
// Sync was enabled: We assume this was triggered by the user in the local
// DevTools session as opposed to synced from a different device. As such, the
// local settings have precedence when merging. The unsynced dictonary is
// cleared.
//
// Sync was disabled: As kDevToolsSyncPreferences is synced itself we can
// clear the synced dictionary after copying to the unsynced one. The unsynced
// dictionary is empty.
//
// Considering the points above, the implementation between both cases can be
// shared modulo the source/target dictionary.
const bool sync_enabled =
profile_->GetPrefs()->GetBoolean(prefs::kDevToolsSyncPreferences);
const char* target_dictionary =
sync_enabled ? prefs::kDevToolsSyncedPreferencesSyncEnabled
: prefs::kDevToolsSyncedPreferencesSyncDisabled;
const char* source_dictionary =
sync_enabled ? prefs::kDevToolsSyncedPreferencesSyncDisabled
: prefs::kDevToolsSyncedPreferencesSyncEnabled;
ScopedDictPrefUpdate source_update(profile_->GetPrefs(), source_dictionary);
ScopedDictPrefUpdate target_update(profile_->GetPrefs(), target_dictionary);
base::Value::Dict source_dict;
std::swap(source_dict, *source_update);
target_update->Merge(std::move(source_dict));
}
|