OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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_service.h" | 5 #include "chrome/browser/extensions/extension_service.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <iterator> | 8 #include <iterator> |
9 #include <set> | 9 #include <set> |
10 | 10 |
(...skipping 848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 } | 859 } |
860 | 860 |
861 const Extension* extension = GetInstalledExtension(extension_id); | 861 const Extension* extension = GetInstalledExtension(extension_id); |
862 // |extension| can be NULL if sync disables an extension that is not | 862 // |extension| can be NULL if sync disables an extension that is not |
863 // installed yet. | 863 // installed yet. |
864 // EXTERNAL_COMPONENT extensions are not generally modifiable by users, but | 864 // EXTERNAL_COMPONENT extensions are not generally modifiable by users, but |
865 // can be uninstalled by the browser if the user sets extension-specific | 865 // can be uninstalled by the browser if the user sets extension-specific |
866 // preferences. | 866 // preferences. |
867 if (extension && | 867 if (extension && |
868 disable_reason != Extension::DISABLE_RELOAD && | 868 disable_reason != Extension::DISABLE_RELOAD && |
| 869 disable_reason != Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY && |
869 !system_->management_policy()->UserMayModifySettings(extension, NULL) && | 870 !system_->management_policy()->UserMayModifySettings(extension, NULL) && |
870 extension->location() != Manifest::EXTERNAL_COMPONENT) { | 871 extension->location() != Manifest::EXTERNAL_COMPONENT) { |
871 return; | 872 return; |
872 } | 873 } |
873 | 874 |
874 extension_prefs_->SetExtensionState(extension_id, Extension::DISABLED); | 875 extension_prefs_->SetExtensionState(extension_id, Extension::DISABLED); |
875 extension_prefs_->AddDisableReason(extension_id, disable_reason); | 876 extension_prefs_->AddDisableReason(extension_id, disable_reason); |
876 | 877 |
877 int include_mask = | 878 int include_mask = |
878 ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::DISABLED; | 879 ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::DISABLED; |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1159 file_task_runner_ = BrowserThread::GetBlockingPool()-> | 1160 file_task_runner_ = BrowserThread::GetBlockingPool()-> |
1160 GetSequencedTaskRunnerWithShutdownBehavior( | 1161 GetSequencedTaskRunnerWithShutdownBehavior( |
1161 BrowserThread::GetBlockingPool()->GetNamedSequenceToken(token), | 1162 BrowserThread::GetBlockingPool()->GetNamedSequenceToken(token), |
1162 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); | 1163 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
1163 return file_task_runner_.get(); | 1164 return file_task_runner_.get(); |
1164 } | 1165 } |
1165 | 1166 |
1166 void ExtensionService::CheckManagementPolicy() { | 1167 void ExtensionService::CheckManagementPolicy() { |
1167 std::vector<std::string> to_unload; | 1168 std::vector<std::string> to_unload; |
1168 std::map<std::string, Extension::DisableReason> to_disable; | 1169 std::map<std::string, Extension::DisableReason> to_disable; |
| 1170 std::vector<std::string> to_enable; |
1169 | 1171 |
1170 // Loop through the extensions list, finding extensions we need to unload or | 1172 // Loop through the extensions list, finding extensions we need to unload or |
1171 // disable. | 1173 // disable. |
1172 const ExtensionSet& extensions = registry_->enabled_extensions(); | 1174 for (scoped_refptr<const Extension> extension : |
1173 for (ExtensionSet::const_iterator iter = extensions.begin(); | 1175 registry_->enabled_extensions()) { |
1174 iter != extensions.end(); ++iter) { | 1176 if (!system_->management_policy()->UserMayLoad(extension.get(), nullptr)) |
1175 const Extension* extension = (iter->get()); | |
1176 if (!system_->management_policy()->UserMayLoad(extension, NULL)) | |
1177 to_unload.push_back(extension->id()); | 1177 to_unload.push_back(extension->id()); |
1178 Extension::DisableReason disable_reason = Extension::DISABLE_NONE; | 1178 Extension::DisableReason disable_reason = Extension::DISABLE_NONE; |
1179 if (system_->management_policy()->MustRemainDisabled( | 1179 if (system_->management_policy()->MustRemainDisabled( |
1180 extension, &disable_reason, NULL)) | 1180 extension.get(), &disable_reason, nullptr)) |
1181 to_disable[extension->id()] = disable_reason; | 1181 to_disable[extension->id()] = disable_reason; |
1182 } | 1182 } |
1183 | 1183 |
1184 for (size_t i = 0; i < to_unload.size(); ++i) | 1184 extensions::ExtensionManagement* management = |
1185 UnloadExtension(to_unload[i], UnloadedExtensionInfo::REASON_DISABLE); | 1185 extensions::ExtensionManagementFactory::GetForBrowserContext(profile()); |
| 1186 |
| 1187 // Loop through the disabled extension list, find extensions to re-enable |
| 1188 // automatically. These extensions are exclusive from the |to_disable| and |
| 1189 // |to_unload| lists constructed above, since disabled_extensions() and |
| 1190 // enabled_extensions() are supposed to be mutually exclusive. |
| 1191 for (scoped_refptr<const Extension> extension : |
| 1192 registry_->disabled_extensions()) { |
| 1193 // Find all disabled extensions disabled due to minimum version requirement, |
| 1194 // but now satisfying it. |
| 1195 if (management->CheckMinimumVersion(extension.get(), nullptr) && |
| 1196 extension_prefs_->HasDisableReason( |
| 1197 extension->id(), Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY)) { |
| 1198 // Is DISABLE_UPDATE_REQUIRED_BY_POLICY the *only* reason? |
| 1199 if (extension_prefs_->GetDisableReasons(extension->id()) == |
| 1200 Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY) { |
| 1201 // We need to enable those disabled *only* due to minimum version |
| 1202 // requirement. |
| 1203 to_enable.push_back(extension->id()); |
| 1204 } |
| 1205 extension_prefs_->RemoveDisableReason( |
| 1206 extension->id(), Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY); |
| 1207 } |
| 1208 } |
| 1209 |
| 1210 for (const std::string& id : to_unload) |
| 1211 UnloadExtension(id, UnloadedExtensionInfo::REASON_DISABLE); |
1186 | 1212 |
1187 for (std::map<std::string, Extension::DisableReason>::const_iterator i = | 1213 for (std::map<std::string, Extension::DisableReason>::const_iterator i = |
1188 to_disable.begin(); i != to_disable.end(); ++i) | 1214 to_disable.begin(); i != to_disable.end(); ++i) |
1189 DisableExtension(i->first, i->second); | 1215 DisableExtension(i->first, i->second); |
| 1216 |
| 1217 // No extension is getting re-enabled here after disabling/unloading |
| 1218 // because to_enable is mutually exclusive to to_disable + to_unload. |
| 1219 for (const std::string& id : to_enable) |
| 1220 EnableExtension(id); |
| 1221 |
| 1222 if (updater_.get()) { |
| 1223 // Find all extensions disabled due to minimum version requirement from |
| 1224 // policy (including the ones that got disabled just now), and check |
| 1225 // for update. |
| 1226 extensions::ExtensionUpdater::CheckParams to_recheck; |
| 1227 for (scoped_refptr<const Extension> extension : |
| 1228 registry_->disabled_extensions()) { |
| 1229 if (extension_prefs_->GetDisableReasons(extension->id()) == |
| 1230 Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY) { |
| 1231 // The minimum version check is the only thing holding this extension |
| 1232 // back, so check if it can be updated to fix that. |
| 1233 to_recheck.ids.push_back(extension->id()); |
| 1234 } |
| 1235 } |
| 1236 if (!to_recheck.ids.empty()) |
| 1237 updater_->CheckNow(to_recheck); |
| 1238 } |
1190 } | 1239 } |
1191 | 1240 |
1192 void ExtensionService::CheckForUpdatesSoon() { | 1241 void ExtensionService::CheckForUpdatesSoon() { |
1193 // This can legitimately happen in unit tests. | 1242 // This can legitimately happen in unit tests. |
1194 if (!updater_.get()) | 1243 if (!updater_.get()) |
1195 return; | 1244 return; |
1196 | 1245 |
1197 if (AreAllExternalProvidersReady()) { | 1246 if (AreAllExternalProvidersReady()) { |
1198 updater_->CheckSoon(); | 1247 updater_->CheckSoon(); |
1199 } else { | 1248 } else { |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1659 // extension; if we're here, that means the user is manually | 1708 // extension; if we're here, that means the user is manually |
1660 // installing the extension. | 1709 // installing the extension. |
1661 if (extension_prefs_->IsExternalExtensionUninstalled(id)) { | 1710 if (extension_prefs_->IsExternalExtensionUninstalled(id)) { |
1662 disable_reasons = Extension::DISABLE_NONE; | 1711 disable_reasons = Extension::DISABLE_NONE; |
1663 } | 1712 } |
1664 } | 1713 } |
1665 | 1714 |
1666 // Unsupported requirements overrides the management policy. | 1715 // Unsupported requirements overrides the management policy. |
1667 if (install_flags & extensions::kInstallFlagHasRequirementErrors) { | 1716 if (install_flags & extensions::kInstallFlagHasRequirementErrors) { |
1668 disable_reasons |= Extension::DISABLE_UNSUPPORTED_REQUIREMENT; | 1717 disable_reasons |= Extension::DISABLE_UNSUPPORTED_REQUIREMENT; |
1669 // If the extension was disabled because of unsupported requirements but | 1718 } else { |
1670 // now supports all requirements after an update and there are not other | 1719 // Requirement is supported now, remove the corresponding disable reason |
1671 // disable reasons, enable it. | 1720 // instead. |
1672 } else if (extension_prefs_->GetDisableReasons(id) == | 1721 extension_prefs_->RemoveDisableReason( |
1673 Extension::DISABLE_UNSUPPORTED_REQUIREMENT) { | 1722 id, Extension::DISABLE_UNSUPPORTED_REQUIREMENT); |
1674 disable_reasons = Extension::DISABLE_NONE; | 1723 disable_reasons &= ~Extension::DISABLE_UNSUPPORTED_REQUIREMENT; |
1675 extension_prefs_->ClearDisableReasons(id); | 1724 } |
| 1725 |
| 1726 // Check if the extension was disabled because of the minimum version |
| 1727 // requirements from enterprise policy, and satisfies it now. |
| 1728 if (extensions::ExtensionManagementFactory::GetForBrowserContext(profile()) |
| 1729 ->CheckMinimumVersion(extension, nullptr)) { |
| 1730 // And remove the corresponding disable reason. |
| 1731 extension_prefs_->RemoveDisableReason( |
| 1732 id, Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY); |
| 1733 disable_reasons &= ~Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY; |
1676 } | 1734 } |
1677 | 1735 |
1678 if (install_flags & extensions::kInstallFlagIsBlacklistedForMalware) { | 1736 if (install_flags & extensions::kInstallFlagIsBlacklistedForMalware) { |
1679 // Installation of a blacklisted extension can happen from sync, policy, | 1737 // Installation of a blacklisted extension can happen from sync, policy, |
1680 // etc, where to maintain consistency we need to install it, just never | 1738 // etc, where to maintain consistency we need to install it, just never |
1681 // load it (see AddExtension). Usually it should be the job of callers to | 1739 // load it (see AddExtension). Usually it should be the job of callers to |
1682 // incercept blacklisted extension earlier (e.g. CrxInstaller, before even | 1740 // incercept blacklisted extension earlier (e.g. CrxInstaller, before even |
1683 // showing the install dialogue). | 1741 // showing the install dialogue). |
1684 extension_prefs_->AcknowledgeBlacklistedExtension(id); | 1742 extension_prefs_->AcknowledgeBlacklistedExtension(id); |
1685 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.SilentInstall", | 1743 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.SilentInstall", |
(...skipping 785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2471 } | 2529 } |
2472 | 2530 |
2473 void ExtensionService::OnProfileDestructionStarted() { | 2531 void ExtensionService::OnProfileDestructionStarted() { |
2474 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); | 2532 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); |
2475 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); | 2533 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); |
2476 it != ids_to_unload.end(); | 2534 it != ids_to_unload.end(); |
2477 ++it) { | 2535 ++it) { |
2478 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); | 2536 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); |
2479 } | 2537 } |
2480 } | 2538 } |
OLD | NEW |