shill: vpn: Conditionally build VPN support into shill.

VPN is disabled if SHILL_VPN=0 is passed to the Makefile.

BUG=chromium-os:39329
TEST=Together with I9e4d5741cbdcd99c9c109259167d87dbff04ee7a:
- FEATURES=test emerge-lumpy shill;
- After unmerging dependencies, FEATURES=test USE=-vpn emerge-lumpy shill
- Connected to OpenVPN successfully with default USE flags.
- Tested connectivity with shill with no VPN support.

Change-Id: I480a5911a4310ff9f80ca312db2a1bc3fe67bbd1
Reviewed-on: https://gerrit.chromium.org/gerrit/45740
Reviewed-by: Paul Stewart <pstew@chromium.org>
Commit-Queue: Darin Petkov <petkov@chromium.org>
Tested-by: Darin Petkov <petkov@chromium.org>
diff --git a/Makefile b/Makefile
index c3bfeee..420198e 100644
--- a/Makefile
+++ b/Makefile
@@ -45,8 +45,6 @@
 	libnetfilter_queue \
 	libnfnetlink
 NSS_GET_CERT_PC_DEPS = $(COMMON_PC_DEPS) nss
-OPENVPN_SCRIPT_PC_DEPS = $(COMMON_PC_DEPS) dbus-c++-1
-PPPD_PLUGIN_PC_DEPS = $(COMMON_PC_DEPS) dbus-c++-1
 SET_APN_HELPER_PC_DEPS = dbus-1
 INCLUDE_DIRS = \
 	-iquote.. \
@@ -55,8 +53,6 @@
 		$(NET_DIAGS_UPLOAD_PC_DEPS) \
 		$(NETFILTER_QUEUE_HELPER_PC_DEPS) \
 		$(NSS_GET_CERT_PC_DEPS) \
-		$(OPENVPN_SCRIPT_PC_DEPS) \
-		$(PPPD_PLUGIN_PC_DEPS) \
 		$(SET_APN_HELPER_PC_DEPS) \
 		$(SHILL_PC_DEPS))
 SHILL_LIBS = \
@@ -73,8 +69,6 @@
 NETFILTER_QUEUE_HELPER_LIBS = \
 	$(shell $(PKG_CONFIG) --libs $(NETFILTER_QUEUE_HELPER_PC_DEPS))
 NSS_GET_CERT_LIBS = $(shell $(PKG_CONFIG) --libs $(NSS_GET_CERT_PC_DEPS))
-OPENVPN_SCRIPT_LIBS = $(shell $(PKG_CONFIG) --libs $(OPENVPN_SCRIPT_PC_DEPS))
-PPPD_PLUGIN_LIBS = $(shell $(PKG_CONFIG) --libs $(PPPD_PLUGIN_PC_DEPS))
 SET_APN_HELPER_LIBS = $(shell $(PKG_CONFIG) --libs $(SET_APN_HELPER_PC_DEPS))
 TEST_LIBS = $(SHILL_LIBS) $(NSS_GET_CERT_LIBS) $(NETFILTER_QUEUE_HELPER_LIBS) \
 	-lgmock -lgtest
@@ -243,7 +237,6 @@
 	key_file_store.o \
 	key_value_store.o \
 	link_monitor.o \
-	l2tp_ipsec_driver.o \
 	manager.o \
 	manager_dbus_adaptor.o \
 	memory_log.o \
@@ -276,8 +269,6 @@
 	nl80211_message.o \
 	nl80211_socket.o \
 	nss.o \
-	openvpn_driver.o \
-	openvpn_management_server.o \
 	portal_detector.o \
 	power_manager.o \
 	power_manager_proxy.o \
@@ -375,7 +366,6 @@
 	ipconfig_unittest.o \
 	key_file_store_unittest.o \
 	key_value_store_unittest.o \
-	l2tp_ipsec_driver_unittest.o \
 	link_monitor_unittest.o \
 	manager_unittest.o \
 	memory_log_unittest.o \
@@ -430,8 +420,6 @@
 	mock_modem_proxy.o \
 	mock_modem_simple_proxy.o \
 	mock_nss.o \
-	mock_openvpn_driver.o \
-	mock_openvpn_management_server.o \
 	mock_portal_detector.o \
 	mock_power_manager.o \
 	mock_power_manager_proxy.o \
@@ -451,10 +439,7 @@
 	mock_supplicant_process_proxy.o \
 	mock_time.o \
 	mock_traffic_monitor.o \
-	mock_vpn.o \
-	mock_vpn_driver.o \
 	mock_vpn_provider.o \
-	mock_vpn_service.o \
 	mock_wifi.o \
 	mock_wifi_provider.o \
 	mock_wifi_service.o \
@@ -470,8 +455,6 @@
 	modem_unittest.o \
 	nice_mock_control.o \
 	nss_unittest.o \
-	openvpn_driver_unittest.o \
-	openvpn_management_server_unittest.o \
 	portal_detector_unittest.o \
 	power_manager_unittest.o \
 	process_killer_unittest.o \
@@ -490,16 +473,11 @@
 	service_unittest.o \
 	shill_unittest.o \
 	shims/certificates_unittest.o \
-	shims/environment_unittest.o \
 	shims/netfilter_queue_processor_unittest.o \
 	static_ip_parameters_unittest.o \
 	technology_unittest.o \
 	traffic_monitor_unittest.o \
 	testrunner.o \
-	vpn_driver_unittest.o \
-	vpn_provider_unittest.o \
-	vpn_service_unittest.o \
-	vpn_unittest.o \
 	wifi_endpoint_unittest.o \
 	wifi_provider_unittest.o \
 	wifi_service_unittest.o \
@@ -520,6 +498,29 @@
 NSS_GET_CERT_MAIN_OBJ = $(BUILD_SHIMS_DIR)/nss_get_cert.o
 NSS_GET_CERT_BIN = $(BUILD_SHIMS_DIR)/nss-get-cert
 
+SET_APN_HELPER_MAIN_OBJ = $(BUILD_SHIMS_DIR)/set_apn_helper.o
+SET_APN_HELPER_BIN = $(BUILD_SHIMS_DIR)/set-apn-helper
+
+WPA_SUPPLICANT_CONF = $(BUILD_SHIMS_DIR)/wpa_supplicant.conf
+
+# If SHILL_VPN=0, don't build VPN support into shill.
+ifeq ($(SHILL_VPN), 0)
+
+CPPFLAGS += -DDISABLE_VPN
+
+else
+
+OPENVPN_SCRIPT_PC_DEPS = $(COMMON_PC_DEPS) dbus-c++-1
+PPPD_PLUGIN_PC_DEPS = $(COMMON_PC_DEPS) dbus-c++-1
+
+INCLUDE_DIRS += \
+	$(shell $(PKG_CONFIG) --cflags \
+		$(OPENVPN_SCRIPT_PC_DEPS) \
+		$(PPPD_PLUGIN_PC_DEPS))
+
+OPENVPN_SCRIPT_LIBS = $(shell $(PKG_CONFIG) --libs $(OPENVPN_SCRIPT_PC_DEPS))
+PPPD_PLUGIN_LIBS = $(shell $(PKG_CONFIG) --libs $(PPPD_PLUGIN_PC_DEPS))
+
 OPENVPN_SCRIPT_OBJS = $(addprefix $(BUILD_SHIMS_DIR)/, \
 	environment.o \
 	task_proxy.o \
@@ -536,10 +537,40 @@
 	)
 PPPD_PLUGIN_SO = $(BUILD_SHIMS_DIR)/shill-pppd-plugin.so
 
-SET_APN_HELPER_MAIN_OBJ = $(BUILD_SHIMS_DIR)/set_apn_helper.o
-SET_APN_HELPER_BIN = $(BUILD_SHIMS_DIR)/set-apn-helper
+SHILL_OBJS += $(addprefix $(BUILDDIR)/, \
+	l2tp_ipsec_driver.o \
+	openvpn_driver.o \
+	openvpn_management_server.o \
+	)
 
-WPA_SUPPLICANT_CONF = $(BUILD_SHIMS_DIR)/wpa_supplicant.conf
+TEST_OBJS += $(addprefix $(BUILDDIR)/, \
+	l2tp_ipsec_driver_unittest.o \
+	mock_openvpn_driver.o \
+	mock_openvpn_management_server.o \
+	mock_vpn.o \
+	mock_vpn_driver.o \
+	mock_vpn_service.o \
+	openvpn_driver_unittest.o \
+	openvpn_management_server_unittest.o \
+	shims/environment_unittest.o \
+	vpn_driver_unittest.o \
+	vpn_provider_unittest.o \
+	vpn_service_unittest.o \
+	vpn_unittest.o \
+	)
+
+$(OPENVPN_SCRIPT_OBJS): $(DBUS_PROXY_BINDINGS)
+$(OPENVPN_SCRIPT_MAIN_OBJ): $(DBUS_PROXY_BINDINGS)
+
+$(OPENVPN_SCRIPT_BIN): $(OPENVPN_SCRIPT_MAIN_OBJ) $(OPENVPN_SCRIPT_OBJS)
+	$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ $(OPENVPN_SCRIPT_LIBS) -o $@
+
+$(PPPD_PLUGIN_OBJS): $(DBUS_PROXY_BINDINGS)
+
+$(PPPD_PLUGIN_SO): $(PPPD_PLUGIN_OBJS)
+	$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $^ $(PPPD_PLUGIN_LIBS) -o $@
+
+endif  # SHILL_VPN=0
 
 OBJS = \
 	$(NET_DIAGS_UPLOAD_MAIN_OBJ) \
@@ -628,17 +659,6 @@
 $(NSS_GET_CERT_BIN): $(NSS_GET_CERT_MAIN_OBJ) $(NSS_GET_CERT_OBJS) $(SHILL_LIB)
 	$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ $(NSS_GET_CERT_LIBS) -o $@
 
-$(OPENVPN_SCRIPT_OBJS): $(DBUS_PROXY_BINDINGS)
-$(OPENVPN_SCRIPT_MAIN_OBJ): $(DBUS_PROXY_BINDINGS)
-
-$(OPENVPN_SCRIPT_BIN): $(OPENVPN_SCRIPT_MAIN_OBJ) $(OPENVPN_SCRIPT_OBJS)
-	$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ $(OPENVPN_SCRIPT_LIBS) -o $@
-
-$(PPPD_PLUGIN_OBJS): $(DBUS_PROXY_BINDINGS)
-
-$(PPPD_PLUGIN_SO): $(PPPD_PLUGIN_OBJS)
-	$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $^ $(PPPD_PLUGIN_LIBS) -o $@
-
 $(SET_APN_HELPER_BIN): $(SET_APN_HELPER_MAIN_OBJ)
 	$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ $(SET_APN_HELPER_LIBS) -o $@
 
diff --git a/device_info.cc b/device_info.cc
index d0a3aa3..2c1b269 100644
--- a/device_info.cc
+++ b/device_info.cc
@@ -41,6 +41,7 @@
 #include "shill/service.h"
 #include "shill/sockets.h"
 #include "shill/virtio_ethernet.h"
+#include "shill/vpn_provider.h"
 #include "shill/wifi.h"
 
 using base::Bind;
diff --git a/device_info_unittest.cc b/device_info_unittest.cc
index eae3a0a..055cfd7 100644
--- a/device_info_unittest.cc
+++ b/device_info_unittest.cc
@@ -117,6 +117,11 @@
     device_info_.set_sockets(mock_sockets_);
   }
 
+  // Takes ownership of |provider|.
+  void SetVPNProvider(VPNProvider *provider) {
+    manager_.vpn_provider_.reset(provider);
+  }
+
  protected:
   static const int kTestDeviceIndex;
   static const char kTestDeviceName[];
@@ -452,9 +457,9 @@
   IPAddress address = CreateInterfaceAddress();
 
   // A VPN device should be offered to VPNProvider.
-  StrictMock<MockVPNProvider> vpn_provider;
-  EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
-  EXPECT_CALL(vpn_provider,
+  MockVPNProvider *vpn_provider = new StrictMock<MockVPNProvider>;
+  SetVPNProvider(vpn_provider);
+  EXPECT_CALL(*vpn_provider,
               OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
       .WillOnce(Return(true));
   EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
@@ -469,9 +474,9 @@
   IPAddress address = CreateInterfaceAddress();
 
   // A VPN device should be offered to VPNProvider.
-  StrictMock<MockVPNProvider> vpn_provider;
-  EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
-  EXPECT_CALL(vpn_provider,
+  MockVPNProvider *vpn_provider = new StrictMock<MockVPNProvider>;
+  SetVPNProvider(vpn_provider);
+  EXPECT_CALL(*vpn_provider,
               OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
       .WillOnce(Return(false));
   EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
@@ -488,9 +493,9 @@
   IPAddress address = CreateInterfaceAddress();
 
   // A VPN device should be offered to VPNProvider.
-  StrictMock<MockVPNProvider> vpn_provider;
-  EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
-  EXPECT_CALL(vpn_provider,
+  MockVPNProvider *vpn_provider = new StrictMock<MockVPNProvider>;
+  SetVPNProvider(vpn_provider);
+  EXPECT_CALL(*vpn_provider,
               OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
       .WillOnce(Return(false));
   EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
diff --git a/manager.cc b/manager.cc
index ff453d0..c1bf9ff 100644
--- a/manager.cc
+++ b/manager.cc
@@ -41,6 +41,7 @@
 #include "shill/resolver.h"
 #include "shill/service.h"
 #include "shill/service_sorter.h"
+#include "shill/vpn_provider.h"
 #include "shill/vpn_service.h"
 #include "shill/wifi.h"
 #include "shill/wifi_provider.h"
@@ -90,7 +91,8 @@
       adaptor_(control_interface->CreateManagerAdaptor(this)),
       device_info_(control_interface, dispatcher, metrics, this),
       modem_info_(control_interface, dispatcher, metrics, this, glib),
-      vpn_provider_(control_interface, dispatcher, metrics, this),
+      vpn_provider_(
+          new VPNProvider(control_interface, dispatcher, metrics, this)),
       wifi_provider_(
           new WiFiProvider(control_interface, dispatcher, metrics, this)),
       wimax_provider_(control_interface, dispatcher, metrics, this),
@@ -205,7 +207,7 @@
   adaptor_->UpdateRunning();
   device_info_.Start();
   modem_info_.Start();
-  vpn_provider_.Start();
+  vpn_provider_->Start();
   wifi_provider_->Start();
   wimax_provider_.Start();
 }
@@ -239,7 +241,7 @@
   adaptor_->UpdateRunning();
   wimax_provider_.Stop();
   wifi_provider_->Stop();
-  vpn_provider_.Stop();
+  vpn_provider_->Stop();
   modem_info_.Stop();
   device_info_.Stop();
   sort_services_task_.Cancel();
@@ -405,7 +407,7 @@
 
   // Offer the Profile contents to the service/device providers which will
   // create new services if necessary.
-  vpn_provider_.CreateServicesFromProfile(profile);
+  vpn_provider_->CreateServicesFromProfile(profile);
   wifi_provider_->CreateServicesFromProfile(profile);
   wimax_provider_.CreateServicesFromProfile(profile);
 
@@ -1446,7 +1448,7 @@
   string type = args.GetString(flimflam::kTypeProperty);
   if (type == flimflam::kTypeVPN) {
     SLOG(Manager, 2) << __func__ << ": getting VPN Service";
-    return vpn_provider_.GetService(args, error);
+    return vpn_provider_->GetService(args, error);
   }
   if (type == flimflam::kTypeWifi) {
     SLOG(Manager, 2) << __func__ << ": getting WiFi Service";
diff --git a/manager.h b/manager.h
index 4c1beba..ae33d39 100644
--- a/manager.h
+++ b/manager.h
@@ -28,7 +28,6 @@
 #include "shill/power_manager.h"
 #include "shill/property_store.h"
 #include "shill/service.h"
-#include "shill/vpn_provider.h"
 #include "shill/wifi.h"
 #include "shill/wimax_provider.h"
 
@@ -42,6 +41,7 @@
 class ManagerAdaptorInterface;
 class Resolver;
 class StoreInterface;
+class VPNProvider;
 class WiFiProvider;
 
 class Manager : public base::SupportsWeakPtr<Manager> {
@@ -228,8 +228,8 @@
   virtual DeviceInfo *device_info() { return &device_info_; }
   virtual ModemInfo *modem_info() { return &modem_info_; }
   PowerManager *power_manager() const { return power_manager_.get(); }
-  virtual VPNProvider *vpn_provider() { return &vpn_provider_; }
-  virtual WiFiProvider *wifi_provider() { return wifi_provider_.get(); }
+  VPNProvider *vpn_provider() const { return vpn_provider_.get(); }
+  WiFiProvider *wifi_provider() const { return wifi_provider_.get(); }
   virtual WiMaxProvider *wimax_provider() { return &wimax_provider_; }
   PropertyStore *mutable_store() { return &store_; }
   virtual const PropertyStore &store() const { return store_; }
@@ -332,9 +332,11 @@
 
  private:
   friend class CellularTest;
+  friend class DeviceInfoTest;
   friend class ManagerAdaptorInterface;
   friend class ManagerTest;
   friend class ServiceTest;
+  friend class VPNServiceTest;
   friend class WiFiObjectTest;
   friend class WiMaxProviderTest;
 
@@ -450,7 +452,7 @@
   scoped_ptr<DBusManager> dbus_manager_;
   DeviceInfo device_info_;
   ModemInfo modem_info_;
-  VPNProvider vpn_provider_;
+  scoped_ptr<VPNProvider> vpn_provider_;
   scoped_ptr<WiFiProvider> wifi_provider_;
   WiMaxProvider wimax_provider_;
   // Hold pointer to singleton Resolver instance for testing purposes.
diff --git a/manager_unittest.cc b/manager_unittest.cc
index b131304..c4fe1a8 100644
--- a/manager_unittest.cc
+++ b/manager_unittest.cc
@@ -1422,6 +1422,15 @@
       new StrictMock<MockProfile>(
           control_interface(), metrics(), manager(), ""));
   AdoptProfile(manager(), profile);
+
+#if defined(DISABLE_VPN)
+
+  ServiceRefPtr service = manager()->GetService(args, &e);
+  EXPECT_EQ(Error::kNotSupported, e.type());
+  EXPECT_FALSE(service);
+
+#else
+
   ServiceRefPtr updated_service;
   EXPECT_CALL(*profile, UpdateService(_))
       .WillOnce(DoAll(SaveArg<0>(&updated_service), Return(true)));
@@ -1435,6 +1444,8 @@
   EXPECT_TRUE(service);
   EXPECT_EQ(service, updated_service);
   EXPECT_EQ(service, configured_service);
+
+#endif  // DISABLE_VPN
 }
 
 TEST_F(ManagerTest, GetServiceWiMaxNoNetworkId) {
diff --git a/mock_manager.h b/mock_manager.h
index 93ec19e..b54744b 100644
--- a/mock_manager.h
+++ b/mock_manager.h
@@ -22,7 +22,6 @@
 
   MOCK_METHOD0(device_info, DeviceInfo *());
   MOCK_METHOD0(modem_info, ModemInfo *());
-  MOCK_METHOD0(vpn_provider, VPNProvider *());
   MOCK_METHOD0(wimax_provider, WiMaxProvider *());
   MOCK_METHOD0(mutable_store, PropertyStore *());
   MOCK_CONST_METHOD0(store, const PropertyStore &());
diff --git a/vpn_provider.cc b/vpn_provider.cc
index 754b1a1..dbadcbc 100644
--- a/vpn_provider.cc
+++ b/vpn_provider.cc
@@ -144,6 +144,13 @@
                                             Error *error) {
   SLOG(VPN, 2) << __func__ << " type " << type << " name " << name
                << " storage id " << storage_id;
+#if defined(DISABLE_VPN)
+
+  Error::PopulateAndLog(error, Error::kNotSupported, "VPN is not supported.");
+  return NULL;
+
+#else
+
   scoped_ptr<VPNDriver> driver;
   if (type == flimflam::kProviderOpenVpn) {
     driver.reset(new OpenVPNDriver(
@@ -170,6 +177,8 @@
   manager_->RegisterService(service);
 
   return service;
+
+#endif  // DISABLE_VPN
 }
 
 VPNServiceRefPtr VPNProvider::FindService(const std::string &type,
diff --git a/vpn_service.cc b/vpn_service.cc
index e5cdc0c..f9a9d30 100644
--- a/vpn_service.cc
+++ b/vpn_service.cc
@@ -14,6 +14,7 @@
 #include "shill/manager.h"
 #include "shill/technology.h"
 #include "shill/vpn_driver.h"
+#include "shill/vpn_provider.h"
 
 using base::Bind;
 using base::StringPrintf;
diff --git a/vpn_service_unittest.cc b/vpn_service_unittest.cc
index dab06fe..5507ecd 100644
--- a/vpn_service_unittest.cc
+++ b/vpn_service_unittest.cc
@@ -84,6 +84,11 @@
     return service_->IsAutoConnectable(reason);
   }
 
+  // Takes ownership of |provider|.
+  void SetVPNProvider(VPNProvider *provider) {
+    manager_.vpn_provider_.reset(provider);
+  }
+
   std::string interface_name_;
   std::string ipconfig_rpc_identifier_;
   MockVPNDriver *driver_;  // Owned by |service_|.
@@ -195,13 +200,13 @@
   service_->set_save_credentials(true);
   EXPECT_CALL(*driver_, Disconnect());
   EXPECT_CALL(*driver_, UnloadCredentials());
-  MockVPNProvider provider;
-  EXPECT_CALL(manager_, vpn_provider()).WillRepeatedly(Return(&provider));
-  provider.services_.push_back(service_);
+  MockVPNProvider *provider = new MockVPNProvider;
+  SetVPNProvider(provider);
+  provider->services_.push_back(service_);
   service_->Unload();
   EXPECT_FALSE(service_->auto_connect());
   EXPECT_FALSE(service_->save_credentials());
-  EXPECT_TRUE(provider.services_.empty());
+  EXPECT_TRUE(provider->services_.empty());
 }
 
 TEST_F(VPNServiceTest, InitPropertyStore) {
@@ -257,9 +262,9 @@
   EXPECT_TRUE(service_->connectable());
   SetHasEverConnected(true);
   EXPECT_CALL(manager_, IsOnline()).WillOnce(Return(true));
-  MockVPNProvider provider;
-  EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&provider));
-  EXPECT_CALL(provider, HasActiveService()).WillOnce(Return(true));
+  MockVPNProvider *provider = new MockVPNProvider;
+  SetVPNProvider(provider);
+  EXPECT_CALL(*provider, HasActiveService()).WillOnce(Return(true));
   const char *reason = NULL;
   EXPECT_FALSE(IsAutoConnectable(&reason));
   EXPECT_STREQ(GetAutoConnVPNAlreadyActive(), reason);
@@ -275,9 +280,9 @@
   EXPECT_TRUE(service_->connectable());
   SetHasEverConnected(true);
   EXPECT_CALL(manager_, IsOnline()).WillOnce(Return(true));
-  MockVPNProvider provider;
-  EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&provider));
-  EXPECT_CALL(provider, HasActiveService()).WillOnce(Return(false));
+  MockVPNProvider *provider = new MockVPNProvider;
+  SetVPNProvider(provider);
+  EXPECT_CALL(*provider, HasActiveService()).WillOnce(Return(false));
   const char *reason = NULL;
   EXPECT_TRUE(IsAutoConnectable(&reason));
   EXPECT_FALSE(reason);