1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chromeos/dbus/fake_shill_manager_client.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/string_util.h"
13 #include "base/values.h"
14 #include "chromeos/chromeos_switches.h"
15 #include "chromeos/dbus/dbus_thread_manager.h"
16 #include "chromeos/dbus/shill_device_client.h"
17 #include "chromeos/dbus/shill_ipconfig_client.h"
18 #include "chromeos/dbus/shill_profile_client.h"
19 #include "chromeos/dbus/shill_property_changed_observer.h"
20 #include "chromeos/dbus/shill_service_client.h"
21 #include "dbus/bus.h"
22 #include "dbus/message.h"
23 #include "dbus/object_path.h"
24 #include "dbus/values_util.h"
25 #include "third_party/cros_system_api/dbus/service_constants.h"
26
27 namespace chromeos {
28
29 namespace {
30
31 // Used to compare values for finding entries to erase in a ListValue.
32 // (ListValue only implements a const_iterator version of Find).
33 struct ValueEquals {
ValueEqualschromeos::__anonf223c8ac0111::ValueEquals34 explicit ValueEquals(const base::Value* first) : first_(first) {}
operator ()chromeos::__anonf223c8ac0111::ValueEquals35 bool operator()(const base::Value* second) const {
36 return first_->Equals(second);
37 }
38 const base::Value* first_;
39 };
40
41 // Appends string entries from |service_list_in| whose entries in ServiceClient
42 // have Type |match_type| to one of the output lists based on the entry's State.
AppendServicesForType(const base::ListValue * service_list_in,const char * match_type,bool technology_enabled,std::vector<std::string> * active_service_list_out,std::vector<std::string> * inactive_service_list_out,std::vector<std::string> * disabled_service_list_out)43 void AppendServicesForType(
44 const base::ListValue* service_list_in,
45 const char* match_type,
46 bool technology_enabled,
47 std::vector<std::string>* active_service_list_out,
48 std::vector<std::string>* inactive_service_list_out,
49 std::vector<std::string>* disabled_service_list_out) {
50 ShillServiceClient::TestInterface* service_client =
51 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
52 for (base::ListValue::const_iterator iter = service_list_in->begin();
53 iter != service_list_in->end(); ++iter) {
54 std::string service_path;
55 if (!(*iter)->GetAsString(&service_path))
56 continue;
57 const base::DictionaryValue* properties =
58 service_client->GetServiceProperties(service_path);
59 if (!properties) {
60 LOG(ERROR) << "Properties not found for service: " << service_path;
61 continue;
62 }
63 std::string type;
64 properties->GetString(shill::kTypeProperty, &type);
65 if (type != match_type)
66 continue;
67 bool visible = false;
68 if (technology_enabled)
69 properties->GetBoolean(shill::kVisibleProperty, &visible);
70 if (!visible) {
71 disabled_service_list_out->push_back(service_path);
72 continue;
73 }
74 std::string state;
75 properties->GetString(shill::kStateProperty, &state);
76 if (state == shill::kStateOnline ||
77 state == shill::kStateAssociation ||
78 state == shill::kStateConfiguration ||
79 state == shill::kStatePortal ||
80 state == shill::kStateReady) {
81 active_service_list_out->push_back(service_path);
82 } else {
83 inactive_service_list_out->push_back(service_path);
84 }
85 }
86 }
87
LogErrorCallback(const std::string & error_name,const std::string & error_message)88 void LogErrorCallback(const std::string& error_name,
89 const std::string& error_message) {
90 LOG(ERROR) << error_name << ": " << error_message;
91 }
92
IsConnectedState(const std::string & state)93 bool IsConnectedState(const std::string& state) {
94 return state == shill::kStateOnline || state == shill::kStatePortal ||
95 state == shill::kStateReady;
96 }
97
UpdatePortaledWifiState(const std::string & service_path)98 void UpdatePortaledWifiState(const std::string& service_path) {
99 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()
100 ->SetServiceProperty(service_path,
101 shill::kStateProperty,
102 base::StringValue(shill::kStatePortal));
103 }
104
105 const char* kTechnologyUnavailable = "unavailable";
106 const char* kNetworkActivated = "activated";
107 const char* kNetworkDisabled = "disabled";
108 const char* kCellularServicePath = "/service/cellular1";
109
110 } // namespace
111
112 // static
113 const char FakeShillManagerClient::kFakeEthernetNetworkGuid[] = "eth1_guid";
114
FakeShillManagerClient()115 FakeShillManagerClient::FakeShillManagerClient()
116 : interactive_delay_(0),
117 weak_ptr_factory_(this) {
118 ParseCommandLineSwitch();
119 }
120
~FakeShillManagerClient()121 FakeShillManagerClient::~FakeShillManagerClient() {}
122
123 // ShillManagerClient overrides.
124
Init(dbus::Bus * bus)125 void FakeShillManagerClient::Init(dbus::Bus* bus) {}
126
AddPropertyChangedObserver(ShillPropertyChangedObserver * observer)127 void FakeShillManagerClient::AddPropertyChangedObserver(
128 ShillPropertyChangedObserver* observer) {
129 observer_list_.AddObserver(observer);
130 }
131
RemovePropertyChangedObserver(ShillPropertyChangedObserver * observer)132 void FakeShillManagerClient::RemovePropertyChangedObserver(
133 ShillPropertyChangedObserver* observer) {
134 observer_list_.RemoveObserver(observer);
135 }
136
GetProperties(const DictionaryValueCallback & callback)137 void FakeShillManagerClient::GetProperties(
138 const DictionaryValueCallback& callback) {
139 DVLOG(1) << "Manager.GetProperties";
140 base::MessageLoop::current()->PostTask(
141 FROM_HERE, base::Bind(
142 &FakeShillManagerClient::PassStubProperties,
143 weak_ptr_factory_.GetWeakPtr(),
144 callback));
145 }
146
GetNetworksForGeolocation(const DictionaryValueCallback & callback)147 void FakeShillManagerClient::GetNetworksForGeolocation(
148 const DictionaryValueCallback& callback) {
149 base::MessageLoop::current()->PostTask(
150 FROM_HERE, base::Bind(
151 &FakeShillManagerClient::PassStubGeoNetworks,
152 weak_ptr_factory_.GetWeakPtr(),
153 callback));
154 }
155
SetProperty(const std::string & name,const base::Value & value,const base::Closure & callback,const ErrorCallback & error_callback)156 void FakeShillManagerClient::SetProperty(const std::string& name,
157 const base::Value& value,
158 const base::Closure& callback,
159 const ErrorCallback& error_callback) {
160 DVLOG(2) << "SetProperty: " << name;
161 stub_properties_.SetWithoutPathExpansion(name, value.DeepCopy());
162 CallNotifyObserversPropertyChanged(name);
163 base::MessageLoop::current()->PostTask(FROM_HERE, callback);
164 }
165
RequestScan(const std::string & type,const base::Closure & callback,const ErrorCallback & error_callback)166 void FakeShillManagerClient::RequestScan(const std::string& type,
167 const base::Closure& callback,
168 const ErrorCallback& error_callback) {
169 // For Stub purposes, default to a Wifi scan.
170 std::string device_type = shill::kTypeWifi;
171 if (!type.empty())
172 device_type = type;
173 ShillDeviceClient::TestInterface* device_client =
174 DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface();
175 std::string device_path = device_client->GetDevicePathForType(device_type);
176 if (!device_path.empty()) {
177 device_client->SetDeviceProperty(
178 device_path, shill::kScanningProperty, base::FundamentalValue(true));
179 }
180 base::MessageLoop::current()->PostDelayedTask(
181 FROM_HERE,
182 base::Bind(&FakeShillManagerClient::ScanCompleted,
183 weak_ptr_factory_.GetWeakPtr(),
184 device_path,
185 callback),
186 base::TimeDelta::FromSeconds(interactive_delay_));
187 }
188
EnableTechnology(const std::string & type,const base::Closure & callback,const ErrorCallback & error_callback)189 void FakeShillManagerClient::EnableTechnology(
190 const std::string& type,
191 const base::Closure& callback,
192 const ErrorCallback& error_callback) {
193 base::ListValue* enabled_list = NULL;
194 if (!stub_properties_.GetListWithoutPathExpansion(
195 shill::kAvailableTechnologiesProperty, &enabled_list)) {
196 base::MessageLoop::current()->PostTask(FROM_HERE, callback);
197 base::MessageLoop::current()->PostTask(
198 FROM_HERE,
199 base::Bind(error_callback, "StubError", "Property not found"));
200 return;
201 }
202 base::MessageLoop::current()->PostDelayedTask(
203 FROM_HERE,
204 base::Bind(&FakeShillManagerClient::SetTechnologyEnabled,
205 weak_ptr_factory_.GetWeakPtr(),
206 type,
207 callback,
208 true),
209 base::TimeDelta::FromSeconds(interactive_delay_));
210 }
211
DisableTechnology(const std::string & type,const base::Closure & callback,const ErrorCallback & error_callback)212 void FakeShillManagerClient::DisableTechnology(
213 const std::string& type,
214 const base::Closure& callback,
215 const ErrorCallback& error_callback) {
216 base::ListValue* enabled_list = NULL;
217 if (!stub_properties_.GetListWithoutPathExpansion(
218 shill::kAvailableTechnologiesProperty, &enabled_list)) {
219 base::MessageLoop::current()->PostTask(
220 FROM_HERE,
221 base::Bind(error_callback, "StubError", "Property not found"));
222 return;
223 }
224 base::MessageLoop::current()->PostDelayedTask(
225 FROM_HERE,
226 base::Bind(&FakeShillManagerClient::SetTechnologyEnabled,
227 weak_ptr_factory_.GetWeakPtr(),
228 type,
229 callback,
230 false),
231 base::TimeDelta::FromSeconds(interactive_delay_));
232 }
233
ConfigureService(const base::DictionaryValue & properties,const ObjectPathCallback & callback,const ErrorCallback & error_callback)234 void FakeShillManagerClient::ConfigureService(
235 const base::DictionaryValue& properties,
236 const ObjectPathCallback& callback,
237 const ErrorCallback& error_callback) {
238 ShillServiceClient::TestInterface* service_client =
239 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
240
241 std::string guid;
242 std::string type;
243 if (!properties.GetString(shill::kGuidProperty, &guid) ||
244 !properties.GetString(shill::kTypeProperty, &type)) {
245 LOG(ERROR) << "ConfigureService requires GUID and Type to be defined";
246 // If the properties aren't filled out completely, then just return an empty
247 // object path.
248 base::MessageLoop::current()->PostTask(
249 FROM_HERE, base::Bind(callback, dbus::ObjectPath()));
250 return;
251 }
252
253 // For the purposes of this stub, we're going to assume that the GUID property
254 // is set to the service path because we don't want to re-implement Shill's
255 // property matching magic here.
256 std::string service_path = guid;
257
258 std::string ipconfig_path;
259 properties.GetString(shill::kIPConfigProperty, &ipconfig_path);
260
261 // Merge the new properties with existing properties, if any.
262 const base::DictionaryValue* existing_properties =
263 service_client->GetServiceProperties(service_path);
264 if (!existing_properties) {
265 // Add a new service to the service client stub because none exists, yet.
266 // This calls AddManagerService.
267 service_client->AddServiceWithIPConfig(service_path,
268 guid /* guid */,
269 guid /* name */,
270 type,
271 shill::kStateIdle,
272 ipconfig_path,
273 true /* visible */);
274 existing_properties = service_client->GetServiceProperties(service_path);
275 }
276
277 scoped_ptr<base::DictionaryValue> merged_properties(
278 existing_properties->DeepCopy());
279 merged_properties->MergeDictionary(&properties);
280
281 // Now set all the properties.
282 for (base::DictionaryValue::Iterator iter(*merged_properties);
283 !iter.IsAtEnd(); iter.Advance()) {
284 service_client->SetServiceProperty(service_path, iter.key(), iter.value());
285 }
286
287 // If the Profile property is set, add it to ProfileClient.
288 std::string profile_path;
289 merged_properties->GetStringWithoutPathExpansion(shill::kProfileProperty,
290 &profile_path);
291 if (!profile_path.empty()) {
292 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface()->
293 AddService(profile_path, service_path);
294 }
295
296 base::MessageLoop::current()->PostTask(
297 FROM_HERE, base::Bind(callback, dbus::ObjectPath(service_path)));
298 }
299
ConfigureServiceForProfile(const dbus::ObjectPath & profile_path,const base::DictionaryValue & properties,const ObjectPathCallback & callback,const ErrorCallback & error_callback)300 void FakeShillManagerClient::ConfigureServiceForProfile(
301 const dbus::ObjectPath& profile_path,
302 const base::DictionaryValue& properties,
303 const ObjectPathCallback& callback,
304 const ErrorCallback& error_callback) {
305 std::string profile_property;
306 properties.GetStringWithoutPathExpansion(shill::kProfileProperty,
307 &profile_property);
308 CHECK(profile_property == profile_path.value());
309 ConfigureService(properties, callback, error_callback);
310 }
311
312
GetService(const base::DictionaryValue & properties,const ObjectPathCallback & callback,const ErrorCallback & error_callback)313 void FakeShillManagerClient::GetService(
314 const base::DictionaryValue& properties,
315 const ObjectPathCallback& callback,
316 const ErrorCallback& error_callback) {
317 base::MessageLoop::current()->PostTask(
318 FROM_HERE, base::Bind(callback, dbus::ObjectPath()));
319 }
320
VerifyDestination(const VerificationProperties & properties,const BooleanCallback & callback,const ErrorCallback & error_callback)321 void FakeShillManagerClient::VerifyDestination(
322 const VerificationProperties& properties,
323 const BooleanCallback& callback,
324 const ErrorCallback& error_callback) {
325 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, true));
326 }
327
VerifyAndEncryptCredentials(const VerificationProperties & properties,const std::string & service_path,const StringCallback & callback,const ErrorCallback & error_callback)328 void FakeShillManagerClient::VerifyAndEncryptCredentials(
329 const VerificationProperties& properties,
330 const std::string& service_path,
331 const StringCallback& callback,
332 const ErrorCallback& error_callback) {
333 base::MessageLoop::current()->PostTask(
334 FROM_HERE, base::Bind(callback, "encrypted_credentials"));
335 }
336
VerifyAndEncryptData(const VerificationProperties & properties,const std::string & data,const StringCallback & callback,const ErrorCallback & error_callback)337 void FakeShillManagerClient::VerifyAndEncryptData(
338 const VerificationProperties& properties,
339 const std::string& data,
340 const StringCallback& callback,
341 const ErrorCallback& error_callback) {
342 base::MessageLoop::current()->PostTask(
343 FROM_HERE, base::Bind(callback, "encrypted_data"));
344 }
345
ConnectToBestServices(const base::Closure & callback,const ErrorCallback & error_callback)346 void FakeShillManagerClient::ConnectToBestServices(
347 const base::Closure& callback,
348 const ErrorCallback& error_callback) {
349 if (best_service_.empty()) {
350 VLOG(1) << "No 'best' service set.";
351 return;
352 }
353
354 DBusThreadManager::Get()->GetShillServiceClient()->Connect(
355 dbus::ObjectPath(best_service_), callback, error_callback);
356 }
357
AddWakeOnPacketConnection(const net::IPEndPoint & ip_endpoint,const base::Closure & callback,const ErrorCallback & error_callback)358 void FakeShillManagerClient::AddWakeOnPacketConnection(
359 const net::IPEndPoint& ip_endpoint,
360 const base::Closure& callback,
361 const ErrorCallback& error_callback) {
362 }
363
RemoveWakeOnPacketConnection(const net::IPEndPoint & ip_endpoint,const base::Closure & callback,const ErrorCallback & error_callback)364 void FakeShillManagerClient::RemoveWakeOnPacketConnection(
365 const net::IPEndPoint& ip_endpoint,
366 const base::Closure& callback,
367 const ErrorCallback& error_callback) {
368 }
369
RemoveAllWakeOnPacketConnections(const base::Closure & callback,const ErrorCallback & error_callback)370 void FakeShillManagerClient::RemoveAllWakeOnPacketConnections(
371 const base::Closure& callback,
372 const ErrorCallback& error_callback) {
373 }
374
GetTestInterface()375 ShillManagerClient::TestInterface* FakeShillManagerClient::GetTestInterface() {
376 return this;
377 }
378
379 // ShillManagerClient::TestInterface overrides.
380
AddDevice(const std::string & device_path)381 void FakeShillManagerClient::AddDevice(const std::string& device_path) {
382 if (GetListProperty(shill::kDevicesProperty)
383 ->AppendIfNotPresent(new base::StringValue(device_path))) {
384 CallNotifyObserversPropertyChanged(shill::kDevicesProperty);
385 }
386 }
387
RemoveDevice(const std::string & device_path)388 void FakeShillManagerClient::RemoveDevice(const std::string& device_path) {
389 base::StringValue device_path_value(device_path);
390 if (GetListProperty(shill::kDevicesProperty)->Remove(
391 device_path_value, NULL)) {
392 CallNotifyObserversPropertyChanged(shill::kDevicesProperty);
393 }
394 }
395
ClearDevices()396 void FakeShillManagerClient::ClearDevices() {
397 GetListProperty(shill::kDevicesProperty)->Clear();
398 CallNotifyObserversPropertyChanged(shill::kDevicesProperty);
399 }
400
AddTechnology(const std::string & type,bool enabled)401 void FakeShillManagerClient::AddTechnology(const std::string& type,
402 bool enabled) {
403 if (GetListProperty(shill::kAvailableTechnologiesProperty)
404 ->AppendIfNotPresent(new base::StringValue(type))) {
405 CallNotifyObserversPropertyChanged(
406 shill::kAvailableTechnologiesProperty);
407 }
408 if (enabled &&
409 GetListProperty(shill::kEnabledTechnologiesProperty)
410 ->AppendIfNotPresent(new base::StringValue(type))) {
411 CallNotifyObserversPropertyChanged(
412 shill::kEnabledTechnologiesProperty);
413 }
414 }
415
RemoveTechnology(const std::string & type)416 void FakeShillManagerClient::RemoveTechnology(const std::string& type) {
417 base::StringValue type_value(type);
418 if (GetListProperty(shill::kAvailableTechnologiesProperty)->Remove(
419 type_value, NULL)) {
420 CallNotifyObserversPropertyChanged(
421 shill::kAvailableTechnologiesProperty);
422 }
423 if (GetListProperty(shill::kEnabledTechnologiesProperty)->Remove(
424 type_value, NULL)) {
425 CallNotifyObserversPropertyChanged(
426 shill::kEnabledTechnologiesProperty);
427 }
428 }
429
SetTechnologyInitializing(const std::string & type,bool initializing)430 void FakeShillManagerClient::SetTechnologyInitializing(const std::string& type,
431 bool initializing) {
432 if (initializing) {
433 if (GetListProperty(shill::kUninitializedTechnologiesProperty)
434 ->AppendIfNotPresent(new base::StringValue(type))) {
435 CallNotifyObserversPropertyChanged(
436 shill::kUninitializedTechnologiesProperty);
437 }
438 } else {
439 if (GetListProperty(shill::kUninitializedTechnologiesProperty)->Remove(
440 base::StringValue(type), NULL)) {
441 CallNotifyObserversPropertyChanged(
442 shill::kUninitializedTechnologiesProperty);
443 }
444 }
445 }
446
AddGeoNetwork(const std::string & technology,const base::DictionaryValue & network)447 void FakeShillManagerClient::AddGeoNetwork(
448 const std::string& technology,
449 const base::DictionaryValue& network) {
450 base::ListValue* list_value = NULL;
451 if (!stub_geo_networks_.GetListWithoutPathExpansion(technology,
452 &list_value)) {
453 list_value = new base::ListValue;
454 stub_geo_networks_.SetWithoutPathExpansion(technology, list_value);
455 }
456 list_value->Append(network.DeepCopy());
457 }
458
AddProfile(const std::string & profile_path)459 void FakeShillManagerClient::AddProfile(const std::string& profile_path) {
460 const char* key = shill::kProfilesProperty;
461 if (GetListProperty(key)
462 ->AppendIfNotPresent(new base::StringValue(profile_path))) {
463 CallNotifyObserversPropertyChanged(key);
464 }
465 }
466
ClearProperties()467 void FakeShillManagerClient::ClearProperties() {
468 stub_properties_.Clear();
469 }
470
SetManagerProperty(const std::string & key,const base::Value & value)471 void FakeShillManagerClient::SetManagerProperty(const std::string& key,
472 const base::Value& value) {
473 SetProperty(key, value,
474 base::Bind(&base::DoNothing), base::Bind(&LogErrorCallback));
475 }
476
AddManagerService(const std::string & service_path,bool notify_observers)477 void FakeShillManagerClient::AddManagerService(
478 const std::string& service_path,
479 bool notify_observers) {
480 DVLOG(2) << "AddManagerService: " << service_path;
481 GetListProperty(shill::kServiceCompleteListProperty)
482 ->AppendIfNotPresent(new base::StringValue(service_path));
483 SortManagerServices(false);
484 if (notify_observers)
485 CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
486 }
487
RemoveManagerService(const std::string & service_path)488 void FakeShillManagerClient::RemoveManagerService(
489 const std::string& service_path) {
490 DVLOG(2) << "RemoveManagerService: " << service_path;
491 base::StringValue service_path_value(service_path);
492 GetListProperty(shill::kServiceCompleteListProperty)->Remove(
493 service_path_value, NULL);
494 CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
495 }
496
ClearManagerServices()497 void FakeShillManagerClient::ClearManagerServices() {
498 DVLOG(1) << "ClearManagerServices";
499 GetListProperty(shill::kServiceCompleteListProperty)->Clear();
500 CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
501 }
502
ServiceStateChanged(const std::string & service_path,const std::string & state)503 void FakeShillManagerClient::ServiceStateChanged(
504 const std::string& service_path,
505 const std::string& state) {
506 if (service_path == default_service_ && !IsConnectedState(state)) {
507 // Default service is no longer connected; clear.
508 default_service_.clear();
509 base::StringValue default_service_value(default_service_);
510 SetManagerProperty(shill::kDefaultServiceProperty, default_service_value);
511 }
512 }
513
SortManagerServices(bool notify)514 void FakeShillManagerClient::SortManagerServices(bool notify) {
515 DVLOG(1) << "SortManagerServices";
516 static const char* ordered_types[] = {shill::kTypeEthernet,
517 shill::kTypeEthernetEap,
518 shill::kTypeWifi,
519 shill::kTypeCellular,
520 shill::kTypeWimax,
521 shill::kTypeVPN};
522
523 base::ListValue* complete_list =
524 GetListProperty(shill::kServiceCompleteListProperty);
525 if (complete_list->empty())
526 return;
527 scoped_ptr<base::ListValue> prev_complete_list(complete_list->DeepCopy());
528
529 std::vector<std::string> active_services;
530 std::vector<std::string> inactive_services;
531 std::vector<std::string> disabled_services;
532 for (size_t i = 0; i < arraysize(ordered_types); ++i) {
533 AppendServicesForType(complete_list,
534 ordered_types[i],
535 TechnologyEnabled(ordered_types[i]),
536 &active_services,
537 &inactive_services,
538 &disabled_services);
539 }
540 complete_list->Clear();
541 for (size_t i = 0; i < active_services.size(); ++i)
542 complete_list->AppendString(active_services[i]);
543 for (size_t i = 0; i < inactive_services.size(); ++i)
544 complete_list->AppendString(inactive_services[i]);
545 for (size_t i = 0; i < disabled_services.size(); ++i)
546 complete_list->AppendString(disabled_services[i]);
547
548 if (notify && !complete_list->Equals(prev_complete_list.get()))
549 CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
550
551 // Set the first active service as the Default service.
552 std::string new_default_service;
553 if (!active_services.empty()) {
554 ShillServiceClient::TestInterface* service_client =
555 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
556 std::string service_path = active_services[0];
557 const base::DictionaryValue* properties =
558 service_client->GetServiceProperties(service_path);
559 if (!properties) {
560 LOG(ERROR) << "Properties not found for service: " << service_path;
561 } else {
562 std::string state;
563 properties->GetString(shill::kStateProperty, &state);
564 if (IsConnectedState(state))
565 new_default_service = service_path;
566 }
567 }
568 if (default_service_ != new_default_service) {
569 default_service_ = new_default_service;
570 base::StringValue default_service_value(default_service_);
571 SetManagerProperty(shill::kDefaultServiceProperty, default_service_value);
572 }
573 }
574
GetInteractiveDelay() const575 int FakeShillManagerClient::GetInteractiveDelay() const {
576 return interactive_delay_;
577 }
578
SetBestServiceToConnect(const std::string & service_path)579 void FakeShillManagerClient::SetBestServiceToConnect(
580 const std::string& service_path) {
581 best_service_ = service_path;
582 }
583
SetupDefaultEnvironment()584 void FakeShillManagerClient::SetupDefaultEnvironment() {
585 // Bail out from setup if there is no message loop. This will be the common
586 // case for tests that are not testing Shill.
587 if (!base::MessageLoop::current())
588 return;
589
590 DBusThreadManager* dbus_manager = DBusThreadManager::Get();
591 ShillServiceClient::TestInterface* services =
592 dbus_manager->GetShillServiceClient()->GetTestInterface();
593 DCHECK(services);
594 ShillProfileClient::TestInterface* profiles =
595 dbus_manager->GetShillProfileClient()->GetTestInterface();
596 DCHECK(profiles);
597 ShillDeviceClient::TestInterface* devices =
598 dbus_manager->GetShillDeviceClient()->GetTestInterface();
599 DCHECK(devices);
600 ShillIPConfigClient::TestInterface* ip_configs =
601 dbus_manager->GetShillIPConfigClient()->GetTestInterface();
602 DCHECK(ip_configs);
603
604 const std::string shared_profile = ShillProfileClient::GetSharedProfilePath();
605 profiles->AddProfile(shared_profile, std::string());
606
607 const bool add_to_visible = true;
608
609 // IPConfigs
610 base::DictionaryValue ipconfig_v4_dictionary;
611 ipconfig_v4_dictionary.SetStringWithoutPathExpansion(
612 shill::kAddressProperty, "0.0.0.0");
613 ipconfig_v4_dictionary.SetStringWithoutPathExpansion(
614 shill::kGatewayProperty, "0.0.0.1");
615 ipconfig_v4_dictionary.SetIntegerWithoutPathExpansion(
616 shill::kPrefixlenProperty, 0);
617 ipconfig_v4_dictionary.SetStringWithoutPathExpansion(
618 shill::kMethodProperty, shill::kTypeIPv4);
619 ip_configs->AddIPConfig("ipconfig_v4_path", ipconfig_v4_dictionary);
620 base::DictionaryValue ipconfig_v6_dictionary;
621 ipconfig_v6_dictionary.SetStringWithoutPathExpansion(
622 shill::kAddressProperty, "0:0:0:0:0:0:0:0");
623 ipconfig_v6_dictionary.SetStringWithoutPathExpansion(
624 shill::kMethodProperty, shill::kTypeIPv6);
625 ip_configs->AddIPConfig("ipconfig_v6_path", ipconfig_v6_dictionary);
626
627 bool enabled;
628 std::string state;
629
630 // Ethernet
631 state = GetInitialStateForType(shill::kTypeEthernet, &enabled);
632 if (state == shill::kStateOnline) {
633 AddTechnology(shill::kTypeEthernet, enabled);
634 devices->AddDevice(
635 "/device/eth1", shill::kTypeEthernet, "stub_eth_device1");
636 devices->SetDeviceProperty("/device/eth1",
637 shill::kAddressProperty,
638 base::StringValue("0123456789ab"));
639 base::ListValue eth_ip_configs;
640 eth_ip_configs.AppendString("ipconfig_v4_path");
641 eth_ip_configs.AppendString("ipconfig_v6_path");
642 devices->SetDeviceProperty("/device/eth1",
643 shill::kIPConfigsProperty,
644 eth_ip_configs);
645 const std::string kFakeEthernetNetworkPath = "/service/eth1";
646 services->AddService(kFakeEthernetNetworkPath,
647 kFakeEthernetNetworkGuid,
648 "eth1" /* name */,
649 shill::kTypeEthernet,
650 state,
651 add_to_visible);
652 profiles->AddService(shared_profile, kFakeEthernetNetworkPath);
653 }
654
655 // Wifi
656 state = GetInitialStateForType(shill::kTypeWifi, &enabled);
657 if (state != kTechnologyUnavailable) {
658 bool portaled = false;
659 if (state == shill::kStatePortal) {
660 portaled = true;
661 state = shill::kStateIdle;
662 }
663 AddTechnology(shill::kTypeWifi, enabled);
664 devices->AddDevice("/device/wifi1", shill::kTypeWifi, "stub_wifi_device1");
665 devices->SetDeviceProperty("/device/wifi1",
666 shill::kAddressProperty,
667 base::StringValue("23456789abc"));
668 base::ListValue wifi_ip_configs;
669 wifi_ip_configs.AppendString("ipconfig_v4_path");
670 wifi_ip_configs.AppendString("ipconfig_v6_path");
671 devices->SetDeviceProperty("/device/wifi1",
672 shill::kIPConfigsProperty,
673 wifi_ip_configs);
674
675 const std::string kWifi1Path = "/service/wifi1";
676 services->AddService(kWifi1Path,
677 "wifi1_guid",
678 "wifi1" /* name */,
679 shill::kTypeWifi,
680 state,
681 add_to_visible);
682 services->SetServiceProperty(kWifi1Path,
683 shill::kSecurityProperty,
684 base::StringValue(shill::kSecurityWep));
685 services->SetServiceProperty(kWifi1Path,
686 shill::kConnectableProperty,
687 base::FundamentalValue(true));
688 profiles->AddService(shared_profile, kWifi1Path);
689
690 const std::string kWifi2Path = "/service/wifi2";
691 services->AddService(kWifi2Path,
692 "wifi2_PSK_guid",
693 "wifi2_PSK" /* name */,
694 shill::kTypeWifi,
695 shill::kStateIdle,
696 add_to_visible);
697 services->SetServiceProperty(kWifi2Path,
698 shill::kSecurityProperty,
699 base::StringValue(shill::kSecurityPsk));
700
701 base::FundamentalValue strength_value(80);
702 services->SetServiceProperty(
703 kWifi2Path, shill::kSignalStrengthProperty, strength_value);
704 profiles->AddService(shared_profile, kWifi2Path);
705
706 if (portaled) {
707 const std::string kPortaledWifiPath = "/service/portaled_wifi";
708 services->AddService(kPortaledWifiPath,
709 "portaled_wifi_guid",
710 "Portaled Wifi" /* name */,
711 shill::kTypeWifi,
712 shill::kStatePortal,
713 add_to_visible);
714 services->SetServiceProperty(kPortaledWifiPath,
715 shill::kSecurityProperty,
716 base::StringValue(shill::kSecurityNone));
717 services->SetConnectBehavior(kPortaledWifiPath,
718 base::Bind(&UpdatePortaledWifiState,
719 "portaled_wifi"));
720 services->SetServiceProperty(kPortaledWifiPath,
721 shill::kConnectableProperty,
722 base::FundamentalValue(true));
723 profiles->AddService(shared_profile, kPortaledWifiPath);
724 }
725 }
726
727 // Wimax
728 state = GetInitialStateForType(shill::kTypeWimax, &enabled);
729 if (state != kTechnologyUnavailable) {
730 AddTechnology(shill::kTypeWimax, enabled);
731 devices->AddDevice(
732 "/device/wimax1", shill::kTypeWimax, "stub_wimax_device1");
733
734 services->AddService("/service/wimax1",
735 "wimax1_guid",
736 "wimax1" /* name */,
737 shill::kTypeWimax,
738 state,
739 add_to_visible);
740 services->SetServiceProperty("/service/wimax1",
741 shill::kConnectableProperty,
742 base::FundamentalValue(true));
743 base::FundamentalValue strength_value(80);
744 services->SetServiceProperty(
745 "/service/wimax1", shill::kSignalStrengthProperty, strength_value);
746 base::StringValue identity_value("test.identity");
747 services->SetServiceProperty(
748 "/service/wimax1", shill::kEapIdentityProperty, identity_value);
749 }
750
751 // Cellular
752 state = GetInitialStateForType(shill::kTypeCellular, &enabled);
753 if (state != kTechnologyUnavailable) {
754 bool activated = false;
755 if (state == kNetworkActivated) {
756 activated = true;
757 state = shill::kStateIdle;
758 }
759 AddTechnology(shill::kTypeCellular, enabled);
760 devices->AddDevice(
761 "/device/cellular1", shill::kTypeCellular, "stub_cellular_device1");
762 devices->SetDeviceProperty("/device/cellular1",
763 shill::kCarrierProperty,
764 base::StringValue(shill::kCarrierSprint));
765 base::ListValue carrier_list;
766 carrier_list.AppendString(shill::kCarrierSprint);
767 carrier_list.AppendString(shill::kCarrierGenericUMTS);
768 devices->SetDeviceProperty("/device/cellular1",
769 shill::kSupportedCarriersProperty,
770 carrier_list);
771
772 services->AddService(kCellularServicePath,
773 "cellular1_guid",
774 "cellular1" /* name */,
775 shill::kTypeCellular,
776 state,
777 add_to_visible);
778 base::StringValue technology_value(shill::kNetworkTechnologyGsm);
779 services->SetServiceProperty(kCellularServicePath,
780 shill::kNetworkTechnologyProperty,
781 technology_value);
782
783 if (activated) {
784 services->SetServiceProperty(
785 kCellularServicePath,
786 shill::kActivationStateProperty,
787 base::StringValue(shill::kActivationStateActivated));
788 services->SetServiceProperty(kCellularServicePath,
789 shill::kConnectableProperty,
790 base::FundamentalValue(true));
791 } else {
792 services->SetServiceProperty(
793 kCellularServicePath,
794 shill::kActivationStateProperty,
795 base::StringValue(shill::kActivationStateNotActivated));
796 }
797
798 services->SetServiceProperty(kCellularServicePath,
799 shill::kRoamingStateProperty,
800 base::StringValue(shill::kRoamingStateHome));
801 }
802
803 // VPN
804 state = GetInitialStateForType(shill::kTypeVPN, &enabled);
805 if (state != kTechnologyUnavailable) {
806 // Set the "Provider" dictionary properties. Note: when setting these in
807 // Shill, "Provider.Type", etc keys are used, but when reading the values
808 // "Provider" . "Type", etc keys are used. Here we are setting the values
809 // that will be read (by the UI, tests, etc).
810 base::DictionaryValue provider_properties_openvpn;
811 provider_properties_openvpn.SetString(shill::kTypeProperty,
812 shill::kProviderOpenVpn);
813 provider_properties_openvpn.SetString(shill::kHostProperty, "vpn_host");
814
815 services->AddService("/service/vpn1",
816 "vpn1_guid",
817 "vpn1" /* name */,
818 shill::kTypeVPN,
819 state,
820 add_to_visible);
821 services->SetServiceProperty(
822 "/service/vpn1", shill::kProviderProperty, provider_properties_openvpn);
823 profiles->AddService(shared_profile, "/service/vpn1");
824
825 base::DictionaryValue provider_properties_l2tp;
826 provider_properties_l2tp.SetString(shill::kTypeProperty,
827 shill::kProviderL2tpIpsec);
828 provider_properties_l2tp.SetString(shill::kHostProperty, "vpn_host2");
829
830 services->AddService("/service/vpn2",
831 "vpn2_guid",
832 "vpn2" /* name */,
833 shill::kTypeVPN,
834 shill::kStateIdle,
835 add_to_visible);
836 services->SetServiceProperty(
837 "/service/vpn2", shill::kProviderProperty, provider_properties_l2tp);
838 }
839
840 // Additional device states
841 for (DevicePropertyMap::iterator iter1 = shill_device_property_map_.begin();
842 iter1 != shill_device_property_map_.end(); ++iter1) {
843 std::string device_type = iter1->first;
844 std::string device_path = devices->GetDevicePathForType(device_type);
845 for (ShillPropertyMap::iterator iter2 = iter1->second.begin();
846 iter2 != iter1->second.end(); ++iter2) {
847 devices->SetDeviceProperty(device_path, iter2->first, *(iter2->second));
848 delete iter2->second;
849 }
850 }
851
852 SortManagerServices(true);
853 }
854
855 // Private methods
856
PassStubProperties(const DictionaryValueCallback & callback) const857 void FakeShillManagerClient::PassStubProperties(
858 const DictionaryValueCallback& callback) const {
859 scoped_ptr<base::DictionaryValue> stub_properties(
860 stub_properties_.DeepCopy());
861 stub_properties->SetWithoutPathExpansion(
862 shill::kServiceCompleteListProperty,
863 GetEnabledServiceList(shill::kServiceCompleteListProperty));
864 callback.Run(DBUS_METHOD_CALL_SUCCESS, *stub_properties);
865 }
866
PassStubGeoNetworks(const DictionaryValueCallback & callback) const867 void FakeShillManagerClient::PassStubGeoNetworks(
868 const DictionaryValueCallback& callback) const {
869 callback.Run(DBUS_METHOD_CALL_SUCCESS, stub_geo_networks_);
870 }
871
CallNotifyObserversPropertyChanged(const std::string & property)872 void FakeShillManagerClient::CallNotifyObserversPropertyChanged(
873 const std::string& property) {
874 // Avoid unnecessary delayed task if we have no observers (e.g. during
875 // initial setup).
876 if (!observer_list_.might_have_observers())
877 return;
878 base::MessageLoop::current()->PostTask(
879 FROM_HERE,
880 base::Bind(&FakeShillManagerClient::NotifyObserversPropertyChanged,
881 weak_ptr_factory_.GetWeakPtr(),
882 property));
883 }
884
NotifyObserversPropertyChanged(const std::string & property)885 void FakeShillManagerClient::NotifyObserversPropertyChanged(
886 const std::string& property) {
887 DVLOG(1) << "NotifyObserversPropertyChanged: " << property;
888 base::Value* value = NULL;
889 if (!stub_properties_.GetWithoutPathExpansion(property, &value)) {
890 LOG(ERROR) << "Notify for unknown property: " << property;
891 return;
892 }
893 if (property == shill::kServiceCompleteListProperty) {
894 scoped_ptr<base::ListValue> services(GetEnabledServiceList(property));
895 FOR_EACH_OBSERVER(ShillPropertyChangedObserver,
896 observer_list_,
897 OnPropertyChanged(property, *(services.get())));
898 return;
899 }
900 FOR_EACH_OBSERVER(ShillPropertyChangedObserver,
901 observer_list_,
902 OnPropertyChanged(property, *value));
903 }
904
GetListProperty(const std::string & property)905 base::ListValue* FakeShillManagerClient::GetListProperty(
906 const std::string& property) {
907 base::ListValue* list_property = NULL;
908 if (!stub_properties_.GetListWithoutPathExpansion(
909 property, &list_property)) {
910 list_property = new base::ListValue;
911 stub_properties_.SetWithoutPathExpansion(property, list_property);
912 }
913 return list_property;
914 }
915
TechnologyEnabled(const std::string & type) const916 bool FakeShillManagerClient::TechnologyEnabled(const std::string& type) const {
917 if (type == shill::kTypeVPN)
918 return true; // VPN is always "enabled" since there is no associated device
919 if (type == shill::kTypeEthernetEap)
920 return true;
921 bool enabled = false;
922 const base::ListValue* technologies;
923 if (stub_properties_.GetListWithoutPathExpansion(
924 shill::kEnabledTechnologiesProperty, &technologies)) {
925 base::StringValue type_value(type);
926 if (technologies->Find(type_value) != technologies->end())
927 enabled = true;
928 }
929 return enabled;
930 }
931
SetTechnologyEnabled(const std::string & type,const base::Closure & callback,bool enabled)932 void FakeShillManagerClient::SetTechnologyEnabled(
933 const std::string& type,
934 const base::Closure& callback,
935 bool enabled) {
936 base::ListValue* enabled_list =
937 GetListProperty(shill::kEnabledTechnologiesProperty);
938 if (enabled)
939 enabled_list->AppendIfNotPresent(new base::StringValue(type));
940 else
941 enabled_list->Remove(base::StringValue(type), NULL);
942 CallNotifyObserversPropertyChanged(
943 shill::kEnabledTechnologiesProperty);
944 base::MessageLoop::current()->PostTask(FROM_HERE, callback);
945 // May affect available services.
946 SortManagerServices(true);
947 }
948
GetEnabledServiceList(const std::string & property) const949 base::ListValue* FakeShillManagerClient::GetEnabledServiceList(
950 const std::string& property) const {
951 base::ListValue* new_service_list = new base::ListValue;
952 const base::ListValue* service_list;
953 if (stub_properties_.GetListWithoutPathExpansion(property, &service_list)) {
954 ShillServiceClient::TestInterface* service_client =
955 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
956 for (base::ListValue::const_iterator iter = service_list->begin();
957 iter != service_list->end(); ++iter) {
958 std::string service_path;
959 if (!(*iter)->GetAsString(&service_path))
960 continue;
961 const base::DictionaryValue* properties =
962 service_client->GetServiceProperties(service_path);
963 if (!properties) {
964 LOG(ERROR) << "Properties not found for service: " << service_path;
965 continue;
966 }
967 std::string type;
968 properties->GetString(shill::kTypeProperty, &type);
969 if (TechnologyEnabled(type))
970 new_service_list->Append((*iter)->DeepCopy());
971 }
972 }
973 return new_service_list;
974 }
975
ScanCompleted(const std::string & device_path,const base::Closure & callback)976 void FakeShillManagerClient::ScanCompleted(const std::string& device_path,
977 const base::Closure& callback) {
978 if (!device_path.empty()) {
979 DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface()->
980 SetDeviceProperty(device_path,
981 shill::kScanningProperty,
982 base::FundamentalValue(false));
983 }
984 DVLOG(2) << "ScanCompleted";
985 CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
986 base::MessageLoop::current()->PostTask(FROM_HERE, callback);
987 }
988
ParseCommandLineSwitch()989 void FakeShillManagerClient::ParseCommandLineSwitch() {
990 // Default setup
991 SetInitialNetworkState(shill::kTypeEthernet, shill::kStateOnline);
992 SetInitialNetworkState(shill::kTypeWifi, shill::kStateOnline);
993 SetInitialNetworkState(shill::kTypeCellular, shill::kStateIdle);
994 SetInitialNetworkState(shill::kTypeVPN, shill::kStateIdle);
995
996 // Parse additional options
997 CommandLine* command_line = CommandLine::ForCurrentProcess();
998 if (!command_line->HasSwitch(switches::kShillStub))
999 return;
1000
1001 std::string option_str =
1002 command_line->GetSwitchValueASCII(switches::kShillStub);
1003 VLOG(1) << "Parsing command line:" << option_str;
1004 base::StringPairs string_pairs;
1005 base::SplitStringIntoKeyValuePairs(option_str, '=', ',', &string_pairs);
1006 for (base::StringPairs::iterator iter = string_pairs.begin();
1007 iter != string_pairs.end(); ++iter) {
1008 ParseOption((*iter).first, (*iter).second);
1009 }
1010 }
1011
ParseOption(const std::string & arg0,const std::string & arg1)1012 bool FakeShillManagerClient::ParseOption(const std::string& arg0,
1013 const std::string& arg1) {
1014 VLOG(1) << "Parsing command line option: '" << arg0 << "=" << arg1 << "'";
1015 if ((arg0 == "clear" || arg0 == "reset") && arg1 == "1") {
1016 shill_initial_state_map_.clear();
1017 return true;
1018 } else if (arg0 == "interactive") {
1019 int seconds = 3;
1020 if (!arg1.empty())
1021 base::StringToInt(arg1, &seconds);
1022 interactive_delay_ = seconds;
1023 return true;
1024 } else if (arg0 == "sim_lock") {
1025 bool locked = (arg1 == "1") ? true : false;
1026 base::DictionaryValue* simlock_dict = new base::DictionaryValue;
1027 simlock_dict->Set(shill::kSIMLockEnabledProperty,
1028 new base::FundamentalValue(locked));
1029 // TODO(stevenjb): Investigate why non-empty value breaks UI.
1030 std::string lock_type = ""; // shill::kSIMLockPin
1031 simlock_dict->SetString(shill::kSIMLockTypeProperty, lock_type);
1032 simlock_dict->SetInteger(shill::kSIMLockRetriesLeftProperty, 5);
1033
1034 shill_device_property_map_
1035 [shill::kTypeCellular][shill::kSIMLockStatusProperty] = simlock_dict;
1036 shill_device_property_map_
1037 [shill::kTypeCellular][shill::kTechnologyFamilyProperty] =
1038 new base::StringValue(shill::kNetworkTechnologyGsm);
1039 return true;
1040 }
1041 return SetInitialNetworkState(arg0, arg1);
1042 }
1043
SetInitialNetworkState(std::string type_arg,std::string state_arg)1044 bool FakeShillManagerClient::SetInitialNetworkState(std::string type_arg,
1045 std::string state_arg) {
1046 std::string state;
1047 state_arg = base::StringToLowerASCII(state_arg);
1048 if (state_arg.empty() || state_arg == "1" || state_arg == "on" ||
1049 state_arg == "enabled" || state_arg == "connected" ||
1050 state_arg == "online") {
1051 // Enabled and connected (default value)
1052 state = shill::kStateOnline;
1053 } else if (state_arg == "0" || state_arg == "off" ||
1054 state_arg == "inactive" || state_arg == shill::kStateIdle) {
1055 // Technology enabled, services are created but are not connected.
1056 state = shill::kStateIdle;
1057 } else if (state_arg == "disabled" || state_arg == "disconnect") {
1058 // Technology disabled but available, services created but not connected.
1059 state = kNetworkDisabled;
1060 } else if (state_arg == "none" || state_arg == "offline") {
1061 // Technology not available, do not create services.
1062 state = kTechnologyUnavailable;
1063 } else if (state_arg == "portal") {
1064 // Technology is enabled, a service is connected and in Portal state.
1065 state = shill::kStatePortal;
1066 } else if (state_arg == "active" || state_arg == "activated") {
1067 // Technology is enabled, a service is connected and Activated.
1068 state = kNetworkActivated;
1069 } else {
1070 LOG(ERROR) << "Unrecognized initial state: " << state_arg;
1071 return false;
1072 }
1073
1074 type_arg = base::StringToLowerASCII(type_arg);
1075 // Special cases
1076 if (type_arg == "wireless") {
1077 shill_initial_state_map_[shill::kTypeWifi] = state;
1078 shill_initial_state_map_[shill::kTypeCellular] = state;
1079 return true;
1080 }
1081 // Convenience synonyms.
1082 if (type_arg == "eth")
1083 type_arg = shill::kTypeEthernet;
1084
1085 if (type_arg != shill::kTypeEthernet &&
1086 type_arg != shill::kTypeWifi &&
1087 type_arg != shill::kTypeCellular &&
1088 type_arg != shill::kTypeWimax &&
1089 type_arg != shill::kTypeVPN) {
1090 LOG(WARNING) << "Unrecognized Shill network type: " << type_arg;
1091 return false;
1092 }
1093
1094 // Unconnected or disabled ethernet is the same as unavailable.
1095 if (type_arg == shill::kTypeEthernet &&
1096 (state == shill::kStateIdle || state == kNetworkDisabled)) {
1097 state = kTechnologyUnavailable;
1098 }
1099
1100 shill_initial_state_map_[type_arg] = state;
1101 return true;
1102 }
1103
GetInitialStateForType(const std::string & type,bool * enabled)1104 std::string FakeShillManagerClient::GetInitialStateForType(
1105 const std::string& type,
1106 bool* enabled) {
1107 std::map<std::string, std::string>::const_iterator iter =
1108 shill_initial_state_map_.find(type);
1109 if (iter == shill_initial_state_map_.end()) {
1110 *enabled = false;
1111 return kTechnologyUnavailable;
1112 }
1113 std::string state = iter->second;
1114 if (state == kNetworkDisabled) {
1115 *enabled = false;
1116 return shill::kStateIdle;
1117 }
1118 *enabled = true;
1119 if ((state == shill::kStatePortal && type != shill::kTypeWifi) ||
1120 (state == kNetworkActivated && type != shill::kTypeCellular)) {
1121 LOG(WARNING) << "Invalid state: " << state << " for " << type;
1122 return shill::kStateIdle;
1123 }
1124 return state;
1125 }
1126
1127 } // namespace chromeos
1128