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

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

Issue 1867543002: Enable deep-linking from notifications for recently used web apps on the Android home screen. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@bulk-webappdatastorage
Patch Set: UI thread strikes again Created 4 years, 8 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.Intent; 8 import android.content.Intent;
9 import android.content.SharedPreferences; 9 import android.content.SharedPreferences;
10 import android.graphics.Bitmap; 10 import android.graphics.Bitmap;
11 import android.os.AsyncTask; 11 import android.os.AsyncTask;
12 12
13 import org.chromium.base.ThreadUtils; 13 import org.chromium.base.ThreadUtils;
14 import org.chromium.base.VisibleForTesting; 14 import org.chromium.base.VisibleForTesting;
15 import org.chromium.chrome.browser.ShortcutHelper; 15 import org.chromium.chrome.browser.ShortcutHelper;
16 import org.chromium.chrome.browser.ShortcutSource; 16 import org.chromium.chrome.browser.ShortcutSource;
17 import org.chromium.chrome.browser.util.IntentUtils; 17 import org.chromium.chrome.browser.util.IntentUtils;
18 import org.chromium.content_public.common.ScreenOrientationValues; 18 import org.chromium.content_public.common.ScreenOrientationValues;
19 19
20 import java.util.Map; 20 import java.util.Map;
21 import java.util.concurrent.TimeUnit;
21 22
22 /** 23 /**
23 * Stores data about an installed web app. Uses SharedPreferences to persist the data to disk. 24 * Stores data about an installed web app. Uses SharedPreferences to persist the data to disk.
24 * This class must only be accessed via {@link WebappRegistry}, which is used to register and keep 25 * This class must only be accessed via {@link WebappRegistry}, which is used to register and keep
25 * track of web app data known to Chrome. 26 * track of web app data known to Chrome.
26 */ 27 */
27 public class WebappDataStorage { 28 public class WebappDataStorage {
28 29
29 static final String SHARED_PREFS_FILE_PREFIX = "webapp_"; 30 static final String SHARED_PREFS_FILE_PREFIX = "webapp_";
30 static final String KEY_SPLASH_ICON = "splash_icon"; 31 static final String KEY_SPLASH_ICON = "splash_icon";
31 static final String KEY_LAST_USED = "last_used"; 32 static final String KEY_LAST_USED = "last_used";
32 static final String KEY_URL = "url"; 33 static final String KEY_URL = "url";
33 static final String KEY_SCOPE = "scope"; 34 static final String KEY_SCOPE = "scope";
34 static final String KEY_ICON = "icon"; 35 static final String KEY_ICON = "icon";
35 static final String KEY_NAME = "name"; 36 static final String KEY_NAME = "name";
36 static final String KEY_SHORT_NAME = "short_name"; 37 static final String KEY_SHORT_NAME = "short_name";
37 static final String KEY_ORIENTATION = "orientation"; 38 static final String KEY_ORIENTATION = "orientation";
38 static final String KEY_THEME_COLOR = "theme_color"; 39 static final String KEY_THEME_COLOR = "theme_color";
39 static final String KEY_BACKGROUND_COLOR = "background_color"; 40 static final String KEY_BACKGROUND_COLOR = "background_color";
40 static final String KEY_SOURCE = "source"; 41 static final String KEY_SOURCE = "source";
41 static final String KEY_ACTION = "action"; 42 static final String KEY_ACTION = "action";
42 static final String KEY_IS_ICON_GENERATED = "is_icon_generated"; 43 static final String KEY_IS_ICON_GENERATED = "is_icon_generated";
43 static final String KEY_VERSION = "version"; 44 static final String KEY_VERSION = "version";
45 static final String KEY_LAUNCHED = "launched";
44 46
45 // Unset/invalid constants for last used times and URLs. 0 is used as the nu ll last 47 // Unset/invalid constants for last used times and URLs. 0 is used as the nu ll last
46 // used time as WebappRegistry assumes that this is always a valid timestamp . 48 // used time as WebappRegistry assumes that this is always a valid timestamp .
47 static final long LAST_USED_UNSET = 0; 49 static final long LAST_USED_UNSET = 0;
48 static final long LAST_USED_INVALID = -1; 50 static final long LAST_USED_INVALID = -1;
49 static final String URL_INVALID = ""; 51 static final String URL_INVALID = "";
50 static final int VERSION_INVALID = 0; 52 static final int VERSION_INVALID = 0;
51 53
54 // We use a heuristic to determine whether a web app is still installed on t he homescreen, as
55 // there is no way to do so directly. Any web app which has been opened in t he last ten days
56 // is considered to be still on the homescreen.
57 static final long WEBAPP_LAST_OPEN_MAX_TIME = TimeUnit.DAYS.toMillis(10L);
58
59 private static Clock sClock = new Clock();
52 private static Factory sFactory = new Factory(); 60 private static Factory sFactory = new Factory();
53 61
54 private final String mId; 62 private final String mId;
55 private final SharedPreferences mPreferences; 63 private final SharedPreferences mPreferences;
56 64
57 /** 65 /**
58 * Opens an instance of WebappDataStorage for the web app specified. Must no t be run on the UI 66 * Opens an instance of WebappDataStorage for the web app specified. Must no t be run on the UI
59 * thread. 67 * thread.
60 * @param context The context to open the SharedPreferences. 68 * @param context The context to open the SharedPreferences.
61 * @param webappId The ID of the web app which is being opened. 69 * @param webappId The ID of the web app which is being opened.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 }.execute(); 129 }.execute();
122 } 130 }
123 131
124 /** 132 /**
125 * Asynchronously retrieves the URL stored in this WebappDataStorage. Used i n testing. 133 * Asynchronously retrieves the URL stored in this WebappDataStorage. Used i n testing.
126 * @param context The context to read the SharedPreferences file. 134 * @param context The context to read the SharedPreferences file.
127 * @param webappId The ID of the web app the used time is being read for. 135 * @param webappId The ID of the web app the used time is being read for.
128 * @param callback Called when the URL has been retrieved. 136 * @param callback Called when the URL has been retrieved.
129 */ 137 */
130 @VisibleForTesting 138 @VisibleForTesting
131 public static void getURL(final Context context, final String webappId, 139 public static void getUrl(final Context context, final String webappId,
132 final FetchCallback<String> callback) { 140 final FetchCallback<String> callback) {
133 new AsyncTask<Void, Void, String>() { 141 new AsyncTask<Void, Void, String>() {
134 @Override 142 @Override
135 protected final String doInBackground(Void... nothing) { 143 protected final String doInBackground(Void... nothing) {
136 return new WebappDataStorage(context.getApplicationContext(), we bappId).getURL(); 144 return new WebappDataStorage(context.getApplicationContext(), we bappId).getUrl();
137 } 145 }
138 146
139 @Override 147 @Override
140 protected final void onPostExecute(String url) { 148 protected final void onPostExecute(String url) {
141 assert callback != null; 149 assert callback != null;
142 callback.onDataRetrieved(url); 150 callback.onDataRetrieved(url);
143 } 151 }
144 }.execute(); 152 }.execute();
145 } 153 }
146 154
147 /** 155 /**
148 * Deletes the data for a web app by clearing all the information inside the SharedPreferences 156 * Deletes the data for a web app by clearing all the information inside the SharedPreferences
149 * file. This does NOT delete the file itself but the file is left empty. 157 * file. This does NOT delete the file itself but the file is left empty.
150 * @param context The context to read the SharedPreferences file. 158 * @param context The context to read the SharedPreferences file.
151 * @param webappId The ID of the web app being deleted. 159 * @param webappId The ID of the web app being deleted.
152 */ 160 */
153 static void deleteDataForWebapp(final Context context, final String webappId ) { 161 static void deleteDataForWebapp(final Context context, final String webappId ) {
154 assert !ThreadUtils.runningOnUiThread(); 162 assert !ThreadUtils.runningOnUiThread();
155 openSharedPreferences(context, webappId).edit().clear().apply(); 163 openSharedPreferences(context, webappId).edit().clear().apply();
156 } 164 }
157 165
158 /** 166 /**
159 * Deletes the URL and scope, and sets last used time to 0 in SharedPreferen ces. 167 * Deletes the launched flag, URL and scope, and sets last used time to 0 in SharedPreferences.
160 * This does not remove the stored splash screen image (if any) for the app. 168 * This does not remove the stored splash screen image (if any) for the app.
161 * @param context The context to read the SharedPreferences file. 169 * @param context The context to read the SharedPreferences file.
162 * @param webappId The ID of the web app for which history is being cleared. 170 * @param webappId The ID of the web app for which history is being cleared.
163 */ 171 */
164 static void clearHistory(final Context context, final String webappId) { 172 static void clearHistory(final Context context, final String webappId) {
165 // The last used time is set to 0 to ensure that a valid value is always present. 173 // The last used time is set to 0 to ensure that a valid value is always present.
166 // If the web app is not launched prior to the next cleanup, then its re maining data will be 174 // If the web app is not launched prior to the next cleanup, then its re maining data will be
167 // removed. Otherwise, the next launch will update the last used time. 175 // removed. Otherwise, the next launch from homescreen will update the l ast used time.
gone 2016/04/07 19:10:44 home screen, here and everywhere else
dominickn 2016/04/08 01:10:45 Done.
168 assert !ThreadUtils.runningOnUiThread(); 176 assert !ThreadUtils.runningOnUiThread();
169 openSharedPreferences(context, webappId).edit() 177 openSharedPreferences(context, webappId).edit().putLong(KEY_LAST_USED, L AST_USED_UNSET)
gone 2016/04/07 19:10:44 At this point, should the sharedPreferences just b
dominickn 2016/04/08 01:10:45 Done.
170 .putLong(KEY_LAST_USED, LAST_USED_UNSET).remove(KEY_URL).remove( KEY_SCOPE).apply(); 178 .remove(KEY_LAUNCHED).remove(KEY_URL).remove(KEY_SCOPE).apply();
171 } 179 }
172 180
173 /** 181 /**
182 * Sets the clock used to get the current time.
183 */
184 @VisibleForTesting
185 public static void setClockForTests(Clock clock) {
186 sClock = clock;
187 }
188
189 /**
174 * Sets the factory used to generate WebappDataStorage objects. 190 * Sets the factory used to generate WebappDataStorage objects.
175 */ 191 */
176 @VisibleForTesting 192 @VisibleForTesting
177 public static void setFactoryForTests(Factory factory) { 193 public static void setFactoryForTests(Factory factory) {
178 sFactory = factory; 194 sFactory = factory;
179 } 195 }
180 196
181 private static SharedPreferences openSharedPreferences(Context context, Stri ng webappId) { 197 private static SharedPreferences openSharedPreferences(Context context, Stri ng webappId) {
182 return context.getApplicationContext().getSharedPreferences( 198 return context.getApplicationContext().getSharedPreferences(
183 SHARED_PREFS_FILE_PREFIX + webappId, Context.MODE_PRIVATE); 199 SHARED_PREFS_FILE_PREFIX + webappId, Context.MODE_PRIVATE);
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 /** 335 /**
320 * Returns the scope stored in this object, or URL_INVALID if it is not stor ed. 336 * Returns the scope stored in this object, or URL_INVALID if it is not stor ed.
321 */ 337 */
322 String getScope() { 338 String getScope() {
323 return mPreferences.getString(KEY_SCOPE, URL_INVALID); 339 return mPreferences.getString(KEY_SCOPE, URL_INVALID);
324 } 340 }
325 341
326 /** 342 /**
327 * Returns the URL stored in this object, or URL_INVALID if it is not stored . 343 * Returns the URL stored in this object, or URL_INVALID if it is not stored .
328 */ 344 */
329 String getURL() { 345 String getUrl() {
330 return mPreferences.getString(KEY_URL, URL_INVALID); 346 return mPreferences.getString(KEY_URL, URL_INVALID);
331 } 347 }
332 348
333 /** 349 /**
334 * Updates the last used time of this object. 350 * Updates the last used time of this object.
335 * @param lastUsedTime the new last used time.
336 */ 351 */
337 void updateLastUsedTime() { 352 void updateLastUsedTime() {
338 mPreferences.edit().putLong(KEY_LAST_USED, System.currentTimeMillis()).a pply(); 353 mPreferences.edit().putLong(KEY_LAST_USED, sClock.currentTimeMillis()).a pply();
339 } 354 }
340 355
341 /** 356 /**
342 * Returns the last used time of this object, or -1 if it is not stored. 357 * Returns the last used time of this object, or -1 if it is not stored.
343 */ 358 */
344 long getLastUsedTime() { 359 long getLastUsedTime() {
345 return mPreferences.getLong(KEY_LAST_USED, LAST_USED_INVALID); 360 return mPreferences.getLong(KEY_LAST_USED, LAST_USED_INVALID);
346 } 361 }
347 362
363 /**
364 * Returns true if this web app has been launched from homescreen recently ( within 10 days).
gone 2016/04/07 19:10:44 This seems like a comment that'll go out of sync q
dominickn 2016/04/08 01:10:45 Done.
365 */
366 public boolean wasLaunchedRecently() {
367 // Registering the web app sets the last used time, so we must also ensu re that the web app
368 // has actually been launched. Otherwise, launches from homescreen are t he only occasion
369 // when last used time is updated.
370 return getLaunched()
371 && (sClock.currentTimeMillis() - getLastUsedTime() < WEBAPP_LAST _OPEN_MAX_TIME);
372 }
373
374 /**
375 * Returns true if this web app has been launched from homescreen.
376 */
377 boolean getLaunched() {
378 return mPreferences.getBoolean(KEY_LAUNCHED, false);
379 }
380
381 /**
382 * Marks this web app as having been launched from homescreen.
383 */
384 void setLaunched() {
385 mPreferences.edit().putBoolean(KEY_LAUNCHED, true).apply();
386 }
387
348 private Map<String, ?> getAllData() { 388 private Map<String, ?> getAllData() {
349 return mPreferences.getAll(); 389 return mPreferences.getAll();
350 } 390 }
351 391
352 /** 392 /**
353 * Called after data has been retrieved from storage. 393 * Called after data has been retrieved from storage.
354 */ 394 */
355 public interface FetchCallback<T> { 395 public interface FetchCallback<T> {
356 public void onDataRetrieved(T readObject); 396 public void onDataRetrieved(T readObject);
357 } 397 }
358 398
359 /** 399 /**
360 * Factory used to generate WebappDataStorage objects. 400 * Factory used to generate WebappDataStorage objects.
361 * 401 *
362 * It is used in tests to override methods in WebappDataStorage and inject t he mocked objects. 402 * It is used in tests to override methods in WebappDataStorage and inject t he mocked objects.
363 */ 403 */
364 public static class Factory { 404 public static class Factory {
365 405
366 /** 406 /**
367 * Generates a WebappDataStorage class for a specified web app. 407 * Generates a WebappDataStorage class for a specified web app.
368 */ 408 */
369 public WebappDataStorage create(final Context context, final String weba ppId) { 409 public WebappDataStorage create(final Context context, final String weba ppId) {
370 return new WebappDataStorage(context, webappId); 410 return new WebappDataStorage(context, webappId);
371 } 411 }
372 } 412 }
413
414 /**
415 * Clock used to generate the current time in millseconds for updating and s etting last used
416 * time.
417 */
418 public static class Clock {
419 /**
420 * Returns the current time in milliseconds.
421 */
422 public long currentTimeMillis() {
423 return System.currentTimeMillis();
424 }
425 }
373 } 426 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698