shill: vpn: Return service from VPNProvider's service_ list

BUG=chromium-os:28157
TEST=New unit test

Change-Id: Id2f1f5f336fd47d3d0c769789151386306c21c0a
Reviewed-on: https://gerrit.chromium.org/gerrit/19844
Reviewed-by: Darin Petkov <petkov@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/mock_vpn_driver.h b/mock_vpn_driver.h
index 45b2e0c..d08ef7f 100644
--- a/mock_vpn_driver.h
+++ b/mock_vpn_driver.h
@@ -25,6 +25,7 @@
   MOCK_METHOD2(Save, bool(StoreInterface *storage,
                           const std::string &storage_id));
   MOCK_METHOD1(InitPropertyStore, void(PropertyStore *store));
+  MOCK_CONST_METHOD0(GetProviderType, std::string());
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockVPNDriver);
diff --git a/openvpn_driver.cc b/openvpn_driver.cc
index be68cfa..2f55edd 100644
--- a/openvpn_driver.cc
+++ b/openvpn_driver.cc
@@ -668,6 +668,10 @@
   // crosbug.com/27323
 }
 
+string OpenVPNDriver::GetProviderType() const {
+  return flimflam::kProviderOpenVpn;
+}
+
 void OpenVPNDriver::ClearMappedProperty(const size_t &index,
                                         Error *error) {
   CHECK(index < arraysize(kProperties));
diff --git a/openvpn_driver.h b/openvpn_driver.h
index c325b10..d5cedb5 100644
--- a/openvpn_driver.h
+++ b/openvpn_driver.h
@@ -62,6 +62,9 @@
   virtual void OnReconnecting();
 
   virtual void InitPropertyStore(PropertyStore *store);
+
+  virtual std::string GetProviderType() const;
+
   void ClearMappedProperty(const size_t &index, Error *error);
   std::string GetMappedProperty(const size_t &index, Error *error);
   void SetMappedProperty(const size_t &index,
diff --git a/vpn_driver.h b/vpn_driver.h
index bf5013d..19a0bd9 100644
--- a/vpn_driver.h
+++ b/vpn_driver.h
@@ -28,6 +28,7 @@
   virtual bool Load(StoreInterface *storage, const std::string &storage_id) = 0;
   virtual bool Save(StoreInterface *storage, const std::string &storage_id) = 0;
   virtual void InitPropertyStore(PropertyStore *store) = 0;
+  virtual std::string GetProviderType() const = 0;
 };
 
 }  // namespace shill
diff --git a/vpn_provider.cc b/vpn_provider.cc
index 13c4464..4f4ae2b 100644
--- a/vpn_provider.cc
+++ b/vpn_provider.cc
@@ -49,6 +49,16 @@
     return NULL;
   }
 
+  // Find a service in the provider list which matches these parameters.
+  for (vector<VPNServiceRefPtr>::const_iterator it = services_.begin();
+       it != services_.end();
+       ++it) {
+    if (type == (*it)->driver()->GetProviderType() &&
+        (*it)->GetStorageIdentifier() == storage_id) {
+      return *it;
+    }
+  }
+
   scoped_ptr<VPNDriver> driver;
   if (type == flimflam::kProviderOpenVpn) {
     driver.reset(new OpenVPNDriver(
diff --git a/vpn_provider_unittest.cc b/vpn_provider_unittest.cc
index d2604db..246c4d0 100644
--- a/vpn_provider_unittest.cc
+++ b/vpn_provider_unittest.cc
@@ -75,11 +75,16 @@
   args.SetString(flimflam::kProviderNameProperty, kName);
   EXPECT_CALL(manager_, device_info()).WillOnce(Return(&device_info_));
   EXPECT_CALL(manager_, RegisterService(_));
-  VPNServiceRefPtr service = provider_.GetService(args, &e);
+  VPNServiceRefPtr service0 = provider_.GetService(args, &e);
   EXPECT_TRUE(e.IsSuccess());
-  ASSERT_TRUE(service);
-  EXPECT_EQ("vpn_10_8_0_1_vpn_name", service->GetStorageIdentifier());
-  EXPECT_EQ(kName, service->friendly_name());
+  ASSERT_TRUE(service0);
+  EXPECT_EQ("vpn_10_8_0_1_vpn_name", service0->GetStorageIdentifier());
+  EXPECT_EQ(kName, service0->friendly_name());
+
+  // A second call should return the same service.
+  VPNServiceRefPtr service1 = provider_.GetService(args, &e);
+  EXPECT_TRUE(e.IsSuccess());
+  ASSERT_EQ(service0.get(), service1.get());
 }
 
 TEST_F(VPNProviderTest, OnDeviceInfoAvailable) {