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

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: Rebase 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_SCOPE = "scope";
35
36 // Unset/invalid constants for last used times and scopes. 0 is used as the null last
37 // used time 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 SCOPE_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();
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 scope stored in this WebappDataStorage. The scope is the URL
97 * over which the webapp data is applied to.
98 * @param context The context to read the SharedPreferences file.
99 * @param webappId The ID of the web app the used time is being read for.
100 * @param callback Called when the scope has been retrieved.
101 */
102 @VisibleForTesting
103 public static void getScope(final Context context, final String webappId,
104 final FetchCallback<String> callback) {
105 new AsyncTask<Void, Void, String>() {
106 @Override
107 protected final String doInBackground(Void... nothing) {
108 return new WebappDataStorage(context.getApplicationContext(), we bappId)
109 .getScope();
110 }
111
112 @Override
113 protected final void onPostExecute(String scope) {
114 callback.onDataRetrieved(scope);
115 }
116 }.execute();
117 }
118
119 /**
120 * Asynchronously sets the scope stored in this WebappDataStorage. Does noth ing if there
121 * is already a scope stored; since webapps added to homescreen cannot chang e the scope which
122 * they launch, it is not intended that a WebappDataStorage will be able to change the scope
123 * once it is set.
124 * @param context The context to read the SharedPreferences file.
125 * @param webappId The ID of the web app the used time is being read for.
126 * @param scope The scope to set for the web app.
127 */
128 public static void setScope(final Context context, final String webappId, fi nal String scope) {
129 new AsyncTask<Void, Void, Void>() {
130 @Override
131 protected final Void doInBackground(Void... nothing) {
132 new WebappDataStorage(context.getApplicationContext(), webappId) .setScope(scope);
133 return null;
134 }
135 }.execute();
136 }
137
138 /**
89 * Deletes the data for a web app by clearing all the information inside the SharedPreferences 139 * 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. 140 * file. This does NOT delete the file itself but the file is left empty.
91 * @param context The context to read the SharedPreferences file. 141 * @param context The context to read the SharedPreferences file.
92 * @param webappId The ID of the web app being deleted. 142 * @param webappId The ID of the web app being deleted.
93 */ 143 */
94 static void deleteDataForWebapp(final Context context, final String webappId ) { 144 static void deleteDataForWebapp(final Context context, final String webappId ) {
95 assert !ThreadUtils.runningOnUiThread(); 145 assert !ThreadUtils.runningOnUiThread();
96 openSharedPreferences(context, webappId).edit().clear().apply(); 146 openSharedPreferences(context, webappId).edit().clear().apply();
97 } 147 }
98 148
99 /** 149 /**
150 * Deletes the scope and sets last used time to 0 this web app in SharedPref erences.
151 * This does not remove the stored splash screen image (if any) for the app.
152 * @param context The context to read the SharedPreferences file.
153 * @param webappId The ID of the web app being deleted.
154 */
155 static void clearHistory(final Context context, final String webappId) {
156 // The last used time is set to 0 to ensure that a valid value is always present.
157 // If the webapp is not launched prior to the next cleanup, then its rem aining data will be
158 // removed. Otherwise, the next launch will update the last used time.
159 assert !ThreadUtils.runningOnUiThread();
160 openSharedPreferences(context, webappId)
161 .edit().putLong(KEY_LAST_USED, LAST_USED_UNSET).remove(KEY_SCOPE ).apply();
162 }
163
164 /**
100 * Sets the factory used to generate WebappDataStorage objects. 165 * Sets the factory used to generate WebappDataStorage objects.
101 */ 166 */
102 @VisibleForTesting 167 @VisibleForTesting
103 public static void setFactoryForTests(Factory factory) { 168 public static void setFactoryForTests(Factory factory) {
104 sFactory = factory; 169 sFactory = factory;
105 } 170 }
106 171
107 private static SharedPreferences openSharedPreferences(Context context, Stri ng webappId) { 172 private static SharedPreferences openSharedPreferences(Context context, Stri ng webappId) {
108 return context.getApplicationContext().getSharedPreferences( 173 return context.getApplicationContext().getSharedPreferences(
109 SHARED_PREFS_FILE_PREFIX + webappId, Context.MODE_PRIVATE); 174 SHARED_PREFS_FILE_PREFIX + webappId, Context.MODE_PRIVATE);
110 } 175 }
111 176
112 protected WebappDataStorage(Context context, String webappId) { 177 protected WebappDataStorage(Context context, String webappId) {
113 mPreferences = openSharedPreferences(context, webappId); 178 mPreferences = openSharedPreferences(context, webappId);
114 } 179 }
115 180
116 /* 181 /*
117 * Asynchronously retrieves the splash screen image associated with the 182 * Asynchronously retrieves the splash screen image associated with the
118 * current web app. 183 * current web app.
119 * @param callback Called when the splash screen image has been retrieved. 184 * @param callback Called when the splash screen image has been retrieved.
120 * May be null if no image was found. 185 * May be null if no image was found.
121 */ 186 */
122 public void getSplashScreenImage(FetchCallback<Bitmap> callback) { 187 public void getSplashScreenImage(final FetchCallback<Bitmap> callback) {
123 new BitmapFetchTask(KEY_SPLASH_ICON, callback).execute(); 188 new AsyncTask<Void, Void, Bitmap>() {
189 @Override
190 protected final Bitmap doInBackground(Void... nothing) {
191 return ShortcutHelper.decodeBitmapFromString(
192 mPreferences.getString(KEY_SPLASH_ICON, null));
193 }
194
195 @Override
196 protected final void onPostExecute(Bitmap result) {
197 callback.onDataRetrieved(result);
198 }
199 }.execute();
124 } 200 }
125 201
126 /* 202 /*
127 * Update the information associated with the web app with the specified dat a. 203 * 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. 204 * @param splashScreenImage The image which should be shown on the splash sc reen of the web app.
129 */ 205 */
130 public void updateSplashScreenImage(Bitmap splashScreenImage) { 206 public void updateSplashScreenImage(final Bitmap splashScreenImage) {
131 new UpdateTask(splashScreenImage).execute(); 207 new AsyncTask<Void, Void, Void>() {
208 @Override
209 protected final Void doInBackground(Void... nothing) {
210 mPreferences.edit()
211 .putString(KEY_SPLASH_ICON,
212 ShortcutHelper.encodeBitmapAsString(splashScreen Image))
213 .apply();
214 return null;
215 }
216 }.execute();
132 } 217 }
133 218
219 /**
220 * Updates the scope stored in this object. Does nothing if there is already a scope stored.
221 * @param scope the scope to store.
222 */
223 void setScope(String scope) {
224 assert !ThreadUtils.runningOnUiThread();
225 if (mPreferences.getString(KEY_SCOPE, SCOPE_INVALID).equals(SCOPE_INVALI D)) {
226 mPreferences.edit().putString(KEY_SCOPE, scope).apply();
227 }
228 }
229
230 /**
231 * Returns the scope stored in this object, or "" if it is not stored.
232 */
233 String getScope() {
234 assert !ThreadUtils.runningOnUiThread();
235 return mPreferences.getString(KEY_SCOPE, SCOPE_INVALID);
236 }
237
238 /**
239 * Updates the last used time of this object.
240 * @param lastUsedTime the new last used time.
241 */
134 void updateLastUsedTime() { 242 void updateLastUsedTime() {
135 assert !ThreadUtils.runningOnUiThread(); 243 assert !ThreadUtils.runningOnUiThread();
136 mPreferences.edit().putLong(KEY_LAST_USED, System.currentTimeMillis()).a pply(); 244 mPreferences.edit().putLong(KEY_LAST_USED, System.currentTimeMillis()).a pply();
137 } 245 }
138 246
247 /**
248 * Returns the last used time of this object, or -1 if it is not stored.
249 */
139 long getLastUsedTime() { 250 long getLastUsedTime() {
140 assert !ThreadUtils.runningOnUiThread(); 251 assert !ThreadUtils.runningOnUiThread();
141 return mPreferences.getLong(KEY_LAST_USED, INVALID_LAST_USED); 252 return mPreferences.getLong(KEY_LAST_USED, LAST_USED_INVALID);
142 } 253 }
143 254
144 private Map<String, ?> getAllData() { 255 private Map<String, ?> getAllData() {
145 return mPreferences.getAll(); 256 return mPreferences.getAll();
146 } 257 }
147 258
148 /** 259 /**
149 * Called after data has been retrieved from storage. 260 * Called after data has been retrieved from storage.
150 */ 261 */
151 public interface FetchCallback<T> { 262 public interface FetchCallback<T> {
152 public void onDataRetrieved(T readObject); 263 public void onDataRetrieved(T readObject);
153 } 264 }
154 265
155 /** 266 /**
156 * Factory used to generate WebappDataStorage objects. 267 * Factory used to generate WebappDataStorage objects.
157 * 268 *
158 * It is used in tests to override methods in WebappDataStorage and inject t he mocked objects. 269 * It is used in tests to override methods in WebappDataStorage and inject t he mocked objects.
159 */ 270 */
160 public static class Factory { 271 public static class Factory {
161 272
162 /** 273 /**
163 * Generates a WebappDataStorage class for a specified web app. 274 * Generates a WebappDataStorage class for a specified web app.
164 */ 275 */
165 public WebappDataStorage create(final Context context, final String weba ppId) { 276 public WebappDataStorage create(final Context context, final String weba ppId) {
166 return new WebappDataStorage(context, webappId); 277 return new WebappDataStorage(context, webappId);
167 } 278 }
168 } 279 }
169 280 }
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