1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.sync.signin; 6 7 import android.accounts.Account; 8 import android.content.Context; 9 import android.os.AsyncTask; 10 import android.preference.PreferenceManager; 11 import android.util.Log; 12 13 import com.google.ipc.invalidation.external.client.contrib.MultiplexingGcmListener; 14 15 import org.chromium.base.CommandLine; 16 import org.chromium.base.ObserverList; 17 import org.chromium.base.VisibleForTesting; 18 import org.chromium.sync.SyncSwitches; 19 20 public class ChromeSigninController { 21 public interface Listener { 22 /** 23 * Called when the user signs out of Chrome. 24 */ 25 void onClearSignedInUser(); 26 } 27 28 public static final String TAG = "ChromeSigninController"; 29 30 @VisibleForTesting 31 public static final String SIGNED_IN_ACCOUNT_KEY = "google.services.username"; 32 33 private static final Object LOCK = new Object(); 34 35 private static ChromeSigninController sChromeSigninController; 36 37 private final Context mApplicationContext; 38 39 private final ObserverList<Listener> mListeners = new ObserverList<Listener>(); 40 41 private boolean mGcmInitialized; 42 43 private ChromeSigninController(Context context) { 44 mApplicationContext = context.getApplicationContext(); 45 } 46 47 /** 48 * A factory method for the ChromeSigninController. 49 * 50 * @param context the ApplicationContext is retrieved from the context used as an argument. 51 * @return a singleton instance of the ChromeSigninController 52 */ 53 public static ChromeSigninController get(Context context) { 54 synchronized (LOCK) { 55 if (sChromeSigninController == null) { 56 sChromeSigninController = new ChromeSigninController(context); 57 } 58 } 59 return sChromeSigninController; 60 } 61 62 public Account getSignedInUser() { 63 String syncAccountName = getSignedInAccountName(); 64 if (syncAccountName == null) { 65 return null; 66 } 67 return AccountManagerHelper.createAccountFromName(syncAccountName); 68 } 69 70 public boolean isSignedIn() { 71 return getSignedInAccountName() != null; 72 } 73 74 public void setSignedInAccountName(String accountName) { 75 PreferenceManager.getDefaultSharedPreferences(mApplicationContext).edit() 76 .putString(SIGNED_IN_ACCOUNT_KEY, accountName) 77 .apply(); 78 } 79 80 public void clearSignedInUser() { 81 Log.d(TAG, "Clearing user signed in to Chrome"); 82 setSignedInAccountName(null); 83 84 for (Listener listener : mListeners) { 85 listener.onClearSignedInUser(); 86 } 87 } 88 89 public String getSignedInAccountName() { 90 return PreferenceManager.getDefaultSharedPreferences(mApplicationContext) 91 .getString(SIGNED_IN_ACCOUNT_KEY, null); 92 } 93 94 /** 95 * Adds a Listener. 96 * @param listener Listener to add. 97 */ 98 public void addListener(Listener listener) { 99 mListeners.addObserver(listener); 100 } 101 102 /** 103 * Removes a Listener. 104 * @param listener Listener to remove from the list. 105 */ 106 public void removeListener(Listener listener) { 107 mListeners.removeObserver(listener); 108 } 109 110 /** 111 * Registers for Google Cloud Messaging (GCM) if there is no existing registration. 112 */ 113 public void ensureGcmIsInitialized() { 114 if (mGcmInitialized) return; 115 mGcmInitialized = true; 116 new AsyncTask<Void, Void, Void>() { 117 @Override 118 protected Void doInBackground(Void... arg0) { 119 if (CommandLine.getInstance().hasSwitch( 120 SyncSwitches.DISABLE_SYNC_GCM_IN_ORDER_TO_TRY_PUSH_API)) { 121 Log.w(TAG, "Sync GCM notifications disabled in order to try Push API!"); 122 return null; 123 } 124 try { 125 String regId = MultiplexingGcmListener.initializeGcm(mApplicationContext); 126 if (!regId.isEmpty()) 127 Log.d(TAG, "Already registered with GCM"); 128 } catch (IllegalStateException exception) { 129 Log.w(TAG, "Application manifest does not correctly configure GCM; " 130 + "sync notifications will not work", exception); 131 } catch (UnsupportedOperationException exception) { 132 Log.w(TAG, "Device does not support GCM; sync notifications will not work", 133 exception); 134 } 135 return null; 136 } 137 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 138 } 139 } 140