Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java |
| index 97583b682427c1491325995f4a6fa8c3e7c6c11d..15620f1f46a6c0cd1b99d1fc2dae556e8e4c5858 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java |
| @@ -26,6 +26,7 @@ import android.graphics.drawable.Drawable; |
| import android.net.Uri; |
| import android.os.AsyncTask; |
| import android.os.Build; |
| +import android.os.StrictMode; |
| import android.support.annotation.Nullable; |
| import android.support.v7.app.AlertDialog; |
| import android.text.TextUtils; |
| @@ -35,17 +36,21 @@ import android.view.View; |
| import android.widget.AdapterView; |
| import android.widget.AdapterView.OnItemClickListener; |
| +import org.chromium.base.ActivityState; |
| import org.chromium.base.ApiCompatibilityUtils; |
| import org.chromium.base.ApplicationState; |
| import org.chromium.base.ApplicationStatus; |
| +import org.chromium.base.ApplicationStatus.ActivityStateListener; |
| import org.chromium.base.Callback; |
| import org.chromium.base.ContextUtils; |
| import org.chromium.base.Log; |
| import org.chromium.base.StreamUtil; |
| +import org.chromium.base.ThreadUtils; |
| import org.chromium.base.VisibleForTesting; |
| import org.chromium.base.annotations.SuppressFBWarnings; |
| import org.chromium.base.metrics.RecordHistogram; |
| import org.chromium.chrome.R; |
| +import org.chromium.chrome.browser.printing.PrintShareActivity; |
| import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; |
| import org.chromium.ui.UiUtils; |
| @@ -53,7 +58,9 @@ import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.util.Collections; |
| +import java.util.HashSet; |
| import java.util.List; |
| +import java.util.Set; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.TimeoutException; |
| @@ -104,6 +111,12 @@ public class ShareHelper { |
| /** If non-null, will be used instead of the real activity. */ |
| private static FakeIntentReceiver sFakeIntentReceiverForTesting; |
| + /** Variables for adding activities dynamically to share picker intent. */ |
| + private static Set<Activity> sPendingShareActivities = |
| + Collections.synchronizedSet(new HashSet<Activity>()); |
| + private static ActivityStateListener sStateListener; |
| + private static AsyncTask<Void, Void, Void> sStateChangeTask; |
| + |
| private ShareHelper() {} |
| private static void fireIntent(Activity activity, Intent intent) { |
| @@ -681,4 +694,109 @@ public class ShareHelper { |
| if (packageName == null || className == null) return null; |
| return new ComponentName(packageName, className); |
| } |
| + |
| + /** |
| + * Enable the print sharing option. |
| + * |
| + * @param activity The activity that will be triggering the share action. The activitiy's |
| + * state will be tracked to disable the print option when the share operation |
| + * has been completed. |
| + * @param callback The callback to be triggered after the print option has been enabled. This |
| + * may or may not be synchronous depending on whether this will require |
| + * interacting with the Android framework. |
| + */ |
| + public static void enablePrintShareOption(final Activity activity, final Runnable callback) { |
|
Ted C
2017/02/11 00:22:27
Don't make this specific to print. In general, th
|
| + ThreadUtils.assertOnUiThread(); |
| + |
| + if (sStateListener == null) { |
| + sStateListener = new ActivityStateListener() { |
| + @Override |
| + public void onActivityStateChange(Activity activity, int newState) { |
| + if (newState == ActivityState.PAUSED) return; |
| + unregisterActivity(activity); |
| + } |
| + }; |
| + } |
| + ApplicationStatus.registerStateListenerForAllActivities(sStateListener); |
| + boolean wasEmpty = sPendingShareActivities.isEmpty(); |
| + sPendingShareActivities.add(activity); |
| + |
| + waitForPendingStateChangeTask(); |
| + if (wasEmpty) { |
| + sStateChangeTask = new AsyncTask<Void, Void, Void>() { |
| + @Override |
| + protected Void doInBackground(Void... params) { |
| + if (sPendingShareActivities.isEmpty()) return null; |
| + |
| + activity.getPackageManager().setComponentEnabledSetting( |
| + new ComponentName(activity, PrintShareActivity.class), |
| + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, |
| + PackageManager.DONT_KILL_APP); |
| + return null; |
| + } |
| + |
| + @Override |
| + protected void onPostExecute(Void result) { |
| + if (sStateChangeTask == this) { |
| + sStateChangeTask = null; |
| + } else { |
| + waitForPendingStateChangeTask(); |
| + } |
| + callback.run(); |
| + } |
| + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
| + } else { |
| + callback.run(); |
| + } |
| + } |
| + |
| + /** |
| + * Disables Components after Share Chooser is done. |
| + */ |
| + public static void unregisterActivity(final Activity activity) { |
|
Ted C
2017/02/11 00:22:27
This name doesn't really make sense IMO. What act
|
| + ThreadUtils.assertOnUiThread(); |
| + |
| + sPendingShareActivities.remove(activity); |
| + if (!sPendingShareActivities.isEmpty()) return; |
| + ApplicationStatus.unregisterActivityStateListener(sStateListener); |
| + |
| + waitForPendingStateChangeTask(); |
| + sStateChangeTask = new AsyncTask<Void, Void, Void>() { |
| + @Override |
| + protected Void doInBackground(Void... params) { |
| + if (!sPendingShareActivities.isEmpty()) return null; |
| + |
| + activity.getPackageManager().setComponentEnabledSetting( |
| + new ComponentName(activity, PrintShareActivity.class), |
| + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, |
| + PackageManager.DONT_KILL_APP); |
| + return null; |
| + } |
| + |
| + @Override |
| + protected void onPostExecute(Void result) { |
| + if (sStateChangeTask == this) sStateChangeTask = null; |
| + } |
| + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
| + } |
| + |
| + /** |
| + * Waits for any pending state change operations to be completed. |
| + * |
| + * This will avoid timing issues described here: crbug.com/649453. |
| + */ |
| + private static void waitForPendingStateChangeTask() { |
| + ThreadUtils.assertOnUiThread(); |
| + |
| + if (sStateChangeTask == null) return; |
| + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); |
| + try { |
| + sStateChangeTask.get(); |
| + sStateChangeTask = null; |
| + } catch (InterruptedException | ExecutionException e) { |
| + Log.e(TAG, "Print state change task did not complete as expected"); |
| + } finally { |
| + StrictMode.setThreadPolicy(oldPolicy); |
| + } |
| + } |
| } |