Bug 1329144 - CustomTabsActivity supports ActionButton draft
authorJulian_Chu <walkingice0204@gmail.com>
Fri, 03 Feb 2017 16:03:21 +0800
changeset 480254 c4a5707785a5ebf3dd31a3d3dd0a4f69238a1fe1
parent 479185 6d31483aae8782aaf77dcbef269ff287f17c5352
child 544911 665813087638b0cb3a4c4e8397557e73fa126640
push id44500
push userbmo:walkingice0204@gmail.com
push dateWed, 08 Feb 2017 02:50:53 +0000
bugs1329144
milestone54.0a1
Bug 1329144 - CustomTabsActivity supports ActionButton 3rd-party-app could launch CustomTabsActivity, and could also configure a custom action button. Now let CustomTabsActivity supports it by creating a MenuItem. MozReview-Commit-ID: 2KuMgBJy2gz
mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
mobile/android/base/resources/values/ids.xml
mobile/android/tests/background/junit4/src/org/mozilla/gecko/customtabs/TestCustomTabsActivity.java
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
@@ -1,23 +1,30 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.customtabs;
 
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.Bitmap;
 import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.VisibleForTesting;
+import android.support.v4.view.MenuItemCompat;
 import android.support.v7.app.ActionBar;
 import android.support.v7.widget.Toolbar;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
 import android.widget.TextView;
 
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.GeckoApp;
@@ -193,25 +200,59 @@ public class CustomTabsActivity extends 
             final Tab tab = tabs.getTab(lastSelectedTabId);
             if (tab == null) {
                 finish();
             }
         }
         super.onResume();
     }
 
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        insertActionButton(menu, getIntent());
+        return super.onPrepareOptionsMenu(menu);
+    }
+
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case android.R.id.home:
                 finish();
                 return true;
+            case R.id.action_button:
+                onActionButtonClicked();
+                return true;
         }
         return super.onOptionsItemSelected(item);
     }
 
+    /**
+     * To insert a MenuItem (as an ActionButton) into Menu.
+     *
+     * @param menu   The options menu in which to place items.
+     * @param intent which to launch this activity
+     * @return the MenuItem which be created and inserted into menu. Otherwise, null.
+     */
+    @VisibleForTesting
+    MenuItem insertActionButton(Menu menu, Intent intent) {
+        if (!IntentUtil.hasActionButton(intent)) {
+            return null;
+        }
+
+        // TODO: Bug 1336373 - Action button icon should support tint
+        MenuItem item = menu.add(Menu.NONE,
+                R.id.action_button,
+                Menu.NONE,
+                IntentUtil.getActionButtonDescription(intent));
+        Bitmap bitmap = IntentUtil.getActionButtonIcon(intent);
+        item.setIcon(new BitmapDrawable(getResources(), bitmap));
+        MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
+
+        return item;
+    }
+
     private void updateActionBarWithToolbar(final Toolbar toolbar) {
         setSupportActionBar(toolbar);
         final ActionBar ab = getSupportActionBar();
         if (ab != null) {
             ab.setDisplayHomeAsUpEnabled(true);
         }
     }
 
@@ -223,9 +264,18 @@ public class CustomTabsActivity extends 
         toolbar.setBackgroundColor(toolbarColor);
 
         final Window window = getWindow();
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
             window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
             window.setStatusBarColor(ColorUtil.darken(toolbarColor, 0.25));
         }
     }
+
+    private void onActionButtonClicked() {
+        PendingIntent pendingIntent = IntentUtil.getActionButtonPendingIntent(getIntent());
+        try {
+            pendingIntent.send();
+        } catch (PendingIntent.CanceledException e) {
+            Log.w(LOGTAG, "Action Button clicked, but pending intent was canceled", e);
+        }
+    }
 }
--- a/mobile/android/base/resources/values/ids.xml
+++ b/mobile/android/base/resources/values/ids.xml
@@ -14,10 +14,11 @@
     <item type="id" name="recycler_view_click_support" />
     <item type="id" name="range_list"/>
     <item type="id" name="pref_header_general"/>
     <item type="id" name="pref_header_privacy"/>
     <item type="id" name="pref_header_search"/>
     <item type="id" name="updateServicePermissionNotification" />
     <item type="id" name="websiteContentNotification" />
     <item type="id" name="foregroundNotification" />
+    <item type="id" name="action_button"/>
 
 </resources>
--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/customtabs/TestCustomTabsActivity.java
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/customtabs/TestCustomTabsActivity.java
@@ -1,26 +1,34 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.gecko.customtabs;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.support.annotation.AnimRes;
 import android.support.customtabs.CustomTabsIntent;
+import android.view.Menu;
+import android.view.MenuItem;
 
 import junit.framework.Assert;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.internal.util.reflection.Whitebox;
+import org.mozilla.gecko.R;
 import org.mozilla.gecko.background.testhelpers.TestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.fakes.RoboMenu;
 
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
@@ -37,16 +45,17 @@ public class TestCustomTabsActivity {
     private final int exitRes = 0x456; // arbitrary number as animation resource id
 
     @Before
     public void setUp() {
         spyContext = spy(RuntimeEnvironment.application);
         doReturn(THIRD_PARTY_PACKAGE_NAME).when(spyContext).getPackageName();
 
         spyActivity = spy(new CustomTabsActivity());
+        doReturn(RuntimeEnvironment.application.getResources()).when(spyActivity).getResources();
 
         final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
         builder.setExitAnimations(spyContext, enterRes, exitRes);
         final Intent i = builder.build().intent;
     }
 
     /**
      * Activity should not call overridePendingTransition if custom animation does not exist.
@@ -86,9 +95,36 @@ public class TestCustomTabsActivity {
         builder.setExitAnimations(spyContext, enterRes, exitRes);
         final Intent i = builder.build().intent;
 
         doReturn(i).when(spyActivity).getIntent();
         Whitebox.setInternalState(spyActivity, "usingCustomAnimation", true);
 
         Assert.assertEquals(THIRD_PARTY_PACKAGE_NAME, spyActivity.getPackageName());
     }
+
+    @Test
+    public void testInsertActionButton() {
+        // create properties for CustomTabsIntent
+        final String description = "Description";
+        final Intent actionIntent = new Intent(Intent.ACTION_VIEW);
+        final int reqCode = 0x123;
+        final PendingIntent pendingIntent = PendingIntent.getActivities(spyContext,
+                reqCode,
+                new Intent[]{actionIntent},
+                PendingIntent.FLAG_CANCEL_CURRENT);
+        final Bitmap bitmap = BitmapFactory.decodeResource(
+                spyContext.getResources(),
+                R.drawable.ic_action_settings); // arbitrary icon resource
+
+        // To create a CustomTabsIntent which is asking for ActionButton.
+        final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
+        builder.setActionButton(bitmap, description, pendingIntent, true);
+
+        // CustomTabsActivity should return a MenuItem with corresponding attributes.
+        Menu menu = new RoboMenu(spyContext);
+        MenuItem item = spyActivity.insertActionButton(menu, builder.build().intent);
+        Assert.assertNotNull(item);
+        Assert.assertEquals(item.getTitle(), description);
+        Assert.assertEquals(0, item.getOrder()); // should be the first one
+        Assert.assertTrue(item.isVisible());
+    }
 }
\ No newline at end of file