OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/extension_prefs.h" | 5 #include "chrome/browser/extensions/extension_prefs.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/prefs/pref_notifier.h" | 8 #include "base/prefs/pref_notifier.h" |
9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
112 | 112 |
113 // A bit we use to keep track of whether we need to do an "active" ping. | 113 // A bit we use to keep track of whether we need to do an "active" ping. |
114 const char kActiveBit[] = "active_bit"; | 114 const char kActiveBit[] = "active_bit"; |
115 | 115 |
116 // Path for settings specific to blacklist update. | 116 // Path for settings specific to blacklist update. |
117 const char kExtensionsBlacklistUpdate[] = "extensions.blacklistupdate"; | 117 const char kExtensionsBlacklistUpdate[] = "extensions.blacklistupdate"; |
118 | 118 |
119 // Path for the idle install info dictionary preference. | 119 // Path for the idle install info dictionary preference. |
120 const char kIdleInstallInfo[] = "idle_install_info"; | 120 const char kIdleInstallInfo[] = "idle_install_info"; |
121 | 121 |
122 // Path for the suggested page ordinal of a delayed extension install. | |
123 const char kPrefSuggestedPageOrdinal[] = "suggested_page_ordinal"; | |
124 | |
122 // A preference that, if true, will allow this extension to run in incognito | 125 // A preference that, if true, will allow this extension to run in incognito |
123 // mode. | 126 // mode. |
124 const char kPrefIncognitoEnabled[] = "incognito"; | 127 const char kPrefIncognitoEnabled[] = "incognito"; |
125 | 128 |
126 // A preference to control whether an extension is allowed to inject script in | 129 // A preference to control whether an extension is allowed to inject script in |
127 // pages with file URLs. | 130 // pages with file URLs. |
128 const char kPrefAllowFileAccess[] = "newAllowFileAccess"; | 131 const char kPrefAllowFileAccess[] = "newAllowFileAccess"; |
129 // TODO(jstritar): As part of fixing http://crbug.com/91577, we revoked all | 132 // TODO(jstritar): As part of fixing http://crbug.com/91577, we revoked all |
130 // extension file access by renaming the pref. We should eventually clean up | 133 // extension file access by renaming the pref. We should eventually clean up |
131 // the old flag and possibly go back to that name. | 134 // the old flag and possibly go back to that name. |
(...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1441 } | 1444 } |
1442 | 1445 |
1443 void ExtensionPrefs::SetActionBoxOrder(const ExtensionIdList& extension_ids) { | 1446 void ExtensionPrefs::SetActionBoxOrder(const ExtensionIdList& extension_ids) { |
1444 SetExtensionPrefFromVector(kExtensionActionBox, extension_ids); | 1447 SetExtensionPrefFromVector(kExtensionActionBox, extension_ids); |
1445 } | 1448 } |
1446 | 1449 |
1447 void ExtensionPrefs::OnExtensionInstalled( | 1450 void ExtensionPrefs::OnExtensionInstalled( |
1448 const Extension* extension, | 1451 const Extension* extension, |
1449 Extension::State initial_state, | 1452 Extension::State initial_state, |
1450 const syncer::StringOrdinal& page_ordinal) { | 1453 const syncer::StringOrdinal& page_ordinal) { |
1451 const std::string& id = extension->id(); | 1454 ScopedExtensionPrefUpdate update(prefs_, extension->id()); |
1452 CHECK(Extension::IdIsValid(id)); | |
1453 ScopedExtensionPrefUpdate update(prefs_, id); | |
1454 DictionaryValue* extension_dict = update.Get(); | 1455 DictionaryValue* extension_dict = update.Get(); |
1455 const base::Time install_time = time_provider_->GetCurrentTime(); | 1456 const base::Time install_time = time_provider_->GetCurrentTime(); |
1456 | 1457 PopulateExtensionInfoPrefs(extension, install_time, initial_state, |
1457 // Leave the state blank for component extensions so that old chrome versions | 1458 extension_dict); |
1458 // loading new profiles do not fail in GetInstalledExtensionInfo. Older | 1459 FinishExtensionInfoPrefs(extension->id(), install_time, |
1459 // Chrome versions would only check for an omitted state. | 1460 extension->RequiresSortOrdinal(), |
1460 if (initial_state != Extension::ENABLED_COMPONENT) | 1461 page_ordinal, extension_dict); |
1461 extension_dict->Set(kPrefState, Value::CreateIntegerValue(initial_state)); | |
1462 | |
1463 extension_dict->Set(kPrefLocation, | |
1464 Value::CreateIntegerValue(extension->location())); | |
1465 extension_dict->Set(kPrefCreationFlags, | |
1466 Value::CreateIntegerValue(extension->creation_flags())); | |
1467 extension_dict->Set(kPrefFromWebStore, | |
1468 Value::CreateBooleanValue(extension->from_webstore())); | |
1469 extension_dict->Set(kPrefFromBookmark, | |
1470 Value::CreateBooleanValue(extension->from_bookmark())); | |
1471 extension_dict->Set(kPrefWasInstalledByDefault, | |
1472 Value::CreateBooleanValue(extension->was_installed_by_default())); | |
1473 extension_dict->Set(kPrefInstallTime, | |
1474 Value::CreateStringValue( | |
1475 base::Int64ToString(install_time.ToInternalValue()))); | |
1476 extension_dict->Set(kPrefPreferences, new DictionaryValue()); | |
1477 extension_dict->Set(kPrefIncognitoPreferences, new DictionaryValue()); | |
1478 extension_dict->Set(kPrefRegularOnlyPreferences, new DictionaryValue()); | |
1479 extension_dict->Set(kPrefContentSettings, new ListValue()); | |
1480 extension_dict->Set(kPrefIncognitoContentSettings, new ListValue()); | |
1481 | |
1482 FilePath::StringType path = MakePathRelative(install_directory_, | |
1483 extension->path()); | |
1484 extension_dict->Set(kPrefPath, Value::CreateStringValue(path)); | |
1485 // We store prefs about LOAD extensions, but don't cache their manifest | |
1486 // since it may change on disk. | |
1487 if (extension->location() != Extension::LOAD) { | |
1488 extension_dict->Set(kPrefManifest, | |
1489 extension->manifest()->value()->DeepCopy()); | |
1490 } | |
1491 | |
1492 // Clear state that may be registered from a previous install. | |
1493 extension_dict->Remove(kRegisteredEvents, NULL); | |
1494 | |
1495 if (extension->RequiresSortOrdinal()) | |
1496 extension_sorting_->EnsureValidOrdinals(extension->id(), page_ordinal); | |
1497 | |
1498 extension_pref_value_map_->RegisterExtension( | |
1499 id, install_time, initial_state == Extension::ENABLED); | |
1500 content_settings_store_->RegisterExtension( | |
1501 id, install_time, initial_state == Extension::ENABLED); | |
1502 } | 1462 } |
1503 | 1463 |
1504 void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id, | 1464 void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id, |
1505 const Extension::Location& location, | 1465 const Extension::Location& location, |
1506 bool external_uninstall) { | 1466 bool external_uninstall) { |
1507 extension_sorting_->ClearOrdinals(extension_id); | 1467 extension_sorting_->ClearOrdinals(extension_id); |
1508 | 1468 |
1509 // For external extensions, we save a preference reminding ourself not to try | 1469 // For external extensions, we save a preference reminding ourself not to try |
1510 // and install the extension anymore (except when |external_uninstall| is | 1470 // and install the extension anymore (except when |external_uninstall| is |
1511 // true, which signifies that the registry key was deleted or the pref file | 1471 // true, which signifies that the registry key was deleted or the pref file |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1710 scoped_ptr<ExtensionInfo> info = GetInstalledExtensionInfo(*extension_id); | 1670 scoped_ptr<ExtensionInfo> info = GetInstalledExtensionInfo(*extension_id); |
1711 if (info) | 1671 if (info) |
1712 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release())); | 1672 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release())); |
1713 } | 1673 } |
1714 | 1674 |
1715 return extensions_info.Pass(); | 1675 return extensions_info.Pass(); |
1716 } | 1676 } |
1717 | 1677 |
1718 void ExtensionPrefs::SetIdleInstallInfo( | 1678 void ExtensionPrefs::SetIdleInstallInfo( |
1719 const Extension* extension, | 1679 const Extension* extension, |
1720 Extension::State initial_state) { | 1680 Extension::State initial_state, |
1721 const base::Time install_time = time_provider_->GetCurrentTime(); | 1681 const syncer::StringOrdinal& page_ordinal) { |
1722 DictionaryValue* extension_dict = new DictionaryValue(); | 1682 DictionaryValue* extension_dict = new DictionaryValue(); |
1723 extension_dict->Set(kPrefState, Value::CreateIntegerValue(initial_state)); | 1683 PopulateExtensionInfoPrefs(extension, time_provider_->GetCurrentTime(), |
1724 extension_dict->Set(kPrefLocation, | 1684 initial_state, extension_dict); |
1725 Value::CreateIntegerValue(extension->location())); | |
1726 extension_dict->Set(kPrefCreationFlags, | |
1727 Value::CreateIntegerValue(extension->creation_flags())); | |
1728 extension_dict->Set(kPrefFromWebStore, | |
1729 Value::CreateBooleanValue(extension->from_webstore())); | |
1730 extension_dict->Set(kPrefFromBookmark, | |
1731 Value::CreateBooleanValue(extension->from_bookmark())); | |
1732 extension_dict->Set(kPrefWasInstalledByDefault, | |
1733 Value::CreateBooleanValue(extension->was_installed_by_default())); | |
1734 extension_dict->Set(kPrefInstallTime, | |
1735 Value::CreateStringValue( | |
1736 base::Int64ToString(install_time.ToInternalValue()))); | |
1737 | 1685 |
1738 FilePath::StringType path = MakePathRelative(install_directory_, | 1686 // Add transient data that is needed by FinishIdleInstallInfo(), but |
1739 extension->path()); | 1687 // should not be in the final extension prefs. All entries here should have |
1740 extension_dict->Set(kPrefPath, Value::CreateStringValue(path)); | 1688 // a corresponding Remove() call in FinishIdleInstallInfo(). |
1741 extension_dict->Set(kPrefManifest, | 1689 if (extension->RequiresSortOrdinal()) { |
1742 extension->manifest()->value()->DeepCopy()); | 1690 extension_dict->SetString(kPrefSuggestedPageOrdinal, |
1691 page_ordinal.ToInternalValue()); | |
1692 } | |
1743 | 1693 |
1744 UpdateExtensionPref(extension->id(), kIdleInstallInfo, extension_dict); | 1694 // RESOLVE BEFORE COMMIT: Why did this used to use UpdateExtensionPref |
Marijn Kruisselbrink
2012/12/07 17:29:49
Why not? Most code seems to use UpdateExtensionPre
awong
2012/12/07 22:02:25
Okay...I'll move back to UpdateExtensionPref(). I
Marijn Kruisselbrink
2012/12/07 22:15:09
Ah, yeah, RemoveIdleInstallInfo I didn't touch, an
| |
1695 // directly? | |
1696 ScopedExtensionPrefUpdate update(prefs_, extension->id()); | |
1697 update->Set(kIdleInstallInfo, extension_dict); | |
1745 } | 1698 } |
1746 | 1699 |
1747 bool ExtensionPrefs::RemoveIdleInstallInfo(const std::string& extension_id) { | 1700 bool ExtensionPrefs::RemoveIdleInstallInfo(const std::string& extension_id) { |
1748 if (!GetExtensionPref(extension_id)) | 1701 if (!GetExtensionPref(extension_id)) |
1749 return false; | 1702 return false; |
1750 ScopedExtensionPrefUpdate update(prefs_, extension_id); | 1703 ScopedExtensionPrefUpdate update(prefs_, extension_id); |
1751 bool result = update->Remove(kIdleInstallInfo, NULL); | 1704 bool result = update->Remove(kIdleInstallInfo, NULL); |
1752 return result; | 1705 return result; |
1753 } | 1706 } |
1754 | 1707 |
1755 bool ExtensionPrefs::FinishIdleInstallInfo(const std::string& extension_id) { | 1708 bool ExtensionPrefs::FinishIdleInstallInfo(const std::string& extension_id) { |
1756 CHECK(Extension::IdIsValid(extension_id)); | 1709 CHECK(Extension::IdIsValid(extension_id)); |
1757 ScopedExtensionPrefUpdate update(prefs_, extension_id); | 1710 ScopedExtensionPrefUpdate update(prefs_, extension_id); |
1758 DictionaryValue* extension_dict = update.Get(); | 1711 DictionaryValue* extension_dict = update.Get(); |
1759 DictionaryValue* update_dict; | 1712 DictionaryValue* pending_install_dict = NULL; |
1760 if (!extension_dict->GetDictionary(kIdleInstallInfo, &update_dict)) | 1713 if (!extension_dict->GetDictionary(kIdleInstallInfo, &pending_install_dict)) |
1761 return false; | 1714 return false; |
1762 | 1715 |
1716 // Retrieve and clear transient values populated by SetIdleInstallInfo(). Also | |
1717 // do any other data cleanup that makes sense. | |
1718 std::string serialized_ordinal; | |
1719 syncer::StringOrdinal suggested_page_ordinal; | |
1720 bool needs_sort_ordinal = false; | |
1721 if (pending_install_dict->GetString(kPrefSuggestedPageOrdinal, | |
1722 &serialized_ordinal)) { | |
1723 suggested_page_ordinal = syncer::StringOrdinal(serialized_ordinal); | |
1724 needs_sort_ordinal = true; | |
1725 pending_install_dict->Remove(kPrefSuggestedPageOrdinal, NULL); | |
1726 } | |
1727 | |
1763 const base::Time install_time = time_provider_->GetCurrentTime(); | 1728 const base::Time install_time = time_provider_->GetCurrentTime(); |
1764 extension_dict->MergeDictionary(update_dict); | 1729 pending_install_dict->Set( |
1765 extension_dict->Set(kPrefInstallTime, | 1730 kPrefInstallTime, |
1766 Value::CreateStringValue( | 1731 Value::CreateStringValue( |
1767 base::Int64ToString(install_time.ToInternalValue()))); | 1732 base::Int64ToString(install_time.ToInternalValue()))); |
1768 extension_dict->Set(kPrefPreferences, new DictionaryValue()); | |
1769 extension_dict->Set(kPrefIncognitoPreferences, new DictionaryValue()); | |
1770 extension_dict->Set(kPrefRegularOnlyPreferences, new DictionaryValue()); | |
1771 extension_dict->Set(kPrefContentSettings, new ListValue()); | |
1772 extension_dict->Set(kPrefIncognitoContentSettings, new ListValue()); | |
1773 | 1733 |
1774 // Clear state that may be registered from a previous install. | 1734 // Commit the delayed install data. |
1775 extension_dict->Remove(kRegisteredEvents, NULL); | 1735 extension_dict->MergeDictionary(pending_install_dict); |
1776 | 1736 FinishExtensionInfoPrefs(extension_id, install_time, needs_sort_ordinal, |
1777 // Remove pending update information | 1737 suggested_page_ordinal, extension_dict); |
1778 extension_dict->Remove(kIdleInstallInfo, NULL); | |
1779 | |
1780 int initial_state; | |
1781 if (extension_dict->GetInteger(kPrefState, &initial_state)) { | |
1782 extension_pref_value_map_->RegisterExtension( | |
1783 extension_id, install_time, initial_state == Extension::ENABLED); | |
1784 content_settings_store_->RegisterExtension( | |
1785 extension_id, install_time, initial_state == Extension::ENABLED); | |
1786 } | |
1787 return true; | 1738 return true; |
1788 } | 1739 } |
1789 | 1740 |
1790 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetIdleInstallInfo( | 1741 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetIdleInstallInfo( |
1791 const std::string& extension_id) const { | 1742 const std::string& extension_id) const { |
1792 const DictionaryValue* extension_prefs = GetExtensionPref(extension_id); | 1743 const DictionaryValue* extension_prefs = GetExtensionPref(extension_id); |
1793 if (!extension_prefs) | 1744 if (!extension_prefs) |
1794 return scoped_ptr<ExtensionInfo>(); | 1745 return scoped_ptr<ExtensionInfo>(); |
1795 | 1746 |
1796 const DictionaryValue* ext = NULL; | 1747 const DictionaryValue* ext = NULL; |
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2308 const char* pref, | 2259 const char* pref, |
2309 const ExtensionIdList& strings) { | 2260 const ExtensionIdList& strings) { |
2310 ListPrefUpdate update(prefs_, pref); | 2261 ListPrefUpdate update(prefs_, pref); |
2311 ListValue* list_of_values = update.Get(); | 2262 ListValue* list_of_values = update.Get(); |
2312 list_of_values->Clear(); | 2263 list_of_values->Clear(); |
2313 for (ExtensionIdList::const_iterator iter = strings.begin(); | 2264 for (ExtensionIdList::const_iterator iter = strings.begin(); |
2314 iter != strings.end(); ++iter) | 2265 iter != strings.end(); ++iter) |
2315 list_of_values->Append(new StringValue(*iter)); | 2266 list_of_values->Append(new StringValue(*iter)); |
2316 } | 2267 } |
2317 | 2268 |
2269 void ExtensionPrefs::PopulateExtensionInfoPrefs( | |
2270 const Extension* extension, | |
2271 const base::Time install_time, | |
2272 Extension::State initial_state, | |
2273 DictionaryValue* extension_dict) { | |
2274 // Leave the state blank for component extensions so that old chrome versions | |
2275 // loading new profiles do not fail in GetInstalledExtensionInfo. Older | |
2276 // Chrome versions would only check for an omitted state. | |
2277 if (initial_state != Extension::ENABLED_COMPONENT) | |
2278 extension_dict->Set(kPrefState, Value::CreateIntegerValue(initial_state)); | |
2279 | |
2280 extension_dict->Set(kPrefLocation, | |
2281 Value::CreateIntegerValue(extension->location())); | |
2282 extension_dict->Set(kPrefCreationFlags, | |
2283 Value::CreateIntegerValue(extension->creation_flags())); | |
2284 extension_dict->Set(kPrefFromWebStore, | |
2285 Value::CreateBooleanValue(extension->from_webstore())); | |
2286 extension_dict->Set(kPrefFromBookmark, | |
2287 Value::CreateBooleanValue(extension->from_bookmark())); | |
2288 extension_dict->Set(kPrefWasInstalledByDefault, | |
2289 Value::CreateBooleanValue(extension->was_installed_by_default())); | |
2290 extension_dict->Set(kPrefInstallTime, | |
2291 Value::CreateStringValue( | |
2292 base::Int64ToString(install_time.ToInternalValue()))); | |
2293 | |
2294 FilePath::StringType path = MakePathRelative(install_directory_, | |
2295 extension->path()); | |
2296 extension_dict->Set(kPrefPath, Value::CreateStringValue(path)); | |
2297 // We store prefs about LOAD extensions, but don't cache their manifest | |
2298 // since it may change on disk. | |
2299 if (extension->location() != Extension::LOAD) { | |
2300 // RESOLVE ME BEFORE COMMIT: We did not preivously avoid this for LOAD exten sions in | |
Marijn Kruisselbrink
2012/12/07 17:29:49
Yes, I agree. No reason to not avoid this even in
awong
2012/12/07 22:02:25
Done.
| |
2301 // SetIdleInstallInfo(). Having this condition still seems sensible even | |
2302 // if the extension was delayed. | |
2303 extension_dict->Set(kPrefManifest, | |
2304 extension->manifest()->value()->DeepCopy()); | |
2305 } | |
2306 | |
2307 // RESOLVE ME BEFORE COMMIT: This could be created post commit, but it feels | |
Marijn Kruisselbrink
2012/12/07 17:29:49
I'm not sure if this actually works though. In Fin
awong
2012/12/07 22:02:25
Ah! Good catch. Moved into FinishExtensionInfoPref
| |
2308 // cleaner to just keep all this in one spot. Do we actually care enough to | |
2309 // save these 5 empty preferences from being committed to disk? | |
2310 extension_dict->Set(kPrefPreferences, new DictionaryValue()); | |
2311 extension_dict->Set(kPrefIncognitoPreferences, new DictionaryValue()); | |
2312 extension_dict->Set(kPrefRegularOnlyPreferences, new DictionaryValue()); | |
2313 extension_dict->Set(kPrefContentSettings, new ListValue()); | |
2314 extension_dict->Set(kPrefIncognitoContentSettings, new ListValue()); | |
2315 } | |
2316 | |
2317 void ExtensionPrefs::FinishExtensionInfoPrefs( | |
2318 const std::string& extension_id, | |
2319 const base::Time install_time, | |
2320 bool needs_sort_ordinal, | |
2321 const syncer::StringOrdinal& suggested_page_ordinal, | |
2322 DictionaryValue* extension_dict) { | |
2323 // If this point has been reached, any pending installs should be considered | |
2324 // out of date. | |
2325 extension_dict->Remove(kIdleInstallInfo, NULL); | |
2326 | |
2327 // Clear state that may be registered from a previous install. | |
2328 extension_dict->Remove(kRegisteredEvents, NULL); | |
2329 | |
2330 // FYI, all code below here races on sudden shutdown because | |
2331 // |extension_dict|, |extension_sorting_|, |extension_pref_value_map_|, | |
2332 // and |content_settings_store_| are updated non-transactionally. This is | |
2333 // probably not fixable without nested transactional updates to pref | |
2334 // dictionaries. | |
2335 if (needs_sort_ordinal) { | |
2336 extension_sorting_->EnsureValidOrdinals(extension_id, | |
2337 suggested_page_ordinal); | |
2338 } | |
2339 | |
2340 int initial_state; | |
2341 if (extension_dict->GetInteger(kPrefState, &initial_state)) { | |
2342 /* RESOLVE ME BEFORE COMMIT: This conditional seems impossible to fail since | |
Marijn Kruisselbrink
2012/12/07 17:29:49
Isn't initial_state not set when its value would b
awong
2012/12/07 22:02:25
Oh interesting. Yeah, that came in via a last minu
Marijn Kruisselbrink
2012/12/07 22:15:09
It probably isn't right to skip these calls. OnExt
awong
2012/12/07 22:56:53
Added some logic that I *think* has the correct be
| |
2343 * SetIdleInstallInfo() sets it. Should we NOTREACHED() the failure of this | |
2344 * or are we supporting old prefs somehow? If we're supporting old prefs, | |
2345 * should we pick a default initial_state? | |
2346 */ | |
2347 extension_pref_value_map_->RegisterExtension( | |
2348 extension_id, install_time, initial_state == Extension::ENABLED); | |
2349 content_settings_store_->RegisterExtension( | |
2350 extension_id, install_time, initial_state == Extension::ENABLED); | |
2351 } | |
2352 } | |
2353 | |
2318 } // namespace extensions | 2354 } // namespace extensions |
OLD | NEW |