Skip to content

[webview_flutter] Support for handling basic authentication requests (Android) #5454

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 43 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
517e9d4
Implement http basic auth
JeroenWeener Aug 10, 2023
967879b
Apply feedback
JeroenWeener Aug 28, 2023
c8624c0
Create HttpAuthHandlerTest.java
JeroenWeener Aug 29, 2023
4f3574d
Format java files
JeroenWeener Aug 29, 2023
1e7f785
Regenerate build_runner files
JeroenWeener Aug 29, 2023
131bc56
Implement feedback
JeroenWeener Sep 11, 2023
bc01be4
Remove redundant key in `Info.plist`
JeroenWeener Sep 11, 2023
67aa00e
Update example apps
JeroenWeener Sep 11, 2023
32496d0
Implement http basic auth
JeroenWeener Aug 10, 2023
aeb8708
Apply feedback
JeroenWeener Aug 28, 2023
fffc4c7
Create HttpAuthHandlerTest.java
JeroenWeener Aug 29, 2023
b455040
Format java files
JeroenWeener Aug 29, 2023
2aa9bfe
Regenerate build_runner files
JeroenWeener Aug 29, 2023
db286ba
Implement feedback
JeroenWeener Sep 11, 2023
467feb3
Remove redundant key in `Info.plist`
JeroenWeener Sep 11, 2023
dad8ae6
Update example apps
JeroenWeener Sep 11, 2023
6f3d802
Merge branch 'webview-auth-request' of https://github.com/andreisas06…
JeroenWeener Nov 1, 2023
0fef591
Add platform interface dev dependency to example
JeroenWeener Nov 1, 2023
b2a4fbb
Merge branch 'main' into webview-auth-request
JeroenWeener Nov 1, 2023
ce35d9b
Update packages/webview_flutter/webview_flutter_platform_interface/li…
bparrishMines Nov 8, 2023
fc32898
Merge branch 'main' of github.com:flutter/packages into webview-auth-…
bparrishMines Nov 8, 2023
4673e65
Merge branch 'webview-auth-request' of github.com:andreisas06/package…
bparrishMines Nov 8, 2023
580521a
Fix some lints, errros and call on errors
bparrishMines Nov 8, 2023
d1f305b
fix lints
bparrishMines Nov 8, 2023
a3f74be
fix tests
bparrishMines Nov 8, 2023
ed3798f
add onProceed and onCancel back
bparrishMines Nov 8, 2023
154c1f8
dont require realm to be nonnull
bparrishMines Nov 8, 2023
3c61dbc
add line back
bparrishMines Nov 8, 2023
7cf0d7e
Merge remote-tracking branch 'upstream/main' into webview-auth-request
JeroenWeener Nov 21, 2023
a21f29a
Update changelogs
JeroenWeener Nov 21, 2023
284d455
Separate android changes
JeroenWeener Nov 21, 2023
c27986a
Delete packages/webview_flutter/webview_flutter_wkwebview/example/ios…
JeroenWeener Nov 21, 2023
e8634e1
Delete packages/webview_flutter/webview_flutter_wkwebview/example/ios…
JeroenWeener Nov 21, 2023
b28fd8a
Delete packages/webview_flutter/webview_flutter_wkwebview/ios/Classes…
JeroenWeener Nov 21, 2023
a886dd8
Delete packages/webview_flutter/webview_flutter_wkwebview/ios/Classes…
JeroenWeener Nov 21, 2023
a580f4c
Delete packages/webview_flutter/webview_flutter_wkwebview/ios/Classes…
JeroenWeener Nov 21, 2023
e43cb52
Delete packages/webview_flutter/webview_flutter_wkwebview/ios/Classes…
JeroenWeener Nov 21, 2023
fbcd3f9
Delete packages/webview_flutter/webview_flutter_wkwebview/ios/Classes…
JeroenWeener Nov 21, 2023
7f95e52
Delete packages/webview_flutter/webview_flutter_wkwebview/ios/Classes…
JeroenWeener Nov 21, 2023
279d3db
Delete packages/webview_flutter/webview_flutter_wkwebview/example/ios…
JeroenWeener Nov 21, 2023
5c8ecc1
Update pubspecs
JeroenWeener Nov 28, 2023
60fe593
cancel by default
bparrishMines Dec 5, 2023
605833c
Merge branch 'main' of github.com:flutter/packages into webview-auth-…
bparrishMines Dec 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 3.13.0

* Adds support for `PlatformNavigationDelegate.setOnHttpAuthRequest`.
* Updates minimum supported SDK version to Flutter 3.10/Dart 3.0.

## 3.12.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2523,6 +2523,29 @@ public void doUpdateVisitedHistory(
Arrays.asList(instanceIdArg, webViewInstanceIdArg, urlArg, isReloadArg)),
channelReply -> callback.reply(null));
}

public void onReceivedHttpAuthRequest(
@NonNull Long instanceIdArg,
@NonNull Long webViewInstanceIdArg,
@NonNull Long httpAuthHandlerInstanceIdArg,
@NonNull String hostArg,
@NonNull String realmArg,
@NonNull Reply<Void> callback) {
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.webview_flutter_android.WebViewClientFlutterApi.onReceivedHttpAuthRequest",
getCodec());
channel.send(
new ArrayList<Object>(
Arrays.asList(
instanceIdArg,
webViewInstanceIdArg,
httpAuthHandlerInstanceIdArg,
hostArg,
realmArg)),
channelReply -> callback.reply(null));
}
}
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
public interface DownloadListenerHostApi {
Expand Down Expand Up @@ -3415,4 +3438,156 @@ public void create(@NonNull Long instanceIdArg, @NonNull Reply<Void> callback) {
channelReply -> callback.reply(null));
}
}
/**
* Host API for `HttpAuthHandler`.
*
* <p>This class may handle instantiating and adding native object instances that are attached to
* a Dart instance or handle method calls on the associated native class or an instance of the
* class.
*
* <p>See https://developer.android.com/reference/android/webkit/HttpAuthHandler.
*
* <p>Generated interface from Pigeon that represents a handler of messages from Flutter.
*/
public interface HttpAuthHandlerHostApi {
/** Handles Dart method `HttpAuthHandler.useHttpAuthUsernamePassword`. */
@NonNull
Boolean useHttpAuthUsernamePassword(@NonNull Long instanceId);
/** Handles Dart method `HttpAuthHandler.cancel`. */
void cancel(@NonNull Long instanceId);
/** Handles Dart method `HttpAuthHandler.proceed`. */
void proceed(@NonNull Long instanceId, @NonNull String username, @NonNull String password);

/** The codec used by HttpAuthHandlerHostApi. */
static @NonNull MessageCodec<Object> getCodec() {
return new StandardMessageCodec();
}
/**
* Sets up an instance of `HttpAuthHandlerHostApi` to handle messages through the
* `binaryMessenger`.
*/
static void setup(
@NonNull BinaryMessenger binaryMessenger, @Nullable HttpAuthHandlerHostApi api) {
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.webview_flutter_android.HttpAuthHandlerHostApi.useHttpAuthUsernamePassword",
getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
ArrayList<Object> args = (ArrayList<Object>) message;
Number instanceIdArg = (Number) args.get(0);
try {
Boolean output =
api.useHttpAuthUsernamePassword(
(instanceIdArg == null) ? null : instanceIdArg.longValue());
wrapped.add(0, output);
} catch (Throwable exception) {
ArrayList<Object> wrappedError = wrapError(exception);
wrapped = wrappedError;
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.webview_flutter_android.HttpAuthHandlerHostApi.cancel",
getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
ArrayList<Object> args = (ArrayList<Object>) message;
Number instanceIdArg = (Number) args.get(0);
try {
api.cancel((instanceIdArg == null) ? null : instanceIdArg.longValue());
wrapped.add(0, null);
} catch (Throwable exception) {
ArrayList<Object> wrappedError = wrapError(exception);
wrapped = wrappedError;
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.webview_flutter_android.HttpAuthHandlerHostApi.proceed",
getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
ArrayList<Object> args = (ArrayList<Object>) message;
Number instanceIdArg = (Number) args.get(0);
String usernameArg = (String) args.get(1);
String passwordArg = (String) args.get(2);
try {
api.proceed(
(instanceIdArg == null) ? null : instanceIdArg.longValue(),
usernameArg,
passwordArg);
wrapped.add(0, null);
} catch (Throwable exception) {
ArrayList<Object> wrappedError = wrapError(exception);
wrapped = wrappedError;
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
}
}
/**
* Flutter API for `HttpAuthHandler`.
*
* <p>This class may handle instantiating and adding Dart instances that are attached to a native
* instance or receiving callback methods from an overridden native class.
*
* <p>See https://developer.android.com/reference/android/webkit/HttpAuthHandler.
*
* <p>Generated class from Pigeon that represents Flutter messages that can be called from Java.
*/
public static class HttpAuthHandlerFlutterApi {
private final @NonNull BinaryMessenger binaryMessenger;

public HttpAuthHandlerFlutterApi(@NonNull BinaryMessenger argBinaryMessenger) {
this.binaryMessenger = argBinaryMessenger;
}

/** Public interface for sending reply. */
@SuppressWarnings("UnknownNullness")
public interface Reply<T> {
void reply(T reply);
}
/** The codec used by HttpAuthHandlerFlutterApi. */
static @NonNull MessageCodec<Object> getCodec() {
return new StandardMessageCodec();
}
/** Create a new Dart instance and add it to the `InstanceManager`. */
public void create(@NonNull Long instanceIdArg, @NonNull Reply<Void> callback) {
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.webview_flutter_android.HttpAuthHandlerFlutterApi.create",
getCodec());
channel.send(
new ArrayList<Object>(Collections.singletonList(instanceIdArg)),
channelReply -> callback.reply(null));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.webviewflutter;

import android.webkit.HttpAuthHandler;
import androidx.annotation.NonNull;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.HttpAuthHandlerFlutterApi;

/**
* Flutter API implementation for {@link HttpAuthHandler}.
*
* <p>This class may handle adding native instances that are attached to a Dart instance or passing
* arguments of callbacks methods to a Dart instance.
*/
public class HttpAuthHandlerFlutterApiImpl {
// To ease adding additional methods, this value is added prematurely.
@SuppressWarnings({"unused", "FieldCanBeLocal"})
private final BinaryMessenger binaryMessenger;

private final InstanceManager instanceManager;

private final HttpAuthHandlerFlutterApi api;

/**
* Constructs a {@link HttpAuthHandlerFlutterApiImpl}.
*
* @param binaryMessenger used to communicate with Dart over asynchronous messages
* @param instanceManager maintains instances stored to communicate with attached Dart objects
*/
public HttpAuthHandlerFlutterApiImpl(
@NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
api = new HttpAuthHandlerFlutterApi(binaryMessenger);
}

/**
* Stores the `HttpAuthHandler` instance and notifies Dart to create and store a new
* `HttpAuthHandler` instance that is attached to this one. If `instance` has already been added,
* this method does nothing.
*/
public void create(
@NonNull HttpAuthHandler instance, @NonNull HttpAuthHandlerFlutterApi.Reply<Void> callback) {
if (!instanceManager.containsInstance(instance)) {
api.create(instanceManager.addHostCreatedInstance(instance), callback);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.webviewflutter;

import android.webkit.HttpAuthHandler;
import androidx.annotation.NonNull;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.HttpAuthHandlerHostApi;
import java.util.Objects;

/**
* Host api implementation for {@link HttpAuthHandler}.
*
* <p>Handles creating {@link HttpAuthHandler}s that intercommunicate with a paired Dart object.
*/
public class HttpAuthHandlerHostApiImpl implements HttpAuthHandlerHostApi {
// To ease adding additional methods, this value is added prematurely.
@SuppressWarnings({"unused", "FieldCanBeLocal"})
private final BinaryMessenger binaryMessenger;

private final InstanceManager instanceManager;

/**
* Constructs a {@link HttpAuthHandlerHostApiImpl}.
*
* @param binaryMessenger used to communicate with Dart over asynchronous messages
* @param instanceManager maintains instances stored to communicate with attached Dart objects
*/
public HttpAuthHandlerHostApiImpl(
@NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
}

@NonNull
@Override
public Boolean useHttpAuthUsernamePassword(@NonNull Long instanceId) {
return getHttpAuthHandlerInstance(instanceId).useHttpAuthUsernamePassword();
}

@Override
public void cancel(@NonNull Long instanceId) {
getHttpAuthHandlerInstance(instanceId).cancel();
}

@Override
public void proceed(
@NonNull Long instanceId, @NonNull String username, @NonNull String password) {
getHttpAuthHandlerInstance(instanceId).proceed(username, password);
}

private HttpAuthHandler getHttpAuthHandlerInstance(@NonNull Long instanceId) {
return Objects.requireNonNull(instanceManager.getInstance(instanceId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import android.annotation.SuppressLint;
import android.os.Build;
import android.webkit.HttpAuthHandler;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
Expand Down Expand Up @@ -230,6 +231,26 @@ public void doUpdateVisitedHistory(
getIdentifierForClient(webViewClient), webViewIdentifier, url, isReload, callback);
}

/** Passes arguments from {@link WebViewClient#onReceivedHttpAuthRequest} to Dart. */
public void onReceivedHttpAuthRequest(
@NonNull WebViewClient webViewClient,
@NonNull WebView webview,
@NonNull HttpAuthHandler httpAuthHandler,
@NonNull String host,
@NonNull String realm,
@NonNull Reply<Void> callback) {
new HttpAuthHandlerFlutterApiImpl(binaryMessenger, instanceManager)
.create(httpAuthHandler, reply -> {});

onReceivedHttpAuthRequest(
Objects.requireNonNull(instanceManager.getIdentifierForStrongReference(webViewClient)),
Objects.requireNonNull(instanceManager.getIdentifierForStrongReference(webview)),
Objects.requireNonNull(instanceManager.getIdentifierForStrongReference(httpAuthHandler)),
host,
realm,
callback);
}

private long getIdentifierForClient(WebViewClient webViewClient) {
final Long identifier = instanceManager.getIdentifierForStrongReference(webViewClient);
if (identifier == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import android.graphics.Bitmap;
import android.os.Build;
import android.view.KeyEvent;
import android.webkit.HttpAuthHandler;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
Expand Down Expand Up @@ -38,7 +39,7 @@ public static class WebViewClientImpl extends WebViewClient {
/**
* Creates a {@link WebViewClient} that passes arguments of callbacks methods to Dart.
*
* @param flutterApi handles sending messages to Dart
* @param flutterApi handles sending messages to Dart.
*/
public WebViewClientImpl(@NonNull WebViewClientFlutterApiImpl flutterApi) {
this.flutterApi = flutterApi;
Expand Down Expand Up @@ -95,6 +96,15 @@ public void doUpdateVisitedHistory(
flutterApi.doUpdateVisitedHistory(this, view, url, isReload, reply -> {});
}

@Override
public void onReceivedHttpAuthRequest(
@NonNull WebView view,
@NonNull HttpAuthHandler handler,
@NonNull String host,
@NonNull String realm) {
flutterApi.onReceivedHttpAuthRequest(this, view, handler, host, realm, reply -> {});
}

@Override
public void onUnhandledKeyEvent(@NonNull WebView view, @NonNull KeyEvent event) {
// Deliberately empty. Occasionally the webview will mark events as having failed to be
Expand Down Expand Up @@ -176,6 +186,16 @@ public void doUpdateVisitedHistory(
flutterApi.doUpdateVisitedHistory(this, view, url, isReload, reply -> {});
}

// Handles an HTTP authentication request.
//
// This callback is invoked when the WebView encounters a website requiring HTTP authentication.
// [host] and [realm] are provided for matching against stored credentials, if any.
@Override
public void onReceivedHttpAuthRequest(
@NonNull WebView view, HttpAuthHandler handler, String host, String realm) {
flutterApi.onReceivedHttpAuthRequest(this, view, handler, host, realm, reply -> {});
}

@Override
public void onUnhandledKeyEvent(@NonNull WebView view, @NonNull KeyEvent event) {
// Deliberately empty. Occasionally the webview will mark events as having failed to be
Expand Down
Loading