// Copyright 2013 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.sync.signin;

import android.accounts.Account;
import android.content.Context;
import android.preference.PreferenceManager;
import android.util.Log;

import com.google.common.annotations.VisibleForTesting;

import org.chromium.base.ObserverList;

public class ChromeSigninController {
    public interface Listener {
        /**
         * Called when the user signs out of Chrome.
         */
        void onClearSignedInUser();
    }

    public static final String TAG = "ChromeSigninController";

    @VisibleForTesting
    public static final String SIGNED_IN_ACCOUNT_KEY = "google.services.username";

    private static final Object LOCK = new Object();

    private static ChromeSigninController sChromeSigninController;

    private final Context mApplicationContext;

    private final ObserverList<Listener> mListeners = new ObserverList<Listener>();

    private ChromeSigninController(Context context) {
        mApplicationContext = context.getApplicationContext();
    }

    /**
     * A factory method for the ChromeSigninController.
     *
     * @param context the ApplicationContext is retrieved from the context used as an argument.
     * @return a singleton instance of the ChromeSigninController
     */
    public static ChromeSigninController get(Context context) {
        synchronized (LOCK) {
            if (sChromeSigninController == null) {
                sChromeSigninController = new ChromeSigninController(context);
            }
        }
        return sChromeSigninController;
    }

    public Account getSignedInUser() {
        String syncAccountName = getSignedInAccountName();
        if (syncAccountName == null) {
            return null;
        }
        return AccountManagerHelper.createAccountFromName(syncAccountName);
    }

    public boolean isSignedIn() {
        return getSignedInAccountName() != null;
    }

    public void setSignedInAccountName(String accountName) {
        PreferenceManager.getDefaultSharedPreferences(mApplicationContext).edit()
                .putString(SIGNED_IN_ACCOUNT_KEY, accountName)
                .apply();
    }

    public void clearSignedInUser() {
        Log.d(TAG, "Clearing user signed in to Chrome");
        setSignedInAccountName(null);

        for (Listener listener : mListeners) {
            listener.onClearSignedInUser();
        }
    }

    public String getSignedInAccountName() {
        return PreferenceManager.getDefaultSharedPreferences(mApplicationContext)
                .getString(SIGNED_IN_ACCOUNT_KEY, null);
    }

    /**
     * Adds a Listener.
     * @param listener Listener to add.
     */
    public void addListener(Listener listener) {
        mListeners.addObserver(listener);
    }

    /**
     * Removes a Listener.
     * @param listener Listener to remove from the list.
     */
    public void removeListener(Listener listener) {
        mListeners.removeObserver(listener);
    }
}

@@ -259,16 +259,45 @@
 ontext;%0A
+import android.os.AsyncTask;%0A
 import a
@@ -414,16 +414,100 @@
 Testing;
+%0Aimport com.google.ipc.invalidation.external.client.contrib.MultiplexingGcmListener;
 %0A%0Aimport
@@ -1152,24 +1152,62 @@
 stener%3E();%0A%0A
+    private boolean mGcmInitialized;%0A%0A
     private 
@@ -3251,11 +3251,1137 @@
 );%0A    %7D
+%0A%0A    /**%0A     * Registers for Google Cloud Messaging (GCM) if there is no existing registration.%0A     */%0A    public void ensureGcmIsInitialized() %7B%0A        if (mGcmInitialized) return;%0A        mGcmInitialized = true;%0A        new AsyncTask%3CVoid, Void, Void%3E() %7B%0A            @Override%0A            protected Void doInBackground(Void... arg0) %7B%0A                try %7B%0A                    String regId = MultiplexingGcmListener.initializeGcm(mApplicationContext);%0A                    if (!regId.isEmpty())%0A                        Log.d(TAG, %22Already registered with GCM%22);%0A                %7D catch (IllegalStateException exception) %7B%0A                    Log.w(TAG, %22Application manifest does not correctly configure GCM; %22%0A                            + %22sync notifications will not work%22, exception);%0A                %7D catch (UnsupportedOperationException exception) %7B%0A                    Log.w(TAG, %22Device does not support GCM; sync notifications will not work%22,%0A                            exception);%0A                %7D%0A                return null;%0A            %7D%0A        %7D.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);%0A    %7D
 %0A%7D%0A

Add functionality to enable GCM.