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.
58   PollCopyVariable(const std::string& name,
59                    const T& ref,
60                    const bool* is_set_p,
61                    const std::string& errmsg)
62       : Variable<T>(name, kVariableModePoll),
63         ref_(ref),
64         is_set_p_(is_set_p),
65         errmsg_(errmsg) {}
66   PollCopyVariable(const std::string& name, const T& ref, const bool* is_set_p)
67       : PollCopyVariable(name, ref, is_set_p, std::string()) {}
68   PollCopyVariable(const std::string& name, const T& ref)
69       : PollCopyVariable(name, ref, nullptr) {}
70 
71   PollCopyVariable(const std::string& name,
72                    const base::TimeDelta poll_interval,
73                    const T& ref,
74                    const bool* is_set_p,
75                    const std::string& errmsg)
76       : Variable<T>(name, poll_interval),
77         ref_(ref),
78         is_set_p_(is_set_p),
79         errmsg_(errmsg) {}
80   PollCopyVariable(const std::string& name,
81                    const base::TimeDelta poll_interval,
82                    const T& ref,
83                    const bool* is_set_p)
84       : PollCopyVariable(name, poll_interval, ref, is_set_p, std::string()) {}
85   PollCopyVariable(const std::string& name,
86                    const base::TimeDelta poll_interval,
87                    const T& ref)
88       : PollCopyVariable(name, poll_interval, ref, nullptr) {}
89 
90  protected:
91   FRIEND_TEST(UmPollCopyVariableTest, SimpleTest);
92   FRIEND_TEST(UmPollCopyVariableTest, UseCopyConstructorTest);
93 
94   // Variable override.
95   inline const T* GetValue(base::TimeDelta /* timeout */,
96                            std::string* errmsg) override {
97     if (is_set_p_ && !(*is_set_p_)) {
98       if (errmsg) {
99         if (errmsg_.empty())
100           *errmsg = "No value set for " + this->GetName();
101         else
102           *errmsg = errmsg_;
103       }
104       return nullptr;
105     }
106     return new T(ref_);
107   }
108 
109  private:
110   // Reference to the object to be copied by GetValue().
111   const T& ref_;
112 
113   // A pointer to a flag indicating whether the value is set. If null, then the
114   // value is assumed to be set.
115   const bool* const is_set_p_;
116 
117   // An error message to be returned when attempting to get an unset value.
118   const std::string errmsg_;
119 };
120 
121 // Variable class returning a constant value that is cached on the variable when
122 // it is created.
123 template <typename T>
124 class ConstCopyVariable : public Variable<T> {
125  public:
126   // Creates the variable returning copies of the passed |obj|. The value passed
127   // is copied in this variable, and new copies of it will be returned by
128   // GetValue().
129   ConstCopyVariable(const std::string& name, const T& obj)
130       : Variable<T>(name, kVariableModeConst), obj_(obj) {}
131 
132  protected:
133   // Variable override.
134   const T* GetValue(base::TimeDelta /* timeout */,
135                     std::string* /* errmsg */) override {
136     return new T(obj_);
137   }
138 
139  private:
140   // Value to be copied by GetValue().
141   const T obj_;
142 };
143 
144 // Variable class returning a copy of a value returned by a given function. The
145 // function is called every time the variable is being polled.
146 template <typename T>
147 class CallCopyVariable : public Variable<T> {
148  public:
149   CallCopyVariable(const std::string& name, base::Callback<T(void)> func)
150       : Variable<T>(name, kVariableModePoll), func_(func) {}
151   CallCopyVariable(const std::string& name,
152                    const base::TimeDelta poll_interval,
153                    base::Callback<T(void)> func)
154       : Variable<T>(name, poll_interval), func_(func) {}
155 
156  protected:
157   // Variable override.
158   const T* GetValue(base::TimeDelta /* timeout */,
159                     std::string* /* errmsg */) override {
160     if (func_.is_null())
161       return nullptr;
162     return new T(func_.Run());
163   }
164 
165  private:
166   FRIEND_TEST(UmCallCopyVariableTest, SimpleTest);
167 
168   // The function to be called, stored as a base::Callback.
169   base::Callback<T(void)> func_;
170 
171   DISALLOW_COPY_AND_ASSIGN(CallCopyVariable);
172 };
173 
174 // A Variable class to implement simple Async variables. It provides two methods
175 // SetValue and UnsetValue to modify the current value of the variable and
176 // notify the registered observers whenever the value changed.
177 //
178 // The type T needs to be copy-constructible, default-constructible and have an
179 // operator== (to determine if the value changed), which makes this class
180 // suitable for basic types.
181 template <typename T>
182 class AsyncCopyVariable : public Variable<T> {
183  public:
184   explicit AsyncCopyVariable(const std::string& name)
185       : Variable<T>(name, kVariableModeAsync), has_value_(false) {}
186 
187   AsyncCopyVariable(const std::string& name, const T value)
188       : Variable<T>(name, kVariableModeAsync),
189         has_value_(true),
190         value_(value) {}
191 
192   void SetValue(const T& new_value) {
193     bool should_notify = !(has_value_ && new_value == value_);
194     value_ = new_value;
195     has_value_ = true;
196     if (should_notify)
197       this->NotifyValueChanged();
198   }
199 
200   void UnsetValue() {
201     if (has_value_) {
202       has_value_ = false;
203       this->NotifyValueChanged();
204     }
205   }
206 
207  protected:
208   // Variable override.
209   const T* GetValue(base::TimeDelta /* timeout */,
210                     std::string* errmsg) override {
211     if (!has_value_) {
212       if (errmsg)
213         *errmsg = "No value set for " + this->GetName();
214       return nullptr;
215     }
216     return new T(value_);
217   }
218 
219  private:
220   // Whether the variable has a value set.
221   bool has_value_;
222 
223   // Copy of the object to be returned by GetValue().
224   T value_;
225 };
226 
227 }  // namespace chromeos_update_manager
228 
229 #endif  // UPDATE_ENGINE_UPDATE_MANAGER_GENERIC_VARIABLES_H_
230