Bug 1414084 - Part 11 - Use a Map for the MenuItemInfo list. r?grisha draft
authorJan Henning <jh+bugzilla@buttercookie.de>
Sun, 18 Mar 2018 18:07:16 +0100
changeset 823886 e64c101eff5ed12e98a3eb83224008b547c7aeb4
parent 823885 060b82ea32b1323dbf029cbb2d943f38f0bf5d23
child 823887 de83af1d10c5636294e8c2a93b9c192a91d0515f
push id117809
push usermozilla@buttercookie.de
push dateSun, 29 Jul 2018 18:19:15 +0000
reviewersgrisha
bugs1414084
milestone63.0a1
Bug 1414084 - Part 11 - Use a Map for the MenuItemInfo list. r?grisha Since all related EventDispatcher messages use UUIDs, it makes sense to store our MenuItemInfos in a Map, so we can access them directly by UUID instead of having to iterate over them until we've found the desired one. Since we want to preserve the order in which MenuItemInfos were added, we use a LinkedHashMap. MozReview-Commit-ID: BEtJ59tX59m
mobile/android/base/java/org/mozilla/gecko/AddonUICache.java
--- a/mobile/android/base/java/org/mozilla/gecko/AddonUICache.java
+++ b/mobile/android/base/java/org/mozilla/gecko/AddonUICache.java
@@ -11,18 +11,18 @@ import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.SubMenu;
 
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.LinkedHashMap;
+import java.util.Map;
 
 /**
  * For certain UI items added by add-ons or other JS/Gecko code, Gecko notifies us whenever an item
  * is added, changed or removed. Since we must not miss any of these notifications and need to re-
  * member the current list of active UI items even if e.g. we're in background and our activities
  * have been destroyed, we need a class whose lifetime matches (or even exceeds) that of Gecko.
  *
  * This class fulfills this purpose - it will be initialised early during app startup and just like
@@ -50,17 +50,17 @@ public class AddonUICache implements Bun
         public boolean checked;
         public boolean enabled = true;
         public boolean visible = true;
         public int parent;
     }
 
     private static final AddonUICache instance = new AddonUICache();
 
-    private final List<MenuItemInfo> mAddonMenuItemsCache = new ArrayList<>();
+    private final Map<String, MenuItemInfo> mAddonMenuItemsCache = new LinkedHashMap<>();
     private int mAddonMenuNextID = ADDON_MENU_OFFSET;
     private Menu mMenu;
 
     private boolean mInitialized;
 
     public static AddonUICache getInstance() {
         return instance;
     }
@@ -96,21 +96,19 @@ public class AddonUICache implements Bun
                 info.checked = message.getBoolean("checked", false);
                 info.enabled = message.getBoolean("enabled", true);
                 info.visible = message.getBoolean("visible", true);
                 info.checkable = message.getBoolean("checkable", false);
                 final String parentUUID = message.getString("parent");
                 if (GECKO_TOOLS_MENU_UUID.equals(parentUUID)) {
                     info.parent = GECKO_TOOLS_MENU_ID;
                 } else if (!TextUtils.isEmpty(parentUUID)) {
-                    for (MenuItemInfo item : mAddonMenuItemsCache) {
-                        if (item.uuid.equals(parentUUID)) {
-                            info.parent = item.id;
-                            break;
-                        }
+                    MenuItemInfo parent = mAddonMenuItemsCache.get(parentUUID);
+                    if (parent != null) {
+                        info.parent = parent.id;
                     }
                 }
                 addAddonMenuItem(info);
                 break;
 
             case "Menu:Remove":
                 removeAddonMenuItem(message.getString("uuid"));
                 break;
@@ -126,17 +124,17 @@ public class AddonUICache implements Bun
      * Starts handling add-on menu items for the given {@link Menu} and also adds any
      * menu items that have already been cached.
      */
     public void onCreateOptionsMenu(Menu menu) {
         mMenu = menu;
 
         // Add add-on menu items, if any exist.
         if (mMenu != null) {
-            for (MenuItemInfo item : mAddonMenuItemsCache) {
+            for (MenuItemInfo item : mAddonMenuItemsCache.values()) {
                 addAddonMenuItemToMenu(mMenu, item);
             }
         }
     }
 
     /**
      * Clears the reference to the Menu passed in {@link AddonUICache#onCreateOptionsMenu}.
      * <p>
@@ -145,74 +143,61 @@ public class AddonUICache implements Bun
     public void onDestroyOptionsMenu() {
         mMenu = null;
     }
 
     /**
      * Adds an addon menu item/webextension browser action to the menu.
      */
     private void addAddonMenuItem(final MenuItemInfo info) {
-        mAddonMenuItemsCache.add(info);
+        mAddonMenuItemsCache.put(info.uuid, info);
 
         if (mMenu == null) {
             return;
         }
 
         addAddonMenuItemToMenu(mMenu, info);
     }
 
     /**
      * Removes an addon menu item/webextension browser action from the menu by its UUID.
      */
     private void removeAddonMenuItem(String uuid) {
-        int id = -1;
+        // Remove add-on menu item from cache, if available.
+        final MenuItemInfo item = mAddonMenuItemsCache.remove(uuid);
 
-        // Remove add-on menu item from cache, if available.
-        for (MenuItemInfo item : mAddonMenuItemsCache) {
-            if (item.uuid.equals(uuid)) {
-                id = item.id;
-                mAddonMenuItemsCache.remove(item);
-                break;
-            }
-        }
-
-        if (mMenu == null || id == -1) {
+        if (mMenu == null || item == null) {
             return;
         }
 
-        final MenuItem menuItem = mMenu.findItem(id);
+        final MenuItem menuItem = mMenu.findItem(item.id);
         if (menuItem != null) {
-            mMenu.removeItem(id);
+            mMenu.removeItem(item.id);
         }
     }
 
     /**
      * Updates the addon menu/webextension browser action with the specified UUID.
      */
     private void updateAddonMenuItem(String uuid, final GeckoBundle options) {
-        int id = -1;
-
         // Set attribute for the menu item in cache, if available
-        for (MenuItemInfo item : mAddonMenuItemsCache) {
-            if (item.uuid.equals(uuid)) {
-                id = item.id;
-                item.label = options.getString("name", item.label);
-                item.checkable = options.getBoolean("checkable", item.checkable);
-                item.checked = options.getBoolean("checked", item.checked);
-                item.enabled = options.getBoolean("enabled", item.enabled);
-                item.visible = options.getBoolean("visible", item.visible);
-                break;
-            }
+        final MenuItemInfo item = mAddonMenuItemsCache.get(uuid);
+        if (item != null) {
+            item.label = options.getString("name", item.label);
+            item.checkable = options.getBoolean("checkable", item.checkable);
+            item.checked = options.getBoolean("checked", item.checked);
+            item.enabled = options.getBoolean("enabled", item.enabled);
+            item.visible = options.getBoolean("visible", item.visible);
         }
 
-        if (mMenu == null || id == -1) {
+        if (mMenu == null || item == null) {
             return;
         }
 
-        final MenuItem menuItem = mMenu.findItem(id);
+        final MenuItem menuItem = mMenu.findItem(item.id);
         if (menuItem != null) {
             menuItem.setTitle(options.getString("name", menuItem.getTitle().toString()));
             menuItem.setCheckable(options.getBoolean("checkable", menuItem.isCheckable()));
             menuItem.setChecked(options.getBoolean("checked", menuItem.isChecked()));
             menuItem.setEnabled(options.getBoolean("enabled", menuItem.isEnabled()));
             menuItem.setVisible(options.getBoolean("visible", menuItem.isVisible()));
         }
     }