blob: 8912f9a92bfed7236e3a938a28b10e5aa882c3de [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
Christopher Wiley1582bdd2012-11-15 11:31:14 -080021const char CellularService::kAutoConnActivating[] = "activating";
Ben Chan19f83972012-10-03 23:25:56 -070022const char CellularService::kAutoConnDeviceDisabled[] = "device disabled";
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040023const char CellularService::kStorageAPN[] = "Cellular.APN";
24const char CellularService::kStorageLastGoodAPN[] = "Cellular.LastGoodAPN";
25
Darin Petkov381928f2012-02-02 23:00:12 +010026// TODO(petkov): Add these to system_api/dbus/service_constants.h
27namespace {
28const char kKeyOLPURL[] = "url";
29const char kKeyOLPMethod[] = "method";
30const char kKeyOLPPostData[] = "postdata";
Ben Chan19f83972012-10-03 23:25:56 -070031} // namespace
Darin Petkov381928f2012-02-02 23:00:12 +010032
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040033static bool GetNonEmptyField(const Stringmap &stringmap,
34 const string &fieldname,
35 string *value) {
36 Stringmap::const_iterator it = stringmap.find(fieldname);
37 if (it != stringmap.end() && !it->second.empty()) {
38 *value = it->second;
39 return true;
40 }
41 return false;
42}
43
Darin Petkov381928f2012-02-02 23:00:12 +010044CellularService::OLP::OLP() {
45 SetURL("");
46 SetMethod("");
47 SetPostData("");
48}
49
50CellularService::OLP::~OLP() {}
51
52void CellularService::OLP::CopyFrom(const OLP &olp) {
53 dict_ = olp.dict_;
54}
55
56bool CellularService::OLP::Equals(const OLP &olp) const {
57 return dict_ == olp.dict_;
58}
59
60const string &CellularService::OLP::GetURL() const {
61 return dict_.find(kKeyOLPURL)->second;
62}
63
64void CellularService::OLP::SetURL(const string &url) {
65 dict_[kKeyOLPURL] = url;
66}
67
68const string &CellularService::OLP::GetMethod() const {
69 return dict_.find(kKeyOLPMethod)->second;
70}
71
72void CellularService::OLP::SetMethod(const string &method) {
73 dict_[kKeyOLPMethod] = method;
74}
75
76const string &CellularService::OLP::GetPostData() const {
77 return dict_.find(kKeyOLPPostData)->second;
78}
79
80void CellularService::OLP::SetPostData(const string &post_data) {
81 dict_[kKeyOLPPostData] = post_data;
82}
83
84const Stringmap &CellularService::OLP::ToDict() const {
85 return dict_;
86}
87
Chris Masone3bd3c8c2011-06-13 08:20:26 -070088CellularService::CellularService(ControlInterface *control_interface,
89 EventDispatcher *dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -080090 Metrics *metrics,
Chris Masone6791a432011-07-12 13:23:19 -070091 Manager *manager,
mukesh agrawal51a7e932011-07-27 16:18:26 -070092 const CellularRefPtr &device)
Thieu Le3426c8f2012-01-11 17:35:11 -080093 : Service(control_interface, dispatcher, metrics, manager,
94 Technology::kCellular),
mukesh agrawal7a4e4002011-09-06 11:26:05 -070095 cellular_(device) {
Thieu Le9fdf1372012-05-14 15:20:48 -070096 set_connectable(true);
mukesh agrawalde29fa82011-09-16 16:16:36 -070097 PropertyStore *store = this->mutable_store();
Paul Stewartac4ac002011-08-26 12:04:26 -070098 store->RegisterConstString(flimflam::kActivationStateProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -070099 &activation_state_);
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400100 HelpRegisterDerivedStringmap(flimflam::kCellularApnProperty,
101 &CellularService::GetApn,
102 &CellularService::SetApn);
Paul Stewartac4ac002011-08-26 12:04:26 -0700103 store->RegisterConstStringmap(flimflam::kCellularLastGoodApnProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700104 &last_good_apn_info_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700105 store->RegisterConstString(flimflam::kNetworkTechnologyProperty,
Darin Petkovb72cf402011-11-22 14:51:39 +0100106 &network_technology_);
Darin Petkov381928f2012-02-02 23:00:12 +0100107 store->RegisterConstStringmap(flimflam::kPaymentPortalProperty,
108 &olp_.ToDict());
Paul Stewartac4ac002011-08-26 12:04:26 -0700109 store->RegisterConstString(flimflam::kRoamingStateProperty, &roaming_state_);
110 store->RegisterConstStringmap(flimflam::kServingOperatorProperty,
Darin Petkov3335b372011-08-22 11:05:32 -0700111 &serving_operator_.ToDict());
Paul Stewartac4ac002011-08-26 12:04:26 -0700112 store->RegisterConstString(flimflam::kUsageURLProperty, &usage_url_);
Darin Petkovac635a82012-01-10 16:51:58 +0100113
114 set_friendly_name(device->CreateFriendlyServiceName());
Darin Petkovdd3e8662012-02-03 13:16:20 +0100115 SetStorageIdentifier(string(flimflam::kTypeCellular) + "_" +
116 device->address() + "_" + friendly_name());
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700117}
118
119CellularService::~CellularService() { }
120
Ben Chan19f83972012-10-03 23:25:56 -0700121bool CellularService::IsAutoConnectable(const char **reason) const {
122 if (!cellular_->running()) {
123 *reason = kAutoConnDeviceDisabled;
124 return false;
125 }
Christopher Wiley1582bdd2012-11-15 11:31:14 -0800126 if (cellular_->IsActivating()) {
127 *reason = kAutoConnActivating;
128 return false;
129 }
Ben Chan19f83972012-10-03 23:25:56 -0700130 return Service::IsAutoConnectable(reason);
131}
132
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400133void CellularService::HelpRegisterDerivedStringmap(
134 const string &name,
135 Stringmap(CellularService::*get)(Error *error),
136 void(CellularService::*set)(
137 const Stringmap &value, Error *error)) {
138 mutable_store()->RegisterDerivedStringmap(
139 name,
140 StringmapAccessor(
141 new CustomAccessor<CellularService, Stringmap>(this, get, set)));
142}
143
144Stringmap *CellularService::GetUserSpecifiedApn() {
145 Stringmap::iterator it = apn_info_.find(flimflam::kApnProperty);
146 if (it == apn_info_.end() || it->second.empty())
147 return NULL;
148 return &apn_info_;
149}
150
151Stringmap *CellularService::GetLastGoodApn() {
152 Stringmap::iterator it =
153 last_good_apn_info_.find(flimflam::kApnProperty);
154 if (it == last_good_apn_info_.end() || it->second.empty())
155 return NULL;
156 return &last_good_apn_info_;
157}
158
159Stringmap CellularService::GetApn(Error */*error*/) {
160 return apn_info_;
161}
162
163void CellularService::SetApn(const Stringmap &value, Error *error) {
164 // Only copy in the fields we care about, and validate the contents.
Eric Shienbroodc7073302012-04-03 14:41:44 -0400165 // If the "apn" field is missing or empty, the APN is cleared.
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400166 string str;
167 if (!GetNonEmptyField(value, flimflam::kApnProperty, &str)) {
Eric Shienbroodc7073302012-04-03 14:41:44 -0400168 apn_info_.clear();
169 } else {
170 apn_info_[flimflam::kApnProperty] = str;
171 if (GetNonEmptyField(value, flimflam::kApnUsernameProperty, &str))
172 apn_info_[flimflam::kApnUsernameProperty] = str;
173 if (GetNonEmptyField(value, flimflam::kApnPasswordProperty, &str))
174 apn_info_[flimflam::kApnPasswordProperty] = str;
175 // Clear the last good APN, otherwise the one the user just
176 // set won't be used, since LastGoodApn comes first in the
177 // search order when trying to connect. Only do this if a
178 // non-empty user APN has been supplied. If the user APN is
179 // being cleared, leave LastGoodApn alone.
180 ClearLastGoodApn();
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400181 }
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400182 adaptor()->EmitStringmapChanged(flimflam::kCellularApnProperty, apn_info_);
183 SaveToCurrentProfile();
184}
185
186void CellularService::SetLastGoodApn(const Stringmap &apn_info) {
187 last_good_apn_info_ = apn_info;
188 adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
189 last_good_apn_info_);
190 SaveToCurrentProfile();
191}
192
193void CellularService::ClearLastGoodApn() {
194 last_good_apn_info_.clear();
195 adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
196 last_good_apn_info_);
197 SaveToCurrentProfile();
198}
199
200bool CellularService::Load(StoreInterface *storage) {
201 // Load properties common to all Services.
202 if (!Service::Load(storage))
203 return false;
204
205 const string id = GetStorageIdentifier();
206 LoadApn(storage, id, kStorageAPN, &apn_info_);
207 LoadApn(storage, id, kStorageLastGoodAPN, &last_good_apn_info_);
208 return true;
209}
210
211void CellularService::LoadApn(StoreInterface *storage,
212 const string &storage_group,
213 const string &keytag,
214 Stringmap *apn_info) {
215 if (!LoadApnField(storage, storage_group, keytag,
216 flimflam::kApnProperty, apn_info))
217 return;
218 LoadApnField(storage, storage_group, keytag,
219 flimflam::kApnUsernameProperty, apn_info);
220 LoadApnField(storage, storage_group, keytag,
221 flimflam::kApnPasswordProperty, apn_info);
222}
223
224bool CellularService::LoadApnField(StoreInterface *storage,
225 const string &storage_group,
226 const string &keytag,
227 const string &apntag,
228 Stringmap *apn_info) {
229 string value;
230 if (storage->GetString(storage_group, keytag + "." + apntag, &value) &&
231 !value.empty()) {
232 (*apn_info)[apntag] = value;
233 return true;
234 }
235 return false;
236}
237
238bool CellularService::Save(StoreInterface *storage) {
239 // Save properties common to all Services.
240 if (!Service::Save(storage))
241 return false;
242
243 const string id = GetStorageIdentifier();
244 SaveApn(storage, id, GetUserSpecifiedApn(), kStorageAPN);
245 SaveApn(storage, id, GetLastGoodApn(), kStorageLastGoodAPN);
246 return true;
247}
248
249void CellularService::SaveApn(StoreInterface *storage,
250 const string &storage_group,
251 const Stringmap *apn_info,
252 const string &keytag) {
253 SaveApnField(storage, storage_group, apn_info, keytag,
254 flimflam::kApnProperty);
255 SaveApnField(storage, storage_group, apn_info, keytag,
256 flimflam::kApnUsernameProperty);
257 SaveApnField(storage, storage_group, apn_info, keytag,
258 flimflam::kApnPasswordProperty);
259}
260
261void CellularService::SaveApnField(StoreInterface *storage,
262 const string &storage_group,
263 const Stringmap *apn_info,
264 const string &keytag,
265 const string &apntag) {
266 const string key = keytag + "." + apntag;
267 string str;
268 if (apn_info && GetNonEmptyField(*apn_info, apntag, &str))
269 storage->SetString(storage_group, key, str);
270 else
271 storage->DeleteKey(storage_group, key);
272}
273
Darin Petkov4d6d9412011-08-24 13:19:54 -0700274void CellularService::Connect(Error *error) {
mukesh agrawaladb68482012-01-17 16:31:51 -0800275 Service::Connect(error);
Darin Petkov4d6d9412011-08-24 13:19:54 -0700276 cellular_->Connect(error);
Darin Petkovc5f56562011-08-06 16:40:05 -0700277}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700278
Darin Petkovfb0625e2012-01-16 13:05:56 +0100279void CellularService::Disconnect(Error *error) {
280 Service::Disconnect(error);
281 cellular_->Disconnect(error);
282}
283
Darin Petkovb100ae72011-08-24 16:19:45 -0700284void CellularService::ActivateCellularModem(const string &carrier,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500285 Error *error,
286 const ResultCallback &callback) {
287 cellular_->Activate(carrier, error, callback);
Darin Petkovc408e692011-08-17 13:47:15 -0700288}
289
Darin Petkov31332412012-01-28 01:50:02 +0100290void CellularService::SetStorageIdentifier(const string &identifier) {
291 storage_identifier_ = identifier;
292 std::replace_if(storage_identifier_.begin(),
293 storage_identifier_.end(),
294 &Service::IllegalChar, '_');
295}
296
Chris Masone6515aab2011-10-12 16:19:09 -0700297string CellularService::GetStorageIdentifier() const {
Darin Petkov31332412012-01-28 01:50:02 +0100298 return storage_identifier_;
Chris Masone34af2182011-08-22 11:59:36 -0700299}
300
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800301string CellularService::GetDeviceRpcId(Error */*error*/) {
Chris Masone95207da2011-06-29 16:50:49 -0700302 return cellular_->GetRpcIdentifier();
303}
304
Darin Petkovb9c99332012-01-12 13:13:00 +0100305void CellularService::SetActivationState(const string &state) {
306 if (state == activation_state_) {
307 return;
308 }
309 activation_state_ = state;
310 adaptor()->EmitStringChanged(flimflam::kActivationStateProperty, state);
Ben Chan96580442012-09-19 16:19:39 -0700311 SetConnectable(state != flimflam::kActivationStateNotActivated);
Darin Petkovb9c99332012-01-12 13:13:00 +0100312}
313
Darin Petkov381928f2012-02-02 23:00:12 +0100314void CellularService::SetOLP(const OLP &olp) {
315 if (olp_.Equals(olp)) {
316 return;
317 }
318 olp_.CopyFrom(olp);
319 adaptor()->EmitStringmapChanged(flimflam::kPaymentPortalProperty,
320 olp.ToDict());
321}
322
323void CellularService::SetUsageURL(const std::string &url) {
324 if (url == usage_url_) {
325 return;
326 }
327 usage_url_ = url;
328 adaptor()->EmitStringChanged(flimflam::kUsageURLProperty, url);
329}
330
Darin Petkovb72cf402011-11-22 14:51:39 +0100331void CellularService::SetNetworkTechnology(const string &technology) {
332 if (technology == network_technology_) {
333 return;
334 }
335 network_technology_ = technology;
336 adaptor()->EmitStringChanged(flimflam::kNetworkTechnologyProperty,
337 technology);
338}
339
340void CellularService::SetRoamingState(const string &state) {
341 if (state == roaming_state_) {
342 return;
343 }
344 roaming_state_ = state;
345 adaptor()->EmitStringChanged(flimflam::kRoamingStateProperty, state);
346}
347
Darin Petkov3335b372011-08-22 11:05:32 -0700348const Cellular::Operator &CellularService::serving_operator() const {
349 return serving_operator_;
350}
351
Darin Petkov9cb02682012-01-28 00:17:38 +0100352void CellularService::SetServingOperator(const Cellular::Operator &oper) {
353 if (serving_operator_.Equals(oper)) {
354 return;
355 }
Darin Petkov3335b372011-08-22 11:05:32 -0700356 serving_operator_.CopyFrom(oper);
Darin Petkov9cb02682012-01-28 00:17:38 +0100357 adaptor()->EmitStringmapChanged(flimflam::kServingOperatorProperty,
358 oper.ToDict());
Darin Petkov3335b372011-08-22 11:05:32 -0700359}
360
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700361} // namespace shill