blob: 74017bc2534bb1cfc82e2d29e833c6e906e8d37b [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) {
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.
151 // The "apn" field is mandatory.
152 string str;
153 if (!GetNonEmptyField(value, flimflam::kApnProperty, &str)) {
154 error->Populate(Error::kInvalidArguments,
155 "supplied APN info is missing the apn");
156 return;
157 }
158 apn_info_[flimflam::kApnProperty] = str;
159 if (GetNonEmptyField(value, flimflam::kApnUsernameProperty, &str))
160 apn_info_[flimflam::kApnUsernameProperty] = str;
161 if (GetNonEmptyField(value, flimflam::kApnPasswordProperty, &str))
162 apn_info_[flimflam::kApnPasswordProperty] = str;
163
164 ClearLastGoodApn();
165 adaptor()->EmitStringmapChanged(flimflam::kCellularApnProperty, apn_info_);
166 SaveToCurrentProfile();
167}
168
169void CellularService::SetLastGoodApn(const Stringmap &apn_info) {
170 last_good_apn_info_ = apn_info;
171 adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
172 last_good_apn_info_);
173 SaveToCurrentProfile();
174}
175
176void CellularService::ClearLastGoodApn() {
177 last_good_apn_info_.clear();
178 adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
179 last_good_apn_info_);
180 SaveToCurrentProfile();
181}
182
183bool CellularService::Load(StoreInterface *storage) {
184 // Load properties common to all Services.
185 if (!Service::Load(storage))
186 return false;
187
188 const string id = GetStorageIdentifier();
189 LoadApn(storage, id, kStorageAPN, &apn_info_);
190 LoadApn(storage, id, kStorageLastGoodAPN, &last_good_apn_info_);
191 return true;
192}
193
194void CellularService::LoadApn(StoreInterface *storage,
195 const string &storage_group,
196 const string &keytag,
197 Stringmap *apn_info) {
198 if (!LoadApnField(storage, storage_group, keytag,
199 flimflam::kApnProperty, apn_info))
200 return;
201 LoadApnField(storage, storage_group, keytag,
202 flimflam::kApnUsernameProperty, apn_info);
203 LoadApnField(storage, storage_group, keytag,
204 flimflam::kApnPasswordProperty, apn_info);
205}
206
207bool CellularService::LoadApnField(StoreInterface *storage,
208 const string &storage_group,
209 const string &keytag,
210 const string &apntag,
211 Stringmap *apn_info) {
212 string value;
213 if (storage->GetString(storage_group, keytag + "." + apntag, &value) &&
214 !value.empty()) {
215 (*apn_info)[apntag] = value;
216 return true;
217 }
218 return false;
219}
220
221bool CellularService::Save(StoreInterface *storage) {
222 // Save properties common to all Services.
223 if (!Service::Save(storage))
224 return false;
225
226 const string id = GetStorageIdentifier();
227 SaveApn(storage, id, GetUserSpecifiedApn(), kStorageAPN);
228 SaveApn(storage, id, GetLastGoodApn(), kStorageLastGoodAPN);
229 return true;
230}
231
232void CellularService::SaveApn(StoreInterface *storage,
233 const string &storage_group,
234 const Stringmap *apn_info,
235 const string &keytag) {
236 SaveApnField(storage, storage_group, apn_info, keytag,
237 flimflam::kApnProperty);
238 SaveApnField(storage, storage_group, apn_info, keytag,
239 flimflam::kApnUsernameProperty);
240 SaveApnField(storage, storage_group, apn_info, keytag,
241 flimflam::kApnPasswordProperty);
242}
243
244void CellularService::SaveApnField(StoreInterface *storage,
245 const string &storage_group,
246 const Stringmap *apn_info,
247 const string &keytag,
248 const string &apntag) {
249 const string key = keytag + "." + apntag;
250 string str;
251 if (apn_info && GetNonEmptyField(*apn_info, apntag, &str))
252 storage->SetString(storage_group, key, str);
253 else
254 storage->DeleteKey(storage_group, key);
255}
256
Darin Petkov4d6d9412011-08-24 13:19:54 -0700257void CellularService::Connect(Error *error) {
mukesh agrawaladb68482012-01-17 16:31:51 -0800258 Service::Connect(error);
Darin Petkov4d6d9412011-08-24 13:19:54 -0700259 cellular_->Connect(error);
Darin Petkovc5f56562011-08-06 16:40:05 -0700260}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700261
Darin Petkovfb0625e2012-01-16 13:05:56 +0100262void CellularService::Disconnect(Error *error) {
263 Service::Disconnect(error);
264 cellular_->Disconnect(error);
265}
266
Darin Petkovb100ae72011-08-24 16:19:45 -0700267void CellularService::ActivateCellularModem(const string &carrier,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500268 Error *error,
269 const ResultCallback &callback) {
270 cellular_->Activate(carrier, error, callback);
Darin Petkovc408e692011-08-17 13:47:15 -0700271}
272
Paul Stewart22aa71b2011-09-16 12:15:11 -0700273bool CellularService::TechnologyIs(const Technology::Identifier type) const {
274 return cellular_->TechnologyIs(type);
275}
276
Darin Petkov31332412012-01-28 01:50:02 +0100277void CellularService::SetStorageIdentifier(const string &identifier) {
278 storage_identifier_ = identifier;
279 std::replace_if(storage_identifier_.begin(),
280 storage_identifier_.end(),
281 &Service::IllegalChar, '_');
282}
283
Chris Masone6515aab2011-10-12 16:19:09 -0700284string CellularService::GetStorageIdentifier() const {
Darin Petkov31332412012-01-28 01:50:02 +0100285 return storage_identifier_;
Chris Masone34af2182011-08-22 11:59:36 -0700286}
287
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800288string CellularService::GetDeviceRpcId(Error */*error*/) {
Chris Masone95207da2011-06-29 16:50:49 -0700289 return cellular_->GetRpcIdentifier();
290}
291
Darin Petkovb9c99332012-01-12 13:13:00 +0100292void CellularService::SetActivationState(const string &state) {
293 if (state == activation_state_) {
294 return;
295 }
296 activation_state_ = state;
297 adaptor()->EmitStringChanged(flimflam::kActivationStateProperty, state);
298}
299
Darin Petkov381928f2012-02-02 23:00:12 +0100300void CellularService::SetOLP(const OLP &olp) {
301 if (olp_.Equals(olp)) {
302 return;
303 }
304 olp_.CopyFrom(olp);
305 adaptor()->EmitStringmapChanged(flimflam::kPaymentPortalProperty,
306 olp.ToDict());
307}
308
309void CellularService::SetUsageURL(const std::string &url) {
310 if (url == usage_url_) {
311 return;
312 }
313 usage_url_ = url;
314 adaptor()->EmitStringChanged(flimflam::kUsageURLProperty, url);
315}
316
Darin Petkovb72cf402011-11-22 14:51:39 +0100317void CellularService::SetNetworkTechnology(const string &technology) {
318 if (technology == network_technology_) {
319 return;
320 }
321 network_technology_ = technology;
322 adaptor()->EmitStringChanged(flimflam::kNetworkTechnologyProperty,
323 technology);
324}
325
326void CellularService::SetRoamingState(const string &state) {
327 if (state == roaming_state_) {
328 return;
329 }
330 roaming_state_ = state;
331 adaptor()->EmitStringChanged(flimflam::kRoamingStateProperty, state);
332}
333
Darin Petkov3335b372011-08-22 11:05:32 -0700334const Cellular::Operator &CellularService::serving_operator() const {
335 return serving_operator_;
336}
337
Darin Petkov9cb02682012-01-28 00:17:38 +0100338void CellularService::SetServingOperator(const Cellular::Operator &oper) {
339 if (serving_operator_.Equals(oper)) {
340 return;
341 }
Darin Petkov3335b372011-08-22 11:05:32 -0700342 serving_operator_.CopyFrom(oper);
Darin Petkov9cb02682012-01-28 00:17:38 +0100343 adaptor()->EmitStringmapChanged(flimflam::kServingOperatorProperty,
344 oper.ToDict());
Darin Petkov3335b372011-08-22 11:05:32 -0700345}
346
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700347} // namespace shill