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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 public static final String EXTRA_WEBAPK_PACKAGE_NAME = | 81 public static final String EXTRA_WEBAPK_PACKAGE_NAME = |
83 "org.chromium.chrome.browser.webapk_package_name"; | 82 "org.chromium.chrome.browser.webapk_package_name"; |
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"; | |
93 | |
94 // There is no public string defining this intent so if Home changes the val ue, we | 91 // There is no public string defining this intent so if Home changes the val ue, we |
95 // have to update this string. | 92 // have to update this string. |
96 private static final String INSTALL_SHORTCUT = "com.android.launcher.action. INSTALL_SHORTCUT"; | 93 public static final String INSTALL_SHORTCUT = "com.android.launcher.action.I NSTALL_SHORTCUT"; |
94 | |
95 private static final String TAG = "ShortcutHelper"; | |
dominickn
2017/02/13 05:18:02
You moved this TAG - perhaps put it back again?
Marti Wong
2017/02/14 02:42:47
This TAG is moved to ChromeShortcutManager
| |
97 | 96 |
98 // The activity class used for launching a WebApk. | 97 // The activity class used for launching a WebApk. |
99 private static final String WEBAPK_MAIN_ACTIVITY = "org.chromium.webapk.shel l_apk.MainActivity"; | 98 private static final String WEBAPK_MAIN_ACTIVITY = "org.chromium.webapk.shel l_apk.MainActivity"; |
100 | 99 |
101 // These sizes are from the Material spec for icons: | 100 // These sizes are from the Material spec for icons: |
102 // https://www.google.com/design/spec/style/icons.html#icons-product-icons | 101 // https://www.google.com/design/spec/style/icons.html#icons-product-icons |
103 private static final float MAX_INNER_SIZE_RATIO = 1.25f; | 102 private static final float MAX_INNER_SIZE_RATIO = 1.25f; |
104 private static final float ICON_PADDING_RATIO = 2.0f / 44.0f; | 103 private static final float ICON_PADDING_RATIO = 2.0f / 44.0f; |
105 private static final float ICON_CORNER_RADIUS_RATIO = 1.0f / 16.0f; | 104 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; | 105 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; | 106 private static final float GENERATED_ICON_FONT_SIZE_RATIO = 1.0f / 3.0f; |
108 | 107 |
109 /** Broadcasts Intents out Android for adding the shortcut. */ | 108 /** Broadcasts Intents out Android for adding the shortcut. */ |
110 public static class Delegate { | 109 public static class Delegate { |
dominickn
2017/02/13 05:18:02
This isn't feasible right now (this comment is for
Marti Wong
2017/02/14 02:42:47
Thanks for the advice~!
| |
111 /** | 110 /** |
112 * Broadcasts an intent to all interested BroadcastReceivers. | 111 * Broadcasts an intent to all interested BroadcastReceivers. |
113 * @param context The Context to use. | 112 * @param context The Context to use. |
114 * @param intent The intent to broadcast. | 113 * @param intent The intent to broadcast. |
115 */ | 114 */ |
116 public void sendBroadcast(Context context, Intent intent) { | 115 public void requestPinShortcut(final Context context, final Intent inten t) { |
dominickn
2017/02/13 05:18:02
Perhaps call this method addShortcutToHomescreen?
Marti Wong
2017/02/14 02:42:47
Done.
| |
117 context.sendBroadcast(intent); | 116 ChromeShortcutManager.getInstance(context).addShortcutToHomeScreen(c ontext, intent); |
118 } | 117 } |
119 | 118 |
120 /** | 119 /** |
121 * Returns the name of the fullscreen Activity to use when launching sho rtcuts. | 120 * Returns the name of the fullscreen Activity to use when launching sho rtcuts. |
122 */ | 121 */ |
123 public String getFullscreenAction() { | 122 public String getFullscreenAction() { |
124 return WebappLauncherActivity.ACTION_START_WEBAPP; | 123 return WebappLauncherActivity.ACTION_START_WEBAPP; |
125 } | 124 } |
126 } | 125 } |
127 | 126 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
159 icon, WEBAPP_SHORTCUT_VERSION, displayMode, orientation, themeColor, | 158 icon, WEBAPP_SHORTCUT_VERSION, displayMode, orientation, themeColor, |
160 backgroundColor, iconUrl.isEmpty()); | 159 backgroundColor, iconUrl.isEmpty()); |
161 shortcutIntent.putExtra(EXTRA_MAC, getEncodedMac(context, url)); | 160 shortcutIntent.putExtra(EXTRA_MAC, getEncodedMac(context, url)); |
162 shortcutIntent.putExtra(EXTRA_SOURCE, source); | 161 shortcutIntent.putExtra(EXTRA_SOURCE, source); |
163 shortcutIntent.setPackage(context.getPackageName()); | 162 shortcutIntent.setPackage(context.getPackageName()); |
164 return shortcutIntent; | 163 return shortcutIntent; |
165 } | 164 } |
166 @Override | 165 @Override |
167 protected void onPostExecute(final Intent resultIntent) { | 166 protected void onPostExecute(final Intent resultIntent) { |
168 Context context = ContextUtils.getApplicationContext(); | 167 Context context = ContextUtils.getApplicationContext(); |
169 sDelegate.sendBroadcast( | 168 sDelegate.requestPinShortcut( |
170 context, createAddToHomeIntent(userTitle, icon, resultIn tent)); | 169 context, createAddToHomeIntent(userTitle, icon, resultIn tent)); |
171 | 170 |
172 // Store the webapp data so that it is accessible without the in tent. Once this | 171 // 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 | 172 // process is complete, call back to native code to start the sp lash image |
174 // download. | 173 // download. |
175 WebappRegistry.getInstance().register( | 174 WebappRegistry.getInstance().register( |
176 id, new WebappRegistry.FetchWebappDataStorageCallback() { | 175 id, new WebappRegistry.FetchWebappDataStorageCallback() { |
177 @Override | 176 @Override |
178 public void onWebappDataStorageRetrieved(WebappDataS torage storage) { | 177 public void onWebappDataStorageRetrieved(WebappDataS torage storage) { |
179 storage.updateFromShortcutIntent(resultIntent); | 178 storage.updateFromShortcutIntent(resultIntent); |
180 nativeOnWebappDataStored(callbackPointer); | 179 nativeOnWebappDataStored(callbackPointer); |
181 } | 180 } |
182 }); | 181 }); |
183 | 182 if (ChromeShortcutManager.getInstance(context).canShowAddedToHom escreenToast( |
184 showAddedToHomescreenToast(userTitle); | 183 context)) { |
184 showAddedToHomescreenToast(userTitle); | |
185 } | |
185 } | 186 } |
186 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | 187 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
187 } | 188 } |
188 | 189 |
189 public static void addWebApkShortcut(Context context, String packageName) { | 190 public static void addWebApkShortcut(Context context, String packageName) { |
190 PackageManager pm = context.getPackageManager(); | 191 PackageManager pm = context.getPackageManager(); |
191 try { | 192 try { |
192 ApplicationInfo appInfo = pm.getApplicationInfo( | 193 ApplicationInfo appInfo = pm.getApplicationInfo( |
193 packageName, PackageManager.GET_META_DATA); | 194 packageName, PackageManager.GET_META_DATA); |
194 String shortcutTitle = pm.getApplicationLabel(appInfo).toString(); | 195 String shortcutTitle = pm.getApplicationLabel(appInfo).toString(); |
195 Bitmap shortcutIcon = ((BitmapDrawable) pm.getApplicationIcon(packag eName)).getBitmap(); | 196 Bitmap shortcutIcon = ((BitmapDrawable) pm.getApplicationIcon(packag eName)).getBitmap(); |
196 | 197 |
197 Bitmap bitmap = createHomeScreenIconFromWebIcon(shortcutIcon); | 198 Bitmap bitmap = createHomeScreenIconFromWebIcon(shortcutIcon); |
198 Intent i = new Intent(); | 199 Intent i = new Intent(); |
199 i.setClassName(packageName, WEBAPK_MAIN_ACTIVITY); | 200 i.setClassName(packageName, WEBAPK_MAIN_ACTIVITY); |
200 i.addCategory(Intent.CATEGORY_LAUNCHER); | 201 i.addCategory(Intent.CATEGORY_LAUNCHER); |
201 context.sendBroadcast(createAddToHomeIntent(shortcutTitle, bitmap, i )); | 202 context.sendBroadcast(createAddToHomeIntent(shortcutTitle, bitmap, i )); |
pkotwicz
2017/02/13 19:22:49
Should we call requestPinShortcut() here too?
Marti Wong
2017/02/14 02:42:46
Thanks for the comment!
Intent i has no id stored
| |
202 } catch (NameNotFoundException e) { | 203 } catch (NameNotFoundException e) { |
203 e.printStackTrace(); | 204 e.printStackTrace(); |
204 } | 205 } |
205 } | 206 } |
206 | 207 |
207 /** | 208 /** |
208 * Adds home screen shortcut which opens in the browser Activity. | 209 * Adds home screen shortcut which opens in the browser Activity. |
209 */ | 210 */ |
210 @SuppressWarnings("unused") | 211 @SuppressWarnings("unused") |
211 @CalledByNative | 212 @CalledByNative |
212 private static void addShortcut(String url, String userTitle, Bitmap icon, i nt source) { | 213 private static void addShortcut( |
214 String id, String url, String userTitle, Bitmap icon, int source) { | |
213 Context context = ContextUtils.getApplicationContext(); | 215 Context context = ContextUtils.getApplicationContext(); |
214 final Intent shortcutIntent = createShortcutIntent(url); | 216 final Intent shortcutIntent = createShortcutIntent(url); |
217 shortcutIntent.putExtra(EXTRA_ID, id); | |
215 shortcutIntent.putExtra(EXTRA_SOURCE, source); | 218 shortcutIntent.putExtra(EXTRA_SOURCE, source); |
216 shortcutIntent.setPackage(context.getPackageName()); | 219 shortcutIntent.setPackage(context.getPackageName()); |
217 sDelegate.sendBroadcast( | 220 sDelegate.requestPinShortcut( |
218 context, createAddToHomeIntent(userTitle, icon, shortcutIntent)) ; | 221 context, createAddToHomeIntent(userTitle, icon, shortcutIntent)) ; |
219 showAddedToHomescreenToast(userTitle); | 222 if (ChromeShortcutManager.getInstance(context).canShowAddedToHomescreenT oast(context)) { |
223 showAddedToHomescreenToast(userTitle); | |
224 } | |
220 } | 225 } |
221 | 226 |
222 /** | 227 /** |
223 * Show toast to alert user that the shortcut was added to the home screen. | 228 * Show toast to alert user that the shortcut was added to the home screen. |
224 */ | 229 */ |
225 private static void showAddedToHomescreenToast(final String title) { | 230 private static void showAddedToHomescreenToast(final String title) { |
226 Context applicationContext = ContextUtils.getApplicationContext(); | 231 Context applicationContext = ContextUtils.getApplicationContext(); |
227 String toastText = applicationContext.getString(R.string.added_to_homesc reen, title); | 232 String toastText = applicationContext.getString(R.string.added_to_homesc reen, title); |
228 showToast(toastText); | 233 showToast(toastText); |
229 } | 234 } |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
354 Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); | 359 Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); |
355 shortcutIntent.putExtra(REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true); | 360 shortcutIntent.putExtra(REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true); |
356 return shortcutIntent; | 361 return shortcutIntent; |
357 } | 362 } |
358 | 363 |
359 /** | 364 /** |
360 * Utility method to check if a shortcut can be added to the home screen. | 365 * Utility method to check if a shortcut can be added to the home screen. |
361 * @param context Context used to get the package manager. | 366 * @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. | 367 * @return if a shortcut can be added to the home screen under the current p rofile. |
363 */ | 368 */ |
364 // TODO(crbug.com/635567): Fix this properly. | |
365 @SuppressLint("WrongConstant") | |
366 public static boolean isAddToHomeIntentSupported(Context context) { | 369 public static boolean isAddToHomeIntentSupported(Context context) { |
367 PackageManager pm = context.getPackageManager(); | 370 return ChromeShortcutManager.getInstance(context).isAddShortcutToHomeScr eenSupported( |
368 Intent i = new Intent(INSTALL_SHORTCUT); | 371 context); |
369 List<ResolveInfo> receivers = pm.queryBroadcastReceivers( | |
370 i, PackageManager.GET_INTENT_FILTERS); | |
371 return !receivers.isEmpty(); | |
372 } | 372 } |
373 | 373 |
374 /** | 374 /** |
375 * Returns whether the given icon matches the size requirements to be used o n the home screen. | 375 * Returns whether the given icon matches the size requirements to be used o n the home screen. |
376 * @param width Icon width, in pixels. | 376 * @param width Icon width, in pixels. |
377 * @param height Icon height, in pixels. | 377 * @param height Icon height, in pixels. |
378 * @return whether the given icon matches the size requirements to be used o n the home screen. | 378 * @return whether the given icon matches the size requirements to be used o n the home screen. |
379 */ | 379 */ |
380 @CalledByNative | 380 @CalledByNative |
381 public static boolean isIconLargeEnoughForLauncher(int width, int height) { | 381 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++) { | 700 for (int i = 0; i < list.size(); i++) { |
701 array[i] = list.get(i); | 701 array[i] = list.get(i); |
702 } | 702 } |
703 return array; | 703 return array; |
704 } | 704 } |
705 | 705 |
706 private static native void nativeOnWebappDataStored(long callbackPointer); | 706 private static native void nativeOnWebappDataStored(long callbackPointer); |
707 private static native void nativeOnWebApksRetrieved(long callbackPointer, St ring[] shortNames, | 707 private static native void nativeOnWebApksRetrieved(long callbackPointer, St ring[] shortNames, |
708 String[] packageName, int[] shellApkVersions, int[] versionCodes); | 708 String[] packageName, int[] shellApkVersions, int[] versionCodes); |
709 } | 709 } |
OLD | NEW |