Created
July 2, 2023 12:46
-
-
Save uazo/d8208d8d6fd732cf1173459a4464f143 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From: Your Name <you@example.com> | |
Date: Sun, 2 Jul 2023 08:27:30 +0000 | |
Subject: internal firewall wip | |
--- | |
base/BUILD.gn | 5 + | |
.../src/org/chromium/base/ContextUtils.java | 5 +- | |
.../base/firewall/BridgeContextWrapper.java | 168 +++++ | |
.../base/firewall/BridgePackageManager.java | 576 ++++++++++++++++++ | |
.../browser/ChromeBaseAppCompatActivity.java | 17 + | |
.../browser/base/SplitCompatApplication.java | 2 + | |
.../ExternalNavigationHandler.java | 116 +++- | |
.../org/chromium/ui/base/WindowAndroid.java | 13 + | |
8 files changed, 896 insertions(+), 6 deletions(-) | |
create mode 100644 base/android/java/src/org/chromium/base/firewall/BridgeContextWrapper.java | |
create mode 100644 base/android/java/src/org/chromium/base/firewall/BridgePackageManager.java | |
diff --git a/base/BUILD.gn b/base/BUILD.gn | |
--- a/base/BUILD.gn | |
+++ b/base/BUILD.gn | |
@@ -4365,6 +4365,11 @@ if (is_android) { | |
"android/java/src/org/chromium/base/task/UiThreadTaskExecutor.java", | |
] | |
+ sources += [ | |
+ "android/java/src/org/chromium/base/firewall/BridgePackageManager.java", | |
+ "android/java/src/org/chromium/base/firewall/BridgeContextWrapper.java", | |
+ ] | |
+ | |
if (!is_cronet_build) { | |
sources += [ "android/java/src/org/chromium/base/IntentUtils.java" ] | |
} | |
diff --git a/base/android/java/src/org/chromium/base/ContextUtils.java b/base/android/java/src/org/chromium/base/ContextUtils.java | |
--- a/base/android/java/src/org/chromium/base/ContextUtils.java | |
+++ b/base/android/java/src/org/chromium/base/ContextUtils.java | |
@@ -21,6 +21,7 @@ import android.preference.PreferenceManager; | |
import androidx.annotation.Nullable; | |
import androidx.annotation.VisibleForTesting; | |
+import org.chromium.base.firewall.BridgeContextWrapper; | |
import org.chromium.base.annotations.JNINamespace; | |
import org.chromium.base.compat.ApiHelperForM; | |
import org.chromium.base.compat.ApiHelperForO; | |
@@ -135,7 +136,9 @@ public class ContextUtils { | |
assert appContext != null; | |
// Guard against anyone trying to downcast. | |
if (BuildConfig.ENABLE_ASSERTS && appContext instanceof Application) { | |
- appContext = new ContextWrapper(appContext); | |
+ appContext = BridgeContextWrapper.wrap(appContext); | |
+ } else { | |
+ appContext = BridgeContextWrapper.wrap(appContext); | |
} | |
sApplicationContext = appContext; | |
} | |
diff --git a/base/android/java/src/org/chromium/base/firewall/BridgeContextWrapper.java b/base/android/java/src/org/chromium/base/firewall/BridgeContextWrapper.java | |
new file mode 100644 | |
--- /dev/null | |
+++ b/base/android/java/src/org/chromium/base/firewall/BridgeContextWrapper.java | |
@@ -0,0 +1,168 @@ | |
+package org.chromium.base.firewall; | |
+ | |
+import android.content.AttributionSource; | |
+import android.content.BroadcastReceiver; | |
+import android.content.ComponentName; | |
+import android.content.Context; | |
+import android.content.ContextWrapper; | |
+import android.content.Intent; | |
+import android.content.IntentFilter; | |
+import android.content.pm.PackageManager; | |
+import android.content.ServiceConnection; | |
+import android.os.Handler; | |
+import android.os.Bundle; | |
+ | |
+import org.chromium.base.firewall.BridgePackageManager; | |
+import org.chromium.base.Log; | |
+ | |
+import androidx.annotation.NonNull; | |
+import androidx.annotation.Nullable; | |
+ | |
+import java.util.concurrent.Executor; | |
+import java.util.List; | |
+import java.util.Set; | |
+ | |
+public class BridgeContextWrapper extends ContextWrapper { | |
+ private static final String TAG = "BridgeContextWrapper"; | |
+ | |
+ public static boolean isBridgeContextWrapper(Context context) { | |
+ while (context instanceof ContextWrapper) { | |
+ if (context instanceof BridgeContextWrapper) return true; | |
+ context = ((ContextWrapper) context).getBaseContext(); | |
+ } | |
+ return (context instanceof BridgeContextWrapper); | |
+ } | |
+ | |
+ public static BridgeContextWrapper wrap(Context base) { | |
+ if (isBridgeContextWrapper(base)) | |
+ return (BridgeContextWrapper)base; | |
+ return new BridgeContextWrapper(base); | |
+ } | |
+ | |
+ public BridgeContextWrapper(Context base) { | |
+ super(base); | |
+ Log.i(TAG, "Initialized"); | |
+ } | |
+ | |
+ BridgePackageManager mBridgePackageManager = null; | |
+ | |
+ @Override | |
+ public PackageManager getPackageManager() { | |
+ if (mBridgePackageManager == null) | |
+ mBridgePackageManager = new BridgePackageManager(super.getPackageManager()); | |
+ return mBridgePackageManager; | |
+ } | |
+ | |
+ @Override | |
+ public void startActivity(Intent intent) { | |
+ Log.i(TAG, "startActivity"); | |
+ BridgePackageManager.dumpIntent(intent); | |
+ super.startActivity(intent); | |
+ } | |
+ | |
+ @Override | |
+ public void startActivity(Intent intent, @Nullable Bundle options) { | |
+ Log.i(TAG, "startActivity"); | |
+ BridgePackageManager.dumpIntent(intent); | |
+ super.startActivity(intent, options); | |
+ } | |
+ | |
+ @Override | |
+ public void sendBroadcast(Intent intent) { | |
+ Log.i(TAG, "sendBroadcast"); | |
+ BridgePackageManager.dumpIntent(intent); | |
+ super.sendBroadcast(intent); | |
+ } | |
+ | |
+ @Override | |
+ public void sendBroadcast(Intent intent, @Nullable String receiverPermission) { | |
+ Log.i(TAG, "sendBroadcast"); | |
+ BridgePackageManager.dumpIntent(intent); | |
+ super.sendBroadcast(intent, receiverPermission); | |
+ } | |
+ | |
+ @Override | |
+ public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter) { | |
+ return super.registerReceiver(receiver, filter); | |
+ } | |
+ | |
+ @Override | |
+ public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter, | |
+ int flags) { | |
+ return super.registerReceiver(receiver, filter, flags); | |
+ } | |
+ | |
+ @Override | |
+ public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter, | |
+ @Nullable String broadcastPermission, @Nullable Handler scheduler) { | |
+ return super.registerReceiver(receiver, filter, broadcastPermission, | |
+ scheduler); | |
+ } | |
+ | |
+ @Override | |
+ public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter, | |
+ @Nullable String broadcastPermission, @Nullable Handler scheduler, int flags) { | |
+ return super.registerReceiver(receiver, filter, broadcastPermission, | |
+ scheduler, flags); | |
+ } | |
+ | |
+ @Override | |
+ public @Nullable ComponentName startService(Intent service) { | |
+ return super.startService(service); | |
+ } | |
+ | |
+ @Override | |
+ public @Nullable ComponentName startForegroundService(Intent service) { | |
+ return super.startForegroundService(service); | |
+ } | |
+ | |
+ @Override | |
+ public boolean bindService(Intent service, ServiceConnection conn, | |
+ int flags) { | |
+ Log.i(TAG, "bindService"); | |
+ BridgePackageManager.dumpIntent(service); | |
+ return super.bindService(service, conn, flags); | |
+ } | |
+ | |
+ @Override | |
+ public boolean bindService(Intent service, int flags, Executor executor, | |
+ ServiceConnection conn) { | |
+ Log.i(TAG, "bindService"); | |
+ BridgePackageManager.dumpIntent(service); | |
+ return super.bindService(service, flags, executor, conn); | |
+ } | |
+ | |
+ @Override | |
+ public boolean bindIsolatedService(Intent service, int flags, String instanceName, | |
+ Executor executor, ServiceConnection conn) { | |
+ Log.i(TAG, "bindIsolatedService"); | |
+ BridgePackageManager.dumpIntent(service); | |
+ return super.bindIsolatedService(service, flags, instanceName, executor, conn); | |
+ } | |
+ | |
+ @Override | |
+ public @Nullable Object getSystemService(String name) { | |
+ return super.getSystemService(name); | |
+ } | |
+ | |
+ @Override | |
+ public String getSystemServiceName(Class<?> serviceClass) { | |
+ return super.getSystemServiceName(serviceClass); | |
+ } | |
+ | |
+ @Override | |
+ public int checkPermission(String permission, int pid, int uid) { | |
+ return super.checkPermission(permission, pid, uid); | |
+ } | |
+ | |
+ @NonNull | |
+ @Override | |
+ public AttributionSource getAttributionSource() { | |
+ return super.getAttributionSource(); | |
+ } | |
+ | |
+ @Override | |
+ public Context createDeviceProtectedStorageContext() { | |
+ return super.createDeviceProtectedStorageContext(); | |
+ } | |
+} | |
diff --git a/base/android/java/src/org/chromium/base/firewall/BridgePackageManager.java b/base/android/java/src/org/chromium/base/firewall/BridgePackageManager.java | |
new file mode 100644 | |
--- /dev/null | |
+++ b/base/android/java/src/org/chromium/base/firewall/BridgePackageManager.java | |
@@ -0,0 +1,576 @@ | |
+package org.chromium.base.firewall; | |
+ | |
+import android.content.ComponentName; | |
+import android.content.Intent; | |
+import android.content.IntentFilter; | |
+import android.content.pm.ActivityInfo; | |
+import android.content.pm.ApplicationInfo; | |
+import android.content.pm.ChangedPackages; | |
+import android.content.pm.FeatureInfo; | |
+import android.content.pm.InstrumentationInfo; | |
+import android.content.pm.PackageInfo; | |
+import android.content.pm.PackageInstaller; | |
+import android.content.pm.PackageManager; | |
+import android.content.pm.PermissionGroupInfo; | |
+import android.content.pm.PermissionInfo; | |
+import android.content.pm.ProviderInfo; | |
+import android.content.pm.ResolveInfo; | |
+import android.content.pm.ServiceInfo; | |
+import android.content.pm.SharedLibraryInfo; | |
+import android.content.pm.VersionedPackage; | |
+import android.content.res.Resources; | |
+import android.content.res.XmlResourceParser; | |
+import android.graphics.Rect; | |
+import android.graphics.drawable.Drawable; | |
+import android.os.UserHandle; | |
+import android.os.Bundle; | |
+ | |
+import java.util.List; | |
+import java.util.Set; | |
+ | |
+import org.chromium.base.Log; | |
+ | |
+// see base/test/android/javatests/src/org/chromium/base/test/util/PackageManagerWrapper.java | |
+ | |
+public class BridgePackageManager extends PackageManager { | |
+ private static final String TAG = "BridgePackageManager"; | |
+ | |
+ private PackageManager mWrapped; | |
+ | |
+ public static void dumpIntent(Intent i){ | |
+ Log.i(TAG, " " + i.toUri(0)); | |
+ | |
+ Bundle bundle = i.getExtras(); | |
+ if (bundle != null) { | |
+ Set<String> keys = bundle.keySet(); | |
+ for (String key : keys) { | |
+ Log.i(TAG, " --> " + key + " = " + bundle.get(key)); | |
+ } | |
+ } | |
+ } | |
+ | |
+ public BridgePackageManager(PackageManager wrapped) { | |
+ super(); | |
+ mWrapped = wrapped; | |
+ Log.i(TAG, "Initialized"); | |
+ } | |
+ | |
+ @Override | |
+ @Deprecated | |
+ public void addPackageToPreferred(String packageName) { | |
+ mWrapped.addPackageToPreferred(packageName); | |
+ } | |
+ | |
+ @Override | |
+ public boolean addPermission(PermissionInfo info) { | |
+ return mWrapped.addPermission(info); | |
+ } | |
+ | |
+ @Override | |
+ public boolean addPermissionAsync(PermissionInfo info) { | |
+ return mWrapped.addPermissionAsync(info); | |
+ } | |
+ | |
+ @Override | |
+ @Deprecated | |
+ public void addPreferredActivity( | |
+ IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { | |
+ mWrapped.addPreferredActivity(filter, match, set, activity); | |
+ } | |
+ | |
+ @Override | |
+ public String[] canonicalToCurrentPackageNames(String[] names) { | |
+ return mWrapped.canonicalToCurrentPackageNames(names); | |
+ } | |
+ | |
+ @Override | |
+ public int checkPermission(String permName, String pkgName) { | |
+ return mWrapped.checkPermission(permName, pkgName); | |
+ } | |
+ | |
+ @Override | |
+ public int checkSignatures(String pkg1, String pkg2) { | |
+ return mWrapped.checkSignatures(pkg1, pkg2); | |
+ } | |
+ | |
+ @Override | |
+ public int checkSignatures(int uid1, int uid2) { | |
+ return mWrapped.checkSignatures(uid1, uid2); | |
+ } | |
+ | |
+ @Override | |
+ public void clearInstantAppCookie() { | |
+ mWrapped.clearInstantAppCookie(); | |
+ } | |
+ | |
+ @Override | |
+ public String[] currentToCanonicalPackageNames(String[] names) { | |
+ return mWrapped.currentToCanonicalPackageNames(names); | |
+ } | |
+ | |
+ @Override | |
+ public ActivityInfo getActivityInfo(ComponentName component, int flags) | |
+ throws NameNotFoundException { | |
+ return mWrapped.getActivityInfo(component, flags); | |
+ } | |
+ | |
+ @Override | |
+ public List<PermissionGroupInfo> getAllPermissionGroups(int flags) { | |
+ return mWrapped.getAllPermissionGroups(flags); | |
+ } | |
+ | |
+ @Override | |
+ public ApplicationInfo getApplicationInfo(String packageName, int flags) | |
+ throws NameNotFoundException { | |
+ Log.i(TAG, "getApplicationInfo %s", packageName); | |
+ return mWrapped.getApplicationInfo(packageName, flags); | |
+ } | |
+ | |
+ @Override | |
+ public List<PackageInfo> getInstalledPackages(int flags) { | |
+ return mWrapped.getInstalledPackages(flags); | |
+ } | |
+ | |
+ @Override | |
+ public Intent getLaunchIntentForPackage(String packageName) { | |
+ return mWrapped.getLaunchIntentForPackage(packageName); | |
+ } | |
+ | |
+ @Override | |
+ public Intent getLeanbackLaunchIntentForPackage(String packageName) { | |
+ return mWrapped.getLeanbackLaunchIntentForPackage(packageName); | |
+ } | |
+ | |
+ @Override | |
+ public int[] getPackageGids(String packageName) throws NameNotFoundException { | |
+ return mWrapped.getPackageGids(packageName); | |
+ } | |
+ | |
+ @Override | |
+ public int[] getPackageGids(String packageName, int flags) throws NameNotFoundException { | |
+ return mWrapped.getPackageGids(packageName, flags); | |
+ } | |
+ | |
+ @Override | |
+ public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException { | |
+ Log.i(TAG, "getPackageInfo %s", packageName); | |
+ if (packageName.equals("com.google.android.gms")) return null; | |
+ return mWrapped.getPackageInfo(packageName, flags); | |
+ } | |
+ | |
+ @Override | |
+ public int getPackageUid(String packageName, int flags) throws NameNotFoundException { | |
+ return mWrapped.getPackageUid(packageName, flags); | |
+ } | |
+ | |
+ @Override | |
+ public List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, int flags) { | |
+ return mWrapped.getPackagesHoldingPermissions(permissions, flags); | |
+ } | |
+ | |
+ @Override | |
+ public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) | |
+ throws NameNotFoundException { | |
+ return mWrapped.getPermissionGroupInfo(name, flags); | |
+ } | |
+ | |
+ @Override | |
+ public PermissionInfo getPermissionInfo(String name, int flags) throws NameNotFoundException { | |
+ return mWrapped.getPermissionInfo(name, flags); | |
+ } | |
+ | |
+ @Override | |
+ public ProviderInfo getProviderInfo(ComponentName component, int flags) | |
+ throws NameNotFoundException { | |
+ return mWrapped.getProviderInfo(component, flags); | |
+ } | |
+ | |
+ @Override | |
+ public ActivityInfo getReceiverInfo(ComponentName component, int flags) | |
+ throws NameNotFoundException { | |
+ return mWrapped.getReceiverInfo(component, flags); | |
+ } | |
+ | |
+ @Override | |
+ public ServiceInfo getServiceInfo(ComponentName component, int flags) | |
+ throws NameNotFoundException { | |
+ Log.i(TAG, "getServiceInfo " + component.flattenToString()); | |
+ return mWrapped.getServiceInfo(component, flags); | |
+ } | |
+ | |
+ @Override | |
+ public boolean isPermissionRevokedByPolicy(String permName, String pkgName) { | |
+ Log.i(TAG, "isPermissionRevokedByPolicy " + permName); | |
+ return mWrapped.isPermissionRevokedByPolicy(permName, pkgName); | |
+ } | |
+ | |
+ @Override | |
+ public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) | |
+ throws NameNotFoundException { | |
+ return mWrapped.queryPermissionsByGroup(group, flags); | |
+ } | |
+ | |
+ @Override | |
+ public void removePermission(String name) { | |
+ mWrapped.removePermission(name); | |
+ } | |
+ | |
+ @Override | |
+ public String[] getPackagesForUid(int uid) { | |
+ return mWrapped.getPackagesForUid(uid); | |
+ } | |
+ | |
+ @Override | |
+ public String getNameForUid(int uid) { | |
+ String value = mWrapped.getNameForUid(uid); | |
+ Log.i(TAG, "getNameForUid " + uid + "=" + value); | |
+ return value; | |
+ } | |
+ | |
+ @Override | |
+ public List<ApplicationInfo> getInstalledApplications(int flags) { | |
+ return mWrapped.getInstalledApplications(flags); | |
+ } | |
+ | |
+ @Override | |
+ public String[] getSystemSharedLibraryNames() { | |
+ return mWrapped.getSystemSharedLibraryNames(); | |
+ } | |
+ | |
+ @Override | |
+ public FeatureInfo[] getSystemAvailableFeatures() { | |
+ return mWrapped.getSystemAvailableFeatures(); | |
+ } | |
+ | |
+ @Override | |
+ public boolean hasSystemFeature(String name) { | |
+ boolean value = mWrapped.hasSystemFeature(name); | |
+ Log.i(TAG, "hasSystemFeature " + name + "=" + value); | |
+ return value; | |
+ } | |
+ | |
+ @Override | |
+ public boolean hasSystemFeature(String name, int version) { | |
+ return mWrapped.hasSystemFeature(name, version); | |
+ } | |
+ | |
+ @Override | |
+ public ResolveInfo resolveActivity(Intent intent, int flags) { | |
+ Log.i(TAG, "resolveActivity"); | |
+ dumpIntent(intent); | |
+ return mWrapped.resolveActivity(intent, flags); | |
+ } | |
+ | |
+ @Override | |
+ public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { | |
+ Log.i(TAG, "queryIntentActivities"); | |
+ dumpIntent(intent); | |
+ return mWrapped.queryIntentActivities(intent, flags); | |
+ } | |
+ | |
+ @Override | |
+ public List<ResolveInfo> queryIntentActivityOptions( | |
+ ComponentName caller, Intent[] specifics, Intent intent, int flags) { | |
+ return mWrapped.queryIntentActivityOptions(caller, specifics, intent, flags); | |
+ } | |
+ | |
+ @Override | |
+ public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) { | |
+ return mWrapped.queryBroadcastReceivers(intent, flags); | |
+ } | |
+ | |
+ @Override | |
+ public ResolveInfo resolveService(Intent intent, int flags) { | |
+ Log.i(TAG, "resolveService"); | |
+ dumpIntent(intent); | |
+ return mWrapped.resolveService(intent, flags); | |
+ } | |
+ | |
+ @Override | |
+ public List<ResolveInfo> queryIntentServices(Intent intent, int flags) { | |
+ Log.i(TAG, "queryIntentServices"); | |
+ dumpIntent(intent); | |
+ return mWrapped.queryIntentServices(intent, flags); | |
+ } | |
+ | |
+ @Override | |
+ public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) { | |
+ return mWrapped.queryIntentContentProviders(intent, flags); | |
+ } | |
+ | |
+ @Override | |
+ public ProviderInfo resolveContentProvider(String name, int flags) { | |
+ return mWrapped.resolveContentProvider(name, flags); | |
+ } | |
+ | |
+ @Override | |
+ public List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) { | |
+ return mWrapped.queryContentProviders(processName, uid, flags); | |
+ } | |
+ | |
+ @Override | |
+ public InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags) | |
+ throws NameNotFoundException { | |
+ return mWrapped.getInstrumentationInfo(className, flags); | |
+ } | |
+ | |
+ @Override | |
+ public List<InstrumentationInfo> queryInstrumentation(String targetPackage, int flags) { | |
+ return mWrapped.queryInstrumentation(targetPackage, flags); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getDrawable(String packageName, int resid, ApplicationInfo appInfo) { | |
+ return mWrapped.getDrawable(packageName, resid, appInfo); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getActivityIcon(ComponentName activityName) throws NameNotFoundException { | |
+ return mWrapped.getActivityIcon(activityName); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getActivityIcon(Intent intent) throws NameNotFoundException { | |
+ return mWrapped.getActivityIcon(intent); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getActivityBanner(ComponentName activityName) throws NameNotFoundException { | |
+ return mWrapped.getActivityBanner(activityName); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getActivityBanner(Intent intent) throws NameNotFoundException { | |
+ return mWrapped.getActivityBanner(intent); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getDefaultActivityIcon() { | |
+ return mWrapped.getDefaultActivityIcon(); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getApplicationIcon(ApplicationInfo info) { | |
+ return mWrapped.getApplicationIcon(info); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getApplicationIcon(String packageName) throws NameNotFoundException { | |
+ return mWrapped.getApplicationIcon(packageName); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getApplicationBanner(ApplicationInfo info) { | |
+ return mWrapped.getApplicationBanner(info); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getApplicationBanner(String packageName) throws NameNotFoundException { | |
+ return mWrapped.getApplicationBanner(packageName); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getActivityLogo(ComponentName activityName) throws NameNotFoundException { | |
+ return mWrapped.getActivityLogo(activityName); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getActivityLogo(Intent intent) throws NameNotFoundException { | |
+ return mWrapped.getActivityLogo(intent); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getApplicationLogo(ApplicationInfo info) { | |
+ return mWrapped.getApplicationLogo(info); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getApplicationLogo(String packageName) throws NameNotFoundException { | |
+ return mWrapped.getApplicationLogo(packageName); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) { | |
+ return mWrapped.getUserBadgedIcon(icon, user); | |
+ } | |
+ | |
+ @Override | |
+ public Drawable getUserBadgedDrawableForDensity( | |
+ Drawable drawable, UserHandle user, Rect badgeLocation, int badgeDensity) { | |
+ return mWrapped.getUserBadgedDrawableForDensity( | |
+ drawable, user, badgeLocation, badgeDensity); | |
+ } | |
+ | |
+ @Override | |
+ public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) { | |
+ return mWrapped.getUserBadgedLabel(label, user); | |
+ } | |
+ | |
+ @Override | |
+ public CharSequence getText(String packageName, int resid, ApplicationInfo appInfo) { | |
+ return mWrapped.getText(packageName, resid, appInfo); | |
+ } | |
+ | |
+ @Override | |
+ public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) { | |
+ return mWrapped.getXml(packageName, resid, appInfo); | |
+ } | |
+ | |
+ @Override | |
+ public CharSequence getApplicationLabel(ApplicationInfo info) { | |
+ return mWrapped.getApplicationLabel(info); | |
+ } | |
+ | |
+ @Override | |
+ public Resources getResourcesForActivity(ComponentName activityName) | |
+ throws NameNotFoundException { | |
+ return mWrapped.getResourcesForActivity(activityName); | |
+ } | |
+ | |
+ @Override | |
+ public Resources getResourcesForApplication(ApplicationInfo app) throws NameNotFoundException { | |
+ Log.i(TAG, "getResourcesForApplication"); | |
+ return mWrapped.getResourcesForApplication(app); | |
+ } | |
+ | |
+ @Override | |
+ public Resources getResourcesForApplication(String appPackageName) | |
+ throws NameNotFoundException { | |
+ return mWrapped.getResourcesForApplication(appPackageName); | |
+ } | |
+ | |
+ @Override | |
+ public void verifyPendingInstall(int id, int verificationCode) { | |
+ mWrapped.verifyPendingInstall(id, verificationCode); | |
+ } | |
+ | |
+ @Override | |
+ public void extendVerificationTimeout( | |
+ int id, int verificationCodeAtTimeout, long millisecondsToDelay) { | |
+ mWrapped.extendVerificationTimeout(id, verificationCodeAtTimeout, millisecondsToDelay); | |
+ } | |
+ | |
+ @Override | |
+ public void setInstallerPackageName(String targetPackage, String installerPackageName) { | |
+ mWrapped.setInstallerPackageName(targetPackage, installerPackageName); | |
+ } | |
+ | |
+ @Override | |
+ public String getInstallerPackageName(String packageName) { | |
+ Log.i(TAG, "getInstallerPackageName %s", packageName); | |
+ return mWrapped.getInstallerPackageName(packageName); | |
+ } | |
+ | |
+ @Deprecated | |
+ @Override | |
+ public void removePackageFromPreferred(String packageName) { | |
+ mWrapped.removePackageFromPreferred(packageName); | |
+ } | |
+ | |
+ @Override | |
+ public List<PackageInfo> getPreferredPackages(int flags) { | |
+ return mWrapped.getPreferredPackages(flags); | |
+ } | |
+ | |
+ @Override | |
+ public void clearPackagePreferredActivities(String packageName) { | |
+ mWrapped.clearPackagePreferredActivities(packageName); | |
+ } | |
+ | |
+ @Override | |
+ public int getPreferredActivities( | |
+ List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName) { | |
+ return mWrapped.getPreferredActivities(outFilters, outActivities, packageName); | |
+ } | |
+ | |
+ @Override | |
+ public void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) { | |
+ mWrapped.setComponentEnabledSetting(componentName, newState, flags); | |
+ } | |
+ | |
+ @Override | |
+ public int getComponentEnabledSetting(ComponentName componentName) { | |
+ return mWrapped.getComponentEnabledSetting(componentName); | |
+ } | |
+ | |
+ @Override | |
+ public void setApplicationEnabledSetting(String packageName, int newState, int flags) { | |
+ mWrapped.setApplicationEnabledSetting(packageName, newState, flags); | |
+ } | |
+ | |
+ @Override | |
+ public int getApplicationEnabledSetting(String packageName) { | |
+ return mWrapped.getApplicationEnabledSetting(packageName); | |
+ } | |
+ | |
+ @Override | |
+ public boolean isSafeMode() { | |
+ return mWrapped.isSafeMode(); | |
+ } | |
+ | |
+ @Override | |
+ public PackageInstaller getPackageInstaller() { | |
+ return mWrapped.getPackageInstaller(); | |
+ } | |
+ | |
+ // O Developer Preview | |
+ | |
+ @Override | |
+ public boolean canRequestPackageInstalls() { | |
+ return mWrapped.canRequestPackageInstalls(); | |
+ } | |
+ | |
+ @Override | |
+ public ChangedPackages getChangedPackages(int sequenceNumber) { | |
+ return mWrapped.getChangedPackages(sequenceNumber); | |
+ } | |
+ | |
+ @Override | |
+ public byte[] getInstantAppCookie() { | |
+ return mWrapped.getInstantAppCookie(); | |
+ } | |
+ | |
+ @Override | |
+ public int getInstantAppCookieMaxBytes() { | |
+ return mWrapped.getInstantAppCookieMaxBytes(); | |
+ } | |
+ | |
+ @Override | |
+ public PackageInfo getPackageInfo(VersionedPackage versionedPackage, int flags) | |
+ throws PackageManager.NameNotFoundException { | |
+ return mWrapped.getPackageInfo(versionedPackage, flags); | |
+ } | |
+ | |
+ @Override | |
+ public List<SharedLibraryInfo> getSharedLibraries(int flags) { | |
+ return mWrapped.getSharedLibraries(flags); | |
+ } | |
+ | |
+ @Override | |
+ public boolean isInstantApp() { | |
+ return mWrapped.isInstantApp(); | |
+ } | |
+ | |
+ @Override | |
+ public boolean isInstantApp(String packageName) { | |
+ return mWrapped.isInstantApp(packageName); | |
+ } | |
+ | |
+ @Override | |
+ public void setApplicationCategoryHint(String packageName, int categoryHint) { | |
+ mWrapped.setApplicationCategoryHint(packageName, categoryHint); | |
+ } | |
+ | |
+ @Override | |
+ public void updateInstantAppCookie(byte[] cookie) { | |
+ mWrapped.updateInstantAppCookie(cookie); | |
+ } | |
+ | |
+ // This is a hidden abstract method in the base class so we can't mark it as | |
+ // overridden, or call the real implementation without reflection. Nothing | |
+ // currently seems to actually care about the result of this function under | |
+ // testing, so we can just return null for now. | |
+ protected Drawable getUserBadgeForDensity(UserHandle userHandle, int i) { | |
+ return null; | |
+ } | |
+} | |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java | |
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java | |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java | |
@@ -39,6 +39,9 @@ import org.chromium.ui.modaldialog.ModalDialogManager; | |
import org.chromium.ui.modaldialog.ModalDialogManagerHolder; | |
import java.util.LinkedHashSet; | |
+import android.content.Intent; | |
+import org.chromium.base.Log; | |
+import org.chromium.base.firewall.BridgePackageManager; | |
/** | |
* A subclass of {@link AppCompatActivity} that maintains states and objects applied to all | |
@@ -52,6 +55,20 @@ public class ChromeBaseAppCompatActivity extends AppCompatActivity | |
private LinkedHashSet<Integer> mThemeResIds = new LinkedHashSet<>(); | |
private ServiceTracingProxyProvider mServiceTracingProxyProvider; | |
+ @Override | |
+ public void startActivity(Intent intent) { | |
+ Log.i("", "---ChromeBaseAppCompatActivity.startActivity1"); | |
+ BridgePackageManager.dumpIntent(intent); | |
+ super.startActivity(intent); | |
+ } | |
+ | |
+ @Override | |
+ public void startActivity(Intent intent, @Nullable Bundle options) { | |
+ Log.i("", "---ChromeBaseAppCompatActivity.startActivity2"); | |
+ BridgePackageManager.dumpIntent(intent); | |
+ super.startActivity(intent, options); | |
+ } | |
+ | |
@Override | |
protected void attachBaseContext(Context newBase) { | |
super.attachBaseContext(newBase); | |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java | |
--- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java | |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java | |
@@ -20,6 +20,7 @@ import org.chromium.base.BundleUtils; | |
import org.chromium.base.CommandLineInitUtil; | |
import org.chromium.base.ContextUtils; | |
import org.chromium.base.EarlyTraceEvent; | |
+import org.chromium.base.firewall.BridgeContextWrapper; | |
import org.chromium.base.JNIUtils; | |
import org.chromium.base.LocaleUtils; | |
import org.chromium.base.Log; | |
@@ -288,6 +289,7 @@ public class SplitCompatApplication extends Application { | |
/** Creates a context which can be used to load code and resources in the chrome split. */ | |
public static Context createChromeContext(Context base) { | |
+ base = BridgeContextWrapper.wrap(base); | |
if (!BundleUtils.isIsolatedSplitInstalled(CHROME_SPLIT_NAME)) { | |
return base; | |
} | |
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java | |
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java | |
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java | |
@@ -79,6 +79,8 @@ import java.util.Iterator; | |
import java.util.List; | |
import java.util.Set; | |
import java.util.concurrent.atomic.AtomicBoolean; | |
+import org.chromium.base.firewall.BridgeContextWrapper; | |
+import org.chromium.base.firewall.BridgePackageManager; | |
/** | |
* Logic related to the URL overriding/intercepting functionality. | |
@@ -457,7 +459,7 @@ public class ExternalNavigationHandler { | |
} | |
private static boolean debug() { | |
- return ExternalIntentsFeatures.EXTERNAL_NAVIGATION_DEBUG_LOGS.isEnabled(); | |
+ return true; //ExternalIntentsFeatures.EXTERNAL_NAVIGATION_DEBUG_LOGS.isEnabled(); | |
} | |
/** | |
@@ -1621,6 +1623,8 @@ public class ExternalNavigationHandler { | |
return OverrideUrlLoadingResult.forNoOverride(); | |
} | |
+ //navigationChainResult = NavigationChainResult.REQUIRES_PROMPT; | |
+ | |
// From this point on, we have determined it is safe to launch an External App from a | |
// fallback URL (unless we have to prompt). | |
if (navigationChainResult == NavigationChainResult.ALLOWED) { | |
@@ -1663,10 +1667,10 @@ public class ExternalNavigationHandler { | |
targetIntent.getExtras() != null && !targetIntent.getExtras().isEmpty(); | |
prepareExternalIntent(targetIntent, params, resolvingInfos.get()); | |
- if (params.isIncognito()) { | |
- return handleIncognitoIntent( | |
- params, targetIntent, intentDataUrl, resolvingInfos.get(), browserFallbackUrl); | |
- } | |
+ // if ((true)) { //params.isIncognito()) { | |
+ // return handleIncognitoIntent( | |
+ // params, targetIntent, intentDataUrl, resolvingInfos.get(), browserFallbackUrl); | |
+ // } | |
if (launchWebApkIfSoleIntentHandler(resolvingInfos, targetIntent, params)) { | |
return OverrideUrlLoadingResult.forExternalIntent(); | |
@@ -1683,12 +1687,14 @@ public class ExternalNavigationHandler { | |
isExternalProtocol, intentDataUrl, resolvingInfos, resolveActivity)) { | |
return OverrideUrlLoadingResult.forNoOverride(); | |
} | |
+ // | |
if (navigationChainResult == NavigationChainResult.REQUIRES_PROMPT) { | |
return maybeAskToLaunchApp(isExternalProtocol, targetIntent, resolvingInfos, | |
resolveActivity, browserFallbackUrl, params); | |
} | |
} | |
+ Log.i("", "---shouldOverrideUrlLoadingInternal"); | |
return startActivity(targetIntent, requiresIntentChooser, resolvingInfos, resolveActivity, | |
browserFallbackUrl, intentDataUrl, params); | |
} | |
@@ -2051,6 +2057,11 @@ public class ExternalNavigationHandler { | |
context = ContextUtils.getApplicationContext(); | |
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
} | |
+ // if (context != null) { | |
+ // Log.i("", "--- startActivity1"); | |
+ // // during startup context maybe null | |
+ // requiresIntentChooser = true; | |
+ // } | |
if (requiresIntentChooser) { | |
return startActivityWithChooser(intent, resolvingInfos, resolveActivity, | |
browserFallbackUrl, intentDataUrl, params, context); | |
@@ -2078,6 +2089,8 @@ public class ExternalNavigationHandler { | |
private OverrideUrlLoadingResult doStartActivity(Intent intent, Context context) { | |
if (debug()) Log.i(TAG, "startActivity"); | |
+ Log.i(TAG, "isBridgeContextWrapper = " + BridgeContextWrapper.isBridgeContextWrapper(context)); | |
+ BridgePackageManager.dumpIntent(intent); | |
context.startActivity(intent); | |
recordExternalNavigationDispatched(intent); | |
return OverrideUrlLoadingResult.forExternalIntent(); | |
@@ -2192,6 +2205,99 @@ public class ExternalNavigationHandler { | |
OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH); | |
} | |
+ protected OverrideUrlLoadingResult askToLaunchApp(boolean isExternalProtocol, | |
+ Intent targetIntent, QueryIntentActivitiesSupplier resolvingInfos, | |
+ ResolveActivitySupplier resolveActivity, GURL browserFallbackUrl, | |
+ ExternalNavigationParams params) { | |
+ // For URLs the browser supports, we shouldn't have reached here. | |
+ //assert isExternalProtocol; | |
+ | |
+ // Use the fallback URL if we have it, otherwise we give sites a fingerprinting mechanism | |
+ // where they can repeatedly attempt to launch apps without a user gesture until they find | |
+ // one the user has installed. | |
+ //if (!browserFallbackUrl.isEmpty()) return OverrideUrlLoadingResult.forNoOverride(); | |
+ | |
+ ResolveInfo intentResolveInfo = resolveActivity.get(); | |
+ | |
+ // No app can resolve the intent, don't prompt. | |
+ if (intentResolveInfo == null || intentResolveInfo.activityInfo == null) { | |
+ if (debug()) Log.i(TAG, "Message doesn't resolve to any app."); | |
+ return OverrideUrlLoadingResult.forNoOverride(); | |
+ } | |
+ | |
+ // If the |resolvingInfos| from queryIntentActivities don't contain the result of | |
+ // resolveActivity, it means there's no default handler for the intent and it's resolving to | |
+ // the ResolverActivity. This means we can't know which app will be launched and can't | |
+ // convey that to the user. We also don't want to just allow the chooser dialog to be shown | |
+ // when the external navigation was otherwise blocked. In this case, we should just continue | |
+ // to block the navigation, and sites hoping to prompt the user when navigation fails should | |
+ // make sure to correctly target their app. | |
+ if (resolvesToChooser(intentResolveInfo, resolvingInfos)) { | |
+ if (debug()) Log.i(TAG, "Message resolves to multiple apps."); | |
+ return OverrideUrlLoadingResult.forNoOverride(); | |
+ } | |
+ | |
+ MessageDispatcher messageDispatcher = | |
+ MessageDispatcherProvider.from(mDelegate.getWindowAndroid()); | |
+ WebContents webContents = mDelegate.getWebContents(); | |
+ if (messageDispatcher == null || webContents == null) { | |
+ if (debug()) Log.i(TAG, "No WebContents to show Message for."); | |
+ return OverrideUrlLoadingResult.forNoOverride(); | |
+ } | |
+ | |
+ String packageName = intentResolveInfo.activityInfo.packageName; | |
+ PackageManager pm = mDelegate.getContext().getPackageManager(); | |
+ ApplicationInfo applicationInfo = null; | |
+ try { | |
+ applicationInfo = pm.getApplicationInfo(packageName, 0); | |
+ } catch (NameNotFoundException e) { | |
+ return OverrideUrlLoadingResult.forNoOverride(); | |
+ } | |
+ | |
+ Drawable icon = pm.getApplicationLogo(applicationInfo); | |
+ if (icon == null) icon = pm.getApplicationIcon(applicationInfo); | |
+ CharSequence label = pm.getApplicationLabel(applicationInfo); | |
+ | |
+ Resources res = mDelegate.getContext().getResources(); | |
+ String title = res.getString(R.string.external_navigation_continue_to_title, label); | |
+ String description = | |
+ res.getString(R.string.external_navigation_continue_to_description, label); | |
+ String action = res.getString(R.string.external_navigation_continue_to_action); | |
+ | |
+ PropertyModel message = | |
+ new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS) | |
+ .with(MessageBannerProperties.MESSAGE_IDENTIFIER, | |
+ MessageIdentifier.EXTERNAL_NAVIGATION) | |
+ .with(MessageBannerProperties.TITLE, title) | |
+ .with(MessageBannerProperties.DESCRIPTION, description) | |
+ .with(MessageBannerProperties.ICON, icon) | |
+ .with(MessageBannerProperties.PRIMARY_BUTTON_TEXT, action) | |
+ .with(MessageBannerProperties.ICON_TINT_COLOR, | |
+ MessageBannerProperties.TINT_NONE) | |
+ .with(MessageBannerProperties.ON_PRIMARY_ACTION, | |
+ () -> { | |
+ startActivity(targetIntent); | |
+ if (params.getRequiredAsyncActionTakenCallback() != null) { | |
+ params.getRequiredAsyncActionTakenCallback().onResult( | |
+ AsyncActionTakenParams.forExternalIntentLaunched( | |
+ true, params)); | |
+ } | |
+ return PrimaryActionClickBehavior.DISMISS_IMMEDIATELY; | |
+ }) | |
+ .with(MessageBannerProperties.ON_DISMISSED, | |
+ (dismissReason) -> { | |
+ if (dismissReason == DismissReason.PRIMARY_ACTION) return; | |
+ if (params.getRequiredAsyncActionTakenCallback() != null) { | |
+ params.getRequiredAsyncActionTakenCallback().onResult( | |
+ AsyncActionTakenParams.forNoAction()); | |
+ } | |
+ }) | |
+ .build(); | |
+ messageDispatcher.enqueueMessage(message, webContents, MessageScopeType.NAVIGATION, false); | |
+ return OverrideUrlLoadingResult.forAsyncAction( | |
+ OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH); | |
+ } | |
+ | |
protected OverrideUrlLoadingResult maybeAskToLaunchApp(boolean isExternalProtocol, | |
Intent targetIntent, QueryIntentActivitiesSupplier resolvingInfos, | |
ResolveActivitySupplier resolveActivity, GURL browserFallbackUrl, | |
diff --git a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java | |
--- a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java | |
+++ b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java | |
@@ -45,6 +45,7 @@ import org.chromium.base.annotations.JNINamespace; | |
import org.chromium.base.annotations.NativeMethods; | |
import org.chromium.base.compat.ApiHelperForO; | |
import org.chromium.base.compat.ApiHelperForOMR1; | |
+import org.chromium.base.firewall.BridgeContextWrapper; | |
import org.chromium.ui.KeyboardVisibilityDelegate; | |
import org.chromium.ui.display.DisplayAndroid; | |
import org.chromium.ui.display.DisplayAndroid.DisplayAndroidObserver; | |
@@ -838,6 +839,8 @@ public class WindowAndroid implements AndroidPermissionDelegate, DisplayAndroidO | |
}); | |
} | |
+ private ImmutableWeakReference<Context> mBridgeContextRef; | |
+ | |
/** | |
* Getter for the current context (not necessarily the application context). | |
* Make no assumptions regarding what type of Context is returned here, it could be for example | |
@@ -845,6 +848,16 @@ public class WindowAndroid implements AndroidPermissionDelegate, DisplayAndroidO | |
* The returned WeakReference is immutable and calling clear will throw an exception. | |
*/ | |
public WeakReference<Context> getContext() { | |
+ if (mContextRef != null) { | |
+ Context ctx = mContextRef.get(); | |
+ if (ctx != null) { | |
+ if (mBridgeContextRef == null || mBridgeContextRef.get() == null) { | |
+ mBridgeContextRef = | |
+ new ImmutableWeakReference<>(BridgeContextWrapper.wrap(ctx)); | |
+ } | |
+ return mBridgeContextRef; | |
+ } | |
+ } | |
return mContextRef; | |
} | |
-- | |
2.25.1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment