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.chrome.browser.webapps; | 5 package org.chromium.chrome.browser.webapps; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.content.SharedPreferences; | 8 import android.content.SharedPreferences; |
9 import android.graphics.Bitmap; | 9 import android.graphics.Bitmap; |
10 import android.os.AsyncTask; | 10 import android.os.AsyncTask; |
(...skipping 13 matching lines...) Expand all Loading... | |
24 * (1) UPDATING/RETRIEVING THE ICON (web app MUST have been registered in Webapp Registry) | 24 * (1) UPDATING/RETRIEVING THE ICON (web app MUST have been registered in Webapp Registry) |
25 * WebappDataStorage storage = WebappDataStorage.open(context, id); | 25 * WebappDataStorage storage = WebappDataStorage.open(context, id); |
26 * storage.updateSplashScreenImage(bitmap); | 26 * storage.updateSplashScreenImage(bitmap); |
27 * storage.getSplashScreenImage(callback); | 27 * storage.getSplashScreenImage(callback); |
28 */ | 28 */ |
29 public class WebappDataStorage { | 29 public class WebappDataStorage { |
30 | 30 |
31 static final String SHARED_PREFS_FILE_PREFIX = "webapp_"; | 31 static final String SHARED_PREFS_FILE_PREFIX = "webapp_"; |
32 static final String KEY_SPLASH_ICON = "splash_icon"; | 32 static final String KEY_SPLASH_ICON = "splash_icon"; |
33 static final String KEY_LAST_USED = "last_used"; | 33 static final String KEY_LAST_USED = "last_used"; |
34 static final long INVALID_LAST_USED = -1; | 34 static final String KEY_ORIGIN_URL = "origin_url"; |
35 | |
36 // Unset/invalid constants for last used times and origins. 0 is used as the null last used time | |
37 // as WebappRegistry assumes that this is always a valid timestamp. | |
38 static final long LAST_USED_UNSET = 0; | |
39 static final long LAST_USED_INVALID = -1; | |
40 static final String ORIGIN_URL_INVALID = ""; | |
35 | 41 |
36 private static Factory sFactory = new Factory(); | 42 private static Factory sFactory = new Factory(); |
37 | 43 |
38 private final SharedPreferences mPreferences; | 44 private final SharedPreferences mPreferences; |
39 | 45 |
40 /** | 46 /** |
41 * Opens an instance of WebappDataStorage for the web app specified. | 47 * Opens an instance of WebappDataStorage for the web app specified. |
42 * @param context The context to open the SharedPreferences. | 48 * @param context The context to open the SharedPreferences. |
43 * @param webappId The ID of the web app which is being opened. | 49 * @param webappId The ID of the web app which is being opened. |
44 */ | 50 */ |
45 public static WebappDataStorage open(final Context context, final String web appId) { | 51 public static WebappDataStorage open(final Context context, final String web appId) { |
46 final WebappDataStorage storage = sFactory.create(context, webappId); | 52 final WebappDataStorage storage = sFactory.create(context, webappId); |
47 new AsyncTask<Void, Void, Void>() { | 53 new AsyncTask<Void, Void, Void>() { |
48 @Override | 54 @Override |
49 protected final Void doInBackground(Void... nothing) { | 55 protected final Void doInBackground(Void... nothing) { |
50 if (storage.getLastUsedTime() == INVALID_LAST_USED) { | 56 if (storage.getLastUsedTime() == LAST_USED_INVALID) { |
51 // If the last used time is invalid then assert that there i s no data | 57 // If the last used time is invalid then assert that there i s no data |
52 // in the WebappDataStorage which needs to be cleaned up. | 58 // in the WebappDataStorage which needs to be cleaned up. |
53 assert storage.getAllData().isEmpty(); | 59 assert storage.getAllData().isEmpty(); |
54 } else { | 60 } else { |
55 storage.updateLastUsedTime(); | 61 storage.updateLastUsedTime(System.currentTimeMillis()); |
56 } | 62 } |
57 return null; | 63 return null; |
58 } | 64 } |
59 }.execute(); | 65 }.execute(); |
60 return storage; | 66 return storage; |
61 } | 67 } |
62 | 68 |
63 /** | 69 /** |
64 * Asynchronously retrieves the time which this WebappDataStorage was last | 70 * Asynchronously retrieves the time which this WebappDataStorage was last |
65 * opened using {@link WebappDataStorage#open(Context, String)}. | 71 * opened using {@link WebappDataStorage#open(Context, String)}. |
66 * @param context The context to read the SharedPreferences file. | 72 * @param context The context to read the SharedPreferences file. |
67 * @param webappId The ID of the web app the used time is being read for. | 73 * @param webappId The ID of the web app the used time is being read for. |
68 * @param callback Called when the last used time has been retrieved. | 74 * @param callback Called when the last used time has been retrieved. |
69 */ | 75 */ |
76 @VisibleForTesting | |
mlamouri (slow - plz ping)
2016/03/16 13:34:28
Can you remove this? I'm pretty sure it is not vis
dominickn
2016/03/17 04:31:26
It's used in the ClearBrowsingDataPreferencesTest,
| |
70 public static void getLastUsedTime(final Context context, final String webap pId, | 77 public static void getLastUsedTime(final Context context, final String webap pId, |
71 final FetchCallback<Long> callback) { | 78 final FetchCallback<Long> callback) { |
72 new AsyncTask<Void, Void, Long>() { | 79 new AsyncTask<Void, Void, Long>() { |
73 @Override | 80 @Override |
74 protected final Long doInBackground(Void... nothing) { | 81 protected final Long doInBackground(Void... nothing) { |
75 long lastUsed = new WebappDataStorage(context.getApplicationCont ext(), webappId) | 82 long lastUsed = new WebappDataStorage(context.getApplicationCont ext(), webappId) |
76 .getLastUsedTime(); | 83 .getLastUsedTime(); |
77 assert lastUsed != INVALID_LAST_USED; | 84 assert lastUsed != LAST_USED_INVALID; |
78 return lastUsed; | 85 return lastUsed; |
79 } | 86 } |
80 | 87 |
81 @Override | 88 @Override |
82 protected final void onPostExecute(Long lastUsed) { | 89 protected final void onPostExecute(Long lastUsed) { |
83 callback.onDataRetrieved(lastUsed); | 90 callback.onDataRetrieved(lastUsed); |
84 } | 91 } |
85 }.execute(); | 92 }.execute(); |
86 } | 93 } |
87 | 94 |
88 /** | 95 /** |
96 * Asynchronously retrieves the origin URL stored in this WebappDataStorage. | |
97 * @param context The context to read the SharedPreferences file. | |
98 * @param webappId The ID of the web app the used time is being read for. | |
99 * @param callback Called when the origin has been retrieved. | |
100 */ | |
101 @VisibleForTesting | |
102 public static void getOriginUrl(final Context context, final String webappId , | |
103 final FetchCallback<String> callback) { | |
104 new AsyncTask<Void, Void, String>() { | |
105 @Override | |
106 protected final String doInBackground(Void... nothing) { | |
107 String originUrl = new WebappDataStorage(context.getApplicationC ontext(), webappId) | |
108 .getOriginUrl(); | |
109 return originUrl; | |
110 } | |
111 | |
112 @Override | |
113 protected final void onPostExecute(String originUrl) { | |
114 callback.onDataRetrieved(originUrl); | |
115 } | |
116 }.execute(); | |
117 } | |
118 | |
119 /** | |
120 * Asynchronously updates the origin URL stored in this WebappDataStorage. | |
121 * @param context The context to read the SharedPreferences file. | |
122 * @param webappId The ID of the web app the used time is being read for. | |
123 * @param origin The origin to set for the web app. | |
124 */ | |
125 public static void updateOriginUrl(final Context context, final String webap pId, | |
126 final String originUrl) { | |
127 new AsyncTask<Void, Void, Void>() { | |
128 @Override | |
129 protected final Void doInBackground(Void... nothing) { | |
130 new WebappDataStorage(context.getApplicationContext(), webappId) | |
131 .updateOriginUrl(originUrl); | |
132 return null; | |
133 } | |
134 }.execute(); | |
135 } | |
136 | |
137 /** | |
89 * Deletes the data for a web app by clearing all the information inside the SharedPreferences | 138 * Deletes the data for a web app by clearing all the information inside the SharedPreferences |
90 * file. This does NOT delete the file itself but the file is left empty. | 139 * file. This does NOT delete the file itself but the file is left empty. |
91 * @param context The context to read the SharedPreferences file. | 140 * @param context The context to read the SharedPreferences file. |
92 * @param webappId The ID of the web app being deleted. | 141 * @param webappId The ID of the web app being deleted. |
93 */ | 142 */ |
94 static void deleteDataForWebapp(final Context context, final String webappId ) { | 143 static void deleteDataForWebapp(final Context context, final String webappId ) { |
95 assert !ThreadUtils.runningOnUiThread(); | 144 assert !ThreadUtils.runningOnUiThread(); |
96 openSharedPreferences(context, webappId).edit().clear().apply(); | 145 openSharedPreferences(context, webappId).edit().clear().apply(); |
97 } | 146 } |
98 | 147 |
99 /** | 148 /** |
149 * Deletes the origin URL and sets last used time to 0 this web app in Share dPreferences. | |
150 * This does not remove the stored splash screen image (if any) for the app. | |
mlamouri (slow - plz ping)
2016/03/16 13:34:28
Deleting the origin sounds odd as in not really re
dominickn
2016/03/17 04:31:26
I guess the combination of having a last used time
mlamouri (slow - plz ping)
2016/03/24 10:36:42
Sure. What I meant is that the splashscreen image
| |
151 * @param context The context to read the SharedPreferences file. | |
152 * @param webappId The ID of the web app being deleted. | |
153 */ | |
154 static void clearHistory(final Context context, final String webappId) { | |
155 // The last used time is set to 0 to ensure that a valid value is always present. | |
156 // If the webapp is not launched prior to the next cleanup, then its rem aining data will be | |
157 // removed. Otherwise, the next launch will update the last used time. | |
158 assert !ThreadUtils.runningOnUiThread(); | |
159 openSharedPreferences(context, webappId) | |
160 .edit().putLong(KEY_LAST_USED, LAST_USED_UNSET).remove(KEY_ORIGI N_URL).apply(); | |
161 } | |
162 | |
163 /** | |
100 * Sets the factory used to generate WebappDataStorage objects. | 164 * Sets the factory used to generate WebappDataStorage objects. |
101 */ | 165 */ |
102 @VisibleForTesting | 166 @VisibleForTesting |
103 public static void setFactoryForTests(Factory factory) { | 167 public static void setFactoryForTests(Factory factory) { |
104 sFactory = factory; | 168 sFactory = factory; |
105 } | 169 } |
106 | 170 |
107 private static SharedPreferences openSharedPreferences(Context context, Stri ng webappId) { | 171 private static SharedPreferences openSharedPreferences(Context context, Stri ng webappId) { |
108 return context.getApplicationContext().getSharedPreferences( | 172 return context.getApplicationContext().getSharedPreferences( |
109 SHARED_PREFS_FILE_PREFIX + webappId, Context.MODE_PRIVATE); | 173 SHARED_PREFS_FILE_PREFIX + webappId, Context.MODE_PRIVATE); |
110 } | 174 } |
111 | 175 |
112 protected WebappDataStorage(Context context, String webappId) { | 176 protected WebappDataStorage(Context context, String webappId) { |
113 mPreferences = openSharedPreferences(context, webappId); | 177 mPreferences = openSharedPreferences(context, webappId); |
114 } | 178 } |
115 | 179 |
116 /* | 180 /* |
117 * Asynchronously retrieves the splash screen image associated with the | 181 * Asynchronously retrieves the splash screen image associated with the |
118 * current web app. | 182 * current web app. |
119 * @param callback Called when the splash screen image has been retrieved. | 183 * @param callback Called when the splash screen image has been retrieved. |
120 * May be null if no image was found. | 184 * May be null if no image was found. |
121 */ | 185 */ |
122 public void getSplashScreenImage(FetchCallback<Bitmap> callback) { | 186 public void getSplashScreenImage(final FetchCallback<Bitmap> callback) { |
123 new BitmapFetchTask(KEY_SPLASH_ICON, callback).execute(); | 187 new AsyncTask<Void, Void, Bitmap>() { |
188 @Override | |
189 protected final Bitmap doInBackground(Void... nothing) { | |
190 return ShortcutHelper.decodeBitmapFromString( | |
191 mPreferences.getString(KEY_SPLASH_ICON, null)); | |
192 } | |
193 | |
194 @Override | |
195 protected final void onPostExecute(Bitmap result) { | |
196 callback.onDataRetrieved(result); | |
197 } | |
198 }.execute(); | |
124 } | 199 } |
125 | 200 |
126 /* | 201 /* |
127 * Update the information associated with the web app with the specified dat a. | 202 * Update the information associated with the web app with the specified dat a. |
128 * @param splashScreenImage The image which should be shown on the splash sc reen of the web app. | 203 * @param splashScreenImage The image which should be shown on the splash sc reen of the web app. |
129 */ | 204 */ |
130 public void updateSplashScreenImage(Bitmap splashScreenImage) { | 205 public void updateSplashScreenImage(final Bitmap splashScreenImage) { |
131 new UpdateTask(splashScreenImage).execute(); | 206 new AsyncTask<Void, Void, Void>() { |
207 @Override | |
208 protected final Void doInBackground(Void... nothing) { | |
209 mPreferences.edit() | |
210 .putString(KEY_SPLASH_ICON, | |
211 ShortcutHelper.encodeBitmapAsString(splashScreen Image)) | |
212 .apply(); | |
213 return null; | |
214 } | |
215 }.execute(); | |
132 } | 216 } |
133 | 217 |
134 void updateLastUsedTime() { | 218 /** |
219 * Updates the origin URL stored in this object. | |
220 * @param originUrl the new origin URL | |
221 */ | |
222 void updateOriginUrl(String originUrl) { | |
135 assert !ThreadUtils.runningOnUiThread(); | 223 assert !ThreadUtils.runningOnUiThread(); |
136 mPreferences.edit().putLong(KEY_LAST_USED, System.currentTimeMillis()).a pply(); | 224 mPreferences.edit().putString(KEY_ORIGIN_URL, originUrl).apply(); |
137 } | 225 } |
138 | 226 |
227 /** | |
228 * Returns the origin URL stored in this object, or "" if it is not stored. | |
229 */ | |
230 String getOriginUrl() { | |
231 assert !ThreadUtils.runningOnUiThread(); | |
232 return mPreferences.getString(KEY_ORIGIN_URL, ORIGIN_URL_INVALID); | |
233 } | |
234 | |
235 /** | |
236 * Updates the last used time of this object. | |
237 * @param lastUsedTime the new last used time. | |
238 */ | |
239 void updateLastUsedTime(long lastUsedTime) { | |
mlamouri (slow - plz ping)
2016/03/16 13:34:28
Did you consider updateLastUsedTime() and resetLas
dominickn
2016/03/17 04:31:26
Originally, the reset method used this mechanism,
| |
240 assert !ThreadUtils.runningOnUiThread(); | |
241 mPreferences.edit().putLong(KEY_LAST_USED, lastUsedTime).apply(); | |
242 } | |
243 | |
244 /** | |
245 * Returns the last used time of this object, or -1 if it is not stored. | |
246 */ | |
139 long getLastUsedTime() { | 247 long getLastUsedTime() { |
140 assert !ThreadUtils.runningOnUiThread(); | 248 assert !ThreadUtils.runningOnUiThread(); |
141 return mPreferences.getLong(KEY_LAST_USED, INVALID_LAST_USED); | 249 return mPreferences.getLong(KEY_LAST_USED, LAST_USED_INVALID); |
142 } | 250 } |
143 | 251 |
144 private Map<String, ?> getAllData() { | 252 private Map<String, ?> getAllData() { |
145 return mPreferences.getAll(); | 253 return mPreferences.getAll(); |
146 } | 254 } |
147 | 255 |
148 /** | 256 /** |
149 * Called after data has been retrieved from storage. | 257 * Called after data has been retrieved from storage. |
150 */ | 258 */ |
151 public interface FetchCallback<T> { | 259 public interface FetchCallback<T> { |
152 public void onDataRetrieved(T readObject); | 260 public void onDataRetrieved(T readObject); |
153 } | 261 } |
154 | 262 |
155 /** | 263 /** |
156 * Factory used to generate WebappDataStorage objects. | 264 * Factory used to generate WebappDataStorage objects. |
157 * | 265 * |
158 * It is used in tests to override methods in WebappDataStorage and inject t he mocked objects. | 266 * It is used in tests to override methods in WebappDataStorage and inject t he mocked objects. |
159 */ | 267 */ |
160 public static class Factory { | 268 public static class Factory { |
161 | 269 |
162 /** | 270 /** |
163 * Generates a WebappDataStorage class for a specified web app. | 271 * Generates a WebappDataStorage class for a specified web app. |
164 */ | 272 */ |
165 public WebappDataStorage create(final Context context, final String weba ppId) { | 273 public WebappDataStorage create(final Context context, final String weba ppId) { |
166 return new WebappDataStorage(context, webappId); | 274 return new WebappDataStorage(context, webappId); |
167 } | 275 } |
168 } | 276 } |
169 | 277 } |
170 private final class BitmapFetchTask extends AsyncTask<Void, Void, Bitmap> { | |
171 | |
172 private final String mKey; | |
173 private final FetchCallback<Bitmap> mCallback; | |
174 | |
175 public BitmapFetchTask(String key, FetchCallback<Bitmap> callback) { | |
176 mKey = key; | |
177 mCallback = callback; | |
178 } | |
179 | |
180 @Override | |
181 protected final Bitmap doInBackground(Void... nothing) { | |
182 return ShortcutHelper.decodeBitmapFromString(mPreferences.getString( mKey, null)); | |
183 } | |
184 | |
185 @Override | |
186 protected final void onPostExecute(Bitmap result) { | |
187 mCallback.onDataRetrieved(result); | |
188 } | |
189 } | |
190 | |
191 private final class UpdateTask extends AsyncTask<Void, Void, Void> { | |
192 | |
193 private final Bitmap mSplashImage; | |
194 | |
195 public UpdateTask(Bitmap splashImage) { | |
196 mSplashImage = splashImage; | |
197 } | |
198 | |
199 @Override | |
200 protected Void doInBackground(Void... nothing) { | |
201 mPreferences.edit() | |
202 .putString(KEY_SPLASH_ICON, ShortcutHelper.encodeBitmapAsStr ing(mSplashImage)) | |
203 .apply(); | |
204 return null; | |
205 } | |
206 } | |
207 } | |
OLD | NEW |