Re-land "[shill] Provide a cmd line toggle between flimflam and shill storage dirs"

This is so that we can easily switch to (and away from) using
the flimflam profile dir (and user profile dirs) when we start shill.

BUG=chromium-os:17253
TEST=unit

Change-Id: I0264162665607bb180688428c4640e42383ae355
Reviewed-on: http://gerrit.chromium.org/gerrit/6568
Reviewed-by: Chris Masone <cmasone@chromium.org>
Tested-by: Chris Masone <cmasone@chromium.org>
diff --git a/cellular_unittest.cc b/cellular_unittest.cc
index ee5bbd4..f227723 100644
--- a/cellular_unittest.cc
+++ b/cellular_unittest.cc
@@ -12,8 +12,10 @@
 #include <mm/mm-modem.h>
 
 #include "shill/cellular_service.h"
+#include "shill/mock_device_info.h"
 #include "shill/mock_dhcp_config.h"
 #include "shill/mock_dhcp_provider.h"
+#include "shill/mock_manager.h"
 #include "shill/mock_modem_cdma_proxy.h"
 #include "shill/mock_modem_proxy.h"
 #include "shill/mock_modem_simple_proxy.h"
@@ -110,6 +112,7 @@
  public:
   CellularTest()
       : manager_(&control_interface_, &dispatcher_, &glib_),
+        device_info_(&control_interface_, &dispatcher_, &manager_),
         proxy_(new MockModemProxy()),
         simple_proxy_(new MockModemSimpleProxy()),
         cdma_proxy_(new MockModemCDMAProxy()),
@@ -134,6 +137,7 @@
     ProxyFactory::set_factory(&proxy_factory_);
     StartRTNLHandler();
     device_->set_dhcp_provider(&dhcp_provider_);
+    EXPECT_CALL(manager_, device_info()).WillRepeatedly(Return(&device_info_));
   }
 
   virtual void TearDown() {
@@ -184,7 +188,8 @@
   NiceMockControl control_interface_;
   TestEventDispatcher dispatcher_;
   MockGLib glib_;
-  Manager manager_;
+  MockManager manager_;
+  MockDeviceInfo device_info_;
   NiceMock<MockSockets> sockets_;
   scoped_ptr<MockModemProxy> proxy_;
   scoped_ptr<MockModemSimpleProxy> simple_proxy_;
@@ -349,6 +354,8 @@
 }
 
 TEST_F(CellularTest, StartConnected) {
+  EXPECT_CALL(device_info_, GetFlags(device_->interface_index(), _))
+      .WillOnce(Return(true));
   device_->type_ = Cellular::kTypeCDMA;
   device_->set_modem_state(Cellular::kModemStateConnected);
   EXPECT_CALL(*proxy_, Enable(true)).Times(1);
@@ -366,7 +373,8 @@
 }
 
 TEST_F(CellularTest, StartLinked) {
-  manager_.device_info()->infos_[device_->interface_index()].flags = IFF_UP;
+  EXPECT_CALL(device_info_, GetFlags(device_->interface_index(), _))
+      .WillOnce(DoAll(SetArgumentPointee<1>(IFF_UP), Return(true)));
   device_->type_ = Cellular::kTypeCDMA;
   device_->set_modem_state(Cellular::kModemStateConnected);
   EXPECT_CALL(*proxy_, Enable(true)).Times(1);
@@ -494,6 +502,9 @@
 }  // namespace {}
 
 TEST_F(CellularTest, Connect) {
+  EXPECT_CALL(device_info_, GetFlags(device_->interface_index(), _))
+      .WillOnce(Return(true))
+      .WillOnce(Return(true));
   device_->state_ = Cellular::kStateConnected;
   device_->Connect();
 
diff --git a/default_profile.cc b/default_profile.cc
index 3f74760..3a3269d 100644
--- a/default_profile.cc
+++ b/default_profile.cc
@@ -4,6 +4,8 @@
 
 #include "shill/default_profile.h"
 
+#include <base/file_path.h>
+#include <base/stringprintf.h>
 #include <chromeos/dbus/service_constants.h>
 
 #include "shill/adaptor_interfaces.h"
@@ -13,11 +15,13 @@
 namespace shill {
 const char DefaultProfile::kDefaultId[] = "default";
 
-DefaultProfile::DefaultProfile(ControlInterface *control_interface,
+DefaultProfile::DefaultProfile(ControlInterface *control,
                                GLib *glib,
                                Manager *manager,
+                               const FilePath &storage_path,
                                const Manager::Properties &manager_props)
-    : Profile(control_interface, glib, manager, Identifier(kDefaultId), true) {
+    : Profile(control, glib, manager, Identifier(kDefaultId), "", true),
+      storage_path_(storage_path) {
   store_.RegisterConstString(flimflam::kCheckPortalListProperty,
                              &manager_props.check_portal_list);
   store_.RegisterConstString(flimflam::kCountryProperty,
@@ -30,4 +34,9 @@
 
 DefaultProfile::~DefaultProfile() {}
 
+bool DefaultProfile::GetStoragePath(FilePath *path) {
+  *path = storage_path_.Append(base::StringPrintf("%s.profile", kDefaultId));
+  return true;
+}
+
 }  // namespace shill
diff --git a/default_profile.h b/default_profile.h
index 36374ae..0876ade 100644
--- a/default_profile.h
+++ b/default_profile.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include <base/file_path.h>
 #include <base/memory/scoped_ptr.h>
 
 #include "shill/manager.h"
@@ -22,15 +23,26 @@
 
 class DefaultProfile : public Profile {
  public:
-  DefaultProfile(ControlInterface *control_interface,
+  DefaultProfile(ControlInterface *control,
                  GLib *glib,
                  Manager *manager,
+                 const FilePath &storage_path,
                  const Manager::Properties &manager_props);
   virtual ~DefaultProfile();
 
+
+  // Sets |path| to the persistent store file path for the default, global
+  // profile. Returns true on success, and false if unable to determine an
+  // appropriate file location.
+  //
+  // In this implementation, |name_| is ignored.
+  virtual bool GetStoragePath(FilePath *path);
+
  private:
   static const char kDefaultId[];
 
+  const FilePath storage_path_;
+
   DISALLOW_COPY_AND_ASSIGN(DefaultProfile);
 };
 
diff --git a/default_profile_unittest.cc b/default_profile_unittest.cc
index 44d755d..5828875 100644
--- a/default_profile_unittest.cc
+++ b/default_profile_unittest.cc
@@ -27,17 +27,22 @@
       : profile_(new DefaultProfile(&control_interface_,
                                     &glib_,
                                     &manager_,
+                                    FilePath(kTestStoragePath),
                                     properties_)) {
   }
 
   virtual ~DefaultProfileTest() {}
 
  protected:
+  static const char kTestStoragePath[];
+
   ProfileRefPtr profile_;
   GLib glib_;
   Manager::Properties properties_;
 };
 
+const char DefaultProfileTest::kTestStoragePath[] = "/no/where";
+
 TEST_F(DefaultProfileTest, GetProperties) {
   Error error(Error::kInvalidProperty, "");
   {
@@ -64,4 +69,10 @@
   }
 }
 
+TEST_F(DefaultProfileTest, GetStoragePath) {
+  FilePath path;
+  EXPECT_TRUE(profile_->GetStoragePath(&path));
+  EXPECT_EQ(string(kTestStoragePath) + "/default.profile", path.value());
+}
+
 }  // namespace shill
diff --git a/device_info_unittest.cc b/device_info_unittest.cc
index 2001c56..bac4b8c 100644
--- a/device_info_unittest.cc
+++ b/device_info_unittest.cc
@@ -21,6 +21,7 @@
 #include "shill/manager.h"
 #include "shill/mock_control.h"
 #include "shill/mock_glib.h"
+#include "shill/mock_manager.h"
 #include "shill/mock_sockets.h"
 #include "shill/rtnl_handler.h"
 #include "shill/rtnl_message.h"
@@ -60,7 +61,7 @@
 
   MockGLib glib_;
   MockControl control_interface_;
-  Manager manager_;
+  MockManager manager_;
   DeviceInfo device_info_;
   TestEventDispatcher dispatcher_;
 };
diff --git a/ephemeral_profile.cc b/ephemeral_profile.cc
index 417666e..1d452d8 100644
--- a/ephemeral_profile.cc
+++ b/ephemeral_profile.cc
@@ -21,7 +21,7 @@
 EphemeralProfile::EphemeralProfile(ControlInterface *control_interface,
                                    GLib *glib,
                                    Manager *manager)
-    : Profile(control_interface, glib, manager, Identifier(), false) {
+    : Profile(control_interface, glib, manager, Identifier(), "", false) {
 }
 
 EphemeralProfile::~EphemeralProfile() {}
diff --git a/manager.cc b/manager.cc
index 43e9bf1..1d04521 100644
--- a/manager.cc
+++ b/manager.cc
@@ -34,18 +34,22 @@
 
 namespace shill {
 
-// static
-const char Manager::kDefaultRunDirectory[] = "/var/run/shill";
-
 Manager::Manager(ControlInterface *control_interface,
                  EventDispatcher *dispatcher,
-                 GLib *glib)
-  : run_path_(FilePath(kDefaultRunDirectory)),
+                 GLib *glib,
+                 const string &run_directory,
+                 const string &storage_directory,
+                 const string &user_storage_format)
+  : run_path_(FilePath(run_directory)),
+    storage_path_(FilePath(storage_directory)),
+    user_storage_format_(user_storage_format),
     adaptor_(control_interface->CreateManagerAdaptor(this)),
     device_info_(control_interface, dispatcher, this),
     modem_info_(control_interface, dispatcher, this, glib),
     running_(false),
-    ephemeral_profile_(new EphemeralProfile(control_interface, glib, this)) {
+    ephemeral_profile_(new EphemeralProfile(control_interface, glib, this)),
+    control_interface_(control_interface),
+    glib_(glib) {
   HelpRegisterDerivedString(flimflam::kActiveProfileProperty,
                             &Manager::GetActiveProfileName,
                             NULL);
@@ -81,10 +85,10 @@
 
   // TODO(cmasone): Wire these up once we actually put in profile support.
   // known_properties_.push_back(flimflam::kProfilesProperty);
-
-  profiles_.push_back(new DefaultProfile(control_interface,
-                                         glib,
+  profiles_.push_back(new DefaultProfile(control_interface_,
+                                         glib_,
                                          this,
+                                         storage_path_,
                                          props_));
   VLOG(2) << "Manager initialized.";
 }
@@ -104,8 +108,11 @@
 void Manager::Start() {
   LOG(INFO) << "Manager started.";
 
-  CHECK(file_util::CreateDirectory(run_path_));
+  CHECK(file_util::CreateDirectory(run_path_)) << run_path_.value();
   Resolver::GetInstance()->set_path(run_path_.Append("resolv.conf"));
+
+  CHECK(file_util::CreateDirectory(storage_path_)) << storage_path_.value();
+
   running_ = true;
   adaptor_->UpdateRunning();
   device_info_.Start();
diff --git a/manager.h b/manager.h
index 9a4aa47..4b6fcba 100644
--- a/manager.h
+++ b/manager.h
@@ -39,10 +39,12 @@
     std::string portal_url;
   };
 
-  // A constructor for the Manager object
   Manager(ControlInterface *control_interface,
           EventDispatcher *dispatcher,
-          GLib *glib);
+          GLib *glib,
+          const std::string &run_directory,
+          const std::string &storage_directory,
+          const std::string &user_storage_format);
   virtual ~Manager();
 
   void AddDeviceToBlackList(const std::string &device_name);
@@ -71,8 +73,6 @@
  private:
   friend class ManagerAdaptorInterface;
 
-  static const char kDefaultRunDirectory[];
-
   std::string CalculateState();
   std::vector<std::string> AvailableTechnologies();
   std::vector<std::string> ConnectedTechnologies();
@@ -90,7 +90,9 @@
                                   Strings(Manager::*get)(void),
                                   bool(Manager::*set)(const Strings&));
 
-  FilePath run_path_;
+  const FilePath run_path_;
+  const FilePath storage_path_;
+  const std::string user_storage_format_;
   scoped_ptr<ManagerAdaptorInterface> adaptor_;
   DeviceInfo device_info_;
   ModemInfo modem_info_;
@@ -100,6 +102,8 @@
   std::vector<ServiceRefPtr> services_;
   std::vector<ProfileRefPtr> profiles_;
   ProfileRefPtr ephemeral_profile_;
+  ControlInterface *control_interface_;
+  GLib *glib_;
 
   // Properties to be get/set via PropertyStore calls.
   Properties props_;
diff --git a/manager_unittest.cc b/manager_unittest.cc
index 2450c86..f2869d1 100644
--- a/manager_unittest.cc
+++ b/manager_unittest.cc
@@ -11,8 +11,8 @@
 #include <base/logging.h>
 #include <base/stl_util-inl.h>
 #include <chromeos/dbus/service_constants.h>
-#include <gtest/gtest.h>
 #include <gmock/gmock.h>
+#include <gtest/gtest.h>
 
 #include "shill/mock_control.h"
 #include "shill/mock_device.h"
diff --git a/mock_manager.h b/mock_manager.h
index 6ebe043..815bcfa 100644
--- a/mock_manager.h
+++ b/mock_manager.h
@@ -23,7 +23,7 @@
   MockManager(ControlInterface *control_interface,
               EventDispatcher *dispatcher,
               GLib *glib)
-      : Manager(control_interface, dispatcher, glib) {
+      : Manager(control_interface, dispatcher, glib, "", "", "") {
   }
   ~MockManager() {}
 
diff --git a/mock_profile.cc b/mock_profile.cc
index 0fc99a0..72e17a5 100644
--- a/mock_profile.cc
+++ b/mock_profile.cc
@@ -18,17 +18,17 @@
 class GLib;
 class Manager;
 
-MockProfile::MockProfile(ControlInterface *control_interface,
+MockProfile::MockProfile(ControlInterface *control,
                          GLib *glib,
                          Manager *manager)
-    : Profile(control_interface, glib, manager, Identifier("mock"), false) {
+    : Profile(control, glib, manager, Identifier("mock"), "", false) {
 }
 
-MockProfile::MockProfile(ControlInterface *control_interface,
+MockProfile::MockProfile(ControlInterface *control,
                          GLib *glib,
                          Manager *manager,
                          const std::string &identifier)
-    : Profile(control_interface, glib, manager, Identifier(identifier), false) {
+    : Profile(control, glib, manager, Identifier(identifier), "", false) {
 }
 
 MockProfile::~MockProfile() {}
diff --git a/mock_profile.h b/mock_profile.h
index c87709f..6d491f6 100644
--- a/mock_profile.h
+++ b/mock_profile.h
@@ -20,10 +20,8 @@
 
 class MockProfile : public Profile {
  public:
-  MockProfile(ControlInterface *control_interface,
-              GLib *glib,
-              Manager *manager);
-  MockProfile(ControlInterface *control_interface,
+  MockProfile(ControlInterface *control, GLib *glib, Manager *manager);
+  MockProfile(ControlInterface *control,
               GLib *glib,
               Manager *manager,
               const std::string &identifier);
diff --git a/modem_info_unittest.cc b/modem_info_unittest.cc
index 8f8515a..099914d 100644
--- a/modem_info_unittest.cc
+++ b/modem_info_unittest.cc
@@ -8,6 +8,7 @@
 #include "shill/manager.h"
 #include "shill/mock_control.h"
 #include "shill/mock_glib.h"
+#include "shill/mock_manager.h"
 #include "shill/modem_info.h"
 #include "shill/modem_manager.h"
 
@@ -27,7 +28,7 @@
   MockGLib glib_;
   MockControl control_interface_;
   EventDispatcher dispatcher_;
-  Manager manager_;
+  MockManager manager_;
   ModemInfo modem_info_;
 };
 
diff --git a/modem_manager_unittest.cc b/modem_manager_unittest.cc
index 5cd1d97..7f3154c 100644
--- a/modem_manager_unittest.cc
+++ b/modem_manager_unittest.cc
@@ -9,6 +9,7 @@
 #include "shill/manager.h"
 #include "shill/mock_control.h"
 #include "shill/mock_glib.h"
+#include "shill/mock_manager.h"
 #include "shill/mock_modem_manager_proxy.h"
 #include "shill/modem.h"
 #include "shill/modem_manager.h"
@@ -64,7 +65,7 @@
   MockGLib glib_;
   MockControl control_interface_;
   EventDispatcher dispatcher_;
-  Manager manager_;
+  MockManager manager_;
   ModemManager modem_manager_;
   scoped_ptr<MockModemManagerProxy> proxy_;
   TestProxyFactory proxy_factory_;
diff --git a/profile.cc b/profile.cc
index ef5182b..d0bcd77 100644
--- a/profile.cc
+++ b/profile.cc
@@ -26,17 +26,16 @@
 
 namespace shill {
 
-const char Profile::kGlobalStorageDir[] = "/var/cache/flimflam";
-const char Profile::kUserStorageDirFormat[] = "/home/%s/user/flimflam";
-
 Profile::Profile(ControlInterface *control_interface,
                  GLib *glib,
                  Manager *manager,
                  const Identifier &name,
+                 const string &user_storage_format,
                  bool connect_to_rpc)
     : manager_(manager),
       name_(name),
-      storage_(glib) {
+      storage_(glib),
+      storage_format_(user_storage_format) {
   if (connect_to_rpc)
     adaptor_.reset(control_interface->CreateProfileAdaptor(this));
 
@@ -150,14 +149,15 @@
   return true;
 }
 
-bool Profile::GetStoragePath(const Identifier &identifier, FilePath *path) {
-  FilePath dir(
-      identifier.user.empty() ?
-      kGlobalStorageDir :
-      base::StringPrintf(kUserStorageDirFormat, identifier.user.c_str()));
+bool Profile::GetStoragePath(FilePath *path) {
+  if (name_.user.empty()) {
+    LOG(ERROR) << "Non-default profiles cannot be stored globally.";
+    return false;
+  }
+  FilePath dir(base::StringPrintf(storage_format_.c_str(), name_.user.c_str()));
   // TODO(petkov): Validate the directory permissions, etc.
   *path = dir.Append(base::StringPrintf("%s.profile",
-                                        identifier.identifier.c_str()));
+                                        name_.identifier.c_str()));
   return true;
 }
 
diff --git a/profile.h b/profile.h
index 7e5b4d1..520664c 100644
--- a/profile.h
+++ b/profile.h
@@ -40,13 +40,11 @@
     std::string identifier;
   };
 
-  static const char kGlobalStorageDir[];
-  static const char kUserStorageDirFormat[];
-
   Profile(ControlInterface *control_interface,
           GLib *glib,
           Manager *manager,
           const Identifier &name,
+          const std::string &user_storage_format,
           bool connect_to_rpc);
   virtual ~Profile();
 
@@ -89,10 +87,12 @@
   static bool ParseIdentifier(const std::string &raw, Identifier *parsed);
 
   // Sets |path| to the persistent store file path for a profile identified by
-  // |identifier|. Returns true on success, and false if unable to determine an
-  // appropriate file location. |identifier| must be a valid identifier,
+  // |name_|. Returns true on success, and false if unable to determine an
+  // appropriate file location. |name_| must be a valid identifier,
   // possibly parsed and validated through Profile::ParseIdentifier.
-  static bool GetStoragePath(const Identifier &identifier, FilePath *path);
+  //
+  // In the default implementation, |name_.user| cannot be empty.
+  virtual bool GetStoragePath(FilePath *path);
 
  protected:
   Manager *manager_;
@@ -127,6 +127,9 @@
   // Persistent store associated with the profile.
   KeyFileStore storage_;
 
+  // Format string used to generate paths to user profile directories.
+  const std::string storage_format_;
+
   scoped_ptr<ProfileAdaptorInterface> adaptor_;
 
   DISALLOW_COPY_AND_ASSIGN(Profile);
diff --git a/profile_unittest.cc b/profile_unittest.cc
index 709e46b..3ae55b4 100644
--- a/profile_unittest.cc
+++ b/profile_unittest.cc
@@ -80,24 +80,29 @@
   Profile::Identifier id;
   id.identifier = kIdentifier;
   ProfileRefPtr profile(
-      new Profile(&control_interface_, &glib_, &manager_, id, false));
+      new Profile(&control_interface_, &glib_, &manager_, id, "", false));
   EXPECT_EQ(kIdentifier, profile->GetFriendlyName());
   id.user = kUser;
-  profile = new Profile(&control_interface_, &glib_, &manager_, id, false);
+  profile = new Profile(&control_interface_, &glib_, &manager_, id, "", false);
   EXPECT_EQ(string(kUser) + "/" + kIdentifier, profile->GetFriendlyName());
 }
 
 TEST_F(ProfileTest, GetStoragePath) {
   static const char kUser[] = "chronos";
   static const char kIdentifier[] = "someprofile";
+  static const char kFormat[] = "/a/place/for/%s";
   FilePath path;
-  Profile::Identifier identifier;
-  identifier.identifier = kIdentifier;
-  EXPECT_TRUE(Profile::GetStoragePath(identifier, &path));
-  EXPECT_EQ("/var/cache/flimflam/someprofile.profile", path.value());
-  identifier.user = kUser;
-  EXPECT_TRUE(Profile::GetStoragePath(identifier, &path));
-  EXPECT_EQ("/home/chronos/user/flimflam/someprofile.profile", path.value());
+  Profile::Identifier id;
+  id.identifier = kIdentifier;
+  ProfileRefPtr profile(
+      new Profile(&control_interface_, &glib_, &manager_, id, "", false));
+  EXPECT_FALSE(profile->GetStoragePath(&path));
+  id.user = kUser;
+  profile =
+      new Profile(&control_interface_, &glib_, &manager_, id, kFormat, false);
+  EXPECT_TRUE(profile->GetStoragePath(&path));
+  string suffix = base::StringPrintf("/%s.profile", kIdentifier);
+  EXPECT_EQ(base::StringPrintf(kFormat, kUser) + suffix, path.value());
 }
 
 TEST_F(ProfileTest, ServiceManagement) {
diff --git a/property_store_unittest.cc b/property_store_unittest.cc
index a9bc561..e84ffec 100644
--- a/property_store_unittest.cc
+++ b/property_store_unittest.cc
@@ -62,7 +62,12 @@
     DBusAdaptor::Uint32ToVariant(0);
 
 PropertyStoreTest::PropertyStoreTest()
-    : manager_(&control_interface_, &dispatcher_, &glib_),
+    : manager_(&control_interface_,
+               &dispatcher_,
+               &glib_,
+               run_dir_.path().value(),
+               storage_dir_.path().value(),
+               string()),
       invalid_args_(Error::kErrorNames[Error::kInvalidArguments]),
       invalid_prop_(Error::kErrorNames[Error::kInvalidProperty]) {
 }
diff --git a/property_store_unittest.h b/property_store_unittest.h
index a5cb0e4..6e451c5 100644
--- a/property_store_unittest.h
+++ b/property_store_unittest.h
@@ -9,9 +9,10 @@
 #include <string>
 #include <vector>
 
+#include <base/memory/scoped_temp_dir.h>
 #include <dbus-c++/dbus.h>
-#include <gtest/gtest.h>
 #include <gmock/gmock.h>
+#include <gtest/gtest.h>
 
 #include "shill/dbus_adaptor.h"
 #include "shill/error.h"
@@ -46,6 +47,8 @@
   virtual ~PropertyStoreTest();
 
  protected:
+  ScopedTempDir run_dir_;
+  ScopedTempDir storage_dir_;
   MockControl control_interface_;
   EventDispatcher dispatcher_;
   Manager manager_;
diff --git a/rtnl_handler_unittest.cc b/rtnl_handler_unittest.cc
index 3530631..a715965 100644
--- a/rtnl_handler_unittest.cc
+++ b/rtnl_handler_unittest.cc
@@ -15,6 +15,7 @@
 #include "shill/manager.h"
 #include "shill/mock_control.h"
 #include "shill/mock_glib.h"
+#include "shill/mock_manager.h"
 #include "shill/mock_sockets.h"
 #include "shill/rtnl_handler.h"
 #include "shill/rtnl_message.h"
@@ -81,7 +82,7 @@
   StrictMock<MockSockets> sockets_;
   MockGLib glib_;
   MockControl control_interface_;
-  Manager manager_;
+  MockManager manager_;
   TestEventDispatcher dispatcher_;
   scoped_ptr<Callback1<const RTNLMessage &>::Type> callback_;
   ScopedRunnableMethodFactory<RTNLHandlerTest> task_factory_;
diff --git a/shill_config.cc b/shill_config.cc
index c876b6d..ddf1c79 100644
--- a/shill_config.cc
+++ b/shill_config.cc
@@ -6,9 +6,39 @@
 
 namespace shill {
 
+// static
 const char Config::kShillDefaultPrefsDir[] = "/var/lib/shill";
 
-Config::Config(/*FilePath &prefs_dir, FilePath &def_prefs_dir*/)
-  /* : prefs_dir_(prefs_dir), def_prefs_dir_(def_prefs_dir) */ {}
+// static
+const char Config::kDefaultRunDirectory[] = "/var/run/shill";
+// static
+const char Config::kDefaultStorageDirectory[] = "/var/cache/shill";
+// static
+const char Config::kDefaultUserStorageFormat[] = "/home/%s/user/shill";
+// static
+const char Config::kFlimflamStorageDirectory[] = "/var/cache/flimflam";
+// static
+const char Config::kFlimflamUserStorageFormat[] = "/home/%s/user/flimflam";
+
+Config::Config() : use_flimflam_(false) {
+}
+
+Config::~Config() {}
+
+std::string Config::RunDirectory() {
+  return kDefaultRunDirectory;
+}
+
+std::string Config::StorageDirectory() {
+  return (use_flimflam_ ?
+          kFlimflamStorageDirectory :
+          kDefaultStorageDirectory);
+}
+
+std::string Config::UserStorageDirectoryFormat() {
+  return (use_flimflam_ ?
+          kFlimflamUserStorageFormat :
+          kDefaultUserStorageFormat);
+}
 
 }  // namespace shill
diff --git a/shill_config.h b/shill_config.h
index 651b329..8229099 100644
--- a/shill_config.h
+++ b/shill_config.h
@@ -5,20 +5,33 @@
 #ifndef SHILL_CONFIG_
 #define SHILL_CONFIG_
 
+#include <string>
+
 namespace shill {
 
 class Config {
  public:
-  Config(/* FilePath &prefs_dir, FilePath &def_prefs_dir */);
   static const char kShillDefaultPrefsDir[];
 
+  Config();
+  virtual ~Config();
+
+  void UseFlimflamStorageDirs() { use_flimflam_ = true; }
+
+  std::string RunDirectory();
+  std::string StorageDirectory();
+  std::string UserStorageDirectoryFormat();
+
  private:
-  /*
-  FilePath prefs_dir_;
-  FilePath def_prefs_dir_;
-  */
+  static const char kDefaultRunDirectory[];
+  static const char kDefaultStorageDirectory[];
+  static const char kDefaultUserStorageFormat[];
+  static const char kFlimflamStorageDirectory[];
+  static const char kFlimflamUserStorageFormat[];
+
+  bool use_flimflam_;
 };
 
 }  // namespace shill
 
-#endif  // SHILL_MANAGER_
+#endif  // SHILL_CONFIG_
diff --git a/shill_daemon.cc b/shill_daemon.cc
index f789186..323f285 100644
--- a/shill_daemon.cc
+++ b/shill_daemon.cc
@@ -8,10 +8,12 @@
 
 #include <string>
 
+#include <base/file_path.h>
 #include <base/logging.h>
 
 #include "shill/dhcp_provider.h"
 #include "shill/rtnl_handler.h"
+#include "shill/shill_config.h"
 
 using std::string;
 
@@ -23,7 +25,13 @@
 Daemon::Daemon(Config *config, ControlInterface *control)
     : config_(config),
       control_(control),
-      manager_(control_, &dispatcher_, &glib_) { }
+      manager_(control_,
+               &dispatcher_,
+               &glib_,
+               config->RunDirectory(),
+               config->StorageDirectory(),
+               config->UserStorageDirectoryFormat()) {
+}
 Daemon::~Daemon() {}
 
 void Daemon::AddDeviceToBlackList(const string &device_name) {
diff --git a/shill_main.cc b/shill_main.cc
index 769669d..5837947 100644
--- a/shill_main.cc
+++ b/shill_main.cc
@@ -35,6 +35,8 @@
 static const char kHelp[] = "help";
 // LOG() level. 0 = INFO, 1 = WARNING, 2 = ERROR.
 static const char kLogLevel[] = "log-level";
+// Use the same directories flimflam uses for global, user profiles..
+static const char kUseFlimflamProfiles[] = "use-flimflam-profiles";
 
 // The help message shown if help flag is passed to the program.
 static const char kHelpMessage[] = "\n"
@@ -49,6 +51,8 @@
     "    Do not manage devices named device1 or device2\n"
     "  --log-level=N\n"
     "    LOG() level. 0 = INFO, 1 = WARNING, 2 = ERROR.\n"
+    "  --use-flimflam-profiles\n"
+    "    Use the same directories flimflam uses for global, user profiles.\n"
     "  --v=N\n"
     "    Enables VLOG(N) and below.\n"
     "  --vmodule=\"*file_pattern*=1,certain_file.cc=2\".\n"
@@ -97,6 +101,8 @@
       cl->GetSwitchValueASCII(switches::kDefaultConfigDir));
 
   shill::Config config; /* (config_dir, default_config_dir) */
+  if (cl->HasSwitch(switches::kUseFlimflamProfiles))
+    config.UseFlimflamStorageDirs();
 
   // TODO(pstew): This should be chosen based on config
   scoped_ptr<shill::DBusControl> dbus_control(new shill::DBusControl());
diff --git a/wifi_unittest.cc b/wifi_unittest.cc
index 78a49cc..b3872b0 100644
--- a/wifi_unittest.cc
+++ b/wifi_unittest.cc
@@ -13,12 +13,13 @@
 #include <base/string_util.h>
 #include <dbus-c++/dbus.h>
 #include <chromeos/dbus/service_constants.h>
-#include <gtest/gtest.h>
 #include <gmock/gmock.h>
+#include <gtest/gtest.h>
 
 #include "shill/dbus_adaptor.h"
 #include "shill/manager.h"
 #include "shill/mock_device.h"
+#include "shill/mock_manager.h"
 #include "shill/mock_supplicant_interface_proxy.h"
 #include "shill/mock_supplicant_process_proxy.h"
 #include "shill/nice_mock_control.h"
@@ -171,7 +172,7 @@
 
  private:
   NiceMockControl control_interface_;
-  Manager manager_;
+  MockManager manager_;
   WiFiRefPtr wifi_;
 
   // protected fields interspersed between private fields, due to