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/session_manager_client.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <cstring>
11 #include <memory>
12 #include <utility>
13 
14 #include "base/bind.h"
15 #include "base/callback.h"
16 #include "base/callback_helpers.h"
17 #include "base/files/file_path.h"
18 #include "base/files/file_util.h"
19 #include "base/files/scoped_file.h"
20 #include "base/location.h"
21 #include "base/logging.h"
22 #include "base/macros.h"
23 #include "base/memory/platform_shared_memory_region.h"
24 #include "base/memory/read_only_shared_memory_region.h"
25 #include "base/memory/writable_shared_memory_region.h"
26 #include "base/metrics/histogram_macros.h"
27 #include "base/optional.h"
28 #include "base/path_service.h"
29 #include "base/strings/string_util.h"
30 #include "base/threading/thread_task_runner_handle.h"
31 #include "base/unguessable_token.h"
32 #include "chromeos/dbus/blocking_method_caller.h"
33 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
34 #include "chromeos/dbus/cryptohome/rpc.pb.h"
35 #include "chromeos/dbus/login_manager/arc.pb.h"
36 #include "chromeos/dbus/login_manager/login_screen_storage.pb.h"
37 #include "chromeos/dbus/login_manager/policy_descriptor.pb.h"
38 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
39 #include "components/policy/proto/device_management_backend.pb.h"
40 #include "dbus/bus.h"
41 #include "dbus/message.h"
42 #include "dbus/object_path.h"
43 #include "dbus/object_proxy.h"
44 #include "dbus/scoped_dbus_error.h"
45 #include "third_party/cros_system_api/dbus/service_constants.h"
46 
47 namespace chromeos {
48 
49 namespace {
50 
51 SessionManagerClient* g_instance = nullptr;
52 
53 using RetrievePolicyResponseType =
54     SessionManagerClient::RetrievePolicyResponseType;
55 
56 constexpr char kEmptyAccountId[] = "";
57 // The timeout used when starting the android container is 90 seconds
58 constexpr int kStartArcTimeout = 90 * 1000;
59 
60 // 10MB. It's the current restriction enforced by session manager.
61 const size_t kSharedMemoryDataSizeLimit = 10 * 1024 * 1024;
62 
63 // Helper to get the enum type of RetrievePolicyResponseType based on error
64 // name.
GetPolicyResponseTypeByError(base::StringPiece error_name)65 RetrievePolicyResponseType GetPolicyResponseTypeByError(
66     base::StringPiece error_name) {
67   if (error_name == login_manager::dbus_error::kNone) {
68     return RetrievePolicyResponseType::SUCCESS;
69   } else if (error_name == login_manager::dbus_error::kGetServiceFail ||
70              error_name == login_manager::dbus_error::kSessionDoesNotExist) {
71     // TODO(crbug.com/765644): Remove kSessionDoesNotExist case once Chrome OS
72     // has switched to kGetServiceFail.
73     return RetrievePolicyResponseType::GET_SERVICE_FAIL;
74   } else if (error_name == login_manager::dbus_error::kSigEncodeFail) {
75     return RetrievePolicyResponseType::POLICY_ENCODE_ERROR;
76   }
77   return RetrievePolicyResponseType::OTHER_ERROR;
78 }
79 
80 // Logs UMA stat for retrieve policy request, corresponding to D-Bus method name
81 // used.
LogPolicyResponseUma(login_manager::PolicyAccountType account_type,RetrievePolicyResponseType response)82 void LogPolicyResponseUma(login_manager::PolicyAccountType account_type,
83                           RetrievePolicyResponseType response) {
84   switch (account_type) {
85     case login_manager::ACCOUNT_TYPE_DEVICE:
86       UMA_HISTOGRAM_ENUMERATION("Enterprise.RetrievePolicyResponse.Device",
87                                 response, RetrievePolicyResponseType::COUNT);
88       break;
89     case login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT:
90       UMA_HISTOGRAM_ENUMERATION(
91           "Enterprise.RetrievePolicyResponse.DeviceLocalAccount", response,
92           RetrievePolicyResponseType::COUNT);
93       break;
94     case login_manager::ACCOUNT_TYPE_USER:
95       UMA_HISTOGRAM_ENUMERATION("Enterprise.RetrievePolicyResponse.User",
96                                 response, RetrievePolicyResponseType::COUNT);
97       break;
98     case login_manager::ACCOUNT_TYPE_SESSIONLESS_USER:
99       UMA_HISTOGRAM_ENUMERATION(
100           "Enterprise.RetrievePolicyResponse.UserDuringLogin", response,
101           RetrievePolicyResponseType::COUNT);
102       break;
103   }
104 }
105 
106 // Creates a PolicyDescriptor object to store/retrieve Chrome policy.
MakeChromePolicyDescriptor(login_manager::PolicyAccountType account_type,const std::string & account_id)107 login_manager::PolicyDescriptor MakeChromePolicyDescriptor(
108     login_manager::PolicyAccountType account_type,
109     const std::string& account_id) {
110   login_manager::PolicyDescriptor descriptor;
111   descriptor.set_account_type(account_type);
112   descriptor.set_account_id(account_id);
113   descriptor.set_domain(login_manager::POLICY_DOMAIN_CHROME);
114   return descriptor;
115 }
116 
117 // Creates a pipe that contains the given data. The data will be prefixed by a
118 // size_t sized variable containing the size of the data to read. Since we don't
119 // pass this pipe's read end anywhere, we can be sure that the only FD that can
120 // read from that pipe will be closed on browser's exit, therefore the password
121 // won't be leaked if the browser crashes.
CreatePasswordPipe(const std::string & data)122 base::ScopedFD CreatePasswordPipe(const std::string& data) {
123   // 64k of data, minus 64 bits for a preceding size. This number was chosen to
124   // fit all the data in a single pipe buffer and avoid blocking on write.
125   // (http://man7.org/linux/man-pages/man7/pipe.7.html)
126   const size_t kPipeDataSizeLimit = 1024 * 64 - sizeof(size_t);
127 
128   int pipe_fds[2];
129   if (data.size() > kPipeDataSizeLimit ||
130       !base::CreateLocalNonBlockingPipe(pipe_fds)) {
131     DLOG(ERROR) << "Failed to create pipe";
132     return base::ScopedFD();
133   }
134   base::ScopedFD pipe_read_end(pipe_fds[0]);
135   base::ScopedFD pipe_write_end(pipe_fds[1]);
136 
137   const size_t data_size = data.size();
138 
139   base::WriteFileDescriptor(pipe_write_end.get(),
140                             reinterpret_cast<const char*>(&data_size),
141                             sizeof(data_size));
142   base::WriteFileDescriptor(pipe_write_end.get(), data.c_str(), data.size());
143 
144   return pipe_read_end;
145 }
146 
147 // Creates a read-only shared memory region that contains the given data.
CreateSharedMemoryRegionFDWithData(const std::string & data)148 base::ScopedFD CreateSharedMemoryRegionFDWithData(const std::string& data) {
149   if (data.size() > kSharedMemoryDataSizeLimit) {
150     LOG(ERROR) << "Couldn't create shared memory, data is too big.";
151     return base::ScopedFD();
152   }
153   auto region = base::WritableSharedMemoryRegion::Create(data.size());
154   base::WritableSharedMemoryMapping mapping = region.Map();
155   if (!mapping.IsValid())
156     return base::ScopedFD();
157   memcpy(mapping.memory(), data.data(), data.size());
158   return base::WritableSharedMemoryRegion::TakeHandleForSerialization(
159              std::move(region))
160       .PassPlatformHandle()
161       .readonly_fd;
162 }
163 
164 // Reads |secret_size| bytes from a given shared memory region. Puts result into
165 // |secret|. |fd| should point at a read-only shared memory region.
ReadSecretFromSharedMemory(base::ScopedFD fd,size_t secret_size,std::vector<uint8_t> * secret)166 bool ReadSecretFromSharedMemory(base::ScopedFD fd,
167                                 size_t secret_size,
168                                 std::vector<uint8_t>* secret) {
169   if (secret_size > kSharedMemoryDataSizeLimit) {
170     LOG(ERROR) << "Couldn't read secret from the shared memory, "
171                   "secret's size is too big.";
172     return false;
173   }
174   auto platform_region(base::subtle::PlatformSharedMemoryRegion::Take(
175       std::move(fd), base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly,
176       secret_size, base::UnguessableToken::Create()));
177   if (!platform_region.IsValid())
178     return false;
179   auto region =
180       base::ReadOnlySharedMemoryRegion::Deserialize(std::move(platform_region));
181   if (!region.IsValid())
182     return false;
183   base::ReadOnlySharedMemoryMapping mapping = region.Map();
184   if (!mapping.IsValid())
185     return false;
186   secret->resize(secret_size);
187   memcpy(secret->data(), mapping.memory(), secret->size());
188   return true;
189 }
190 
191 }  // namespace
192 
193 // The SessionManagerClient implementation used in production.
194 class SessionManagerClientImpl : public SessionManagerClient {
195  public:
196   SessionManagerClientImpl() = default;
197   ~SessionManagerClientImpl() override = default;
198 
199   // SessionManagerClient overrides:
SetStubDelegate(StubDelegate * delegate)200   void SetStubDelegate(StubDelegate* delegate) override {
201     // Do nothing; this isn't a stub implementation.
202   }
203 
AddObserver(Observer * observer)204   void AddObserver(Observer* observer) override {
205     observers_.AddObserver(observer);
206   }
207 
RemoveObserver(Observer * observer)208   void RemoveObserver(Observer* observer) override {
209     observers_.RemoveObserver(observer);
210   }
211 
HasObserver(const Observer * observer) const212   bool HasObserver(const Observer* observer) const override {
213     return observers_.HasObserver(observer);
214   }
215 
WaitForServiceToBeAvailable(WaitForServiceToBeAvailableCallback callback)216   void WaitForServiceToBeAvailable(
217       WaitForServiceToBeAvailableCallback callback) override {
218     session_manager_proxy_->WaitForServiceToBeAvailable(std::move(callback));
219   }
220 
IsScreenLocked() const221   bool IsScreenLocked() const override { return screen_is_locked_; }
222 
EmitLoginPromptVisible()223   void EmitLoginPromptVisible() override {
224     SimpleMethodCallToSessionManager(
225         login_manager::kSessionManagerEmitLoginPromptVisible);
226     for (auto& observer : observers_)
227       observer.EmitLoginPromptVisibleCalled();
228   }
229 
EmitAshInitialized()230   void EmitAshInitialized() override {
231     SimpleMethodCallToSessionManager(
232         login_manager::kSessionManagerEmitAshInitialized);
233   }
234 
RestartJob(int socket_fd,const std::vector<std::string> & argv,VoidDBusMethodCallback callback)235   void RestartJob(int socket_fd,
236                   const std::vector<std::string>& argv,
237                   VoidDBusMethodCallback callback) override {
238     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
239                                  login_manager::kSessionManagerRestartJob);
240     dbus::MessageWriter writer(&method_call);
241     writer.AppendFileDescriptor(socket_fd);
242     writer.AppendArrayOfStrings(argv);
243     session_manager_proxy_->CallMethod(
244         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
245         base::BindOnce(&SessionManagerClientImpl::OnVoidMethod,
246                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
247   }
248 
SaveLoginPassword(const std::string & password)249   void SaveLoginPassword(const std::string& password) override {
250     dbus::MethodCall method_call(
251         login_manager::kSessionManagerInterface,
252         login_manager::kSessionManagerSaveLoginPassword);
253     dbus::MessageWriter writer(&method_call);
254 
255     base::ScopedFD fd = CreatePasswordPipe(password);
256     if (fd.get() == -1) {
257       LOG(WARNING) << "Could not create password pipe.";
258       return;
259     }
260 
261     writer.AppendFileDescriptor(fd.get());
262 
263     session_manager_proxy_->CallMethod(&method_call,
264                                        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
265                                        base::DoNothing());
266   }
267 
LoginScreenStorageStore(const std::string & key,const login_manager::LoginScreenStorageMetadata & metadata,const std::string & data,LoginScreenStorageStoreCallback callback)268   void LoginScreenStorageStore(
269       const std::string& key,
270       const login_manager::LoginScreenStorageMetadata& metadata,
271       const std::string& data,
272       LoginScreenStorageStoreCallback callback) override {
273     dbus::MethodCall method_call(
274         login_manager::kSessionManagerInterface,
275         login_manager::kSessionManagerLoginScreenStorageStore);
276     dbus::MessageWriter writer(&method_call);
277     writer.AppendString(key);
278 
279     const std::string metadata_blob = metadata.SerializeAsString();
280     writer.AppendArrayOfBytes(
281         reinterpret_cast<const uint8_t*>(metadata_blob.data()),
282         metadata_blob.size());
283     writer.AppendUint64(data.size());
284 
285     base::ScopedFD fd = CreateSharedMemoryRegionFDWithData(data);
286     if (!fd.is_valid()) {
287       std::string error = "Could not create shared memory.";
288       std::move(callback).Run(std::move(error));
289       return;
290     }
291     writer.AppendFileDescriptor(fd.get());
292 
293     session_manager_proxy_->CallMethod(
294         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
295         base::BindOnce(&SessionManagerClientImpl::OnLoginScreenStorageStore,
296                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
297   }
298 
LoginScreenStorageRetrieve(const std::string & key,LoginScreenStorageRetrieveCallback callback)299   void LoginScreenStorageRetrieve(
300       const std::string& key,
301       LoginScreenStorageRetrieveCallback callback) override {
302     dbus::MethodCall method_call(
303         login_manager::kSessionManagerInterface,
304         login_manager::kSessionManagerLoginScreenStorageRetrieve);
305     dbus::MessageWriter writer(&method_call);
306     writer.AppendString(key);
307     session_manager_proxy_->CallMethod(
308         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
309         base::BindOnce(&SessionManagerClientImpl::OnLoginScreenStorageRetrieve,
310                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
311   }
312 
LoginScreenStorageListKeys(LoginScreenStorageListKeysCallback callback)313   void LoginScreenStorageListKeys(
314       LoginScreenStorageListKeysCallback callback) override {
315     dbus::MethodCall method_call(
316         login_manager::kSessionManagerInterface,
317         login_manager::kSessionManagerLoginScreenStorageListKeys);
318     session_manager_proxy_->CallMethod(
319         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
320         base::BindOnce(&SessionManagerClientImpl::OnLoginScreenStorageListKeys,
321                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
322   }
323 
LoginScreenStorageDelete(const std::string & key)324   void LoginScreenStorageDelete(const std::string& key) override {
325     dbus::MethodCall method_call(
326         login_manager::kSessionManagerInterface,
327         login_manager::kSessionManagerLoginScreenStorageDelete);
328     dbus::MessageWriter writer(&method_call);
329     writer.AppendString(key);
330     session_manager_proxy_->CallMethod(&method_call,
331                                        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
332                                        base::DoNothing());
333   }
334 
StartSession(const cryptohome::AccountIdentifier & cryptohome_id)335   void StartSession(
336       const cryptohome::AccountIdentifier& cryptohome_id) override {
337     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
338                                  login_manager::kSessionManagerStartSession);
339     dbus::MessageWriter writer(&method_call);
340     writer.AppendString(cryptohome_id.account_id());
341     writer.AppendString("");  // Unique ID is deprecated
342     session_manager_proxy_->CallMethod(&method_call,
343                                        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
344                                        base::DoNothing());
345   }
346 
StopSession(login_manager::SessionStopReason reason)347   void StopSession(login_manager::SessionStopReason reason) override {
348     dbus::MethodCall method_call(
349         login_manager::kSessionManagerInterface,
350         login_manager::kSessionManagerStopSessionWithReason);
351     dbus::MessageWriter writer(&method_call);
352     writer.AppendUint32(static_cast<uint32_t>(reason));
353     session_manager_proxy_->CallMethod(&method_call,
354                                        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
355                                        base::DoNothing());
356   }
357 
StartDeviceWipe()358   void StartDeviceWipe() override {
359     SimpleMethodCallToSessionManager(
360         login_manager::kSessionManagerStartDeviceWipe);
361   }
362 
StartRemoteDeviceWipe(const enterprise_management::SignedData & signed_command)363   void StartRemoteDeviceWipe(
364       const enterprise_management::SignedData& signed_command) override {
365     dbus::MethodCall method_call(
366         login_manager::kSessionManagerInterface,
367         login_manager::kSessionManagerStartRemoteDeviceWipe);
368     dbus::MessageWriter writer(&method_call);
369     writer.AppendProtoAsArrayOfBytes(signed_command);
370     session_manager_proxy_->CallMethod(&method_call,
371                                        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
372                                        base::DoNothing());
373   }
374 
ClearForcedReEnrollmentVpd(VoidDBusMethodCallback callback)375   void ClearForcedReEnrollmentVpd(VoidDBusMethodCallback callback) override {
376     dbus::MethodCall method_call(
377         login_manager::kSessionManagerInterface,
378         login_manager::kSessionManagerClearForcedReEnrollmentVpd);
379     dbus::MessageWriter writer(&method_call);
380     session_manager_proxy_->CallMethod(
381         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
382         base::BindOnce(&SessionManagerClientImpl::OnVoidMethod,
383                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
384   }
385 
StartTPMFirmwareUpdate(const std::string & update_mode)386   void StartTPMFirmwareUpdate(const std::string& update_mode) override {
387     dbus::MethodCall method_call(
388         login_manager::kSessionManagerInterface,
389         login_manager::kSessionManagerStartTPMFirmwareUpdate);
390     dbus::MessageWriter writer(&method_call);
391     writer.AppendString(update_mode);
392     session_manager_proxy_->CallMethod(&method_call,
393                                        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
394                                        base::DoNothing());
395   }
396 
RequestLockScreen()397   void RequestLockScreen() override {
398     SimpleMethodCallToSessionManager(login_manager::kSessionManagerLockScreen);
399   }
400 
NotifyLockScreenShown()401   void NotifyLockScreenShown() override {
402     SimpleMethodCallToSessionManager(
403         login_manager::kSessionManagerHandleLockScreenShown);
404   }
405 
NotifyLockScreenDismissed()406   void NotifyLockScreenDismissed() override {
407     SimpleMethodCallToSessionManager(
408         login_manager::kSessionManagerHandleLockScreenDismissed);
409   }
410 
RetrieveActiveSessions(ActiveSessionsCallback callback)411   void RetrieveActiveSessions(ActiveSessionsCallback callback) override {
412     dbus::MethodCall method_call(
413         login_manager::kSessionManagerInterface,
414         login_manager::kSessionManagerRetrieveActiveSessions);
415 
416     session_manager_proxy_->CallMethod(
417         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
418         base::BindOnce(&SessionManagerClientImpl::OnRetrieveActiveSessions,
419                        weak_ptr_factory_.GetWeakPtr(),
420                        login_manager::kSessionManagerRetrieveActiveSessions,
421                        std::move(callback)));
422   }
423 
RetrieveDevicePolicy(RetrievePolicyCallback callback)424   void RetrieveDevicePolicy(RetrievePolicyCallback callback) override {
425     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
426         login_manager::ACCOUNT_TYPE_DEVICE, kEmptyAccountId);
427     CallRetrievePolicy(descriptor, std::move(callback));
428   }
429 
BlockingRetrieveDevicePolicy(std::string * policy_out)430   RetrievePolicyResponseType BlockingRetrieveDevicePolicy(
431       std::string* policy_out) override {
432     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
433         login_manager::ACCOUNT_TYPE_DEVICE, kEmptyAccountId);
434     return BlockingRetrievePolicy(descriptor, policy_out);
435   }
436 
RetrievePolicyForUser(const cryptohome::AccountIdentifier & cryptohome_id,RetrievePolicyCallback callback)437   void RetrievePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id,
438                              RetrievePolicyCallback callback) override {
439     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
440         login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id());
441     CallRetrievePolicy(descriptor, std::move(callback));
442   }
443 
BlockingRetrievePolicyForUser(const cryptohome::AccountIdentifier & cryptohome_id,std::string * policy_out)444   RetrievePolicyResponseType BlockingRetrievePolicyForUser(
445       const cryptohome::AccountIdentifier& cryptohome_id,
446       std::string* policy_out) override {
447     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
448         login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id());
449     return BlockingRetrievePolicy(descriptor, policy_out);
450   }
451 
RetrievePolicyForUserWithoutSession(const cryptohome::AccountIdentifier & cryptohome_id,RetrievePolicyCallback callback)452   void RetrievePolicyForUserWithoutSession(
453       const cryptohome::AccountIdentifier& cryptohome_id,
454       RetrievePolicyCallback callback) override {
455     login_manager::PolicyDescriptor descriptor =
456         MakeChromePolicyDescriptor(login_manager::ACCOUNT_TYPE_SESSIONLESS_USER,
457                                    cryptohome_id.account_id());
458     CallRetrievePolicy(descriptor, std::move(callback));
459   }
460 
RetrieveDeviceLocalAccountPolicy(const std::string & account_name,RetrievePolicyCallback callback)461   void RetrieveDeviceLocalAccountPolicy(
462       const std::string& account_name,
463       RetrievePolicyCallback callback) override {
464     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
465         login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT, account_name);
466     CallRetrievePolicy(descriptor, std::move(callback));
467   }
468 
BlockingRetrieveDeviceLocalAccountPolicy(const std::string & account_name,std::string * policy_out)469   RetrievePolicyResponseType BlockingRetrieveDeviceLocalAccountPolicy(
470       const std::string& account_name,
471       std::string* policy_out) override {
472     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
473         login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT, account_name);
474     return BlockingRetrievePolicy(descriptor, policy_out);
475   }
476 
RetrievePolicy(const login_manager::PolicyDescriptor & descriptor,RetrievePolicyCallback callback)477   void RetrievePolicy(const login_manager::PolicyDescriptor& descriptor,
478                       RetrievePolicyCallback callback) override {
479     CallRetrievePolicy(descriptor, std::move(callback));
480   }
481 
BlockingRetrievePolicy(const login_manager::PolicyDescriptor & descriptor,std::string * policy_out)482   RetrievePolicyResponseType BlockingRetrievePolicy(
483       const login_manager::PolicyDescriptor& descriptor,
484       std::string* policy_out) override {
485     return CallBlockingRetrievePolicy(descriptor, policy_out);
486   }
487 
StoreDevicePolicy(const std::string & policy_blob,VoidDBusMethodCallback callback)488   void StoreDevicePolicy(const std::string& policy_blob,
489                          VoidDBusMethodCallback callback) override {
490     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
491         login_manager::ACCOUNT_TYPE_DEVICE, kEmptyAccountId);
492     CallStorePolicy(descriptor, policy_blob, std::move(callback));
493   }
494 
StorePolicyForUser(const cryptohome::AccountIdentifier & cryptohome_id,const std::string & policy_blob,VoidDBusMethodCallback callback)495   void StorePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id,
496                           const std::string& policy_blob,
497                           VoidDBusMethodCallback callback) override {
498     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
499         login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id());
500     CallStorePolicy(descriptor, policy_blob, std::move(callback));
501   }
502 
StoreDeviceLocalAccountPolicy(const std::string & account_name,const std::string & policy_blob,VoidDBusMethodCallback callback)503   void StoreDeviceLocalAccountPolicy(const std::string& account_name,
504                                      const std::string& policy_blob,
505                                      VoidDBusMethodCallback callback) override {
506     login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
507         login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT, account_name);
508     CallStorePolicy(descriptor, policy_blob, std::move(callback));
509   }
510 
StorePolicy(const login_manager::PolicyDescriptor & descriptor,const std::string & policy_blob,VoidDBusMethodCallback callback)511   void StorePolicy(const login_manager::PolicyDescriptor& descriptor,
512                    const std::string& policy_blob,
513                    VoidDBusMethodCallback callback) override {
514     CallStorePolicy(descriptor, policy_blob, std::move(callback));
515   }
516 
SupportsBrowserRestart() const517   bool SupportsBrowserRestart() const override { return true; }
518 
SetFlagsForUser(const cryptohome::AccountIdentifier & cryptohome_id,const std::vector<std::string> & flags)519   void SetFlagsForUser(const cryptohome::AccountIdentifier& cryptohome_id,
520                        const std::vector<std::string>& flags) override {
521     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
522                                  login_manager::kSessionManagerSetFlagsForUser);
523     dbus::MessageWriter writer(&method_call);
524     writer.AppendString(cryptohome_id.account_id());
525     writer.AppendArrayOfStrings(flags);
526     session_manager_proxy_->CallMethod(&method_call,
527                                        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
528                                        base::DoNothing());
529   }
530 
GetServerBackedStateKeys(StateKeysCallback callback)531   void GetServerBackedStateKeys(StateKeysCallback callback) override {
532     dbus::MethodCall method_call(
533         login_manager::kSessionManagerInterface,
534         login_manager::kSessionManagerGetServerBackedStateKeys);
535 
536     // Infinite timeout needed because the state keys are not generated as long
537     // as the time sync hasn't been done (which requires network).
538     // TODO(igorcov): Since this is a resource allocated that could last a long
539     // time, we will need to change the behavior to either listen to
540     // LastSyncInfo event from tlsdated or communicate through signals with
541     // session manager in this particular flow.
542     session_manager_proxy_->CallMethod(
543         &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE,
544         base::BindOnce(&SessionManagerClientImpl::OnGetServerBackedStateKeys,
545                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
546   }
547 
StartArcMiniContainer(const login_manager::StartArcMiniContainerRequest & request,VoidDBusMethodCallback callback)548   void StartArcMiniContainer(
549       const login_manager::StartArcMiniContainerRequest& request,
550       VoidDBusMethodCallback callback) override {
551     DCHECK(!callback.is_null());
552     dbus::MethodCall method_call(
553         login_manager::kSessionManagerInterface,
554         login_manager::kSessionManagerStartArcMiniContainer);
555     dbus::MessageWriter writer(&method_call);
556 
557     writer.AppendProtoAsArrayOfBytes(request);
558 
559     session_manager_proxy_->CallMethod(
560         &method_call, kStartArcTimeout,
561         base::BindOnce(&SessionManagerClientImpl::OnVoidMethod,
562                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
563   }
564 
UpgradeArcContainer(const login_manager::UpgradeArcContainerRequest & request,VoidDBusMethodCallback callback)565   void UpgradeArcContainer(
566       const login_manager::UpgradeArcContainerRequest& request,
567       VoidDBusMethodCallback callback) override {
568     DCHECK(!callback.is_null());
569     dbus::MethodCall method_call(
570         login_manager::kSessionManagerInterface,
571         login_manager::kSessionManagerUpgradeArcContainer);
572     dbus::MessageWriter writer(&method_call);
573 
574     writer.AppendProtoAsArrayOfBytes(request);
575 
576     session_manager_proxy_->CallMethod(
577         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
578         base::BindOnce(&SessionManagerClientImpl::OnVoidMethod,
579                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
580   }
581 
StopArcInstance(const std::string & account_id,bool should_backup_log,VoidDBusMethodCallback callback)582   void StopArcInstance(const std::string& account_id,
583                        bool should_backup_log,
584                        VoidDBusMethodCallback callback) override {
585     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
586                                  login_manager::kSessionManagerStopArcInstance);
587 
588     dbus::MessageWriter writer(&method_call);
589     writer.AppendString(account_id);
590     writer.AppendBool(should_backup_log);
591 
592     session_manager_proxy_->CallMethod(
593         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
594         base::BindOnce(&SessionManagerClientImpl::OnVoidMethod,
595                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
596   }
597 
SetArcCpuRestriction(login_manager::ContainerCpuRestrictionState restriction_state,VoidDBusMethodCallback callback)598   void SetArcCpuRestriction(
599       login_manager::ContainerCpuRestrictionState restriction_state,
600       VoidDBusMethodCallback callback) override {
601     dbus::MethodCall method_call(
602         login_manager::kSessionManagerInterface,
603         login_manager::kSessionManagerSetArcCpuRestriction);
604     dbus::MessageWriter writer(&method_call);
605     writer.AppendUint32(restriction_state);
606     session_manager_proxy_->CallMethod(
607         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
608         base::BindOnce(&SessionManagerClientImpl::OnVoidMethod,
609                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
610   }
611 
EmitArcBooted(const cryptohome::AccountIdentifier & cryptohome_id,VoidDBusMethodCallback callback)612   void EmitArcBooted(const cryptohome::AccountIdentifier& cryptohome_id,
613                      VoidDBusMethodCallback callback) override {
614     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
615                                  login_manager::kSessionManagerEmitArcBooted);
616     dbus::MessageWriter writer(&method_call);
617     writer.AppendString(cryptohome_id.account_id());
618     session_manager_proxy_->CallMethod(
619         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
620         base::BindOnce(&SessionManagerClientImpl::OnVoidMethod,
621                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
622   }
623 
GetArcStartTime(DBusMethodCallback<base::TimeTicks> callback)624   void GetArcStartTime(DBusMethodCallback<base::TimeTicks> callback) override {
625     dbus::MethodCall method_call(
626         login_manager::kSessionManagerInterface,
627         login_manager::kSessionManagerGetArcStartTimeTicks);
628 
629     session_manager_proxy_->CallMethod(
630         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
631         base::BindOnce(&SessionManagerClientImpl::OnGetArcStartTime,
632                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
633   }
634 
EnableAdbSideload(EnableAdbSideloadCallback callback)635   void EnableAdbSideload(EnableAdbSideloadCallback callback) override {
636     dbus::MethodCall method_call(
637         login_manager::kSessionManagerInterface,
638         login_manager::kSessionManagerEnableAdbSideload);
639 
640     session_manager_proxy_->CallMethodWithErrorResponse(
641         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
642         base::BindOnce(&SessionManagerClientImpl::OnEnableAdbSideload,
643                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
644   }
645 
QueryAdbSideload(QueryAdbSideloadCallback callback)646   void QueryAdbSideload(QueryAdbSideloadCallback callback) override {
647     dbus::MethodCall method_call(
648         login_manager::kSessionManagerInterface,
649         login_manager::kSessionManagerQueryAdbSideload);
650 
651     session_manager_proxy_->CallMethodWithErrorResponse(
652         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
653         base::BindOnce(&SessionManagerClientImpl::OnQueryAdbSideload,
654                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
655   }
656 
Init(dbus::Bus * bus)657   void Init(dbus::Bus* bus) {
658     session_manager_proxy_ = bus->GetObjectProxy(
659         login_manager::kSessionManagerServiceName,
660         dbus::ObjectPath(login_manager::kSessionManagerServicePath));
661     blocking_method_caller_.reset(
662         new BlockingMethodCaller(bus, session_manager_proxy_));
663 
664     // Signals emitted on the session manager's interface.
665     session_manager_proxy_->ConnectToSignal(
666         login_manager::kSessionManagerInterface,
667         login_manager::kOwnerKeySetSignal,
668         base::BindRepeating(&SessionManagerClientImpl::OwnerKeySetReceived,
669                             weak_ptr_factory_.GetWeakPtr()),
670         base::BindOnce(&SessionManagerClientImpl::SignalConnected,
671                        weak_ptr_factory_.GetWeakPtr()));
672     session_manager_proxy_->ConnectToSignal(
673         login_manager::kSessionManagerInterface,
674         login_manager::kPropertyChangeCompleteSignal,
675         base::BindRepeating(
676             &SessionManagerClientImpl::PropertyChangeCompleteReceived,
677             weak_ptr_factory_.GetWeakPtr()),
678         base::BindOnce(&SessionManagerClientImpl::SignalConnected,
679                        weak_ptr_factory_.GetWeakPtr()));
680     session_manager_proxy_->ConnectToSignal(
681         login_manager::kSessionManagerInterface,
682         login_manager::kScreenIsLockedSignal,
683         base::BindRepeating(&SessionManagerClientImpl::ScreenIsLockedReceived,
684                             weak_ptr_factory_.GetWeakPtr()),
685         base::BindOnce(&SessionManagerClientImpl::SignalConnected,
686                        weak_ptr_factory_.GetWeakPtr()));
687     session_manager_proxy_->ConnectToSignal(
688         login_manager::kSessionManagerInterface,
689         login_manager::kScreenIsUnlockedSignal,
690         base::BindRepeating(&SessionManagerClientImpl::ScreenIsUnlockedReceived,
691                             weak_ptr_factory_.GetWeakPtr()),
692         base::BindOnce(&SessionManagerClientImpl::SignalConnected,
693                        weak_ptr_factory_.GetWeakPtr()));
694     session_manager_proxy_->ConnectToSignal(
695         login_manager::kSessionManagerInterface,
696         login_manager::kArcInstanceStopped,
697         base::BindRepeating(
698             &SessionManagerClientImpl::ArcInstanceStoppedReceived,
699             weak_ptr_factory_.GetWeakPtr()),
700         base::BindOnce(&SessionManagerClientImpl::SignalConnected,
701                        weak_ptr_factory_.GetWeakPtr()));
702   }
703 
704  private:
705   // Makes a method call to the session manager with no arguments and no
706   // response.
SimpleMethodCallToSessionManager(const std::string & method_name)707   void SimpleMethodCallToSessionManager(const std::string& method_name) {
708     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
709                                  method_name);
710     session_manager_proxy_->CallMethod(&method_call,
711                                        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
712                                        base::DoNothing());
713   }
714 
715   // Called when the method call without result is completed.
OnVoidMethod(VoidDBusMethodCallback callback,dbus::Response * response)716   void OnVoidMethod(VoidDBusMethodCallback callback, dbus::Response* response) {
717     std::move(callback).Run(response);
718   }
719 
720   // Non-blocking call to Session Manager to retrieve policy.
CallRetrievePolicy(const login_manager::PolicyDescriptor & descriptor,RetrievePolicyCallback callback)721   void CallRetrievePolicy(const login_manager::PolicyDescriptor& descriptor,
722                           RetrievePolicyCallback callback) {
723     dbus::MethodCall method_call(
724         login_manager::kSessionManagerInterface,
725         login_manager::kSessionManagerRetrievePolicyEx);
726     dbus::MessageWriter writer(&method_call);
727     const std::string descriptor_blob = descriptor.SerializeAsString();
728     // static_cast does not work due to signedness.
729     writer.AppendArrayOfBytes(
730         reinterpret_cast<const uint8_t*>(descriptor_blob.data()),
731         descriptor_blob.size());
732     session_manager_proxy_->CallMethodWithErrorResponse(
733         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
734         base::BindOnce(&SessionManagerClientImpl::OnRetrievePolicy,
735                        weak_ptr_factory_.GetWeakPtr(),
736                        descriptor.account_type(), std::move(callback)));
737   }
738 
739   // Blocking call to Session Manager to retrieve policy.
CallBlockingRetrievePolicy(const login_manager::PolicyDescriptor & descriptor,std::string * policy_out)740   RetrievePolicyResponseType CallBlockingRetrievePolicy(
741       const login_manager::PolicyDescriptor& descriptor,
742       std::string* policy_out) {
743     dbus::MethodCall method_call(
744         login_manager::kSessionManagerInterface,
745         login_manager::kSessionManagerRetrievePolicyEx);
746     dbus::MessageWriter writer(&method_call);
747     const std::string descriptor_blob = descriptor.SerializeAsString();
748     // static_cast does not work due to signedness.
749     writer.AppendArrayOfBytes(
750         reinterpret_cast<const uint8_t*>(descriptor_blob.data()),
751         descriptor_blob.size());
752     dbus::ScopedDBusError error;
753     std::unique_ptr<dbus::Response> response =
754         blocking_method_caller_->CallMethodAndBlockWithError(&method_call,
755                                                              &error);
756     RetrievePolicyResponseType result = RetrievePolicyResponseType::SUCCESS;
757     if (error.is_set() && error.name()) {
758       result = GetPolicyResponseTypeByError(error.name());
759     }
760     if (result == RetrievePolicyResponseType::SUCCESS) {
761       ExtractPolicyResponseString(descriptor.account_type(), response.get(),
762                                   policy_out);
763     } else {
764       policy_out->clear();
765     }
766     LogPolicyResponseUma(descriptor.account_type(), result);
767     return result;
768   }
769 
CallStorePolicy(const login_manager::PolicyDescriptor & descriptor,const std::string & policy_blob,VoidDBusMethodCallback callback)770   void CallStorePolicy(const login_manager::PolicyDescriptor& descriptor,
771                        const std::string& policy_blob,
772                        VoidDBusMethodCallback callback) {
773     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
774                                  login_manager::kSessionManagerStorePolicyEx);
775     dbus::MessageWriter writer(&method_call);
776     const std::string descriptor_blob = descriptor.SerializeAsString();
777     // static_cast does not work due to signedness.
778     writer.AppendArrayOfBytes(
779         reinterpret_cast<const uint8_t*>(descriptor_blob.data()),
780         descriptor_blob.size());
781     writer.AppendArrayOfBytes(
782         reinterpret_cast<const uint8_t*>(policy_blob.data()),
783         policy_blob.size());
784     // TODO(crbug/1155533) On grunt devices, initially storing device policy may
785     // take about 45s, which is longer than the default timeout for dbus calls.
786     // We need to investiage why this is happening. In the meantime, increase
787     // the timeout to make sure enrollment does not fail.
788     session_manager_proxy_->CallMethod(
789         &method_call, /*timeout_ms=*/90000,
790         base::BindOnce(&SessionManagerClientImpl::OnVoidMethod,
791                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
792   }
793 
794   // Called when kSessionManagerRetrieveActiveSessions method is complete.
OnRetrieveActiveSessions(const std::string & method_name,ActiveSessionsCallback callback,dbus::Response * response)795   void OnRetrieveActiveSessions(const std::string& method_name,
796                                 ActiveSessionsCallback callback,
797                                 dbus::Response* response) {
798     if (!response) {
799       std::move(callback).Run(base::nullopt);
800       return;
801     }
802 
803     dbus::MessageReader reader(response);
804     dbus::MessageReader array_reader(nullptr);
805     if (!reader.PopArray(&array_reader)) {
806       LOG(ERROR) << method_name
807                  << " response is incorrect: " << response->ToString();
808       std::move(callback).Run(base::nullopt);
809       return;
810     }
811 
812     ActiveSessionsMap sessions;
813     while (array_reader.HasMoreData()) {
814       dbus::MessageReader dict_entry_reader(nullptr);
815       std::string key;
816       std::string value;
817       if (!array_reader.PopDictEntry(&dict_entry_reader) ||
818           !dict_entry_reader.PopString(&key) ||
819           !dict_entry_reader.PopString(&value)) {
820         LOG(ERROR) << method_name
821                    << " response is incorrect: " << response->ToString();
822       } else {
823         sessions[key] = value;
824       }
825     }
826     std::move(callback).Run(std::move(sessions));
827   }
828 
OnLoginScreenStorageStore(LoginScreenStorageStoreCallback callback,dbus::Response * response)829   void OnLoginScreenStorageStore(LoginScreenStorageStoreCallback callback,
830                                  dbus::Response* response) {
831     std::move(callback).Run(base::nullopt);
832   }
833 
OnLoginScreenStorageRetrieve(LoginScreenStorageRetrieveCallback callback,dbus::Response * response)834   void OnLoginScreenStorageRetrieve(LoginScreenStorageRetrieveCallback callback,
835                                     dbus::Response* response) {
836     if (!response) {
837       std::move(callback).Run(base::nullopt /* data */,
838                               "LoginScreenStorageRetrieve() D-Bus method "
839                               "returned an empty response");
840       return;
841     }
842 
843     dbus::MessageReader reader(response);
844     base::ScopedFD result_fd;
845     uint64_t result_size;
846     if (!reader.PopUint64(&result_size) ||
847         !reader.PopFileDescriptor(&result_fd)) {
848       std::string error = "Invalid response: " + response->ToString();
849       std::move(callback).Run(base::nullopt /* data */, error);
850       return;
851     }
852     std::vector<uint8_t> result_data;
853     if (!ReadSecretFromSharedMemory(std::move(result_fd), result_size,
854                                     &result_data)) {
855       std::string error = "Couldn't read retrieved data from shared memory.";
856       std::move(callback).Run(base::nullopt /* data */, error);
857       return;
858     }
859     std::move(callback).Run(std::string(result_data.begin(), result_data.end()),
860                             base::nullopt /* error */);
861   }
862 
OnLoginScreenStorageListKeys(LoginScreenStorageListKeysCallback callback,dbus::Response * response)863   void OnLoginScreenStorageListKeys(LoginScreenStorageListKeysCallback callback,
864                                     dbus::Response* response) {
865     if (!response) {
866       // TODO(voit): Add more granular error handling: key is not found error vs
867       // general 'something went wrong' error.
868       std::move(callback).Run({} /* keys */,
869                               "LoginScreenStorageListKeys() D-Bus method "
870                               "returned an empty response");
871       return;
872     }
873     dbus::MessageReader reader(response);
874     std::vector<std::string> keys;
875     if (!reader.PopArrayOfStrings(&keys)) {
876       std::string error = "Invalid response: " + response->ToString();
877       std::move(callback).Run({} /* keys */, error);
878       return;
879     }
880     std::move(callback).Run(std::move(keys), base::nullopt /* error */);
881   }
882 
883   // Reads an array of policy data bytes data as std::string.
ExtractPolicyResponseString(login_manager::PolicyAccountType account_type,dbus::Response * response,std::string * extracted)884   void ExtractPolicyResponseString(
885       login_manager::PolicyAccountType account_type,
886       dbus::Response* response,
887       std::string* extracted) {
888     if (!response) {
889       LOG(ERROR) << "Failed to call RetrievePolicyEx for account type "
890                  << account_type;
891       return;
892     }
893     dbus::MessageReader reader(response);
894     const uint8_t* values = nullptr;
895     size_t length = 0;
896     if (!reader.PopArrayOfBytes(&values, &length)) {
897       LOG(ERROR) << "Invalid response: " << response->ToString();
898       return;
899     }
900     // static_cast does not work due to signedness.
901     extracted->assign(reinterpret_cast<const char*>(values), length);
902   }
903 
904   // Called when kSessionManagerRetrievePolicy or
905   // kSessionManagerRetrievePolicyForUser method is complete.
OnRetrievePolicy(login_manager::PolicyAccountType account_type,RetrievePolicyCallback callback,dbus::Response * response,dbus::ErrorResponse * error)906   void OnRetrievePolicy(login_manager::PolicyAccountType account_type,
907                         RetrievePolicyCallback callback,
908                         dbus::Response* response,
909                         dbus::ErrorResponse* error) {
910     if (!response) {
911       RetrievePolicyResponseType response_type =
912           GetPolicyResponseTypeByError(error ? error->GetErrorName() : "");
913       LogPolicyResponseUma(account_type, response_type);
914       std::move(callback).Run(response_type, std::string());
915       return;
916     }
917 
918     dbus::MessageReader reader(response);
919     std::string proto_blob;
920     ExtractPolicyResponseString(account_type, response, &proto_blob);
921     LogPolicyResponseUma(account_type, RetrievePolicyResponseType::SUCCESS);
922     std::move(callback).Run(RetrievePolicyResponseType::SUCCESS, proto_blob);
923   }
924 
925   // Called when the owner key set signal is received.
OwnerKeySetReceived(dbus::Signal * signal)926   void OwnerKeySetReceived(dbus::Signal* signal) {
927     dbus::MessageReader reader(signal);
928     std::string result_string;
929     if (!reader.PopString(&result_string)) {
930       LOG(ERROR) << "Invalid signal: " << signal->ToString();
931       return;
932     }
933     const bool success = base::StartsWith(result_string, "success",
934                                           base::CompareCase::INSENSITIVE_ASCII);
935     for (auto& observer : observers_)
936       observer.OwnerKeySet(success);
937   }
938 
939   // Called when the property change complete signal is received.
PropertyChangeCompleteReceived(dbus::Signal * signal)940   void PropertyChangeCompleteReceived(dbus::Signal* signal) {
941     dbus::MessageReader reader(signal);
942     std::string result_string;
943     if (!reader.PopString(&result_string)) {
944       LOG(ERROR) << "Invalid signal: " << signal->ToString();
945       return;
946     }
947     const bool success = base::StartsWith(result_string, "success",
948                                           base::CompareCase::INSENSITIVE_ASCII);
949     for (auto& observer : observers_)
950       observer.PropertyChangeComplete(success);
951   }
952 
ScreenIsLockedReceived(dbus::Signal * signal)953   void ScreenIsLockedReceived(dbus::Signal* signal) {
954     screen_is_locked_ = true;
955   }
956 
ScreenIsUnlockedReceived(dbus::Signal * signal)957   void ScreenIsUnlockedReceived(dbus::Signal* signal) {
958     screen_is_locked_ = false;
959   }
960 
ArcInstanceStoppedReceived(dbus::Signal * signal)961   void ArcInstanceStoppedReceived(dbus::Signal* signal) {
962     for (auto& observer : observers_)
963       observer.ArcInstanceStopped();
964   }
965 
966   // Called when the object is connected to the signal.
SignalConnected(const std::string & interface_name,const std::string & signal_name,bool success)967   void SignalConnected(const std::string& interface_name,
968                        const std::string& signal_name,
969                        bool success) {
970     LOG_IF(ERROR, !success) << "Failed to connect to " << signal_name;
971   }
972 
973   // Called when kSessionManagerGetServerBackedStateKeys method is complete.
OnGetServerBackedStateKeys(StateKeysCallback callback,dbus::Response * response)974   void OnGetServerBackedStateKeys(StateKeysCallback callback,
975                                   dbus::Response* response) {
976     std::vector<std::string> state_keys;
977     if (response) {
978       dbus::MessageReader reader(response);
979       dbus::MessageReader array_reader(nullptr);
980 
981       if (!reader.PopArray(&array_reader)) {
982         LOG(ERROR) << "Bad response: " << response->ToString();
983       } else {
984         while (array_reader.HasMoreData()) {
985           const uint8_t* data = nullptr;
986           size_t size = 0;
987           if (!array_reader.PopArrayOfBytes(&data, &size)) {
988             LOG(ERROR) << "Bad response: " << response->ToString();
989             state_keys.clear();
990             break;
991           }
992           state_keys.emplace_back(reinterpret_cast<const char*>(data), size);
993         }
994       }
995     }
996 
997     std::move(callback).Run(state_keys);
998   }
999 
OnGetArcStartTime(DBusMethodCallback<base::TimeTicks> callback,dbus::Response * response)1000   void OnGetArcStartTime(DBusMethodCallback<base::TimeTicks> callback,
1001                          dbus::Response* response) {
1002     if (!response) {
1003       std::move(callback).Run(base::nullopt);
1004       return;
1005     }
1006 
1007     dbus::MessageReader reader(response);
1008     int64_t ticks = 0;
1009     if (!reader.PopInt64(&ticks)) {
1010       LOG(ERROR) << "Invalid response: " << response->ToString();
1011       std::move(callback).Run(base::nullopt);
1012       return;
1013     }
1014 
1015     std::move(callback).Run(base::TimeTicks::FromInternalValue(ticks));
1016   }
1017 
OnEnableAdbSideload(EnableAdbSideloadCallback callback,dbus::Response * response,dbus::ErrorResponse * error)1018   void OnEnableAdbSideload(EnableAdbSideloadCallback callback,
1019                            dbus::Response* response,
1020                            dbus::ErrorResponse* error) {
1021     if (!response) {
1022       LOG(ERROR) << "Failed to call EnableAdbSideload: "
1023                  << (error ? error->ToString() : "(null)");
1024       if (error && error->GetErrorName() == DBUS_ERROR_NOT_SUPPORTED) {
1025         std::move(callback).Run(AdbSideloadResponseCode::NEED_POWERWASH);
1026       } else {
1027         std::move(callback).Run(AdbSideloadResponseCode::FAILED);
1028       }
1029       return;
1030     }
1031 
1032     bool succeeded;
1033     dbus::MessageReader reader(response);
1034     if (!reader.PopBool(&succeeded)) {
1035       LOG(ERROR) << "Failed to enable sideloading";
1036       std::move(callback).Run(AdbSideloadResponseCode::FAILED);
1037       return;
1038     }
1039     std::move(callback).Run(AdbSideloadResponseCode::SUCCESS);
1040   }
1041 
OnQueryAdbSideload(QueryAdbSideloadCallback callback,dbus::Response * response,dbus::ErrorResponse * error)1042   void OnQueryAdbSideload(QueryAdbSideloadCallback callback,
1043                           dbus::Response* response,
1044                           dbus::ErrorResponse* error) {
1045     if (!response) {
1046       LOG(ERROR) << "Failed to call QueryAdbSideload: "
1047                  << (error ? error->ToString() : "(null)");
1048       if (error && error->GetErrorName() == DBUS_ERROR_NOT_SUPPORTED) {
1049         std::move(callback).Run(AdbSideloadResponseCode::NEED_POWERWASH, false);
1050       } else {
1051         std::move(callback).Run(AdbSideloadResponseCode::FAILED, false);
1052       }
1053       return;
1054     }
1055 
1056     bool is_allowed;
1057     dbus::MessageReader reader(response);
1058     if (!reader.PopBool(&is_allowed)) {
1059       LOG(ERROR) << "Failed to interpret the response";
1060       std::move(callback).Run(AdbSideloadResponseCode::FAILED, false);
1061       return;
1062     }
1063     std::move(callback).Run(AdbSideloadResponseCode::SUCCESS, is_allowed);
1064   }
1065 
1066   dbus::ObjectProxy* session_manager_proxy_ = nullptr;
1067   std::unique_ptr<BlockingMethodCaller> blocking_method_caller_;
1068   base::ObserverList<Observer>::Unchecked observers_{
1069       SessionManagerClient::kObserverListPolicy};
1070 
1071   // Most recent screen-lock state received from session_manager.
1072   bool screen_is_locked_ = false;
1073 
1074   // Note: This should remain the last member so it'll be destroyed and
1075   // invalidate its weak pointers before any other members are destroyed.
1076   base::WeakPtrFactory<SessionManagerClientImpl> weak_ptr_factory_{this};
1077 
1078   DISALLOW_COPY_AND_ASSIGN(SessionManagerClientImpl);
1079 };
1080 
SessionManagerClient()1081 SessionManagerClient::SessionManagerClient() {
1082   DCHECK(!g_instance);
1083   g_instance = this;
1084 }
1085 
~SessionManagerClient()1086 SessionManagerClient::~SessionManagerClient() {
1087   DCHECK_EQ(this, g_instance);
1088   g_instance = nullptr;
1089 }
1090 
1091 // static
Initialize(dbus::Bus * bus)1092 void SessionManagerClient::Initialize(dbus::Bus* bus) {
1093   DCHECK(bus);
1094   (new SessionManagerClientImpl)->Init(bus);
1095 }
1096 
1097 // static
InitializeFake()1098 void SessionManagerClient::InitializeFake() {
1099   // Do not create a new fake if it was initialized early in a browser test (for
1100   // early setup calls dependent on SessionManagerClient).
1101   if (!FakeSessionManagerClient::Get()) {
1102     new FakeSessionManagerClient(
1103         FakeSessionManagerClient::PolicyStorageType::kOnDisk);
1104   }
1105 }
1106 
1107 // static
InitializeFakeInMemory()1108 void SessionManagerClient::InitializeFakeInMemory() {
1109   if (!FakeSessionManagerClient::Get()) {
1110     new FakeSessionManagerClient(
1111         FakeSessionManagerClient::PolicyStorageType::kInMemory);
1112   }
1113 }
1114 
1115 // static
Shutdown()1116 void SessionManagerClient::Shutdown() {
1117   DCHECK(g_instance);
1118   delete g_instance;
1119 }
1120 
1121 // static
Get()1122 SessionManagerClient* SessionManagerClient::Get() {
1123   return g_instance;
1124 }
1125 
1126 }  // namespace chromeos
1127