OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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_impl_cros.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/command_line.h" | |
9 #include "base/json/json_writer.h" // for debug output only. | |
10 #include "base/metrics/histogram.h" | |
11 #include "base/stl_util.h" | |
12 #include "base/values.h" | |
13 #include "chrome/browser/chromeos/cros/native_network_constants.h" | |
14 #include "chrome/browser/chromeos/cros/native_network_parser.h" | |
15 #include "chrome/browser/chromeos/settings/cros_settings.h" | |
16 #include "chrome/common/chrome_switches.h" | |
17 #include "chromeos/network/cros_network_functions.h" | |
18 #include "chromeos/network/network_state_handler.h" | |
19 #include "chromeos/network/network_util.h" | |
20 #include "content/public/browser/browser_thread.h" | |
21 #include "third_party/cros_system_api/dbus/service_constants.h" | |
22 | |
23 using content::BrowserThread; | |
24 | |
25 namespace chromeos { | |
26 | |
27 // Structure used to pass IP parameter info to a DoSetIPParameters callback, | |
28 // since Bind only takes up to six parameters. | |
29 struct NetworkLibraryImplCros::IPParameterInfo { | |
30 std::string address; | |
31 std::string netmask; | |
32 std::string gateway; | |
33 std::string name_servers; | |
34 int dhcp_usage_mask; | |
35 }; | |
36 | |
37 //////////////////////////////////////////////////////////////////////////// | |
38 | |
39 NetworkLibraryImplCros::NetworkLibraryImplCros() | |
40 : NetworkLibraryImplBase(), | |
41 weak_ptr_factory_(this) { | |
42 } | |
43 | |
44 NetworkLibraryImplCros::~NetworkLibraryImplCros() { | |
45 STLDeleteValues(&monitored_networks_); | |
46 STLDeleteValues(&monitored_devices_); | |
47 } | |
48 | |
49 void NetworkLibraryImplCros::Init() { | |
50 // First, get the currently available networks. This data is cached | |
51 // on the connman side, so the call should be quick. | |
52 VLOG(1) << "Requesting initial network manager info from libcros."; | |
53 CrosRequestNetworkManagerProperties( | |
54 base::Bind(&NetworkLibraryImplCros::NetworkManagerUpdate, | |
55 weak_ptr_factory_.GetWeakPtr())); | |
56 network_manager_watcher_.reset(CrosMonitorNetworkManagerProperties( | |
57 base::Bind(&NetworkLibraryImplCros::NetworkManagerStatusChangedHandler, | |
58 weak_ptr_factory_.GetWeakPtr()))); | |
59 // Always have at least one device obsever so that device updates are | |
60 // always received. | |
61 network_device_observer_.reset(new NetworkLibraryDeviceObserver()); | |
62 } | |
63 | |
64 bool NetworkLibraryImplCros::IsCros() const { | |
65 return true; | |
66 } | |
67 | |
68 ////////////////////////////////////////////////////////////////////////////// | |
69 // NetworkLibraryImplBase implementation. | |
70 | |
71 void NetworkLibraryImplCros::MonitorNetworkStart( | |
72 const std::string& service_path) { | |
73 if (monitored_networks_.find(service_path) == monitored_networks_.end()) { | |
74 CrosNetworkWatcher* watcher = CrosMonitorNetworkServiceProperties( | |
75 base::Bind(&NetworkLibraryImplCros::UpdateNetworkStatus, | |
76 weak_ptr_factory_.GetWeakPtr()), | |
77 service_path); | |
78 monitored_networks_[service_path] = watcher; | |
79 } | |
80 } | |
81 | |
82 void NetworkLibraryImplCros::MonitorNetworkStop( | |
83 const std::string& service_path) { | |
84 NetworkWatcherMap::iterator iter = monitored_networks_.find(service_path); | |
85 if (iter != monitored_networks_.end()) { | |
86 delete iter->second; | |
87 monitored_networks_.erase(iter); | |
88 } | |
89 } | |
90 | |
91 void NetworkLibraryImplCros::MonitorNetworkDeviceStart( | |
92 const std::string& device_path) { | |
93 if (monitored_devices_.find(device_path) == monitored_devices_.end()) { | |
94 CrosNetworkWatcher* watcher = CrosMonitorNetworkDeviceProperties( | |
95 base::Bind(&NetworkLibraryImplCros::UpdateNetworkDeviceStatus, | |
96 weak_ptr_factory_.GetWeakPtr()), | |
97 device_path); | |
98 monitored_devices_[device_path] = watcher; | |
99 } | |
100 } | |
101 | |
102 void NetworkLibraryImplCros::MonitorNetworkDeviceStop( | |
103 const std::string& device_path) { | |
104 NetworkWatcherMap::iterator iter = monitored_devices_.find(device_path); | |
105 if (iter != monitored_devices_.end()) { | |
106 delete iter->second; | |
107 monitored_devices_.erase(iter); | |
108 } | |
109 } | |
110 | |
111 void NetworkLibraryImplCros::UpdateNetworkStatus( | |
112 const std::string& path, const std::string& key, const Value& value) { | |
113 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
114 Network* network = FindNetworkByPath(path); | |
115 if (network) { | |
116 VLOG(2) << "UpdateNetworkStatus: " << network->name() << "." << key; | |
117 bool prev_connected = network->connected(); | |
118 if (!network->UpdateStatus(key, value, NULL)) { | |
119 LOG(WARNING) << "UpdateNetworkStatus: Error updating: " | |
120 << path << "." << key; | |
121 } | |
122 if (key == flimflam::kProfileProperty) | |
123 SetProfileTypeFromPath(network); | |
124 // If we just connected, this may have been added to remembered list. | |
125 if (!prev_connected && network->connected()) | |
126 RequestRememberedNetworksUpdate(); | |
127 NotifyNetworkChanged(network); | |
128 // Anything observing the manager needs to know about any service change. | |
129 NotifyNetworkManagerChanged(false); // Not forced. | |
130 } | |
131 } | |
132 | |
133 void NetworkLibraryImplCros::UpdateNetworkDeviceStatus( | |
134 const std::string& path, const std::string& key, const Value& value) { | |
135 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
136 NetworkDevice* device = FindNetworkDeviceByPath(path); | |
137 if (device) { | |
138 VLOG(2) << "UpdateNetworkDeviceStatus: " << device->name() << "." << key; | |
139 PropertyIndex index = PROPERTY_INDEX_UNKNOWN; | |
140 if (device->UpdateStatus(key, value, &index)) { | |
141 if (device->type() == TYPE_CELLULAR) { | |
142 if (!UpdateCellularDeviceStatus(device, index)) | |
143 return; // Update aborted, skip notify. | |
144 } | |
145 } else { | |
146 VLOG(1) << "UpdateNetworkDeviceStatus: Failed to update: " | |
147 << path << "." << key; | |
148 } | |
149 if (device->type() == TYPE_WIFI && device->scanning() != wifi_scanning_) { | |
150 wifi_scanning_ = device->scanning(); | |
151 NotifyNetworkManagerChanged(false); // Not forced. | |
152 } | |
153 // Notify only observers on device property change. | |
154 NotifyNetworkDeviceChanged(device, index); | |
155 // If a device's power state changes, new properties may become defined. | |
156 if (index == PROPERTY_INDEX_POWERED) { | |
157 CrosRequestNetworkDeviceProperties( | |
158 path, | |
159 base::Bind(&NetworkLibraryImplCros::NetworkDeviceUpdate, | |
160 weak_ptr_factory_.GetWeakPtr())); | |
161 } | |
162 } | |
163 } | |
164 | |
165 bool NetworkLibraryImplCros::UpdateCellularDeviceStatus(NetworkDevice* device, | |
166 PropertyIndex index) { | |
167 if (index == PROPERTY_INDEX_CELLULAR_ALLOW_ROAMING) { | |
168 if (IsCellularAlwaysInRoaming()) { | |
169 if (!device->data_roaming_allowed()) | |
170 SetCellularDataRoamingAllowed(true); | |
171 } else { | |
172 bool settings_value; | |
173 if ((CrosSettings::Get()->GetBoolean( | |
174 kSignedDataRoamingEnabled, &settings_value)) && | |
175 (device->data_roaming_allowed() != settings_value)) { | |
176 // Switch back to signed settings value. | |
177 SetCellularDataRoamingAllowed(settings_value); | |
178 return false; | |
179 } | |
180 } | |
181 } else if (index == PROPERTY_INDEX_SIM_LOCK) { | |
182 // We only ever request a sim unlock when we wish to enable the device. | |
183 if (!device->is_sim_locked() && !cellular_enabled()) | |
184 EnableCellularNetworkDevice(true); | |
185 } | |
186 return true; | |
187 } | |
188 | |
189 ///////////////////////////////////////////////////////////////////////////// | |
190 // NetworkLibraryImplBase connect implementation. | |
191 | |
192 void NetworkLibraryImplCros::CallConfigureService(const std::string& identifier, | |
193 const DictionaryValue* info) { | |
194 CrosConfigureService(*info); | |
195 } | |
196 | |
197 void NetworkLibraryImplCros::NetworkConnectCallback( | |
198 const std::string& service_path, | |
199 NetworkMethodErrorType error, | |
200 const std::string& error_message) { | |
201 NetworkConnectStatus status; | |
202 if (error == NETWORK_METHOD_ERROR_NONE) { | |
203 status = CONNECT_SUCCESS; | |
204 } else { | |
205 LOG(WARNING) << "Error from ServiceConnect callback for: " | |
206 << service_path | |
207 << " Error: " << error << " Message: " << error_message; | |
208 if (error_message == flimflam::kErrorPassphraseRequiredMsg) { | |
209 status = CONNECT_BAD_PASSPHRASE; | |
210 } else { | |
211 status = CONNECT_FAILED; | |
212 } | |
213 } | |
214 Network* network = FindNetworkByPath(service_path); | |
215 if (!network) { | |
216 LOG(ERROR) << "No network for path: " << service_path; | |
217 return; | |
218 } | |
219 NetworkConnectCompleted(network, status); | |
220 } | |
221 | |
222 void NetworkLibraryImplCros::CallConnectToNetwork(Network* network) { | |
223 DCHECK(network); | |
224 CrosRequestNetworkServiceConnect( | |
225 network->service_path(), | |
226 base::Bind(&NetworkLibraryImplCros::NetworkConnectCallback, | |
227 weak_ptr_factory_.GetWeakPtr())); | |
228 } | |
229 | |
230 void NetworkLibraryImplCros::WifiServiceUpdateAndConnect( | |
231 const std::string& service_path, | |
232 const base::DictionaryValue* properties) { | |
233 if (properties) { | |
234 Network* network = ParseNetwork(service_path, *properties); | |
235 CHECK_EQ(network->type(), TYPE_WIFI); | |
236 ConnectToWifiNetworkUsingConnectData(static_cast<WifiNetwork*>(network)); | |
237 } | |
238 } | |
239 | |
240 void NetworkLibraryImplCros::CallRequestWifiNetworkAndConnect( | |
241 const std::string& ssid, ConnectionSecurity security) { | |
242 // Asynchronously request service properties and call | |
243 // WifiServiceUpdateAndConnect. | |
244 CrosRequestHiddenWifiNetworkProperties( | |
245 ssid, | |
246 SecurityToString(security), | |
247 base::Bind(&NetworkLibraryImplCros::WifiServiceUpdateAndConnect, | |
248 weak_ptr_factory_.GetWeakPtr())); | |
249 } | |
250 | |
251 void NetworkLibraryImplCros::VPNServiceUpdateAndConnect( | |
252 const std::string& service_path, | |
253 const base::DictionaryValue* properties) { | |
254 if (properties) { | |
255 VLOG(1) << "Connecting to new VPN Service: " << service_path; | |
256 Network* network = ParseNetwork(service_path, *properties); | |
257 CHECK_EQ(network->type(), TYPE_VPN); | |
258 ConnectToVirtualNetworkUsingConnectData( | |
259 static_cast<VirtualNetwork*>(network)); | |
260 } else { | |
261 LOG(WARNING) << "Unable to create VPN Service: " << service_path; | |
262 } | |
263 } | |
264 | |
265 void NetworkLibraryImplCros::CallRequestVirtualNetworkAndConnect( | |
266 const std::string& service_name, | |
267 const std::string& server_hostname, | |
268 ProviderType provider_type) { | |
269 CrosRequestVirtualNetworkProperties( | |
270 service_name, | |
271 server_hostname, | |
272 ProviderTypeToString(provider_type), | |
273 base::Bind(&NetworkLibraryImplCros::VPNServiceUpdateAndConnect, | |
274 weak_ptr_factory_.GetWeakPtr())); | |
275 } | |
276 | |
277 void NetworkLibraryImplCros::CallDeleteRememberedNetwork( | |
278 const std::string& profile_path, | |
279 const std::string& service_path) { | |
280 CrosDeleteServiceFromProfile(profile_path, service_path); | |
281 } | |
282 | |
283 ////////////////////////////////////////////////////////////////////////////// | |
284 // NetworkLibrary implementation. | |
285 | |
286 void NetworkLibraryImplCros::ChangePin(const std::string& old_pin, | |
287 const std::string& new_pin) { | |
288 const NetworkDevice* cellular = FindCellularDevice(); | |
289 if (!cellular) { | |
290 NOTREACHED() << "Calling ChangePin method w/o cellular device."; | |
291 return; | |
292 } | |
293 sim_operation_ = SIM_OPERATION_CHANGE_PIN; | |
294 CrosRequestChangePin( | |
295 cellular->device_path(), old_pin, new_pin, | |
296 base::Bind(&NetworkLibraryImplCros::PinOperationCallback, | |
297 weak_ptr_factory_.GetWeakPtr())); | |
298 } | |
299 | |
300 void NetworkLibraryImplCros::ChangeRequirePin(bool require_pin, | |
301 const std::string& pin) { | |
302 VLOG(1) << "ChangeRequirePin require_pin: " << require_pin | |
303 << " pin: " << pin; | |
304 const NetworkDevice* cellular = FindCellularDevice(); | |
305 if (!cellular) { | |
306 NOTREACHED() << "Calling ChangeRequirePin method w/o cellular device."; | |
307 return; | |
308 } | |
309 sim_operation_ = SIM_OPERATION_CHANGE_REQUIRE_PIN; | |
310 CrosRequestRequirePin( | |
311 cellular->device_path(), pin, require_pin, | |
312 base::Bind(&NetworkLibraryImplCros::PinOperationCallback, | |
313 weak_ptr_factory_.GetWeakPtr())); | |
314 } | |
315 | |
316 void NetworkLibraryImplCros::EnterPin(const std::string& pin) { | |
317 const NetworkDevice* cellular = FindCellularDevice(); | |
318 if (!cellular) { | |
319 NOTREACHED() << "Calling EnterPin method w/o cellular device."; | |
320 return; | |
321 } | |
322 sim_operation_ = SIM_OPERATION_ENTER_PIN; | |
323 CrosRequestEnterPin(cellular->device_path(), pin, | |
324 base::Bind(&NetworkLibraryImplCros::PinOperationCallback, | |
325 weak_ptr_factory_.GetWeakPtr())); | |
326 } | |
327 | |
328 void NetworkLibraryImplCros::UnblockPin(const std::string& puk, | |
329 const std::string& new_pin) { | |
330 const NetworkDevice* cellular = FindCellularDevice(); | |
331 if (!cellular) { | |
332 NOTREACHED() << "Calling UnblockPin method w/o cellular device."; | |
333 return; | |
334 } | |
335 sim_operation_ = SIM_OPERATION_UNBLOCK_PIN; | |
336 CrosRequestUnblockPin( | |
337 cellular->device_path(), puk, new_pin, | |
338 base::Bind(&NetworkLibraryImplCros::PinOperationCallback, | |
339 weak_ptr_factory_.GetWeakPtr())); | |
340 } | |
341 | |
342 void NetworkLibraryImplCros::PinOperationCallback( | |
343 const std::string& path, | |
344 NetworkMethodErrorType error, | |
345 const std::string& error_message) { | |
346 PinOperationError pin_error; | |
347 VLOG(1) << "PinOperationCallback, error: " << error | |
348 << " error_msg: " << error_message; | |
349 if (error == chromeos::NETWORK_METHOD_ERROR_NONE) { | |
350 pin_error = PIN_ERROR_NONE; | |
351 VLOG(1) << "Pin operation completed successfuly"; | |
352 } else { | |
353 if (error_message == flimflam::kErrorIncorrectPinMsg || | |
354 error_message == flimflam::kErrorPinRequiredMsg) { | |
355 pin_error = PIN_ERROR_INCORRECT_CODE; | |
356 } else if (error_message == flimflam::kErrorPinBlockedMsg) { | |
357 pin_error = PIN_ERROR_BLOCKED; | |
358 } else { | |
359 pin_error = PIN_ERROR_UNKNOWN; | |
360 NOTREACHED() << "Unknown PIN error: " << error_message; | |
361 } | |
362 } | |
363 NotifyPinOperationCompleted(pin_error); | |
364 } | |
365 | |
366 void NetworkLibraryImplCros::RequestCellularScan() { | |
367 const NetworkDevice* cellular = FindCellularDevice(); | |
368 if (!cellular) { | |
369 NOTREACHED() << "Calling RequestCellularScan method w/o cellular device."; | |
370 return; | |
371 } | |
372 CrosProposeScan(cellular->device_path()); | |
373 } | |
374 | |
375 void NetworkLibraryImplCros::RequestCellularRegister( | |
376 const std::string& network_id) { | |
377 const NetworkDevice* cellular = FindCellularDevice(); | |
378 if (!cellular) { | |
379 NOTREACHED() << "Calling CellularRegister method w/o cellular device."; | |
380 return; | |
381 } | |
382 CrosRequestCellularRegister( | |
383 cellular->device_path(), network_id, | |
384 base::Bind(&NetworkLibraryImplCros::CellularRegisterCallback, | |
385 weak_ptr_factory_.GetWeakPtr())); | |
386 } | |
387 | |
388 void NetworkLibraryImplCros::CellularRegisterCallback( | |
389 const std::string& path, | |
390 NetworkMethodErrorType error, | |
391 const std::string& error_message) { | |
392 // TODO(dpolukhin): Notify observers about network registration status | |
393 // but not UI doesn't assume such notification so just ignore result. | |
394 } | |
395 | |
396 void NetworkLibraryImplCros::SetCellularDataRoamingAllowed(bool new_value) { | |
397 const NetworkDevice* cellular = FindCellularDevice(); | |
398 if (!cellular) { | |
399 NOTREACHED() << "Calling SetCellularDataRoamingAllowed method " | |
400 "w/o cellular device."; | |
401 return; | |
402 } | |
403 base::FundamentalValue value(new_value); | |
404 CrosSetNetworkDeviceProperty(cellular->device_path(), | |
405 flimflam::kCellularAllowRoamingProperty, | |
406 value); | |
407 } | |
408 | |
409 void NetworkLibraryImplCros::SetCarrier( | |
410 const std::string& carrier, | |
411 const NetworkOperationCallback& completed) { | |
412 const NetworkDevice* cellular = FindCellularDevice(); | |
413 if (!cellular) { | |
414 NOTREACHED() << "Calling SetCarrier method w/o cellular device."; | |
415 return; | |
416 } | |
417 CrosSetCarrier(cellular->device_path(), carrier, completed); | |
418 } | |
419 | |
420 bool NetworkLibraryImplCros::IsCellularAlwaysInRoaming() { | |
421 const NetworkDevice* cellular = FindCellularDevice(); | |
422 if (!cellular) { | |
423 NOTREACHED() << "Calling IsCellularAlwaysInRoaming method " | |
424 "w/o cellular device."; | |
425 return false; | |
426 } | |
427 return cellular->provider_requires_roaming(); | |
428 } | |
429 | |
430 void NetworkLibraryImplCros::RequestNetworkScan() { | |
431 if (wifi_enabled()) | |
432 CrosRequestNetworkScan(flimflam::kTypeWifi); | |
433 | |
434 if (wimax_enabled()) | |
435 CrosRequestNetworkScan(flimflam::kTypeWimax); | |
436 | |
437 // Make sure all Manager info is up to date. This will also update | |
438 // remembered networks and visible services. | |
439 CrosRequestNetworkManagerProperties( | |
440 base::Bind(&NetworkLibraryImplCros::NetworkManagerUpdate, | |
441 weak_ptr_factory_.GetWeakPtr())); | |
442 } | |
443 | |
444 void NetworkLibraryImplCros::RefreshIPConfig(Network* network) { | |
445 DCHECK(network); | |
446 CrosRequestNetworkDeviceProperties( | |
447 network->device_path(), | |
448 base::Bind(&NetworkLibraryImplCros::RefreshIPConfigCallback, | |
449 weak_ptr_factory_.GetWeakPtr())); | |
450 } | |
451 | |
452 void NetworkLibraryImplCros::RefreshIPConfigCallback( | |
453 const std::string& device_path, | |
454 const base::DictionaryValue* properties) { | |
455 const ListValue* ips = NULL; | |
456 if (!properties->GetListWithoutPathExpansion( | |
457 flimflam::kIPConfigsProperty, &ips)) | |
458 return; | |
459 | |
460 for (size_t i = 0; i < ips->GetSize(); i++) { | |
461 std::string ipconfig_path; | |
462 if (!ips->GetString(i, &ipconfig_path)) | |
463 continue; | |
464 CrosRequestIPConfigRefresh(ipconfig_path); | |
465 } | |
466 } | |
467 | |
468 void NetworkLibraryImplCros::DisconnectFromNetwork(const Network* network) { | |
469 DCHECK(network); | |
470 // Asynchronous disconnect request. Network state will be updated through | |
471 // the network manager once disconnect completes. | |
472 CrosRequestNetworkServiceDisconnect(network->service_path()); | |
473 } | |
474 | |
475 void NetworkLibraryImplCros::CallEnableNetworkDeviceType( | |
476 ConnectionType device, bool enable) { | |
477 busy_devices_ |= 1 << device; | |
478 CrosRequestNetworkDeviceEnable(ConnectionTypeToString(device), enable); | |
479 if (device == TYPE_WIFI && enable) | |
480 RequestNetworkScan(); | |
481 } | |
482 | |
483 void NetworkLibraryImplCros::CallRemoveNetwork(const Network* network) { | |
484 const std::string& service_path = network->service_path(); | |
485 if (network->connected()) | |
486 CrosRequestNetworkServiceDisconnect(service_path); | |
487 CrosRequestRemoveNetworkService(service_path); | |
488 } | |
489 | |
490 void NetworkLibraryImplCros::GetIPConfigsCallback( | |
491 const NetworkGetIPConfigsCallback& callback, | |
492 HardwareAddressFormat format, | |
493 const NetworkIPConfigVector& ipconfig_vector, | |
494 const std::string& hardware_address) { | |
495 std::string hardware_address_tmp = hardware_address; | |
496 for (size_t i = 0; i < hardware_address_tmp.size(); ++i) | |
497 hardware_address_tmp[i] = toupper(hardware_address_tmp[i]); | |
498 if (format == FORMAT_COLON_SEPARATED_HEX) { | |
499 if (hardware_address_tmp.size() % 2 == 0) { | |
500 std::string output; | |
501 for (size_t i = 0; i < hardware_address_tmp.size(); ++i) { | |
502 if ((i != 0) && (i % 2 == 0)) | |
503 output.push_back(':'); | |
504 output.push_back(hardware_address_tmp[i]); | |
505 } | |
506 hardware_address_tmp.swap(output); | |
507 } | |
508 } else { | |
509 DCHECK_EQ(format, FORMAT_RAW_HEX); | |
510 } | |
511 callback.Run(ipconfig_vector, hardware_address_tmp); | |
512 } | |
513 | |
514 void NetworkLibraryImplCros::GetIPConfigs( | |
515 const std::string& device_path, | |
516 HardwareAddressFormat format, | |
517 const NetworkGetIPConfigsCallback& callback) { | |
518 CrosListIPConfigs(device_path, | |
519 base::Bind(&NetworkLibraryImplCros::GetIPConfigsCallback, | |
520 weak_ptr_factory_.GetWeakPtr(), | |
521 callback, | |
522 format)); | |
523 } | |
524 | |
525 void NetworkLibraryImplCros::SetIPParameters(const std::string& service_path, | |
526 const std::string& address, | |
527 const std::string& netmask, | |
528 const std::string& gateway, | |
529 const std::string& name_servers, | |
530 int dhcp_usage_mask) { | |
531 if (service_path.empty()) | |
532 return; | |
533 | |
534 VLOG(1) << "Setting IP parameters: " | |
535 << "address: " << address | |
536 << (dhcp_usage_mask & USE_DHCP_ADDRESS ? | |
537 " (ignored)" : " (in use)") | |
538 << "netmask: " << netmask | |
539 << (dhcp_usage_mask & USE_DHCP_NETMASK ? | |
540 " (ignored)" : " (in use)") | |
541 << "gateway: " << gateway | |
542 << (dhcp_usage_mask & USE_DHCP_GATEWAY ? | |
543 " (ignored)" : " (in use)") | |
544 << "name_servers: " << name_servers | |
545 << (dhcp_usage_mask & USE_DHCP_NAME_SERVERS ? | |
546 " (ignored)" : " (in use)"); | |
547 | |
548 // Have to pass these in a structure, since Bind only takes up to six | |
549 // parameters. | |
550 IPParameterInfo info; | |
551 info.address = address; | |
552 info.netmask = netmask; | |
553 info.gateway = gateway; | |
554 info.name_servers = name_servers; | |
555 info.dhcp_usage_mask = dhcp_usage_mask; | |
556 chromeos::NetworkPropertiesCallback callback = | |
557 base::Bind(&NetworkLibraryImplCros::SetIPParametersCallback, | |
558 weak_ptr_factory_.GetWeakPtr(), info); | |
559 | |
560 CrosRequestNetworkServiceProperties(service_path, callback); | |
561 } | |
562 | |
563 void NetworkLibraryImplCros::RequestNetworkServiceProperties( | |
564 const std::string& service_path, | |
565 const NetworkServicePropertiesCallback& callback) { | |
566 chromeos::CrosRequestNetworkServiceProperties(service_path, callback); | |
567 } | |
568 | |
569 ///////////////////////////////////////////////////////////////////////////// | |
570 // Network Manager functions. | |
571 | |
572 void NetworkLibraryImplCros::NetworkManagerStatusChangedHandler( | |
573 const std::string& path, | |
574 const std::string& key, | |
575 const Value& value) { | |
576 if (!NetworkManagerStatusChanged(key, &value)) { | |
577 LOG(ERROR) << "Invalid key-value pair, key: " << key << " type: " | |
578 << value.GetType(); | |
579 } | |
580 } | |
581 | |
582 // This processes all Manager update messages. | |
583 bool NetworkLibraryImplCros::NetworkManagerStatusChanged( | |
584 const std::string& key, const Value* value) { | |
585 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
586 base::TimeTicks start = base::TimeTicks::Now(); | |
587 VLOG(1) << "NetworkManagerStatusChanged: KEY=" << key; | |
588 int index = NativeNetworkParser::property_mapper()->Get(key); | |
589 switch (index) { | |
590 case PROPERTY_INDEX_STATE: | |
591 // Currently we ignore the network manager state. | |
592 break; | |
593 case PROPERTY_INDEX_AVAILABLE_TECHNOLOGIES: { | |
594 const ListValue* vlist = NULL; | |
595 if (!value->GetAsList(&vlist)) | |
596 return false; | |
597 UpdateAvailableTechnologies(vlist); | |
598 break; | |
599 } | |
600 case PROPERTY_INDEX_UNINITIALIZED_TECHNOLOGIES: { | |
601 const ListValue* vlist = NULL; | |
602 if (!value->GetAsList(&vlist)) | |
603 return false; | |
604 UpdateTechnologies(vlist, &uninitialized_devices_); | |
605 break; | |
606 } | |
607 case PROPERTY_INDEX_ENABLED_TECHNOLOGIES: { | |
608 const ListValue* vlist = NULL; | |
609 if (!value->GetAsList(&vlist)) | |
610 return false; | |
611 UpdateEnabledTechnologies(vlist); | |
612 break; | |
613 } | |
614 case PROPERTY_INDEX_DEFAULT_TECHNOLOGY: | |
615 // Currently we ignore DefaultTechnology. | |
616 break; | |
617 case PROPERTY_INDEX_ACTIVE_PROFILE: { | |
618 std::string prev = active_profile_path_; | |
619 DCHECK_EQ(value->GetType(), Value::TYPE_STRING); | |
620 value->GetAsString(&active_profile_path_); | |
621 VLOG(1) << "Active Profile: " << active_profile_path_; | |
622 if (active_profile_path_ != prev && | |
623 active_profile_path_ != kSharedProfilePath) | |
624 SwitchToPreferredNetwork(); | |
625 break; | |
626 } | |
627 case PROPERTY_INDEX_PROFILES: { | |
628 const ListValue* vlist = NULL; | |
629 if (!value->GetAsList(&vlist)) | |
630 return false; | |
631 UpdateRememberedNetworks(vlist); | |
632 break; | |
633 } | |
634 case PROPERTY_INDEX_SERVICES: { | |
635 const ListValue* vlist = NULL; | |
636 if (!value->GetAsList(&vlist)) | |
637 return false; | |
638 UpdateNetworkServiceList(vlist); | |
639 break; | |
640 } | |
641 case PROPERTY_INDEX_SERVICE_WATCH_LIST: { | |
642 const ListValue* vlist = NULL; | |
643 if (!value->GetAsList(&vlist)) | |
644 return false; | |
645 UpdateWatchedNetworkServiceList(vlist); | |
646 break; | |
647 } | |
648 case PROPERTY_INDEX_DEVICE: | |
649 case PROPERTY_INDEX_DEVICES: { | |
650 const ListValue* vlist = NULL; | |
651 if (!value->GetAsList(&vlist)) | |
652 return false; | |
653 UpdateNetworkDeviceList(vlist); | |
654 break; | |
655 } | |
656 case PROPERTY_INDEX_CHECK_PORTAL_LIST: { | |
657 DCHECK_EQ(value->GetType(), Value::TYPE_STRING); | |
658 value->GetAsString(&check_portal_list_); | |
659 break; | |
660 } | |
661 case PROPERTY_INDEX_PORTAL_URL: | |
662 case PROPERTY_INDEX_ARP_GATEWAY: | |
663 // Currently we ignore PortalURL and ArpGateway. | |
664 break; | |
665 default: | |
666 VLOG(2) << "Manager: Unhandled key: " << key; | |
667 break; | |
668 } | |
669 base::TimeDelta delta = base::TimeTicks::Now() - start; | |
670 VLOG(2) << "NetworkManagerStatusChanged: time: " | |
671 << delta.InMilliseconds() << " ms."; | |
672 HISTOGRAM_TIMES("CROS_NETWORK_UPDATE", delta); | |
673 return true; | |
674 } | |
675 | |
676 void NetworkLibraryImplCros::NetworkManagerUpdate( | |
677 const std::string& manager_path, | |
678 const base::DictionaryValue* properties) { | |
679 if (!properties) { | |
680 LOG(ERROR) << "Error retrieving manager properties: " << manager_path; | |
681 return; | |
682 } | |
683 VLOG(1) << "Received NetworkManagerUpdate."; | |
684 | |
685 for (DictionaryValue::Iterator iter(*properties); !iter.IsAtEnd(); | |
686 iter.Advance()) { | |
687 if (!NetworkManagerStatusChanged(iter.key(), &iter.value())) { | |
688 LOG(ERROR) << "Invalid key-value pair, key: " << iter.key() << " type: " | |
689 << iter.value().GetType(); | |
690 } | |
691 } | |
692 // If there is no Profiles entry, request remembered networks here. | |
693 if (!properties->HasKey(flimflam::kProfilesProperty)) | |
694 RequestRememberedNetworksUpdate(); | |
695 } | |
696 | |
697 //////////////////////////////////////////////////////////////////////////// | |
698 | |
699 void NetworkLibraryImplCros::UpdateTechnologies( | |
700 const ListValue* technologies, int* bitfieldp) { | |
701 DCHECK(bitfieldp); | |
702 if (!technologies) | |
703 return; | |
704 int bitfield = 0; | |
705 for (ListValue::const_iterator iter = technologies->begin(); | |
706 iter != technologies->end(); ++iter) { | |
707 std::string technology; | |
708 (*iter)->GetAsString(&technology); | |
709 if (!technology.empty()) { | |
710 ConnectionType type = | |
711 NativeNetworkParser::ParseConnectionType(technology); | |
712 bitfield |= 1 << type; | |
713 } | |
714 } | |
715 *bitfieldp = bitfield; | |
716 NotifyNetworkManagerChanged(false); // Not forced. | |
717 } | |
718 | |
719 void NetworkLibraryImplCros::UpdateAvailableTechnologies( | |
720 const ListValue* technologies) { | |
721 UpdateTechnologies(technologies, &available_devices_); | |
722 } | |
723 | |
724 void NetworkLibraryImplCros::UpdateEnabledTechnologies( | |
725 const ListValue* technologies) { | |
726 int old_enabled_devices = enabled_devices_; | |
727 UpdateTechnologies(technologies, &enabled_devices_); | |
728 busy_devices_ &= ~(old_enabled_devices ^ enabled_devices_); | |
729 if (!ethernet_enabled()) | |
730 ethernet_ = NULL; | |
731 if (!wifi_enabled()) { | |
732 active_wifi_ = NULL; | |
733 wifi_networks_.clear(); | |
734 } | |
735 if (!cellular_enabled()) { | |
736 active_cellular_ = NULL; | |
737 cellular_networks_.clear(); | |
738 } | |
739 } | |
740 | |
741 //////////////////////////////////////////////////////////////////////////// | |
742 | |
743 // Update all network lists, and request associated service updates. | |
744 void NetworkLibraryImplCros::UpdateNetworkServiceList( | |
745 const ListValue* services) { | |
746 // Copy the list of existing networks to "old" and clear the map and lists. | |
747 NetworkMap old_network_map = network_map_; | |
748 ClearNetworks(); | |
749 // Clear the list of update requests. | |
750 int network_priority_order = 0; | |
751 network_update_requests_.clear(); | |
752 // |services| represents a complete list of visible networks. | |
753 for (ListValue::const_iterator iter = services->begin(); | |
754 iter != services->end(); ++iter) { | |
755 std::string service_path; | |
756 (*iter)->GetAsString(&service_path); | |
757 if (!service_path.empty()) { | |
758 // If we find the network in "old", add it immediately to the map | |
759 // and lists. Otherwise it will get added when NetworkServiceUpdate | |
760 // calls ParseNetwork. | |
761 NetworkMap::iterator found = old_network_map.find(service_path); | |
762 if (found != old_network_map.end()) { | |
763 AddNetwork(found->second); | |
764 old_network_map.erase(found); | |
765 } | |
766 // Always request network updates. | |
767 // TODO(stevenjb): Investigate why we are missing updates then | |
768 // rely on watched network updates and only request updates here for | |
769 // new networks. | |
770 // Use update_request map to store network priority. | |
771 network_update_requests_[service_path] = network_priority_order++; | |
772 VLOG(2) << "UpdateNetworkServiceList, Service: " << service_path; | |
773 CrosRequestNetworkServiceProperties( | |
774 service_path, | |
775 base::Bind(&NetworkLibraryImplCros::NetworkServiceUpdate, | |
776 weak_ptr_factory_.GetWeakPtr())); | |
777 } | |
778 } | |
779 | |
780 // Iterate through list of remaining networks that are no longer in the | |
781 // list and delete them or update their status and re-add them to the list. | |
782 for (NetworkMap::iterator iter = old_network_map.begin(); | |
783 iter != old_network_map.end(); ++iter) { | |
784 Network* network = iter->second; | |
785 VLOG(2) << "Delete Network: " << network->name() | |
786 << " State = " << network->GetStateString() | |
787 << " connecting = " << network->connecting() | |
788 << " connection_started = " << network->connection_started(); | |
789 WifiNetwork* wifi = NULL; | |
790 if (network->type() == TYPE_WIFI) | |
791 wifi = static_cast<WifiNetwork*>(network); | |
792 if (network->failed() && network->notify_failure()) { | |
793 // We have not notified observers of a connection failure yet. | |
794 AddNetwork(network); | |
795 } else if (network->connecting() && network->connection_started() && | |
796 !(wifi && wifi->hidden_ssid())) { | |
797 // Network was in connecting state; set state to failed, but not if it | |
798 // had a hidden SSID (since that won't appear in the scanning list). | |
799 VLOG(2) << "Removed network was connecting: " << network->name(); | |
800 network->SetState(STATE_FAILURE); | |
801 AddNetwork(network); | |
802 } else { | |
803 VLOG(2) << "Deleting removed network: " << network->name() | |
804 << " State = " << network->GetStateString(); | |
805 DeleteNetwork(network); | |
806 } | |
807 } | |
808 // If the last network has disappeared, nothing else will | |
809 // have notified observers, so do it now. | |
810 if (services->empty()) | |
811 NotifyNetworkManagerChanged(true); // Forced update | |
812 } | |
813 | |
814 // Request updates for watched networks. Does not affect network lists. | |
815 // Existing networks will be updated. There should not be any new networks | |
816 // in this list, but if there are they will be added appropriately. | |
817 void NetworkLibraryImplCros::UpdateWatchedNetworkServiceList( | |
818 const ListValue* services) { | |
819 for (ListValue::const_iterator iter = services->begin(); | |
820 iter != services->end(); ++iter) { | |
821 std::string service_path; | |
822 (*iter)->GetAsString(&service_path); | |
823 if (!service_path.empty()) { | |
824 VLOG(1) << "Watched Service: " << service_path; | |
825 CrosRequestNetworkServiceProperties( | |
826 service_path, | |
827 base::Bind(&NetworkLibraryImplCros::NetworkServiceUpdate, | |
828 weak_ptr_factory_.GetWeakPtr())); | |
829 } | |
830 } | |
831 } | |
832 | |
833 void NetworkLibraryImplCros::NetworkServiceUpdate( | |
834 const std::string& service_path, | |
835 const base::DictionaryValue* properties) { | |
836 if (!properties) | |
837 return; // Network no longer in visible list, ignore. | |
838 VLOG(2) << "NetworkServiceUpdate: " << service_path; | |
839 ParseNetwork(service_path, *properties); | |
840 } | |
841 | |
842 // Called from NetworkServiceUpdate and WifiServiceUpdateAndConnect. | |
843 Network* NetworkLibraryImplCros::ParseNetwork( | |
844 const std::string& service_path, const DictionaryValue& info) { | |
845 Network* network = FindNetworkByPath(service_path); | |
846 if (!network) { | |
847 NativeNetworkParser parser; | |
848 network = parser.CreateNetworkFromInfo(service_path, info); | |
849 AddNetwork(network); | |
850 } else { | |
851 // Erase entry from network_unique_id_map_ in case unique id changes. | |
852 if (!network->unique_id().empty()) | |
853 network_unique_id_map_.erase(network->unique_id()); | |
854 if (network->network_parser()) { | |
855 ConnectionState old_state = network->state(); | |
856 network->network_parser()->UpdateNetworkFromInfo(info, network); | |
857 if (old_state != network->state()) { | |
858 VLOG(1) << "ParseNetwork: " << network->name() | |
859 << " State: " << old_state << " -> " << network->state(); | |
860 } | |
861 } | |
862 } | |
863 | |
864 if (!network->unique_id().empty()) | |
865 network_unique_id_map_[network->unique_id()] = network; | |
866 | |
867 SetProfileTypeFromPath(network); | |
868 | |
869 UpdateActiveNetwork(network); | |
870 | |
871 // Copy remembered credentials if required. | |
872 Network* remembered = FindRememberedFromNetwork(network); | |
873 if (remembered) | |
874 network->CopyCredentialsFromRemembered(remembered); | |
875 | |
876 // Find and erase entry in update_requests, and set network priority. | |
877 PriorityMap::iterator found2 = network_update_requests_.find(service_path); | |
878 if (found2 != network_update_requests_.end()) { | |
879 network->priority_order_ = found2->second; | |
880 network_update_requests_.erase(found2); | |
881 } else { | |
882 // TODO(stevenjb): Enable warning once UpdateNetworkServiceList is fixed. | |
883 // LOG(WARNING) << "ParseNetwork called with no update request entry: " | |
884 // << service_path; | |
885 } | |
886 | |
887 VLOG(2) << "ParseNetwork: " << network->name() | |
888 << " path: " << network->service_path() | |
889 << " profile: " << network->profile_path_; | |
890 NotifyNetworkManagerChanged(false); // Not forced. | |
891 return network; | |
892 } | |
893 | |
894 //////////////////////////////////////////////////////////////////////////// | |
895 | |
896 void NetworkLibraryImplCros::UpdateRememberedNetworks( | |
897 const ListValue* profiles) { | |
898 VLOG(1) << "UpdateRememberedNetworks"; | |
899 // Update the list of profiles. | |
900 NetworkProfileList old_profile_list; | |
901 old_profile_list.swap(profile_list_); | |
902 | |
903 for (ListValue::const_iterator iter = profiles->begin(); | |
904 iter != profiles->end(); ++iter) { | |
905 std::string profile_path; | |
906 (*iter)->GetAsString(&profile_path); | |
907 if (profile_path.empty()) { | |
908 LOG(WARNING) << "Bad or empty profile path."; | |
909 continue; | |
910 } | |
911 NetworkProfileType profile_type; | |
912 if (profile_path == kSharedProfilePath) | |
913 profile_type = PROFILE_SHARED; | |
914 else | |
915 profile_type = PROFILE_USER; | |
916 AddProfile(profile_path, profile_type); | |
917 } | |
918 bool lists_equal = old_profile_list.size() == profile_list_.size() && | |
919 std::equal(profile_list_.begin(), profile_list_.end(), | |
920 old_profile_list.begin(), AreProfilePathsEqual); | |
921 | |
922 RequestRememberedNetworksUpdate(); | |
923 if (!lists_equal) | |
924 NotifyNetworkProfileObservers(); | |
925 } | |
926 | |
927 void NetworkLibraryImplCros::RequestRememberedNetworksUpdate() { | |
928 VLOG(1) << "RequestRememberedNetworksUpdate"; | |
929 // Delete all remembered networks. We delete them because | |
930 // RequestNetworkProfileProperties is asynchronous and may invoke | |
931 // UpdateRememberedServiceList multiple times (once per profile). | |
932 // We can do this safely because we do not save any local state for | |
933 // remembered networks. This list updates infrequently. | |
934 DeleteRememberedNetworks(); | |
935 // Request remembered networks from each profile. Later entries will | |
936 // override earlier entries, so default/local entries will override | |
937 // user entries (as desired). | |
938 for (NetworkProfileList::iterator iter = profile_list_.begin(); | |
939 iter != profile_list_.end(); ++iter) { | |
940 NetworkProfile& profile = *iter; | |
941 VLOG(1) << " Requesting Profile: " << profile.path; | |
942 CrosRequestNetworkProfileProperties( | |
943 profile.path, | |
944 base::Bind(&NetworkLibraryImplCros::UpdateProfile, | |
945 weak_ptr_factory_.GetWeakPtr())); | |
946 } | |
947 } | |
948 | |
949 void NetworkLibraryImplCros::UpdateProfile( | |
950 const std::string& profile_path, | |
951 const base::DictionaryValue* properties) { | |
952 if (!properties) { | |
953 LOG(ERROR) << "Error retrieving profile: " << profile_path; | |
954 return; | |
955 } | |
956 VLOG(1) << "UpdateProfile for path: " << profile_path; | |
957 const ListValue* profile_entries(NULL); | |
958 properties->GetList(flimflam::kEntriesProperty, &profile_entries); | |
959 if (!profile_entries) { | |
960 LOG(ERROR) << "'Entries' property is missing."; | |
961 return; | |
962 } | |
963 | |
964 NetworkProfileList::iterator iter1; | |
965 for (iter1 = profile_list_.begin(); iter1 != profile_list_.end(); ++iter1) { | |
966 if (iter1->path == profile_path) | |
967 break; | |
968 } | |
969 if (iter1 == profile_list_.end()) { | |
970 // This can happen if shill gets restarted while Chrome is running. | |
971 LOG(WARNING) << "Profile not in list: " << profile_path; | |
972 return; | |
973 } | |
974 NetworkProfile& profile = *iter1; | |
975 // |profile_entries| is a list of remembered networks from |profile_path|. | |
976 profile.services.clear(); | |
977 for (ListValue::const_iterator iter2 = profile_entries->begin(); | |
978 iter2 != profile_entries->end(); ++iter2) { | |
979 std::string service_path; | |
980 (*iter2)->GetAsString(&service_path); | |
981 if (service_path.empty()) { | |
982 LOG(WARNING) << "Empty service path in profile."; | |
983 continue; | |
984 } | |
985 VLOG(2) << " Remembered service: " << service_path; | |
986 // Add service to profile list. | |
987 profile.services.insert(service_path); | |
988 // Request update for remembered network. | |
989 // Shill does not set the Profile property for remembered networks, but only | |
990 // for the active networks, so we provide |profile_path| to the callback. | |
991 CrosRequestNetworkProfileEntryProperties( | |
992 profile_path, | |
993 service_path, | |
994 base::Bind(&NetworkLibraryImplCros::RememberedNetworkServiceUpdate, | |
995 weak_ptr_factory_.GetWeakPtr(), | |
996 profile_path)); | |
997 } | |
998 } | |
999 | |
1000 void NetworkLibraryImplCros::RememberedNetworkServiceUpdate( | |
1001 const std::string& profile_path, | |
1002 const std::string& service_path, | |
1003 const base::DictionaryValue* properties) { | |
1004 VLOG(2) << "RememberedNetworkServiceUpdate: profile: " << profile_path | |
1005 << " service: " << service_path | |
1006 << (properties == NULL ? " got removed" : " got updated"); | |
1007 if (properties) { | |
1008 ParseRememberedNetwork(profile_path, service_path, *properties); | |
1009 } else { | |
1010 // Remove this service from the respective Profile::services list. | |
1011 for (NetworkProfileList::iterator iter = profile_list_.begin(); | |
1012 iter != profile_list_.end(); ++iter) { | |
1013 NetworkProfile& profile = *iter; | |
1014 if (profile.path != profile_path) | |
1015 continue; | |
1016 | |
1017 if (profile.services.erase(service_path) != 0) { | |
1018 VLOG(1) << "Removed service path: " << service_path | |
1019 << " from Profile::services of: " << profile_path; | |
1020 } | |
1021 break; | |
1022 } | |
1023 } | |
1024 } | |
1025 | |
1026 // Returns NULL if |service_path| refers to a network that is not a | |
1027 // remembered type. Called from RememberedNetworkServiceUpdate. | |
1028 Network* NetworkLibraryImplCros::ParseRememberedNetwork( | |
1029 const std::string& profile_path, | |
1030 const std::string& service_path, | |
1031 const DictionaryValue& info) { | |
1032 Network* remembered; | |
1033 NetworkMap::iterator found = remembered_network_map_.find(service_path); | |
1034 if (found != remembered_network_map_.end()) { | |
1035 remembered = found->second; | |
1036 if (remembered->network_parser()) | |
1037 remembered->network_parser()->UpdateNetworkFromInfo(info, remembered); | |
1038 } else { | |
1039 NativeNetworkParser parser; | |
1040 remembered = parser.CreateNetworkFromInfo(service_path, info); | |
1041 if (remembered->type() == TYPE_WIFI || remembered->type() == TYPE_VPN) { | |
1042 if (!ValidateAndAddRememberedNetwork(remembered)) | |
1043 return NULL; | |
1044 } else { | |
1045 LOG(WARNING) << "Ignoring remembered network: " << service_path | |
1046 << " Type: " << ConnectionTypeToString(remembered->type()); | |
1047 delete remembered; | |
1048 return NULL; | |
1049 } | |
1050 } | |
1051 | |
1052 remembered->set_profile_path(profile_path); | |
1053 SetProfileTypeFromPath(remembered); | |
1054 | |
1055 VLOG(2) << "ParseRememberedNetwork: " << remembered->name() | |
1056 << " path: " << remembered->service_path() | |
1057 << " profile: " << remembered->profile_path_; | |
1058 NotifyNetworkManagerChanged(false); // Not forced. | |
1059 | |
1060 if (remembered->type() == TYPE_VPN) { | |
1061 // VPNs are only stored in profiles. If we don't have a network for it, | |
1062 // request one. | |
1063 if (!FindNetworkByUniqueId(remembered->unique_id())) { | |
1064 VirtualNetwork* vpn = static_cast<VirtualNetwork*>(remembered); | |
1065 std::string provider_type = ProviderTypeToString(vpn->provider_type()); | |
1066 VLOG(2) << "Requesting VPN: " << vpn->name() | |
1067 << " Server: " << vpn->server_hostname() | |
1068 << " Type: " << provider_type; | |
1069 CrosRequestVirtualNetworkProperties( | |
1070 vpn->name(), | |
1071 vpn->server_hostname(), | |
1072 provider_type, | |
1073 base::Bind(&NetworkLibraryImplCros::NetworkServiceUpdate, | |
1074 weak_ptr_factory_.GetWeakPtr())); | |
1075 } | |
1076 } | |
1077 | |
1078 return remembered; | |
1079 } | |
1080 | |
1081 //////////////////////////////////////////////////////////////////////////// | |
1082 // NetworkDevice list management functions. | |
1083 | |
1084 // Update device list, and request associated device updates. | |
1085 // |devices| represents a complete list of devices. | |
1086 void NetworkLibraryImplCros::UpdateNetworkDeviceList(const ListValue* devices) { | |
1087 NetworkDeviceMap old_device_map = device_map_; | |
1088 device_map_.clear(); | |
1089 VLOG(2) << "Updating Device List."; | |
1090 for (ListValue::const_iterator iter = devices->begin(); | |
1091 iter != devices->end(); ++iter) { | |
1092 std::string device_path; | |
1093 (*iter)->GetAsString(&device_path); | |
1094 if (!device_path.empty()) { | |
1095 NetworkDeviceMap::iterator found = old_device_map.find(device_path); | |
1096 if (found != old_device_map.end()) { | |
1097 VLOG(2) << " Adding existing device: " << device_path; | |
1098 CHECK(found->second) << "Attempted to add NULL device pointer"; | |
1099 device_map_[device_path] = found->second; | |
1100 old_device_map.erase(found); | |
1101 } | |
1102 CrosRequestNetworkDeviceProperties( | |
1103 device_path, | |
1104 base::Bind(&NetworkLibraryImplCros::NetworkDeviceUpdate, | |
1105 weak_ptr_factory_.GetWeakPtr())); | |
1106 } | |
1107 } | |
1108 // Delete any old devices that no longer exist. | |
1109 for (NetworkDeviceMap::iterator iter = old_device_map.begin(); | |
1110 iter != old_device_map.end(); ++iter) { | |
1111 DeleteDeviceFromDeviceObserversMap(iter->first); | |
1112 // Delete device. | |
1113 delete iter->second; | |
1114 } | |
1115 } | |
1116 | |
1117 void NetworkLibraryImplCros::NetworkDeviceUpdate( | |
1118 const std::string& device_path, | |
1119 const base::DictionaryValue* properties) { | |
1120 if (!properties) { | |
1121 // device no longer exists. | |
1122 DeleteDevice(device_path); | |
1123 } else { | |
1124 ParseNetworkDevice(device_path, *properties); | |
1125 } | |
1126 } | |
1127 | |
1128 void NetworkLibraryImplCros::ParseNetworkDevice(const std::string& device_path, | |
1129 const DictionaryValue& info) { | |
1130 NetworkDeviceMap::iterator found = device_map_.find(device_path); | |
1131 NetworkDevice* device; | |
1132 if (found != device_map_.end()) { | |
1133 device = found->second; | |
1134 device->device_parser()->UpdateDeviceFromInfo(info, device); | |
1135 } else { | |
1136 NativeNetworkDeviceParser parser; | |
1137 device = parser.CreateDeviceFromInfo(device_path, info); | |
1138 VLOG(2) << " Adding device: " << device_path; | |
1139 if (device) { | |
1140 device_map_[device_path] = device; | |
1141 } | |
1142 CHECK(device) << "Attempted to add NULL device for path: " << device_path; | |
1143 } | |
1144 VLOG(2) << "ParseNetworkDevice:" << device->name(); | |
1145 | |
1146 // Re-synchronize the roaming setting with the device property if required. | |
1147 if (device && device->type() == TYPE_CELLULAR) | |
1148 UpdateCellularDeviceStatus(device, PROPERTY_INDEX_CELLULAR_ALLOW_ROAMING); | |
1149 | |
1150 if (device && device->type() == TYPE_WIFI) | |
1151 wifi_scanning_ = device->scanning(); | |
1152 | |
1153 NotifyNetworkManagerChanged(false); // Not forced. | |
1154 AddNetworkDeviceObserver(device_path, network_device_observer_.get()); | |
1155 } | |
1156 | |
1157 void NetworkLibraryImplCros::SetIPParametersCallback( | |
1158 const IPParameterInfo& info, | |
1159 const std::string& service_path, | |
1160 const base::DictionaryValue* properties) { | |
1161 // crbug.com/146616 will fix this once we have better | |
1162 // handling of shill errors. | |
1163 if (!properties) | |
1164 return; | |
1165 | |
1166 Network* network = FindNetworkByPath(service_path); | |
1167 if (!network) | |
1168 return; | |
1169 | |
1170 // Find the properties we're going to set, and minimize the DBus calls below | |
1171 // by not clearing if it's already cleared, and not setting if it's already | |
1172 // set to the same value. Also, don't reconnect at the end if nothing changed. | |
1173 bool something_changed = false; | |
1174 std::string current_address; | |
1175 int32 current_prefixlen = -1; | |
1176 std::string current_gateway; | |
1177 std::string current_name_servers; | |
1178 bool address_exists = properties->GetStringWithoutPathExpansion( | |
1179 shill::kStaticIPAddressProperty, | |
1180 ¤t_address); | |
1181 VLOG_IF(2, address_exists) << shill::kStaticIPAddressProperty | |
1182 << "=" << current_address; | |
1183 bool prefixlen_exists = properties->GetIntegerWithoutPathExpansion( | |
1184 shill::kStaticIPPrefixlenProperty, | |
1185 ¤t_prefixlen); | |
1186 VLOG_IF(2, prefixlen_exists) << shill::kStaticIPPrefixlenProperty | |
1187 << "=" << current_prefixlen; | |
1188 bool gateway_exists = properties->GetStringWithoutPathExpansion( | |
1189 shill::kStaticIPGatewayProperty, | |
1190 ¤t_gateway); | |
1191 VLOG_IF(2, gateway_exists) << shill::kStaticIPGatewayProperty | |
1192 << "=" << current_gateway; | |
1193 bool name_servers_exist = properties->GetStringWithoutPathExpansion( | |
1194 shill::kStaticIPNameServersProperty, | |
1195 ¤t_name_servers); | |
1196 VLOG_IF(2, name_servers_exist) << shill::kStaticIPNameServersProperty | |
1197 << "=" << current_name_servers; | |
1198 | |
1199 if (info.dhcp_usage_mask & USE_DHCP_ADDRESS) { | |
1200 if (address_exists) { | |
1201 something_changed = true; | |
1202 CrosClearNetworkServiceProperty(service_path, | |
1203 shill::kStaticIPAddressProperty); | |
1204 VLOG(2) << "Clearing " << shill::kStaticIPAddressProperty; | |
1205 } | |
1206 } else if (current_address != info.address) { | |
1207 base::StringValue value(info.address); | |
1208 VLOG(2) << "Setting " << shill::kStaticIPAddressProperty | |
1209 << " to " << info.address; | |
1210 something_changed = true; | |
1211 CrosSetNetworkServiceProperty(service_path, | |
1212 shill::kStaticIPAddressProperty, | |
1213 value); | |
1214 } | |
1215 | |
1216 if (info.dhcp_usage_mask & USE_DHCP_NETMASK) { | |
1217 if (prefixlen_exists) { | |
1218 something_changed = true; | |
1219 CrosClearNetworkServiceProperty(service_path, | |
1220 shill::kStaticIPPrefixlenProperty); | |
1221 VLOG(2) << "Clearing " << shill::kStaticIPPrefixlenProperty; | |
1222 } | |
1223 } else { | |
1224 int prefixlen = network_util::NetmaskToPrefixLength(info.netmask); | |
1225 if (prefixlen == -1) { | |
1226 VLOG(1) << "IPConfig prefix length is invalid for netmask " | |
1227 << info.netmask; | |
1228 } else if (current_prefixlen != prefixlen) { | |
1229 base::FundamentalValue value(prefixlen); | |
1230 VLOG(2) << "Setting " << shill::kStaticIPPrefixlenProperty | |
1231 << " to " << prefixlen; | |
1232 something_changed = true; | |
1233 CrosSetNetworkServiceProperty(service_path, | |
1234 shill::kStaticIPPrefixlenProperty, | |
1235 value); | |
1236 } | |
1237 } | |
1238 | |
1239 if (info.dhcp_usage_mask & USE_DHCP_GATEWAY) { | |
1240 if (gateway_exists) { | |
1241 something_changed = true; | |
1242 CrosClearNetworkServiceProperty(service_path, | |
1243 shill::kStaticIPGatewayProperty); | |
1244 VLOG(2) << "Clearing " << shill::kStaticIPGatewayProperty; | |
1245 } | |
1246 } else if (current_gateway != info.gateway){ | |
1247 base::StringValue value(info.gateway); | |
1248 VLOG(2) << "Setting " << shill::kStaticIPGatewayProperty | |
1249 << " to " << info.gateway; | |
1250 something_changed = true; | |
1251 CrosSetNetworkServiceProperty(service_path, | |
1252 shill::kStaticIPGatewayProperty, | |
1253 value); | |
1254 } | |
1255 | |
1256 if (info.dhcp_usage_mask & USE_DHCP_NAME_SERVERS) { | |
1257 if (name_servers_exist) { | |
1258 something_changed = true; | |
1259 CrosClearNetworkServiceProperty(service_path, | |
1260 shill::kStaticIPNameServersProperty); | |
1261 VLOG(2) << "Clearing " << shill::kStaticIPNameServersProperty; | |
1262 | |
1263 // Notify that the network changed, so that the DNS cache can be | |
1264 // cleared properly. | |
1265 NotifyNetworkChanged(network); | |
1266 } | |
1267 } else if (current_name_servers != info.name_servers){ | |
1268 base::StringValue value(info.name_servers); | |
1269 VLOG(2) << "Setting " << shill::kStaticIPNameServersProperty | |
1270 << " to " << info.name_servers; | |
1271 something_changed = true; | |
1272 CrosSetNetworkServiceProperty(service_path, | |
1273 shill::kStaticIPNameServersProperty, | |
1274 value); | |
1275 | |
1276 // Notify that the network changed, so that the DNS cache can be | |
1277 // cleared properly. | |
1278 NotifyNetworkChanged(network); | |
1279 } | |
1280 | |
1281 if (!something_changed) | |
1282 return; | |
1283 | |
1284 // Ensure NetworkStateHandler properties are up-to-date. | |
1285 if (NetworkHandler::IsInitialized()) { | |
1286 NetworkHandler::Get()->network_state_handler()->RequestUpdateForNetwork( | |
1287 service_path); | |
1288 } | |
1289 | |
1290 // Attempt to refresh its IP parameters, so that the changes to the service | |
1291 // properties can take effect. | |
1292 if (network->connecting_or_connected()) | |
1293 RefreshIPConfig(network); | |
1294 } | |
1295 | |
1296 // static | |
1297 bool NetworkLibraryImplCros::AreProfilePathsEqual(const NetworkProfile& a, | |
1298 const NetworkProfile& b) { | |
1299 return a.path == b.path; | |
1300 } | |
1301 | |
1302 } // namespace chromeos | |
OLD | NEW |