Bug 710325 - Show addon icon in about:home (r=mfinkle)
authorLucas Rocha <lucasr@mozilla.com>
Tue, 24 Jan 2012 16:52:26 +0000
changeset 86470 3ac73fd59a12f87ab198f2122f5f8c1b2b572452
parent 86469 c1a1a872ecaa1145bb80c3b3227e80746bf7c538
child 86471 fd472718b66ebbedb5f783a057da8725de2c8232
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs710325
milestone12.0a1
Bug 710325 - Show addon icon in about:home (r=mfinkle)
mobile/android/base/AboutHomeContent.java
mobile/android/base/Makefile.in
mobile/android/base/resources/drawable-hdpi-v8/ic_addons_empty.png
mobile/android/base/resources/drawable-mdpi-v8/ic_addons_empty.png
mobile/android/base/resources/drawable-xhdpi-v11/ic_addons_empty.png
mobile/android/base/resources/layout/abouthome_addon_row.xml
--- a/mobile/android/base/AboutHomeContent.java
+++ b/mobile/android/base/AboutHomeContent.java
@@ -38,16 +38,18 @@
 
 package org.mozilla.gecko;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.io.IOException;
+import java.net.URL;
+import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.db.BrowserDB;
@@ -60,16 +62,17 @@ import android.app.Activity;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.text.SpannableString;
 import android.text.style.StyleSpan;
 import android.text.style.UnderlineSpan;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.DisplayMetrics;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -401,16 +404,34 @@ public class AboutHomeContent extends Sc
                 // catch this here because we can continue even if the
                 // close failed
                 Log.e(LOGTAG, "error closing filestream", ioe);
             }
         }
         return str;
     }
 
+    private String getPageUrlFromIconUrl(String iconUrl) {
+        // Addon icon URLs come with a query argument that is usually
+        // used for expiration purposes. We want the "page URL" here to be
+        // stable enough to avoid unnecessary duplicate records of the
+        // same addon.
+        String pageUrl = iconUrl;
+
+        try {
+            URL urlForIcon = new URL(iconUrl);
+            URL urlForPage = new URL(urlForIcon.getProtocol(), urlForIcon.getAuthority(), urlForIcon.getPath());
+            pageUrl = urlForPage.toString();
+        } catch (MalformedURLException e) {
+            // Defaults to pageUrl = iconUrl in case of error
+        }
+
+        return pageUrl;
+    }
+
     private void readRecommendedAddons(final Activity activity) {
         final String addonsFilename = "recommended-addons.json";
         String jsonString = readJSONFile(activity, addonsFilename);
         if (jsonString == null) {
             Log.i("Addons", "filestream is null");
             jsonString = readFromZipFile(activity, addonsFilename);
         }
         if (jsonString == null)
@@ -425,20 +446,34 @@ public class AboutHomeContent extends Sc
         }
 
         GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
             public void run() {
                 try {
                     for (int i = 0; i < array.length(); i++) {
                         JSONObject jsonobj = array.getJSONObject(i);
 
-                        View row = mInflater.inflate(R.layout.abouthome_addon_row, mAddonsLayout, false);
+                        final View row = mInflater.inflate(R.layout.abouthome_addon_row, mAddonsLayout, false);
                         ((TextView) row.findViewById(R.id.addon_title)).setText(jsonobj.getString("name"));
                         ((TextView) row.findViewById(R.id.addon_version)).setText(jsonobj.getString("version"));
 
+                        String iconUrl = jsonobj.getString("iconURL");
+                        String pageUrl = getPageUrlFromIconUrl(iconUrl);
+
+                        Favicons favicons = GeckoApp.mAppContext.mFavicons;
+                        favicons.loadFavicon(pageUrl, iconUrl,
+                                    new Favicons.OnFaviconLoadedListener() {
+                            public void onFaviconLoaded(String url, Drawable favicon) {
+                                if (favicon != null) {
+                                    ImageView icon = (ImageView) row.findViewById(R.id.addon_icon);
+                                    icon.setImageDrawable(favicon);
+                                }
+                            }
+                        });
+
                         mAddonsLayout.addView(row);
                     }
                 } catch (JSONException e) {
                     Log.i(LOGTAG, "error reading json file", e);
                 }
             }
         });
     }
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -279,16 +279,17 @@ RES_DRAWABLE_MDPI_V8 = \
   res/drawable-mdpi-v8/abouthome_separator.9.png \
   res/drawable-mdpi-v8/abouthome_sync_logo.png \
   res/drawable-mdpi-v8/abouthome_sync_bg.9.png \
   res/drawable-mdpi-v8/abouthome_sync_pressed_bg.9.png \
   res/drawable-mdpi-v8/abouthome_topsite_placeholder.png \
   res/drawable-mdpi-v8/abouthome_topsite_shadow.9.png \
   res/drawable-mdpi-v8/awesomebar_tab.9.png \
   res/drawable-mdpi-v8/awesomebar_tab_pressed.9.png \
+  res/drawable-mdpi-v8/ic_addons_empty.png \
   res/drawable-mdpi-v8/ic_awesomebar_go.png \
   res/drawable-mdpi-v8/ic_awesomebar_search.png \
   res/drawable-mdpi-v8/ic_menu_bookmark_add.png \
   res/drawable-mdpi-v8/ic_menu_bookmark_remove.png \
   res/drawable-mdpi-v8/ic_menu_find_in_page.png \
   res/drawable-mdpi-v8/ic_menu_reload.png \
   res/drawable-mdpi-v8/ic_menu_save_as_pdf.png \
   res/drawable-mdpi-v8/ic_menu_share.png \
@@ -322,16 +323,17 @@ RES_DRAWABLE_HDPI_V8 = \
   res/drawable-hdpi-v8/abouthome_separator.9.png \
   res/drawable-hdpi-v8/abouthome_sync_logo.png \
   res/drawable-hdpi-v8/abouthome_sync_bg.9.png \
   res/drawable-hdpi-v8/abouthome_sync_pressed_bg.9.png \
   res/drawable-hdpi-v8/abouthome_topsite_placeholder.png \
   res/drawable-hdpi-v8/abouthome_topsite_shadow.9.png \
   res/drawable-hdpi-v8/awesomebar_tab.9.png \
   res/drawable-hdpi-v8/awesomebar_tab_pressed.9.png \
+  res/drawable-hdpi-v8/ic_addons_empty.png \
   res/drawable-hdpi-v8/ic_awesomebar_go.png \
   res/drawable-hdpi-v8/ic_awesomebar_search.png \
   res/drawable-hdpi-v8/ic_menu_bookmark_add.png \
   res/drawable-hdpi-v8/ic_menu_bookmark_remove.png \
   res/drawable-hdpi-v8/ic_menu_find_in_page.png \
   res/drawable-hdpi-v8/ic_menu_reload.png \
   res/drawable-hdpi-v8/ic_menu_save_as_pdf.png \
   res/drawable-hdpi-v8/ic_menu_share.png \
@@ -383,16 +385,17 @@ RES_DRAWABLE_XHDPI_V11 = \
   res/drawable-xhdpi-v11/abouthome_separator.9.png \
   res/drawable-xhdpi-v11/abouthome_sync_logo.png \
   res/drawable-xhdpi-v11/abouthome_sync_bg.9.png \
   res/drawable-xhdpi-v11/abouthome_sync_pressed_bg.9.png \
   res/drawable-xhdpi-v11/abouthome_topsite_placeholder.png \
   res/drawable-xhdpi-v11/abouthome_topsite_shadow.9.png \
   res/drawable-xhdpi-v11/awesomebar_tab.9.png \
   res/drawable-xhdpi-v11/awesomebar_tab_pressed.9.png \
+  res/drawable-xhdpi-v11/ic_addons_empty.png \
   res/drawable-xhdpi-v11/ic_awesomebar_go.png \
   res/drawable-xhdpi-v11/ic_awesomebar_search.png \
   res/drawable-xhdpi-v11/ic_menu_bookmark_add.png \
   res/drawable-xhdpi-v11/ic_menu_bookmark_remove.png \
   res/drawable-xhdpi-v11/ic_menu_find_in_page.png \
   res/drawable-xhdpi-v11/ic_menu_reload.png \
   res/drawable-xhdpi-v11/ic_menu_save_as_pdf.png \
   res/drawable-xhdpi-v11/ic_menu_share.png \
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..646b8734e66aab5dd6ec63ff8b484c9d81ba07a2
GIT binary patch
literal 639
zc$@)$0)YLAP)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!AxT6*RCwC#nz>5@K@`R(F^abY6%z#;
zZL|<EXd!~Nf(KaGC<>NhZ)s`mUmyfq3k%UoEJPFpZ-_Q3MASgkpx}Xt-@^$k!{(UH
zZk&br;75|3+2wtEyqS3$Pb!sS({uC8qB=o42ngF>K@=Q<FXo_p1?)QsIx@61^R^HO
zgSb-$ycYNC%M!d%elYIj6|iccTcU3(Xi&{Sm1O@))eIyg`@g7W;6S49nFYg+8#o8s
zdGxyh8!A4;q<s*{(*6zB_@|NvSdKyJ$LZkhF!1kky@B*pViA<vd~7=2lH@)gU|HWn
z+JH8o4QK<}fHt5F6nQRWHkYS`$OWhYJz(%3;|%aZLMeCym*CN8;Fve2bpr1AcPdit
zfI7))gk7TI*#sytY#RWZ;3#ciD~|(3ieP|(3>kh`^DFN)={F2+Wh!&;ML64Z7mP@l
z?Q;7=?3Xd%RXGa<gaBhE3-X}K24;mNC1s$n!Gxbb`K}oUs35xlu0aL+dk0XaVEoB!
zS*TV>X(}q_Q!F4Vl&uQmz!)>HhEoOOR5b%ha4&2lLsNVvkk&I;2MHfjUz8D7KpUTz
z(d()xzgo;L195)lJ`HI(Xye#Hb=E7HEF_~{KG_r10%n}fUWJ~ahYZ0pewp`FU(m#I
zv_GkCpgu=?qv{6eg?4X-wkFW;hBfgJA8<sCGW$#Rju`L?%RM_YoGz;<FAx3Q#?AT_
ZU;ue-R-<L;nLPji002ovPDHLkV1oH&4?zF`
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9be84f414def68cfe869fcfc5f60445654331435
GIT binary patch
literal 467
zc$@*#0WAKBP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzbxA})RCwBAiAl<0AOi3Mu@?}l05LOE
z>=zK<1mdkg{DXl^z(S<DFd&vj6JrBnT_FAk#Ouj*022{vc(7QG4AdAX0K_=pClLR|
zBmb4w4)_hkdvM5sf`1>a9RLEyf%qC0@sl{jsqO$=K}}Kclj;DP08lpM0OATV^}9eZ
zKG1=$oEY#B7<Is?0|u=FKGCxr0F~#@kSd<_PzQi&xp1WVpBg|1h@GKTIjAkModw#k
zn1x00Eg*gb#EKMJY5=X!K#dwZByl5<-Gmw>zp3DB4?J?31Dy!jK_S43<VsNOb`aVC
z;Uv%!qFN#ZB{E|qF)bi|2yK9J)7bt$*wTOq6jKXafQBeP)Kkdd0Sg`Cc?VK;>;w&M
zP{=+2$+6Hm(d~m`HfZ)|AjJV74U2*JF_aHVyq?hfOe*+APF-*f$#Pg3v5(RqA;kf_
zIJ#_fbAU1sn<DX<p<On*R>xvUY*u=Q08Ien|Ns97)Byki1^}J3KjXiAhL->U002ov
JPDHLkV1f<^y9WRO
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3845ad6aea505f167f937b7ccea13d282b2442b9
GIT binary patch
literal 793
zc$@(l1LpjRP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!yGcYrRCwC#o6k!WVHn4sT}?A2D~!xK
zC~83<)y*KNPIc&F9i+g6^yAV$;Gf_>;LV^AJa`I2D3Ll8ScfnuvV*}As2#$MNQzZk
zzYp^cEaU9X%+Bb{`@YW?KCnCczAyWH=Y8k>Ik|GVOvCpcQ9?QhE`gJvwMv>lU=1vQ
zf0UvoACFUGg5`CCL2x)k+B4uHm;uXanvhSZoa5kb$lzUZ+97bl1Ou*t19jx%JXdr#
zfXnEMk-sm&8<C0u&2`@W%39E@vjJN%^Z!qvj8qNS1gkOfuc<P$eh9vak@uAey}%N9
zQAfUc@XZ7RSnt5g2<cygx0JGy?tT^{q<v2rP@XK87$62%E_XUSs^;?hsnMAEc`ac~
zYJeCZ28aP-fEXYKhyh}N7$63S0b+m{ur~&j$XWMaH+emvn!bSN;II0A6x;+o8pPI4
z&K7(JXaT>#2l6b#y9WFKO`ZaH$7YtCtt(eWFa;i{g0re~;5KNexYntze^NKKRB6DI
z2!(HxbGl<Nqrvy9|CX=uJIC-WOcSW4Vg>@`8vD@adS{5d7r;kQXe51=4;gH&W>T=Z
z8*H<E9FU7+fHB6^8^~$X210%tBRn>k1RI{~e7x<l4K;uVIwRn$>T+6DA9|nme-|mW
zp)e08?-=?J+_JqFSdB9h%!2r2ncumj0dkJ+))G(d7IimZTg~pg`U-{vCTlb9!`;Lt
zz=1tgQ+cm`s)^rH*oUC5;wnC^)-R5MBdS|piP{V3u42&4b*~Kg4d%di_1P64j6Maf
zf-aqh!a>z<0(|xa?>@N;svRzyYQTa|;C`Al)qs@<?XzT}0f$1SYogr?u|^nhK4iLn
zQ=339xE_#(_Z4oKY5<F0p6ssi`z?z1o>Arvpnw1ybXX9vLSlgJ2ITndaWTMR?FcXc
Xx}t7e$yv4B00000NkvXXu0mjf3z=(R
--- a/mobile/android/base/resources/layout/abouthome_addon_row.xml
+++ b/mobile/android/base/resources/layout/abouthome_addon_row.xml
@@ -1,18 +1,26 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 android:layout_width="fill_parent"
                 android:layout_height="47dip"
                 android:gravity="left|center_vertical"
                 android:background="@drawable/abouthome_separator">
 
+    <ImageView android:id="@+id/addon_icon"
+               android:layout_width="32dp"
+               android:layout_height="32dp"
+               android:layout_centerVertical="true"
+               android:layout_marginLeft="12dip"
+               android:src="@drawable/ic_addons_empty"/>
+
     <TextView android:id="@+id/addon_title"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
+              android:layout_toRightOf="@id/addon_icon"
               android:layout_marginLeft="12dip"
               android:layout_centerVertical="true"
               android:textSize="15sp"
               android:textColor="#222222"/>
 
     <TextView android:id="@+id/addon_version"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"