Chromium Code Reviews| 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.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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |