blob: b18f7f3ee6942f62953b500c03a0e47bb87b88f1 [file] [log] [blame]
mukesh agrawal8a3188d2011-12-01 20:56:44 +00001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Chris Masone3bd3c8c2011-06-13 08:20:26 -07002// 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/cellular_service.h"
6
7#include <string>
8
Chris Masone34af2182011-08-22 11:59:36 -07009#include <base/stringprintf.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070010#include <chromeos/dbus/service_constants.h>
11
Darin Petkovb72cf402011-11-22 14:51:39 +010012#include "shill/adaptor_interfaces.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070013#include "shill/cellular.h"
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040014#include "shill/property_accessor.h"
15#include "shill/store_interface.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070016
17using std::string;
18
19namespace shill {
Darin Petkovc5f56562011-08-06 16:40:05 -070020
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040021const char CellularService::kStorageAPN[] = "Cellular.APN";
22const char CellularService::kStorageLastGoodAPN[] = "Cellular.LastGoodAPN";
23
Darin Petkov381928f2012-02-02 23:00:12 +010024// TODO(petkov): Add these to system_api/dbus/service_constants.h
25namespace {
26const char kKeyOLPURL[] = "url";
27const char kKeyOLPMethod[] = "method";
28const char kKeyOLPPostData[] = "postdata";
29} // namespace {}
30
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040031static bool GetNonEmptyField(const Stringmap &stringmap,
32 const string &fieldname,
33 string *value) {
34 Stringmap::const_iterator it = stringmap.find(fieldname);
35 if (it != stringmap.end() && !it->second.empty()) {
36 *value = it->second;
37 return true;
38 }
39 return false;
40}
41
Darin Petkov381928f2012-02-02 23:00:12 +010042CellularService::OLP::OLP() {
43 SetURL("");
44 SetMethod("");
45 SetPostData("");
46}
47
48CellularService::OLP::~OLP() {}
49
50void CellularService::OLP::CopyFrom(const OLP &olp) {
51 dict_ = olp.dict_;
52}
53
54bool CellularService::OLP::Equals(const OLP &olp) const {
55 return dict_ == olp.dict_;
56}
57
58const string &CellularService::OLP::GetURL() const {
59 return dict_.find(kKeyOLPURL)->second;
60}
61
62void CellularService::OLP::SetURL(const string &url) {
63 dict_[kKeyOLPURL] = url;
64}
65
66const string &CellularService::OLP::GetMethod() const {
67 return dict_.find(kKeyOLPMethod)->second;
68}
69
70void CellularService::OLP::SetMethod(const string &method) {
71 dict_[kKeyOLPMethod] = method;
72}
73
74const string &CellularService::OLP::GetPostData() const {
75 return dict_.find(kKeyOLPPostData)->second;
76}
77
78void CellularService::OLP::SetPostData(const string &post_data) {
79 dict_[kKeyOLPPostData] = post_data;
80}
81
82const Stringmap &CellularService::OLP::ToDict() const {
83 return dict_;
84}
85
Chris Masone3bd3c8c2011-06-13 08:20:26 -070086CellularService::CellularService(ControlInterface *control_interface,
87 EventDispatcher *dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -080088 Metrics *metrics,
Chris Masone6791a432011-07-12 13:23:19 -070089 Manager *manager,
mukesh agrawal51a7e932011-07-27 16:18:26 -070090 const CellularRefPtr &device)
Thieu Le3426c8f2012-01-11 17:35:11 -080091 : Service(control_interface, dispatcher, metrics, manager,
92 Technology::kCellular),
mukesh agrawal7a4e4002011-09-06 11:26:05 -070093 cellular_(device) {
Thieu Le9fdf1372012-05-14 15:20:48 -070094 set_connectable(true);
mukesh agrawalde29fa82011-09-16 16:16:36 -070095 PropertyStore *store = this->mutable_store();
Paul Stewartac4ac002011-08-26 12:04:26 -070096 store->RegisterConstString(flimflam::kActivationStateProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -070097 &activation_state_);
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040098 HelpRegisterDerivedStringmap(flimflam::kCellularApnProperty,
99 &CellularService::GetApn,
100 &CellularService::SetApn);
Paul Stewartac4ac002011-08-26 12:04:26 -0700101 store->RegisterConstStringmap(flimflam::kCellularLastGoodApnProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700102 &last_good_apn_info_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700103 store->RegisterConstString(flimflam::kNetworkTechnologyProperty,
Darin Petkovb72cf402011-11-22 14:51:39 +0100104 &network_technology_);
Darin Petkov381928f2012-02-02 23:00:12 +0100105 store->RegisterConstStringmap(flimflam::kPaymentPortalProperty,
106 &olp_.ToDict());
Paul Stewartac4ac002011-08-26 12:04:26 -0700107 store->RegisterConstString(flimflam::kRoamingStateProperty, &roaming_state_);
108 store->RegisterConstStringmap(flimflam::kServingOperatorProperty,
Darin Petkov3335b372011-08-22 11:05:32 -0700109 &serving_operator_.ToDict());
Paul Stewartac4ac002011-08-26 12:04:26 -0700110 store->RegisterConstString(flimflam::kUsageURLProperty, &usage_url_);
Darin Petkovac635a82012-01-10 16:51:58 +0100111
112 set_friendly_name(device->CreateFriendlyServiceName());
Darin Petkovdd3e8662012-02-03 13:16:20 +0100113 SetStorageIdentifier(string(flimflam::kTypeCellular) + "_" +
114 device->address() + "_" + friendly_name());
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700115}
116
117CellularService::~CellularService() { }
118
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400119void CellularService::HelpRegisterDerivedStringmap(
120 const string &name,
121 Stringmap(CellularService::*get)(Error *error),
122 void(CellularService::*set)(
123 const Stringmap &value, Error *error)) {
124 mutable_store()->RegisterDerivedStringmap(
125 name,
126 StringmapAccessor(
127 new CustomAccessor<CellularService, Stringmap>(this, get, set)));
128}
129
130Stringmap *CellularService::GetUserSpecifiedApn() {
131 Stringmap::iterator it = apn_info_.find(flimflam::kApnProperty);
132 if (it == apn_info_.end() || it->second.empty())
133 return NULL;
134 return &apn_info_;
135}
136
137Stringmap *CellularService::GetLastGoodApn() {
138 Stringmap::iterator it =
139 last_good_apn_info_.find(flimflam::kApnProperty);
140 if (it == last_good_apn_info_.end() || it->second.empty())
141 return NULL;
142 return &last_good_apn_info_;
143}
144
145Stringmap CellularService::GetApn(Error */*error*/) {
146 return apn_info_;
147}
148
149void CellularService::SetApn(const Stringmap &value, Error *error) {
150 // Only copy in the fields we care about, and validate the contents.
Eric Shienbroodc7073302012-04-03 14:41:44 -0400151 // If the "apn" field is missing or empty, the APN is cleared.
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400152 string str;
153 if (!GetNonEmptyField(value, flimflam::kApnProperty, &str)) {
Eric Shienbroodc7073302012-04-03 14:41:44 -0400154 apn_info_.clear();
155 } else {
156 apn_info_[flimflam::kApnProperty] = str;
157 if (GetNonEmptyField(value, flimflam::kApnUsernameProperty, &str))
158 apn_info_[flimflam::kApnUsernameProperty] = str;
159 if (GetNonEmptyField(value, flimflam::kApnPasswordProperty, &str))
160 apn_info_[flimflam::kApnPasswordProperty] = str;
161 // Clear the last good APN, otherwise the one the user just
162 // set won't be used, since LastGoodApn comes first in the
163 // search order when trying to connect. Only do this if a
164 // non-empty user APN has been supplied. If the user APN is
165 // being cleared, leave LastGoodApn alone.
166 ClearLastGoodApn();
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400167 }
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400168 adaptor()->EmitStringmapChanged(flimflam::kCellularApnProperty, apn_info_);
169 SaveToCurrentProfile();
170}
171
172void CellularService::SetLastGoodApn(const Stringmap &apn_info) {
173 last_good_apn_info_ = apn_info;
174 adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
175 last_good_apn_info_);
176 SaveToCurrentProfile();
177}
178
179void CellularService::ClearLastGoodApn() {
180 last_good_apn_info_.clear();
181 adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
182 last_good_apn_info_);
183 SaveToCurrentProfile();
184}
185
186bool CellularService::Load(StoreInterface *storage) {
187 // Load properties common to all Services.
188 if (!Service::Load(storage))
189 return false;
190
191 const string id = GetStorageIdentifier();
192 LoadApn(storage, id, kStorageAPN, &apn_info_);
193 LoadApn(storage, id, kStorageLastGoodAPN, &last_good_apn_info_);
194 return true;
195}
196
197void CellularService::LoadApn(StoreInterface *storage,
198 const string &storage_group,
199 const string &keytag,
200 Stringmap *apn_info) {
201 if (!LoadApnField(storage, storage_group, keytag,
202 flimflam::kApnProperty, apn_info))
203 return;
204 LoadApnField(storage, storage_group, keytag,
205 flimflam::kApnUsernameProperty, apn_info);
206 LoadApnField(storage, storage_group, keytag,
207 flimflam::kApnPasswordProperty, apn_info);
208}
209
210bool CellularService::LoadApnField(StoreInterface *storage,
211 const string &storage_group,
212 const string &keytag,
213 const string &apntag,
214 Stringmap *apn_info) {
215 string value;
216 if (storage->GetString(storage_group, keytag + "." + apntag, &value) &&
217 !value.empty()) {
218 (*apn_info)[apntag] = value;
219 return true;
220 }
221 return false;
222}
223
224bool CellularService::Save(StoreInterface *storage) {
225 // Save properties common to all Services.
226 if (!Service::Save(storage))
227 return false;
228
229 const string id = GetStorageIdentifier();
230 SaveApn(storage, id, GetUserSpecifiedApn(), kStorageAPN);
231 SaveApn(storage, id, GetLastGoodApn(), kStorageLastGoodAPN);
232 return true;
233}
234
235void CellularService::SaveApn(StoreInterface *storage,
236 const string &storage_group,
237 const Stringmap *apn_info,
238 const string &keytag) {
239 SaveApnField(storage, storage_group, apn_info, keytag,
240 flimflam::kApnProperty);
241 SaveApnField(storage, storage_group, apn_info, keytag,
242 flimflam::kApnUsernameProperty);
243 SaveApnField(storage, storage_group, apn_info, keytag,
244 flimflam::kApnPasswordProperty);
245}
246
247void CellularService::SaveApnField(StoreInterface *storage,
248 const string &storage_group,
249 const Stringmap *apn_info,
250 const string &keytag,
251 const string &apntag) {
252 const string key = keytag + "." + apntag;
253 string str;
254 if (apn_info && GetNonEmptyField(*apn_info, apntag, &str))
255 storage->SetString(storage_group, key, str);
256 else
257 storage->DeleteKey(storage_group, key);
258}
259
Darin Petkov4d6d9412011-08-24 13:19:54 -0700260void CellularService::Connect(Error *error) {
mukesh agrawaladb68482012-01-17 16:31:51 -0800261 Service::Connect(error);
Darin Petkov4d6d9412011-08-24 13:19:54 -0700262 cellular_->Connect(error);
Darin Petkovc5f56562011-08-06 16:40:05 -0700263}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700264
Darin Petkovfb0625e2012-01-16 13:05:56 +0100265void CellularService::Disconnect(Error *error) {
266 Service::Disconnect(error);
267 cellular_->Disconnect(error);
268}
269
Darin Petkovb100ae72011-08-24 16:19:45 -0700270void CellularService::ActivateCellularModem(const string &carrier,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500271 Error *error,
272 const ResultCallback &callback) {
273 cellular_->Activate(carrier, error, callback);
Darin Petkovc408e692011-08-17 13:47:15 -0700274}
275
Darin Petkov31332412012-01-28 01:50:02 +0100276void CellularService::SetStorageIdentifier(const string &identifier) {
277 storage_identifier_ = identifier;
278 std::replace_if(storage_identifier_.begin(),
279 storage_identifier_.end(),
280 &Service::IllegalChar, '_');
281}
282
Chris Masone6515aab2011-10-12 16:19:09 -0700283string CellularService::GetStorageIdentifier() const {
Darin Petkov31332412012-01-28 01:50:02 +0100284 return storage_identifier_;
Chris Masone34af2182011-08-22 11:59:36 -0700285}
286
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800287string CellularService::GetDeviceRpcId(Error */*error*/) {
Chris Masone95207da2011-06-29 16:50:49 -0700288 return cellular_->GetRpcIdentifier();
289}
290
Darin Petkovb9c99332012-01-12 13:13:00 +0100291void CellularService::SetActivationState(const string &state) {
292 if (state == activation_state_) {
293 return;
294 }
295 activation_state_ = state;
296 adaptor()->EmitStringChanged(flimflam::kActivationStateProperty, state);
297}
298
Darin Petkov381928f2012-02-02 23:00:12 +0100299void CellularService::SetOLP(const OLP &olp) {
300 if (olp_.Equals(olp)) {
301 return;
302 }
303 olp_.CopyFrom(olp);
304 adaptor()->EmitStringmapChanged(flimflam::kPaymentPortalProperty,
305 olp.ToDict());
306}
307
308void CellularService::SetUsageURL(const std::string &url) {
309 if (url == usage_url_) {
310 return;
311 }
312 usage_url_ = url;
313 adaptor()->EmitStringChanged(flimflam::kUsageURLProperty, url);
314}
315
Darin Petkovb72cf402011-11-22 14:51:39 +0100316void CellularService::SetNetworkTechnology(const string &technology) {
317 if (technology == network_technology_) {
318 return;
319 }
320 network_technology_ = technology;
321 adaptor()->EmitStringChanged(flimflam::kNetworkTechnologyProperty,
322 technology);
323}
324
325void CellularService::SetRoamingState(const string &state) {
326 if (state == roaming_state_) {
327 return;
328 }
329 roaming_state_ = state;
330 adaptor()->EmitStringChanged(flimflam::kRoamingStateProperty, state);
331}
332
Darin Petkov3335b372011-08-22 11:05:32 -0700333const Cellular::Operator &CellularService::serving_operator() const {
334 return serving_operator_;
335}
336
Darin Petkov9cb02682012-01-28 00:17:38 +0100337void CellularService::SetServingOperator(const Cellular::Operator &oper) {
338 if (serving_operator_.Equals(oper)) {
339 return;
340 }
Darin Petkov3335b372011-08-22 11:05:32 -0700341 serving_operator_.CopyFrom(oper);
Darin Petkov9cb02682012-01-28 00:17:38 +0100342 adaptor()->EmitStringmapChanged(flimflam::kServingOperatorProperty,
343 oper.ToDict());
Darin Petkov3335b372011-08-22 11:05:32 -0700344}
345
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700346} // namespace shill