Bug 1406338 - Part 2: Show favicons in tabs tray page. r=nechen
authorJing-wei Wu <topwu.tw@gmail.com>
Mon, 09 Oct 2017 11:02:52 +0800
changeset 385338 5e2772fd3b677aa1d266c62ccface234028cc9ed
parent 385337 ef0e62e2956d5afb4fe228a6094e32c526c21e8b
child 385339 71d6058e889b542e489cd7b260e603a979ffee12
push id32652
push userarchaeopteryx@coole-files.de
push dateTue, 10 Oct 2017 21:49:31 +0000
treeherdermozilla-central@f1ecd5c26948 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnechen
bugs1406338
milestone58.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 1406338 - Part 2: Show favicons in tabs tray page. r=nechen MozReview-Commit-ID: BXOFuxwI0sl
mobile/android/app/src/main/res/layout-large/tabs_layout_item_view.xml
mobile/android/app/src/main/res/layout/tabs_layout_item_view.xml
mobile/android/app/src/main/res/layout/tabs_list_item_view.xml
mobile/android/app/src/photon/res/values-v17/styles.xml
mobile/android/app/src/photon/res/values/dimens.xml
mobile/android/app/src/photon/res/values/styles.xml
mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutItemView.java
--- a/mobile/android/app/src/main/res/layout-large/tabs_layout_item_view.xml
+++ b/mobile/android/app/src/main/res/layout-large/tabs_layout_item_view.xml
@@ -15,45 +15,57 @@
     <LinearLayout android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:orientation="horizontal"
                   android:duplicateParentState="true"
                   android:paddingLeft="@dimen/tab_highlight_stroke_width"
                   android:paddingRight="@dimen/tab_highlight_stroke_width"
                   android:paddingBottom="@dimen/tab_highlight_stroke_width">
 
-       <org.mozilla.gecko.widget.FadedSingleColorTextView
-               android:id="@+id/title"
-               android:layout_width="0dip"
-               android:layout_height="wrap_content"
-               android:layout_weight="1.0"
-               style="@style/TabLayoutItemTextAppearance"
-               android:textSize="14sp"
-               android:textColor="@color/tab_item_title"
-               android:singleLine="true"
-               android:duplicateParentState="true"
-               gecko:fadeWidth="15dp"
-               android:paddingRight="5dp"
-               android:paddingEnd="5dp"
-               android:paddingLeft="0dp"
-               android:paddingStart="0dp"
-               android:drawablePadding="6dp"/>
+        <org.mozilla.gecko.widget.FaviconView
+            android:id="@+id/favicon"
+            style="@style/TabsLayoutItemFavicon"
+            android:layout_width="16dp"
+            android:layout_height="16dp"
+            android:layout_gravity="center_vertical"
+            android:scaleType="centerInside"
+            gecko:dominantBorderEnabled="false"
+            gecko:overrideScaleType="false"/>
+
+        <org.mozilla.gecko.widget.FadedSingleColorTextView
+            android:id="@+id/title"
+            style="@style/TabLayoutItemTextAppearance"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical"
+            android:drawablePadding="6dp"
+            android:duplicateParentState="true"
+            android:paddingEnd="5dp"
+            android:paddingLeft="0dp"
+            android:paddingRight="5dp"
+            android:paddingStart="0dp"
+            android:singleLine="true"
+            android:textColor="@color/tab_item_title"
+            android:textSize="14sp"
+            gecko:fadeWidth="15dp"/>
 
         <!-- Use of baselineAlignBottom only supported from API 11+ - if this needs to work on lower API versions
              we'll need to override getBaseLine() and return image height, but we assume this won't happen -->
-        <ImageView android:id="@+id/close"
-                     style="@style/TabsItemClose"
-                     android:layout_width="wrap_content"
-                     android:layout_height="wrap_content"
-                     android:scaleType="center"
-                     android:baselineAlignBottom="true"
-                     android:background="@android:color/transparent"
-                     android:contentDescription="@string/close_tab"
-                     android:src="@drawable/tab_item_close_button"
-                     android:duplicateParentState="true"/>
+        <ImageView
+            android:id="@+id/close"
+            style="@style/TabsItemClose"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:background="@android:color/transparent"
+            android:contentDescription="@string/close_tab"
+            android:duplicateParentState="true"
+            android:scaleType="center"
+            android:src="@drawable/tab_item_close_button"/>
 
     </LinearLayout>
 
     <!-- We set state_private on this View dynamically in TabsGridLayout. -->
     <org.mozilla.gecko.widget.TabThumbnailWrapper
             android:id="@+id/wrapper"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
--- a/mobile/android/app/src/main/res/layout/tabs_layout_item_view.xml
+++ b/mobile/android/app/src/main/res/layout/tabs_layout_item_view.xml
@@ -15,45 +15,55 @@
     <LinearLayout android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:orientation="horizontal"
                   android:duplicateParentState="true"
                   android:paddingLeft="@dimen/tab_highlight_stroke_width"
                   android:paddingRight="@dimen/tab_highlight_stroke_width"
                   android:paddingBottom="@dimen/tab_highlight_stroke_width">
 
-       <org.mozilla.gecko.widget.FadedSingleColorTextView
-               android:id="@+id/title"
-               android:layout_width="0dip"
-               android:layout_height="wrap_content"
-               android:layout_weight="1.0"
-               style="@style/TabLayoutItemTextAppearance"
-               android:textSize="14sp"
-               android:textColor="@color/tab_item_title"
-               android:singleLine="true"
-               android:duplicateParentState="true"
-               gecko:fadeWidth="15dp"
-               android:paddingRight="5dp"
-               android:paddingEnd="5dp"
-               android:paddingLeft="0dp"
-               android:paddingStart="0dp"
-               android:drawablePadding="6dp"/>
+        <org.mozilla.gecko.widget.FaviconView
+            android:id="@+id/favicon"
+            style="@style/TabsLayoutItemFavicon"
+            android:layout_width="16dp"
+            android:layout_height="16dp"
+            android:layout_gravity="center_vertical"
+            android:scaleType="centerInside"
+            gecko:dominantBorderEnabled="false"
+            gecko:overrideScaleType="false"/>
 
-        <!-- Use of baselineAlignBottom only supported from API 11+ - if this needs to work on lower API versions
-             we'll need to override getBaseLine() and return image height, but we assume this won't happen -->
-        <ImageView android:id="@+id/close"
-                     style="@style/TabsItemClose"
-                     android:layout_width="wrap_content"
-                     android:layout_height="wrap_content"
-                     android:scaleType="center"
-                     android:baselineAlignBottom="true"
-                     android:background="@android:color/transparent"
-                     android:contentDescription="@string/close_tab"
-                     android:src="@drawable/tab_item_close_button"
-                     android:duplicateParentState="true"/>
+        <org.mozilla.gecko.widget.FadedSingleColorTextView
+            android:id="@+id/title"
+            style="@style/TabLayoutItemTextAppearance"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:layout_weight="1.0"
+            android:drawablePadding="6dp"
+            android:duplicateParentState="true"
+            android:paddingEnd="5dp"
+            android:paddingLeft="0dp"
+            android:paddingRight="5dp"
+            android:paddingStart="0dp"
+            android:singleLine="true"
+            android:textColor="@color/tab_item_title"
+            android:textSize="14sp"
+            gecko:fadeWidth="15dp"/>
+
+        <ImageView
+            android:id="@+id/close"
+            style="@style/TabsItemClose"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:background="@android:color/transparent"
+            android:contentDescription="@string/close_tab"
+            android:duplicateParentState="true"
+            android:scaleType="center"
+            android:src="@drawable/tab_item_close_button"/>
 
     </LinearLayout>
 
     <!-- We set state_private on this View dynamically in TabsGridLayout. -->
     <org.mozilla.gecko.widget.TabThumbnailWrapper
             android:id="@+id/wrapper"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
--- a/mobile/android/app/src/main/res/layout/tabs_list_item_view.xml
+++ b/mobile/android/app/src/main/res/layout/tabs_list_item_view.xml
@@ -1,72 +1,69 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
 
 <org.mozilla.gecko.tabs.TabsLayoutItemView xmlns:android="http://schemas.android.com/apk/res/android"
+                                           xmlns:gecko="http://schemas.android.com/apk/res-auto"
                                            style="@style/TabsItem"
                                            android:focusable="true"
                                            android:id="@+id/info"
                                            android:layout_width="match_parent"
                                            android:layout_height="wrap_content"
                                            android:paddingLeft="12dip"
                                            android:paddingStart="12dip"
                                            android:paddingRight="0dip"
                                            android:paddingEnd="0dip"
                                            android:paddingTop="6dip"
                                            android:paddingBottom="6dip"
                                            android:background="@drawable/tab_row">
 
     <!-- We set state_private on this View dynamically in TabsListLayout. -->
     <org.mozilla.gecko.widget.TabThumbnailWrapper
-            android:id="@+id/wrapper"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:padding="4dip"
-            android:background="@drawable/tab_thumbnail"
-            android:duplicateParentState="true"
-            android:clipToPadding="false">
+        android:id="@+id/wrapper"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="4dip"
+        android:background="@drawable/tab_thumbnail"
+        android:duplicateParentState="true"
+        android:clipToPadding="false">
 
         <org.mozilla.gecko.tabs.TabsPanelThumbnailView
             android:id="@+id/thumbnail"
             android:layout_width="137dp"
             android:layout_height="wrap_content"/>
 
     </org.mozilla.gecko.widget.TabThumbnailWrapper>
 
-    <LinearLayout android:layout_width="0dip"
-                  android:layout_height="match_parent"
-                  android:orientation="vertical"
-                  android:layout_weight="1.0"
-                  android:paddingTop="4dip"
-                  android:paddingLeft="10dp"
-                  android:paddingStart="10dp"
-                  android:paddingRight="2dp"
-                  android:paddingEnd="4dip"
-                  android:duplicateParentState="true">
+    <org.mozilla.gecko.widget.FaviconView
+        android:id="@+id/favicon"
+        style="@style/TabsListItemFavicon"
+        android:layout_width="16dp"
+        android:layout_height="16dp"
+        android:layout_gravity="center_vertical"
+        android:scaleType="centerInside"
+        gecko:dominantBorderEnabled="false"
+        gecko:overrideScaleType="false"/>
 
-        <TextView android:id="@+id/title"
-                  android:layout_width="match_parent"
-                  android:layout_height="0dip"
-                  android:layout_weight="1.0"
-                  style="@style/TabLayoutItemTextAppearance"
-                  android:textColor="@color/tab_item_title"
-                  android:textSize="14sp"
-                  android:gravity="center_vertical"
-                  android:singleLine="false"
-                  android:maxLines="4"
-                  android:drawablePadding="6dp"
-                  android:duplicateParentState="true"/>
-
-    </LinearLayout>
+    <TextView android:id="@+id/title"
+              android:layout_width="0dp"
+              android:layout_height="wrap_content"
+              android:layout_weight="1"
+              style="@style/TabLayoutItemTextAppearance"
+              android:textColor="@color/tab_item_title"
+              android:textSize="14sp"
+              android:layout_gravity="center_vertical"
+              android:singleLine="false"
+              android:maxLines="4"
+              android:duplicateParentState="true"/>
 
     <ImageView android:id="@+id/close"
-                 style="@style/TabsItemClose"
-                 android:layout_width="34dip"
-                 android:layout_height="match_parent"
-                 android:scaleType="center"
-                 android:contentDescription="@string/close_tab"
-                 android:src="@drawable/tab_item_close_button"
-                 android:duplicateParentState="true"/>
+               style="@style/TabsItemClose"
+               android:layout_width="34dip"
+               android:layout_height="match_parent"
+               android:contentDescription="@string/close_tab"
+               android:duplicateParentState="true"
+               android:scaleType="center"
+               android:src="@drawable/tab_item_close_button"/>
 
 </org.mozilla.gecko.tabs.TabsLayoutItemView>
\ No newline at end of file
--- a/mobile/android/app/src/photon/res/values-v17/styles.xml
+++ b/mobile/android/app/src/photon/res/values-v17/styles.xml
@@ -72,16 +72,25 @@
         <item name="android:layout_alignEnd">@id/url_bar_entry</item>
     </style>
 
     <style name="UrlBar.QRCode" parent="UrlBar.V17.QRCode"/>
     <style name="UrlBar.V17.QRCode" parent="UrlBar.ImageButton">
         <item name="android:layout_marginRight">-3dp</item>
     </style>
 
+    <style name="TabsLayoutItemFavicon">
+        <item name="android:layout_marginEnd">4dp</item>
+    </style>
+
+    <style name="TabsListItemFavicon">
+        <item name="android:layout_marginStart">10dp</item>
+        <item name="android:layout_marginEnd">6dp</item>
+    </style>
+
     <style name="TabsTray.AddTab" parent="TabsTray.V17.AddTab" />
     <style name="TabsTray.V17.AddTab" parent="TabsTray.Base.AddTab">
         <item name="android:layout_marginEnd">-3dp</item>
     </style>
 
     <style name="TabsTray.Menu" parent="TabsTray.V17.Menu" />
     <style name="TabsTray.V17.Menu" parent="TabsTray.Base.Menu"/>
 
--- a/mobile/android/app/src/photon/res/values/dimens.xml
+++ b/mobile/android/app/src/photon/res/values/dimens.xml
@@ -170,16 +170,18 @@
     <!-- CompactTabsGridLayout -->
     <dimen name="tab_panel_grid_hpadding_compact">15dp</dimen>
     <dimen name="tab_panel_grid_vpadding_compact">7dp</dimen>
     <dimen name="tab_panel_grid_item_hpadding_compact">10dp</dimen>
     <dimen name="tab_panel_grid_item_vpadding_compact">6dp</dimen>
 
     <!-- TabsListLayout -->
     <dimen name="tab_highlight_stroke_width">5dp</dimen>
+    <dimen name="tab_favicon_size">16dp</dimen>
+    <dimen name="tab_favicon_text_size">12sp</dimen>
 
     <!-- PageActionButtons dimensions -->
     <dimen name="page_action_button_width">@dimen/browser_toolbar_image_button_width</dimen>
 
     <!-- Banner -->
     <dimen name="home_banner_height">72dp</dimen>
     <dimen name="home_banner_close_width">42dp</dimen>
     <dimen name="home_banner_icon_height">48dip</dimen>
--- a/mobile/android/app/src/photon/res/values/styles.xml
+++ b/mobile/android/app/src/photon/res/values/styles.xml
@@ -513,16 +513,25 @@
     <style name="TabsItem">
          <item name="android:nextFocusRight">@+id/close</item>
     </style>
 
     <style name="TabsItemClose">
          <item name="android:nextFocusLeft">@+id/info</item>
     </style>
 
+    <style name="TabsLayoutItemFavicon">
+        <item name="android:layout_marginRight">4dp</item>
+    </style>
+
+    <style name="TabsListItemFavicon">
+        <item name="android:layout_marginLeft">10dp</item>
+        <item name="android:layout_marginRight">6dp</item>
+    </style>
+
     <style name="Widget.RemoteTabsItemView" parent="Widget.TwoLinePageRow"/>
 
     <style name="Widget.RemoteTabsClientView" parent="Widget.TwoLinePageRow">
         <item name="android:background">@color/about_page_header_grey</item>
     </style>
 
     <style name="Widget.RemoteTabsListView" parent="Widget.HomeListView">
         <item name="android:childDivider">@color/toolbar_divider_grey</item>
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutItemView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutItemView.java
@@ -2,48 +2,56 @@
  * 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.R;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
+import org.mozilla.gecko.icons.IconResponse;
+import org.mozilla.gecko.icons.Icons;
+import org.mozilla.gecko.widget.FaviconView;
 import org.mozilla.gecko.widget.HoverDelegateWithReset;
 import org.mozilla.gecko.widget.TabThumbnailWrapper;
 import org.mozilla.gecko.widget.TouchDelegateWithReset;
 import org.mozilla.gecko.widget.themed.ThemedRelativeLayout;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.support.v4.widget.TextViewCompat;
 import android.support.v7.widget.ViewUtils;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.Checkable;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import java.util.concurrent.Future;
+
 public class TabsLayoutItemView extends LinearLayout
                                 implements Checkable {
     private static final String LOGTAG = "Gecko" + TabsLayoutItemView.class.getSimpleName();
     private static final int[] STATE_CHECKED = { android.R.attr.state_checked };
     private boolean mChecked;
 
     private int mTabId;
     private TextView mTitle;
     private TabsPanelThumbnailView mThumbnail;
     private ImageView mCloseButton;
     private TabThumbnailWrapper mThumbnailWrapper;
     private HoverDelegateWithReset mHoverDelegate;
 
+    private FaviconView mFaviconView;
+    private Future<IconResponse> mOngoingIconLoad;
+
     public TabsLayoutItemView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
     @Override
     public int[] onCreateDrawableState(int extraSpace) {
         final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
 
@@ -93,16 +101,17 @@ public class TabsLayoutItemView extends 
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
         mTitle = (TextView) findViewById(R.id.title);
         mThumbnail = (TabsPanelThumbnailView) findViewById(R.id.thumbnail);
         mCloseButton = (ImageView) findViewById(R.id.close);
         mThumbnailWrapper = (TabThumbnailWrapper) findViewById(R.id.wrapper);
+        mFaviconView = (FaviconView) findViewById(R.id.favicon);
 
         growCloseButtonHitArea();
     }
 
     private void growCloseButtonHitArea() {
         addOnLayoutChangeListener(new OnLayoutChangeListener() {
             @Override
             public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
@@ -164,22 +173,37 @@ public class TabsLayoutItemView extends 
             mThumbnailWrapper.setRecording(tab.isRecording());
         }
 
         final String tabTitle = tab.getDisplayTitle();
         mTitle.setText(tabTitle);
         mCloseButton.setTag(this);
 
         if (tab.isAudioPlaying()) {
-            TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(mTitle, R.drawable.tab_audio_playing, 0, 0, 0);
+            mFaviconView.setImageResource(R.drawable.tab_audio_playing);
             final String tabTitleWithAudio =
                     getResources().getString(R.string.tab_title_prefix_is_playing_audio, tabTitle);
             mTitle.setContentDescription(tabTitleWithAudio);
         } else {
-            TextViewCompat.setCompoundDrawablesRelative(mTitle, null, null, null, null);
+            if (mOngoingIconLoad != null) {
+                mOngoingIconLoad.cancel(true);
+            }
+
+            final Resources resources = getResources();
+            final int iconSize = resources.getDimensionPixelSize(R.dimen.tab_favicon_size);
+            final float textSize = resources.getDimensionPixelSize(R.dimen.tab_favicon_text_size);
+
+            mOngoingIconLoad = Icons.with(getContext())
+                                       .pageUrl(tab.getURL())
+                                       .skipNetwork()
+                                       .targetSize(iconSize)
+                                       .textSize(textSize)
+                                       .build()
+                                       .execute(mFaviconView.createIconCallback());
+
             mTitle.setContentDescription(tabTitle);
         }
     }
 
     public int getTabId() {
         return mTabId;
     }