This source file includes following definitions.
- ensureSettingsAreForAccount
 
- clearUpdateStatus
 
- getDidUpdateStatus
 
- getSyncAutomatically
 
- updateSyncSettingsForAccount
 
- setIsSyncable
 
- setSyncAutomatically
 
- updateSyncSettingsForAccountInternal
 
- setIsSyncableInternal
 
- setSyncAutomaticallyInternal
 
- syncSettingsChanged
 
- updateMasterSyncAutomaticallySetting
 
- get
 
- overrideSyncStatusHelperForTests
 
- overrideSyncStatusHelperForTests
 
- getContractAuthority
 
- registerSyncSettingsChangedObserver
 
- unregisterSyncSettingsChangedObserver
 
- isSyncEnabled
 
- isSyncEnabled
 
- isSyncEnabledForChrome
 
- isMasterSyncAutomaticallyEnabled
 
- enableAndroidSync
 
- disableAndroidSync
 
- makeSyncable
 
- onStatusChanged
 
- temporarilyAllowDiskWritesAndDiskReads
 
- getAndClearDidUpdateStatus
 
- notifyObserversIfAccountSettingsChanged
 
- notifyObservers
 
package org.chromium.sync.notifier;
import android.accounts.Account;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SyncStatusObserver;
import android.os.StrictMode;
import com.google.common.annotations.VisibleForTesting;
import org.chromium.base.ObserverList;
import org.chromium.sync.signin.AccountManagerHelper;
import org.chromium.sync.signin.ChromeSigninController;
import javax.annotation.concurrent.NotThreadSafe;
import javax.annotation.concurrent.ThreadSafe;
@ThreadSafe
public class SyncStatusHelper {
    
    @NotThreadSafe
    @VisibleForTesting
    public static class CachedAccountSyncSettings {
        private final String mContractAuthority;
        private final SyncContentResolverDelegate mSyncContentResolverDelegate;
        private Account mAccount;
        private boolean mDidUpdate;
        private boolean mSyncAutomatically;
        private int mIsSyncable;
        public CachedAccountSyncSettings(String contractAuthority,
                SyncContentResolverDelegate contentResolverWrapper) {
            mContractAuthority = contractAuthority;
            mSyncContentResolverDelegate = contentResolverWrapper;
        }
        private void ensureSettingsAreForAccount(Account account) {
            assert account != null;
            if (account.equals(mAccount)) return;
            updateSyncSettingsForAccount(account);
            mDidUpdate = true;
        }
        public void clearUpdateStatus() {
            mDidUpdate = false;
        }
        public boolean getDidUpdateStatus() {
            return mDidUpdate;
        }
        
        public boolean getSyncAutomatically(Account account) {
            ensureSettingsAreForAccount(account);
            return mSyncAutomatically;
        }
        public void updateSyncSettingsForAccount(Account account) {
            if (account == null) return;
            updateSyncSettingsForAccountInternal(account);
        }
        public void setIsSyncable(Account account) {
            ensureSettingsAreForAccount(account);
            if (mIsSyncable == 1) return;
            setIsSyncableInternal(account);
        }
        public void setSyncAutomatically(Account account, boolean value) {
            ensureSettingsAreForAccount(account);
            if (mSyncAutomatically == value) return;
            setSyncAutomaticallyInternal(account, value);
        }
        @VisibleForTesting
        protected void updateSyncSettingsForAccountInternal(Account account) {
            
            if (account == null) return;
            boolean oldSyncAutomatically = mSyncAutomatically;
            int oldIsSyncable = mIsSyncable;
            Account oldAccount = mAccount;
            mAccount = account;
            StrictMode.ThreadPolicy oldPolicy = temporarilyAllowDiskWritesAndDiskReads();
            mSyncAutomatically = mSyncContentResolverDelegate.getSyncAutomatically(
                    account, mContractAuthority);
            mIsSyncable = mSyncContentResolverDelegate.getIsSyncable(account, mContractAuthority);
            StrictMode.setThreadPolicy(oldPolicy);
            mDidUpdate = (oldIsSyncable != mIsSyncable)
                || (oldSyncAutomatically != mSyncAutomatically)
                || (!account.equals(oldAccount));
        }
        @VisibleForTesting
        protected void setIsSyncableInternal(Account account) {
            mIsSyncable = 1;
            StrictMode.ThreadPolicy oldPolicy = temporarilyAllowDiskWritesAndDiskReads();
            mSyncContentResolverDelegate.setIsSyncable(account, mContractAuthority, 1);
            StrictMode.setThreadPolicy(oldPolicy);
            mDidUpdate = true;
        }
        @VisibleForTesting
        protected void setSyncAutomaticallyInternal(Account account, boolean value) {
            mSyncAutomatically = value;
            StrictMode.ThreadPolicy oldPolicy = temporarilyAllowDiskWritesAndDiskReads();
            mSyncContentResolverDelegate.setSyncAutomatically(account, mContractAuthority, value);
            StrictMode.setThreadPolicy(oldPolicy);
            mDidUpdate = true;
        }
    }
    
    public static final String CHROME_SYNC_OAUTH2_SCOPE =
            "https://www.googleapis.com/auth/chromesync";
    public static final String TAG = "SyncStatusHelper";
    
    private static final Object INSTANCE_LOCK = new Object();
    private static SyncStatusHelper sSyncStatusHelper;
    private final String mContractAuthority;
    private final Context mApplicationContext;
    private final SyncContentResolverDelegate mSyncContentResolverDelegate;
    private boolean mCachedMasterSyncAutomatically;
    
    private CachedAccountSyncSettings mCachedSettings;
    private final ObserverList<SyncSettingsChangedObserver> mObservers =
            new ObserverList<SyncSettingsChangedObserver>();
    
    public interface SyncSettingsChangedObserver {
        public void syncSettingsChanged();
    }
    
    private SyncStatusHelper(Context context,
            SyncContentResolverDelegate syncContentResolverDelegate,
            CachedAccountSyncSettings cachedAccountSettings) {
        mApplicationContext = context.getApplicationContext();
        mSyncContentResolverDelegate = syncContentResolverDelegate;
        mContractAuthority = getContractAuthority();
        mCachedSettings = cachedAccountSettings;
        updateMasterSyncAutomaticallySetting();
        mSyncContentResolverDelegate.addStatusChangeListener(
                ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS,
                new AndroidSyncSettingsChangedObserver());
    }
    private void updateMasterSyncAutomaticallySetting() {
        StrictMode.ThreadPolicy oldPolicy = temporarilyAllowDiskWritesAndDiskReads();
        synchronized (mCachedSettings) {
            mCachedMasterSyncAutomatically = mSyncContentResolverDelegate
                    .getMasterSyncAutomatically();
        }
        StrictMode.setThreadPolicy(oldPolicy);
    }
    
    public static SyncStatusHelper get(Context context) {
        synchronized (INSTANCE_LOCK) {
            if (sSyncStatusHelper == null) {
                SyncContentResolverDelegate contentResolverDelegate =
                        new SystemSyncContentResolverDelegate();
                CachedAccountSyncSettings cache = new CachedAccountSyncSettings(
                        context.getPackageName(), contentResolverDelegate);
                sSyncStatusHelper = new SyncStatusHelper(context, contentResolverDelegate, cache);
            }
        }
        return sSyncStatusHelper;
    }
    
    @VisibleForTesting
    public static void overrideSyncStatusHelperForTests(Context context,
            SyncContentResolverDelegate syncContentResolverDelegate,
            CachedAccountSyncSettings cachedAccountSettings) {
        synchronized (INSTANCE_LOCK) {
            if (sSyncStatusHelper != null) {
                throw new IllegalStateException("SyncStatusHelper already exists");
            }
            sSyncStatusHelper = new SyncStatusHelper(context, syncContentResolverDelegate,
                    cachedAccountSettings);
        }
    }
    @VisibleForTesting
    public static void overrideSyncStatusHelperForTests(Context context,
            SyncContentResolverDelegate syncContentResolverDelegate) {
        CachedAccountSyncSettings cachedAccountSettings = new CachedAccountSyncSettings(
                context.getPackageName(), syncContentResolverDelegate);
        overrideSyncStatusHelperForTests(context, syncContentResolverDelegate,
                cachedAccountSettings);
    }
    
    public String getContractAuthority() {
        return mApplicationContext.getPackageName();
    }
    
    public void registerSyncSettingsChangedObserver(SyncSettingsChangedObserver observer) {
        mObservers.addObserver(observer);
    }
    
    public void unregisterSyncSettingsChangedObserver(SyncSettingsChangedObserver observer) {
        mObservers.removeObserver(observer);
    }
    
    public boolean isSyncEnabled(Account account) {
        if (account == null) return false;
        boolean returnValue;
        synchronized (mCachedSettings) {
            returnValue = mCachedMasterSyncAutomatically &&
                mCachedSettings.getSyncAutomatically(account);
        }
        notifyObserversIfAccountSettingsChanged();
        return returnValue;
    }
    
    public boolean isSyncEnabled() {
        return isSyncEnabled(ChromeSigninController.get(mApplicationContext).getSignedInUser());
    }
    
    public boolean isSyncEnabledForChrome(Account account) {
        if (account == null) return false;
        boolean returnValue;
        synchronized (mCachedSettings) {
            returnValue = mCachedSettings.getSyncAutomatically(account);
        }
        notifyObserversIfAccountSettingsChanged();
        return returnValue;
    }
    
    public boolean isMasterSyncAutomaticallyEnabled() {
        synchronized (mCachedSettings) {
            return mCachedMasterSyncAutomatically;
        }
    }
    
    public void enableAndroidSync(Account account) {
        makeSyncable(account);
        synchronized (mCachedSettings) {
            mCachedSettings.setSyncAutomatically(account, true);
        }
        notifyObserversIfAccountSettingsChanged();
    }
    
    public void disableAndroidSync(Account account) {
        synchronized (mCachedSettings) {
            mCachedSettings.setSyncAutomatically(account, false);
        }
        notifyObserversIfAccountSettingsChanged();
    }
    
    private void makeSyncable(Account account) {
        synchronized (mCachedSettings) {
            mCachedSettings.setIsSyncable(account);
        }
        StrictMode.ThreadPolicy oldPolicy = temporarilyAllowDiskWritesAndDiskReads();
        
        
        
        Account[] googleAccounts = AccountManagerHelper.get(mApplicationContext).
                getGoogleAccounts();
        for (Account accountToSetNotSyncable : googleAccounts) {
            if (!accountToSetNotSyncable.equals(account) &&
                    mSyncContentResolverDelegate.getIsSyncable(
                            accountToSetNotSyncable, mContractAuthority) > 0) {
                mSyncContentResolverDelegate.setIsSyncable(accountToSetNotSyncable,
                        mContractAuthority, 0);
            }
        }
        StrictMode.setThreadPolicy(oldPolicy);
    }
    
    private class AndroidSyncSettingsChangedObserver implements SyncStatusObserver {
        @Override
        public void onStatusChanged(int which) {
            if (ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS == which) {
                
                synchronized (mCachedSettings) {
                    mCachedSettings.updateSyncSettingsForAccount(
                            ChromeSigninController.get(mApplicationContext).getSignedInUser());
                }
                boolean oldMasterSyncEnabled = isMasterSyncAutomaticallyEnabled();
                updateMasterSyncAutomaticallySetting();
                boolean didMasterSyncChanged =
                        oldMasterSyncEnabled != isMasterSyncAutomaticallyEnabled();
                
                if (didMasterSyncChanged || getAndClearDidUpdateStatus())
                    notifyObservers();
            }
        }
    }
    
    private static StrictMode.ThreadPolicy temporarilyAllowDiskWritesAndDiskReads() {
        StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
        StrictMode.ThreadPolicy.Builder newPolicy =
                new StrictMode.ThreadPolicy.Builder(oldPolicy);
        newPolicy.permitDiskReads();
        newPolicy.permitDiskWrites();
        StrictMode.setThreadPolicy(newPolicy.build());
        return oldPolicy;
    }
    private boolean getAndClearDidUpdateStatus() {
        boolean didGetStatusUpdate;
        synchronized (mCachedSettings) {
            didGetStatusUpdate = mCachedSettings.getDidUpdateStatus();
            mCachedSettings.clearUpdateStatus();
        }
        return didGetStatusUpdate;
    }
    private void notifyObserversIfAccountSettingsChanged() {
        if (getAndClearDidUpdateStatus()) {
            notifyObservers();
        }
    }
    private void notifyObservers() {
        for (SyncSettingsChangedObserver observer : mObservers) {
            observer.syncSettingsChanged();
        }
    }
}