Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[url_launcher] Error handling when URL cannot be parsed with Uri.parse #4365

Merged
merged 8 commits into from
Sep 23, 2021
4 changes: 4 additions & 0 deletions packages/url_launcher/url_launcher/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 6.0.12

* Fixed an error where 'launch' method of url_launcher would cause an error if the provided URL was not valid by RFC 3986.

## 6.0.11

* Update minimum Flutter SDK to 2.5 and iOS deployment target to 9.0.
Expand Down
6 changes: 4 additions & 2 deletions packages/url_launcher/url_launcher/lib/url_launcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ Future<bool> launch(
Brightness? statusBarBrightness,
String? webOnlyWindowName,
}) async {
final Uri url = Uri.parse(urlString.trimLeft());
final bool isWebURL = url.scheme == 'http' || url.scheme == 'https';
final Uri? url = Uri.tryParse(urlString.trimLeft());
final bool isWebURL =
url != null && (url.scheme == 'http' || url.scheme == 'https');

if ((forceSafariVC == true || forceWebView == true) && !isWebURL) {
throw PlatformException(
code: 'NOT_A_WEB_SCHEME',
Expand Down
2 changes: 1 addition & 1 deletion packages/url_launcher/url_launcher/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Flutter plugin for launching a URL. Supports
web, phone, SMS, and email schemes.
repository: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22
version: 6.0.11
version: 6.0.12

environment:
sdk: ">=2.14.0 <3.0.0"
Expand Down
36 changes: 36 additions & 0 deletions packages/url_launcher/url_launcher/test/url_launcher_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,42 @@ void main() {
await launchResult;
expect(binding.renderView.automaticSystemUiAdjustment, true);
});

test('open non-parseable url', () async {
mock
..setLaunchExpectations(
url:
'rdp://full%20address=s:mypc:3389&audiomode=i:2&disable%20themes=i:1',
useSafariVC: false,
useWebView: false,
enableJavaScript: false,
enableDomStorage: false,
universalLinksOnly: false,
headers: <String, String>{},
webOnlyWindowName: null,
)
..setResponse(true);
expect(
await launch(
'rdp://full%20address=s:mypc:3389&audiomode=i:2&disable%20themes=i:1'),
isTrue);
});

test('cannot open non-parseable url with forceSafariVC: true', () async {
expect(
() async => await launch(
'rdp://full%20address=s:mypc:3389&audiomode=i:2&disable%20themes=i:1',
forceSafariVC: true),
throwsA(isA<PlatformException>()));
});

test('cannot open non-parseable url with forceWebView: true', () async {
expect(
() async => await launch(
'rdp://full%20address=s:mypc:3389&audiomode=i:2&disable%20themes=i:1',
forceWebView: true),
throwsA(isA<PlatformException>()));
});
});
}

Expand Down