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; |
} |
} |