Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(680)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java

Issue 2666833002: Create entry to PWSharing through ShareHelper (Closed)
Patch Set: Fixing nits Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..649e5c8a335a6e7a7d98e9e8430a6e07d65a5229 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,25 +36,34 @@ 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.physicalweb.PhysicalWebShareActivity;
+import org.chromium.chrome.browser.printing.PrintShareActivity;
+import org.chromium.chrome.browser.tab.Tab;
import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
import org.chromium.ui.UiUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.util.ArrayList;
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;
@@ -98,12 +108,27 @@ public class ShareHelper {
*/
private static final String SHARE_IMAGES_DIRECTORY_NAME = "screenshot";
+ /**
+ * Potential activities to add to the share picker intent.
+ */
+ private static final List<ShareActivity> SHARE_ACTIVITIES = Collections.unmodifiableList(
+ new ArrayList<ShareActivity>() { {
+ add(new PrintShareActivity());
+ add(new PhysicalWebShareActivity());
+ }});
+
/** Force the use of a Chrome-specific intent chooser, not the system chooser. */
private static boolean sForceCustomChooserForTesting;
/** 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 =
cco3 2017/02/07 19:51:39 Should these be ShareActivities?
+ 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 +706,134 @@ public class ShareHelper {
if (packageName == null || className == null) return null;
return new ComponentName(packageName, className);
}
+
+ /**
+ * Dynamically add Chrome activities to Share chooser.
+ *
+ * @param activity The activity that will be triggering the share action.
+ * @param currentTab The current tab of the chrome Activity that is launching the share intent.
+ * @param callback The callback to be triggered after the options have been enabled. This
+ * may or may not be synchronous depending on whether this will require
+ * interacting with the Android framework.
+ */
+ public static void enableShareActivitiesAndStartShareIntent(final Activity activity,
+ final Tab currentTab, final Runnable callback) {
+ ThreadUtils.assertOnUiThread();
+
+ if (sStateListener == null) {
+ sStateListener = new ActivityStateListener() {
+ @Override
+ public void onActivityStateChange(Activity activity, int newState) {
+ if (newState == ActivityState.PAUSED) return;
+ unregisterShareActivities(activity);
+ }
+ };
+ }
+ ApplicationStatus.registerStateListenerForAllActivities(sStateListener);
+ boolean wasEmpty = sPendingShareActivities.isEmpty();
+ sPendingShareActivities.add(activity);
+
+ final List<ShareActivity> enabledActivities = filterEnabledShareActivities(currentTab);
+ waitForPendingStateChangeTask();
+ if (enabledActivities.isEmpty()) {
+ callback.run();
+ return;
+ }
+ sStateChangeTask = new StateChangeTask(activity, enabledActivities,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+ @Override
+ protected void onPostExecute(Void result) {
+ if (sStateChangeTask == this) {
+ sStateChangeTask = null;
+ } else {
+ waitForPendingStateChangeTask();
+ }
+ callback.run();
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ /**
+ * Disables Components after Share Chooser is done.
+ */
+ public static void unregisterShareActivities(final Activity activity) {
cco3 2017/02/07 19:51:39 this parameter needs a more helpful name...is it t
+ ThreadUtils.assertOnUiThread();
+
+ sPendingShareActivities.remove(activity);
+ if (!sPendingShareActivities.isEmpty()) return;
+ ApplicationStatus.unregisterActivityStateListener(sStateListener);
+
+ waitForPendingStateChangeTask();
+ sStateChangeTask = new StateChangeTask(activity, SHARE_ACTIVITIES,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+ @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, "Share Helper state change task did not complete as expected");
+ } finally {
+ StrictMode.setThreadPolicy(oldPolicy);
+ }
+ }
+
+ /**
+ * List of the potential ShareActivities to enable.
+ * @param currentTab The current tab of the chrome activity.
+ * @return Filtered list of options to enable for share chooser.
+ */
+ private static List<ShareActivity> filterEnabledShareActivities(Tab currentTab) {
+ List<ShareActivity> enabledShareActivities = new ArrayList<ShareActivity>(2);
+ for (ShareActivity activity: SHARE_ACTIVITIES) {
+ if (activity.featureIsEnabled(currentTab)) {
+ enabledShareActivities.add(activity);
+ }
+ }
+ return enabledShareActivities;
+ }
+
+ private static class StateChangeTask extends AsyncTask<Void, Void, Void> {
+
+ private Activity mCallingActivity;
+ private List<ShareActivity> mActivities;
+ private int mComponentEnabledState;
+
+ public StateChangeTask(Activity activity, List<ShareActivity> activityList, int state) {
+ mCallingActivity = activity;
+ mActivities = activityList;
+ mComponentEnabledState = state;
+ }
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ if (sPendingShareActivities.isEmpty()) return null;
+
+ for (int i = 0; i < mActivities.size(); i++) {
+ mCallingActivity.getPackageManager().setComponentEnabledSetting(
+ new ComponentName(mCallingActivity,
+ mActivities.get(i).getClass()),
+ mComponentEnabledState,
+ PackageManager.DONT_KILL_APP);
+ }
+ return null;
+ }
+ }
}

Powered by Google App Engine
This is Rietveld 408576698