This source file includes following definitions.
- metadata_set_
- SetExternalDataStore
- Connect
- Disconnect
- OnMetadataUpdated
- OnDownloadSuccess
- Fetch
- FetchAll
- GetMaxExternalDataSize
- RunCallback
- StartDownload
- backend_
- SetExternalDataStore
- SetPolicyStore
- OnPolicyStoreLoaded
- Connect
- Disconnect
- Fetch
- SetMaxExternalDataSizeForTesting
- FetchAll
#include "chrome/browser/chromeos/policy/cloud_external_data_manager_base.h"
#include <map>
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/chromeos/policy/cloud_external_data_store.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
#include "components/policy/core/common/cloud/external_policy_data_fetcher.h"
#include "components/policy/core/common/cloud/external_policy_data_updater.h"
#include "components/policy/core/common/external_data_fetcher.h"
#include "components/policy/core/common/policy_map.h"
#include "net/url_request/url_request_context_getter.h"
namespace policy {
namespace {
const int kMaxParallelFetches = 2;
int max_external_data_size_for_testing = 0;
}
class CloudExternalDataManagerBase::Backend {
public:
Backend(const GetChromePolicyDetailsCallback& get_policy_details,
scoped_refptr<base::SequencedTaskRunner> task_runner,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
void SetExternalDataStore(
scoped_ptr<CloudExternalDataStore> external_data_store);
void Connect(
scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher);
void Disconnect();
void OnMetadataUpdated(scoped_ptr<Metadata> metadata);
bool OnDownloadSuccess(const std::string& policy,
const std::string& hash,
const std::string& data);
void Fetch(const std::string& policy,
const ExternalDataFetcher::FetchCallback& callback);
void FetchAll();
private:
typedef std::vector<ExternalDataFetcher::FetchCallback> FetchCallbackList;
typedef std::map<std::string, FetchCallbackList> FetchCallbackMap;
size_t GetMaxExternalDataSize(const std::string& policy) const;
void RunCallback(const ExternalDataFetcher::FetchCallback& callback,
scoped_ptr<std::string> data) const;
void StartDownload(const std::string& policy);
GetChromePolicyDetailsCallback get_policy_details_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
FetchCallbackMap pending_downloads_;
bool metadata_set_;
Metadata metadata_;
scoped_ptr<CloudExternalDataStore> external_data_store_;
scoped_ptr<ExternalPolicyDataUpdater> updater_;
DISALLOW_COPY_AND_ASSIGN(Backend);
};
CloudExternalDataManagerBase::Backend::Backend(
const GetChromePolicyDetailsCallback& get_policy_details,
scoped_refptr<base::SequencedTaskRunner> task_runner,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner)
: get_policy_details_(get_policy_details),
task_runner_(task_runner),
callback_task_runner_(callback_task_runner),
metadata_set_(false) {
}
void CloudExternalDataManagerBase::Backend::SetExternalDataStore(
scoped_ptr<CloudExternalDataStore> external_data_store) {
external_data_store_.reset(external_data_store.release());
if (metadata_set_ && external_data_store_)
external_data_store_->Prune(metadata_);
}
void CloudExternalDataManagerBase::Backend::Connect(
scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher) {
DCHECK(!updater_);
updater_.reset(new ExternalPolicyDataUpdater(
task_runner_,
external_policy_data_fetcher.Pass(),
kMaxParallelFetches));
for (FetchCallbackMap::const_iterator it = pending_downloads_.begin();
it != pending_downloads_.end(); ++it) {
StartDownload(it->first);
}
}
void CloudExternalDataManagerBase::Backend::Disconnect() {
updater_.reset();
}
void CloudExternalDataManagerBase::Backend::OnMetadataUpdated(
scoped_ptr<Metadata> metadata) {
metadata_set_ = true;
Metadata old_metadata;
metadata_.swap(old_metadata);
if (metadata)
metadata_.swap(*metadata);
if (external_data_store_)
external_data_store_->Prune(metadata_);
for (FetchCallbackMap::iterator it = pending_downloads_.begin();
it != pending_downloads_.end(); ) {
const std::string policy = it->first;
Metadata::const_iterator metadata = metadata_.find(policy);
if (metadata == metadata_.end()) {
if (updater_) {
updater_->CancelExternalDataFetch(policy);
}
for (FetchCallbackList::const_iterator callback = it->second.begin();
callback != it->second.end(); ++callback) {
RunCallback(*callback, scoped_ptr<std::string>());
}
pending_downloads_.erase(it++);
continue;
}
if (updater_ && metadata->second != old_metadata[policy]) {
updater_->CancelExternalDataFetch(policy);
StartDownload(policy);
}
++it;
}
}
bool CloudExternalDataManagerBase::Backend::OnDownloadSuccess(
const std::string& policy,
const std::string& hash,
const std::string& data) {
DCHECK(metadata_.find(policy) != metadata_.end());
DCHECK_EQ(hash, metadata_[policy].hash);
if (external_data_store_)
external_data_store_->Store(policy, hash, data);
const FetchCallbackList& pending_callbacks = pending_downloads_[policy];
for (FetchCallbackList::const_iterator it = pending_callbacks.begin();
it != pending_callbacks.end(); ++it) {
RunCallback(*it, make_scoped_ptr(new std::string(data)));
}
pending_downloads_.erase(policy);
return true;
}
void CloudExternalDataManagerBase::Backend::Fetch(
const std::string& policy,
const ExternalDataFetcher::FetchCallback& callback) {
Metadata::const_iterator metadata = metadata_.find(policy);
if (metadata == metadata_.end()) {
RunCallback(callback, scoped_ptr<std::string>());
return;
}
if (pending_downloads_.find(policy) != pending_downloads_.end()) {
pending_downloads_[policy].push_back(callback);
return;
}
scoped_ptr<std::string> data(new std::string);
if (external_data_store_ && external_data_store_->Load(
policy, metadata->second.hash, GetMaxExternalDataSize(policy),
data.get())) {
RunCallback(callback, data.Pass());
return;
}
pending_downloads_[policy].push_back(callback);
StartDownload(policy);
}
void CloudExternalDataManagerBase::Backend::FetchAll() {
for (Metadata::const_iterator it = metadata_.begin(); it != metadata_.end();
++it) {
const std::string& policy = it->first;
scoped_ptr<std::string> data(new std::string);
if (pending_downloads_.find(policy) != pending_downloads_.end() ||
(external_data_store_ && external_data_store_->Load(
policy, it->second.hash, GetMaxExternalDataSize(policy),
data.get()))) {
continue;
}
pending_downloads_[policy];
StartDownload(policy);
}
}
size_t CloudExternalDataManagerBase::Backend::GetMaxExternalDataSize(
const std::string& policy) const {
if (max_external_data_size_for_testing)
return max_external_data_size_for_testing;
const PolicyDetails* details = get_policy_details_.Run(policy);
if (details)
return details->max_external_data_size;
NOTREACHED();
return 0;
}
void CloudExternalDataManagerBase::Backend::RunCallback(
const ExternalDataFetcher::FetchCallback& callback,
scoped_ptr<std::string> data) const {
callback_task_runner_->PostTask(FROM_HERE,
base::Bind(callback, base::Passed(&data)));
}
void CloudExternalDataManagerBase::Backend::StartDownload(
const std::string& policy) {
DCHECK(pending_downloads_.find(policy) != pending_downloads_.end());
if (!updater_)
return;
const MetadataEntry& metadata = metadata_[policy];
updater_->FetchExternalData(
policy,
ExternalPolicyDataUpdater::Request(metadata.url,
metadata.hash,
GetMaxExternalDataSize(policy)),
base::Bind(&CloudExternalDataManagerBase::Backend::OnDownloadSuccess,
base::Unretained(this),
policy,
metadata.hash));
}
CloudExternalDataManagerBase::CloudExternalDataManagerBase(
const GetChromePolicyDetailsCallback& get_policy_details,
scoped_refptr<base::SequencedTaskRunner> backend_task_runner,
scoped_refptr<base::SequencedTaskRunner> io_task_runner)
: backend_task_runner_(backend_task_runner),
io_task_runner_(io_task_runner),
backend_(new Backend(get_policy_details,
backend_task_runner_,
base::MessageLoopProxy::current())) {
}
CloudExternalDataManagerBase::~CloudExternalDataManagerBase() {
DCHECK(CalledOnValidThread());
io_task_runner_->DeleteSoon(FROM_HERE,
external_policy_data_fetcher_backend_.release());
backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release());
}
void CloudExternalDataManagerBase::SetExternalDataStore(
scoped_ptr<CloudExternalDataStore> external_data_store) {
DCHECK(CalledOnValidThread());
backend_task_runner_->PostTask(FROM_HERE, base::Bind(
&Backend::SetExternalDataStore,
base::Unretained(backend_.get()),
base::Passed(&external_data_store)));
}
void CloudExternalDataManagerBase::SetPolicyStore(
CloudPolicyStore* policy_store) {
DCHECK(CalledOnValidThread());
CloudExternalDataManager::SetPolicyStore(policy_store);
if (policy_store_ && policy_store_->is_initialized())
OnPolicyStoreLoaded();
}
void CloudExternalDataManagerBase::OnPolicyStoreLoaded() {
DCHECK(CalledOnValidThread());
scoped_ptr<Metadata> metadata(new Metadata);
const PolicyMap& policy_map = policy_store_->policy_map();
for (PolicyMap::const_iterator it = policy_map.begin();
it != policy_map.end(); ++it) {
if (!it->second.external_data_fetcher) {
continue;
}
const base::DictionaryValue* dict = NULL;
std::string url;
std::string hex_hash;
std::vector<uint8> hash;
if (it->second.value && it->second.value->GetAsDictionary(&dict) &&
dict->GetStringWithoutPathExpansion("url", &url) &&
dict->GetStringWithoutPathExpansion("hash", &hex_hash) &&
!url.empty() && !hex_hash.empty() &&
base::HexStringToBytes(hex_hash, &hash)) {
(*metadata)[it->first] =
MetadataEntry(url, std::string(hash.begin(), hash.end()));
}
}
backend_task_runner_->PostTask(FROM_HERE, base::Bind(
&Backend::OnMetadataUpdated,
base::Unretained(backend_.get()),
base::Passed(&metadata)));
}
void CloudExternalDataManagerBase::Connect(
scoped_refptr<net::URLRequestContextGetter> request_context) {
DCHECK(CalledOnValidThread());
DCHECK(!external_policy_data_fetcher_backend_);
external_policy_data_fetcher_backend_.reset(
new ExternalPolicyDataFetcherBackend(io_task_runner_,
request_context));
backend_task_runner_->PostTask(FROM_HERE, base::Bind(
&Backend::Connect,
base::Unretained(backend_.get()),
base::Passed(external_policy_data_fetcher_backend_->CreateFrontend(
backend_task_runner_))));
}
void CloudExternalDataManagerBase::Disconnect() {
DCHECK(CalledOnValidThread());
io_task_runner_->DeleteSoon(FROM_HERE,
external_policy_data_fetcher_backend_.release());
backend_task_runner_->PostTask(FROM_HERE, base::Bind(
&Backend::Disconnect, base::Unretained(backend_.get())));
}
void CloudExternalDataManagerBase::Fetch(
const std::string& policy,
const ExternalDataFetcher::FetchCallback& callback) {
DCHECK(CalledOnValidThread());
backend_task_runner_->PostTask(FROM_HERE, base::Bind(
&Backend::Fetch, base::Unretained(backend_.get()), policy, callback));
}
void CloudExternalDataManagerBase::SetMaxExternalDataSizeForTesting(
int max_size) {
max_external_data_size_for_testing = max_size;
}
void CloudExternalDataManagerBase::FetchAll() {
DCHECK(CalledOnValidThread());
backend_task_runner_->PostTask(FROM_HERE, base::Bind(
&Backend::FetchAll, base::Unretained(backend_.get())));
}
}