blob: d0bcd77a1f6467c2956f1b8548e11796b0578998 [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 Masone52cd19b2011-06-29 17:23:04 -070022
Chris Masone6791a432011-07-12 13:23:19 -070023using std::map;
Chris Masone52cd19b2011-06-29 17:23:04 -070024using std::string;
Chris Masone6791a432011-07-12 13:23:19 -070025using std::vector;
Chris Masone52cd19b2011-06-29 17:23:04 -070026
27namespace shill {
Darin Petkova4766822011-07-07 10:42:22 -070028
Darin Petkova4766822011-07-07 10:42:22 -070029Profile::Profile(ControlInterface *control_interface,
Chris Masone6791a432011-07-12 13:23:19 -070030 GLib *glib,
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_(glib),
38 storage_format_(user_storage_format) {
Chris Masone7df0c672011-07-15 10:24:54 -070039 if (connect_to_rpc)
40 adaptor_.reset(control_interface->CreateProfileAdaptor(this));
41
Chris Masone88cbd5f2011-07-03 14:30:04 -070042 // flimflam::kCheckPortalListProperty: Registered in DefaultProfile
43 // flimflam::kCountryProperty: Registered in DefaultProfile
Chris Masone7df0c672011-07-15 10:24:54 -070044 store_.RegisterConstString(flimflam::kNameProperty, &name_.identifier);
Chris Masone88cbd5f2011-07-03 14:30:04 -070045
46 // flimflam::kOfflineModeProperty: Registered in DefaultProfile
47 // flimflam::kPortalURLProperty: Registered in DefaultProfile
48
Chris Masone6791a432011-07-12 13:23:19 -070049 HelpRegisterDerivedStrings(flimflam::kServicesProperty,
50 &Profile::EnumerateAvailableServices,
51 NULL);
Chris Masone7df0c672011-07-15 10:24:54 -070052 HelpRegisterDerivedStrings(flimflam::kEntriesProperty,
53 &Profile::EnumerateEntries,
54 NULL);
Chris Masone52cd19b2011-06-29 17:23:04 -070055}
56
57Profile::~Profile() {}
58
Chris Masone7df0c672011-07-15 10:24:54 -070059string Profile::GetFriendlyName() {
60 return (name_.user.empty() ? "" : name_.user + "/") + name_.identifier;
61}
62
63string Profile::GetRpcIdentifier() {
64 return adaptor_->GetRpcIdentifier();
65}
66
Chris Masone6791a432011-07-12 13:23:19 -070067bool Profile::AdoptService(const ServiceRefPtr &service) {
68 if (ContainsKey(services_, service->UniqueName()))
69 return false;
70 service->set_profile(this);
71 services_[service->UniqueName()] = service;
72 return true;
73}
74
75bool Profile::AbandonService(const string &name) {
76 map<string, ServiceRefPtr>::iterator to_abandon = services_.find(name);
77 if (to_abandon != services_.end()) {
78 services_.erase(to_abandon);
79 return true;
80 }
81 return false;
82}
83
84bool Profile::DemoteService(const string &name) {
85 map<string, ServiceRefPtr>::iterator to_demote = services_.find(name);
86 if (to_demote == services_.end())
87 return false;
88 return true; // TODO(cmasone): mark |to_demote| as inactive or something.
89}
90
91bool Profile::MergeService(const ServiceRefPtr &service) {
92 map<string, ServiceRefPtr>::iterator it;
93 for (it = services_.begin(); it != services_.end(); ++it) {
94 if (Mergeable(it->second, service))
95 return true; // TODO(cmasone): Perform merge.
96 }
97 return false;
98}
99
100ServiceRefPtr Profile::FindService(const std::string& name) {
101 if (ContainsKey(services_, name))
102 return services_[name];
103 return NULL;
104}
105
106void Profile::Finalize() {
107 // TODO(cmasone): Flush all of |services_| to disk if needed.
108 services_.clear();
Chris Masone7aa5f902011-07-11 11:13:35 -0700109}
110
Darin Petkova4766822011-07-07 10:42:22 -0700111bool Profile::IsValidIdentifierToken(const std::string &token) {
112 if (token.empty()) {
113 return false;
114 }
115 for (string::const_iterator it = token.begin(); it != token.end(); ++it) {
116 if (!IsAsciiAlpha(*it) && !IsAsciiDigit(*it)) {
117 return false;
118 }
119 }
120 return true;
121}
122
123bool Profile::ParseIdentifier(const string &raw, Identifier *parsed) {
124 if (raw.empty()) {
125 return false;
126 }
127 if (raw[0] == '~') {
128 // Format: "~user/identifier".
129 size_t slash = raw.find('/');
130 if (slash == string::npos) {
131 return false;
132 }
133 string user(raw.begin() + 1, raw.begin() + slash);
134 string identifier(raw.begin() + slash + 1, raw.end());
135 if (!IsValidIdentifierToken(user) || !IsValidIdentifierToken(identifier)) {
136 return false;
137 }
138 parsed->user = user;
139 parsed->identifier = identifier;
140 return true;
141 }
142
143 // Format: "identifier".
144 if (!IsValidIdentifierToken(raw)) {
145 return false;
146 }
147 parsed->user = "";
148 parsed->identifier = raw;
149 return true;
150}
151
Chris Masone2ae797d2011-08-23 20:41:00 -0700152bool Profile::GetStoragePath(FilePath *path) {
153 if (name_.user.empty()) {
154 LOG(ERROR) << "Non-default profiles cannot be stored globally.";
155 return false;
156 }
157 FilePath dir(base::StringPrintf(storage_format_.c_str(), name_.user.c_str()));
Darin Petkova4766822011-07-07 10:42:22 -0700158 // TODO(petkov): Validate the directory permissions, etc.
159 *path = dir.Append(base::StringPrintf("%s.profile",
Chris Masone2ae797d2011-08-23 20:41:00 -0700160 name_.identifier.c_str()));
Darin Petkova4766822011-07-07 10:42:22 -0700161 return true;
162}
163
Chris Masone6791a432011-07-12 13:23:19 -0700164vector<string> Profile::EnumerateAvailableServices() {
165 return manager_->EnumerateAvailableServices();
166}
167
168vector<string> Profile::EnumerateEntries() {
169 vector<string> rpc_ids;
170 map<string, ServiceRefPtr>::const_iterator it;
171 for (it = services_.begin(); it != services_.end(); ++it) {
172 rpc_ids.push_back(it->second->GetRpcIdentifier());
173 }
174 return rpc_ids;
175}
176
177void Profile::HelpRegisterDerivedStrings(const string &name,
178 Strings(Profile::*get)(void),
179 bool(Profile::*set)(const Strings&)) {
180 store_.RegisterDerivedStrings(
181 name,
182 StringsAccessor(new CustomAccessor<Profile, Strings>(this, get, set)));
183}
184
Chris Masone52cd19b2011-06-29 17:23:04 -0700185} // namespace shill