1a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Copyright 2013 The Chromium Authors. All rights reserved. 2c55a96383497a772a307b346368133960b02ad03Eric Laurent// Use of this source code is governed by a BSD-style license that can be 3c55a96383497a772a307b346368133960b02ad03Eric Laurent// found in the LICENSE file. 4c55a96383497a772a307b346368133960b02ad03Eric Laurent 5c55a96383497a772a307b346368133960b02ad03Eric Laurentpackage org.chromium.chrome.browser.sync; 6c55a96383497a772a307b346368133960b02ad03Eric Laurent 7c55a96383497a772a307b346368133960b02ad03Eric Laurentimport android.accounts.Account; 8e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentimport android.content.ContentResolver; 9e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentimport android.content.Context; 10e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentimport android.content.SharedPreferences; 11e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentimport android.os.AsyncTask; 12e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentimport android.os.Bundle; 13c55a96383497a772a307b346368133960b02ad03Eric Laurentimport android.preference.PreferenceManager; 14c55a96383497a772a307b346368133960b02ad03Eric Laurentimport android.util.Log; 15e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 16e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentimport org.chromium.base.ApplicationStatus; 17e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentimport org.chromium.base.VisibleForTesting; 18e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentimport org.chromium.sync.notifier.SyncStatusHelper; 19e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentimport org.chromium.sync.signin.AccountManagerHelper; 20a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 21a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin/** 22e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * A class for controlling when a sync should be performed immediately, and when it should be 23e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * delayed until Chrome comes to the foreground again. 24e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 25a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinpublic class DelayedSyncController { 26e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent private static final String TAG = "DelayedSyncController"; 27c55a96383497a772a307b346368133960b02ad03Eric Laurent private static final String DELAYED_ACCOUNT_NAME = "delayed_account"; 28e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 29c55a96383497a772a307b346368133960b02ad03Eric Laurent private static class LazyHolder { 30e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent private static final DelayedSyncController INSTANCE = new DelayedSyncController(); 31e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 32e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 33e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent public static DelayedSyncController getInstance() { 34e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return LazyHolder.INSTANCE; 35e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 36e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 37c55a96383497a772a307b346368133960b02ad03Eric Laurent @VisibleForTesting 38e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent DelayedSyncController() {} 39c55a96383497a772a307b346368133960b02ad03Eric Laurent 40c55a96383497a772a307b346368133960b02ad03Eric Laurent /** 41a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * Resume any syncs that were delayed while Chromium was backgrounded. 42c55a96383497a772a307b346368133960b02ad03Eric Laurent */ 43c55a96383497a772a307b346368133960b02ad03Eric Laurent public boolean resumeDelayedSyncs(final Context context) { 445d8e19eb3b3c4b541df50f8eddd6198b4be992a4Przemyslaw Szczepaniak SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 45c55a96383497a772a307b346368133960b02ad03Eric Laurent String accountName = prefs.getString(DELAYED_ACCOUNT_NAME, null); 46c55a96383497a772a307b346368133960b02ad03Eric Laurent if (accountName == null) { 47c55a96383497a772a307b346368133960b02ad03Eric Laurent Log.d(TAG, "No delayed sync."); 48c55a96383497a772a307b346368133960b02ad03Eric Laurent return false; 49792d5464151b0e5744e311ff79eca886e277807bYing Wang } else { 50792d5464151b0e5744e311ff79eca886e277807bYing Wang Log.d(TAG, "Handling delayed sync."); 51792d5464151b0e5744e311ff79eca886e277807bYing Wang Account account = AccountManagerHelper.createAccountFromName(accountName); 52792d5464151b0e5744e311ff79eca886e277807bYing Wang requestSyncOnBackgroundThread(context, account); 53792d5464151b0e5744e311ff79eca886e277807bYing Wang return true; 54792d5464151b0e5744e311ff79eca886e277807bYing Wang } 55792d5464151b0e5744e311ff79eca886e277807bYing Wang } 56c55a96383497a772a307b346368133960b02ad03Eric Laurent 57c55a96383497a772a307b346368133960b02ad03Eric Laurent /** 58c55a96383497a772a307b346368133960b02ad03Eric Laurent * Calls ContentResolver.requestSync() in a separate thread as it performs some blocking 59c55a96383497a772a307b346368133960b02ad03Eric Laurent * IO operations. 60c55a96383497a772a307b346368133960b02ad03Eric Laurent */ 615d8e19eb3b3c4b541df50f8eddd6198b4be992a4Przemyslaw Szczepaniak @VisibleForTesting 625d8e19eb3b3c4b541df50f8eddd6198b4be992a4Przemyslaw Szczepaniak void requestSyncOnBackgroundThread(final Context context, final Account account) { 63e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent new AsyncTask<Void, Void, Void>() { 645d8e19eb3b3c4b541df50f8eddd6198b4be992a4Przemyslaw Szczepaniak @Override 655d8e19eb3b3c4b541df50f8eddd6198b4be992a4Przemyslaw Szczepaniak protected Void doInBackground(Void... unused) { 665d8e19eb3b3c4b541df50f8eddd6198b4be992a4Przemyslaw Szczepaniak String contractAuthority = 675d8e19eb3b3c4b541df50f8eddd6198b4be992a4Przemyslaw Szczepaniak SyncStatusHelper.get(context).getContractAuthority(); 68c55a96383497a772a307b346368133960b02ad03Eric Laurent ContentResolver.requestSync(account, contractAuthority, new Bundle()); 695d8e19eb3b3c4b541df50f8eddd6198b4be992a4Przemyslaw Szczepaniak return null; 70e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 71 }.execute(); 72 } 73 74 /** 75 * Stores preferences to indicate that an invalidation has arrived, but dropped on the floor. 76 */ 77 void setDelayedSync(Context ctx, String accountName) { 78 SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(ctx).edit(); 79 editor.putString(DELAYED_ACCOUNT_NAME, accountName); 80 editor.apply(); 81 } 82 83 /** 84 * If there is a delayed sync, it will be cleared. 85 */ 86 @VisibleForTesting 87 void clearDelayedSyncs(Context context) { 88 setDelayedSync(context, null); 89 } 90 91 @VisibleForTesting 92 boolean shouldPerformSync(Context ctx, Bundle extras, Account account) { 93 boolean manualSync = isManualSync(extras); 94 95 if (manualSync || ApplicationStatus.hasVisibleActivities()) { 96 clearDelayedSyncs(ctx); 97 return true; 98 } else { 99 Log.d(TAG, "Delaying sync."); 100 setDelayedSync(ctx, account.name); 101 return false; 102 } 103 } 104 105 private static boolean isManualSync(Bundle extras) { 106 boolean manualSync = false; 107 if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)) { 108 manualSync = true; 109 Log.d(TAG, "Manual sync requested."); 110 } 111 return manualSync; 112 } 113} 114