OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/extensions/extension_prefs.h" | |
6 | |
7 #include <iterator> | |
8 | |
9 #include "base/command_line.h" | |
10 #include "base/prefs/pref_notifier.h" | |
11 #include "base/prefs/pref_service.h" | |
12 #include "base/strings/string_number_conversions.h" | |
13 #include "base/strings/string_util.h" | |
14 #include "base/value_conversions.h" | |
15 #include "chrome/browser/extensions/api/content_settings/content_settings_store.
h" | |
16 #include "chrome/browser/extensions/api/preference/preference_api.h" | |
17 #include "chrome/browser/extensions/extension_pref_store.h" | |
18 #include "chrome/browser/extensions/extension_prefs_factory.h" | |
19 #include "components/user_prefs/pref_registry_syncable.h" | |
20 #include "extensions/browser/admin_policy.h" | |
21 #include "extensions/browser/app_sorting.h" | |
22 #include "extensions/browser/event_router.h" | |
23 #include "extensions/browser/pref_names.h" | |
24 #include "extensions/common/feature_switch.h" | |
25 #include "extensions/common/manifest.h" | |
26 #include "extensions/common/permissions/permission_set.h" | |
27 #include "extensions/common/permissions/permissions_info.h" | |
28 #include "extensions/common/url_pattern.h" | |
29 #include "extensions/common/user_script.h" | |
30 #include "grit/generated_resources.h" | |
31 #include "ui/base/l10n/l10n_util.h" | |
32 | |
33 using base::Value; | |
34 using base::DictionaryValue; | |
35 using base::ListValue; | |
36 | |
37 namespace extensions { | |
38 | |
39 namespace { | |
40 | |
41 // Additional preferences keys, which are not needed by external clients. | |
42 | |
43 // True if this extension is running. Note this preference stops getting updated | |
44 // during Chrome shutdown (and won't be updated on a browser crash) and so can | |
45 // be used at startup to determine whether the extension was running when Chrome | |
46 // was last terminated. | |
47 const char kPrefRunning[] = "running"; | |
48 | |
49 // Whether this extension had windows when it was last running. | |
50 const char kIsActive[] = "is_active"; | |
51 | |
52 // Where an extension was installed from. (see Manifest::Location) | |
53 const char kPrefLocation[] = "location"; | |
54 | |
55 // Enabled, disabled, killed, etc. (see Extension::State) | |
56 const char kPrefState[] = "state"; | |
57 | |
58 // The path to the current version's manifest file. | |
59 const char kPrefPath[] = "path"; | |
60 | |
61 // The dictionary containing the extension's manifest. | |
62 const char kPrefManifest[] = "manifest"; | |
63 | |
64 // The version number. | |
65 const char kPrefVersion[] = "manifest.version"; | |
66 | |
67 // Indicates whether an extension is blacklisted. | |
68 const char kPrefBlacklist[] = "blacklist"; | |
69 | |
70 // The count of how many times we prompted the user to acknowledge an | |
71 // extension. | |
72 const char kPrefAcknowledgePromptCount[] = "ack_prompt_count"; | |
73 | |
74 // Indicates whether the user has acknowledged various types of extensions. | |
75 const char kPrefExternalAcknowledged[] = "ack_external"; | |
76 const char kPrefBlacklistAcknowledged[] = "ack_blacklist"; | |
77 const char kPrefWipeoutAcknowledged[] = "ack_wiped"; | |
78 | |
79 // Indicates whether the external extension was installed during the first | |
80 // run of this profile. | |
81 const char kPrefExternalInstallFirstRun[] = "external_first_run"; | |
82 | |
83 // Indicates whether to show an install warning when the user enables. | |
84 const char kExtensionDidEscalatePermissions[] = "install_warning_on_enable"; | |
85 | |
86 // DO NOT USE, use kPrefDisableReasons instead. | |
87 // Indicates whether the extension was updated while it was disabled. | |
88 const char kDeprecatedPrefDisableReason[] = "disable_reason"; | |
89 | |
90 // A bitmask of all the reasons an extension is disabled. | |
91 const char kPrefDisableReasons[] = "disable_reasons"; | |
92 | |
93 // The key for a serialized Time value indicating the start of the day (from the | |
94 // server's perspective) an extension last included a "ping" parameter during | |
95 // its update check. | |
96 const char kLastPingDay[] = "lastpingday"; | |
97 | |
98 // Similar to kLastPingDay, but for "active" instead of "rollcall" pings. | |
99 const char kLastActivePingDay[] = "last_active_pingday"; | |
100 | |
101 // A bit we use to keep track of whether we need to do an "active" ping. | |
102 const char kActiveBit[] = "active_bit"; | |
103 | |
104 // Path for settings specific to blacklist update. | |
105 const char kExtensionsBlacklistUpdate[] = "extensions.blacklistupdate"; | |
106 | |
107 // Path for the delayed install info dictionary preference. The actual string | |
108 // value is a legacy artifact for when delayed installs only pertained to | |
109 // updates that were waiting for idle. | |
110 const char kDelayedInstallInfo[] = "idle_install_info"; | |
111 | |
112 // Reason why the extension's install was delayed. | |
113 const char kDelayedInstallReason[] = "delay_install_reason"; | |
114 | |
115 // Path for the suggested page ordinal of a delayed extension install. | |
116 const char kPrefSuggestedPageOrdinal[] = "suggested_page_ordinal"; | |
117 | |
118 // A preference that, if true, will allow this extension to run in incognito | |
119 // mode. | |
120 const char kPrefIncognitoEnabled[] = "incognito"; | |
121 | |
122 // A preference to control whether an extension is allowed to inject script in | |
123 // pages with file URLs. | |
124 const char kPrefAllowFileAccess[] = "newAllowFileAccess"; | |
125 // TODO(jstritar): As part of fixing http://crbug.com/91577, we revoked all | |
126 // extension file access by renaming the pref. We should eventually clean up | |
127 // the old flag and possibly go back to that name. | |
128 // const char kPrefAllowFileAccessOld[] = "allowFileAccess"; | |
129 | |
130 // A preference specifying if the user dragged the app on the NTP. | |
131 const char kPrefUserDraggedApp[] = "user_dragged_app_ntp"; | |
132 | |
133 // Preferences that hold which permissions the user has granted the extension. | |
134 // We explicitly keep track of these so that extensions can contain unknown | |
135 // permissions, for backwards compatibility reasons, and we can still prompt | |
136 // the user to accept them once recognized. We store the active permission | |
137 // permissions because they may differ from those defined in the manifest. | |
138 const char kPrefActivePermissions[] = "active_permissions"; | |
139 const char kPrefGrantedPermissions[] = "granted_permissions"; | |
140 | |
141 // The preference names for PermissionSet values. | |
142 const char kPrefAPIs[] = "api"; | |
143 const char kPrefManifestPermissions[] = "manifest_permissions"; | |
144 const char kPrefExplicitHosts[] = "explicit_host"; | |
145 const char kPrefScriptableHosts[] = "scriptable_host"; | |
146 | |
147 // The preference names for the old granted permissions scheme. | |
148 const char kPrefOldGrantedFullAccess[] = "granted_permissions.full"; | |
149 const char kPrefOldGrantedHosts[] = "granted_permissions.host"; | |
150 const char kPrefOldGrantedAPIs[] = "granted_permissions.api"; | |
151 | |
152 // A preference that indicates when an extension was installed. | |
153 const char kPrefInstallTime[] = "install_time"; | |
154 | |
155 // A preference which saves the creation flags for extensions. | |
156 const char kPrefCreationFlags[] = "creation_flags"; | |
157 | |
158 // A preference that indicates whether the extension was installed from the | |
159 // Chrome Web Store. | |
160 const char kPrefFromWebStore[] = "from_webstore"; | |
161 | |
162 // A preference that indicates whether the extension was installed from a | |
163 // mock App created from a bookmark. | |
164 const char kPrefFromBookmark[] = "from_bookmark"; | |
165 | |
166 // A preference that indicates whether the extension was installed as | |
167 // default apps. | |
168 const char kPrefWasInstalledByDefault[] = "was_installed_by_default"; | |
169 | |
170 // Key for Geometry Cache preference. | |
171 const char kPrefGeometryCache[] = "geometry_cache"; | |
172 | |
173 // A preference that indicates when an extension is last launched. | |
174 const char kPrefLastLaunchTime[] = "last_launch_time"; | |
175 | |
176 // A list of installed ids and a signature. | |
177 const char kInstallSignature[] = "extensions.install_signature"; | |
178 | |
179 // Provider of write access to a dictionary storing extension prefs. | |
180 class ScopedExtensionPrefUpdate : public DictionaryPrefUpdate { | |
181 public: | |
182 ScopedExtensionPrefUpdate(PrefService* service, | |
183 const std::string& extension_id) : | |
184 DictionaryPrefUpdate(service, pref_names::kExtensions), | |
185 extension_id_(extension_id) {} | |
186 | |
187 virtual ~ScopedExtensionPrefUpdate() { | |
188 } | |
189 | |
190 // DictionaryPrefUpdate overrides: | |
191 virtual base::DictionaryValue* Get() OVERRIDE { | |
192 base::DictionaryValue* dict = DictionaryPrefUpdate::Get(); | |
193 base::DictionaryValue* extension = NULL; | |
194 if (!dict->GetDictionary(extension_id_, &extension)) { | |
195 // Extension pref does not exist, create it. | |
196 extension = new base::DictionaryValue(); | |
197 dict->SetWithoutPathExpansion(extension_id_, extension); | |
198 } | |
199 return extension; | |
200 } | |
201 | |
202 private: | |
203 const std::string extension_id_; | |
204 | |
205 DISALLOW_COPY_AND_ASSIGN(ScopedExtensionPrefUpdate); | |
206 }; | |
207 | |
208 std::string JoinPrefs(const std::string& parent, const char* child) { | |
209 return parent + "." + child; | |
210 } | |
211 | |
212 // Checks if kPrefBlacklist is set to true in the base::DictionaryValue. | |
213 // Return false if the value is false or kPrefBlacklist does not exist. | |
214 // This is used to decide if an extension is blacklisted. | |
215 bool IsBlacklistBitSet(const base::DictionaryValue* ext) { | |
216 bool bool_value; | |
217 return ext->GetBoolean(kPrefBlacklist, &bool_value) && bool_value; | |
218 } | |
219 | |
220 } // namespace | |
221 | |
222 // | |
223 // TimeProvider | |
224 // | |
225 | |
226 ExtensionPrefs::TimeProvider::TimeProvider() { | |
227 } | |
228 | |
229 ExtensionPrefs::TimeProvider::~TimeProvider() { | |
230 } | |
231 | |
232 base::Time ExtensionPrefs::TimeProvider::GetCurrentTime() const { | |
233 return base::Time::Now(); | |
234 } | |
235 | |
236 // | |
237 // ScopedUpdate | |
238 // | |
239 template <typename T, base::Value::Type type_enum_value> | |
240 ExtensionPrefs::ScopedUpdate<T, type_enum_value>::ScopedUpdate( | |
241 ExtensionPrefs* prefs, | |
242 const std::string& extension_id, | |
243 const std::string& key) | |
244 : update_(prefs->pref_service(), pref_names::kExtensions), | |
245 extension_id_(extension_id), | |
246 key_(key) { | |
247 DCHECK(Extension::IdIsValid(extension_id_)); | |
248 } | |
249 | |
250 template <typename T, base::Value::Type type_enum_value> | |
251 ExtensionPrefs::ScopedUpdate<T, type_enum_value>::~ScopedUpdate() { | |
252 } | |
253 | |
254 template <typename T, base::Value::Type type_enum_value> | |
255 T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Get() { | |
256 base::DictionaryValue* dict = update_.Get(); | |
257 base::DictionaryValue* extension = NULL; | |
258 base::Value* key_value = NULL; | |
259 if (!dict->GetDictionary(extension_id_, &extension) || | |
260 !extension->Get(key_, &key_value)) { | |
261 return NULL; | |
262 } | |
263 return key_value->GetType() == type_enum_value ? | |
264 static_cast<T*>(key_value) : | |
265 NULL; | |
266 } | |
267 | |
268 template <typename T, base::Value::Type type_enum_value> | |
269 T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Create() { | |
270 base::DictionaryValue* dict = update_.Get(); | |
271 base::DictionaryValue* extension = NULL; | |
272 base::Value* key_value = NULL; | |
273 T* value_as_t = NULL; | |
274 if (!dict->GetDictionary(extension_id_, &extension)) { | |
275 extension = new base::DictionaryValue; | |
276 dict->SetWithoutPathExpansion(extension_id_, extension); | |
277 } | |
278 if (!extension->Get(key_, &key_value)) { | |
279 value_as_t = new T; | |
280 extension->SetWithoutPathExpansion(key_, value_as_t); | |
281 } else { | |
282 CHECK(key_value->GetType() == type_enum_value); | |
283 value_as_t = static_cast<T*>(key_value); | |
284 } | |
285 return value_as_t; | |
286 } | |
287 | |
288 // Explicit instantiations for Dictionary and List value types. | |
289 template class ExtensionPrefs::ScopedUpdate<base::DictionaryValue, | |
290 base::Value::TYPE_DICTIONARY>; | |
291 template class ExtensionPrefs::ScopedUpdate<base::ListValue, | |
292 base::Value::TYPE_LIST>; | |
293 | |
294 // | |
295 // ExtensionPrefs | |
296 // | |
297 | |
298 // static | |
299 ExtensionPrefs* ExtensionPrefs::Create( | |
300 PrefService* prefs, | |
301 const base::FilePath& root_dir, | |
302 ExtensionPrefValueMap* extension_pref_value_map, | |
303 scoped_ptr<AppSorting> app_sorting, | |
304 bool extensions_disabled) { | |
305 return ExtensionPrefs::Create(prefs, | |
306 root_dir, | |
307 extension_pref_value_map, | |
308 app_sorting.Pass(), | |
309 extensions_disabled, | |
310 make_scoped_ptr(new TimeProvider())); | |
311 } | |
312 | |
313 // static | |
314 ExtensionPrefs* ExtensionPrefs::Create( | |
315 PrefService* pref_service, | |
316 const base::FilePath& root_dir, | |
317 ExtensionPrefValueMap* extension_pref_value_map, | |
318 scoped_ptr<AppSorting> app_sorting, | |
319 bool extensions_disabled, | |
320 scoped_ptr<TimeProvider> time_provider) { | |
321 return new ExtensionPrefs(pref_service, | |
322 root_dir, | |
323 extension_pref_value_map, | |
324 app_sorting.Pass(), | |
325 time_provider.Pass(), | |
326 extensions_disabled); | |
327 } | |
328 | |
329 ExtensionPrefs::~ExtensionPrefs() { | |
330 } | |
331 | |
332 // static | |
333 ExtensionPrefs* ExtensionPrefs::Get(content::BrowserContext* context) { | |
334 return ExtensionPrefsFactory::GetInstance()->GetForBrowserContext(context); | |
335 } | |
336 | |
337 static base::FilePath::StringType MakePathRelative(const base::FilePath& parent, | |
338 const base::FilePath& child) { | |
339 if (!parent.IsParent(child)) | |
340 return child.value(); | |
341 | |
342 base::FilePath::StringType retval = child.value().substr( | |
343 parent.value().length()); | |
344 if (base::FilePath::IsSeparator(retval[0])) | |
345 return retval.substr(1); | |
346 else | |
347 return retval; | |
348 } | |
349 | |
350 void ExtensionPrefs::MakePathsRelative() { | |
351 const base::DictionaryValue* dict = | |
352 prefs_->GetDictionary(pref_names::kExtensions); | |
353 if (!dict || dict->empty()) | |
354 return; | |
355 | |
356 // Collect all extensions ids with absolute paths in |absolute_keys|. | |
357 std::set<std::string> absolute_keys; | |
358 for (base::DictionaryValue::Iterator i(*dict); !i.IsAtEnd(); i.Advance()) { | |
359 const base::DictionaryValue* extension_dict = NULL; | |
360 if (!i.value().GetAsDictionary(&extension_dict)) | |
361 continue; | |
362 int location_value; | |
363 if (extension_dict->GetInteger(kPrefLocation, &location_value) && | |
364 Manifest::IsUnpackedLocation( | |
365 static_cast<Manifest::Location>(location_value))) { | |
366 // Unpacked extensions can have absolute paths. | |
367 continue; | |
368 } | |
369 base::FilePath::StringType path_string; | |
370 if (!extension_dict->GetString(kPrefPath, &path_string)) | |
371 continue; | |
372 base::FilePath path(path_string); | |
373 if (path.IsAbsolute()) | |
374 absolute_keys.insert(i.key()); | |
375 } | |
376 if (absolute_keys.empty()) | |
377 return; | |
378 | |
379 // Fix these paths. | |
380 DictionaryPrefUpdate update(prefs_, pref_names::kExtensions); | |
381 base::DictionaryValue* update_dict = update.Get(); | |
382 for (std::set<std::string>::iterator i = absolute_keys.begin(); | |
383 i != absolute_keys.end(); ++i) { | |
384 base::DictionaryValue* extension_dict = NULL; | |
385 if (!update_dict->GetDictionaryWithoutPathExpansion(*i, &extension_dict)) { | |
386 NOTREACHED() << "Control should never reach here for extension " << *i; | |
387 continue; | |
388 } | |
389 base::FilePath::StringType path_string; | |
390 extension_dict->GetString(kPrefPath, &path_string); | |
391 base::FilePath path(path_string); | |
392 extension_dict->SetString(kPrefPath, | |
393 MakePathRelative(install_directory_, path)); | |
394 } | |
395 } | |
396 | |
397 const base::DictionaryValue* ExtensionPrefs::GetExtensionPref( | |
398 const std::string& extension_id) const { | |
399 const base::DictionaryValue* extensions = | |
400 prefs_->GetDictionary(pref_names::kExtensions); | |
401 const base::DictionaryValue* extension_dict = NULL; | |
402 if (!extensions || | |
403 !extensions->GetDictionary(extension_id, &extension_dict)) { | |
404 return NULL; | |
405 } | |
406 return extension_dict; | |
407 } | |
408 | |
409 void ExtensionPrefs::UpdateExtensionPref(const std::string& extension_id, | |
410 const std::string& key, | |
411 base::Value* data_value) { | |
412 if (!Extension::IdIsValid(extension_id)) { | |
413 NOTREACHED() << "Invalid extension_id " << extension_id; | |
414 return; | |
415 } | |
416 ScopedExtensionPrefUpdate update(prefs_, extension_id); | |
417 if (data_value) | |
418 update->Set(key, data_value); | |
419 else | |
420 update->Remove(key, NULL); | |
421 } | |
422 | |
423 void ExtensionPrefs::DeleteExtensionPrefs(const std::string& extension_id) { | |
424 extension_pref_value_map_->UnregisterExtension(extension_id); | |
425 content_settings_store_->UnregisterExtension(extension_id); | |
426 DictionaryPrefUpdate update(prefs_, pref_names::kExtensions); | |
427 base::DictionaryValue* dict = update.Get(); | |
428 dict->Remove(extension_id, NULL); | |
429 } | |
430 | |
431 bool ExtensionPrefs::ReadPrefAsBoolean(const std::string& extension_id, | |
432 const std::string& pref_key, | |
433 bool* out_value) const { | |
434 const base::DictionaryValue* ext = GetExtensionPref(extension_id); | |
435 if (!ext || !ext->GetBoolean(pref_key, out_value)) | |
436 return false; | |
437 | |
438 return true; | |
439 } | |
440 | |
441 bool ExtensionPrefs::ReadPrefAsInteger(const std::string& extension_id, | |
442 const std::string& pref_key, | |
443 int* out_value) const { | |
444 const base::DictionaryValue* ext = GetExtensionPref(extension_id); | |
445 if (!ext || !ext->GetInteger(pref_key, out_value)) | |
446 return false; | |
447 | |
448 return true; | |
449 } | |
450 | |
451 bool ExtensionPrefs::ReadPrefAsString(const std::string& extension_id, | |
452 const std::string& pref_key, | |
453 std::string* out_value) const { | |
454 const base::DictionaryValue* ext = GetExtensionPref(extension_id); | |
455 if (!ext || !ext->GetString(pref_key, out_value)) | |
456 return false; | |
457 | |
458 return true; | |
459 } | |
460 | |
461 bool ExtensionPrefs::ReadPrefAsList(const std::string& extension_id, | |
462 const std::string& pref_key, | |
463 const base::ListValue** out_value) const { | |
464 const base::DictionaryValue* ext = GetExtensionPref(extension_id); | |
465 const base::ListValue* out = NULL; | |
466 if (!ext || !ext->GetList(pref_key, &out)) | |
467 return false; | |
468 if (out_value) | |
469 *out_value = out; | |
470 | |
471 return true; | |
472 } | |
473 | |
474 bool ExtensionPrefs::ReadPrefAsDictionary( | |
475 const std::string& extension_id, | |
476 const std::string& pref_key, | |
477 const base::DictionaryValue** out_value) const { | |
478 const base::DictionaryValue* ext = GetExtensionPref(extension_id); | |
479 const base::DictionaryValue* out = NULL; | |
480 if (!ext || !ext->GetDictionary(pref_key, &out)) | |
481 return false; | |
482 if (out_value) | |
483 *out_value = out; | |
484 | |
485 return true; | |
486 } | |
487 | |
488 bool ExtensionPrefs::HasPrefForExtension( | |
489 const std::string& extension_id) const { | |
490 return GetExtensionPref(extension_id) != NULL; | |
491 } | |
492 | |
493 bool ExtensionPrefs::ReadPrefAsURLPatternSet(const std::string& extension_id, | |
494 const std::string& pref_key, | |
495 URLPatternSet* result, | |
496 int valid_schemes) { | |
497 const base::ListValue* value = NULL; | |
498 if (!ReadPrefAsList(extension_id, pref_key, &value)) | |
499 return false; | |
500 | |
501 bool allow_file_access = AllowFileAccess(extension_id); | |
502 return result->Populate(*value, valid_schemes, allow_file_access, NULL); | |
503 } | |
504 | |
505 void ExtensionPrefs::SetExtensionPrefURLPatternSet( | |
506 const std::string& extension_id, | |
507 const std::string& pref_key, | |
508 const URLPatternSet& new_value) { | |
509 UpdateExtensionPref(extension_id, pref_key, new_value.ToValue().release()); | |
510 } | |
511 | |
512 bool ExtensionPrefs::ReadPrefAsBooleanAndReturn( | |
513 const std::string& extension_id, | |
514 const std::string& pref_key) const { | |
515 bool out_value = false; | |
516 return ReadPrefAsBoolean(extension_id, pref_key, &out_value) && out_value; | |
517 } | |
518 | |
519 PermissionSet* ExtensionPrefs::ReadPrefAsPermissionSet( | |
520 const std::string& extension_id, | |
521 const std::string& pref_key) { | |
522 if (!GetExtensionPref(extension_id)) | |
523 return NULL; | |
524 | |
525 // Retrieve the API permissions. Please refer SetExtensionPrefPermissionSet() | |
526 // for api_values format. | |
527 APIPermissionSet apis; | |
528 const base::ListValue* api_values = NULL; | |
529 std::string api_pref = JoinPrefs(pref_key, kPrefAPIs); | |
530 if (ReadPrefAsList(extension_id, api_pref, &api_values)) { | |
531 APIPermissionSet::ParseFromJSON(api_values, | |
532 APIPermissionSet::kAllowInternalPermissions, | |
533 &apis, NULL, NULL); | |
534 } | |
535 | |
536 // Retrieve the Manifest Keys permissions. Please refer to | |
537 // |SetExtensionPrefPermissionSet| for manifest_permissions_values format. | |
538 ManifestPermissionSet manifest_permissions; | |
539 const base::ListValue* manifest_permissions_values = NULL; | |
540 std::string manifest_permission_pref = | |
541 JoinPrefs(pref_key, kPrefManifestPermissions); | |
542 if (ReadPrefAsList(extension_id, manifest_permission_pref, | |
543 &manifest_permissions_values)) { | |
544 ManifestPermissionSet::ParseFromJSON( | |
545 manifest_permissions_values, &manifest_permissions, NULL, NULL); | |
546 } | |
547 | |
548 // Retrieve the explicit host permissions. | |
549 URLPatternSet explicit_hosts; | |
550 ReadPrefAsURLPatternSet( | |
551 extension_id, JoinPrefs(pref_key, kPrefExplicitHosts), | |
552 &explicit_hosts, Extension::kValidHostPermissionSchemes); | |
553 | |
554 // Retrieve the scriptable host permissions. | |
555 URLPatternSet scriptable_hosts; | |
556 ReadPrefAsURLPatternSet( | |
557 extension_id, JoinPrefs(pref_key, kPrefScriptableHosts), | |
558 &scriptable_hosts, UserScript::ValidUserScriptSchemes()); | |
559 | |
560 return new PermissionSet( | |
561 apis, manifest_permissions, explicit_hosts, scriptable_hosts); | |
562 } | |
563 | |
564 // Set the API or Manifest permissions. | |
565 // The format of api_values is: | |
566 // [ "permission_name1", // permissions do not support detail. | |
567 // "permission_name2", | |
568 // {"permission_name3": value }, | |
569 // // permission supports detail, permission detail will be stored in value. | |
570 // ... | |
571 // ] | |
572 template<typename T> | |
573 static base::ListValue* CreatePermissionList(const T& permissions) { | |
574 base::ListValue* values = new base::ListValue(); | |
575 for (typename T::const_iterator i = permissions.begin(); | |
576 i != permissions.end(); ++i) { | |
577 scoped_ptr<base::Value> detail(i->ToValue()); | |
578 if (detail) { | |
579 base::DictionaryValue* tmp = new base::DictionaryValue(); | |
580 tmp->Set(i->name(), detail.release()); | |
581 values->Append(tmp); | |
582 } else { | |
583 values->Append(new base::StringValue(i->name())); | |
584 } | |
585 } | |
586 return values; | |
587 } | |
588 | |
589 void ExtensionPrefs::SetExtensionPrefPermissionSet( | |
590 const std::string& extension_id, | |
591 const std::string& pref_key, | |
592 const PermissionSet* new_value) { | |
593 std::string api_pref = JoinPrefs(pref_key, kPrefAPIs); | |
594 base::ListValue* api_values = CreatePermissionList(new_value->apis()); | |
595 UpdateExtensionPref(extension_id, api_pref, api_values); | |
596 | |
597 std::string manifest_permissions_pref = | |
598 JoinPrefs(pref_key, kPrefManifestPermissions); | |
599 base::ListValue* manifest_permissions_values = CreatePermissionList( | |
600 new_value->manifest_permissions()); | |
601 UpdateExtensionPref(extension_id, | |
602 manifest_permissions_pref, | |
603 manifest_permissions_values); | |
604 | |
605 // Set the explicit host permissions. | |
606 if (!new_value->explicit_hosts().is_empty()) { | |
607 SetExtensionPrefURLPatternSet(extension_id, | |
608 JoinPrefs(pref_key, kPrefExplicitHosts), | |
609 new_value->explicit_hosts()); | |
610 } | |
611 | |
612 // Set the scriptable host permissions. | |
613 if (!new_value->scriptable_hosts().is_empty()) { | |
614 SetExtensionPrefURLPatternSet(extension_id, | |
615 JoinPrefs(pref_key, kPrefScriptableHosts), | |
616 new_value->scriptable_hosts()); | |
617 } | |
618 } | |
619 | |
620 int ExtensionPrefs::IncrementAcknowledgePromptCount( | |
621 const std::string& extension_id) { | |
622 int count = 0; | |
623 ReadPrefAsInteger(extension_id, kPrefAcknowledgePromptCount, &count); | |
624 ++count; | |
625 UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, | |
626 new base::FundamentalValue(count)); | |
627 return count; | |
628 } | |
629 | |
630 bool ExtensionPrefs::IsExternalExtensionAcknowledged( | |
631 const std::string& extension_id) { | |
632 return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalAcknowledged); | |
633 } | |
634 | |
635 void ExtensionPrefs::AcknowledgeExternalExtension( | |
636 const std::string& extension_id) { | |
637 DCHECK(Extension::IdIsValid(extension_id)); | |
638 UpdateExtensionPref(extension_id, kPrefExternalAcknowledged, | |
639 new base::FundamentalValue(true)); | |
640 UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL); | |
641 } | |
642 | |
643 bool ExtensionPrefs::IsBlacklistedExtensionAcknowledged( | |
644 const std::string& extension_id) { | |
645 return ReadPrefAsBooleanAndReturn(extension_id, kPrefBlacklistAcknowledged); | |
646 } | |
647 | |
648 void ExtensionPrefs::AcknowledgeBlacklistedExtension( | |
649 const std::string& extension_id) { | |
650 DCHECK(Extension::IdIsValid(extension_id)); | |
651 UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged, | |
652 new base::FundamentalValue(true)); | |
653 UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL); | |
654 } | |
655 | |
656 bool ExtensionPrefs::IsExternalInstallFirstRun( | |
657 const std::string& extension_id) { | |
658 return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalInstallFirstRun); | |
659 } | |
660 | |
661 void ExtensionPrefs::SetExternalInstallFirstRun( | |
662 const std::string& extension_id) { | |
663 DCHECK(Extension::IdIsValid(extension_id)); | |
664 UpdateExtensionPref(extension_id, kPrefExternalInstallFirstRun, | |
665 new base::FundamentalValue(true)); | |
666 } | |
667 | |
668 bool ExtensionPrefs::HasWipeoutBeenAcknowledged( | |
669 const std::string& extension_id) { | |
670 return ReadPrefAsBooleanAndReturn(extension_id, kPrefWipeoutAcknowledged); | |
671 } | |
672 | |
673 void ExtensionPrefs::SetWipeoutAcknowledged( | |
674 const std::string& extension_id, | |
675 bool value) { | |
676 UpdateExtensionPref(extension_id, kPrefWipeoutAcknowledged, | |
677 value ? base::Value::CreateBooleanValue(value) : NULL); | |
678 } | |
679 | |
680 bool ExtensionPrefs::SetAlertSystemFirstRun() { | |
681 if (prefs_->GetBoolean(pref_names::kAlertsInitialized)) { | |
682 return true; | |
683 } | |
684 prefs_->SetBoolean(pref_names::kAlertsInitialized, true); | |
685 return false; | |
686 } | |
687 | |
688 bool ExtensionPrefs::ExtensionsBlacklistedByDefault() const { | |
689 return admin_policy::BlacklistedByDefault( | |
690 prefs_->GetList(pref_names::kInstallDenyList)); | |
691 } | |
692 | |
693 bool ExtensionPrefs::DidExtensionEscalatePermissions( | |
694 const std::string& extension_id) { | |
695 return ReadPrefAsBooleanAndReturn(extension_id, | |
696 kExtensionDidEscalatePermissions); | |
697 } | |
698 | |
699 void ExtensionPrefs::SetDidExtensionEscalatePermissions( | |
700 const Extension* extension, bool did_escalate) { | |
701 UpdateExtensionPref(extension->id(), kExtensionDidEscalatePermissions, | |
702 new base::FundamentalValue(did_escalate)); | |
703 } | |
704 | |
705 int ExtensionPrefs::GetDisableReasons(const std::string& extension_id) const { | |
706 int value = -1; | |
707 if (ReadPrefAsInteger(extension_id, kPrefDisableReasons, &value) && | |
708 value >= 0) { | |
709 return value; | |
710 } | |
711 return Extension::DISABLE_NONE; | |
712 } | |
713 | |
714 void ExtensionPrefs::AddDisableReason(const std::string& extension_id, | |
715 Extension::DisableReason disable_reason) { | |
716 int new_value = GetDisableReasons(extension_id) | | |
717 static_cast<int>(disable_reason); | |
718 UpdateExtensionPref(extension_id, kPrefDisableReasons, | |
719 new base::FundamentalValue(new_value)); | |
720 } | |
721 | |
722 void ExtensionPrefs::RemoveDisableReason( | |
723 const std::string& extension_id, | |
724 Extension::DisableReason disable_reason) { | |
725 int new_value = GetDisableReasons(extension_id) & | |
726 ~static_cast<int>(disable_reason); | |
727 if (new_value == Extension::DISABLE_NONE) { | |
728 UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL); | |
729 } else { | |
730 UpdateExtensionPref(extension_id, kPrefDisableReasons, | |
731 new base::FundamentalValue(new_value)); | |
732 } | |
733 } | |
734 | |
735 void ExtensionPrefs::ClearDisableReasons(const std::string& extension_id) { | |
736 UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL); | |
737 } | |
738 | |
739 std::set<std::string> ExtensionPrefs::GetBlacklistedExtensions() { | |
740 std::set<std::string> ids; | |
741 | |
742 const base::DictionaryValue* extensions = | |
743 prefs_->GetDictionary(pref_names::kExtensions); | |
744 if (!extensions) | |
745 return ids; | |
746 | |
747 for (base::DictionaryValue::Iterator it(*extensions); | |
748 !it.IsAtEnd(); it.Advance()) { | |
749 if (!it.value().IsType(base::Value::TYPE_DICTIONARY)) { | |
750 NOTREACHED() << "Invalid pref for extension " << it.key(); | |
751 continue; | |
752 } | |
753 if (IsBlacklistBitSet( | |
754 static_cast<const base::DictionaryValue*>(&it.value()))) { | |
755 ids.insert(it.key()); | |
756 } | |
757 } | |
758 | |
759 return ids; | |
760 } | |
761 | |
762 void ExtensionPrefs::SetExtensionBlacklisted(const std::string& extension_id, | |
763 bool is_blacklisted) { | |
764 bool currently_blacklisted = IsExtensionBlacklisted(extension_id); | |
765 if (is_blacklisted == currently_blacklisted) { | |
766 NOTREACHED() << extension_id << " is " << | |
767 (currently_blacklisted ? "already" : "not") << | |
768 " blacklisted"; | |
769 return; | |
770 } | |
771 | |
772 // Always make sure the "acknowledged" bit is cleared since the blacklist bit | |
773 // is changing. | |
774 UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged, NULL); | |
775 | |
776 if (is_blacklisted) { | |
777 UpdateExtensionPref(extension_id, | |
778 kPrefBlacklist, | |
779 new base::FundamentalValue(true)); | |
780 } else { | |
781 UpdateExtensionPref(extension_id, kPrefBlacklist, NULL); | |
782 const base::DictionaryValue* dict = GetExtensionPref(extension_id); | |
783 if (dict && dict->empty()) | |
784 DeleteExtensionPrefs(extension_id); | |
785 } | |
786 } | |
787 | |
788 bool ExtensionPrefs::IsExtensionBlacklisted(const std::string& id) const { | |
789 const base::DictionaryValue* ext_prefs = GetExtensionPref(id); | |
790 return ext_prefs && IsBlacklistBitSet(ext_prefs); | |
791 } | |
792 | |
793 namespace { | |
794 | |
795 // Serializes |time| as a string value mapped to |key| in |dictionary|. | |
796 void SaveTime(base::DictionaryValue* dictionary, | |
797 const char* key, | |
798 const base::Time& time) { | |
799 if (!dictionary) | |
800 return; | |
801 std::string string_value = base::Int64ToString(time.ToInternalValue()); | |
802 dictionary->SetString(key, string_value); | |
803 } | |
804 | |
805 // The opposite of SaveTime. If |key| is not found, this returns an empty Time | |
806 // (is_null() will return true). | |
807 base::Time ReadTime(const base::DictionaryValue* dictionary, const char* key) { | |
808 if (!dictionary) | |
809 return base::Time(); | |
810 std::string string_value; | |
811 int64 value; | |
812 if (dictionary->GetString(key, &string_value)) { | |
813 if (base::StringToInt64(string_value, &value)) { | |
814 return base::Time::FromInternalValue(value); | |
815 } | |
816 } | |
817 return base::Time(); | |
818 } | |
819 | |
820 } // namespace | |
821 | |
822 base::Time ExtensionPrefs::LastPingDay(const std::string& extension_id) const { | |
823 DCHECK(Extension::IdIsValid(extension_id)); | |
824 return ReadTime(GetExtensionPref(extension_id), kLastPingDay); | |
825 } | |
826 | |
827 void ExtensionPrefs::SetLastPingDay(const std::string& extension_id, | |
828 const base::Time& time) { | |
829 DCHECK(Extension::IdIsValid(extension_id)); | |
830 ScopedExtensionPrefUpdate update(prefs_, extension_id); | |
831 SaveTime(update.Get(), kLastPingDay, time); | |
832 } | |
833 | |
834 base::Time ExtensionPrefs::BlacklistLastPingDay() const { | |
835 return ReadTime(prefs_->GetDictionary(kExtensionsBlacklistUpdate), | |
836 kLastPingDay); | |
837 } | |
838 | |
839 void ExtensionPrefs::SetBlacklistLastPingDay(const base::Time& time) { | |
840 DictionaryPrefUpdate update(prefs_, kExtensionsBlacklistUpdate); | |
841 SaveTime(update.Get(), kLastPingDay, time); | |
842 } | |
843 | |
844 base::Time ExtensionPrefs::LastActivePingDay(const std::string& extension_id) { | |
845 DCHECK(Extension::IdIsValid(extension_id)); | |
846 return ReadTime(GetExtensionPref(extension_id), kLastActivePingDay); | |
847 } | |
848 | |
849 void ExtensionPrefs::SetLastActivePingDay(const std::string& extension_id, | |
850 const base::Time& time) { | |
851 DCHECK(Extension::IdIsValid(extension_id)); | |
852 ScopedExtensionPrefUpdate update(prefs_, extension_id); | |
853 SaveTime(update.Get(), kLastActivePingDay, time); | |
854 } | |
855 | |
856 bool ExtensionPrefs::GetActiveBit(const std::string& extension_id) { | |
857 const base::DictionaryValue* dictionary = GetExtensionPref(extension_id); | |
858 bool result = false; | |
859 if (dictionary && dictionary->GetBoolean(kActiveBit, &result)) | |
860 return result; | |
861 return false; | |
862 } | |
863 | |
864 void ExtensionPrefs::SetActiveBit(const std::string& extension_id, | |
865 bool active) { | |
866 UpdateExtensionPref(extension_id, kActiveBit, | |
867 new base::FundamentalValue(active)); | |
868 } | |
869 | |
870 void ExtensionPrefs::MigratePermissions(const ExtensionIdList& extension_ids) { | |
871 PermissionsInfo* info = PermissionsInfo::GetInstance(); | |
872 for (ExtensionIdList::const_iterator ext_id = | |
873 extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) { | |
874 | |
875 // An extension's granted permissions need to be migrated if the | |
876 // full_access bit is present. This bit was always present in the previous | |
877 // scheme and is never present now. | |
878 bool full_access; | |
879 const base::DictionaryValue* ext = GetExtensionPref(*ext_id); | |
880 if (!ext || !ext->GetBoolean(kPrefOldGrantedFullAccess, &full_access)) | |
881 continue; | |
882 | |
883 // Remove the full access bit (empty list will get trimmed). | |
884 UpdateExtensionPref( | |
885 *ext_id, kPrefOldGrantedFullAccess, new base::ListValue()); | |
886 | |
887 // Add the plugin permission if the full access bit was set. | |
888 if (full_access) { | |
889 const base::ListValue* apis = NULL; | |
890 base::ListValue* new_apis = NULL; | |
891 | |
892 std::string granted_apis = | |
893 JoinPrefs(kPrefGrantedPermissions, kPrefAPIs); | |
894 if (ext->GetList(kPrefOldGrantedAPIs, &apis)) | |
895 new_apis = apis->DeepCopy(); | |
896 else | |
897 new_apis = new base::ListValue(); | |
898 | |
899 std::string plugin_name = info->GetByID( | |
900 APIPermission::kPlugin)->name(); | |
901 new_apis->Append(new base::StringValue(plugin_name)); | |
902 UpdateExtensionPref(*ext_id, granted_apis, new_apis); | |
903 } | |
904 | |
905 // The granted permissions originally only held the effective hosts, | |
906 // which are a combination of host and user script host permissions. | |
907 // We now maintain these lists separately. For migration purposes, it | |
908 // does not matter how we treat the old effective hosts as long as the | |
909 // new effective hosts will be the same, so we move them to explicit | |
910 // host permissions. | |
911 const base::ListValue* hosts = NULL; | |
912 std::string explicit_hosts = | |
913 JoinPrefs(kPrefGrantedPermissions, kPrefExplicitHosts); | |
914 if (ext->GetList(kPrefOldGrantedHosts, &hosts)) { | |
915 UpdateExtensionPref( | |
916 *ext_id, explicit_hosts, hosts->DeepCopy()); | |
917 | |
918 // We can get rid of the old one by setting it to an empty list. | |
919 UpdateExtensionPref(*ext_id, kPrefOldGrantedHosts, new base::ListValue()); | |
920 } | |
921 } | |
922 } | |
923 | |
924 void ExtensionPrefs::MigrateDisableReasons( | |
925 const ExtensionIdList& extension_ids) { | |
926 for (ExtensionIdList::const_iterator ext_id = | |
927 extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) { | |
928 int value = -1; | |
929 if (ReadPrefAsInteger(*ext_id, kDeprecatedPrefDisableReason, &value)) { | |
930 int new_value = Extension::DISABLE_NONE; | |
931 switch (value) { | |
932 case Extension::DEPRECATED_DISABLE_USER_ACTION: | |
933 new_value = Extension::DISABLE_USER_ACTION; | |
934 break; | |
935 case Extension::DEPRECATED_DISABLE_PERMISSIONS_INCREASE: | |
936 new_value = Extension::DISABLE_PERMISSIONS_INCREASE; | |
937 break; | |
938 case Extension::DEPRECATED_DISABLE_RELOAD: | |
939 new_value = Extension::DISABLE_RELOAD; | |
940 break; | |
941 } | |
942 | |
943 UpdateExtensionPref(*ext_id, kPrefDisableReasons, | |
944 new base::FundamentalValue(new_value)); | |
945 // Remove the old disable reason. | |
946 UpdateExtensionPref(*ext_id, kDeprecatedPrefDisableReason, NULL); | |
947 } | |
948 } | |
949 } | |
950 | |
951 PermissionSet* ExtensionPrefs::GetGrantedPermissions( | |
952 const std::string& extension_id) { | |
953 CHECK(Extension::IdIsValid(extension_id)); | |
954 return ReadPrefAsPermissionSet(extension_id, kPrefGrantedPermissions); | |
955 } | |
956 | |
957 void ExtensionPrefs::AddGrantedPermissions( | |
958 const std::string& extension_id, | |
959 const PermissionSet* permissions) { | |
960 CHECK(Extension::IdIsValid(extension_id)); | |
961 | |
962 scoped_refptr<PermissionSet> granted_permissions( | |
963 GetGrantedPermissions(extension_id)); | |
964 | |
965 // The new granted permissions are the union of the already granted | |
966 // permissions and the newly granted permissions. | |
967 scoped_refptr<PermissionSet> new_perms( | |
968 PermissionSet::CreateUnion( | |
969 permissions, granted_permissions.get())); | |
970 | |
971 SetExtensionPrefPermissionSet( | |
972 extension_id, kPrefGrantedPermissions, new_perms.get()); | |
973 } | |
974 | |
975 void ExtensionPrefs::RemoveGrantedPermissions( | |
976 const std::string& extension_id, | |
977 const PermissionSet* permissions) { | |
978 CHECK(Extension::IdIsValid(extension_id)); | |
979 | |
980 scoped_refptr<PermissionSet> granted_permissions( | |
981 GetGrantedPermissions(extension_id)); | |
982 | |
983 // The new granted permissions are the difference of the already granted | |
984 // permissions and the newly ungranted permissions. | |
985 scoped_refptr<PermissionSet> new_perms( | |
986 PermissionSet::CreateDifference( | |
987 granted_permissions.get(), permissions)); | |
988 | |
989 SetExtensionPrefPermissionSet( | |
990 extension_id, kPrefGrantedPermissions, new_perms.get()); | |
991 } | |
992 | |
993 PermissionSet* ExtensionPrefs::GetActivePermissions( | |
994 const std::string& extension_id) { | |
995 CHECK(Extension::IdIsValid(extension_id)); | |
996 return ReadPrefAsPermissionSet(extension_id, kPrefActivePermissions); | |
997 } | |
998 | |
999 void ExtensionPrefs::SetActivePermissions( | |
1000 const std::string& extension_id, | |
1001 const PermissionSet* permissions) { | |
1002 SetExtensionPrefPermissionSet( | |
1003 extension_id, kPrefActivePermissions, permissions); | |
1004 } | |
1005 | |
1006 void ExtensionPrefs::SetExtensionRunning(const std::string& extension_id, | |
1007 bool is_running) { | |
1008 base::Value* value = new base::FundamentalValue(is_running); | |
1009 UpdateExtensionPref(extension_id, kPrefRunning, value); | |
1010 } | |
1011 | |
1012 bool ExtensionPrefs::IsExtensionRunning(const std::string& extension_id) { | |
1013 const base::DictionaryValue* extension = GetExtensionPref(extension_id); | |
1014 if (!extension) | |
1015 return false; | |
1016 bool running = false; | |
1017 extension->GetBoolean(kPrefRunning, &running); | |
1018 return running; | |
1019 } | |
1020 | |
1021 void ExtensionPrefs::SetIsActive(const std::string& extension_id, | |
1022 bool is_active) { | |
1023 base::Value* value = new base::FundamentalValue(is_active); | |
1024 UpdateExtensionPref(extension_id, kIsActive, value); | |
1025 } | |
1026 | |
1027 bool ExtensionPrefs::IsActive(const std::string& extension_id) { | |
1028 const base::DictionaryValue* extension = GetExtensionPref(extension_id); | |
1029 if (!extension) | |
1030 return false; | |
1031 bool is_active = false; | |
1032 extension->GetBoolean(kIsActive, &is_active); | |
1033 return is_active; | |
1034 } | |
1035 | |
1036 bool ExtensionPrefs::IsIncognitoEnabled(const std::string& extension_id) const { | |
1037 return ReadPrefAsBooleanAndReturn(extension_id, kPrefIncognitoEnabled); | |
1038 } | |
1039 | |
1040 void ExtensionPrefs::SetIsIncognitoEnabled(const std::string& extension_id, | |
1041 bool enabled) { | |
1042 UpdateExtensionPref(extension_id, kPrefIncognitoEnabled, | |
1043 new base::FundamentalValue(enabled)); | |
1044 } | |
1045 | |
1046 bool ExtensionPrefs::AllowFileAccess(const std::string& extension_id) const { | |
1047 return ReadPrefAsBooleanAndReturn(extension_id, kPrefAllowFileAccess); | |
1048 } | |
1049 | |
1050 void ExtensionPrefs::SetAllowFileAccess(const std::string& extension_id, | |
1051 bool allow) { | |
1052 UpdateExtensionPref(extension_id, kPrefAllowFileAccess, | |
1053 new base::FundamentalValue(allow)); | |
1054 } | |
1055 | |
1056 bool ExtensionPrefs::HasAllowFileAccessSetting( | |
1057 const std::string& extension_id) const { | |
1058 const base::DictionaryValue* ext = GetExtensionPref(extension_id); | |
1059 return ext && ext->HasKey(kPrefAllowFileAccess); | |
1060 } | |
1061 | |
1062 bool ExtensionPrefs::DoesExtensionHaveState( | |
1063 const std::string& id, Extension::State check_state) const { | |
1064 const base::DictionaryValue* extension = GetExtensionPref(id); | |
1065 int state = -1; | |
1066 if (!extension || !extension->GetInteger(kPrefState, &state)) | |
1067 return false; | |
1068 | |
1069 if (state < 0 || state >= Extension::NUM_STATES) { | |
1070 LOG(ERROR) << "Bad pref 'state' for extension '" << id << "'"; | |
1071 return false; | |
1072 } | |
1073 | |
1074 return state == check_state; | |
1075 } | |
1076 | |
1077 bool ExtensionPrefs::IsExternalExtensionUninstalled( | |
1078 const std::string& id) const { | |
1079 return DoesExtensionHaveState(id, Extension::EXTERNAL_EXTENSION_UNINSTALLED); | |
1080 } | |
1081 | |
1082 bool ExtensionPrefs::IsExtensionDisabled( | |
1083 const std::string& id) const { | |
1084 return DoesExtensionHaveState(id, Extension::DISABLED); | |
1085 } | |
1086 | |
1087 ExtensionIdList ExtensionPrefs::GetToolbarOrder() { | |
1088 ExtensionIdList id_list_out; | |
1089 GetUserExtensionPrefIntoContainer(pref_names::kToolbar, &id_list_out); | |
1090 return id_list_out; | |
1091 } | |
1092 | |
1093 void ExtensionPrefs::SetToolbarOrder(const ExtensionIdList& extension_ids) { | |
1094 SetExtensionPrefFromContainer(pref_names::kToolbar, extension_ids); | |
1095 } | |
1096 | |
1097 bool ExtensionPrefs::GetKnownDisabled(ExtensionIdSet* id_set_out) { | |
1098 return GetUserExtensionPrefIntoContainer(pref_names::kKnownDisabled, | |
1099 id_set_out); | |
1100 } | |
1101 | |
1102 void ExtensionPrefs::SetKnownDisabled(const ExtensionIdSet& extension_ids) { | |
1103 SetExtensionPrefFromContainer(pref_names::kKnownDisabled, extension_ids); | |
1104 } | |
1105 | |
1106 void ExtensionPrefs::OnExtensionInstalled( | |
1107 const Extension* extension, | |
1108 Extension::State initial_state, | |
1109 bool blacklisted_for_malware, | |
1110 const syncer::StringOrdinal& page_ordinal) { | |
1111 ScopedExtensionPrefUpdate update(prefs_, extension->id()); | |
1112 base::DictionaryValue* extension_dict = update.Get(); | |
1113 const base::Time install_time = time_provider_->GetCurrentTime(); | |
1114 PopulateExtensionInfoPrefs(extension, install_time, initial_state, | |
1115 blacklisted_for_malware, extension_dict); | |
1116 FinishExtensionInfoPrefs(extension->id(), install_time, | |
1117 extension->RequiresSortOrdinal(), | |
1118 page_ordinal, extension_dict); | |
1119 } | |
1120 | |
1121 void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id, | |
1122 const Manifest::Location& location, | |
1123 bool external_uninstall) { | |
1124 app_sorting_->ClearOrdinals(extension_id); | |
1125 | |
1126 // For external extensions, we save a preference reminding ourself not to try | |
1127 // and install the extension anymore (except when |external_uninstall| is | |
1128 // true, which signifies that the registry key was deleted or the pref file | |
1129 // no longer lists the extension). | |
1130 if (!external_uninstall && Manifest::IsExternalLocation(location)) { | |
1131 UpdateExtensionPref(extension_id, kPrefState, | |
1132 new base::FundamentalValue( | |
1133 Extension::EXTERNAL_EXTENSION_UNINSTALLED)); | |
1134 extension_pref_value_map_->SetExtensionState(extension_id, false); | |
1135 content_settings_store_->SetExtensionState(extension_id, false); | |
1136 } else { | |
1137 DeleteExtensionPrefs(extension_id); | |
1138 } | |
1139 } | |
1140 | |
1141 void ExtensionPrefs::SetExtensionState(const std::string& extension_id, | |
1142 Extension::State state) { | |
1143 UpdateExtensionPref(extension_id, kPrefState, | |
1144 new base::FundamentalValue(state)); | |
1145 bool enabled = (state == Extension::ENABLED); | |
1146 extension_pref_value_map_->SetExtensionState(extension_id, enabled); | |
1147 content_settings_store_->SetExtensionState(extension_id, enabled); | |
1148 } | |
1149 | |
1150 std::string ExtensionPrefs::GetVersionString(const std::string& extension_id) { | |
1151 const base::DictionaryValue* extension = GetExtensionPref(extension_id); | |
1152 if (!extension) | |
1153 return std::string(); | |
1154 | |
1155 std::string version; | |
1156 extension->GetString(kPrefVersion, &version); | |
1157 | |
1158 return version; | |
1159 } | |
1160 | |
1161 void ExtensionPrefs::UpdateManifest(const Extension* extension) { | |
1162 if (!Manifest::IsUnpackedLocation(extension->location())) { | |
1163 const base::DictionaryValue* extension_dict = | |
1164 GetExtensionPref(extension->id()); | |
1165 if (!extension_dict) | |
1166 return; | |
1167 const base::DictionaryValue* old_manifest = NULL; | |
1168 bool update_required = | |
1169 !extension_dict->GetDictionary(kPrefManifest, &old_manifest) || | |
1170 !extension->manifest()->value()->Equals(old_manifest); | |
1171 if (update_required) { | |
1172 UpdateExtensionPref(extension->id(), kPrefManifest, | |
1173 extension->manifest()->value()->DeepCopy()); | |
1174 } | |
1175 } | |
1176 } | |
1177 | |
1178 base::FilePath ExtensionPrefs::GetExtensionPath( | |
1179 const std::string& extension_id) { | |
1180 const base::DictionaryValue* dict = GetExtensionPref(extension_id); | |
1181 if (!dict) | |
1182 return base::FilePath(); | |
1183 | |
1184 std::string path; | |
1185 if (!dict->GetString(kPrefPath, &path)) | |
1186 return base::FilePath(); | |
1187 | |
1188 return install_directory_.Append(base::FilePath::FromUTF8Unsafe(path)); | |
1189 } | |
1190 | |
1191 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledInfoHelper( | |
1192 const std::string& extension_id, | |
1193 const base::DictionaryValue* extension) const { | |
1194 int location_value; | |
1195 if (!extension->GetInteger(kPrefLocation, &location_value)) | |
1196 return scoped_ptr<ExtensionInfo>(); | |
1197 | |
1198 base::FilePath::StringType path; | |
1199 if (!extension->GetString(kPrefPath, &path)) | |
1200 return scoped_ptr<ExtensionInfo>(); | |
1201 | |
1202 // Make path absolute. Unpacked extensions will already have absolute paths, | |
1203 // otherwise make it so. | |
1204 Manifest::Location location = static_cast<Manifest::Location>(location_value); | |
1205 if (!Manifest::IsUnpackedLocation(location)) { | |
1206 DCHECK(location == Manifest::COMPONENT || | |
1207 !base::FilePath(path).IsAbsolute()); | |
1208 path = install_directory_.Append(path).value(); | |
1209 } | |
1210 | |
1211 // Only the following extension types have data saved in the preferences. | |
1212 if (location != Manifest::INTERNAL && | |
1213 !Manifest::IsUnpackedLocation(location) && | |
1214 !Manifest::IsExternalLocation(location)) { | |
1215 NOTREACHED(); | |
1216 return scoped_ptr<ExtensionInfo>(); | |
1217 } | |
1218 | |
1219 const base::DictionaryValue* manifest = NULL; | |
1220 if (!Manifest::IsUnpackedLocation(location) && | |
1221 !extension->GetDictionary(kPrefManifest, &manifest)) { | |
1222 LOG(WARNING) << "Missing manifest for extension " << extension_id; | |
1223 // Just a warning for now. | |
1224 } | |
1225 | |
1226 return scoped_ptr<ExtensionInfo>(new ExtensionInfo( | |
1227 manifest, extension_id, base::FilePath(path), location)); | |
1228 } | |
1229 | |
1230 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledExtensionInfo( | |
1231 const std::string& extension_id) const { | |
1232 const base::DictionaryValue* ext = NULL; | |
1233 const base::DictionaryValue* extensions = | |
1234 prefs_->GetDictionary(pref_names::kExtensions); | |
1235 if (!extensions || | |
1236 !extensions->GetDictionaryWithoutPathExpansion(extension_id, &ext)) | |
1237 return scoped_ptr<ExtensionInfo>(); | |
1238 int state_value; | |
1239 if (!ext->GetInteger(kPrefState, &state_value) || | |
1240 state_value == Extension::ENABLED_COMPONENT) { | |
1241 // Old preferences files may not have kPrefState for component extensions. | |
1242 return scoped_ptr<ExtensionInfo>(); | |
1243 } | |
1244 | |
1245 if (state_value == Extension::EXTERNAL_EXTENSION_UNINSTALLED) { | |
1246 LOG(WARNING) << "External extension with id " << extension_id | |
1247 << " has been uninstalled by the user"; | |
1248 return scoped_ptr<ExtensionInfo>(); | |
1249 } | |
1250 | |
1251 return GetInstalledInfoHelper(extension_id, ext); | |
1252 } | |
1253 | |
1254 scoped_ptr<ExtensionPrefs::ExtensionsInfo> | |
1255 ExtensionPrefs::GetInstalledExtensionsInfo() const { | |
1256 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo); | |
1257 | |
1258 const base::DictionaryValue* extensions = | |
1259 prefs_->GetDictionary(pref_names::kExtensions); | |
1260 for (base::DictionaryValue::Iterator extension_id(*extensions); | |
1261 !extension_id.IsAtEnd(); extension_id.Advance()) { | |
1262 if (!Extension::IdIsValid(extension_id.key())) | |
1263 continue; | |
1264 | |
1265 scoped_ptr<ExtensionInfo> info = | |
1266 GetInstalledExtensionInfo(extension_id.key()); | |
1267 if (info) | |
1268 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release())); | |
1269 } | |
1270 | |
1271 return extensions_info.Pass(); | |
1272 } | |
1273 | |
1274 scoped_ptr<ExtensionPrefs::ExtensionsInfo> | |
1275 ExtensionPrefs::GetUninstalledExtensionsInfo() const { | |
1276 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo); | |
1277 | |
1278 const base::DictionaryValue* extensions = | |
1279 prefs_->GetDictionary(pref_names::kExtensions); | |
1280 for (base::DictionaryValue::Iterator extension_id(*extensions); | |
1281 !extension_id.IsAtEnd(); extension_id.Advance()) { | |
1282 const base::DictionaryValue* ext = NULL; | |
1283 if (!Extension::IdIsValid(extension_id.key()) || | |
1284 !IsExternalExtensionUninstalled(extension_id.key()) || | |
1285 !extension_id.value().GetAsDictionary(&ext)) | |
1286 continue; | |
1287 | |
1288 scoped_ptr<ExtensionInfo> info = | |
1289 GetInstalledInfoHelper(extension_id.key(), ext); | |
1290 if (info) | |
1291 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release())); | |
1292 } | |
1293 | |
1294 return extensions_info.Pass(); | |
1295 } | |
1296 | |
1297 void ExtensionPrefs::SetDelayedInstallInfo( | |
1298 const Extension* extension, | |
1299 Extension::State initial_state, | |
1300 bool blacklisted_for_malware, | |
1301 DelayReason delay_reason, | |
1302 const syncer::StringOrdinal& page_ordinal) { | |
1303 base::DictionaryValue* extension_dict = new base::DictionaryValue(); | |
1304 PopulateExtensionInfoPrefs(extension, time_provider_->GetCurrentTime(), | |
1305 initial_state, blacklisted_for_malware, | |
1306 extension_dict); | |
1307 | |
1308 // Add transient data that is needed by FinishDelayedInstallInfo(), but | |
1309 // should not be in the final extension prefs. All entries here should have | |
1310 // a corresponding Remove() call in FinishDelayedInstallInfo(). | |
1311 if (extension->RequiresSortOrdinal()) { | |
1312 extension_dict->SetString( | |
1313 kPrefSuggestedPageOrdinal, | |
1314 page_ordinal.IsValid() ? page_ordinal.ToInternalValue() | |
1315 : std::string()); | |
1316 } | |
1317 extension_dict->SetInteger(kDelayedInstallReason, | |
1318 static_cast<int>(delay_reason)); | |
1319 | |
1320 UpdateExtensionPref(extension->id(), kDelayedInstallInfo, extension_dict); | |
1321 } | |
1322 | |
1323 bool ExtensionPrefs::RemoveDelayedInstallInfo( | |
1324 const std::string& extension_id) { | |
1325 if (!GetExtensionPref(extension_id)) | |
1326 return false; | |
1327 ScopedExtensionPrefUpdate update(prefs_, extension_id); | |
1328 bool result = update->Remove(kDelayedInstallInfo, NULL); | |
1329 return result; | |
1330 } | |
1331 | |
1332 bool ExtensionPrefs::FinishDelayedInstallInfo( | |
1333 const std::string& extension_id) { | |
1334 CHECK(Extension::IdIsValid(extension_id)); | |
1335 ScopedExtensionPrefUpdate update(prefs_, extension_id); | |
1336 base::DictionaryValue* extension_dict = update.Get(); | |
1337 base::DictionaryValue* pending_install_dict = NULL; | |
1338 if (!extension_dict->GetDictionary(kDelayedInstallInfo, | |
1339 &pending_install_dict)) { | |
1340 return false; | |
1341 } | |
1342 | |
1343 // Retrieve and clear transient values populated by SetDelayedInstallInfo(). | |
1344 // Also do any other data cleanup that makes sense. | |
1345 std::string serialized_ordinal; | |
1346 syncer::StringOrdinal suggested_page_ordinal; | |
1347 bool needs_sort_ordinal = false; | |
1348 if (pending_install_dict->GetString(kPrefSuggestedPageOrdinal, | |
1349 &serialized_ordinal)) { | |
1350 suggested_page_ordinal = syncer::StringOrdinal(serialized_ordinal); | |
1351 needs_sort_ordinal = true; | |
1352 pending_install_dict->Remove(kPrefSuggestedPageOrdinal, NULL); | |
1353 } | |
1354 pending_install_dict->Remove(kDelayedInstallReason, NULL); | |
1355 | |
1356 const base::Time install_time = time_provider_->GetCurrentTime(); | |
1357 pending_install_dict->Set( | |
1358 kPrefInstallTime, | |
1359 new base::StringValue( | |
1360 base::Int64ToString(install_time.ToInternalValue()))); | |
1361 | |
1362 // Commit the delayed install data. | |
1363 for (base::DictionaryValue::Iterator it(*pending_install_dict); !it.IsAtEnd(); | |
1364 it.Advance()) { | |
1365 extension_dict->Set(it.key(), it.value().DeepCopy()); | |
1366 } | |
1367 FinishExtensionInfoPrefs(extension_id, install_time, needs_sort_ordinal, | |
1368 suggested_page_ordinal, extension_dict); | |
1369 return true; | |
1370 } | |
1371 | |
1372 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetDelayedInstallInfo( | |
1373 const std::string& extension_id) const { | |
1374 const base::DictionaryValue* extension_prefs = | |
1375 GetExtensionPref(extension_id); | |
1376 if (!extension_prefs) | |
1377 return scoped_ptr<ExtensionInfo>(); | |
1378 | |
1379 const base::DictionaryValue* ext = NULL; | |
1380 if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext)) | |
1381 return scoped_ptr<ExtensionInfo>(); | |
1382 | |
1383 return GetInstalledInfoHelper(extension_id, ext); | |
1384 } | |
1385 | |
1386 ExtensionPrefs::DelayReason ExtensionPrefs::GetDelayedInstallReason( | |
1387 const std::string& extension_id) const { | |
1388 const base::DictionaryValue* extension_prefs = | |
1389 GetExtensionPref(extension_id); | |
1390 if (!extension_prefs) | |
1391 return DELAY_REASON_NONE; | |
1392 | |
1393 const base::DictionaryValue* ext = NULL; | |
1394 if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext)) | |
1395 return DELAY_REASON_NONE; | |
1396 | |
1397 int delay_reason; | |
1398 if (!ext->GetInteger(kDelayedInstallReason, &delay_reason)) | |
1399 return DELAY_REASON_NONE; | |
1400 | |
1401 return static_cast<DelayReason>(delay_reason); | |
1402 } | |
1403 | |
1404 scoped_ptr<ExtensionPrefs::ExtensionsInfo> ExtensionPrefs:: | |
1405 GetAllDelayedInstallInfo() const { | |
1406 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo); | |
1407 | |
1408 const base::DictionaryValue* extensions = | |
1409 prefs_->GetDictionary(pref_names::kExtensions); | |
1410 for (base::DictionaryValue::Iterator extension_id(*extensions); | |
1411 !extension_id.IsAtEnd(); extension_id.Advance()) { | |
1412 if (!Extension::IdIsValid(extension_id.key())) | |
1413 continue; | |
1414 | |
1415 scoped_ptr<ExtensionInfo> info = GetDelayedInstallInfo(extension_id.key()); | |
1416 if (info) | |
1417 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release())); | |
1418 } | |
1419 | |
1420 return extensions_info.Pass(); | |
1421 } | |
1422 | |
1423 bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) { | |
1424 return ReadPrefAsBooleanAndReturn(extension_id, kPrefUserDraggedApp); | |
1425 } | |
1426 | |
1427 void ExtensionPrefs::SetAppDraggedByUser(const std::string& extension_id) { | |
1428 UpdateExtensionPref(extension_id, kPrefUserDraggedApp, | |
1429 new base::FundamentalValue(true)); | |
1430 } | |
1431 | |
1432 bool ExtensionPrefs::IsFromWebStore( | |
1433 const std::string& extension_id) const { | |
1434 const base::DictionaryValue* dictionary = GetExtensionPref(extension_id); | |
1435 bool result = false; | |
1436 if (dictionary && dictionary->GetBoolean(kPrefFromWebStore, &result)) | |
1437 return result; | |
1438 return false; | |
1439 } | |
1440 | |
1441 bool ExtensionPrefs::IsFromBookmark( | |
1442 const std::string& extension_id) const { | |
1443 const base::DictionaryValue* dictionary = GetExtensionPref(extension_id); | |
1444 bool result = false; | |
1445 if (dictionary && dictionary->GetBoolean(kPrefFromBookmark, &result)) | |
1446 return result; | |
1447 return false; | |
1448 } | |
1449 | |
1450 int ExtensionPrefs::GetCreationFlags(const std::string& extension_id) const { | |
1451 int creation_flags = Extension::NO_FLAGS; | |
1452 if (!ReadPrefAsInteger(extension_id, kPrefCreationFlags, &creation_flags)) { | |
1453 // Since kPrefCreationFlags was added later, it will be missing for | |
1454 // previously installed extensions. | |
1455 if (IsFromBookmark(extension_id)) | |
1456 creation_flags |= Extension::FROM_BOOKMARK; | |
1457 if (IsFromWebStore(extension_id)) | |
1458 creation_flags |= Extension::FROM_WEBSTORE; | |
1459 if (WasInstalledByDefault(extension_id)) | |
1460 creation_flags |= Extension::WAS_INSTALLED_BY_DEFAULT; | |
1461 } | |
1462 return creation_flags; | |
1463 } | |
1464 | |
1465 int ExtensionPrefs::GetDelayedInstallCreationFlags( | |
1466 const std::string& extension_id) const { | |
1467 int creation_flags = Extension::NO_FLAGS; | |
1468 const base::DictionaryValue* delayed_info = NULL; | |
1469 if (ReadPrefAsDictionary(extension_id, kDelayedInstallInfo, &delayed_info)) { | |
1470 delayed_info->GetInteger(kPrefCreationFlags, &creation_flags); | |
1471 } | |
1472 return creation_flags; | |
1473 } | |
1474 | |
1475 bool ExtensionPrefs::WasInstalledByDefault( | |
1476 const std::string& extension_id) const { | |
1477 const base::DictionaryValue* dictionary = GetExtensionPref(extension_id); | |
1478 bool result = false; | |
1479 if (dictionary && | |
1480 dictionary->GetBoolean(kPrefWasInstalledByDefault, &result)) | |
1481 return result; | |
1482 return false; | |
1483 } | |
1484 | |
1485 base::Time ExtensionPrefs::GetInstallTime( | |
1486 const std::string& extension_id) const { | |
1487 const base::DictionaryValue* extension = GetExtensionPref(extension_id); | |
1488 if (!extension) { | |
1489 NOTREACHED(); | |
1490 return base::Time(); | |
1491 } | |
1492 std::string install_time_str; | |
1493 if (!extension->GetString(kPrefInstallTime, &install_time_str)) | |
1494 return base::Time(); | |
1495 int64 install_time_i64 = 0; | |
1496 if (!base::StringToInt64(install_time_str, &install_time_i64)) | |
1497 return base::Time(); | |
1498 return base::Time::FromInternalValue(install_time_i64); | |
1499 } | |
1500 | |
1501 base::Time ExtensionPrefs::GetLastLaunchTime( | |
1502 const std::string& extension_id) const { | |
1503 const base::DictionaryValue* extension = GetExtensionPref(extension_id); | |
1504 if (!extension) | |
1505 return base::Time(); | |
1506 | |
1507 std::string launch_time_str; | |
1508 if (!extension->GetString(kPrefLastLaunchTime, &launch_time_str)) | |
1509 return base::Time(); | |
1510 int64 launch_time_i64 = 0; | |
1511 if (!base::StringToInt64(launch_time_str, &launch_time_i64)) | |
1512 return base::Time(); | |
1513 return base::Time::FromInternalValue(launch_time_i64); | |
1514 } | |
1515 | |
1516 void ExtensionPrefs::SetLastLaunchTime(const std::string& extension_id, | |
1517 const base::Time& time) { | |
1518 DCHECK(Extension::IdIsValid(extension_id)); | |
1519 ScopedExtensionPrefUpdate update(prefs_, extension_id); | |
1520 SaveTime(update.Get(), kPrefLastLaunchTime, time); | |
1521 } | |
1522 | |
1523 void ExtensionPrefs::GetExtensions(ExtensionIdList* out) { | |
1524 CHECK(out); | |
1525 | |
1526 scoped_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo()); | |
1527 | |
1528 for (size_t i = 0; i < extensions_info->size(); ++i) { | |
1529 ExtensionInfo* info = extensions_info->at(i).get(); | |
1530 out->push_back(info->extension_id); | |
1531 } | |
1532 } | |
1533 | |
1534 // static | |
1535 ExtensionIdList ExtensionPrefs::GetExtensionsFrom( | |
1536 const PrefService* pref_service) { | |
1537 ExtensionIdList result; | |
1538 | |
1539 const base::DictionaryValue* extension_prefs = NULL; | |
1540 const base::Value* extension_prefs_value = | |
1541 pref_service->GetUserPrefValue(pref_names::kExtensions); | |
1542 if (!extension_prefs_value || | |
1543 !extension_prefs_value->GetAsDictionary(&extension_prefs)) { | |
1544 return result; // Empty set | |
1545 } | |
1546 | |
1547 for (base::DictionaryValue::Iterator it(*extension_prefs); !it.IsAtEnd(); | |
1548 it.Advance()) { | |
1549 const base::DictionaryValue* ext = NULL; | |
1550 if (!it.value().GetAsDictionary(&ext)) { | |
1551 NOTREACHED() << "Invalid pref for extension " << it.key(); | |
1552 continue; | |
1553 } | |
1554 if (!IsBlacklistBitSet(ext)) | |
1555 result.push_back(it.key()); | |
1556 } | |
1557 return result; | |
1558 } | |
1559 | |
1560 void ExtensionPrefs::FixMissingPrefs(const ExtensionIdList& extension_ids) { | |
1561 // Fix old entries that did not get an installation time entry when they | |
1562 // were installed or don't have a preferences field. | |
1563 for (ExtensionIdList::const_iterator ext_id = extension_ids.begin(); | |
1564 ext_id != extension_ids.end(); ++ext_id) { | |
1565 if (GetInstallTime(*ext_id) == base::Time()) { | |
1566 VLOG(1) << "Could not parse installation time of extension " | |
1567 << *ext_id << ". It was probably installed before setting " | |
1568 << kPrefInstallTime << " was introduced. Updating " | |
1569 << kPrefInstallTime << " to the current time."; | |
1570 const base::Time install_time = time_provider_->GetCurrentTime(); | |
1571 UpdateExtensionPref(*ext_id, | |
1572 kPrefInstallTime, | |
1573 new base::StringValue(base::Int64ToString( | |
1574 install_time.ToInternalValue()))); | |
1575 } | |
1576 } | |
1577 } | |
1578 | |
1579 void ExtensionPrefs::InitPrefStore() { | |
1580 if (extensions_disabled_) { | |
1581 extension_pref_value_map_->NotifyInitializationCompleted(); | |
1582 return; | |
1583 } | |
1584 | |
1585 // When this is called, the PrefService is initialized and provides access | |
1586 // to the user preferences stored in a JSON file. | |
1587 ExtensionIdList extension_ids; | |
1588 GetExtensions(&extension_ids); | |
1589 // Create empty preferences dictionary for each extension (these dictionaries | |
1590 // are pruned when persisting the preferences to disk). | |
1591 for (ExtensionIdList::iterator ext_id = extension_ids.begin(); | |
1592 ext_id != extension_ids.end(); ++ext_id) { | |
1593 ScopedExtensionPrefUpdate update(prefs_, *ext_id); | |
1594 // This creates an empty dictionary if none is stored. | |
1595 update.Get(); | |
1596 } | |
1597 | |
1598 FixMissingPrefs(extension_ids); | |
1599 MigratePermissions(extension_ids); | |
1600 MigrateDisableReasons(extension_ids); | |
1601 app_sorting_->Initialize(extension_ids); | |
1602 | |
1603 PreferenceAPI::InitExtensionControlledPrefs(this, extension_pref_value_map_); | |
1604 | |
1605 extension_pref_value_map_->NotifyInitializationCompleted(); | |
1606 } | |
1607 | |
1608 bool ExtensionPrefs::HasIncognitoPrefValue(const std::string& pref_key) { | |
1609 bool has_incognito_pref_value = false; | |
1610 extension_pref_value_map_->GetEffectivePrefValue(pref_key, | |
1611 true, | |
1612 &has_incognito_pref_value); | |
1613 return has_incognito_pref_value; | |
1614 } | |
1615 | |
1616 URLPatternSet ExtensionPrefs::GetAllowedInstallSites() { | |
1617 URLPatternSet result; | |
1618 const base::ListValue* list = | |
1619 prefs_->GetList(pref_names::kAllowedInstallSites); | |
1620 CHECK(list); | |
1621 | |
1622 for (size_t i = 0; i < list->GetSize(); ++i) { | |
1623 std::string entry_string; | |
1624 URLPattern entry(URLPattern::SCHEME_ALL); | |
1625 if (!list->GetString(i, &entry_string) || | |
1626 entry.Parse(entry_string) != URLPattern::PARSE_SUCCESS) { | |
1627 LOG(ERROR) << "Invalid value for preference: " | |
1628 << pref_names::kAllowedInstallSites << "." << i; | |
1629 continue; | |
1630 } | |
1631 result.AddPattern(entry); | |
1632 } | |
1633 | |
1634 return result; | |
1635 } | |
1636 | |
1637 const base::DictionaryValue* ExtensionPrefs::GetGeometryCache( | |
1638 const std::string& extension_id) const { | |
1639 const base::DictionaryValue* extension_prefs = GetExtensionPref(extension_id); | |
1640 if (!extension_prefs) | |
1641 return NULL; | |
1642 | |
1643 const base::DictionaryValue* ext = NULL; | |
1644 if (!extension_prefs->GetDictionary(kPrefGeometryCache, &ext)) | |
1645 return NULL; | |
1646 | |
1647 return ext; | |
1648 } | |
1649 | |
1650 void ExtensionPrefs::SetGeometryCache( | |
1651 const std::string& extension_id, | |
1652 scoped_ptr<base::DictionaryValue> cache) { | |
1653 UpdateExtensionPref(extension_id, kPrefGeometryCache, cache.release()); | |
1654 } | |
1655 | |
1656 const base::DictionaryValue* ExtensionPrefs::GetInstallSignature() { | |
1657 return prefs_->GetDictionary(kInstallSignature); | |
1658 } | |
1659 | |
1660 void ExtensionPrefs::SetInstallSignature( | |
1661 const base::DictionaryValue* signature) { | |
1662 if (signature) { | |
1663 prefs_->Set(kInstallSignature, *signature); | |
1664 DVLOG(1) << "SetInstallSignature - saving"; | |
1665 } else { | |
1666 DVLOG(1) << "SetInstallSignature - clearing"; | |
1667 prefs_->ClearPref(kInstallSignature); | |
1668 } | |
1669 } | |
1670 | |
1671 | |
1672 ExtensionPrefs::ExtensionPrefs( | |
1673 PrefService* prefs, | |
1674 const base::FilePath& root_dir, | |
1675 ExtensionPrefValueMap* extension_pref_value_map, | |
1676 scoped_ptr<AppSorting> app_sorting, | |
1677 scoped_ptr<TimeProvider> time_provider, | |
1678 bool extensions_disabled) | |
1679 : prefs_(prefs), | |
1680 install_directory_(root_dir), | |
1681 extension_pref_value_map_(extension_pref_value_map), | |
1682 app_sorting_(app_sorting.Pass()), | |
1683 content_settings_store_(new ContentSettingsStore()), | |
1684 time_provider_(time_provider.Pass()), | |
1685 extensions_disabled_(extensions_disabled) { | |
1686 app_sorting_->SetExtensionScopedPrefs(this), | |
1687 MakePathsRelative(); | |
1688 InitPrefStore(); | |
1689 } | |
1690 | |
1691 void ExtensionPrefs::SetNeedsStorageGarbageCollection(bool value) { | |
1692 prefs_->SetBoolean(pref_names::kStorageGarbageCollect, value); | |
1693 } | |
1694 | |
1695 bool ExtensionPrefs::NeedsStorageGarbageCollection() { | |
1696 return prefs_->GetBoolean(pref_names::kStorageGarbageCollect); | |
1697 } | |
1698 | |
1699 // static | |
1700 void ExtensionPrefs::RegisterProfilePrefs( | |
1701 user_prefs::PrefRegistrySyncable* registry) { | |
1702 registry->RegisterDictionaryPref( | |
1703 pref_names::kExtensions, | |
1704 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1705 registry->RegisterListPref(pref_names::kToolbar, | |
1706 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); | |
1707 registry->RegisterIntegerPref( | |
1708 pref_names::kToolbarSize, | |
1709 -1, // default value | |
1710 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1711 registry->RegisterDictionaryPref( | |
1712 kExtensionsBlacklistUpdate, | |
1713 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1714 registry->RegisterListPref(pref_names::kInstallAllowList, | |
1715 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1716 registry->RegisterListPref(pref_names::kInstallDenyList, | |
1717 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1718 registry->RegisterDictionaryPref( | |
1719 pref_names::kInstallForceList, | |
1720 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1721 registry->RegisterListPref(pref_names::kAllowedTypes, | |
1722 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1723 registry->RegisterBooleanPref( | |
1724 pref_names::kStorageGarbageCollect, | |
1725 false, // default value | |
1726 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1727 registry->RegisterInt64Pref( | |
1728 pref_names::kLastUpdateCheck, | |
1729 0, // default value | |
1730 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1731 registry->RegisterInt64Pref( | |
1732 pref_names::kNextUpdateCheck, | |
1733 0, // default value | |
1734 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1735 registry->RegisterListPref(pref_names::kAllowedInstallSites, | |
1736 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1737 registry->RegisterStringPref( | |
1738 pref_names::kLastChromeVersion, | |
1739 std::string(), // default value | |
1740 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1741 registry->RegisterListPref(pref_names::kKnownDisabled, | |
1742 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1743 #if defined(TOOLKIT_VIEWS) | |
1744 registry->RegisterIntegerPref( | |
1745 pref_names::kBrowserActionContainerWidth, | |
1746 0, | |
1747 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1748 #endif | |
1749 registry->RegisterDictionaryPref( | |
1750 kInstallSignature, | |
1751 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1752 | |
1753 registry->RegisterListPref(pref_names::kNativeMessagingBlacklist, | |
1754 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1755 registry->RegisterListPref(pref_names::kNativeMessagingWhitelist, | |
1756 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
1757 } | |
1758 | |
1759 template <class ExtensionIdContainer> | |
1760 bool ExtensionPrefs::GetUserExtensionPrefIntoContainer( | |
1761 const char* pref, | |
1762 ExtensionIdContainer* id_container_out) { | |
1763 DCHECK(id_container_out->empty()); | |
1764 | |
1765 const base::Value* user_pref_value = prefs_->GetUserPrefValue(pref); | |
1766 const base::ListValue* user_pref_as_list; | |
1767 if (!user_pref_value || !user_pref_value->GetAsList(&user_pref_as_list)) | |
1768 return false; | |
1769 | |
1770 std::insert_iterator<ExtensionIdContainer> insert_iterator( | |
1771 *id_container_out, id_container_out->end()); | |
1772 std::string extension_id; | |
1773 for (base::ListValue::const_iterator value_it = user_pref_as_list->begin(); | |
1774 value_it != user_pref_as_list->end(); ++value_it) { | |
1775 if (!(*value_it)->GetAsString(&extension_id)) { | |
1776 NOTREACHED(); | |
1777 continue; | |
1778 } | |
1779 insert_iterator = extension_id; | |
1780 } | |
1781 return true; | |
1782 } | |
1783 | |
1784 template <class ExtensionIdContainer> | |
1785 void ExtensionPrefs::SetExtensionPrefFromContainer( | |
1786 const char* pref, | |
1787 const ExtensionIdContainer& strings) { | |
1788 ListPrefUpdate update(prefs_, pref); | |
1789 base::ListValue* list_of_values = update.Get(); | |
1790 list_of_values->Clear(); | |
1791 for (typename ExtensionIdContainer::const_iterator iter = strings.begin(); | |
1792 iter != strings.end(); ++iter) { | |
1793 list_of_values->Append(new base::StringValue(*iter)); | |
1794 } | |
1795 } | |
1796 | |
1797 void ExtensionPrefs::PopulateExtensionInfoPrefs( | |
1798 const Extension* extension, | |
1799 const base::Time install_time, | |
1800 Extension::State initial_state, | |
1801 bool blacklisted_for_malware, | |
1802 base::DictionaryValue* extension_dict) { | |
1803 // Leave the state blank for component extensions so that old chrome versions | |
1804 // loading new profiles do not fail in GetInstalledExtensionInfo. Older | |
1805 // Chrome versions would only check for an omitted state. | |
1806 if (initial_state != Extension::ENABLED_COMPONENT) | |
1807 extension_dict->Set(kPrefState, new base::FundamentalValue(initial_state)); | |
1808 | |
1809 extension_dict->Set(kPrefLocation, | |
1810 new base::FundamentalValue(extension->location())); | |
1811 extension_dict->Set(kPrefCreationFlags, | |
1812 new base::FundamentalValue(extension->creation_flags())); | |
1813 extension_dict->Set(kPrefFromWebStore, | |
1814 new base::FundamentalValue(extension->from_webstore())); | |
1815 extension_dict->Set(kPrefFromBookmark, | |
1816 new base::FundamentalValue(extension->from_bookmark())); | |
1817 extension_dict->Set( | |
1818 kPrefWasInstalledByDefault, | |
1819 new base::FundamentalValue(extension->was_installed_by_default())); | |
1820 extension_dict->Set(kPrefInstallTime, | |
1821 new base::StringValue( | |
1822 base::Int64ToString(install_time.ToInternalValue()))); | |
1823 if (blacklisted_for_malware) | |
1824 extension_dict->Set(kPrefBlacklist, new base::FundamentalValue(true)); | |
1825 | |
1826 base::FilePath::StringType path = MakePathRelative(install_directory_, | |
1827 extension->path()); | |
1828 extension_dict->Set(kPrefPath, new base::StringValue(path)); | |
1829 // We store prefs about LOAD extensions, but don't cache their manifest | |
1830 // since it may change on disk. | |
1831 if (!Manifest::IsUnpackedLocation(extension->location())) { | |
1832 extension_dict->Set(kPrefManifest, | |
1833 extension->manifest()->value()->DeepCopy()); | |
1834 } | |
1835 } | |
1836 | |
1837 void ExtensionPrefs::FinishExtensionInfoPrefs( | |
1838 const std::string& extension_id, | |
1839 const base::Time install_time, | |
1840 bool needs_sort_ordinal, | |
1841 const syncer::StringOrdinal& suggested_page_ordinal, | |
1842 base::DictionaryValue* extension_dict) { | |
1843 // Reinitializes various preferences with empty dictionaries. | |
1844 if (!extension_dict->HasKey(pref_names::kPrefPreferences)) { | |
1845 extension_dict->Set(pref_names::kPrefPreferences, | |
1846 new base::DictionaryValue); | |
1847 } | |
1848 | |
1849 if (!extension_dict->HasKey(pref_names::kPrefIncognitoPreferences)) { | |
1850 extension_dict->Set(pref_names::kPrefIncognitoPreferences, | |
1851 new base::DictionaryValue); | |
1852 } | |
1853 | |
1854 if (!extension_dict->HasKey(pref_names::kPrefRegularOnlyPreferences)) { | |
1855 extension_dict->Set(pref_names::kPrefRegularOnlyPreferences, | |
1856 new base::DictionaryValue); | |
1857 } | |
1858 | |
1859 if (!extension_dict->HasKey(pref_names::kPrefContentSettings)) | |
1860 extension_dict->Set(pref_names::kPrefContentSettings, new base::ListValue); | |
1861 | |
1862 if (!extension_dict->HasKey(pref_names::kPrefIncognitoContentSettings)) { | |
1863 extension_dict->Set(pref_names::kPrefIncognitoContentSettings, | |
1864 new base::ListValue); | |
1865 } | |
1866 | |
1867 // If this point has been reached, any pending installs should be considered | |
1868 // out of date. | |
1869 extension_dict->Remove(kDelayedInstallInfo, NULL); | |
1870 | |
1871 // Clear state that may be registered from a previous install. | |
1872 extension_dict->Remove(EventRouter::kRegisteredEvents, NULL); | |
1873 | |
1874 // FYI, all code below here races on sudden shutdown because |extension_dict|, | |
1875 // |app_sorting_|, |extension_pref_value_map_|, and |content_settings_store_| | |
1876 // are updated non-transactionally. This is probably not fixable without | |
1877 // nested transactional updates to pref dictionaries. | |
1878 if (needs_sort_ordinal) | |
1879 app_sorting_->EnsureValidOrdinals(extension_id, suggested_page_ordinal); | |
1880 | |
1881 bool is_enabled = false; | |
1882 int initial_state; | |
1883 if (extension_dict->GetInteger(kPrefState, &initial_state)) { | |
1884 is_enabled = initial_state == Extension::ENABLED; | |
1885 } | |
1886 | |
1887 extension_pref_value_map_->RegisterExtension(extension_id, install_time, | |
1888 is_enabled); | |
1889 content_settings_store_->RegisterExtension(extension_id, install_time, | |
1890 is_enabled); | |
1891 } | |
1892 | |
1893 } // namespace extensions | |
OLD | NEW |