blob: 6233934a5d9b54a47468b13a0dbf8ee85ea6b3bb [file] [log] [blame]
// Copyright 2021 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 "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/bind.h"
#include "base/callback.h"
#include "weblayer/browser/profile_impl.h"
#include "weblayer/browser/tab_impl.h"
#include "weblayer/public/google_account_access_token_fetch_delegate.h"
#include "weblayer/shell/browser/shell.h"
#include "weblayer/test/weblayer_browser_test.h"
#include "weblayer/test/weblayer_browsertests_jni/AccessTokenFetchTestBridge_jni.h"
#include "weblayer/test/weblayer_browsertests_jni/GoogleAccountAccessTokenFetcherTestStub_jni.h"
namespace weblayer {
// Callback passed to GoogleAccountAccessTokenFetcherDelegate to be invoked on
// access token fetch completion.
void OnAccessTokenFetched(base::OnceClosure quit_closure,
std::string* target_token,
const std::string& received_token) {
*target_token = received_token;
std::move(quit_closure).Run();
}
// Utility to return the scopes from the most recent access token request to
// |java_client_stub|.
std::set<std::string> GetMostRecentRequestScopes(
base::android::ScopedJavaLocalRef<jobject> java_client_stub) {
JNIEnv* env = base::android::AttachCurrentThread();
std::vector<std::string> most_recent_request_scopes_vector;
base::android::AppendJavaStringArrayToStringVector(
env,
Java_GoogleAccountAccessTokenFetcherTestStub_getMostRecentRequestScopes(
env, java_client_stub),
&most_recent_request_scopes_vector);
return std::set<std::string>(most_recent_request_scopes_vector.begin(),
most_recent_request_scopes_vector.end());
}
// Tests proper operation of access token fetches initiated from C++ when the
// embedder has set a client for access token fetches in Java.
class AccessTokenFetchBrowserTest : public WebLayerBrowserTest {
public:
AccessTokenFetchBrowserTest() {}
~AccessTokenFetchBrowserTest() override = default;
protected:
ProfileImpl* profile() {
auto* tab_impl = static_cast<TabImpl*>(shell()->tab());
return tab_impl->profile();
}
GoogleAccountAccessTokenFetchDelegate* access_token_fetch_delegate() {
return profile()->access_token_fetch_delegate();
}
};
// Tests that when the embedder hasn't set a
// GoogleAccountAccessTokenFetcherClient instance in Java, access token fetches
// from C++ on Android result in the empty string being returned.
IN_PROC_BROWSER_TEST_F(AccessTokenFetchBrowserTest,
NoGoogleAccountAccessTokenFetcherClientSetInJava) {
base::RunLoop run_loop;
std::string access_token = "dummy";
access_token_fetch_delegate()->FetchAccessToken(
{"scope1"}, base::BindOnce(&OnAccessTokenFetched, run_loop.QuitClosure(),
&access_token));
run_loop.Run();
EXPECT_EQ("", access_token);
}
// Tests that when the embedder sets a Java client that returns a given access
// token, access token fetches initiated from C++ resolve to that token.
IN_PROC_BROWSER_TEST_F(AccessTokenFetchBrowserTest, SuccessfulFetch) {
base::RunLoop run_loop;
std::string access_token = "";
std::string kTokenFromResponse = "token";
std::set<std::string> kScopes = {"scope1", "scope2"};
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> java_client_stub =
Java_AccessTokenFetchTestBridge_installGoogleAccountAccessTokenFetcherTestStub(
env, profile()->GetJavaProfile());
access_token_fetch_delegate()->FetchAccessToken(
kScopes, base::BindOnce(&OnAccessTokenFetched, run_loop.QuitClosure(),
&access_token));
EXPECT_EQ("", access_token);
EXPECT_EQ(
1, Java_GoogleAccountAccessTokenFetcherTestStub_getNumOutstandingRequests(
env, java_client_stub));
int request_id =
Java_GoogleAccountAccessTokenFetcherTestStub_getMostRecentRequestId(
env, java_client_stub);
auto most_recent_request_scopes =
GetMostRecentRequestScopes(java_client_stub);
EXPECT_EQ(kScopes, most_recent_request_scopes);
Java_GoogleAccountAccessTokenFetcherTestStub_respondWithTokenForRequest(
env, java_client_stub, request_id,
base::android::ConvertUTF8ToJavaString(env, kTokenFromResponse));
run_loop.Run();
EXPECT_EQ(kTokenFromResponse, access_token);
}
// Tests correct operation when there are multiple ongoing fetches.
IN_PROC_BROWSER_TEST_F(AccessTokenFetchBrowserTest, MultipleFetches) {
base::RunLoop run_loop1;
base::RunLoop run_loop2;
std::string access_token1 = "";
std::string access_token2 = "";
std::string kTokenFromResponse1 = "token1";
std::string kTokenFromResponse2 = "token2";
std::set<std::string> kScopes1 = {"scope1", "scope2"};
std::set<std::string> kScopes2 = {"scope3"};
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> java_client_stub =
Java_AccessTokenFetchTestBridge_installGoogleAccountAccessTokenFetcherTestStub(
env, profile()->GetJavaProfile());
access_token_fetch_delegate()->FetchAccessToken(
kScopes1, base::BindOnce(&OnAccessTokenFetched, run_loop1.QuitClosure(),
&access_token1));
EXPECT_EQ(
1, Java_GoogleAccountAccessTokenFetcherTestStub_getNumOutstandingRequests(
env, java_client_stub));
int request_id1 =
Java_GoogleAccountAccessTokenFetcherTestStub_getMostRecentRequestId(
env, java_client_stub);
auto most_recent_request_scopes1 =
GetMostRecentRequestScopes(java_client_stub);
EXPECT_EQ(kScopes1, most_recent_request_scopes1);
EXPECT_EQ("", access_token1);
EXPECT_EQ("", access_token2);
access_token_fetch_delegate()->FetchAccessToken(
kScopes2, base::BindOnce(&OnAccessTokenFetched, run_loop2.QuitClosure(),
&access_token2));
EXPECT_EQ(
2, Java_GoogleAccountAccessTokenFetcherTestStub_getNumOutstandingRequests(
env, java_client_stub));
int request_id2 =
Java_GoogleAccountAccessTokenFetcherTestStub_getMostRecentRequestId(
env, java_client_stub);
auto most_recent_request_scopes2 =
GetMostRecentRequestScopes(java_client_stub);
EXPECT_EQ(kScopes2, most_recent_request_scopes2);
EXPECT_EQ("", access_token1);
EXPECT_EQ("", access_token2);
Java_GoogleAccountAccessTokenFetcherTestStub_respondWithTokenForRequest(
env, java_client_stub, request_id2,
base::android::ConvertUTF8ToJavaString(env, kTokenFromResponse2));
run_loop2.Run();
EXPECT_EQ("", access_token1);
EXPECT_EQ(kTokenFromResponse2, access_token2);
Java_GoogleAccountAccessTokenFetcherTestStub_respondWithTokenForRequest(
env, java_client_stub, request_id1,
base::android::ConvertUTF8ToJavaString(env, kTokenFromResponse1));
run_loop1.Run();
EXPECT_EQ(kTokenFromResponse1, access_token1);
EXPECT_EQ(kTokenFromResponse2, access_token2);
}
} // namespace weblayer