| Index: chrome/android/java/src/org/chromium/chrome/browser/sync/DelayedSyncController.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/DelayedSyncController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/DelayedSyncController.java
|
| index 8b896444047bbe081606c8300425a0f0536acd75..9ca9f20f29577e829b1329f7e761f30e4636ceb5 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/DelayedSyncController.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/DelayedSyncController.java
|
| @@ -11,20 +11,28 @@ import android.content.SharedPreferences;
|
| import android.os.AsyncTask;
|
| import android.os.Bundle;
|
| import android.preference.PreferenceManager;
|
| -import android.util.Log;
|
|
|
| import org.chromium.base.ApplicationStatus;
|
| +import org.chromium.base.Log;
|
| import org.chromium.base.VisibleForTesting;
|
| +import org.chromium.components.invalidation.PendingInvalidation;
|
| import org.chromium.sync.AndroidSyncSettings;
|
| import org.chromium.sync.signin.AccountManagerHelper;
|
|
|
| +import java.util.ArrayList;
|
| +import java.util.Arrays;
|
| +import java.util.HashSet;
|
| +import java.util.List;
|
| +import java.util.Set;
|
| +
|
| /**
|
| - * A class for controlling when a sync should be performed immediately, and when it should be
|
| + * A class for controlling whether an invalidation should be notified immediately, or should be
|
| * delayed until Chrome comes to the foreground again.
|
| */
|
| public class DelayedSyncController {
|
| - private static final String TAG = "DelayedSyncController";
|
| + private static final String TAG = Log.makeTag("invalidation");
|
| private static final String DELAYED_ACCOUNT_NAME = "delayed_account";
|
| + private static final String DELAYED_INVALIDATIONS = "delayed_invalidations";
|
|
|
| private static class LazyHolder {
|
| private static final DelayedSyncController INSTANCE = new DelayedSyncController();
|
| @@ -38,18 +46,19 @@ public class DelayedSyncController {
|
| DelayedSyncController() {}
|
|
|
| /**
|
| - * Resume any syncs that were delayed while Chromium was backgrounded.
|
| + * Notify any invalidations that were delayed while Chromium was backgrounded.
|
| */
|
| - public boolean resumeDelayedSyncs(final Context context) {
|
| + public boolean notifyPendingInvalidations(final Context context) {
|
| SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
| String accountName = prefs.getString(DELAYED_ACCOUNT_NAME, null);
|
| if (accountName == null) {
|
| - Log.d(TAG, "No delayed sync.");
|
| + Log.d(TAG, "No pending invalidations.");
|
| return false;
|
| } else {
|
| - Log.d(TAG, "Handling delayed sync.");
|
| + Log.d(TAG, "Handling pending invalidations.");
|
| Account account = AccountManagerHelper.createAccountFromName(accountName);
|
| - requestSyncOnBackgroundThread(context, account);
|
| + List<Bundle> bundles = popPendingInvalidations(context);
|
| + notifyInvalidationsOnBackgroundThread(context, account, bundles);
|
| return true;
|
| }
|
| }
|
| @@ -59,12 +68,15 @@ public class DelayedSyncController {
|
| * IO operations.
|
| */
|
| @VisibleForTesting
|
| - void requestSyncOnBackgroundThread(final Context context, final Account account) {
|
| + void notifyInvalidationsOnBackgroundThread(
|
| + final Context context, final Account account, final List<Bundle> bundles) {
|
| new AsyncTask<Void, Void, Void>() {
|
| @Override
|
| protected Void doInBackground(Void... unused) {
|
| String contractAuthority = AndroidSyncSettings.getContractAuthority(context);
|
| - ContentResolver.requestSync(account, contractAuthority, new Bundle());
|
| + for (Bundle bundle : bundles) {
|
| + ContentResolver.requestSync(account, contractAuthority, bundle);
|
| + }
|
| return null;
|
| }
|
| }.execute();
|
| @@ -73,40 +85,67 @@ public class DelayedSyncController {
|
| /**
|
| * Stores preferences to indicate that an invalidation has arrived, but dropped on the floor.
|
| */
|
| - void setDelayedSync(Context ctx, String accountName) {
|
| - SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(ctx).edit();
|
| - editor.putString(DELAYED_ACCOUNT_NAME, accountName);
|
| + @VisibleForTesting
|
| + void addPendingInvalidation(Context context, String account, PendingInvalidation invalidation) {
|
| + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
| + String oldAccount = prefs.getString(DELAYED_ACCOUNT_NAME, null);
|
| + Set<String> invals = prefs.getStringSet(DELAYED_INVALIDATIONS, new HashSet<String>(1));
|
| + if (oldAccount != null && !oldAccount.equals(account)) {
|
| + clearPendingInvalidations(context);
|
| + }
|
| + SharedPreferences.Editor editor = prefs.edit();
|
| + editor.putString(DELAYED_ACCOUNT_NAME, account);
|
| + if (invalidation.isInvalidateAll() || (oldAccount != null && invals.size() == 0)) {
|
| + editor.putStringSet(DELAYED_INVALIDATIONS, null);
|
| + } else {
|
| + invals.add(invalidation.toString());
|
| + editor.putStringSet(DELAYED_INVALIDATIONS, invals);
|
| + }
|
| editor.apply();
|
| }
|
|
|
| + private List<Bundle> popPendingInvalidations(final Context context) {
|
| + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
| + assert prefs.contains(DELAYED_ACCOUNT_NAME);
|
| + Set<String> cachedInvalidations = prefs.getStringSet(DELAYED_INVALIDATIONS, null);
|
| + clearPendingInvalidations(context);
|
| + // Absence of specific invalidations indicates invalidate all types.
|
| + if (cachedInvalidations == null) return Arrays.asList(new Bundle());
|
| +
|
| + List<Bundle> bundles = new ArrayList<Bundle>(cachedInvalidations.size());
|
| + for (String invalidation : cachedInvalidations) {
|
| + PendingInvalidation parsedInvalidation = PendingInvalidation.fromString(invalidation);
|
| + if (parsedInvalidation == null) {
|
| + Log.e(TAG, "Error parsing cached invalidation. Invalidating all.");
|
| + return Arrays.asList(new Bundle());
|
| + }
|
| + bundles.add(parsedInvalidation.toBundle());
|
| + }
|
| + return bundles;
|
| + }
|
| +
|
| /**
|
| - * If there is a delayed sync, it will be cleared.
|
| + * If there is a pending invalidation, it will be cleared.
|
| */
|
| @VisibleForTesting
|
| - void clearDelayedSyncs(Context context) {
|
| - setDelayedSync(context, null);
|
| + void clearPendingInvalidations(Context context) {
|
| + SharedPreferences.Editor editor =
|
| + PreferenceManager.getDefaultSharedPreferences(context).edit();
|
| + editor.putString(DELAYED_ACCOUNT_NAME, null);
|
| + editor.putStringSet(DELAYED_INVALIDATIONS, null);
|
| + editor.apply();
|
| }
|
|
|
| @VisibleForTesting
|
| - boolean shouldPerformSync(Context ctx, Bundle extras, Account account) {
|
| - boolean manualSync = isManualSync(extras);
|
| -
|
| - if (manualSync || ApplicationStatus.hasVisibleActivities()) {
|
| - clearDelayedSyncs(ctx);
|
| - return true;
|
| - } else {
|
| - Log.d(TAG, "Delaying sync.");
|
| - setDelayedSync(ctx, account.name);
|
| - return false;
|
| - }
|
| + boolean shouldNotifyInvalidation(Bundle extras) {
|
| + return isManualRequest(extras) || ApplicationStatus.hasVisibleActivities();
|
| }
|
|
|
| - private static boolean isManualSync(Bundle extras) {
|
| - boolean manualSync = false;
|
| + private static boolean isManualRequest(Bundle extras) {
|
| if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)) {
|
| - manualSync = true;
|
| Log.d(TAG, "Manual sync requested.");
|
| + return true;
|
| }
|
| - return manualSync;
|
| + return false;
|
| }
|
| }
|
|
|