blob: 3a32ed6e4b61a929228e713f26a3eb1bf3056fe0 [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
Ben Chan19f83972012-10-03 23:25:56 -070021const char CellularService::kAutoConnDeviceDisabled[] = "device disabled";
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";
Ben Chan19f83972012-10-03 23:25:56 -070030} // namespace
Darin Petkov381928f2012-02-02 23:00:12 +010031
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
Ben Chan19f83972012-10-03 23:25:56 -0700120bool CellularService::IsAutoConnectable(const char **reason) const {
121 if (!cellular_->running()) {
122 *reason = kAutoConnDeviceDisabled;
123 return false;
124 }
125 return Service::IsAutoConnectable(reason);
126}
127
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400128void CellularService::HelpRegisterDerivedStringmap(
129 const string &name,
130 Stringmap(CellularService::*get)(Error *error),
131 void(CellularService::*set)(
132 const Stringmap &value, Error *error)) {
133 mutable_store()->RegisterDerivedStringmap(
134 name,
135 StringmapAccessor(
136 new CustomAccessor<CellularService, Stringmap>(this, get, set)));
137}
138
139Stringmap *CellularService::GetUserSpecifiedApn() {
140 Stringmap::iterator it = apn_info_.find(flimflam::kApnProperty);
141 if (it == apn_info_.end() || it->second.empty())
142 return NULL;
143 return &apn_info_;
144}
145
146Stringmap *CellularService::GetLastGoodApn() {
147 Stringmap::iterator it =
148 last_good_apn_info_.find(flimflam::kApnProperty);
149 if (it == last_good_apn_info_.end() || it->second.empty())
150 return NULL;
151 return &last_good_apn_info_;
152}
153
154Stringmap CellularService::GetApn(Error */*error*/) {
155 return apn_info_;
156}
157
158void CellularService::SetApn(const Stringmap &value, Error *error) {
159 // Only copy in the fields we care about, and validate the contents.
Eric Shienbroodc7073302012-04-03 14:41:44 -0400160 // If the "apn" field is missing or empty, the APN is cleared.
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400161 string str;
162 if (!GetNonEmptyField(value, flimflam::kApnProperty, &str)) {
Eric Shienbroodc7073302012-04-03 14:41:44 -0400163 apn_info_.clear();
164 } else {
165 apn_info_[flimflam::kApnProperty] = str;
166 if (GetNonEmptyField(value, flimflam::kApnUsernameProperty, &str))
167 apn_info_[flimflam::kApnUsernameProperty] = str;
168 if (GetNonEmptyField(value, flimflam::kApnPasswordProperty, &str))
169 apn_info_[flimflam::kApnPasswordProperty] = str;
170 // Clear the last good APN, otherwise the one the user just
171 // set won't be used, since LastGoodApn comes first in the
172 // search order when trying to connect. Only do this if a
173 // non-empty user APN has been supplied. If the user APN is
174 // being cleared, leave LastGoodApn alone.
175 ClearLastGoodApn();
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400176 }
Eric Shienbrood30bc0ec2012-03-21 18:19:46 -0400177 adaptor()->EmitStringmapChanged(flimflam::kCellularApnProperty, apn_info_);
178 SaveToCurrentProfile();
179}
180
181void CellularService::SetLastGoodApn(const Stringmap &apn_info) {
182 last_good_apn_info_ = apn_info;
183 adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
184 last_good_apn_info_);
185 SaveToCurrentProfile();
186}
187
188void CellularService::ClearLastGoodApn() {
189 last_good_apn_info_.clear();
190 adaptor()->EmitStringmapChanged(flimflam::kCellularLastGoodApnProperty,
191 last_good_apn_info_);
192 SaveToCurrentProfile();
193}
194
195bool CellularService::Load(StoreInterface *storage) {
196 // Load properties common to all Services.
197 if (!Service::Load(storage))
198 return false;
199
200 const string id = GetStorageIdentifier();
201 LoadApn(storage, id, kStorageAPN, &apn_info_);
202 LoadApn(storage, id, kStorageLastGoodAPN, &last_good_apn_info_);
203 return true;
204}
205
206void CellularService::LoadApn(StoreInterface *storage,
207 const string &storage_group,
208 const string &keytag,
209 Stringmap *apn_info) {
210 if (!LoadApnField(storage, storage_group, keytag,
211 flimflam::kApnProperty, apn_info))
212 return;
213 LoadApnField(storage, storage_group, keytag,
214 flimflam::kApnUsernameProperty, apn_info);
215 LoadApnField(storage, storage_group, keytag,
216 flimflam::kApnPasswordProperty, apn_info);
217}
218
219bool CellularService::LoadApnField(StoreInterface *storage,
220 const string &storage_group,
221 const string &keytag,
222 const string &apntag,
223 Stringmap *apn_info) {
224 string value;
225 if (storage->GetString(storage_group, keytag + "." + apntag, &value) &&
226 !value.empty()) {
227 (*apn_info)[apntag] = value;
228 return true;
229 }
230 return false;
231}
232
233bool CellularService::Save(StoreInterface *storage) {
234 // Save properties common to all Services.
235 if (!Service::Save(storage))
236 return false;
237
238 const string id = GetStorageIdentifier();
239 SaveApn(storage, id, GetUserSpecifiedApn(), kStorageAPN);
240 SaveApn(storage, id, GetLastGoodApn(), kStorageLastGoodAPN);
241 return true;
242}
243
244void CellularService::SaveApn(StoreInterface *storage,
245 const string &storage_group,
246 const Stringmap *apn_info,
247 const string &keytag) {
248 SaveApnField(storage, storage_group, apn_info, keytag,
249 flimflam::kApnProperty);
250 SaveApnField(storage, storage_group, apn_info, keytag,
251 flimflam::kApnUsernameProperty);
252 SaveApnField(storage, storage_group, apn_info, keytag,
253 flimflam::kApnPasswordProperty);
254}
255
256void CellularService::SaveApnField(StoreInterface *storage,
257 const string &storage_group,
258 const Stringmap *apn_info,
259 const string &keytag,
260 const string &apntag) {
261 const string key = keytag + "." + apntag;
262 string str;
263 if (apn_info && GetNonEmptyField(*apn_info, apntag, &str))
264 storage->SetString(storage_group, key, str);
265 else
266 storage->DeleteKey(storage_group, key);
267}
268
Darin Petkov4d6d9412011-08-24 13:19:54 -0700269void CellularService::Connect(Error *error) {
mukesh agrawaladb68482012-01-17 16:31:51 -0800270 Service::Connect(error);
Darin Petkov4d6d9412011-08-24 13:19:54 -0700271 cellular_->Connect(error);
Darin Petkovc5f56562011-08-06 16:40:05 -0700272}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700273
Darin Petkovfb0625e2012-01-16 13:05:56 +0100274void CellularService::Disconnect(Error *error) {
275 Service::Disconnect(error);
276 cellular_->Disconnect(error);
277}
278
Darin Petkovb100ae72011-08-24 16:19:45 -0700279void CellularService::ActivateCellularModem(const string &carrier,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500280 Error *error,
281 const ResultCallback &callback) {
282 cellular_->Activate(carrier, error, callback);
Darin Petkovc408e692011-08-17 13:47:15 -0700283}
284
Darin Petkov31332412012-01-28 01:50:02 +0100285void CellularService::SetStorageIdentifier(const string &identifier) {
286 storage_identifier_ = identifier;
287 std::replace_if(storage_identifier_.begin(),
288 storage_identifier_.end(),
289 &Service::IllegalChar, '_');
290}
291
Chris Masone6515aab2011-10-12 16:19:09 -0700292string CellularService::GetStorageIdentifier() const {
Darin Petkov31332412012-01-28 01:50:02 +0100293 return storage_identifier_;
Chris Masone34af2182011-08-22 11:59:36 -0700294}
295
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800296string CellularService::GetDeviceRpcId(Error */*error*/) {
Chris Masone95207da2011-06-29 16:50:49 -0700297 return cellular_->GetRpcIdentifier();
298}
299
Darin Petkovb9c99332012-01-12 13:13:00 +0100300void CellularService::SetActivationState(const string &state) {
301 if (state == activation_state_) {
302 return;
303 }
304 activation_state_ = state;
305 adaptor()->EmitStringChanged(flimflam::kActivationStateProperty, state);
Ben Chan96580442012-09-19 16:19:39 -0700306 SetConnectable(state != flimflam::kActivationStateNotActivated);
Darin Petkovb9c99332012-01-12 13:13:00 +0100307}
308
Darin Petkov381928f2012-02-02 23:00:12 +0100309void CellularService::SetOLP(const OLP &olp) {
310 if (olp_.Equals(olp)) {
311 return;
312 }
313 olp_.CopyFrom(olp);
314 adaptor()->EmitStringmapChanged(flimflam::kPaymentPortalProperty,
315 olp.ToDict());
316}
317
318void CellularService::SetUsageURL(const std::string &url) {
319 if (url == usage_url_) {
320 return;
321 }
322 usage_url_ = url;
323 adaptor()->EmitStringChanged(flimflam::kUsageURLProperty, url);
324}
325
Darin Petkovb72cf402011-11-22 14:51:39 +0100326void CellularService::SetNetworkTechnology(const string &technology) {
327 if (technology == network_technology_) {
328 return;
329 }
330 network_technology_ = technology;
331 adaptor()->EmitStringChanged(flimflam::kNetworkTechnologyProperty,
332 technology);
333}
334
335void CellularService::SetRoamingState(const string &state) {
336 if (state == roaming_state_) {
337 return;
338 }
339 roaming_state_ = state;
340 adaptor()->EmitStringChanged(flimflam::kRoamingStateProperty, state);
341}
342
Darin Petkov3335b372011-08-22 11:05:32 -0700343const Cellular::Operator &CellularService::serving_operator() const {
344 return serving_operator_;
345}
346
Darin Petkov9cb02682012-01-28 00:17:38 +0100347void CellularService::SetServingOperator(const Cellular::Operator &oper) {
348 if (serving_operator_.Equals(oper)) {
349 return;
350 }
Darin Petkov3335b372011-08-22 11:05:32 -0700351 serving_operator_.CopyFrom(oper);
Darin Petkov9cb02682012-01-28 00:17:38 +0100352 adaptor()->EmitStringmapChanged(flimflam::kServingOperatorProperty,
353 oper.ToDict());
Darin Petkov3335b372011-08-22 11:05:32 -0700354}
355
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700356} // namespace shill