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.
5 #include "chromeos/dbus/session_manager_client.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"
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"
28 // The SessionManagerClient implementation used in production.
29 class SessionManagerClientImpl : public SessionManagerClient {
31 SessionManagerClientImpl()
32 : session_manager_proxy_(NULL),
33 weak_ptr_factory_(this) {}
35 virtual ~SessionManagerClientImpl() {
38 // SessionManagerClient overrides:
39 virtual void AddObserver(Observer* observer) OVERRIDE {
40 observers_.AddObserver(observer);
43 virtual void RemoveObserver(Observer* observer) OVERRIDE {
44 observers_.RemoveObserver(observer);
47 virtual bool HasObserver(Observer* observer) OVERRIDE {
48 return observers_.HasObserver(observer);
51 virtual void EmitLoginPromptVisible() OVERRIDE {
52 SimpleMethodCallToSessionManager(
53 login_manager::kSessionManagerEmitLoginPromptVisible);
54 FOR_EACH_OBSERVER(Observer, observers_, EmitLoginPromptVisibleCalled());
57 virtual void RestartJob(int pid, const std::string& command_line) OVERRIDE {
58 dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
59 login_manager::kSessionManagerRestartJob);
60 dbus::MessageWriter writer(&method_call);
61 writer.AppendInt32(pid);
62 writer.AppendString(command_line);
63 session_manager_proxy_->CallMethod(
65 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
66 base::Bind(&SessionManagerClientImpl::OnRestartJob,
67 weak_ptr_factory_.GetWeakPtr()));
70 virtual void StartSession(const std::string& user_email) OVERRIDE {
71 dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
72 login_manager::kSessionManagerStartSession);
73 dbus::MessageWriter writer(&method_call);
74 writer.AppendString(user_email);
75 writer.AppendString(""); // Unique ID is deprecated
76 session_manager_proxy_->CallMethod(
78 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
79 base::Bind(&SessionManagerClientImpl::OnStartSession,
80 weak_ptr_factory_.GetWeakPtr()));
83 virtual void StopSession() OVERRIDE {
84 dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
85 login_manager::kSessionManagerStopSession);
86 dbus::MessageWriter writer(&method_call);
87 writer.AppendString(""); // Unique ID is deprecated
88 session_manager_proxy_->CallMethod(
90 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
91 base::Bind(&SessionManagerClientImpl::OnStopSession,
92 weak_ptr_factory_.GetWeakPtr()));
95 virtual void StartDeviceWipe() OVERRIDE {
96 dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
97 login_manager::kSessionManagerStartDeviceWipe);
98 session_manager_proxy_->CallMethod(
100 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
101 base::Bind(&SessionManagerClientImpl::OnDeviceWipe,
102 weak_ptr_factory_.GetWeakPtr()));
105 virtual void RequestLockScreen() OVERRIDE {
106 SimpleMethodCallToSessionManager(login_manager::kSessionManagerLockScreen);
109 virtual void NotifyLockScreenShown() OVERRIDE {
110 SimpleMethodCallToSessionManager(
111 login_manager::kSessionManagerHandleLockScreenShown);
114 virtual void NotifyLockScreenDismissed() OVERRIDE {
115 SimpleMethodCallToSessionManager(
116 login_manager::kSessionManagerHandleLockScreenDismissed);
119 virtual void RetrieveActiveSessions(
120 const ActiveSessionsCallback& callback) OVERRIDE {
121 dbus::MethodCall method_call(
122 login_manager::kSessionManagerInterface,
123 login_manager::kSessionManagerRetrieveActiveSessions);
125 session_manager_proxy_->CallMethod(
127 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
128 base::Bind(&SessionManagerClientImpl::OnRetrieveActiveSessions,
129 weak_ptr_factory_.GetWeakPtr(),
130 login_manager::kSessionManagerRetrieveActiveSessions,
134 virtual void RetrieveDevicePolicy(
135 const RetrievePolicyCallback& callback) OVERRIDE {
136 dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
137 login_manager::kSessionManagerRetrievePolicy);
138 session_manager_proxy_->CallMethod(
140 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
141 base::Bind(&SessionManagerClientImpl::OnRetrievePolicy,
142 weak_ptr_factory_.GetWeakPtr(),
143 login_manager::kSessionManagerRetrievePolicy,
147 virtual void RetrievePolicyForUser(
148 const std::string& username,
149 const RetrievePolicyCallback& callback) OVERRIDE {
150 CallRetrievePolicyByUsername(
151 login_manager::kSessionManagerRetrievePolicyForUser,
156 virtual std::string BlockingRetrievePolicyForUser(
157 const std::string& username) OVERRIDE {
158 dbus::MethodCall method_call(
159 login_manager::kSessionManagerInterface,
160 login_manager::kSessionManagerRetrievePolicyForUser);
161 dbus::MessageWriter writer(&method_call);
162 writer.AppendString(username);
163 scoped_ptr<dbus::Response> response =
164 blocking_method_caller_->CallMethodAndBlock(&method_call);
166 ExtractString(login_manager::kSessionManagerRetrievePolicyForUser,
172 virtual void RetrieveDeviceLocalAccountPolicy(
173 const std::string& account_name,
174 const RetrievePolicyCallback& callback) OVERRIDE {
175 CallRetrievePolicyByUsername(
176 login_manager::kSessionManagerRetrieveDeviceLocalAccountPolicy,
181 virtual void StoreDevicePolicy(const std::string& policy_blob,
182 const StorePolicyCallback& callback) OVERRIDE {
183 dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
184 login_manager::kSessionManagerStorePolicy);
185 dbus::MessageWriter writer(&method_call);
186 // static_cast does not work due to signedness.
187 writer.AppendArrayOfBytes(
188 reinterpret_cast<const uint8*>(policy_blob.data()), policy_blob.size());
189 session_manager_proxy_->CallMethod(
191 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
192 base::Bind(&SessionManagerClientImpl::OnStorePolicy,
193 weak_ptr_factory_.GetWeakPtr(),
194 login_manager::kSessionManagerStorePolicy,
198 virtual void StorePolicyForUser(
199 const std::string& username,
200 const std::string& policy_blob,
201 const std::string& ignored_policy_key,
202 const StorePolicyCallback& callback) OVERRIDE {
203 CallStorePolicyByUsername(login_manager::kSessionManagerStorePolicyForUser,
209 virtual void StoreDeviceLocalAccountPolicy(
210 const std::string& account_name,
211 const std::string& policy_blob,
212 const StorePolicyCallback& callback) OVERRIDE {
213 CallStorePolicyByUsername(
214 login_manager::kSessionManagerStoreDeviceLocalAccountPolicy,
220 virtual void SetFlagsForUser(const std::string& username,
221 const std::vector<std::string>& flags) OVERRIDE {
222 dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
223 login_manager::kSessionManagerSetFlagsForUser);
224 dbus::MessageWriter writer(&method_call);
225 writer.AppendString(username);
226 writer.AppendArrayOfStrings(flags);
227 session_manager_proxy_->CallMethod(
229 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
230 dbus::ObjectProxy::EmptyResponseCallback());
234 virtual void Init(dbus::Bus* bus) OVERRIDE {
235 session_manager_proxy_ = bus->GetObjectProxy(
236 login_manager::kSessionManagerServiceName,
237 dbus::ObjectPath(login_manager::kSessionManagerServicePath));
238 blocking_method_caller_.reset(
239 new BlockingMethodCaller(bus, session_manager_proxy_));
241 // Signals emitted on Chromium's interface. Many of these ought to be
242 // method calls instead.
243 session_manager_proxy_->ConnectToSignal(
244 chromium::kChromiumInterface,
245 chromium::kLockScreenSignal,
246 base::Bind(&SessionManagerClientImpl::ScreenLockReceived,
247 weak_ptr_factory_.GetWeakPtr()),
248 base::Bind(&SessionManagerClientImpl::SignalConnected,
249 weak_ptr_factory_.GetWeakPtr()));
251 // Signals emitted on the session manager's interface.
252 session_manager_proxy_->ConnectToSignal(
253 login_manager::kSessionManagerInterface,
254 login_manager::kOwnerKeySetSignal,
255 base::Bind(&SessionManagerClientImpl::OwnerKeySetReceived,
256 weak_ptr_factory_.GetWeakPtr()),
257 base::Bind(&SessionManagerClientImpl::SignalConnected,
258 weak_ptr_factory_.GetWeakPtr()));
259 session_manager_proxy_->ConnectToSignal(
260 login_manager::kSessionManagerInterface,
261 login_manager::kPropertyChangeCompleteSignal,
262 base::Bind(&SessionManagerClientImpl::PropertyChangeCompleteReceived,
263 weak_ptr_factory_.GetWeakPtr()),
264 base::Bind(&SessionManagerClientImpl::SignalConnected,
265 weak_ptr_factory_.GetWeakPtr()));
266 session_manager_proxy_->ConnectToSignal(
267 login_manager::kSessionManagerInterface,
268 login_manager::kScreenIsLockedSignal,
269 base::Bind(&SessionManagerClientImpl::ScreenIsLockedReceived,
270 weak_ptr_factory_.GetWeakPtr()),
271 base::Bind(&SessionManagerClientImpl::SignalConnected,
272 weak_ptr_factory_.GetWeakPtr()));
273 session_manager_proxy_->ConnectToSignal(
274 login_manager::kSessionManagerInterface,
275 login_manager::kScreenIsUnlockedSignal,
276 base::Bind(&SessionManagerClientImpl::ScreenIsUnlockedReceived,
277 weak_ptr_factory_.GetWeakPtr()),
278 base::Bind(&SessionManagerClientImpl::SignalConnected,
279 weak_ptr_factory_.GetWeakPtr()));
283 // Makes a method call to the session manager with no arguments and no
285 void SimpleMethodCallToSessionManager(const std::string& method_name) {
286 dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
288 session_manager_proxy_->CallMethod(
290 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
291 dbus::ObjectProxy::EmptyResponseCallback());
294 // Helper for RetrieveDeviceLocalAccountPolicy and RetrievePolicyForUser.
295 void CallRetrievePolicyByUsername(const std::string& method_name,
296 const std::string& username,
297 const RetrievePolicyCallback& callback) {
298 dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
300 dbus::MessageWriter writer(&method_call);
301 writer.AppendString(username);
302 session_manager_proxy_->CallMethod(
304 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
306 &SessionManagerClientImpl::OnRetrievePolicy,
307 weak_ptr_factory_.GetWeakPtr(),
312 void CallStorePolicyByUsername(const std::string& method_name,
313 const std::string& username,
314 const std::string& policy_blob,
315 const StorePolicyCallback& callback) {
316 dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
318 dbus::MessageWriter writer(&method_call);
319 writer.AppendString(username);
320 // static_cast does not work due to signedness.
321 writer.AppendArrayOfBytes(
322 reinterpret_cast<const uint8*>(policy_blob.data()), policy_blob.size());
323 session_manager_proxy_->CallMethod(
325 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
327 &SessionManagerClientImpl::OnStorePolicy,
328 weak_ptr_factory_.GetWeakPtr(),
333 // Called when kSessionManagerRestartJob method is complete.
334 void OnRestartJob(dbus::Response* response) {
335 LOG_IF(ERROR, !response)
337 << login_manager::kSessionManagerRestartJob;
340 // Called when kSessionManagerStartSession method is complete.
341 void OnStartSession(dbus::Response* response) {
342 LOG_IF(ERROR, !response)
344 << login_manager::kSessionManagerStartSession;
347 // Called when kSessionManagerStopSession method is complete.
348 void OnStopSession(dbus::Response* response) {
349 LOG_IF(ERROR, !response)
351 << login_manager::kSessionManagerStopSession;
354 // Called when kSessionManagerStopSession method is complete.
355 void OnDeviceWipe(dbus::Response* response) {
356 LOG_IF(ERROR, !response)
358 << login_manager::kSessionManagerStartDeviceWipe;
361 // Called when kSessionManagerRetrieveActiveSessions method is complete.
362 void OnRetrieveActiveSessions(const std::string& method_name,
363 const ActiveSessionsCallback& callback,
364 dbus::Response* response) {
365 ActiveSessionsMap sessions;
366 bool success = false;
368 LOG(ERROR) << "Failed to call " << method_name;
369 callback.Run(sessions, success);
373 dbus::MessageReader reader(response);
374 dbus::MessageReader array_reader(NULL);
376 if (!reader.PopArray(&array_reader)) {
377 LOG(ERROR) << method_name << " response is incorrect: "
378 << response->ToString();
380 while (array_reader.HasMoreData()) {
381 dbus::MessageReader dict_entry_reader(NULL);
384 if (!array_reader.PopDictEntry(&dict_entry_reader) ||
385 !dict_entry_reader.PopString(&key) ||
386 !dict_entry_reader.PopString(&value)) {
387 LOG(ERROR) << method_name << " response is incorrect: "
388 << response->ToString();
390 sessions[key] = value;
395 callback.Run(sessions, success);
398 void ExtractString(const std::string& method_name,
399 dbus::Response* response,
400 std::string* extracted) {
402 LOG(ERROR) << "Failed to call " << method_name;
405 dbus::MessageReader reader(response);
406 uint8* values = NULL;
408 if (!reader.PopArrayOfBytes(&values, &length)) {
409 LOG(ERROR) << "Invalid response: " << response->ToString();
412 // static_cast does not work due to signedness.
413 extracted->assign(reinterpret_cast<char*>(values), length);
416 // Called when kSessionManagerRetrievePolicy or
417 // kSessionManagerRetrievePolicyForUser method is complete.
418 void OnRetrievePolicy(const std::string& method_name,
419 const RetrievePolicyCallback& callback,
420 dbus::Response* response) {
421 std::string serialized_proto;
422 ExtractString(method_name, response, &serialized_proto);
423 callback.Run(serialized_proto);
426 // Called when kSessionManagerStorePolicy or kSessionManagerStorePolicyForUser
427 // method is complete.
428 void OnStorePolicy(const std::string& method_name,
429 const StorePolicyCallback& callback,
430 dbus::Response* response) {
431 bool success = false;
433 LOG(ERROR) << "Failed to call " << method_name;
435 dbus::MessageReader reader(response);
436 if (!reader.PopBool(&success))
437 LOG(ERROR) << "Invalid response: " << response->ToString();
439 callback.Run(success);
442 // Called when the owner key set signal is received.
443 void OwnerKeySetReceived(dbus::Signal* signal) {
444 dbus::MessageReader reader(signal);
445 std::string result_string;
446 if (!reader.PopString(&result_string)) {
447 LOG(ERROR) << "Invalid signal: " << signal->ToString();
450 const bool success = StartsWithASCII(result_string, "success", false);
451 FOR_EACH_OBSERVER(Observer, observers_, OwnerKeySet(success));
454 // Called when the property change complete signal is received.
455 void PropertyChangeCompleteReceived(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();
462 const bool success = StartsWithASCII(result_string, "success", false);
463 FOR_EACH_OBSERVER(Observer, observers_, PropertyChangeComplete(success));
466 void ScreenLockReceived(dbus::Signal* signal) {
467 FOR_EACH_OBSERVER(Observer, observers_, LockScreen());
470 void ScreenIsLockedReceived(dbus::Signal* signal) {
471 FOR_EACH_OBSERVER(Observer, observers_, ScreenIsLocked());
474 void ScreenIsUnlockedReceived(dbus::Signal* signal) {
475 FOR_EACH_OBSERVER(Observer, observers_, ScreenIsUnlocked());
478 // Called when the object is connected to the signal.
479 void SignalConnected(const std::string& interface_name,
480 const std::string& signal_name,
482 LOG_IF(ERROR, !success) << "Failed to connect to " << signal_name;
485 dbus::ObjectProxy* session_manager_proxy_;
486 scoped_ptr<BlockingMethodCaller> blocking_method_caller_;
487 ObserverList<Observer> observers_;
489 // Note: This should remain the last member so it'll be destroyed and
490 // invalidate its weak pointers before any other members are destroyed.
491 base::WeakPtrFactory<SessionManagerClientImpl> weak_ptr_factory_;
493 DISALLOW_COPY_AND_ASSIGN(SessionManagerClientImpl);
496 // The SessionManagerClient implementation used on Linux desktop,
497 // which does nothing.
498 class SessionManagerClientStubImpl : public SessionManagerClient {
500 SessionManagerClientStubImpl() {}
501 virtual ~SessionManagerClientStubImpl() {}
503 // SessionManagerClient overrides
504 virtual void Init(dbus::Bus* bus) OVERRIDE {
505 // Make sure that there are no keys left over from a previous browser run.
506 base::FilePath user_policy_key_dir;
507 if (PathService::Get(chromeos::DIR_USER_POLICY_KEYS,
508 &user_policy_key_dir)) {
509 base::WorkerPool::PostTask(
511 base::Bind(base::IgnoreResult(&base::DeleteFile),
512 user_policy_key_dir, true),
517 virtual void AddObserver(Observer* observer) OVERRIDE {
518 observers_.AddObserver(observer);
520 virtual void RemoveObserver(Observer* observer) OVERRIDE {
521 observers_.RemoveObserver(observer);
523 virtual bool HasObserver(Observer* observer) OVERRIDE {
524 return observers_.HasObserver(observer);
526 virtual void EmitLoginPromptVisible() OVERRIDE {}
527 virtual void RestartJob(int pid, const std::string& command_line) OVERRIDE {}
528 virtual void StartSession(const std::string& user_email) OVERRIDE {}
529 virtual void StopSession() OVERRIDE {}
530 virtual void StartDeviceWipe() OVERRIDE {}
531 virtual void RequestLockScreen() OVERRIDE {
532 FOR_EACH_OBSERVER(Observer, observers_, LockScreen());
534 virtual void NotifyLockScreenShown() OVERRIDE {
535 FOR_EACH_OBSERVER(Observer, observers_, ScreenIsLocked());
537 virtual void NotifyLockScreenDismissed() OVERRIDE {
538 FOR_EACH_OBSERVER(Observer, observers_, ScreenIsUnlocked());
540 virtual void RetrieveActiveSessions(
541 const ActiveSessionsCallback& callback) OVERRIDE {}
542 virtual void RetrieveDevicePolicy(
543 const RetrievePolicyCallback& callback) OVERRIDE {
544 callback.Run(device_policy_);
546 virtual void RetrievePolicyForUser(
547 const std::string& username,
548 const RetrievePolicyCallback& callback) OVERRIDE {
549 callback.Run(user_policies_[username]);
551 virtual std::string BlockingRetrievePolicyForUser(
552 const std::string& username) OVERRIDE {
553 return user_policies_[username];
555 virtual void RetrieveDeviceLocalAccountPolicy(
556 const std::string& account_name,
557 const RetrievePolicyCallback& callback) OVERRIDE {
558 callback.Run(user_policies_[account_name]);
560 virtual void StoreDevicePolicy(const std::string& policy_blob,
561 const StorePolicyCallback& callback) OVERRIDE {
562 device_policy_ = policy_blob;
565 virtual void StorePolicyForUser(
566 const std::string& username,
567 const std::string& policy_blob,
568 const std::string& policy_key,
569 const StorePolicyCallback& callback) OVERRIDE {
570 if (policy_key.empty()) {
571 user_policies_[username] = policy_blob;
575 // The session manager writes the user policy key to a well-known
576 // location. Do the same with the stub impl, so that user policy works and
577 // can be tested on desktop builds.
578 // TODO(joaodasilva): parse the PolicyFetchResponse in |policy_blob| to get
579 // the policy key directly, after moving the policy protobufs to a top-level
580 // directory. The |policy_key| argument to this method can then be removed.
581 // http://crbug.com/240269
582 base::FilePath key_path;
583 if (!PathService::Get(chromeos::DIR_USER_POLICY_KEYS, &key_path)) {
587 const std::string sanitized =
588 CryptohomeClient::GetStubSanitizedUsername(username);
589 key_path = key_path.AppendASCII(sanitized).AppendASCII("policy.pub");
590 // Assume that the key write is successful.
591 user_policies_[username] = policy_blob;
592 base::WorkerPool::PostTaskAndReply(
594 base::Bind(&SessionManagerClientStubImpl::StoreFileInBackground,
595 key_path, policy_key),
596 base::Bind(callback, true),
599 virtual void StoreDeviceLocalAccountPolicy(
600 const std::string& account_name,
601 const std::string& policy_blob,
602 const StorePolicyCallback& callback) OVERRIDE {
603 user_policies_[account_name] = policy_blob;
606 virtual void SetFlagsForUser(const std::string& username,
607 const std::vector<std::string>& flags) OVERRIDE {
610 static void StoreFileInBackground(const base::FilePath& path,
611 const std::string& data) {
612 const int size = static_cast<int>(data.size());
613 if (!base::CreateDirectory(path.DirName()) ||
614 file_util::WriteFile(path, data.data(), size) != size) {
615 LOG(WARNING) << "Failed to write policy key to " << path.value();
620 ObserverList<Observer> observers_;
621 std::string device_policy_;
622 std::map<std::string, std::string> user_policies_;
624 DISALLOW_COPY_AND_ASSIGN(SessionManagerClientStubImpl);
627 SessionManagerClient::SessionManagerClient() {
630 SessionManagerClient::~SessionManagerClient() {
633 SessionManagerClient* SessionManagerClient::Create(
634 DBusClientImplementationType type) {
635 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
636 return new SessionManagerClientImpl();
637 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
638 return new SessionManagerClientStubImpl();
641 } // namespace chromeos