Index: chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgent.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgent.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgent.java |
index 172cf787a6735082de3422e6ccd2e94d5fbcee8e..360b0dbcbe99e70439b78089a227c5d89672ba31 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgent.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgent.java |
@@ -4,6 +4,8 @@ |
package org.chromium.chrome.browser; |
+import android.accounts.Account; |
+import android.accounts.AccountManager; |
import android.annotation.TargetApi; |
import android.app.backup.BackupAgent; |
import android.app.backup.BackupDataInput; |
@@ -14,6 +16,7 @@ import android.os.ParcelFileDescriptor; |
import org.chromium.base.ContextUtils; |
import org.chromium.base.Log; |
+import org.chromium.base.VisibleForTesting; |
import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; |
import org.chromium.chrome.browser.firstrun.FirstRunStatus; |
import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferences; |
@@ -27,6 +30,10 @@ import java.util.Set; |
/** |
* Backup agent for Chrome, filters the restored backup to remove preferences that should not have |
* been restored. |
+ * |
+ * Note: Nothing in this class can depend on the ChromeApplication instance having been created. |
+ * During restore Android creates a special instance of the Chrome application with its own |
+ * Android defined application class, which is not derived from ChromeApplication. |
*/ |
@TargetApi(Build.VERSION_CODES.LOLLIPOP) |
public class ChromeBackupAgent extends BackupAgent { |
@@ -37,15 +44,17 @@ public class ChromeBackupAgent extends BackupAgent { |
// TODO(aberent): At present this only restores the signed in user, and the FRE settings |
// (whether is has been completed, and whether the user disabled crash dump reporting). It |
- // should restore all non-device specific aspects of the user's state. This will involve both |
- // restoring many more Android preferences and many Chrome preferences (in Chrome's JSON |
- // preference file). |
+ // should also restore all the user's sync choices. This will involve restoring a number of |
+ // Chrome preferences (in Chrome's JSON preference file) in addition to the Android preferences |
+ // currently restored. |
private static final String[] RESTORED_ANDROID_PREFS = { |
PrivacyPreferences.PREF_CRASH_DUMP_UPLOAD, |
FirstRunStatus.FIRST_RUN_FLOW_COMPLETE, |
FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_SETUP, |
}; |
+ private static boolean sAllowChromeApplication = false; |
+ |
@Override |
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, |
ParcelFileDescriptor newState) throws IOException { |
@@ -60,27 +69,61 @@ public class ChromeBackupAgent extends BackupAgent { |
// Android Backup |
} |
+ // May be overriden by downstream products that access account information in a different way. |
+ protected Account[] getAccounts() { |
+ Log.d(TAG, "Getting accounts from AccountManager"); |
+ AccountManager manager = (AccountManager) getSystemService(ACCOUNT_SERVICE); |
+ return manager.getAccounts(); |
+ } |
+ |
+ private boolean accountExistsOnDevice(String userName) { |
+ // This cannot use AccountManagerHelper, since that depends on ChromeApplication. |
+ for (Account account: getAccounts()) { |
+ if (account.name.equals(userName)) return true; |
+ } |
+ return false; |
+ } |
+ |
@Override |
public void onRestoreFinished() { |
+ if (getApplicationContext() instanceof ChromeApplication && !sAllowChromeApplication) { |
+ // This should never happen in real use, but will happen during testing if Chrome is |
+ // already running (even in background, started to provide a service, for example). |
+ Log.w(TAG, "Running with wrong type of Application class"); |
+ return; |
+ } |
+ // This is running without a ChromeApplication instance, so this has to be done here. |
+ ContextUtils.initApplicationContext(getApplicationContext()); |
SharedPreferences sharedPrefs = ContextUtils.getAppSharedPreferences(); |
Set<String> prefNames = sharedPrefs.getAll().keySet(); |
// Save the user name for later restoration. |
String userName = sharedPrefs.getString(ChromeSigninController.SIGNED_IN_ACCOUNT_KEY, null); |
+ Log.d(TAG, "Previous signed in user name = " + userName); |
+ // If the user hasn't signed in, or can't sign in, then don't restore anything. |
+ if (userName == null || !accountExistsOnDevice(userName)) { |
+ boolean commitResult = sharedPrefs.edit().clear().commit(); |
+ Log.d(TAG, "onRestoreFinished complete, nothing restored; commit result = %s", |
+ commitResult); |
+ return; |
+ } |
+ |
SharedPreferences.Editor editor = sharedPrefs.edit(); |
// Throw away prefs we don't want to restore. |
Set<String> restoredPrefs = new HashSet<>(Arrays.asList(RESTORED_ANDROID_PREFS)); |
for (String pref : prefNames) { |
- Log.d(TAG, "Checking pref " + pref); |
if (!restoredPrefs.contains(pref)) editor.remove(pref); |
} |
// Because FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_COMPLETE is not restored Chrome |
// will sign in the user on first run to the account in FIRST_RUN_FLOW_SIGNIN_ACCOUNT_NAME |
// if any. If the rest of FRE has been completed this will happen silently. |
- if (userName != null) { |
- editor.putString(FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_ACCOUNT_NAME, userName); |
- } |
+ editor.putString(FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_ACCOUNT_NAME, userName); |
boolean commitResult = editor.commit(); |
- Log.d(TAG, "onRestoreFinished complete; commit result = " + commitResult); |
+ Log.d(TAG, "onRestoreFinished complete; commit result = %s", commitResult); |
+ } |
+ |
+ @VisibleForTesting |
+ static void allowChromeApplicationForTesting() { |
+ sAllowChromeApplication = true; |
} |
} |