Home | History | Annotate | Download | only in policy
      1 // Copyright 2014 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/server_backed_state_keys_broker.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/bind.h"
     10 #include "base/location.h"
     11 #include "base/task_runner.h"
     12 #include "chromeos/dbus/session_manager_client.h"
     13 
     14 namespace policy {
     15 
     16 namespace {
     17 
     18 // Refresh interval for state keys. There's a quantized time component in
     19 // state key generation, so they rotate over time. The quantum size is pretty
     20 // coarse though (currently 2^23 seconds), so simply polling for a new state
     21 // keys once a day is good enough.
     22 const int kPollIntervalSeconds = 60 * 60 * 24;
     23 
     24 }  // namespace
     25 
     26 ServerBackedStateKeysBroker::ServerBackedStateKeysBroker(
     27     chromeos::SessionManagerClient* session_manager_client,
     28     scoped_refptr<base::TaskRunner> delayed_task_runner)
     29     : session_manager_client_(session_manager_client),
     30       delayed_task_runner_(delayed_task_runner),
     31       requested_(false),
     32       initial_retrieval_completed_(false),
     33       weak_factory_(this) {
     34 }
     35 
     36 ServerBackedStateKeysBroker::~ServerBackedStateKeysBroker() {
     37 }
     38 
     39 ServerBackedStateKeysBroker::Subscription
     40 ServerBackedStateKeysBroker::RegisterUpdateCallback(
     41     const base::Closure& callback) {
     42   if (!available())
     43     FetchStateKeys();
     44   return update_callbacks_.Add(callback);
     45 }
     46 
     47 void ServerBackedStateKeysBroker::RequestStateKeys(
     48     const StateKeysCallback& callback) {
     49   if (pending()) {
     50     request_callbacks_.push_back(callback);
     51     FetchStateKeys();
     52     return;
     53   }
     54 
     55   if (!callback.is_null())
     56     callback.Run(state_keys_);
     57   return;
     58 }
     59 
     60 void ServerBackedStateKeysBroker::FetchStateKeys() {
     61   if (!requested_) {
     62     requested_ = true;
     63     session_manager_client_->GetServerBackedStateKeys(
     64         base::Bind(&ServerBackedStateKeysBroker::StoreStateKeys,
     65                    weak_factory_.GetWeakPtr()));
     66   }
     67 }
     68 
     69 void ServerBackedStateKeysBroker::StoreStateKeys(
     70     const std::vector<std::string>& state_keys) {
     71   bool send_notification = !initial_retrieval_completed_;
     72 
     73   requested_ = false;
     74   initial_retrieval_completed_ = true;
     75   if (state_keys.empty()) {
     76     LOG(WARNING) << "Failed to obtain server-backed state keys.";
     77   } else if (state_keys.end() !=
     78              std::find(state_keys.begin(), state_keys.end(), std::string())) {
     79     LOG(WARNING) << "Bad state keys.";
     80   } else {
     81     send_notification |= state_keys_ != state_keys;
     82     state_keys_ = state_keys;
     83   }
     84 
     85   if (send_notification)
     86     update_callbacks_.Notify();
     87 
     88   std::vector<StateKeysCallback> callbacks;
     89   request_callbacks_.swap(callbacks);
     90   for (std::vector<StateKeysCallback>::const_iterator callback(
     91            callbacks.begin());
     92        callback != callbacks.end();
     93        ++callback) {
     94     if (!callback->is_null())
     95       callback->Run(state_keys_);
     96   }
     97 
     98   delayed_task_runner_->PostDelayedTask(
     99       FROM_HERE,
    100       base::Bind(&ServerBackedStateKeysBroker::FetchStateKeys,
    101                  weak_factory_.GetWeakPtr()),
    102       base::TimeDelta::FromSeconds(kPollIntervalSeconds));
    103 }
    104 
    105 }  // namespace policy
    106