[url_launcher_web] Open url in same window when browser is in standalone mode. (#2656)

Fixes https://github.com/flutter/flutter/issues/51461
diff --git a/packages/url_launcher/url_launcher_web/CHANGELOG.md b/packages/url_launcher/url_launcher_web/CHANGELOG.md
index 0cb57ef..f8416af 100644
--- a/packages/url_launcher/url_launcher_web/CHANGELOG.md
+++ b/packages/url_launcher/url_launcher_web/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 0.1.1+2
+
+- Open urls with target "_top" on iOS PWAs.
+
 # 0.1.1+1
 
 - Make the pedantic dev_dependency explicit.
diff --git a/packages/url_launcher/url_launcher_web/lib/src/navigator.dart b/packages/url_launcher/url_launcher_web/lib/src/navigator.dart
new file mode 100644
index 0000000..4c7a99d
--- /dev/null
+++ b/packages/url_launcher/url_launcher_web/lib/src/navigator.dart
@@ -0,0 +1,15 @@
+@JS()
+library navigator;
+
+import 'package:js/js.dart';
+import 'package:meta/meta.dart';
+
+@JS('window.navigator.standalone')
+external bool get _standalone;
+
+/// The window.navigator.standalone DOM property.
+bool get standalone => _standalone ?? false;
+
+@visibleForTesting
+@JS('window.navigator.standalone')
+external set standalone(bool enabled);
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 c37d872..688df43 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
@@ -4,6 +4,7 @@
 import 'package:flutter_web_plugins/flutter_web_plugins.dart';
 import 'package:meta/meta.dart';
 import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
+import 'src/navigator.dart' as navigator;
 
 /// The web implementation of [UrlLauncherPlatform].
 ///
@@ -19,7 +20,10 @@
   /// Returns the newly created window.
   @visibleForTesting
   html.WindowBase openNewWindow(String url) {
-    return html.window.open(url, '');
+    // We need to open on _top in ios browsers in standalone mode.
+    // See https://github.com/flutter/flutter/issues/51461 for reference.
+    final target = navigator.standalone ? '_top' : '';
+    return html.window.open(url, target);
   }
 
   @override
diff --git a/packages/url_launcher/url_launcher_web/pubspec.yaml b/packages/url_launcher/url_launcher_web/pubspec.yaml
index 8e74677..a43a828 100644
--- a/packages/url_launcher/url_launcher_web/pubspec.yaml
+++ b/packages/url_launcher/url_launcher_web/pubspec.yaml
@@ -1,7 +1,7 @@
 name: url_launcher_web
 description: Web platform implementation of url_launcher
 homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher_web
-version: 0.1.1+1
+version: 0.1.1+2
 
 flutter:
   plugin:
@@ -17,6 +17,7 @@
   flutter_web_plugins:
     sdk: flutter
   meta: ^1.1.7
+  js: ^0.6.0
 
 dev_dependencies:
   flutter_test:
diff --git a/packages/url_launcher/url_launcher_web/test/url_launcher_web_test.dart b/packages/url_launcher/url_launcher_web/test/url_launcher_web_test.dart
index 3fb9b78..8711013 100644
--- a/packages/url_launcher/url_launcher_web/test/url_launcher_web_test.dart
+++ b/packages/url_launcher/url_launcher_web/test/url_launcher_web_test.dart
@@ -5,10 +5,10 @@
 @TestOn('chrome') // Uses web-only Flutter SDK
 
 import 'dart:html' as html;
-
 import 'package:flutter_test/flutter_test.dart';
 import 'package:url_launcher/url_launcher.dart';
 import 'package:url_launcher_web/url_launcher_web.dart';
+import 'package:url_launcher_web/src/navigator.dart' as navigator;
 import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
 
 void main() {
@@ -54,6 +54,19 @@
       expect(newWindow.opener, equals(html.window));
     });
 
+    test('the window that is launched is in the same window', () {
+      final originalStandalone = navigator.standalone;
+      // Simulate the navigator is in standalone mode on iOS devices.
+      // https://developer.mozilla.org/en-US/docs/Web/API/Navigator
+      navigator.standalone = true;
+      final UrlLauncherPlugin urlLauncherPlugin = UrlLauncherPlugin();
+      final html.WindowBase window =
+          urlLauncherPlugin.openNewWindow('https://www.google.com');
+      expect(window, isNotNull);
+      expect(window.opener, isNot(equals(html.window)));
+      navigator.standalone = originalStandalone;
+    });
+
     test('does not implement closeWebView()', () {
       expect(closeWebView(), throwsUnimplementedError);
     });