Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(401)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgent.java

Issue 2750323002: [Android] Histogram for Android restore (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser; 5 package org.chromium.chrome.browser;
6 6
7 import android.app.backup.BackupAgent; 7 import android.app.backup.BackupAgent;
8 import android.app.backup.BackupDataInput; 8 import android.app.backup.BackupDataInput;
9 import android.app.backup.BackupDataOutput; 9 import android.app.backup.BackupDataOutput;
10 import android.content.Context; 10 import android.content.Context;
11 import android.content.SharedPreferences; 11 import android.content.SharedPreferences;
12 import android.os.ParcelFileDescriptor; 12 import android.os.ParcelFileDescriptor;
13 import android.support.annotation.IntDef;
13 14
14 import org.chromium.base.ContextUtils; 15 import org.chromium.base.ContextUtils;
15 import org.chromium.base.Log; 16 import org.chromium.base.Log;
16 import org.chromium.base.PathUtils; 17 import org.chromium.base.PathUtils;
17 import org.chromium.base.ThreadUtils; 18 import org.chromium.base.ThreadUtils;
18 import org.chromium.base.VisibleForTesting; 19 import org.chromium.base.VisibleForTesting;
19 import org.chromium.base.annotations.SuppressFBWarnings; 20 import org.chromium.base.annotations.SuppressFBWarnings;
20 import org.chromium.base.library_loader.ProcessInitException; 21 import org.chromium.base.library_loader.ProcessInitException;
22 import org.chromium.base.metrics.RecordHistogram;
21 import org.chromium.chrome.browser.firstrun.FirstRunGlueImpl; 23 import org.chromium.chrome.browser.firstrun.FirstRunGlueImpl;
22 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; 24 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor;
23 import org.chromium.chrome.browser.firstrun.FirstRunStatus; 25 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
24 import org.chromium.chrome.browser.init.AsyncInitTaskRunner; 26 import org.chromium.chrome.browser.init.AsyncInitTaskRunner;
25 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; 27 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
26 import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager ; 28 import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager ;
27 import org.chromium.components.signin.AccountManagerHelper; 29 import org.chromium.components.signin.AccountManagerHelper;
28 import org.chromium.components.signin.ChromeSigninController; 30 import org.chromium.components.signin.ChromeSigninController;
29 31
30 import java.io.FileInputStream; 32 import java.io.FileInputStream;
31 import java.io.FileOutputStream; 33 import java.io.FileOutputStream;
32 import java.io.IOException; 34 import java.io.IOException;
33 import java.io.ObjectInputStream; 35 import java.io.ObjectInputStream;
34 import java.io.ObjectOutputStream; 36 import java.io.ObjectOutputStream;
37 import java.lang.annotation.Retention;
38 import java.lang.annotation.RetentionPolicy;
35 import java.util.ArrayList; 39 import java.util.ArrayList;
36 import java.util.Arrays; 40 import java.util.Arrays;
37 import java.util.concurrent.Callable; 41 import java.util.concurrent.Callable;
38 import java.util.concurrent.CountDownLatch; 42 import java.util.concurrent.CountDownLatch;
39 import java.util.concurrent.TimeUnit; 43 import java.util.concurrent.TimeUnit;
40 44
41 /** 45 /**
42 * Backup agent for Chrome, using Android key/value backup. 46 * Backup agent for Chrome, using Android key/value backup.
43 */ 47 */
44 48
45 public class ChromeBackupAgent extends BackupAgent { 49 public class ChromeBackupAgent extends BackupAgent {
50 /**
51 *
Bernhard Bauer 2017/03/16 11:36:36 :)
aberent 2017/03/16 12:16:50 Done.
52 */
46 private static final String ANDROID_DEFAULT_PREFIX = "AndroidDefault."; 53 private static final String ANDROID_DEFAULT_PREFIX = "AndroidDefault.";
47 private static final String NATIVE_PREF_PREFIX = "native."; 54 private static final String NATIVE_PREF_PREFIX = "native.";
48 55
49 private static final String TAG = "ChromeBackupAgent"; 56 private static final String TAG = "ChromeBackupAgent";
50 57
58 @VisibleForTesting
59 static final String HISTOGRAM_ANDROID_RESTORE_RESULT = "Android.RestoreResul t";
60 // Restore status is used to pass the result of any restore to Chrome's firs t run, so that
Bernhard Bauer 2017/03/16 11:36:36 Can you leave empty lines before comments?
aberent 2017/03/16 12:16:50 Done here, and where I think it helps readability
Bernhard Bauer 2017/03/16 14:34:01 That's fine, I wouldn't add them there either (or
61 // it can be recorded as a histogram.
62 @Retention(RetentionPolicy.SOURCE)
63 @IntDef({NO_RESTORE, RESTORE_COMPLETED, RESTORE_AFTER_FIRST_RUN, BROWSER_STA RTUP_FAILED,
64 NOT_SIGNED_IN, RESTORE_STATUS_RECORDED})
65 public @interface RestoreStatus {}
66
67 // Values must match those in histogram.xml AndroidRestoreResult.
68 static final int NO_RESTORE = 0;
69 static final int RESTORE_COMPLETED = 1;
70 static final int RESTORE_AFTER_FIRST_RUN = 2;
71 static final int BROWSER_STARTUP_FAILED = 3;
72 static final int NOT_SIGNED_IN = 4;
73 static final int RESTORE_HISTOGRAM_BOUNDARY = 5;
74 // Set RESTORE_STATUS_RECORDED when the histogram has been recorded; so that it is only recorded
75 // once.
76 public static final int RESTORE_STATUS_RECORDED = 5;
77
78 private static final String RESTORE_STATUS = "Android_restore_status";
Bernhard Bauer 2017/03/16 11:36:36 Nit: The combination of uppercase initial and unde
aberent 2017/03/16 12:16:50 Done.
79
51 // Lists of preferences that should be restored unchanged. 80 // Lists of preferences that should be restored unchanged.
52 81
53 static final String[] BACKUP_ANDROID_BOOL_PREFS = { 82 static final String[] BACKUP_ANDROID_BOOL_PREFS = {
54 FirstRunGlueImpl.CACHED_TOS_ACCEPTED_PREF, 83 FirstRunGlueImpl.CACHED_TOS_ACCEPTED_PREF,
55 FirstRunStatus.FIRST_RUN_FLOW_COMPLETE, 84 FirstRunStatus.FIRST_RUN_FLOW_COMPLETE,
56 FirstRunStatus.LIGHTWEIGHT_FIRST_RUN_FLOW_COMPLETE, 85 FirstRunStatus.LIGHTWEIGHT_FIRST_RUN_FLOW_COMPLETE,
57 FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_SETUP, 86 FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_SETUP,
58 PrivacyPreferencesManager.PREF_METRICS_REPORTING, 87 PrivacyPreferencesManager.PREF_METRICS_REPORTING,
59 }; 88 };
60 89
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 239
211 @Override 240 @Override
212 public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDe scriptor newState) 241 public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDe scriptor newState)
213 throws IOException { 242 throws IOException {
214 // TODO(aberent) Check that this is not running on the UI thread. Doing so, however, makes 243 // TODO(aberent) Check that this is not running on the UI thread. Doing so, however, makes
215 // testing difficult since the test code runs on the UI thread. 244 // testing difficult since the test code runs on the UI thread.
216 245
217 // Check that the user hasn't already seen FRE (not sure if this can eve r happen, but if it 246 // Check that the user hasn't already seen FRE (not sure if this can eve r happen, but if it
218 // does then restoring the backup will overwrite the user's choices). 247 // does then restoring the backup will overwrite the user's choices).
219 SharedPreferences sharedPrefs = ContextUtils.getAppSharedPreferences(); 248 SharedPreferences sharedPrefs = ContextUtils.getAppSharedPreferences();
220 if (sharedPrefs.getBoolean(FirstRunStatus.FIRST_RUN_FLOW_COMPLETE, false ) 249 if (FirstRunStatus.getFirstRunFlowComplete()
221 || sharedPrefs.getBoolean( 250 || FirstRunStatus.getLightweightFirstRunFlowComplete()) {
222 FirstRunStatus.LIGHTWEIGHT_FIRST_RUN_FLOW_COMPLETE, f alse)) { 251 setRestoreStatus(RESTORE_AFTER_FIRST_RUN);
223 Log.w(TAG, "Restore attempted after first run"); 252 Log.w(TAG, "Restore attempted after first run");
224 return; 253 return;
225 } 254 }
226 255
227 final ArrayList<String> backupNames = new ArrayList<>(); 256 final ArrayList<String> backupNames = new ArrayList<>();
228 final ArrayList<byte[]> backupValues = new ArrayList<>(); 257 final ArrayList<byte[]> backupValues = new ArrayList<>();
229 258
230 String restoredUserName = null; 259 String restoredUserName = null;
231 while (data.readNextHeader()) { 260 while (data.readNextHeader()) {
232 String key = data.getKey(); 261 String key = data.getKey();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 boolean browserStarted = 302 boolean browserStarted =
274 ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolea n>() { 303 ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolea n>() {
275 @Override 304 @Override
276 public Boolean call() { 305 public Boolean call() {
277 // Start the browser if necessary. 306 // Start the browser if necessary.
278 return initializeBrowser(backupAgent); 307 return initializeBrowser(backupAgent);
279 } 308 }
280 }); 309 });
281 if (!browserStarted) { 310 if (!browserStarted) {
282 // Something went wrong starting Chrome, skip the restore. 311 // Something went wrong starting Chrome, skip the restore.
312 setRestoreStatus(BROWSER_STARTUP_FAILED);
283 return; 313 return;
284 } 314 }
285 // If the user hasn't signed in, or can't sign in, then don't restore an ything. 315 // If the user hasn't signed in, or can't sign in, then don't restore an ything.
286 if (restoredUserName == null || !accountExistsOnDevice(restoredUserName) ) { 316 if (restoredUserName == null || !accountExistsOnDevice(restoredUserName) ) {
317 setRestoreStatus(NOT_SIGNED_IN);
287 Log.i(TAG, "Chrome was not signed in with a known account name, not restoring"); 318 Log.i(TAG, "Chrome was not signed in with a known account name, not restoring");
288 return; 319 return;
289 } 320 }
290 // Restore the native preferences on the UI thread 321 // Restore the native preferences on the UI thread
291 ThreadUtils.runOnUiThreadBlocking(new Runnable() { 322 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
292 @Override 323 @Override
293 public void run() { 324 public void run() {
294 ArrayList<String> nativeBackupNames = new ArrayList<>(); 325 ArrayList<String> nativeBackupNames = new ArrayList<>();
295 boolean[] nativeBackupValues = new boolean[backupNames.size()]; 326 boolean[] nativeBackupValues = new boolean[backupNames.size()];
296 int count = 0; 327 int count = 0;
(...skipping 27 matching lines...) Expand all
324 355
325 // Because FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_COMPLETE is not restored Chrome 356 // Because FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_COMPLETE is not restored Chrome
326 // will sign in the user on first run to the account in FIRST_RUN_FLOW_S IGNIN_ACCOUNT_NAME 357 // will sign in the user on first run to the account in FIRST_RUN_FLOW_S IGNIN_ACCOUNT_NAME
327 // if any. If the rest of FRE has been completed this will happen silent ly. 358 // if any. If the rest of FRE has been completed this will happen silent ly.
328 editor.putString( 359 editor.putString(
329 FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_ACCOUNT_NAME, rest oredUserName); 360 FirstRunSignInProcessor.FIRST_RUN_FLOW_SIGNIN_ACCOUNT_NAME, rest oredUserName);
330 editor.apply(); 361 editor.apply();
331 362
332 // The silent first run will change things, so there is no point in tryi ng to prevent 363 // The silent first run will change things, so there is no point in tryi ng to prevent
333 // additional backups at this stage. Don't write anything to |newState|. 364 // additional backups at this stage. Don't write anything to |newState|.
365 setRestoreStatus(RESTORE_COMPLETED);
334 Log.i(TAG, "Restore complete"); 366 Log.i(TAG, "Restore complete");
335 } 367 }
336 368
337 @VisibleForTesting 369 @VisibleForTesting
338 AsyncInitTaskRunner createAsyncInitTaskRunner(final CountDownLatch latch) { 370 AsyncInitTaskRunner createAsyncInitTaskRunner(final CountDownLatch latch) {
339 return new AsyncInitTaskRunner() { 371 return new AsyncInitTaskRunner() {
340 372
341 @Override 373 @Override
342 protected void onSuccess() { 374 protected void onSuccess() {
343 latch.countDown(); 375 latch.countDown();
344 } 376 }
345 377
346 @Override 378 @Override
347 protected void onFailure() { 379 protected void onFailure() {
348 // Ignore failure. Problems with the variation seed can be ignor ed, and other 380 // Ignore failure. Problems with the variation seed can be ignor ed, and other
349 // problems will either recover or be repeated when Chrome is st arted synchronously. 381 // problems will either recover or be repeated when Chrome is st arted synchronously.
350 latch.countDown(); 382 latch.countDown();
351 } 383 }
352 }; 384 };
353 } 385 }
354 386
387 /**
388 * Get the saved result of any restore that may have happened.
389 *
390 * @return the restore status, a RestoreStatus value.
391 */
392 @VisibleForTesting
393 @RestoreStatus
394 static int getRestoreStatus() {
395 return ContextUtils.getAppSharedPreferences().getInt(RESTORE_STATUS, NO_ RESTORE);
396 }
397
398 /**
399 * Set the restore status
Bernhard Bauer 2017/03/16 11:36:36 Nit: I don't think this comments adds any value.
aberent 2017/03/16 12:16:50 Updated comment.
400 *
401 * @param status the status.
402 */
403 @VisibleForTesting
404 static void setRestoreStatus(@RestoreStatus int status) {
405 ContextUtils.getAppSharedPreferences().edit().putInt(RESTORE_STATUS, sta tus).apply();
406 }
407
408 /**
409 * Record the restore histogram. To be called from Chrome itself once it is running.
410 */
411 static void recordRestoreHistogram() {
412 int restoreStatus = getRestoreStatus();
413 // Ensure restore status is only recorded once
414 if (restoreStatus != RESTORE_STATUS_RECORDED) {
415 RecordHistogram.recordEnumeratedHistogram(
416 HISTOGRAM_ANDROID_RESTORE_RESULT, restoreStatus, RESTORE_HIS TOGRAM_BOUNDARY);
417 setRestoreStatus(RESTORE_STATUS_RECORDED);
418 }
419 }
420
355 @VisibleForTesting 421 @VisibleForTesting
356 protected native String[] nativeGetBoolBackupNames(); 422 protected native String[] nativeGetBoolBackupNames();
357 423
358 @VisibleForTesting 424 @VisibleForTesting
359 protected native boolean[] nativeGetBoolBackupValues(); 425 protected native boolean[] nativeGetBoolBackupValues();
360 426
361 @VisibleForTesting 427 @VisibleForTesting
362 protected native void nativeSetBoolBackupPrefs(String[] name, boolean[] valu e); 428 protected native void nativeSetBoolBackupPrefs(String[] name, boolean[] valu e);
363 } 429 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698