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

Unified Diff: chrome/browser/chromeos/policy/cloud_external_data_policy_observer_chromeos.cc

Issue 88423002: Add CloudExternalDataPolicyObserverChromeOS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Whitespace fix. Created 7 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/policy/cloud_external_data_policy_observer_chromeos.cc
diff --git a/chrome/browser/chromeos/policy/cloud_external_data_policy_observer_chromeos.cc b/chrome/browser/chromeos/policy/cloud_external_data_policy_observer_chromeos.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ff69d60ddfac1d964870cf0d3f09fbfe001b52b7
--- /dev/null
+++ b/chrome/browser/chromeos/policy/cloud_external_data_policy_observer_chromeos.cc
@@ -0,0 +1,293 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/policy/cloud_external_data_policy_observer_chromeos.h"
+
+#include <set>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/login/user.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/policy/device_local_account.h"
+#include "chrome/browser/policy/cloud/cloud_policy_core.h"
+#include "chrome/browser/policy/cloud/cloud_policy_store.h"
+#include "chrome/browser/policy/policy_service.h"
+#include "chrome/browser/policy/profile_policy_connector.h"
+#include "chrome/browser/policy/profile_policy_connector_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chromeos/settings/cros_settings_names.h"
+#include "chromeos/settings/cros_settings_provider.h"
+#include "components/policy/core/common/external_data_fetcher.h"
+#include "components/policy/core/common/policy_namespace.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+
+namespace policy {
+
+// Helper class that observes a policy for a logged-in user, notifying the
+// |parent_| whenever the external data reference for this user changes.
+class CloudExternalDataPolicyObserverChromeOS::PolicyServiceObserver
+ : public PolicyService::Observer {
+ public:
+ PolicyServiceObserver(CloudExternalDataPolicyObserverChromeOS* parent,
+ const std::string& user_id,
+ PolicyService* policy_service);
+ virtual ~PolicyServiceObserver();
+
+ // PolicyService::Observer:
+ virtual void OnPolicyUpdated(const PolicyNamespace& ns,
+ const PolicyMap& previous,
+ const PolicyMap& current) OVERRIDE;
+
+ private:
+ CloudExternalDataPolicyObserverChromeOS* parent_;
+ const std::string user_id_;
+ PolicyService* policy_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(PolicyServiceObserver);
+};
+
+CloudExternalDataPolicyObserverChromeOS::PolicyServiceObserver::
+ PolicyServiceObserver(CloudExternalDataPolicyObserverChromeOS* parent,
+ const std::string& user_id,
+ PolicyService* policy_service)
+ : parent_(parent),
+ user_id_(user_id),
+ policy_service_(policy_service) {
+ policy_service_->AddObserver(POLICY_DOMAIN_CHROME, this);
+
+ if (!IsDeviceLocalAccountUser(user_id, NULL)) {
+ // Notify |parent_| if the external data reference for |user_id_| is set
+ // during login. This is omitted for device-local accounts because their
+ // policy is available before login and the external data reference will
+ // have been seen by the |parent_| already.
+ const PolicyMap::Entry* entry = policy_service_->GetPolicies(
+ PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
+ .Get(parent_->policy_);
+ if (entry)
+ parent_->HandleExternalDataPolicyUpdate(user_id_, entry);
+ }
+}
+
+CloudExternalDataPolicyObserverChromeOS::PolicyServiceObserver::
+ ~PolicyServiceObserver() {
+ policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, this);
+}
+
+void CloudExternalDataPolicyObserverChromeOS::PolicyServiceObserver::
+ OnPolicyUpdated(const PolicyNamespace& ns,
+ const PolicyMap& previous,
+ const PolicyMap& current) {
+ DCHECK(ns == PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
+
+ const PolicyMap::Entry* previous_entry = previous.Get(parent_->policy_);
+ const PolicyMap::Entry* current_entry = current.Get(parent_->policy_);
+ if ((!previous_entry && current_entry) ||
+ (previous_entry && !current_entry) ||
+ (previous_entry && current_entry &&
+ !previous_entry->Equals(*current_entry))) {
+ // Notify |parent_| if the external data reference for |user_id_| has
+ // changed.
+ parent_->HandleExternalDataPolicyUpdate(user_id_, current_entry);
+ }
+}
+
+CloudExternalDataPolicyObserverChromeOS::
+ CloudExternalDataPolicyObserverChromeOS(
+ chromeos::CrosSettings* cros_settings,
+ chromeos::UserManager* user_manager,
+ DeviceLocalAccountPolicyService* device_local_account_policy_service,
+ const std::string& policy)
+ : cros_settings_(cros_settings),
+ user_manager_(user_manager),
+ device_local_account_policy_service_(device_local_account_policy_service),
+ policy_(policy) {
+ notification_registrar_.Add(
+ this,
+ chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
+ content::NotificationService::AllSources());
+
+ if (device_local_account_policy_service_)
+ device_local_account_policy_service_->AddObserver(this);
+
+ device_local_accounts_subscription_ = cros_settings_->AddSettingsObserver(
+ chromeos::kAccountsPrefDeviceLocalAccounts,
+ base::Bind(
+ &CloudExternalDataPolicyObserverChromeOS::RetrieveDeviceLocalAccounts,
+ base::Unretained(this)));
+}
+
+CloudExternalDataPolicyObserverChromeOS::
+ ~CloudExternalDataPolicyObserverChromeOS() {
+}
+
+void CloudExternalDataPolicyObserverChromeOS::Init() {
+ RetrieveDeviceLocalAccounts();
+}
+
+void CloudExternalDataPolicyObserverChromeOS::Shutdown() {
+ device_local_accounts_subscription_.reset();
+ if (device_local_account_policy_service_)
+ device_local_account_policy_service_->RemoveObserver(this);
+ notification_registrar_.RemoveAll();
+
+ for (DeviceLocalAccountEntryMap::iterator it =
+ device_local_account_entries_.begin();
+ it != device_local_account_entries_.end(); ++it) {
+ delete it->second.value;
+ delete it->second.external_data_fetcher;
+ }
Joao da Silva 2013/11/27 14:33:59 device_local_account_entries_.clear()?
bartfab (slow) 2013/11/27 20:10:15 Done.
+ logged_in_user_observers_.clear();
+}
+
+void CloudExternalDataPolicyObserverChromeOS::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type != chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED) {
+ NOTREACHED();
+ return;
+ }
+ Profile* profile = content::Details<Profile>(details).ptr();
+
+ const chromeos::User* user = user_manager_->GetUserByProfile(profile);
+ if (!user) {
+ NOTREACHED();
+ return;
+ }
+
+ const std::string& user_id = user->email();
+ if (logged_in_user_observers_.find(user_id) !=
+ logged_in_user_observers_.end()) {
Joao da Silva 2013/11/27 14:33:59 ContainsKey() is clearer
bartfab (slow) 2013/11/27 20:10:15 Done.
+ NOTREACHED();
+ return;
+ }
+
+ ProfilePolicyConnector* policy_connector =
+ ProfilePolicyConnectorFactory::GetForProfile(profile);
+ logged_in_user_observers_[user_id] = make_linked_ptr(
+ new PolicyServiceObserver(this,
+ user_id,
+ policy_connector->policy_service()));
+}
+
+void CloudExternalDataPolicyObserverChromeOS::OnPolicyUpdated(
+ const std::string& user_id) {
+ if (logged_in_user_observers_.find(user_id) !=
+ logged_in_user_observers_.end()) {
Joao da Silva 2013/11/27 14:33:59 ContainsKey
bartfab (slow) 2013/11/27 20:10:15 Done.
+ // When a device-local account is logged in, a policy change triggers both
+ // OnPolicyUpdated() and PolicyServiceObserver::OnPolicyUpdated(). Ignore
+ // the former so that the policy change is handled only once.
+ return;
+ }
+
+ if (!device_local_account_policy_service_) {
+ NOTREACHED();
+ return;
+ }
+ DeviceLocalAccountPolicyBroker* broker =
+ device_local_account_policy_service_->GetBrokerForUser(user_id);
+ if (!broker) {
+ NOTREACHED();
+ return;
+ }
+
+ const PolicyMap::Entry* entry =
+ broker->core()->store()->policy_map().Get(policy_);
+ if (!entry) {
+ DeviceLocalAccountEntryMap::iterator it =
+ device_local_account_entries_.find(user_id);
+ if (it != device_local_account_entries_.end()) {
+ delete it->second.value;
+ delete it->second.external_data_fetcher;
+ device_local_account_entries_.erase(it);
+ HandleExternalDataPolicyUpdate(user_id, NULL);
+ }
+ return;
+ }
+
+ PolicyMap::Entry& map_entry = device_local_account_entries_[user_id];
+ if (map_entry.Equals(*entry))
+ return;
+
+ map_entry = *entry->DeepCopy();
Joao da Silva 2013/11/27 14:33:59 This leaks map_entry.value and map_entry.external_
bartfab (slow) 2013/11/27 20:10:15 Done.
+ HandleExternalDataPolicyUpdate(user_id, entry);
+}
+
+void CloudExternalDataPolicyObserverChromeOS::OnDeviceLocalAccountsChanged() {
+ // No action needed here, changes to the list of device-local accounts get
+ // handled via the kAccountsPrefDeviceLocalAccounts device setting observer.
+}
+
+void CloudExternalDataPolicyObserverChromeOS::RetrieveDeviceLocalAccounts() {
+ // Schedule a callback if device policy has not yet been verified.
+ if (chromeos::CrosSettingsProvider::TRUSTED !=
+ cros_settings_->PrepareTrustedValues(base::Bind(
+ &CloudExternalDataPolicyObserverChromeOS::RetrieveDeviceLocalAccounts,
+ base::Unretained(this)))) {
Joao da Silva 2013/11/27 14:33:59 Is it safe to pass an unretained this? Can't the c
bartfab (slow) 2013/11/27 20:10:15 Nice catch. I copy & pasted this snippet from some
+ return;
+ }
+
+ std::vector<DeviceLocalAccount> device_local_account_list =
+ policy::GetDeviceLocalAccounts(cros_settings_);
+ std::set<std::string> device_local_accounts;
+ for (std::vector<DeviceLocalAccount>::const_iterator it =
+ device_local_account_list.begin();
+ it != device_local_account_list.end(); ++it) {
+ device_local_accounts.insert(it->user_id);
+ }
+
+ for (DeviceLocalAccountEntryMap::iterator it =
+ device_local_account_entries_.begin();
+ it != device_local_account_entries_.end(); ) {
+ if (device_local_accounts.find(it->first) == device_local_accounts.end()) {
Joao da Silva 2013/11/27 14:33:59 !ContainsKey
bartfab (slow) 2013/11/27 20:10:15 Done.
+ const std::string user_id = it->first;
+ delete it->second.value;
+ delete it->second.external_data_fetcher;
Joao da Silva 2013/11/27 14:33:59 This is repeated in 3 places, and maybe a 4th is a
bartfab (slow) 2013/11/27 20:10:15 Done.
+ device_local_account_entries_.erase(it++);
+ // When a device-local account whose external data reference was set is
+ // removed, emit a notification that the external data reference has been
+ // cleared.
+ HandleExternalDataPolicyUpdate(user_id, NULL);
+ } else {
+ ++it;
+ }
+ }
+
+ for (std::set<std::string>::const_iterator it = device_local_accounts.begin();
+ it != device_local_accounts.end(); ++it) {
+ OnPolicyUpdated(*it);
+ }
+}
+
+void CloudExternalDataPolicyObserverChromeOS::HandleExternalDataPolicyUpdate(
+ const std::string& user_id,
+ const PolicyMap::Entry* entry) {
+ if (!entry) {
+ OnExternalDataCleared(user_id);
+ fetch_weak_ptrs_.erase(user_id);
+ return;
+ }
+
+ OnExternalDataSet(user_id);
+
+ linked_ptr<WeakPtrFactory>& weak_ptr_factory = fetch_weak_ptrs_[user_id];
+ weak_ptr_factory.reset(new WeakPtrFactory(this));
+ if (entry->external_data_fetcher) {
+ entry->external_data_fetcher->Fetch(base::Bind(
+ &CloudExternalDataPolicyObserverChromeOS::OnExternalDataFetched,
+ weak_ptr_factory->GetWeakPtr(),
+ user_id));
+ } else {
+ NOTREACHED();
+ }
+}
+
+} // namespace policy

Powered by Google App Engine
This is Rietveld 408576698