Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java

Issue 1749603002: Store URLs in WebappDataStorage, and purge them when history is cleared. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressing reviewer comments. Add dependency patchset for unit test hanging Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 {
gone 2016/03/10 23:27:22 Does this need to run in the case when it's invali
dominickn 2016/03/11 05:14:43 No. WebappDataStorage.getLastUsedTime() should onl
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
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.
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) {
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698