/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.webapp; import java.util.ArrayList; import org.mozilla.gecko.GeckoAppShell; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.util.Log; public class Allocator { private final String LOGTAG = "GeckoWebappAllocator"; private static final String PREFIX_ORIGIN = "webapp-origin-"; private static final String PREFIX_PACKAGE_NAME = "webapp-package-name-"; // These prefixes are for prefs used by the old shortcut-based runtime. // We define them here so maybeMigrateOldPrefs can migrate them to their // new equivalents if this app was originally installed as a shortcut. // Maybe we can remove this code in the future! private static final String PREFIX_OLD_APP = "app"; private static final String PREFIX_OLD_ICON = "icon"; // The number of Webapp# and WEBAPP# activities/apps/intents private final static int MAX_WEB_APPS = 100; protected static Allocator sInstance; public static Allocator getInstance() { return getInstance(GeckoAppShell.getContext()); } public static synchronized Allocator getInstance(Context cx) { if (sInstance == null) { sInstance = new Allocator(cx); } return sInstance; } SharedPreferences mPrefs; protected Allocator(Context context) { mPrefs = context.getSharedPreferences("webapps", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS); } private static String appKey(int index) { return PREFIX_PACKAGE_NAME + index; } public static String iconKey(int index) { return "web-app-color-" + index; } public static String originKey(int i) { return PREFIX_ORIGIN + i; } private static String oldAppKey(int index) { return PREFIX_OLD_APP + index; } private static String oldIconKey(int index) { return PREFIX_OLD_ICON + index; } public ArrayList getInstalledPackageNames() { ArrayList installedPackages = new ArrayList(); for (int i = 0; i < MAX_WEB_APPS; ++i) { if (mPrefs.contains(appKey(i))) { installedPackages.add(mPrefs.getString(appKey(i), "")); } } return installedPackages; } public synchronized int findOrAllocatePackage(final String packageName) { int index = getIndexForApp(packageName); if (index != -1) return index; for (int i = 0; i < MAX_WEB_APPS; ++i) { if (!mPrefs.contains(appKey(i))) { // found unused index i putPackageName(i, packageName); return i; } } // no more apps! return -1; } public synchronized void putPackageName(final int index, final String packageName) { mPrefs.edit().putString(appKey(index), packageName).apply(); } public void updateColor(int index, int color) { mPrefs.edit().putInt(iconKey(index), color).apply(); } public synchronized int getIndexForApp(String packageName) { return findSlotForPrefix(PREFIX_PACKAGE_NAME, packageName); } protected int findSlotForPrefix(String prefix, String value) { for (int i = 0; i < MAX_WEB_APPS; ++i) { if (mPrefs.getString(prefix + i, "").equals(value)) { return i; } } return -1; } public synchronized String getAppForIndex(int index) { return mPrefs.getString(appKey(index), null); } public synchronized int releaseIndexForApp(String app) { int index = getIndexForApp(app); if (index == -1) return -1; releaseIndex(index); return index; } public synchronized void releaseIndex(final int index) { mPrefs.edit().remove(appKey(index)).remove(iconKey(index)).remove(originKey(index)).apply(); } public void putOrigin(int index, String origin) { mPrefs.edit().putString(originKey(index), origin).apply(); } public String getOrigin(int index) { return mPrefs.getString(originKey(index), null); } public int getColor(int index) { return mPrefs.getInt(iconKey(index), -1); } /** * Migrate old prefs to their new equivalents if this app was originally * installed by the shortcut-based implementation. */ public void maybeMigrateOldPrefs(int index) { if (!mPrefs.contains(oldAppKey(index))) { return; } Log.i(LOGTAG, "migrating old prefs"); // The old appKey pref stored the origin, while the new appKey pref // stores the packageName, so we migrate oldAppKey to the origin pref. putOrigin(index, mPrefs.getString(oldAppKey(index), null)); // The old iconKey pref actually stored the splash screen background // color, so we migrate oldIconKey to the color pref. updateColor(index, mPrefs.getInt(oldIconKey(index), -1)); // Remove the old prefs so we don't migrate them the next time around. mPrefs.edit().remove(oldAppKey(index)).remove(oldIconKey(index)).apply(); } }