| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/browser/extension_prefs.h" | 5 #include "extensions/browser/extension_prefs.h" |
| 6 | 6 |
| 7 #include <iterator> | 7 #include <iterator> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/prefs/pref_notifier.h" | 10 #include "base/prefs/pref_notifier.h" |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 // A preference that indicates whether the extension was installed as an | 175 // A preference that indicates whether the extension was installed as an |
| 176 // OEM app. | 176 // OEM app. |
| 177 const char kPrefWasInstalledByOem[] = "was_installed_by_oem"; | 177 const char kPrefWasInstalledByOem[] = "was_installed_by_oem"; |
| 178 | 178 |
| 179 // Key for Geometry Cache preference. | 179 // Key for Geometry Cache preference. |
| 180 const char kPrefGeometryCache[] = "geometry_cache"; | 180 const char kPrefGeometryCache[] = "geometry_cache"; |
| 181 | 181 |
| 182 // A preference that indicates when an extension is last launched. | 182 // A preference that indicates when an extension is last launched. |
| 183 const char kPrefLastLaunchTime[] = "last_launch_time"; | 183 const char kPrefLastLaunchTime[] = "last_launch_time"; |
| 184 | 184 |
| 185 // A preference that marks an ephemeral app that was evicted from the cache. | |
| 186 // Their data is retained and garbage collected when inactive for a long period | |
| 187 // of time. | |
| 188 const char kPrefEvictedEphemeralApp[] = "evicted_ephemeral_app"; | |
| 189 | |
| 190 // A preference indicating whether the extension is an ephemeral app. | 185 // A preference indicating whether the extension is an ephemeral app. |
| 191 const char kPrefEphemeralApp[] = "ephemeral_app"; | 186 const char kPrefEphemeralApp[] = "ephemeral_app"; |
| 192 | 187 |
| 193 // Am installation parameter bundled with an extension. | 188 // Am installation parameter bundled with an extension. |
| 194 const char kPrefInstallParam[] = "install_parameter"; | 189 const char kPrefInstallParam[] = "install_parameter"; |
| 195 | 190 |
| 196 // A list of installed ids and a signature. | 191 // A list of installed ids and a signature. |
| 197 const char kInstallSignature[] = "extensions.install_signature"; | 192 const char kInstallSignature[] = "extensions.install_signature"; |
| 198 | 193 |
| 199 // Provider of write access to a dictionary storing extension prefs. | 194 // Provider of write access to a dictionary storing extension prefs. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 230 } | 225 } |
| 231 | 226 |
| 232 // Checks if kPrefBlacklist is set to true in the base::DictionaryValue. | 227 // Checks if kPrefBlacklist is set to true in the base::DictionaryValue. |
| 233 // Return false if the value is false or kPrefBlacklist does not exist. | 228 // Return false if the value is false or kPrefBlacklist does not exist. |
| 234 // This is used to decide if an extension is blacklisted. | 229 // This is used to decide if an extension is blacklisted. |
| 235 bool IsBlacklistBitSet(const base::DictionaryValue* ext) { | 230 bool IsBlacklistBitSet(const base::DictionaryValue* ext) { |
| 236 bool bool_value; | 231 bool bool_value; |
| 237 return ext->GetBoolean(kPrefBlacklist, &bool_value) && bool_value; | 232 return ext->GetBoolean(kPrefBlacklist, &bool_value) && bool_value; |
| 238 } | 233 } |
| 239 | 234 |
| 240 bool IsEvictedEphemeralApp(const base::DictionaryValue* ext) { | |
| 241 bool bool_value; | |
| 242 return ext->GetBoolean(kPrefEvictedEphemeralApp, &bool_value) && bool_value; | |
| 243 } | |
| 244 | |
| 245 void LoadExtensionControlledPrefs(ExtensionPrefs* prefs, | 235 void LoadExtensionControlledPrefs(ExtensionPrefs* prefs, |
| 246 ExtensionPrefValueMap* value_map, | 236 ExtensionPrefValueMap* value_map, |
| 247 const std::string& extension_id, | 237 const std::string& extension_id, |
| 248 ExtensionPrefsScope scope) { | 238 ExtensionPrefsScope scope) { |
| 249 std::string scope_string; | 239 std::string scope_string; |
| 250 if (!pref_names::ScopeToPrefName(scope, &scope_string)) | 240 if (!pref_names::ScopeToPrefName(scope, &scope_string)) |
| 251 return; | 241 return; |
| 252 std::string key = extension_id + "." + scope_string; | 242 std::string key = extension_id + "." + scope_string; |
| 253 | 243 |
| 254 const base::DictionaryValue* source_dict = | 244 const base::DictionaryValue* source_dict = |
| (...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 // no longer lists the extension). | 1258 // no longer lists the extension). |
| 1269 if (!external_uninstall && Manifest::IsExternalLocation(location)) { | 1259 if (!external_uninstall && Manifest::IsExternalLocation(location)) { |
| 1270 UpdateExtensionPref(extension_id, kPrefState, | 1260 UpdateExtensionPref(extension_id, kPrefState, |
| 1271 new base::FundamentalValue( | 1261 new base::FundamentalValue( |
| 1272 Extension::EXTERNAL_EXTENSION_UNINSTALLED)); | 1262 Extension::EXTERNAL_EXTENSION_UNINSTALLED)); |
| 1273 extension_pref_value_map_->SetExtensionState(extension_id, false); | 1263 extension_pref_value_map_->SetExtensionState(extension_id, false); |
| 1274 FOR_EACH_OBSERVER(ExtensionPrefsObserver, | 1264 FOR_EACH_OBSERVER(ExtensionPrefsObserver, |
| 1275 observer_list_, | 1265 observer_list_, |
| 1276 OnExtensionStateChanged(extension_id, false)); | 1266 OnExtensionStateChanged(extension_id, false)); |
| 1277 } else { | 1267 } else { |
| 1278 if (IsEphemeralApp(extension_id)) { | 1268 DeleteExtensionPrefs(extension_id); |
| 1279 // Keep ephemeral apps around, but mark them as evicted. | |
| 1280 UpdateExtensionPref(extension_id, kPrefEvictedEphemeralApp, | |
| 1281 new base::FundamentalValue(true)); | |
| 1282 } else { | |
| 1283 DeleteExtensionPrefs(extension_id); | |
| 1284 } | |
| 1285 } | 1269 } |
| 1286 } | 1270 } |
| 1287 | 1271 |
| 1288 void ExtensionPrefs::SetExtensionState(const std::string& extension_id, | 1272 void ExtensionPrefs::SetExtensionState(const std::string& extension_id, |
| 1289 Extension::State state) { | 1273 Extension::State state) { |
| 1290 UpdateExtensionPref(extension_id, kPrefState, | 1274 UpdateExtensionPref(extension_id, kPrefState, |
| 1291 new base::FundamentalValue(state)); | 1275 new base::FundamentalValue(state)); |
| 1292 bool enabled = (state == Extension::ENABLED); | 1276 bool enabled = (state == Extension::ENABLED); |
| 1293 extension_pref_value_map_->SetExtensionState(extension_id, enabled); | 1277 extension_pref_value_map_->SetExtensionState(extension_id, enabled); |
| 1294 FOR_EACH_OBSERVER(ExtensionPrefsObserver, | 1278 FOR_EACH_OBSERVER(ExtensionPrefsObserver, |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1402 // Old preferences files may not have kPrefState for component extensions. | 1386 // Old preferences files may not have kPrefState for component extensions. |
| 1403 return scoped_ptr<ExtensionInfo>(); | 1387 return scoped_ptr<ExtensionInfo>(); |
| 1404 } | 1388 } |
| 1405 | 1389 |
| 1406 if (state_value == Extension::EXTERNAL_EXTENSION_UNINSTALLED) { | 1390 if (state_value == Extension::EXTERNAL_EXTENSION_UNINSTALLED) { |
| 1407 LOG(WARNING) << "External extension with id " << extension_id | 1391 LOG(WARNING) << "External extension with id " << extension_id |
| 1408 << " has been uninstalled by the user"; | 1392 << " has been uninstalled by the user"; |
| 1409 return scoped_ptr<ExtensionInfo>(); | 1393 return scoped_ptr<ExtensionInfo>(); |
| 1410 } | 1394 } |
| 1411 | 1395 |
| 1412 if (IsEvictedEphemeralApp(ext)) { | |
| 1413 // Hide evicted ephemeral apps. | |
| 1414 return scoped_ptr<ExtensionInfo>(); | |
| 1415 } | |
| 1416 | |
| 1417 return GetInstalledInfoHelper(extension_id, ext); | 1396 return GetInstalledInfoHelper(extension_id, ext); |
| 1418 } | 1397 } |
| 1419 | 1398 |
| 1420 scoped_ptr<ExtensionPrefs::ExtensionsInfo> | 1399 scoped_ptr<ExtensionPrefs::ExtensionsInfo> |
| 1421 ExtensionPrefs::GetInstalledExtensionsInfo() const { | 1400 ExtensionPrefs::GetInstalledExtensionsInfo() const { |
| 1422 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo); | 1401 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo); |
| 1423 | 1402 |
| 1424 const base::DictionaryValue* extensions = | 1403 const base::DictionaryValue* extensions = |
| 1425 prefs_->GetDictionary(pref_names::kExtensions); | 1404 prefs_->GetDictionary(pref_names::kExtensions); |
| 1426 for (base::DictionaryValue::Iterator extension_id(*extensions); | 1405 for (base::DictionaryValue::Iterator extension_id(*extensions); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1583 continue; | 1562 continue; |
| 1584 | 1563 |
| 1585 scoped_ptr<ExtensionInfo> info = GetDelayedInstallInfo(extension_id.key()); | 1564 scoped_ptr<ExtensionInfo> info = GetDelayedInstallInfo(extension_id.key()); |
| 1586 if (info) | 1565 if (info) |
| 1587 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release())); | 1566 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release())); |
| 1588 } | 1567 } |
| 1589 | 1568 |
| 1590 return extensions_info.Pass(); | 1569 return extensions_info.Pass(); |
| 1591 } | 1570 } |
| 1592 | 1571 |
| 1593 scoped_ptr<ExtensionPrefs::ExtensionsInfo> | |
| 1594 ExtensionPrefs::GetEvictedEphemeralAppsInfo() const { | |
| 1595 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo); | |
| 1596 | |
| 1597 const base::DictionaryValue* extensions = | |
| 1598 prefs_->GetDictionary(pref_names::kExtensions); | |
| 1599 for (base::DictionaryValue::Iterator extension_id(*extensions); | |
| 1600 !extension_id.IsAtEnd(); extension_id.Advance()) { | |
| 1601 const base::DictionaryValue* ext = NULL; | |
| 1602 if (!Extension::IdIsValid(extension_id.key()) || | |
| 1603 !extension_id.value().GetAsDictionary(&ext)) { | |
| 1604 continue; | |
| 1605 } | |
| 1606 | |
| 1607 if (!IsEvictedEphemeralApp(ext)) | |
| 1608 continue; | |
| 1609 | |
| 1610 scoped_ptr<ExtensionInfo> info = | |
| 1611 GetInstalledInfoHelper(extension_id.key(), ext); | |
| 1612 if (info) | |
| 1613 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release())); | |
| 1614 } | |
| 1615 | |
| 1616 return extensions_info.Pass(); | |
| 1617 } | |
| 1618 | |
| 1619 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetEvictedEphemeralAppInfo( | |
| 1620 const std::string& extension_id) const { | |
| 1621 const base::DictionaryValue* extension_prefs = GetExtensionPref(extension_id); | |
| 1622 if (!extension_prefs) | |
| 1623 return scoped_ptr<ExtensionInfo>(); | |
| 1624 | |
| 1625 if (!IsEvictedEphemeralApp(extension_prefs)) | |
| 1626 return scoped_ptr<ExtensionInfo>(); | |
| 1627 | |
| 1628 return GetInstalledInfoHelper(extension_id, extension_prefs); | |
| 1629 } | |
| 1630 | |
| 1631 void ExtensionPrefs::RemoveEvictedEphemeralApp( | |
| 1632 const std::string& extension_id) { | |
| 1633 if (ReadPrefAsBooleanAndReturn(extension_id, kPrefEvictedEphemeralApp)) | |
| 1634 DeleteExtensionPrefs(extension_id); | |
| 1635 } | |
| 1636 | |
| 1637 bool ExtensionPrefs::IsEphemeralApp(const std::string& extension_id) const { | 1572 bool ExtensionPrefs::IsEphemeralApp(const std::string& extension_id) const { |
| 1638 // Hide the data of evicted ephemeral apps. | |
| 1639 if (ReadPrefAsBooleanAndReturn(extension_id, kPrefEvictedEphemeralApp)) | |
| 1640 return false; | |
| 1641 | |
| 1642 if (ReadPrefAsBooleanAndReturn(extension_id, kPrefEphemeralApp)) | 1573 if (ReadPrefAsBooleanAndReturn(extension_id, kPrefEphemeralApp)) |
| 1643 return true; | 1574 return true; |
| 1644 | 1575 |
| 1645 // Ephemerality was previously stored in the creation flags, so we must also | 1576 // Ephemerality was previously stored in the creation flags, so we must also |
| 1646 // check it for backcompatibility. | 1577 // check it for backcompatibility. |
| 1647 return (GetCreationFlags(extension_id) & Extension::IS_EPHEMERAL) != 0; | 1578 return (GetCreationFlags(extension_id) & Extension::IS_EPHEMERAL) != 0; |
| 1648 } | 1579 } |
| 1649 | 1580 |
| 1650 void ExtensionPrefs::OnEphemeralAppPromoted(const std::string& extension_id) { | 1581 void ExtensionPrefs::OnEphemeralAppPromoted(const std::string& extension_id) { |
| 1651 DCHECK(IsEphemeralApp(extension_id)); | 1582 DCHECK(IsEphemeralApp(extension_id)); |
| 1652 | 1583 |
| 1653 ScopedExtensionPrefUpdate update(prefs_, extension_id); | 1584 UpdateExtensionPref( |
| 1654 update->Set(kPrefEphemeralApp, new base::FundamentalValue(false)); | 1585 extension_id, kPrefEphemeralApp, new base::FundamentalValue(false)); |
| 1655 | |
| 1656 DCHECK(!IsEvictedEphemeralApp(update.Get())); | |
| 1657 update->Remove(kPrefEvictedEphemeralApp, NULL); | |
| 1658 } | 1586 } |
| 1659 | 1587 |
| 1660 bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) { | 1588 bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) { |
| 1661 return ReadPrefAsBooleanAndReturn(extension_id, kPrefUserDraggedApp); | 1589 return ReadPrefAsBooleanAndReturn(extension_id, kPrefUserDraggedApp); |
| 1662 } | 1590 } |
| 1663 | 1591 |
| 1664 void ExtensionPrefs::SetAppDraggedByUser(const std::string& extension_id) { | 1592 void ExtensionPrefs::SetAppDraggedByUser(const std::string& extension_id) { |
| 1665 UpdateExtensionPref(extension_id, kPrefUserDraggedApp, | 1593 UpdateExtensionPref(extension_id, kPrefUserDraggedApp, |
| 1666 new base::FundamentalValue(true)); | 1594 new base::FundamentalValue(true)); |
| 1667 } | 1595 } |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2199 new base::ListValue); | 2127 new base::ListValue); |
| 2200 } | 2128 } |
| 2201 | 2129 |
| 2202 // If this point has been reached, any pending installs should be considered | 2130 // If this point has been reached, any pending installs should be considered |
| 2203 // out of date. | 2131 // out of date. |
| 2204 extension_dict->Remove(kDelayedInstallInfo, NULL); | 2132 extension_dict->Remove(kDelayedInstallInfo, NULL); |
| 2205 | 2133 |
| 2206 // Clear state that may be registered from a previous install. | 2134 // Clear state that may be registered from a previous install. |
| 2207 extension_dict->Remove(EventRouter::kRegisteredEvents, NULL); | 2135 extension_dict->Remove(EventRouter::kRegisteredEvents, NULL); |
| 2208 | 2136 |
| 2209 // When evicted ephemeral apps are re-installed, this flag must be reset. | |
| 2210 extension_dict->Remove(kPrefEvictedEphemeralApp, NULL); | |
| 2211 | |
| 2212 // FYI, all code below here races on sudden shutdown because |extension_dict|, | 2137 // FYI, all code below here races on sudden shutdown because |extension_dict|, |
| 2213 // |app_sorting_|, |extension_pref_value_map_|, and (potentially) observers | 2138 // |app_sorting_|, |extension_pref_value_map_|, and (potentially) observers |
| 2214 // are updated non-transactionally. This is probably not fixable without | 2139 // are updated non-transactionally. This is probably not fixable without |
| 2215 // nested transactional updates to pref dictionaries. | 2140 // nested transactional updates to pref dictionaries. |
| 2216 if (needs_sort_ordinal) | 2141 if (needs_sort_ordinal) |
| 2217 app_sorting_->EnsureValidOrdinals(extension_id, suggested_page_ordinal); | 2142 app_sorting_->EnsureValidOrdinals(extension_id, suggested_page_ordinal); |
| 2218 | 2143 |
| 2219 bool is_enabled = false; | 2144 bool is_enabled = false; |
| 2220 int initial_state; | 2145 int initial_state; |
| 2221 if (extension_dict->GetInteger(kPrefState, &initial_state)) { | 2146 if (extension_dict->GetInteger(kPrefState, &initial_state)) { |
| 2222 is_enabled = initial_state == Extension::ENABLED; | 2147 is_enabled = initial_state == Extension::ENABLED; |
| 2223 } | 2148 } |
| 2224 bool is_incognito_enabled = IsIncognitoEnabled(extension_id); | 2149 bool is_incognito_enabled = IsIncognitoEnabled(extension_id); |
| 2225 | 2150 |
| 2226 extension_pref_value_map_->RegisterExtension( | 2151 extension_pref_value_map_->RegisterExtension( |
| 2227 extension_id, install_time, is_enabled, is_incognito_enabled); | 2152 extension_id, install_time, is_enabled, is_incognito_enabled); |
| 2228 | 2153 |
| 2229 FOR_EACH_OBSERVER( | 2154 FOR_EACH_OBSERVER( |
| 2230 ExtensionPrefsObserver, | 2155 ExtensionPrefsObserver, |
| 2231 observer_list_, | 2156 observer_list_, |
| 2232 OnExtensionRegistered(extension_id, install_time, is_enabled)); | 2157 OnExtensionRegistered(extension_id, install_time, is_enabled)); |
| 2233 } | 2158 } |
| 2234 | 2159 |
| 2235 } // namespace extensions | 2160 } // namespace extensions |
| OLD | NEW |