• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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 "components/policy/core/common/policy_loader_mac.h"
6 
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/files/file_util.h"
11 #include "base/mac/foundation_util.h"
12 #include "base/mac/scoped_cftyperef.h"
13 #include "base/path_service.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/strings/sys_string_conversions.h"
16 #include "base/values.h"
17 #include "components/policy/core/common/external_data_fetcher.h"
18 #include "components/policy/core/common/mac_util.h"
19 #include "components/policy/core/common/policy_bundle.h"
20 #include "components/policy/core/common/policy_load_status.h"
21 #include "components/policy/core/common/policy_map.h"
22 #include "components/policy/core/common/preferences_mac.h"
23 #include "components/policy/core/common/schema.h"
24 #include "components/policy/core/common/schema_map.h"
25 
26 using base::ScopedCFTypeRef;
27 
28 namespace policy {
29 
PolicyLoaderMac(scoped_refptr<base::SequencedTaskRunner> task_runner,const base::FilePath & managed_policy_path,MacPreferences * preferences)30 PolicyLoaderMac::PolicyLoaderMac(
31     scoped_refptr<base::SequencedTaskRunner> task_runner,
32     const base::FilePath& managed_policy_path,
33     MacPreferences* preferences)
34     : AsyncPolicyLoader(task_runner),
35       preferences_(preferences),
36       managed_policy_path_(managed_policy_path) {}
37 
~PolicyLoaderMac()38 PolicyLoaderMac::~PolicyLoaderMac() {}
39 
InitOnBackgroundThread()40 void PolicyLoaderMac::InitOnBackgroundThread() {
41   if (!managed_policy_path_.empty()) {
42     watcher_.Watch(
43         managed_policy_path_, false,
44         base::Bind(&PolicyLoaderMac::OnFileUpdated, base::Unretained(this)));
45   }
46 }
47 
Load()48 scoped_ptr<PolicyBundle> PolicyLoaderMac::Load() {
49   preferences_->AppSynchronize(kCFPreferencesCurrentApplication);
50   scoped_ptr<PolicyBundle> bundle(new PolicyBundle());
51 
52   // Load Chrome's policy.
53   PolicyMap& chrome_policy =
54       bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
55 
56   PolicyLoadStatusSample status;
57   bool policy_present = false;
58   const Schema* schema =
59       schema_map()->GetSchema(PolicyNamespace(POLICY_DOMAIN_CHROME, ""));
60   for (Schema::Iterator it = schema->GetPropertiesIterator();
61        !it.IsAtEnd(); it.Advance()) {
62     base::ScopedCFTypeRef<CFStringRef> name(
63         base::SysUTF8ToCFStringRef(it.key()));
64     base::ScopedCFTypeRef<CFPropertyListRef> value(
65         preferences_->CopyAppValue(name, kCFPreferencesCurrentApplication));
66     if (!value.get())
67       continue;
68     policy_present = true;
69     bool forced =
70         preferences_->AppValueIsForced(name, kCFPreferencesCurrentApplication);
71     PolicyLevel level = forced ? POLICY_LEVEL_MANDATORY :
72                                  POLICY_LEVEL_RECOMMENDED;
73     // TODO(joaodasilva): figure the policy scope.
74     scoped_ptr<base::Value> policy = PropertyToValue(value);
75     if (policy) {
76       chrome_policy.Set(
77           it.key(), level, POLICY_SCOPE_USER, policy.release(), NULL);
78     } else {
79       status.Add(POLICY_LOAD_STATUS_PARSE_ERROR);
80     }
81   }
82 
83   if (!policy_present)
84     status.Add(POLICY_LOAD_STATUS_NO_POLICY);
85 
86   // Load policy for the registered components.
87   LoadPolicyForDomain(POLICY_DOMAIN_EXTENSIONS, "extensions", bundle.get());
88 
89   return bundle.Pass();
90 }
91 
LastModificationTime()92 base::Time PolicyLoaderMac::LastModificationTime() {
93   base::File::Info file_info;
94   if (!base::GetFileInfo(managed_policy_path_, &file_info) ||
95       file_info.is_directory) {
96     return base::Time();
97   }
98 
99   return file_info.last_modified;
100 }
101 
LoadPolicyForDomain(PolicyDomain domain,const std::string & domain_name,PolicyBundle * bundle)102 void PolicyLoaderMac::LoadPolicyForDomain(
103     PolicyDomain domain,
104     const std::string& domain_name,
105     PolicyBundle* bundle) {
106   std::string id_prefix(base::mac::BaseBundleID());
107   id_prefix.append(".").append(domain_name).append(".");
108 
109   const ComponentMap* components = schema_map()->GetComponents(domain);
110   if (!components)
111     return;
112 
113   for (ComponentMap::const_iterator it = components->begin();
114        it != components->end(); ++it) {
115     PolicyMap policy;
116     LoadPolicyForComponent(id_prefix + it->first, it->second, &policy);
117     if (!policy.empty())
118       bundle->Get(PolicyNamespace(domain, it->first)).Swap(&policy);
119   }
120 }
121 
LoadPolicyForComponent(const std::string & bundle_id_string,const Schema & schema,PolicyMap * policy)122 void PolicyLoaderMac::LoadPolicyForComponent(
123     const std::string& bundle_id_string,
124     const Schema& schema,
125     PolicyMap* policy) {
126   // TODO(joaodasilva): Extensions may be registered in a ComponentMap
127   // without a schema, to allow a graceful update of the Legacy Browser Support
128   // extension on Windows. Remove this check once that support is removed.
129   if (!schema.valid())
130     return;
131 
132   base::ScopedCFTypeRef<CFStringRef> bundle_id(
133       base::SysUTF8ToCFStringRef(bundle_id_string));
134   preferences_->AppSynchronize(bundle_id);
135 
136   for (Schema::Iterator it = schema.GetPropertiesIterator();
137        !it.IsAtEnd(); it.Advance()) {
138     base::ScopedCFTypeRef<CFStringRef> pref_name(
139         base::SysUTF8ToCFStringRef(it.key()));
140     base::ScopedCFTypeRef<CFPropertyListRef> value(
141         preferences_->CopyAppValue(pref_name, bundle_id));
142     if (!value.get())
143       continue;
144     bool forced =
145         preferences_->AppValueIsForced(pref_name, bundle_id);
146     PolicyLevel level = forced ? POLICY_LEVEL_MANDATORY :
147                                  POLICY_LEVEL_RECOMMENDED;
148     scoped_ptr<base::Value> policy_value = PropertyToValue(value);
149     if (policy_value) {
150       policy->Set(it.key(), level, POLICY_SCOPE_USER,
151                   policy_value.release(), NULL);
152     }
153   }
154 }
155 
OnFileUpdated(const base::FilePath & path,bool error)156 void PolicyLoaderMac::OnFileUpdated(const base::FilePath& path, bool error) {
157   if (!error)
158     Reload(false);
159 }
160 
161 }  // namespace policy
162