Commit 6844031c authored by Mathias Carlen's avatar Mathias Carlen Committed by Commit Bot

[Autofill Assistant] Provide token fetcher to service.

Before this patch, the AA extension API was only able to send
unauthenticated requests to the backend (i.e. explicitly disabling
autofill-assistant-auth and providing API keys etc).

This patch introduces an token access fetcher so that extensions will be
able to send requests on behalf of a signed in (sync) user.

For simplicity, this patch uses the primary account by default. That
logic will be relaxed later if needed.

Bug: b/143736397
Change-Id: I89019abf7bc94aeeb2bb152ed10a0e62b0a9d442
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2089690Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarSandro Maggi <sandromaggi@google.com>
Commit-Queue: Mathias Carlen <mcarlen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748167}
parent 7b8f8ddd
...@@ -930,6 +930,8 @@ jumbo_static_library("extensions") { ...@@ -930,6 +930,8 @@ jumbo_static_library("extensions") {
sources += [ sources += [
"api/autofill_assistant_private/autofill_assistant_private_api.cc", "api/autofill_assistant_private/autofill_assistant_private_api.cc",
"api/autofill_assistant_private/autofill_assistant_private_api.h", "api/autofill_assistant_private/autofill_assistant_private_api.h",
"api/autofill_assistant_private/extension_access_token_fetcher.cc",
"api/autofill_assistant_private/extension_access_token_fetcher.h",
] ]
deps += [ "//components/autofill_assistant/browser" ] deps += [ "//components/autofill_assistant/browser" ]
} }
......
...@@ -11,7 +11,10 @@ ...@@ -11,7 +11,10 @@
#include "base/time/default_tick_clock.h" #include "base/time/default_tick_clock.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h" #include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.h"
#include "chrome/browser/extensions/chrome_extension_function_details.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/field_types.h"
#include "extensions/browser/event_router_factory.h" #include "extensions/browser/event_router_factory.h"
...@@ -233,9 +236,15 @@ void BrowserContextKeyedAPIFactory< ...@@ -233,9 +236,15 @@ void BrowserContextKeyedAPIFactory<
AutofillAssistantPrivateAPI::AutofillAssistantPrivateAPI( AutofillAssistantPrivateAPI::AutofillAssistantPrivateAPI(
content::BrowserContext* context) content::BrowserContext* context)
: browser_context_(context) {} : browser_context_(context) {
access_token_fetcher_ = std::make_unique<ExtensionAccessTokenFetcher>(
IdentityManagerFactory::GetForProfile(
Profile::FromBrowserContext(browser_context_)));
}
AutofillAssistantPrivateAPI::~AutofillAssistantPrivateAPI() = default; AutofillAssistantPrivateAPI::~AutofillAssistantPrivateAPI() {
access_token_fetcher_.reset();
}
void AutofillAssistantPrivateAPI::CreateAutofillAssistantController( void AutofillAssistantPrivateAPI::CreateAutofillAssistantController(
content::WebContents* web_contents) { content::WebContents* web_contents) {
...@@ -312,7 +321,7 @@ std::string AutofillAssistantPrivateAPI::GetAccountEmailAddress() { ...@@ -312,7 +321,7 @@ std::string AutofillAssistantPrivateAPI::GetAccountEmailAddress() {
autofill_assistant::AccessTokenFetcher* autofill_assistant::AccessTokenFetcher*
AutofillAssistantPrivateAPI::GetAccessTokenFetcher() { AutofillAssistantPrivateAPI::GetAccessTokenFetcher() {
return nullptr; return access_token_fetcher_.get();
} }
autofill::PersonalDataManager* autofill::PersonalDataManager*
...@@ -327,7 +336,7 @@ AutofillAssistantPrivateAPI::GetWebsiteLoginFetcher() { ...@@ -327,7 +336,7 @@ AutofillAssistantPrivateAPI::GetWebsiteLoginFetcher() {
} }
std::string AutofillAssistantPrivateAPI::GetServerUrl() { std::string AutofillAssistantPrivateAPI::GetServerUrl() {
// TODO(crbug.com/1015753): Consider the autofill-assistant-url for endpoing // TODO(crbug.com/1015753): Consider the autofill-assistant-url for endpoint
// overrides and share the kDefaultAutofillAssistantServerUrl to expose it // overrides and share the kDefaultAutofillAssistantServerUrl to expose it
// here. // here.
return "https://automate-pa.googleapis.com"; return "https://automate-pa.googleapis.com";
......
...@@ -232,6 +232,7 @@ class AutofillAssistantPrivateAPI : public BrowserContextKeyedAPI, ...@@ -232,6 +232,7 @@ class AutofillAssistantPrivateAPI : public BrowserContextKeyedAPI,
std::unique_ptr<AutofillAssistantPrivateEventRouter> event_router; std::unique_ptr<AutofillAssistantPrivateEventRouter> event_router;
}; };
std::unique_ptr<ActiveAutofillAssistant> active_autofill_assistant_; std::unique_ptr<ActiveAutofillAssistant> active_autofill_assistant_;
std::unique_ptr<autofill_assistant::AccessTokenFetcher> access_token_fetcher_;
}; };
} // namespace extensions } // namespace extensions
......
// 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/extensions/api/autofill_assistant_private/extension_access_token_fetcher.h"
#include "base/callback.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/scope_set.h"
#include "google_apis/gaia/gaia_constants.h"
namespace extensions {
ExtensionAccessTokenFetcher::ExtensionAccessTokenFetcher(
signin::IdentityManager* identity_manager)
: identity_manager_(identity_manager) {}
ExtensionAccessTokenFetcher::~ExtensionAccessTokenFetcher() = default;
void ExtensionAccessTokenFetcher::FetchAccessToken(
base::OnceCallback<void(bool, const std::string&)> callback) {
// TODO(b/143736397): Use a more flexible logic to pick this account.
auto account_info = identity_manager_->GetPrimaryAccountInfo();
callback_ = std::move(callback);
signin::ScopeSet scopes;
scopes.insert(GaiaConstants::kGoogleUserInfoProfile);
auto mode = signin::AccessTokenFetcher::Mode::kImmediate;
access_token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount(
account_info.account_id,
/*consumer_name=*/"AccessTokenFetcher", scopes,
base::BindOnce(&ExtensionAccessTokenFetcher::OnCompleted,
// It is safe to use base::Unretained as
// |this| owns |access_token_fetcher_|.
base::Unretained(this)),
mode);
}
void ExtensionAccessTokenFetcher::InvalidateAccessToken(
const std::string& access_token) {
// TODO(b/143736397) Implement this by providing the data required for
// RemoveAccessTokenFromCache?
}
void ExtensionAccessTokenFetcher::OnCompleted(
GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info) {
access_token_fetcher_.reset();
if (!callback_)
return;
if (error.state() == GoogleServiceAuthError::NONE) {
std::move(callback_).Run(true, access_token_info.token);
} else {
VLOG(2) << "Access token fetching failed with error state " << error.state()
<< " and message " << error.ToString();
std::move(callback_).Run(false, "");
}
}
} // namespace extensions
// 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_EXTENSIONS_API_AUTOFILL_ASSISTANT_PRIVATE_EXTENSION_ACCESS_TOKEN_FETCHER_H_
#define CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_ASSISTANT_PRIVATE_EXTENSION_ACCESS_TOKEN_FETCHER_H_
#include "components/autofill_assistant/browser/access_token_fetcher.h"
#include "components/signin/public/identity_manager/identity_manager.h"
namespace extensions {
// A class that fetches tokens as needed for requests to Autofill Assistant
// backends. This is an implementation provided to a service in the AA
// component.
class ExtensionAccessTokenFetcher
: public autofill_assistant::AccessTokenFetcher {
public:
explicit ExtensionAccessTokenFetcher(
signin::IdentityManager* identity_manager);
~ExtensionAccessTokenFetcher() override;
// AccessTokenFetcher:
void FetchAccessToken(
base::OnceCallback<void(bool, const std::string&)> callback) override;
void InvalidateAccessToken(const std::string& access_token) override;
private:
void OnCompleted(GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info);
signin::IdentityManager* identity_manager_;
std::unique_ptr<signin::AccessTokenFetcher> access_token_fetcher_;
base::OnceCallback<void(bool, const std::string&)> callback_;
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_ASSISTANT_PRIVATE_EXTENSION_ACCESS_TOKEN_FETCHER_H_
// Copyright 2013 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/extensions/api/autofill_assistant_private/extension_access_token_fetcher.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
class ExtensionAccessTokenFetcherTest : public testing::Test {
public:
ExtensionAccessTokenFetcherTest() = default;
~ExtensionAccessTokenFetcherTest() override = default;
void SetUp() override {
identity_test_env_.MakePrimaryAccountAvailable("primary@example.com");
}
void TearDown() override {}
protected:
// The environment needs to be the first member to be initialized.
base::test::TaskEnvironment task_environment_;
signin::IdentityTestEnvironment identity_test_env_;
};
TEST_F(ExtensionAccessTokenFetcherTest, SuccessfulAccessTokenFetch) {
base::MockCallback<base::OnceCallback<void(bool, const std::string&)>>
callback;
EXPECT_CALL(callback, Run(true, "access_token"));
ExtensionAccessTokenFetcher fetcher(identity_test_env_.identity_manager());
fetcher.FetchAccessToken(callback.Get());
identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Max());
}
TEST_F(ExtensionAccessTokenFetcherTest, FailedAccessTokenFetch) {
base::MockCallback<base::OnceCallback<void(bool, const std::string&)>>
callback;
EXPECT_CALL(callback, Run(false, ""));
ExtensionAccessTokenFetcher fetcher(identity_test_env_.identity_manager());
fetcher.FetchAccessToken(callback.Get());
identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
GoogleServiceAuthError::FromConnectionError(
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
}
} // namespace extensions
...@@ -4861,6 +4861,10 @@ test("unit_tests") { ...@@ -4861,6 +4861,10 @@ test("unit_tests") {
"../utility/image_writer/image_writer_unittest.cc", "../utility/image_writer/image_writer_unittest.cc",
] ]
if (enable_autofill_assistant_api) {
sources += [ "../browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher_unittest.cc" ]
}
allow_circular_includes_from = [ allow_circular_includes_from = [
"//chrome/browser/web_applications:web_applications_unit_tests", "//chrome/browser/web_applications:web_applications_unit_tests",
"//chrome/browser/web_applications/extensions:unit_tests", "//chrome/browser/web_applications/extensions:unit_tests",
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <string> #include <string>
#include "base/callback.h"
namespace autofill_assistant { namespace autofill_assistant {
// An interface that abstracts the steps needed to choose a user to sign in, // An interface that abstracts the steps needed to choose a user to sign in,
......
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