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 "chrome/browser/chromeos/login/tpm_password_fetcher.h"
6
7#include "base/bind.h"
8#include "base/compiler_specific.h"
9#include "base/message_loop/message_loop.h"
10#include "chromeos/dbus/cryptohome_client.h"
11#include "chromeos/dbus/dbus_thread_manager.h"
12
13namespace chromeos {
14
15namespace {
16
17// Interval between TPM password checks.
18const int kTpmCheckIntervalMs = 500;
19
20}  // namespace
21
22TpmPasswordFetcher::TpmPasswordFetcher(TpmPasswordFetcherDelegate* delegate)
23    : weak_factory_(this),
24      delegate_(delegate) {
25  DCHECK(delegate_);
26}
27
28TpmPasswordFetcher::~TpmPasswordFetcher() {
29}
30
31void TpmPasswordFetcher::Fetch() {
32  // Since this method is also called directly.
33  weak_factory_.InvalidateWeakPtrs();
34
35  DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsReady(
36      base::Bind(&TpmPasswordFetcher::OnTpmIsReady,
37                 weak_factory_.GetWeakPtr()));
38}
39
40void TpmPasswordFetcher::OnTpmIsReady(DBusMethodCallStatus call_status,
41                                      bool tpm_is_ready) {
42  if (call_status == DBUS_METHOD_CALL_SUCCESS && tpm_is_ready) {
43    DBusThreadManager::Get()->GetCryptohomeClient()->TpmGetPassword(
44        base::Bind(&TpmPasswordFetcher::OnTpmGetPassword,
45                   weak_factory_.GetWeakPtr()));
46  } else {
47    // Password hasn't been acquired, reschedule fetch.
48    RescheduleFetch();
49  }
50}
51
52void TpmPasswordFetcher::OnTpmGetPassword(DBusMethodCallStatus call_status,
53                                          const std::string& password) {
54  if (call_status == DBUS_METHOD_CALL_SUCCESS) {
55    if (password.empty()) {
56      // For a fresh OOBE flow TPM is uninitialized,
57      // ownership process is started at the EULA screen,
58      // password is cleared after EULA is accepted.
59      LOG(ERROR) << "TPM returned an empty password.";
60    }
61    delegate_->OnPasswordFetched(password);
62  } else {
63    // Password hasn't been acquired, reschedule fetch.
64    RescheduleFetch();
65  }
66}
67
68void TpmPasswordFetcher::RescheduleFetch() {
69  base::MessageLoop::current()->PostDelayedTask(
70      FROM_HERE,
71      base::Bind(&TpmPasswordFetcher::Fetch, weak_factory_.GetWeakPtr()),
72      base::TimeDelta::FromMilliseconds(kTpmCheckIntervalMs));
73}
74
75}  // namespace chromeos
76