Skip to content
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

[url_launcher] Add an inAppBrowserView mode #5205

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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,3 +1,11 @@
## 2.2.0

* Adds a new `inAppBrowserView` launch mode, to distinguish in-app browser
views (such as Android Custom Tabs or SFSafariViewController) from simple
web views.
* Adds `supportsMode` and `supportsCloseForMode` to query platform support for
launching and closing with various modes.

## 2.1.5

* Updates documentation to mention support for Android Custom Tabs.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ enum PreferredLaunchMode {
/// implementation.
platformDefault,

/// Loads the URL in an in-app web view (e.g., Android Custom Tabs, Safari View Controller).
/// Loads the URL in an in-app web view (e.g., Android WebView).
inAppWebView,

/// Loads the URL in an in-app browser view (e.g., Android Custom Tabs,
/// SFSafariViewController).
inAppBrowserView,

/// Passes the URL to the OS to be handled by another application.
externalApplication,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import '../link.dart';
import '../method_channel_url_launcher.dart';
import '../url_launcher_platform_interface.dart';
import 'types.dart';

/// The interface that implementations of url_launcher must implement.
///
Expand Down Expand Up @@ -72,6 +73,7 @@ abstract class UrlLauncherPlatform extends PlatformInterface {
Future<bool> launchUrl(String url, LaunchOptions options) {
final bool isWebURL = url.startsWith('http:') || url.startsWith('https:');
final bool useWebView = options.mode == PreferredLaunchMode.inAppWebView ||
options.mode == PreferredLaunchMode.inAppBrowserView ||
(isWebURL && options.mode == PreferredLaunchMode.platformDefault);

return launch(
Expand All @@ -87,8 +89,31 @@ abstract class UrlLauncherPlatform extends PlatformInterface {
);
}

/// Closes the WebView, if one was opened earlier by [launch].
/// Closes the web view, if one was opened earlier by [launchUrl].
///
/// This will only work if the launch mode (the actual launch mode used,
/// not the requested launch mode, which may not match if [supportsMode] is
/// false for the requested mode) was one for which [supportsCloseForMode]
/// returns true.
Future<void> closeWebView() {
throw UnimplementedError('closeWebView() has not been implemented.');
}

/// Returns true if the given launch mode is supported by the current
/// implementation.
///
/// Clients are not required to query this, as implementations are strongly
/// encouraged to automatically fall back to other modes if a launch is
/// requested using an unsupported mode (matching historical behavior of the
/// plugin, and thus maximizing compatibility with existing code).
Future<bool> supportsMode(PreferredLaunchMode mode) {
return Future<bool>.value(mode == PreferredLaunchMode.platformDefault);
}

/// Returns true if the given launch mode can be closed with [closeWebView].
Future<bool> supportsCloseForMode(PreferredLaunchMode mode) {
// This is the historical documented behavior, so default to that for
// compatibility.
return Future<bool>.value(mode == PreferredLaunchMode.inAppWebView);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/url_launcher/
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
version: 2.1.5
version: 2.2.0

environment:
sdk: ">=2.19.0 <4.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,55 @@ void main() {
expect(launcher.headers['foo'], 'bar');
expect(launcher.webOnlyWindowName, 'a_name');
});

test('supportsMode defaults to true for platform default', () async {
final UrlLauncherPlatform launcher = CapturingUrlLauncher();

expect(
await launcher.supportsMode(PreferredLaunchMode.platformDefault), true);
});

test('supportsMode defaults to false for all specific values', () async {
final UrlLauncherPlatform launcher = CapturingUrlLauncher();

expect(await launcher.supportsMode(PreferredLaunchMode.externalApplication),
false);
expect(
await launcher
.supportsMode(PreferredLaunchMode.externalNonBrowserApplication),
false);
expect(await launcher.supportsMode(PreferredLaunchMode.inAppBrowserView),
false);
expect(
await launcher.supportsMode(PreferredLaunchMode.inAppWebView), false);
});

test('supportsCloseForMode defaults to true for in-app web views', () async {
final UrlLauncherPlatform launcher = CapturingUrlLauncher();

expect(
await launcher.supportsCloseForMode(PreferredLaunchMode.inAppWebView),
true);
});

test('supportsCloseForMode defaults to false for all other values', () async {
final UrlLauncherPlatform launcher = CapturingUrlLauncher();

expect(
await launcher
.supportsCloseForMode(PreferredLaunchMode.externalApplication),
false);
expect(
await launcher.supportsCloseForMode(
PreferredLaunchMode.externalNonBrowserApplication),
false);
expect(
await launcher
.supportsCloseForMode(PreferredLaunchMode.inAppBrowserView),
false);
expect(
await launcher
.supportsCloseForMode(PreferredLaunchMode.platformDefault),
false);
});
}