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

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 comments. 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 CloudExternalDataPolicyObserver::Delegate::~Delegate() {
104 }
105
106 CloudExternalDataPolicyObserver::CloudExternalDataPolicyObserver(
107 chromeos::CrosSettings* cros_settings,
108 chromeos::UserManager* user_manager,
109 DeviceLocalAccountPolicyService* device_local_account_policy_service,
110 const std::string& policy,
111 Delegate* delegate)
112 : cros_settings_(cros_settings),
113 user_manager_(user_manager),
114 device_local_account_policy_service_(device_local_account_policy_service),
115 policy_(policy),
116 delegate_(delegate),
117 weak_factory_(this) {
118 notification_registrar_.Add(
119 this,
120 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
121 content::NotificationService::AllSources());
122
123 if (device_local_account_policy_service_)
124 device_local_account_policy_service_->AddObserver(this);
125
126 device_local_accounts_subscription_ = cros_settings_->AddSettingsObserver(
127 chromeos::kAccountsPrefDeviceLocalAccounts,
128 base::Bind(&CloudExternalDataPolicyObserver::RetrieveDeviceLocalAccounts,
129 base::Unretained(this)));
130 }
131
132 CloudExternalDataPolicyObserver::~CloudExternalDataPolicyObserver() {
133 if (device_local_account_policy_service_)
134 device_local_account_policy_service_->RemoveObserver(this);
135 for (DeviceLocalAccountEntryMap::iterator it =
136 device_local_account_entries_.begin();
137 it != device_local_account_entries_.end(); ++it) {
138 it->second.DeleteOwnedMembers();
139 }
140 device_local_account_entries_.clear();
141 }
142
143 void CloudExternalDataPolicyObserver::Init() {
144 RetrieveDeviceLocalAccounts();
145 }
146
147 void CloudExternalDataPolicyObserver::Observe(
148 int type,
149 const content::NotificationSource& source,
150 const content::NotificationDetails& details) {
151 if (type != chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED) {
152 NOTREACHED();
153 return;
154 }
155 Profile* profile = content::Details<Profile>(details).ptr();
156
157 const chromeos::User* user = user_manager_->GetUserByProfile(profile);
158 if (!user) {
159 NOTREACHED();
160 return;
161 }
162
163 const std::string& user_id = user->email();
164 if (ContainsKey(logged_in_user_observers_, user_id)) {
165 NOTREACHED();
166 return;
167 }
168
169 ProfilePolicyConnector* policy_connector =
170 ProfilePolicyConnectorFactory::GetForProfile(profile);
171 logged_in_user_observers_[user_id] = make_linked_ptr(
172 new PolicyServiceObserver(this,
173 user_id,
174 policy_connector->policy_service()));
175 }
176
177 void CloudExternalDataPolicyObserver::OnPolicyUpdated(
178 const std::string& user_id) {
179 if (ContainsKey(logged_in_user_observers_, user_id)) {
180 // When a device-local account is logged in, a policy change triggers both
181 // OnPolicyUpdated() and PolicyServiceObserver::OnPolicyUpdated(). Ignore
182 // the former so that the policy change is handled only once.
183 return;
184 }
185
186 if (!device_local_account_policy_service_) {
187 NOTREACHED();
188 return;
189 }
190 DeviceLocalAccountPolicyBroker* broker =
191 device_local_account_policy_service_->GetBrokerForUser(user_id);
192 if (!broker) {
193 NOTREACHED();
194 return;
195 }
196
197 const PolicyMap::Entry* entry =
198 broker->core()->store()->policy_map().Get(policy_);
199 if (!entry) {
200 DeviceLocalAccountEntryMap::iterator it =
201 device_local_account_entries_.find(user_id);
202 if (it != device_local_account_entries_.end()) {
203 it->second.DeleteOwnedMembers();
204 device_local_account_entries_.erase(it);
205 HandleExternalDataPolicyUpdate(user_id, NULL);
206 }
207 return;
208 }
209
210 PolicyMap::Entry& map_entry = device_local_account_entries_[user_id];
211 if (map_entry.Equals(*entry))
212 return;
213
214 map_entry.DeleteOwnedMembers();
215 map_entry = *entry->DeepCopy();
216 HandleExternalDataPolicyUpdate(user_id, entry);
217 }
218
219 void CloudExternalDataPolicyObserver::OnDeviceLocalAccountsChanged() {
220 // No action needed here, changes to the list of device-local accounts get
221 // handled via the kAccountsPrefDeviceLocalAccounts device setting observer.
222 }
223
224 void CloudExternalDataPolicyObserver::RetrieveDeviceLocalAccounts() {
225 // Schedule a callback if device policy has not yet been verified.
226 if (chromeos::CrosSettingsProvider::TRUSTED !=
227 cros_settings_->PrepareTrustedValues(base::Bind(
228 &CloudExternalDataPolicyObserver::RetrieveDeviceLocalAccounts,
229 weak_factory_.GetWeakPtr()))) {
230 return;
231 }
232
233 std::vector<DeviceLocalAccount> device_local_account_list =
234 policy::GetDeviceLocalAccounts(cros_settings_);
235 std::set<std::string> device_local_accounts;
236 for (std::vector<DeviceLocalAccount>::const_iterator it =
237 device_local_account_list.begin();
238 it != device_local_account_list.end(); ++it) {
239 device_local_accounts.insert(it->user_id);
240 }
241
242 for (DeviceLocalAccountEntryMap::iterator it =
243 device_local_account_entries_.begin();
244 it != device_local_account_entries_.end(); ) {
245 if (!ContainsKey(device_local_accounts, it->first)) {
246 const std::string user_id = it->first;
247 it->second.DeleteOwnedMembers();
248 device_local_account_entries_.erase(it++);
249 // When a device-local account whose external data reference was set is
250 // removed, emit a notification that the external data reference has been
251 // cleared.
252 HandleExternalDataPolicyUpdate(user_id, NULL);
253 } else {
254 ++it;
255 }
256 }
257
258 for (std::set<std::string>::const_iterator it = device_local_accounts.begin();
259 it != device_local_accounts.end(); ++it) {
260 OnPolicyUpdated(*it);
261 }
262 }
263
264 void CloudExternalDataPolicyObserver::HandleExternalDataPolicyUpdate(
265 const std::string& user_id,
266 const PolicyMap::Entry* entry) {
267 if (!entry) {
268 delegate_->OnExternalDataCleared(policy_, user_id);
269 fetch_weak_ptrs_.erase(user_id);
270 return;
271 }
272
273 delegate_->OnExternalDataSet(policy_, user_id);
274
275 linked_ptr<WeakPtrFactory>& weak_ptr_factory = fetch_weak_ptrs_[user_id];
276 weak_ptr_factory.reset(new WeakPtrFactory(this));
277 if (entry->external_data_fetcher) {
278 entry->external_data_fetcher->Fetch(base::Bind(
279 &CloudExternalDataPolicyObserver::OnExternalDataFetched,
280 weak_ptr_factory->GetWeakPtr(),
281 user_id));
282 } else {
283 NOTREACHED();
284 }
285 }
286
287 void CloudExternalDataPolicyObserver::OnExternalDataFetched(
288 const std::string& user_id,
289 scoped_ptr<std::string> data) {
290 FetchWeakPtrMap::iterator it = fetch_weak_ptrs_.find(user_id);
291 DCHECK(it != fetch_weak_ptrs_.end());
292 fetch_weak_ptrs_.erase(it);
293 DCHECK(data);
294 delegate_->OnExternalDataFetched(policy_, user_id, data.Pass());
295 }
296
297 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698