| // Copyright (c) 2012 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 "chrome/browser/policy/configuration_policy_provider_mac.h" |
| |
| #include "base/file_path.h" |
| #include "base/file_util.h" |
| #include "base/mac/scoped_cftyperef.h" |
| #include "base/path_service.h" |
| #include "base/platform_file.h" |
| #include "base/sys_string_conversions.h" |
| #include "chrome/browser/policy/policy_map.h" |
| #include "chrome/browser/preferences_mac.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "policy/policy_constants.h" |
| |
| namespace policy { |
| |
| namespace { |
| |
| FilePath GetManagedPolicyPath() { |
| // 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, FileBasedPolicyLoader has a task that |
| // polls periodically in order to reload managed preferences later even if we |
| // missed the change. |
| FilePath path; |
| if (!PathService::Get(chrome::DIR_MANAGED_PREFS, &path)) |
| return FilePath(); |
| |
| CFBundleRef bundle(CFBundleGetMainBundle()); |
| if (!bundle) |
| return FilePath(); |
| |
| CFStringRef bundle_id = CFBundleGetIdentifier(bundle); |
| if (!bundle_id) |
| return FilePath(); |
| |
| return path.Append(base::SysCFStringRefToUTF8(bundle_id) + ".plist"); |
| } |
| |
| } // namespace |
| |
| MacPreferencesPolicyProviderDelegate::MacPreferencesPolicyProviderDelegate( |
| MacPreferences* preferences, |
| const PolicyDefinitionList* policy_list, |
| PolicyLevel level) |
| : FileBasedPolicyProvider::ProviderDelegate(GetManagedPolicyPath()), |
| policy_list_(policy_list), |
| preferences_(preferences), |
| level_(level) {} |
| |
| MacPreferencesPolicyProviderDelegate::~MacPreferencesPolicyProviderDelegate() {} |
| |
| PolicyMap* MacPreferencesPolicyProviderDelegate::Load() { |
| preferences_->AppSynchronize(kCFPreferencesCurrentApplication); |
| PolicyMap* policy = new PolicyMap; |
| |
| const PolicyDefinitionList::Entry* current; |
| for (current = policy_list_->begin; current != policy_list_->end; ++current) { |
| base::mac::ScopedCFTypeRef<CFStringRef> name( |
| base::SysUTF8ToCFStringRef(current->name)); |
| base::mac::ScopedCFTypeRef<CFPropertyListRef> value( |
| preferences_->CopyAppValue(name, kCFPreferencesCurrentApplication)); |
| if (!value.get()) |
| continue; |
| bool forced = |
| preferences_->AppValueIsForced(name, kCFPreferencesCurrentApplication); |
| PolicyLevel level = forced ? POLICY_LEVEL_MANDATORY : |
| POLICY_LEVEL_RECOMMENDED; |
| if (level != level_) |
| continue; |
| Value* policy_value = NULL; |
| switch (current->value_type) { |
| case Value::TYPE_STRING: |
| if (CFGetTypeID(value) == CFStringGetTypeID()) { |
| policy_value = Value::CreateStringValue( |
| base::SysCFStringRefToUTF8((CFStringRef) value.get())); |
| } |
| break; |
| case Value::TYPE_BOOLEAN: |
| if (CFGetTypeID(value) == CFBooleanGetTypeID()) { |
| policy_value = Value::CreateBooleanValue( |
| CFBooleanGetValue((CFBooleanRef) value.get())); |
| } |
| break; |
| case Value::TYPE_INTEGER: |
| if (CFGetTypeID(value) == CFNumberGetTypeID()) { |
| int int_value; |
| bool cast = CFNumberGetValue((CFNumberRef) value.get(), |
| kCFNumberIntType, |
| &int_value); |
| if (cast) |
| policy_value = Value::CreateIntegerValue(int_value); |
| } |
| break; |
| case Value::TYPE_LIST: |
| if (CFGetTypeID(value) == CFArrayGetTypeID()) { |
| scoped_ptr<ListValue> list_value(new ListValue); |
| bool valid_array = true; |
| CFArrayRef array_value = (CFArrayRef)value.get(); |
| for (CFIndex i = 0; i < CFArrayGetCount(array_value); ++i) { |
| // For now we assume that all values are strings. |
| CFStringRef array_string = |
| (CFStringRef)CFArrayGetValueAtIndex(array_value, i); |
| if (CFGetTypeID(array_string) == CFStringGetTypeID()) { |
| std::string array_string_value = |
| base::SysCFStringRefToUTF8(array_string); |
| list_value->Append(Value::CreateStringValue(array_string_value)); |
| } else { |
| valid_array = false; |
| } |
| } |
| if (valid_array) |
| policy_value = list_value.release(); |
| } |
| break; |
| case Value::TYPE_DICTIONARY: |
| // TODO(joaodasilva): http://crbug.com/108995 |
| break; |
| default: |
| NOTREACHED(); |
| } |
| // TODO(joaodasilva): figure the policy scope. |
| if (policy_value) |
| policy->Set(current->name, level_, POLICY_SCOPE_USER, policy_value); |
| } |
| |
| return policy; |
| } |
| |
| base::Time MacPreferencesPolicyProviderDelegate::GetLastModification() { |
| base::PlatformFileInfo file_info; |
| if (!file_util::GetFileInfo(config_file_path(), &file_info) || |
| file_info.is_directory) { |
| return base::Time(); |
| } |
| |
| return file_info.last_modified; |
| } |
| |
| ConfigurationPolicyProviderMac::ConfigurationPolicyProviderMac( |
| const PolicyDefinitionList* policy_list, |
| PolicyLevel level) |
| : FileBasedPolicyProvider( |
| policy_list, |
| new MacPreferencesPolicyProviderDelegate(new MacPreferences, |
| policy_list, |
| level)) {} |
| |
| ConfigurationPolicyProviderMac::ConfigurationPolicyProviderMac( |
| const PolicyDefinitionList* policy_list, |
| PolicyLevel level, |
| MacPreferences* preferences) |
| : FileBasedPolicyProvider( |
| policy_list, |
| new MacPreferencesPolicyProviderDelegate(preferences, |
| policy_list, |
| level)) {} |
| |
| } // namespace policy |