org.chromium.chrome.browser.sync.SyncNotificationController.java Source code

Java tutorial

Introduction

Here is the source code for org.chromium.chrome.browser.sync.SyncNotificationController.java

Source

// 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.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import org.chromium.base.ThreadUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.notifications.NotificationConstants;
import org.chromium.chrome.browser.notifications.NotificationManagerProxy;
import org.chromium.chrome.browser.notifications.NotificationManagerProxyImpl;
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 NotificationManagerProxy mNotificationManager;
    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();
        mNotificationManager = new NotificationManagerProxyImpl(
                (NotificationManager) mApplicationContext.getSystemService(Context.NOTIFICATION_SERVICE));
        mProfileSyncService = ProfileSyncService.get();
        assert mProfileSyncService != null;
        mPassphraseRequestActivity = passphraseRequestActivity;
        mAccountManagementFragment = accountManagementFragment;
    }

    /**
     * Callback for {@link ProfileSyncService.SyncStateChangedListener}.
     */
    @Override
    public void syncStateChanged() {
        ThreadUtils.assertOnUiThread();

        // Auth errors take precedence over passphrase errors.
        if (!AndroidSyncSettings.isSyncEnabled(mApplicationContext)) {
            mNotificationManager.cancel(NotificationConstants.NOTIFICATION_ID_SYNC);
            return;
        }
        if (shouldSyncAuthErrorBeShown()) {
            showSyncNotification(mProfileSyncService.getAuthError().getMessage(), createSettingsIntent());
        } else if (mProfileSyncService.isEngineInitialized()
                && 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:
                showSyncNotification(R.string.sync_need_passphrase, createPasswordIntent());
                break;
            case KEYSTORE_PASSPHRASE: // Falling through intentionally.
            default:
                mNotificationManager.cancel(NotificationConstants.NOTIFICATION_ID_SYNC);
                return;
            }
        } else {
            mNotificationManager.cancel(NotificationConstants.NOTIFICATION_ID_SYNC);
            return;
        }
    }

    /**
     * Builds and shows a notification for the |message|.
     *
     * @param message Resource id of the message to display in the notification.
     * @param intent Intent to send when the user activates the notification.
     */
    private void showSyncNotification(int message, Intent intent) {
        String title = mApplicationContext.getString(R.string.app_name);
        String text = mApplicationContext.getString(R.string.sign_in_sync) + ": "
                + mApplicationContext.getString(message);

        PendingIntent contentIntent = PendingIntent.getActivity(mApplicationContext, 0, intent, 0);

        // There is no need to provide a group summary notification because the NOTIFICATION_ID_SYNC
        // notification id ensures there's only one sync notification at a time.
        NotificationCompat.Builder builder = new NotificationCompat.Builder(mApplicationContext).setAutoCancel(true)
                .setContentIntent(contentIntent).setContentTitle(title).setContentText(text)
                .setSmallIcon(R.drawable.ic_chrome).setTicker(text).setLocalOnly(true)
                .setGroup(NotificationConstants.GROUP_SYNC);

        Notification notification = new NotificationCompat.BigTextStyle(builder).bigText(text).build();

        mNotificationManager.notify(NotificationConstants.NOTIFICATION_ID_SYNC, notification);
    }

    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;
    }
}