shill: Implement Service.Remove & delete DHCP leases

Implement the Service.Remove dbus API and modify the unload sequence to
remove the DHCP lease file. Add unit tests to DHCPProvider & WiFiService to
check lease file deletion. Currently only WiFi does the DHCP lease delete
from DBus - WiMax/Cell/VPN do their own things for IP configuration and
Ethernet can't be removed as per the API spec.

Also make sure FilePath is qualified as base::FilePath throughout the project.

BUG=chromium-os:32756
TEST=added unittests to test the call path on Unload() to delete the lease file

Change-Id: Ic6eee17b9d81cd0be8d09c683d85d6a4d19278c9
Reviewed-on: https://gerrit.chromium.org/gerrit/44339
Tested-by: Albert Chaulk <achaulk@chromium.org>
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Queue: Albert Chaulk <achaulk@chromium.org>
diff --git a/activating_iccid_store.cc b/activating_iccid_store.cc
index 4762098..536f385 100644
--- a/activating_iccid_store.cc
+++ b/activating_iccid_store.cc
@@ -7,6 +7,7 @@
 #include "shill/key_file_store.h"
 #include "shill/logging.h"
 
+using base::FilePath;
 using std::string;
 
 namespace shill {
diff --git a/activating_iccid_store.h b/activating_iccid_store.h
index 1339900..248b5c0 100644
--- a/activating_iccid_store.h
+++ b/activating_iccid_store.h
@@ -53,7 +53,7 @@
   // open will allways be flushed and closed, however it is not guaranteed that
   // the file will always be successfully reopened (technically it should, but
   // it is not guaranteed).
-  virtual bool InitStorage(GLib *glib, const FilePath &storage_path);
+  virtual bool InitStorage(GLib *glib, const base::FilePath &storage_path);
 
   // Returns the activation state for a SIM with the given ICCID. A return value
   // of kStateUnknown indicates that the given ICCID was not found.
diff --git a/activating_iccid_store_unittest.cc b/activating_iccid_store_unittest.cc
index 02f0181..8dc49b1 100644
--- a/activating_iccid_store_unittest.cc
+++ b/activating_iccid_store_unittest.cc
@@ -12,6 +12,7 @@
 #include "shill/glib.h"
 #include "shill/mock_store.h"
 
+using base::FilePath;
 using ::testing::_;
 using ::testing::DoAll;
 using ::testing::Return;
diff --git a/cellular_operator_info.cc b/cellular_operator_info.cc
index 716510d..37807d4 100644
--- a/cellular_operator_info.cc
+++ b/cellular_operator_info.cc
@@ -14,6 +14,7 @@
 
 #include "shill/logging.h"
 
+using base::FilePath;
 using std::map;
 using std::string;
 using std::vector;
diff --git a/cellular_operator_info.h b/cellular_operator_info.h
index aa46560..b5185aa 100644
--- a/cellular_operator_info.h
+++ b/cellular_operator_info.h
@@ -148,7 +148,7 @@
   virtual ~CellularOperatorInfo();
 
   // Loads the operator info from |info_file_path|. Returns true on success.
-  bool Load(const FilePath &info_file_path);
+  bool Load(const base::FilePath &info_file_path);
 
   // Gets the cellular operator info of the operator with MCCMNC |mccmnc|.
   // If found, returns a pointer to the matching operator.
diff --git a/cellular_operator_info_unittest.cc b/cellular_operator_info_unittest.cc
index 016e48b..61477b9 100644
--- a/cellular_operator_info_unittest.cc
+++ b/cellular_operator_info_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "shill/glib.h"
 
+using base::FilePath;
 using std::map;
 using std::string;
 using std::vector;
diff --git a/crypto_des_cbc.cc b/crypto_des_cbc.cc
index 8c12a44..71ac52a 100644
--- a/crypto_des_cbc.cc
+++ b/crypto_des_cbc.cc
@@ -11,6 +11,7 @@
 
 #include "shill/glib.h"
 
+using base::FilePath;
 using std::string;
 using std::vector;
 
diff --git a/crypto_des_cbc_unittest.cc b/crypto_des_cbc_unittest.cc
index 81681f9..0ba8206 100644
--- a/crypto_des_cbc_unittest.cc
+++ b/crypto_des_cbc_unittest.cc
@@ -9,6 +9,7 @@
 #include "shill/crypto_des_cbc.h"
 #include "shill/glib.h"
 
+using base::FilePath;
 using std::string;
 using std::vector;
 using testing::Test;
diff --git a/crypto_provider.h b/crypto_provider.h
index 9d56928..2930d07 100644
--- a/crypto_provider.h
+++ b/crypto_provider.h
@@ -31,7 +31,9 @@
   // |ciphertext| as is.
   std::string Decrypt(const std::string &ciphertext);
 
-  void set_key_matter_file(const FilePath &path) { key_matter_file_ = path; }
+  void set_key_matter_file(const base::FilePath &path) {
+    key_matter_file_ = path;
+  }
 
  private:
   FRIEND_TEST(CryptoProviderTest, Init);
@@ -45,7 +47,7 @@
   // Registered crypto modules in high to low priority order.
   Cryptos cryptos_;
 
-  FilePath key_matter_file_;
+  base::FilePath key_matter_file_;
 
   DISALLOW_COPY_AND_ASSIGN(CryptoProvider);
 };
diff --git a/crypto_provider_unittest.cc b/crypto_provider_unittest.cc
index da893bb..e6aa897 100644
--- a/crypto_provider_unittest.cc
+++ b/crypto_provider_unittest.cc
@@ -11,6 +11,7 @@
 #include "shill/crypto_rot47.h"
 #include "shill/glib.h"
 
+using base::FilePath;
 using base::ScopedTempDir;
 using std::string;
 using testing::Test;
diff --git a/default_profile.cc b/default_profile.cc
index 76baa15..9d30d72 100644
--- a/default_profile.cc
+++ b/default_profile.cc
@@ -19,6 +19,7 @@
 #include "shill/resolver.h"
 #include "shill/store_interface.h"
 
+using base::FilePath;
 using std::string;
 using std::vector;
 
diff --git a/default_profile.h b/default_profile.h
index c31997c..05fc4fb 100644
--- a/default_profile.h
+++ b/default_profile.h
@@ -29,7 +29,7 @@
   DefaultProfile(ControlInterface *control,
                  Metrics *metrics,
                  Manager *manager,
-                 const FilePath &storage_path,
+                 const base::FilePath &storage_path,
                  const std::string &profile_id,
                  const Manager::Properties &manager_props);
   virtual ~DefaultProfile();
@@ -56,7 +56,7 @@
   // appropriate file location.
   //
   // In this implementation, |name_| is ignored.
-  virtual bool GetStoragePath(FilePath *path);
+  virtual bool GetStoragePath(base::FilePath *path);
 
  private:
   friend class DefaultProfileTest;
@@ -77,7 +77,7 @@
   static const char kStoragePortalURL[];
   static const char kStorageShortDNSTimeoutTechnologies[];
 
-  const FilePath storage_path_;
+  const base::FilePath storage_path_;
   const std::string profile_id_;
   const Manager::Properties &props_;
 
diff --git a/default_profile_unittest.cc b/default_profile_unittest.cc
index 342073d..c1a1d58 100644
--- a/default_profile_unittest.cc
+++ b/default_profile_unittest.cc
@@ -25,6 +25,7 @@
 #include "shill/property_store_unittest.h"
 #include "shill/resolver.h"
 
+using base::FilePath;
 using std::map;
 using std::string;
 using std::vector;
diff --git a/device.cc b/device.cc
index 490969d..aeb48f8 100644
--- a/device.cc
+++ b/device.cc
@@ -40,6 +40,7 @@
 #include "shill/traffic_monitor.h"
 
 using base::Bind;
+using base::FilePath;
 using base::StringPrintf;
 using std::string;
 using std::vector;
@@ -390,6 +391,10 @@
   return ipconfig_->RequestIP();
 }
 
+void Device::DestroyIPConfigLease(const string &name) {
+  dhcp_provider_->DestroyLease(name);
+}
+
 void Device::HelpRegisterDerivedString(
     const string &name,
     string(Device::*get)(Error *error),
diff --git a/device.h b/device.h
index 440a42c..aede214 100644
--- a/device.h
+++ b/device.h
@@ -198,6 +198,10 @@
   // the base class implementation.
   virtual void OnAfterResume();
 
+  // Destroy the lease, if any, with this |name|.
+  // Called by the service during Unload() as part of the cleanup sequence.
+  virtual void DestroyIPConfigLease(const std::string &name);
+
  protected:
   friend class base::RefCounted<Device>;
   FRIEND_TEST(CellularServiceTest, IsAutoConnectable);
diff --git a/device_info.cc b/device_info.cc
index 1513457..d0a3aa3 100644
--- a/device_info.cc
+++ b/device_info.cc
@@ -44,6 +44,7 @@
 #include "shill/wifi.h"
 
 using base::Bind;
+using base::FilePath;
 using base::StringPrintf;
 using base::Unretained;
 using std::map;
diff --git a/device_info.h b/device_info.h
index 37bfafc..90fac40 100644
--- a/device_info.h
+++ b/device_info.h
@@ -175,7 +175,7 @@
 
   // Return the FilePath for a given |path_name| in the device sysinfo for
   // a specific interface |iface_name|.
-  FilePath GetDeviceInfoPath(const std::string &iface_name,
+  base::FilePath GetDeviceInfoPath(const std::string &iface_name,
                              const std::string &path_name);
   // Return the contents of the device info file |path_name| for interface
   // |iface_name| in output parameter |contents_out|.  Returns true if file
@@ -189,7 +189,7 @@
   // Returns true if symbolic link read succeeded, false otherwise.
   bool GetDeviceInfoSymbolicLink(const std::string &iface_name,
                                  const std::string &path_name,
-                                 FilePath *path_out);
+                                 base::FilePath *path_out);
   // Classify the device named |iface_name|, and return an identifier
   // indicating its type.
   virtual Technology::Identifier GetDeviceTechnology(
@@ -201,7 +201,8 @@
   // Returns true if |base_dir| has a subdirectory named |subdir|.
   // |subdir| can be an immediate subdirectory of |base_dir| or can be
   // several levels deep.
-  static bool HasSubdir(const FilePath &base_dir, const FilePath &subdir);
+  static bool HasSubdir(const base::FilePath &base_dir,
+                        const base::FilePath &subdir);
 
   void AddLinkMsgHandler(const RTNLMessage &msg);
   void DelLinkMsgHandler(const RTNLMessage &msg);
@@ -230,7 +231,7 @@
   scoped_ptr<RTNLListener> link_listener_;
   scoped_ptr<RTNLListener> address_listener_;
   std::set<std::string> black_list_;
-  FilePath device_info_root_;
+  base::FilePath device_info_root_;
 
   // Keep track of devices that require a delayed call to CreateDevice().
   base::CancelableClosure delayed_devices_callback_;
diff --git a/device_info_unittest.cc b/device_info_unittest.cc
index f6a1f63..eae3a0a 100644
--- a/device_info_unittest.cc
+++ b/device_info_unittest.cc
@@ -40,6 +40,7 @@
 #include "shill/wimax.h"
 
 using base::Callback;
+using base::FilePath;
 using std::map;
 using std::set;
 using std::string;
diff --git a/dhcp_config.cc b/dhcp_config.cc
index b2b7da3..cf0ebc7 100644
--- a/dhcp_config.cc
+++ b/dhcp_config.cc
@@ -41,8 +41,6 @@
 const int DHCPConfig::kDHCPCDExitPollMilliseconds = 50;
 const int DHCPConfig::kDHCPCDExitWaitMilliseconds = 3000;
 const char DHCPConfig::kDHCPCDPath[] = "/sbin/dhcpcd";
-const char DHCPConfig::kDHCPCDPathFormatLease[] =
-    "var/lib/dhcpcd/dhcpcd-%s.lease";
 const char DHCPConfig::kDHCPCDPathFormatPID[] =
     "var/run/dhcpcd/dhcpcd-%s.pid";
 const int DHCPConfig::kDHCPTimeoutSeconds = 30;
@@ -431,7 +429,7 @@
   if (lease_file_suffix_ == device_name()) {
     // If the lease file suffix was left as default, clean it up at exit.
     file_util::Delete(root_.Append(
-        base::StringPrintf(kDHCPCDPathFormatLease,
+        base::StringPrintf(DHCPProvider::kDHCPCDPathFormatLease,
                            device_name().c_str())), false);
   }
   file_util::Delete(root_.Append(
diff --git a/dhcp_config.h b/dhcp_config.h
index 4465e30..6cee9cf 100644
--- a/dhcp_config.h
+++ b/dhcp_config.h
@@ -107,7 +107,6 @@
   static const int kDHCPCDExitPollMilliseconds;
   static const int kDHCPCDExitWaitMilliseconds;
   static const char kDHCPCDPath[];
-  static const char kDHCPCDPathFormatLease[];
   static const char kDHCPCDPathFormatPID[];
   static const int kDHCPTimeoutSeconds;
   static const char kDHCPCDUser[];
@@ -202,7 +201,7 @@
   unsigned int lease_acquisition_timeout_seconds_;
 
   // Root file path, used for testing.
-  FilePath root_;
+  base::FilePath root_;
 
   base::WeakPtrFactory<DHCPConfig> weak_ptr_factory_;
   EventDispatcher *dispatcher_;
diff --git a/dhcp_config_unittest.cc b/dhcp_config_unittest.cc
index f7322d4..dacafbf 100644
--- a/dhcp_config_unittest.cc
+++ b/dhcp_config_unittest.cc
@@ -23,6 +23,7 @@
 #include "shill/proxy_factory.h"
 
 using base::Bind;
+using base::FilePath;
 using base::ScopedTempDir;
 using base::Unretained;
 using std::string;
diff --git a/dhcp_provider.cc b/dhcp_provider.cc
index f423b6d..10ddd64 100644
--- a/dhcp_provider.cc
+++ b/dhcp_provider.cc
@@ -4,12 +4,16 @@
 
 #include "shill/dhcp_provider.h"
 
+#include <base/file_util.h>
+#include <base/stringprintf.h>
+
 #include "shill/control_interface.h"
 #include "shill/dhcp_config.h"
 #include "shill/dhcpcd_proxy.h"
 #include "shill/logging.h"
 #include "shill/proxy_factory.h"
 
+using base::FilePath;
 using std::string;
 
 namespace shill {
@@ -18,8 +22,12 @@
 base::LazyInstance<DHCPProvider> g_dhcp_provider = LAZY_INSTANCE_INITIALIZER;
 }  // namespace
 
+const char DHCPProvider::kDHCPCDPathFormatLease[] =
+    "var/lib/dhcpcd/dhcpcd-%s.lease";
+
 DHCPProvider::DHCPProvider()
     : proxy_factory_(ProxyFactory::GetInstance()),
+      root_("/"),
       control_interface_(NULL),
       dispatcher_(NULL),
       glib_(NULL) {
@@ -78,4 +86,11 @@
   configs_.erase(pid);
 }
 
+void DHCPProvider::DestroyLease(const string &name) {
+  SLOG(DHCP, 2) << __func__ << " name: " << name;
+  file_util::Delete(root_.Append(
+      base::StringPrintf(kDHCPCDPathFormatLease,
+                         name.c_str())), false);
+}
+
 }  // namespace shill
diff --git a/dhcp_provider.h b/dhcp_provider.h
index bad79dd..901a858 100644
--- a/dhcp_provider.h
+++ b/dhcp_provider.h
@@ -8,6 +8,7 @@
 #include <map>
 #include <string>
 
+#include <base/file_path.h>
 #include <base/lazy_instance.h>
 #include <base/memory/scoped_ptr.h>
 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
@@ -33,6 +34,8 @@
 //                                           arp_gateway)->Request();
 class DHCPProvider {
  public:
+  static const char kDHCPCDPathFormatLease[];
+
   virtual ~DHCPProvider();
 
   // This is a singleton -- use DHCPProvider::GetInstance()->Foo()
@@ -72,6 +75,9 @@
   // destruction of the DHCP config instance if its reference count goes to 0.
   void UnbindPID(int pid);
 
+  // Destroy lease file associated with this |name|.
+  virtual void DestroyLease(const std::string &name);
+
  protected:
   DHCPProvider();
 
@@ -82,6 +88,7 @@
   friend class DeviceInfoTest;
   friend class DeviceTest;
   FRIEND_TEST(DHCPProviderTest, CreateConfig);
+  FRIEND_TEST(DHCPProviderTest, DestroyLease);
 
   typedef std::map<int, DHCPConfigRefPtr> PIDConfigMap;
 
@@ -95,6 +102,7 @@
   // A map that binds PIDs to DHCP configuration instances.
   PIDConfigMap configs_;
 
+  base::FilePath root_;
   ControlInterface *control_interface_;
   EventDispatcher *dispatcher_;
   GLib *glib_;
diff --git a/dhcp_provider_unittest.cc b/dhcp_provider_unittest.cc
index 7107b48..a9ae06c 100644
--- a/dhcp_provider_unittest.cc
+++ b/dhcp_provider_unittest.cc
@@ -4,10 +4,16 @@
 
 #include "shill/dhcp_provider.h"
 
+#include <base/file_util.h>
+#include <base/files/scoped_temp_dir.h>
+#include <base/stringprintf.h>
+
 #include "shill/dhcp_config.h"
 #include "shill/mock_control.h"
 #include "shill/mock_glib.h"
 
+using base::FilePath;
+using base::ScopedTempDir;
 using testing::Test;
 
 namespace shill {
@@ -47,4 +53,19 @@
   EXPECT_TRUE(provider_->configs_.empty());
 }
 
+TEST_F(DHCPProviderTest, DestroyLease) {
+  ScopedTempDir temp_dir;
+  FilePath lease_file;
+  EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
+  provider_->root_ = temp_dir.path();
+  lease_file = provider_->root_.Append(base::StringPrintf(
+      DHCPProvider::kDHCPCDPathFormatLease,
+      kDeviceName));
+  EXPECT_TRUE(file_util::CreateDirectory(lease_file.DirName()));
+  EXPECT_EQ(0, file_util::WriteFile(lease_file, "", 0));
+  EXPECT_TRUE(file_util::PathExists(lease_file));
+  provider_->DestroyLease(kDeviceName);
+  EXPECT_FALSE(file_util::PathExists(lease_file));
+}
+
 }  // namespace shill
diff --git a/diagnostics_reporter.h b/diagnostics_reporter.h
index eae7cf8..1d21a33 100644
--- a/diagnostics_reporter.h
+++ b/diagnostics_reporter.h
@@ -40,7 +40,7 @@
   ProcessKiller *process_killer_;
   Time *time_;
   uint64 last_log_stash_;  // Monotonic time seconds.
-  FilePath stashed_net_log_;
+  base::FilePath stashed_net_log_;
 
   DISALLOW_COPY_AND_ASSIGN(DiagnosticsReporter);
 };
diff --git a/diagnostics_reporter_unittest.cc b/diagnostics_reporter_unittest.cc
index 824f77c..ad5fb0e 100644
--- a/diagnostics_reporter_unittest.cc
+++ b/diagnostics_reporter_unittest.cc
@@ -13,6 +13,7 @@
 #include "shill/mock_process_killer.h"
 #include "shill/mock_time.h"
 
+using base::FilePath;
 using testing::_;
 using testing::ElementsAre;
 using testing::InSequence;
diff --git a/doc/service-api.txt b/doc/service-api.txt
index 35c6484..32f1198 100644
--- a/doc/service-api.txt
+++ b/doc/service-api.txt
@@ -101,8 +101,6 @@
 			Possible Errors: [service].Error.InvalidArguments
 					 [service].Error.NotSupported
 
-			[Silently ignored in shill so far]
-
 		void MoveBefore(object service)
 
 			Silently ignored in shill.  Do not use.
@@ -472,14 +470,14 @@
 
 			This property is included in get requests only
 			when the requester has sufficient privileges.
-		
+
 		string EAP.Password [readwrite]
 
 			The password to use in 802.1x authentication.
 
 			This property is included in get requests only
 			when the requester has sufficient privileges.
-		
+
 		string EAP.KeyMgmt [readwrite]
 
 			(WiFi only) The key management algorithm to be
@@ -760,7 +758,7 @@
 
 			The following credentials are not recorded when
 			this property is set to FALSE:
-			
+
 			Passphrase
 			EAP.Identity
 			EAP.AnonymousIdentity
diff --git a/ethernet_service.cc b/ethernet_service.cc
index 77ac11a..5f33e74 100644
--- a/ethernet_service.cc
+++ b/ethernet_service.cc
@@ -72,4 +72,8 @@
   Service::SetAutoConnect(connect, error);
 }
 
+void EthernetService::Remove(Error *error) {
+  error->Populate(Error::kNotSupported);
+}
+
 }  // namespace shill
diff --git a/ethernet_service.h b/ethernet_service.h
index bf90a89..1da04ee 100644
--- a/ethernet_service.h
+++ b/ethernet_service.h
@@ -36,6 +36,8 @@
   virtual bool IsAutoConnectByDefault() const { return true; }
   virtual void SetAutoConnect(const bool &connect, Error *error);
 
+  virtual void Remove(Error *error);
+
  private:
   static const char kServiceType[];
 
diff --git a/file_reader.cc b/file_reader.cc
index 450d7e0..f670964 100644
--- a/file_reader.cc
+++ b/file_reader.cc
@@ -4,6 +4,7 @@
 
 #include "shill/file_reader.h"
 
+using base::FilePath;
 using std::string;
 
 namespace shill {
diff --git a/file_reader.h b/file_reader.h
index a31177a..f73b6cc 100644
--- a/file_reader.h
+++ b/file_reader.h
@@ -25,7 +25,7 @@
   void Close();
 
   // Opens the file of a given path. Returns true on success.
-  bool Open(const FilePath &file_path);
+  bool Open(const base::FilePath &file_path);
 
   // Reads a line, terminated by either LF or EOF, from the file into
   // a given string, with LF excluded. Returns false if no more line
diff --git a/file_reader_unittest.cc b/file_reader_unittest.cc
index 3585d96..f87aacf 100644
--- a/file_reader_unittest.cc
+++ b/file_reader_unittest.cc
@@ -12,6 +12,7 @@
 #include <base/string_util.h>
 #include <gtest/gtest.h>
 
+using base::FilePath;
 using std::string;
 using std::vector;
 
diff --git a/key_file_store.h b/key_file_store.h
index 5519fc1..a421346 100644
--- a/key_file_store.h
+++ b/key_file_store.h
@@ -22,8 +22,8 @@
   explicit KeyFileStore(GLib *glib);
   virtual ~KeyFileStore();
 
-  void set_path(const FilePath &path) { path_ = path; }
-  const FilePath &path() const { return path_; }
+  void set_path(const base::FilePath &path) { path_ = path; }
+  const base::FilePath &path() const { return path_; }
 
   // Returns true if the store exists and is non-empty.
   bool IsNonEmpty() const;
@@ -105,7 +105,7 @@
   GLib *glib_;
   CryptoProvider crypto_;
   GKeyFile *key_file_;
-  FilePath path_;
+  base::FilePath path_;
 
   DISALLOW_COPY_AND_ASSIGN(KeyFileStore);
 };
diff --git a/key_file_store_unittest.cc b/key_file_store_unittest.cc
index 834b942..598543c 100644
--- a/key_file_store_unittest.cc
+++ b/key_file_store_unittest.cc
@@ -13,6 +13,7 @@
 
 #include "shill/key_value_store.h"
 
+using base::FilePath;
 using file_util::FileEnumerator;
 using std::set;
 using std::string;
diff --git a/l2tp_ipsec_driver.cc b/l2tp_ipsec_driver.cc
index 0638393..876fe97 100644
--- a/l2tp_ipsec_driver.cc
+++ b/l2tp_ipsec_driver.cc
@@ -20,6 +20,7 @@
 
 using base::Bind;
 using base::Closure;
+using base::FilePath;
 using std::map;
 using std::string;
 using std::vector;
diff --git a/l2tp_ipsec_driver.h b/l2tp_ipsec_driver.h
index c74d01c..c32cae7 100644
--- a/l2tp_ipsec_driver.h
+++ b/l2tp_ipsec_driver.h
@@ -135,7 +135,7 @@
 
   VPNServiceRefPtr service_;
   scoped_ptr<RPCTask> rpc_task_;
-  FilePath psk_file_;
+  base::FilePath psk_file_;
   VPNRefPtr device_;
 
   // The PID of the spawned l2tpipsec_vpn process. May be 0 if no process has
diff --git a/l2tp_ipsec_driver_unittest.cc b/l2tp_ipsec_driver_unittest.cc
index ef2e984..2487d02 100644
--- a/l2tp_ipsec_driver_unittest.cc
+++ b/l2tp_ipsec_driver_unittest.cc
@@ -22,6 +22,7 @@
 #include "shill/mock_vpn_service.h"
 #include "shill/vpn.h"
 
+using base::FilePath;
 using std::find;
 using std::map;
 using std::string;
diff --git a/manager.cc b/manager.cc
index c16f34d..ff453d0 100644
--- a/manager.cc
+++ b/manager.cc
@@ -48,6 +48,7 @@
 #include "shill/wimax_service.h"
 
 using base::Bind;
+using base::FilePath;
 using base::StringPrintf;
 using base::Unretained;
 using std::map;
diff --git a/manager.h b/manager.h
index d2866c4..4c1beba 100644
--- a/manager.h
+++ b/manager.h
@@ -234,8 +234,8 @@
   PropertyStore *mutable_store() { return &store_; }
   virtual const PropertyStore &store() const { return store_; }
   GLib *glib() const { return glib_; }
-  virtual const FilePath &run_path() const { return run_path_; }
-  const FilePath &storage_path() const { return storage_path_; }
+  virtual const base::FilePath &run_path() const { return run_path_; }
+  const base::FilePath &storage_path() const { return storage_path_; }
 
   void set_startup_profiles(const std::vector<std::string> &startup_profiles) {
     startup_profiles_ = startup_profiles;
@@ -443,8 +443,8 @@
   }
 
   EventDispatcher *dispatcher_;
-  const FilePath run_path_;
-  const FilePath storage_path_;
+  const base::FilePath run_path_;
+  const base::FilePath storage_path_;
   const std::string user_storage_format_;
   scoped_ptr<ManagerAdaptorInterface> adaptor_;
   scoped_ptr<DBusManager> dbus_manager_;
diff --git a/manager_unittest.cc b/manager_unittest.cc
index 6b273ab..b131304 100644
--- a/manager_unittest.cc
+++ b/manager_unittest.cc
@@ -44,6 +44,7 @@
 #include "shill/wifi_service.h"
 #include "shill/wimax_service.h"
 
+using base::FilePath;
 using base::ScopedTempDir;
 using std::map;
 using std::set;
diff --git a/memory_log.cc b/memory_log.cc
index 4bf9b8d..efe62da 100644
--- a/memory_log.cc
+++ b/memory_log.cc
@@ -21,6 +21,8 @@
 #include "shill/logging.h"
 #include "shill/shill_time.h"
 
+using base::FilePath;
+
 namespace shill {
 
 namespace {
diff --git a/memory_log_unittest.cc b/memory_log_unittest.cc
index dde98d8..60b1094 100644
--- a/memory_log_unittest.cc
+++ b/memory_log_unittest.cc
@@ -14,6 +14,7 @@
 #include "shill/logging.h"
 #include "shill/mock_log.h"
 
+using base::FilePath;
 using testing::_;
 
 namespace {
diff --git a/mock_activating_iccid_store.h b/mock_activating_iccid_store.h
index bf064a6..2221e26 100644
--- a/mock_activating_iccid_store.h
+++ b/mock_activating_iccid_store.h
@@ -19,7 +19,8 @@
   MockActivatingIccidStore();
   virtual ~MockActivatingIccidStore();
 
-  MOCK_METHOD2(InitStorage, bool(GLib *glib, const FilePath &storage_path));
+  MOCK_METHOD2(InitStorage,
+               bool(GLib *glib,const base::FilePath &storage_path));
   MOCK_CONST_METHOD1(GetActivationState, State(const std::string &iccid));
   MOCK_METHOD2(SetActivationState,
                bool(const std::string &iccid, State state));
diff --git a/mock_cellular_operator_info.h b/mock_cellular_operator_info.h
index a9cb38e..eafbb5a 100644
--- a/mock_cellular_operator_info.h
+++ b/mock_cellular_operator_info.h
@@ -18,7 +18,7 @@
   MockCellularOperatorInfo();
   virtual ~MockCellularOperatorInfo();
 
-  MOCK_METHOD1(Load, bool(const FilePath &info_file_path));
+  MOCK_METHOD1(Load, bool(const base::FilePath &info_file_path));
   MOCK_CONST_METHOD1(GetOLPByMCCMNC,
                      const CellularService::OLP *(const std::string &mccmnc));
   MOCK_CONST_METHOD1(GetCellularOperatorByMCCMNC,
diff --git a/mock_manager.h b/mock_manager.h
index 8c946d6..93ec19e 100644
--- a/mock_manager.h
+++ b/mock_manager.h
@@ -26,7 +26,7 @@
   MOCK_METHOD0(wimax_provider, WiMaxProvider *());
   MOCK_METHOD0(mutable_store, PropertyStore *());
   MOCK_CONST_METHOD0(store, const PropertyStore &());
-  MOCK_CONST_METHOD0(run_path, const FilePath &());
+  MOCK_CONST_METHOD0(run_path, const base::FilePath &());
   MOCK_METHOD0(Start, void());
   MOCK_METHOD0(Stop, void());
   MOCK_METHOD1(RegisterDevice, void(const DeviceRefPtr &to_manage));
diff --git a/mock_nss.h b/mock_nss.h
index f1b3049..718fad1 100644
--- a/mock_nss.h
+++ b/mock_nss.h
@@ -16,10 +16,10 @@
   MockNSS();
   virtual ~MockNSS();
 
-  MOCK_METHOD2(GetPEMCertfile, FilePath(const std::string &nickname,
-                                        const std::vector<char> &id));
-  MOCK_METHOD2(GetDERCertfile, FilePath(const std::string &nickname,
-                                        const std::vector<char> &id));
+  MOCK_METHOD2(GetPEMCertfile, base::FilePath(const std::string &nickname,
+                                              const std::vector<char> &id));
+  MOCK_METHOD2(GetDERCertfile, base::FilePath(const std::string &nickname,
+                                              const std::vector<char> &id));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockNSS);
diff --git a/mock_wifi.h b/mock_wifi.h
index bdcdd31..ae53140 100644
--- a/mock_wifi.h
+++ b/mock_wifi.h
@@ -47,6 +47,7 @@
   MOCK_CONST_METHOD0(IsIdle, bool());
   MOCK_METHOD1(NotifyEndpointChanged,
                void(const WiFiEndpointConstRefPtr &endpoint));
+  MOCK_METHOD1(DestroyIPConfigLease, void(const std::string &));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockWiFi);
diff --git a/modem.h b/modem.h
index d74061a..ecb0351 100644
--- a/modem.h
+++ b/modem.h
@@ -187,7 +187,7 @@
  private:
   friend class Modem1Test;
 
-  FilePath netfiles_path_;  // Used for testing
+  base::FilePath netfiles_path_;  // Used for testing
 
   DISALLOW_COPY_AND_ASSIGN(Modem1);
 };
diff --git a/modem_1.cc b/modem_1.cc
index 1eea438..13aa1aa 100644
--- a/modem_1.cc
+++ b/modem_1.cc
@@ -11,6 +11,7 @@
 #include "shill/cellular.h"
 #include "shill/device_info.h"
 
+using base::FilePath;
 using std::string;
 
 namespace shill {
diff --git a/modem_1_unittest.cc b/modem_1_unittest.cc
index 05f60b6..df1fde4 100644
--- a/modem_1_unittest.cc
+++ b/modem_1_unittest.cc
@@ -24,6 +24,7 @@
 #include "shill/proxy_factory.h"
 #include "shill/rtnl_handler.h"
 
+using base::FilePath;
 using std::string;
 using testing::_;
 using testing::DoAll;
diff --git a/modem_info.cc b/modem_info.cc
index b4f6da8..268202e 100644
--- a/modem_info.cc
+++ b/modem_info.cc
@@ -12,6 +12,7 @@
 #include "shill/logging.h"
 #include "shill/modem_manager.h"
 
+using base::FilePath;
 using std::string;
 
 // TODO(rochberg): Fix modemmanager-next-interfaces ebuild to include
diff --git a/nss.cc b/nss.cc
index 47e121e..9b3783b 100644
--- a/nss.cc
+++ b/nss.cc
@@ -11,6 +11,7 @@
 #include "shill/logging.h"
 #include "shill/minijail.h"
 
+using base::FilePath;
 using base::HexEncode;
 using base::StringPrintf;
 using std::string;
diff --git a/nss.h b/nss.h
index 1af798f..75f5e5f 100644
--- a/nss.h
+++ b/nss.h
@@ -24,12 +24,12 @@
   static NSS *GetInstance();
 
   // Returns an empty path on failure.
-  virtual FilePath GetPEMCertfile(const std::string &nickname,
-                                  const std::vector<char> &id);
+  virtual base::FilePath GetPEMCertfile(const std::string &nickname,
+                                        const std::vector<char> &id);
 
   // Returns an empty path on failure.
-  virtual FilePath GetDERCertfile(const std::string &nickname,
-                                  const std::vector<char> &id);
+  virtual base::FilePath GetDERCertfile(const std::string &nickname,
+                                        const std::vector<char> &id);
 
  protected:
   NSS();
@@ -39,9 +39,9 @@
   friend class NSSTest;
   FRIEND_TEST(NSSTest, GetCertfile);
 
-  FilePath GetCertfile(const std::string &nickname,
-                       const std::vector<char> &id,
-                       const std::string &type);
+  base::FilePath GetCertfile(const std::string &nickname,
+                             const std::vector<char> &id,
+                             const std::string &type);
 
   Minijail *minijail_;
 
diff --git a/openvpn_driver.cc b/openvpn_driver.cc
index a322476..adb17a7 100644
--- a/openvpn_driver.cc
+++ b/openvpn_driver.cc
@@ -27,6 +27,7 @@
 #include "shill/vpn_service.h"
 
 using base::Closure;
+using base::FilePath;
 using base::SplitString;
 using base::Unretained;
 using base::WeakPtr;
diff --git a/openvpn_driver.h b/openvpn_driver.h
index 39d7a7f..fbc483d 100644
--- a/openvpn_driver.h
+++ b/openvpn_driver.h
@@ -218,13 +218,13 @@
   scoped_ptr<OpenVPNManagementServer> management_server_;
   NSS *nss_;
   ProcessKiller *process_killer_;
-  FilePath lsb_release_file_;
+  base::FilePath lsb_release_file_;
 
   VPNServiceRefPtr service_;
   scoped_ptr<RPCTask> rpc_task_;
   std::string tunnel_interface_;
   VPNRefPtr device_;
-  FilePath tls_auth_file_;
+  base::FilePath tls_auth_file_;
   IPConfig::Properties ip_properties_;
 
   // The PID of the spawned openvpn process. May be 0 if no process has been
diff --git a/openvpn_driver_unittest.cc b/openvpn_driver_unittest.cc
index bbe6b61..caadf03 100644
--- a/openvpn_driver_unittest.cc
+++ b/openvpn_driver_unittest.cc
@@ -34,6 +34,7 @@
 #include "shill/vpn.h"
 #include "shill/vpn_service.h"
 
+using base::FilePath;
 using base::WeakPtr;
 using std::map;
 using std::string;
diff --git a/profile.cc b/profile.cc
index b88b679..912a17c 100644
--- a/profile.cc
+++ b/profile.cc
@@ -24,6 +24,7 @@
 #include "shill/service.h"
 #include "shill/store_interface.h"
 
+using base::FilePath;
 using std::set;
 using std::string;
 using std::vector;
diff --git a/profile_unittest.cc b/profile_unittest.cc
index 7702dae..4283341 100644
--- a/profile_unittest.cc
+++ b/profile_unittest.cc
@@ -24,6 +24,7 @@
 #include "shill/property_store_unittest.h"
 #include "shill/service_under_test.h"
 
+using base::FilePath;
 using std::set;
 using std::string;
 using std::vector;
diff --git a/resolver.h b/resolver.h
index 6a2ccb1..f7608ad 100644
--- a/resolver.h
+++ b/resolver.h
@@ -42,7 +42,7 @@
   // Since this is a singleton, use Resolver::GetInstance()->Foo()
   static Resolver *GetInstance();
 
-  virtual void set_path(const FilePath &path) { path_ = path; }
+  virtual void set_path(const base::FilePath &path) { path_ = path; }
 
   // Install domain name service parameters, given a list of
   // DNS servers in |dns_servers|, a list of DNS search suffixes in
@@ -71,7 +71,7 @@
   static const char kDefaultTimeoutOptions[];
   static const char kShortTimeoutOptions[];
 
-  FilePath path_;
+  base::FilePath path_;
   std::vector<std::string> ignored_search_list_;
 
   DISALLOW_COPY_AND_ASSIGN(Resolver);
diff --git a/resolver_unittest.cc b/resolver_unittest.cc
index 0f9d6ef..a5ee72d 100644
--- a/resolver_unittest.cc
+++ b/resolver_unittest.cc
@@ -12,6 +12,7 @@
 
 #include "shill/mock_control.h"
 
+using base::FilePath;
 using std::string;
 using std::vector;
 using testing::Test;
diff --git a/routing_table.cc b/routing_table.cc
index c2f21c1..17fc9e9 100644
--- a/routing_table.cc
+++ b/routing_table.cc
@@ -34,6 +34,7 @@
 #include "shill/rtnl_message.h"
 
 using base::Bind;
+using base::FilePath;
 using base::Unretained;
 using std::deque;
 using std::string;
diff --git a/service.cc b/service.cc
index 017a16c..eb04052 100644
--- a/service.cc
+++ b/service.cc
@@ -466,6 +466,10 @@
   return false;
 }
 
+void Service::Remove(Error */*error*/) {
+  Unload();
+}
+
 bool Service::Save(StoreInterface *storage) {
   const string id = GetStorageIdentifier();
 
diff --git a/service.h b/service.h
index cd55602..f4c0a05 100644
--- a/service.h
+++ b/service.h
@@ -271,6 +271,9 @@
   // the manager, false otherwise.
   virtual bool Unload();
 
+  // Attempt to remove the service. On failure, no changes in state will occur.
+  virtual void Remove(Error *error);
+
   // Saves the service to persistent |storage|. Returns true on success.
   virtual bool Save(StoreInterface *storage);
 
diff --git a/service_dbus_adaptor.cc b/service_dbus_adaptor.cc
index 7d459ad..66f55a8 100644
--- a/service_dbus_adaptor.cc
+++ b/service_dbus_adaptor.cc
@@ -127,8 +127,11 @@
   e.ToDBusError(&error);
 }
 
-void ServiceDBusAdaptor::Remove(::DBus::Error &/*error*/) {
+void ServiceDBusAdaptor::Remove(::DBus::Error &error) {
   SLOG(DBus, 2) << __func__;
+  Error e;
+  service_->Remove(&e);
+  e.ToDBusError(&error);
 }
 
 void ServiceDBusAdaptor::MoveBefore(const ::DBus::Path& ,
diff --git a/shill_main.cc b/shill_main.cc
index 5caf2a0..d2471bf 100644
--- a/shill_main.cc
+++ b/shill_main.cc
@@ -24,6 +24,7 @@
 #include "shill/shill_config.h"
 #include "shill/shill_daemon.h"
 
+using base::FilePath;
 using std::string;
 using std::vector;
 
diff --git a/wifi.cc b/wifi.cc
index d6e6484..50556dc 100644
--- a/wifi.cc
+++ b/wifi.cc
@@ -1086,6 +1086,14 @@
   }
 }
 
+string WiFi::GetServiceLeaseName(const WiFiService &service) {
+  return service.GetStorageIdentifier();
+}
+
+void WiFi::DestroyServiceLease(const WiFiService &service) {
+  DestroyIPConfigLease(GetServiceLeaseName(service));
+}
+
 void WiFi::StateChanged(const string &new_state) {
   const string old_state = supplicant_state_;
   supplicant_state_ = new_state;
@@ -1117,7 +1125,7 @@
     } else if (has_already_completed_) {
       LOG(INFO) << link_name() << " L3 configuration already started.";
     } else if (AcquireIPConfigWithLeaseName(
-                   affected_service->GetStorageIdentifier())) {
+                   GetServiceLeaseName(*affected_service))) {
       LOG(INFO) << link_name() << " is up; started L3 configuration.";
       affected_service->SetState(Service::kStateConfiguring);
     } else {
diff --git a/wifi.h b/wifi.h
index 65e00c3..fc84c98 100644
--- a/wifi.h
+++ b/wifi.h
@@ -177,6 +177,9 @@
   // Called by a WiFiService when it disassociates itself from this Device.
   virtual void DisassociateFromService(const WiFiServiceRefPtr &service);
 
+  // Called by a WiFiService when it unloads to destroy its lease file.
+  virtual void DestroyServiceLease(const WiFiService &service);
+
  private:
   friend class WiFiObjectTest;  // access to supplicant_*_proxy_, link_up_
   friend class WiFiTimerTest;  // kNumFastScanAttempts, kFastScanIntervalSeconds
@@ -329,6 +332,8 @@
 
   void Restart();
 
+  std::string GetServiceLeaseName(const WiFiService &service);
+
   // Pointer to the provider object that maintains WiFiService objects.
   WiFiProvider *provider_;
 
diff --git a/wifi_service.cc b/wifi_service.cc
index b076d17..88f6a51 100644
--- a/wifi_service.cc
+++ b/wifi_service.cc
@@ -32,6 +32,7 @@
 #include "shill/wifi_provider.h"
 #include "shill/wpa_supplicant.h"
 
+using base::FilePath;
 using std::set;
 using std::string;
 using std::vector;
@@ -311,6 +312,9 @@
 
 bool WiFiService::Unload() {
   Service::Unload();
+  if (wifi_) {
+    wifi_->DestroyServiceLease(*this);
+  }
   hidden_ssid_ = false;
   Error unused_error;
   ClearPassphrase(&unused_error);
diff --git a/wifi_service_unittest.cc b/wifi_service_unittest.cc
index 4b18730..16499e9 100644
--- a/wifi_service_unittest.cc
+++ b/wifi_service_unittest.cc
@@ -32,6 +32,7 @@
 #include "shill/wifi_endpoint.h"
 #include "shill/wpa_supplicant.h"
 
+using base::FilePath;
 using std::map;
 using std::set;
 using std::string;
@@ -1622,4 +1623,12 @@
   }
 }
 
+TEST_F(WiFiServiceTest, Unload) {
+  WiFiServiceRefPtr service = MakeServiceWithWiFi(flimflam::kSecurityNone);
+  EXPECT_CALL(*wifi(), DestroyIPConfigLease(service->GetStorageIdentifier())).
+    Times(1);
+  service->Unload();
+}
+
+
 }  // namespace shill
diff --git a/wifi_unittest.cc b/wifi_unittest.cc
index 94baab9..e6b8bd4 100644
--- a/wifi_unittest.cc
+++ b/wifi_unittest.cc
@@ -61,6 +61,7 @@
 #include "shill/wpa_supplicant.h"
 
 
+using base::FilePath;
 using std::map;
 using std::string;
 using std::vector;
diff --git a/wimax_provider_unittest.cc b/wimax_provider_unittest.cc
index 91490fa..93997eb 100644
--- a/wimax_provider_unittest.cc
+++ b/wimax_provider_unittest.cc
@@ -25,6 +25,7 @@
 #include "shill/proxy_factory.h"
 #include "shill/wimax_service.h"
 
+using base::FilePath;
 using std::string;
 using std::vector;
 using testing::_;