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
ServerBackedStateKeysBroker(chromeos::SessionManagerClient * session_manager_client,scoped_refptr<base::TaskRunner> delayed_task_runner)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
~ServerBackedStateKeysBroker()36 ServerBackedStateKeysBroker::~ServerBackedStateKeysBroker() {
37 }
38
39 ServerBackedStateKeysBroker::Subscription
RegisterUpdateCallback(const base::Closure & callback)40 ServerBackedStateKeysBroker::RegisterUpdateCallback(
41 const base::Closure& callback) {
42 if (!available())
43 FetchStateKeys();
44 return update_callbacks_.Add(callback);
45 }
46
RequestStateKeys(const StateKeysCallback & callback)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
FetchStateKeys()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
StoreStateKeys(const std::vector<std::string> & state_keys)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