Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java |
| index 50c0a6d78c31d6f41e09d212a9e2f9c7ccd9ec41..b77d2016c84a85b76eec8a187698a99e025b8e14 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java |
| @@ -4,24 +4,42 @@ |
| package org.chromium.chrome.browser; |
| +import android.app.ActivityManager; |
| import android.content.Context; |
| import android.content.Intent; |
| +import android.content.pm.PackageManager; |
| +import android.content.pm.ResolveInfo; |
| import android.graphics.Bitmap; |
| +import android.graphics.Canvas; |
| +import android.graphics.Color; |
| +import android.graphics.Paint; |
| +import android.graphics.Path; |
| +import android.graphics.PorterDuff; |
| +import android.graphics.PorterDuffXfermode; |
| +import android.graphics.Rect; |
| +import android.graphics.RectF; |
| +import android.graphics.drawable.BitmapDrawable; |
| +import android.graphics.drawable.Drawable; |
| +import android.net.Uri; |
| import android.os.Handler; |
| import android.os.Looper; |
| import android.util.Base64; |
| +import android.util.DisplayMetrics; |
| +import android.util.TypedValue; |
| +import org.chromium.base.ApiCompatibilityUtils; |
| import org.chromium.base.ApplicationStatus; |
| +import org.chromium.base.Log; |
| import org.chromium.base.VisibleForTesting; |
| import org.chromium.base.annotations.CalledByNative; |
| import org.chromium.chrome.R; |
| -import org.chromium.chrome.browser.tab.Tab; |
| import org.chromium.chrome.browser.webapps.WebappLauncherActivity; |
| -import org.chromium.content_public.browser.WebContents; |
| +import org.chromium.chrome.browser.widget.RoundedIconGenerator; |
| import org.chromium.content_public.common.ScreenOrientationConstants; |
| import org.chromium.ui.widget.Toast; |
| import java.io.ByteArrayOutputStream; |
| +import java.util.List; |
| import java.util.UUID; |
| /** |
| @@ -43,14 +61,18 @@ public class ShortcutHelper { |
| // This value is equal to kInvalidOrMissingThemeColor in the C++ content::Manifest struct. |
| public static final long THEME_COLOR_INVALID_OR_MISSING = ((long) Integer.MAX_VALUE) + 1; |
| - /** Observes the data fetching pipeline. */ |
| - public interface ShortcutHelperObserver { |
| - /** Called when the title of the page is available. */ |
| - void onUserTitleAvailable(String title); |
| - |
| - /** Called when the icon to use in the launcher is available. */ |
| - void onIconAvailable(Bitmap icon); |
| - } |
| + // There is no public string defining this intent so if Home changes the value, we |
| + // have to update this string. |
| + private static final String INSTALL_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT"; |
| + private static final int DEFAULT_RGB_VALUE = 145; |
| + private static final String TAG = "cr.Shortcuts"; |
| + public static final String REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB = |
|
gone
2015/08/19 18:49:16
while you're here, move this up with the other pub
Lalit Maganti
2015/08/20 17:12:18
Done.
|
| + "REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB"; |
| + private static final int INSET_DIMENSION_FOR_TOUCHICON = 1; |
| + private static final int TOUCHICON_BORDER_RADII_DP = 4; |
| + private static final int GENERATED_ICON_SIZE_DP = 40; |
| + private static final int GENERATED_ICON_ROUNDED_CORNERS_DP = 2; |
| + private static final int GENERATED_ICON_FONT_SIZE_DP = 16; |
| /** Broadcasts Intents out Android for adding the shortcut. */ |
| public static class Delegate { |
| @@ -73,47 +95,6 @@ public class ShortcutHelper { |
| private static Delegate sDelegate = new Delegate(); |
| - private final Context mAppContext; |
| - private final Tab mTab; |
| - |
| - private ShortcutHelperObserver mObserver; |
| - private boolean mIsInitialized; |
| - private long mNativeShortcutHelper; |
| - |
| - public ShortcutHelper(Context appContext, Tab tab) { |
| - mAppContext = appContext; |
| - mTab = tab; |
| - } |
| - |
| - /** |
| - * Gets all the information required to initialize the UI. The observer will be notified as |
| - * information required for the shortcut become available. |
| - * @param observer Observer to notify. |
| - */ |
| - public void initialize(ShortcutHelperObserver observer) { |
| - mObserver = observer; |
| - mNativeShortcutHelper = nativeInitialize(mTab.getWebContents()); |
| - } |
| - |
| - /** |
| - * Returns whether the object is initialized. |
| - */ |
| - public boolean isInitialized() { |
| - return mIsInitialized; |
| - } |
| - |
| - /** |
| - * Puts the object in a state where it is safe to be destroyed. |
| - */ |
| - public void destroy() { |
| - nativeDestroy(mNativeShortcutHelper); |
| - |
| - // Make sure the callback isn't run if the tear down happens before |
| - // onInitialized() is called. |
| - mObserver = null; |
| - mNativeShortcutHelper = 0; |
| - } |
| - |
| /** |
| * Sets the delegate to use. |
| */ |
| @@ -122,35 +103,6 @@ public class ShortcutHelper { |
| sDelegate = delegate; |
| } |
| - @CalledByNative |
| - private void onUserTitleAvailable(String title) { |
| - mObserver.onUserTitleAvailable(title); |
| - } |
| - |
| - @CalledByNative |
| - private void onIconAvailable(Bitmap icon) { |
| - mObserver.onIconAvailable(icon); |
| - mIsInitialized = true; |
| - } |
| - |
| - /** |
| - * Adds a shortcut for the current Tab. |
| - * @param userRequestedTitle Updated title for the shortcut. |
| - */ |
| - public void addShortcut(String userRequestedTitle) { |
| - nativeAddShortcut(mNativeShortcutHelper, userRequestedTitle); |
| - } |
| - |
| - /** |
| - * Creates an icon that is acceptable to show on the launcher. |
| - */ |
| - @CalledByNative |
| - private static Bitmap finalizeLauncherIcon( |
| - String url, Bitmap icon, int red, int green, int blue) { |
| - return BookmarkUtils.createLauncherIcon( |
| - ApplicationStatus.getApplicationContext(), icon, url, red, green, blue); |
| - } |
| - |
| /** |
| * Called when we have to fire an Intent to add a shortcut to the homescreen. |
| * If the webpage indicated that it was capable of functioning as a webapp, it is added as a |
| @@ -186,7 +138,7 @@ public class ShortcutHelper { |
| shortcutIntent.putExtra(EXTRA_THEME_COLOR, themeColor); |
| } else { |
| // Add the shortcut as a launcher icon to open in the browser Activity. |
| - shortcutIntent = BookmarkUtils.createShortcutIntent(url); |
| + shortcutIntent = ShortcutHelper.createShortcutIntent(url); |
| } |
| // Always attach a source (one of add to homescreen menu item, app banner, or unknown) to |
| @@ -194,7 +146,7 @@ public class ShortcutHelper { |
| shortcutIntent.putExtra(EXTRA_SOURCE, source); |
| shortcutIntent.setPackage(context.getPackageName()); |
| sDelegate.sendBroadcast( |
| - context, BookmarkUtils.createAddToHomeIntent(shortcutIntent, userTitle, icon, url)); |
| + context, createAddToHomeIntent(shortcutIntent, userTitle, icon, url)); |
| // Alert the user about adding the shortcut. |
| final String shortUrl = UrlUtilities.getDomainAndRegistry(url, true); |
| @@ -212,6 +164,163 @@ public class ShortcutHelper { |
| } |
| /** |
| + * Creates an intent that will add a shortcut to the home screen. |
| + * @param shortcutIntent Intent to fire when the shortcut is activated. |
| + * @param title Title of the bookmark. |
| + * @param icon Image that represents the bookmark. |
| + * @param url URL of the bookmark. |
| + * @return Intent for the shortcut. |
| + */ |
| + public static Intent createAddToHomeIntent( |
| + Intent shortcutIntent, String title, Bitmap icon, String url) { |
|
gone
2015/08/19 18:49:16
can you make the ordering of the parameters consis
|
| + Intent i = new Intent(INSTALL_SHORTCUT); |
| + i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); |
| + i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title); |
| + i.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon); |
| + return i; |
| + } |
| + |
| + /** |
| + * Creates an intent that will add a shortcut to the home screen. |
| + * @param url Url of the bookmark. |
| + * @param title Title of the bookmark. |
| + * @param icon Image that represents the bookmark. |
| + * @return Intent for the shortcut. |
| + */ |
| + public static Intent createAddToHomeIntent(String url, String title, Bitmap icon) { |
| + Intent shortcutIntent = createShortcutIntent(url); |
| + return createAddToHomeIntent(shortcutIntent, title, icon, url); |
| + } |
| + |
| + /** |
| + * Shortcut intent for icon on homescreen. |
| + * @param url Url of the bookmark. |
| + * @return Intent for onclick action of the shortcut. |
| + */ |
| + public static Intent createShortcutIntent(String url) { |
| + Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); |
| + shortcutIntent.putExtra(REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true); |
| + return shortcutIntent; |
| + } |
| + |
| + /** |
| + * Utility method to check if a shortcut can be added to the homescreen. |
| + * @param context Context used to get the package manager. |
| + * @return if a shortcut can be added to the homescreen under the current profile. |
| + */ |
| + public static boolean isAddToHomeIntentSupported(Context context) { |
| + PackageManager pm = context.getPackageManager(); |
| + Intent i = new Intent(INSTALL_SHORTCUT); |
| + List<ResolveInfo> receivers = pm.queryBroadcastReceivers( |
| + i, PackageManager.GET_INTENT_FILTERS); |
| + return !receivers.isEmpty(); |
| + } |
| + |
| + /** |
| + * Creates an icon to be associated with this bookmark. If available, the touch icon |
|
gone
2015/08/19 18:49:16
bookmark -> shortcut
|
| + * will be used, else we draw our own. |
| + * @param context Context used to create the intent. |
| + * @param icon Image representing the bookmark. |
| + * @param url URL of the bookmark. |
| + * @param rValue Red component of the dominant icon color. |
| + * @param gValue Green component of the dominant icon color. |
| + * @param bValue Blue component of the dominant icon color. |
| + * @return Bitmap Either the touch-icon or the newly created favicon. |
| + */ |
| + public static Bitmap createLauncherIcon(Context context, Bitmap icon, String url, int rValue, |
| + int gValue, int bValue) { |
| + Bitmap bitmap = null; |
| + ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); |
| + final int iconSize = am.getLauncherLargeIconSize(); |
| + final int iconDensity = am.getLauncherLargeIconDensity(); |
| + try { |
| + bitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); |
| + Canvas canvas = new Canvas(bitmap); |
| + if (icon == null) { |
| + icon = getBitmapFromResourceId(context, R.drawable.globe_favicon, iconDensity); |
| + rValue = gValue = bValue = DEFAULT_RGB_VALUE; |
| + } |
| + final int smallestSide = iconSize; |
| + if (icon.getWidth() >= smallestSide / 2 && icon.getHeight() >= smallestSide / 2) { |
| + drawTouchIconToCanvas(context, icon, canvas); |
| + } else { |
| + drawWidgetBackgroundToCanvas(context, canvas, iconDensity, url, |
| + Color.rgb(rValue, gValue, bValue)); |
| + } |
| + canvas.setBitmap(null); |
| + } catch (OutOfMemoryError e) { |
| + Log.w(TAG, "OutOfMemoryError while trying to draw bitmap on canvas."); |
| + } |
| + return bitmap; |
| + } |
| + |
| + private static Bitmap getBitmapFromResourceId(Context context, int id, int density) { |
| + Drawable drawable = ApiCompatibilityUtils.getDrawableForDensity( |
| + context.getResources(), id, density); |
| + |
| + if (drawable instanceof BitmapDrawable) { |
| + BitmapDrawable bd = (BitmapDrawable) drawable; |
| + return bd.getBitmap(); |
| + } |
| + assert false : "The drawable was not a bitmap drawable as expected"; |
| + return null; |
| + } |
| + |
| + /** |
| + * Use touch-icon or higher-resolution favicon and round the corners. |
| + * @param context Context used to get resources. |
| + * @param touchIcon Touch icon bitmap. |
| + * @param canvas Canvas that holds the touch icon. |
| + */ |
| + private static void drawTouchIconToCanvas(Context context, Bitmap touchIcon, Canvas canvas) { |
| + Rect iconBounds = new Rect(0, 0, canvas.getWidth(), canvas.getHeight()); |
| + Rect src = new Rect(0, 0, touchIcon.getWidth(), touchIcon.getHeight()); |
| + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); |
| + paint.setFilterBitmap(true); |
| + canvas.drawBitmap(touchIcon, src, iconBounds, paint); |
| + // Convert dp to px. |
| + int borderRadii = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, |
| + TOUCHICON_BORDER_RADII_DP, context.getResources().getDisplayMetrics()); |
| + Path path = new Path(); |
| + path.setFillType(Path.FillType.INVERSE_WINDING); |
| + RectF rect = new RectF(iconBounds); |
| + rect.inset(INSET_DIMENSION_FOR_TOUCHICON, INSET_DIMENSION_FOR_TOUCHICON); |
| + path.addRoundRect(rect, borderRadii, borderRadii, Path.Direction.CW); |
| + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); |
| + canvas.drawPath(path, paint); |
| + } |
| + |
| + /** |
| + * Draw document icon to canvas. |
| + * @param context Context used to get bitmap resources. |
| + * @param canvas Canvas that holds the document icon. |
| + * @param iconDensity Density information to get bitmap resources. |
| + * @param url URL of the bookmark. |
| + * @param color Color for the document icon's folding and the bottom strip. |
| + */ |
| + private static void drawWidgetBackgroundToCanvas( |
| + Context context, Canvas canvas, int iconDensity, String url, int color) { |
| + Rect iconBounds = new Rect(0, 0, canvas.getWidth(), canvas.getHeight()); |
| + Bitmap bookmarkWidgetBg = |
| + getBitmapFromResourceId(context, R.mipmap.bookmark_widget_bg, iconDensity); |
| + |
| + Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); |
| + canvas.drawBitmap(bookmarkWidgetBg, null, iconBounds, paint); |
| + |
| + float density = (float) iconDensity / DisplayMetrics.DENSITY_MEDIUM; |
| + int iconSize = (int) (GENERATED_ICON_SIZE_DP * density); |
| + int iconRoundedEdge = (int) (GENERATED_ICON_ROUNDED_CORNERS_DP * density); |
| + int iconFontSize = (int) (GENERATED_ICON_FONT_SIZE_DP * density); |
| + |
| + RoundedIconGenerator generator = new RoundedIconGenerator( |
| + iconSize, iconSize, iconRoundedEdge, color, iconFontSize); |
| + Bitmap icon = generator.generateIconForUrl(url); |
| + if (icon == null) return; // Bookmark URL does not have a domain. |
| + canvas.drawBitmap(icon, iconBounds.exactCenterX() - icon.getWidth() / 2.0f, |
| + iconBounds.exactCenterY() - icon.getHeight() / 2.0f, null); |
| + } |
| + |
| + /** |
| * @return String that can be used to verify that a WebappActivity is being started by Chrome. |
| */ |
| public static String getEncodedMac(Context context, String url) { |
| @@ -221,8 +330,4 @@ public class ShortcutHelper { |
| byte[] mac = WebappAuthenticator.getMacForUrl(context, url); |
| return Base64.encodeToString(mac, Base64.DEFAULT); |
| } |
| - |
| - private native long nativeInitialize(WebContents webContents); |
| - private native void nativeAddShortcut(long nativeShortcutHelper, String userRequestedTitle); |
| - private native void nativeDestroy(long nativeShortcutHelper); |
| } |