// 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