Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(535)

Side by Side Diff: chrome/browser/chromeos/policy/cloud_external_data_policy_observer.cc

Issue 88423002: Add CloudExternalDataPolicyObserverChromeOS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed suggestion. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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/chromeos/policy/cloud_external_data_policy_observer.h"
6
7 #include <set>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/logging.h"
13 #include "base/stl_util.h"
14 #include "base/values.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/chromeos/login/user.h"
17 #include "chrome/browser/chromeos/login/user_manager.h"
18 #include "chrome/browser/chromeos/policy/device_local_account.h"
19 #include "chrome/browser/policy/cloud/cloud_policy_core.h"
20 #include "chrome/browser/policy/cloud/cloud_policy_store.h"
21 #include "chrome/browser/policy/policy_service.h"
22 #include "chrome/browser/policy/profile_policy_connector.h"
23 #include "chrome/browser/policy/profile_policy_connector_factory.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chromeos/settings/cros_settings_names.h"
26 #include "chromeos/settings/cros_settings_provider.h"
27 #include "components/policy/core/common/external_data_fetcher.h"
28 #include "components/policy/core/common/policy_namespace.h"
29 #include "content/public/browser/notification_details.h"
30 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/notification_source.h"
32
33 namespace policy {
34
35 // Helper class that observes a policy for a logged-in user, notifying the
36 // |parent_| whenever the external data reference for this user changes.
37 class CloudExternalDataPolicyObserver::PolicyServiceObserver
38 : public PolicyService::Observer {
39 public:
40 PolicyServiceObserver(CloudExternalDataPolicyObserver* parent,
41 const std::string& user_id,
42 PolicyService* policy_service);
43 virtual ~PolicyServiceObserver();
44
45 // PolicyService::Observer:
46 virtual void OnPolicyUpdated(const PolicyNamespace& ns,
47 const PolicyMap& previous,
48 const PolicyMap& current) OVERRIDE;
49
50 private:
51 CloudExternalDataPolicyObserver* parent_;
52 const std::string user_id_;
53 PolicyService* policy_service_;
54
55 DISALLOW_COPY_AND_ASSIGN(PolicyServiceObserver);
56 };
57
58 CloudExternalDataPolicyObserver::PolicyServiceObserver::PolicyServiceObserver(
59 CloudExternalDataPolicyObserver* parent,
60 const std::string& user_id,
61 PolicyService* policy_service)
62 : parent_(parent),
63 user_id_(user_id),
64 policy_service_(policy_service) {
65 policy_service_->AddObserver(POLICY_DOMAIN_CHROME, this);
66
67 if (!IsDeviceLocalAccountUser(user_id, NULL)) {
68 // Notify |parent_| if the external data reference for |user_id_| is set
69 // during login. This is omitted for device-local accounts because their
70 // policy is available before login and the external data reference will
71 // have been seen by the |parent_| already.
72 const PolicyMap::Entry* entry = policy_service_->GetPolicies(
73 PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
74 .Get(parent_->policy_);
75 if (entry)
76 parent_->HandleExternalDataPolicyUpdate(user_id_, entry);
77 }
78 }
79
80 CloudExternalDataPolicyObserver::PolicyServiceObserver::
81 ~PolicyServiceObserver() {
82 policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, this);
83 }
84
85 void CloudExternalDataPolicyObserver::PolicyServiceObserver::OnPolicyUpdated(
86 const PolicyNamespace& ns,
87 const PolicyMap& previous,
88 const PolicyMap& current) {
89 DCHECK(ns == PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
90
91 const PolicyMap::Entry* previous_entry = previous.Get(parent_->policy_);
92 const PolicyMap::Entry* current_entry = current.Get(parent_->policy_);
93 if ((!previous_entry && current_entry) ||
94 (previous_entry && !current_entry) ||
95 (previous_entry && current_entry &&
96 !previous_entry->Equals(*current_entry))) {
97 // Notify |parent_| if the external data reference for |user_id_| has
98 // changed.
99 parent_->HandleExternalDataPolicyUpdate(user_id_, current_entry);
100 }
101 }
102
103 void CloudExternalDataPolicyObserver::Delegate::OnExternalDataSet(
104 const std::string& policy,
105 const std::string& user_id) {
106 }
107
108 void CloudExternalDataPolicyObserver::Delegate::OnExternalDataCleared(
109 const std::string& policy,
110 const std::string& user_id) {
111 }
112
113 void CloudExternalDataPolicyObserver::Delegate::OnExternalDataFetched(
114 const std::string& policy,
115 const std::string& user_id,
116 scoped_ptr<std::string> data) {
117 }
118
119 CloudExternalDataPolicyObserver::Delegate::~Delegate() {
120 }
121
122 CloudExternalDataPolicyObserver::CloudExternalDataPolicyObserver(
123 chromeos::CrosSettings* cros_settings,
124 chromeos::UserManager* user_manager,
125 DeviceLocalAccountPolicyService* device_local_account_policy_service,
126 const std::string& policy,
127 Delegate* delegate)
128 : cros_settings_(cros_settings),
129 user_manager_(user_manager),
130 device_local_account_policy_service_(device_local_account_policy_service),
131 policy_(policy),
132 delegate_(delegate),
133 weak_factory_(this) {
134 notification_registrar_.Add(
135 this,
136 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
137 content::NotificationService::AllSources());
138
139 if (device_local_account_policy_service_)
140 device_local_account_policy_service_->AddObserver(this);
141
142 device_local_accounts_subscription_ = cros_settings_->AddSettingsObserver(
143 chromeos::kAccountsPrefDeviceLocalAccounts,
144 base::Bind(&CloudExternalDataPolicyObserver::RetrieveDeviceLocalAccounts,
145 base::Unretained(this)));
146 }
147
148 CloudExternalDataPolicyObserver::~CloudExternalDataPolicyObserver() {
149 if (device_local_account_policy_service_)
150 device_local_account_policy_service_->RemoveObserver(this);
151 for (DeviceLocalAccountEntryMap::iterator it =
152 device_local_account_entries_.begin();
153 it != device_local_account_entries_.end(); ++it) {
154 it->second.DeleteOwnedMembers();
155 }
156 device_local_account_entries_.clear();
157 }
158
159 void CloudExternalDataPolicyObserver::Init() {
160 RetrieveDeviceLocalAccounts();
161 }
162
163 void CloudExternalDataPolicyObserver::Observe(
164 int type,
165 const content::NotificationSource& source,
166 const content::NotificationDetails& details) {
167 if (type != chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED) {
168 NOTREACHED();
169 return;
170 }
171 Profile* profile = content::Details<Profile>(details).ptr();
172
173 const chromeos::User* user = user_manager_->GetUserByProfile(profile);
174 if (!user) {
175 NOTREACHED();
176 return;
177 }
178
179 const std::string& user_id = user->email();
180 if (ContainsKey(logged_in_user_observers_, user_id)) {
181 NOTREACHED();
182 return;
183 }
184
185 ProfilePolicyConnector* policy_connector =
186 ProfilePolicyConnectorFactory::GetForProfile(profile);
187 logged_in_user_observers_[user_id] = make_linked_ptr(
188 new PolicyServiceObserver(this,
189 user_id,
190 policy_connector->policy_service()));
191 }
192
193 void CloudExternalDataPolicyObserver::OnPolicyUpdated(
194 const std::string& user_id) {
195 if (ContainsKey(logged_in_user_observers_, user_id)) {
196 // When a device-local account is logged in, a policy change triggers both
197 // OnPolicyUpdated() and PolicyServiceObserver::OnPolicyUpdated(). Ignore
198 // the former so that the policy change is handled only once.
199 return;
200 }
201
202 if (!device_local_account_policy_service_) {
203 NOTREACHED();
204 return;
205 }
206 DeviceLocalAccountPolicyBroker* broker =
207 device_local_account_policy_service_->GetBrokerForUser(user_id);
208 if (!broker) {
209 NOTREACHED();
210 return;
211 }
212
213 const PolicyMap::Entry* entry =
214 broker->core()->store()->policy_map().Get(policy_);
215 if (!entry) {
216 DeviceLocalAccountEntryMap::iterator it =
217 device_local_account_entries_.find(user_id);
218 if (it != device_local_account_entries_.end()) {
219 it->second.DeleteOwnedMembers();
220 device_local_account_entries_.erase(it);
221 HandleExternalDataPolicyUpdate(user_id, NULL);
222 }
223 return;
224 }
225
226 PolicyMap::Entry& map_entry = device_local_account_entries_[user_id];
227 if (map_entry.Equals(*entry))
228 return;
229
230 map_entry.DeleteOwnedMembers();
231 map_entry = *entry->DeepCopy();
232 HandleExternalDataPolicyUpdate(user_id, entry);
233 }
234
235 void CloudExternalDataPolicyObserver::OnDeviceLocalAccountsChanged() {
236 // No action needed here, changes to the list of device-local accounts get
237 // handled via the kAccountsPrefDeviceLocalAccounts device setting observer.
238 }
239
240 void CloudExternalDataPolicyObserver::RetrieveDeviceLocalAccounts() {
241 // Schedule a callback if device policy has not yet been verified.
242 if (chromeos::CrosSettingsProvider::TRUSTED !=
243 cros_settings_->PrepareTrustedValues(base::Bind(
244 &CloudExternalDataPolicyObserver::RetrieveDeviceLocalAccounts,
245 weak_factory_.GetWeakPtr()))) {
246 return;
247 }
248
249 std::vector<DeviceLocalAccount> device_local_account_list =
250 policy::GetDeviceLocalAccounts(cros_settings_);
251 std::set<std::string> device_local_accounts;
252 for (std::vector<DeviceLocalAccount>::const_iterator it =
253 device_local_account_list.begin();
254 it != device_local_account_list.end(); ++it) {
255 device_local_accounts.insert(it->user_id);
256 }
257
258 for (DeviceLocalAccountEntryMap::iterator it =
259 device_local_account_entries_.begin();
260 it != device_local_account_entries_.end(); ) {
261 if (!ContainsKey(device_local_accounts, it->first)) {
262 const std::string user_id = it->first;
263 it->second.DeleteOwnedMembers();
264 device_local_account_entries_.erase(it++);
265 // When a device-local account whose external data reference was set is
266 // removed, emit a notification that the external data reference has been
267 // cleared.
268 HandleExternalDataPolicyUpdate(user_id, NULL);
269 } else {
270 ++it;
271 }
272 }
273
274 for (std::set<std::string>::const_iterator it = device_local_accounts.begin();
275 it != device_local_accounts.end(); ++it) {
276 OnPolicyUpdated(*it);
277 }
278 }
279
280 void CloudExternalDataPolicyObserver::HandleExternalDataPolicyUpdate(
281 const std::string& user_id,
282 const PolicyMap::Entry* entry) {
283 if (!entry) {
284 delegate_->OnExternalDataCleared(policy_, user_id);
285 fetch_weak_ptrs_.erase(user_id);
286 return;
287 }
288
289 delegate_->OnExternalDataSet(policy_, user_id);
290
291 linked_ptr<WeakPtrFactory>& weak_ptr_factory = fetch_weak_ptrs_[user_id];
292 weak_ptr_factory.reset(new WeakPtrFactory(this));
293 if (entry->external_data_fetcher) {
294 entry->external_data_fetcher->Fetch(base::Bind(
295 &CloudExternalDataPolicyObserver::OnExternalDataFetched,
296 weak_ptr_factory->GetWeakPtr(),
297 user_id));
298 } else {
299 NOTREACHED();
300 }
301 }
302
303 void CloudExternalDataPolicyObserver::OnExternalDataFetched(
304 const std::string& user_id,
305 scoped_ptr<std::string> data) {
306 FetchWeakPtrMap::iterator it = fetch_weak_ptrs_.find(user_id);
307 DCHECK(it != fetch_weak_ptrs_.end());
308 fetch_weak_ptrs_.erase(it);
309 DCHECK(data);
310 delegate_->OnExternalDataFetched(policy_, user_id, data.Pass());
311 }
312
313 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698