| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser; | 5 package org.chromium.chrome.browser; |
| 6 | 6 |
| 7 import android.app.ActivityManager; | 7 import android.app.ActivityManager; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.Intent; | 9 import android.content.Intent; |
| 10 import android.content.pm.PackageManager; | 10 import android.content.pm.PackageManager; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 import android.graphics.RectF; | 21 import android.graphics.RectF; |
| 22 import android.graphics.drawable.BitmapDrawable; | 22 import android.graphics.drawable.BitmapDrawable; |
| 23 import android.graphics.drawable.Drawable; | 23 import android.graphics.drawable.Drawable; |
| 24 import android.net.Uri; | 24 import android.net.Uri; |
| 25 import android.os.Handler; | 25 import android.os.Handler; |
| 26 import android.os.Looper; | 26 import android.os.Looper; |
| 27 import android.text.TextUtils; | 27 import android.text.TextUtils; |
| 28 import android.util.Base64; | 28 import android.util.Base64; |
| 29 | 29 |
| 30 import org.chromium.base.ApiCompatibilityUtils; | 30 import org.chromium.base.ApiCompatibilityUtils; |
| 31 import org.chromium.base.CommandLine; |
| 31 import org.chromium.base.ContextUtils; | 32 import org.chromium.base.ContextUtils; |
| 32 import org.chromium.base.Log; | 33 import org.chromium.base.Log; |
| 33 import org.chromium.base.ThreadUtils; | 34 import org.chromium.base.ThreadUtils; |
| 34 import org.chromium.base.VisibleForTesting; | 35 import org.chromium.base.VisibleForTesting; |
| 35 import org.chromium.base.annotations.CalledByNative; | 36 import org.chromium.base.annotations.CalledByNative; |
| 36 import org.chromium.blink_public.platform.WebDisplayMode; | 37 import org.chromium.blink_public.platform.WebDisplayMode; |
| 37 import org.chromium.chrome.R; | 38 import org.chromium.chrome.R; |
| 39 import org.chromium.chrome.browser.webapps.WebApkBuilder; |
| 38 import org.chromium.chrome.browser.webapps.WebappAuthenticator; | 40 import org.chromium.chrome.browser.webapps.WebappAuthenticator; |
| 39 import org.chromium.chrome.browser.webapps.WebappDataStorage; | 41 import org.chromium.chrome.browser.webapps.WebappDataStorage; |
| 40 import org.chromium.chrome.browser.webapps.WebappLauncherActivity; | 42 import org.chromium.chrome.browser.webapps.WebappLauncherActivity; |
| 41 import org.chromium.chrome.browser.webapps.WebappRegistry; | 43 import org.chromium.chrome.browser.webapps.WebappRegistry; |
| 42 import org.chromium.chrome.browser.widget.RoundedIconGenerator; | 44 import org.chromium.chrome.browser.widget.RoundedIconGenerator; |
| 43 import org.chromium.content_public.common.ScreenOrientationConstants; | 45 import org.chromium.content_public.common.ScreenOrientationConstants; |
| 46 import org.chromium.net.GURLUtils; |
| 44 import org.chromium.ui.widget.Toast; | 47 import org.chromium.ui.widget.Toast; |
| 45 | 48 |
| 46 import java.io.ByteArrayOutputStream; | 49 import java.io.ByteArrayOutputStream; |
| 47 import java.util.List; | 50 import java.util.List; |
| 48 | 51 |
| 49 /** | 52 /** |
| 50 * This class contains functions related to adding shortcuts to the Android Home | 53 * This class contains functions related to adding shortcuts to the Android Home |
| 51 * screen. These shortcuts are used to either open a page in the main browser | 54 * screen. These shortcuts are used to either open a page in the main browser |
| 52 * or open a web app. | 55 * or open a web app. |
| 53 */ | 56 */ |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 /** | 133 /** |
| 131 * Called when we have to fire an Intent to add a shortcut to the home scree
n. | 134 * Called when we have to fire an Intent to add a shortcut to the home scree
n. |
| 132 * If the webpage indicated that it was capable of functioning as a webapp,
it is added as a | 135 * If the webpage indicated that it was capable of functioning as a webapp,
it is added as a |
| 133 * shortcut to a webapp Activity rather than as a general bookmark. User is
sent to the | 136 * shortcut to a webapp Activity rather than as a general bookmark. User is
sent to the |
| 134 * home screen as soon as the shortcut is created. | 137 * home screen as soon as the shortcut is created. |
| 135 * | 138 * |
| 136 * This method must not be called on the UI thread. | 139 * This method must not be called on the UI thread. |
| 137 */ | 140 */ |
| 138 @SuppressWarnings("unused") | 141 @SuppressWarnings("unused") |
| 139 @CalledByNative | 142 @CalledByNative |
| 140 private static void addShortcut(Context context, String id, String url, fina
l String userTitle, | 143 private static void addShortcut(String id, String url, final String userTitl
e, |
| 141 String name, String shortName, Bitmap icon, int displayMode, int ori
entation, | 144 String name, String shortName, Bitmap icon, int displayMode, int ori
entation, |
| 142 int source, long themeColor, long backgroundColor, boolean isIconGen
erated, | 145 int source, long themeColor, long backgroundColor, boolean isIconGen
erated, |
| 143 final long callbackPointer) { | 146 final long callbackPointer) { |
| 144 assert !ThreadUtils.runningOnUiThread(); | 147 assert !ThreadUtils.runningOnUiThread(); |
| 148 |
| 149 Context context = ContextUtils.getApplicationContext(); |
| 145 final Intent shortcutIntent; | 150 final Intent shortcutIntent; |
| 146 boolean isWebappCapable = (displayMode == WebDisplayMode.Standalone | 151 boolean isWebappCapable = (displayMode == WebDisplayMode.Standalone |
| 147 || displayMode == WebDisplayMode.Fullscreen); | 152 || displayMode == WebDisplayMode.Fullscreen); |
| 148 if (isWebappCapable) { | 153 if (isWebappCapable) { |
| 154 if (CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_WEBAPK
)) { |
| 155 WebApkBuilder apkBuilder = ((ChromeApplication) context).createW
ebApkBuilder(); |
| 156 if (apkBuilder != null) { |
| 157 apkBuilder.buildWebApkAsync(url, GURLUtils.getOrigin(url), s
hortName, icon); |
| 158 return; |
| 159 } |
| 160 } |
| 149 shortcutIntent = createWebappShortcutIntent(id, sDelegate.getFullscr
eenAction(), url, | 161 shortcutIntent = createWebappShortcutIntent(id, sDelegate.getFullscr
eenAction(), url, |
| 150 getScopeFromUrl(url), name, shortName, icon, WEBAPP_SHORTCUT
_VERSION, | 162 getScopeFromUrl(url), name, shortName, icon, WEBAPP_SHORTCUT
_VERSION, |
| 151 displayMode, orientation, themeColor, backgroundColor, isIco
nGenerated); | 163 displayMode, orientation, themeColor, backgroundColor, isIco
nGenerated); |
| 152 shortcutIntent.putExtra(EXTRA_MAC, getEncodedMac(context, url)); | 164 shortcutIntent.putExtra(EXTRA_MAC, getEncodedMac(context, url)); |
| 153 } else { | 165 } else { |
| 154 // Add the shortcut as a launcher icon to open in the browser Activi
ty. | 166 // Add the shortcut as a launcher icon to open in the browser Activi
ty. |
| 155 shortcutIntent = createShortcutIntent(url); | 167 shortcutIntent = createShortcutIntent(url); |
| 156 } | 168 } |
| 157 | 169 |
| 158 // Always attach a source (one of add to home screen menu item, app bann
er, or unknown) to | 170 // Always attach a source (one of add to home screen menu item, app bann
er, or unknown) to |
| (...skipping 26 matching lines...) Expand all Loading... |
| 185 String toastText = | 197 String toastText = |
| 186 applicationContext.getString(R.string.added_to_homescree
n, userTitle); | 198 applicationContext.getString(R.string.added_to_homescree
n, userTitle); |
| 187 Toast toast = Toast.makeText(applicationContext, toastText, Toas
t.LENGTH_SHORT); | 199 Toast toast = Toast.makeText(applicationContext, toastText, Toas
t.LENGTH_SHORT); |
| 188 toast.show(); | 200 toast.show(); |
| 189 } | 201 } |
| 190 }); | 202 }); |
| 191 } | 203 } |
| 192 | 204 |
| 193 /** | 205 /** |
| 194 * Creates a storage location and stores the data for a web app using {@link
WebappDataStorage}. | 206 * Creates a storage location and stores the data for a web app using {@link
WebappDataStorage}. |
| 195 * @param context Context to open the WebappDataStorage with. | |
| 196 * @param id ID of the webapp which is storing data. | 207 * @param id ID of the webapp which is storing data. |
| 197 * @param splashImage Image which should be displayed on the splash screen o
f | 208 * @param splashImage Image which should be displayed on the splash screen o
f |
| 198 * the webapp. This can be null of there is no image to s
how. | 209 * the webapp. This can be null of there is no image to s
how. |
| 199 */ | 210 */ |
| 200 @SuppressWarnings("unused") | 211 @SuppressWarnings("unused") |
| 201 @CalledByNative | 212 @CalledByNative |
| 202 private static void storeWebappSplashImage(final Context context, final Stri
ng id, | 213 private static void storeWebappSplashImage(final String id, final Bitmap spl
ashImage) { |
| 203 final Bitmap splashImage) { | 214 WebappRegistry.getWebappDataStorage(ContextUtils.getApplicationContext()
, id, |
| 204 WebappRegistry.getWebappDataStorage(context, id, | |
| 205 new WebappRegistry.FetchWebappDataStorageCallback() { | 215 new WebappRegistry.FetchWebappDataStorageCallback() { |
| 206 @Override | 216 @Override |
| 207 public void onWebappDataStorageRetrieved(WebappDataStorage s
torage) { | 217 public void onWebappDataStorageRetrieved(WebappDataStorage s
torage) { |
| 208 if (storage == null) return; | 218 if (storage == null) return; |
| 209 | 219 |
| 210 storage.updateSplashScreenImage(splashImage); | 220 storage.updateSplashScreenImage(splashImage); |
| 211 } | 221 } |
| 212 | 222 |
| 213 } | 223 }); |
| 214 ); | |
| 215 } | 224 } |
| 216 | 225 |
| 217 /** | 226 /** |
| 218 * Creates an intent that will add a shortcut to the home screen. | 227 * Creates an intent that will add a shortcut to the home screen. |
| 219 * @param shortcutIntent Intent to fire when the shortcut is activated. | 228 * @param shortcutIntent Intent to fire when the shortcut is activated. |
| 220 * @param url URL of the shortcut. | 229 * @param url URL of the shortcut. |
| 221 * @param title Title of the shortcut. | 230 * @param title Title of the shortcut. |
| 222 * @param icon Image that represents the shortcut. | 231 * @param icon Image that represents the shortcut. |
| 223 * @return Intent for the shortcut. | 232 * @return Intent for the shortcut. |
| 224 */ | 233 */ |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 public static boolean isAddToHomeIntentSupported(Context context) { | 312 public static boolean isAddToHomeIntentSupported(Context context) { |
| 304 PackageManager pm = context.getPackageManager(); | 313 PackageManager pm = context.getPackageManager(); |
| 305 Intent i = new Intent(INSTALL_SHORTCUT); | 314 Intent i = new Intent(INSTALL_SHORTCUT); |
| 306 List<ResolveInfo> receivers = pm.queryBroadcastReceivers( | 315 List<ResolveInfo> receivers = pm.queryBroadcastReceivers( |
| 307 i, PackageManager.GET_INTENT_FILTERS); | 316 i, PackageManager.GET_INTENT_FILTERS); |
| 308 return !receivers.isEmpty(); | 317 return !receivers.isEmpty(); |
| 309 } | 318 } |
| 310 | 319 |
| 311 /** | 320 /** |
| 312 * Returns whether the given icon matches the size requirements to be used o
n the home screen. | 321 * Returns whether the given icon matches the size requirements to be used o
n the home screen. |
| 313 * @param context Context used to create the intent. | |
| 314 * @param width Icon width, in pixels. | 322 * @param width Icon width, in pixels. |
| 315 * @param height Icon height, in pixels. | 323 * @param height Icon height, in pixels. |
| 316 * @return whether the given icon matches the size requirements to be used o
n the home screen. | 324 * @return whether the given icon matches the size requirements to be used o
n the home screen. |
| 317 */ | 325 */ |
| 318 @CalledByNative | 326 @CalledByNative |
| 319 public static boolean isIconLargeEnoughForLauncher(Context context, int widt
h, int height) { | 327 public static boolean isIconLargeEnoughForLauncher(int width, int height) { |
| 328 Context context = ContextUtils.getApplicationContext(); |
| 320 ActivityManager am = (ActivityManager) context.getSystemService(Context.
ACTIVITY_SERVICE); | 329 ActivityManager am = (ActivityManager) context.getSystemService(Context.
ACTIVITY_SERVICE); |
| 321 final int minimalSize = am.getLauncherLargeIconSize() / 2; | 330 final int minimalSize = am.getLauncherLargeIconSize() / 2; |
| 322 return width >= minimalSize && height >= minimalSize; | 331 return width >= minimalSize && height >= minimalSize; |
| 323 } | 332 } |
| 324 | 333 |
| 325 /** | 334 /** |
| 326 * Adapts a website's icon (e.g. favicon or touch icon) to the Material desi
gn style guidelines | 335 * Adapts a website's icon (e.g. favicon or touch icon) to the Material desi
gn style guidelines |
| 327 * for home screen icons. This involves adding some padding and rounding the
corners. | 336 * for home screen icons. This involves adding some padding and rounding the
corners. |
| 328 * | 337 * |
| 329 * @param context Context used to create the intent. | 338 * @param context Context used to create the intent. |
| 330 * @param webIcon The website's favicon or touch icon. | 339 * @param webIcon The website's favicon or touch icon. |
| 331 * @return Bitmap Either the touch-icon or the newly created favicon. | 340 * @return Bitmap Either the touch-icon or the newly created favicon. |
| 332 */ | 341 */ |
| 333 @CalledByNative | 342 @CalledByNative |
| 334 public static Bitmap createHomeScreenIconFromWebIcon(Context context, Bitmap
webIcon) { | 343 public static Bitmap createHomeScreenIconFromWebIcon(Bitmap webIcon) { |
| 335 // getLauncherLargeIconSize() is just a guess at the launcher icon size,
and is often | 344 // getLauncherLargeIconSize() is just a guess at the launcher icon size,
and is often |
| 336 // wrong -- the launcher can show icons at any size it pleases. Instead
of resizing the | 345 // wrong -- the launcher can show icons at any size it pleases. Instead
of resizing the |
| 337 // icon to the supposed launcher size and then having the launcher resiz
e the icon again, | 346 // icon to the supposed launcher size and then having the launcher resiz
e the icon again, |
| 338 // just leave the icon at its original size and let the launcher do a si
ngle rescaling. | 347 // just leave the icon at its original size and let the launcher do a si
ngle rescaling. |
| 339 // Unless the icon is much too big; then scale it down here too. | 348 // Unless the icon is much too big; then scale it down here too. |
| 349 Context context = ContextUtils.getApplicationContext(); |
| 340 ActivityManager am = (ActivityManager) context.getSystemService(Context.
ACTIVITY_SERVICE); | 350 ActivityManager am = (ActivityManager) context.getSystemService(Context.
ACTIVITY_SERVICE); |
| 341 int maxInnerSize = Math.round(am.getLauncherLargeIconSize() * MAX_INNER_
SIZE_RATIO); | 351 int maxInnerSize = Math.round(am.getLauncherLargeIconSize() * MAX_INNER_
SIZE_RATIO); |
| 342 int innerSize = Math.min(maxInnerSize, Math.max(webIcon.getWidth(), webI
con.getHeight())); | 352 int innerSize = Math.min(maxInnerSize, Math.max(webIcon.getWidth(), webI
con.getHeight())); |
| 343 int padding = Math.round(ICON_PADDING_RATIO * innerSize); | 353 int padding = Math.round(ICON_PADDING_RATIO * innerSize); |
| 344 int outerSize = innerSize + 2 * padding; | 354 int outerSize = innerSize + 2 * padding; |
| 345 | 355 |
| 346 Bitmap bitmap = null; | 356 Bitmap bitmap = null; |
| 347 try { | 357 try { |
| 348 bitmap = Bitmap.createBitmap(outerSize, outerSize, Bitmap.Config.ARG
B_8888); | 358 bitmap = Bitmap.createBitmap(outerSize, outerSize, Bitmap.Config.ARG
B_8888); |
| 349 } catch (OutOfMemoryError e) { | 359 } catch (OutOfMemoryError e) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 367 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); | 377 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); |
| 368 canvas.drawPath(path, paint); | 378 canvas.drawPath(path, paint); |
| 369 | 379 |
| 370 return bitmap; | 380 return bitmap; |
| 371 } | 381 } |
| 372 | 382 |
| 373 /** | 383 /** |
| 374 * Generates a generic icon to be used in the launcher. This is just a round
ed rectangle with | 384 * Generates a generic icon to be used in the launcher. This is just a round
ed rectangle with |
| 375 * a letter in the middle taken from the website's domain name. | 385 * a letter in the middle taken from the website's domain name. |
| 376 * | 386 * |
| 377 * @param context Context used to create the intent. | |
| 378 * @param url URL of the shortcut. | 387 * @param url URL of the shortcut. |
| 379 * @param red Red component of the dominant icon color. | 388 * @param red Red component of the dominant icon color. |
| 380 * @param green Green component of the dominant icon color. | 389 * @param green Green component of the dominant icon color. |
| 381 * @param blue Blue component of the dominant icon color. | 390 * @param blue Blue component of the dominant icon color. |
| 382 * @return Bitmap Either the touch-icon or the newly created favicon. | 391 * @return Bitmap Either the touch-icon or the newly created favicon. |
| 383 */ | 392 */ |
| 384 @CalledByNative | 393 @CalledByNative |
| 385 public static Bitmap generateHomeScreenIcon(Context context, String url, int
red, int green, | 394 public static Bitmap generateHomeScreenIcon(String url, int red, int green, |
| 386 int blue) { | 395 int blue) { |
| 396 Context context = ContextUtils.getApplicationContext(); |
| 387 ActivityManager am = (ActivityManager) context.getSystemService(Context.
ACTIVITY_SERVICE); | 397 ActivityManager am = (ActivityManager) context.getSystemService(Context.
ACTIVITY_SERVICE); |
| 388 final int outerSize = am.getLauncherLargeIconSize(); | 398 final int outerSize = am.getLauncherLargeIconSize(); |
| 389 final int iconDensity = am.getLauncherLargeIconDensity(); | 399 final int iconDensity = am.getLauncherLargeIconDensity(); |
| 390 | 400 |
| 391 Bitmap bitmap = null; | 401 Bitmap bitmap = null; |
| 392 try { | 402 try { |
| 393 bitmap = Bitmap.createBitmap(outerSize, outerSize, Bitmap.Config.ARG
B_8888); | 403 bitmap = Bitmap.createBitmap(outerSize, outerSize, Bitmap.Config.ARG
B_8888); |
| 394 } catch (OutOfMemoryError e) { | 404 } catch (OutOfMemoryError e) { |
| 395 Log.w(TAG, "OutOfMemoryError while trying to draw bitmap on canvas."
); | 405 Log.w(TAG, "OutOfMemoryError while trying to draw bitmap on canvas."
); |
| 396 return null; | 406 return null; |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 builder.fragment(""); | 538 builder.fragment(""); |
| 529 builder.query(""); | 539 builder.query(""); |
| 530 return builder.build().toString(); | 540 return builder.build().toString(); |
| 531 } | 541 } |
| 532 | 542 |
| 533 /** | 543 /** |
| 534 * Returns an array of sizes which describe the ideal size and minimum size
of the Home screen | 544 * Returns an array of sizes which describe the ideal size and minimum size
of the Home screen |
| 535 * icon and the ideal and minimum sizes of the splash screen image in that o
rder. | 545 * icon and the ideal and minimum sizes of the splash screen image in that o
rder. |
| 536 */ | 546 */ |
| 537 @CalledByNative | 547 @CalledByNative |
| 538 private static int[] getHomeScreenIconAndSplashImageSizes(Context context) { | 548 private static int[] getHomeScreenIconAndSplashImageSizes() { |
| 549 Context context = ContextUtils.getApplicationContext(); |
| 539 // This ordering must be kept up to date with the C++ ShortcutHelper. | 550 // This ordering must be kept up to date with the C++ ShortcutHelper. |
| 540 return new int[] { | 551 return new int[] { |
| 541 getIdealHomescreenIconSizeInDp(context), | 552 getIdealHomescreenIconSizeInDp(context), |
| 542 getMinimumHomescreenIconSizeInDp(context), | 553 getMinimumHomescreenIconSizeInDp(context), |
| 543 getIdealSplashImageSizeInDp(context), | 554 getIdealSplashImageSizeInDp(context), |
| 544 getMinimumSplashImageSizeInDp(context) | 555 getMinimumSplashImageSizeInDp(context) |
| 545 }; | 556 }; |
| 546 } | 557 } |
| 547 | 558 |
| 548 private static int getIdealSizeFromResourceInDp(Context context, int resourc
e) { | 559 private static int getIdealSizeFromResourceInDp(Context context, int resourc
e) { |
| 549 float sizeInPx = context.getResources().getDimension(resource); | 560 float sizeInPx = context.getResources().getDimension(resource); |
| 550 float density = context.getResources().getDisplayMetrics().density; | 561 float density = context.getResources().getDisplayMetrics().density; |
| 551 return Math.round(sizeInPx / density); | 562 return Math.round(sizeInPx / density); |
| 552 } | 563 } |
| 553 | 564 |
| 554 private static Bitmap getBitmapFromResourceId(Context context, int id, int d
ensity) { | 565 private static Bitmap getBitmapFromResourceId(Context context, int id, int d
ensity) { |
| 555 Drawable drawable = ApiCompatibilityUtils.getDrawableForDensity( | 566 Drawable drawable = ApiCompatibilityUtils.getDrawableForDensity( |
| 556 context.getResources(), id, density); | 567 context.getResources(), id, density); |
| 557 | 568 |
| 558 if (drawable instanceof BitmapDrawable) { | 569 if (drawable instanceof BitmapDrawable) { |
| 559 BitmapDrawable bd = (BitmapDrawable) drawable; | 570 BitmapDrawable bd = (BitmapDrawable) drawable; |
| 560 return bd.getBitmap(); | 571 return bd.getBitmap(); |
| 561 } | 572 } |
| 562 assert false : "The drawable was not a bitmap drawable as expected"; | 573 assert false : "The drawable was not a bitmap drawable as expected"; |
| 563 return null; | 574 return null; |
| 564 } | 575 } |
| 565 | 576 |
| 566 private static native void nativeOnWebappDataStored(long callbackPointer); | 577 private static native void nativeOnWebappDataStored(long callbackPointer); |
| 567 } | 578 } |
| OLD | NEW |