| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/enterprise/browser/reporting/policy_info.h" |
| |
| #include <string> |
| |
| #include "base/json/json_writer.h" |
| #include "build/build_config.h" |
| #include "build/chromeos_buildflags.h" |
| #include "components/policy/core/browser/policy_conversions.h" |
| #include "components/policy/core/common/cloud/cloud_policy_client.h" |
| #include "components/policy/core/common/cloud/cloud_policy_constants.h" |
| #include "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h" |
| #include "components/policy/core/common/policy_types.h" |
| #include "components/strings/grit/components_strings.h" |
| |
| namespace em = enterprise_management; |
| |
| namespace enterprise_reporting { |
| |
| namespace { |
| |
| em::Policy_PolicyLevel GetLevel(const base::Value& policy) { |
| switch (static_cast<policy::PolicyLevel>(*policy.FindIntKey("level"))) { |
| case policy::POLICY_LEVEL_RECOMMENDED: |
| return em::Policy_PolicyLevel_LEVEL_RECOMMENDED; |
| case policy::POLICY_LEVEL_MANDATORY: |
| return em::Policy_PolicyLevel_LEVEL_MANDATORY; |
| } |
| NOTREACHED() << "Invalid policy level: " << *policy.FindIntKey("level"); |
| return em::Policy_PolicyLevel_LEVEL_UNKNOWN; |
| } |
| |
| em::Policy_PolicyScope GetScope(const base::Value& policy) { |
| switch (static_cast<policy::PolicyScope>(*policy.FindIntKey("scope"))) { |
| case policy::POLICY_SCOPE_USER: |
| return em::Policy_PolicyScope_SCOPE_USER; |
| case policy::POLICY_SCOPE_MACHINE: |
| return em::Policy_PolicyScope_SCOPE_MACHINE; |
| } |
| NOTREACHED() << "Invalid policy scope: " << *policy.FindIntKey("scope"); |
| return em::Policy_PolicyScope_SCOPE_UNKNOWN; |
| } |
| |
| em::Policy_PolicySource GetSource(const base::Value& policy) { |
| switch (static_cast<policy::PolicySource>(*policy.FindIntKey("source"))) { |
| case policy::POLICY_SOURCE_ENTERPRISE_DEFAULT: |
| return em::Policy_PolicySource_SOURCE_ENTERPRISE_DEFAULT; |
| case policy::POLICY_SOURCE_COMMAND_LINE: |
| return em::Policy_PolicySource_SOURCE_COMMAND_LINE; |
| case policy::POLICY_SOURCE_CLOUD: |
| return em::Policy_PolicySource_SOURCE_CLOUD; |
| case policy::POLICY_SOURCE_ACTIVE_DIRECTORY: |
| return em::Policy_PolicySource_SOURCE_ACTIVE_DIRECTORY; |
| case policy::POLICY_SOURCE_DEVICE_LOCAL_ACCOUNT_OVERRIDE_DEPRECATED: |
| return em:: |
| Policy_PolicySource_SOURCE_DEVICE_LOCAL_ACCOUNT_OVERRIDE_DEPRECATED; |
| case policy::POLICY_SOURCE_PLATFORM: |
| return em::Policy_PolicySource_SOURCE_PLATFORM; |
| case policy::POLICY_SOURCE_PRIORITY_CLOUD: |
| return em::Policy_PolicySource_SOURCE_PRIORITY_CLOUD; |
| case policy::POLICY_SOURCE_MERGED: |
| return em::Policy_PolicySource_SOURCE_MERGED; |
| case policy::POLICY_SOURCE_CLOUD_FROM_ASH: |
| return em::Policy_PolicySource_SOURCE_CLOUD_FROM_ASH; |
| case policy::POLICY_SOURCE_COUNT: |
| NOTREACHED(); |
| return em::Policy_PolicySource_SOURCE_UNKNOWN; |
| } |
| NOTREACHED() << "Invalid policy source: " << *policy.FindIntKey("source"); |
| return em::Policy_PolicySource_SOURCE_UNKNOWN; |
| } |
| |
| void UpdatePolicyInfo(em::Policy* policy_info, |
| const std::string& policy_name, |
| const base::Value& policy) { |
| policy_info->set_name(policy_name); |
| policy_info->set_level(GetLevel(policy)); |
| policy_info->set_scope(GetScope(policy)); |
| policy_info->set_source(GetSource(policy)); |
| base::JSONWriter::Write(*policy.FindKey("value"), |
| policy_info->mutable_value()); |
| const std::string* error = policy.FindStringKey("error"); |
| std::string deprecated_error; |
| std::string future_error; |
| // Because server side use keyword "deprecated" to determine policy |
| // deprecation error. Using l10n string actually causing issue. |
| if (policy.FindBoolKey("deprecated")) |
| deprecated_error = "This policy has been deprecated"; |
| |
| if (policy.FindBoolKey("future")) |
| future_error = "This policy hasn't been released"; |
| |
| if (error && !deprecated_error.empty()) |
| policy_info->set_error( |
| base::JoinString({*error, deprecated_error, future_error}, "\n")); |
| else if (error) |
| policy_info->set_error(*error); |
| else if (!deprecated_error.empty()) |
| policy_info->set_error(deprecated_error); |
| } |
| |
| } // namespace |
| |
| void AppendChromePolicyInfoIntoProfileReport( |
| const base::Value& policies, |
| em::ChromeUserProfileInfo* profile_info) { |
| for (auto policy_iter : policies.FindKey("chromePolicies")->DictItems()) { |
| UpdatePolicyInfo(profile_info->add_chrome_policies(), policy_iter.first, |
| policy_iter.second); |
| } |
| } |
| |
| void AppendExtensionPolicyInfoIntoProfileReport( |
| const base::Value& policies, |
| em::ChromeUserProfileInfo* profile_info) { |
| if (!policies.FindKey("extensionPolicies")) { |
| // Android and iOS don't support extensions and their policies. |
| return; |
| } |
| |
| for (auto extension_iter : |
| policies.FindKey("extensionPolicies")->DictItems()) { |
| const base::Value& policies = extension_iter.second; |
| if (policies.DictSize() == 0) |
| continue; |
| auto* extension = profile_info->add_extension_policies(); |
| extension->set_extension_id(extension_iter.first); |
| for (auto policy_iter : policies.DictItems()) { |
| UpdatePolicyInfo(extension->add_policies(), policy_iter.first, |
| policy_iter.second); |
| } |
| } |
| } |
| |
| void AppendMachineLevelUserCloudPolicyFetchTimestamp( |
| em::ChromeUserProfileInfo* profile_info, |
| policy::MachineLevelUserCloudPolicyManager* manager) { |
| #if !BUILDFLAG(IS_CHROMEOS_ASH) |
| if (!manager || !manager->IsClientRegistered()) |
| return; |
| auto* timestamp = profile_info->add_policy_fetched_timestamps(); |
| timestamp->set_type( |
| policy::dm_protocol::kChromeMachineLevelExtensionCloudPolicyType); |
| timestamp->set_timestamp( |
| manager->core()->client()->last_policy_timestamp().ToJavaTime()); |
| #endif // !BUILDFLAG(IS_CHROMEOS_ASH) |
| } |
| |
| } // namespace enterprise_reporting |