OLD | NEW |
| (Empty) |
1 // Copyright (c) 2009 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. | |
4 | |
5 #include "chrome/browser/chromeos/cros_network_library.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/string_util.h" | |
10 #include "chrome/browser/chrome_thread.h" | |
11 #include "chrome/browser/chromeos/cros_library.h" | |
12 #include "net/url_request/url_request_job.h" | |
13 | |
14 // Allows InvokeLater without adding refcounting. This class is a Singleton and | |
15 // won't be deleted until it's last InvokeLater is run. | |
16 template <> | |
17 struct RunnableMethodTraits<CrosNetworkLibrary> { | |
18 void RetainCallee(CrosNetworkLibrary* obj) {} | |
19 void ReleaseCallee(CrosNetworkLibrary* obj) {} | |
20 }; | |
21 | |
22 //////////////////////////////////////////////////////////////////////////////// | |
23 // CrosNetworkLibrary | |
24 | |
25 // static | |
26 const int CrosNetworkLibrary::kNetworkTrafficeTimerSecs = 1; | |
27 | |
28 CrosNetworkLibrary::CrosNetworkLibrary() | |
29 : traffic_type_(0), | |
30 ethernet_connected_(false) { | |
31 if (CrosLibrary::loaded()) { | |
32 Init(); | |
33 } | |
34 g_url_request_job_tracker.AddObserver(this); | |
35 } | |
36 | |
37 CrosNetworkLibrary::~CrosNetworkLibrary() { | |
38 if (CrosLibrary::loaded()) { | |
39 chromeos::DisconnectNetworkStatus(network_status_connection_); | |
40 } | |
41 g_url_request_job_tracker.RemoveObserver(this); | |
42 } | |
43 | |
44 // static | |
45 CrosNetworkLibrary* CrosNetworkLibrary::Get() { | |
46 return Singleton<CrosNetworkLibrary>::get(); | |
47 } | |
48 | |
49 // static | |
50 bool CrosNetworkLibrary::loaded() { | |
51 return CrosLibrary::loaded(); | |
52 } | |
53 | |
54 //////////////////////////////////////////////////////////////////////////////// | |
55 // CrosNetworkLibrary, URLRequestJobTracker::JobObserver implementation: | |
56 | |
57 void CrosNetworkLibrary::OnJobAdded(URLRequestJob* job) { | |
58 CheckNetworkTraffic(false); | |
59 } | |
60 | |
61 void CrosNetworkLibrary::OnJobRemoved(URLRequestJob* job) { | |
62 CheckNetworkTraffic(false); | |
63 } | |
64 | |
65 void CrosNetworkLibrary::OnJobDone(URLRequestJob* job, | |
66 const URLRequestStatus& status) { | |
67 CheckNetworkTraffic(false); | |
68 } | |
69 | |
70 void CrosNetworkLibrary::OnJobRedirect(URLRequestJob* job, const GURL& location, | |
71 int status_code) { | |
72 CheckNetworkTraffic(false); | |
73 } | |
74 | |
75 void CrosNetworkLibrary::OnBytesRead(URLRequestJob* job, int byte_count) { | |
76 CheckNetworkTraffic(true); | |
77 } | |
78 | |
79 void CrosNetworkLibrary::AddObserver(Observer* observer) { | |
80 observers_.AddObserver(observer); | |
81 } | |
82 | |
83 void CrosNetworkLibrary::RemoveObserver(Observer* observer) { | |
84 observers_.RemoveObserver(observer); | |
85 } | |
86 | |
87 static const char* GetEncryptionString(chromeos::EncryptionType encryption) { | |
88 switch (encryption) { | |
89 case chromeos::NONE: | |
90 return "none"; | |
91 case chromeos::RSN: | |
92 return "rsn"; | |
93 case chromeos::WEP: | |
94 return "wep"; | |
95 case chromeos::WPA: | |
96 return "wpa"; | |
97 } | |
98 return "none"; | |
99 } | |
100 | |
101 void CrosNetworkLibrary::ConnectToWifiNetwork(WifiNetwork network, | |
102 const string16& password) { | |
103 if (CrosLibrary::loaded()) { | |
104 // This call kicks off a request to connect to this network, the results of | |
105 // which we'll hear about through the monitoring we've set up in Init(); | |
106 chromeos::ConnectToWifiNetwork( | |
107 network.ssid.c_str(), | |
108 password.empty() ? NULL : UTF16ToUTF8(password).c_str(), | |
109 GetEncryptionString(network.encryption)); | |
110 } | |
111 } | |
112 | |
113 // static | |
114 void CrosNetworkLibrary::NetworkStatusChangedHandler(void* object, | |
115 const chromeos::ServiceStatus& service_status) { | |
116 CrosNetworkLibrary* network = static_cast<CrosNetworkLibrary*>(object); | |
117 WifiNetworkVector networks; | |
118 bool ethernet_connected; | |
119 ParseNetworks(service_status, &networks, ðernet_connected); | |
120 network->UpdateNetworkStatus(networks, ethernet_connected); | |
121 } | |
122 | |
123 // static | |
124 void CrosNetworkLibrary::ParseNetworks( | |
125 const chromeos::ServiceStatus& service_status, WifiNetworkVector* networks, | |
126 bool* ethernet_connected) { | |
127 *ethernet_connected = false; | |
128 for (int i = 0; i < service_status.size; i++) { | |
129 const chromeos::ServiceInfo& service = service_status.services[i]; | |
130 DLOG(INFO) << "Parse " << service.ssid << | |
131 " typ=" << service.type << | |
132 " sta=" << service.state << | |
133 " pas=" << service.needs_passphrase << | |
134 " enc=" << service.encryption << | |
135 " sig=" << service.signal_strength; | |
136 if (service.type == chromeos::TYPE_ETHERNET) { | |
137 // Get the ethernet status. | |
138 *ethernet_connected = service.state == chromeos::STATE_READY; | |
139 } else if (service.type == chromeos::TYPE_WIFI) { | |
140 bool connecting = service.state == chromeos::STATE_ASSOCIATION || | |
141 service.state == chromeos::STATE_CONFIGURATION; | |
142 bool connected = service.state == chromeos::STATE_READY; | |
143 networks->push_back(WifiNetwork(service.ssid, | |
144 service.needs_passphrase, | |
145 service.encryption, | |
146 service.signal_strength, | |
147 connecting, | |
148 connected)); | |
149 } | |
150 } | |
151 } | |
152 | |
153 void CrosNetworkLibrary::Init() { | |
154 // First, get the currently available networks. This data is cached | |
155 // on the connman side, so the call should be quick. | |
156 chromeos::ServiceStatus* service_status = chromeos::GetAvailableNetworks(); | |
157 if (service_status) { | |
158 LOG(INFO) << "Getting initial CrOS network info."; | |
159 WifiNetworkVector networks; | |
160 bool ethernet_connected; | |
161 ParseNetworks(*service_status, &networks, ðernet_connected); | |
162 UpdateNetworkStatus(networks, ethernet_connected); | |
163 chromeos::FreeServiceStatus(service_status); | |
164 } | |
165 LOG(INFO) << "Registering for network status updates."; | |
166 // Now, register to receive updates on network status. | |
167 network_status_connection_ = chromeos::MonitorNetworkStatus( | |
168 &NetworkStatusChangedHandler, this); | |
169 } | |
170 | |
171 void CrosNetworkLibrary::UpdateNetworkStatus( | |
172 const WifiNetworkVector& networks, bool ethernet_connected) { | |
173 // Make sure we run on UI thread. | |
174 if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) { | |
175 ChromeThread::PostTask( | |
176 ChromeThread::UI, FROM_HERE, | |
177 NewRunnableMethod(this, | |
178 &CrosNetworkLibrary::UpdateNetworkStatus, networks, | |
179 ethernet_connected)); | |
180 return; | |
181 } | |
182 | |
183 ethernet_connected_ = ethernet_connected; | |
184 wifi_networks_ = networks; | |
185 // Sort the list of wifi networks by ssid. | |
186 std::sort(wifi_networks_.begin(), wifi_networks_.end()); | |
187 wifi_ = WifiNetwork(); | |
188 for (size_t i = 0; i < wifi_networks_.size(); i++) { | |
189 if (wifi_networks_[i].connecting || wifi_networks_[i].connected) { | |
190 wifi_ = wifi_networks_[i]; | |
191 break; // There is only one connected or connecting wifi network. | |
192 } | |
193 } | |
194 FOR_EACH_OBSERVER(Observer, observers_, NetworkChanged(this)); | |
195 } | |
196 | |
197 void CrosNetworkLibrary::CheckNetworkTraffic(bool download) { | |
198 // If we already have a pending upload and download notification, then | |
199 // shortcut and return. | |
200 if (traffic_type_ == (Observer::TRAFFIC_DOWNLOAD | Observer::TRAFFIC_UPLOAD)) | |
201 return; | |
202 // Figure out if we are uploading and/or downloading. We are downloading | |
203 // if download == true. We are uploading if we have upload progress. | |
204 if (download) | |
205 traffic_type_ |= Observer::TRAFFIC_DOWNLOAD; | |
206 if ((traffic_type_ & Observer::TRAFFIC_UPLOAD) == 0) { | |
207 URLRequestJobTracker::JobIterator it; | |
208 for (it = g_url_request_job_tracker.begin(); | |
209 it != g_url_request_job_tracker.end(); | |
210 ++it) { | |
211 URLRequestJob* job = *it; | |
212 if (job->GetUploadProgress() > 0) { | |
213 traffic_type_ |= Observer::TRAFFIC_UPLOAD; | |
214 break; | |
215 } | |
216 } | |
217 } | |
218 // If we have new traffic data to send out and the timer is not currently | |
219 // running, then start a new timer. | |
220 if (traffic_type_ && !timer_.IsRunning()) { | |
221 timer_.Start(base::TimeDelta::FromSeconds(kNetworkTrafficeTimerSecs), this, | |
222 &CrosNetworkLibrary::NetworkTrafficTimerFired); | |
223 } | |
224 } | |
225 | |
226 void CrosNetworkLibrary:: NetworkTrafficTimerFired() { | |
227 ChromeThread::PostTask( | |
228 ChromeThread::UI, FROM_HERE, | |
229 NewRunnableMethod(this, &CrosNetworkLibrary::NotifyNetworkTraffic, | |
230 traffic_type_)); | |
231 // Reset traffic type so that we don't send the same data next time. | |
232 traffic_type_ = 0; | |
233 } | |
234 | |
235 void CrosNetworkLibrary::NotifyNetworkTraffic(int traffic_type) { | |
236 FOR_EACH_OBSERVER(Observer, observers_, NetworkTraffic(this, traffic_type)); | |
237 } | |
OLD | NEW |