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

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

Issue 2666833002: Create entry to PWSharing through ShareHelper (Closed)
Patch Set: Unregister now disables component 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 unified diff | Download patch
OLDNEW
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;
11 import android.content.ClipData; 11 import android.content.ClipData;
12 import android.content.ComponentName; 12 import android.content.ComponentName;
13 import android.content.Context; 13 import android.content.Context;
14 import android.content.DialogInterface; 14 import android.content.DialogInterface;
15 import android.content.DialogInterface.OnDismissListener; 15 import android.content.DialogInterface.OnDismissListener;
16 import android.content.Intent; 16 import android.content.Intent;
17 import android.content.IntentFilter; 17 import android.content.IntentFilter;
18 import android.content.SharedPreferences; 18 import android.content.SharedPreferences;
19 import android.content.pm.ActivityInfo; 19 import android.content.pm.ActivityInfo;
20 import android.content.pm.ApplicationInfo; 20 import android.content.pm.ApplicationInfo;
21 import android.content.pm.PackageManager; 21 import android.content.pm.PackageManager;
22 import android.content.pm.PackageManager.NameNotFoundException; 22 import android.content.pm.PackageManager.NameNotFoundException;
23 import android.content.pm.ResolveInfo; 23 import android.content.pm.ResolveInfo;
24 import android.graphics.Bitmap; 24 import android.graphics.Bitmap;
25 import android.graphics.drawable.Drawable; 25 import android.graphics.drawable.Drawable;
26 import android.net.Uri; 26 import android.net.Uri;
27 import android.os.AsyncTask; 27 import android.os.AsyncTask;
28 import android.os.Build; 28 import android.os.Build;
29 import android.os.StrictMode;
29 import android.support.annotation.Nullable; 30 import android.support.annotation.Nullable;
30 import android.support.v7.app.AlertDialog; 31 import android.support.v7.app.AlertDialog;
31 import android.text.TextUtils; 32 import android.text.TextUtils;
32 import android.util.Pair; 33 import android.util.Pair;
33 import android.view.MenuItem; 34 import android.view.MenuItem;
34 import android.view.View; 35 import android.view.View;
35 import android.widget.AdapterView; 36 import android.widget.AdapterView;
36 import android.widget.AdapterView.OnItemClickListener; 37 import android.widget.AdapterView.OnItemClickListener;
37 38
39 import org.chromium.base.ActivityState;
38 import org.chromium.base.ApiCompatibilityUtils; 40 import org.chromium.base.ApiCompatibilityUtils;
39 import org.chromium.base.ApplicationState; 41 import org.chromium.base.ApplicationState;
40 import org.chromium.base.ApplicationStatus; 42 import org.chromium.base.ApplicationStatus;
43 import org.chromium.base.ApplicationStatus.ActivityStateListener;
41 import org.chromium.base.Callback; 44 import org.chromium.base.Callback;
42 import org.chromium.base.ContextUtils; 45 import org.chromium.base.ContextUtils;
43 import org.chromium.base.Log; 46 import org.chromium.base.Log;
44 import org.chromium.base.StreamUtil; 47 import org.chromium.base.StreamUtil;
48 import org.chromium.base.ThreadUtils;
45 import org.chromium.base.VisibleForTesting; 49 import org.chromium.base.VisibleForTesting;
46 import org.chromium.base.annotations.SuppressFBWarnings; 50 import org.chromium.base.annotations.SuppressFBWarnings;
47 import org.chromium.base.metrics.RecordHistogram; 51 import org.chromium.base.metrics.RecordHistogram;
48 import org.chromium.chrome.R; 52 import org.chromium.chrome.R;
49 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; 53 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
50 import org.chromium.ui.UiUtils; 54 import org.chromium.ui.UiUtils;
51 55
52 import java.io.File; 56 import java.io.File;
53 import java.io.FileOutputStream; 57 import java.io.FileOutputStream;
54 import java.io.IOException; 58 import java.io.IOException;
55 import java.util.Collections; 59 import java.util.Collections;
60 import java.util.HashSet;
56 import java.util.List; 61 import java.util.List;
62 import java.util.Set;
57 import java.util.concurrent.ExecutionException; 63 import java.util.concurrent.ExecutionException;
58 import java.util.concurrent.TimeUnit; 64 import java.util.concurrent.TimeUnit;
59 import java.util.concurrent.TimeoutException; 65 import java.util.concurrent.TimeoutException;
60 66
61 /** 67 /**
62 * A helper class that helps to start an intent to share titles and URLs. 68 * A helper class that helps to start an intent to share titles and URLs.
63 */ 69 */
64 public class ShareHelper { 70 public class ShareHelper {
65 71
66 /** Interface that receives intents for testing (to fake out actually sendin g them). */ 72 /** Interface that receives intents for testing (to fake out actually sendin g them). */
(...skipping 30 matching lines...) Expand all
97 * Named "screenshot" for historical reasons as we only initially shared scr eenshot images. 103 * Named "screenshot" for historical reasons as we only initially shared scr eenshot images.
98 */ 104 */
99 private static final String SHARE_IMAGES_DIRECTORY_NAME = "screenshot"; 105 private static final String SHARE_IMAGES_DIRECTORY_NAME = "screenshot";
100 106
101 /** Force the use of a Chrome-specific intent chooser, not the system choose r. */ 107 /** Force the use of a Chrome-specific intent chooser, not the system choose r. */
102 private static boolean sForceCustomChooserForTesting; 108 private static boolean sForceCustomChooserForTesting;
103 109
104 /** If non-null, will be used instead of the real activity. */ 110 /** If non-null, will be used instead of the real activity. */
105 private static FakeIntentReceiver sFakeIntentReceiverForTesting; 111 private static FakeIntentReceiver sFakeIntentReceiverForTesting;
106 112
113 /** Variables for adding options dynamically to app chooser. */
114 private static Set<Activity> sPendingShareActivities =
115 Collections.synchronizedSet(new HashSet<Activity>());
116 private static ActivityStateListener sStateListener;
117 private static AsyncTask<Void, Void, Void> sStateChangeTask;
118
107 private ShareHelper() {} 119 private ShareHelper() {}
108 120
109 private static void fireIntent(Activity activity, Intent intent) { 121 private static void fireIntent(Activity activity, Intent intent) {
110 if (sFakeIntentReceiverForTesting != null) { 122 if (sFakeIntentReceiverForTesting != null) {
111 Context context = activity.getApplicationContext(); 123 Context context = activity.getApplicationContext();
112 sFakeIntentReceiverForTesting.fireIntent(context, intent); 124 sFakeIntentReceiverForTesting.fireIntent(context, intent);
113 } else { 125 } else {
114 activity.startActivity(intent); 126 activity.startActivity(intent);
115 } 127 }
116 } 128 }
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 return intent; 686 return intent;
675 } 687 }
676 688
677 private static ComponentName getLastShareComponentName() { 689 private static ComponentName getLastShareComponentName() {
678 SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); 690 SharedPreferences preferences = ContextUtils.getAppSharedPreferences();
679 String packageName = preferences.getString(PACKAGE_NAME_KEY, null); 691 String packageName = preferences.getString(PACKAGE_NAME_KEY, null);
680 String className = preferences.getString(CLASS_NAME_KEY, null); 692 String className = preferences.getString(CLASS_NAME_KEY, null);
681 if (packageName == null || className == null) return null; 693 if (packageName == null || className == null) return null;
682 return new ComponentName(packageName, className); 694 return new ComponentName(packageName, className);
683 } 695 }
696
697 /**
698 * Dynamically add Chrome activities to Share chooser.
699 *
700 * @param activity The activity that will be triggering the share action.
701 * @param options List of classes to add to the chooser.
702 * @param callback The callback to be triggered after the options have been enabled. This
703 * may or may not be synchronous depending on whether this w ill require
704 * interacting with the Android framework.
705 */
706 public static void enableOptions(final Activity activity,
707 final List<Class> options, final Runnable callback) {
708 Log.v(TAG, "enableOptions Called");
709 ThreadUtils.assertOnUiThread();
710
711 if (sStateListener == null) {
712 sStateListener = new ActivityStateListener() {
713 @Override
714 public void onActivityStateChange(Activity activity, int newStat e) {
715 if (newState == ActivityState.PAUSED) return;
716 unregisterActivity(activity, options);
717 }
718 };
719 }
720 ApplicationStatus.registerStateListenerForAllActivities(sStateListener);
721 boolean wasEmpty = sPendingShareActivities.isEmpty();
722 sPendingShareActivities.add(activity);
723
724 waitForPendingStateChangeTask();
725 if (wasEmpty) {
726 sStateChangeTask = new AsyncTask<Void, Void, Void>() {
727 @Override
728 protected Void doInBackground(Void... params) {
729 if (sPendingShareActivities.isEmpty()) return null;
730
731 for (int i = 0; i < options.size(); i++) {
732 Log.v(TAG, "enableOptions: " + options.get(i).getName()) ;
cco3 2017/02/02 00:58:58 remove extra logging.
iankc 2017/02/02 01:52:24 Done.
733 activity.getPackageManager().setComponentEnabledSetting(
734 new ComponentName(activity, options.get(i)),
735 PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
736 PackageManager.DONT_KILL_APP);
737 }
738 return null;
739 }
740
741 @Override
742 protected void onPostExecute(Void result) {
743 if (sStateChangeTask == this) {
744 sStateChangeTask = null;
745 } else {
746 waitForPendingStateChangeTask();
747 }
748 callback.run();
749 }
750 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
751 } else {
752 callback.run();
753 }
754 }
755
756 public static void unregisterActivity(final Activity activity,
757 final List<Class> options) {
758 Log.v(TAG, "unregisterActivity Called");
759 ThreadUtils.assertOnUiThread();
760
761 sPendingShareActivities.remove(activity);
762 if (!sPendingShareActivities.isEmpty()) return;
763 ApplicationStatus.unregisterActivityStateListener(sStateListener);
764
765 waitForPendingStateChangeTask();
766 sStateChangeTask = new AsyncTask<Void, Void, Void>() {
767 @Override
768 protected Void doInBackground(Void... params) {
769 if (!sPendingShareActivities.isEmpty()) return null;
770
771 for (int i = 0; i < options.size(); i++) {
772 Log.v(TAG, "unregisterActivity: " + options.get(i).getNa me());
773 activity.getPackageManager().setComponentEnabledSetting(
774 new ComponentName(activity, options.get(i)),
775 PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
776 PackageManager.DONT_KILL_APP);
777 }
778 return null;
779 }
780
781 @Override
782 protected void onPostExecute(Void result) {
783 if (sStateChangeTask == this) sStateChangeTask = null;
784 }
785 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
786 }
787
788 /**
789 * Waits for any pending state change operations to be completed.
790 *
791 * This will avoid timing issues described here: crbug.com/649453.
792 */
793 public static void waitForPendingStateChangeTask() {
794 ThreadUtils.assertOnUiThread();
795
796 if (sStateChangeTask == null) return;
797 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
798 try {
799 sStateChangeTask.get();
800 sStateChangeTask = null;
801 } catch (InterruptedException | ExecutionException e) {
802 Log.e(TAG, "Share Helper state change task did not complete as expec ted");
803 } finally {
804 StrictMode.setThreadPolicy(oldPolicy);
805 }
806 }
684 } 807 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698