15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/policy_statistics_collector.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/callback.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h"
141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/metrics/sparse_histogram.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/task_runner.h"
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "components/policy/core/common/policy_pref_names.h"
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/policy_service.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int PolicyStatisticsCollector::kStatisticsUpdateRate =
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    24 * 60 * 60 * 1000;  // 24 hours.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyStatisticsCollector::PolicyStatisticsCollector(
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const GetChromePolicyDetailsCallback& get_details,
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const Schema& chrome_schema,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PolicyService* policy_service,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrefService* prefs,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<base::TaskRunner>& task_runner)
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : get_details_(get_details),
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      chrome_schema_(chrome_schema),
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      policy_service_(policy_service),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs_(prefs),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      task_runner_(task_runner) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyStatisticsCollector::~PolicyStatisticsCollector() {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyStatisticsCollector::Initialize() {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using base::Time;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using base::TimeDelta;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta update_rate = TimeDelta::FromMilliseconds(kStatisticsUpdateRate);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time last_update = Time::FromInternalValue(
488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      prefs_->GetInt64(policy_prefs::kLastPolicyStatisticsUpdate));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta delay = std::max(Time::Now() - last_update, TimeDelta::FromDays(0));
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delay >= update_rate)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CollectStatistics();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleUpdate(update_rate - delay);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PolicyStatisticsCollector::RegisterPrefs(PrefRegistrySimple* registry) {
588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  registry->RegisterInt64Pref(policy_prefs::kLastPolicyStatisticsUpdate, 0);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyStatisticsCollector::RecordPolicyUse(int id) {
621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  UMA_HISTOGRAM_SPARSE_SLOWLY("Enterprise.Policies", id);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyStatisticsCollector::CollectStatistics() {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const PolicyMap& policies = policy_service_->GetPolicies(
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Collect statistics.
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (Schema::Iterator it(chrome_schema_.GetPropertiesIterator());
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       !it.IsAtEnd(); it.Advance()) {
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (policies.Get(it.key())) {
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const PolicyDetails* details = get_details_.Run(it.key());
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (details)
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        RecordPolicyUse(details->id);
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      else
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        NOTREACHED();
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Take care of next update.
828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  prefs_->SetInt64(policy_prefs::kLastPolicyStatisticsUpdate,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Time::Now().ToInternalValue());
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleUpdate(base::TimeDelta::FromMilliseconds(kStatisticsUpdateRate));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyStatisticsCollector::ScheduleUpdate(base::TimeDelta delay) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  update_callback_.Reset(base::Bind(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &PolicyStatisticsCollector::CollectStatistics,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this)));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task_runner_->PostDelayedTask(FROM_HERE, update_callback_.callback(), delay);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace policy
95