// 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; import android.app.Activity; import android.app.Fragment; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.provider.Settings; import android.util.Log; import org.chromium.base.ThreadUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.notifications.GoogleServicesNotificationController; import org.chromium.chrome.browser.notifications.NotificationConstants; import org.chromium.chrome.browser.preferences.PreferencesLauncher; import org.chromium.components.sync.AndroidSyncSettings; /** * {@link SyncNotificationController} provides functionality for displaying Android notifications * regarding the user sync status. */ public class SyncNotificationController implements ProfileSyncService.SyncStateChangedListener { private static final String TAG = "SyncNotificationController"; private final Context mApplicationContext; private final GoogleServicesNotificationController mNotificationController; private final Class<? extends Activity> mPassphraseRequestActivity; private final Class<? extends Fragment> mAccountManagementFragment; private final ProfileSyncService mProfileSyncService; public SyncNotificationController(Context context, Class<? extends Activity> passphraseRequestActivity, Class<? extends Fragment> accountManagementFragment) { mApplicationContext = context.getApplicationContext(); mNotificationController = GoogleServicesNotificationController.get(context); mProfileSyncService = ProfileSyncService.get(); assert mProfileSyncService != null; mPassphraseRequestActivity = passphraseRequestActivity; mAccountManagementFragment = accountManagementFragment; } public void displayAndroidMasterSyncDisabledNotification() { String masterSyncDisabled = GoogleServicesNotificationController.formatMessageParts(mApplicationContext, R.string.sign_in_sync, R.string.sync_android_master_sync_disabled); mNotificationController.showNotification(masterSyncDisabled.hashCode(), masterSyncDisabled, masterSyncDisabled, new Intent(Settings.ACTION_SYNC_SETTINGS)); } /** * Callback for {@link ProfileSyncService.SyncStateChangedListener}. */ @Override public void syncStateChanged() { ThreadUtils.assertOnUiThread(); int message; Intent intent; // Auth errors take precedence over passphrase errors. if (!AndroidSyncSettings.isSyncEnabled(mApplicationContext)) { mNotificationController.cancelNotification(NotificationConstants.NOTIFICATION_ID_SYNC); return; } if (shouldSyncAuthErrorBeShown()) { message = mProfileSyncService.getAuthError().getMessage(); intent = createSettingsIntent(); } else if (mProfileSyncService.isBackendInitialized() && mProfileSyncService.isPassphraseRequiredForDecryption()) { if (mProfileSyncService.isPassphrasePrompted()) { return; } switch (mProfileSyncService.getPassphraseType()) { case IMPLICIT_PASSPHRASE: // Falling through intentionally. case FROZEN_IMPLICIT_PASSPHRASE: // Falling through intentionally. case CUSTOM_PASSPHRASE: message = R.string.sync_need_passphrase; intent = createPasswordIntent(); break; case KEYSTORE_PASSPHRASE: // Falling through intentionally. default: mNotificationController.cancelNotification( NotificationConstants.NOTIFICATION_ID_SYNC); return; } } else { mNotificationController.cancelNotification(NotificationConstants.NOTIFICATION_ID_SYNC); return; } mNotificationController.updateSingleNotification(NotificationConstants.NOTIFICATION_ID_SYNC, GoogleServicesNotificationController.formatMessageParts( mApplicationContext, R.string.sign_in_sync, message), intent); } private boolean shouldSyncAuthErrorBeShown() { switch (mProfileSyncService.getAuthError()) { case NONE: case CONNECTION_FAILED: case SERVICE_UNAVAILABLE: case REQUEST_CANCELED: case INVALID_GAIA_CREDENTIALS: return false; case USER_NOT_SIGNED_UP: case CAPTCHA_REQUIRED: case ACCOUNT_DELETED: case ACCOUNT_DISABLED: case TWO_FACTOR: return true; default: Log.w(TAG, "Not showing unknown Auth Error: " + mProfileSyncService.getAuthError()); return false; } } /** * Creates an intent that launches the Chrome settings, and automatically opens the fragment * for signed in users. * * @return the intent for opening the settings */ private Intent createSettingsIntent() { return PreferencesLauncher.createIntentForSettingsPage( mApplicationContext, mAccountManagementFragment.getCanonicalName()); } /** * Creates an intent that launches an activity that requests the users password/passphrase. * * @return the intent for opening the password/passphrase activity */ private Intent createPasswordIntent() { // Make sure we don't prompt too many times. mProfileSyncService.setPassphrasePrompted(true); Intent intent = new Intent(Intent.ACTION_MAIN); intent.setComponent(new ComponentName(mApplicationContext, mPassphraseRequestActivity)); intent.addCategory(Intent.CATEGORY_LAUNCHER); // This activity will become the start of a new task on this history stack. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // Clears the task stack above this activity if it already exists. intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); return intent; } }