1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/policy/configuration_policy_provider_mac.h"
6
7#include "base/file_util.h"
8#include "base/logging.h"
9#include "base/mac/scoped_cftyperef.h"
10#include "base/path_service.h"
11#include "base/sys_string_conversions.h"
12#include "chrome/common/chrome_paths.h"
13
14namespace policy {
15
16static FilePath GetManagedPolicyPath() {
17  // This constructs the path to the plist file in which Mac OS X stores the
18  // managed preference for the application. This is undocumented and therefore
19  // fragile, but if it doesn't work out, FileBasedPolicyLoader has a task that
20  // polls periodically in order to reload managed preferences later even if we
21  // missed the change.
22  FilePath path;
23  if (!PathService::Get(chrome::DIR_MANAGED_PREFS, &path))
24    return FilePath();
25
26  CFBundleRef bundle(CFBundleGetMainBundle());
27  if (!bundle)
28    return FilePath();
29
30  CFStringRef bundle_id = CFBundleGetIdentifier(bundle);
31  if (!bundle_id)
32    return FilePath();
33
34  return path.Append(base::SysCFStringRefToUTF8(bundle_id) + ".plist");
35}
36
37MacPreferencesPolicyProviderDelegate::MacPreferencesPolicyProviderDelegate(
38    MacPreferences* preferences,
39    const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list)
40    : FileBasedPolicyProvider::ProviderDelegate(GetManagedPolicyPath()),
41      policy_list_(policy_list),
42      preferences_(preferences) {
43}
44
45MacPreferencesPolicyProviderDelegate::~MacPreferencesPolicyProviderDelegate() {}
46
47DictionaryValue* MacPreferencesPolicyProviderDelegate::Load() {
48  preferences_->AppSynchronize(kCFPreferencesCurrentApplication);
49  DictionaryValue* policy = new DictionaryValue;
50
51  const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current;
52  for (current = policy_list_->begin; current != policy_list_->end; ++current) {
53    base::mac::ScopedCFTypeRef<CFStringRef> name(
54        base::SysUTF8ToCFStringRef(current->name));
55    base::mac::ScopedCFTypeRef<CFPropertyListRef> value(
56        preferences_->CopyAppValue(name, kCFPreferencesCurrentApplication));
57    if (!value.get())
58      continue;
59    if (!preferences_->AppValueIsForced(name, kCFPreferencesCurrentApplication))
60      continue;
61
62    switch (current->value_type) {
63      case Value::TYPE_STRING:
64        if (CFGetTypeID(value) == CFStringGetTypeID()) {
65          std::string string_value =
66              base::SysCFStringRefToUTF8((CFStringRef)value.get());
67          policy->SetString(current->name, string_value);
68        }
69        break;
70      case Value::TYPE_BOOLEAN:
71        if (CFGetTypeID(value) == CFBooleanGetTypeID()) {
72          bool bool_value = CFBooleanGetValue((CFBooleanRef)value.get());
73          policy->SetBoolean(current->name, bool_value);
74        }
75        break;
76      case Value::TYPE_INTEGER:
77        if (CFGetTypeID(value) == CFNumberGetTypeID()) {
78          int int_value;
79          bool cast = CFNumberGetValue((CFNumberRef)value.get(),
80                                       kCFNumberIntType,
81                                       &int_value);
82          if (cast)
83            policy->SetInteger(current->name, int_value);
84        }
85        break;
86      case Value::TYPE_LIST:
87        if (CFGetTypeID(value) == CFArrayGetTypeID()) {
88          scoped_ptr<ListValue> list_value(new ListValue);
89          bool valid_array = true;
90          CFArrayRef array_value = (CFArrayRef)value.get();
91          for (CFIndex i = 0; i < CFArrayGetCount(array_value); ++i) {
92            // For now we assume that all values are strings.
93            CFStringRef array_string =
94                (CFStringRef)CFArrayGetValueAtIndex(array_value, i);
95            if (CFGetTypeID(array_string) == CFStringGetTypeID()) {
96              std::string array_string_value =
97                  base::SysCFStringRefToUTF8(array_string);
98              list_value->Append(Value::CreateStringValue(array_string_value));
99            } else {
100              valid_array = false;
101            }
102          }
103          if (valid_array)
104            policy->Set(current->name, list_value.release());
105        }
106        break;
107      default:
108        NOTREACHED();
109    }
110  }
111
112  return policy;
113}
114
115base::Time MacPreferencesPolicyProviderDelegate::GetLastModification() {
116  base::PlatformFileInfo file_info;
117  if (!file_util::GetFileInfo(config_file_path(), &file_info) ||
118      file_info.is_directory) {
119    return base::Time();
120  }
121
122  return file_info.last_modified;
123}
124
125ConfigurationPolicyProviderMac::ConfigurationPolicyProviderMac(
126    const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list)
127    : FileBasedPolicyProvider(policy_list,
128          new MacPreferencesPolicyProviderDelegate(new MacPreferences,
129                                                   policy_list)) {
130}
131
132ConfigurationPolicyProviderMac::ConfigurationPolicyProviderMac(
133    const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list,
134    MacPreferences* preferences)
135    : FileBasedPolicyProvider(policy_list,
136          new MacPreferencesPolicyProviderDelegate(preferences,
137                                                   policy_list)) {
138}
139
140}  // namespace policy
141