Skip to content

Commit

Permalink
[webview_flutter] Add loadRequest functionality to app facing package. (
Browse files Browse the repository at this point in the history
flutter#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.
  • Loading branch information
BeMacized committed Dec 7, 2021
1 parent 0f0dcbf commit c691451
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 18 deletions.
4 changes: 4 additions & 0 deletions packages/webview_flutter/webview_flutter/CHANGELOG.md
@@ -1,3 +1,7 @@
## 2.6.0

* Adds support for the `loadRequest` method.

## 2.5.0

* Adds an option to set the background color of the webview.
Expand Down
5 changes: 5 additions & 0 deletions packages/webview_flutter/webview_flutter/README.md
Expand Up @@ -92,3 +92,8 @@ android {

To use Material Components when the user interacts with input elements in the WebView,
follow the steps described in the [Enabling Material Components instructions](https://flutter.dev/docs/deployment/android#enabling-material-components).

### Setting custom headers on POST requests

Currently, setting custom headers when making a post request with the WebViewController's `loadRequest` method is not supported on Android.
If you require this functionality, a workaround is to make the request manually, and then load the response data using `loadHTMLString` instead.
20 changes: 20 additions & 0 deletions packages/webview_flutter/webview_flutter/example/lib/main.dart
Expand Up @@ -7,6 +7,7 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
Expand Down Expand Up @@ -176,6 +177,7 @@ enum MenuOptions {
listCache,
clearCache,
navigationDelegate,
doPostRequest,
loadLocalFile,
loadHtmlString,
transparentBackground,
Expand Down Expand Up @@ -218,6 +220,9 @@ class SampleMenu extends StatelessWidget {
case MenuOptions.navigationDelegate:
_onNavigationDelegateExample(controller.data!, context);
break;
case MenuOptions.doPostRequest:
_onDoPostRequest(controller.data!, context);
break;
case MenuOptions.loadLocalFile:
_onLoadLocalFileExample(controller.data!, context);
break;
Expand Down Expand Up @@ -259,6 +264,10 @@ class SampleMenu extends StatelessWidget {
value: MenuOptions.navigationDelegate,
child: Text('Navigation Delegate example'),
),
const PopupMenuItem<MenuOptions>(
value: MenuOptions.doPostRequest,
child: Text('Post Request'),
),
const PopupMenuItem<MenuOptions>(
value: MenuOptions.loadHtmlString,
child: Text('Load HTML string'),
Expand Down Expand Up @@ -348,6 +357,17 @@ class SampleMenu extends StatelessWidget {
await controller.loadUrl('data:text/html;base64,$contentBase64');
}

Future<void> _onDoPostRequest(
WebViewController controller, BuildContext context) async {
final WebViewRequest request = WebViewRequest(
uri: Uri.parse('https://httpbin.org/post'),
method: WebViewRequestMethod.post,
headers: <String, String>{'foo': 'bar', 'Content-Type': 'text/plain'},
body: Uint8List.fromList('Test Body'.codeUnits),
);
await controller.loadRequest(request);
}

Future<void> _onLoadLocalFileExample(
WebViewController controller, BuildContext context) async {
final String pathToIndex = await _prepareLocalFile();
Expand Down
Expand Up @@ -21,4 +21,6 @@ export 'package:webview_flutter_platform_interface/webview_flutter_platform_inte
WebSetting,
WebSettings,
WebResourceError,
WebResourceErrorType;
WebResourceErrorType,
WebViewRequest,
WebViewRequestMethod;
20 changes: 20 additions & 0 deletions packages/webview_flutter/webview_flutter/lib/src/webview.dart
Expand Up @@ -550,6 +550,26 @@ class WebViewController {
return _webViewPlatformController.loadUrl(url, headers);
}

/// Makes a specific HTTP request and loads the response in the webview.
///
/// [WebViewRequest.method] must be one of the supported HTTP methods
/// in [WebViewRequestMethod].
///
/// If [WebViewRequest.headers] is not empty, its key-value pairs will be
/// added as the headers for the request.
///
/// If [WebViewRequest.body] is not null, it will be added as the body
/// for the request.
///
/// Throws an ArgumentError if [WebViewRequest.uri] has empty scheme.
///
/// Android only:
/// When making a POST request, headers are ignored. As a workaround, make
/// the request manually and load the response data using [loadHTMLString].
Future<void> loadRequest(WebViewRequest request) async {
return _webViewPlatformController.loadRequest(request);
}

/// Accessor to the current URL that the WebView is displaying.
///
/// If [WebView.initialUrl] was never specified, returns `null`.
Expand Down
6 changes: 3 additions & 3 deletions packages/webview_flutter/webview_flutter/pubspec.yaml
Expand Up @@ -2,7 +2,7 @@ name: webview_flutter
description: A Flutter plugin that provides a WebView widget on Android and iOS.
repository: https://github.com/flutter/plugins/tree/master/packages/webview_flutter/webview_flutter
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
version: 2.5.0
version: 2.6.0

environment:
sdk: ">=2.14.0 <3.0.0"
Expand All @@ -19,8 +19,8 @@ flutter:
dependencies:
flutter:
sdk: flutter
webview_flutter_android: ^2.5.0
webview_flutter_platform_interface: ^1.7.0
webview_flutter_android: ^2.7.0
webview_flutter_platform_interface: ^1.8.0
webview_flutter_wkwebview: ^2.5.0

dev_dependencies:
Expand Down
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:typed_data';

import 'package:flutter/src/foundation/basic_types.dart';
import 'package:flutter/src/gestures/recognizer.dart';
import 'package:flutter/widgets.dart';
Expand Down Expand Up @@ -246,6 +248,29 @@ void main() {
));
});

testWidgets('loadRequest', (WidgetTester tester) async {
WebViewController? controller;
await tester.pumpWidget(
WebView(
onWebViewCreated: (WebViewController webViewController) {
controller = webViewController;
},
),
);
expect(controller, isNotNull);

final WebViewRequest req = WebViewRequest(
uri: Uri.parse('https://flutter.dev'),
method: WebViewRequestMethod.post,
headers: <String, String>{'foo': 'bar'},
body: Uint8List.fromList('Test Body'.codeUnits),
);

await controller!.loadRequest(req);

verify(mockWebViewPlatformController.loadRequest(req));
});

testWidgets('Clear Cache', (WidgetTester tester) async {
WebViewController? controller;
await tester.pumpWidget(
Expand Down
@@ -1,22 +1,26 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Mocks generated by Mockito 5.0.16 from annotations
// in webview_flutter/test/webview_flutter_test.dart.
// Do not manually edit this file.

import 'dart:async' as _i9;

import 'package:flutter/foundation.dart' as _i7;
import 'package:flutter/foundation.dart' as _i3;
import 'package:flutter/gestures.dart' as _i8;
import 'package:flutter/widgets.dart' as _i2;
import 'package:mockito/mockito.dart' as _i1;
import 'package:webview_flutter_platform_interface/src/platform_interface/javascript_channel_registry.dart'
as _i6;
as _i7;
import 'package:webview_flutter_platform_interface/src/platform_interface/webview_platform.dart'
as _i3;
as _i4;
import 'package:webview_flutter_platform_interface/src/platform_interface/webview_platform_callbacks_handler.dart'
as _i5;
as _i6;
import 'package:webview_flutter_platform_interface/src/platform_interface/webview_platform_controller.dart'
as _i10;
import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i4;
import 'package:webview_flutter_platform_interface/src/types/types.dart' as _i5;

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

class _FakeWidget_0 extends _i1.Fake implements _i2.Widget {
@override
String toString({_i2.DiagnosticLevel? minLevel = _i2.DiagnosticLevel.info}) =>
String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) =>
super.toString();
}

/// A class which mocks [WebViewPlatform].
///
/// See the documentation for Mockito's code generation for more information.
class MockWebViewPlatform extends _i1.Mock implements _i3.WebViewPlatform {
class MockWebViewPlatform extends _i1.Mock implements _i4.WebViewPlatform {
MockWebViewPlatform() {
_i1.throwOnMissingStub(this);
}

@override
_i2.Widget build(
{_i2.BuildContext? context,
_i4.CreationParams? creationParams,
_i5.WebViewPlatformCallbacksHandler? webViewPlatformCallbacksHandler,
_i6.JavascriptChannelRegistry? javascriptChannelRegistry,
_i3.WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
Set<_i7.Factory<_i8.OneSequenceGestureRecognizer>>?
_i5.CreationParams? creationParams,
_i6.WebViewPlatformCallbacksHandler? webViewPlatformCallbacksHandler,
_i7.JavascriptChannelRegistry? javascriptChannelRegistry,
_i4.WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
Set<_i3.Factory<_i8.OneSequenceGestureRecognizer>>?
gestureRecognizers}) =>
(super.noSuchMethod(
Invocation.method(#build, [], {
Expand Down Expand Up @@ -83,6 +87,11 @@ class MockWebViewPlatformController extends _i1.Mock
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
@override
_i9.Future<void> loadFlutterAsset(String? key) =>
(super.noSuchMethod(Invocation.method(#loadFlutterAsset, [key]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
@override
_i9.Future<void> loadHtmlString(String? html, {String? baseUrl}) =>
(super.noSuchMethod(
Invocation.method(#loadHtmlString, [html], {#baseUrl: baseUrl}),
Expand All @@ -94,12 +103,12 @@ class MockWebViewPlatformController extends _i1.Mock
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
@override
_i9.Future<void> loadRequest(_i4.WebViewRequest? request) =>
_i9.Future<void> loadRequest(_i5.WebViewRequest? request) =>
(super.noSuchMethod(Invocation.method(#loadRequest, [request]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
@override
_i9.Future<void> updateSettings(_i4.WebSettings? setting) =>
_i9.Future<void> updateSettings(_i5.WebSettings? setting) =>
(super.noSuchMethod(Invocation.method(#updateSettings, [setting]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i9.Future<void>);
Expand Down

0 comments on commit c691451

Please sign in to comment.