Commit 4c06b60f authored by Yue Li's avatar Yue Li Committed by Commit Bot

Quick Answers: Add browser client

Add the browser client to get Access token.

Bug: b/150034512
Test: Manual Test
Change-Id: Ic3f87ee4299779797005d56daa411b122750bea7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2429528
Commit-Queue: Yue Li <updowndota@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Auto-Submit: Yue Li <updowndota@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811079}
parent adf019b9
......@@ -241,6 +241,8 @@ component("cpp") {
"presentation_time_recorder.h",
"privacy_screen_dlp_helper.cc",
"privacy_screen_dlp_helper.h",
"quick_answers/controller/quick_answers_browser_client.cc",
"quick_answers/controller/quick_answers_browser_client.h",
"quick_answers/controller/quick_answers_controller.cc",
"quick_answers/controller/quick_answers_controller.h",
"rounded_corner_decorator.cc",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/public/cpp/quick_answers/controller/quick_answers_browser_client.h"
#include "base/check_op.h"
namespace ash {
namespace {
QuickAnswersBrowserClient* g_instance = nullptr;
}
QuickAnswersBrowserClient::QuickAnswersBrowserClient() {
DCHECK_EQ(nullptr, g_instance);
g_instance = this;
}
QuickAnswersBrowserClient::~QuickAnswersBrowserClient() {
DCHECK_EQ(this, g_instance);
g_instance = nullptr;
}
QuickAnswersBrowserClient* QuickAnswersBrowserClient::Get() {
return g_instance;
}
} // namespace ash
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_PUBLIC_CPP_QUICK_ANSWERS_CONTROLLER_QUICK_ANSWERS_BROWSER_CLIENT_H_
#define ASH_PUBLIC_CPP_QUICK_ANSWERS_CONTROLLER_QUICK_ANSWERS_BROWSER_CLIENT_H_
#include <string>
#include "ash/public/cpp/ash_public_export.h"
#include "base/callback_forward.h"
namespace ash {
// A client class which provides browser access to Quick Answers.
class ASH_PUBLIC_EXPORT QuickAnswersBrowserClient {
public:
using GetAccessTokenCallback =
base::OnceCallback<void(const std::string& access_token)>;
QuickAnswersBrowserClient();
virtual ~QuickAnswersBrowserClient();
// Get the instance of |QuickAnswersBrowserClient|.
static QuickAnswersBrowserClient* Get();
// Request for the access token associated with the active user's profile.
// Request is handled asynchronously if the token is not available.
// AccessTokenCallbacks are invoked as soon as the token if fetched.
// If the token is available, AccessTokenCallbacks are invoked
// synchronously before RequestAccessToken() returns.
virtual void RequestAccessToken(GetAccessTokenCallback callback) = 0;
};
} // namespace ash
#endif // ASH_PUBLIC_CPP_QUICK_ANSWERS_CONTROLLER_QUICK_ANSWERS_BROWSER_CLIENT_H_
......@@ -1996,6 +1996,8 @@ static_library("ui") {
"ash/network/network_state_notifier.h",
"ash/network/tether_notification_presenter.cc",
"ash/network/tether_notification_presenter.h",
"ash/quick_answers/quick_answers_browser_client_impl.cc",
"ash/quick_answers/quick_answers_browser_client_impl.h",
"ash/screen_orientation_delegate_chromeos.cc",
"ash/screen_orientation_delegate_chromeos.h",
"ash/session_controller_client_impl.cc",
......
......@@ -40,6 +40,7 @@
#include "chrome/browser/ui/ash/network/mobile_data_notifications.h"
#include "chrome/browser/ui/ash/network/network_connect_delegate_chromeos.h"
#include "chrome/browser/ui/ash/network/network_portal_notification_controller.h"
#include "chrome/browser/ui/ash/quick_answers/quick_answers_browser_client_impl.h"
#include "chrome/browser/ui/ash/screen_orientation_delegate_chromeos.h"
#include "chrome/browser/ui/ash/session_controller_client_impl.h"
#include "chrome/browser/ui/ash/system_tray_client.h"
......@@ -125,6 +126,11 @@ void ChromeBrowserMainExtraPartsAsh::PreProfileInit() {
if (chromeos::features::IsAmbientModeEnabled())
ambient_client_ = std::make_unique<AmbientClientImpl>();
if (chromeos::features::IsQuickAnswersEnabled()) {
quick_answers_browser_client_ =
std::make_unique<QuickAnswersBrowserClientImpl>();
}
media_notification_provider_ =
std::make_unique<MediaNotificationProviderImpl>();
ash::MediaNotificationProvider::Set(media_notification_provider_.get());
......
......@@ -33,6 +33,7 @@ class MediaClientImpl;
class MobileDataNotifications;
class NetworkConnectDelegateChromeOS;
class NightLightClient;
class QuickAnswersBrowserClientImpl;
class ScreenOrientationDelegateChromeos;
class SessionControllerClientImpl;
class SystemTrayClient;
......@@ -112,6 +113,7 @@ class ChromeBrowserMainExtraPartsAsh : public ChromeBrowserMainExtraParts {
std::unique_ptr<MobileDataNotifications> mobile_data_notifications_;
std::unique_ptr<NightLightClient> night_light_client_;
std::unique_ptr<AmbientClientImpl> ambient_client_;
std::unique_ptr<QuickAnswersBrowserClientImpl> quick_answers_browser_client_;
DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainExtraPartsAsh);
};
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/ash/quick_answers/quick_answers_browser_client_impl.h"
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/time/time.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "components/account_id/account_id.h"
#include "components/signin/public/identity_manager/access_token_fetcher.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "components/signin/public/identity_manager/consent_level.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/scope_set.h"
namespace {
constexpr char kCloudTranslationScope[] =
"https://www.googleapis.com/auth/cloud-translation";
constexpr base::TimeDelta kMinTokenRefreshDelay =
base::TimeDelta::FromMilliseconds(1000);
constexpr base::TimeDelta kMaxTokenRefreshDelay =
base::TimeDelta::FromMilliseconds(60 * 1000);
} // namespace
QuickAnswersBrowserClientImpl::QuickAnswersBrowserClientImpl() = default;
QuickAnswersBrowserClientImpl::~QuickAnswersBrowserClientImpl() = default;
void QuickAnswersBrowserClientImpl::RequestAccessToken(
AccessTokenCallback callback) {
if (!access_token_.empty()) {
// Return the token if there is enough time to use the access token when
// requested.
if (expiration_time_ - base::Time::Now() > token_usage_time_buffer_) {
std::move(callback).Run(access_token_);
return;
}
access_token_.clear();
expiration_time_ = base::Time::Now();
}
callbacks_.emplace_back(std::move(callback));
// There is already pending request.
if (access_token_fetcher_)
return;
RefreshAccessToken();
}
void QuickAnswersBrowserClientImpl::RefreshAccessToken() {
auto* profile = ProfileManager::GetActiveUserProfile();
DCHECK(profile);
signin::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(profile);
DCHECK(identity_manager);
CoreAccountInfo account_info = identity_manager->GetPrimaryAccountInfo(
signin::ConsentLevel::kNotRequired);
const signin::ScopeSet scopes{kCloudTranslationScope};
DCHECK(!access_token_fetcher_);
access_token_fetcher_ = identity_manager->CreateAccessTokenFetcherForAccount(
account_info.account_id, /*oauth_consumer_name=*/"cros_quick_answers",
scopes,
base::BindOnce(&QuickAnswersBrowserClientImpl::OnAccessTokenRefreshed,
weak_factory_.GetWeakPtr()),
signin::AccessTokenFetcher::Mode::kImmediate);
}
void QuickAnswersBrowserClientImpl::OnAccessTokenRefreshed(
GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info) {
// It's safe to delete AccessTokenFetcher from inside its own callback.
access_token_fetcher_.reset();
if (error.state() != GoogleServiceAuthError::NONE) {
LOG(ERROR) << "Failed to retrieve token, error: " << error.ToString();
RetryRefreshAccessToken();
return;
}
VLOG(1) << "Access token fetched.";
access_token_ = access_token_info.token;
expiration_time_ = access_token_info.expiration_time;
NotifyAccessTokenRefreshed();
}
void QuickAnswersBrowserClientImpl::RetryRefreshAccessToken() {
base::TimeDelta backoff_delay =
std::min(kMinTokenRefreshDelay *
(1 << (token_refresh_error_backoff_factor_ - 1)),
kMaxTokenRefreshDelay) +
base::RandDouble() * kMinTokenRefreshDelay;
if (backoff_delay < kMaxTokenRefreshDelay)
++token_refresh_error_backoff_factor_;
token_refresh_timer_.Start(
FROM_HERE, backoff_delay,
base::BindOnce(&QuickAnswersBrowserClientImpl::RefreshAccessToken,
weak_factory_.GetWeakPtr()));
}
void QuickAnswersBrowserClientImpl::NotifyAccessTokenRefreshed() {
std::vector<AccessTokenCallback> callbacks;
callbacks.swap(callbacks_);
for (auto& callback : callbacks)
std::move(callback).Run(access_token_);
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_ASH_QUICK_ANSWERS_QUICK_ANSWERS_BROWSER_CLIENT_IMPL_H_
#define CHROME_BROWSER_UI_ASH_QUICK_ANSWERS_QUICK_ANSWERS_BROWSER_CLIENT_IMPL_H_
#include <string>
#include <vector>
#include "ash/public/cpp/quick_answers/controller/quick_answers_browser_client.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
class GoogleServiceAuthError;
namespace signin {
class AccessTokenFetcher;
struct AccessTokenInfo;
} // namespace signin
// A client class which provides browser access to quick answers.
class QuickAnswersBrowserClientImpl : public ash::QuickAnswersBrowserClient {
public:
using AccessTokenCallback =
base::OnceCallback<void(const std::string& access_token)>;
QuickAnswersBrowserClientImpl();
QuickAnswersBrowserClientImpl(const QuickAnswersBrowserClientImpl&) = delete;
QuickAnswersBrowserClientImpl& operator=(
const QuickAnswersBrowserClientImpl&) = delete;
~QuickAnswersBrowserClientImpl() override;
// ash::QuickAnswersBrowserClient:
void RequestAccessToken(AccessTokenCallback callback) override;
private:
void RefreshAccessToken();
void OnAccessTokenRefreshed(GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info);
void RetryRefreshAccessToken();
void NotifyAccessTokenRefreshed();
std::string access_token_;
std::unique_ptr<signin::AccessTokenFetcher> access_token_fetcher_;
// The expiration time of the |access_token_|.
base::Time expiration_time_;
// The buffer time to use the access token.
base::TimeDelta token_usage_time_buffer_ = base::TimeDelta::FromMinutes(1);
base::OneShotTimer token_refresh_timer_;
int token_refresh_error_backoff_factor_ = 1;
std::vector<AccessTokenCallback> callbacks_;
base::WeakPtrFactory<QuickAnswersBrowserClientImpl> weak_factory_{this};
};
#endif // CHROME_BROWSER_UI_ASH_QUICK_ANSWERS_QUICK_ANSWERS_BROWSER_CLIENT_IMPL_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment