1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/base/webapp/Allocator.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,190 @@ 1.4 +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +package org.mozilla.gecko.webapp; 1.10 + 1.11 +import java.util.ArrayList; 1.12 + 1.13 +import org.mozilla.gecko.GeckoAppShell; 1.14 + 1.15 +import android.content.Context; 1.16 +import android.content.SharedPreferences; 1.17 +import android.content.SharedPreferences.Editor; 1.18 +import android.util.Log; 1.19 + 1.20 +public class Allocator { 1.21 + 1.22 + private final String LOGTAG = "GeckoWebappAllocator"; 1.23 + 1.24 + private static final String PREFIX_ORIGIN = "webapp-origin-"; 1.25 + private static final String PREFIX_PACKAGE_NAME = "webapp-package-name-"; 1.26 + 1.27 + // These prefixes are for prefs used by the old shortcut-based runtime. 1.28 + // We define them here so maybeMigrateOldPrefs can migrate them to their 1.29 + // new equivalents if this app was originally installed as a shortcut. 1.30 + // Maybe we can remove this code in the future! 1.31 + private static final String PREFIX_OLD_APP = "app"; 1.32 + private static final String PREFIX_OLD_ICON = "icon"; 1.33 + 1.34 + // The number of Webapp# and WEBAPP# activities/apps/intents 1.35 + private final static int MAX_WEB_APPS = 100; 1.36 + 1.37 + protected static Allocator sInstance = null; 1.38 + public static Allocator getInstance() { 1.39 + return getInstance(GeckoAppShell.getContext()); 1.40 + } 1.41 + 1.42 + public static synchronized Allocator getInstance(Context cx) { 1.43 + if (sInstance == null) { 1.44 + sInstance = new Allocator(cx); 1.45 + } 1.46 + 1.47 + return sInstance; 1.48 + } 1.49 + 1.50 + SharedPreferences mPrefs; 1.51 + 1.52 + protected Allocator(Context context) { 1.53 + mPrefs = context.getSharedPreferences("webapps", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS); 1.54 + } 1.55 + 1.56 + private static String appKey(int index) { 1.57 + return PREFIX_PACKAGE_NAME + index; 1.58 + } 1.59 + 1.60 + public static String iconKey(int index) { 1.61 + return "web-app-color-" + index; 1.62 + } 1.63 + 1.64 + public static String originKey(int i) { 1.65 + return PREFIX_ORIGIN + i; 1.66 + } 1.67 + 1.68 + private static String oldAppKey(int index) { 1.69 + return PREFIX_OLD_APP + index; 1.70 + } 1.71 + 1.72 + private static String oldIconKey(int index) { 1.73 + return PREFIX_OLD_ICON + index; 1.74 + } 1.75 + 1.76 + private static void save(Editor editor) { 1.77 + // Use SharedPreferences.Editor.apply() where available and commit() 1.78 + // where it isn't. We could also use a background thread with commit(), 1.79 + // but our callers might expect the changes we make to be available 1.80 + // immediately, so we instead take the commit() performance hit 1.81 + // on the small percentage of extant devices that don't support apply(). 1.82 + if (android.os.Build.VERSION.SDK_INT > 8) { 1.83 + editor.apply(); 1.84 + } else { 1.85 + editor.commit(); 1.86 + } 1.87 + } 1.88 + 1.89 + public ArrayList<String> getInstalledPackageNames() { 1.90 + ArrayList<String> installedPackages = new ArrayList<String>(); 1.91 + 1.92 + for (int i = 0; i < MAX_WEB_APPS; ++i) { 1.93 + if (mPrefs.contains(appKey(i))) { 1.94 + installedPackages.add(mPrefs.getString(appKey(i), "")); 1.95 + } 1.96 + } 1.97 + return installedPackages; 1.98 + } 1.99 + 1.100 + public synchronized int findOrAllocatePackage(final String packageName) { 1.101 + int index = getIndexForApp(packageName); 1.102 + if (index != -1) 1.103 + return index; 1.104 + 1.105 + for (int i = 0; i < MAX_WEB_APPS; ++i) { 1.106 + if (!mPrefs.contains(appKey(i))) { 1.107 + // found unused index i 1.108 + putPackageName(i, packageName); 1.109 + return i; 1.110 + } 1.111 + } 1.112 + 1.113 + // no more apps! 1.114 + return -1; 1.115 + } 1.116 + 1.117 + public synchronized void putPackageName(final int index, final String packageName) { 1.118 + save(mPrefs.edit().putString(appKey(index), packageName)); 1.119 + } 1.120 + 1.121 + public void updateColor(int index, int color) { 1.122 + save(mPrefs.edit().putInt(iconKey(index), color)); 1.123 + } 1.124 + 1.125 + public synchronized int getIndexForApp(String packageName) { 1.126 + return findSlotForPrefix(PREFIX_PACKAGE_NAME, packageName); 1.127 + } 1.128 + 1.129 + public synchronized int getIndexForOrigin(String origin) { 1.130 + return findSlotForPrefix(PREFIX_ORIGIN, origin); 1.131 + } 1.132 + 1.133 + protected int findSlotForPrefix(String prefix, String value) { 1.134 + for (int i = 0; i < MAX_WEB_APPS; ++i) { 1.135 + if (mPrefs.getString(prefix + i, "").equals(value)) { 1.136 + return i; 1.137 + } 1.138 + } 1.139 + return -1; 1.140 + } 1.141 + 1.142 + public synchronized String getAppForIndex(int index) { 1.143 + return mPrefs.getString(appKey(index), null); 1.144 + } 1.145 + 1.146 + public synchronized int releaseIndexForApp(String app) { 1.147 + int index = getIndexForApp(app); 1.148 + if (index == -1) 1.149 + return -1; 1.150 + 1.151 + releaseIndex(index); 1.152 + return index; 1.153 + } 1.154 + 1.155 + public synchronized void releaseIndex(final int index) { 1.156 + save(mPrefs.edit().remove(appKey(index)).remove(iconKey(index)).remove(originKey(index))); 1.157 + } 1.158 + 1.159 + public void putOrigin(int index, String origin) { 1.160 + save(mPrefs.edit().putString(originKey(index), origin)); 1.161 + } 1.162 + 1.163 + public String getOrigin(int index) { 1.164 + return mPrefs.getString(originKey(index), null); 1.165 + } 1.166 + 1.167 + public int getColor(int index) { 1.168 + return mPrefs.getInt(iconKey(index), -1); 1.169 + } 1.170 + 1.171 + /** 1.172 + * Migrate old prefs to their new equivalents if this app was originally 1.173 + * installed by the shortcut-based implementation. 1.174 + */ 1.175 + public void maybeMigrateOldPrefs(int index) { 1.176 + if (!mPrefs.contains(oldAppKey(index))) { 1.177 + return; 1.178 + } 1.179 + 1.180 + Log.i(LOGTAG, "migrating old prefs"); 1.181 + 1.182 + // The old appKey pref stored the origin, while the new appKey pref 1.183 + // stores the packageName, so we migrate oldAppKey to the origin pref. 1.184 + putOrigin(index, mPrefs.getString(oldAppKey(index), null)); 1.185 + 1.186 + // The old iconKey pref actually stored the splash screen background 1.187 + // color, so we migrate oldIconKey to the color pref. 1.188 + updateColor(index, mPrefs.getInt(oldIconKey(index), -1)); 1.189 + 1.190 + // Remove the old prefs so we don't migrate them the next time around. 1.191 + save(mPrefs.edit().remove(oldAppKey(index)).remove(oldIconKey(index))); 1.192 + } 1.193 +}