summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Cernekee <cernekee@google.com>2016-05-01 20:33:47 -0700
committerKevin Cernekee <cernekee@google.com>2016-05-15 13:57:24 -0700
commite5fb49474296421454309d1995890613a0da9ceb (patch)
treec530010dafbe1a796195d78aa3accc66254931ef
parent49f7411df36e849a34227ceb54610dea798a50af (diff)
downloadshill-e5fb49474296421454309d1995890613a0da9ceb.tar.gz
Add Service::OnDefaultServiceStateChanged() callback
This allows VPNs to figure out when the default physical service has transitioned back to the Online state, so they can trigger a reconnection. Bug: None BUG=chromium:598781 TEST=`FEATURES=test emerge-link shill` Change-Id: I331eb12cbcd5f60c4fa1687d55fcca58331316fe
-rw-r--r--manager.cc10
-rw-r--r--manager.h4
-rw-r--r--manager_unittest.cc36
-rw-r--r--mock_service.h2
-rw-r--r--service.cc6
-rw-r--r--service.h4
6 files changed, 61 insertions, 1 deletions
diff --git a/manager.cc b/manager.cc
index afa07e9f..39cc8792 100644
--- a/manager.cc
+++ b/manager.cc
@@ -1466,6 +1466,16 @@ void Manager::UpdateService(const ServiceRefPtr& to_update) {
SortServices();
}
+void Manager::NotifyServiceStateChanged(const ServiceRefPtr& to_update) {
+ UpdateService(to_update);
+ if (to_update != last_default_physical_service_) {
+ return;
+ }
+ for (const auto& service : services_) {
+ service->OnDefaultServiceStateChanged(to_update);
+ }
+}
+
void Manager::UpdateDevice(const DeviceRefPtr& to_update) {
LOG(INFO) << "Device " << to_update->link_name() << " updated: "
<< (to_update->enabled_persistent() ? "enabled" : "disabled");
diff --git a/manager.h b/manager.h
index 772d6a14..6a1fca54 100644
--- a/manager.h
+++ b/manager.h
@@ -159,6 +159,9 @@ class Manager : public base::SupportsWeakPtr<Manager> {
// for disconnecting the Service before-hand.
virtual void DeregisterService(const ServiceRefPtr& to_forget);
virtual void UpdateService(const ServiceRefPtr& to_update);
+ // Called when any service's state changes. Informs other services
+ // (e.g. VPNs) if the default physical service's state has changed.
+ virtual void NotifyServiceStateChanged(const ServiceRefPtr& to_update);
// Persists |to_update| into an appropriate profile.
virtual void UpdateDevice(const DeviceRefPtr& to_update);
@@ -590,6 +593,7 @@ class Manager : public base::SupportsWeakPtr<Manager> {
FRIEND_TEST(ManagerTest, ConnectToBestServices);
FRIEND_TEST(ManagerTest, CreateConnectivityReport);
FRIEND_TEST(ManagerTest, DefaultTechnology);
+ FRIEND_TEST(ManagerTest, DefaultServiceStateChange);
FRIEND_TEST(ManagerTest, DetectMultiHomedDevices);
FRIEND_TEST(ManagerTest, DeviceClaimerVanishedTask);
FRIEND_TEST(ManagerTest, DevicePresenceStatusCheck);
diff --git a/manager_unittest.cc b/manager_unittest.cc
index 547bc6bd..7b1bd6a7 100644
--- a/manager_unittest.cc
+++ b/manager_unittest.cc
@@ -2760,6 +2760,42 @@ TEST_F(ManagerTest, UpdateDefaultServices) {
EXPECT_TRUE(manager()->default_service_callbacks_.empty());
}
+TEST_F(ManagerTest, DefaultServiceStateChange) {
+ MockMetrics mock_metrics(dispatcher());
+ SetMetrics(&mock_metrics);
+
+ scoped_refptr<MockService> mock_service0(
+ new NiceMock<MockService>(
+ control_interface(), dispatcher(), metrics(), manager()));
+ scoped_refptr<MockService> mock_service1(
+ new NiceMock<MockService>(
+ control_interface(), dispatcher(), metrics(), manager()));
+
+ manager()->RegisterService(mock_service0);
+ manager()->RegisterService(mock_service1);
+
+ EXPECT_CALL(mock_metrics, NotifyDefaultServiceChanged(mock_service0.get()));
+ manager()->UpdateDefaultServices(mock_service0, mock_service0);
+
+ // Changing the default service's state should notify both services.
+ EXPECT_CALL(*mock_service0.get(), OnDefaultServiceStateChanged(_));
+ EXPECT_CALL(*mock_service1.get(), OnDefaultServiceStateChanged(_));
+ manager()->NotifyServiceStateChanged(mock_service0);
+ Mock::VerifyAndClearExpectations(mock_service0.get());
+ Mock::VerifyAndClearExpectations(mock_service1.get());
+
+ // Changing the non-default service's state shouldn't notify anyone.
+ EXPECT_CALL(*mock_service0.get(), OnDefaultServiceStateChanged(_)).Times(0);
+ EXPECT_CALL(*mock_service1.get(), OnDefaultServiceStateChanged(_)).Times(0);
+ manager()->NotifyServiceStateChanged(mock_service1);
+
+ EXPECT_CALL(mock_metrics, NotifyDefaultServiceChanged(nullptr));
+ manager()->UpdateDefaultServices(nullptr, nullptr);
+
+ manager()->DeregisterService(mock_service1);
+ manager()->DeregisterService(mock_service0);
+}
+
TEST_F(ManagerTest, ReportServicesOnSameNetwork) {
int connection_id1 = 100;
int connection_id2 = 200;
diff --git a/mock_service.h b/mock_service.h
index 1ae54b3c..cdc96479 100644
--- a/mock_service.h
+++ b/mock_service.h
@@ -90,6 +90,8 @@ class MockService : public Service {
MOCK_METHOD0(EnableAndRetainAutoConnect, void());
MOCK_METHOD1(OnBeforeSuspend, void(const ResultCallback& callback));
MOCK_METHOD0(OnAfterResume, void());
+ MOCK_METHOD1(OnDefaultServiceStateChanged,
+ void(const ServiceRefPtr& service));
// Set a string for this Service via |store|. Can be wired to Save() for
// test purposes.
diff --git a/service.cc b/service.cc
index 522b54b6..256ec55b 100644
--- a/service.cc
+++ b/service.cc
@@ -440,7 +440,7 @@ void Service::SetState(ConnectState state) {
reenable_auto_connect_task_.Cancel();
}
UpdateErrorProperty();
- manager_->UpdateService(this);
+ manager_->NotifyServiceStateChanged(this);
metrics_->NotifyServiceStateChanged(*this, state);
adaptor_->EmitStringChanged(kStateProperty, GetStateString());
}
@@ -1232,6 +1232,10 @@ void Service::OnDarkResume() {
// Nothing to do in the general case.
}
+void Service::OnDefaultServiceStateChanged(const ServiceRefPtr& parent) {
+ // Nothing to do in the general case.
+}
+
string Service::GetIPConfigRpcIdentifier(Error* error) const {
if (!connection_) {
error->Populate(Error::kNotFound);
diff --git a/service.h b/service.h
index 125e31fa..e35d17d2 100644
--- a/service.h
+++ b/service.h
@@ -502,6 +502,10 @@ class Service : public base::RefCounted<Service> {
// Called by the manager once when entering dark resume.
virtual void OnDarkResume();
+ // Called by the manager when the default physical service's state has
+ // changed.
+ virtual void OnDefaultServiceStateChanged(const ServiceRefPtr& parent);
+
// Called by the manager to clear remembered state of being explicitly
// disconnected.
virtual void ClearExplicitlyDisconnected();