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 "base/bind.h"
8#include "base/callback.h"
9#include "base/file_util.h"
10#include "base/files/file_path.h"
11#include "base/location.h"
12#include "base/path_service.h"
13#include "base/strings/string_number_conversions.h"
14#include "base/strings/string_util.h"
15#include "base/task_runner_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 "crypto/sha2.h"
21#include "dbus/bus.h"
22#include "dbus/message.h"
23#include "dbus/object_path.h"
24#include "dbus/object_proxy.h"
25#include "policy/proto/device_management_backend.pb.h"
26#include "third_party/cros_system_api/dbus/service_constants.h"
27
28namespace chromeos {
29
30namespace {
31
32// Returns a location for |file| that is specific to the given |username|.
33// These paths will be relative to DIR_USER_POLICY_KEYS, and can be used only
34// to store stub files.
35base::FilePath GetUserFilePath(const std::string& username, const char* file) {
36  base::FilePath keys_path;
37  if (!PathService::Get(chromeos::DIR_USER_POLICY_KEYS, &keys_path))
38    return base::FilePath();
39  const std::string sanitized =
40      CryptohomeClient::GetStubSanitizedUsername(username);
41  return keys_path.AppendASCII(sanitized).AppendASCII(file);
42}
43
44// Helper to asynchronously retrieve a file's content.
45std::string GetFileContent(const base::FilePath& path) {
46  std::string result;
47  if (!path.empty())
48    base::ReadFileToString(path, &result);
49  return result;
50}
51
52// Helper to write a file in a background thread.
53void StoreFile(const base::FilePath& path, const std::string& data) {
54  const int size = static_cast<int>(data.size());
55  if (path.empty() ||
56      !base::CreateDirectory(path.DirName()) ||
57      base::WriteFile(path, data.data(), size) != size) {
58    LOG(WARNING) << "Failed to write to " << path.value();
59  }
60}
61
62}  // namespace
63
64// The SessionManagerClient implementation used in production.
65class SessionManagerClientImpl : public SessionManagerClient {
66 public:
67  SessionManagerClientImpl()
68      : session_manager_proxy_(NULL),
69        weak_ptr_factory_(this) {}
70
71  virtual ~SessionManagerClientImpl() {
72  }
73
74  // SessionManagerClient overrides:
75  virtual void SetStubDelegate(StubDelegate* delegate) OVERRIDE {
76    // Do nothing; this isn't a stub implementation.
77  }
78
79  virtual void AddObserver(Observer* observer) OVERRIDE {
80    observers_.AddObserver(observer);
81  }
82
83  virtual void RemoveObserver(Observer* observer) OVERRIDE {
84    observers_.RemoveObserver(observer);
85  }
86
87  virtual bool HasObserver(Observer* observer) OVERRIDE {
88    return observers_.HasObserver(observer);
89  }
90
91  virtual void EmitLoginPromptVisible() OVERRIDE {
92    SimpleMethodCallToSessionManager(
93        login_manager::kSessionManagerEmitLoginPromptVisible);
94    FOR_EACH_OBSERVER(Observer, observers_, EmitLoginPromptVisibleCalled());
95  }
96
97  virtual void RestartJob(int pid, const std::string& command_line) OVERRIDE {
98    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
99                                 login_manager::kSessionManagerRestartJob);
100    dbus::MessageWriter writer(&method_call);
101    writer.AppendInt32(pid);
102    writer.AppendString(command_line);
103    session_manager_proxy_->CallMethod(
104        &method_call,
105        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
106        base::Bind(&SessionManagerClientImpl::OnRestartJob,
107                   weak_ptr_factory_.GetWeakPtr()));
108  }
109
110  virtual void StartSession(const std::string& user_email) OVERRIDE {
111    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
112                                 login_manager::kSessionManagerStartSession);
113    dbus::MessageWriter writer(&method_call);
114    writer.AppendString(user_email);
115    writer.AppendString("");  // Unique ID is deprecated
116    session_manager_proxy_->CallMethod(
117        &method_call,
118        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
119        base::Bind(&SessionManagerClientImpl::OnStartSession,
120                   weak_ptr_factory_.GetWeakPtr()));
121  }
122
123  virtual void StopSession() OVERRIDE {
124    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
125                                 login_manager::kSessionManagerStopSession);
126    dbus::MessageWriter writer(&method_call);
127    writer.AppendString("");  // Unique ID is deprecated
128    session_manager_proxy_->CallMethod(
129        &method_call,
130        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
131        base::Bind(&SessionManagerClientImpl::OnStopSession,
132                   weak_ptr_factory_.GetWeakPtr()));
133  }
134
135  virtual void StartDeviceWipe() OVERRIDE {
136    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
137                                 login_manager::kSessionManagerStartDeviceWipe);
138    session_manager_proxy_->CallMethod(
139        &method_call,
140        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
141        base::Bind(&SessionManagerClientImpl::OnDeviceWipe,
142                   weak_ptr_factory_.GetWeakPtr()));
143  }
144
145  virtual void RequestLockScreen() OVERRIDE {
146    SimpleMethodCallToSessionManager(login_manager::kSessionManagerLockScreen);
147  }
148
149  virtual void NotifyLockScreenShown() OVERRIDE {
150    SimpleMethodCallToSessionManager(
151        login_manager::kSessionManagerHandleLockScreenShown);
152  }
153
154  virtual void NotifyLockScreenDismissed() OVERRIDE {
155    SimpleMethodCallToSessionManager(
156        login_manager::kSessionManagerHandleLockScreenDismissed);
157  }
158
159  virtual void RetrieveActiveSessions(
160      const ActiveSessionsCallback& callback) OVERRIDE {
161    dbus::MethodCall method_call(
162        login_manager::kSessionManagerInterface,
163        login_manager::kSessionManagerRetrieveActiveSessions);
164
165    session_manager_proxy_->CallMethod(
166        &method_call,
167        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
168        base::Bind(&SessionManagerClientImpl::OnRetrieveActiveSessions,
169                   weak_ptr_factory_.GetWeakPtr(),
170                   login_manager::kSessionManagerRetrieveActiveSessions,
171                   callback));
172  }
173
174  virtual void RetrieveDevicePolicy(
175      const RetrievePolicyCallback& callback) OVERRIDE {
176    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
177                                 login_manager::kSessionManagerRetrievePolicy);
178    session_manager_proxy_->CallMethod(
179        &method_call,
180        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
181        base::Bind(&SessionManagerClientImpl::OnRetrievePolicy,
182                   weak_ptr_factory_.GetWeakPtr(),
183                   login_manager::kSessionManagerRetrievePolicy,
184                   callback));
185  }
186
187  virtual void RetrievePolicyForUser(
188      const std::string& username,
189      const RetrievePolicyCallback& callback) OVERRIDE {
190    CallRetrievePolicyByUsername(
191        login_manager::kSessionManagerRetrievePolicyForUser,
192        username,
193        callback);
194  }
195
196  virtual std::string BlockingRetrievePolicyForUser(
197      const std::string& username) OVERRIDE {
198    dbus::MethodCall method_call(
199        login_manager::kSessionManagerInterface,
200        login_manager::kSessionManagerRetrievePolicyForUser);
201    dbus::MessageWriter writer(&method_call);
202    writer.AppendString(username);
203    scoped_ptr<dbus::Response> response =
204        blocking_method_caller_->CallMethodAndBlock(&method_call);
205    std::string policy;
206    ExtractString(login_manager::kSessionManagerRetrievePolicyForUser,
207                  response.get(),
208                  &policy);
209    return policy;
210  }
211
212  virtual void RetrieveDeviceLocalAccountPolicy(
213      const std::string& account_name,
214      const RetrievePolicyCallback& callback) OVERRIDE {
215    CallRetrievePolicyByUsername(
216        login_manager::kSessionManagerRetrieveDeviceLocalAccountPolicy,
217        account_name,
218        callback);
219  }
220
221  virtual void StoreDevicePolicy(const std::string& policy_blob,
222                                 const StorePolicyCallback& callback) OVERRIDE {
223    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
224                                 login_manager::kSessionManagerStorePolicy);
225    dbus::MessageWriter writer(&method_call);
226    // static_cast does not work due to signedness.
227    writer.AppendArrayOfBytes(
228        reinterpret_cast<const uint8*>(policy_blob.data()), policy_blob.size());
229    session_manager_proxy_->CallMethod(
230        &method_call,
231        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
232        base::Bind(&SessionManagerClientImpl::OnStorePolicy,
233                   weak_ptr_factory_.GetWeakPtr(),
234                   login_manager::kSessionManagerStorePolicy,
235                   callback));
236  }
237
238  virtual void StorePolicyForUser(
239      const std::string& username,
240      const std::string& policy_blob,
241      const StorePolicyCallback& callback) OVERRIDE {
242    CallStorePolicyByUsername(login_manager::kSessionManagerStorePolicyForUser,
243                              username,
244                              policy_blob,
245                              callback);
246  }
247
248  virtual void StoreDeviceLocalAccountPolicy(
249      const std::string& account_name,
250      const std::string& policy_blob,
251      const StorePolicyCallback& callback) OVERRIDE {
252    CallStorePolicyByUsername(
253        login_manager::kSessionManagerStoreDeviceLocalAccountPolicy,
254        account_name,
255        policy_blob,
256        callback);
257  }
258
259  virtual void SetFlagsForUser(const std::string& username,
260                               const std::vector<std::string>& flags) OVERRIDE {
261    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
262                                 login_manager::kSessionManagerSetFlagsForUser);
263    dbus::MessageWriter writer(&method_call);
264    writer.AppendString(username);
265    writer.AppendArrayOfStrings(flags);
266    session_manager_proxy_->CallMethod(
267        &method_call,
268        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
269        dbus::ObjectProxy::EmptyResponseCallback());
270  }
271
272  virtual void GetServerBackedStateKeys(const StateKeysCallback& callback)
273      OVERRIDE {
274    dbus::MethodCall method_call(
275        login_manager::kSessionManagerInterface,
276        login_manager::kSessionManagerGetServerBackedStateKeys);
277
278    session_manager_proxy_->CallMethod(
279        &method_call,
280        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
281        base::Bind(&SessionManagerClientImpl::OnGetServerBackedStateKeys,
282                   weak_ptr_factory_.GetWeakPtr(),
283                   callback));
284  }
285
286 protected:
287  virtual void Init(dbus::Bus* bus) OVERRIDE {
288    session_manager_proxy_ = bus->GetObjectProxy(
289        login_manager::kSessionManagerServiceName,
290        dbus::ObjectPath(login_manager::kSessionManagerServicePath));
291    blocking_method_caller_.reset(
292        new BlockingMethodCaller(bus, session_manager_proxy_));
293
294    // Signals emitted on the session manager's interface.
295    session_manager_proxy_->ConnectToSignal(
296        login_manager::kSessionManagerInterface,
297        login_manager::kOwnerKeySetSignal,
298        base::Bind(&SessionManagerClientImpl::OwnerKeySetReceived,
299                   weak_ptr_factory_.GetWeakPtr()),
300        base::Bind(&SessionManagerClientImpl::SignalConnected,
301                   weak_ptr_factory_.GetWeakPtr()));
302    session_manager_proxy_->ConnectToSignal(
303        login_manager::kSessionManagerInterface,
304        login_manager::kPropertyChangeCompleteSignal,
305        base::Bind(&SessionManagerClientImpl::PropertyChangeCompleteReceived,
306                   weak_ptr_factory_.GetWeakPtr()),
307        base::Bind(&SessionManagerClientImpl::SignalConnected,
308                   weak_ptr_factory_.GetWeakPtr()));
309    session_manager_proxy_->ConnectToSignal(
310        login_manager::kSessionManagerInterface,
311        login_manager::kScreenIsLockedSignal,
312        base::Bind(&SessionManagerClientImpl::ScreenIsLockedReceived,
313                   weak_ptr_factory_.GetWeakPtr()),
314        base::Bind(&SessionManagerClientImpl::SignalConnected,
315                   weak_ptr_factory_.GetWeakPtr()));
316    session_manager_proxy_->ConnectToSignal(
317        login_manager::kSessionManagerInterface,
318        login_manager::kScreenIsUnlockedSignal,
319        base::Bind(&SessionManagerClientImpl::ScreenIsUnlockedReceived,
320                   weak_ptr_factory_.GetWeakPtr()),
321        base::Bind(&SessionManagerClientImpl::SignalConnected,
322                   weak_ptr_factory_.GetWeakPtr()));
323  }
324
325 private:
326  // Makes a method call to the session manager with no arguments and no
327  // response.
328  void SimpleMethodCallToSessionManager(const std::string& method_name) {
329    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
330                                 method_name);
331    session_manager_proxy_->CallMethod(
332        &method_call,
333        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
334        dbus::ObjectProxy::EmptyResponseCallback());
335  }
336
337  // Helper for RetrieveDeviceLocalAccountPolicy and RetrievePolicyForUser.
338  void CallRetrievePolicyByUsername(const std::string& method_name,
339                                    const std::string& username,
340                                    const RetrievePolicyCallback& callback) {
341    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
342                                 method_name);
343    dbus::MessageWriter writer(&method_call);
344    writer.AppendString(username);
345    session_manager_proxy_->CallMethod(
346        &method_call,
347        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
348        base::Bind(
349            &SessionManagerClientImpl::OnRetrievePolicy,
350            weak_ptr_factory_.GetWeakPtr(),
351            method_name,
352            callback));
353  }
354
355  void CallStorePolicyByUsername(const std::string& method_name,
356                                 const std::string& username,
357                                 const std::string& policy_blob,
358                                 const StorePolicyCallback& callback) {
359    dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
360                                 method_name);
361    dbus::MessageWriter writer(&method_call);
362    writer.AppendString(username);
363    // static_cast does not work due to signedness.
364    writer.AppendArrayOfBytes(
365        reinterpret_cast<const uint8*>(policy_blob.data()), policy_blob.size());
366    session_manager_proxy_->CallMethod(
367        &method_call,
368        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
369        base::Bind(
370            &SessionManagerClientImpl::OnStorePolicy,
371            weak_ptr_factory_.GetWeakPtr(),
372            method_name,
373            callback));
374  }
375
376  // Called when kSessionManagerRestartJob method is complete.
377  void OnRestartJob(dbus::Response* response) {
378    LOG_IF(ERROR, !response)
379        << "Failed to call "
380        << login_manager::kSessionManagerRestartJob;
381  }
382
383  // Called when kSessionManagerStartSession method is complete.
384  void OnStartSession(dbus::Response* response) {
385    LOG_IF(ERROR, !response)
386        << "Failed to call "
387        << login_manager::kSessionManagerStartSession;
388  }
389
390  // Called when kSessionManagerStopSession method is complete.
391  void OnStopSession(dbus::Response* response) {
392    LOG_IF(ERROR, !response)
393        << "Failed to call "
394        << login_manager::kSessionManagerStopSession;
395  }
396
397  // Called when kSessionManagerStopSession method is complete.
398  void OnDeviceWipe(dbus::Response* response) {
399    LOG_IF(ERROR, !response)
400        << "Failed to call "
401        << login_manager::kSessionManagerStartDeviceWipe;
402  }
403
404  // Called when kSessionManagerRetrieveActiveSessions method is complete.
405  void OnRetrieveActiveSessions(const std::string& method_name,
406                                const ActiveSessionsCallback& callback,
407                                dbus::Response* response) {
408    ActiveSessionsMap sessions;
409    bool success = false;
410    if (!response) {
411      LOG(ERROR) << "Failed to call " << method_name;
412      callback.Run(sessions, success);
413      return;
414    }
415
416    dbus::MessageReader reader(response);
417    dbus::MessageReader array_reader(NULL);
418
419    if (!reader.PopArray(&array_reader)) {
420      LOG(ERROR) << method_name << " response is incorrect: "
421                 << response->ToString();
422    } else {
423      while (array_reader.HasMoreData()) {
424        dbus::MessageReader dict_entry_reader(NULL);
425        std::string key;
426        std::string value;
427        if (!array_reader.PopDictEntry(&dict_entry_reader) ||
428            !dict_entry_reader.PopString(&key) ||
429            !dict_entry_reader.PopString(&value)) {
430          LOG(ERROR) << method_name << " response is incorrect: "
431                     << response->ToString();
432        } else {
433          sessions[key] = value;
434        }
435      }
436      success = true;
437    }
438    callback.Run(sessions, success);
439  }
440
441  void ExtractString(const std::string& method_name,
442                     dbus::Response* response,
443                     std::string* extracted) {
444    if (!response) {
445      LOG(ERROR) << "Failed to call " << method_name;
446      return;
447    }
448    dbus::MessageReader reader(response);
449    const uint8* values = NULL;
450    size_t length = 0;
451    if (!reader.PopArrayOfBytes(&values, &length)) {
452      LOG(ERROR) << "Invalid response: " << response->ToString();
453      return;
454    }
455    // static_cast does not work due to signedness.
456    extracted->assign(reinterpret_cast<const char*>(values), length);
457  }
458
459  // Called when kSessionManagerRetrievePolicy or
460  // kSessionManagerRetrievePolicyForUser method is complete.
461  void OnRetrievePolicy(const std::string& method_name,
462                        const RetrievePolicyCallback& callback,
463                        dbus::Response* response) {
464    std::string serialized_proto;
465    ExtractString(method_name, response, &serialized_proto);
466    callback.Run(serialized_proto);
467  }
468
469  // Called when kSessionManagerStorePolicy or kSessionManagerStorePolicyForUser
470  // method is complete.
471  void OnStorePolicy(const std::string& method_name,
472                     const StorePolicyCallback& callback,
473                     dbus::Response* response) {
474    bool success = false;
475    if (!response) {
476      LOG(ERROR) << "Failed to call " << method_name;
477    } else {
478      dbus::MessageReader reader(response);
479      if (!reader.PopBool(&success))
480        LOG(ERROR) << "Invalid response: " << response->ToString();
481    }
482    callback.Run(success);
483  }
484
485  // Called when the owner key set signal is received.
486  void OwnerKeySetReceived(dbus::Signal* signal) {
487    dbus::MessageReader reader(signal);
488    std::string result_string;
489    if (!reader.PopString(&result_string)) {
490      LOG(ERROR) << "Invalid signal: " << signal->ToString();
491      return;
492    }
493    const bool success = StartsWithASCII(result_string, "success", false);
494    FOR_EACH_OBSERVER(Observer, observers_, OwnerKeySet(success));
495  }
496
497  // Called when the property change complete signal is received.
498  void PropertyChangeCompleteReceived(dbus::Signal* signal) {
499    dbus::MessageReader reader(signal);
500    std::string result_string;
501    if (!reader.PopString(&result_string)) {
502      LOG(ERROR) << "Invalid signal: " << signal->ToString();
503      return;
504    }
505    const bool success = StartsWithASCII(result_string, "success", false);
506    FOR_EACH_OBSERVER(Observer, observers_, PropertyChangeComplete(success));
507  }
508
509  void ScreenIsLockedReceived(dbus::Signal* signal) {
510    FOR_EACH_OBSERVER(Observer, observers_, ScreenIsLocked());
511  }
512
513  void ScreenIsUnlockedReceived(dbus::Signal* signal) {
514    FOR_EACH_OBSERVER(Observer, observers_, ScreenIsUnlocked());
515  }
516
517  // Called when the object is connected to the signal.
518  void SignalConnected(const std::string& interface_name,
519                       const std::string& signal_name,
520                       bool success) {
521    LOG_IF(ERROR, !success) << "Failed to connect to " << signal_name;
522  }
523
524  // Called when kSessionManagerGetServerBackedStateKeys method is complete.
525  void OnGetServerBackedStateKeys(const StateKeysCallback& callback,
526                                  dbus::Response* response) {
527    std::vector<std::string> state_keys;
528    if (!response) {
529      LOG(ERROR) << "Failed to call "
530                 << login_manager::kSessionManagerStartSession;
531    } else {
532      dbus::MessageReader reader(response);
533      dbus::MessageReader array_reader(NULL);
534
535      if (!reader.PopArray(&array_reader)) {
536        LOG(ERROR) << "Bad response: " << response->ToString();
537      } else {
538        while (array_reader.HasMoreData()) {
539          const uint8* data = NULL;
540          size_t size = 0;
541          if (!array_reader.PopArrayOfBytes(&data, &size)) {
542            LOG(ERROR) << "Bad response: " << response->ToString();
543            state_keys.clear();
544            break;
545          }
546          state_keys.push_back(
547              std::string(reinterpret_cast<const char*>(data), size));
548        }
549      }
550    }
551
552    if (!callback.is_null())
553      callback.Run(state_keys);
554  }
555
556
557  dbus::ObjectProxy* session_manager_proxy_;
558  scoped_ptr<BlockingMethodCaller> blocking_method_caller_;
559  ObserverList<Observer> observers_;
560
561  // Note: This should remain the last member so it'll be destroyed and
562  // invalidate its weak pointers before any other members are destroyed.
563  base::WeakPtrFactory<SessionManagerClientImpl> weak_ptr_factory_;
564
565  DISALLOW_COPY_AND_ASSIGN(SessionManagerClientImpl);
566};
567
568// The SessionManagerClient implementation used on Linux desktop,
569// which does nothing.
570class SessionManagerClientStubImpl : public SessionManagerClient {
571 public:
572  SessionManagerClientStubImpl() : delegate_(NULL) {}
573  virtual ~SessionManagerClientStubImpl() {}
574
575  // SessionManagerClient overrides
576  virtual void Init(dbus::Bus* bus) OVERRIDE {}
577  virtual void SetStubDelegate(StubDelegate* delegate) OVERRIDE {
578    delegate_ = delegate;
579  }
580  virtual void AddObserver(Observer* observer) OVERRIDE {
581    observers_.AddObserver(observer);
582  }
583  virtual void RemoveObserver(Observer* observer) OVERRIDE {
584    observers_.RemoveObserver(observer);
585  }
586  virtual bool HasObserver(Observer* observer) OVERRIDE {
587    return observers_.HasObserver(observer);
588  }
589  virtual void EmitLoginPromptVisible() OVERRIDE {}
590  virtual void RestartJob(int pid, const std::string& command_line) OVERRIDE {}
591  virtual void StartSession(const std::string& user_email) OVERRIDE {}
592  virtual void StopSession() OVERRIDE {}
593  virtual void StartDeviceWipe() OVERRIDE {}
594  virtual void RequestLockScreen() OVERRIDE {
595    if (delegate_)
596      delegate_->LockScreenForStub();
597  }
598  virtual void NotifyLockScreenShown() OVERRIDE {
599    FOR_EACH_OBSERVER(Observer, observers_, ScreenIsLocked());
600  }
601  virtual void NotifyLockScreenDismissed() OVERRIDE {
602    FOR_EACH_OBSERVER(Observer, observers_, ScreenIsUnlocked());
603  }
604  virtual void RetrieveActiveSessions(
605      const ActiveSessionsCallback& callback) OVERRIDE {}
606  virtual void RetrieveDevicePolicy(
607      const RetrievePolicyCallback& callback) OVERRIDE {
608    base::FilePath owner_key_path;
609    if (!PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
610      callback.Run("");
611      return;
612    }
613    base::FilePath device_policy_path =
614        owner_key_path.DirName().AppendASCII("stub_device_policy");
615    base::PostTaskAndReplyWithResult(
616        base::WorkerPool::GetTaskRunner(false),
617        FROM_HERE,
618        base::Bind(&GetFileContent, device_policy_path),
619        callback);
620  }
621  virtual void RetrievePolicyForUser(
622      const std::string& username,
623      const RetrievePolicyCallback& callback) OVERRIDE {
624    base::PostTaskAndReplyWithResult(
625        base::WorkerPool::GetTaskRunner(false),
626        FROM_HERE,
627        base::Bind(&GetFileContent, GetUserFilePath(username, "stub_policy")),
628        callback);
629  }
630  virtual std::string BlockingRetrievePolicyForUser(
631      const std::string& username) OVERRIDE {
632    return GetFileContent(GetUserFilePath(username, "stub_policy"));
633  }
634  virtual void RetrieveDeviceLocalAccountPolicy(
635      const std::string& account_name,
636      const RetrievePolicyCallback& callback) OVERRIDE {
637    RetrievePolicyForUser(account_name, callback);
638  }
639  virtual void StoreDevicePolicy(const std::string& policy_blob,
640                                 const StorePolicyCallback& callback) OVERRIDE {
641    enterprise_management::PolicyFetchResponse response;
642    base::FilePath owner_key_path;
643    if (!response.ParseFromString(policy_blob) ||
644        !PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
645      callback.Run(false);
646      return;
647    }
648
649    if (response.has_new_public_key()) {
650      base::WorkerPool::PostTask(
651          FROM_HERE,
652          base::Bind(&StoreFile, owner_key_path, response.new_public_key()),
653          false);
654    }
655
656    // Chrome will attempt to retrieve the device policy right after storing
657    // during enrollment, so make sure it's written before signaling
658    // completion.
659    // Note also that the owner key will be written before the device policy,
660    // if it was present in the blob.
661    base::FilePath device_policy_path =
662        owner_key_path.DirName().AppendASCII("stub_device_policy");
663    base::WorkerPool::PostTaskAndReply(
664        FROM_HERE,
665        base::Bind(&StoreFile, device_policy_path, policy_blob),
666        base::Bind(callback, true),
667        false);
668  }
669  virtual void StorePolicyForUser(
670      const std::string& username,
671      const std::string& policy_blob,
672      const StorePolicyCallback& callback) OVERRIDE {
673    // The session manager writes the user policy key to a well-known
674    // location. Do the same with the stub impl, so that user policy works and
675    // can be tested on desktop builds.
676    enterprise_management::PolicyFetchResponse response;
677    if (!response.ParseFromString(policy_blob)) {
678      callback.Run(false);
679      return;
680    }
681
682    if (response.has_new_public_key()) {
683      base::FilePath key_path = GetUserFilePath(username, "policy.pub");
684      base::WorkerPool::PostTask(
685          FROM_HERE,
686          base::Bind(&StoreFile, key_path, response.new_public_key()),
687          false);
688    }
689
690    // This file isn't read directly by Chrome, but is used by this class to
691    // reload the user policy across restarts.
692    base::FilePath stub_policy_path = GetUserFilePath(username, "stub_policy");
693    base::WorkerPool::PostTaskAndReply(
694        FROM_HERE,
695        base::Bind(&StoreFile, stub_policy_path, policy_blob),
696        base::Bind(callback, true),
697        false);
698  }
699  virtual void StoreDeviceLocalAccountPolicy(
700      const std::string& account_name,
701      const std::string& policy_blob,
702      const StorePolicyCallback& callback) OVERRIDE {
703    StorePolicyForUser(account_name, policy_blob, callback);
704  }
705  virtual void SetFlagsForUser(const std::string& username,
706                               const std::vector<std::string>& flags) OVERRIDE {
707  }
708
709  virtual void GetServerBackedStateKeys(const StateKeysCallback& callback)
710      OVERRIDE {
711    std::vector<std::string> state_keys;
712    for (int i = 0; i < 5; ++i)
713      state_keys.push_back(crypto::SHA256HashString(base::IntToString(i)));
714
715    if (!callback.is_null())
716      callback.Run(state_keys);
717  }
718
719 private:
720  StubDelegate* delegate_;  // Weak pointer; may be NULL.
721  ObserverList<Observer> observers_;
722  std::string device_policy_;
723
724  DISALLOW_COPY_AND_ASSIGN(SessionManagerClientStubImpl);
725};
726
727SessionManagerClient::SessionManagerClient() {
728}
729
730SessionManagerClient::~SessionManagerClient() {
731}
732
733SessionManagerClient* SessionManagerClient::Create(
734    DBusClientImplementationType type) {
735  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
736    return new SessionManagerClientImpl();
737  DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
738  return new SessionManagerClientStubImpl();
739}
740
741}  // namespace chromeos
742