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