blob: 3fb9f0307d3f0574383f6cbf49cadbfd8e4cb960 [file] [log] [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/arc/auth/arc_auth_context.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/logging.h"
#include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
#include "chrome/browser/ash/arc/arc_support_host.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "components/signin/public/identity_manager/access_token_fetcher.h"
#include "content/public/common/url_constants.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
// Enable VLOG level 1.
#undef ENABLED_VLOG_LEVEL
#define ENABLED_VLOG_LEVEL 1
namespace arc {
namespace {
constexpr base::TimeDelta kRefreshTokenTimeout = base::Seconds(10);
} // namespace
ArcAuthContext::ArcAuthContext(Profile* profile,
const CoreAccountId& account_id)
: account_id_(account_id),
identity_manager_(IdentityManagerFactory::GetForProfile(profile)) {
DCHECK(identity_manager_->HasAccountWithRefreshToken(account_id));
}
ArcAuthContext::~ArcAuthContext() {
identity_manager_->RemoveObserver(this);
}
void ArcAuthContext::Prepare(PrepareCallback callback) {
if (context_prepared_) {
std::move(callback).Run(true);
return;
}
callback_ = std::move(callback);
identity_manager_->RemoveObserver(this);
refresh_token_timeout_.Stop();
if (!identity_manager_->HasAccountWithRefreshToken(account_id_)) {
identity_manager_->AddObserver(this);
VLOG(1) << "Waiting for refresh token for account " << account_id_;
refresh_token_timeout_.Start(FROM_HERE, kRefreshTokenTimeout, this,
&ArcAuthContext::OnRefreshTokenTimeout);
return;
}
// Refresh token is already available.
std::move(callback_).Run(true);
}
std::unique_ptr<signin::AccessTokenFetcher>
ArcAuthContext::CreateAccessTokenFetcher(
const std::string& consumer_name,
const signin::ScopeSet& scopes,
signin::AccessTokenFetcher::TokenCallback callback) {
DCHECK(identity_manager_->HasAccountWithRefreshToken(account_id_));
return identity_manager_->CreateAccessTokenFetcherForAccount(
account_id_, consumer_name, scopes, std::move(callback),
signin::AccessTokenFetcher::Mode::kImmediate);
}
void ArcAuthContext::RemoveAccessTokenFromCache(
const signin::ScopeSet& scopes,
const std::string& access_token) {
identity_manager_->RemoveAccessTokenFromCache(account_id_, scopes,
access_token);
}
void ArcAuthContext::OnRefreshTokenUpdatedForAccount(
const CoreAccountInfo& account_info) {
// There is no need to check |is_valid| here. It is intended to avoid
// adding the ability to query the persistent error state to the
// IdentityManager API, which is irrelevant for this case.
if (account_info.account_id != account_id_)
return;
OnRefreshTokensLoaded();
}
void ArcAuthContext::OnRefreshTokensLoaded() {
identity_manager_->RemoveObserver(this);
VLOG(1) << "Refresh token for account " << account_id_ << " loaded.";
refresh_token_timeout_.Stop();
std::move(callback_).Run(true);
}
void ArcAuthContext::OnRefreshTokenTimeout() {
LOG(WARNING) << "Failed to wait for refresh token.";
identity_manager_->RemoveObserver(this);
std::move(callback_).Run(false);
}
} // namespace arc