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 |