Home | History | Annotate | Download | only in dbus
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chromeos/dbus/session_manager_client.h"
      6 
      7 #include <map>
      8 
      9 #include "base/bind.h"
     10 #include "base/callback.h"
     11 #include "base/file_util.h"
     12 #include "base/files/file_path.h"
     13 #include "base/location.h"
     14 #include "base/path_service.h"
     15 #include "base/strings/string_util.h"
     16 #include "base/threading/worker_pool.h"
     17 #include "chromeos/chromeos_paths.h"
     18 #include "chromeos/dbus/blocking_method_caller.h"
     19 #include "chromeos/dbus/cryptohome_client.h"
     20 #include "dbus/bus.h"
     21 #include "dbus/message.h"
     22 #include "dbus/object_path.h"
     23 #include "dbus/object_proxy.h"
     24 #include "third_party/cros_system_api/dbus/service_constants.h"
     25 
     26 namespace chromeos {
     27 
     28 // The SessionManagerClient implementation used in production.
     29 class SessionManagerClientImpl : public SessionManagerClient {
     30  public:
     31   SessionManagerClientImpl()
     32       : session_manager_proxy_(NULL),
     33         weak_ptr_factory_(this) {}
     34 
     35   virtual ~SessionManagerClientImpl() {
     36   }
     37 
     38   // SessionManagerClient overrides:
     39   virtual void AddObserver(Observer* observer) OVERRIDE {
     40     observers_.AddObserver(observer);
     41   }
     42 
     43   virtual void RemoveObserver(Observer* observer) OVERRIDE {
     44     observers_.RemoveObserver(observer);
     45   }
     46 
     47   virtual bool HasObserver(Observer* observer) OVERRIDE {
     48     return observers_.HasObserver(observer);
     49   }
     50 
     51   virtual void EmitLoginPromptReady() OVERRIDE {
     52     SimpleMethodCallToSessionManager(
     53         login_manager::kSessionManagerEmitLoginPromptReady);
     54   }
     55 
     56   virtual void EmitLoginPromptVisible() OVERRIDE {
     57     SimpleMethodCallToSessionManager(
     58         login_manager::kSessionManagerEmitLoginPromptVisible);
     59     FOR_EACH_OBSERVER(Observer, observers_, EmitLoginPromptVisibleCalled());
     60   }
     61 
     62   virtual void RestartJob(int pid, const std::string& command_line) OVERRIDE {
     63     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
     64                                  login_manager::kSessionManagerRestartJob);
     65     dbus::MessageWriter writer(&method_call);
     66     writer.AppendInt32(pid);
     67     writer.AppendString(command_line);
     68     session_manager_proxy_->CallMethod(
     69         &method_call,
     70         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
     71         base::Bind(&SessionManagerClientImpl::OnRestartJob,
     72                    weak_ptr_factory_.GetWeakPtr()));
     73   }
     74 
     75   virtual void StartSession(const std::string& user_email) OVERRIDE {
     76     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
     77                                  login_manager::kSessionManagerStartSession);
     78     dbus::MessageWriter writer(&method_call);
     79     writer.AppendString(user_email);
     80     writer.AppendString("");  // Unique ID is deprecated
     81     session_manager_proxy_->CallMethod(
     82         &method_call,
     83         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
     84         base::Bind(&SessionManagerClientImpl::OnStartSession,
     85                    weak_ptr_factory_.GetWeakPtr()));
     86   }
     87 
     88   virtual void StopSession() OVERRIDE {
     89     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
     90                                  login_manager::kSessionManagerStopSession);
     91     dbus::MessageWriter writer(&method_call);
     92     writer.AppendString("");  // Unique ID is deprecated
     93     session_manager_proxy_->CallMethod(
     94         &method_call,
     95         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
     96         base::Bind(&SessionManagerClientImpl::OnStopSession,
     97                    weak_ptr_factory_.GetWeakPtr()));
     98   }
     99 
    100   virtual void StartDeviceWipe() OVERRIDE {
    101     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
    102                                  login_manager::kSessionManagerStartDeviceWipe);
    103     session_manager_proxy_->CallMethod(
    104         &method_call,
    105         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    106         base::Bind(&SessionManagerClientImpl::OnDeviceWipe,
    107                    weak_ptr_factory_.GetWeakPtr()));
    108   }
    109 
    110   virtual void RequestLockScreen() OVERRIDE {
    111     SimpleMethodCallToSessionManager(login_manager::kSessionManagerLockScreen);
    112   }
    113 
    114   virtual void NotifyLockScreenShown() OVERRIDE {
    115     SimpleMethodCallToSessionManager(
    116         login_manager::kSessionManagerHandleLockScreenShown);
    117   }
    118 
    119   virtual void NotifyLockScreenDismissed() OVERRIDE {
    120     SimpleMethodCallToSessionManager(
    121         login_manager::kSessionManagerHandleLockScreenDismissed);
    122   }
    123 
    124   virtual void RetrieveActiveSessions(
    125       const ActiveSessionsCallback& callback) OVERRIDE {
    126     dbus::MethodCall method_call(
    127         login_manager::kSessionManagerInterface,
    128         login_manager::kSessionManagerRetrieveActiveSessions);
    129 
    130     session_manager_proxy_->CallMethod(
    131         &method_call,
    132         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    133         base::Bind(&SessionManagerClientImpl::OnRetrieveActiveSessions,
    134                    weak_ptr_factory_.GetWeakPtr(),
    135                    login_manager::kSessionManagerRetrieveActiveSessions,
    136                    callback));
    137   }
    138 
    139   virtual void RetrieveDevicePolicy(
    140       const RetrievePolicyCallback& callback) OVERRIDE {
    141     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
    142                                  login_manager::kSessionManagerRetrievePolicy);
    143     session_manager_proxy_->CallMethod(
    144         &method_call,
    145         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    146         base::Bind(&SessionManagerClientImpl::OnRetrievePolicy,
    147                    weak_ptr_factory_.GetWeakPtr(),
    148                    login_manager::kSessionManagerRetrievePolicy,
    149                    callback));
    150   }
    151 
    152   virtual void RetrievePolicyForUser(
    153       const std::string& username,
    154       const RetrievePolicyCallback& callback) OVERRIDE {
    155     CallRetrievePolicyByUsername(
    156         login_manager::kSessionManagerRetrievePolicyForUser,
    157         username,
    158         callback);
    159   }
    160 
    161   virtual std::string BlockingRetrievePolicyForUser(
    162       const std::string& username) OVERRIDE {
    163     dbus::MethodCall method_call(
    164         login_manager::kSessionManagerInterface,
    165         login_manager::kSessionManagerRetrievePolicyForUser);
    166     dbus::MessageWriter writer(&method_call);
    167     writer.AppendString(username);
    168     scoped_ptr<dbus::Response> response =
    169         blocking_method_caller_->CallMethodAndBlock(&method_call);
    170     std::string policy;
    171     ExtractString(login_manager::kSessionManagerRetrievePolicyForUser,
    172                   response.get(),
    173                   &policy);
    174     return policy;
    175   }
    176 
    177   virtual void RetrieveDeviceLocalAccountPolicy(
    178       const std::string& account_name,
    179       const RetrievePolicyCallback& callback) OVERRIDE {
    180     CallRetrievePolicyByUsername(
    181         login_manager::kSessionManagerRetrieveDeviceLocalAccountPolicy,
    182         account_name,
    183         callback);
    184   }
    185 
    186   virtual void StoreDevicePolicy(const std::string& policy_blob,
    187                                  const StorePolicyCallback& callback) OVERRIDE {
    188     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
    189                                  login_manager::kSessionManagerStorePolicy);
    190     dbus::MessageWriter writer(&method_call);
    191     // static_cast does not work due to signedness.
    192     writer.AppendArrayOfBytes(
    193         reinterpret_cast<const uint8*>(policy_blob.data()), policy_blob.size());
    194     session_manager_proxy_->CallMethod(
    195         &method_call,
    196         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    197         base::Bind(&SessionManagerClientImpl::OnStorePolicy,
    198                    weak_ptr_factory_.GetWeakPtr(),
    199                    login_manager::kSessionManagerStorePolicy,
    200                    callback));
    201   }
    202 
    203   virtual void StorePolicyForUser(
    204       const std::string& username,
    205       const std::string& policy_blob,
    206       const std::string& ignored_policy_key,
    207       const StorePolicyCallback& callback) OVERRIDE {
    208     CallStorePolicyByUsername(login_manager::kSessionManagerStorePolicyForUser,
    209                               username,
    210                               policy_blob,
    211                               callback);
    212   }
    213 
    214   virtual void StoreDeviceLocalAccountPolicy(
    215       const std::string& account_name,
    216       const std::string& policy_blob,
    217       const StorePolicyCallback& callback) OVERRIDE {
    218     CallStorePolicyByUsername(
    219         login_manager::kSessionManagerStoreDeviceLocalAccountPolicy,
    220         account_name,
    221         policy_blob,
    222         callback);
    223   }
    224 
    225   virtual void SetFlagsForUser(const std::string& username,
    226                                const std::vector<std::string>& flags) OVERRIDE {
    227     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
    228                                  login_manager::kSessionManagerSetFlagsForUser);
    229     dbus::MessageWriter writer(&method_call);
    230     writer.AppendString(username);
    231     writer.AppendArrayOfStrings(flags);
    232     session_manager_proxy_->CallMethod(
    233         &method_call,
    234         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    235         dbus::ObjectProxy::EmptyResponseCallback());
    236   }
    237 
    238  protected:
    239   virtual void Init(dbus::Bus* bus) OVERRIDE {
    240     session_manager_proxy_ = bus->GetObjectProxy(
    241         login_manager::kSessionManagerServiceName,
    242         dbus::ObjectPath(login_manager::kSessionManagerServicePath));
    243     blocking_method_caller_.reset(
    244         new BlockingMethodCaller(bus, session_manager_proxy_));
    245 
    246     // Signals emitted on Chromium's interface.  Many of these ought to be
    247     // method calls instead.
    248     session_manager_proxy_->ConnectToSignal(
    249         chromium::kChromiumInterface,
    250         chromium::kOwnerKeySetSignal,
    251         base::Bind(&SessionManagerClientImpl::OwnerKeySetReceived,
    252                    weak_ptr_factory_.GetWeakPtr()),
    253         base::Bind(&SessionManagerClientImpl::SignalConnected,
    254                    weak_ptr_factory_.GetWeakPtr()));
    255     session_manager_proxy_->ConnectToSignal(
    256         chromium::kChromiumInterface,
    257         chromium::kPropertyChangeCompleteSignal,
    258         base::Bind(&SessionManagerClientImpl::PropertyChangeCompleteReceived,
    259                    weak_ptr_factory_.GetWeakPtr()),
    260         base::Bind(&SessionManagerClientImpl::SignalConnected,
    261                    weak_ptr_factory_.GetWeakPtr()));
    262     session_manager_proxy_->ConnectToSignal(
    263         chromium::kChromiumInterface,
    264         chromium::kLockScreenSignal,
    265         base::Bind(&SessionManagerClientImpl::ScreenLockReceived,
    266                    weak_ptr_factory_.GetWeakPtr()),
    267         base::Bind(&SessionManagerClientImpl::SignalConnected,
    268                    weak_ptr_factory_.GetWeakPtr()));
    269     session_manager_proxy_->ConnectToSignal(
    270         chromium::kChromiumInterface,
    271         chromium::kLivenessRequestedSignal,
    272         base::Bind(&SessionManagerClientImpl::LivenessRequestedReceived,
    273                    weak_ptr_factory_.GetWeakPtr()),
    274         base::Bind(&SessionManagerClientImpl::SignalConnected,
    275                    weak_ptr_factory_.GetWeakPtr()));
    276 
    277     // Signals emitted on the session manager's interface.
    278     session_manager_proxy_->ConnectToSignal(
    279         login_manager::kSessionManagerInterface,
    280         login_manager::kScreenIsLockedSignal,
    281         base::Bind(&SessionManagerClientImpl::ScreenIsLockedReceived,
    282                    weak_ptr_factory_.GetWeakPtr()),
    283         base::Bind(&SessionManagerClientImpl::SignalConnected,
    284                    weak_ptr_factory_.GetWeakPtr()));
    285     session_manager_proxy_->ConnectToSignal(
    286         login_manager::kSessionManagerInterface,
    287         login_manager::kScreenIsUnlockedSignal,
    288         base::Bind(&SessionManagerClientImpl::ScreenIsUnlockedReceived,
    289                    weak_ptr_factory_.GetWeakPtr()),
    290         base::Bind(&SessionManagerClientImpl::SignalConnected,
    291                    weak_ptr_factory_.GetWeakPtr()));
    292   }
    293 
    294  private:
    295   // Makes a method call to the session manager with no arguments and no
    296   // response.
    297   void SimpleMethodCallToSessionManager(const std::string& method_name) {
    298     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
    299                                  method_name);
    300     session_manager_proxy_->CallMethod(
    301         &method_call,
    302         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    303         dbus::ObjectProxy::EmptyResponseCallback());
    304   }
    305 
    306   // Helper for RetrieveDeviceLocalAccountPolicy and RetrievePolicyForUser.
    307   void CallRetrievePolicyByUsername(const std::string& method_name,
    308                                     const std::string& username,
    309                                     const RetrievePolicyCallback& callback) {
    310     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
    311                                  method_name);
    312     dbus::MessageWriter writer(&method_call);
    313     writer.AppendString(username);
    314     session_manager_proxy_->CallMethod(
    315         &method_call,
    316         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    317         base::Bind(
    318             &SessionManagerClientImpl::OnRetrievePolicy,
    319             weak_ptr_factory_.GetWeakPtr(),
    320             method_name,
    321             callback));
    322   }
    323 
    324   void CallStorePolicyByUsername(const std::string& method_name,
    325                                  const std::string& username,
    326                                  const std::string& policy_blob,
    327                                  const StorePolicyCallback& callback) {
    328     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
    329                                  method_name);
    330     dbus::MessageWriter writer(&method_call);
    331     writer.AppendString(username);
    332     // static_cast does not work due to signedness.
    333     writer.AppendArrayOfBytes(
    334         reinterpret_cast<const uint8*>(policy_blob.data()), policy_blob.size());
    335     session_manager_proxy_->CallMethod(
    336         &method_call,
    337         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    338         base::Bind(
    339             &SessionManagerClientImpl::OnStorePolicy,
    340             weak_ptr_factory_.GetWeakPtr(),
    341             method_name,
    342             callback));
    343   }
    344 
    345   // Called when kSessionManagerRestartJob method is complete.
    346   void OnRestartJob(dbus::Response* response) {
    347     LOG_IF(ERROR, !response)
    348         << "Failed to call "
    349         << login_manager::kSessionManagerRestartJob;
    350   }
    351 
    352   // Called when kSessionManagerStartSession method is complete.
    353   void OnStartSession(dbus::Response* response) {
    354     LOG_IF(ERROR, !response)
    355         << "Failed to call "
    356         << login_manager::kSessionManagerStartSession;
    357   }
    358 
    359   // Called when kSessionManagerStopSession method is complete.
    360   void OnStopSession(dbus::Response* response) {
    361     LOG_IF(ERROR, !response)
    362         << "Failed to call "
    363         << login_manager::kSessionManagerStopSession;
    364   }
    365 
    366   // Called when kSessionManagerStopSession method is complete.
    367   void OnDeviceWipe(dbus::Response* response) {
    368     LOG_IF(ERROR, !response)
    369         << "Failed to call "
    370         << login_manager::kSessionManagerStartDeviceWipe;
    371   }
    372 
    373   // Called when kSessionManagerRetrieveActiveSessions method is complete.
    374   void OnRetrieveActiveSessions(const std::string& method_name,
    375                                 const ActiveSessionsCallback& callback,
    376                                 dbus::Response* response) {
    377     ActiveSessionsMap sessions;
    378     bool success = false;
    379     if (!response) {
    380       LOG(ERROR) << "Failed to call " << method_name;
    381       callback.Run(sessions, success);
    382       return;
    383     }
    384 
    385     dbus::MessageReader reader(response);
    386     dbus::MessageReader array_reader(NULL);
    387 
    388     if (!reader.PopArray(&array_reader)) {
    389       LOG(ERROR) << method_name << " response is incorrect: "
    390                  << response->ToString();
    391     } else {
    392       while (array_reader.HasMoreData()) {
    393         dbus::MessageReader dict_entry_reader(NULL);
    394         std::string key;
    395         std::string value;
    396         if (!array_reader.PopDictEntry(&dict_entry_reader) ||
    397             !dict_entry_reader.PopString(&key) ||
    398             !dict_entry_reader.PopString(&value)) {
    399           LOG(ERROR) << method_name << " response is incorrect: "
    400                      << response->ToString();
    401         } else {
    402           sessions[key] = value;
    403         }
    404       }
    405       success = true;
    406     }
    407     callback.Run(sessions, success);
    408   }
    409 
    410   void ExtractString(const std::string& method_name,
    411                      dbus::Response* response,
    412                      std::string* extracted) {
    413     if (!response) {
    414       LOG(ERROR) << "Failed to call " << method_name;
    415       return;
    416     }
    417     dbus::MessageReader reader(response);
    418     uint8* values = NULL;
    419     size_t length = 0;
    420     if (!reader.PopArrayOfBytes(&values, &length)) {
    421       LOG(ERROR) << "Invalid response: " << response->ToString();
    422       return;
    423     }
    424     // static_cast does not work due to signedness.
    425     extracted->assign(reinterpret_cast<char*>(values), length);
    426   }
    427 
    428   // Called when kSessionManagerRetrievePolicy or
    429   // kSessionManagerRetrievePolicyForUser method is complete.
    430   void OnRetrievePolicy(const std::string& method_name,
    431                         const RetrievePolicyCallback& callback,
    432                         dbus::Response* response) {
    433     std::string serialized_proto;
    434     ExtractString(method_name, response, &serialized_proto);
    435     callback.Run(serialized_proto);
    436   }
    437 
    438   // Called when kSessionManagerStorePolicy or kSessionManagerStorePolicyForUser
    439   // method is complete.
    440   void OnStorePolicy(const std::string& method_name,
    441                      const StorePolicyCallback& callback,
    442                      dbus::Response* response) {
    443     bool success = false;
    444     if (!response) {
    445       LOG(ERROR) << "Failed to call " << method_name;
    446     } else {
    447       dbus::MessageReader reader(response);
    448       if (!reader.PopBool(&success))
    449         LOG(ERROR) << "Invalid response: " << response->ToString();
    450     }
    451     callback.Run(success);
    452   }
    453 
    454   // Called when the owner key set signal is received.
    455   void OwnerKeySetReceived(dbus::Signal* signal) {
    456     dbus::MessageReader reader(signal);
    457     std::string result_string;
    458     if (!reader.PopString(&result_string)) {
    459       LOG(ERROR) << "Invalid signal: " << signal->ToString();
    460       return;
    461     }
    462     const bool success = StartsWithASCII(result_string, "success", false);
    463     FOR_EACH_OBSERVER(Observer, observers_, OwnerKeySet(success));
    464   }
    465 
    466   // Called when the property change complete signal is received.
    467   void PropertyChangeCompleteReceived(dbus::Signal* signal) {
    468     dbus::MessageReader reader(signal);
    469     std::string result_string;
    470     if (!reader.PopString(&result_string)) {
    471       LOG(ERROR) << "Invalid signal: " << signal->ToString();
    472       return;
    473     }
    474     const bool success = StartsWithASCII(result_string, "success", false);
    475     FOR_EACH_OBSERVER(Observer, observers_, PropertyChangeComplete(success));
    476   }
    477 
    478   void ScreenLockReceived(dbus::Signal* signal) {
    479     FOR_EACH_OBSERVER(Observer, observers_, LockScreen());
    480   }
    481 
    482   void LivenessRequestedReceived(dbus::Signal* signal) {
    483     SimpleMethodCallToSessionManager(
    484         login_manager::kSessionManagerHandleLivenessConfirmed);
    485   }
    486 
    487   void ScreenIsLockedReceived(dbus::Signal* signal) {
    488     FOR_EACH_OBSERVER(Observer, observers_, ScreenIsLocked());
    489   }
    490 
    491   void ScreenIsUnlockedReceived(dbus::Signal* signal) {
    492     FOR_EACH_OBSERVER(Observer, observers_, ScreenIsUnlocked());
    493   }
    494 
    495   // Called when the object is connected to the signal.
    496   void SignalConnected(const std::string& interface_name,
    497                        const std::string& signal_name,
    498                        bool success) {
    499     LOG_IF(ERROR, !success) << "Failed to connect to " << signal_name;
    500   }
    501 
    502   dbus::ObjectProxy* session_manager_proxy_;
    503   scoped_ptr<BlockingMethodCaller> blocking_method_caller_;
    504   ObserverList<Observer> observers_;
    505 
    506   // Note: This should remain the last member so it'll be destroyed and
    507   // invalidate its weak pointers before any other members are destroyed.
    508   base::WeakPtrFactory<SessionManagerClientImpl> weak_ptr_factory_;
    509 
    510   DISALLOW_COPY_AND_ASSIGN(SessionManagerClientImpl);
    511 };
    512 
    513 // The SessionManagerClient implementation used on Linux desktop,
    514 // which does nothing.
    515 class SessionManagerClientStubImpl : public SessionManagerClient {
    516  public:
    517   SessionManagerClientStubImpl() {}
    518   virtual ~SessionManagerClientStubImpl() {}
    519 
    520   // SessionManagerClient overrides
    521   virtual void Init(dbus::Bus* bus) OVERRIDE {
    522     // Make sure that there are no keys left over from a previous browser run.
    523     base::FilePath user_policy_key_dir;
    524     if (PathService::Get(chromeos::DIR_USER_POLICY_KEYS,
    525                          &user_policy_key_dir)) {
    526       base::WorkerPool::PostTask(
    527           FROM_HERE,
    528           base::Bind(base::IgnoreResult(&base::DeleteFile),
    529                      user_policy_key_dir, true),
    530           false);
    531     }
    532   }
    533 
    534   virtual void AddObserver(Observer* observer) OVERRIDE {
    535     observers_.AddObserver(observer);
    536   }
    537   virtual void RemoveObserver(Observer* observer) OVERRIDE {
    538     observers_.RemoveObserver(observer);
    539   }
    540   virtual bool HasObserver(Observer* observer) OVERRIDE {
    541     return observers_.HasObserver(observer);
    542   }
    543   virtual void EmitLoginPromptReady() OVERRIDE {}
    544   virtual void EmitLoginPromptVisible() OVERRIDE {}
    545   virtual void RestartJob(int pid, const std::string& command_line) OVERRIDE {}
    546   virtual void StartSession(const std::string& user_email) OVERRIDE {}
    547   virtual void StopSession() OVERRIDE {}
    548   virtual void StartDeviceWipe() OVERRIDE {}
    549   virtual void RequestLockScreen() OVERRIDE {
    550     FOR_EACH_OBSERVER(Observer, observers_, LockScreen());
    551   }
    552   virtual void NotifyLockScreenShown() OVERRIDE {
    553     FOR_EACH_OBSERVER(Observer, observers_, ScreenIsLocked());
    554   }
    555   virtual void NotifyLockScreenDismissed() OVERRIDE {
    556     FOR_EACH_OBSERVER(Observer, observers_, ScreenIsUnlocked());
    557   }
    558   virtual void RetrieveActiveSessions(
    559       const ActiveSessionsCallback& callback) OVERRIDE {}
    560   virtual void RetrieveDevicePolicy(
    561       const RetrievePolicyCallback& callback) OVERRIDE {
    562     callback.Run(device_policy_);
    563   }
    564   virtual void RetrievePolicyForUser(
    565       const std::string& username,
    566       const RetrievePolicyCallback& callback) OVERRIDE {
    567     callback.Run(user_policies_[username]);
    568   }
    569   virtual std::string BlockingRetrievePolicyForUser(
    570       const std::string& username) OVERRIDE {
    571     return user_policies_[username];
    572   }
    573   virtual void RetrieveDeviceLocalAccountPolicy(
    574       const std::string& account_name,
    575       const RetrievePolicyCallback& callback) OVERRIDE {
    576     callback.Run(user_policies_[account_name]);
    577   }
    578   virtual void StoreDevicePolicy(const std::string& policy_blob,
    579                                  const StorePolicyCallback& callback) OVERRIDE {
    580     device_policy_ = policy_blob;
    581     callback.Run(true);
    582   }
    583   virtual void StorePolicyForUser(
    584       const std::string& username,
    585       const std::string& policy_blob,
    586       const std::string& policy_key,
    587       const StorePolicyCallback& callback) OVERRIDE {
    588     if (policy_key.empty()) {
    589       user_policies_[username] = policy_blob;
    590       callback.Run(true);
    591       return;
    592     }
    593     // The session manager writes the user policy key to a well-known
    594     // location. Do the same with the stub impl, so that user policy works and
    595     // can be tested on desktop builds.
    596     // TODO(joaodasilva): parse the PolicyFetchResponse in |policy_blob| to get
    597     // the policy key directly, after moving the policy protobufs to a top-level
    598     // directory. The |policy_key| argument to this method can then be removed.
    599     // http://crbug.com/240269
    600     base::FilePath key_path;
    601     if (!PathService::Get(chromeos::DIR_USER_POLICY_KEYS, &key_path)) {
    602       callback.Run(false);
    603       return;
    604     }
    605     const std::string sanitized =
    606         CryptohomeClient::GetStubSanitizedUsername(username);
    607     key_path = key_path.AppendASCII(sanitized).AppendASCII("policy.pub");
    608     // Assume that the key write is successful.
    609     user_policies_[username] = policy_blob;
    610     base::WorkerPool::PostTaskAndReply(
    611         FROM_HERE,
    612         base::Bind(&SessionManagerClientStubImpl::StoreFileInBackground,
    613                    key_path, policy_key),
    614         base::Bind(callback, true),
    615         false);
    616   }
    617   virtual void StoreDeviceLocalAccountPolicy(
    618       const std::string& account_name,
    619       const std::string& policy_blob,
    620       const StorePolicyCallback& callback) OVERRIDE {
    621     user_policies_[account_name] = policy_blob;
    622     callback.Run(true);
    623   }
    624   virtual void SetFlagsForUser(const std::string& username,
    625                                const std::vector<std::string>& flags) OVERRIDE {
    626   }
    627 
    628   static void StoreFileInBackground(const base::FilePath& path,
    629                                     const std::string& data) {
    630     const int size = static_cast<int>(data.size());
    631     if (!base::CreateDirectory(path.DirName()) ||
    632         file_util::WriteFile(path, data.data(), size) != size) {
    633       LOG(WARNING) << "Failed to write policy key to " << path.value();
    634     }
    635   }
    636 
    637  private:
    638   ObserverList<Observer> observers_;
    639   std::string device_policy_;
    640   std::map<std::string, std::string> user_policies_;
    641 
    642   DISALLOW_COPY_AND_ASSIGN(SessionManagerClientStubImpl);
    643 };
    644 
    645 SessionManagerClient::SessionManagerClient() {
    646 }
    647 
    648 SessionManagerClient::~SessionManagerClient() {
    649 }
    650 
    651 SessionManagerClient* SessionManagerClient::Create(
    652     DBusClientImplementationType type) {
    653   if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
    654     return new SessionManagerClientImpl();
    655   DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
    656   return new SessionManagerClientStubImpl();
    657 }
    658 
    659 }  // namespace chromeos
    660