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
26namespace chromeos {
27
28// The SessionManagerClient implementation used in production.
29class 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.
515class 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
645SessionManagerClient::SessionManagerClient() {
646}
647
648SessionManagerClient::~SessionManagerClient() {
649}
650
651SessionManagerClient* 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