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
30namespace 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//   };
50template<typename T>
51class 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, 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) {}
62  PollCopyVariable(const std::string& name, const T& ref, const bool* is_set_p)
63      : PollCopyVariable(name, ref, is_set_p, std::string()) {}
64  PollCopyVariable(const std::string& name, const T& ref)
65      : PollCopyVariable(name, ref, nullptr) {}
66
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) {}
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()) {}
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.
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.
112template<typename T>
113class 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().
118  ConstCopyVariable(const std::string& name, const T& obj)
119      : Variable<T>(name, kVariableModeConst), obj_(obj) {}
120
121 protected:
122  // Variable override.
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.
135template<typename T>
136class CallCopyVariable : public Variable<T> {
137 public:
138  CallCopyVariable(const std::string& name, base::Callback<T(void)> func)
139      : Variable<T>(name, kVariableModePoll), func_(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.
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.
171template<typename T>
172class AsyncCopyVariable : public Variable<T> {
173 public:
174  explicit AsyncCopyVariable(const std::string& name)
175      : Variable<T>(name, kVariableModeAsync), has_value_(false) {}
176
177  AsyncCopyVariable(const std::string& name, const T value)
178      : Variable<T>(name, kVariableModeAsync),
179        has_value_(true), value_(value) {}
180
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
189  void UnsetValue() {
190    if (has_value_) {
191      has_value_ = false;
192      this->NotifyValueChanged();
193    }
194  }
195
196 protected:
197  // Variable override.
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