Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/settings_private/settings_private_delega te.h" | |
| 6 | |
| 7 #include "base/json/json_reader.h" | |
| 8 #include "base/prefs/pref_service.h" | 5 #include "base/prefs/pref_service.h" |
| 9 #include "base/values.h" | |
| 10 #include "chrome/browser/browser_process.h" | 6 #include "chrome/browser/browser_process.h" |
| 7 #include "chrome/browser/extensions/api/settings_private/prefs_util.h" | |
| 8 #include "chrome/browser/profiles/profile.h" | |
| 11 #include "chrome/common/pref_names.h" | 9 #include "chrome/common/pref_names.h" |
| 12 #include "components/url_fixer/url_fixer.h" | |
| 13 #include "extensions/browser/extension_registry.h" | |
| 14 #include "extensions/common/extension.h" | |
| 15 #include "url/gurl.h" | |
| 16 | 10 |
| 17 namespace extensions { | 11 namespace extensions { |
| 18 | 12 |
| 19 namespace settings_private = api::settings_private; | 13 namespace settings_private = api::settings_private; |
| 20 | 14 |
| 21 namespace { | 15 namespace prefs_util { |
| 22 | |
| 23 // NOTE: Consider moving this function to a separate file, e.g. in | |
| 24 // chrome/browser/prefs. | |
| 25 bool IsPrefUserModifiable(Profile* profile, | |
| 26 PrefService* pref_service, | |
| 27 const std::string& pref_name) { | |
| 28 if (pref_name != prefs::kBrowserGuestModeEnabled && | |
| 29 pref_name != prefs::kBrowserAddPersonEnabled) { | |
| 30 return true; | |
| 31 } | |
| 32 | |
| 33 const PrefService::Preference* pref = | |
| 34 pref_service->FindPreference(pref_name.c_str()); | |
| 35 if (!pref || !pref->IsUserModifiable() || profile->IsSupervised()) | |
| 36 return false; | |
| 37 | |
| 38 return true; | |
| 39 } | |
| 40 | 16 |
| 41 const TypedPrefMap& GetWhitelistedKeys() { | 17 const TypedPrefMap& GetWhitelistedKeys() { |
| 42 static TypedPrefMap* s_whitelist = nullptr; | 18 static TypedPrefMap* s_whitelist = nullptr; |
| 43 if (s_whitelist) | 19 if (s_whitelist) |
| 44 return *s_whitelist; | 20 return *s_whitelist; |
| 45 s_whitelist = new TypedPrefMap(); | 21 s_whitelist = new TypedPrefMap(); |
| 46 (*s_whitelist)["download.default_directory"] = | 22 (*s_whitelist)["download.default_directory"] = |
| 47 settings_private::PrefType::PREF_TYPE_STRING; | 23 settings_private::PrefType::PREF_TYPE_STRING; |
| 48 (*s_whitelist)["download.prompt_for_download"] = | 24 (*s_whitelist)["download.prompt_for_download"] = |
| 49 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 25 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 50 (*s_whitelist)["homepage"] = | 26 (*s_whitelist)["homepage"] = settings_private::PrefType::PREF_TYPE_URL; |
| 51 settings_private::PrefType::PREF_TYPE_URL; | |
| 52 return *s_whitelist; | |
| 53 } | |
| 54 | 27 |
| 55 #if defined(OS_CHROMEOS) | 28 #if defined(OS_CHROMEOS) |
| 56 const TypedPrefMap& GetWhitelistedCrosKeys() { | |
| 57 static TypedPrefMap* s_whitelist = nullptr; | |
| 58 if (s_whitelist) | |
| 59 return *s_whitelist; | |
| 60 s_whitelist = new TypedPrefMap(); | |
| 61 (*s_whitelist)["settings.accessibility"] = | 29 (*s_whitelist)["settings.accessibility"] = |
| 62 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 30 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 63 (*s_whitelist)["settings.a11y.autoclick"] = | 31 (*s_whitelist)["settings.a11y.autoclick"] = |
| 64 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 32 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 65 (*s_whitelist)["settings.a11y.autoclick_delay_ms"] = | 33 (*s_whitelist)["settings.a11y.autoclick_delay_ms"] = |
| 66 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 34 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 67 (*s_whitelist)["settings.a11y.enable_menu"] = | 35 (*s_whitelist)["settings.a11y.enable_menu"] = |
| 68 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 36 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 69 (*s_whitelist)["settings.a11y.high_contrast_enabled"] = | 37 (*s_whitelist)["settings.a11y.high_contrast_enabled"] = |
| 70 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 38 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 71 (*s_whitelist)["settings.a11y.large_cursor_enabled"] = | 39 (*s_whitelist)["settings.a11y.large_cursor_enabled"] = |
| 72 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 40 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 73 (*s_whitelist)["settings.a11y.screen_magnifier"] = | 41 (*s_whitelist)["settings.a11y.screen_magnifier"] = |
| 74 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 42 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 75 (*s_whitelist)["settings.a11y.sticky_keys_enabled"] = | 43 (*s_whitelist)["settings.a11y.sticky_keys_enabled"] = |
| 76 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 44 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 77 (*s_whitelist)["settings.a11y.virtual_keyboard"] = | 45 (*s_whitelist)["settings.a11y.virtual_keyboard"] = |
| 78 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 46 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 79 (*s_whitelist)["settings.touchpad.enable_tap_dragging"] = | 47 (*s_whitelist)["settings.touchpad.enable_tap_dragging"] = |
| 80 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 48 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 49 #endif | |
| 50 | |
| 81 return *s_whitelist; | 51 return *s_whitelist; |
| 82 } | 52 } |
| 83 #endif | 53 |
| 54 bool IsPrefUserModifiable(Profile* profile, const std::string& pref_name) { | |
|
stevenjb
2015/04/06 22:40:59
Order in C++ should match .h (or vice versa)
Oren Blasberg
2015/04/06 23:27:06
Done.
| |
| 55 if (pref_name != prefs::kBrowserGuestModeEnabled && | |
| 56 pref_name != prefs::kBrowserAddPersonEnabled) { | |
| 57 return true; | |
| 58 } | |
| 59 | |
| 60 PrefService* pref_service = profile->GetPrefs(); | |
| 61 const PrefService::Preference* pref = | |
| 62 pref_service->FindPreference(pref_name.c_str()); | |
| 63 if (!pref || !pref->IsUserModifiable() || profile->IsSupervised()) | |
| 64 return false; | |
| 65 | |
| 66 return true; | |
| 67 } | |
| 84 | 68 |
| 85 bool IsPrefTypeURL(const std::string& pref_name) { | 69 bool IsPrefTypeURL(const std::string& pref_name) { |
| 86 settings_private::PrefType pref_type = | 70 settings_private::PrefType pref_type = |
| 87 settings_private::PrefType::PREF_TYPE_NONE; | 71 settings_private::PrefType::PREF_TYPE_NONE; |
| 88 | 72 |
| 89 const TypedPrefMap keys = GetWhitelistedKeys(); | 73 const TypedPrefMap keys = GetWhitelistedKeys(); |
| 90 const auto& iter = keys.find(pref_name); | 74 const auto& iter = keys.find(pref_name); |
| 91 if (iter != keys.end()) { | 75 if (iter != keys.end()) { |
| 92 pref_type = iter->second; | 76 pref_type = iter->second; |
| 93 } | 77 } |
| 94 | 78 |
| 95 #if defined(OS_CHROMEOS) | |
| 96 const TypedPrefMap cros_keys = GetWhitelistedCrosKeys(); | |
| 97 const auto& cros_iter = cros_keys.find(pref_name); | |
| 98 if (cros_iter != cros_keys.end()) { | |
| 99 pref_type = cros_iter->second; | |
| 100 } | |
| 101 #endif | |
| 102 | |
| 103 return pref_type == settings_private::PrefType::PREF_TYPE_URL; | 79 return pref_type == settings_private::PrefType::PREF_TYPE_URL; |
| 104 } | 80 } |
| 105 | 81 |
| 106 } // namespace | 82 PrefService* FindServiceForPref(Profile* profile, |
| 83 const std::string& pref_name) { | |
| 84 PrefService* user_prefs = profile->GetPrefs(); | |
| 107 | 85 |
| 108 SettingsPrivateDelegate::SettingsPrivateDelegate(Profile* profile) | 86 // Proxy is a peculiar case: on ChromeOS, settings exist in both user |
| 109 : profile_(profile) { | 87 // prefs and local state, but chrome://settings should affect only user prefs. |
| 88 // Elsewhere the proxy settings are stored in local state. | |
| 89 // See http://crbug.com/157147 | |
| 90 | |
| 91 if (pref_name == prefs::kProxy) { | |
| 92 #if defined(OS_CHROMEOS) | |
| 93 return user_prefs; | |
| 94 #else | |
| 95 return g_browser_process->local_state(); | |
| 96 #endif | |
| 97 } | |
| 98 | |
| 99 // Find which PrefService contains the given pref. Pref names should not | |
| 100 // be duplicated across services, however if they are, prefer the user's | |
| 101 // prefs. | |
| 102 if (user_prefs->FindPreference(pref_name)) | |
| 103 return user_prefs; | |
| 104 | |
| 105 if (g_browser_process->local_state()->FindPreference(pref_name)) | |
| 106 return g_browser_process->local_state(); | |
| 107 | |
| 108 return user_prefs; | |
| 110 } | 109 } |
| 111 | 110 |
| 112 SettingsPrivateDelegate::~SettingsPrivateDelegate() { | 111 scoped_ptr<api::settings_private::PrefObject> GetPref(Profile* profile, |
| 113 } | 112 const std::string& name) { |
| 113 scoped_ptr<api::settings_private::PrefObject> pref_object( | |
| 114 new api::settings_private::PrefObject()); | |
| 114 | 115 |
| 115 scoped_ptr<base::Value> SettingsPrivateDelegate::GetPref( | 116 PrefService* pref_service = FindServiceForPref(profile, name); |
| 116 const std::string& name) { | |
| 117 PrefService* pref_service = profile_->GetPrefs(); | |
| 118 const PrefService::Preference* pref = pref_service->FindPreference(name); | 117 const PrefService::Preference* pref = pref_service->FindPreference(name); |
| 119 if (!pref) | 118 if (!pref) |
| 120 return make_scoped_ptr(base::Value::CreateNullValue()); | 119 return pref_object.Pass(); |
| 121 | 120 |
| 122 api::settings_private::PrefObject* pref_object = | |
| 123 new api::settings_private::PrefObject(); | |
| 124 pref_object->key = pref->name(); | 121 pref_object->key = pref->name(); |
| 125 switch (pref->GetType()) { | 122 switch (pref->GetType()) { |
| 126 case base::Value::Type::TYPE_BOOLEAN: | 123 case base::Value::Type::TYPE_BOOLEAN: |
| 127 pref_object->type = api::settings_private::PrefType::PREF_TYPE_BOOLEAN; | 124 pref_object->type = api::settings_private::PrefType::PREF_TYPE_BOOLEAN; |
| 128 break; | 125 break; |
| 129 case base::Value::Type::TYPE_INTEGER: | 126 case base::Value::Type::TYPE_INTEGER: |
| 130 case base::Value::Type::TYPE_DOUBLE: | 127 case base::Value::Type::TYPE_DOUBLE: |
| 131 pref_object->type = api::settings_private::PrefType::PREF_TYPE_NUMBER; | 128 pref_object->type = api::settings_private::PrefType::PREF_TYPE_NUMBER; |
| 132 break; | 129 break; |
| 133 case base::Value::Type::TYPE_STRING: | 130 case base::Value::Type::TYPE_STRING: |
| 134 pref_object->type = IsPrefTypeURL(name) | 131 pref_object->type = |
| 135 ? api::settings_private::PrefType::PREF_TYPE_URL | 132 IsPrefTypeURL(name) |
| 136 : api::settings_private::PrefType::PREF_TYPE_STRING; | 133 ? api::settings_private::PrefType::PREF_TYPE_URL |
| 134 : api::settings_private::PrefType::PREF_TYPE_STRING; | |
| 137 break; | 135 break; |
| 138 case base::Value::Type::TYPE_LIST: | 136 case base::Value::Type::TYPE_LIST: |
| 139 pref_object->type = api::settings_private::PrefType::PREF_TYPE_LIST; | 137 pref_object->type = api::settings_private::PrefType::PREF_TYPE_LIST; |
| 140 break; | 138 break; |
| 141 default: | 139 default: |
| 142 break; | 140 break; |
| 143 } | 141 } |
| 144 | 142 |
| 145 pref_object->value.reset(pref->GetValue()->DeepCopy()); | 143 pref_object->value.reset(pref->GetValue()->DeepCopy()); |
| 146 | 144 |
| 147 if (pref->IsManaged()) { | 145 if (pref->IsManaged()) { |
| 148 if (pref->IsManagedByCustodian()) { | 146 if (pref->IsManagedByCustodian()) { |
| 149 pref_object->policy_source = | 147 pref_object->policy_source = |
| 150 api::settings_private::PolicySource::POLICY_SOURCE_DEVICE; | 148 api::settings_private::PolicySource::POLICY_SOURCE_DEVICE; |
| 151 } else { | 149 } else { |
| 152 pref_object->policy_source = | 150 pref_object->policy_source = |
| 153 api::settings_private::PolicySource::POLICY_SOURCE_USER; | 151 api::settings_private::PolicySource::POLICY_SOURCE_USER; |
| 154 } | 152 } |
| 155 pref_object->policy_enforcement = | 153 pref_object->policy_enforcement = |
| 156 pref->IsRecommended() ? api::settings_private::PolicyEnforcement:: | 154 pref->IsRecommended() ? api::settings_private::PolicyEnforcement:: |
| 157 POLICY_ENFORCEMENT_RECOMMENDED | 155 POLICY_ENFORCEMENT_RECOMMENDED |
| 158 : api::settings_private::PolicyEnforcement:: | 156 : api::settings_private::PolicyEnforcement:: |
| 159 POLICY_ENFORCEMENT_ENFORCED; | 157 POLICY_ENFORCEMENT_ENFORCED; |
| 160 } else if (!IsPrefUserModifiable(profile_, pref_service, name)) { | 158 } else if (!IsPrefUserModifiable(profile, name)) { |
| 161 pref_object->policy_source = | 159 pref_object->policy_source = |
| 162 api::settings_private::PolicySource::POLICY_SOURCE_USER; | 160 api::settings_private::PolicySource::POLICY_SOURCE_USER; |
| 163 pref_object->policy_enforcement = | 161 pref_object->policy_enforcement = |
| 164 api::settings_private::PolicyEnforcement::POLICY_ENFORCEMENT_ENFORCED; | 162 api::settings_private::PolicyEnforcement::POLICY_ENFORCEMENT_ENFORCED; |
| 165 } | 163 } |
| 166 | 164 |
| 167 return pref_object->ToValue(); | 165 return pref_object.Pass(); |
| 168 } | 166 } |
| 169 | 167 |
| 170 scoped_ptr<base::Value> SettingsPrivateDelegate::GetAllPrefs() { | 168 } // namespace prefs_util |
| 171 scoped_ptr<base::ListValue> prefs(new base::ListValue()); | |
| 172 | |
| 173 const TypedPrefMap& keys = GetWhitelistedKeys(); | |
| 174 for (const auto& it : keys) { | |
| 175 prefs->Append(GetPref(it.first).release()); | |
| 176 } | |
| 177 | |
| 178 #if defined(OS_CHROMEOS) | |
| 179 const TypedPrefMap cros_keys = GetWhitelistedCrosKeys(); | |
| 180 for (const auto& it : cros_keys) { | |
| 181 prefs->Append(GetPref(it.first).release()); | |
| 182 } | |
| 183 #endif | |
| 184 | |
| 185 return prefs.Pass(); | |
| 186 } | |
| 187 | |
| 188 PrefService* SettingsPrivateDelegate::FindServiceForPref( | |
| 189 const std::string& pref_name) { | |
| 190 PrefService* user_prefs = profile_->GetPrefs(); | |
| 191 | |
| 192 // Proxy is a peculiar case: on ChromeOS, settings exist in both user | |
| 193 // prefs and local state, but chrome://settings should affect only user prefs. | |
| 194 // Elsewhere the proxy settings are stored in local state. | |
| 195 // See http://crbug.com/157147 | |
| 196 | |
| 197 if (pref_name == prefs::kProxy) { | |
| 198 #if defined(OS_CHROMEOS) | |
| 199 return user_prefs; | |
| 200 #else | |
| 201 return g_browser_process->local_state(); | |
| 202 #endif | |
| 203 } | |
| 204 | |
| 205 // Find which PrefService contains the given pref. Pref names should not | |
| 206 // be duplicated across services, however if they are, prefer the user's | |
| 207 // prefs. | |
| 208 if (user_prefs->FindPreference(pref_name)) | |
| 209 return user_prefs; | |
| 210 | |
| 211 if (g_browser_process->local_state()->FindPreference(pref_name)) | |
| 212 return g_browser_process->local_state(); | |
| 213 | |
| 214 return user_prefs; | |
| 215 } | |
| 216 | |
| 217 bool SettingsPrivateDelegate::SetPref(const std::string& pref_name, | |
| 218 const base::Value* value) { | |
| 219 PrefService* pref_service = FindServiceForPref(pref_name); | |
| 220 | |
| 221 if (!IsPrefUserModifiable(profile_, pref_service, pref_name)) | |
| 222 return false; | |
| 223 | |
| 224 const PrefService::Preference* pref = | |
| 225 pref_service->FindPreference(pref_name.c_str()); | |
| 226 if (!pref) | |
| 227 return false; | |
| 228 | |
| 229 DCHECK_EQ(pref->GetType(), value->GetType()); | |
| 230 | |
| 231 scoped_ptr<base::Value> temp_value; | |
| 232 | |
| 233 switch (pref->GetType()) { | |
| 234 case base::Value::TYPE_INTEGER: { | |
| 235 // In JS all numbers are doubles. | |
| 236 double double_value; | |
| 237 if (!value->GetAsDouble(&double_value)) | |
| 238 return false; | |
| 239 | |
| 240 int int_value = static_cast<int>(double_value); | |
| 241 temp_value.reset(new base::FundamentalValue(int_value)); | |
| 242 value = temp_value.get(); | |
| 243 break; | |
| 244 } | |
| 245 case base::Value::TYPE_STRING: { | |
| 246 std::string original; | |
| 247 if (!value->GetAsString(&original)) | |
| 248 return false; | |
| 249 | |
| 250 if (IsPrefTypeURL(pref_name)) { | |
| 251 GURL fixed = url_fixer::FixupURL(original, std::string()); | |
| 252 temp_value.reset(new base::StringValue(fixed.spec())); | |
| 253 value = temp_value.get(); | |
| 254 } | |
| 255 break; | |
| 256 } | |
| 257 case base::Value::TYPE_LIST: { | |
| 258 // In case we have a List pref we got a JSON string. | |
| 259 std::string json_string; | |
| 260 if (!value->GetAsString(&json_string)) | |
| 261 return false; | |
| 262 | |
| 263 temp_value.reset(base::JSONReader::Read(json_string)); | |
| 264 value = temp_value.get(); | |
| 265 if (!value->IsType(base::Value::TYPE_LIST)) | |
| 266 return false; | |
| 267 | |
| 268 break; | |
| 269 } | |
| 270 case base::Value::TYPE_BOOLEAN: | |
| 271 case base::Value::TYPE_DOUBLE: | |
| 272 break; | |
| 273 default: | |
| 274 return false; | |
| 275 } | |
| 276 | |
| 277 // TODO(orenb): Process setting metrics here (like "ProcessUserMetric" in | |
| 278 // CoreOptionsHandler). | |
| 279 pref_service->Set(pref_name.c_str(), *value); | |
| 280 return true; | |
| 281 } | |
| 282 | 169 |
| 283 } // namespace extensions | 170 } // namespace extensions |
| OLD | NEW |