Bug 1260321 - Follow-up: Migrate users with customized panels to combined history panel. r=sebastian draft
authorChenxia Liu <liuche@mozilla.com>
Mon, 04 Apr 2016 21:47:19 -0700
changeset 347703 ae71ab6885a89d836d4e2557bba46e2f5956fad9
parent 347462 8649e83a43b9c1fc271d43e50ade50966c7e94b9
child 517692 d4f6ef3f57dcf3119866ab5cb71f6b58bf707bab
push id14649
push usercliu@mozilla.com
push dateTue, 05 Apr 2016 18:42:06 +0000
reviewerssebastian
bugs1260321
milestone48.0a1
Bug 1260321 - Follow-up: Migrate users with customized panels to combined history panel. r=sebastian MozReview-Commit-ID: 6SQ7nuZhCe0
mobile/android/base/java/org/mozilla/gecko/home/HomeConfig.java
mobile/android/base/java/org/mozilla/gecko/home/HomeConfigPrefsBackend.java
--- a/mobile/android/base/java/org/mozilla/gecko/home/HomeConfig.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/HomeConfig.java
@@ -289,16 +289,20 @@ public final class HomeConfig {
         public int getViewCount() {
             return (mViews != null ? mViews.size() : 0);
         }
 
         public ViewConfig getViewAt(int index) {
             return (mViews != null ? mViews.get(index) : null);
         }
 
+        public EnumSet<Flags> getFlags() {
+            return mFlags.clone();
+        }
+
         public boolean isDynamic() {
             return (mType == PanelType.DYNAMIC);
         }
 
         public boolean isDefault() {
             return mFlags.contains(Flags.DEFAULT_PANEL);
         }
 
--- a/mobile/android/base/java/org/mozilla/gecko/home/HomeConfigPrefsBackend.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/HomeConfigPrefsBackend.java
@@ -15,34 +15,32 @@ import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.home.HomeConfig.HomeConfigBackend;
 import org.mozilla.gecko.home.HomeConfig.OnReloadListener;
 import org.mozilla.gecko.home.HomeConfig.PanelConfig;
 import org.mozilla.gecko.home.HomeConfig.PanelType;
 import org.mozilla.gecko.home.HomeConfig.State;
-import org.mozilla.gecko.restrictions.Restrictable;
-import org.mozilla.gecko.restrictions.Restrictions;
 import org.mozilla.gecko.util.HardwareUtils;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.support.v4.content.LocalBroadcastManager;
 import android.text.TextUtils;
 import android.util.Log;
 
 public class HomeConfigPrefsBackend implements HomeConfigBackend {
     private static final String LOGTAG = "GeckoHomeConfigBackend";
 
     // Increment this to trigger a migration.
-    private static final int VERSION = 3;
+    private static final int VERSION = 4;
 
     // This key was originally used to store only an array of panel configs.
     public static final String PREFS_CONFIG_KEY_OLD = "home_panels";
 
     // This key is now used to store a version number with the array of panel configs.
     public static final String PREFS_CONFIG_KEY = "home_panels_with_version";
 
     // Keys used with JSON object stored in prefs.
@@ -142,16 +140,81 @@ public class HomeConfigPrefsBackend impl
         // Maybe add the new panel to the back of the array.
         if ((isPhone && positionOnPhones == Position.BACK) ||
             (isTablet && positionOnTablets == Position.BACK)) {
             jsonPanels.put(jsonPanelConfig);
         }
     }
 
     /**
+     * Updates the panels to combine the History and Sync panels into the (Combined) History panel.
+     *
+     * Tries to replace the History panel with the Combined History panel if visible, or falls back to
+     * replacing the Sync panel if it's visible. That way, we minimize panel reordering during a migration.
+     * @param context Android context
+     * @param jsonPanels array of original JSON panels
+     * @return new array of updated JSON panels
+     * @throws JSONException
+     */
+    private static JSONArray combineHistoryAndSyncPanels(Context context, JSONArray jsonPanels) throws JSONException {
+        EnumSet<PanelConfig.Flags> historyFlags = null;
+        EnumSet<PanelConfig.Flags> syncFlags = null;
+
+        int historyIndex = -1;
+        int syncIndex = -1;
+
+        // Determine state and location of History and Sync panels.
+        for (int i = 0; i < jsonPanels.length(); i++) {
+            JSONObject panelObj = jsonPanels.getJSONObject(i);
+            final PanelConfig panelConfig = new PanelConfig(panelObj);
+            final PanelType type = panelConfig.getType();
+            if (type == PanelType.HISTORY) {
+                historyIndex = i;
+                historyFlags = panelConfig.getFlags();
+            } else if (type == PanelType.REMOTE_TABS) {
+                syncIndex = i;
+                syncFlags = panelConfig.getFlags();
+            }
+        }
+
+        if (historyIndex == -1 || syncIndex == -1) {
+            throw new IllegalArgumentException("Missing default panels");
+        }
+
+        PanelConfig newPanel;
+        int replaceIndex;
+        int removeIndex;
+        if (historyFlags.contains(PanelConfig.Flags.DISABLED_PANEL) && !syncFlags.contains(PanelConfig.Flags.DISABLED_PANEL)) {
+            // Replace the Sync panel if it's visible and the History panel is disabled.
+            replaceIndex = syncIndex;
+            removeIndex = historyIndex;
+            newPanel = createBuiltinPanelConfig(context, PanelType.COMBINED_HISTORY, syncFlags);
+        } else {
+            // Otherwise, just replace the History panel.
+            replaceIndex = historyIndex;
+            removeIndex = syncIndex;
+            newPanel = createBuiltinPanelConfig(context, PanelType.COMBINED_HISTORY, historyFlags);
+        }
+
+        // Copy the array with updated panel and removed panel.
+        final JSONArray newArray = new JSONArray();
+        for (int i = 0; i < jsonPanels.length(); i++) {
+            if (i == replaceIndex) {
+                newArray.put(newPanel.toJSON());
+            } else if (i == removeIndex) {
+                continue;
+            } else {
+                newArray.put(jsonPanels.get(i));
+            }
+        }
+
+        return newArray;
+    }
+
+    /**
      * Checks to see if the reading list panel already exists.
      *
      * @param jsonPanels JSONArray array representing the curent set of panel configs.
      *
      * @return boolean Whether or not the reading list panel exists.
      */
     private static boolean readingListPanelExists(JSONArray jsonPanels) {
         final int count = jsonPanels.length();
@@ -184,17 +247,17 @@ public class HomeConfigPrefsBackend impl
         if (sMigrationDone) {
             final JSONObject json = new JSONObject(jsonString);
             return json.getJSONArray(JSON_KEY_PANELS);
         }
 
         // Make sure we only do this version check once.
         sMigrationDone = true;
 
-        final JSONArray jsonPanels;
+        JSONArray jsonPanels;
         final int version;
 
         final SharedPreferences prefs = GeckoSharedPrefs.forProfile(context);
         if (prefs.contains(PREFS_CONFIG_KEY_OLD)) {
             // Our original implementation did not contain versioning, so this is implicitly version 0.
             jsonPanels = new JSONArray(jsonString);
             version = 0;
         } else {
@@ -237,16 +300,23 @@ public class HomeConfigPrefsBackend impl
                     // This migration should only occur for "low memory" devices.
                     // Note: This will not agree with the default configuration, which
                     // has REMOTE_TABS after READING_LIST on some devices.
                     if (!readingListPanelExists(jsonPanels)) {
                         addBuiltinPanelConfig(context, jsonPanels,
                                 PanelType.READING_LIST, Position.BACK, Position.BACK);
                     }
                     break;
+
+                case 4:
+                    // Combine the History and Sync panels. In order to minimize an unexpected reordering
+                    // of panels, we try to replace the History panel if it's visible, and fall back to
+                    // the Sync panel if that's visible.
+                    jsonPanels = combineHistoryAndSyncPanels(context, jsonPanels);
+                    break;
             }
         }
 
         // Save the new panel config and the new version number.
         final JSONObject newJson = new JSONObject();
         newJson.put(JSON_KEY_PANELS, jsonPanels);
         newJson.put(JSON_KEY_VERSION, VERSION);