Chromium Code Reviews| 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.annotation.SuppressLint; | |
| 8 import android.app.ActivityManager; | 7 import android.app.ActivityManager; |
| 9 import android.content.Context; | 8 import android.content.Context; |
| 10 import android.content.Intent; | 9 import android.content.Intent; |
| 11 import android.content.pm.ApplicationInfo; | 10 import android.content.pm.ApplicationInfo; |
| 12 import android.content.pm.PackageInfo; | 11 import android.content.pm.PackageInfo; |
| 13 import android.content.pm.PackageManager; | 12 import android.content.pm.PackageManager; |
| 14 import android.content.pm.PackageManager.NameNotFoundException; | 13 import android.content.pm.PackageManager.NameNotFoundException; |
| 15 import android.content.pm.ResolveInfo; | |
| 16 import android.graphics.Bitmap; | 14 import android.graphics.Bitmap; |
| 17 import android.graphics.BitmapFactory; | 15 import android.graphics.BitmapFactory; |
| 18 import android.graphics.Canvas; | 16 import android.graphics.Canvas; |
| 19 import android.graphics.Color; | 17 import android.graphics.Color; |
| 20 import android.graphics.Paint; | 18 import android.graphics.Paint; |
| 21 import android.graphics.Rect; | 19 import android.graphics.Rect; |
| 22 import android.graphics.drawable.BitmapDrawable; | 20 import android.graphics.drawable.BitmapDrawable; |
| 23 import android.graphics.drawable.Drawable; | 21 import android.graphics.drawable.Drawable; |
| 24 import android.net.Uri; | 22 import android.net.Uri; |
| 25 import android.os.AsyncTask; | 23 import android.os.AsyncTask; |
| 26 import android.support.annotation.NonNull; | 24 import android.support.annotation.NonNull; |
| 27 import android.text.TextUtils; | 25 import android.text.TextUtils; |
| 28 import android.util.Base64; | 26 import android.util.Base64; |
| 29 | 27 |
| 30 import org.chromium.base.ApiCompatibilityUtils; | 28 import org.chromium.base.ApiCompatibilityUtils; |
| 31 import org.chromium.base.ContextUtils; | 29 import org.chromium.base.ContextUtils; |
| 32 import org.chromium.base.Log; | 30 import org.chromium.base.Log; |
| 33 import org.chromium.base.ThreadUtils; | 31 import org.chromium.base.ThreadUtils; |
| 34 import org.chromium.base.VisibleForTesting; | 32 import org.chromium.base.VisibleForTesting; |
| 35 import org.chromium.base.annotations.CalledByNative; | 33 import org.chromium.base.annotations.CalledByNative; |
| 36 import org.chromium.blink_public.platform.WebDisplayMode; | 34 import org.chromium.blink_public.platform.WebDisplayMode; |
| 37 import org.chromium.chrome.R; | 35 import org.chromium.chrome.R; |
| 36 import org.chromium.chrome.browser.webapps.ChromeShortcutManager; | |
| 38 import org.chromium.chrome.browser.webapps.ChromeWebApkHost; | 37 import org.chromium.chrome.browser.webapps.ChromeWebApkHost; |
| 39 import org.chromium.chrome.browser.webapps.WebApkInfo; | 38 import org.chromium.chrome.browser.webapps.WebApkInfo; |
| 40 import org.chromium.chrome.browser.webapps.WebappActivity; | 39 import org.chromium.chrome.browser.webapps.WebappActivity; |
| 41 import org.chromium.chrome.browser.webapps.WebappAuthenticator; | 40 import org.chromium.chrome.browser.webapps.WebappAuthenticator; |
| 42 import org.chromium.chrome.browser.webapps.WebappDataStorage; | 41 import org.chromium.chrome.browser.webapps.WebappDataStorage; |
| 43 import org.chromium.chrome.browser.webapps.WebappLauncherActivity; | 42 import org.chromium.chrome.browser.webapps.WebappLauncherActivity; |
| 44 import org.chromium.chrome.browser.webapps.WebappRegistry; | 43 import org.chromium.chrome.browser.webapps.WebappRegistry; |
| 45 import org.chromium.chrome.browser.widget.RoundedIconGenerator; | 44 import org.chromium.chrome.browser.widget.RoundedIconGenerator; |
| 46 import org.chromium.content_public.common.ScreenOrientationConstants; | 45 import org.chromium.content_public.common.ScreenOrientationConstants; |
| 47 import org.chromium.ui.widget.Toast; | 46 import org.chromium.ui.widget.Toast; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 | 83 |
| 85 // When a new field is added to the intent, this version should be increment ed so that it will | 84 // When a new field is added to the intent, this version should be increment ed so that it will |
| 86 // be correctly populated into the WebappRegistry/WebappDataStorage. | 85 // be correctly populated into the WebappRegistry/WebappDataStorage. |
| 87 public static final int WEBAPP_SHORTCUT_VERSION = 2; | 86 public static final int WEBAPP_SHORTCUT_VERSION = 2; |
| 88 | 87 |
| 89 // This value is equal to kInvalidOrMissingColor in the C++ content::Manifes t struct. | 88 // This value is equal to kInvalidOrMissingColor in the C++ content::Manifes t struct. |
| 90 public static final long MANIFEST_COLOR_INVALID_OR_MISSING = ((long) Integer .MAX_VALUE) + 1; | 89 public static final long MANIFEST_COLOR_INVALID_OR_MISSING = ((long) Integer .MAX_VALUE) + 1; |
| 91 | 90 |
| 92 private static final String TAG = "ShortcutHelper"; | 91 private static final String TAG = "ShortcutHelper"; |
| 93 | 92 |
| 94 // There is no public string defining this intent so if Home changes the val ue, we | |
| 95 // have to update this string. | |
| 96 private static final String INSTALL_SHORTCUT = "com.android.launcher.action. INSTALL_SHORTCUT"; | |
| 97 | |
| 98 // The activity class used for launching a WebApk. | 93 // The activity class used for launching a WebApk. |
| 99 private static final String WEBAPK_MAIN_ACTIVITY = "org.chromium.webapk.shel l_apk.MainActivity"; | 94 private static final String WEBAPK_MAIN_ACTIVITY = "org.chromium.webapk.shel l_apk.MainActivity"; |
| 100 | 95 |
| 101 // These sizes are from the Material spec for icons: | 96 // These sizes are from the Material spec for icons: |
| 102 // https://www.google.com/design/spec/style/icons.html#icons-product-icons | 97 // https://www.google.com/design/spec/style/icons.html#icons-product-icons |
| 103 private static final float MAX_INNER_SIZE_RATIO = 1.25f; | 98 private static final float MAX_INNER_SIZE_RATIO = 1.25f; |
| 104 private static final float ICON_PADDING_RATIO = 2.0f / 44.0f; | 99 private static final float ICON_PADDING_RATIO = 2.0f / 44.0f; |
| 105 private static final float ICON_CORNER_RADIUS_RATIO = 1.0f / 16.0f; | 100 private static final float ICON_CORNER_RADIUS_RATIO = 1.0f / 16.0f; |
| 106 private static final float GENERATED_ICON_PADDING_RATIO = 1.0f / 12.0f; | 101 private static final float GENERATED_ICON_PADDING_RATIO = 1.0f / 12.0f; |
| 107 private static final float GENERATED_ICON_FONT_SIZE_RATIO = 1.0f / 3.0f; | 102 private static final float GENERATED_ICON_FONT_SIZE_RATIO = 1.0f / 3.0f; |
| 108 | 103 |
| 109 /** Broadcasts Intents out Android for adding the shortcut. */ | 104 /** Request Android to add a shortcut to the home screen. */ |
| 110 public static class Delegate { | 105 public static class Delegate { |
| 111 /** | 106 /** |
| 112 * Broadcasts an intent to all interested BroadcastReceivers. | 107 * Request Android to add a shortcut to the home screen |
| 113 * @param context The Context to use. | 108 * @param title Title of the shortcut. |
| 114 * @param intent The intent to broadcast. | 109 * @param icon Image that represents the shortcut. |
| 110 * @param intent Intent to fire when the shortcut is activated. | |
| 115 */ | 111 */ |
| 116 public void sendBroadcast(Context context, Intent intent) { | 112 public void addShortcutToHomescreen(String title, Bitmap icon, Intent sh ortcutIntent) { |
| 117 context.sendBroadcast(intent); | 113 ChromeShortcutManager.getInstance().addShortcutToHomeScreen( |
| 114 title, icon, shortcutIntent); | |
| 118 } | 115 } |
| 119 | 116 |
| 120 /** | 117 /** |
| 121 * Returns the name of the fullscreen Activity to use when launching sho rtcuts. | 118 * Returns the name of the fullscreen Activity to use when launching sho rtcuts. |
| 122 */ | 119 */ |
| 123 public String getFullscreenAction() { | 120 public String getFullscreenAction() { |
| 124 return WebappLauncherActivity.ACTION_START_WEBAPP; | 121 return WebappLauncherActivity.ACTION_START_WEBAPP; |
| 125 } | 122 } |
| 126 } | 123 } |
| 127 | 124 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 158 sDelegate.getFullscreenAction(), url, nonEmptyScopeUrl, name, shortName, | 155 sDelegate.getFullscreenAction(), url, nonEmptyScopeUrl, name, shortName, |
| 159 icon, WEBAPP_SHORTCUT_VERSION, displayMode, orientation, themeColor, | 156 icon, WEBAPP_SHORTCUT_VERSION, displayMode, orientation, themeColor, |
| 160 backgroundColor, iconUrl.isEmpty()); | 157 backgroundColor, iconUrl.isEmpty()); |
| 161 shortcutIntent.putExtra(EXTRA_MAC, getEncodedMac(context, url)); | 158 shortcutIntent.putExtra(EXTRA_MAC, getEncodedMac(context, url)); |
| 162 shortcutIntent.putExtra(EXTRA_SOURCE, source); | 159 shortcutIntent.putExtra(EXTRA_SOURCE, source); |
| 163 shortcutIntent.setPackage(context.getPackageName()); | 160 shortcutIntent.setPackage(context.getPackageName()); |
| 164 return shortcutIntent; | 161 return shortcutIntent; |
| 165 } | 162 } |
| 166 @Override | 163 @Override |
| 167 protected void onPostExecute(final Intent resultIntent) { | 164 protected void onPostExecute(final Intent resultIntent) { |
| 168 Context context = ContextUtils.getApplicationContext(); | 165 sDelegate.addShortcutToHomescreen(userTitle, icon, resultIntent) ; |
| 169 sDelegate.sendBroadcast( | |
| 170 context, createAddToHomeIntent(userTitle, icon, resultIn tent)); | |
| 171 | 166 |
| 172 // Store the webapp data so that it is accessible without the in tent. Once this | 167 // Store the webapp data so that it is accessible without the in tent. Once this |
| 173 // process is complete, call back to native code to start the sp lash image | 168 // process is complete, call back to native code to start the sp lash image |
| 174 // download. | 169 // download. |
| 175 WebappRegistry.getInstance().register( | 170 WebappRegistry.getInstance().register( |
| 176 id, new WebappRegistry.FetchWebappDataStorageCallback() { | 171 id, new WebappRegistry.FetchWebappDataStorageCallback() { |
| 177 @Override | 172 @Override |
| 178 public void onWebappDataStorageRetrieved(WebappDataS torage storage) { | 173 public void onWebappDataStorageRetrieved(WebappDataS torage storage) { |
| 179 storage.updateFromShortcutIntent(resultIntent); | 174 storage.updateFromShortcutIntent(resultIntent); |
| 180 nativeOnWebappDataStored(callbackPointer); | 175 nativeOnWebappDataStored(callbackPointer); |
| 181 } | 176 } |
| 182 }); | 177 }); |
| 183 | 178 if (ChromeShortcutManager.getInstance().shouldShowAddedToHomescr eenToast()) { |
| 184 showAddedToHomescreenToast(userTitle); | 179 showAddedToHomescreenToast(userTitle); |
| 180 } | |
| 185 } | 181 } |
| 186 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | 182 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
| 187 } | 183 } |
| 188 | 184 |
| 189 public static void addWebApkShortcut(Context context, String packageName) { | 185 public static void addWebApkShortcut(Context context, String packageName) { |
| 190 PackageManager pm = context.getPackageManager(); | 186 PackageManager pm = context.getPackageManager(); |
| 191 try { | 187 try { |
| 192 ApplicationInfo appInfo = pm.getApplicationInfo( | 188 ApplicationInfo appInfo = pm.getApplicationInfo( |
| 193 packageName, PackageManager.GET_META_DATA); | 189 packageName, PackageManager.GET_META_DATA); |
| 194 String shortcutTitle = pm.getApplicationLabel(appInfo).toString(); | 190 String shortcutTitle = pm.getApplicationLabel(appInfo).toString(); |
| 195 Bitmap shortcutIcon = ((BitmapDrawable) pm.getApplicationIcon(packag eName)).getBitmap(); | 191 Bitmap shortcutIcon = ((BitmapDrawable) pm.getApplicationIcon(packag eName)).getBitmap(); |
| 196 | 192 |
| 197 Bitmap bitmap = createHomeScreenIconFromWebIcon(shortcutIcon); | 193 Bitmap bitmap = createHomeScreenIconFromWebIcon(shortcutIcon); |
| 198 Intent i = new Intent(); | 194 Intent i = new Intent(); |
| 199 i.setClassName(packageName, WEBAPK_MAIN_ACTIVITY); | 195 i.setClassName(packageName, WEBAPK_MAIN_ACTIVITY); |
| 200 i.addCategory(Intent.CATEGORY_LAUNCHER); | 196 i.addCategory(Intent.CATEGORY_LAUNCHER); |
|
pkotwicz
2017/02/14 16:25:56
Should we call addShortcutToHomescreen() here?
Marti Wong
2017/02/15 02:36:55
Thanks for the comment!
Actually, WebAPK people wi
pkotwicz
2017/02/15 22:11:00
- We will be removing this code path in M59 not M5
Marti Wong
2017/02/17 05:10:48
Got it. Thanks for the advice.
I will do this in
pkotwicz
2017/02/17 22:26:36
LGTM as long as you do this in follow up CL
| |
| 201 context.sendBroadcast(createAddToHomeIntent(shortcutTitle, bitmap, i )); | 197 context.sendBroadcast( |
| 198 ChromeShortcutManager.createAddToHomeIntent(shortcutTitle, b itmap, i)); | |
| 202 } catch (NameNotFoundException e) { | 199 } catch (NameNotFoundException e) { |
| 203 e.printStackTrace(); | 200 e.printStackTrace(); |
| 204 } | 201 } |
| 205 } | 202 } |
| 206 | 203 |
| 207 /** | 204 /** |
| 208 * Adds home screen shortcut which opens in the browser Activity. | 205 * Adds home screen shortcut which opens in the browser Activity. |
| 209 */ | 206 */ |
| 210 @SuppressWarnings("unused") | 207 @SuppressWarnings("unused") |
| 211 @CalledByNative | 208 @CalledByNative |
| 212 private static void addShortcut(String url, String userTitle, Bitmap icon, i nt source) { | 209 private static void addShortcut( |
| 210 String id, String url, String userTitle, Bitmap icon, int source) { | |
| 213 Context context = ContextUtils.getApplicationContext(); | 211 Context context = ContextUtils.getApplicationContext(); |
| 214 final Intent shortcutIntent = createShortcutIntent(url); | 212 final Intent shortcutIntent = createShortcutIntent(url); |
| 213 shortcutIntent.putExtra(EXTRA_ID, id); | |
| 215 shortcutIntent.putExtra(EXTRA_SOURCE, source); | 214 shortcutIntent.putExtra(EXTRA_SOURCE, source); |
| 216 shortcutIntent.setPackage(context.getPackageName()); | 215 shortcutIntent.setPackage(context.getPackageName()); |
| 217 sDelegate.sendBroadcast( | 216 sDelegate.addShortcutToHomescreen(userTitle, icon, shortcutIntent); |
| 218 context, createAddToHomeIntent(userTitle, icon, shortcutIntent)) ; | 217 if (ChromeShortcutManager.getInstance().shouldShowAddedToHomescreenToast ()) { |
| 219 showAddedToHomescreenToast(userTitle); | 218 showAddedToHomescreenToast(userTitle); |
| 219 } | |
| 220 } | 220 } |
| 221 | 221 |
| 222 /** | 222 /** |
| 223 * Show toast to alert user that the shortcut was added to the home screen. | 223 * Show toast to alert user that the shortcut was added to the home screen. |
| 224 */ | 224 */ |
| 225 private static void showAddedToHomescreenToast(final String title) { | 225 private static void showAddedToHomescreenToast(final String title) { |
| 226 Context applicationContext = ContextUtils.getApplicationContext(); | 226 Context applicationContext = ContextUtils.getApplicationContext(); |
| 227 String toastText = applicationContext.getString(R.string.added_to_homesc reen, title); | 227 String toastText = applicationContext.getString(R.string.added_to_homesc reen, title); |
| 228 showToast(toastText); | 228 showToast(toastText); |
| 229 } | 229 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 | 266 |
| 267 @Override | 267 @Override |
| 268 protected void onPostExecute(String encodedImage) { | 268 protected void onPostExecute(String encodedImage) { |
| 269 storage.updateSplashScreenImage(encodedImage); | 269 storage.updateSplashScreenImage(encodedImage); |
| 270 } | 270 } |
| 271 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | 271 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
| 272 } | 272 } |
| 273 } | 273 } |
| 274 | 274 |
| 275 /** | 275 /** |
| 276 * Creates an intent that will add a shortcut to the home screen. | |
| 277 * @param title Title of the shortcut. | |
| 278 * @param icon Image that represents the shortcut. | |
| 279 * @param shortcutIntent Intent to fire when the shortcut is activated. | |
| 280 * @return Intent for the shortcut. | |
| 281 */ | |
| 282 public static Intent createAddToHomeIntent(String title, Bitmap icon, | |
| 283 Intent shortcutIntent) { | |
| 284 Intent i = new Intent(INSTALL_SHORTCUT); | |
| 285 i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); | |
| 286 i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title); | |
| 287 i.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon); | |
| 288 return i; | |
| 289 } | |
| 290 | |
| 291 /** | |
| 292 * Creates a shortcut to launch a web app on the home screen. | 276 * Creates a shortcut to launch a web app on the home screen. |
| 293 * @param id Id of the web app. | 277 * @param id Id of the web app. |
| 294 * @param action Intent action to open a full screen activity. | 278 * @param action Intent action to open a full screen activity. |
| 295 * @param url Url of the web app. | 279 * @param url Url of the web app. |
| 296 * @param scope Url scope of the web app. | 280 * @param scope Url scope of the web app. |
| 297 * @param name Name of the web app. | 281 * @param name Name of the web app. |
| 298 * @param shortName Short name of the web app. | 282 * @param shortName Short name of the web app. |
| 299 * @param icon Icon of the web app. | 283 * @param icon Icon of the web app. |
| 300 * @param version Version number of the shortcut. | 284 * @param version Version number of the shortcut. |
| 301 * @param displayMode Display mode of the web app. | 285 * @param displayMode Display mode of the web app. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 354 Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); | 338 Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); |
| 355 shortcutIntent.putExtra(REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true); | 339 shortcutIntent.putExtra(REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true); |
| 356 return shortcutIntent; | 340 return shortcutIntent; |
| 357 } | 341 } |
| 358 | 342 |
| 359 /** | 343 /** |
| 360 * Utility method to check if a shortcut can be added to the home screen. | 344 * Utility method to check if a shortcut can be added to the home screen. |
| 361 * @param context Context used to get the package manager. | 345 * @param context Context used to get the package manager. |
| 362 * @return if a shortcut can be added to the home screen under the current p rofile. | 346 * @return if a shortcut can be added to the home screen under the current p rofile. |
| 363 */ | 347 */ |
| 364 // TODO(crbug.com/635567): Fix this properly. | |
| 365 @SuppressLint("WrongConstant") | |
| 366 public static boolean isAddToHomeIntentSupported(Context context) { | 348 public static boolean isAddToHomeIntentSupported(Context context) { |
| 367 PackageManager pm = context.getPackageManager(); | 349 return ChromeShortcutManager.getInstance().canAddShortcutToHomescreen(); |
| 368 Intent i = new Intent(INSTALL_SHORTCUT); | |
| 369 List<ResolveInfo> receivers = pm.queryBroadcastReceivers( | |
| 370 i, PackageManager.GET_INTENT_FILTERS); | |
| 371 return !receivers.isEmpty(); | |
| 372 } | 350 } |
| 373 | 351 |
| 374 /** | 352 /** |
| 375 * Returns whether the given icon matches the size requirements to be used o n the home screen. | 353 * Returns whether the given icon matches the size requirements to be used o n the home screen. |
| 376 * @param width Icon width, in pixels. | 354 * @param width Icon width, in pixels. |
| 377 * @param height Icon height, in pixels. | 355 * @param height Icon height, in pixels. |
| 378 * @return whether the given icon matches the size requirements to be used o n the home screen. | 356 * @return whether the given icon matches the size requirements to be used o n the home screen. |
| 379 */ | 357 */ |
| 380 @CalledByNative | 358 @CalledByNative |
| 381 public static boolean isIconLargeEnoughForLauncher(int width, int height) { | 359 public static boolean isIconLargeEnoughForLauncher(int width, int height) { |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 700 for (int i = 0; i < list.size(); i++) { | 678 for (int i = 0; i < list.size(); i++) { |
| 701 array[i] = list.get(i); | 679 array[i] = list.get(i); |
| 702 } | 680 } |
| 703 return array; | 681 return array; |
| 704 } | 682 } |
| 705 | 683 |
| 706 private static native void nativeOnWebappDataStored(long callbackPointer); | 684 private static native void nativeOnWebappDataStored(long callbackPointer); |
| 707 private static native void nativeOnWebApksRetrieved(long callbackPointer, St ring[] shortNames, | 685 private static native void nativeOnWebApksRetrieved(long callbackPointer, St ring[] shortNames, |
| 708 String[] packageName, int[] shellApkVersions, int[] versionCodes); | 686 String[] packageName, int[] shellApkVersions, int[] versionCodes); |
| 709 } | 687 } |
| OLD | NEW |