1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromeos/network/geolocation_handler.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/values.h"
10 #include "chromeos/dbus/dbus_thread_manager.h"
11 #include "chromeos/dbus/shill_manager_client.h"
12 #include "third_party/cros_system_api/dbus/service_constants.h"
16 GeolocationHandler::GeolocationHandler()
17 : wifi_enabled_(false),
18 weak_ptr_factory_(this) {
21 GeolocationHandler::~GeolocationHandler() {
22 ShillManagerClient
* manager_client
=
23 DBusThreadManager::Get()->GetShillManagerClient();
25 manager_client
->RemovePropertyChangedObserver(this);
28 void GeolocationHandler::Init() {
29 ShillManagerClient
* manager_client
=
30 DBusThreadManager::Get()->GetShillManagerClient();
31 manager_client
->GetProperties(
32 base::Bind(&GeolocationHandler::ManagerPropertiesCallback
,
33 weak_ptr_factory_
.GetWeakPtr()));
34 manager_client
->AddPropertyChangedObserver(this);
37 bool GeolocationHandler::GetWifiAccessPoints(
38 WifiAccessPointVector
* access_points
, int64
* age_ms
) {
41 // Always request updated access points.
42 RequestWifiAccessPoints();
43 // If no data has been received, return false.
44 if (geolocation_received_time_
.is_null())
47 *access_points
= wifi_access_points_
;
49 base::TimeDelta dtime
= base::Time::Now() - geolocation_received_time_
;
50 *age_ms
= dtime
.InMilliseconds();
55 void GeolocationHandler::OnPropertyChanged(const std::string
& key
,
56 const base::Value
& value
) {
57 HandlePropertyChanged(key
, value
);
60 //------------------------------------------------------------------------------
63 void GeolocationHandler::ManagerPropertiesCallback(
64 DBusMethodCallStatus call_status
,
65 const base::DictionaryValue
& properties
) {
66 const base::Value
* value
= NULL
;
67 if (properties
.Get(shill::kEnabledTechnologiesProperty
, &value
) && value
)
68 HandlePropertyChanged(shill::kEnabledTechnologiesProperty
, *value
);
71 void GeolocationHandler::HandlePropertyChanged(const std::string
& key
,
72 const base::Value
& value
) {
73 if (key
!= shill::kEnabledTechnologiesProperty
)
75 const base::ListValue
* technologies
= NULL
;
76 if (!value
.GetAsList(&technologies
) || !technologies
)
78 bool wifi_was_enabled
= wifi_enabled_
;
79 wifi_enabled_
= false;
80 for (base::ListValue::const_iterator iter
= technologies
->begin();
81 iter
!= technologies
->end(); ++iter
) {
82 std::string technology
;
83 (*iter
)->GetAsString(&technology
);
84 if (technology
== shill::kTypeWifi
) {
89 if (!wifi_was_enabled
&& wifi_enabled_
)
90 RequestWifiAccessPoints(); // Request initial location data.
93 void GeolocationHandler::RequestWifiAccessPoints() {
94 DBusThreadManager::Get()->GetShillManagerClient()->GetNetworksForGeolocation(
95 base::Bind(&GeolocationHandler::GeolocationCallback
,
96 weak_ptr_factory_
.GetWeakPtr()));
99 void GeolocationHandler::GeolocationCallback(
100 DBusMethodCallStatus call_status
,
101 const base::DictionaryValue
& properties
) {
102 if (call_status
!= DBUS_METHOD_CALL_SUCCESS
) {
103 LOG(ERROR
) << "Failed to get Geolocation data: " << call_status
;
106 wifi_access_points_
.clear();
107 if (properties
.empty())
108 return; // No enabled devices, don't update received time.
110 // Dictionary<device_type, entry_list>
111 for (base::DictionaryValue::Iterator
iter(properties
);
112 !iter
.IsAtEnd(); iter
.Advance()) {
113 const base::ListValue
* entry_list
= NULL
;
114 if (!iter
.value().GetAsList(&entry_list
)) {
115 LOG(WARNING
) << "Geolocation dictionary value not a List: " << iter
.key();
118 // List[Dictionary<key, value_str>]
119 for (size_t i
= 0; i
< entry_list
->GetSize(); ++i
) {
120 const base::DictionaryValue
* entry
= NULL
;
121 if (!entry_list
->GetDictionary(i
, &entry
) || !entry
) {
122 LOG(WARNING
) << "Geolocation list value not a Dictionary: " << i
;
125 // Docs: developers.google.com/maps/documentation/business/geolocation
127 entry
->GetString(shill::kGeoMacAddressProperty
, &wap
.mac_address
);
129 if (entry
->GetString(shill::kGeoAgeProperty
, &age_str
)) {
131 if (base::StringToInt64(age_str
, &age_ms
)) {
133 base::Time::Now() - base::TimeDelta::FromMilliseconds(age_ms
);
136 std::string strength_str
;
137 if (entry
->GetString(shill::kGeoSignalStrengthProperty
, &strength_str
))
138 base::StringToInt(strength_str
, &wap
.signal_strength
);
139 std::string signal_str
;
140 if (entry
->GetString(shill::kGeoSignalToNoiseRatioProperty
, &signal_str
))
141 base::StringToInt(signal_str
, &wap
.signal_to_noise
);
142 std::string channel_str
;
143 if (entry
->GetString(shill::kGeoChannelProperty
, &channel_str
))
144 base::StringToInt(channel_str
, &wap
.channel
);
145 wifi_access_points_
.push_back(wap
);
148 geolocation_received_time_
= base::Time::Now();
151 } // namespace chromeos