generic_variables.h revision c16fca2f1b263872e12503eab4621250ef1f1e1c
1// Copyright (c) 2014 The Chromium OS 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// Generic and provider-independent Variable subclasses. These variables can be
6// used by any state provider to implement simple variables to avoid repeat the
7// same common code on different state providers.
8
9#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_GENERIC_VARIABLES_H_
10#define CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_GENERIC_VARIABLES_H_
11
12#include <base/callback.h>
13
14#include "update_engine/policy_manager/variable.h"
15
16namespace {
17
18const char* kCopyVariableDefaultErrMsg = "Requested value is not set";
19
20}  // namespace
21
22
23namespace chromeos_policy_manager {
24
25// Variable class returning a copy of a given object using the copy constructor.
26// This template class can be used to define variables that expose as a variable
27// any fixed object, such as the a provider's private member. The variable will
28// create copies of the provided object using the copy constructor of that
29// class.
30//
31// For example, a state provider exposing a private member as a variable can
32// implement this as follows:
33//
34//   class SomethingProvider {
35//    public:
36//      SomethingProvider(...) {
37//        var_something_foo = new CopyVariable<MyType>(foo_);
38//      }
39//      ...
40//    private:
41//     MyType foo_;
42//   };
43template<typename T>
44class CopyVariable : public Variable<T> {
45 public:
46  // Creates the variable returning copies of the passed |ref|. The reference to
47  // this object is kept and it should be available whenever the GetValue()
48  // method is called. If |is_set_p| is not null, then this flag will be
49  // consulted prior to returning the value, and an |errmsg| will be returned if
50  // it is not set.
51  CopyVariable(const std::string& name, VariableMode mode, const T& ref,
52               const bool* is_set_p, const std::string& errmsg)
53      : Variable<T>(name, mode), ref_(ref), is_set_p_(is_set_p),
54        errmsg_(errmsg) {}
55  CopyVariable(const std::string& name, VariableMode mode, const T& ref,
56               const bool* is_set_p)
57      : CopyVariable(name, mode, ref, is_set_p, kCopyVariableDefaultErrMsg) {}
58  CopyVariable(const std::string& name, VariableMode mode, const T& ref)
59      : CopyVariable(name, mode, ref, nullptr) {}
60
61  CopyVariable(const std::string& name, const base::TimeDelta poll_interval,
62               const T& ref, const bool* is_set_p, const std::string& errmsg)
63      : Variable<T>(name, poll_interval), ref_(ref), is_set_p_(is_set_p),
64        errmsg_(errmsg) {}
65  CopyVariable(const std::string& name, const base::TimeDelta poll_interval,
66               const T& ref, const bool* is_set_p)
67      : CopyVariable(name, poll_interval, ref, is_set_p,
68                     kCopyVariableDefaultErrMsg) {}
69  CopyVariable(const std::string& name, const base::TimeDelta poll_interval,
70               const T& ref)
71      : CopyVariable(name, poll_interval, ref, nullptr) {}
72
73 protected:
74  FRIEND_TEST(PmCopyVariableTest, SimpleTest);
75  FRIEND_TEST(PmCopyVariableTest, UseCopyConstructorTest);
76
77  // Variable override.
78  virtual inline const T* GetValue(base::TimeDelta /* timeout */,
79                                   std::string* errmsg) {
80    if (is_set_p_ && !(*is_set_p_)) {
81      if (errmsg)
82        *errmsg = errmsg_;
83      return nullptr;
84    }
85    return new T(ref_);
86  }
87
88 private:
89  // Reference to the object to be copied by GetValue().
90  const T& ref_;
91
92  // A pointer to a flag indicating whether the value is set. If null, then the
93  // value is assumed to be set.
94  const bool* const is_set_p_;
95
96  // An error message to be returned when attempting to get an unset value.
97  const std::string errmsg_;
98};
99
100// Variable class returning a constant value that is cached on the variable when
101// it is created.
102template<typename T>
103class ConstCopyVariable : public Variable<T> {
104 public:
105  // Creates the variable returning copies of the passed |obj|. The value passed
106  // is copied in this variable, and new copies of it will be returned by
107  // GetValue().
108  ConstCopyVariable(const std::string& name, const T& obj)
109      : Variable<T>(name, kVariableModeConst), obj_(obj) {}
110
111 protected:
112  // Variable override.
113  virtual const T* GetValue(base::TimeDelta /* timeout */,
114                            std::string* /* errmsg */) {
115    return new T(obj_);
116  }
117
118 private:
119  // Value to be copied by GetValue().
120  const T obj_;
121};
122
123// Variable class returning a copy of a value returned by a given function. The
124// function is called every time the variable is being polled.
125template<typename T>
126class CallCopyVariable : public Variable<T> {
127 public:
128  CallCopyVariable(const std::string& name, base::Callback<T(void)> func)
129      : Variable<T>(name, kVariableModePoll), func_(func) {}
130  CallCopyVariable(const std::string& name,
131                   const base::TimeDelta poll_interval,
132                   base::Callback<T(void)> func)
133      : Variable<T>(name, poll_interval), func_(func) {}
134
135 protected:
136  // Variable override.
137  virtual const T* GetValue(base::TimeDelta /* timeout */,
138                            std::string* /* errmsg */) {
139    if (func_.is_null())
140      return nullptr;
141    return new T(func_.Run());
142  }
143
144 private:
145  FRIEND_TEST(PmCallCopyVariableTest, SimpleTest);
146
147  // The function to be called, stored as a base::Callback.
148  base::Callback<T(void)> func_;
149
150  DISALLOW_COPY_AND_ASSIGN(CallCopyVariable);
151};
152
153
154// A Variable class to implement simple Async variables. It provides two methods
155// SetValue and UnsetValue to modify the current value of the variable and
156// notify the registered observers whenever the value changed.
157//
158// The type T needs to be copy-constructable, default-constructable and have an
159// operator== (to determine if the value changed), which makes this class
160// suitable for basic types.
161template<typename T>
162class AsyncCopyVariable : public Variable<T> {
163 public:
164  explicit AsyncCopyVariable(const std::string& name)
165      : Variable<T>(name, kVariableModeAsync), has_value_(false) {}
166
167  AsyncCopyVariable(const std::string& name, const T value)
168      : Variable<T>(name, kVariableModeAsync),
169        has_value_(true), value_(value) {}
170
171  void SetValue(const T& new_value) {
172    bool should_notify = !(has_value_ && new_value == value_);
173    value_ = new_value;
174    has_value_ = true;
175    if (should_notify)
176      this->NotifyValueChanged();
177  }
178
179  void UnsetValue() {
180    if (has_value_) {
181      has_value_ = false;
182      this->NotifyValueChanged();
183    }
184  }
185
186 protected:
187  // Variable override.
188  virtual const T* GetValue(base::TimeDelta /* timeout */,
189                            std::string* errmsg) {
190    if (!has_value_) {
191      if (errmsg)
192        *errmsg = "No value set for " + this->GetName();
193      return nullptr;
194    }
195    return new T(value_);
196  }
197
198 private:
199  // Whether the variable has a value set.
200  bool has_value_;
201
202  // Copy of the object to be returned by GetValue().
203  T value_;
204};
205
206}  // namespace chromeos_policy_manager
207
208#endif  // CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_GENERIC_VARIABLES_H_
209