1 // Copyright 2020 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.
4
5 #include "chrome/browser/android/signin/web_signin_bridge.h"
6
7 #include "base/android/jni_android.h"
8 #include "base/android/scoped_java_ref.h"
9 #include "chrome/android/chrome_jni_headers/WebSigninBridge_jni.h"
10 #include "chrome/browser/profiles/profile_android.h"
11 #include "chrome/browser/signin/account_reconcilor_factory.h"
12 #include "chrome/browser/signin/identity_manager_factory.h"
13 #include "components/signin/public/android/jni_headers/GoogleServiceAuthError_jni.h"
14 #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
15
16 using base::android::JavaParamRef;
17
ForwardOnSigninCompletedToJava(const base::android::ScopedJavaGlobalRef<jobject> & j_listener,const GoogleServiceAuthError & error)18 void ForwardOnSigninCompletedToJava(
19 const base::android::ScopedJavaGlobalRef<jobject>& j_listener,
20 const GoogleServiceAuthError& error) {
21 JNIEnv* env = base::android::AttachCurrentThread();
22 if (error.state() == GoogleServiceAuthError::State::NONE) {
23 Java_WebSigninBridge_onSigninSucceded(env, j_listener);
24 } else {
25 base::android::ScopedJavaLocalRef<jobject> j_error =
26 signin::Java_GoogleServiceAuthError_Constructor(env, error.state());
27 Java_WebSigninBridge_onSigninFailed(env, j_listener, j_error);
28 }
29 }
30
WebSigninBridge(signin::IdentityManager * identity_manager,AccountReconcilor * account_reconcilor,CoreAccountInfo signin_account,OnSigninCompletedCallback on_signin_completed)31 WebSigninBridge::WebSigninBridge(signin::IdentityManager* identity_manager,
32 AccountReconcilor* account_reconcilor,
33 CoreAccountInfo signin_account,
34 OnSigninCompletedCallback on_signin_completed)
35 : identity_manager_(identity_manager),
36 account_reconcilor_(account_reconcilor),
37 signin_account_(signin_account),
38 on_signin_completed_(std::move(on_signin_completed)) {
39 DCHECK(on_signin_completed_) << "Callback must be non-null!";
40
41 identity_manager_->AddObserver(this);
42 account_reconcilor_->AddObserver(this);
43
44 signin::AccountsInCookieJarInfo info =
45 identity_manager_->GetAccountsInCookieJar();
46 if (info.accounts_are_fresh)
47 OnAccountsInCookieUpdated(info, GoogleServiceAuthError::AuthErrorNone());
48 }
49
~WebSigninBridge()50 WebSigninBridge::~WebSigninBridge() {
51 identity_manager_->RemoveObserver(this);
52 account_reconcilor_->RemoveObserver(this);
53 }
54
OnAccountsInCookieUpdated(const signin::AccountsInCookieJarInfo & accounts_in_cookie_jar_info,const GoogleServiceAuthError & error)55 void WebSigninBridge::OnAccountsInCookieUpdated(
56 const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
57 const GoogleServiceAuthError& error) {
58 for (const auto& account : accounts_in_cookie_jar_info.signed_in_accounts) {
59 if (account.valid && account.gaia_id == signin_account_.gaia) {
60 OnSigninCompleted(GoogleServiceAuthError());
61 return;
62 }
63 }
64 }
65
OnStateChanged(signin_metrics::AccountReconcilorState state)66 void WebSigninBridge::OnStateChanged(
67 signin_metrics::AccountReconcilorState state) {
68 if (state !=
69 signin_metrics::AccountReconcilorState::ACCOUNT_RECONCILOR_ERROR) {
70 return;
71 }
72
73 bool is_auth_error =
74 identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState(
75 signin_account_.account_id);
76 OnSigninCompleted(GoogleServiceAuthError(
77 is_auth_error ? GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS
78 : GoogleServiceAuthError::State::CONNECTION_FAILED));
79 }
80
OnSigninCompleted(const GoogleServiceAuthError & error)81 void WebSigninBridge::OnSigninCompleted(const GoogleServiceAuthError& error) {
82 on_signin_completed_.Run(error);
83 }
84
JNI_WebSigninBridge_Create(JNIEnv * env,const JavaParamRef<jobject> & j_profile,const JavaParamRef<jobject> & j_account,const JavaParamRef<jobject> & j_listener)85 static jlong JNI_WebSigninBridge_Create(
86 JNIEnv* env,
87 const JavaParamRef<jobject>& j_profile,
88 const JavaParamRef<jobject>& j_account,
89 const JavaParamRef<jobject>& j_listener) {
90 DCHECK(j_listener) << "Listener should be non-null";
91
92 Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
93 signin::IdentityManager* identity_manager =
94 IdentityManagerFactory::GetForProfile(profile);
95 AccountReconcilor* account_reconcilor =
96 AccountReconcilorFactory::GetForProfile(profile);
97 CoreAccountInfo signin_account =
98 ConvertFromJavaCoreAccountInfo(env, j_account);
99 base::RepeatingCallback<void(const GoogleServiceAuthError&)>
100 on_signin_completed = base::BindRepeating(
101 &ForwardOnSigninCompletedToJava,
102 base::android::ScopedJavaGlobalRef<jobject>(j_listener));
103 return reinterpret_cast<intptr_t>(
104 new WebSigninBridge(identity_manager, account_reconcilor, signin_account,
105 std::move(on_signin_completed)));
106 }
107
JNI_WebSigninBridge_Destroy(JNIEnv * env,jlong web_signin_bridge)108 static void JNI_WebSigninBridge_Destroy(JNIEnv* env, jlong web_signin_bridge) {
109 delete reinterpret_cast<WebSigninBridge*>(web_signin_bridge);
110 }
111