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 "web_signin_bridge.h"
6 
7 #include <memory>
8 #include <set>
9 
10 #include "base/test/mock_callback.h"
11 #include "base/test/task_environment.h"
12 #include "components/signin/core/browser/account_reconcilor.h"
13 #include "components/signin/public/base/account_consistency_method.h"
14 #include "components/signin/public/base/test_signin_client.h"
15 #include "components/signin/public/identity_manager/identity_test_environment.h"
16 #include "components/sync_preferences/testing_pref_service_syncable.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 
20 using ::testing::_;
21 
22 class StubAccountReconcilorDelegate : public signin::AccountReconcilorDelegate {
23  public:
24   StubAccountReconcilorDelegate() = default;
25   ~StubAccountReconcilorDelegate() override = default;
26 
IsReconcileEnabled() const27   bool IsReconcileEnabled() const override { return true; }
ShouldAbortReconcileIfPrimaryHasError() const28   bool ShouldAbortReconcileIfPrimaryHasError() const override { return true; }
29 };
30 
31 class WebSigninBridgeTest : public ::testing::Test {
32  public:
WebSigninBridgeTest()33   WebSigninBridgeTest()
34       : signin_client_(&prefs_),
35         identity_test_env_(nullptr,
36                            &prefs_,
37                            signin::AccountConsistencyMethod::kDisabled,
38                            &signin_client_) {
39     account_reconcilor_ = std::make_unique<AccountReconcilor>(
40         identity_test_env_.identity_manager(), &signin_client_,
41         std::make_unique<StubAccountReconcilorDelegate>());
42   }
43 
~WebSigninBridgeTest()44   ~WebSigninBridgeTest() override { account_reconcilor_->Shutdown(); }
45 
CreateWebSigninBridge(CoreAccountInfo account,WebSigninBridge::OnSigninCompletedCallback callback)46   std::unique_ptr<WebSigninBridge> CreateWebSigninBridge(
47       CoreAccountInfo account,
48       WebSigninBridge::OnSigninCompletedCallback callback) {
49     return std::make_unique<WebSigninBridge>(
50         identity_test_env_.identity_manager(), account_reconcilor_.get(),
51         account, std::move(callback));
52   }
53 
54  protected:
55   base::test::SingleThreadTaskEnvironment task_environment_;
56   sync_preferences::TestingPrefServiceSyncable prefs_;
57   TestSigninClient signin_client_;
58   signin::IdentityTestEnvironment identity_test_env_;
59   std::unique_ptr<AccountReconcilor> account_reconcilor_;
60 
61   DISALLOW_COPY_AND_ASSIGN(WebSigninBridgeTest);
62 };
63 
TEST_F(WebSigninBridgeTest,CookiesWithSigninAccountShouldTriggerOnSigninSucceeded)64 TEST_F(WebSigninBridgeTest,
65        CookiesWithSigninAccountShouldTriggerOnSigninSucceeded) {
66   AccountInfo account =
67       identity_test_env_.MakeAccountAvailable("test@gmail.com");
68   base::MockCallback<WebSigninBridge::OnSigninCompletedCallback> callback;
69   std::unique_ptr<WebSigninBridge> web_signin_bridge =
70       CreateWebSigninBridge(account, callback.Get());
71   EXPECT_CALL(callback, Run(GoogleServiceAuthError()));
72 
73   identity_test_env_.SetPrimaryAccount(account.email);
74   signin::CookieParamsForTest cookie_params{account.email, account.gaia};
75   identity_test_env_.SetCookieAccounts({cookie_params});
76 }
77 
TEST_F(WebSigninBridgeTest,CookiesWithSigninAccountShouldTriggerOnSigninSucceededAfterSigninFailed)78 TEST_F(
79     WebSigninBridgeTest,
80     CookiesWithSigninAccountShouldTriggerOnSigninSucceededAfterSigninFailed) {
81   AccountInfo account =
82       identity_test_env_.MakeAccountAvailable("test@gmail.com");
83   base::MockCallback<WebSigninBridge::OnSigninCompletedCallback> callback;
84   std::unique_ptr<WebSigninBridge> web_signin_bridge =
85       CreateWebSigninBridge(account, callback.Get());
86 
87   EXPECT_CALL(callback,
88               Run(GoogleServiceAuthError(
89                   GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS)));
90   identity_test_env_.SetPrimaryAccount(account.email);
91   identity_test_env_.SetInvalidRefreshTokenForAccount(account.account_id);
92   identity_test_env_.UpdatePersistentErrorOfRefreshTokenForAccount(
93       account.account_id,
94       GoogleServiceAuthError(
95           GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
96   account_reconcilor_->EnableReconcile();
97   EXPECT_EQ(signin_metrics::AccountReconcilorState::ACCOUNT_RECONCILOR_ERROR,
98             account_reconcilor_->GetState());
99 
100   EXPECT_CALL(callback, Run(GoogleServiceAuthError()));
101   identity_test_env_.SetRefreshTokenForAccount(account.account_id);
102   signin::CookieParamsForTest cookie_params{account.email, account.gaia};
103   identity_test_env_.SetCookieAccounts({cookie_params});
104 }
105 
TEST_F(WebSigninBridgeTest,CookiesWithoutSigninAccountDontTriggerOnSigninSucceeded)106 TEST_F(WebSigninBridgeTest,
107        CookiesWithoutSigninAccountDontTriggerOnSigninSucceeded) {
108   AccountInfo signin_account =
109       identity_test_env_.MakeAccountAvailable("test1@gmail.com");
110   AccountInfo non_signin_account =
111       identity_test_env_.MakeAccountAvailable("test2@gmail.com");
112   base::MockCallback<WebSigninBridge::OnSigninCompletedCallback> callback;
113   std::unique_ptr<WebSigninBridge> web_signin_bridge =
114       CreateWebSigninBridge(signin_account, callback.Get());
115   EXPECT_CALL(callback, Run(_)).Times(0);
116 
117   identity_test_env_.SetPrimaryAccount(non_signin_account.email);
118   signin::CookieParamsForTest cookie_params{non_signin_account.email,
119                                             non_signin_account.gaia};
120   identity_test_env_.SetCookieAccounts({cookie_params});
121 }
122 
TEST_F(WebSigninBridgeTest,ReconcilorErrorShouldTriggerOnSigninFailed)123 TEST_F(WebSigninBridgeTest, ReconcilorErrorShouldTriggerOnSigninFailed) {
124   AccountInfo account =
125       identity_test_env_.MakeAccountAvailable("test@gmail.com");
126   base::MockCallback<WebSigninBridge::OnSigninCompletedCallback> callback;
127   std::unique_ptr<WebSigninBridge> web_signin_bridge =
128       CreateWebSigninBridge(account, callback.Get());
129   EXPECT_CALL(callback,
130               Run(GoogleServiceAuthError(
131                   GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS)));
132 
133   identity_test_env_.SetPrimaryAccount(account.email);
134   identity_test_env_.SetInvalidRefreshTokenForAccount(account.account_id);
135   identity_test_env_.UpdatePersistentErrorOfRefreshTokenForAccount(
136       account.account_id,
137       GoogleServiceAuthError(
138           GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
139   CoreAccountId account_id1 =
140       identity_test_env_.identity_manager()->GetPrimaryAccountId();
141   EXPECT_TRUE(
142       identity_test_env_.identity_manager()
143           ->HasAccountWithRefreshTokenInPersistentErrorState(account_id1));
144   account_reconcilor_->EnableReconcile();
145   EXPECT_EQ(signin_metrics::AccountReconcilorState::ACCOUNT_RECONCILOR_ERROR,
146             account_reconcilor_->GetState());
147   CoreAccountId account_id2 =
148       identity_test_env_.identity_manager()->GetPrimaryAccountId();
149   EXPECT_TRUE(
150       identity_test_env_.identity_manager()
151           ->HasAccountWithRefreshTokenInPersistentErrorState(account_id2));
152 }
153