network_state_handler.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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 "chromeos/network/network_state_handler.h"
6
7#include "base/bind.h"
8#include "base/format_macros.h"
9#include "base/location.h"
10#include "base/stl_util.h"
11#include "base/strings/string_util.h"
12#include "base/strings/stringprintf.h"
13#include "base/values.h"
14#include "chromeos/network/device_state.h"
15#include "chromeos/network/managed_state.h"
16#include "chromeos/network/network_event_log.h"
17#include "chromeos/network/network_state.h"
18#include "chromeos/network/network_state_handler_observer.h"
19#include "chromeos/network/shill_property_handler.h"
20#include "third_party/cros_system_api/dbus/service_constants.h"
21
22namespace {
23
24// Returns true if |network->type()| == |match_type|, or it matches one of the
25// following special match types:
26// * kMatchTypeDefault matches any network (i.e. the first instance)
27// * kMatchTypeNonVirtual matches non virtual networks
28// * kMatchTypeWireless matches wireless networks
29// * kMatchTypeMobile matches cellular or wimax networks
30bool ManagedStateMatchesType(const chromeos::ManagedState* managed,
31                             const std::string& match_type) {
32  const std::string& type = managed->type();
33  if (match_type == chromeos::NetworkStateHandler::kMatchTypeDefault)
34    return true;
35  if (match_type == type)
36    return true;
37  if (match_type == chromeos::NetworkStateHandler::kMatchTypeNonVirtual &&
38      type != flimflam::kTypeVPN) {
39    return true;
40  }
41  if (match_type == chromeos::NetworkStateHandler::kMatchTypeWireless &&
42      type != flimflam::kTypeEthernet && type != flimflam::kTypeVPN) {
43    return true;
44  }
45  if (match_type == chromeos::NetworkStateHandler::kMatchTypeMobile &&
46      (type == flimflam::kTypeCellular || type == flimflam::kTypeWimax)) {
47    return true;
48  }
49  return false;
50}
51
52bool ConnectionStateChanged(chromeos::NetworkState* network,
53                            const std::string& prev_connection_state) {
54  return (network->connection_state() != prev_connection_state) &&
55         (network->connection_state() != flimflam::kStateIdle ||
56          !prev_connection_state.empty());
57}
58
59std::string GetManagedStateLogName(const chromeos::ManagedState* state) {
60  if (!state)
61    return "None";
62  return base::StringPrintf("%s (%s)", state->name().c_str(),
63                            state->path().c_str());
64}
65
66}  // namespace
67
68namespace chromeos {
69
70const char NetworkStateHandler::kMatchTypeDefault[] = "default";
71const char NetworkStateHandler::kMatchTypeWireless[] = "wireless";
72const char NetworkStateHandler::kMatchTypeMobile[] = "mobile";
73const char NetworkStateHandler::kMatchTypeNonVirtual[] = "non-virtual";
74const char NetworkStateHandler::kDefaultCheckPortalList[] =
75    "ethernet,wifi,cellular";
76
77NetworkStateHandler::NetworkStateHandler() {
78}
79
80NetworkStateHandler::~NetworkStateHandler() {
81  STLDeleteContainerPointers(network_list_.begin(), network_list_.end());
82  STLDeleteContainerPointers(device_list_.begin(), device_list_.end());
83}
84
85void NetworkStateHandler::InitShillPropertyHandler() {
86  shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
87  shill_property_handler_->Init();
88}
89
90// static
91NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
92  NetworkStateHandler* handler = new NetworkStateHandler();
93  handler->InitShillPropertyHandler();
94  return handler;
95}
96
97void NetworkStateHandler::AddObserver(
98    NetworkStateHandlerObserver* observer,
99    const tracked_objects::Location& from_here) {
100  observers_.AddObserver(observer);
101  network_event_log::internal::AddEntry(
102      from_here.file_name(), from_here.line_number(),
103      network_event_log::LOG_LEVEL_DEBUG,
104      "NetworkStateHandler::AddObserver", "");
105}
106
107void NetworkStateHandler::RemoveObserver(
108    NetworkStateHandlerObserver* observer,
109    const tracked_objects::Location& from_here) {
110  observers_.RemoveObserver(observer);
111  network_event_log::internal::AddEntry(
112      from_here.file_name(), from_here.line_number(),
113      network_event_log::LOG_LEVEL_DEBUG,
114      "NetworkStateHandler::RemoveObserver", "");
115}
116
117NetworkStateHandler::TechnologyState NetworkStateHandler::GetTechnologyState(
118    const std::string& type) const {
119  std::string technology = GetTechnologyForType(type);
120  TechnologyState state;
121  if (shill_property_handler_->IsTechnologyEnabled(technology))
122    state = TECHNOLOGY_ENABLED;
123  else if (shill_property_handler_->IsTechnologyEnabling(technology))
124    state = TECHNOLOGY_ENABLING;
125  else if (shill_property_handler_->IsTechnologyUninitialized(technology))
126    state = TECHNOLOGY_UNINITIALIZED;
127  else if (shill_property_handler_->IsTechnologyAvailable(technology))
128    state = TECHNOLOGY_AVAILABLE;
129  else
130    state = TECHNOLOGY_UNAVAILABLE;
131  VLOG(2) << "GetTechnologyState: " << type << " = " << state;
132  return state;
133}
134
135void NetworkStateHandler::SetTechnologyEnabled(
136    const std::string& type,
137    bool enabled,
138    const network_handler::ErrorCallback& error_callback) {
139  std::string technology = GetTechnologyForType(type);
140  NET_LOG_USER("SetTechnologyEnabled",
141               base::StringPrintf("%s:%d", technology.c_str(), enabled));
142  shill_property_handler_->SetTechnologyEnabled(
143      technology, enabled, error_callback);
144  // Signal Technology state changed -> ENABLING
145  NotifyManagerPropertyChanged();
146}
147
148const DeviceState* NetworkStateHandler::GetDeviceState(
149    const std::string& device_path) const {
150  return GetModifiableDeviceState(device_path);
151}
152
153const DeviceState* NetworkStateHandler::GetDeviceStateByType(
154    const std::string& type) const {
155  for (ManagedStateList::const_iterator iter = device_list_.begin();
156       iter != device_list_.end(); ++iter) {
157    ManagedState* device = *iter;
158    if (ManagedStateMatchesType(device, type))
159      return device->AsDeviceState();
160  }
161  return NULL;
162}
163
164bool NetworkStateHandler::GetScanningByType(const std::string& type) const {
165  for (ManagedStateList::const_iterator iter = device_list_.begin();
166       iter != device_list_.end(); ++iter) {
167    const DeviceState* device = (*iter)->AsDeviceState();
168    DCHECK(device);
169    if (ManagedStateMatchesType(device, type) && device->scanning())
170      return true;
171  }
172  return false;
173}
174
175const NetworkState* NetworkStateHandler::GetNetworkState(
176    const std::string& service_path) const {
177  return GetModifiableNetworkState(service_path);
178}
179
180const NetworkState* NetworkStateHandler::DefaultNetwork() const {
181  if (network_list_.empty())
182    return NULL;
183  const NetworkState* network = network_list_.front()->AsNetworkState();
184  DCHECK(network);
185  if (!network->IsConnectedState())
186    return NULL;
187  return network;
188}
189
190const NetworkState* NetworkStateHandler::ConnectedNetworkByType(
191    const std::string& type) const {
192  for (ManagedStateList::const_iterator iter = network_list_.begin();
193       iter != network_list_.end(); ++iter) {
194    const NetworkState* network = (*iter)->AsNetworkState();
195    DCHECK(network);
196    if (!network->IsConnectedState())
197      break;  // Connected networks are listed first.
198    if (ManagedStateMatchesType(network, type))
199      return network;
200  }
201  return NULL;
202}
203
204const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
205    const std::string& type) const {
206  for (ManagedStateList::const_iterator iter = network_list_.begin();
207       iter != network_list_.end(); ++iter) {
208    const NetworkState* network = (*iter)->AsNetworkState();
209    DCHECK(network);
210    if (network->IsConnectedState())
211      continue;
212    if (!network->IsConnectingState())
213      break;  // Connected and connecting networks are listed first.
214    if (ManagedStateMatchesType(network, type))
215      return network;
216  }
217  return NULL;
218}
219
220const NetworkState* NetworkStateHandler::FirstNetworkByType(
221    const std::string& type) const {
222  for (ManagedStateList::const_iterator iter = network_list_.begin();
223       iter != network_list_.end(); ++iter) {
224    const NetworkState* network = (*iter)->AsNetworkState();
225    DCHECK(network);
226    if (ManagedStateMatchesType(network, type))
227      return network;
228  }
229  return NULL;
230}
231
232std::string NetworkStateHandler::HardwareAddressForType(
233    const std::string& type) const {
234  std::string result;
235  const NetworkState* network = ConnectedNetworkByType(type);
236  if (network) {
237    const DeviceState* device = GetDeviceState(network->device_path());
238    if (device)
239      result = device->mac_address();
240  }
241  StringToUpperASCII(&result);
242  return result;
243}
244
245std::string NetworkStateHandler::FormattedHardwareAddressForType(
246    const std::string& type) const {
247  std::string address = HardwareAddressForType(type);
248  if (address.size() % 2 != 0)
249    return address;
250  std::string result;
251  for (size_t i = 0; i < address.size(); ++i) {
252    if ((i != 0) && (i % 2 == 0))
253      result.push_back(':');
254    result.push_back(address[i]);
255  }
256  return result;
257}
258
259void NetworkStateHandler::GetNetworkList(NetworkStateList* list) const {
260  DCHECK(list);
261  NetworkStateList result;
262  list->clear();
263  for (ManagedStateList::const_iterator iter = network_list_.begin();
264       iter != network_list_.end(); ++iter) {
265    const NetworkState* network = (*iter)->AsNetworkState();
266    DCHECK(network);
267    list->push_back(network);
268  }
269}
270
271void NetworkStateHandler::RequestScan() const {
272  NET_LOG_USER("RequestScan", "");
273  shill_property_handler_->RequestScan();
274}
275
276void NetworkStateHandler::WaitForScan(const std::string& type,
277                                      const base::Closure& callback) {
278  scan_complete_callbacks_[type].push_back(callback);
279  if (!GetScanningByType(type))
280    RequestScan();
281}
282
283void NetworkStateHandler::ConnectToBestWifiNetwork() {
284  NET_LOG_USER("ConnectToBestWifiNetwork", "");
285  WaitForScan(flimflam::kTypeWifi,
286              base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices,
287                         shill_property_handler_->AsWeakPtr()));
288}
289
290bool NetworkStateHandler::RequestUpdateForNetwork(
291    const std::string& service_path) {
292  NetworkState* network = GetModifiableNetworkState(service_path);
293  if (!network)
294    return false;  // Only request an update for known networks.
295  network->set_update_requested(true);
296  NET_LOG_EVENT("RequestUpdate", service_path);
297  shill_property_handler_->RequestProperties(
298      ManagedState::MANAGED_TYPE_NETWORK, service_path);
299  return true;
300}
301
302void NetworkStateHandler::RequestUpdateForAllNetworks() {
303  NET_LOG_EVENT("RequestUpdateForAllNetworks", "");
304  for (ManagedStateList::iterator iter = network_list_.begin();
305       iter != network_list_.end(); ++iter) {
306    ManagedState* network = *iter;
307    network->set_update_requested(true);
308    shill_property_handler_->RequestProperties(
309        ManagedState::MANAGED_TYPE_NETWORK, network->path());
310  }
311}
312
313void NetworkStateHandler::SetConnectingNetwork(
314    const std::string& service_path) {
315  connecting_network_ = service_path;
316  const NetworkState* network = GetNetworkState(service_path);
317  if (network)
318    NET_LOG_EVENT("SetConnectingNetwork", GetManagedStateLogName(network));
319  else
320    NET_LOG_ERROR("SetConnectingNetwork to unknown network", service_path);
321}
322
323void NetworkStateHandler::SetCheckPortalList(
324    const std::string& check_portal_list) {
325  NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
326  shill_property_handler_->SetCheckPortalList(check_portal_list);
327}
328
329void NetworkStateHandler::GetNetworkStatePropertiesForTest(
330    base::DictionaryValue* dictionary) const {
331  for (ManagedStateList::const_iterator iter = network_list_.begin();
332       iter != network_list_.end(); ++iter) {
333    base::DictionaryValue* network_dict = new base::DictionaryValue;
334    (*iter)->AsNetworkState()->GetProperties(network_dict);
335    dictionary->SetWithoutPathExpansion((*iter)->path(), network_dict);
336  }
337}
338
339//------------------------------------------------------------------------------
340// ShillPropertyHandler::Delegate overrides
341
342void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
343                                            const base::ListValue& entries) {
344  ManagedStateList* managed_list = GetManagedList(type);
345  VLOG(2) << "UpdateManagedList: " << type;
346  // Create a map of existing entries.
347  std::map<std::string, ManagedState*> managed_map;
348  for (ManagedStateList::iterator iter = managed_list->begin();
349       iter != managed_list->end(); ++iter) {
350    ManagedState* managed = *iter;
351    managed_map[managed->path()] = managed;
352  }
353  // Clear the list (pointers are owned by managed_map).
354  managed_list->clear();
355  // Updates managed_list and request updates for new entries.
356  for (base::ListValue::const_iterator iter = entries.begin();
357       iter != entries.end(); ++iter) {
358    std::string path;
359    (*iter)->GetAsString(&path);
360    DCHECK(!path.empty());
361    std::map<std::string, ManagedState*>::iterator found =
362        managed_map.find(path);
363    bool request_properties = false;
364    ManagedState* managed;
365    bool is_observing = shill_property_handler_->IsObservingNetwork(path);
366    if (found == managed_map.end()) {
367      request_properties = true;
368      managed = ManagedState::Create(type, path);
369      managed_list->push_back(managed);
370    } else {
371      managed = found->second;
372      managed_list->push_back(managed);
373      managed_map.erase(found);
374      if (!managed->is_observed() && is_observing)
375        request_properties = true;
376    }
377    if (is_observing)
378      managed->set_is_observed(true);
379    if (request_properties)
380      shill_property_handler_->RequestProperties(type, path);
381  }
382  // Delete any remaning entries in managed_map.
383  STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
384}
385
386void NetworkStateHandler::ProfileListChanged() {
387  NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
388  for (ManagedStateList::iterator iter = network_list_.begin();
389       iter != network_list_.end(); ++iter) {
390    shill_property_handler_->RequestProperties(
391        ManagedState::MANAGED_TYPE_NETWORK, (*iter)->path());
392  }
393}
394
395void NetworkStateHandler::UpdateManagedStateProperties(
396    ManagedState::ManagedType type,
397    const std::string& path,
398    const base::DictionaryValue& properties) {
399  ManagedState* managed = GetModifiableManagedState(GetManagedList(type), path);
400  if (!managed) {
401    LOG(ERROR) << "GetPropertiesCallback: " << path << " Not found!";
402    return;
403  }
404  bool network_property_updated = false;
405  std::string prev_connection_state;
406  if (type == ManagedState::MANAGED_TYPE_NETWORK)
407    prev_connection_state = managed->AsNetworkState()->connection_state();
408  for (base::DictionaryValue::Iterator iter(properties);
409       !iter.IsAtEnd(); iter.Advance()) {
410    if (type == ManagedState::MANAGED_TYPE_NETWORK) {
411      if (managed->PropertyChanged(iter.key(), iter.value()))
412        network_property_updated = true;
413    } else {
414      managed->PropertyChanged(iter.key(), iter.value());
415    }
416  }
417  managed->InitialPropertiesReceived();
418  NET_LOG_DEBUG("PropertiesReceived", GetManagedStateLogName(managed));
419  // Notify observers.
420  if (network_property_updated || managed->update_requested()) {
421    NetworkState* network = managed->AsNetworkState();
422    DCHECK(network);
423    // Signal connection state changed after all properties have been updated.
424    if (ConnectionStateChanged(network, prev_connection_state))
425      OnNetworkConnectionStateChanged(network);
426    NetworkPropertiesUpdated(network);
427  }
428  managed->set_update_requested(false);
429}
430
431void NetworkStateHandler::UpdateNetworkServiceProperty(
432    const std::string& service_path,
433    const std::string& key,
434    const base::Value& value) {
435  NetworkState* network = GetModifiableNetworkState(service_path);
436  if (!network)
437    return;
438  std::string prev_connection_state = network->connection_state();
439  if (!network->PropertyChanged(key, value))
440    return;
441
442  if (key == flimflam::kStateProperty) {
443    if (ConnectionStateChanged(network, prev_connection_state))
444      OnNetworkConnectionStateChanged(network);
445  } else {
446    if (network->path() == default_network_path_ &&
447        key != flimflam::kSignalStrengthProperty) {
448      // WiFi signal strength updates are too noisy, so don't
449      // trigger default network updates for those changes.
450      OnDefaultNetworkChanged();
451    }
452    std::string detail = network->name() + "." + key;
453    detail += " = " + network_event_log::ValueAsString(value);
454    network_event_log::LogLevel log_level = network_event_log::LOG_LEVEL_EVENT;
455    if (key == flimflam::kErrorProperty || key == shill::kErrorDetailsProperty)
456      log_level = network_event_log::LOG_LEVEL_ERROR;
457    else if (key == flimflam::kSignalStrengthProperty)
458      log_level = network_event_log::LOG_LEVEL_DEBUG;
459    NET_LOG_LEVEL(log_level, "NetworkPropertyUpdated", detail);
460  }
461  NetworkPropertiesUpdated(network);
462}
463
464void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
465                                               const std::string& key,
466                                               const base::Value& value) {
467  DeviceState* device = GetModifiableDeviceState(device_path);
468  if (!device)
469    return;
470  if (!device->PropertyChanged(key, value))
471    return;
472
473  std::string detail = device->name() + "." + key;
474  detail += " = " + network_event_log::ValueAsString(value);
475  NET_LOG_EVENT("DevicePropertyUpdated", detail);
476
477  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
478                    DeviceListChanged());
479
480  if (key == flimflam::kScanningProperty && device->scanning() == false)
481    ScanCompleted(device->type());
482}
483
484void NetworkStateHandler::CheckPortalListChanged(
485    const std::string& check_portal_list) {
486  check_portal_list_ = check_portal_list;
487}
488
489void NetworkStateHandler::NotifyManagerPropertyChanged() {
490  NET_LOG_DEBUG("NotifyManagerPropertyChanged", "");
491  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
492                    NetworkManagerChanged());
493}
494
495void NetworkStateHandler::ManagedStateListChanged(
496    ManagedState::ManagedType type) {
497  if (type == ManagedState::MANAGED_TYPE_NETWORK) {
498    // Notify observers that the list of networks has changed.
499    NET_LOG_EVENT("NetworkListChanged",
500                  base::StringPrintf("Size:%"PRIuS, network_list_.size()));
501    FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
502                      NetworkListChanged());
503    // The list order may have changed, so check if the default network changed.
504    if (CheckDefaultNetworkChanged())
505      OnDefaultNetworkChanged();
506  } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
507    NET_LOG_DEBUG("DeviceListChanged",
508                  base::StringPrintf("Size:%"PRIuS, device_list_.size()));
509    FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
510                      DeviceListChanged());
511  } else {
512    NOTREACHED();
513  }
514}
515
516//------------------------------------------------------------------------------
517// Private methods
518
519DeviceState* NetworkStateHandler::GetModifiableDeviceState(
520    const std::string& device_path) const {
521  ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
522  if (!managed)
523    return NULL;
524  return managed->AsDeviceState();
525}
526
527NetworkState* NetworkStateHandler::GetModifiableNetworkState(
528    const std::string& service_path) const {
529  ManagedState* managed =
530      GetModifiableManagedState(&network_list_, service_path);
531  if (!managed)
532    return NULL;
533  return managed->AsNetworkState();
534}
535
536ManagedState* NetworkStateHandler::GetModifiableManagedState(
537    const ManagedStateList* managed_list,
538    const std::string& path) const {
539  for (ManagedStateList::const_iterator iter = managed_list->begin();
540       iter != managed_list->end(); ++iter) {
541    ManagedState* managed = *iter;
542    if (managed->path() == path)
543      return managed;
544  }
545  return NULL;
546}
547
548NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
549    ManagedState::ManagedType type) {
550  switch (type) {
551    case ManagedState::MANAGED_TYPE_NETWORK:
552      return &network_list_;
553    case ManagedState::MANAGED_TYPE_DEVICE:
554      return &device_list_;
555  }
556  NOTREACHED();
557  return NULL;
558}
559
560void NetworkStateHandler::OnNetworkConnectionStateChanged(
561    NetworkState* network) {
562  DCHECK(network);
563  NET_LOG_EVENT("NetworkConnectionStateChanged", base::StringPrintf(
564      "%s:%s", GetManagedStateLogName(network).c_str(),
565      network->connection_state().c_str()));
566  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
567                    NetworkConnectionStateChanged(network));
568  if (CheckDefaultNetworkChanged() || network->path() == default_network_path_)
569    OnDefaultNetworkChanged();
570}
571
572bool NetworkStateHandler::CheckDefaultNetworkChanged() {
573  std::string new_default_network_path;
574  const NetworkState* new_default_network = DefaultNetwork();
575  if (new_default_network)
576    new_default_network_path = new_default_network->path();
577  if (new_default_network_path == default_network_path_)
578    return false;
579  default_network_path_ = new_default_network_path;
580  return true;
581}
582
583void NetworkStateHandler::OnDefaultNetworkChanged() {
584  const NetworkState* default_network = DefaultNetwork();
585  NET_LOG_EVENT("DefaultNetworkChanged",
586                GetManagedStateLogName(default_network));
587  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
588                    DefaultNetworkChanged(default_network));
589}
590
591void NetworkStateHandler::NetworkPropertiesUpdated(
592    const NetworkState* network) {
593  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
594                    NetworkPropertiesUpdated(network));
595  // If |connecting_network_| transitions to a non-idle, non-connecting state,
596  // clear it *after* signalling observers.
597  if (network->path() == connecting_network_ &&
598      !network->IsConnectingState() &&
599      network->connection_state() != flimflam::kStateIdle) {
600    connecting_network_.clear();
601    NET_LOG_EVENT("ClearConnectingNetwork", base::StringPrintf(
602        "%s:%s", GetManagedStateLogName(network).c_str(),
603        network->connection_state().c_str()));
604  }
605}
606
607void NetworkStateHandler::ScanCompleted(const std::string& type) {
608  size_t num_callbacks = scan_complete_callbacks_.count(type);
609  NET_LOG_EVENT("ScanCompleted",
610                base::StringPrintf("%s:%"PRIuS, type.c_str(), num_callbacks));
611  if (num_callbacks == 0)
612    return;
613  ScanCallbackList& callback_list = scan_complete_callbacks_[type];
614  for (ScanCallbackList::iterator iter = callback_list.begin();
615       iter != callback_list.end(); ++iter) {
616    (*iter).Run();
617  }
618  scan_complete_callbacks_.erase(type);
619}
620
621std::string NetworkStateHandler::GetTechnologyForType(
622    const std::string& type) const {
623  if (type == kMatchTypeMobile) {
624    if (shill_property_handler_->IsTechnologyAvailable(flimflam::kTypeWimax))
625      return flimflam::kTypeWimax;
626    else
627      return flimflam::kTypeCellular;
628  }
629  if (type == kMatchTypeDefault || type == kMatchTypeNonVirtual ||
630      type == kMatchTypeWireless) {
631    NOTREACHED();
632    return flimflam::kTypeWifi;
633  }
634  return type;
635}
636
637}  // namespace chromeos
638