blob: f5712ac34b0651c9d7df56b2fb2615cecae403ec [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
9#include <base/logging.h>
Chris Masone34af2182011-08-22 11:59:36 -070010#include <base/stringprintf.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070011#include <chromeos/dbus/service_constants.h>
12
Darin Petkovb72cf402011-11-22 14:51:39 +010013#include "shill/adaptor_interfaces.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070014#include "shill/cellular.h"
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040015#include "shill/property_accessor.h"
16#include "shill/store_interface.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070017
18using std::string;
19
20namespace shill {
Darin Petkovc5f56562011-08-06 16:40:05 -070021
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040022const char CellularService::kStorageAPN[] = "Cellular.APN";
23const char CellularService::kStorageLastGoodAPN[] = "Cellular.LastGoodAPN";
24
Darin Petkov381928f2012-02-02 23:00:12 +010025// TODO(petkov): Add these to system_api/dbus/service_constants.h
26namespace {
27const char kKeyOLPURL[] = "url";
28const char kKeyOLPMethod[] = "method";
29const char kKeyOLPPostData[] = "postdata";
30} // namespace {}
31
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040032static bool GetNonEmptyField(const Stringmap &stringmap,
33 const string &fieldname,
34 string *value) {
35 Stringmap::const_iterator it = stringmap.find(fieldname);
36 if (it != stringmap.end() && !it->second.empty()) {
37 *value = it->second;
38 return true;
39 }
40 return false;
41}
42
Darin Petkov381928f2012-02-02 23:00:12 +010043CellularService::OLP::OLP() {
44 SetURL("");
45 SetMethod("");
46 SetPostData("");
47}
48
49CellularService::OLP::~OLP() {}
50
51void CellularService::OLP::CopyFrom(const OLP &olp) {
52 dict_ = olp.dict_;
53}
54
55bool CellularService::OLP::Equals(const OLP &olp) const {
56 return dict_ == olp.dict_;
57}
58
59const string &CellularService::OLP::GetURL() const {
60 return dict_.find(kKeyOLPURL)->second;
61}
62
63void CellularService::OLP::SetURL(const string &url) {
64 dict_[kKeyOLPURL] = url;
65}
66
67const string &CellularService::OLP::GetMethod() const {
68 return dict_.find(kKeyOLPMethod)->second;
69}
70
71void CellularService::OLP::SetMethod(const string &method) {
72 dict_[kKeyOLPMethod] = method;
73}
74
75const string &CellularService::OLP::GetPostData() const {
76 return dict_.find(kKeyOLPPostData)->second;
77}
78
79void CellularService::OLP::SetPostData(const string &post_data) {
80 dict_[kKeyOLPPostData] = post_data;
81}
82
83const Stringmap &CellularService::OLP::ToDict() const {
84 return dict_;
85}
86
Chris Masone3bd3c8c2011-06-13 08:20:26 -070087CellularService::CellularService(ControlInterface *control_interface,
88 EventDispatcher *dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -080089 Metrics *metrics,
Chris Masone6791a432011-07-12 13:23:19 -070090 Manager *manager,
mukesh agrawal51a7e932011-07-27 16:18:26 -070091 const CellularRefPtr &device)
Thieu Le3426c8f2012-01-11 17:35:11 -080092 : Service(control_interface, dispatcher, metrics, manager,
93 Technology::kCellular),
mukesh agrawal7a4e4002011-09-06 11:26:05 -070094 cellular_(device) {
Thieu Le9fdf1372012-05-14 15:20:48 -070095 set_connectable(true);
mukesh agrawalde29fa82011-09-16 16:16:36 -070096 PropertyStore *store = this->mutable_store();
Paul Stewartac4ac002011-08-26 12:04:26 -070097 store->RegisterConstString(flimflam::kActivationStateProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -070098 &activation_state_);
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -040099 HelpRegisterDerivedStringmap(flimflam::kCellularApnProperty,
100 &CellularService::GetApn,
101 &CellularService::SetApn);
Paul Stewartac4ac002011-08-26 12:04:26 -0700102 store->RegisterConstStringmap(flimflam::kCellularLastGoodApnProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700103 &last_good_apn_info_);
Paul Stewartac4ac002011-08-26 12:04:26 -0700104 store->RegisterConstString(flimflam::kNetworkTechnologyProperty,
Darin Petkovb72cf402011-11-22 14:51:39 +0100105 &network_technology_);
Darin Petkov381928f2012-02-02 23:00:12 +0100106 store->RegisterConstStringmap(flimflam::kPaymentPortalProperty,
107 &olp_.ToDict());
Paul Stewartac4ac002011-08-26 12:04:26 -0700108 store->RegisterConstString(flimflam::kRoamingStateProperty, &roaming_state_);
109 store->RegisterConstStringmap(flimflam::kServingOperatorProperty,
Darin Petkov3335b372011-08-22 11:05:32 -0700110 &serving_operator_.ToDict());
Paul Stewartac4ac002011-08-26 12:04:26 -0700111 store->RegisterConstString(flimflam::kUsageURLProperty, &usage_url_);
Darin Petkovac635a82012-01-10 16:51:58 +0100112
113 set_friendly_name(device->CreateFriendlyServiceName());
Darin Petkovdd3e8662012-02-03 13:16:20 +0100114 SetStorageIdentifier(string(flimflam::kTypeCellular) + "_" +
115 device->address() + "_" + friendly_name());
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700116}
117
118CellularService::~CellularService() { }
119
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400120void CellularService::HelpRegisterDerivedStringmap(
121 const string &name,
122 Stringmap(CellularService::*get)(Error *error),
123 void(CellularService::*set)(
124 const Stringmap &value, Error *error)) {
125 mutable_store()->RegisterDerivedStringmap(
126 name,
127 StringmapAccessor(
128 new CustomAccessor<CellularService, Stringmap>(this, get, set)));
129}
130
131Stringmap *CellularService::GetUserSpecifiedApn() {
132 Stringmap::iterator it = apn_info_.find(flimflam::kApnProperty);
133 if (it == apn_info_.end() || it->second.empty())
134 return NULL;
135 return &apn_info_;
136}
137
138Stringmap *CellularService::GetLastGoodApn() {
139 Stringmap::iterator it =
140 last_good_apn_info_.find(flimflam::kApnProperty);
141 if (it == last_good_apn_info_.end() || it->second.empty())
142 return NULL;
143 return &last_good_apn_info_;
144}
145
146Stringmap CellularService::GetApn(Error */*error*/) {
147 return apn_info_;
148}
149
150void CellularService::SetApn(const Stringmap &value, Error *error) {
151 // Only copy in the fields we care about, and validate the contents.
Eric Shienbroodc7073302012-04-03 14:41:44 -0400152 // If the "apn" field is missing or empty, the APN is cleared.
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400153 string str;
154 if (!GetNonEmptyField(value, flimflam::kApnProperty, &str)) {
Eric Shienbroodc7073302012-04-03 14:41:44 -0400155 apn_info_.clear();
156 } else {
157 apn_info_[flimflam::kApnProperty] = str;
158 if (GetNonEmptyField(value, flimflam::kApnUsernameProperty, &str))
159 apn_info_[flimflam::kApnUsernameProperty] = str;
160 if (GetNonEmptyField(value, flimflam::kApnPasswordProperty, &str))
161 apn_info_[flimflam::kApnPasswordProperty] = str;
162 // Clear the last good APN, otherwise the one the user just
163 // set won't be used, since LastGoodApn comes first in the
164 // search order when trying to connect. Only do this if a
165 // non-empty user APN has been supplied. If the user APN is
166 // being cleared, leave LastGoodApn alone.
167 ClearLastGoodApn();
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400168 }
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400169 adaptor()->EmitStringmapChanged(flimflam::kCellularApnProperty, apn_info_);
170 SaveToCurrentProfile();
171}
172
173void CellularService::SetLastGoodApn(const Stringmap &apn_info) {
174 last_good_apn_info_ = apn_info;
175 adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
176 last_good_apn_info_);
177 SaveToCurrentProfile();
178}
179
180void CellularService::ClearLastGoodApn() {
181 last_good_apn_info_.clear();
182 adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
183 last_good_apn_info_);
184 SaveToCurrentProfile();
185}
186
187bool CellularService::Load(StoreInterface *storage) {
188 // Load properties common to all Services.
189 if (!Service::Load(storage))
190 return false;
191
192 const string id = GetStorageIdentifier();
193 LoadApn(storage, id, kStorageAPN, &apn_info_);
194 LoadApn(storage, id, kStorageLastGoodAPN, &last_good_apn_info_);
195 return true;
196}
197
198void CellularService::LoadApn(StoreInterface *storage,
199 const string &storage_group,
200 const string &keytag,
201 Stringmap *apn_info) {
202 if (!LoadApnField(storage, storage_group, keytag,
203 flimflam::kApnProperty, apn_info))
204 return;
205 LoadApnField(storage, storage_group, keytag,
206 flimflam::kApnUsernameProperty, apn_info);
207 LoadApnField(storage, storage_group, keytag,
208 flimflam::kApnPasswordProperty, apn_info);
209}
210
211bool CellularService::LoadApnField(StoreInterface *storage,
212 const string &storage_group,
213 const string &keytag,
214 const string &apntag,
215 Stringmap *apn_info) {
216 string value;
217 if (storage->GetString(storage_group, keytag + "." + apntag, &value) &&
218 !value.empty()) {
219 (*apn_info)[apntag] = value;
220 return true;
221 }
222 return false;
223}
224
225bool CellularService::Save(StoreInterface *storage) {
226 // Save properties common to all Services.
227 if (!Service::Save(storage))
228 return false;
229
230 const string id = GetStorageIdentifier();
231 SaveApn(storage, id, GetUserSpecifiedApn(), kStorageAPN);
232 SaveApn(storage, id, GetLastGoodApn(), kStorageLastGoodAPN);
233 return true;
234}
235
236void CellularService::SaveApn(StoreInterface *storage,
237 const string &storage_group,
238 const Stringmap *apn_info,
239 const string &keytag) {
240 SaveApnField(storage, storage_group, apn_info, keytag,
241 flimflam::kApnProperty);
242 SaveApnField(storage, storage_group, apn_info, keytag,
243 flimflam::kApnUsernameProperty);
244 SaveApnField(storage, storage_group, apn_info, keytag,
245 flimflam::kApnPasswordProperty);
246}
247
248void CellularService::SaveApnField(StoreInterface *storage,
249 const string &storage_group,
250 const Stringmap *apn_info,
251 const string &keytag,
252 const string &apntag) {
253 const string key = keytag + "." + apntag;
254 string str;
255 if (apn_info && GetNonEmptyField(*apn_info, apntag, &str))
256 storage->SetString(storage_group, key, str);
257 else
258 storage->DeleteKey(storage_group, key);
259}
260
Darin Petkov4d6d9412011-08-24 13:19:54 -0700261void CellularService::Connect(Error *error) {
mukesh agrawaladb68482012-01-17 16:31:51 -0800262 Service::Connect(error);
Darin Petkov4d6d9412011-08-24 13:19:54 -0700263 cellular_->Connect(error);
Darin Petkovc5f56562011-08-06 16:40:05 -0700264}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700265
Darin Petkovfb0625e2012-01-16 13:05:56 +0100266void CellularService::Disconnect(Error *error) {
267 Service::Disconnect(error);
268 cellular_->Disconnect(error);
269}
270
Darin Petkovb100ae72011-08-24 16:19:45 -0700271void CellularService::ActivateCellularModem(const string &carrier,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500272 Error *error,
273 const ResultCallback &callback) {
274 cellular_->Activate(carrier, error, callback);
Darin Petkovc408e692011-08-17 13:47:15 -0700275}
276
Paul Stewart22aa71b2011-09-16 12:15:11 -0700277bool CellularService::TechnologyIs(const Technology::Identifier type) const {
278 return cellular_->TechnologyIs(type);
279}
280
Darin Petkov31332412012-01-28 01:50:02 +0100281void CellularService::SetStorageIdentifier(const string &identifier) {
282 storage_identifier_ = identifier;
283 std::replace_if(storage_identifier_.begin(),
284 storage_identifier_.end(),
285 &Service::IllegalChar, '_');
286}
287
Chris Masone6515aab2011-10-12 16:19:09 -0700288string CellularService::GetStorageIdentifier() const {
Darin Petkov31332412012-01-28 01:50:02 +0100289 return storage_identifier_;
Chris Masone34af2182011-08-22 11:59:36 -0700290}
291
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800292string CellularService::GetDeviceRpcId(Error */*error*/) {
Chris Masone95207da2011-06-29 16:50:49 -0700293 return cellular_->GetRpcIdentifier();
294}
295
Darin Petkovb9c99332012-01-12 13:13:00 +0100296void CellularService::SetActivationState(const string &state) {
297 if (state == activation_state_) {
298 return;
299 }
300 activation_state_ = state;
301 adaptor()->EmitStringChanged(flimflam::kActivationStateProperty, state);
302}
303
Darin Petkov381928f2012-02-02 23:00:12 +0100304void CellularService::SetOLP(const OLP &olp) {
305 if (olp_.Equals(olp)) {
306 return;
307 }
308 olp_.CopyFrom(olp);
309 adaptor()->EmitStringmapChanged(flimflam::kPaymentPortalProperty,
310 olp.ToDict());
311}
312
313void CellularService::SetUsageURL(const std::string &url) {
314 if (url == usage_url_) {
315 return;
316 }
317 usage_url_ = url;
318 adaptor()->EmitStringChanged(flimflam::kUsageURLProperty, url);
319}
320
Darin Petkovb72cf402011-11-22 14:51:39 +0100321void CellularService::SetNetworkTechnology(const string &technology) {
322 if (technology == network_technology_) {
323 return;
324 }
325 network_technology_ = technology;
326 adaptor()->EmitStringChanged(flimflam::kNetworkTechnologyProperty,
327 technology);
328}
329
330void CellularService::SetRoamingState(const string &state) {
331 if (state == roaming_state_) {
332 return;
333 }
334 roaming_state_ = state;
335 adaptor()->EmitStringChanged(flimflam::kRoamingStateProperty, state);
336}
337
Darin Petkov3335b372011-08-22 11:05:32 -0700338const Cellular::Operator &CellularService::serving_operator() const {
339 return serving_operator_;
340}
341
Darin Petkov9cb02682012-01-28 00:17:38 +0100342void CellularService::SetServingOperator(const Cellular::Operator &oper) {
343 if (serving_operator_.Equals(oper)) {
344 return;
345 }
Darin Petkov3335b372011-08-22 11:05:32 -0700346 serving_operator_.CopyFrom(oper);
Darin Petkov9cb02682012-01-28 00:17:38 +0100347 adaptor()->EmitStringmapChanged(flimflam::kServingOperatorProperty,
348 oper.ToDict());
Darin Petkov3335b372011-08-22 11:05:32 -0700349}
350
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700351} // namespace shill