| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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.share; | 5 package org.chromium.chrome.browser.share; |
| 6 | 6 |
| 7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
| 8 import android.app.Activity; | 8 import android.app.Activity; |
| 9 import android.app.PendingIntent; | 9 import android.app.PendingIntent; |
| 10 import android.content.BroadcastReceiver; | 10 import android.content.BroadcastReceiver; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 import java.util.concurrent.TimeUnit; | 52 import java.util.concurrent.TimeUnit; |
| 53 import java.util.concurrent.TimeoutException; | 53 import java.util.concurrent.TimeoutException; |
| 54 | 54 |
| 55 /** | 55 /** |
| 56 * A helper class that helps to start an intent to share titles and URLs. | 56 * A helper class that helps to start an intent to share titles and URLs. |
| 57 */ | 57 */ |
| 58 public class ShareHelper { | 58 public class ShareHelper { |
| 59 | 59 |
| 60 private static final String TAG = "share"; | 60 private static final String TAG = "share"; |
| 61 | 61 |
| 62 /** The task ID of the activity that triggered the share action. */ |
| 63 public static final String EXTRA_TASK_ID = "org.chromium.chrome.extra.TASK_I
D"; |
| 64 |
| 62 private static final String JPEG_EXTENSION = ".jpg"; | 65 private static final String JPEG_EXTENSION = ".jpg"; |
| 63 private static final String PACKAGE_NAME_KEY = "last_shared_package_name"; | 66 private static final String PACKAGE_NAME_KEY = "last_shared_package_name"; |
| 64 private static final String CLASS_NAME_KEY = "last_shared_class_name"; | 67 private static final String CLASS_NAME_KEY = "last_shared_class_name"; |
| 65 private static final String EXTRA_SHARE_SCREENSHOT_AS_STREAM = "share_screen
shot_as_stream"; | 68 private static final String EXTRA_SHARE_SCREENSHOT_AS_STREAM = "share_screen
shot_as_stream"; |
| 66 private static final long COMPONENT_INFO_READ_TIMEOUT_IN_MS = 1000; | 69 private static final long COMPONENT_INFO_READ_TIMEOUT_IN_MS = 1000; |
| 67 | 70 |
| 68 /** | 71 /** |
| 69 * Directory name for shared images. | 72 * Directory name for shared images. |
| 70 * | 73 * |
| 71 * Named "screenshot" for historical reasons as we only initially shared scr
eenshot images. | 74 * Named "screenshot" for historical reasons as we only initially shared scr
eenshot images. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 context.getApplicationContext().unregisterReceiver(sLastRegister
edReceiver); | 136 context.getApplicationContext().unregisterReceiver(sLastRegister
edReceiver); |
| 134 sLastRegisteredReceiver = null; | 137 sLastRegisteredReceiver = null; |
| 135 } | 138 } |
| 136 if (!intent.hasExtra(EXTRA_RECEIVER_TOKEN) | 139 if (!intent.hasExtra(EXTRA_RECEIVER_TOKEN) |
| 137 || intent.getIntExtra(EXTRA_RECEIVER_TOKEN, 0) != this.hashC
ode()) { | 140 || intent.getIntExtra(EXTRA_RECEIVER_TOKEN, 0) != this.hashC
ode()) { |
| 138 return; | 141 return; |
| 139 } | 142 } |
| 140 | 143 |
| 141 ComponentName target = intent.getParcelableExtra(Intent.EXTRA_CHOSEN
_COMPONENT); | 144 ComponentName target = intent.getParcelableExtra(Intent.EXTRA_CHOSEN
_COMPONENT); |
| 142 if (target != null) { | 145 if (target != null) { |
| 143 setLastShareComponentName(context, target); | 146 setLastShareComponentName(target); |
| 144 } | 147 } |
| 145 } | 148 } |
| 146 } | 149 } |
| 147 | 150 |
| 148 /** | 151 /** |
| 149 * Clears all shared image files. | 152 * Clears all shared image files. |
| 150 */ | 153 */ |
| 151 public static void clearSharedImages(final Context context) { | 154 public static void clearSharedImages(final Context context) { |
| 152 new AsyncTask<Void, Void, Void>() { | 155 new AsyncTask<Void, Void, Void>() { |
| 153 @Override | 156 @Override |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 /** | 255 /** |
| 253 * Creates and shows a share intent picker dialog. | 256 * Creates and shows a share intent picker dialog. |
| 254 * | 257 * |
| 255 * @param activity Activity that is used to access package manager. | 258 * @param activity Activity that is used to access package manager. |
| 256 * @param title Title of the page to be shared. | 259 * @param title Title of the page to be shared. |
| 257 * @param url URL of the page to be shared. | 260 * @param url URL of the page to be shared. |
| 258 * @param screenshot Screenshot of the page to be shared. | 261 * @param screenshot Screenshot of the page to be shared. |
| 259 */ | 262 */ |
| 260 private static void showShareDialog(final Activity activity, final String ti
tle, | 263 private static void showShareDialog(final Activity activity, final String ti
tle, |
| 261 final String url, final Bitmap screenshot) { | 264 final String url, final Bitmap screenshot) { |
| 262 Intent intent = getShareIntent(title, url, null); | 265 Intent intent = getShareIntent(activity, title, url, null); |
| 263 PackageManager manager = activity.getPackageManager(); | 266 PackageManager manager = activity.getPackageManager(); |
| 264 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent
, 0); | 267 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent
, 0); |
| 265 assert resolveInfoList.size() > 0; | 268 assert resolveInfoList.size() > 0; |
| 266 if (resolveInfoList.size() == 0) return; | 269 if (resolveInfoList.size() == 0) return; |
| 267 Collections.sort(resolveInfoList, new ResolveInfo.DisplayNameComparator(
manager)); | 270 Collections.sort(resolveInfoList, new ResolveInfo.DisplayNameComparator(
manager)); |
| 268 | 271 |
| 269 final ShareDialogAdapter adapter = | 272 final ShareDialogAdapter adapter = |
| 270 new ShareDialogAdapter(activity, manager, resolveInfoList); | 273 new ShareDialogAdapter(activity, manager, resolveInfoList); |
| 271 AlertDialog.Builder builder = new AlertDialog.Builder(activity, R.style.
AlertDialogTheme); | 274 AlertDialog.Builder builder = new AlertDialog.Builder(activity, R.style.
AlertDialogTheme); |
| 272 builder.setTitle(activity.getString(R.string.share_link_chooser_title)); | 275 builder.setTitle(activity.getString(R.string.share_link_chooser_title)); |
| 273 builder.setAdapter(adapter, null); | 276 builder.setAdapter(adapter, null); |
| 274 | 277 |
| 275 final AlertDialog dialog = builder.create(); | 278 final AlertDialog dialog = builder.create(); |
| 276 dialog.show(); | 279 dialog.show(); |
| 277 dialog.getListView().setOnItemClickListener(new OnItemClickListener() { | 280 dialog.getListView().setOnItemClickListener(new OnItemClickListener() { |
| 278 @Override | 281 @Override |
| 279 public void onItemClick(AdapterView<?> parent, View view, int positi
on, long id) { | 282 public void onItemClick(AdapterView<?> parent, View view, int positi
on, long id) { |
| 280 ResolveInfo info = adapter.getItem(position); | 283 ResolveInfo info = adapter.getItem(position); |
| 281 ActivityInfo ai = info.activityInfo; | 284 ActivityInfo ai = info.activityInfo; |
| 282 ComponentName component = | 285 ComponentName component = |
| 283 new ComponentName(ai.applicationInfo.packageName, ai.nam
e); | 286 new ComponentName(ai.applicationInfo.packageName, ai.nam
e); |
| 284 setLastShareComponentName(activity, component); | 287 setLastShareComponentName(component); |
| 285 makeIntentAndShare(activity, title, url, screenshot, component); | 288 makeIntentAndShare(activity, title, url, screenshot, component); |
| 286 dialog.dismiss(); | 289 dialog.dismiss(); |
| 287 } | 290 } |
| 288 }); | 291 }); |
| 289 } | 292 } |
| 290 | 293 |
| 291 /** | 294 /** |
| 292 * Starts a share intent with the activity that was most recently used to sh
are. | 295 * Starts a share intent with the activity that was most recently used to sh
are. |
| 293 * If there is no most recently used activity, it does nothing. | 296 * If there is no most recently used activity, it does nothing. |
| 294 * @param activity Activity that is used to start the share intent. | 297 * @param activity Activity that is used to start the share intent. |
| 295 * @param title Title of the page to be shared. | 298 * @param title Title of the page to be shared. |
| 296 * @param url URL of the page to be shared. | 299 * @param url URL of the page to be shared. |
| 297 * @param screenshot Screenshot of the page to be shared. | 300 * @param screenshot Screenshot of the page to be shared. |
| 298 */ | 301 */ |
| 299 private static void shareWithLastUsed( | 302 private static void shareWithLastUsed( |
| 300 Activity activity, String title, String url, Bitmap screenshot) { | 303 Activity activity, String title, String url, Bitmap screenshot) { |
| 301 ComponentName component = getLastShareComponentName(activity); | 304 ComponentName component = getLastShareComponentName(); |
| 302 if (component == null) return; | 305 if (component == null) return; |
| 303 makeIntentAndShare(activity, title, url, screenshot, component); | 306 makeIntentAndShare(activity, title, url, screenshot, component); |
| 304 } | 307 } |
| 305 | 308 |
| 306 private static void shareIntent(Activity activity, Intent sharingIntent) { | 309 private static void shareIntent(Activity activity, Intent sharingIntent) { |
| 307 if (sharingIntent.getComponent() != null) { | 310 if (sharingIntent.getComponent() != null) { |
| 308 activity.startActivity(sharingIntent); | 311 activity.startActivity(sharingIntent); |
| 309 } else { | 312 } else { |
| 310 assert TargetChosenReceiver.isSupported(); | 313 assert TargetChosenReceiver.isSupported(); |
| 311 TargetChosenReceiver.sendChooserIntent(activity, sharingIntent); | 314 TargetChosenReceiver.sendChooserIntent(activity, sharingIntent); |
| 312 } | 315 } |
| 313 } | 316 } |
| 314 | 317 |
| 315 private static void makeIntentAndShare(final Activity activity, final String
title, | 318 private static void makeIntentAndShare(final Activity activity, final String
title, |
| 316 final String url, final Bitmap screenshot, final ComponentName compo
nent) { | 319 final String url, final Bitmap screenshot, final ComponentName compo
nent) { |
| 317 if (screenshot == null) { | 320 if (screenshot == null) { |
| 318 shareIntent(activity, getDirectShareIntentForComponent(title, url, n
ull, component)); | 321 shareIntent(activity, |
| 322 getDirectShareIntentForComponent(activity, title, url, null,
component)); |
| 319 } else { | 323 } else { |
| 320 new AsyncTask<Void, Void, File>() { | 324 new AsyncTask<Void, Void, File>() { |
| 321 @Override | 325 @Override |
| 322 protected File doInBackground(Void... params) { | 326 protected File doInBackground(Void... params) { |
| 323 FileOutputStream fOut = null; | 327 FileOutputStream fOut = null; |
| 324 try { | 328 try { |
| 325 File path = new File(UiUtils.getDirectoryForImageCapture
(activity), | 329 File path = new File(UiUtils.getDirectoryForImageCapture
(activity), |
| 326 SHARE_IMAGES_DIRECTORY_NAME); | 330 SHARE_IMAGES_DIRECTORY_NAME); |
| 327 if (path.exists() || path.mkdir()) { | 331 if (path.exists() || path.mkdir()) { |
| 328 File saveFile = File.createTempFile( | 332 File saveFile = File.createTempFile( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 348 return null; | 352 return null; |
| 349 } | 353 } |
| 350 | 354 |
| 351 @Override | 355 @Override |
| 352 protected void onPostExecute(File saveFile) { | 356 protected void onPostExecute(File saveFile) { |
| 353 if (ApplicationStatus.getStateForApplication() | 357 if (ApplicationStatus.getStateForApplication() |
| 354 != ApplicationState.HAS_DESTROYED_ACTIVITIES) { | 358 != ApplicationState.HAS_DESTROYED_ACTIVITIES) { |
| 355 Uri screenshotUri = saveFile == null | 359 Uri screenshotUri = saveFile == null |
| 356 ? null : UiUtils.getUriForImageCaptureFile(activ
ity, saveFile); | 360 ? null : UiUtils.getUriForImageCaptureFile(activ
ity, saveFile); |
| 357 shareIntent(activity, getDirectShareIntentForComponent( | 361 shareIntent(activity, getDirectShareIntentForComponent( |
| 358 title, url, screenshotUri, component)); | 362 activity, title, url, screenshotUri, component))
; |
| 359 } | 363 } |
| 360 } | 364 } |
| 361 }.execute(); | 365 }.execute(); |
| 362 } | 366 } |
| 363 } | 367 } |
| 364 | 368 |
| 365 /** | 369 /** |
| 366 * Set the icon and the title for the menu item used for direct share. | 370 * Set the icon and the title for the menu item used for direct share. |
| 367 * | 371 * |
| 368 * @param activity Activity that is used to access the package manager. | 372 * @param activity Activity that is used to access the package manager. |
| 369 * @param item The menu item that is used for direct share | 373 * @param item The menu item that is used for direct share |
| 370 */ | 374 */ |
| 371 public static void configureDirectShareMenuItem(Activity activity, MenuItem
item) { | 375 public static void configureDirectShareMenuItem(Activity activity, MenuItem
item) { |
| 372 Drawable directShareIcon = null; | 376 Drawable directShareIcon = null; |
| 373 CharSequence directShareTitle = null; | 377 CharSequence directShareTitle = null; |
| 374 | 378 |
| 375 final ComponentName component = getLastShareComponentName(activity); | 379 final ComponentName component = getLastShareComponentName(); |
| 376 boolean isComponentValid = false; | 380 boolean isComponentValid = false; |
| 377 if (component != null) { | 381 if (component != null) { |
| 378 Intent intent = getShareIntent("", "", null); | 382 Intent intent = getShareIntent(activity, "", "", null); |
| 379 intent.setPackage(component.getPackageName()); | 383 intent.setPackage(component.getPackageName()); |
| 380 PackageManager manager = activity.getPackageManager(); | 384 PackageManager manager = activity.getPackageManager(); |
| 381 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(in
tent, 0); | 385 List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(in
tent, 0); |
| 382 for (ResolveInfo info : resolveInfoList) { | 386 for (ResolveInfo info : resolveInfoList) { |
| 383 ActivityInfo ai = info.activityInfo; | 387 ActivityInfo ai = info.activityInfo; |
| 384 if (component.equals(new ComponentName(ai.applicationInfo.packag
eName, ai.name))) { | 388 if (component.equals(new ComponentName(ai.applicationInfo.packag
eName, ai.name))) { |
| 385 isComponentValid = true; | 389 isComponentValid = true; |
| 386 break; | 390 break; |
| 387 } | 391 } |
| 388 } | 392 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 } | 431 } |
| 428 | 432 |
| 429 item.setIcon(directShareIcon); | 433 item.setIcon(directShareIcon); |
| 430 if (directShareTitle != null) { | 434 if (directShareTitle != null) { |
| 431 item.setTitle(activity.getString(R.string.accessibility_menu_share_v
ia, | 435 item.setTitle(activity.getString(R.string.accessibility_menu_share_v
ia, |
| 432 directShareTitle)); | 436 directShareTitle)); |
| 433 } | 437 } |
| 434 } | 438 } |
| 435 | 439 |
| 436 @VisibleForTesting | 440 @VisibleForTesting |
| 437 public static Intent getShareIntent(String title, String url, Uri screenshot
Uri) { | 441 protected static Intent getShareIntent( |
| 442 Activity activity, String title, String url, Uri screenshotUri) { |
| 438 url = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); | 443 url = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); |
| 439 Intent intent = new Intent(Intent.ACTION_SEND); | 444 Intent intent = new Intent(Intent.ACTION_SEND); |
| 440 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); | 445 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); |
| 441 intent.setType("text/plain"); | 446 intent.setType("text/plain"); |
| 442 intent.putExtra(Intent.EXTRA_SUBJECT, title); | 447 intent.putExtra(Intent.EXTRA_SUBJECT, title); |
| 443 intent.putExtra(Intent.EXTRA_TEXT, url); | 448 intent.putExtra(Intent.EXTRA_TEXT, url); |
| 449 intent.putExtra(EXTRA_TASK_ID, activity.getTaskId()); |
| 450 |
| 444 if (screenshotUri != null) { | 451 if (screenshotUri != null) { |
| 445 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); | 452 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); |
| 446 // To give read access to an Intent target, we need to put |screensh
otUri| in clipData | 453 // To give read access to an Intent target, we need to put |screensh
otUri| in clipData |
| 447 // because adding Intent.FLAG_GRANT_READ_URI_PERMISSION doesn't work
for | 454 // because adding Intent.FLAG_GRANT_READ_URI_PERMISSION doesn't work
for |
| 448 // EXTRA_SHARE_SCREENSHOT_AS_STREAM. | 455 // EXTRA_SHARE_SCREENSHOT_AS_STREAM. |
| 449 intent.setClipData(ClipData.newRawUri("", screenshotUri)); | 456 intent.setClipData(ClipData.newRawUri("", screenshotUri)); |
| 450 intent.putExtra(EXTRA_SHARE_SCREENSHOT_AS_STREAM, screenshotUri); | 457 intent.putExtra(EXTRA_SHARE_SCREENSHOT_AS_STREAM, screenshotUri); |
| 451 } | 458 } |
| 452 return intent; | 459 return intent; |
| 453 } | 460 } |
| 454 | 461 |
| 455 private static Intent getShareImageIntent(Uri imageUri) { | 462 private static Intent getShareImageIntent(Uri imageUri) { |
| 456 Intent intent = new Intent(Intent.ACTION_SEND); | 463 Intent intent = new Intent(Intent.ACTION_SEND); |
| 457 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); | 464 intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); |
| 458 intent.setType("image/jpeg"); | 465 intent.setType("image/jpeg"); |
| 459 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); | 466 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); |
| 460 intent.putExtra(Intent.EXTRA_STREAM, imageUri); | 467 intent.putExtra(Intent.EXTRA_STREAM, imageUri); |
| 461 return intent; | 468 return intent; |
| 462 } | 469 } |
| 463 | 470 |
| 464 private static Intent getDirectShareIntentForComponent( | 471 private static Intent getDirectShareIntentForComponent( |
| 465 String title, String url, Uri screenshotUri, ComponentName component
) { | 472 Activity activity, String title, String url, |
| 466 Intent intent = getShareIntent(title, url, screenshotUri); | 473 Uri screenshotUri, ComponentName component) { |
| 474 Intent intent = getShareIntent(activity, title, url, screenshotUri); |
| 467 intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT | 475 intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT |
| 468 | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); | 476 | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); |
| 469 intent.setComponent(component); | 477 intent.setComponent(component); |
| 470 return intent; | 478 return intent; |
| 471 } | 479 } |
| 472 | 480 |
| 473 private static ComponentName getLastShareComponentName(Context context) { | 481 private static ComponentName getLastShareComponentName() { |
| 474 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); | 482 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); |
| 475 String packageName = preferences.getString(PACKAGE_NAME_KEY, null); | 483 String packageName = preferences.getString(PACKAGE_NAME_KEY, null); |
| 476 String className = preferences.getString(CLASS_NAME_KEY, null); | 484 String className = preferences.getString(CLASS_NAME_KEY, null); |
| 477 if (packageName == null || className == null) return null; | 485 if (packageName == null || className == null) return null; |
| 478 return new ComponentName(packageName, className); | 486 return new ComponentName(packageName, className); |
| 479 } | 487 } |
| 480 | 488 |
| 481 private static void setLastShareComponentName(Context context, ComponentName
component) { | 489 private static void setLastShareComponentName(ComponentName component) { |
| 482 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); | 490 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); |
| 483 SharedPreferences.Editor editor = preferences.edit(); | 491 SharedPreferences.Editor editor = preferences.edit(); |
| 484 editor.putString(PACKAGE_NAME_KEY, component.getPackageName()); | 492 editor.putString(PACKAGE_NAME_KEY, component.getPackageName()); |
| 485 editor.putString(CLASS_NAME_KEY, component.getClassName()); | 493 editor.putString(CLASS_NAME_KEY, component.getClassName()); |
| 486 editor.apply(); | 494 editor.apply(); |
| 487 } | 495 } |
| 488 } | 496 } |
| OLD | NEW |