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.sync;
6
7import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
8
9import android.accounts.Account;
10import android.app.Activity;
11import android.content.ContentResolver;
12import android.content.Context;
13import android.content.Intent;
14import android.os.Bundle;
15import android.test.suitebuilder.annotation.SmallTest;
16
17import org.chromium.base.ApplicationStatus;
18import org.chromium.base.VisibleForTesting;
19import org.chromium.base.test.util.Feature;
20import org.chromium.chrome.shell.ChromeShellTestBase;
21import org.chromium.content.browser.test.util.Criteria;
22import org.chromium.content.browser.test.util.CriteriaHelper;
23import org.chromium.sync.signin.AccountManagerHelper;
24
25public class DelayedSyncControllerTest extends ChromeShellTestBase {
26    private static final Account TEST_ACCOUNT =
27            AccountManagerHelper.createAccountFromName("something@gmail.com");
28    private static final long WAIT_FOR_LAUNCHER_MS = scaleTimeout(10 * 1000);
29    private static final long POLL_INTERVAL_MS = 100;
30    private TestDelayedSyncController mController;
31
32    private static class TestDelayedSyncController extends DelayedSyncController {
33        private boolean mSyncRequested;
34
35        private TestDelayedSyncController() {}
36
37        @Override
38        void requestSyncOnBackgroundThread(Context context, Account account) {
39            mSyncRequested = true;
40        }
41    }
42
43    @Override
44    protected void setUp() throws Exception {
45        super.setUp();
46        mController = new TestDelayedSyncController();
47        launchChromeShellWithBlankPage();
48    }
49
50    @SmallTest
51    @Feature({"Sync"})
52    public void testManualSyncRequestsShouldAlwaysTriggerSync() throws InterruptedException {
53        // Sync should trigger for manual requests when Chrome is in the foreground.
54        assertTrue(isActivityResumed());
55        Bundle extras = new Bundle();
56        extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
57        assertTrue(mController.shouldPerformSync(getActivity(), extras, TEST_ACCOUNT));
58
59        // Sync should trigger for manual requests when Chrome is in the background.
60        sendChromeToBackground(getActivity());
61        extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
62        assertTrue(mController.shouldPerformSync(getActivity(), extras, TEST_ACCOUNT));
63    }
64
65    @SmallTest
66    @Feature({"Sync"})
67    public void testSyncRequestsShouldTriggerSyncWhenChromeIsInForeground() {
68        assertTrue(isActivityResumed());
69        Bundle extras = new Bundle();
70        assertTrue(mController.shouldPerformSync(getActivity(), extras, TEST_ACCOUNT));
71    }
72
73    @SmallTest
74    @Feature({"Sync"})
75    public void testSyncRequestsWhenChromeIsInBackgroundShouldBeDelayed()
76            throws InterruptedException {
77        sendChromeToBackground(getActivity());
78        Bundle extras = new Bundle();
79        assertFalse(mController.shouldPerformSync(getActivity(), extras, TEST_ACCOUNT));
80    }
81
82    @SmallTest
83    @Feature({"Sync"})
84    public void testDelayedSyncRequestsShouldBeTriggeredOnResume() throws InterruptedException {
85        // First make sure there are no delayed syncs.
86        mController.clearDelayedSyncs(getActivity());
87        assertFalse(mController.resumeDelayedSyncs(getActivity()));
88        assertFalse(mController.mSyncRequested);
89
90        // Trying to perform sync when Chrome is in the background should create a delayed sync.
91        sendChromeToBackground(getActivity());
92        Bundle extras = new Bundle();
93        assertFalse(mController.shouldPerformSync(getActivity(), extras, TEST_ACCOUNT));
94
95        // Make sure the delayed sync can be resumed.
96        assertTrue(mController.resumeDelayedSyncs(getActivity()));
97        assertTrue(mController.mSyncRequested);
98    }
99
100    @VisibleForTesting
101    static void sendChromeToBackground(Activity activity) throws InterruptedException {
102        Intent intent = new Intent(Intent.ACTION_MAIN);
103        intent.addCategory(Intent.CATEGORY_HOME);
104        activity.startActivity(intent);
105
106        assertTrue("Activity should have been resumed",
107                CriteriaHelper.pollForCriteria(new Criteria() {
108                    @Override
109                    public boolean isSatisfied() {
110                        return !isActivityResumed();
111                    }
112                }, WAIT_FOR_LAUNCHER_MS, POLL_INTERVAL_MS));
113    }
114
115    private static boolean isActivityResumed() {
116        return ApplicationStatus.hasVisibleActivities();
117    }
118}
119