// 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. package org.chromium.chrome.browser.sync.ui; import android.accounts.Account; import android.app.Dialog; import android.app.DialogFragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.ProgressDialog; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.util.Log; import org.chromium.base.library_loader.ProcessInitException; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.sync.ProfileSyncService; import org.chromium.chrome.browser.sync.SyncController; import org.chromium.components.signin.ChromeSigninController; /** * This activity is used for requesting a sync passphrase from the user. Typically, * this will be the target of an Android notification. */ public class PassphraseActivity extends FragmentActivity implements PassphraseDialogFragment.Listener, FragmentManager.OnBackStackChangedListener { public static final String FRAGMENT_PASSPHRASE = "passphrase_fragment"; public static final String FRAGMENT_SPINNER = "spinner_fragment"; private static final String TAG = "PassphraseActivity"; private ProfileSyncService.SyncStateChangedListener mSyncStateChangedListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // The Chrome browser process must be started here because this Activity // may be started explicitly from Android notifications. // During a normal user flow the ChromeTabbedActivity would start the Chrome browser // process and this wouldn't be necessary. try { ChromeBrowserInitializer.getInstance(this).handleSynchronousStartup(); } catch (ProcessInitException e) { Log.e(TAG, "Failed to start browser process.", e); ChromeApplication.reportStartupErrorAndExit(e); return; } assert ProfileSyncService.get() != null; getFragmentManager().addOnBackStackChangedListener(this); } @Override protected void onResume() { super.onResume(); Account account = ChromeSigninController.get(this).getSignedInUser(); if (account == null) { finish(); return; } if (!isShowingDialog(FRAGMENT_PASSPHRASE)) { if (ProfileSyncService.get().isBackendInitialized()) { displayPassphraseDialog(); } else { addSyncStateChangedListener(); displaySpinnerDialog(); } } } @Override protected void onPause() { super.onPause(); // Make sure we don't receive callbacks while in the background. // See http://crbug.com/469890. removeSyncStateChangedListener(); } private void addSyncStateChangedListener() { if (mSyncStateChangedListener != null) { return; } mSyncStateChangedListener = new ProfileSyncService.SyncStateChangedListener() { @Override public void syncStateChanged() { if (ProfileSyncService.get().isBackendInitialized()) { removeSyncStateChangedListener(); displayPassphraseDialog(); } } }; ProfileSyncService.get().addSyncStateChangedListener(mSyncStateChangedListener); } private void removeSyncStateChangedListener() { if (mSyncStateChangedListener != null) { ProfileSyncService.get().removeSyncStateChangedListener(mSyncStateChangedListener); mSyncStateChangedListener = null; } } private boolean isShowingDialog(String tag) { return getFragmentManager().findFragmentByTag(tag) != null; } private void displayPassphraseDialog() { assert ProfileSyncService.get().isBackendInitialized(); FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.addToBackStack(null); PassphraseDialogFragment.newInstance(null).show(ft, FRAGMENT_PASSPHRASE); } private void displaySpinnerDialog() { FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.addToBackStack(null); SpinnerDialogFragment dialog = new SpinnerDialogFragment(); dialog.show(ft, FRAGMENT_SPINNER); } /** * Callback for PassphraseDialogFragment.Listener */ @Override public boolean onPassphraseEntered(String passphrase) { if (!passphrase.isEmpty() && ProfileSyncService.get().setDecryptionPassphrase(passphrase)) { // The passphrase was correct - close this activity. finish(); return true; } return false; } @Override public void onPassphraseCanceled() { // Re add the notification. SyncController.get(this).getSyncNotificationController().syncStateChanged(); finish(); } @Override public void onBackStackChanged() { if (getFragmentManager().getBackStackEntryCount() == 0) { finish(); } } /** * Dialog shown while sync is loading. */ public static class SpinnerDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { ProgressDialog dialog = new ProgressDialog(getActivity()); dialog.setMessage(getResources().getString(R.string.sync_loading)); return dialog; } } }