зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1549418 - Add GeckoRuntime.ActivityDelegate r=geckoview-reviewers,agi,esawin
This allows GeckoView to ask the embedding application to launch other Activities on our behalf and collect the result. We need this to invoke the FIDO authentication tools for WebAuthn. Differential Revision: https://phabricator.services.mozilla.com/D91445
This commit is contained in:
Родитель
479ef2392a
Коммит
4312bd0da2
|
@ -1,4 +1,5 @@
|
|||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
|
@ -563,6 +564,7 @@ package org.mozilla.geckoview {
|
|||
method @UiThread public void configurationChanged(@NonNull Configuration);
|
||||
method @UiThread @NonNull public static GeckoRuntime create(@NonNull Context);
|
||||
method @UiThread @NonNull public static GeckoRuntime create(@NonNull Context, @NonNull GeckoRuntimeSettings);
|
||||
method @UiThread @Nullable public GeckoRuntime.ActivityDelegate getActivityDelegate();
|
||||
method @UiThread @NonNull public ContentBlockingController getContentBlockingController();
|
||||
method @UiThread @NonNull public static synchronized GeckoRuntime getDefault(@NonNull Context);
|
||||
method @UiThread @Nullable public GeckoRuntime.Delegate getDelegate();
|
||||
|
@ -577,6 +579,7 @@ package org.mozilla.geckoview {
|
|||
method @UiThread public void orientationChanged();
|
||||
method @UiThread public void orientationChanged(int);
|
||||
method @AnyThread public void readFromParcel(@NonNull Parcel);
|
||||
method @UiThread public void setActivityDelegate(@Nullable GeckoRuntime.ActivityDelegate);
|
||||
method @UiThread public void setDelegate(@Nullable GeckoRuntime.Delegate);
|
||||
method @UiThread public void setLoginStorageDelegate(@Nullable Autocomplete.LoginStorageDelegate);
|
||||
method @UiThread public void setServiceWorkerDelegate(@Nullable GeckoRuntime.ServiceWorkerDelegate);
|
||||
|
@ -589,6 +592,10 @@ package org.mozilla.geckoview {
|
|||
field public static final String EXTRA_MINIDUMP_PATH = "minidumpPath";
|
||||
}
|
||||
|
||||
public static interface GeckoRuntime.ActivityDelegate {
|
||||
method @UiThread @Nullable public GeckoResult<Intent> onStartActivityForResult(@NonNull PendingIntent);
|
||||
}
|
||||
|
||||
public static interface GeckoRuntime.Delegate {
|
||||
method @UiThread public void onShutdown();
|
||||
}
|
||||
|
|
|
@ -11,7 +11,9 @@ import androidx.lifecycle.Lifecycle;
|
|||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.lifecycle.OnLifecycleEvent;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -166,6 +168,7 @@ public final class GeckoRuntime implements Parcelable {
|
|||
private Delegate mDelegate;
|
||||
private ServiceWorkerDelegate mServiceWorkerDelegate;
|
||||
private WebNotificationDelegate mNotificationDelegate;
|
||||
private ActivityDelegate mActivityDelegate;
|
||||
private StorageController mStorageController;
|
||||
private final WebExtensionController mWebExtensionController;
|
||||
private WebPushController mPushController;
|
||||
|
@ -187,7 +190,7 @@ public final class GeckoRuntime implements Parcelable {
|
|||
|
||||
@WrapForJNI
|
||||
@UiThread
|
||||
private @Nullable static GeckoRuntime getInstance() {
|
||||
/* package */ @Nullable static GeckoRuntime getInstance() {
|
||||
return sRuntime;
|
||||
}
|
||||
|
||||
|
@ -647,6 +650,86 @@ public final class GeckoRuntime implements Parcelable {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to allow GeckoRuntime to start activities via the embedding
|
||||
* application (and {@link android.app.Activity}). Currently this is used to invoke the
|
||||
* Google Play FIDO Activity in order to integrate with the Web Authentication API.
|
||||
*
|
||||
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API">Web Authentication API</a>
|
||||
*/
|
||||
public interface ActivityDelegate {
|
||||
/**
|
||||
* Sometimes GeckoView needs the application to perform a
|
||||
* {@link android.app.Activity#startActivityForResult(Intent, int)}
|
||||
* on its behalf. Implementations of this method should call that based on the information
|
||||
* in the passed {@link PendingIntent}, collect the result, and resolve the returned
|
||||
* {@link GeckoResult} with that data. If the
|
||||
* Activity does not return {@link android.app.Activity#RESULT_OK}, the {@link GeckoResult}
|
||||
* must be completed with an exception of your choosing.
|
||||
*
|
||||
* @param intent The {@link PendingIntent} to launch
|
||||
* @return A {@link GeckoResult} that is eventually resolved with the Activity result.
|
||||
*/
|
||||
@UiThread
|
||||
@Nullable GeckoResult<Intent> onStartActivityForResult(@NonNull PendingIntent intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ActivityDelegate} instance on this runtime.
|
||||
* This delegate is used to provide GeckoView support for launching external
|
||||
* activities and receiving results from those activities.
|
||||
*
|
||||
* @param delegate The {@link ActivityDelegate} handling intent launching requests.
|
||||
*/
|
||||
@UiThread
|
||||
public void setActivityDelegate(
|
||||
final @Nullable ActivityDelegate delegate) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
mActivityDelegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link ActivityDelegate} instance set on this runtime, if any,
|
||||
*
|
||||
* @return The {@link ActivityDelegate} set on this runtime.
|
||||
*/
|
||||
@UiThread
|
||||
public @Nullable ActivityDelegate getActivityDelegate() {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
return mActivityDelegate;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
/* package */ GeckoResult<Intent> startActivityForResult(final @NonNull PendingIntent intent) {
|
||||
if (!ThreadUtils.isOnUiThread()) {
|
||||
// Delegates expect to be called on the UI thread.
|
||||
final GeckoResult<Intent> result = new GeckoResult<>();
|
||||
|
||||
ThreadUtils.runOnUiThread(() -> {
|
||||
final GeckoResult<Intent> delegateResult = startActivityForResult(intent);
|
||||
if (delegateResult != null) {
|
||||
delegateResult.accept(val -> result.complete(val), e -> result.completeExceptionally(e));
|
||||
} else {
|
||||
result.completeExceptionally(new IllegalStateException("No result"));
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (mActivityDelegate == null) {
|
||||
return GeckoResult.fromException(new IllegalStateException("No delegate attached"));
|
||||
}
|
||||
|
||||
@SuppressLint("WrongThread")
|
||||
GeckoResult<Intent> result = mActivityDelegate.onStartActivityForResult(intent);
|
||||
if (result == null) {
|
||||
result = GeckoResult.fromException(new IllegalStateException("No result"));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@SuppressWarnings("checkstyle:javadocmethod")
|
||||
public @NonNull GeckoRuntimeSettings getSettings() {
|
||||
|
|
|
@ -26,10 +26,14 @@ exclude: true
|
|||
- Added [`ContentBlocking.SafeBrowsingProvider`][83.3] to configure Safe
|
||||
Browsing providers.
|
||||
([bug 1660241]({{bugzilla}}1660241))
|
||||
- Added [`GeckoRuntime.ActivityDelegate`][83.4] which allows applications to handle
|
||||
starting external Activities on behalf of GeckoView. Currently this is used to integrate
|
||||
FIDO support for WebAuthn.
|
||||
|
||||
[83.1]: {{javadoc_uri}}/WebExtension.MetaData.html#temporary
|
||||
[83.2]: {{javadoc_uri}}/MediaSession.Delegate.html#onMetadata-org.mozilla.geckoview.GeckoSession-org.mozilla.geckoview.MediaSession-org.mozilla.geckoview.MediaSession.Metadata-
|
||||
[83.3]: {{javadoc_uri}}/ContentBlocking.SafeBrowsingProvider.html
|
||||
[83.4]: {{javadoc_uri}}/GeckoRuntime.ActivityDelegate.html
|
||||
|
||||
## v82
|
||||
- ⚠️ [`WebNotification.source`][79.2] is now `@Nullable` to account for
|
||||
|
@ -819,4 +823,4 @@ to allow adding gecko profiler markers.
|
|||
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
|
||||
[65.25]: {{javadoc_uri}}/GeckoResult.html
|
||||
|
||||
[api-version]: 2a562a8a5620ba5db90a9e7f59f6396eaeb4356f
|
||||
[api-version]: d3186b70503f71a6476c765f76c6d49f9a1fb282
|
||||
|
|
|
@ -37,6 +37,7 @@ import android.app.NotificationChannel;
|
|||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -418,6 +419,9 @@ public class GeckoViewActivity
|
|||
|
||||
private LinkedList<WebResponse> mPendingDownloads = new LinkedList<>();
|
||||
|
||||
private int mNextActivityResultCode = 10;
|
||||
private HashMap<Integer, GeckoResult<Intent>> mPendingActivityResult = new HashMap<>();
|
||||
|
||||
private LocationView.CommitListener mCommitListener = new LocationView.CommitListener() {
|
||||
@Override
|
||||
public void onCommit(String text) {
|
||||
|
@ -673,6 +677,18 @@ public class GeckoViewActivity
|
|||
mKillProcessOnDestroy = true;
|
||||
finish();
|
||||
});
|
||||
|
||||
sGeckoRuntime.setActivityDelegate(pendingIntent -> {
|
||||
final GeckoResult<Intent> result = new GeckoResult<>();
|
||||
try {
|
||||
final int code = mNextActivityResultCode++;
|
||||
mPendingActivityResult.put(code, result);
|
||||
GeckoViewActivity.this.startIntentSenderForResult(pendingIntent.getIntentSender(), code, null, 0, 0, 0);
|
||||
} catch (IntentSender.SendIntentException e) {
|
||||
result.completeExceptionally(e);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
sExtensionManager.setExtensionDelegate(this);
|
||||
|
@ -1170,6 +1186,14 @@ public class GeckoViewActivity
|
|||
final BasicGeckoViewPrompt prompt = (BasicGeckoViewPrompt)
|
||||
mTabSessionManager.getCurrentSession().getPromptDelegate();
|
||||
prompt.onFileCallbackResult(resultCode, data);
|
||||
} else if (mPendingActivityResult.containsKey(requestCode)) {
|
||||
final GeckoResult<Intent> result = mPendingActivityResult.remove(requestCode);
|
||||
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
result.complete(data);
|
||||
} else {
|
||||
result.completeExceptionally(new RuntimeException("Unknown error"));
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче