OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.sync; | 5 package org.chromium.sync; |
6 | 6 |
7 import android.accounts.Account; | 7 import android.accounts.Account; |
8 import android.content.ContentResolver; | 8 import android.content.ContentResolver; |
9 import android.content.Context; | 9 import android.content.Context; |
10 import android.content.SyncStatusObserver; | 10 import android.content.SyncStatusObserver; |
11 import android.os.StrictMode; | 11 import android.os.StrictMode; |
12 | 12 |
13 import org.chromium.base.ObserverList; | 13 import org.chromium.base.ObserverList; |
14 import org.chromium.base.VisibleForTesting; | 14 import org.chromium.base.VisibleForTesting; |
15 import org.chromium.sync.signin.AccountManagerHelper; | 15 import org.chromium.sync.signin.AccountManagerHelper; |
16 | 16 |
17 import javax.annotation.concurrent.ThreadSafe; | 17 import javax.annotation.concurrent.ThreadSafe; |
18 | 18 |
19 /** | 19 /** |
20 * A helper class to handle the current status of sync for Chrome in Android set
tings. | 20 * A helper class to handle the current status of sync for Chrome in Android set
tings. |
21 * | 21 * |
22 * It also provides an observer to be used whenever Android sync settings change
. | 22 * It also provides an observer to be used whenever Android sync settings change
. |
23 * | 23 * |
24 * To retrieve an instance of this class, call AndroidSyncSettings.get(someConte
xt). | 24 * This class is a collection of static methods so that no references to its obj
ect can be |
| 25 * stored. This is important because tests need to be able to overwrite the obje
ct with a |
| 26 * mock content resolver and know that no references to the old one are cached. |
25 * | 27 * |
26 * This class must be initialized via updateAccount() on startup if the user is
signed in. | 28 * This class must be initialized via updateAccount() on startup if the user is
signed in. |
27 */ | 29 */ |
28 @ThreadSafe | 30 @ThreadSafe |
29 public class AndroidSyncSettings { | 31 public class AndroidSyncSettings { |
30 | 32 |
31 public static final String TAG = "AndroidSyncSettings"; | 33 public static final String TAG = "AndroidSyncSettings"; |
32 | 34 |
33 /** | 35 /** |
34 * Lock for ensuring singleton instantiation across threads. | 36 * Lock for ensuring singleton instantiation across threads. |
35 */ | 37 */ |
36 private static final Object CLASS_LOCK = new Object(); | 38 private static final Object CLASS_LOCK = new Object(); |
37 | 39 |
38 private static AndroidSyncSettings sAndroidSyncSettings; | 40 private static AndroidSyncSettings sInstance; |
39 | 41 |
40 private final Object mLock = new Object(); | 42 private final Object mLock = new Object(); |
41 | 43 |
42 private final String mContractAuthority; | 44 private final String mContractAuthority; |
43 | 45 |
44 private final Context mApplicationContext; | 46 private final Context mApplicationContext; |
45 | 47 |
46 private final SyncContentResolverDelegate mSyncContentResolverDelegate; | 48 private final SyncContentResolverDelegate mSyncContentResolverDelegate; |
47 | 49 |
48 private Account mAccount = null; | 50 private Account mAccount = null; |
49 | 51 |
50 private boolean mIsSyncable = false; | 52 private boolean mIsSyncable = false; |
51 | 53 |
52 private boolean mChromeSyncEnabled = false; | 54 private boolean mChromeSyncEnabled = false; |
53 | 55 |
54 private boolean mMasterSyncEnabled = false; | 56 private boolean mMasterSyncEnabled = false; |
55 | 57 |
56 private final ObserverList<AndroidSyncSettingsObserver> mObservers = | 58 private final ObserverList<AndroidSyncSettingsObserver> mObservers = |
57 new ObserverList<AndroidSyncSettingsObserver>(); | 59 new ObserverList<AndroidSyncSettingsObserver>(); |
58 | 60 |
59 /** | 61 /** |
60 * Provides notifications when Android sync settings have changed. | 62 * Provides notifications when Android sync settings have changed. |
61 */ | 63 */ |
62 public interface AndroidSyncSettingsObserver { | 64 public interface AndroidSyncSettingsObserver { |
63 public void androidSyncSettingsChanged(); | 65 public void androidSyncSettingsChanged(); |
64 } | 66 } |
65 | 67 |
66 /** | 68 private static void ensureInitialized(Context context) { |
67 * A factory method for the AndroidSyncSettings. | |
68 * | |
69 * It is possible to override the {@link SyncContentResolverDelegate} to use
in tests for the | |
70 * instance of the AndroidSyncSettings by calling overrideForTests(...) with | |
71 * your {@link SyncContentResolverDelegate}. | |
72 * | |
73 * @param context the ApplicationContext is retrieved from the context used
as an argument. | |
74 * @return a singleton instance of the AndroidSyncSettings | |
75 */ | |
76 public static AndroidSyncSettings get(Context context) { | |
77 synchronized (CLASS_LOCK) { | 69 synchronized (CLASS_LOCK) { |
78 if (sAndroidSyncSettings == null) { | 70 if (sInstance == null) { |
79 SyncContentResolverDelegate contentResolver = | 71 SyncContentResolverDelegate contentResolver = |
80 new SystemSyncContentResolverDelegate(); | 72 new SystemSyncContentResolverDelegate(); |
81 sAndroidSyncSettings = new AndroidSyncSettings(context, contentR
esolver); | 73 sInstance = new AndroidSyncSettings(context, contentResolver); |
82 } | 74 } |
83 } | 75 } |
84 return sAndroidSyncSettings; | |
85 } | 76 } |
86 | 77 |
87 @VisibleForTesting | 78 @VisibleForTesting |
88 public static void overrideForTests(Context context, | 79 public static void overrideForTests(Context context, |
89 SyncContentResolverDelegate contentResolver) { | 80 SyncContentResolverDelegate contentResolver) { |
90 synchronized (CLASS_LOCK) { | 81 synchronized (CLASS_LOCK) { |
91 sAndroidSyncSettings = new AndroidSyncSettings(context, contentResol
ver); | 82 sInstance = new AndroidSyncSettings(context, contentResolver); |
92 } | 83 } |
93 } | 84 } |
94 | 85 |
95 /** | 86 /** |
96 * @param context the context | 87 * @param context the context the ApplicationContext will be retrieved from. |
97 * @param syncContentResolverDelegate an implementation of {@link SyncConten
tResolverDelegate}. | 88 * @param syncContentResolverDelegate an implementation of {@link SyncConten
tResolverDelegate}. |
98 */ | 89 */ |
99 private AndroidSyncSettings(Context context, | 90 private AndroidSyncSettings(Context context, |
100 SyncContentResolverDelegate syncContentResolverDelegate) { | 91 SyncContentResolverDelegate syncContentResolverDelegate) { |
101 mApplicationContext = context.getApplicationContext(); | 92 mApplicationContext = context.getApplicationContext(); |
102 mSyncContentResolverDelegate = syncContentResolverDelegate; | 93 mSyncContentResolverDelegate = syncContentResolverDelegate; |
103 mContractAuthority = getContractAuthority(); | 94 mContractAuthority = getContractAuthority(); |
104 | 95 |
105 updateCachedSettings(); | 96 updateCachedSettings(); |
106 | 97 |
107 mSyncContentResolverDelegate.addStatusChangeListener( | 98 mSyncContentResolverDelegate.addStatusChangeListener( |
108 ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, | 99 ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, |
109 new AndroidSyncSettingsChangedObserver()); | 100 new AndroidSyncSettingsChangedObserver()); |
110 } | 101 } |
111 | 102 |
112 /** | 103 /** |
113 * Checks whether sync is currently enabled from Chrome for the currently si
gned in account. | 104 * Checks whether sync is currently enabled from Chrome for the currently si
gned in account. |
114 * | 105 * |
115 * It checks both the master sync for the device, and Chrome sync setting fo
r the given account. | 106 * It checks both the master sync for the device, and Chrome sync setting fo
r the given account. |
116 * If no user is currently signed in it returns false. | 107 * If no user is currently signed in it returns false. |
117 * | 108 * |
118 * @return true if sync is on, false otherwise | 109 * @return true if sync is on, false otherwise |
119 */ | 110 */ |
120 public boolean isSyncEnabled() { | 111 public static boolean isSyncEnabled(Context context) { |
121 return mMasterSyncEnabled && mChromeSyncEnabled; | 112 ensureInitialized(context); |
| 113 return sInstance.mMasterSyncEnabled && sInstance.mChromeSyncEnabled; |
122 } | 114 } |
123 | 115 |
124 /** | 116 /** |
125 * Checks whether sync is currently enabled from Chrome for a given account. | 117 * Checks whether sync is currently enabled from Chrome for a given account. |
126 * | 118 * |
127 * It checks only Chrome sync setting for the given account, | 119 * It checks only Chrome sync setting for the given account, |
128 * and ignores the master sync setting. | 120 * and ignores the master sync setting. |
129 * | 121 * |
130 * @return true if sync is on, false otherwise | 122 * @return true if sync is on, false otherwise |
131 */ | 123 */ |
132 public boolean isChromeSyncEnabled() { | 124 public static boolean isChromeSyncEnabled(Context context) { |
133 return mChromeSyncEnabled; | 125 ensureInitialized(context); |
| 126 return sInstance.mChromeSyncEnabled; |
134 } | 127 } |
135 | 128 |
136 /** | 129 /** |
137 * Checks whether the master sync flag for Android is currently enabled. | 130 * Checks whether the master sync flag for Android is currently enabled. |
138 */ | 131 */ |
139 public boolean isMasterSyncEnabled() { | 132 public static boolean isMasterSyncEnabled(Context context) { |
140 return mMasterSyncEnabled; | 133 ensureInitialized(context); |
| 134 return sInstance.mMasterSyncEnabled; |
141 } | 135 } |
142 | 136 |
143 /** | 137 /** |
144 * Make sure Chrome is syncable, and enable sync. | 138 * Make sure Chrome is syncable, and enable sync. |
145 */ | 139 */ |
146 public void enableChromeSync() { | 140 public static void enableChromeSync(Context context) { |
147 setChromeSyncEnabled(true); | 141 ensureInitialized(context); |
| 142 sInstance.setChromeSyncEnabled(true); |
148 } | 143 } |
149 | 144 |
150 /** | 145 /** |
151 * Disables Android Chrome sync | 146 * Disables Android Chrome sync |
152 */ | 147 */ |
153 public void disableChromeSync() { | 148 public static void disableChromeSync(Context context) { |
154 setChromeSyncEnabled(false); | 149 ensureInitialized(context); |
| 150 sInstance.setChromeSyncEnabled(false); |
155 } | 151 } |
156 | 152 |
157 /** | 153 /** |
158 * Must be called when a new account is signed in. | 154 * Must be called when a new account is signed in. |
159 */ | 155 */ |
160 public void updateAccount(Account account) { | 156 public static void updateAccount(Context context, Account account) { |
161 synchronized (mLock) { | 157 ensureInitialized(context); |
162 mAccount = account; | 158 synchronized (sInstance.mLock) { |
163 updateSyncability(); | 159 sInstance.mAccount = account; |
| 160 sInstance.updateSyncability(); |
164 } | 161 } |
165 if (updateCachedSettings()) { | 162 if (sInstance.updateCachedSettings()) { |
166 notifyObservers(); | 163 sInstance.notifyObservers(); |
167 } | 164 } |
168 } | 165 } |
169 | 166 |
170 /** | 167 /** |
171 * Returns the contract authority to use when requesting sync. | 168 * Returns the contract authority to use when requesting sync. |
172 */ | 169 */ |
173 public String getContractAuthority() { | 170 public static String getContractAuthority(Context context) { |
174 return mApplicationContext.getPackageName(); | 171 ensureInitialized(context); |
| 172 return sInstance.getContractAuthority(); |
175 } | 173 } |
176 | 174 |
177 /** | 175 /** |
178 * Add a new AndroidSyncSettingsObserver. | 176 * Add a new AndroidSyncSettingsObserver. |
179 */ | 177 */ |
180 public void registerObserver(AndroidSyncSettingsObserver observer) { | 178 public static void registerObserver(Context context, AndroidSyncSettingsObse
rver observer) { |
181 synchronized (mLock) { | 179 ensureInitialized(context); |
182 mObservers.addObserver(observer); | 180 synchronized (sInstance.mLock) { |
| 181 sInstance.mObservers.addObserver(observer); |
183 } | 182 } |
184 } | 183 } |
185 | 184 |
186 /** | 185 /** |
187 * Remove an AndroidSyncSettingsObserver that was previously added. | 186 * Remove an AndroidSyncSettingsObserver that was previously added. |
188 */ | 187 */ |
189 public void unregisterObserver(AndroidSyncSettingsObserver observer) { | 188 public static void unregisterObserver(Context context, AndroidSyncSettingsOb
server observer) { |
190 synchronized (mLock) { | 189 ensureInitialized(context); |
191 mObservers.removeObserver(observer); | 190 synchronized (sInstance.mLock) { |
| 191 sInstance.mObservers.removeObserver(observer); |
192 } | 192 } |
193 } | 193 } |
194 | 194 |
195 private void setChromeSyncEnabled(boolean value) { | 195 private void setChromeSyncEnabled(boolean value) { |
196 synchronized (mLock) { | 196 synchronized (mLock) { |
197 updateSyncability(); | 197 updateSyncability(); |
198 if (value == mChromeSyncEnabled || mAccount == null) return; | 198 if (value == mChromeSyncEnabled || mAccount == null) return; |
199 mChromeSyncEnabled = value; | 199 mChromeSyncEnabled = value; |
200 | 200 |
201 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites
(); | 201 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites
(); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 return oldChromeSyncEnabled != mChromeSyncEnabled | 283 return oldChromeSyncEnabled != mChromeSyncEnabled |
284 || oldMasterSyncEnabled != mMasterSyncEnabled; | 284 || oldMasterSyncEnabled != mMasterSyncEnabled; |
285 } | 285 } |
286 } | 286 } |
287 | 287 |
288 private void notifyObservers() { | 288 private void notifyObservers() { |
289 for (AndroidSyncSettingsObserver observer : mObservers) { | 289 for (AndroidSyncSettingsObserver observer : mObservers) { |
290 observer.androidSyncSettingsChanged(); | 290 observer.androidSyncSettingsChanged(); |
291 } | 291 } |
292 } | 292 } |
| 293 |
| 294 // TODO(maxbogue): make private once downstream uses are removed. |
| 295 @Deprecated |
| 296 public String getContractAuthority() { |
| 297 return mApplicationContext.getPackageName(); |
| 298 } |
| 299 |
| 300 // Deprecated section; to be removed once downstream no longer uses them. |
| 301 |
| 302 @Deprecated |
| 303 public static AndroidSyncSettings get(Context context) { |
| 304 ensureInitialized(context); |
| 305 return sInstance; |
| 306 } |
| 307 |
| 308 @Deprecated |
| 309 public boolean isSyncEnabled() { |
| 310 return mMasterSyncEnabled && mChromeSyncEnabled; |
| 311 } |
| 312 |
| 313 @Deprecated |
| 314 public boolean isChromeSyncEnabled() { |
| 315 return mChromeSyncEnabled; |
| 316 } |
| 317 |
| 318 @Deprecated |
| 319 public boolean isMasterSyncEnabled() { |
| 320 return mMasterSyncEnabled; |
| 321 } |
| 322 |
| 323 @Deprecated |
| 324 public void enableChromeSync() { |
| 325 setChromeSyncEnabled(true); |
| 326 } |
| 327 |
| 328 @Deprecated |
| 329 public void disableChromeSync() { |
| 330 setChromeSyncEnabled(false); |
| 331 } |
| 332 |
| 333 @Deprecated |
| 334 public void updateAccount(Account account) { |
| 335 synchronized (mLock) { |
| 336 mAccount = account; |
| 337 updateSyncability(); |
| 338 } |
| 339 if (updateCachedSettings()) { |
| 340 notifyObservers(); |
| 341 } |
| 342 } |
| 343 |
| 344 @Deprecated |
| 345 public void registerObserver(AndroidSyncSettingsObserver observer) { |
| 346 synchronized (mLock) { |
| 347 mObservers.addObserver(observer); |
| 348 } |
| 349 } |
| 350 |
| 351 @Deprecated |
| 352 public void unregisterObserver(AndroidSyncSettingsObserver observer) { |
| 353 synchronized (mLock) { |
| 354 mObservers.removeObserver(observer); |
| 355 } |
| 356 } |
293 } | 357 } |
OLD | NEW |