Implement {Available|Connected|Enabled}Technolgies and DefaultTechnology
This is Part 1 of a series of changes required for the Manager to generate
the right set of DBus events allowing shill to properly tell Chrome about
connectivity.
Some other side-effects in the change (needed to implement the above):
- Emit these manager properties over DBus everytime we re-sort the Service
vector.
- Add a technology data member to Device, this allows easy enumeration of
technologies.
- Add interface for getting a handle to the selected service on a device.
- Map connected state to online instead of ready state. This is needed for
so that Chrome doesn't wait for the portal detection code to switch the
state from ready->online.
- Default set the ethernet service as connectable.
BUG=chromium-os:14887
TEST=1) manual test to verify shill properly configures the ethernet
device and Chrome correctly detects that.
2) new unit tests
Change-Id: Ib10f2f0836f8d4aacaad1491f58ed9b3b5d37e7d
Reviewed-on: https://gerrit.chromium.org/gerrit/12019
Tested-by: Gaurav Shah <gauravsh@chromium.org>
Reviewed-by: mukesh agrawal <quiche@chromium.org>
diff --git a/adaptor_interfaces.h b/adaptor_interfaces.h
index 10e4f2c..640053f 100644
--- a/adaptor_interfaces.h
+++ b/adaptor_interfaces.h
@@ -47,11 +47,11 @@
// RPC interface to which the implementation is adapting.
virtual const std::string &GetRpcIdentifier() = 0;
- virtual void EmitBoolChanged(const std::string& name, bool value) = 0;
- virtual void EmitUintChanged(const std::string& name, uint32 value) = 0;
- virtual void EmitIntChanged(const std::string& name, int value) = 0;
- virtual void EmitStringChanged(const std::string& name,
- const std::string& value) = 0;
+ virtual void EmitBoolChanged(const std::string &name, bool value) = 0;
+ virtual void EmitUintChanged(const std::string &name, uint32 value) = 0;
+ virtual void EmitIntChanged(const std::string &name, int value) = 0;
+ virtual void EmitStringChanged(const std::string &name,
+ const std::string &value) = 0;
};
// These are the functions that a Manager adaptor must support
@@ -65,16 +65,18 @@
virtual void UpdateRunning() = 0;
- virtual void EmitBoolChanged(const std::string& name, bool value) = 0;
- virtual void EmitUintChanged(const std::string& name, uint32 value) = 0;
- virtual void EmitIntChanged(const std::string& name, int value) = 0;
- virtual void EmitStringChanged(const std::string& name,
- const std::string& value) = 0;
+ virtual void EmitBoolChanged(const std::string &name, bool value) = 0;
+ virtual void EmitUintChanged(const std::string &name, uint32 value) = 0;
+ virtual void EmitIntChanged(const std::string &name, int value) = 0;
+ virtual void EmitStringChanged(const std::string &name,
+ const std::string &value) = 0;
+ virtual void EmitStringsChanged(const std::string &name,
+ const std::vector<std::string> &value) = 0;
virtual void EmitRpcIdentifierArrayChanged(
const std::string &name,
const std::vector<std::string> &value) = 0;
- virtual void EmitStateChanged(const std::string& new_state) = 0;
+ virtual void EmitStateChanged(const std::string &new_state) = 0;
};
// These are the functions that a Profile adaptor must support
@@ -86,11 +88,11 @@
// RPC interface to which the implementation is adapting.
virtual const std::string &GetRpcIdentifier() = 0;
- virtual void EmitBoolChanged(const std::string& name, bool value) = 0;
- virtual void EmitUintChanged(const std::string& name, uint32 value) = 0;
- virtual void EmitIntChanged(const std::string& name, int value) = 0;
- virtual void EmitStringChanged(const std::string& name,
- const std::string& value) = 0;
+ virtual void EmitBoolChanged(const std::string &name, bool value) = 0;
+ virtual void EmitUintChanged(const std::string &name, uint32 value) = 0;
+ virtual void EmitIntChanged(const std::string &name, int value) = 0;
+ virtual void EmitStringChanged(const std::string &name,
+ const std::string &value) = 0;
};
// These are the functions that a Service adaptor must support
@@ -104,11 +106,11 @@
virtual void UpdateConnected() = 0;
- virtual void EmitBoolChanged(const std::string& name, bool value) = 0;
- virtual void EmitUintChanged(const std::string& name, uint32 value) = 0;
- virtual void EmitIntChanged(const std::string& name, int value) = 0;
- virtual void EmitStringChanged(const std::string& name,
- const std::string& value) = 0;
+ virtual void EmitBoolChanged(const std::string &name, bool value) = 0;
+ virtual void EmitUintChanged(const std::string &name, uint32 value) = 0;
+ virtual void EmitIntChanged(const std::string &name, int value) = 0;
+ virtual void EmitStringChanged(const std::string &name,
+ const std::string &value) = 0;
};
} // namespace shill
diff --git a/cellular.cc b/cellular.cc
index d8cf370..9b43507 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -31,6 +31,7 @@
#include "shill/property_accessor.h"
#include "shill/proxy_factory.h"
#include "shill/rtnl_handler.h"
+#include "shill/technology.h"
using std::map;
using std::string;
@@ -96,7 +97,8 @@
manager,
link_name,
address,
- interface_index),
+ interface_index,
+ Technology::kCellular),
proxy_factory_(ProxyFactory::GetInstance()),
state_(kStateDisabled),
modem_state_(kModemStateUnknown),
diff --git a/cellular_service.cc b/cellular_service.cc
index d27a360..2daf880 100644
--- a/cellular_service.cc
+++ b/cellular_service.cc
@@ -24,7 +24,7 @@
EventDispatcher *dispatcher,
Manager *manager,
const CellularRefPtr &device)
- : Service(control_interface, dispatcher, manager, flimflam::kTypeCellular),
+ : Service(control_interface, dispatcher, manager, Technology::kCellular),
strength_(0),
cellular_(device) {
PropertyStore *store = this->mutable_store();
diff --git a/device.cc b/device.cc
index 81adb00..ad9e766 100644
--- a/device.cc
+++ b/device.cc
@@ -30,6 +30,7 @@
#include "shill/rtnl_handler.h"
#include "shill/service.h"
#include "shill/store_interface.h"
+#include "shill/technology.h"
using base::StringPrintf;
using std::string;
@@ -48,7 +49,8 @@
Manager *manager,
const string &link_name,
const string &address,
- int interface_index)
+ int interface_index,
+ Technology::Identifier technology)
: powered_(true),
reconnect_(true),
hardware_address_(address),
@@ -60,6 +62,7 @@
dispatcher_(dispatcher),
manager_(manager),
adaptor_(control_interface->CreateDeviceAdaptor(this)),
+ technology_(technology),
dhcp_provider_(DHCPProvider::GetInstance()),
rtnl_handler_(RTNLHandler::GetInstance()) {
store_.RegisterConstString(flimflam::kAddressProperty, &hardware_address_);
@@ -180,6 +183,12 @@
"Device doesn't support ChangePIN.");
}
+bool Device::IsConnected() const {
+ if (selected_service_)
+ return selected_service_->IsConnected();
+ return false;
+}
+
string Device::GetRpcIdentifier() {
return adaptor_->GetRpcIdentifier();
}
diff --git a/device.h b/device.h
index bc8dd9d..299b0c6 100644
--- a/device.h
+++ b/device.h
@@ -41,7 +41,8 @@
Manager *manager,
const std::string &link_name,
const std::string &address,
- int interface_index);
+ int interface_index,
+ Technology::Identifier technology);
virtual ~Device();
virtual void Start();
@@ -51,6 +52,9 @@
// to Start()), or destroyed (if its refcount falls to zero).
virtual void Stop();
+
+ // TODO(gauravsh): We do not really need this since technology() can be used
+ // to get a device's technology for direct comparison.
// Base method always returns false.
virtual bool TechnologyIs(const Technology::Identifier type) const;
@@ -70,6 +74,11 @@
const std::string &new_pin,
Error *error);
+ // Returns true if the selected service on the device (if any) is connected.
+ // Returns false if there is no selected service, or if the selected service
+ // is not connected.
+ bool IsConnected() const;
+
std::string GetRpcIdentifier();
std::string GetStorageIdentifier();
@@ -78,6 +87,7 @@
int interface_index() const { return interface_index_; }
const ConnectionRefPtr &connection() const { return connection_; }
bool powered() const { return powered_; }
+ virtual Technology::Identifier technology() const { return technology_; }
const std::string &FriendlyName() const;
@@ -112,6 +122,8 @@
FRIEND_TEST(DeviceTest, SelectedService);
FRIEND_TEST(DeviceTest, Stop);
FRIEND_TEST(ManagerTest, DeviceRegistrationAndStart);
+ FRIEND_TEST(ManagerTest, ConnectedTechnologies);
+ FRIEND_TEST(ManagerTest, DefaultTechnology);
FRIEND_TEST(WiFiMainTest, Connect);
// If there's an IP configuration in |ipconfig_|, releases the IP address and
@@ -188,6 +200,7 @@
IPConfigRefPtr ipconfig_;
ConnectionRefPtr connection_;
scoped_ptr<DeviceAdaptorInterface> adaptor_;
+ Technology::Identifier technology_;
// Maintain a reference to the connected / connecting service
ServiceRefPtr selected_service_;
diff --git a/device_stub.h b/device_stub.h
index 840eb8c..bc866a1 100644
--- a/device_stub.h
+++ b/device_stub.h
@@ -34,16 +34,14 @@
int interface_index,
Technology::Identifier technology)
: Device(control_interface, dispatcher, manager, link_name, address,
- interface_index),
- technology_(technology) {}
+ interface_index, technology) {}
void Start() {}
void Stop() {}
bool TechnologyIs(const Technology::Identifier type) const {
- return type == technology_;
+ return type == technology();
}
private:
- Technology::Identifier technology_;
DISALLOW_COPY_AND_ASSIGN(DeviceStub);
};
diff --git a/device_unittest.cc b/device_unittest.cc
index 89493d6..20ca565 100644
--- a/device_unittest.cc
+++ b/device_unittest.cc
@@ -30,6 +30,7 @@
#include "shill/mock_service.h"
#include "shill/mock_store.h"
#include "shill/property_store_unittest.h"
+#include "shill/technology.h"
using std::map;
using std::string;
@@ -52,7 +53,8 @@
NULL,
kDeviceName,
kDeviceAddress,
- 0)) {
+ 0,
+ Technology::kUnknown)) {
DHCPProvider::GetInstance()->glib_ = glib();
DHCPProvider::GetInstance()->control_interface_ = control_interface();
}
diff --git a/ethernet.cc b/ethernet.cc
index f8e2b55..8fe8caf 100644
--- a/ethernet.cc
+++ b/ethernet.cc
@@ -37,7 +37,8 @@
manager,
link_name,
address,
- interface_index),
+ interface_index,
+ Technology::kEthernet),
service_registered_(false),
link_up_(false) {
VLOG(2) << "Ethernet device " << link_name << " initialized.";
diff --git a/ethernet_service.cc b/ethernet_service.cc
index a450460..07459b7 100644
--- a/ethernet_service.cc
+++ b/ethernet_service.cc
@@ -34,8 +34,9 @@
EventDispatcher *dispatcher,
Manager *manager,
const EthernetRefPtr &device)
- : Service(control_interface, dispatcher, manager, flimflam::kTypeEthernet),
+ : Service(control_interface, dispatcher, manager, Technology::kEthernet),
ethernet_(device) {
+ set_connectable(true);
set_auto_connect(true);
}
diff --git a/manager.cc b/manager.cc
index c9dda91..d7824ac 100644
--- a/manager.cc
+++ b/manager.cc
@@ -15,6 +15,7 @@
#include <base/file_util.h>
#include <base/logging.h>
#include <base/memory/ref_counted.h>
+#include <base/stl_util-inl.h>
#include <base/string_split.h>
#include <base/string_util.h>
#include <chromeos/dbus/service_constants.h>
@@ -38,6 +39,7 @@
#include "shill/wifi_service.h"
using std::map;
+using std::set;
using std::string;
using std::vector;
@@ -318,6 +320,12 @@
// unit tests sometimes do things in otherwise invalid states.
if (running_ && to_manage->powered())
to_manage->Start();
+
+ Error error;
+ adaptor_->EmitStringsChanged(flimflam::kAvailableTechnologiesProperty,
+ AvailableTechnologies(&error));
+ adaptor_->EmitStringsChanged(flimflam::kEnabledTechnologiesProperty,
+ EnabledTechnologies(&error));
}
void Manager::DeregisterDevice(const DeviceRefPtr &to_forget) {
@@ -327,6 +335,11 @@
VLOG(2) << "Deregistered device: " << to_forget->UniqueName();
to_forget->Stop();
devices_.erase(it);
+ Error error;
+ adaptor_->EmitStringsChanged(flimflam::kAvailableTechnologiesProperty,
+ AvailableTechnologies(&error));
+ adaptor_->EmitStringsChanged(flimflam::kEnabledTechnologiesProperty,
+ EnabledTechnologies(&error));
return;
}
}
@@ -429,6 +442,12 @@
}
adaptor_->EmitRpcIdentifierArrayChanged(flimflam::kServicesProperty,
service_paths);
+
+ Error error;
+ adaptor_->EmitStringsChanged(flimflam::kConnectedTechnologiesProperty,
+ ConnectedTechnologies(&error));
+ adaptor_->EmitStringChanged(flimflam::kDefaultTechnologyProperty,
+ DefaultTechnology(&error));
}
string Manager::CalculateState(Error */*error*/) {
@@ -436,19 +455,35 @@
}
vector<string> Manager::AvailableTechnologies(Error */*error*/) {
- return vector<string>();
+ set<string> unique_technologies;
+ for (vector<DeviceRefPtr>::iterator it = devices_.begin();
+ it != devices_.end(); ++it) {
+ unique_technologies.insert(
+ Technology::NameFromIdentifier((*it)->technology()));
+ }
+ return vector<string>(unique_technologies.begin(), unique_technologies.end());
}
vector<string> Manager::ConnectedTechnologies(Error */*error*/) {
- return vector<string>();
+ set<string> unique_technologies;
+ for (vector<DeviceRefPtr>::iterator it = devices_.begin();
+ it != devices_.end(); ++it) {
+ if ((*it)->IsConnected())
+ unique_technologies.insert(
+ Technology::NameFromIdentifier((*it)->technology()));
+ }
+ return vector<string>(unique_technologies.begin(), unique_technologies.end());
}
-string Manager::DefaultTechnology(Error */*error*/) {
- return "";
+string Manager::DefaultTechnology(Error *error) {
+ return (!services_.empty() && services_[0]->IsConnected()) ?
+ services_[0]->GetTechnologyString(error) : "";
}
-vector<string> Manager::EnabledTechnologies(Error */*error*/) {
- return vector<string>();
+vector<string> Manager::EnabledTechnologies(Error *error) {
+ // TODO(gauravsh): This must be wired up to the RPC interface to handle
+ // enabled/disabled devices as set by the user. crosbug.com/23319
+ return AvailableTechnologies(error);
}
vector<string> Manager::EnumerateDevices(Error */*error*/) {
diff --git a/manager.h b/manager.h
index 90c66af..b57cea4 100644
--- a/manager.h
+++ b/manager.h
@@ -99,6 +99,9 @@
FRIEND_TEST(ManagerTest, DeviceRegistrationAndStart);
FRIEND_TEST(ManagerTest, PushPopProfile);
FRIEND_TEST(ManagerTest, SortServices);
+ FRIEND_TEST(ManagerTest, AvailableTechnologies);
+ FRIEND_TEST(ManagerTest, ConnectedTechnologies);
+ FRIEND_TEST(ManagerTest, DefaultTechnology);
static const char kManagerErrorNoDevice[];
diff --git a/manager_dbus_adaptor.cc b/manager_dbus_adaptor.cc
index 27bba64..0bf611c 100644
--- a/manager_dbus_adaptor.cc
+++ b/manager_dbus_adaptor.cc
@@ -57,6 +57,11 @@
PropertyChanged(name, DBusAdaptor::StringToVariant(value));
}
+void ManagerDBusAdaptor::EmitStringsChanged(const string &name,
+ const vector<string> &value) {
+ PropertyChanged(name, DBusAdaptor::StringsToVariant(value));
+}
+
void ManagerDBusAdaptor::EmitRpcIdentifierArrayChanged(
const string &name,
const vector<string> &value) {
diff --git a/manager_dbus_adaptor.h b/manager_dbus_adaptor.h
index bc72273..d67128e 100644
--- a/manager_dbus_adaptor.h
+++ b/manager_dbus_adaptor.h
@@ -41,6 +41,8 @@
void EmitUintChanged(const std::string &name, uint32 value);
void EmitIntChanged(const std::string &name, int value);
void EmitStringChanged(const std::string &name, const std::string &value);
+ void EmitStringsChanged(const std::string &name,
+ const std::vector<std::string> &value);
void EmitRpcIdentifierArrayChanged(
const std::string &name, const std::vector<std::string> &value);
void EmitStateChanged(const std::string &new_state);
diff --git a/manager_unittest.cc b/manager_unittest.cc
index bf440cb..8a4d223 100644
--- a/manager_unittest.cc
+++ b/manager_unittest.cc
@@ -42,9 +42,11 @@
namespace shill {
using ::testing::_;
using ::testing::AnyNumber;
+using ::testing::ContainerEq;
using ::testing::Ne;
using ::testing::NiceMock;
using ::testing::Return;
+using ::testing::StrEq;
using ::testing::Test;
class ManagerTest : public PropertyStoreTest {
@@ -74,6 +76,12 @@
"null2",
"addr2",
2));
+ mock_devices_.push_back(new NiceMock<MockDevice>(control_interface(),
+ dispatcher(),
+ manager(),
+ "null3",
+ "addr3",
+ 3));
manager()->connect_profiles_to_rpc_ = false;
}
virtual ~ManagerTest() {}
@@ -200,18 +208,18 @@
ON_CALL(*mock_devices_[1].get(), TechnologyIs(Technology::kWifi))
.WillByDefault(Return(true));
- manager()->RegisterDevice(mock_devices_[0].get());
- manager()->RegisterDevice(mock_devices_[1].get());
+ manager()->RegisterDevice(mock_devices_[0]);
+ manager()->RegisterDevice(mock_devices_[1]);
ASSERT_TRUE(IsDeviceRegistered(mock_devices_[0], Technology::kEthernet));
ASSERT_TRUE(IsDeviceRegistered(mock_devices_[1], Technology::kWifi));
EXPECT_CALL(*mock_devices_[0].get(), Stop());
- manager()->DeregisterDevice(mock_devices_[0].get());
+ manager()->DeregisterDevice(mock_devices_[0]);
EXPECT_FALSE(IsDeviceRegistered(mock_devices_[0], Technology::kEthernet));
EXPECT_CALL(*mock_devices_[1].get(), Stop());
- manager()->DeregisterDevice(mock_devices_[1].get());
+ manager()->DeregisterDevice(mock_devices_[1]);
EXPECT_FALSE(IsDeviceRegistered(mock_devices_[1], Technology::kWifi));
}
@@ -354,8 +362,8 @@
TEST_F(ManagerTest, GetDevicesProperty) {
ProfileRefPtr profile(new MockProfile(control_interface(), manager(), ""));
AdoptProfile(manager(), profile);
- manager()->RegisterDevice(mock_devices_[0].get());
- manager()->RegisterDevice(mock_devices_[1].get());
+ manager()->RegisterDevice(mock_devices_[0]);
+ manager()->RegisterDevice(mock_devices_[1]);
{
map<string, ::DBus::Variant> props;
::DBus::Error dbus_error;
@@ -702,7 +710,7 @@
EXPECT_TRUE(error.IsSuccess());
EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
- // Priority
+ // Priority.
mock_service0->set_priority(1);
manager()->UpdateService(mock_service0);
EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
@@ -712,15 +720,19 @@
manager()->UpdateService(mock_service1);
EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
- // Connecting
+ // Connecting.
EXPECT_CALL(*mock_service0.get(), state())
.WillRepeatedly(Return(Service::kStateAssociating));
+ EXPECT_CALL(*mock_service0.get(), IsConnecting())
+ .WillRepeatedly(Return(true));
manager()->UpdateService(mock_service0);
EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
- // Connected
+ // Connected.
EXPECT_CALL(*mock_service1.get(), state())
.WillRepeatedly(Return(Service::kStateConnected));
+ EXPECT_CALL(*mock_service1.get(), IsConnected())
+ .WillRepeatedly(Return(true));
manager()->UpdateService(mock_service1);
EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
@@ -728,6 +740,134 @@
manager()->DeregisterService(mock_service1);
}
+TEST_F(ManagerTest, AvailableTechnologies) {
+ mock_devices_.push_back(new NiceMock<MockDevice>(control_interface(),
+ dispatcher(),
+ manager(),
+ "null4",
+ "addr4",
+ 0));
+ manager()->RegisterDevice(mock_devices_[0]);
+ manager()->RegisterDevice(mock_devices_[1]);
+ manager()->RegisterDevice(mock_devices_[2]);
+ manager()->RegisterDevice(mock_devices_[3]);
+
+ ON_CALL(*mock_devices_[0].get(), technology())
+ .WillByDefault(Return(Technology::kEthernet));
+ ON_CALL(*mock_devices_[1].get(), technology())
+ .WillByDefault(Return(Technology::kWifi));
+ ON_CALL(*mock_devices_[2].get(), technology())
+ .WillByDefault(Return(Technology::kCellular));
+ ON_CALL(*mock_devices_[3].get(), technology())
+ .WillByDefault(Return(Technology::kWifi));
+
+ set<string> expected_technologies;
+ expected_technologies.insert(Technology::NameFromIdentifier(
+ Technology::kEthernet));
+ expected_technologies.insert(Technology::NameFromIdentifier(
+ Technology::kWifi));
+ expected_technologies.insert(Technology::NameFromIdentifier(
+ Technology::kCellular));
+ Error error;
+ vector<string> technologies = manager()->AvailableTechnologies(&error);
+
+ EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
+ ContainerEq(expected_technologies));
+}
+
+TEST_F(ManagerTest, ConnectedTechnologies) {
+ scoped_refptr<MockService> connected_service1(
+ new NiceMock<MockService>(control_interface(),
+ dispatcher(),
+ manager()));
+ scoped_refptr<MockService> connected_service2(
+ new NiceMock<MockService>(control_interface(),
+ dispatcher(),
+ manager()));
+ scoped_refptr<MockService> disconnected_service1(
+ new NiceMock<MockService>(control_interface(),
+ dispatcher(),
+ manager()));
+ scoped_refptr<MockService> disconnected_service2(
+ new NiceMock<MockService>(control_interface(),
+ dispatcher(),
+ manager()));
+
+ ON_CALL(*connected_service1.get(), IsConnected())
+ .WillByDefault(Return(true));
+ ON_CALL(*connected_service2.get(), IsConnected())
+ .WillByDefault(Return(true));
+
+ manager()->RegisterService(connected_service1);
+ manager()->RegisterService(connected_service2);
+ manager()->RegisterService(disconnected_service1);
+ manager()->RegisterService(disconnected_service2);
+
+ manager()->RegisterDevice(mock_devices_[0]);
+ manager()->RegisterDevice(mock_devices_[1]);
+ manager()->RegisterDevice(mock_devices_[2]);
+ manager()->RegisterDevice(mock_devices_[3]);
+
+ ON_CALL(*mock_devices_[0].get(), technology())
+ .WillByDefault(Return(Technology::kEthernet));
+ ON_CALL(*mock_devices_[1].get(), technology())
+ .WillByDefault(Return(Technology::kWifi));
+ ON_CALL(*mock_devices_[2].get(), technology())
+ .WillByDefault(Return(Technology::kCellular));
+ ON_CALL(*mock_devices_[3].get(), technology())
+ .WillByDefault(Return(Technology::kWifi));
+
+ mock_devices_[0]->SelectService(connected_service1);
+ mock_devices_[1]->SelectService(disconnected_service1);
+ mock_devices_[2]->SelectService(disconnected_service2);
+ mock_devices_[3]->SelectService(connected_service2);
+
+ set<string> expected_technologies;
+ expected_technologies.insert(Technology::NameFromIdentifier(
+ Technology::kEthernet));
+ expected_technologies.insert(Technology::NameFromIdentifier(
+ Technology::kWifi));
+ Error error;
+
+ vector<string> technologies = manager()->ConnectedTechnologies(&error);
+ EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
+ ContainerEq(expected_technologies));
+}
+
+TEST_F(ManagerTest, DefaultTechnology) {
+ scoped_refptr<MockService> connected_service(
+ new NiceMock<MockService>(control_interface(),
+ dispatcher(),
+ manager()));
+ scoped_refptr<MockService> disconnected_service(
+ new NiceMock<MockService>(control_interface(),
+ dispatcher(),
+ manager()));
+
+ // Connected. WiFi.
+ ON_CALL(*connected_service.get(), IsConnected())
+ .WillByDefault(Return(true));
+ ON_CALL(*connected_service.get(), state())
+ .WillByDefault(Return(Service::kStateConnected));
+ ON_CALL(*connected_service.get(), technology())
+ .WillByDefault(Return(Technology::kWifi));
+
+ // Disconnected. Ethernet.
+ ON_CALL(*disconnected_service.get(), technology())
+ .WillByDefault(Return(Technology::kEthernet));
+
+ manager()->RegisterService(disconnected_service);
+ Error error;
+ EXPECT_THAT(manager()->DefaultTechnology(&error), StrEq(""));
+
+
+ manager()->RegisterService(connected_service);
+ // Connected service should be brought to the front now.
+ string expected_technology =
+ Technology::NameFromIdentifier(Technology::kWifi);
+ EXPECT_THAT(manager()->DefaultTechnology(&error), StrEq(expected_technology));
+}
+
TEST_F(ManagerTest, DisconnectServicesOnStop) {
scoped_refptr<MockService> mock_service(
new NiceMock<MockService>(control_interface(),
@@ -747,8 +887,8 @@
EXPECT_FALSE(mock_service->favorite());
EXPECT_FALSE(mock_service->auto_connect());
- EXPECT_CALL(*mock_service.get(), state())
- .WillRepeatedly(Return(Service::kStateConnected));
+ EXPECT_CALL(*mock_service.get(), IsConnected())
+ .WillRepeatedly(Return(true));
manager()->UpdateService(mock_service);
// We can't EXPECT_CALL(..., MakeFavorite), because that requires us
// to mock out MakeFavorite. And mocking that out would break the
diff --git a/mock_adaptors.h b/mock_adaptors.h
index a722fa7..84819c6 100644
--- a/mock_adaptors.h
+++ b/mock_adaptors.h
@@ -69,6 +69,8 @@
MOCK_METHOD2(EmitUintChanged, void(const std::string&, uint32));
MOCK_METHOD2(EmitIntChanged, void(const std::string&, int));
MOCK_METHOD2(EmitStringChanged, void(const std::string&, const std::string&));
+ MOCK_METHOD2(EmitStringsChanged,
+ void(const std::string &, const std::vector<std::string> &));
MOCK_METHOD2(EmitRpcIdentifierArrayChanged,
void(const std::string &, const std::vector<std::string> &));
diff --git a/mock_device.cc b/mock_device.cc
index 4e5187a..3abd7b6 100644
--- a/mock_device.cc
+++ b/mock_device.cc
@@ -16,6 +16,7 @@
class EventDispatcher;
using ::testing::_;
+using ::testing::DefaultValue;
using ::testing::Return;
using std::string;
@@ -30,8 +31,10 @@
manager,
link_name,
address,
- interface_index) {
+ interface_index,
+ Technology::kUnknown) {
ON_CALL(*this, TechnologyIs(_)).WillByDefault(Return(false));
+ DefaultValue<Technology::Identifier>::Set(Technology::kUnknown);
}
MockDevice::~MockDevice() {}
diff --git a/mock_device.h b/mock_device.h
index b5053ee..7a81659 100644
--- a/mock_device.h
+++ b/mock_device.h
@@ -31,6 +31,7 @@
bool(const Technology::Identifier technology));
MOCK_METHOD1(Load, bool(StoreInterface*));
MOCK_METHOD1(Save, bool(StoreInterface*));
+ MOCK_CONST_METHOD0(technology, Technology::Identifier());
private:
DISALLOW_COPY_AND_ASSIGN(MockDevice);
diff --git a/mock_service.cc b/mock_service.cc
index 5b44fda..2af9656 100644
--- a/mock_service.cc
+++ b/mock_service.cc
@@ -12,6 +12,7 @@
#include "shill/refptr_types.h"
#include "shill/store_interface.h"
+#include "shill/technology.h"
using std::string;
using testing::_;
@@ -26,7 +27,7 @@
MockService::MockService(ControlInterface *control_interface,
EventDispatcher *dispatcher,
Manager *manager)
- : Service(control_interface, dispatcher, manager, "mock") {
+ : Service(control_interface, dispatcher, manager, Technology::kUnknown) {
const string &id = UniqueName();
EXPECT_CALL(*this, GetRpcIdentifier()).WillRepeatedly(Return(id));
EXPECT_CALL(*this, GetStorageIdentifier()).WillRepeatedly(Return(id));
diff --git a/mock_service.h b/mock_service.h
index a9d738a..d58503c 100644
--- a/mock_service.h
+++ b/mock_service.h
@@ -10,6 +10,7 @@
#include "shill/refptr_types.h"
#include "shill/service.h"
+#include "shill/technology.h"
namespace shill {
@@ -26,8 +27,10 @@
MOCK_METHOD1(CalculateState, std::string(Error *error));
MOCK_CONST_METHOD1(TechnologyIs,
bool(const Technology::Identifier technology));
- MOCK_METHOD1(SetState, void(ConnectState state));
MOCK_CONST_METHOD0(state, ConnectState());
+ MOCK_METHOD1(SetState, void(ConnectState state));
+ MOCK_CONST_METHOD0(IsConnected, bool());
+ MOCK_CONST_METHOD0(IsConnecting, bool());
MOCK_METHOD1(SetFailure, void(ConnectFailure failure));
MOCK_CONST_METHOD0(failure, ConnectFailure());
MOCK_METHOD1(GetDeviceRpcId, std::string(Error *error));
@@ -35,7 +38,7 @@
MOCK_CONST_METHOD0(GetStorageIdentifier, std::string());
MOCK_METHOD1(Load, bool(StoreInterface *store_interface));
MOCK_METHOD1(Save, bool(StoreInterface *store_interface));
-
+ MOCK_CONST_METHOD0(technology, Technology::Identifier());
// Set a string for this Service via |store|. Can be wired to Save() for
// test purposes.
bool FauxSave(StoreInterface *store);
diff --git a/service.cc b/service.cc
index 66131f5..2fc1b3f 100644
--- a/service.cc
+++ b/service.cc
@@ -66,7 +66,7 @@
Service::Service(ControlInterface *control_interface,
EventDispatcher *dispatcher,
Manager *manager,
- const string &type)
+ Technology::Identifier technology)
: state_(kStateUnknown),
failure_(kFailureUnknown),
auto_connect_(false),
@@ -77,7 +77,7 @@
security_level_(0),
strength_(0),
save_credentials_(true),
- type_(type),
+ technology_(technology),
dispatcher_(dispatcher),
unique_name_(base::UintToString(serial_number_++)),
friendly_name_(unique_name_),
@@ -142,13 +142,14 @@
// store_.RegisterConstStringmap(flimflam::kProviderProperty, &provider_);
store_.RegisterBool(flimflam::kSaveCredentialsProperty, &save_credentials_);
- store_.RegisterConstString(flimflam::kTypeProperty, &type_);
+ HelpRegisterDerivedString(flimflam::kTypeProperty,
+ &Service::GetTechnologyString,
+ NULL);
// flimflam::kSecurityProperty: Registered in WiFiService
HelpRegisterDerivedString(flimflam::kStateProperty,
&Service::CalculateState,
NULL);
// flimflam::kSignalStrengthProperty: Registered in WiFi/CellularService
- // flimflam::kTypeProperty: Registered in all derived classes.
// flimflam::kWifiAuthMode: Registered in WiFiService
// flimflam::kWifiHiddenSsid: Registered in WiFiService
// flimflam::kWifiFrequency: Registered in WiFiService
@@ -354,6 +355,10 @@
// static
+string Service::GetTechnologyString(Error */*error*/) {
+ return Technology::NameFromIdentifier(technology());
+}
+
bool Service::DecideBetween(int a, int b, bool *decision) {
if (a == b)
return false;
@@ -418,7 +423,9 @@
case kStateConfiguring:
return flimflam::kStateConfiguration;
case kStateConnected:
- return flimflam::kStateReady;
+ // TODO(gauravsh): Until portal handling is implemented, go to "online"
+ // instead of "ready" state. crosbug.com/23318
+ return flimflam::kStateOnline;
case kStateDisconnected:
return flimflam::kStateDisconnect;
case kStateFailure:
diff --git a/service.h b/service.h
index 7cb1498..a5b5ece 100644
--- a/service.h
+++ b/service.h
@@ -90,7 +90,7 @@
Service(ControlInterface *control_interface,
EventDispatcher *dispatcher,
Manager *manager,
- const std::string &type);
+ Technology::Identifier technology);
virtual ~Service();
virtual void Connect(Error *error) = 0;
@@ -110,8 +110,8 @@
virtual void SetState(ConnectState state);
// State utility functions
- bool IsConnected() const { return state() == kStateConnected; }
- bool IsConnecting() const {
+ virtual bool IsConnected() const { return state() == kStateConnected; }
+ virtual bool IsConnecting() const {
return state() == kStateAssociating || state() == kStateConfiguring;
}
@@ -150,6 +150,9 @@
bool auto_connect() const { return auto_connect_; }
void set_auto_connect(bool connect) { auto_connect_ = connect; }
+ bool connectable() const { return connectable_; }
+ void set_connectable(bool connectable) { connectable_ = connectable; }
+
bool favorite() const { return favorite_; }
// Setter is deliberately omitted; use MakeFavorite.
@@ -164,6 +167,9 @@
int32 strength() const { return strength_; }
void set_strength(int32 strength) { strength_ = strength; }
+ virtual Technology::Identifier technology() const { return technology_; }
+ std::string GetTechnologyString(Error *error);
+
const std::string &error() const { return error_; }
void set_error(const std::string &error) { error_ = error; }
@@ -279,7 +285,7 @@
std::string proxy_config_;
bool save_credentials_;
EapCredentials eap_; // Only saved if |save_credentials_| is true.
- const std::string type_;
+ Technology::Identifier technology_;
ProfileRefPtr profile_;
PropertyStore store_;
diff --git a/service_under_test.cc b/service_under_test.cc
index dd915da..90aa893 100644
--- a/service_under_test.cc
+++ b/service_under_test.cc
@@ -20,7 +20,7 @@
ServiceUnderTest::ServiceUnderTest(ControlInterface *control_interface,
EventDispatcher *dispatcher,
Manager *manager)
- : Service(control_interface, dispatcher, manager, "stub") {
+ : Service(control_interface, dispatcher, manager, Technology::kUnknown) {
}
ServiceUnderTest::~ServiceUnderTest() {}
diff --git a/technology.cc b/technology.cc
index 1be4184..9e42618 100644
--- a/technology.cc
+++ b/technology.cc
@@ -14,7 +14,7 @@
const char Technology::kUnknownName[] = "Unknown";
-
+// static
Technology::Identifier Technology::IdentifierFromName(const std::string &name) {
if (name == flimflam::kTypeEthernet) {
return kEthernet;
@@ -27,6 +27,7 @@
}
}
+// static
std::string Technology::NameFromIdentifier(Technology::Identifier id) {
if (id == kEthernet) {
return flimflam::kTypeEthernet;
diff --git a/wifi.cc b/wifi.cc
index 34ea231..b0f1c41 100644
--- a/wifi.cc
+++ b/wifi.cc
@@ -34,6 +34,7 @@
#include "shill/store_interface.h"
#include "shill/supplicant_interface_proxy_interface.h"
#include "shill/supplicant_process_proxy_interface.h"
+#include "shill/technology.h"
#include "shill/wifi_endpoint.h"
#include "shill/wifi_service.h"
#include "shill/wpa_supplicant.h"
@@ -76,7 +77,8 @@
manager,
link,
address,
- interface_index),
+ interface_index,
+ Technology::kWifi),
proxy_factory_(ProxyFactory::GetInstance()),
task_factory_(this),
link_up_(false),
diff --git a/wifi_service.cc b/wifi_service.cc
index 7c1748c..a8173a0 100644
--- a/wifi_service.cc
+++ b/wifi_service.cc
@@ -41,7 +41,7 @@
const string &mode,
const string &security,
bool hidden_ssid)
- : Service(control_interface, dispatcher, manager, flimflam::kTypeWifi),
+ : Service(control_interface, dispatcher, manager, Technology::kWifi),
need_passphrase_(false),
security_(security),
mode_(mode),