Fix race condition in WebstoreInstallHelper.
[chromium-blink-merge.git] / chromeos / network / geolocation_handler.cc
blobd4adfb8998b549ba63f859f9af9c2c072f8dbbf6
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"
7 #include "base/bind.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"
14 namespace chromeos {
16 GeolocationHandler::GeolocationHandler()
17 : wifi_enabled_(false),
18 weak_ptr_factory_(this) {
21 GeolocationHandler::~GeolocationHandler() {
22 ShillManagerClient* manager_client =
23 DBusThreadManager::Get()->GetShillManagerClient();
24 if (manager_client)
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) {
39 if (!wifi_enabled_)
40 return false;
41 // Always request updated access points.
42 RequestWifiAccessPoints();
43 // If no data has been received, return false.
44 if (geolocation_received_time_.is_null())
45 return false;
46 if (access_points)
47 *access_points = wifi_access_points_;
48 if (age_ms) {
49 base::TimeDelta dtime = base::Time::Now() - geolocation_received_time_;
50 *age_ms = dtime.InMilliseconds();
52 return true;
55 void GeolocationHandler::OnPropertyChanged(const std::string& key,
56 const base::Value& value) {
57 HandlePropertyChanged(key, value);
60 //------------------------------------------------------------------------------
61 // Private methods
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)
74 return;
75 const base::ListValue* technologies = NULL;
76 if (!value.GetAsList(&technologies) || !technologies)
77 return;
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) {
85 wifi_enabled_ = true;
86 break;
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;
104 return;
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();
116 continue;
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;
123 continue;
125 // Docs: developers.google.com/maps/documentation/business/geolocation
126 WifiAccessPoint wap;
127 entry->GetString(shill::kGeoMacAddressProperty, &wap.mac_address);
128 std::string age_str;
129 if (entry->GetString(shill::kGeoAgeProperty, &age_str)) {
130 int64 age_ms;
131 if (base::StringToInt64(age_str, &age_ms)) {
132 wap.timestamp =
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