Reland "[webview_flutter] Add a getTitle method to WebViewController" (#1981)" (#2056)

This reverts commit e4feab651ad6aec18d8fc2b71633fee9f41164b7.
diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md
index 75b2bf4..4419c2f 100644
--- a/packages/webview_flutter/CHANGELOG.md
+++ b/packages/webview_flutter/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.3.14
+
+* Added a getTitle getter to WebViewController.
+
 ## 0.3.13
 
 * Add an optional `userAgent` property to set a custom User Agent.
diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java
index 2288b8f..a7f2db3 100644
--- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java
+++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java
@@ -134,6 +134,9 @@
       case "clearCache":
         clearCache(result);
         break;
+      case "getTitle":
+        getTitle(result);
+        break;
       default:
         result.notImplemented();
     }
@@ -226,6 +229,10 @@
     result.success(null);
   }
 
+  private void getTitle(Result result) {
+    result.success(webView.getTitle());
+  }
+
   private void applySettings(Map<String, Object> settings) {
     for (String key : settings.keySet()) {
       switch (key) {
diff --git a/packages/webview_flutter/example/test_driver/webview.dart b/packages/webview_flutter/example/test_driver/webview.dart
index be7e859..e24afd7 100644
--- a/packages/webview_flutter/example/test_driver/webview.dart
+++ b/packages/webview_flutter/example/test_driver/webview.dart
@@ -457,6 +457,43 @@
       expect(isPaused, _webviewBool(false));
     });
   });
+
+  test('getTitle', () async {
+    final String getTitleTest = '''
+        <!DOCTYPE html><html>
+        <head><title>Some title</title>
+        </head>
+        <body>
+        </body>
+        </html>
+      ''';
+    final String getTitleTestBase64 =
+        base64Encode(const Utf8Encoder().convert(getTitleTest));
+    final Completer<void> pageLoaded = Completer<void>();
+    final Completer<WebViewController> controllerCompleter =
+        Completer<WebViewController>();
+
+    await pumpWidget(
+      Directionality(
+        textDirection: TextDirection.ltr,
+        child: WebView(
+          initialUrl: 'data:text/html;charset=utf-8;base64,$getTitleTestBase64',
+          onWebViewCreated: (WebViewController controller) {
+            controllerCompleter.complete(controller);
+          },
+          onPageFinished: (String url) {
+            pageLoaded.complete(null);
+          },
+        ),
+      ),
+    );
+
+    final WebViewController controller = await controllerCompleter.future;
+    await pageLoaded.future;
+
+    final String title = await controller.getTitle();
+    expect(title, 'Some title');
+  });
 }
 
 Future<void> pumpWidget(Widget widget) {
diff --git a/packages/webview_flutter/ios/Classes/FlutterWebView.m b/packages/webview_flutter/ios/Classes/FlutterWebView.m
index fed73d8..36f4e8c 100644
--- a/packages/webview_flutter/ios/Classes/FlutterWebView.m
+++ b/packages/webview_flutter/ios/Classes/FlutterWebView.m
@@ -118,6 +118,8 @@
     [self onRemoveJavaScriptChannels:call result:result];
   } else if ([[call method] isEqualToString:@"clearCache"]) {
     [self clearCache:result];
+  } else if ([[call method] isEqualToString:@"getTitle"]) {
+    [self onGetTitle:result];
   } else {
     result(FlutterMethodNotImplemented);
   }
@@ -238,6 +240,11 @@
   }
 }
 
+- (void)onGetTitle:(FlutterResult)result {
+  NSString* title = _webView.title;
+  result(title);
+}
+
 // Returns nil when successful, or an error message when one or more keys are unknown.
 - (NSString*)applySettings:(NSDictionary<NSString*, id>*)settings {
   NSMutableArray<NSString*>* unknownKeys = [[NSMutableArray alloc] init];
diff --git a/packages/webview_flutter/lib/platform_interface.dart b/packages/webview_flutter/lib/platform_interface.dart
index 972cb25..7e82bae 100644
--- a/packages/webview_flutter/lib/platform_interface.dart
+++ b/packages/webview_flutter/lib/platform_interface.dart
@@ -158,6 +158,12 @@
     throw UnimplementedError(
         "WebView removeJavascriptChannels is not implemented on the current platform");
   }
+
+  /// Returns the title of the currently loaded page.
+  Future<String> getTitle() {
+    throw UnimplementedError(
+        "WebView getTitle is not implemented on the current platform");
+  }
 }
 
 /// A single setting for configuring a WebViewPlatform which may be absent.
diff --git a/packages/webview_flutter/lib/src/webview_method_channel.dart b/packages/webview_flutter/lib/src/webview_method_channel.dart
index f340005..c2949cc 100644
--- a/packages/webview_flutter/lib/src/webview_method_channel.dart
+++ b/packages/webview_flutter/lib/src/webview_method_channel.dart
@@ -103,6 +103,9 @@
         'removeJavascriptChannels', javascriptChannelNames.toList());
   }
 
+  @override
+  Future<String> getTitle() => _channel.invokeMethod<String>("getTitle");
+
   /// Method channel implementation for [WebViewPlatform.clearCookies].
   static Future<bool> clearCookies() {
     return _cookieManagerChannel
diff --git a/packages/webview_flutter/lib/webview_flutter.dart b/packages/webview_flutter/lib/webview_flutter.dart
index 97b7786..dec62b7 100644
--- a/packages/webview_flutter/lib/webview_flutter.dart
+++ b/packages/webview_flutter/lib/webview_flutter.dart
@@ -625,6 +625,11 @@
     // ignore: strong_mode_implicit_dynamic_method
     return _webViewPlatformController.evaluateJavascript(javascriptString);
   }
+
+  /// Returns the title of the currently loaded page.
+  Future<String> getTitle() {
+    return _webViewPlatformController.getTitle();
+  }
 }
 
 /// Manages cookies pertaining to all [WebView]s.
diff --git a/packages/webview_flutter/pubspec.yaml b/packages/webview_flutter/pubspec.yaml
index 23c09e8..69f4511 100644
--- a/packages/webview_flutter/pubspec.yaml
+++ b/packages/webview_flutter/pubspec.yaml
@@ -1,6 +1,6 @@
 name: webview_flutter
 description: A Flutter plugin that provides a WebView widget on Android and iOS.
-version: 0.3.13
+version: 0.3.14
 author: Flutter Team <flutter-dev@googlegroups.com>
 homepage: https://github.com/flutter/plugins/tree/master/packages/webview_flutter