From 0c29f9463acb09a5ad8f1ada9ff16e7b8221bf68 Mon Sep 17 00:00:00 2001 From: Frank3K <8014077+Frank3K@users.noreply.github.com> Date: Sun, 28 Jul 2024 15:07:26 +0200 Subject: [PATCH 1/5] [url_launcher] Prevent launchUrl from incorrectly returning false on web Since noopener is used to open URLs, there is no way to determine if the browser has succesfully opened a given URL. Therefore success is now assumed for supported schemes. Fixes https://github.com/flutter/flutter/issues/139783. --- packages/url_launcher/url_launcher_web/CHANGELOG.md | 4 ++++ packages/url_launcher/url_launcher_web/README.md | 12 +++++++++++- .../url_launcher_web/lib/url_launcher_web.dart | 6 ++++-- packages/url_launcher/url_launcher_web/pubspec.yaml | 2 +- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/url_launcher/url_launcher_web/CHANGELOG.md b/packages/url_launcher/url_launcher_web/CHANGELOG.md index ca4d9d86cc66..7b870e458422 100644 --- a/packages/url_launcher/url_launcher_web/CHANGELOG.md +++ b/packages/url_launcher/url_launcher_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.3.2 + +* Fixes issue where `launchUrl` incorrectly returned `false`. + ## 2.3.1 * Implements correct handling of keyboard events with Link. diff --git a/packages/url_launcher/url_launcher_web/README.md b/packages/url_launcher/url_launcher_web/README.md index 91d7fb623b0a..1ed4c383e903 100644 --- a/packages/url_launcher/url_launcher_web/README.md +++ b/packages/url_launcher/url_launcher_web/README.md @@ -30,4 +30,14 @@ In such cases, you can use the `webOnlyWindowName` parameter, setting it to `_self`, to open the URL within the current tab. Another approach is to ensure that the `uri` is synchronously ready. -Read more: MDN > [Transient activation](https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation). \ No newline at end of file +Read more: MDN > [Transient activation](https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation). + +### Method `launchUrl` always returns `true` for supported schemes + +The `launchUrl` method always returns `true` on the web platform for supported +schemes. This is because URLs are opened in a new window using the `noopener` +window feature. When the `noopener` feature is used, the browser does not +return any information that can be used to determine if the link was +successfully opened. + +Read more: MDN > [window.open](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#noopener). \ No newline at end of file diff --git a/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart b/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart index 070852db4c3e..7f2e8d738013 100644 --- a/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart +++ b/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart @@ -66,7 +66,8 @@ class UrlLauncherPlugin extends UrlLauncherPlatform { /// Opens the given [url] in the specified [webOnlyWindowName]. /// - /// Returns the newly created window. + /// Always returns `null` on the web platform, because `noopener` is used. + /// See https://html.spec.whatwg.org/multipage/nav-history-apis.html#window-open-steps. @visibleForTesting html.Window? openNewWindow(String url, {String? webOnlyWindowName}) { final String? scheme = _getUrlScheme(url); @@ -109,7 +110,8 @@ class UrlLauncherPlugin extends UrlLauncherPlatform { @override Future launchUrl(String url, LaunchOptions options) async { final String? windowName = options.webOnlyWindowName; - return openNewWindow(url, webOnlyWindowName: windowName) != null; + openNewWindow(url, webOnlyWindowName: windowName); + return canLaunch(url); } @override diff --git a/packages/url_launcher/url_launcher_web/pubspec.yaml b/packages/url_launcher/url_launcher_web/pubspec.yaml index 51f320a32a5e..d80bee5e5f2b 100644 --- a/packages/url_launcher/url_launcher_web/pubspec.yaml +++ b/packages/url_launcher/url_launcher_web/pubspec.yaml @@ -2,7 +2,7 @@ name: url_launcher_web description: Web platform implementation of url_launcher repository: https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22 -version: 2.3.1 +version: 2.3.2 environment: sdk: ^3.3.0 From 4764f5ea8ec9d3730a1dc4d5bc13f8d83e9eda64 Mon Sep 17 00:00:00 2001 From: Frank3K <8014077+Frank3K@users.noreply.github.com> Date: Sat, 3 Aug 2024 21:49:24 +0200 Subject: [PATCH 2/5] [url_launcher] Always return true for launchUrl, except for disallowed schemes --- packages/url_launcher/url_launcher_web/README.md | 4 ++-- .../url_launcher_web/lib/url_launcher_web.dart | 15 +++++++++------ .../url_launcher/url_launcher_web/pubspec.yaml | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/url_launcher/url_launcher_web/README.md b/packages/url_launcher/url_launcher_web/README.md index 1ed4c383e903..6853a6ccc538 100644 --- a/packages/url_launcher/url_launcher_web/README.md +++ b/packages/url_launcher/url_launcher_web/README.md @@ -32,9 +32,9 @@ that the `uri` is synchronously ready. Read more: MDN > [Transient activation](https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation). -### Method `launchUrl` always returns `true` for supported schemes +### Method `launchUrl` always returns `true` for allowed schemes -The `launchUrl` method always returns `true` on the web platform for supported +The `launchUrl` method always returns `true` on the web platform for allowed schemes. This is because URLs are opened in a new window using the `noopener` window feature. When the `noopener` feature is used, the browser does not return any information that can be used to determine if the link was diff --git a/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart b/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart index 7f2e8d738013..1a33f3aea7c6 100644 --- a/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart +++ b/packages/url_launcher/url_launcher_web/lib/url_launcher_web.dart @@ -66,10 +66,12 @@ class UrlLauncherPlugin extends UrlLauncherPlatform { /// Opens the given [url] in the specified [webOnlyWindowName]. /// - /// Always returns `null` on the web platform, because `noopener` is used. + /// Always returns `true`, except for disallowed schemes. Because `noopener` + /// is used as a window feature, it can not be detected if the window was + /// opened successfully. /// See https://html.spec.whatwg.org/multipage/nav-history-apis.html#window-open-steps. @visibleForTesting - html.Window? openNewWindow(String url, {String? webOnlyWindowName}) { + bool openNewWindow(String url, {String? webOnlyWindowName}) { final String? scheme = _getUrlScheme(url); // Actively disallow opening some schemes, like javascript. // See https://github.com/flutter/flutter/issues/136657 @@ -77,7 +79,7 @@ class UrlLauncherPlugin extends UrlLauncherPlatform { if (kDebugMode) { print('Disallowed URL with scheme: $scheme'); } - return null; + return false; } // Some schemes need to be opened on the _top window context on Safari. // See https://github.com/flutter/flutter/issues/51461 @@ -85,7 +87,9 @@ class UrlLauncherPlugin extends UrlLauncherPlatform { ((_isSafari && _isSafariTargetTopScheme(scheme)) ? '_top' : ''); // ignore: unsafe_html - return _window.open(url, target, 'noopener,noreferrer'); + _window.open(url, target, 'noopener,noreferrer'); + + return true; } @override @@ -110,8 +114,7 @@ class UrlLauncherPlugin extends UrlLauncherPlatform { @override Future launchUrl(String url, LaunchOptions options) async { final String? windowName = options.webOnlyWindowName; - openNewWindow(url, webOnlyWindowName: windowName); - return canLaunch(url); + return openNewWindow(url, webOnlyWindowName: windowName); } @override diff --git a/packages/url_launcher/url_launcher_web/pubspec.yaml b/packages/url_launcher/url_launcher_web/pubspec.yaml index 9149edfcbe37..3730a4dd90e4 100644 --- a/packages/url_launcher/url_launcher_web/pubspec.yaml +++ b/packages/url_launcher/url_launcher_web/pubspec.yaml @@ -2,7 +2,7 @@ name: url_launcher_web description: Web platform implementation of url_launcher repository: https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22 -version: 2.3.2 +version: 2.3.3 environment: sdk: ^3.3.0 From 36b1437e05a97d9367b854843195bb7f282dd1ca Mon Sep 17 00:00:00 2001 From: Frank3K <8014077+Frank3K@users.noreply.github.com> Date: Sat, 3 Aug 2024 21:52:05 +0200 Subject: [PATCH 3/5] [url_launcher] Add test for unknown scheme --- .../example/integration_test/url_launcher_web_test.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.dart b/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.dart index b75903873467..188994dde031 100644 --- a/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.dart +++ b/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.dart @@ -120,6 +120,14 @@ void main() { (WidgetTester _) async { expect(plugin.launch('javascript:alert("1")'), completion(isFalse)); }); + + testWidgets('launching a unknown sceheme returns true', (WidgetTester _) async { + expect( + plugin.launch( + 'foo:bar', + ), + completion(isTrue)); + }); }); group('openNewWindow', () { From ba2b3d5a7ad9dd0d5f29c412c895da048ecf1e80 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Mon, 5 Aug 2024 11:10:36 -0700 Subject: [PATCH 4/5] dart format . --- .../example/integration_test/url_launcher_web_test.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.dart b/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.dart index 188994dde031..00b74cd6f59c 100644 --- a/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.dart +++ b/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.dart @@ -121,13 +121,14 @@ void main() { expect(plugin.launch('javascript:alert("1")'), completion(isFalse)); }); - testWidgets('launching a unknown sceheme returns true', (WidgetTester _) async { + testWidgets('launching a unknown sceheme returns true', + (WidgetTester _) async { expect( plugin.launch( 'foo:bar', ), completion(isTrue)); - }); + }); }); group('openNewWindow', () { From e057a583c5e55f679e40ecd83c40127cefcc4791 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Mon, 5 Aug 2024 11:41:37 -0700 Subject: [PATCH 5/5] Slight rewrite of the CHANGELOG.md --- packages/url_launcher/url_launcher_web/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/url_launcher/url_launcher_web/CHANGELOG.md b/packages/url_launcher/url_launcher_web/CHANGELOG.md index 7fd9b4b29b5f..b891293c005f 100644 --- a/packages/url_launcher/url_launcher_web/CHANGELOG.md +++ b/packages/url_launcher/url_launcher_web/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.3.3 -* Fixes issue where `launchUrl` incorrectly returned `false`. +* Changes `launchUrl` so it always returns `true`, except for disallowed URL schemes. ## 2.3.2