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