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

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

Issue 2390753004: Revert of [Reland] Refactor WebappRegistry into a singleton instance. (Closed)
Patch Set: Created 4 years, 2 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.content.pm.PackageManager; 9 import android.content.pm.PackageManager;
10 import android.content.pm.PackageManager.NameNotFoundException; 10 import android.content.pm.PackageManager.NameNotFoundException;
11 import android.os.AsyncTask; 11 import android.os.AsyncTask;
12 12
13 import org.chromium.base.ContextUtils; 13 import org.chromium.base.ContextUtils;
14 import org.chromium.base.ThreadUtils;
14 import org.chromium.base.VisibleForTesting; 15 import org.chromium.base.VisibleForTesting;
15 import org.chromium.base.annotations.CalledByNative; 16 import org.chromium.base.annotations.CalledByNative;
16 import org.chromium.chrome.browser.browsing_data.UrlFilter; 17 import org.chromium.chrome.browser.browsing_data.UrlFilter;
17 import org.chromium.chrome.browser.browsing_data.UrlFilterBridge; 18 import org.chromium.chrome.browser.browsing_data.UrlFilterBridge;
18 19
19 import java.util.Collections; 20 import java.util.Collections;
20 import java.util.HashMap; 21 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.Set; 22 import java.util.Set;
23 import java.util.concurrent.TimeUnit; 23 import java.util.concurrent.TimeUnit;
24 24
25 /** 25 /**
26 * Singleton class which tracks web apps backed by a SharedPreferences file (abs tracted by the 26 * Keeps track of web apps which have created a SharedPreference file (through t he used of the
27 * WebappDataStorage class). This class must be used on the main thread, except when warming 27 * WebappDataStorage class) which may need to be cleaned up in the future.
28 * SharedPreferences.
29 * 28 *
30 * Aside from web app registration, which is asynchronous as a new SharedPrefere nces file must be 29 * It is NOT intended to be 100% accurate nor a comprehensive list of all instal led web apps
31 * opened, all methods in this class are synchronous. All web app SharedPreferen ces known to 30 * because it is impossible to track when the user removes a web app from the Ho me screen and it
32 * WebappRegistry are pre-warmed on browser startup when creating the singleton WebappRegistry 31 * is similarily impossible to track pre-registry era web apps (this case is not a problem anyway
33 * instance, whilst registering a new web app will automatically cache the new S haredPreferences 32 * as these web apps have no external data to cleanup).
34 * after it is created.
35 *
36 * This class is not a comprehensive list of installed web apps because it is im possible to know
37 * when the user removes a web app from the home screen. The WebappDataStorage.w asLaunchedRecently()
38 * heuristic attempts to compensate for this.
39 */ 33 */
40 public class WebappRegistry { 34 public class WebappRegistry {
41 35
42 static final String REGISTRY_FILE_NAME = "webapp_registry"; 36 static final String REGISTRY_FILE_NAME = "webapp_registry";
43 static final String KEY_WEBAPP_SET = "webapp_set"; 37 static final String KEY_WEBAPP_SET = "webapp_set";
44 static final String KEY_LAST_CLEANUP = "last_cleanup"; 38 static final String KEY_LAST_CLEANUP = "last_cleanup";
45 39
46 /** Represents a period of 4 weeks in milliseconds */ 40 /** Represents a period of 4 weeks in milliseconds */
47 static final long FULL_CLEANUP_DURATION = TimeUnit.DAYS.toMillis(4L * 7L); 41 static final long FULL_CLEANUP_DURATION = TimeUnit.DAYS.toMillis(4L * 7L);
48 42
49 /** Represents a period of 13 weeks in milliseconds */ 43 /** Represents a period of 13 weeks in milliseconds */
50 static final long WEBAPP_UNOPENED_CLEANUP_DURATION = TimeUnit.DAYS.toMillis( 13L * 7L); 44 static final long WEBAPP_UNOPENED_CLEANUP_DURATION = TimeUnit.DAYS.toMillis( 13L * 7L);
51 45
52 private static volatile WebappRegistry sInstance; 46 /**
53 47 * Called when a retrieval of the set of stored web app IDs occurs.
54 private HashMap<String, WebappDataStorage> mStorages; 48 */
55 private SharedPreferences mPreferences; 49 public interface FetchCallback {
50 void onWebappIdsRetrieved(Set<String> readObject);
51 }
56 52
57 /** 53 /**
58 * Callback run when a WebappDataStorage object is registered for the first time. The storage 54 * Called when a retrieval of the stored WebappDataStorage occurs. The stora ge parameter will
59 * parameter will never be null. 55 * be null if the web app queried for was not in the registry.
60 */ 56 */
61 public interface FetchWebappDataStorageCallback { 57 public interface FetchWebappDataStorageCallback {
62 void onWebappDataStorageRetrieved(WebappDataStorage storage); 58 void onWebappDataStorageRetrieved(WebappDataStorage storage);
63 } 59 }
64 60
65 /** 61 /**
66 * Returns the singleton WebappRegistry instance. Creates the instance if ne cessary.
67 */
68 public static WebappRegistry getInstance() {
69 if (sInstance == null) sInstance = new WebappRegistry();
70 return sInstance;
71 }
72
73 /**
74 * Warm up the WebappRegistry and a specific WebappDataStorage SharedPrefere nces. This static
75 * method can be called on any thread, so it must not initialize sInstance.
76 * @param id The web app id to warm up in addition to the WebappRegistry.
77 */
78 public static void warmUpSharedPrefsForId(String id) {
79 sInstance.initStorages(id, false);
80 }
81
82 /**
83 * Warm up the WebappRegistry and all WebappDataStorage SharedPreferences. T his static method
84 * can be called on any thread, so it must not initialize sInstance.
85 */
86 public static void warmUpSharedPrefs() {
87 sInstance.initStorages(null, false);
88 }
89
90 public static void refreshSharedPrefsForTesting() {
91 sInstance = new WebappRegistry();
92 sInstance.initStorages(null, true);
93 }
94
95 /**
96 * Registers the existence of a web app, creates a SharedPreference entry fo r it, and runs the 62 * Registers the existence of a web app, creates a SharedPreference entry fo r it, and runs the
97 * supplied callback (if not null) on the UI thread with the resulting Webap pDataStorage object. 63 * supplied callback (if not null) on the UI thread with the resulting Webap pDataStorage object.
98 * @param webappId The id of the web app to register. 64 * @param webappId The id of the web app to register.
99 * @param callback The callback to run with the WebappDataStorage argument. 65 * @param callback The callback to run with the WebappDataStorage argument.
100 * @return The storage object for the web app. 66 * @return The storage object for the web app.
101 */ 67 */
102 public void register(final String webappId, final FetchWebappDataStorageCall back callback) { 68 public static void registerWebapp(final String webappId,
69 final FetchWebappDataStorageCallback callback) {
103 new AsyncTask<Void, Void, WebappDataStorage>() { 70 new AsyncTask<Void, Void, WebappDataStorage>() {
104 @Override 71 @Override
105 protected final WebappDataStorage doInBackground(Void... nothing) { 72 protected final WebappDataStorage doInBackground(Void... nothing) {
106 // Create the WebappDataStorage on the background thread, as thi s must create and 73 SharedPreferences preferences = openSharedPreferences();
107 // open a new SharedPreferences. 74 // The set returned by getRegisteredWebappIds must be treated as immutable, so we
108 return WebappDataStorage.open(webappId); 75 // make a copy to edit and save.
76 Set<String> webapps = new HashSet<>(getRegisteredWebappIds(prefe rences));
77 boolean added = webapps.add(webappId);
78 assert added;
79
80 preferences.edit().putStringSet(KEY_WEBAPP_SET, webapps).apply() ;
81
82 // Create the WebappDataStorage and update the last used time, s o we can guarantee
83 // that a web app which appears in the registry will have a
84 // last used time != WebappDataStorage.LAST_USED_INVALID.
85 WebappDataStorage storage = new WebappDataStorage(webappId);
86 storage.updateLastUsedTime();
87 return storage;
109 } 88 }
110 89
111 @Override 90 @Override
112 protected final void onPostExecute(WebappDataStorage storage) { 91 protected final void onPostExecute(WebappDataStorage storage) {
113 // Guarantee that last used time != WebappDataStorage.LAST_USED_ INVALID. Must be
114 // run on the main thread as SharedPreferences.Editor.apply() is called.
115 mStorages.put(webappId, storage);
116 mPreferences.edit().putStringSet(KEY_WEBAPP_SET, mStorages.keySe t()).apply();
117 storage.updateLastUsedTime();
118 if (callback != null) callback.onWebappDataStorageRetrieved(stor age); 92 if (callback != null) callback.onWebappDataStorageRetrieved(stor age);
119 } 93 }
120 }.execute(); 94 }.execute();
121 } 95 }
122 96
123 /** 97 /**
124 * Returns the WebappDataStorage object for webappId, or null if one cannot be found. 98 * Runs the callback, supplying the WebappDataStorage object for webappId, o r null if the web
125 * @param webappId The id of the web app. 99 * app has not been registered.
100 * @param webappId The id of the web app to register.
126 * @return The storage object for the web app, or null if webappId is not re gistered. 101 * @return The storage object for the web app, or null if webappId is not re gistered.
127 */ 102 */
128 public WebappDataStorage getWebappDataStorage(String webappId) { 103 public static void getWebappDataStorage(final String webappId,
129 return mStorages.get(webappId); 104 final FetchWebappDataStorageCallback callback) {
130 } 105 new AsyncTask<Void, Void, WebappDataStorage>() {
131 106 @Override
132 /** 107 protected final WebappDataStorage doInBackground(Void... nothing) {
133 * Returns the WebappDataStorage object whose scope most closely matches the provided URL, or 108 SharedPreferences preferences = openSharedPreferences();
134 * null if a matching web app cannot be found. The most closely matching sco pe is the longest 109 if (getRegisteredWebappIds(preferences).contains(webappId)) {
135 * scope which has the same prefix as the URL to open. 110 WebappDataStorage storage = WebappDataStorage.open(webappId) ;
136 * @param url The URL to search for. 111 return storage;
137 * @return The storage object for the web app, or null if one cannot be foun d. 112 }
138 */ 113 return null;
139 public WebappDataStorage getWebappDataStorageForUrl(final String url) { 114 }
140 WebappDataStorage bestMatch = null; 115
141 int largestOverlap = 0; 116 @Override
142 for (HashMap.Entry<String, WebappDataStorage> entry : mStorages.entrySet ()) { 117 protected final void onPostExecute(WebappDataStorage storage) {
143 WebappDataStorage storage = entry.getValue(); 118 assert callback != null;
144 String scope = storage.getScope(); 119 callback.onWebappDataStorageRetrieved(storage);
145 if (url.startsWith(scope) && scope.length() > largestOverlap) { 120 }
146 bestMatch = storage; 121 }.execute();
147 largestOverlap = scope.length(); 122 }
148 } 123
149 } 124 /**
150 return bestMatch; 125 * Runs the callback, supplying the WebappDataStorage object whose scope mos t closely matches
151 } 126 * the provided URL, or null if a matching web app cannot be found. The most closely matching
152 127 * scope is the longest scope which has the same prefix as the URL to open.
153 /** 128 * @param url The URL to search for.
154 * Returns the list of web app IDs which are written to SharedPreferences. 129 * @return The storage object for the web app, or null if webappId is not re gistered.
130 */
131 public static void getWebappDataStorageForUrl(final String url,
132 final FetchWebappDataStorageCallback callback) {
133 new AsyncTask<Void, Void, WebappDataStorage>() {
134 @Override
135 protected final WebappDataStorage doInBackground(Void... nothing) {
136 SharedPreferences preferences = openSharedPreferences();
137 WebappDataStorage bestMatch = null;
138 int largestOverlap = 0;
139 for (String id : getRegisteredWebappIds(preferences)) {
140 WebappDataStorage storage = WebappDataStorage.open(id);
141 String scope = storage.getScope();
142 if (url.startsWith(scope) && scope.length() > largestOverlap ) {
143 bestMatch = storage;
144 largestOverlap = scope.length();
145 }
146 }
147 return bestMatch;
148 }
149
150 protected final void onPostExecute(WebappDataStorage storage) {
151 assert callback != null;
152 callback.onWebappDataStorageRetrieved(storage);
153 }
154 }.execute();
155 }
156
157 /**
158 * Asynchronously retrieves the list of web app IDs which this registry is a ware of.
159 * @param callback Called when the set has been retrieved. The set may be em pty.
155 */ 160 */
156 @VisibleForTesting 161 @VisibleForTesting
157 public static Set<String> getRegisteredWebappIdsForTesting() { 162 public static void getRegisteredWebappIds(final FetchCallback callback) {
158 // Wrap with unmodifiableSet to ensure it's never modified. See crbug.co m/568369. 163 new AsyncTask<Void, Void, Set<String>>() {
159 return Collections.unmodifiableSet(openSharedPreferences().getStringSet( 164 @Override
160 KEY_WEBAPP_SET, Collections.<String>emptySet())); 165 protected final Set<String> doInBackground(Void... nothing) {
161 } 166 return getRegisteredWebappIds(openSharedPreferences());
162 167 }
163 /** 168
164 * Deletes the data for all "old" web apps, as well as all WebAPKs that have been uninstalled in 169 @Override
165 * the last month. "Old" web apps have not been opened by the user in the la st 3 months, or have 170 protected final void onPostExecute(Set<String> result) {
166 * had their last used time set to 0 by the user clearing their history. Cle anup is run, at 171 assert callback != null;
167 * most, once a month. 172 callback.onWebappIdsRetrieved(result);
173 }
174 }.execute();
175 }
176
177 /**
178 * 1. Deletes the data for all "old" web apps.
179 * "Old" web apps have not been opened by the user in the last 3 months, or have had their last
180 * used time set to 0 by the user clearing their history. Cleanup is run, at most, once a month.
181 * 2. Deletes the data for all WebAPKs that have been uninstalled in the las t month.
182 *
168 * @param currentTime The current time which will be checked to decide if th e task should be run 183 * @param currentTime The current time which will be checked to decide if th e task should be run
169 * and if a web app should be cleaned up. 184 * and if a web app should be cleaned up.
170 */ 185 */
171 public void unregisterOldWebapps(long currentTime) { 186 static void unregisterOldWebapps(final long currentTime) {
172 if ((currentTime - mPreferences.getLong(KEY_LAST_CLEANUP, 0)) < FULL_CLE ANUP_DURATION) { 187 new AsyncTask<Void, Void, Void>() {
173 return; 188 @Override
174 } 189 protected final Void doInBackground(Void... nothing) {
175 190 SharedPreferences preferences = openSharedPreferences();
176 Iterator<HashMap.Entry<String, WebappDataStorage>> it = mStorages.entryS et().iterator(); 191 long lastCleanup = preferences.getLong(KEY_LAST_CLEANUP, 0);
177 while (it.hasNext()) { 192 if ((currentTime - lastCleanup) < FULL_CLEANUP_DURATION) return null;
178 HashMap.Entry<String, WebappDataStorage> entry = it.next(); 193
179 WebappDataStorage storage = entry.getValue(); 194 Set<String> currentWebapps = getRegisteredWebappIds(preferences) ;
180 String webApkPackage = storage.getWebApkPackageName(); 195 Set<String> retainedWebapps = new HashSet<>(currentWebapps);
181 if (webApkPackage != null) { 196 PackageManager pm = ContextUtils.getApplicationContext().getPack ageManager();
182 if (isWebApkInstalled(webApkPackage)) { 197 for (String id : currentWebapps) {
183 continue; 198 WebappDataStorage storage = new WebappDataStorage(id);
184 } 199 String webApkPackage = storage.getWebApkPackageName();
185 } else if ((currentTime - storage.getLastUsedTime()) 200 if (webApkPackage != null) {
186 < WEBAPP_UNOPENED_CLEANUP_DURATION) { 201 if (isWebApkInstalled(pm, webApkPackage)) continue;
187 continue; 202 } else {
188 } 203 long lastUsed = storage.getLastUsedTime();
189 storage.delete(); 204 if ((currentTime - lastUsed) < WEBAPP_UNOPENED_CLEANUP_D URATION) continue;
190 it.remove(); 205 }
191 } 206 WebappDataStorage.deleteDataForWebapp(id);
192 207 retainedWebapps.remove(id);
193 mPreferences.edit() 208 }
194 .putLong(KEY_LAST_CLEANUP, currentTime) 209
195 .putStringSet(KEY_WEBAPP_SET, mStorages.keySet()) 210 preferences.edit()
196 .apply(); 211 .putLong(KEY_LAST_CLEANUP, currentTime)
197 } 212 .putStringSet(KEY_WEBAPP_SET, retainedWebapps)
198 213 .apply();
199 /** 214 return null;
200 * Deletes the data of all web apps whose url matches |urlFilter|. 215 }
201 * @param urlFilter The filter object to check URLs. 216 }.execute();
202 */ 217 }
203 @VisibleForTesting 218
204 void unregisterWebappsForUrlsImpl(UrlFilter urlFilter) { 219 /**
205 Iterator<HashMap.Entry<String, WebappDataStorage>> it = mStorages.entryS et().iterator(); 220 * Returns whether the given WebAPK is still installed.
206 while (it.hasNext()) { 221 */
207 HashMap.Entry<String, WebappDataStorage> entry = it.next(); 222 private static boolean isWebApkInstalled(PackageManager pm, String webApkPac kage) {
208 WebappDataStorage storage = entry.getValue(); 223 assert !ThreadUtils.runningOnUiThread();
209 if (urlFilter.matchesUrl(storage.getUrl())) {
210 storage.delete();
211 it.remove();
212 }
213 }
214
215 if (mStorages.isEmpty()) {
216 mPreferences.edit().clear().apply();
217 } else {
218 mPreferences.edit().putStringSet(KEY_WEBAPP_SET, mStorages.keySet()) .apply();
219 }
220 }
221
222 @CalledByNative
223 static void unregisterWebappsForUrls(UrlFilterBridge urlFilter) {
224 WebappRegistry.getInstance().unregisterWebappsForUrlsImpl(urlFilter);
225 urlFilter.destroy();
226 }
227
228 /**
229 * Deletes the URL and scope, and sets the last used time to 0 for all web a pps whose url
230 * matches |urlFilter|.
231 * @param urlFilter The filter object to check URLs.
232 */
233 @VisibleForTesting
234 void clearWebappHistoryForUrlsImpl(UrlFilter urlFilter) {
235 for (HashMap.Entry<String, WebappDataStorage> entry : mStorages.entrySet ()) {
236 WebappDataStorage storage = entry.getValue();
237 if (urlFilter.matchesUrl(storage.getUrl())) {
238 storage.clearHistory();
239 }
240 }
241 }
242
243 @CalledByNative
244 static void clearWebappHistoryForUrls(UrlFilterBridge urlFilter) {
245 WebappRegistry.getInstance().clearWebappHistoryForUrlsImpl(urlFilter);
246 urlFilter.destroy();
247 }
248
249 /**
250 * Returns true if the given WebAPK is installed.
251 */
252 private boolean isWebApkInstalled(String webApkPackage) {
253 try { 224 try {
254 ContextUtils.getApplicationContext().getPackageManager().getPackageI nfo( 225 pm.getPackageInfo(webApkPackage, PackageManager.GET_ACTIVITIES);
255 webApkPackage, PackageManager.GET_ACTIVITIES);
256 } catch (NameNotFoundException e) { 226 } catch (NameNotFoundException e) {
257 return false; 227 return false;
258 } 228 }
259 return true; 229 return true;
260 } 230 }
261 231
232 /**
233 * Deletes the data of all web apps whose url matches |urlFilter|, as well a s the registry
234 * tracking those web apps.
235 */
236 @VisibleForTesting
237 static void unregisterWebappsForUrls(final UrlFilter urlFilter, final Runnab le callback) {
238 new AsyncTask<Void, Void, Void>() {
239 @Override
240 protected final Void doInBackground(Void... nothing) {
241 SharedPreferences preferences = openSharedPreferences();
242 Set<String> registeredWebapps =
243 new HashSet<>(getRegisteredWebappIds(preferences));
244 Set<String> webappsToUnregister = new HashSet<>();
245 for (String id : registeredWebapps) {
246 if (urlFilter.matchesUrl(WebappDataStorage.open(id).getUrl() )) {
247 WebappDataStorage.deleteDataForWebapp(id);
248 webappsToUnregister.add(id);
249 }
250 }
251
252 // TODO(dominickn): SharedPreferences should be accessed on the main thread, not
253 // from an AsyncTask. Simultaneous access from two threads creat es a race condition.
254 // Update all callsites in this class.
255 registeredWebapps.removeAll(webappsToUnregister);
256 if (registeredWebapps.isEmpty()) {
257 preferences.edit().clear().apply();
258 } else {
259 preferences.edit().putStringSet(KEY_WEBAPP_SET, registeredWe bapps).apply();
260 }
261
262 return null;
263 }
264
265 @Override
266 protected final void onPostExecute(Void nothing) {
267 assert callback != null;
268 callback.run();
269 }
270 }.execute();
271 }
272
273 @CalledByNative
274 static void unregisterWebappsForUrls(
275 final UrlFilterBridge urlFilter, final long callbackPointer) {
276 unregisterWebappsForUrls(urlFilter, new Runnable() {
277 @Override
278 public void run() {
279 urlFilter.destroy();
280 nativeOnWebappsUnregistered(callbackPointer);
281 }
282 });
283 }
284
285 /**
286 * Deletes the URL and scope, and sets the last used time to 0 for all web a pps whose url
287 * matches |urlFilter|.
288 */
289 @VisibleForTesting
290 static void clearWebappHistoryForUrls(final UrlFilter urlFilter, final Runna ble callback) {
291 new AsyncTask<Void, Void, Void>() {
292 @Override
293 protected final Void doInBackground(Void... nothing) {
294 SharedPreferences preferences = openSharedPreferences();
295 for (String id : getRegisteredWebappIds(preferences)) {
296 if (urlFilter.matchesUrl(WebappDataStorage.open(id).getUrl() )) {
297 WebappDataStorage.clearHistory(id);
298 }
299 }
300 return null;
301 }
302
303 @Override
304 protected final void onPostExecute(Void nothing) {
305 assert callback != null;
306 callback.run();
307 }
308 }.execute();
309 }
310
311 @CalledByNative
312 static void clearWebappHistoryForUrls(
313 final UrlFilterBridge urlFilter, final long callbackPointer) {
314 clearWebappHistoryForUrls(urlFilter, new Runnable() {
315 @Override
316 public void run() {
317 urlFilter.destroy();
318 nativeOnClearedWebappHistory(callbackPointer);
319 }
320 });
321 }
322
262 private static SharedPreferences openSharedPreferences() { 323 private static SharedPreferences openSharedPreferences() {
263 return ContextUtils.getApplicationContext().getSharedPreferences( 324 return ContextUtils.getApplicationContext().getSharedPreferences(
264 REGISTRY_FILE_NAME, Context.MODE_PRIVATE); 325 REGISTRY_FILE_NAME, Context.MODE_PRIVATE);
265 } 326 }
266 327
328 private static Set<String> getRegisteredWebappIds(SharedPreferences preferen ces) {
329 // Wrap with unmodifiableSet to ensure it's never modified. See crbug.co m/568369.
330 return Collections.unmodifiableSet(
331 preferences.getStringSet(KEY_WEBAPP_SET, Collections.<String>emp tySet()));
332 }
333
267 private WebappRegistry() { 334 private WebappRegistry() {
268 mPreferences = openSharedPreferences(); 335 }
269 mStorages = new HashMap<String, WebappDataStorage>(); 336
270 } 337 private static native void nativeOnWebappsUnregistered(long callbackPointer) ;
271 338 private static native void nativeOnClearedWebappHistory(long callbackPointer );
272 private void initStorages(String idToInitialize, boolean replaceExisting) {
273 Set<String> webapps =
274 mPreferences.getStringSet(KEY_WEBAPP_SET, Collections.<String>em ptySet());
275 boolean initAll = (idToInitialize == null || idToInitialize.isEmpty());
276
277 // Don't overwrite any entry in mStorages unless replaceExisting is set to true.
278 if (initAll) {
279 for (String id : webapps) {
280 if (replaceExisting || !mStorages.containsKey(id)) {
281 mStorages.put(id, WebappDataStorage.open(id));
282 }
283 }
284 } else {
285 if (webapps.contains(idToInitialize)
286 && (replaceExisting || !mStorages.containsKey(idToInitialize ))) {
287 mStorages.put(idToInitialize, WebappDataStorage.open(idToInitial ize));
288 }
289 }
290 }
291 } 339 }
OLDNEW
« no previous file with comments | « chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java ('k') | chrome/android/java_sources.gni » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698