Skip to content

Instantly share code, notes, and snippets.

@uazo
Created July 2, 2023 12:46
Show Gist options
  • Save uazo/d8208d8d6fd732cf1173459a4464f143 to your computer and use it in GitHub Desktop.
Save uazo/d8208d8d6fd732cf1173459a4464f143 to your computer and use it in GitHub Desktop.
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