1//
2// Copyright (C) 2012 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#ifndef SHILL_PROFILE_H_
18#define SHILL_PROFILE_H_
19
20#include <map>
21#include <memory>
22#include <string>
23#include <vector>
24
25#include <base/files/file_path.h>
26#include <gtest/gtest_prod.h>  // for FRIEND_TEST
27
28#include "shill/event_dispatcher.h"
29#include "shill/property_store.h"
30#include "shill/refptr_types.h"
31
32namespace base {
33
34class FilePath;
35
36}  // namespace base
37
38namespace shill {
39
40class ControlInterface;
41class Error;
42class Manager;
43class Metrics;
44class ProfileAdaptorInterface;
45class StoreInterface;
46
47#if !defined(DISABLE_WIFI)
48class WiFiProvider;
49#endif  // DISABLE_WIFI
50
51class Profile : public base::RefCounted<Profile> {
52 public:
53  enum InitStorageOption {
54    kOpenExisting,
55    kCreateNew,
56    kCreateOrOpenExisting
57  };
58  struct Identifier {
59    Identifier() {}
60    explicit Identifier(const std::string& i) : identifier(i) {}
61    Identifier(const std::string& u, const std::string& i)
62        : user(u),
63          identifier(i) {
64    }
65    std::string user;  // Empty for global.
66    std::string identifier;
67    std::string user_hash;
68  };
69
70  // Path to the cached list of inserted user profiles to be loaded at
71  // startup.
72  static const char kUserProfileListPathname[];
73
74  Profile(ControlInterface* control_interface,
75          Metrics* metrics,
76          Manager* manager,
77          const Identifier& name,
78          const base::FilePath& storage_directory,
79          bool connect_to_rpc);
80
81  virtual ~Profile();
82
83  // Set up persistent storage for this Profile.
84  bool InitStorage(InitStorageOption storage_option,
85                   Error* error);
86
87  // Set up stub storage for this Profile. The data will NOT be
88  // persisted. In most cases, you should prefer InitStorage.
89  void InitStubStorage();
90
91  // Remove the persistent storage for this Profile.  It is an error to
92  // do so while the underlying storage is open via InitStorage() or
93  // set_storage().
94  bool RemoveStorage(Error* error);
95
96  virtual std::string GetFriendlyName();
97
98  virtual std::string GetRpcIdentifier();
99
100  PropertyStore* mutable_store() { return &store_; }
101  const PropertyStore& store() const { return store_; }
102
103  // Set the storage inteface.  This is used for testing purposes.  It
104  // takes ownership of |storage|.
105  void set_storage(StoreInterface* storage);
106
107  // Begin managing the persistence of |service|.
108  // Returns true if |service| is new to this profile and was added,
109  // false if the |service| already existed.
110  virtual bool AdoptService(const ServiceRefPtr& service);
111
112  // Cease managing the persistence of the Service |service|.
113  // Returns true if |service| was found and abandoned, or not found.
114  // Returns false if can't be abandoned.
115  virtual bool AbandonService(const ServiceRefPtr& service);
116
117  // Clobbers persisted notion of |service| with data from |service|.
118  // Returns true if |service| was found and updated, false if not found.
119  virtual bool UpdateService(const ServiceRefPtr& service);
120
121  // Ask |service| if it can configure itself from the profile.  If it can,
122  // ask |service| to perform the configuration and return true.  If not,
123  // return false.
124  virtual bool LoadService(const ServiceRefPtr& service);
125
126  // Perform LoadService() on |service|.  If this succeeds, change
127  // the service to point at this profile and return true.  If not, return
128  // false.
129  virtual bool ConfigureService(const ServiceRefPtr& service);
130
131  // Allow the device to configure itself from this profile.  Returns
132  // true if the device succeeded in finding its configuration.  If not,
133  // return false.
134  virtual bool ConfigureDevice(const DeviceRefPtr& device);
135
136  // Remove a named entry from the profile.  This includes detaching
137  // any service that uses this profile entry.
138  virtual void DeleteEntry(const std::string& entry_name, Error* error);
139
140  // Return a service configured from the given profile entry.
141  // Callers must not register the returned service with the Manager or connect
142  // it since it might not be in the provider's service list.
143  virtual ServiceRefPtr GetServiceFromEntry(const std::string& entry_name,
144                                            Error* error);
145
146  // Return whether |service| can configure itself from the profile.
147  bool ContainsService(const ServiceConstRefPtr& service);
148
149  std::vector<std::string> EnumerateAvailableServices(Error* error);
150  std::vector<std::string> EnumerateEntries(Error* error);
151
152  // Clobbers persisted notion of |device| with data from |device|. Returns true
153  // if |device| was found and updated, false otherwise. The base implementation
154  // always returns false -- currently devices are persisted only in
155  // DefaultProfile.
156  virtual bool UpdateDevice(const DeviceRefPtr& device);
157
158#if !defined(DISABLE_WIFI)
159  // Clobbers persisted notion of |wifi_provider| with data from
160  // |wifi_provider|. Returns true if |wifi_provider| was found and updated,
161  // false otherwise. The base implementation always returns false -- currently
162  // wifi_provider is persisted only in DefaultProfile.
163  virtual bool UpdateWiFiProvider(const WiFiProvider& wifi_provider);
164#endif  // DISABLE_WIFI
165
166  // Write all in-memory state to disk via |storage_|.
167  virtual bool Save();
168
169  // Parses a profile identifier. There're two acceptable forms of the |raw|
170  // identifier: "identifier" and "~user/identifier". Both "user" and
171  // "identifier" must be suitable for use in a D-Bus object path. Returns true
172  // on success.
173  static bool ParseIdentifier(const std::string& raw, Identifier* parsed);
174
175  // Returns the composite string identifier for a profile, as would have
176  // been used in an argument to Manager::PushProfile() in creating this
177  // profile.  It returns a string in the form "identifier", or
178  // "~user/identifier" depending on whether this profile has a user
179  // component.
180  static std::string IdentifierToString(const Identifier& name);
181
182  // Load a list of user profile identifiers from a cache file |path|.
183  // The profiles themselves are not loaded.
184  static std::vector<Identifier> LoadUserProfileList(
185      const base::FilePath& path);
186
187  // Save a list of user profile identifiers |profiles| to a cache file |path|.
188  // Returns true if successful, false otherwise.
189  static bool SaveUserProfileList(const base::FilePath& path,
190                                  const std::vector<ProfileRefPtr>& profiles);
191
192  // Returns whether |name| matches this Profile's |name_|.
193  virtual bool MatchesIdentifier(const Identifier& name) const;
194
195  // Returns the username component of the profile identifier.
196  const std::string& GetUser() const { return name_.user; }
197
198  // Returns the user_hash component of the profile identifier.
199  const std::string& GetUserHash() const { return name_.user_hash; }
200
201  virtual StoreInterface* GetStorage() {
202    return storage_.get();
203  }
204
205  // Returns a read-only copy of the backing storage of the profile.
206  virtual const StoreInterface* GetConstStorage() const {
207    return storage_.get();
208  }
209
210  virtual bool IsDefault() const { return false; }
211
212 protected:
213  // Returns the persistent store file path for a Profile with the
214  // given |storage_dir| and |profile_name|. Provided as a static
215  // method, so that tests can use this logic without having to
216  // instantiate a Profile.
217  static base::FilePath GetFinalStoragePath(
218      const base::FilePath& storage_dir,
219      const Identifier& profile_name);
220
221  Metrics* metrics() const { return metrics_; }
222  Manager* manager() const { return manager_; }
223  StoreInterface* storage() { return storage_.get(); }
224  const base::FilePath& persistent_profile_path() {
225    return persistent_profile_path_;
226  }
227  void set_persistent_profile_path(const base::FilePath& path) {
228    persistent_profile_path_ = path;
229  }
230
231 private:
232  friend class ManagerTest;
233  friend class ProfileAdaptorInterface;
234  FRIEND_TEST(ManagerTest, CreateDuplicateProfileWithMissingKeyfile);
235  FRIEND_TEST(ManagerTest, RemoveProfile);
236  FRIEND_TEST(ProfileTest, DeleteEntry);
237  FRIEND_TEST(ProfileTest, GetStoragePath);
238  FRIEND_TEST(ProfileTest, IsValidIdentifierToken);
239  FRIEND_TEST(ProfileTest, GetServiceFromEntry);
240
241  static bool IsValidIdentifierToken(const std::string& token);
242
243  void HelpRegisterConstDerivedStrings(
244      const std::string& name,
245      Strings(Profile::*get)(Error* error));
246
247  // Data members shared with subclasses via getter/setters above in the
248  // protected: section
249  Metrics* metrics_;
250  Manager* manager_;
251  ControlInterface* control_interface_;
252  base::FilePath persistent_profile_path_;
253
254  // Shared with |adaptor_| via public getter.
255  PropertyStore store_;
256
257  // Properties to be gotten via PropertyStore calls.
258  Identifier name_;
259
260  // Allows this profile to be backed with on-disk storage.
261  std::unique_ptr<StoreInterface> storage_;
262
263  std::unique_ptr<ProfileAdaptorInterface> adaptor_;
264
265  DISALLOW_COPY_AND_ASSIGN(Profile);
266};
267
268}  // namespace shill
269
270#endif  // SHILL_PROFILE_H_
271