OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/network/network_state_handler.h" | 5 #include "chromeos/network/network_state_handler.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/format_macros.h" | 11 #include "base/format_macros.h" |
12 #include "base/guid.h" | 12 #include "base/guid.h" |
13 #include "base/json/json_string_value_serializer.h" | 13 #include "base/json/json_string_value_serializer.h" |
14 #include "base/json/json_writer.h" | 14 #include "base/json/json_writer.h" |
15 #include "base/location.h" | 15 #include "base/location.h" |
16 #include "base/logging.h" | |
17 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
18 #include "base/metrics/histogram_macros.h" | 17 #include "base/metrics/histogram_macros.h" |
19 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
20 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
21 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
22 #include "base/values.h" | 21 #include "base/values.h" |
23 #include "chromeos/chromeos_switches.h" | 22 #include "chromeos/chromeos_switches.h" |
24 #include "chromeos/network/device_state.h" | 23 #include "chromeos/network/device_state.h" |
25 #include "chromeos/network/network_event_log.h" | 24 #include "chromeos/network/network_event_log.h" |
26 #include "chromeos/network/network_state.h" | 25 #include "chromeos/network/network_state.h" |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 } | 215 } |
217 | 216 |
218 const NetworkState* NetworkStateHandler::DefaultNetwork() const { | 217 const NetworkState* NetworkStateHandler::DefaultNetwork() const { |
219 if (default_network_path_.empty()) | 218 if (default_network_path_.empty()) |
220 return nullptr; | 219 return nullptr; |
221 return GetNetworkState(default_network_path_); | 220 return GetNetworkState(default_network_path_); |
222 } | 221 } |
223 | 222 |
224 const NetworkState* NetworkStateHandler::ConnectedNetworkByType( | 223 const NetworkState* NetworkStateHandler::ConnectedNetworkByType( |
225 const NetworkTypePattern& type) const { | 224 const NetworkTypePattern& type) const { |
| 225 const NetworkState* connected_network = nullptr; |
| 226 |
226 // Active networks are always listed first by Shill so no need to sort. | 227 // Active networks are always listed first by Shill so no need to sort. |
227 for (auto iter = network_list_.begin(); iter != network_list_.end(); ++iter) { | 228 for (auto iter = network_list_.begin(); iter != network_list_.end(); ++iter) { |
228 const NetworkState* network = (*iter)->AsNetworkState(); | 229 const NetworkState* network = (*iter)->AsNetworkState(); |
229 DCHECK(network); | 230 DCHECK(network); |
230 if (!network->update_received()) | 231 if (!network->update_received()) |
231 continue; | 232 continue; |
232 if (!network->IsConnectedState()) | 233 if (!network->IsConnectedState()) |
233 break; // Connected networks are listed first. | 234 break; // Connected networks are listed first. |
234 if (network->Matches(type)) | 235 if (network->Matches(type)) { |
235 return network; | 236 connected_network = network; |
| 237 break; |
| 238 } |
236 } | 239 } |
237 return nullptr; | 240 |
| 241 // Ethernet networks are prioritized over Tether networks. |
| 242 if (connected_network && connected_network->type() == shill::kTypeEthernet) { |
| 243 return connected_network; |
| 244 } |
| 245 |
| 246 // Tether networks are prioritized over non-Ethernet networks. |
| 247 if (type.MatchesPattern(NetworkTypePattern::Tether())) { |
| 248 for (auto iter = tether_network_list_.begin(); |
| 249 iter != tether_network_list_.end(); ++iter) { |
| 250 const NetworkState* network = (*iter)->AsNetworkState(); |
| 251 DCHECK(network); |
| 252 if (network->IsConnectedState()) |
| 253 return network; |
| 254 } |
| 255 } |
| 256 |
| 257 return connected_network; |
238 } | 258 } |
239 | 259 |
240 const NetworkState* NetworkStateHandler::ConnectingNetworkByType( | 260 const NetworkState* NetworkStateHandler::ConnectingNetworkByType( |
241 const NetworkTypePattern& type) const { | 261 const NetworkTypePattern& type) const { |
| 262 const NetworkState* connecting_network = nullptr; |
| 263 |
242 // Active networks are always listed first by Shill so no need to sort. | 264 // Active networks are always listed first by Shill so no need to sort. |
243 for (auto iter = network_list_.begin(); iter != network_list_.end(); ++iter) { | 265 for (auto iter = network_list_.begin(); iter != network_list_.end(); ++iter) { |
244 const NetworkState* network = (*iter)->AsNetworkState(); | 266 const NetworkState* network = (*iter)->AsNetworkState(); |
245 DCHECK(network); | 267 DCHECK(network); |
246 if (!network->update_received() || network->IsConnectedState()) | 268 if (!network->update_received() || network->IsConnectedState()) |
247 continue; | 269 continue; |
248 if (!network->IsConnectingState()) | 270 if (!network->IsConnectingState()) |
249 break; // Connected and connecting networks are listed first. | 271 break; // Connected and connecting networks are listed first. |
250 if (network->Matches(type)) | 272 if (network->Matches(type)) { |
251 return network; | 273 connecting_network = network; |
| 274 break; |
| 275 } |
252 } | 276 } |
253 return nullptr; | 277 |
| 278 // Ethernet networks are prioritized over Tether networks. |
| 279 if (connecting_network && |
| 280 connecting_network->type() == shill::kTypeEthernet) { |
| 281 return connecting_network; |
| 282 } |
| 283 |
| 284 // Tether networks are prioritized over non-Ethernet networks. |
| 285 if (type.MatchesPattern(NetworkTypePattern::Tether())) { |
| 286 for (auto iter = tether_network_list_.begin(); |
| 287 iter != tether_network_list_.end(); ++iter) { |
| 288 const NetworkState* network = (*iter)->AsNetworkState(); |
| 289 DCHECK(network); |
| 290 if (network->IsConnectingState()) |
| 291 return network; |
| 292 } |
| 293 } |
| 294 |
| 295 return connecting_network; |
254 } | 296 } |
255 | 297 |
256 const NetworkState* NetworkStateHandler::FirstNetworkByType( | 298 const NetworkState* NetworkStateHandler::FirstNetworkByType( |
257 const NetworkTypePattern& type) { | 299 const NetworkTypePattern& type) { |
258 if (!network_list_sorted_) | 300 if (!network_list_sorted_) |
259 SortNetworkList(); // Sort to ensure visible networks are listed first. | 301 SortNetworkList(); // Sort to ensure visible networks are listed first. |
| 302 |
| 303 // If |type| matches tether networks and at least one tether network is |
| 304 // present, return the first network (since it has been sorted already). |
| 305 if (type.MatchesPattern(NetworkTypePattern::Tether()) && |
| 306 !tether_network_list_.empty()) { |
| 307 return tether_network_list_[0]->AsNetworkState(); |
| 308 } |
| 309 |
260 for (auto iter = network_list_.begin(); iter != network_list_.end(); ++iter) { | 310 for (auto iter = network_list_.begin(); iter != network_list_.end(); ++iter) { |
261 const NetworkState* network = (*iter)->AsNetworkState(); | 311 const NetworkState* network = (*iter)->AsNetworkState(); |
262 DCHECK(network); | 312 DCHECK(network); |
263 if (!network->update_received()) | 313 if (!network->update_received()) |
264 continue; | 314 continue; |
265 if (!network->visible()) | 315 if (!network->visible()) |
266 break; | 316 break; |
267 if (network->Matches(type)) | 317 if (network->Matches(type)) |
268 return network; | 318 return network; |
269 } | 319 } |
(...skipping 21 matching lines...) Expand all Loading... |
291 GetVisibleNetworkListByType(NetworkTypePattern::Default(), list); | 341 GetVisibleNetworkListByType(NetworkTypePattern::Default(), list); |
292 } | 342 } |
293 | 343 |
294 void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type, | 344 void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type, |
295 bool configured_only, | 345 bool configured_only, |
296 bool visible_only, | 346 bool visible_only, |
297 int limit, | 347 int limit, |
298 NetworkStateList* list) { | 348 NetworkStateList* list) { |
299 DCHECK(list); | 349 DCHECK(list); |
300 list->clear(); | 350 list->clear(); |
301 int count = 0; | 351 |
302 // Sort the network list if necessary. | 352 // Sort the network list if necessary. |
303 if (!network_list_sorted_) | 353 if (!network_list_sorted_) |
304 SortNetworkList(); | 354 SortNetworkList(); |
| 355 |
| 356 if (type.MatchesPattern(NetworkTypePattern::Tether())) { |
| 357 GetTetherNetworkList(limit, list); |
| 358 } |
| 359 |
| 360 int count = list->size(); |
| 361 |
| 362 if (type.Equals(NetworkTypePattern::Tether()) || |
| 363 (limit != 0 && count >= limit)) { |
| 364 // If only searching for tether networks, there is no need to continue |
| 365 // searching through other network types; likewise, if the limit has already |
| 366 // been reached, there is no need to continue searching. |
| 367 return; |
| 368 } |
| 369 |
305 for (auto iter = network_list_.begin(); iter != network_list_.end(); ++iter) { | 370 for (auto iter = network_list_.begin(); iter != network_list_.end(); ++iter) { |
306 const NetworkState* network = (*iter)->AsNetworkState(); | 371 const NetworkState* network = (*iter)->AsNetworkState(); |
307 DCHECK(network); | 372 DCHECK(network); |
308 if (!network->update_received() || !network->Matches(type)) | 373 if (!network->update_received() || !network->Matches(type)) |
309 continue; | 374 continue; |
310 if (configured_only && !network->IsInProfile()) | 375 if (configured_only && !network->IsInProfile()) |
311 continue; | 376 continue; |
312 if (visible_only && !network->visible()) | 377 if (visible_only && !network->visible()) |
313 continue; | 378 continue; |
314 list->push_back(network); | 379 if (network->type() == shill::kTypeEthernet) { |
| 380 // Ethernet networks should always be in front. |
| 381 list->insert(list->begin(), network); |
| 382 } else { |
| 383 list->push_back(network); |
| 384 } |
315 if (limit > 0 && ++count >= limit) | 385 if (limit > 0 && ++count >= limit) |
316 break; | 386 break; |
317 } | 387 } |
318 } | 388 } |
319 | 389 |
320 void NetworkStateHandler::GetTetherNetworkList(int limit, | 390 void NetworkStateHandler::GetTetherNetworkList(int limit, |
321 NetworkStateList* list) { | 391 NetworkStateList* list) { |
322 DCHECK(list); | 392 DCHECK(list); |
323 list->clear(); | 393 list->clear(); |
324 int count = 0; | 394 int count = 0; |
(...skipping 22 matching lines...) Expand all Loading... |
347 return network; | 417 return network; |
348 } | 418 } |
349 | 419 |
350 const NetworkState* NetworkStateHandler::GetNetworkStateFromGuid( | 420 const NetworkState* NetworkStateHandler::GetNetworkStateFromGuid( |
351 const std::string& guid) const { | 421 const std::string& guid) const { |
352 DCHECK(!guid.empty()); | 422 DCHECK(!guid.empty()); |
353 return GetModifiableNetworkStateFromGuid(guid); | 423 return GetModifiableNetworkStateFromGuid(guid); |
354 } | 424 } |
355 | 425 |
356 void NetworkStateHandler::AddTetherNetworkState(const std::string& guid, | 426 void NetworkStateHandler::AddTetherNetworkState(const std::string& guid, |
357 const std::string& name) { | 427 const std::string& name, |
| 428 const std::string& carrier, |
| 429 int battery_percentage, |
| 430 int signal_strength) { |
358 DCHECK(!guid.empty()); | 431 DCHECK(!guid.empty()); |
| 432 DCHECK(battery_percentage >= 0 && battery_percentage <= 100); |
| 433 DCHECK(signal_strength >= 0 && signal_strength <= 100); |
359 | 434 |
360 // If the network already exists, do nothing. | 435 // If the network already exists, do nothing. |
361 if (GetNetworkStateFromGuid(guid)) { | 436 if (GetNetworkStateFromGuid(guid)) { |
362 NET_LOG(ERROR) << "AddTetherNetworkState: " << name | 437 NET_LOG(ERROR) << "AddTetherNetworkState: " << name |
363 << " called with existing guid:" << guid; | 438 << " called with existing guid:" << guid; |
364 return; | 439 return; |
365 } | 440 } |
366 | 441 |
| 442 // Use the GUID as the network's service path. |
367 std::unique_ptr<NetworkState> tether_network_state = | 443 std::unique_ptr<NetworkState> tether_network_state = |
368 base::MakeUnique<NetworkState>(guid); | 444 base::MakeUnique<NetworkState>(guid /* path */); |
369 | 445 |
370 tether_network_state->set_name(name); | 446 tether_network_state->set_name(name); |
371 tether_network_state->set_type(kTypeTether); | 447 tether_network_state->set_type(kTypeTether); |
372 tether_network_state->SetGuid(guid); | 448 tether_network_state->SetGuid(guid); |
373 tether_network_state->set_visible(true); | 449 tether_network_state->set_visible(true); |
374 tether_network_state->set_update_received(); | 450 tether_network_state->set_update_received(); |
| 451 tether_network_state->set_update_requested(false); |
| 452 tether_network_state->set_connectable(true); |
| 453 tether_network_state->set_carrier(carrier); |
| 454 tether_network_state->set_battery_percentage(battery_percentage); |
| 455 tether_network_state->set_signal_strength(signal_strength); |
375 | 456 |
376 tether_network_list_.push_back(std::move(tether_network_state)); | 457 tether_network_list_.push_back(std::move(tether_network_state)); |
377 NotifyNetworkListChanged(); | 458 NotifyNetworkListChanged(); |
378 } | 459 } |
379 | 460 |
| 461 bool NetworkStateHandler::UpdateTetherNetworkProperties( |
| 462 const std::string& guid, |
| 463 const std::string& carrier, |
| 464 int battery_percentage, |
| 465 int signal_strength) { |
| 466 NetworkState* tether_network_state = GetModifiableNetworkStateFromGuid(guid); |
| 467 if (!tether_network_state) |
| 468 return false; |
| 469 |
| 470 tether_network_state->set_carrier(carrier); |
| 471 tether_network_state->set_battery_percentage(battery_percentage); |
| 472 tether_network_state->set_signal_strength(signal_strength); |
| 473 |
| 474 NotifyNetworkListChanged(); |
| 475 return true; |
| 476 } |
| 477 |
380 void NetworkStateHandler::RemoveTetherNetworkState(const std::string& guid) { | 478 void NetworkStateHandler::RemoveTetherNetworkState(const std::string& guid) { |
381 for (auto iter = tether_network_list_.begin(); | 479 for (auto iter = tether_network_list_.begin(); |
382 iter != tether_network_list_.end(); ++iter) { | 480 iter != tether_network_list_.end(); ++iter) { |
383 if (iter->get()->AsNetworkState()->guid() == guid) { | 481 if (iter->get()->AsNetworkState()->guid() == guid) { |
384 NetworkState* wifi_network = GetModifiableNetworkStateFromGuid( | 482 NetworkState* wifi_network = GetModifiableNetworkStateFromGuid( |
385 iter->get()->AsNetworkState()->tether_guid()); | 483 iter->get()->AsNetworkState()->tether_guid()); |
386 if (wifi_network) | 484 if (wifi_network) |
387 wifi_network->set_tether_guid(std::string()); | 485 wifi_network->set_tether_guid(std::string()); |
388 | 486 |
389 tether_network_list_.erase(iter); | 487 tether_network_list_.erase(iter); |
(...skipping 30 matching lines...) Expand all Loading... |
420 } | 518 } |
421 | 519 |
422 tether_network->set_tether_guid(wifi_network_guid); | 520 tether_network->set_tether_guid(wifi_network_guid); |
423 wifi_network->set_tether_guid(tether_network_guid); | 521 wifi_network->set_tether_guid(tether_network_guid); |
424 NotifyNetworkListChanged(); | 522 NotifyNetworkListChanged(); |
425 return true; | 523 return true; |
426 } | 524 } |
427 | 525 |
428 void NetworkStateHandler::SetTetherNetworkStateDisconnected( | 526 void NetworkStateHandler::SetTetherNetworkStateDisconnected( |
429 const std::string& guid) { | 527 const std::string& guid) { |
| 528 // TODO(khorimoto): Remove the tether network as the default network, and |
| 529 // send a connection status change. |
430 SetTetherNetworkStateConnectionState(guid, shill::kStateDisconnect); | 530 SetTetherNetworkStateConnectionState(guid, shill::kStateDisconnect); |
431 } | 531 } |
432 | 532 |
433 void NetworkStateHandler::SetTetherNetworkStateConnecting( | 533 void NetworkStateHandler::SetTetherNetworkStateConnecting( |
434 const std::string& guid) { | 534 const std::string& guid) { |
| 535 // TODO(khorimoto): Set the tether network as the default network, and send |
| 536 // a connection status change. |
435 SetTetherNetworkStateConnectionState(guid, shill::kStateConfiguration); | 537 SetTetherNetworkStateConnectionState(guid, shill::kStateConfiguration); |
436 } | 538 } |
437 | 539 |
438 void NetworkStateHandler::SetTetherNetworkStateConnected( | 540 void NetworkStateHandler::SetTetherNetworkStateConnected( |
439 const std::string& guid) { | 541 const std::string& guid) { |
| 542 // Being connected implies that AssociateTetherNetworkStateWithWifiNetwork() |
| 543 // was already called, so ensure that the association is still intact. |
| 544 DCHECK(GetNetworkStateFromGuid(GetNetworkStateFromGuid(guid)->tether_guid()) |
| 545 ->tether_guid() == guid); |
| 546 |
| 547 // TODO(khorimoto): Send a connection status change. |
440 SetTetherNetworkStateConnectionState(guid, shill::kStateOnline); | 548 SetTetherNetworkStateConnectionState(guid, shill::kStateOnline); |
441 } | 549 } |
442 | 550 |
443 void NetworkStateHandler::SetTetherNetworkStateConnectionState( | 551 void NetworkStateHandler::SetTetherNetworkStateConnectionState( |
444 const std::string& guid, | 552 const std::string& guid, |
445 const std::string& connection_state) { | 553 const std::string& connection_state) { |
446 NetworkState* tether_network = GetModifiableNetworkStateFromGuid(guid); | 554 NetworkState* tether_network = GetModifiableNetworkStateFromGuid(guid); |
447 if (!tether_network) { | 555 if (!tether_network) { |
448 NET_LOG(ERROR) << "SetTetherNetworkStateConnectionState: Tether network " | 556 NET_LOG(ERROR) << "SetTetherNetworkStateConnectionState: Tether network " |
449 << "not found: " << guid; | 557 << "not found: " << guid; |
450 return; | 558 return; |
451 } | 559 } |
452 | 560 |
453 if (!NetworkTypePattern::Tether().MatchesType(tether_network->type())) { | 561 DCHECK(NetworkTypePattern::Tether().MatchesType(tether_network->type())); |
454 NET_LOG(ERROR) << "SetTetherNetworkStateConnectionState: network " | |
455 << "is not a Tether network: " << guid; | |
456 return; | |
457 } | |
458 | 562 |
459 tether_network->set_connection_state(connection_state); | 563 tether_network->set_connection_state(connection_state); |
460 NotifyNetworkListChanged(); | 564 NotifyNetworkListChanged(); |
461 } | 565 } |
462 | 566 |
463 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const { | 567 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const { |
464 GetDeviceListByType(NetworkTypePattern::Default(), list); | 568 GetDeviceListByType(NetworkTypePattern::Default(), list); |
465 } | 569 } |
466 | 570 |
467 void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type, | 571 void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type, |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 service_path.c_str())); | 672 service_path.c_str())); |
569 return nullptr; | 673 return nullptr; |
570 } | 674 } |
571 return list.front(); | 675 return list.front(); |
572 } | 676 } |
573 | 677 |
574 void NetworkStateHandler::SetLastErrorForTest(const std::string& service_path, | 678 void NetworkStateHandler::SetLastErrorForTest(const std::string& service_path, |
575 const std::string& error) { | 679 const std::string& error) { |
576 NetworkState* network_state = GetModifiableNetworkState(service_path); | 680 NetworkState* network_state = GetModifiableNetworkState(service_path); |
577 if (!network_state) { | 681 if (!network_state) { |
578 LOG(ERROR) << "No matching NetworkState for: " << service_path; | 682 NET_LOG(ERROR) << "No matching NetworkState for: " << service_path; |
579 return; | 683 return; |
580 } | 684 } |
581 network_state->last_error_ = error; | 685 network_state->last_error_ = error; |
582 } | 686 } |
583 | 687 |
584 //------------------------------------------------------------------------------ | 688 //------------------------------------------------------------------------------ |
585 // ShillPropertyHandler::Delegate overrides | 689 // ShillPropertyHandler::Delegate overrides |
586 | 690 |
587 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type, | 691 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type, |
588 const base::ListValue& entries) { | 692 const base::ListValue& entries) { |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 devices += ", "; | 964 devices += ", "; |
861 devices += (*iter)->name(); | 965 devices += (*iter)->name(); |
862 } | 966 } |
863 NET_LOG_EVENT("DeviceList", devices); | 967 NET_LOG_EVENT("DeviceList", devices); |
864 NotifyDeviceListChanged(); | 968 NotifyDeviceListChanged(); |
865 } else { | 969 } else { |
866 NOTREACHED(); | 970 NOTREACHED(); |
867 } | 971 } |
868 } | 972 } |
869 | 973 |
| 974 // TODO(khorimoto): Add sorting for the tether network list as well. |
870 void NetworkStateHandler::SortNetworkList() { | 975 void NetworkStateHandler::SortNetworkList() { |
871 // Note: usually active networks will precede inactive networks, however | 976 // Note: usually active networks will precede inactive networks, however |
872 // this may briefly be untrue during state transitions (e.g. a network may | 977 // this may briefly be untrue during state transitions (e.g. a network may |
873 // transition to idle before the list is updated). | 978 // transition to idle before the list is updated). |
874 ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks; | 979 ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks; |
875 for (ManagedStateList::iterator iter = network_list_.begin(); | 980 for (ManagedStateList::iterator iter = network_list_.begin(); |
876 iter != network_list_.end(); ++iter) { | 981 iter != network_list_.end(); ++iter) { |
877 NetworkState* network = (*iter)->AsNetworkState(); | 982 NetworkState* network = (*iter)->AsNetworkState(); |
878 if (!network->update_received()) { | 983 if (!network->update_received()) { |
879 new_networks.push_back(std::move(*iter)); | 984 new_networks.push_back(std::move(*iter)); |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1169 if (type.MatchesType(shill::kTypeBluetooth)) | 1274 if (type.MatchesType(shill::kTypeBluetooth)) |
1170 technologies.emplace_back(shill::kTypeBluetooth); | 1275 technologies.emplace_back(shill::kTypeBluetooth); |
1171 if (type.MatchesType(shill::kTypeVPN)) | 1276 if (type.MatchesType(shill::kTypeVPN)) |
1172 technologies.emplace_back(shill::kTypeVPN); | 1277 technologies.emplace_back(shill::kTypeVPN); |
1173 | 1278 |
1174 CHECK_GT(technologies.size(), 0ul); | 1279 CHECK_GT(technologies.size(), 0ul); |
1175 return technologies; | 1280 return technologies; |
1176 } | 1281 } |
1177 | 1282 |
1178 } // namespace chromeos | 1283 } // namespace chromeos |
OLD | NEW |