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

Commit c691451

Browse files
authored
[webview_flutter] Add loadRequest functionality to app facing package. (#4573)
* Add android implementations for loadRequest. * Update changelog and pubspec. * Fix comment. * Fix comment. * Add tests * Add back removed license headers * Fix analysis error * Add support for loadRequest to app facing package * Add test * Comment pending dependency in pubspec * Remove workaround for supporting custom headers when making post requests on Android. * Document android workaround in dart doc * Enforce uri scheme * Update loadRequest dartdoc * Document android workaround in readme * Processed PR feedback. * Updated dependency, version and changelog.
1 parent 0f0dcbf commit c691451

File tree

8 files changed

+103
-18
lines changed

8 files changed

+103
-18
lines changed

packages/webview_flutter/webview_flutter/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.6.0
2+
3+
* Adds support for the `loadRequest` method.
4+
15
## 2.5.0
26

37
* Adds an option to set the background color of the webview.

packages/webview_flutter/webview_flutter/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,8 @@ android {
9292
9393
To use Material Components when the user interacts with input elements in the WebView,
9494
follow the steps described in the [Enabling Material Components instructions](https://flutter.dev/docs/deployment/android#enabling-material-components).
95+
96+
### Setting custom headers on POST requests
97+
98+
Currently, setting custom headers when making a post request with the WebViewController's `loadRequest` method is not supported on Android.
99+
If you require this functionality, a workaround is to make the request manually, and then load the response data using `loadHTMLString` instead.

packages/webview_flutter/webview_flutter/example/lib/main.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import 'dart:async';
88
import 'dart:convert';
99
import 'dart:io';
10+
import 'dart:typed_data';
1011

1112
import 'package:flutter/material.dart';
1213
import 'package:path_provider/path_provider.dart';
@@ -176,6 +177,7 @@ enum MenuOptions {
176177
listCache,
177178
clearCache,
178179
navigationDelegate,
180+
doPostRequest,
179181
loadLocalFile,
180182
loadHtmlString,
181183
transparentBackground,
@@ -218,6 +220,9 @@ class SampleMenu extends StatelessWidget {
218220
case MenuOptions.navigationDelegate:
219221
_onNavigationDelegateExample(controller.data!, context);
220222
break;
223+
case MenuOptions.doPostRequest:
224+
_onDoPostRequest(controller.data!, context);
225+
break;
221226
case MenuOptions.loadLocalFile:
222227
_onLoadLocalFileExample(controller.data!, context);
223228
break;
@@ -259,6 +264,10 @@ class SampleMenu extends StatelessWidget {
259264
value: MenuOptions.navigationDelegate,
260265
child: Text('Navigation Delegate example'),
261266
),
267+
const PopupMenuItem<MenuOptions>(
268+
value: MenuOptions.doPostRequest,
269+
child: Text('Post Request'),
270+
),
262271
const PopupMenuItem<MenuOptions>(
263272
value: MenuOptions.loadHtmlString,
264273
child: Text('Load HTML string'),
@@ -348,6 +357,17 @@ class SampleMenu extends StatelessWidget {
348357
await controller.loadUrl('data:text/html;base64,$contentBase64');
349358
}
350359

360+
Future<void> _onDoPostRequest(
361+
WebViewController controller, BuildContext context) async {
362+
final WebViewRequest request = WebViewRequest(
363+
uri: Uri.parse('https://httpbin.org/post'),
364+
method: WebViewRequestMethod.post,
365+
headers: <String, String>{'foo': 'bar', 'Content-Type': 'text/plain'},
366+
body: Uint8List.fromList('Test Body'.codeUnits),
367+
);
368+
await controller.loadRequest(request);
369+
}
370+
351371
Future<void> _onLoadLocalFileExample(
352372
WebViewController controller, BuildContext context) async {
353373
final String pathToIndex = await _prepareLocalFile();

packages/webview_flutter/webview_flutter/lib/platform_interface.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ export 'package:webview_flutter_platform_interface/webview_flutter_platform_inte
2121
WebSetting,
2222
WebSettings,
2323
WebResourceError,
24-
WebResourceErrorType;
24+
WebResourceErrorType,
25+
WebViewRequest,
26+
WebViewRequestMethod;

packages/webview_flutter/webview_flutter/lib/src/webview.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,26 @@ class WebViewController {
550550
return _webViewPlatformController.loadUrl(url, headers);
551551
}
552552

553+
/// Makes a specific HTTP request and loads the response in the webview.
554+
///
555+
/// [WebViewRequest.method] must be one of the supported HTTP methods
556+
/// in [WebViewRequestMethod].
557+
///
558+
/// If [WebViewRequest.headers] is not empty, its key-value pairs will be
559+
/// added as the headers for the request.
560+
///
561+
/// If [WebViewRequest.body] is not null, it will be added as the body
562+
/// for the request.
563+
///
564+
/// Throws an ArgumentError if [WebViewRequest.uri] has empty scheme.
565+
///
566+
/// Android only:
567+
/// When making a POST request, headers are ignored. As a workaround, make
568+
/// the request manually and load the response data using [loadHTMLString].
569+
Future<void> loadRequest(WebViewRequest request) async {
570+
return _webViewPlatformController.loadRequest(request);
571+
}
572+
553573
/// Accessor to the current URL that the WebView is displaying.
554574
///
555575
/// If [WebView.initialUrl] was never specified, returns `null`.

packages/webview_flutter/webview_flutter/pubspec.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: webview_flutter
22
description: A Flutter plugin that provides a WebView widget on Android and iOS.
33
repository: https://github.com/flutter/plugins/tree/master/packages/webview_flutter/webview_flutter
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
5-
version: 2.5.0
5+
version: 2.6.0
66

77
environment:
88
sdk: ">=2.14.0 <3.0.0"
@@ -19,8 +19,8 @@ flutter:
1919
dependencies:
2020
flutter:
2121
sdk: flutter
22-
webview_flutter_android: ^2.5.0
23-
webview_flutter_platform_interface: ^1.7.0
22+
webview_flutter_android: ^2.7.0
23+
webview_flutter_platform_interface: ^1.8.0
2424
webview_flutter_wkwebview: ^2.5.0
2525

2626
dev_dependencies:

packages/webview_flutter/webview_flutter/test/webview_flutter_test.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:typed_data';
6+
57
import 'package:flutter/src/foundation/basic_types.dart';
68
import 'package:flutter/src/gestures/recognizer.dart';
79
import 'package:flutter/widgets.dart';
@@ -246,6 +248,29 @@ void main() {
246248
));
247249
});
248250

251+
testWidgets('loadRequest', (WidgetTester tester) async {
252+
WebViewController? controller;
253+
await tester.pumpWidget(
254+
WebView(
255+
onWebViewCreated: (WebViewController webViewController) {
256+
controller = webViewController;
257+
},
258+
),
259+
);
260+
expect(controller, isNotNull);
261+
262+
final WebViewRequest req = WebViewRequest(
263+
uri: Uri.parse('https://flutter.dev'),
264+
method: WebViewRequestMethod.post,
265+
headers: <String, String>{'foo': 'bar'},
266+
body: Uint8List.fromList('Test Body'.codeUnits),
267+
);
268+
269+
await controller!.loadRequest(req);
270+
271+
verify(mockWebViewPlatformController.loadRequest(req));
272+
});
273+
249274
testWidgets('Clear Cache', (WidgetTester tester) async {
250275
WebViewController? controller;
251276
await tester.pumpWidget(

packages/webview_flutter/webview_flutter/test/webview_flutter_test.mocks.dart

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
15
// Mocks generated by Mockito 5.0.16 from annotations
26
// in webview_flutter/test/webview_flutter_test.dart.
37
// Do not manually edit this file.
48

59
import 'dart:async' as _i9;
610

7-
import 'package:flutter/foundation.dart' as _i7;
11+
import 'package:flutter/foundation.dart' as _i3;
812
import 'package:flutter/gestures.dart' as _i8;
913
import 'package:flutter/widgets.dart' as _i2;
1014
import 'package:mockito/mockito.dart' as _i1;
1115
import 'package:webview_flutter_platform_interface/src/platform_interface/javascript_channel_registry.dart'
12-
as _i6;
16+
as _i7;
1317
import 'package:webview_flutter_platform_interface/src/platform_interface/webview_platform.dart'
14-
as _i3;
18+
as _i4;
1519
import 'package:webview_flutter_platform_interface/src/platform_interface/webview_platform_callbacks_handler.dart'
16-
as _i5;
20+
as _i6;
1721
import 'package:webview_flutter_platform_interface/src/platform_interface/webview_platform_controller.dart'
1822
as _i10;
19-
import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i4;
23+
import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i5;
2024

2125
// ignore_for_file: avoid_redundant_argument_values
2226
// ignore_for_file: avoid_setters_without_getters
@@ -29,26 +33,26 @@ import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i4;
2933

3034
class _FakeWidget_0 extends _i1.Fake implements _i2.Widget {
3135
@override
32-
String toString({_i2.DiagnosticLevel? minLevel = _i2.DiagnosticLevel.info}) =>
36+
String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) =>
3337
super.toString();
3438
}
3539

3640
/// A class which mocks [WebViewPlatform].
3741
///
3842
/// See the documentation for Mockito's code generation for more information.
39-
class MockWebViewPlatform extends _i1.Mock implements _i3.WebViewPlatform {
43+
class MockWebViewPlatform extends _i1.Mock implements _i4.WebViewPlatform {
4044
MockWebViewPlatform() {
4145
_i1.throwOnMissingStub(this);
4246
}
4347

4448
@override
4549
_i2.Widget build(
4650
{_i2.BuildContext? context,
47-
_i4.CreationParams? creationParams,
48-
_i5.WebViewPlatformCallbacksHandler? webViewPlatformCallbacksHandler,
49-
_i6.JavascriptChannelRegistry? javascriptChannelRegistry,
50-
_i3.WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
51-
Set<_i7.Factory<_i8.OneSequenceGestureRecognizer>>?
51+
_i5.CreationParams? creationParams,
52+
_i6.WebViewPlatformCallbacksHandler? webViewPlatformCallbacksHandler,
53+
_i7.JavascriptChannelRegistry? javascriptChannelRegistry,
54+
_i4.WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
55+
Set<_i3.Factory<_i8.OneSequenceGestureRecognizer>>?
5256
gestureRecognizers}) =>
5357
(super.noSuchMethod(
5458
Invocation.method(#build, [], {
@@ -83,6 +87,11 @@ class MockWebViewPlatformController extends _i1.Mock
8387
returnValue: Future<void>.value(),
8488
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
8589
@override
90+
_i9.Future<void> loadFlutterAsset(String? key) =>
91+
(super.noSuchMethod(Invocation.method(#loadFlutterAsset, [key]),
92+
returnValue: Future<void>.value(),
93+
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
94+
@override
8695
_i9.Future<void> loadHtmlString(String? html, {String? baseUrl}) =>
8796
(super.noSuchMethod(
8897
Invocation.method(#loadHtmlString, [html], {#baseUrl: baseUrl}),
@@ -94,12 +103,12 @@ class MockWebViewPlatformController extends _i1.Mock
94103
returnValue: Future<void>.value(),
95104
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
96105
@override
97-
_i9.Future<void> loadRequest(_i4.WebViewRequest? request) =>
106+
_i9.Future<void> loadRequest(_i5.WebViewRequest? request) =>
98107
(super.noSuchMethod(Invocation.method(#loadRequest, [request]),
99108
returnValue: Future<void>.value(),
100109
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
101110
@override
102-
_i9.Future<void> updateSettings(_i4.WebSettings? setting) =>
111+
_i9.Future<void> updateSettings(_i5.WebSettings? setting) =>
103112
(super.noSuchMethod(Invocation.method(#updateSettings, [setting]),
104113
returnValue: Future<void>.value(),
105114
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);

0 commit comments

Comments
 (0)