1 // Copyright 2015 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 "chrome/browser/chromeos/login/signin/token_handle_util.h"
7 #include "base/memory/weak_ptr.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "base/values.h"
10 #include "chrome/browser/chromeos/profiles/profile_helper.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "components/user_manager/user_id.h"
13 #include "components/user_manager/user_manager.h"
14 #include "google_apis/gaia/gaia_oauth_client.h"
18 const char kTokenHandlePref
[] = "PasswordTokenHandle";
19 const char kTokenHandleStatusPref
[] = "TokenHandleStatus";
21 const char kHandleStatusValid
[] = "valid";
22 const char kHandleStatusInvalid
[] = "invalid";
23 const char* kDefaultHandleStatus
= kHandleStatusValid
;
25 static const int kMaxRetries
= 3;
29 TokenHandleUtil::TokenHandleUtil(user_manager::UserManager
* user_manager
)
30 : user_manager_(user_manager
), weak_factory_(this) {
33 TokenHandleUtil::~TokenHandleUtil() {
34 weak_factory_
.InvalidateWeakPtrs();
38 bool TokenHandleUtil::HasToken(const user_manager::UserID
& user_id
) {
39 const base::DictionaryValue
* dict
= nullptr;
41 if (!user_manager_
->FindKnownUserPrefs(user_id
, &dict
))
43 if (!dict
->GetString(kTokenHandlePref
, &token
))
45 return !token
.empty();
48 bool TokenHandleUtil::ShouldObtainHandle(const user_manager::UserID
& user_id
) {
49 const base::DictionaryValue
* dict
= nullptr;
51 if (!user_manager_
->FindKnownUserPrefs(user_id
, &dict
))
53 if (!dict
->GetString(kTokenHandlePref
, &token
))
57 std::string
status(kDefaultHandleStatus
);
58 dict
->GetString(kTokenHandleStatusPref
, &status
);
59 return kHandleStatusInvalid
== status
;
62 void TokenHandleUtil::DeleteHandle(const user_manager::UserID
& user_id
) {
63 const base::DictionaryValue
* dict
= nullptr;
64 if (!user_manager_
->FindKnownUserPrefs(user_id
, &dict
))
66 scoped_ptr
<base::DictionaryValue
> dict_copy(dict
->DeepCopy());
67 dict_copy
->Remove(kTokenHandlePref
, nullptr);
68 dict_copy
->Remove(kTokenHandleStatusPref
, nullptr);
69 user_manager_
->UpdateKnownUserPrefs(user_id
, *dict_copy
.get(),
70 /* replace values */ true);
73 void TokenHandleUtil::MarkHandleInvalid(const user_manager::UserID
& user_id
) {
74 user_manager_
->SetKnownUserStringPref(user_id
, kTokenHandleStatusPref
,
75 kHandleStatusInvalid
);
78 void TokenHandleUtil::CheckToken(const user_manager::UserID
& user_id
,
79 const TokenValidationCallback
& callback
) {
80 const base::DictionaryValue
* dict
= nullptr;
82 if (!user_manager_
->FindKnownUserPrefs(user_id
, &dict
)) {
83 callback
.Run(user_id
, UNKNOWN
);
86 if (!dict
->GetString(kTokenHandlePref
, &token
)) {
87 callback
.Run(user_id
, UNKNOWN
);
91 if (!gaia_client_
.get()) {
92 auto request_context
=
93 chromeos::ProfileHelper::Get()->GetSigninProfile()->GetRequestContext();
94 gaia_client_
.reset(new gaia::GaiaOAuthClient(request_context
));
97 validation_delegates_
.set(
98 token
, scoped_ptr
<TokenDelegate
>(new TokenDelegate(
99 weak_factory_
.GetWeakPtr(), user_id
, token
, callback
)));
100 gaia_client_
->GetTokenHandleInfo(token
, kMaxRetries
,
101 validation_delegates_
.get(token
));
104 void TokenHandleUtil::StoreTokenHandle(const user_manager::UserID
& user_id
,
105 const std::string
& handle
) {
106 user_manager_
->SetKnownUserStringPref(user_id
, kTokenHandlePref
, handle
);
107 user_manager_
->SetKnownUserStringPref(user_id
, kTokenHandleStatusPref
,
111 void TokenHandleUtil::OnValidationComplete(const std::string
& token
) {
112 validation_delegates_
.erase(token
);
115 void TokenHandleUtil::OnObtainTokenComplete(
116 const user_manager::UserID
& user_id
) {
117 obtain_delegates_
.erase(user_id
);
120 TokenHandleUtil::TokenDelegate::TokenDelegate(
121 const base::WeakPtr
<TokenHandleUtil
>& owner
,
122 const user_manager::UserID
& user_id
,
123 const std::string
& token
,
124 const TokenValidationCallback
& callback
)
128 tokeninfo_response_start_time_(base::TimeTicks::Now()),
129 callback_(callback
) {
132 TokenHandleUtil::TokenDelegate::~TokenDelegate() {
135 void TokenHandleUtil::TokenDelegate::OnOAuthError() {
136 callback_
.Run(user_id_
, INVALID
);
140 // Warning: NotifyDone() deletes |this|
141 void TokenHandleUtil::TokenDelegate::NotifyDone() {
143 owner_
->OnValidationComplete(token_
);
146 void TokenHandleUtil::TokenDelegate::OnNetworkError(int response_code
) {
147 callback_
.Run(user_id_
, UNKNOWN
);
151 void TokenHandleUtil::TokenDelegate::OnGetTokenInfoResponse(
152 scoped_ptr
<base::DictionaryValue
> token_info
) {
153 TokenHandleStatus outcome
= UNKNOWN
;
154 if (!token_info
->HasKey("error")) {
156 if (token_info
->GetInteger("expires_in", &expires_in
))
157 outcome
= (expires_in
< 0) ? INVALID
: VALID
;
160 const base::TimeDelta duration
=
161 base::TimeTicks::Now() - tokeninfo_response_start_time_
;
162 UMA_HISTOGRAM_TIMES("Login.TokenCheckResponseTime", duration
);
163 callback_
.Run(user_id_
, outcome
);