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 "base/json/json_reader.h" | |
5 #include "base/prefs/pref_service.h" | 6 #include "base/prefs/pref_service.h" |
6 #include "chrome/browser/browser_process.h" | 7 #include "chrome/browser/browser_process.h" |
7 #include "chrome/browser/extensions/api/settings_private/prefs_util.h" | 8 #include "chrome/browser/extensions/api/settings_private/prefs_util.h" |
9 #include "chrome/browser/extensions/chrome_extension_function.h" | |
8 #include "chrome/browser/profiles/profile.h" | 10 #include "chrome/browser/profiles/profile.h" |
9 #include "chrome/common/pref_names.h" | 11 #include "chrome/common/pref_names.h" |
12 #include "components/url_fixer/url_fixer.h" | |
13 | |
14 #if defined(OS_CHROMEOS) | |
15 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h" | |
16 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_fact ory.h" | |
17 #include "chrome/browser/chromeos/settings/cros_settings.h" | |
18 #endif | |
10 | 19 |
11 namespace extensions { | 20 namespace extensions { |
12 | 21 |
13 namespace settings_private = api::settings_private; | 22 namespace settings_private = api::settings_private; |
14 | 23 |
15 namespace prefs_util { | 24 PrefsUtil::PrefsUtil(Profile* profile) : profile_(profile) { |
25 } | |
16 | 26 |
17 const TypedPrefMap& GetWhitelistedKeys() { | 27 PrefsUtil::~PrefsUtil() { |
18 static TypedPrefMap* s_whitelist = nullptr; | 28 } |
29 | |
30 #if defined(OS_CHROMEOS) | |
31 using CrosSettings = chromeos::CrosSettings; | |
32 #endif | |
33 | |
34 const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() { | |
35 static PrefsUtil::TypedPrefMap* s_whitelist = nullptr; | |
19 if (s_whitelist) | 36 if (s_whitelist) |
20 return *s_whitelist; | 37 return *s_whitelist; |
21 s_whitelist = new TypedPrefMap(); | 38 s_whitelist = new PrefsUtil::TypedPrefMap(); |
22 (*s_whitelist)["browser.show_home_button"] = | 39 (*s_whitelist)["browser.show_home_button"] = |
23 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 40 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
24 (*s_whitelist)["bookmark_bar.show_on_all_tabs"] = | 41 (*s_whitelist)["bookmark_bar.show_on_all_tabs"] = |
25 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 42 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
26 (*s_whitelist)["download.default_directory"] = | 43 (*s_whitelist)["download.default_directory"] = |
27 settings_private::PrefType::PREF_TYPE_STRING; | 44 settings_private::PrefType::PREF_TYPE_STRING; |
28 (*s_whitelist)["download.prompt_for_download"] = | 45 (*s_whitelist)["download.prompt_for_download"] = |
29 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 46 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
30 (*s_whitelist)["homepage"] = settings_private::PrefType::PREF_TYPE_URL; | 47 (*s_whitelist)["homepage"] = settings_private::PrefType::PREF_TYPE_URL; |
31 | 48 |
32 #if defined(OS_CHROMEOS) | 49 #if defined(OS_CHROMEOS) |
50 (*s_whitelist)["cros.accounts.allowBWSI"] = | |
51 settings_private::PrefType::PREF_TYPE_BOOLEAN; | |
52 (*s_whitelist)["cros.accounts.supervisedUsersEnabled"] = | |
53 settings_private::PrefType::PREF_TYPE_BOOLEAN; | |
54 (*s_whitelist)["cros.accounts.showUserNamesOnSignIn"] = | |
55 settings_private::PrefType::PREF_TYPE_BOOLEAN; | |
56 (*s_whitelist)["cros.accounts.allowGuest"] = | |
57 settings_private::PrefType::PREF_TYPE_BOOLEAN; | |
33 (*s_whitelist)["settings.accessibility"] = | 58 (*s_whitelist)["settings.accessibility"] = |
34 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 59 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
35 (*s_whitelist)["settings.a11y.autoclick"] = | 60 (*s_whitelist)["settings.a11y.autoclick"] = |
36 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 61 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
37 (*s_whitelist)["settings.a11y.autoclick_delay_ms"] = | 62 (*s_whitelist)["settings.a11y.autoclick_delay_ms"] = |
38 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 63 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
39 (*s_whitelist)["settings.a11y.enable_menu"] = | 64 (*s_whitelist)["settings.a11y.enable_menu"] = |
40 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 65 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
41 (*s_whitelist)["settings.a11y.high_contrast_enabled"] = | 66 (*s_whitelist)["settings.a11y.high_contrast_enabled"] = |
42 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 67 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
43 (*s_whitelist)["settings.a11y.large_cursor_enabled"] = | 68 (*s_whitelist)["settings.a11y.large_cursor_enabled"] = |
44 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 69 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
45 (*s_whitelist)["settings.a11y.screen_magnifier"] = | 70 (*s_whitelist)["settings.a11y.screen_magnifier"] = |
46 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 71 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
47 (*s_whitelist)["settings.a11y.sticky_keys_enabled"] = | 72 (*s_whitelist)["settings.a11y.sticky_keys_enabled"] = |
48 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 73 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
49 (*s_whitelist)["settings.a11y.virtual_keyboard"] = | 74 (*s_whitelist)["settings.a11y.virtual_keyboard"] = |
50 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 75 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
51 (*s_whitelist)["settings.clock.use_24hour_clock"] = | 76 (*s_whitelist)["settings.clock.use_24hour_clock"] = |
52 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 77 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
53 (*s_whitelist)["settings.touchpad.enable_tap_dragging"] = | 78 (*s_whitelist)["settings.touchpad.enable_tap_dragging"] = |
54 settings_private::PrefType::PREF_TYPE_BOOLEAN; | 79 settings_private::PrefType::PREF_TYPE_BOOLEAN; |
55 #endif | 80 #endif |
56 | 81 |
57 return *s_whitelist; | 82 return *s_whitelist; |
58 } | 83 } |
59 | 84 |
60 scoped_ptr<api::settings_private::PrefObject> GetPref(Profile* profile, | 85 api::settings_private::PrefType PrefsUtil::GetType(const std::string& name, |
61 const std::string& name) { | 86 base::Value::Type type) { |
87 switch (type) { | |
88 case base::Value::Type::TYPE_BOOLEAN: | |
89 return api::settings_private::PrefType::PREF_TYPE_BOOLEAN; | |
90 case base::Value::Type::TYPE_INTEGER: | |
91 case base::Value::Type::TYPE_DOUBLE: | |
92 return api::settings_private::PrefType::PREF_TYPE_NUMBER; | |
93 case base::Value::Type::TYPE_STRING: | |
94 return IsPrefTypeURL(name) | |
95 ? api::settings_private::PrefType::PREF_TYPE_URL | |
96 : api::settings_private::PrefType::PREF_TYPE_STRING; | |
97 case base::Value::Type::TYPE_LIST: | |
98 return api::settings_private::PrefType::PREF_TYPE_LIST; | |
99 default: | |
100 return api::settings_private::PrefType::PREF_TYPE_NONE; | |
101 } | |
102 } | |
103 | |
104 scoped_ptr<api::settings_private::PrefObject> PrefsUtil::GetCrosSettingsPref( | |
105 const std::string& name) { | |
62 scoped_ptr<api::settings_private::PrefObject> pref_object( | 106 scoped_ptr<api::settings_private::PrefObject> pref_object( |
63 new api::settings_private::PrefObject()); | 107 new api::settings_private::PrefObject()); |
64 | 108 |
65 PrefService* pref_service = FindServiceForPref(profile, name); | 109 #if defined(OS_CHROMEOS) |
110 const base::Value* value = CrosSettings::Get()->GetPref(name); | |
111 pref_object->key = name; | |
112 pref_object->type = GetType(name, value->GetType()); | |
Oren Blasberg
2015/06/06 00:42:55
Somehow, this line segfaults if name is 'cros.acco
stevenjb
2015/06/06 00:48:17
Is value maybe NULL?
Oren Blasberg
2015/06/06 01:02:11
Whoops, you're right, it's null.
However, I don't
| |
113 pref_object->value.reset(value->DeepCopy()); | |
114 #endif | |
115 | |
116 return pref_object.Pass(); | |
117 } | |
118 | |
119 scoped_ptr<api::settings_private::PrefObject> PrefsUtil::GetPref( | |
120 const std::string& name) { | |
121 scoped_ptr<api::settings_private::PrefObject> pref_object( | |
122 new api::settings_private::PrefObject()); | |
123 | |
124 if (IsCrosSetting(name)) | |
125 return GetCrosSettingsPref(name); | |
126 | |
127 PrefService* pref_service = FindServiceForPref(name); | |
66 const PrefService::Preference* pref = pref_service->FindPreference(name); | 128 const PrefService::Preference* pref = pref_service->FindPreference(name); |
67 if (!pref) | 129 if (!pref) |
68 return pref_object.Pass(); | 130 return pref_object.Pass(); |
69 | 131 |
70 pref_object->key = pref->name(); | 132 pref_object->key = pref->name(); |
71 switch (pref->GetType()) { | 133 pref_object->type = GetType(name, pref->GetType()); |
72 case base::Value::Type::TYPE_BOOLEAN: | |
73 pref_object->type = api::settings_private::PrefType::PREF_TYPE_BOOLEAN; | |
74 break; | |
75 case base::Value::Type::TYPE_INTEGER: | |
76 case base::Value::Type::TYPE_DOUBLE: | |
77 pref_object->type = api::settings_private::PrefType::PREF_TYPE_NUMBER; | |
78 break; | |
79 case base::Value::Type::TYPE_STRING: | |
80 pref_object->type = | |
81 IsPrefTypeURL(name) | |
82 ? api::settings_private::PrefType::PREF_TYPE_URL | |
83 : api::settings_private::PrefType::PREF_TYPE_STRING; | |
84 break; | |
85 case base::Value::Type::TYPE_LIST: | |
86 pref_object->type = api::settings_private::PrefType::PREF_TYPE_LIST; | |
87 break; | |
88 default: | |
89 break; | |
90 } | |
91 | |
92 pref_object->value.reset(pref->GetValue()->DeepCopy()); | 134 pref_object->value.reset(pref->GetValue()->DeepCopy()); |
93 | 135 |
94 if (pref->IsManaged()) { | 136 if (pref->IsManaged()) { |
95 if (pref->IsManagedByCustodian()) { | 137 if (pref->IsManagedByCustodian()) { |
96 pref_object->policy_source = | 138 pref_object->policy_source = |
97 api::settings_private::PolicySource::POLICY_SOURCE_DEVICE; | 139 api::settings_private::PolicySource::POLICY_SOURCE_DEVICE; |
98 } else { | 140 } else { |
99 pref_object->policy_source = | 141 pref_object->policy_source = |
100 api::settings_private::PolicySource::POLICY_SOURCE_USER; | 142 api::settings_private::PolicySource::POLICY_SOURCE_USER; |
101 } | 143 } |
102 pref_object->policy_enforcement = | 144 pref_object->policy_enforcement = |
103 pref->IsRecommended() ? api::settings_private::PolicyEnforcement:: | 145 pref->IsRecommended() ? api::settings_private::PolicyEnforcement:: |
104 POLICY_ENFORCEMENT_RECOMMENDED | 146 POLICY_ENFORCEMENT_RECOMMENDED |
105 : api::settings_private::PolicyEnforcement:: | 147 : api::settings_private::PolicyEnforcement:: |
106 POLICY_ENFORCEMENT_ENFORCED; | 148 POLICY_ENFORCEMENT_ENFORCED; |
107 } else if (!IsPrefUserModifiable(profile, name)) { | 149 } else if (!IsPrefUserModifiable(name)) { |
108 pref_object->policy_source = | 150 pref_object->policy_source = |
109 api::settings_private::PolicySource::POLICY_SOURCE_USER; | 151 api::settings_private::PolicySource::POLICY_SOURCE_USER; |
110 pref_object->policy_enforcement = | 152 pref_object->policy_enforcement = |
111 api::settings_private::PolicyEnforcement::POLICY_ENFORCEMENT_ENFORCED; | 153 api::settings_private::PolicyEnforcement::POLICY_ENFORCEMENT_ENFORCED; |
112 } | 154 } |
113 | 155 |
114 return pref_object.Pass(); | 156 return pref_object.Pass(); |
115 } | 157 } |
116 | 158 |
117 bool IsPrefTypeURL(const std::string& pref_name) { | 159 bool PrefsUtil::SetPref(const std::string& pref_name, |
160 const base::Value* value) { | |
161 if (IsCrosSetting(pref_name)) | |
162 return SetCrosSettingsPref(pref_name, value); | |
163 | |
164 PrefService* pref_service = FindServiceForPref(pref_name); | |
165 | |
166 if (!IsPrefUserModifiable(pref_name)) | |
167 return false; | |
168 | |
169 const PrefService::Preference* pref = | |
170 pref_service->FindPreference(pref_name.c_str()); | |
171 if (!pref) | |
172 return false; | |
173 | |
174 DCHECK_EQ(pref->GetType(), value->GetType()); | |
175 | |
176 scoped_ptr<base::Value> temp_value; | |
177 | |
178 switch (pref->GetType()) { | |
179 case base::Value::TYPE_INTEGER: { | |
180 // In JS all numbers are doubles. | |
181 double double_value; | |
182 if (!value->GetAsDouble(&double_value)) | |
183 return false; | |
184 | |
185 int int_value = static_cast<int>(double_value); | |
186 temp_value.reset(new base::FundamentalValue(int_value)); | |
187 value = temp_value.get(); | |
188 break; | |
189 } | |
190 case base::Value::TYPE_STRING: { | |
191 std::string original; | |
192 if (!value->GetAsString(&original)) | |
193 return false; | |
194 | |
195 if (IsPrefTypeURL(pref_name)) { | |
196 GURL fixed = url_fixer::FixupURL(original, std::string()); | |
197 temp_value.reset(new base::StringValue(fixed.spec())); | |
198 value = temp_value.get(); | |
199 } | |
200 break; | |
201 } | |
202 case base::Value::TYPE_LIST: { | |
203 // In case we have a List pref we got a JSON string. | |
204 std::string json_string; | |
205 if (!value->GetAsString(&json_string)) | |
206 return false; | |
207 | |
208 temp_value.reset(base::JSONReader::DeprecatedRead(json_string)); | |
209 value = temp_value.get(); | |
210 if (!value->IsType(base::Value::TYPE_LIST)) | |
211 return false; | |
212 | |
213 break; | |
214 } | |
215 case base::Value::TYPE_BOOLEAN: | |
216 case base::Value::TYPE_DOUBLE: | |
217 break; | |
218 default: | |
219 return false; | |
220 } | |
221 | |
222 // TODO(orenb): Process setting metrics here and in the CrOS setting method | |
223 // too (like "ProcessUserMetric" in CoreOptionsHandler). | |
224 pref_service->Set(pref_name.c_str(), *value); | |
225 return true; | |
226 } | |
227 | |
228 bool PrefsUtil::SetCrosSettingsPref(const std::string& pref_name, | |
229 const base::Value* value) { | |
230 #if defined(OS_CHROMEOS) | |
231 chromeos::OwnerSettingsServiceChromeOS* service = | |
232 chromeos::OwnerSettingsServiceChromeOSFactory::GetForBrowserContext( | |
233 profile_); | |
234 | |
235 // Returns false if not the owner, for settings requiring owner. | |
236 if (service && service->HandlesSetting(pref_name)) | |
237 return service->Set(pref_name, *value); | |
238 | |
239 chromeos::CrosSettings::Get()->Set(pref_name, *value); | |
240 return true; | |
241 #else | |
242 return false; | |
243 #endif | |
244 } | |
245 | |
246 bool PrefsUtil::AppendToListCrosSetting(const std::string& setting, | |
247 const base::Value& value) { | |
248 #if defined(OS_CHROMEOS) | |
249 chromeos::OwnerSettingsServiceChromeOS* service = | |
250 chromeos::OwnerSettingsServiceChromeOSFactory::GetForBrowserContext( | |
251 profile_); | |
252 DCHECK(service); | |
253 return service->AppendToList(setting, value); | |
254 #else | |
255 return false; | |
256 #endif | |
257 } | |
258 | |
259 bool PrefsUtil::RemoveFromListCrosSetting(const std::string& setting, | |
260 const base::Value& value) { | |
261 #if defined(OS_CHROMEOS) | |
262 chromeos::OwnerSettingsServiceChromeOS* service = | |
263 chromeos::OwnerSettingsServiceChromeOSFactory::GetForBrowserContext( | |
264 profile_); | |
265 DCHECK(service); | |
266 return service->RemoveFromList(setting, value); | |
267 #else | |
268 return false; | |
269 #endif | |
270 } | |
271 | |
272 bool PrefsUtil::IsPrefTypeURL(const std::string& pref_name) { | |
118 settings_private::PrefType pref_type = | 273 settings_private::PrefType pref_type = |
119 settings_private::PrefType::PREF_TYPE_NONE; | 274 settings_private::PrefType::PREF_TYPE_NONE; |
120 | 275 |
121 const TypedPrefMap keys = GetWhitelistedKeys(); | 276 const TypedPrefMap keys = GetWhitelistedKeys(); |
122 const auto& iter = keys.find(pref_name); | 277 const auto& iter = keys.find(pref_name); |
123 if (iter != keys.end()) | 278 if (iter != keys.end()) |
124 pref_type = iter->second; | 279 pref_type = iter->second; |
125 | 280 |
126 return pref_type == settings_private::PrefType::PREF_TYPE_URL; | 281 return pref_type == settings_private::PrefType::PREF_TYPE_URL; |
127 } | 282 } |
128 | 283 |
129 bool IsPrefUserModifiable(Profile* profile, const std::string& pref_name) { | 284 bool PrefsUtil::IsPrefUserModifiable(const std::string& pref_name) { |
130 if (pref_name != prefs::kBrowserGuestModeEnabled && | 285 if (pref_name != prefs::kBrowserGuestModeEnabled && |
131 pref_name != prefs::kBrowserAddPersonEnabled) { | 286 pref_name != prefs::kBrowserAddPersonEnabled) { |
132 return true; | 287 return true; |
133 } | 288 } |
134 | 289 |
135 PrefService* pref_service = profile->GetPrefs(); | 290 PrefService* pref_service = profile_->GetPrefs(); |
136 const PrefService::Preference* pref = | 291 const PrefService::Preference* pref = |
137 pref_service->FindPreference(pref_name.c_str()); | 292 pref_service->FindPreference(pref_name.c_str()); |
138 if (!pref || !pref->IsUserModifiable() || profile->IsSupervised()) | 293 if (!pref || !pref->IsUserModifiable() || profile_->IsSupervised()) |
139 return false; | 294 return false; |
140 | 295 |
141 return true; | 296 return true; |
142 } | 297 } |
143 | 298 |
144 PrefService* FindServiceForPref(Profile* profile, | 299 PrefService* PrefsUtil::FindServiceForPref(const std::string& pref_name) { |
145 const std::string& pref_name) { | 300 PrefService* user_prefs = profile_->GetPrefs(); |
146 PrefService* user_prefs = profile->GetPrefs(); | |
147 | 301 |
148 // Proxy is a peculiar case: on ChromeOS, settings exist in both user | 302 // Proxy is a peculiar case: on ChromeOS, settings exist in both user |
149 // prefs and local state, but chrome://settings should affect only user prefs. | 303 // prefs and local state, but chrome://settings should affect only user prefs. |
150 // Elsewhere the proxy settings are stored in local state. | 304 // Elsewhere the proxy settings are stored in local state. |
151 // See http://crbug.com/157147 | 305 // See http://crbug.com/157147 |
152 | 306 |
153 if (pref_name == prefs::kProxy) { | 307 if (pref_name == prefs::kProxy) { |
154 #if defined(OS_CHROMEOS) | 308 #if defined(OS_CHROMEOS) |
155 return user_prefs; | 309 return user_prefs; |
156 #else | 310 #else |
157 return g_browser_process->local_state(); | 311 return g_browser_process->local_state(); |
158 #endif | 312 #endif |
159 } | 313 } |
160 | 314 |
161 // Find which PrefService contains the given pref. Pref names should not | 315 // Find which PrefService contains the given pref. Pref names should not |
162 // be duplicated across services, however if they are, prefer the user's | 316 // be duplicated across services, however if they are, prefer the user's |
163 // prefs. | 317 // prefs. |
164 if (user_prefs->FindPreference(pref_name)) | 318 if (user_prefs->FindPreference(pref_name)) |
165 return user_prefs; | 319 return user_prefs; |
166 | 320 |
167 if (g_browser_process->local_state()->FindPreference(pref_name)) | 321 if (g_browser_process->local_state()->FindPreference(pref_name)) |
168 return g_browser_process->local_state(); | 322 return g_browser_process->local_state(); |
169 | 323 |
170 return user_prefs; | 324 return user_prefs; |
171 } | 325 } |
172 | 326 |
173 } // namespace prefs_util | 327 bool PrefsUtil::IsCrosSetting(const std::string& pref_name) { |
328 #if defined(OS_CHROMEOS) | |
329 return CrosSettings::Get()->IsCrosSettings(pref_name); | |
330 #else | |
331 return false; | |
332 #endif | |
333 } | |
174 | 334 |
175 } // namespace extensions | 335 } // namespace extensions |
OLD | NEW |