Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3128)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java

Issue 1288903002: Refactor ShortcutHelper and merge in BookmarkUtils (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix test file name Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 ec1ffdabc0c7d2dde778cf21628f575e05dc5f3c..ecb2acdea553ba595f9bc8bddd9d754555f935c8 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;
/**
@@ -41,18 +59,22 @@ public class ShortcutHelper {
public static final String EXTRA_THEME_COLOR = "org.chromium.chrome.browser.theme_color";
public static final String EXTRA_BACKGROUND_COLOR =
"org.chromium.chrome.browser.background_color";
+ public static final String REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB =
+ "REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB";
// This value is equal to kInvalidOrMissingColor in the C++ content::Manifest struct.
public static final long MANIFEST_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);
- }
+ private static final String TAG = "cr.Shortcuts";
+ // 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 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 {
@@ -75,47 +97,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.
*/
@@ -124,35 +105,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
@@ -189,7 +141,7 @@ public class ShortcutHelper {
shortcutIntent.putExtra(EXTRA_BACKGROUND_COLOR, backgroundColor);
} else {
// Add the shortcut as a launcher icon to open in the browser Activity.
- shortcutIntent = BookmarkUtils.createShortcutIntent(url);
+ shortcutIntent = createShortcutIntent(url);
}
// Always attach a source (one of add to homescreen menu item, app banner, or unknown) to
@@ -197,7 +149,7 @@ public class ShortcutHelper {
shortcutIntent.putExtra(EXTRA_SOURCE, source);
shortcutIntent.setPackage(context.getPackageName());
sDelegate.sendBroadcast(
- context, BookmarkUtils.createAddToHomeIntent(shortcutIntent, userTitle, icon, url));
+ context, createAddToHomeIntent(url, userTitle, icon, shortcutIntent));
// Alert the user about adding the shortcut.
final String shortUrl = UrlUtilities.getDomainAndRegistry(url, true);
@@ -215,6 +167,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 url URL of the shortcut.
+ * @param title Title of the shortcut.
+ * @param icon Image that represents the shortcut.
+ * @return Intent for the shortcut.
+ */
+ public static Intent createAddToHomeIntent(String url, String title,
+ Bitmap icon, Intent shortcutIntent) {
+ 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 shortcut.
+ * @param title Title of the shortcut.
+ * @param icon Image that represents the shortcut.
+ * @return Intent for the shortcut.
+ */
+ public static Intent createAddToHomeIntent(String url, String title, Bitmap icon) {
+ Intent shortcutIntent = createShortcutIntent(url);
+ return createAddToHomeIntent(url, title, icon, shortcutIntent);
+ }
+
+ /**
+ * Shortcut intent for icon on homescreen.
+ * @param url Url of the shortcut.
+ * @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 shortcut. If available, the touch icon
+ * will be used, else we draw our own.
+ * @param context Context used to create the intent.
+ * @param icon Image representing the shortcut.
+ * @param url URL of the shortcut.
+ * @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 shortcut.
+ * @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) {
@@ -224,8 +333,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);
}

Powered by Google App Engine
This is Rietveld 408576698