Bug 781262: Replaced sync box on about:home with promo box abstraction. r=sriram
authorMichael Comella <michael.l.comella@gmail.com>
Mon, 20 Aug 2012 16:10:00 +1200
changeset 102910 fb8c41ccafedafc7637136bf5bbbbdd48ef700b1
parent 102909 ca2c1aa1acbc28d78407cff3f16dfb39e3bdbeab
child 102911 bface603ef7211eb6c637f7ed0dd0b59b7df7dbd
push id23313
push usergsharp@mozilla.com
push dateTue, 21 Aug 2012 18:08:14 +0000
treeherderautoland@688a80cdf39f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssriram
bugs781262
milestone17.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 781262: Replaced sync box on about:home with promo box abstraction. r=sriram Bug 781262: Replaced sync box on about:home with promo box abstraction. r=sriram
mobile/android/base/AboutHomeContent.java
mobile/android/base/AboutHomePromoBox.java
mobile/android/base/GeckoViewsFactory.java
mobile/android/base/Makefile.in
mobile/android/base/resources/drawable-hdpi/abouthome_promo_box_bg.9.png
mobile/android/base/resources/drawable-hdpi/abouthome_promo_box_pressed_bg.9.png
mobile/android/base/resources/drawable-hdpi/abouthome_sync_bg.9.png
mobile/android/base/resources/drawable-hdpi/abouthome_sync_pressed_bg.9.png
mobile/android/base/resources/drawable-xhdpi/abouthome_promo_box_bg.9.png
mobile/android/base/resources/drawable-xhdpi/abouthome_promo_box_pressed_bg.9.png
mobile/android/base/resources/drawable-xhdpi/abouthome_sync_bg.9.png
mobile/android/base/resources/drawable-xhdpi/abouthome_sync_pressed_bg.9.png
mobile/android/base/resources/drawable/abouthome_promo_box.xml
mobile/android/base/resources/drawable/abouthome_promo_box_bg.9.png
mobile/android/base/resources/drawable/abouthome_promo_box_pressed_bg.9.png
mobile/android/base/resources/drawable/abouthome_sync_bg.9.png
mobile/android/base/resources/drawable/abouthome_sync_box.xml
mobile/android/base/resources/drawable/abouthome_sync_pressed_bg.9.png
mobile/android/base/resources/layout-xlarge-land-v11/abouthome_content.xml.in
mobile/android/base/resources/layout/abouthome_content.xml.in
mobile/android/base/resources/layout/abouthome_promo_box.xml
--- a/mobile/android/base/AboutHomeContent.java
+++ b/mobile/android/base/AboutHomeContent.java
@@ -80,16 +80,17 @@ public class AboutHomeContent extends Sc
     private LayoutInflater mInflater;
 
     private AccountManager mAccountManager;
     private OnAccountsUpdateListener mAccountListener = null;
 
     protected SimpleCursorAdapter mTopSitesAdapter;
     protected GridView mTopSitesGrid;
 
+    private AboutHomePromoBox mPromoBox;
     protected AboutHomeSection mAddons;
     protected AboutHomeSection mLastTabs;
     protected AboutHomeSection mRemoteTabs;
 
     private View.OnClickListener mRemoteTabClickListener;
     private OnInterceptTouchListener mOnInterceptTouchListener;
 
     public interface UriLoadCallback {
@@ -150,16 +151,17 @@ public class AboutHomeContent extends Sc
                 String spec = c.getString(c.getColumnIndex(URLColumns.URL));
                 Log.i(LOGTAG, "clicked: " + spec);
 
                 if (mUriLoadCallback != null)
                     mUriLoadCallback.callback(spec);
             }
         });
 
+        mPromoBox = (AboutHomePromoBox) findViewById(R.id.promo_box);
         mAddons = (AboutHomeSection) findViewById(R.id.recommended_addons);
         mLastTabs = (AboutHomeSection) findViewById(R.id.last_tabs);
         mRemoteTabs = (AboutHomeSection) findViewById(R.id.remote_tabs);
 
         TextView allTopSitesText = (TextView) findViewById(R.id.all_top_sites_text);
         allTopSitesText.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 mActivity.showAwesomebar(AwesomeBar.Target.CURRENT_TAB);
@@ -174,38 +176,16 @@ public class AboutHomeContent extends Sc
         });
 
         mRemoteTabs.setOnMoreTextClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 mActivity.showRemoteTabs();
             }
         });
 
-        TextView syncTextView = (TextView) findViewById(R.id.sync_text);
-        String syncText = syncTextView.getText().toString() + " \u00BB";
-        String boldName = getContext().getResources().getString(R.string.abouthome_sync_bold_name);
-        int styleIndex = syncText.indexOf(boldName);
-
-        // Highlight any occurrence of "Firefox Sync" in the string
-        // with a bold style.
-        if (styleIndex >= 0) {
-            SpannableString spannableText = new SpannableString(syncText);
-            spannableText.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), styleIndex, styleIndex + 12, 0);
-            syncTextView.setText(spannableText, TextView.BufferType.SPANNABLE);
-        }
-
-        LinearLayout syncBox = (LinearLayout) findViewById(R.id.sync_box);
-        syncBox.setOnClickListener(new View.OnClickListener() {
-            public void onClick(View v) {
-                Context context = v.getContext();
-                Intent intent = new Intent(context, SetupSyncActivity.class);
-                context.startActivity(intent);
-            }
-        });
-
         setTopSitesConstants();
     }
 
     public void onDestroy() {
         if (mAccountListener != null) {
             mAccountManager.removeOnAccountsUpdatedListener(mAccountListener);
             mAccountListener = null;
         }
@@ -227,31 +207,33 @@ public class AboutHomeContent extends Sc
         int visibilityWithoutTopSites = visible && !hasTopSites ? View.VISIBLE : View.GONE;
 
         findViewById(R.id.top_sites_grid).setVisibility(visibilityWithTopSites);
         findViewById(R.id.top_sites_title).setVisibility(visibility);
         findViewById(R.id.all_top_sites_text).setVisibility(visibilityWithTopSites);
         findViewById(R.id.no_top_sites_text).setVisibility(visibilityWithoutTopSites);
     }
 
-    private void setSyncVisibility(boolean visible) {
-        int visibility = visible ? View.VISIBLE : View.GONE;
-        findViewById(R.id.sync_box).setVisibility(visibility);
+    private void setPromoBoxVisibility(boolean visible, AboutHomePromoBox.Type type) {
+        if (visible)
+            mPromoBox.show(type);
+        else
+            mPromoBox.hide();
     }
 
     private void updateLayout(GeckoApp.StartupMode startupMode, boolean syncIsSetup) {
         // The idea here is that we only show the sync invitation
         // on the very first run. Show sync banner below the top
         // sites section in all other cases.
 
         boolean hasTopSites = mTopSitesAdapter.getCount() > 0;
         boolean isFirstRun = (startupMode == GeckoApp.StartupMode.NEW_PROFILE);
 
         setTopSitesVisibility(!isFirstRun || hasTopSites, hasTopSites);
-        setSyncVisibility(!syncIsSetup);
+        setPromoBoxVisibility(!syncIsSetup, AboutHomePromoBox.Type.SYNC);
     }
 
     private void updateLayoutForSync() {
         final GeckoApp.StartupMode startupMode = mActivity.getStartupMode();
         final boolean syncIsSetup = SyncAccounts.syncAccountsExist(mContext);
 
         post(new Runnable() {
             public void run() {
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/AboutHomePromoBox.java
@@ -0,0 +1,126 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko;
+
+import org.mozilla.gecko.sync.setup.activities.SetupSyncActivity;
+
+import android.content.Context;
+import android.content.Intent;
+import android.text.SpannableString;
+import android.text.style.StyleSpan;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * A promotional box for the about:home page. The layout contains an ImageView to the left of a
+ * TextView whose resources may be overidden to display custom values for a new type of promo box.
+ * To do this, add a new Type value and update show() to call setResources() for your values -
+ * including a set[Box Type]Resources() helper method is recommended.
+ */
+public class AboutHomePromoBox extends LinearLayout implements View.OnClickListener {
+    private static final String LOGTAG = "AboutHomePromoBox";
+
+    public enum Type { SYNC };
+
+    private Type mType;
+
+    private final Context mContext;
+    private final TextView mTextView;
+    private final ImageView mImageView;
+
+    // Use setResources() to set these variables for each PromoBox type.
+    private int mTextResource;
+    private int mBoldTextResource;
+    private int mImageResource;
+
+    public AboutHomePromoBox(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        final LayoutInflater inflater = LayoutInflater.from(context);
+        inflater.inflate(R.layout.abouthome_promo_box, this);
+
+        mContext = context;
+        mTextView = (TextView) findViewById(R.id.text);
+        mImageView = (ImageView) findViewById(R.id.icon);
+        setOnClickListener(this);
+    }
+
+    @Override
+    public void onClick(View v) {
+        Log.d(LOGTAG, "I work out.");
+        switch (mType) {
+            case SYNC:
+                final Context context = v.getContext();
+                final Intent intent = new Intent(context, SetupSyncActivity.class);
+                context.startActivity(intent);
+                break;
+
+            default:
+                Log.e(LOGTAG, "Invalid type was set when promo box was clicked.");
+                break;
+        }
+    }
+
+    /**
+     * Shows the specified promo box. If a promo box is already active, it will be overidden with a
+     * promo box of the specified type.
+     */
+    public void show(Type type) {
+        mType = type;
+        switch (type) {
+            case SYNC:
+                setSyncResources();
+                break;
+
+            default:
+                Log.e(LOGTAG, "Invalid PromoBoxType specified.");
+                break;
+        }
+        updateViewResources();
+        setVisibility(View.VISIBLE);
+    }
+
+    public void hide() {
+        setVisibility(View.GONE);
+        mType = null;
+    }
+
+    private void setResources(int textResource, int boldTextResource, int imageResource) {
+        mTextResource = textResource;
+        mBoldTextResource = boldTextResource;
+        mImageResource = imageResource;
+    }
+
+    private void updateViewResources() {
+        updateTextViewResources();
+        mImageView.setImageResource(mImageResource);
+    }
+
+    private void updateTextViewResources() {
+        final String promoText = mContext.getResources().getString(mTextResource) + " \u00BB";
+
+        final String boldName = mContext.getResources().getString(mBoldTextResource);
+        final int styleIndex = promoText.indexOf(boldName);
+        if (styleIndex < 0)
+            mTextView.setText(promoText);
+        else {
+            final SpannableString spannableText = new SpannableString(promoText);
+            spannableText.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), styleIndex,
+                    styleIndex + boldName.length(), 0);
+            mTextView.setText(spannableText, TextView.BufferType.SPANNABLE);
+        }
+    }
+
+    // Type.SYNC: Setup Firefox sync.
+    private void setSyncResources() {
+        setResources(R.string.abouthome_about_sync, R.string.abouthome_sync_bold_name,
+                R.drawable.abouthome_sync_logo);
+    }
+}
--- a/mobile/android/base/GeckoViewsFactory.java
+++ b/mobile/android/base/GeckoViewsFactory.java
@@ -33,17 +33,19 @@ public final class GeckoViewsFactory imp
         if (!TextUtils.isEmpty(name) && name.startsWith(GECKO_VIEW_IDENTIFIER)) {
             String viewName = name.substring(GECKO_VIEW_IDENTIFIER_LENGTH);
 
             if (TextUtils.isEmpty(viewName))
                 return null;
         
             Log.i(LOGTAG, "Creating custom Gecko view: " + viewName);
 
-            if (TextUtils.equals(viewName, "AboutHomeSection"))
+            if (TextUtils.equals(viewName, "AboutHomePromoBox"))
+                return new AboutHomePromoBox(context, attrs);
+            else if (TextUtils.equals(viewName, "AboutHomeSection"))
                 return new AboutHomeSection(context, attrs);
             else if (TextUtils.equals(viewName, "AwesomeBarTabs"))
                 return new AwesomeBarTabs(context, attrs);
             else if (TextUtils.equals(viewName, "FormAssistPopup"))
                 return new FormAssistPopup(context, attrs);
             else if (TextUtils.equals(viewName, "LinkTextView"))
                 return new LinkTextView(context, attrs);
             else if (TextUtils.equals(viewName, "FindInPageBar"))
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -31,16 +31,17 @@ UTIL_JAVA_FILES := \
   INIParser.java \
   INISection.java \
   util/EventDispatcher.java \
   util/FloatUtils.java \
   $(NULL)
 
 FENNEC_JAVA_FILES = \
   AboutHomeContent.java \
+  AboutHomePromoBox.java \
   AboutHomeSection.java \
   ActivityHandlerHelper.java \
   AndroidImport.java \
   AndroidImportPreference.java \
   AlertNotification.java \
   AwesomeBar.java \
   AwesomebarResultHandler.java \
   AwesomeBarTabs.java \
@@ -328,16 +329,17 @@ RES_LAYOUT = \
   res/layout/tabs_panel_toolbar.xml \
   res/layout/tabs_panel_toolbar_menu.xml \
   res/layout/tabs_row.xml \
   res/layout/tabs_tray.xml \
   res/layout/list_item_header.xml \
   res/layout/select_dialog_list.xml \
   res/layout/abouthome_addon_row.xml \
   res/layout/abouthome_last_tabs_row.xml \
+  res/layout/abouthome_promo_box.xml \
   res/layout/abouthome_section.xml \
   res/layout/abouthome_remote_tab_row.xml \
   res/layout/abouthome_topsite_item.xml \
   res/layout/validation_message.xml \
   $(NULL)
  
 RES_LAYOUT_LAND_V14 = \
   res/layout-land-v14/browser_toolbar.xml \
@@ -414,19 +416,19 @@ RES_DRAWABLE_NODPI = \
   res/drawable-nodpi/tabs_tray_selected_bg.png \
   $(NULL)
 
 RES_DRAWABLE_BASE = \
   res/drawable/favicon.png \
   res/drawable/folder.png \
   res/drawable/abouthome_icon.png \
   res/drawable/abouthome_logo.png \
+  res/drawable/abouthome_promo_box_bg.9.png \
   res/drawable/abouthome_sync_logo.png \
-  res/drawable/abouthome_sync_bg.9.png \
-  res/drawable/abouthome_sync_pressed_bg.9.png \
+  res/drawable/abouthome_promo_box_pressed_bg.9.png \
   res/drawable/abouthome_thumbnail.png \
   res/drawable/address_bar_bg_shadow.png \
   res/drawable/alert_addon.png \
   res/drawable/alert_app.png \
   res/drawable/alert_download.png \
   res/drawable/awesomebar_tab_center.9.png \
   res/drawable/awesomebar_tab_left.9.png \
   res/drawable/awesomebar_tab_right.9.png \
@@ -498,19 +500,19 @@ RES_DRAWABLE_LDPI = \
 
 RES_DRAWABLE_HDPI = \
   res/drawable-hdpi/favicon.png \
   res/drawable-hdpi/folder.png \
   res/drawable-hdpi/home_bg.png \
   res/drawable-hdpi/home_star.png \
   res/drawable-hdpi/abouthome_icon.png \
   res/drawable-hdpi/abouthome_logo.png \
+  res/drawable-hdpi/abouthome_promo_box_bg.9.png \
   res/drawable-hdpi/abouthome_sync_logo.png \
-  res/drawable-hdpi/abouthome_sync_bg.9.png \
-  res/drawable-hdpi/abouthome_sync_pressed_bg.9.png \
+  res/drawable-hdpi/abouthome_promo_box_pressed_bg.9.png \
   res/drawable-hdpi/abouthome_thumbnail.png \
   res/drawable-hdpi/address_bar_bg_shadow.png \
   res/drawable-hdpi/alert_addon.png \
   res/drawable-hdpi/alert_app.png \
   res/drawable-hdpi/alert_download.png \
   res/drawable-hdpi/awesomebar_tab_center.9.png \
   res/drawable-hdpi/awesomebar_tab_left.9.png \
   res/drawable-hdpi/awesomebar_tab_right.9.png \
@@ -564,19 +566,19 @@ RES_DRAWABLE_HDPI = \
   $(addprefix res/drawable-hdpi/,$(notdir $(SYNC_RES_DRAWABLE_HDPI))) \
   $(NULL)
 
 RES_DRAWABLE_XHDPI = \
   res/drawable-xhdpi/favicon.png \
   res/drawable-xhdpi/folder.png \
   res/drawable-xhdpi/abouthome_icon.png \
   res/drawable-xhdpi/abouthome_logo.png \
+  res/drawable-xhdpi/abouthome_promo_box_bg.9.png \
   res/drawable-xhdpi/abouthome_sync_logo.png \
-  res/drawable-xhdpi/abouthome_sync_bg.9.png \
-  res/drawable-xhdpi/abouthome_sync_pressed_bg.9.png \
+  res/drawable-xhdpi/abouthome_promo_box_pressed_bg.9.png \
   res/drawable-xhdpi/abouthome_thumbnail.png \
   res/drawable-xhdpi/address_bar_bg_curve.png \
   res/drawable-xhdpi/address_bar_bg_shadow.png \
   res/drawable-xhdpi/address_bar_texture_port.png \
   res/drawable-xhdpi/address_bar_url_default.9.png \
   res/drawable-xhdpi/address_bar_url_pressed.9.png \
   res/drawable-xhdpi/alert_addon.png \
   res/drawable-xhdpi/alert_app.png \
@@ -953,17 +955,17 @@ FENNEC_PP_JAVA_FILES += CrashReporter.ja
 MOZ_ANDROID_DRAWABLES += mobile/android/base/resources/drawable/crash_reporter.png
 RES_LAYOUT += res/layout/crash_reporter.xml
 endif
 
 MOZ_ANDROID_DRAWABLES += \
   $(SYNC_RES_DRAWABLE)                                                          \
   mobile/android/base/resources/drawable/abouthome_bg_repeat.xml                \
   mobile/android/base/resources/drawable/abouthome_divider.xml                  \
-  mobile/android/base/resources/drawable/abouthome_sync_box.xml                 \
+  mobile/android/base/resources/drawable/abouthome_promo_box.xml                \
   mobile/android/base/resources/drawable/action_bar_button.xml                  \
   mobile/android/base/resources/drawable/address_bar_bg.xml                     \
   mobile/android/base/resources/drawable/address_bar_bg_shadow_repeat.xml       \
   mobile/android/base/resources/drawable/autocomplete_list_bg.9.png             \
   mobile/android/base/resources/drawable/awesomebar_tab_indicator.xml           \
   mobile/android/base/resources/drawable/awesomebar_tab_selected.xml            \
   mobile/android/base/resources/drawable/awesomebar_tab_unselected.xml          \
   mobile/android/base/resources/drawable/desktop_notification.png               \
rename from mobile/android/base/resources/drawable-hdpi/abouthome_sync_bg.9.png
rename to mobile/android/base/resources/drawable-hdpi/abouthome_promo_box_bg.9.png
rename from mobile/android/base/resources/drawable-hdpi/abouthome_sync_pressed_bg.9.png
rename to mobile/android/base/resources/drawable-hdpi/abouthome_promo_box_pressed_bg.9.png
rename from mobile/android/base/resources/drawable-xhdpi/abouthome_sync_bg.9.png
rename to mobile/android/base/resources/drawable-xhdpi/abouthome_promo_box_bg.9.png
rename from mobile/android/base/resources/drawable-xhdpi/abouthome_sync_pressed_bg.9.png
rename to mobile/android/base/resources/drawable-xhdpi/abouthome_promo_box_pressed_bg.9.png
rename from mobile/android/base/resources/drawable/abouthome_sync_box.xml
rename to mobile/android/base/resources/drawable/abouthome_promo_box.xml
--- a/mobile/android/base/resources/drawable/abouthome_sync_box.xml
+++ b/mobile/android/base/resources/drawable/abouthome_promo_box.xml
@@ -1,11 +1,11 @@
 <?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/. -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <item android:state_pressed="true" android:drawable="@drawable/abouthome_sync_pressed_bg"/>
-    <item android:drawable="@drawable/abouthome_sync_bg"/>
+    <item android:state_pressed="true" android:drawable="@drawable/abouthome_promo_box_pressed_bg"/>
+    <item android:drawable="@drawable/abouthome_promo_box_bg"/>
 
 </selector>
rename from mobile/android/base/resources/drawable/abouthome_sync_bg.9.png
rename to mobile/android/base/resources/drawable/abouthome_promo_box_bg.9.png
rename from mobile/android/base/resources/drawable/abouthome_sync_pressed_bg.9.png
rename to mobile/android/base/resources/drawable/abouthome_promo_box_pressed_bg.9.png
--- a/mobile/android/base/resources/layout-xlarge-land-v11/abouthome_content.xml.in
+++ b/mobile/android/base/resources/layout-xlarge-land-v11/abouthome_content.xml.in
@@ -64,47 +64,28 @@
                                             android:text="@string/abouthome_top_sites_browse"
                                             android:layout_width="fill_parent"
                                             android:layout_height="30dip"
                                             android:layout_marginTop="7dip"
                                             android:textColor="#22629e"
                                             android:textSize="12sp"
                                             android:gravity="top|center_horizontal"/>
 
-                <LinearLayout android:id="@+id/sync_box"
-                              android:background="@drawable/abouthome_sync_box"
-                              android:orientation="horizontal"
-                              android:layout_width="fill_parent"
-                              android:layout_height="wrap_content"
-                              android:layout_marginLeft="12dp"
-                              android:layout_marginRight="12dp"
-                              android:layout_marginTop="17dp"
-                              android:layout_marginBottom="14dp"
-                              android:gravity="center"
-                              android:clickable="true"
-                              android:visibility="gone">
-
-                    <ImageView android:id="@+id/sync_logo"
-                               android:src="@drawable/abouthome_sync_logo"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
-                               android:layout_weight="0"
-                               android:gravity="left|center_vertical"/>
-
-                    <TextView android:id="@+id/sync_text"
-                              android:text="@string/abouthome_about_sync"
-                              android:layout_width="0dp"
-                              android:layout_height="wrap_content"
-                              android:layout_weight="1"
-                              android:layout_marginLeft="7dp"
-                              android:gravity="center"
-                              android:textSize="15sp"
-                              android:textColor="#FFFFFF"/>
-
-                </LinearLayout>
+            <org.mozilla.gecko.AboutHomePromoBox android:id="@+id/promo_box"
+                                                 android:orientation="horizontal"
+                                                 android:background="@drawable/abouthome_promo_box"
+                                                 android:layout_width="fill_parent"
+                                                 android:layout_height="wrap_content"
+                                                 android:layout_marginLeft="12dp"
+                                                 android:layout_marginRight="12dp"
+                                                 android:layout_marginTop="17dp"
+                                                 android:layout_marginBottom="14dp"
+                                                 android:gravity="center"
+                                                 android:clickable="true"
+                                                 android:visibility="gone"/>
 
         </LinearLayout>
 
         <RelativeLayout android:layout_width="0dp"
                         android:layout_height="fill_parent"
                         android:layout_weight="0.4"
                         android:layout_marginLeft="@dimen/abouthome_gutter_small"
                         android:layout_marginRight="@dimen/abouthome_gutter_large">
--- a/mobile/android/base/resources/layout/abouthome_content.xml.in
+++ b/mobile/android/base/resources/layout/abouthome_content.xml.in
@@ -71,47 +71,28 @@
                                             android:text="@string/abouthome_top_sites_browse"
                                             android:layout_width="fill_parent"
                                             android:layout_height="30dip"
                                             android:layout_marginTop="7dip"
                                             android:textColor="#22629e"
                                             android:textSize="12sp"
                                             android:gravity="top|center_horizontal"/>
 
-            <LinearLayout android:id="@+id/sync_box"
-                          android:background="@drawable/abouthome_sync_box"
-                          android:orientation="horizontal"
-                          android:layout_width="fill_parent"
-                          android:layout_height="wrap_content"
-                          android:layout_marginLeft="12dp"
-                          android:layout_marginRight="12dp"
-                          android:layout_marginTop="17dp"
-                          android:layout_marginBottom="14dp"
-                          android:gravity="center"
-                          android:clickable="true"
-                          android:visibility="gone">
-
-                <ImageView android:id="@+id/sync_logo"
-                           android:src="@drawable/abouthome_sync_logo"
-                           android:layout_width="wrap_content"
-                           android:layout_height="wrap_content"
-                           android:layout_weight="0"
-                           android:gravity="left|center_vertical"/>
-
-                <TextView android:id="@+id/sync_text"
-                          android:text="@string/abouthome_about_sync"
-                          android:layout_width="0dp"
-                          android:layout_height="wrap_content"
-                          android:layout_weight="1"
-                          android:layout_marginLeft="7dp"
-                          android:gravity="center"
-                          android:textSize="15sp"
-                          android:textColor="#FFFFFF"/>
-
-            </LinearLayout>
+            <org.mozilla.gecko.AboutHomePromoBox android:id="@+id/promo_box"
+                                                 android:orientation="horizontal"
+                                                 android:background="@drawable/abouthome_promo_box"
+                                                 android:layout_width="fill_parent"
+                                                 android:layout_height="wrap_content"
+                                                 android:layout_marginLeft="12dp"
+                                                 android:layout_marginRight="12dp"
+                                                 android:layout_marginTop="17dp"
+                                                 android:layout_marginBottom="14dp"
+                                                 android:gravity="center"
+                                                 android:clickable="true"
+                                                 android:visibility="gone"/>
 
             <org.mozilla.gecko.AboutHomeSection android:id="@+id/last_tabs"
                                                 android:layout_width="fill_parent"
                                                 android:layout_height="wrap_content"
                                                 android:visibility="gone"
                                                 gecko:title="@string/abouthome_last_tabs_title"
                                                 gecko:more_text="@string/abouthome_last_tabs_open"/>
 
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/layout/abouthome_promo_box.xml
@@ -0,0 +1,24 @@
+<?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/. -->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+       xmlns:gecko="http://schemas.android.com/apk/res/@ANDROID_PACKAGE_NAME@">
+
+    <ImageView android:id="@+id/icon"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_weight="0"
+               android:gravity="left|center_vertical"/>
+
+    <TextView android:id="@+id/text"
+              android:layout_width="0dp"
+              android:layout_height="wrap_content"
+              android:layout_weight="1"
+              android:layout_marginLeft="7dp"
+              android:gravity="center"
+              android:textSize="15sp"
+              android:textColor="#FFFFFF"/>
+
+</merge>