blob: 3fa0ed1671c7c9c6f3a6b2c2198ee573ad5f7261 [file] [log] [blame]
Chris Masone52cd19b2011-06-29 17:23:04 -07001// Copyright (c) 2011 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#include "shill/profile.h"
6
Chris Masone6791a432011-07-12 13:23:19 -07007#include <map>
Chris Masone52cd19b2011-06-29 17:23:04 -07008#include <string>
Chris Masone6791a432011-07-12 13:23:19 -07009#include <vector>
Chris Masone52cd19b2011-06-29 17:23:04 -070010
11#include <base/logging.h>
Chris Masone6791a432011-07-12 13:23:19 -070012#include <base/stl_util-inl.h>
Darin Petkova4766822011-07-07 10:42:22 -070013#include <base/string_util.h>
Chris Masone6791a432011-07-12 13:23:19 -070014#include <base/stringprintf.h>
Chris Masone88cbd5f2011-07-03 14:30:04 -070015#include <chromeos/dbus/service_constants.h>
Chris Masone52cd19b2011-06-29 17:23:04 -070016
17#include "shill/adaptor_interfaces.h"
18#include "shill/control_interface.h"
Chris Masone6791a432011-07-12 13:23:19 -070019#include "shill/manager.h"
Chris Masone52cd19b2011-06-29 17:23:04 -070020#include "shill/property_accessor.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070021#include "shill/service.h"
Chris Masone9d779932011-08-25 16:33:41 -070022#include "shill/store_interface.h"
Chris Masone52cd19b2011-06-29 17:23:04 -070023
Chris Masone6791a432011-07-12 13:23:19 -070024using std::map;
Chris Masone52cd19b2011-06-29 17:23:04 -070025using std::string;
Chris Masone6791a432011-07-12 13:23:19 -070026using std::vector;
Chris Masone52cd19b2011-06-29 17:23:04 -070027
28namespace shill {
Darin Petkova4766822011-07-07 10:42:22 -070029
Darin Petkova4766822011-07-07 10:42:22 -070030Profile::Profile(ControlInterface *control_interface,
Chris Masone7df0c672011-07-15 10:24:54 -070031 Manager *manager,
32 const Identifier &name,
Chris Masone2ae797d2011-08-23 20:41:00 -070033 const string &user_storage_format,
Chris Masone7df0c672011-07-15 10:24:54 -070034 bool connect_to_rpc)
Chris Masone6791a432011-07-12 13:23:19 -070035 : manager_(manager),
Chris Masone7df0c672011-07-15 10:24:54 -070036 name_(name),
Chris Masone2ae797d2011-08-23 20:41:00 -070037 storage_format_(user_storage_format) {
Chris Masone7df0c672011-07-15 10:24:54 -070038 if (connect_to_rpc)
39 adaptor_.reset(control_interface->CreateProfileAdaptor(this));
40
Chris Masone88cbd5f2011-07-03 14:30:04 -070041 // flimflam::kCheckPortalListProperty: Registered in DefaultProfile
42 // flimflam::kCountryProperty: Registered in DefaultProfile
Chris Masone7df0c672011-07-15 10:24:54 -070043 store_.RegisterConstString(flimflam::kNameProperty, &name_.identifier);
Chris Masone88cbd5f2011-07-03 14:30:04 -070044
45 // flimflam::kOfflineModeProperty: Registered in DefaultProfile
46 // flimflam::kPortalURLProperty: Registered in DefaultProfile
47
Chris Masone6791a432011-07-12 13:23:19 -070048 HelpRegisterDerivedStrings(flimflam::kServicesProperty,
49 &Profile::EnumerateAvailableServices,
50 NULL);
Chris Masone7df0c672011-07-15 10:24:54 -070051 HelpRegisterDerivedStrings(flimflam::kEntriesProperty,
52 &Profile::EnumerateEntries,
53 NULL);
Chris Masone52cd19b2011-06-29 17:23:04 -070054}
55
Chris Masone9d779932011-08-25 16:33:41 -070056Profile::~Profile() {
57 DCHECK_EQ(services_.size(), 0);
58}
Chris Masone52cd19b2011-06-29 17:23:04 -070059
Chris Masone7df0c672011-07-15 10:24:54 -070060string Profile::GetFriendlyName() {
61 return (name_.user.empty() ? "" : name_.user + "/") + name_.identifier;
62}
63
64string Profile::GetRpcIdentifier() {
65 return adaptor_->GetRpcIdentifier();
66}
67
Chris Masone6791a432011-07-12 13:23:19 -070068bool Profile::AdoptService(const ServiceRefPtr &service) {
69 if (ContainsKey(services_, service->UniqueName()))
70 return false;
71 service->set_profile(this);
72 services_[service->UniqueName()] = service;
73 return true;
74}
75
76bool Profile::AbandonService(const string &name) {
77 map<string, ServiceRefPtr>::iterator to_abandon = services_.find(name);
78 if (to_abandon != services_.end()) {
79 services_.erase(to_abandon);
80 return true;
81 }
82 return false;
83}
84
85bool Profile::DemoteService(const string &name) {
86 map<string, ServiceRefPtr>::iterator to_demote = services_.find(name);
87 if (to_demote == services_.end())
88 return false;
89 return true; // TODO(cmasone): mark |to_demote| as inactive or something.
90}
91
92bool Profile::MergeService(const ServiceRefPtr &service) {
93 map<string, ServiceRefPtr>::iterator it;
94 for (it = services_.begin(); it != services_.end(); ++it) {
95 if (Mergeable(it->second, service))
96 return true; // TODO(cmasone): Perform merge.
97 }
98 return false;
99}
100
101ServiceRefPtr Profile::FindService(const std::string& name) {
102 if (ContainsKey(services_, name))
103 return services_[name];
104 return NULL;
105}
106
Chris Masone9d779932011-08-25 16:33:41 -0700107void Profile::Finalize(StoreInterface *storage) {
108 Save(storage);
Chris Masone6791a432011-07-12 13:23:19 -0700109 services_.clear();
Chris Masone7aa5f902011-07-11 11:13:35 -0700110}
111
Darin Petkova4766822011-07-07 10:42:22 -0700112bool Profile::IsValidIdentifierToken(const std::string &token) {
113 if (token.empty()) {
114 return false;
115 }
116 for (string::const_iterator it = token.begin(); it != token.end(); ++it) {
117 if (!IsAsciiAlpha(*it) && !IsAsciiDigit(*it)) {
118 return false;
119 }
120 }
121 return true;
122}
123
124bool Profile::ParseIdentifier(const string &raw, Identifier *parsed) {
125 if (raw.empty()) {
126 return false;
127 }
128 if (raw[0] == '~') {
129 // Format: "~user/identifier".
130 size_t slash = raw.find('/');
131 if (slash == string::npos) {
132 return false;
133 }
134 string user(raw.begin() + 1, raw.begin() + slash);
135 string identifier(raw.begin() + slash + 1, raw.end());
136 if (!IsValidIdentifierToken(user) || !IsValidIdentifierToken(identifier)) {
137 return false;
138 }
139 parsed->user = user;
140 parsed->identifier = identifier;
141 return true;
142 }
143
144 // Format: "identifier".
145 if (!IsValidIdentifierToken(raw)) {
146 return false;
147 }
148 parsed->user = "";
149 parsed->identifier = raw;
150 return true;
151}
152
Chris Masone9d779932011-08-25 16:33:41 -0700153bool Profile::Load(StoreInterface *storage) {
154 return false;
155}
156
157bool Profile::Save(StoreInterface *storage) {
158 // TODO(cmasone): Persist other profile info to disk.
159 return SaveServices(storage);
160}
161
Chris Masone2ae797d2011-08-23 20:41:00 -0700162bool Profile::GetStoragePath(FilePath *path) {
163 if (name_.user.empty()) {
164 LOG(ERROR) << "Non-default profiles cannot be stored globally.";
165 return false;
166 }
167 FilePath dir(base::StringPrintf(storage_format_.c_str(), name_.user.c_str()));
Darin Petkova4766822011-07-07 10:42:22 -0700168 // TODO(petkov): Validate the directory permissions, etc.
169 *path = dir.Append(base::StringPrintf("%s.profile",
Chris Masone2ae797d2011-08-23 20:41:00 -0700170 name_.identifier.c_str()));
Darin Petkova4766822011-07-07 10:42:22 -0700171 return true;
172}
173
Chris Masone6791a432011-07-12 13:23:19 -0700174vector<string> Profile::EnumerateAvailableServices() {
175 return manager_->EnumerateAvailableServices();
176}
177
178vector<string> Profile::EnumerateEntries() {
179 vector<string> rpc_ids;
180 map<string, ServiceRefPtr>::const_iterator it;
181 for (it = services_.begin(); it != services_.end(); ++it) {
182 rpc_ids.push_back(it->second->GetRpcIdentifier());
183 }
184 return rpc_ids;
185}
186
187void Profile::HelpRegisterDerivedStrings(const string &name,
188 Strings(Profile::*get)(void),
189 bool(Profile::*set)(const Strings&)) {
190 store_.RegisterDerivedStrings(
191 name,
192 StringsAccessor(new CustomAccessor<Profile, Strings>(this, get, set)));
193}
194
Chris Masone9d779932011-08-25 16:33:41 -0700195bool Profile::SaveServices(StoreInterface *storage) {
196 for (map<string, ServiceRefPtr>::iterator it = services_.begin();
197 it != services_.end();
198 ++it) {
199 VLOG(1) << "Saving service named " << it->first;
200 if (!it->second->Save(storage))
201 return false;
202 }
203 return true;
204}
205
Chris Masone52cd19b2011-06-29 17:23:04 -0700206} // namespace shill