OAuth2TokenServiceIntegrationTest.java revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright 2013 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
5package org.chromium.chrome.browser.signin;
6
7import android.accounts.Account;
8import android.test.UiThreadTest;
9import android.test.suitebuilder.annotation.MediumTest;
10
11import org.chromium.base.ThreadUtils;
12import org.chromium.base.test.util.AdvancedMockContext;
13import org.chromium.base.test.util.Feature;
14import org.chromium.chrome.browser.profiles.Profile;
15import org.chromium.chrome.shell.ChromeShellTestBase;
16import org.chromium.sync.signin.AccountManagerHelper;
17import org.chromium.sync.signin.ChromeSigninController;
18import org.chromium.sync.test.util.AccountHolder;
19import org.chromium.sync.test.util.MockAccountManager;
20
21import java.util.concurrent.atomic.AtomicReference;
22
23/**
24 * Integration test for the OAuth2TokenService.
25 *
26 * These tests initialize the native part of the service.
27 */
28public class OAuth2TokenServiceIntegrationTest extends ChromeShellTestBase {
29
30    private static final Account TEST_ACCOUNT1 =
31            AccountManagerHelper.createAccountFromName("foo@gmail.com");
32    private static final Account TEST_ACCOUNT2 =
33            AccountManagerHelper.createAccountFromName("bar@gmail.com");
34    private static final AccountHolder TEST_ACCOUNT_HOLDER_1 =
35            AccountHolder.create().account(TEST_ACCOUNT1).alwaysAccept(true).build();
36    private static final AccountHolder TEST_ACCOUNT_HOLDER_2 =
37            AccountHolder.create().account(TEST_ACCOUNT2).alwaysAccept(true).build();
38
39    private AdvancedMockContext mContext;
40    private OAuth2TokenService mOAuth2TokenService;
41    private MockAccountManager mAccountManager;
42    private TestObserver mObserver;
43    private ChromeSigninController mChromeSigninController;
44
45    @Override
46    protected void setUp() throws Exception {
47        super.setUp();
48        clearAppData();
49        startChromeBrowserProcessSync(getInstrumentation().getTargetContext());
50
51        // Set up AccountManager.
52        mContext = new AdvancedMockContext(getInstrumentation().getTargetContext());
53        mAccountManager = new MockAccountManager(mContext, getInstrumentation().getContext());
54        AccountManagerHelper.overrideAccountManagerHelperForTests(mContext, mAccountManager);
55
56        // Make sure there is no account signed in yet.
57        mChromeSigninController = ChromeSigninController.get(mContext);
58        mChromeSigninController.setSignedInAccountName(null);
59
60        // Get a reference to the service.
61        mOAuth2TokenService = getOAuth2TokenServiceOnUiThread();
62
63        // Set up observer.
64        mObserver = new TestObserver();
65        addObserver(mObserver);
66    }
67
68    /**
69     * The {@link OAuth2TokenService} and the {@link Profile} can only be accessed from the UI
70     * thread, so this helper method is a convenience method to retrieve it.
71     *
72     * @return the OAuth2TokenService.
73     */
74    private static OAuth2TokenService getOAuth2TokenServiceOnUiThread() {
75        final AtomicReference<OAuth2TokenService> service =
76                new AtomicReference<OAuth2TokenService>();
77        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
78            @Override
79            public void run() {
80                service.set(OAuth2TokenService.getForProfile(Profile.getLastUsedProfile()));
81            }
82        });
83        return service.get();
84    }
85
86    private void addObserver(final TestObserver observer) {
87        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
88            @Override
89            public void run() {
90                mOAuth2TokenService.addObserver(observer);
91            }
92        });
93    }
94
95    @MediumTest
96    @UiThreadTest
97    @Feature({"Sync"})
98    public void testFireRefreshTokenAvailableNotifiesJavaObservers() {
99        // Adding an observer should not lead to a callback.
100        assertEquals(0, mObserver.getAvailableCallCount());
101
102        // An observer should be called with the correct account.
103        mOAuth2TokenService.fireRefreshTokenAvailable(TEST_ACCOUNT1);
104        assertEquals(1, mObserver.getAvailableCallCount());
105        assertEquals(TEST_ACCOUNT1, mObserver.getLastAccount());
106
107        // When mOAuth2TokenService, an observer should not be called.
108        mOAuth2TokenService.removeObserver(mObserver);
109        mOAuth2TokenService.fireRefreshTokenAvailable(TEST_ACCOUNT1);
110        assertEquals(1, mObserver.getAvailableCallCount());
111
112        // No other observer interface method should ever have been called.
113        assertEquals(0, mObserver.getRevokedCallCount());
114        assertEquals(0, mObserver.getLoadedCallCount());
115    }
116
117    @MediumTest
118    @UiThreadTest
119    @Feature({"Sync"})
120    public void testFireRefreshTokenRevokedNotifiesJavaObservers() {
121        // Adding an observer should not lead to a callback.
122        assertEquals(0, mObserver.getRevokedCallCount());
123
124        // An observer should be called with the correct account.
125        mOAuth2TokenService.fireRefreshTokenRevoked(TEST_ACCOUNT1);
126        assertEquals(1, mObserver.getRevokedCallCount());
127        assertEquals(TEST_ACCOUNT1, mObserver.getLastAccount());
128
129        // When removed, an observer should not be called.
130        mOAuth2TokenService.removeObserver(mObserver);
131        mOAuth2TokenService.fireRefreshTokenRevoked(TEST_ACCOUNT1);
132        assertEquals(1, mObserver.getRevokedCallCount());
133
134        // No other observer interface method should ever have been called.
135        assertEquals(0, mObserver.getAvailableCallCount());
136        assertEquals(0, mObserver.getLoadedCallCount());
137    }
138
139    @MediumTest
140    @UiThreadTest
141    @Feature({"Sync"})
142    public void testFireRefreshTokensLoadedNotifiesJavaObservers() {
143        // Adding an observer should not lead to a callback.
144        assertEquals(0, mObserver.getLoadedCallCount());
145
146        // An observer should be called with the correct account.
147        mOAuth2TokenService.fireRefreshTokensLoaded();
148        assertEquals(1, mObserver.getLoadedCallCount());
149
150        // When removed, an observer should not be called.
151        mOAuth2TokenService.removeObserver(mObserver);
152        mOAuth2TokenService.fireRefreshTokensLoaded();
153        assertEquals(1, mObserver.getLoadedCallCount());
154
155        // No other observer interface method should ever have been called.
156        assertEquals(0, mObserver.getAvailableCallCount());
157        assertEquals(0, mObserver.getRevokedCallCount());
158    }
159
160    @MediumTest
161    @UiThreadTest
162    public void testValidateAccountsNoAccountsRegisteredAndNoSignedInUser() {
163        // Run test.
164        mOAuth2TokenService.validateAccounts(mContext, false);
165
166        // Ensure no calls have been made to the observer.
167        assertEquals(0, mObserver.getAvailableCallCount());
168        assertEquals(0, mObserver.getRevokedCallCount());
169        assertEquals(0, mObserver.getLoadedCallCount());
170    }
171
172    @MediumTest
173    @UiThreadTest
174    public void testValidateAccountsOneAccountsRegisteredAndNoSignedInUser() {
175        // Add account.
176        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
177
178        // Run test.
179        mOAuth2TokenService.validateAccounts(mContext, false);
180
181        // Ensure no calls have been made to the observer.
182        assertEquals(0, mObserver.getAvailableCallCount());
183        assertEquals(0, mObserver.getRevokedCallCount());
184        assertEquals(0, mObserver.getLoadedCallCount());
185    }
186
187    @MediumTest
188    @UiThreadTest
189    public void testValidateAccountsOneAccountsRegisteredSignedIn() {
190        // Add account.
191        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
192
193        // Mark user as signed in.
194        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
195
196        // Run test.
197        mOAuth2TokenService.validateAccounts(mContext, false);
198
199        // Ensure one call for the signed in account.
200        assertEquals(1, mObserver.getAvailableCallCount());
201        assertEquals(0, mObserver.getRevokedCallCount());
202        assertEquals(0, mObserver.getLoadedCallCount());
203
204        // Validate again and make sure no new calls are made.
205        mOAuth2TokenService.validateAccounts(mContext, false);
206        assertEquals(1, mObserver.getAvailableCallCount());
207        assertEquals(0, mObserver.getRevokedCallCount());
208        assertEquals(0, mObserver.getLoadedCallCount());
209
210        // Validate again with force notifications and make sure one new calls is made.
211        mOAuth2TokenService.validateAccounts(mContext, true);
212        assertEquals(2, mObserver.getAvailableCallCount());
213        assertEquals(0, mObserver.getRevokedCallCount());
214        assertEquals(0, mObserver.getLoadedCallCount());
215    }
216
217    @MediumTest
218    @UiThreadTest
219    public void testValidateAccountsSingleAccountWithoutChanges() {
220        // Add account.
221        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
222
223        // Mark user as signed in.
224        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
225
226        // Run one validation.
227        mOAuth2TokenService.validateAccounts(mContext, false);
228        assertEquals(1, mObserver.getAvailableCallCount());
229        assertEquals(0, mObserver.getRevokedCallCount());
230        assertEquals(0, mObserver.getLoadedCallCount());
231
232        // Re-run validation.
233        mOAuth2TokenService.validateAccounts(mContext, false);
234        assertEquals(1, mObserver.getAvailableCallCount());
235        assertEquals(0, mObserver.getRevokedCallCount());
236        assertEquals(0, mObserver.getLoadedCallCount());
237    }
238
239    @MediumTest
240    @UiThreadTest
241    public void testValidateAccountsSingleAccountThenAddOne() {
242        // Add account.
243        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
244
245        // Mark user as signed in.
246        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
247
248        // Run one validation.
249        mOAuth2TokenService.validateAccounts(mContext, false);
250        assertEquals(1, mObserver.getAvailableCallCount());
251        assertEquals(0, mObserver.getRevokedCallCount());
252        assertEquals(0, mObserver.getLoadedCallCount());
253
254        // Add another account.
255        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
256
257        // Re-run validation.
258        mOAuth2TokenService.validateAccounts(mContext, false);
259        assertEquals(2, mObserver.getAvailableCallCount());
260        assertEquals(0, mObserver.getRevokedCallCount());
261        assertEquals(0, mObserver.getLoadedCallCount());
262    }
263
264    @MediumTest
265    @UiThreadTest
266    public void testValidateAccountsTwoAccountsThenRemoveOne() {
267        // Add accounts.
268        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
269        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
270
271        // Mark user as signed in.
272        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
273
274        // Run one validation.
275        mOAuth2TokenService.validateAccounts(mContext, false);
276        assertEquals(2, mObserver.getAvailableCallCount());
277
278        mAccountManager.removeAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
279        mOAuth2TokenService.validateAccounts(mContext, false);
280
281        assertEquals(2, mObserver.getAvailableCallCount());
282        assertEquals(1, mObserver.getRevokedCallCount());
283        assertEquals(0, mObserver.getLoadedCallCount());
284    }
285
286    @MediumTest
287    @UiThreadTest
288    public void testValidateAccountsTwoAccountsThenRemoveAll() {
289        // Add accounts.
290        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
291        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
292
293        // Mark user as signed in.
294        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
295
296        mOAuth2TokenService.validateAccounts(mContext, false);
297        assertEquals(2, mObserver.getAvailableCallCount());
298
299        // Remove all.
300        mAccountManager.removeAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
301        mAccountManager.removeAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
302
303        // Re-validate and run checks.
304        mOAuth2TokenService.validateAccounts(mContext, false);
305        assertEquals(2, mObserver.getRevokedCallCount());
306        assertEquals(0, mObserver.getLoadedCallCount());
307    }
308
309    @MediumTest
310    @UiThreadTest
311    public void testValidateAccountsTwoAccountsThenRemoveAllSignOut() {
312        // Add accounts.
313        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
314        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
315
316        // Mark user as signed in.
317        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
318
319        mOAuth2TokenService.validateAccounts(mContext, false);
320        assertEquals(2, mObserver.getAvailableCallCount());
321
322        // Remove all.
323        mChromeSigninController.clearSignedInUser();
324        mAccountManager.removeAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
325        mAccountManager.removeAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
326
327        // Re-validate and run checks.
328        mOAuth2TokenService.validateAccounts(mContext, false);
329        assertEquals(2, mObserver.getRevokedCallCount());
330        assertEquals(0, mObserver.getLoadedCallCount());
331    }
332
333    @MediumTest
334    @UiThreadTest
335    public void testValidateAccountsTwoAccountsRegisteredAndOneSignedIn() {
336        // Add accounts.
337        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
338        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
339
340        // Mark user as signed in.
341        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
342
343        // Run test.
344        mOAuth2TokenService.validateAccounts(mContext, false);
345
346        // All accounts will be notified. It is up to the observer
347        // to design if any action is needed.
348        assertEquals(2, mObserver.getAvailableCallCount());
349        assertEquals(0, mObserver.getRevokedCallCount());
350        assertEquals(0, mObserver.getLoadedCallCount());
351    }
352
353    @MediumTest
354    @UiThreadTest
355    public void testValidateAccountsNoAccountsRegisteredButSignedIn() {
356        // Mark user as signed in without setting up the account.
357        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
358
359        // Run test.
360        mOAuth2TokenService.validateAccounts(mContext, false);
361
362        // Ensure no calls have been made to the observer.
363        assertEquals(0, mObserver.getAvailableCallCount());
364        assertEquals(0, mObserver.getRevokedCallCount());
365        assertEquals(0, mObserver.getLoadedCallCount());
366    }
367
368    @MediumTest
369    @UiThreadTest
370    public void testValidateAccountsFiresEventAtTheEnd() {
371        // Mark user as signed in without setting up the account.
372        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
373        TestObserver ob = new TestObserver() {
374            @Override
375            public void onRefreshTokenAvailable(Account account) {
376                super.onRefreshTokenAvailable(account);
377                assertEquals(1, OAuth2TokenService.getAccounts(mContext).length);
378            }
379        };
380
381        addObserver(ob);
382        mOAuth2TokenService.validateAccounts(mContext, false);
383    }
384
385    private static class TestObserver implements OAuth2TokenService.OAuth2TokenServiceObserver {
386        private int mAvailableCallCount;
387        private int mRevokedCallCount;
388        private int mLoadedCallCount;
389        private Account mLastAccount;
390
391        @Override
392        public void onRefreshTokenAvailable(Account account) {
393            mAvailableCallCount++;
394            mLastAccount = account;
395        }
396
397        @Override
398        public void onRefreshTokenRevoked(Account account) {
399            mRevokedCallCount++;
400            mLastAccount = account;
401        }
402
403        @Override
404        public void onRefreshTokensLoaded() {
405            mLoadedCallCount++;
406        }
407
408        public int getAvailableCallCount() {
409            return mAvailableCallCount;
410        }
411
412        public int getRevokedCallCount() {
413            return mRevokedCallCount;
414        }
415
416        public int getLoadedCallCount() {
417            return mLoadedCallCount;
418        }
419
420        public Account getLastAccount() {
421            return mLastAccount;
422        }
423    }
424}
425