forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This enables backup and restore of Chrome's signin state. Most other preferences are not, at present, restored. BUG=607535 Review-Url: https://codereview.chromium.org/1954143002 Cr-Commit-Position: refs/heads/master@{#393840}
- Loading branch information
aberent
authored and
Commit bot
committed
May 16, 2016
1 parent
bac7970
commit 12cf3ae
Showing
12 changed files
with
292 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- Copyright 2015 The Chromium Authors. All rights reserved. | ||
Use of this source code is governed by a BSD-style license that can be | ||
found in the LICENSE file. --> | ||
|
||
<full-backup-content> | ||
<include domain="sharedpref" path="{{manifest_package}}_preferences.xml"/> | ||
</full-backup-content> |
87 changes: 87 additions & 0 deletions
87
chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// Copyright 2016 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
package org.chromium.chrome.browser; | ||
|
||
import android.annotation.TargetApi; | ||
import android.app.backup.BackupAgent; | ||
import android.app.backup.BackupDataInput; | ||
import android.app.backup.BackupDataOutput; | ||
import android.content.SharedPreferences; | ||
import android.os.Build; | ||
import android.os.ParcelFileDescriptor; | ||
import android.preference.PreferenceManager; | ||
|
||
import org.chromium.base.Log; | ||
import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; | ||
import org.chromium.chrome.browser.firstrun.FirstRunStatus; | ||
import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferences; | ||
import org.chromium.sync.signin.ChromeSigninController; | ||
|
||
import java.io.IOException; | ||
import java.util.Arrays; | ||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
/** | ||
* Backup agent for Chrome, filters the restored backup to remove preferences that should not have | ||
* been restored. | ||
*/ | ||
@TargetApi(Build.VERSION_CODES.LOLLIPOP) | ||
public class ChromeBackupAgent extends BackupAgent { | ||
|
||
private static final String TAG = "ChromeBackupAgent"; | ||
|
||
// Lists of preferences that should be restored unchanged. | ||
|
||
// 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). | ||
private static final String[] RESTORED_ANDROID_PREFS = { | ||
PrivacyPreferences.PREF_CRASH_DUMP_UPLOAD, | ||
FirstRunStatus.FIRST_RUN_FLOW_COMPLETE, | ||
FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_SETUP, | ||
}; | ||
|
||
@Override | ||
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, | ||
ParcelFileDescriptor newState) throws IOException { | ||
// No implementation needed for Android 6.0 Auto Backup. Used only on older versions of | ||
// Android Backup | ||
} | ||
|
||
@Override | ||
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) | ||
throws IOException { | ||
// No implementation needed for Android 6.0 Auto Backup. Used only on older versions of | ||
// Android Backup | ||
} | ||
|
||
@Override | ||
public void onRestoreFinished() { | ||
SharedPreferences sharedPrefs = | ||
PreferenceManager.getDefaultSharedPreferences(ChromeBackupAgent.this); | ||
Set<String> prefNames = sharedPrefs.getAll().keySet(); | ||
// Save the user name for later restoration. | ||
String userName = sharedPrefs.getString(ChromeSigninController.SIGNED_IN_ACCOUNT_KEY, null); | ||
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); | ||
} | ||
boolean commitResult = editor.commit(); | ||
|
||
Log.d(TAG, "onRestoreFinished complete; commit result = " + commitResult); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
120 changes: 120 additions & 0 deletions
120
chrome/android/javatests/src/org/chromium/chrome/browser/ChromeBackupIntegrationTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// Copyright 2016 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
package org.chromium.chrome.browser; | ||
|
||
import android.accounts.Account; | ||
import android.annotation.TargetApi; | ||
import android.content.Context; | ||
import android.content.SharedPreferences; | ||
import android.os.Build; | ||
import android.preference.PreferenceManager; | ||
import android.test.suitebuilder.annotation.SmallTest; | ||
|
||
import org.chromium.base.test.util.CommandLineFlags; | ||
import org.chromium.base.test.util.MinAndroidSdkLevel; | ||
import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; | ||
import org.chromium.chrome.browser.firstrun.FirstRunStatus; | ||
import org.chromium.chrome.browser.signin.AccountIdProvider; | ||
import org.chromium.chrome.test.ChromeTabbedActivityTestBase; | ||
import org.chromium.sync.signin.AccountManagerHelper; | ||
import org.chromium.sync.signin.ChromeSigninController; | ||
import org.chromium.sync.test.util.MockAccountManager; | ||
|
||
/** | ||
* Android backup tests. | ||
*/ | ||
@TargetApi(Build.VERSION_CODES.LOLLIPOP) | ||
@CommandLineFlags.Remove({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) | ||
public class ChromeBackupIntegrationTest extends ChromeTabbedActivityTestBase { | ||
|
||
private static final String GOOGLE_ACCOUNT_TYPE = "com.google"; | ||
|
||
@Override | ||
public void startMainActivity() throws InterruptedException { | ||
// Do nothing here, the tests need to do some per-test setup before they start the main | ||
// activity. | ||
} | ||
|
||
private static final class MockAccountIdProvider extends AccountIdProvider { | ||
@Override | ||
public String getAccountId(Context ctx, String accountName) { | ||
return accountName; | ||
} | ||
|
||
@Override | ||
public boolean canBeUsed(Context ctx) { | ||
return true; | ||
} | ||
} | ||
|
||
static class ChromeTestBackupAgent extends ChromeBackupAgent { | ||
ChromeTestBackupAgent(Context context) { | ||
// This is protected in ContextWrapper, so can only be called within a derived | ||
// class. | ||
attachBaseContext(context); | ||
} | ||
} | ||
|
||
@SmallTest | ||
@MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP) | ||
public void testSimpleRestore() throws InterruptedException { | ||
Context targetContext = getInstrumentation().getTargetContext(); | ||
|
||
// Fake having previously gone through FRE and signed in. | ||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(targetContext); | ||
SharedPreferences.Editor preferenceEditor = prefs.edit(); | ||
preferenceEditor.putBoolean(FirstRunStatus.FIRST_RUN_FLOW_COMPLETE, true); | ||
preferenceEditor.putBoolean(FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_SETUP, true); | ||
preferenceEditor.putString(ChromeSigninController.SIGNED_IN_ACCOUNT_KEY, "user1@gmail.com"); | ||
preferenceEditor.commit(); | ||
|
||
Account account = new Account("user1@gmail.com", GOOGLE_ACCOUNT_TYPE); | ||
MockAccountManager accountManager = | ||
new MockAccountManager(targetContext, getInstrumentation().getContext(), account); | ||
AccountManagerHelper.overrideAccountManagerHelperForTests(targetContext, accountManager); | ||
AccountIdProvider.setInstanceForTest(new MockAccountIdProvider()); | ||
|
||
// Run Chrome's restore code. | ||
new ChromeTestBackupAgent(targetContext).onRestoreFinished(); | ||
|
||
// Start Chrome and check that it signs in. | ||
startMainActivityFromLauncher(); | ||
|
||
assertTrue(ChromeSigninController.get(targetContext).isSignedIn()); | ||
assertEquals("user1@gmail.com", | ||
ChromeSigninController.get(targetContext).getSignedInAccountName()); | ||
} | ||
|
||
@SmallTest | ||
@MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP) | ||
public void testRestoreAccountMissing() throws InterruptedException { | ||
Context targetContext = getInstrumentation().getTargetContext(); | ||
|
||
// Fake having previously gone through FRE and signed in. | ||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(targetContext); | ||
SharedPreferences.Editor preferenceEditor = prefs.edit(); | ||
preferenceEditor.putBoolean(FirstRunStatus.FIRST_RUN_FLOW_COMPLETE, true); | ||
preferenceEditor.putBoolean(FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_SETUP, true); | ||
preferenceEditor.putString(ChromeSigninController.SIGNED_IN_ACCOUNT_KEY, "user1@gmail.com"); | ||
preferenceEditor.commit(); | ||
|
||
// Create a mock account manager with a different account | ||
Account account = new Account("user2@gmail.com", GOOGLE_ACCOUNT_TYPE); | ||
MockAccountManager accountManager = | ||
new MockAccountManager(targetContext, getInstrumentation().getContext(), account); | ||
AccountManagerHelper.overrideAccountManagerHelperForTests(targetContext, accountManager); | ||
AccountIdProvider.setInstanceForTest(new MockAccountIdProvider()); | ||
|
||
// Run Chrome's restore code. | ||
new ChromeTestBackupAgent(targetContext).onRestoreFinished(); | ||
|
||
// Start Chrome. | ||
startMainActivityFromLauncher(); | ||
|
||
// Since the account didn't exist, Chrome should not be signed in. | ||
assertFalse(ChromeSigninController.get(targetContext).isSignedIn()); | ||
} | ||
|
||
} |
56 changes: 56 additions & 0 deletions
56
chrome/android/junit/src/org/chromium/chrome/browser/ChromeBackupAgentTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Copyright 2016 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
package org.chromium.chrome.browser; | ||
|
||
import static org.hamcrest.CoreMatchers.equalTo; | ||
import static org.hamcrest.CoreMatchers.nullValue; | ||
import static org.junit.Assert.assertThat; | ||
|
||
import android.content.SharedPreferences; | ||
import android.preference.PreferenceManager; | ||
|
||
import org.chromium.testing.local.LocalRobolectricTestRunner; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.robolectric.Robolectric; | ||
import org.robolectric.annotation.Config; | ||
|
||
/** | ||
* Unit tests for {@link org.chromium.chrome.browser.ChromeBackupAgent}. | ||
*/ | ||
@RunWith(LocalRobolectricTestRunner.class) | ||
@Config(manifest = Config.NONE) | ||
public class ChromeBackupAgentTest { | ||
|
||
static class ChromeTestBackupAgent extends ChromeBackupAgent { | ||
ChromeTestBackupAgent() { | ||
// This is protected in ContextWrapper, so can only be called within a derived | ||
// class. | ||
attachBaseContext(Robolectric.application); | ||
} | ||
} | ||
|
||
@Test | ||
public void testOnRestoreFinished() { | ||
SharedPreferences sharedPrefs = | ||
PreferenceManager.getDefaultSharedPreferences(Robolectric.application); | ||
SharedPreferences.Editor editor = sharedPrefs.edit(); | ||
editor.putBoolean("crash_dump_upload", false); | ||
editor.putString("google.services.username", "user1"); | ||
editor.putString("junk", "junk"); | ||
editor.commit(); | ||
|
||
new ChromeTestBackupAgent().onRestoreFinished(); | ||
|
||
// Check that we have only restored the correct preferences | ||
assertThat(sharedPrefs.getBoolean("crash_dump_upload", true), equalTo(false)); | ||
assertThat(sharedPrefs.getString("google.services.username", null), nullValue()); | ||
assertThat(sharedPrefs.getString("junk", null), nullValue()); | ||
|
||
// Check that the preferences for which there is special code are correct | ||
assertThat(sharedPrefs.getString("first_run_signin_account_name", null), equalTo("user1")); | ||
} | ||
|
||
} |
Oops, something went wrong.