summaryrefslogtreecommitdiff
path: root/chromium/components/policy/core/common/policy_loader_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/policy/core/common/policy_loader_mac.mm')
-rw-r--r--chromium/components/policy/core/common/policy_loader_mac.mm254
1 files changed, 254 insertions, 0 deletions
diff --git a/chromium/components/policy/core/common/policy_loader_mac.mm b/chromium/components/policy/core/common/policy_loader_mac.mm
new file mode 100644
index 00000000000..b717d39fbf1
--- /dev/null
+++ b/chromium/components/policy/core/common/policy_loader_mac.mm
@@ -0,0 +1,254 @@
+// Copyright (c) 2015 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/policy/core/common/policy_loader_mac.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/enterprise_util.h"
+#include "base/feature_list.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/mac/foundation_util.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "components/policy/core/common/external_data_fetcher.h"
+#include "components/policy/core/common/features.h"
+#include "components/policy/core/common/mac_util.h"
+#include "components/policy/core/common/policy_bundle.h"
+#include "components/policy/core/common/policy_load_status.h"
+#include "components/policy/core/common/policy_loader_common.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/core/common/preferences_mac.h"
+#include "components/policy/core/common/schema.h"
+#include "components/policy/core/common/schema_map.h"
+
+using base::ScopedCFTypeRef;
+
+namespace policy {
+
+namespace {
+
+// Encapsulates logic to determine if enterprise policies should be honored.
+bool ShouldHonorPolicies() {
+ // Only honor sensitive policies if the Mac is managed externally.
+ base::DeviceUserDomainJoinState join_state =
+ base::AreDeviceAndUserJoinedToDomain();
+ if (join_state.device_joined)
+ return true;
+
+ // IsDeviceRegisteredWithManagementNew is only available after 10.13.4.
+ // Eventually switch to it when that is the minimum OS required by Chromium.
+ if (@available(macOS 10.13.4, *)) {
+ base::MacDeviceManagementStateNew mdm_state =
+ base::IsDeviceRegisteredWithManagementNew();
+ return mdm_state ==
+ base::MacDeviceManagementStateNew::kLimitedMDMEnrollment ||
+ mdm_state == base::MacDeviceManagementStateNew::kFullMDMEnrollment ||
+ mdm_state == base::MacDeviceManagementStateNew::kDEPMDMEnrollment;
+ }
+ base::MacDeviceManagementStateOld mdm_state =
+ base::IsDeviceRegisteredWithManagementOld();
+ return mdm_state == base::MacDeviceManagementStateOld::kMDMEnrollment;
+}
+
+} // namespace
+
+PolicyLoaderMac::PolicyLoaderMac(
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ const base::FilePath& managed_policy_path,
+ MacPreferences* preferences)
+ : PolicyLoaderMac(task_runner,
+ managed_policy_path,
+ preferences,
+ kCFPreferencesCurrentApplication) {}
+
+PolicyLoaderMac::PolicyLoaderMac(
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ const base::FilePath& managed_policy_path,
+ MacPreferences* preferences,
+ CFStringRef application_id)
+ : AsyncPolicyLoader(task_runner, /*periodic_updates=*/true),
+ preferences_(preferences),
+ managed_policy_path_(managed_policy_path),
+ application_id_(CFStringCreateCopy(kCFAllocatorDefault, application_id)) {
+}
+
+PolicyLoaderMac::~PolicyLoaderMac() {
+}
+
+void PolicyLoaderMac::InitOnBackgroundThread() {
+ if (!managed_policy_path_.empty()) {
+ watcher_.Watch(managed_policy_path_,
+ base::FilePathWatcher::Type::kNonRecursive,
+ base::BindRepeating(&PolicyLoaderMac::OnFileUpdated,
+ base::Unretained(this)));
+ }
+
+ base::File::Info file_info;
+ bool managed_policy_file_exists = false;
+ if (base::GetFileInfo(managed_policy_path_, &file_info) &&
+ !file_info.is_directory) {
+ managed_policy_file_exists = true;
+ }
+
+ base::UmaHistogramBoolean("EnterpriseCheck.IsManaged2",
+ managed_policy_file_exists);
+ base::UmaHistogramBoolean("EnterpriseCheck.IsEnterpriseUser",
+ base::IsMachineExternallyManaged());
+
+ base::UmaHistogramEnumeration("EnterpriseCheck.Mac.IsDeviceMDMEnrolledOld",
+ base::IsDeviceRegisteredWithManagementOld());
+ base::UmaHistogramEnumeration("EnterpriseCheck.Mac.IsDeviceMDMEnrolledNew",
+ base::IsDeviceRegisteredWithManagementNew());
+ base::DeviceUserDomainJoinState state =
+ base::AreDeviceAndUserJoinedToDomain();
+ base::UmaHistogramBoolean("EnterpriseCheck.Mac.IsDeviceDomainJoined",
+ state.device_joined);
+ base::UmaHistogramBoolean("EnterpriseCheck.Mac.IsCurrentUserDomainUser",
+ state.user_joined);
+}
+
+std::unique_ptr<PolicyBundle> PolicyLoaderMac::Load() {
+ preferences_->AppSynchronize(application_id_);
+ std::unique_ptr<PolicyBundle> bundle(new PolicyBundle());
+
+ // Load Chrome's policy.
+ PolicyMap& chrome_policy =
+ bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
+
+ PolicyLoadStatusUmaReporter status;
+ bool policy_present = false;
+ const Schema* schema =
+ schema_map()->GetSchema(PolicyNamespace(POLICY_DOMAIN_CHROME, ""));
+ for (Schema::Iterator it = schema->GetPropertiesIterator(); !it.IsAtEnd();
+ it.Advance()) {
+ base::ScopedCFTypeRef<CFStringRef> name(
+ base::SysUTF8ToCFStringRef(it.key()));
+ base::ScopedCFTypeRef<CFPropertyListRef> value(
+ preferences_->CopyAppValue(name, application_id_));
+ if (!value)
+ continue;
+ policy_present = true;
+ bool forced = preferences_->AppValueIsForced(name, application_id_);
+ PolicyLevel level =
+ forced ? POLICY_LEVEL_MANDATORY : POLICY_LEVEL_RECOMMENDED;
+ // TODO(joaodasilva): figure the policy scope.
+ std::unique_ptr<base::Value> policy = PropertyToValue(value);
+ if (policy) {
+ chrome_policy.Set(it.key(), level, POLICY_SCOPE_MACHINE,
+ POLICY_SOURCE_PLATFORM, std::move(*policy), nullptr);
+ } else {
+ status.Add(POLICY_LOAD_STATUS_PARSE_ERROR);
+ }
+ }
+
+ if (!policy_present)
+ status.Add(POLICY_LOAD_STATUS_NO_POLICY);
+
+ // Load policy for the registered components.
+ LoadPolicyForDomain(POLICY_DOMAIN_EXTENSIONS, "extensions", bundle.get());
+
+ if (!ShouldHonorPolicies())
+ FilterSensitivePolicies(&chrome_policy);
+
+ return bundle;
+}
+
+base::Time PolicyLoaderMac::LastModificationTime() {
+ base::File::Info file_info;
+ if (!base::GetFileInfo(managed_policy_path_, &file_info) ||
+ file_info.is_directory) {
+ return base::Time();
+ }
+
+ return file_info.last_modified;
+}
+
+#if BUILDFLAG(IS_MAC)
+
+base::FilePath PolicyLoaderMac::GetManagedPolicyPath(CFStringRef bundle_id) {
+ // This constructs the path to the plist file in which Mac OS X stores the
+ // managed preference for the application. This is undocumented and therefore
+ // fragile, but if it doesn't work out, AsyncPolicyLoader has a task that
+ // polls periodically in order to reload managed preferences later even if we
+ // missed the change.
+
+ base::FilePath path;
+ if (!base::mac::GetLocalDirectory(NSLibraryDirectory, &path))
+ return base::FilePath();
+ path = path.Append(FILE_PATH_LITERAL("Managed Preferences"));
+ char* login = getlogin();
+ if (!login)
+ return base::FilePath();
+ path = path.AppendASCII(login);
+ return path.Append(base::SysCFStringRefToUTF8(bundle_id) + ".plist");
+}
+
+#endif
+
+void PolicyLoaderMac::LoadPolicyForDomain(PolicyDomain domain,
+ const std::string& domain_name,
+ PolicyBundle* bundle) {
+ std::string id_prefix(base::SysCFStringRefToUTF8(application_id_));
+ id_prefix.append(".").append(domain_name).append(".");
+
+ const ComponentMap* components = schema_map()->GetComponents(domain);
+ if (!components)
+ return;
+
+ for (ComponentMap::const_iterator it = components->begin();
+ it != components->end(); ++it) {
+ PolicyMap policy;
+ LoadPolicyForComponent(id_prefix + it->first, it->second, &policy);
+ if (!policy.empty())
+ bundle->Get(PolicyNamespace(domain, it->first)).Swap(&policy);
+ }
+}
+
+void PolicyLoaderMac::LoadPolicyForComponent(
+ const std::string& bundle_id_string,
+ const Schema& schema,
+ PolicyMap* policy) {
+ // TODO(joaodasilva): Extensions may be registered in a ComponentMap
+ // without a schema, to allow a graceful update of the Legacy Browser Support
+ // extension on Windows. Remove this check once that support is removed.
+ if (!schema.valid())
+ return;
+
+ base::ScopedCFTypeRef<CFStringRef> bundle_id(
+ base::SysUTF8ToCFStringRef(bundle_id_string));
+ preferences_->AppSynchronize(bundle_id);
+
+ for (Schema::Iterator it = schema.GetPropertiesIterator(); !it.IsAtEnd();
+ it.Advance()) {
+ base::ScopedCFTypeRef<CFStringRef> pref_name(
+ base::SysUTF8ToCFStringRef(it.key()));
+ base::ScopedCFTypeRef<CFPropertyListRef> value(
+ preferences_->CopyAppValue(pref_name, bundle_id));
+ if (!value)
+ continue;
+ bool forced = preferences_->AppValueIsForced(pref_name, bundle_id);
+ PolicyLevel level =
+ forced ? POLICY_LEVEL_MANDATORY : POLICY_LEVEL_RECOMMENDED;
+ std::unique_ptr<base::Value> policy_value = PropertyToValue(value);
+ if (policy_value) {
+ policy->Set(it.key(), level, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
+ std::move(*policy_value), nullptr);
+ }
+ }
+}
+
+void PolicyLoaderMac::OnFileUpdated(const base::FilePath& path, bool error) {
+ if (!error)
+ Reload(false);
+}
+
+} // namespace policy