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/files/file_path.h"
10#include "base/files/file_util.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    bool first_run = false;
529    if (!response) {
530      LOG(ERROR) << "Failed to call "
531                 << login_manager::kSessionManagerStartSession;
532    } else {
533      dbus::MessageReader reader(response);
534      dbus::MessageReader array_reader(NULL);
535
536      if (!reader.PopArray(&array_reader)) {
537        LOG(ERROR) << "Bad response: " << response->ToString();
538      } else {
539        while (array_reader.HasMoreData()) {
540          const uint8* data = NULL;
541          size_t size = 0;
542          if (!array_reader.PopArrayOfBytes(&data, &size)) {
543            LOG(ERROR) << "Bad response: " << response->ToString();
544            state_keys.clear();
545            break;
546          }
547          state_keys.push_back(
548              std::string(reinterpret_cast<const char*>(data), size));
549        }
550      }
551      if (!reader.PopBool(&first_run)) {
552        // TODO(tnagel): After 2014-11-19 turn this warning into an error.
553        LOG(WARNING) << "Chrome OS is too old. Defaulting to first_run=false.";
554      }
555    }
556
557    if (!callback.is_null())
558      callback.Run(state_keys, first_run);
559  }
560
561
562  dbus::ObjectProxy* session_manager_proxy_;
563  scoped_ptr<BlockingMethodCaller> blocking_method_caller_;
564  ObserverList<Observer> observers_;
565
566  // Note: This should remain the last member so it'll be destroyed and
567  // invalidate its weak pointers before any other members are destroyed.
568  base::WeakPtrFactory<SessionManagerClientImpl> weak_ptr_factory_;
569
570  DISALLOW_COPY_AND_ASSIGN(SessionManagerClientImpl);
571};
572
573// The SessionManagerClient implementation used on Linux desktop,
574// which does nothing.
575class SessionManagerClientStubImpl : public SessionManagerClient {
576 public:
577  SessionManagerClientStubImpl() : delegate_(NULL) {}
578  virtual ~SessionManagerClientStubImpl() {}
579
580  // SessionManagerClient overrides
581  virtual void Init(dbus::Bus* bus) OVERRIDE {}
582  virtual void SetStubDelegate(StubDelegate* delegate) OVERRIDE {
583    delegate_ = delegate;
584  }
585  virtual void AddObserver(Observer* observer) OVERRIDE {
586    observers_.AddObserver(observer);
587  }
588  virtual void RemoveObserver(Observer* observer) OVERRIDE {
589    observers_.RemoveObserver(observer);
590  }
591  virtual bool HasObserver(Observer* observer) OVERRIDE {
592    return observers_.HasObserver(observer);
593  }
594  virtual void EmitLoginPromptVisible() OVERRIDE {}
595  virtual void RestartJob(int pid, const std::string& command_line) OVERRIDE {}
596  virtual void StartSession(const std::string& user_email) OVERRIDE {}
597  virtual void StopSession() OVERRIDE {}
598  virtual void StartDeviceWipe() OVERRIDE {}
599  virtual void RequestLockScreen() OVERRIDE {
600    if (delegate_)
601      delegate_->LockScreenForStub();
602  }
603  virtual void NotifyLockScreenShown() OVERRIDE {
604    FOR_EACH_OBSERVER(Observer, observers_, ScreenIsLocked());
605  }
606  virtual void NotifyLockScreenDismissed() OVERRIDE {
607    FOR_EACH_OBSERVER(Observer, observers_, ScreenIsUnlocked());
608  }
609  virtual void RetrieveActiveSessions(
610      const ActiveSessionsCallback& callback) OVERRIDE {}
611  virtual void RetrieveDevicePolicy(
612      const RetrievePolicyCallback& callback) OVERRIDE {
613    base::FilePath owner_key_path;
614    if (!PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
615      callback.Run("");
616      return;
617    }
618    base::FilePath device_policy_path =
619        owner_key_path.DirName().AppendASCII("stub_device_policy");
620    base::PostTaskAndReplyWithResult(
621        base::WorkerPool::GetTaskRunner(false).get(),
622        FROM_HERE,
623        base::Bind(&GetFileContent, device_policy_path),
624        callback);
625  }
626  virtual void RetrievePolicyForUser(
627      const std::string& username,
628      const RetrievePolicyCallback& callback) OVERRIDE {
629    base::PostTaskAndReplyWithResult(
630        base::WorkerPool::GetTaskRunner(false).get(),
631        FROM_HERE,
632        base::Bind(&GetFileContent, GetUserFilePath(username, "stub_policy")),
633        callback);
634  }
635  virtual std::string BlockingRetrievePolicyForUser(
636      const std::string& username) OVERRIDE {
637    return GetFileContent(GetUserFilePath(username, "stub_policy"));
638  }
639  virtual void RetrieveDeviceLocalAccountPolicy(
640      const std::string& account_name,
641      const RetrievePolicyCallback& callback) OVERRIDE {
642    RetrievePolicyForUser(account_name, callback);
643  }
644  virtual void StoreDevicePolicy(const std::string& policy_blob,
645                                 const StorePolicyCallback& callback) OVERRIDE {
646    enterprise_management::PolicyFetchResponse response;
647    base::FilePath owner_key_path;
648    if (!response.ParseFromString(policy_blob) ||
649        !PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
650      callback.Run(false);
651      return;
652    }
653
654    if (response.has_new_public_key()) {
655      base::WorkerPool::PostTask(
656          FROM_HERE,
657          base::Bind(&StoreFile, owner_key_path, response.new_public_key()),
658          false);
659    }
660
661    // Chrome will attempt to retrieve the device policy right after storing
662    // during enrollment, so make sure it's written before signaling
663    // completion.
664    // Note also that the owner key will be written before the device policy,
665    // if it was present in the blob.
666    base::FilePath device_policy_path =
667        owner_key_path.DirName().AppendASCII("stub_device_policy");
668    base::WorkerPool::PostTaskAndReply(
669        FROM_HERE,
670        base::Bind(&StoreFile, device_policy_path, policy_blob),
671        base::Bind(callback, true),
672        false);
673  }
674  virtual void StorePolicyForUser(
675      const std::string& username,
676      const std::string& policy_blob,
677      const StorePolicyCallback& callback) OVERRIDE {
678    // The session manager writes the user policy key to a well-known
679    // location. Do the same with the stub impl, so that user policy works and
680    // can be tested on desktop builds.
681    enterprise_management::PolicyFetchResponse response;
682    if (!response.ParseFromString(policy_blob)) {
683      callback.Run(false);
684      return;
685    }
686
687    if (response.has_new_public_key()) {
688      base::FilePath key_path = GetUserFilePath(username, "policy.pub");
689      base::WorkerPool::PostTask(
690          FROM_HERE,
691          base::Bind(&StoreFile, key_path, response.new_public_key()),
692          false);
693    }
694
695    // This file isn't read directly by Chrome, but is used by this class to
696    // reload the user policy across restarts.
697    base::FilePath stub_policy_path = GetUserFilePath(username, "stub_policy");
698    base::WorkerPool::PostTaskAndReply(
699        FROM_HERE,
700        base::Bind(&StoreFile, stub_policy_path, policy_blob),
701        base::Bind(callback, true),
702        false);
703  }
704  virtual void StoreDeviceLocalAccountPolicy(
705      const std::string& account_name,
706      const std::string& policy_blob,
707      const StorePolicyCallback& callback) OVERRIDE {
708    StorePolicyForUser(account_name, policy_blob, callback);
709  }
710  virtual void SetFlagsForUser(const std::string& username,
711                               const std::vector<std::string>& flags) OVERRIDE {
712  }
713
714  virtual void GetServerBackedStateKeys(const StateKeysCallback& callback)
715      OVERRIDE {
716    std::vector<std::string> state_keys;
717    for (int i = 0; i < 5; ++i)
718      state_keys.push_back(crypto::SHA256HashString(base::IntToString(i)));
719
720    if (!callback.is_null())
721      callback.Run(state_keys, false);
722  }
723
724 private:
725  StubDelegate* delegate_;  // Weak pointer; may be NULL.
726  ObserverList<Observer> observers_;
727  std::string device_policy_;
728
729  DISALLOW_COPY_AND_ASSIGN(SessionManagerClientStubImpl);
730};
731
732SessionManagerClient::SessionManagerClient() {
733}
734
735SessionManagerClient::~SessionManagerClient() {
736}
737
738SessionManagerClient* SessionManagerClient::Create(
739    DBusClientImplementationType type) {
740  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
741    return new SessionManagerClientImpl();
742  DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
743  return new SessionManagerClientStubImpl();
744}
745
746}  // namespace chromeos
747