Bug 1063750 - Part 2: Implement link from Remote Tabs tray to Remote Tabs home panel. r=mcomella
authorNick Alexander <nalexander@mozilla.com>
Tue, 07 Oct 2014 16:53:28 -0700
changeset 232531 918c616ddc23985d40c6d170cbe847de490070aa
parent 232530 439792036cc72d763b518c7caf220d0bf99d2596
child 232532 8b8ce071a7e5661e7eb804415fae9f98026a4d75
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcomella
bugs1063750, 1063753
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1063750 - Part 2: Implement link from Remote Tabs tray to Remote Tabs home panel. r=mcomella Deriving the correct panel UUID from the active Home Panel configuration is challenging. This is easy and will only exist for one release. (The Remote Tabs tray icon will disappear after this release; see Bug 1063753.) This solves the problem in essentially all the situations we expect to see.
mobile/android/base/AboutPages.java
mobile/android/base/home/HomeConfig.java
mobile/android/base/tabs/RemoteTabsPanel.java
--- a/mobile/android/base/AboutPages.java
+++ b/mobile/android/base/AboutPages.java
@@ -1,15 +1,18 @@
 /* -*- 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;
 
+import org.mozilla.gecko.home.HomeConfig;
+import org.mozilla.gecko.home.HomeConfig.PanelType;
+import org.mozilla.gecko.mozglue.RobocopTarget;
 import org.mozilla.gecko.util.StringUtils;
 
 public class AboutPages {
     // All of our special pages.
     public static final String ADDONS          = "about:addons";
     public static final String APPS            = "about:apps";
     public static final String CONFIG          = "about:config";
     public static final String DOWNLOADS       = "about:downloads";
@@ -84,10 +87,21 @@ public class AboutPages {
         // TODO: it'd be quicker to not compare the "about:" part every time.
         for (int i = 0; i < DEFAULT_ICON_PAGES.length; ++i) {
             if (DEFAULT_ICON_PAGES[i].equals(url)) {
                 return true;
             }
         }
         return false;
     }
+
+    /**
+     * Get a URL that navigates to the specified built-in Home Panel.
+     *
+     * @param panelType to navigate to.
+     * @return URL.
+     * @throws IllegalArgumentException if the built-in panel type is not a built-in panel.
+     */
+    @RobocopTarget
+    public static String getURLForBuiltinPanelType(PanelType panelType) throws IllegalArgumentException {
+        return HOME + "?panel=" + HomeConfig.getIdForBuiltinPanelType(panelType);
+    }
 }
-
--- a/mobile/android/base/home/HomeConfig.java
+++ b/mobile/android/base/home/HomeConfig.java
@@ -1,38 +1,37 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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.home;
 
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.GeckoEvent;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.home.RemoteTabsPanel;
-import org.mozilla.gecko.util.ThreadUtils;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.content.Context;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.mozilla.gecko.GeckoAppShell;
+import org.mozilla.gecko.GeckoEvent;
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.util.ThreadUtils;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
 public final class HomeConfig {
     /**
      * Used to determine what type of HomeFragment subclass to use when creating
      * a given panel. With the exception of DYNAMIC, all of these types correspond
      * to a default set of built-in panels. The DYNAMIC panel type is used by
      * third-party services to create panels with varying types of content.
      */
     public static enum PanelType implements Parcelable {
@@ -827,17 +826,16 @@ public final class HomeConfig {
         static final String JSON_KEY_TEXT = "text";
         static final String JSON_KEY_IMAGE_URL = "imageUrl";
 
         public EmptyViewConfig(JSONObject json) throws JSONException, IllegalArgumentException {
             mText = json.optString(JSON_KEY_TEXT, null);
             mImageUrl = json.optString(JSON_KEY_IMAGE_URL, null);
         }
 
-        @SuppressWarnings("unchecked")
         public EmptyViewConfig(Parcel in) {
             mText = in.readString();
             mImageUrl = in.readString();
         }
 
         public EmptyViewConfig(EmptyViewConfig emptyViewConfig) {
             mText = emptyViewConfig.mText;
             mImageUrl = emptyViewConfig.mImageUrl;
@@ -899,17 +897,16 @@ public final class HomeConfig {
         static final String JSON_KEY_IMAGE_URL = "imageUrl";
 
         public AuthConfig(JSONObject json) throws JSONException, IllegalArgumentException {
             mMessageText = json.optString(JSON_KEY_MESSAGE_TEXT);
             mButtonText = json.optString(JSON_KEY_BUTTON_TEXT);
             mImageUrl = json.optString(JSON_KEY_IMAGE_URL, null);
         }
 
-        @SuppressWarnings("unchecked")
         public AuthConfig(Parcel in) {
             mMessageText = in.readString();
             mButtonText = in.readString();
             mImageUrl = in.readString();
 
             validate();
         }
 
@@ -1490,17 +1487,22 @@ public final class HomeConfig {
 
     public interface HomeConfigBackend {
         public State load();
         public void save(State configState);
         public String getLocale();
         public void setOnReloadListener(OnReloadListener listener);
     }
 
-    // UUIDs used to create PanelConfigs for default built-in panels
+    // UUIDs used to create PanelConfigs for default built-in panels. These are
+    // public because they can be used in "about:home?panel=UUID" query strings
+    // to open specific panels without querying the active Home Panel
+    // configuration. Because they don't consider the active configuration, it
+    // is only sensible to do this for built-in panels (and not for dynamic
+    // panels).
     private static final String TOP_SITES_PANEL_ID = "4becc86b-41eb-429a-a042-88fe8b5a094e";
     private static final String BOOKMARKS_PANEL_ID = "7f6d419a-cd6c-4e34-b26f-f68b1b551907";
     private static final String READING_LIST_PANEL_ID = "20f4549a-64ad-4c32-93e4-1dcef792733b";
     private static final String HISTORY_PANEL_ID = "f134bf20-11f7-4867-ab8b-e8e705d7fbe8";
     private static final String RECENT_TABS_PANEL_ID = "5c2601a5-eedc-4477-b297-ce4cef52adf8";
     private static final String REMOTE_TABS_PANEL_ID = "72429afd-8d8b-43d8-9189-14b779c563d0";
 
     private final HomeConfigBackend mBackend;
@@ -1527,54 +1529,69 @@ public final class HomeConfig {
     public void setOnReloadListener(OnReloadListener listener) {
         mBackend.setOnReloadListener(listener);
     }
 
     public static PanelConfig createBuiltinPanelConfig(Context context, PanelType panelType) {
         return createBuiltinPanelConfig(context, panelType, EnumSet.noneOf(PanelConfig.Flags.class));
     }
 
-    public static PanelConfig createBuiltinPanelConfig(Context context, PanelType panelType, EnumSet<PanelConfig.Flags> flags) {
-        int titleId = 0;
-        String id = null;
-
+    public static int getTitleResourceIdForBuiltinPanelType(PanelType panelType) {
         switch(panelType) {
-            case TOP_SITES:
-                titleId = R.string.home_top_sites_title;
-                id = TOP_SITES_PANEL_ID;
-                break;
+        case TOP_SITES:
+            return R.string.home_top_sites_title;
+
+        case BOOKMARKS:
+            return R.string.bookmarks_title;
+
+        case HISTORY:
+            return R.string.home_history_title;
 
-            case BOOKMARKS:
-                titleId = R.string.bookmarks_title;
-                id = BOOKMARKS_PANEL_ID;
-                break;
+        case REMOTE_TABS:
+            return R.string.home_remote_tabs_title;
+
+        case READING_LIST:
+            return R.string.reading_list_title;
+
+        case RECENT_TABS:
+            return R.string.recent_tabs_title;
+
+        default:
+            throw new IllegalArgumentException("Only for built-in panel types: " + panelType);
+        }
+    }
 
-            case HISTORY:
-                titleId = R.string.home_history_title;
-                id = HISTORY_PANEL_ID;
-                break;
+    public static String getIdForBuiltinPanelType(PanelType panelType) {
+        switch(panelType) {
+        case TOP_SITES:
+            return TOP_SITES_PANEL_ID;
 
-            case REMOTE_TABS:
-                titleId = R.string.home_remote_tabs_title;
-                id = REMOTE_TABS_PANEL_ID;
-                break;
+        case BOOKMARKS:
+            return BOOKMARKS_PANEL_ID;
+
+        case HISTORY:
+            return HISTORY_PANEL_ID;
+
+        case REMOTE_TABS:
+            return REMOTE_TABS_PANEL_ID;
 
-            case READING_LIST:
-                titleId = R.string.reading_list_title;
-                id = READING_LIST_PANEL_ID;
-                break;
+        case READING_LIST:
+            return READING_LIST_PANEL_ID;
+
+        case RECENT_TABS:
+            return RECENT_TABS_PANEL_ID;
 
-            case RECENT_TABS:
-                titleId = R.string.recent_tabs_title;
-                id = RECENT_TABS_PANEL_ID;
-                break;
+        default:
+            throw new IllegalArgumentException("Only for built-in panel types: " + panelType);
+        }
+    }
 
-            case DYNAMIC:
-                throw new IllegalArgumentException("createBuiltinPanelConfig() is only for built-in panels");
-        }
+    public static PanelConfig createBuiltinPanelConfig(Context context, PanelType panelType, EnumSet<PanelConfig.Flags> flags) {
+        final int titleId = getTitleResourceIdForBuiltinPanelType(panelType);
+        final String id = getIdForBuiltinPanelType(panelType);
 
         return new PanelConfig(panelType, context.getString(titleId), id, flags);
     }
 
     public static HomeConfig getDefault(Context context) {
         return new HomeConfig(new HomeConfigPrefsBackend(context));
     }
 }
--- a/mobile/android/base/tabs/RemoteTabsPanel.java
+++ b/mobile/android/base/tabs/RemoteTabsPanel.java
@@ -1,17 +1,18 @@
 /* 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.tabs;
 
+import org.mozilla.gecko.AboutPages;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Tabs;
-import org.mozilla.gecko.home.HomeConfig;
+import org.mozilla.gecko.home.HomeConfig.PanelType;
 import org.mozilla.gecko.tabs.TabsPanel.PanelView;
 
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
@@ -28,17 +29,25 @@ class RemoteTabsPanel extends FrameLayou
         super(context, attrs);
 
         LayoutInflater.from(context).inflate(R.layout.remote_tabs_panel, this);
 
         final View link = findViewById(R.id.go_to_panel);
         link.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                // For now, we don't do anything.
+                // It is possible that this will fail: if the user has removed
+                // the Remote Tabs panel, it won't exist. (The new tab will open
+                // to the default panel, which is confusing but not
+                // catastrophic.) Querying the current configuration to
+                // determine if the panel is present is not worth the effort; we
+                // expect very few configurations to not include the Remote Tabs
+                // panel.
+                Tabs.getInstance().loadUrl(AboutPages.getURLForBuiltinPanelType(PanelType.REMOTE_TABS),
+                        Tabs.LOADURL_NEW_TAB);
                 if (tabsPanel != null) {
                     tabsPanel.autoHidePanel();
                 }
             }
         });
     }
 
     @Override