| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/updater/policy/policy_manager.h" |
| |
| #include <algorithm> |
| #include <optional> |
| #include <string> |
| #include <string_view> |
| #include <vector> |
| |
| #include "base/containers/flat_set.h" |
| #include "base/logging.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/strings/strcat.h" |
| #include "base/strings/string_util.h" |
| #include "base/values.h" |
| #include "chrome/updater/policy/manager.h" |
| #include "chrome/updater/updater_scope.h" |
| |
| namespace updater { |
| |
| namespace { |
| |
| constexpr char kCloudPolicyOverridesPlatformPolicy[] = |
| "CloudPolicyOverridesPlatformPolicy"; |
| |
| // Preferences Category. |
| constexpr char kAutoUpdateCheckPeriodOverrideMinutes[] = |
| "AutoUpdateCheckPeriodMinutes"; |
| constexpr char kUpdatesSuppressedStartHour[] = "UpdatesSuppressedStartHour"; |
| constexpr char kUpdatesSuppressedStartMin[] = "UpdatesSuppressedStartMin"; |
| constexpr char kUpdatesSuppressedDurationMin[] = "UpdatesSuppressedDurationMin"; |
| |
| // This policy specifies what kind of download URLs could be returned to the |
| // client in the update response and in which order of priority. The client |
| // provides this information in the update request as a hint for the server. |
| // The server may decide to ignore the hint. As a general idea, some urls are |
| // cacheable, some urls have higher bandwidth, and some urls are slightly more |
| // secure since they are https. |
| constexpr char kDownloadPreference[] = "DownloadPreference"; |
| |
| // Proxy Server Category. (The keys used, and the values of ProxyMode, |
| // directly mirror that of Chrome. However, we omit ProxyBypassList, as the |
| // domains that Omaha uses are largely fixed.) |
| constexpr char kProxyMode[] = "ProxyMode"; |
| constexpr char kProxyServer[] = "ProxyServer"; |
| constexpr char kProxyPacUrl[] = "ProxyPacUrl"; |
| |
| // Package cache constants. |
| constexpr char kCacheSizeLimitMBytes[] = "PackageCacheSizeLimit"; |
| constexpr char kCacheLifeLimitDays[] = "PackageCacheLifeLimit"; |
| |
| // Applications Category. |
| // The prefix strings have the app's GUID appended to them. |
| constexpr char kInstallAppsDefault[] = "installdefault"; |
| constexpr char kInstallAppPrefix[] = "install"; |
| constexpr char kUpdateAppsDefault[] = "updatedefault"; |
| constexpr char kUpdateAppPrefix[] = "update"; |
| constexpr char kTargetVersionPrefix[] = "targetversionprefix"; |
| constexpr char kTargetChannel[] = "targetchannel"; |
| constexpr char kRollbackToTargetVersion[] = "RollbackToTargetVersion"; |
| constexpr char kMajorVersionRolloutPrefix[] = "MajorVersionRollout"; |
| constexpr char kMinorVersionRolloutPrefix[] = "MinorVersionRollout"; |
| |
| } // namespace |
| |
| PolicyManager::PolicyManager(base::Value::Dict policies) |
| : policies_(std::move(policies)) { |
| static constexpr size_t kInstallAppPrefixLength = |
| std::string_view(kInstallAppPrefix).length(); |
| std::ranges::for_each(policies_, [&](const auto& policy) { |
| const std::string policy_name = policy.first; |
| VLOG_IF(1, policy_name != base::ToLowerASCII(policy_name)) |
| << "Policy [" << policy_name |
| << "] is ignored because it's not all lower-case."; |
| if (policy_name.length() <= kInstallAppPrefixLength || |
| !base::StartsWith(policy_name, kInstallAppPrefix, |
| base::CompareCase::INSENSITIVE_ASCII) || |
| base::StartsWith(policy_name, kInstallAppsDefault, |
| base::CompareCase::INSENSITIVE_ASCII) || |
| !policy.second.is_int()) { |
| return; |
| } |
| |
| if (policy.second.GetInt() != (IsSystemInstall() |
| ? kPolicyForceInstallMachine |
| : kPolicyForceInstallUser)) { |
| return; |
| } |
| |
| force_install_apps_.push_back(policy_name.substr(kInstallAppPrefixLength)); |
| }); |
| } |
| |
| PolicyManager::~PolicyManager() = default; |
| |
| std::optional<bool> PolicyManager::CloudPolicyOverridesPlatformPolicy() const { |
| std::optional<int> policy = |
| GetIntegerPolicy(kCloudPolicyOverridesPlatformPolicy); |
| return policy ? std::optional<bool>(policy.value()) : std::nullopt; |
| } |
| |
| bool PolicyManager::HasActiveDevicePolicies() const { |
| return true; |
| } |
| |
| std::string PolicyManager::source() const { |
| return kSourceDictValuesPolicyManager; |
| } |
| |
| std::optional<base::TimeDelta> PolicyManager::GetLastCheckPeriod() const { |
| std::optional<int> minutes = |
| GetIntegerPolicy(kAutoUpdateCheckPeriodOverrideMinutes); |
| if (!minutes) { |
| return std::nullopt; |
| } |
| return base::Minutes(*minutes); |
| } |
| |
| std::optional<UpdatesSuppressedTimes> PolicyManager::GetUpdatesSuppressedTimes() |
| const { |
| std::optional<int> start_hour = GetIntegerPolicy(kUpdatesSuppressedStartHour); |
| std::optional<int> start_min = GetIntegerPolicy(kUpdatesSuppressedStartMin); |
| std::optional<int> duration_min = |
| GetIntegerPolicy(kUpdatesSuppressedDurationMin); |
| |
| if (!start_hour || !start_min || !duration_min) { |
| return std::nullopt; |
| } |
| |
| UpdatesSuppressedTimes supressed_times; |
| supressed_times.start_hour_ = start_hour.value(); |
| supressed_times.start_minute_ = start_min.value(); |
| supressed_times.duration_minute_ = duration_min.value(); |
| return supressed_times; |
| } |
| |
| std::optional<std::string> PolicyManager::GetDownloadPreference() const { |
| return GetStringPolicy(kDownloadPreference); |
| } |
| |
| std::optional<int> PolicyManager::GetPackageCacheSizeLimitMBytes() const { |
| return GetIntegerPolicy(kCacheSizeLimitMBytes); |
| } |
| |
| std::optional<int> PolicyManager::GetPackageCacheExpirationTimeDays() const { |
| return GetIntegerPolicy(kCacheLifeLimitDays); |
| } |
| |
| std::optional<int> PolicyManager::GetEffectivePolicyForAppInstalls( |
| const std::string& app_id) const { |
| std::optional<int> policy = |
| GetIntegerPolicy(base::StrCat({kInstallAppPrefix, app_id})); |
| return policy ? policy : GetIntegerPolicy(kInstallAppsDefault); |
| } |
| |
| std::optional<int> PolicyManager::GetEffectivePolicyForAppUpdates( |
| const std::string& app_id) const { |
| std::optional<int> policy = |
| GetIntegerPolicy(base::StrCat({kUpdateAppPrefix, app_id})); |
| return policy ? policy : GetIntegerPolicy(kUpdateAppsDefault); |
| } |
| |
| std::optional<std::string> PolicyManager::GetTargetChannel( |
| const std::string& app_id) const { |
| return GetStringPolicy(base::StrCat({kTargetChannel, app_id})); |
| } |
| |
| std::optional<std::string> PolicyManager::GetTargetVersionPrefix( |
| const std::string& app_id) const { |
| return GetStringPolicy(base::StrCat({kTargetVersionPrefix, app_id})); |
| } |
| |
| std::optional<bool> PolicyManager::IsRollbackToTargetVersionAllowed( |
| const std::string& app_id) const { |
| std::optional<int> policy = |
| GetIntegerPolicy(base::StrCat({kRollbackToTargetVersion, app_id})); |
| return policy ? std::optional<bool>(policy.value()) : std::nullopt; |
| } |
| |
| std::optional<int> PolicyManager::GetMajorVersionRolloutPolicy( |
| const std::string& app_id) const { |
| return GetIntegerPolicy(base::StrCat({kMajorVersionRolloutPrefix, app_id})); |
| } |
| |
| std::optional<int> PolicyManager::GetMinorVersionRolloutPolicy( |
| const std::string& app_id) const { |
| return GetIntegerPolicy(base::StrCat({kMinorVersionRolloutPrefix, app_id})); |
| } |
| |
| std::optional<std::string> PolicyManager::GetProxyMode() const { |
| return GetStringPolicy(kProxyMode); |
| } |
| |
| std::optional<std::string> PolicyManager::GetProxyPacUrl() const { |
| return GetStringPolicy(kProxyPacUrl); |
| } |
| |
| std::optional<std::string> PolicyManager::GetProxyServer() const { |
| return GetStringPolicy(kProxyServer); |
| } |
| |
| std::optional<std::vector<std::string>> PolicyManager::GetForceInstallApps() |
| const { |
| return force_install_apps_.empty() ? std::optional<std::vector<std::string>>() |
| : force_install_apps_; |
| } |
| |
| std::optional<std::vector<std::string>> PolicyManager::GetAppsWithPolicy() |
| const { |
| const base::flat_set<std::string> prefixed_policy_names = { |
| // prefixed by kUpdateAppPrefix: |
| base::ToLowerASCII(kUpdatesSuppressedStartHour), |
| base::ToLowerASCII(kUpdatesSuppressedStartMin), |
| base::ToLowerASCII(kUpdatesSuppressedDurationMin), |
| }; |
| static constexpr const char* kAppPolicyPrefixes[] = { |
| kInstallAppsDefault, kInstallAppPrefix, |
| kUpdateAppsDefault, kUpdateAppPrefix, |
| kTargetVersionPrefix, kTargetChannel, |
| kRollbackToTargetVersion, kMajorVersionRolloutPrefix, |
| kMinorVersionRolloutPrefix}; |
| std::vector<std::string> apps_with_policy; |
| std::ranges::for_each(policies_, [&](const auto& policy) { |
| const std::string policy_name = policy.first; |
| std::ranges::for_each(kAppPolicyPrefixes, [&](const auto& prefix) { |
| if (base::StartsWith(policy_name, base::ToLowerASCII(prefix)) && |
| !prefixed_policy_names.contains(policy_name)) { |
| apps_with_policy.push_back( |
| policy_name.substr(std::string_view(prefix).length())); |
| } |
| }); |
| }); |
| |
| return apps_with_policy; |
| } |
| |
| std::optional<int> PolicyManager::GetIntegerPolicy( |
| const std::string& key) const { |
| return policies_.FindInt(base::ToLowerASCII(key)); |
| } |
| |
| std::optional<std::string> PolicyManager::GetStringPolicy( |
| const std::string& key) const { |
| const std::string* policy = policies_.FindString(base::ToLowerASCII(key)); |
| return policy ? std::make_optional(*policy) : std::nullopt; |
| } |
| |
| scoped_refptr<PolicyManagerInterface> CreateDictPolicyManager( |
| base::Value::Dict policies) { |
| return policies.empty() |
| ? nullptr |
| : base::MakeRefCounted<PolicyManager>(std::move(policies)); |
| } |
| |
| } // namespace updater |