diff options
author | Kevin Cernekee <cernekee@google.com> | 2016-05-01 20:33:47 -0700 |
---|---|---|
committer | Kevin Cernekee <cernekee@google.com> | 2016-05-15 13:57:24 -0700 |
commit | e5fb49474296421454309d1995890613a0da9ceb (patch) | |
tree | c530010dafbe1a796195d78aa3accc66254931ef | |
parent | 49f7411df36e849a34227ceb54610dea798a50af (diff) | |
download | shill-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.cc | 10 | ||||
-rw-r--r-- | manager.h | 4 | ||||
-rw-r--r-- | manager_unittest.cc | 36 | ||||
-rw-r--r-- | mock_service.h | 2 | ||||
-rw-r--r-- | service.cc | 6 | ||||
-rw-r--r-- | service.h | 4 |
6 files changed, 61 insertions, 1 deletions
@@ -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"); @@ -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. @@ -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); @@ -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(); |