Updated Tile view for folder and favicon

- New layouts for folder icons in Bookmarks view.
- Reworked favicon tile views.
- Display of SSL certification information on top of favicon
- Modified logic behind showing counter on top of favicon

Change-Id: Iaacc13be37e7cc65e859b46e0d91d5d5d6b62a9e
diff --git a/res/color/clickable_color.xml b/res/color/clickable_color.xml
new file mode 100644
index 0000000..2e50a54
--- /dev/null
+++ b/res/color/clickable_color.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, are permitted provided that the following conditions are
+     met:
+         * Redistributions of source code must retain the above copyright
+           notice, this list of conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above
+           copyright notice, this list of conditions and the following
+           disclaimer in the documentation and/or other materials provided
+           with the distribution.
+         * Neither the name of The Linux Foundation nor the names of its
+           contributors may be used to endorse or promote products derived
+           from this software without specific prior written permission.
+
+     THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+     WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+     ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+     OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+     IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_enabled="true" android:state_pressed="true"
+        android:color="@color/accent" />
+
+    <item android:state_enabled="true" android:state_selected="true"
+        android:color="@color/accent" />
+
+    <item android:color="@color/bookmarkLabelColor" />
+
+</selector>
diff --git a/res/drawable-xxhdpi/img_deco_bookmarks_folder_small_bright.png b/res/drawable-xxhdpi/img_deco_bookmarks_folder_small_bright.png
new file mode 100644
index 0000000..c76ea0d
--- /dev/null
+++ b/res/drawable-xxhdpi/img_deco_bookmarks_folder_small_bright.png
Binary files differ
diff --git a/res/drawable-xxhdpi/img_deco_tile_avoid.png b/res/drawable-xxhdpi/img_deco_tile_avoid.png
new file mode 100644
index 0000000..4e96b81
--- /dev/null
+++ b/res/drawable-xxhdpi/img_deco_tile_avoid.png
Binary files differ
diff --git a/res/drawable-xxhdpi/img_deco_tile_avoid_accent.png b/res/drawable-xxhdpi/img_deco_tile_avoid_accent.png
new file mode 100644
index 0000000..defcc26
--- /dev/null
+++ b/res/drawable-xxhdpi/img_deco_tile_avoid_accent.png
Binary files differ
diff --git a/res/drawable-xxhdpi/img_deco_tile_unknown.png b/res/drawable-xxhdpi/img_deco_tile_unknown.png
new file mode 100644
index 0000000..80a263a
--- /dev/null
+++ b/res/drawable-xxhdpi/img_deco_tile_unknown.png
Binary files differ
diff --git a/res/drawable-xxhdpi/img_deco_tile_unknown_accent.png b/res/drawable-xxhdpi/img_deco_tile_unknown_accent.png
new file mode 100644
index 0000000..9fba533
--- /dev/null
+++ b/res/drawable-xxhdpi/img_deco_tile_unknown_accent.png
Binary files differ
diff --git a/res/drawable-xxhdpi/img_deco_tile_untrusted.png b/res/drawable-xxhdpi/img_deco_tile_untrusted.png
new file mode 100644
index 0000000..79568c3
--- /dev/null
+++ b/res/drawable-xxhdpi/img_deco_tile_untrusted.png
Binary files differ
diff --git a/res/drawable-xxhdpi/img_deco_tile_untrusted_accent.png b/res/drawable-xxhdpi/img_deco_tile_untrusted_accent.png
new file mode 100644
index 0000000..0955608
--- /dev/null
+++ b/res/drawable-xxhdpi/img_deco_tile_untrusted_accent.png
Binary files differ
diff --git a/res/drawable-xxhdpi/img_deco_tile_verified.png b/res/drawable-xxhdpi/img_deco_tile_verified.png
new file mode 100644
index 0000000..ec2098b
--- /dev/null
+++ b/res/drawable-xxhdpi/img_deco_tile_verified.png
Binary files differ
diff --git a/res/drawable-xxhdpi/img_deco_tile_verified_accent.png b/res/drawable-xxhdpi/img_deco_tile_verified_accent.png
new file mode 100644
index 0000000..592bdf5
--- /dev/null
+++ b/res/drawable-xxhdpi/img_deco_tile_verified_accent.png
Binary files differ
diff --git a/res/layout/bookmark_thumbnail.xml b/res/layout/bookmark_thumbnail.xml
index 8913551..763fcd8 100644
--- a/res/layout/bookmark_thumbnail.xml
+++ b/res/layout/bookmark_thumbnail.xml
@@ -23,10 +23,16 @@
     android:paddingEnd="@dimen/combo_horizontalSpacing"
     android:paddingStart="@dimen/combo_horizontalSpacing" >
 
-    <com.android.browser.SiteTileView
-        android:id="@+id/thumb_image"
+    <FrameLayout
+        android:id="@+id/container"
         android:layout_width="@dimen/bookmarkThumbnailWidth"
-        android:layout_height="@dimen/bookmarkThumbnailHeight" />
+        android:layout_height="@dimen/bookmarkThumbnailHeight">
+
+        <!-- The SiteTileView or FolderTileView will be injected here dynamically -->
+
+        <!-- The Managed (MDM) badge (an ImageView) will be injected here dynamically -->
+
+    </FrameLayout>
 
     <TextView
         android:id="@+id/label"
diff --git a/res/layout/folder_tile_view.xml b/res/layout/folder_tile_view.xml
new file mode 100644
index 0000000..a92f124
--- /dev/null
+++ b/res/layout/folder_tile_view.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, are permitted provided that the following conditions are
+     met:
+         * Redistributions of source code must retain the above copyright
+           notice, this list of conditions and the following disclaimer.
+         * Redistributions in binary form must reproduce the above
+           copyright notice, this list of conditions and the following
+           disclaimer in the documentation and/or other materials provided
+           with the distribution.
+         * Neither the name of The Linux Foundation nor the names of its
+           contributors may be used to endorse or promote products derived
+           from this software without specific prior written permission.
+
+     THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+     WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+     ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+     OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+     IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!-- Note: the layout_width and height are ignored and replaced at runtime -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="80dp"
+    android:layout_height="80dp"
+    android:orientation="vertical"
+    android:padding="4dp">
+
+    <!-- upper part, with the large bright text -->
+    <TextView
+        android:id="@android:id/text1"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_marginEnd="16dp"
+        android:layout_weight="1"
+        android:ellipsize="end"
+        android:lineSpacingMultiplier="1.2"
+        android:lines="3"
+        android:maxLines="3"
+        android:textColor="@color/FolderTileTitle"
+        android:textSize="16sp" />
+
+    <!-- lower part, with the number of items -->
+    <TextView
+        android:id="@android:id/text2"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:drawableEnd="@drawable/img_deco_bookmarks_folder_small_bright"
+        android:drawablePadding="2dp"
+        android:ellipsize="none"
+        android:gravity="center_vertical"
+        android:singleLine="true"
+        android:textColor="@color/FolderTileCount"
+        android:textSize="10sp"
+        tools:ignore="SmallSp" />
+
+</LinearLayout>
+
diff --git a/res/values-v17/styles.xml b/res/values-v17/styles.xml
index 63ff214..7f1e82a 100644
--- a/res/values-v17/styles.xml
+++ b/res/values-v17/styles.xml
@@ -71,7 +71,8 @@
 
     <style name="BookmarkPathText">
         <item name="android:textSize">18sp</item>
-        <item name="android:textColor">@color/bookmarkLabelColor</item>
+        <item name="android:textColor">@color/clickable_color</item>
+        <item name="android:background">?android:attr/selectableItemBackgroundBorderless</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textAlignment">center</item>
         <item name="android:fontFamily">roboto</item>
diff --git a/res/values/attrs_site_tile_view.xml b/res/values/attrs_tiles.xml
similarity index 89%
rename from res/values/attrs_site_tile_view.xml
rename to res/values/attrs_tiles.xml
index 26b8486..d6ec292 100644
--- a/res/values/attrs_site_tile_view.xml
+++ b/res/values/attrs_tiles.xml
@@ -27,11 +27,17 @@
     IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 -->
 <resources>
+
     <declare-styleable name="SiteTileView">
         <attr name="android:src" />
-        <attr name="flat" format="boolean|reference" />
-        <attr name="floating" format="boolean|reference" />
+        <attr name="disableBackground" format="boolean|reference" />
         <attr name="trustLevel" format="integer|reference" />
         <attr name="blockedObjects" format="integer|reference" />
     </declare-styleable>
+
+    <declare-styleable name="FolderTileView">
+        <attr name="android:text" />
+        <attr name="android:label" />
+    </declare-styleable>
+
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index b76ad30..6a3edfd 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -55,8 +55,13 @@
     <color name="tabViewTitleBackground">#D0000000</color>
     <color name="navtab_bg">#80606060</color>
 
-    <color name="SiteTileOverlineUnknown">@android:color/transparent</color>
-    <color name="SiteTileOverlineTrusted">#00b813</color>
-    <color name="SiteTileOverlineUntrusted">#ebc400</color>
-    <color name="SiteTileOverlineAvoid">#d70704</color>
+    <color name="TileBadgeTextAvoid">#fff</color>
+    <color name="TileBadgeTextUntrusted">#333</color>
+    <color name="TileBadgeTextUnknown">#333</color>
+    <color name="TileBadgeTextVerified">#fff</color>
+
+    <!-- xml configuration for FolderTileView -->
+    <color name="FolderTileBackground">#555</color>
+    <color name="FolderTileTitle">#fff</color>
+    <color name="FolderTileCount">#fff</color>
 </resources>
diff --git a/src/com/android/browser/BrowserBookmarksAdapter.java b/src/com/android/browser/BrowserBookmarksAdapter.java
index fc75050..a65753c 100644
--- a/src/com/android/browser/BrowserBookmarksAdapter.java
+++ b/src/com/android/browser/BrowserBookmarksAdapter.java
@@ -17,6 +17,7 @@
 package com.android.browser;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -24,8 +25,6 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
 
 import com.android.browser.mdm.EditBookmarksRestriction;
 import com.android.browser.mdm.ManagedBookmarksRestriction;
@@ -62,75 +61,46 @@
         return mInflater.inflate(R.layout.bookmark_thumbnail, parent, false);
     }
 
-    @Override
-    public void bindView(View view, BrowserBookmarksAdapterItem object) {
-        BookmarkContainer container = (BookmarkContainer) view;
-        container.setIgnoreRequestLayout(true);
-        bindGridView(view, mContext, object);
-        container.setIgnoreRequestLayout(false);
-    }
-
     CharSequence getTitle(Cursor cursor) {
         int type = cursor.getInt(BookmarksLoader.COLUMN_INDEX_TYPE);
         switch (type) {
-        case Bookmarks.BOOKMARK_TYPE_OTHER_FOLDER:
-            return mContext.getText(R.string.other_bookmarks);
+            case Bookmarks.BOOKMARK_TYPE_OTHER_FOLDER:
+                return mContext.getText(R.string.other_bookmarks);
         }
         return cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
     }
 
-    void bindGridView(View view, Context context, BrowserBookmarksAdapterItem item) {
-        // We need to set this to handle rotation and other configuration change
-        // events. If the padding didn't change, this is a no op.
-        int padding = context.getResources()
+    @Override
+    public void bindView(View view, BrowserBookmarksAdapterItem item) {
+        BookmarkContainer c = (BookmarkContainer) view;
+
+        // we need to set this to handle rotation and other configuration change events.
+        // (if the padding didn't change, this is a no op)
+        int padding = mContext.getResources()
                 .getDimensionPixelSize(R.dimen.combo_horizontalSpacing);
-        view.setPadding(padding, view.getPaddingTop(),
-                padding, view.getPaddingBottom());
-        SiteTileView thumb =  (SiteTileView) view.findViewById(R.id.thumb_image);
-        TextView tv = (TextView) view.findViewById(R.id.label);
-        tv.setText(item.title);
+        c.setPadding(padding, c.getPaddingTop(), padding, c.getPaddingBottom());
 
-        Bitmap b;
-
-        thumb.setFloating(false);
-
+        // configure the main content of the bookmark icon
         if (item.is_folder) {
-            b = BitmapFactory.decodeResource(mContext.getResources(),
-                    R.drawable.ic_deco_folder_normal);
-            thumb.setFloating(true);
-        }
-        else if (item.thumbnail == null || !item.has_thumbnail) {
-            b = BitmapFactory.decodeResource(mContext.getResources(),
-                    R.drawable.browser_thumbnail);
-        }
-        else {
-            b = item.thumbnail.getBitmap();
+            c.reConfigureAsFolder(item.title.toString(), "");
+        } else {
+            final Bitmap favicon = (item.thumbnail == null || !item.has_thumbnail) ?
+                    null : item.thumbnail.getBitmap();
+            c.reConfigureAsSite(favicon);
         }
 
-        // If the item is managed by mdm or edit bookmark restriction enabled
+        // configure the label under the bookmark
+        if (item.title != null) {
+            c.setBottomLabelText(item.title.toString());
+        }
+
+        // if the item is managed by mdm or edit bookmark restriction, show a badge
         if (item.title != null &&
                 (item.is_mdm_managed || EditBookmarksRestriction.getInstance().isEnabled())) {
-            int containerWidth = view.getResources().getDimensionPixelSize(R.dimen.bookmarkThumbnailWidth);
-            int containerHeight = view.getResources().getDimensionPixelSize(R.dimen.bookmarkThumbnailHeight);
-            Bitmap bm;
-
-            if (item.is_mdm_managed) {
-                bm = BrowserBookmarksPage.overlayBookmarkBitmap(mContext, b,
-                        R.drawable.img_deco_mdm_badge_bright,
-                        containerWidth, containerHeight, 0.6f, 185, 20);
-            }
-            else {
-                bm = BrowserBookmarksPage.overlayBookmarkBitmap(mContext, b,
-                        R.drawable.ic_deco_secure,
-                        containerWidth, containerHeight, 1.7f, 110, 0);
-            }
-
-            thumb.replaceFavicon(bm);
-        }
-        else {
-            thumb.replaceFavicon(b);
-        }
-        thumb.setLongClickable(true);
+            c.setOverlayBadge(item.is_mdm_managed ? R.drawable.img_deco_mdm_badge_bright :
+                    R.drawable.ic_deco_secure);
+        } else
+            c.setOverlayBadge(0);
     }
 
     @Override
diff --git a/src/com/android/browser/FolderTileView.java b/src/com/android/browser/FolderTileView.java
new file mode 100644
index 0000000..2d23ebf
--- /dev/null
+++ b/src/com/android/browser/FolderTileView.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+package com.android.browser;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class FolderTileView extends ViewGroup {
+
+    // created in the constructor
+    private View mInnerLayout;
+    private TextView mTextView;
+    private TextView mLabelView;
+    private int mPaddingLeft = 0;
+    private int mPaddingTop = 0;
+    private int mPaddingRight = 0;
+    private int mPaddingBottom = 0;
+
+    // runtime params set on Layout
+    private int mCurrentWidth;
+    private int mCurrentHeight;
+
+    // static objects, to be recycled amongst instances (this is an optimization)
+    private static Paint sBackgroundPaint;
+    private String mText;
+    private String mLabel;
+
+
+    /* XML constructors */
+
+    public FolderTileView(Context context) {
+        super(context);
+        xmlInit(null, 0);
+    }
+
+    public FolderTileView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        xmlInit(attrs, 0);
+    }
+
+    public FolderTileView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        xmlInit(attrs, defStyle);
+    }
+
+
+    /* Programmatic Constructors */
+
+    public FolderTileView(Context context, String text, String label) {
+        super(context);
+        mText = text;
+        mLabel = label;
+        init();
+    }
+
+
+    /**
+     * Replaces the main text of the bookmark tile
+     */
+    public void setText(String text) {
+        mText = text;
+        if (mTextView != null)
+            mTextView.setText(mText);
+    }
+
+    /**
+     * Replaces the subtitle, for example "32 items"
+     */
+    public void setLabel(String label) {
+        mLabel = label;
+        if (mLabelView != null)
+            mLabelView.setText(mLabel);
+    }
+
+
+    /* private stuff ahead */
+
+    private void xmlInit(AttributeSet attrs, int defStyle) {
+        // load attributes
+        final TypedArray a = getContext().obtainStyledAttributes(attrs,
+                R.styleable.FolderTileView, defStyle, 0);
+
+        // saves the text for later
+        setText(a.getString(R.styleable.FolderTileView_android_text));
+
+        // saves the label for later
+        setLabel(a.getString(R.styleable.FolderTileView_android_label));
+
+        // delete attribute resolution
+        a.recycle();
+
+        // proceed with real initialization
+        init();
+    }
+
+    private void init() {
+        // create new Views for us from the XML (and automatically add them)
+        inflate(getContext(), R.layout.folder_tile_view, this);
+
+        // we make the assumption that the XML file will always have 1 and only 1 child
+        mInnerLayout = getChildAt(0);
+        mInnerLayout.setVisibility(View.VISIBLE);
+
+        // reference objects
+        mTextView = (TextView) mInnerLayout.findViewById(android.R.id.text1);
+        if (mText != null && !mText.isEmpty())
+            mTextView.setText(mText);
+        mLabelView = (TextView) mInnerLayout.findViewById(android.R.id.text2);
+        if (mLabel != null && !mLabel.isEmpty())
+            mLabelView.setText(mLabel);
+
+        // load the common statics, also for the SiteTileView if needed
+        final Resources resources = getResources();
+        SiteTileView.ensureCommonLoaded(resources);
+        ensureCommonLoaded(resources);
+
+        // get the padding rect from the Tile View (to stay synced in size)
+        final Rect padding = SiteTileView.getBackgroundDrawablePadding();
+        mPaddingLeft = padding.left;
+        mPaddingTop = padding.top;
+        mPaddingRight = padding.right;
+        mPaddingBottom = padding.bottom;
+
+        // we'll draw our background (usually ViewGroups don't)
+        setWillNotDraw(false);
+    }
+
+    private static void ensureCommonLoaded(Resources r) {
+        if (sBackgroundPaint != null)
+            return;
+
+        // shared tiles background paint
+        sBackgroundPaint = new Paint();
+        sBackgroundPaint.setColor(r.getColor(R.color.FolderTileBackground));
+        sBackgroundPaint.setAntiAlias(true);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // layout the xml inflated contents
+        if (mInnerLayout != null) {
+            final int desiredWidth = MeasureSpec.getSize(widthMeasureSpec);
+            final int desiredHeight = MeasureSpec.getSize(heightMeasureSpec);
+            if (desiredHeight > 0 || desiredHeight > 0)
+                mInnerLayout.measure(
+                        MeasureSpec.EXACTLY | desiredWidth - mPaddingLeft - mPaddingRight,
+                        MeasureSpec.EXACTLY | desiredHeight - mPaddingTop - mPaddingBottom);
+            else
+                mInnerLayout.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+        }
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        // update current params
+        mCurrentWidth = right - left;
+        mCurrentHeight = bottom - top;
+
+        // layout the inflated XML layout using the same Padding as the SiteTileView
+        if (mInnerLayout != null)
+            mInnerLayout.layout(mPaddingLeft, mPaddingTop,
+                    mCurrentWidth - mPaddingRight, mCurrentHeight - mPaddingBottom);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
+        final int left = mPaddingLeft;
+        final int top = mPaddingTop;
+        final int right = mCurrentWidth - mPaddingRight;
+        final int bottom = mCurrentHeight - mPaddingBottom;
+
+        // draw the background rectangle
+        float roundedRadius = SiteTileView.sRoundedRadius;
+        if (roundedRadius >= 1.) {
+            SiteTileView.sRectF.set(left, top, right, bottom);
+            canvas.drawRoundRect(SiteTileView.sRectF, roundedRadius, roundedRadius, sBackgroundPaint);
+        } else
+            canvas.drawRect(left, top, right, bottom, sBackgroundPaint);
+    }
+
+}
diff --git a/src/com/android/browser/NavigationBarBase.java b/src/com/android/browser/NavigationBarBase.java
index c032872..c1ad5c9 100644
--- a/src/com/android/browser/NavigationBarBase.java
+++ b/src/com/android/browser/NavigationBarBase.java
@@ -147,7 +147,7 @@
                         if (wv != null && WebRefiner.isInitialized()) {
                             int count = WebRefiner.getInstance().getBlockedURLCount(wv);
                             if (count > 0) {
-                                mFaviconTile.setExtraBlockedObjectsCount(count);
+                                mFaviconTile.setBadgeBlockedObjectsCount(count);
                             }
                         }
                         mHandler.sendEmptyMessageDelayed(WEBREFINER_COUNTER_MSG,
@@ -170,12 +170,15 @@
         switch (mSecurityState) {
             case SECURITY_STATE_SECURE:
                 mFaviconTile.setTrustLevel(SiteTileView.TRUST_TRUSTED);
+                mFaviconTile.setBadgeHasCertIssues(false);
                 break;
             case SECURITY_STATE_MIXED:
                 mFaviconTile.setTrustLevel(SiteTileView.TRUST_UNTRUSTED);
+                mFaviconTile.setBadgeHasCertIssues(true);
                 break;
             case SECURITY_STATE_BAD_CERTIFICATE:
                 mFaviconTile.setTrustLevel(SiteTileView.TRUST_AVOID);
+                mFaviconTile.setBadgeHasCertIssues(true);
                 break;
             case SECURITY_STATE_NOT_SECURE:
             default:
@@ -719,8 +722,9 @@
     }
 
     public void onProgressStarted() {
-        mFaviconTile.setExtraBlockedObjectsCount(0);
+        mFaviconTile.setBadgeBlockedObjectsCount(0);
         mFaviconTile.setTrustLevel(SiteTileView.TRUST_UNKNOWN);
+        mFaviconTile.setBadgeHasCertIssues(false);
         mFaviconTile.replaceFavicon(mDefaultFavicon);
         mSecurityState = Tab.SecurityState.SECURITY_STATE_NOT_SECURE;
         mHandler.removeMessages(WEBREFINER_COUNTER_MSG);
diff --git a/src/com/android/browser/SiteTileView.java b/src/com/android/browser/SiteTileView.java
index e22404f..e2951ae 100644
--- a/src/com/android/browser/SiteTileView.java
+++ b/src/com/android/browser/SiteTileView.java
@@ -29,20 +29,26 @@
 package com.android.browser;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.graphics.Typeface;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.view.View;
 
+import java.util.Map;
+
 /**
  * This represents a WebSite Tile that is created from a Drawable and will scale across any
  * area this is externally layouted to. There are 3 possible looks:
@@ -70,14 +76,10 @@
     private static final int THRESHOLD_LARGE_DP = 64;
     private static final int LARGE_FAVICON_SIZE_DP = 48;
     private static final int BACKGROUND_DRAWABLE_RES = R.drawable.img_tile_background;
+    private static final int DEFAULT_SITE_FAVICON = 0;
     private static final float FILLER_RADIUS_DP = 2f; // sync with the bg image radius
     private static final int FILLER_FALLBACK_COLOR = Color.WHITE; // in case there is no favicon
-    private static final int OVERLINE_WIDTH_RES = R.dimen.SiteTileOverlineWidth;
-    private static final int OVERLINE_COLOR_DEFAULT_RES = R.color.SiteTileOverlineUnknown;
-    private static final int OVERLINE_COLOR_TRUSTED_RES = R.color.SiteTileOverlineTrusted;
-    private static final int OVERLINE_COLOR_UNTRUSTED_RES = R.color.SiteTileOverlineUntrusted;
-    private static final int OVERLINE_COLOR_AVOID_RES = R.color.SiteTileOverlineAvoid;
-    private static final boolean SHOW_EXTRAS_BLOCKED_COUNT = true;
+    private static final boolean BADGE_SHOW_BLOCKED_COUNT = false;
 
     // internal enums
     private static final int TYPE_SMALL = 1;
@@ -92,12 +94,11 @@
     private Paint mFundamentalPaint = null;
     private int mFaviconWidth = 0;
     private int mFaviconHeight = 0;
-    private int mForcedType = TYPE_AUTO;
     private int mForcedFundamentalColor = COLOR_AUTO;
-    private boolean mFloating = false;
+    private boolean mBackgroundDisabled = false;
     private int mTrustLevel = TRUST_UNKNOWN;
-    private int mExtraBlockedObjectsCount = 0;
-    private boolean mExtrasShown = false;
+    private int mBadgeBlockedObjectsCount = 0;
+    private boolean mBadgeHasCertIssues = false;
 
     // runtime params set on Layout
     private int mCurrentWidth = 0;
@@ -107,21 +108,28 @@
     private int mPaddingTop = 0;
     private int mPaddingRight = 0;
     private int mPaddingBottom = 0;
-    private boolean mCurrentBackgroundDrawn = false;
+    private boolean mCurrentShadowDrawn = false;
 
     // static objects, to be recycled amongst instances (this is an optimization)
+    // NOTE: package-visible statics are for optimized usage inside FolderTileView as well
     private static int sMediumPxThreshold = -1;
     private static int sLargePxThreshold = -1;
     private static int sLargeFaviconPx = -1;
-    private static float sRoundedRadius = -1;
+    /* package */ static float sRoundedRadius = -1;
     private static Paint sBitmapPaint = null;
-    private static Paint sExtrasPaint = null;
+    private static Paint sBadgeTextPaint = null;
     private static Rect sSrcRect = new Rect();
     private static Rect sDstRect = new Rect();
-    private static RectF sRectF = new RectF();
-    private static Paint sOverlineOutlinePaint = null;
+    /* package */ static RectF sRectF = new RectF();
     private static Drawable sBackgroundDrawable = null;
-    private static Rect sBackgroundDrawablePadding = new Rect();
+    private static class BadgeAssets {
+        Drawable back;
+        Drawable accent;
+        int textColor;
+    }
+    private static Map<Integer, BadgeAssets> sBadges;
+    private static Bitmap sDefaultSiteBitmap = null;
+    /* package */ static Rect sBackgroundDrawablePadding = new Rect();
 
 
     /* XML constructors */
@@ -175,24 +183,34 @@
     /**
      * Disables the automatic background and filling. Useful for things that are not really
      * "Website Tiles", like folders.
-     * @param floating true to disable the background (defaults to false)
+     * @param disabled true to disable the background (defaults to false)
      */
-    public void setFloating(boolean floating) {
-        if (mFloating != floating) {
-            mFloating = floating;
+    public void setBackgroundDisabled(boolean disabled) {
+        if (mBackgroundDisabled != disabled) {
+            mBackgroundDisabled = disabled;
             invalidate();
         }
     }
 
     /**
-     * For 'Medium' tiles updates the border and corner badges
+     * This results in the Badge being updated
      * @param trustLevel one of the TRUST_ constants
      */
     public void setTrustLevel(int trustLevel) {
         if (mTrustLevel != trustLevel) {
             mTrustLevel = trustLevel;
-            if (requiresOverline())
-                invalidate();
+            invalidate();
+        }
+    }
+
+    /**
+     * Tells that there will be some message about issues inside
+     * @param certIssues true if there are issues.
+     */
+    public void setBadgeHasCertIssues(boolean certIssues) {
+        if (certIssues != mBadgeHasCertIssues) {
+            mBadgeHasCertIssues = certIssues;
+            invalidate();
         }
     }
 
@@ -201,24 +219,16 @@
      * may or may not have the number indication.
      * @param sessionCounter Counter of blocked objects. Use 0 to not display anything.
      */
-    public void setExtraBlockedObjectsCount(int sessionCounter) {
-        if (sessionCounter != mExtraBlockedObjectsCount) {
-            mExtraBlockedObjectsCount = sessionCounter;
-            updateExtrasShown();
-            if (SHOW_EXTRAS_BLOCKED_COUNT)
+    public void setBadgeBlockedObjectsCount(int sessionCounter) {
+        if (sessionCounter != mBadgeBlockedObjectsCount) {
+            // repaint if going from or to 0, or if showing the ads count
+            //noinspection PointlessBooleanExpression,ConstantConditions
+            if (mBadgeBlockedObjectsCount == 0 || sessionCounter == 0 || BADGE_SHOW_BLOCKED_COUNT)
                 invalidate();
+            mBadgeBlockedObjectsCount = sessionCounter;
         }
     }
 
-    private void updateExtrasShown() {
-        boolean shouldBeShown = mExtraBlockedObjectsCount > 0;
-        if (shouldBeShown != mExtrasShown) {
-            mExtrasShown = shouldBeShown;
-            invalidate();
-        }
-    }
-
-
 
     /**
      * @return The fundamental color representing the site.
@@ -234,6 +244,30 @@
 
     /*** private stuff ahead ***/
 
+    private boolean requiresBadge() {
+        return !mBackgroundDisabled && (mTrustLevel != TRUST_UNKNOWN || mBadgeHasCertIssues
+                || mBadgeBlockedObjectsCount > 0);
+    }
+
+    private int computeBadgeMessages() {
+        // special case, for TRUST_AVOID, always show the common accent
+        if (mTrustLevel == TRUST_AVOID)
+            return 0;
+
+        // recompute number of 'messages' inside the badge
+        int count = 0;
+        if (mBadgeHasCertIssues)
+            count++;
+        if (mBadgeBlockedObjectsCount > 0)
+            count++;
+
+        // add the number of blocked objects (-1, for having already counted the message) if needed
+        if (BADGE_SHOW_BLOCKED_COUNT)
+            count += mBadgeBlockedObjectsCount - 1;
+
+        return count;
+    }
+
     private void xmlInit(AttributeSet attrs, int defStyle) {
         // load attributes
         final TypedArray a = getContext().obtainStyledAttributes(attrs,
@@ -244,19 +278,15 @@
         final Bitmap favicon = drawable instanceof BitmapDrawable ?
                 ((BitmapDrawable) drawable).getBitmap() : null;
 
-        // check if we disable shading (plain favicon)
-        if (a.getBoolean(R.styleable.SiteTileView_flat, false))
-            mForcedType = TYPE_SMALL;
-
-        // check if we want it floating (disable shadow and filler)
-        setFloating(a.getBoolean(R.styleable.SiteTileView_floating, false));
+        // check if we want it background-less (disable shadow and filler)
+        setBackgroundDisabled(a.getBoolean(R.styleable.SiteTileView_disableBackground, false));
 
         // read the trust level (unknown, aka 'default', if not present)
         setTrustLevel(a.getInteger(R.styleable.SiteTileView_trustLevel, TRUST_UNKNOWN)
                 & TRUST_MASK);
 
         // read the amount of blocked objects (or 0 if not present)
-        setExtraBlockedObjectsCount(a.getInteger(R.styleable.SiteTileView_blockedObjects, 0));
+        setBadgeBlockedObjectsCount(a.getInteger(R.styleable.SiteTileView_blockedObjects, 0));
 
         // delete attribute resolution
         a.recycle();
@@ -267,6 +297,16 @@
 
     private void init(Bitmap favicon, int fundamentalColor) {
         mFaviconBitmap = favicon;
+
+        // show a default favicon if nothing is set (consider removing this, it's ugly)
+        if (mFaviconBitmap == null && DEFAULT_SITE_FAVICON != 0) {
+            if (sDefaultSiteBitmap == null)
+                sDefaultSiteBitmap = BitmapFactory.decodeResource(getResources(),
+                        DEFAULT_SITE_FAVICON);
+            mFaviconBitmap = sDefaultSiteBitmap;
+            fundamentalColor = 0xFF262626;
+        }
+
         if (mFaviconBitmap != null) {
             mFaviconWidth = mFaviconBitmap.getWidth();
             mFaviconHeight = mFaviconBitmap.getHeight();
@@ -277,47 +317,70 @@
         mForcedFundamentalColor = fundamentalColor;
 
         // shared (static) resources initialization; except for background, inited on-demand
-        if (sMediumPxThreshold < 0) {
-            final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
-
-            // heuristics thresholds
-            sMediumPxThreshold = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                    THRESHOLD_MEDIUM_DP, displayMetrics);
-            sLargePxThreshold = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                    THRESHOLD_LARGE_DP, displayMetrics);
-            sLargeFaviconPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                    LARGE_FAVICON_SIZE_DP, displayMetrics);
-
-            // rounded radius
-            sRoundedRadius = FILLER_RADIUS_DP > 0 ? TypedValue.applyDimension(
-                    TypedValue.COMPLEX_UNIT_DIP, FILLER_RADIUS_DP, displayMetrics) : 0;
-
-            // bitmap paint (copy, smooth scale)
-            sBitmapPaint = new Paint();
-            sBitmapPaint.setColor(Color.BLACK);
-            sBitmapPaint.setFilterBitmap(true);
-
-            // overline configuration (null if we don't need it)
-            float ovlWidthPx = getResources().getDimension(OVERLINE_WIDTH_RES);
-            if (ovlWidthPx > 0.5) {
-                sOverlineOutlinePaint = new Paint();
-                sOverlineOutlinePaint.setStrokeWidth(ovlWidthPx);
-                sOverlineOutlinePaint.setStyle(Paint.Style.STROKE);
-            }
-
-            // extras paint (anti-aliased)
-            sExtrasPaint = new Paint();
-            sExtrasPaint.setAntiAlias(true);
-            sExtrasPaint.setColor(getResources().getColor(OVERLINE_COLOR_TRUSTED_RES));
-            sExtrasPaint.setStrokeWidth(Math.max(ovlWidthPx, 1));
-        }
+        ensureCommonLoaded(getResources());
 
         // change when clicked
         setClickable(true);
-        // disable by default the long click
-        setLongClickable(false);
     }
 
+    static void ensureCommonLoaded(Resources r) {
+        // check if already initialized
+        if (sMediumPxThreshold != -1)
+            return;
+
+        // heuristics thresholds
+        final DisplayMetrics displayMetrics = r.getDisplayMetrics();
+        sMediumPxThreshold = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                THRESHOLD_MEDIUM_DP, displayMetrics);
+        sLargePxThreshold = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                THRESHOLD_LARGE_DP, displayMetrics);
+        sLargeFaviconPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                LARGE_FAVICON_SIZE_DP, displayMetrics);
+
+        // rounded radius
+        sRoundedRadius = FILLER_RADIUS_DP > 0 ? TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, FILLER_RADIUS_DP, displayMetrics) : 0;
+
+        // bitmap paint (copy, smooth scale)
+        sBitmapPaint = new Paint();
+        sBitmapPaint.setColor(Color.BLACK);
+        sBitmapPaint.setFilterBitmap(true);
+
+        // badge text paint (anti-aliased)
+        sBadgeTextPaint = new Paint();
+        sBadgeTextPaint.setAntiAlias(true);
+        Typeface badgeTypeface = Typeface.create("sans-serif-medium", Typeface.NORMAL);
+        if (badgeTypeface != null)
+            sBadgeTextPaint.setTypeface(badgeTypeface);
+
+        // load the background (could be loaded on demand, but in the end it's always needed)
+        sBackgroundDrawable = r.getDrawable(BACKGROUND_DRAWABLE_RES);
+        if (sBackgroundDrawable != null)
+            sBackgroundDrawable.getPadding(sBackgroundDrawablePadding);
+
+        // load all the badge drawables
+        sBadges = new ArrayMap<>();
+        loadBadgeResources(r, TRUST_AVOID, R.drawable.img_deco_tile_avoid,
+                R.drawable.img_deco_tile_avoid_accent, R.color.TileBadgeTextAvoid);
+        loadBadgeResources(r, TRUST_UNTRUSTED, R.drawable.img_deco_tile_untrusted,
+                R.drawable.img_deco_tile_untrusted_accent, R.color.TileBadgeTextUntrusted);
+        loadBadgeResources(r, TRUST_UNKNOWN, R.drawable.img_deco_tile_unknown,
+                R.drawable.img_deco_tile_unknown_accent, R.color.TileBadgeTextUnknown);
+        loadBadgeResources(r, TRUST_TRUSTED, R.drawable.img_deco_tile_verified,
+                R.drawable.img_deco_tile_verified_accent, R.color.TileBadgeTextVerified);
+    }
+
+    private static void loadBadgeResources(Resources r, int t, int back, int accent, int color) {
+        BadgeAssets ba = new BadgeAssets();
+        ba.back = back == 0 ? null : r.getDrawable(back);
+        ba.accent = accent == 0 ? null : r.getDrawable(accent);
+        ba.textColor = color == 0 ? Color.TRANSPARENT : r.getColor(color);
+        sBadges.put(t, ba);
+    }
+
+    static Rect getBackgroundDrawablePadding() {
+        return sBackgroundDrawablePadding != null ? sBackgroundDrawablePadding : new Rect();
+    }
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
@@ -325,39 +388,27 @@
         mCurrentHeight = bottom - top;
 
         // auto-determine the "TYPE_" from the physical size of the layout
-        if (mForcedType == TYPE_AUTO) {
-            if (mCurrentWidth < sMediumPxThreshold && mCurrentHeight < sMediumPxThreshold)
-                mCurrentType = TYPE_SMALL;
-            else if (mCurrentWidth < sLargePxThreshold && mCurrentHeight < sLargePxThreshold)
-                mCurrentType = TYPE_MEDIUM;
-            else
-                mCurrentType = TYPE_LARGE;
-        } else {
-            // or use the forced one, if defined
-            mCurrentType = mForcedType;
-        }
+        if (mCurrentWidth < sMediumPxThreshold && mCurrentHeight < sMediumPxThreshold)
+            mCurrentType = TYPE_SMALL;
+        else if (mCurrentWidth < sLargePxThreshold && mCurrentHeight < sLargePxThreshold)
+            mCurrentType = TYPE_MEDIUM;
+        else
+            mCurrentType = TYPE_LARGE;
 
         // set or remove the background (if the need changed!)
-        boolean requiresBackground = mCurrentType >= TYPE_MEDIUM;
-        if (requiresBackground && !mCurrentBackgroundDrawn) {
+        boolean requiresBackgroundDrawable = mCurrentType >= TYPE_MEDIUM;
+        if (requiresBackgroundDrawable && !mCurrentShadowDrawn) {
             // draw the background
-            mCurrentBackgroundDrawn = true;
-
-            // load the background just the first time, on demand (it may fail too)
-            if (sBackgroundDrawable == null) {
-                sBackgroundDrawable = getResources().getDrawable(BACKGROUND_DRAWABLE_RES);
-                if (sBackgroundDrawable != null)
-                    sBackgroundDrawable.getPadding(sBackgroundDrawablePadding);
-            }
+            mCurrentShadowDrawn = mCurrentType >= TYPE_LARGE;
 
             // background -> padding
             mPaddingLeft = sBackgroundDrawablePadding.left;
             mPaddingTop = sBackgroundDrawablePadding.top;
             mPaddingRight = sBackgroundDrawablePadding.right;
             mPaddingBottom = sBackgroundDrawablePadding.bottom;
-        } else if (!requiresBackground && mCurrentBackgroundDrawn) {
+        } else if (!requiresBackgroundDrawable && mCurrentShadowDrawn) {
             // turn off background drawing
-            mCurrentBackgroundDrawn = false;
+            mCurrentShadowDrawn = false;
 
             // no background -> no padding
             mPaddingLeft = 0;
@@ -410,15 +461,15 @@
         final int contentHeight = bottom - top;
 
         // A. the background drawable (if set)
-        boolean requiresBackground = mCurrentBackgroundDrawn && sBackgroundDrawable != null
-                && !isPressed() && !mFloating;
+        boolean requiresBackground = mCurrentShadowDrawn && sBackgroundDrawable != null
+                && !isPressed() && !mBackgroundDisabled;
         if (requiresBackground) {
             sBackgroundDrawable.setBounds(0, 0, mCurrentWidth, mCurrentHeight);
             sBackgroundDrawable.draw(canvas);
         }
 
         // B. (when needed) draw the background rectangle; sharp our rounded
-        boolean requiresFundamentalFiller = mCurrentType >= TYPE_LARGE && !mFloating;
+        boolean requiresFundamentalFiller = mCurrentType >= TYPE_LARGE && !mBackgroundDisabled;
         if (requiresFundamentalFiller) {
             // create the filler paint on demand (not all icons need it)
             if (mFundamentalPaint == null)
@@ -481,73 +532,52 @@
             canvas.drawBitmap(mFaviconBitmap, sSrcRect, sDstRect, sBitmapPaint);
         }
 
-        // D. (when needed) draw the thin over-line
-        if (requiresOverline()) {
-            int colorRes;
-            switch (mTrustLevel) {
-                case TRUST_TRUSTED:
-                    colorRes = OVERLINE_COLOR_TRUSTED_RES;
-                    break;
-                case TRUST_UNTRUSTED:
-                    colorRes = OVERLINE_COLOR_UNTRUSTED_RES;
-                    break;
-                case TRUST_AVOID:
-                    colorRes = OVERLINE_COLOR_AVOID_RES;
-                    break;
-                default:
-                    colorRes = OVERLINE_COLOR_DEFAULT_RES;
-                    break;
-            }
-            int lineColor = getResources().getColor(colorRes);
-            if (lineColor != Color.TRANSPARENT) {
-                // draw the white inline first
-                boolean needSeparation = mTrustLevel != TRUST_UNKNOWN;
-                if (needSeparation) {
-                    sOverlineOutlinePaint.setColor(Color.WHITE);
-                    float d = sOverlineOutlinePaint.getStrokeWidth();
-                    canvas.drawRect(left + d, top + d, right - d, bottom - d, sOverlineOutlinePaint);
+        // D. show badge, if requested
+        if (requiresBadge()) {
+            // retrieve the badge resources
+            final BadgeAssets ba = sBadges.get(mTrustLevel);
+            if (ba != null) {
+
+                // paint back
+                final Drawable back = ba.back;
+                int badgeL = 0, badgeT = 0, badgeW = 0, badgeH = 0;
+                if (back != null) {
+                    badgeW = back.getIntrinsicWidth();
+                    badgeH = back.getIntrinsicHeight();
+                    badgeL = mCurrentWidth - mPaddingRight / 3 - badgeW;
+                    badgeT = mCurrentHeight - mPaddingBottom / 3 - badgeH;
+                    back.setBounds(badgeL, badgeT, badgeL + badgeW, badgeT + badgeH);
+                    back.draw(canvas);
                 }
+                int messagesCount = computeBadgeMessages();
 
-                // then draw the outline
-                sOverlineOutlinePaint.setColor(lineColor);
-                canvas.drawRect(left, top, right, bottom, sOverlineOutlinePaint);
+                // paint accent, if 0 messages
+                if (messagesCount < 1) {
+                    final Drawable accent = ba.accent;
+                    if (accent != null && badgeW > 0 && badgeH > 0) {
+                        int accentW = accent.getIntrinsicWidth();
+                        int accentH = accent.getIntrinsicHeight();
+                        int accentL = badgeL + (badgeW - accentW) / 2;
+                        int accentT = badgeT + (badgeH - accentH) / 2;
+                        accent.setBounds(accentL, accentT, accentL + accentW, accentT + accentH);
+                        accent.draw(canvas);
+                    }
+                }
+                // at least 1 message, draw text
+                else if (Color.alpha(ba.textColor) > 0) {
+                    float textSize = Math.min(2 * contentWidth / 5, sMediumPxThreshold / 4) * 1.1f;
+                    sBadgeTextPaint.setTextSize(textSize);
+                    sBadgeTextPaint.setColor(ba.textColor);
+                    final String text = String.valueOf(messagesCount);
+                    int textWidth = Math.round(sBadgeTextPaint.measureText(text) / 2);
+                    int textCx = badgeL + badgeW / 2;
+                    int textCy = badgeT + badgeH / 2;
+                    canvas.drawText(text, textCx - textWidth, textCy + textSize / 3 + 1,
+                            sBadgeTextPaint);
+                }
             }
         }
 
-        // E. show extra, if requested
-        if (mExtrasShown) {
-            // as default, we show a bubble
-            int eRad = Math.min(2 * contentWidth / 5, sMediumPxThreshold / 4);
-            int eCX = Math.min(right - eRad / 2, mCurrentWidth - eRad); //left + (4 * contentWidth / 5) - eRad;
-            int eCY = Math.min(bottom - eRad / 4, mCurrentHeight - eRad);
-
-            // circle back
-            //canvas.drawCircle(eCX, eCY, eRad, sExtrasPaint);
-
-            // round rect back
-            sRectF.set(eCX - eRad, eCY - eRad, eCX + eRad, eCY + eRad);
-            sExtrasPaint.setStyle(Paint.Style.FILL);
-            sExtrasPaint.setColor(0xff666666);
-            canvas.drawRoundRect(sRectF, eRad / 2, eRad / 2, sExtrasPaint);
-
-            // DEBUG! -- draw blocked count
-            if (SHOW_EXTRAS_BLOCKED_COUNT && mExtraBlockedObjectsCount > 0) {
-                final Paint paint = new Paint();
-                float textSize = eRad * 1.2f;
-                paint.setColor(Color.WHITE);
-                paint.setAntiAlias(true);
-                paint.setTextSize(textSize);
-                String text = String.valueOf(mExtraBlockedObjectsCount);
-                int textWidth = Math.round(paint.measureText(text) / 2);
-                canvas.drawText(text, eCX - textWidth - 1, eCY + textSize / 3 + 1, paint);
-            }
-
-            // round rect stroke
-            sExtrasPaint.setStyle(Paint.Style.STROKE);
-            sExtrasPaint.setColor(0xFFeeeeee);
-            canvas.drawRoundRect(sRectF, eRad / 2, eRad / 2, sExtrasPaint);
-        }
-
         /*if (true) { // DEBUG TYPE
             Paint paint = new Paint();
             paint.setColor(Color.BLACK);
@@ -556,10 +586,6 @@
         }*/
     }
 
-    private boolean requiresOverline() {
-        return mCurrentType == TYPE_MEDIUM && sOverlineOutlinePaint != null && !mFloating;
-    }
-
 
     /**
      * Creates a fill Paint from the favicon, or using the forced color (if not COLOR_AUTO)
@@ -651,4 +677,4 @@
         return color;
     }
 
-}
\ No newline at end of file
+}
diff --git a/src/com/android/browser/view/BookmarkContainer.java b/src/com/android/browser/view/BookmarkContainer.java
index 730f127..b36dde2 100644
--- a/src/com/android/browser/view/BookmarkContainer.java
+++ b/src/com/android/browser/view/BookmarkContainer.java
@@ -17,15 +17,22 @@
 package com.android.browser.view;
 
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
 import android.graphics.drawable.TransitionDrawable;
 import android.util.AttributeSet;
+import android.view.Gravity;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.TextView;
 
+import com.android.browser.FolderTileView;
 import com.android.browser.R;
 import com.android.browser.SiteTileView;
 
@@ -34,6 +41,11 @@
     private OnClickListener mClickListener;
     private boolean mIgnoreRequestLayout = false;
 
+    private FrameLayout mTileContainer;
+    private FolderTileView mFolderTile;
+    private SiteTileView mSiteTile;
+    private ImageView mOverlayBadge;
+
     public BookmarkContainer(Context context) {
         super(context);
         init();
@@ -44,33 +56,107 @@
         init();
     }
 
-    public BookmarkContainer(
-            Context context, AttributeSet attrs, int defStyle) {
+    public BookmarkContainer(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         init();
     }
 
     void init() {
         setFocusable(true);
+
+        if (mSiteTile == null) {
+            mSiteTile = new SiteTileView(getContext(), (Bitmap)null);
+        }
+
+        if (mFolderTile == null) {
+            mFolderTile = new FolderTileView(getContext(), null, null);
+            mFolderTile.setClickable(true);
+        }
         super.setOnClickListener(this);
     }
 
+    public void reConfigureAsFolder(String title, String numItems) {
+        // hide elements that may have been already created
+        mSiteTile.setVisibility(View.GONE);
+        if (mOverlayBadge != null)
+            mOverlayBadge.setVisibility(View.GONE);
+
+        // reconfigure the existing Folder
+        mFolderTile.setVisibility(View.VISIBLE);
+        mFolderTile.setText(title);
+        mFolderTile.setLabel(numItems);
+        addTileToContainer(mFolderTile);
+    }
+
+    public void reConfigureAsSite(Bitmap favicon) {
+        // hide elements that may have been already created
+        mFolderTile.setVisibility(View.GONE);
+        if (mOverlayBadge != null)
+            mOverlayBadge.setVisibility(View.GONE);
+
+        // reconfigure the existing Site
+        mSiteTile.setVisibility(View.VISIBLE);
+        mSiteTile.replaceFavicon(favicon);
+        addTileToContainer(mSiteTile);
+    }
+
+    public void setBottomLabelText(String bottomLabel) {
+        ((TextView) findViewById(R.id.label)).setText(bottomLabel);
+    }
+
+    public void setOverlayBadge(int imgResId) {
+        // remove the badge if already existing
+        if (imgResId == 0) {
+            if (mOverlayBadge != null) {
+                mOverlayBadge.setVisibility(View.GONE);
+                mOverlayBadge.setImageDrawable(null);
+            }
+            return;
+        }
+
+        // create the badge if needed and not present
+        if (mOverlayBadge == null) {
+            mOverlayBadge = new ImageView(getContext());
+            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT
+            );
+            lp.gravity = Gravity.BOTTOM | Gravity.END;
+            FrameLayout frameLayout = (FrameLayout) findViewById(R.id.container);
+            frameLayout.addView(mOverlayBadge, lp);
+        }
+        mOverlayBadge.setVisibility(View.VISIBLE);
+        mOverlayBadge.bringToFront();
+        mOverlayBadge.setImageResource(imgResId);
+    }
+
+
+    private void addTileToContainer(View view) {
+        if (view.getParent() != null) {
+            return;
+        }
+
+        // insert the view in the container, filling it
+        FrameLayout frameLayout = (FrameLayout) findViewById(R.id.container);
+        frameLayout.addView(view, 0, new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
+        ));
+        // common customizations for folders or sites
+        view.setLongClickable(true);
+    }
+
+
     @Override
     public void setOnClickListener(OnClickListener l) {
         mClickListener = l;
-        View thumb =  findViewById(R.id.thumb_image);
-        if (thumb != null) {
-            thumb.setOnClickListener(l);
-        }
+        mSiteTile.setOnClickListener(l);
+        mFolderTile.setOnClickListener(l);
     }
 
     @Override
     public void setTag(int key, final Object tag) {
         super.setTag(key, tag);
-        View thumb =  findViewById(R.id.thumb_image);
-        if (thumb != null) {
-            thumb.setTag(key, tag);
-        }
+        mSiteTile.setTag(key, tag);
+        mFolderTile.setTag(key, tag);
     }
 
     @Override
@@ -80,12 +166,12 @@
     }
 
     void updateTransitionDrawable(boolean pressed) {
-        final int longPressTimeout = ViewConfiguration.getLongPressTimeout();
         Drawable selector = getBackground();
         if (selector != null && selector instanceof StateListDrawable) {
             Drawable d = ((StateListDrawable)selector).getCurrent();
             if (d != null && d instanceof TransitionDrawable) {
                 if (pressed && isLongClickable()) {
+                    final int longPressTimeout = ViewConfiguration.getLongPressTimeout();
                     ((TransitionDrawable) d).startTransition(longPressTimeout);
                 } else {
                     ((TransitionDrawable) d).resetTransition();
@@ -108,8 +194,8 @@
 
     @Override
     public void requestLayout() {
-        if (!mIgnoreRequestLayout) {
+        if (!mIgnoreRequestLayout)
             super.requestLayout();
-        }
     }
+
 }