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