[webview_flutter] Adds the `loadFlutterAsset` method to the interface. (#4562)

diff --git a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md
index 1b8a1fd..ac61d48 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md
+++ b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.8.0
+
+* Adds the `loadFlutterAsset` method to the platform interface.
+
 ## 1.7.0
 
 * Add an option to set the background color of the webview.
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart
index ef1b919..bb2a4ac 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart
+++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart
@@ -84,7 +84,31 @@
   @override
   Future<void> loadFile(String absoluteFilePath) async {
     assert(absoluteFilePath != null);
-    return _channel.invokeMethod<void>('loadFile', absoluteFilePath);
+
+    try {
+      return await _channel.invokeMethod<void>('loadFile', absoluteFilePath);
+    } on PlatformException catch (ex) {
+      if (ex.code == 'loadFile_failed') {
+        throw ArgumentError(ex.message);
+      }
+
+      rethrow;
+    }
+  }
+
+  @override
+  Future<void> loadFlutterAsset(String key) async {
+    assert(key.isNotEmpty);
+
+    try {
+      return await _channel.invokeMethod<void>('loadFlutterAsset', key);
+    } on PlatformException catch (ex) {
+      if (ex.code == 'loadFlutterAsset_invalidKey') {
+        throw ArgumentError(ex.message);
+      }
+
+      rethrow;
+    }
   }
 
   @override
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart
index da73204..3437fe1 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart
+++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart
@@ -37,6 +37,17 @@
     String absoluteFilePath,
   ) {
     throw UnimplementedError(
+        'WebView loadFile is not implemented on the current platform');
+  }
+
+  /// Loads the Flutter asset specified in the pubspec.yaml file.
+  ///
+  /// Throws an ArgumentError if [key] is not part of the specified assets
+  /// in the pubspec.yaml file.
+  Future<void> loadFlutterAsset(
+    String key,
+  ) {
+    throw UnimplementedError(
         'WebView loadFlutterAsset is not implemented on the current platform');
   }
 
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml b/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml
index 2bad743..5950cab 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml
+++ b/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml
@@ -4,7 +4,7 @@
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview_flutter%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: 1.7.0
+version: 1.8.0
 
 environment:
   sdk: ">=2.12.0 <3.0.0"
diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart
index 3bcc2fe..5d2c717 100644
--- a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart
+++ b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart
@@ -33,6 +33,35 @@
         case 'canGoBack':
         case 'canGoForward':
           return true;
+        case 'loadFile':
+          if (methodCall.arguments == 'invalid file') {
+            throw PlatformException(
+                code: 'loadFile_failed',
+                message: 'Failed loading file.',
+                details: null);
+          } else if (methodCall.arguments == 'some error') {
+            throw PlatformException(
+              code: 'some_error',
+              message: 'Some error occurred.',
+              details: null,
+            );
+          }
+          return null;
+        case 'loadFlutterAsset':
+          if (methodCall.arguments == 'invalid key') {
+            throw PlatformException(
+              code: 'loadFlutterAsset_invalidKey',
+              message: 'Failed loading asset.',
+              details: null,
+            );
+          } else if (methodCall.arguments == 'some error') {
+            throw PlatformException(
+              code: 'some_error',
+              message: 'Some error occurred.',
+              details: null,
+            );
+          }
+          return null;
         case 'runJavascriptReturningResult':
         case 'evaluateJavascript':
           return methodCall.arguments as String;
@@ -74,6 +103,78 @@
       );
     });
 
+    test('loadFile with invalid file', () async {
+      expect(
+        () => webViewPlatform.loadFile('invalid file'),
+        throwsA(
+          isA<ArgumentError>().having(
+            (ArgumentError error) => error.message,
+            'message',
+            'Failed loading file.',
+          ),
+        ),
+      );
+    });
+
+    test('loadFile with some error.', () async {
+      expect(
+        () => webViewPlatform.loadFile('some error'),
+        throwsA(
+          isA<PlatformException>().having(
+            (PlatformException error) => error.message,
+            'message',
+            'Some error occurred.',
+          ),
+        ),
+      );
+    });
+
+    test('loadFlutterAsset', () async {
+      await webViewPlatform.loadFlutterAsset(
+        'folder/asset.html',
+      );
+
+      expect(
+        log,
+        <Matcher>[
+          isMethodCall(
+            'loadFlutterAsset',
+            arguments: 'folder/asset.html',
+          ),
+        ],
+      );
+    });
+
+    test('loadFlutterAsset with empty key', () async {
+      expect(() => webViewPlatform.loadFlutterAsset(''), throwsAssertionError);
+    });
+
+    test('loadFlutterAsset with invalid key', () async {
+      expect(
+        () => webViewPlatform.loadFlutterAsset('invalid key'),
+        throwsA(
+          isA<ArgumentError>().having(
+            (ArgumentError error) => error.message,
+            'message',
+            'Failed loading asset.',
+          ),
+        ),
+      );
+    });
+
+    test('loadFlutterAsset with some error.', () async {
+      expect(
+        () => webViewPlatform.loadFlutterAsset('some error'),
+        throwsA(
+          isA<PlatformException>().having(
+            (PlatformException error) => error.message,
+            'message',
+            'Some error occurred.',
+          ),
+        ),
+      );
+    });
+
     test('loadHtmlString without base URL', () async {
       await webViewPlatform.loadHtmlString(
         'Test HTML string',