• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 package org.chromium.chrome.browser.sync;
6 
7 import android.accounts.Account;
8 import android.content.ContentResolver;
9 import android.content.Context;
10 import android.content.SharedPreferences;
11 import android.os.AsyncTask;
12 import android.os.Bundle;
13 import android.preference.PreferenceManager;
14 import android.util.Log;
15 
16 import com.google.common.annotations.VisibleForTesting;
17 
18 import org.chromium.base.ActivityStatus;
19 import org.chromium.sync.notifier.SyncStatusHelper;
20 import org.chromium.sync.signin.AccountManagerHelper;
21 
22 /**
23  * A class for controlling when a sync should be performed immediately, and when it should be
24  * delayed until Chrome comes to the foreground again.
25  */
26 public class DelayedSyncController {
27     private static final String TAG = "DelayedSyncController";
28     private static final String DELAYED_ACCOUNT_NAME = "delayed_account";
29 
30     private static class LazyHolder {
31         private static final DelayedSyncController INSTANCE = new DelayedSyncController();
32     }
33 
getInstance()34     public static DelayedSyncController getInstance() {
35         return LazyHolder.INSTANCE;
36     }
37 
38     @VisibleForTesting
DelayedSyncController()39     DelayedSyncController() {}
40 
41     /**
42      * Resume any syncs that were delayed while Chromium was backgrounded.
43      */
resumeDelayedSyncs(final Context context)44     public boolean resumeDelayedSyncs(final Context context) {
45         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
46         String accountName = prefs.getString(DELAYED_ACCOUNT_NAME, null);
47         if (accountName == null) {
48             Log.d(TAG, "No delayed sync.");
49             return false;
50         } else {
51             Log.d(TAG, "Handling delayed sync.");
52             Account account = AccountManagerHelper.createAccountFromName(accountName);
53             requestSyncOnBackgroundThread(context, account);
54             return true;
55         }
56     }
57 
58     /**
59      * Calls ContentResolver.requestSync() in a separate thread as it performs some blocking
60      * IO operations.
61      */
62     @VisibleForTesting
requestSyncOnBackgroundThread(final Context context, final Account account)63     void requestSyncOnBackgroundThread(final Context context, final Account account) {
64         new AsyncTask<Void, Void, Void>() {
65             @Override
66             protected Void doInBackground(Void... unused) {
67                 String contractAuthority =
68                         SyncStatusHelper.get(context).getContractAuthority();
69                 ContentResolver.requestSync(account, contractAuthority, new Bundle());
70                 return null;
71             }
72         }.execute();
73     }
74 
75     /**
76      * Stores preferences to indicate that an invalidation has arrived, but dropped on the floor.
77      */
setDelayedSync(Context ctx, String accountName)78     void setDelayedSync(Context ctx, String accountName) {
79         SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(ctx).edit();
80         editor.putString(DELAYED_ACCOUNT_NAME, accountName);
81         editor.apply();
82     }
83 
84     /**
85      * If there is a delayed sync, it will be cleared.
86      */
87     @VisibleForTesting
clearDelayedSyncs(Context context)88     void clearDelayedSyncs(Context context) {
89         setDelayedSync(context, null);
90     }
91 
92     @VisibleForTesting
shouldPerformSync(Context ctx, Bundle extras, Account account)93     boolean shouldPerformSync(Context ctx, Bundle extras, Account account) {
94         boolean manualSync = isManualSync(extras);
95 
96         if (manualSync || ActivityStatus.isApplicationVisible()) {
97             clearDelayedSyncs(ctx);
98             return true;
99         } else {
100             Log.d(TAG, "Delaying sync.");
101             setDelayedSync(ctx, account.name);
102             return false;
103         }
104     }
105 
isManualSync(Bundle extras)106     private static boolean isManualSync(Bundle extras) {
107         boolean manualSync = false;
108         if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)) {
109             manualSync = true;
110             Log.d(TAG, "Manual sync requested.");
111         }
112         return manualSync;
113     }
114 }
115