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

Commit

Permalink
[webview_flutter_web] Copies web implementation of webview_flutter fr…
Browse files Browse the repository at this point in the history
…om v4_webview (#6854)

* v4 web impl

* add breaking change

* fix lints

* exclude web plugin
  • Loading branch information
bparrishMines committed Dec 16, 2022
1 parent 5f62d21 commit ca974ab
Show file tree
Hide file tree
Showing 22 changed files with 1,136 additions and 381 deletions.
4 changes: 3 additions & 1 deletion packages/webview_flutter/webview_flutter_web/CHANGELOG.md
@@ -1,5 +1,7 @@
## NEXT
## 0.2.0

* **BREAKING CHANGE** Updates platform implementation to `2.0.0` release of
`webview_flutter_platform_interface`. See README for updated usage.
* Updates minimum Flutter version to 2.10.

## 0.1.0+4
Expand Down
12 changes: 5 additions & 7 deletions packages/webview_flutter/webview_flutter_web/README.md
Expand Up @@ -5,10 +5,8 @@ This is an implementation of the [`webview_flutter`](https://pub.dev/packages/we
It is currently severely limited and doesn't implement most of the available functionality.
The following functionality is currently available:

- `loadUrl` (Without headers)
- `requestUrl`
- `loadHTMLString` (Without `baseUrl`)
- Setting the `initialUrl` through `CreationParams`.
- `loadRequest`
- `loadHtmlString` (Without `baseUrl`)

Nothing else is currently supported.

Expand All @@ -20,7 +18,7 @@ yet, so it currently requires extra setup to use:
* [Add this package](https://pub.dev/packages/webview_flutter_web/install)
as an explicit dependency of your project, in addition to depending on
`webview_flutter`.
* Register `WebWebViewPlatform` as the `WebView.platform` before creating a
* Register `WebWebViewPlatform` as the `WebViewPlatform.instance` before creating a
`WebView`. See below for examples.

Once those steps below are complete, the APIs from `webview_flutter` listed
Expand All @@ -39,7 +37,7 @@ import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_web/webview_flutter_web.dart';
main() {
WebView.platform = WebWebViewPlatform();
WebViewPlatform.instance = WebWebViewPlatform();
...
```

Expand All @@ -55,7 +53,7 @@ import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_web/webview_flutter_web.dart';
void registerWebViewWebImplementation() {
WebView.platform = WebWebViewPlatform();
WebViewPlatform.instance = WebWebViewPlatform();
}
```

Expand Down
@@ -0,0 +1,72 @@
// 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.

import 'dart:async';
import 'dart:html' as html;

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:webview_flutter_web_example/legacy/web_view.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

// URLs to navigate to in tests. These need to be URLs that we are confident will
// always be accessible, and won't do redirection. (E.g., just
// 'https://www.google.com/' will sometimes redirect traffic that looks
// like it's coming from a bot, which is true of these tests).
const String primaryUrl = 'https://flutter.dev/';
const String secondaryUrl = 'https://www.google.com/robots.txt';

testWidgets('initialUrl', (WidgetTester tester) async {
final Completer<WebViewController> controllerCompleter =
Completer<WebViewController>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: WebView(
key: GlobalKey(),
initialUrl: primaryUrl,
onWebViewCreated: (WebViewController controller) {
controllerCompleter.complete(controller);
},
),
),
);
await controllerCompleter.future;

// Assert an iframe has been rendered to the DOM with the correct src attribute.
final html.IFrameElement? element =
html.document.querySelector('iframe') as html.IFrameElement?;
expect(element, isNotNull);
expect(element!.src, primaryUrl);
});

testWidgets('loadUrl', (WidgetTester tester) async {
final Completer<WebViewController> controllerCompleter =
Completer<WebViewController>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: WebView(
key: GlobalKey(),
initialUrl: primaryUrl,
onWebViewCreated: (WebViewController controller) {
controllerCompleter.complete(controller);
},
),
),
);
final WebViewController controller = await controllerCompleter.future;
await controller.loadUrl(secondaryUrl);

// Assert an iframe has been rendered to the DOM with the correct src attribute.
final html.IFrameElement? element =
html.document.querySelector('iframe') as html.IFrameElement?;
expect(element, isNotNull);
expect(element!.src, secondaryUrl);
});
}
Expand Up @@ -2,41 +2,48 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:html' as html;
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:webview_flutter_web_example/web_view.dart';
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
import 'package:webview_flutter_web/webview_flutter_web.dart';

void main() {
Future<void> main() async {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

// URLs to navigate to in tests. These need to be URLs that we are confident will
// always be accessible, and won't do redirection. (E.g., just
// 'https://www.google.com/' will sometimes redirect traffic that looks
// like it's coming from a bot, which is true of these tests).
const String primaryUrl = 'https://flutter.dev/';
const String secondaryUrl = 'https://www.google.com/robots.txt';
final HttpServer server = await HttpServer.bind(InternetAddress.anyIPv4, 0);
server.forEach((HttpRequest request) {
if (request.uri.path == '/hello.txt') {
request.response.writeln('Hello, world.');
} else {
fail('unexpected request: ${request.method} ${request.uri}');
}
request.response.close();
});
final String prefixUrl = 'http://${server.address.address}:${server.port}';
final String primaryUrl = '$prefixUrl/hello.txt';

testWidgets('loadRequest', (WidgetTester tester) async {
final WebWebViewController controller =
WebWebViewController(const PlatformWebViewControllerCreationParams())
..loadRequest(
LoadRequestParams(uri: Uri.parse(primaryUrl)),
);

testWidgets('initialUrl', (WidgetTester tester) async {
final Completer<WebViewController> controllerCompleter =
Completer<WebViewController>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: WebView(
key: GlobalKey(),
initialUrl: primaryUrl,
onWebViewCreated: (WebViewController controller) {
controllerCompleter.complete(controller);
},
),
child: Builder(builder: (BuildContext context) {
return WebWebViewWidget(
PlatformWebViewWidgetCreationParams(controller: controller),
).build(context);
}),
),
);
await controllerCompleter.future;

// Assert an iframe has been rendered to the DOM with the correct src attribute.
final html.IFrameElement? element =
Expand All @@ -45,28 +52,31 @@ void main() {
expect(element!.src, primaryUrl);
});

testWidgets('loadUrl', (WidgetTester tester) async {
final Completer<WebViewController> controllerCompleter =
Completer<WebViewController>();
testWidgets('loadHtmlString', (WidgetTester tester) async {
final WebWebViewController controller =
WebWebViewController(const PlatformWebViewControllerCreationParams())
..loadHtmlString(
'data:text/html;charset=utf-8,${Uri.encodeFull('test html')}',
);

await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: WebView(
key: GlobalKey(),
initialUrl: primaryUrl,
onWebViewCreated: (WebViewController controller) {
controllerCompleter.complete(controller);
},
),
child: Builder(builder: (BuildContext context) {
return WebWebViewWidget(
PlatformWebViewWidgetCreationParams(controller: controller),
).build(context);
}),
),
);
final WebViewController controller = await controllerCompleter.future;
await controller.loadUrl(secondaryUrl);

// Assert an iframe has been rendered to the DOM with the correct src attribute.
final html.IFrameElement? element =
html.document.querySelector('iframe') as html.IFrameElement?;
expect(element, isNotNull);
expect(element!.src, secondaryUrl);
expect(
element!.src,
'data:text/html;charset=utf-8,data:text/html;charset=utf-8,test%2520html',
);
});
}
Expand Up @@ -5,8 +5,10 @@
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
import 'package:webview_flutter_web/webview_flutter_web.dart';
// ignore: implementation_imports
import 'package:webview_flutter_platform_interface/src/webview_flutter_platform_interface_legacy.dart';
// ignore: implementation_imports
import 'package:webview_flutter_web/src/webview_flutter_web_legacy.dart';

/// Optional callback invoked when a web view is first created. [controller] is
/// the [WebViewController] for the created web view.
Expand Down
72 changes: 35 additions & 37 deletions packages/webview_flutter/webview_flutter_web/example/lib/main.dart
Expand Up @@ -8,10 +8,10 @@ import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';

import 'web_view.dart';
import 'package:webview_flutter_web/webview_flutter_web.dart';

void main() {
WebViewPlatform.instance = WebWebViewPlatform();
runApp(const MaterialApp(home: _WebViewExample()));
}

Expand All @@ -23,24 +23,26 @@ class _WebViewExample extends StatefulWidget {
}

class _WebViewExampleState extends State<_WebViewExample> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();
final PlatformWebViewController _controller = PlatformWebViewController(
const PlatformWebViewControllerCreationParams(),
)..loadRequest(
LoadRequestParams(
uri: Uri.parse('https://flutter.dev'),
),
);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView example'),
actions: <Widget>[
_SampleMenu(_controller.future),
_SampleMenu(_controller),
],
),
body: WebView(
initialUrl: 'https://flutter.dev',
onWebViewCreated: (WebViewController controller) {
_controller.complete(controller);
},
),
body: PlatformWebViewWidget(
PlatformWebViewWidgetCreationParams(controller: _controller),
).build(context),
);
}
}
Expand All @@ -52,41 +54,37 @@ enum _MenuOptions {
class _SampleMenu extends StatelessWidget {
const _SampleMenu(this.controller);

final Future<WebViewController> controller;
final PlatformWebViewController controller;

@override
Widget build(BuildContext context) {
return FutureBuilder<WebViewController>(
future: controller,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> controller) {
return PopupMenuButton<_MenuOptions>(
onSelected: (_MenuOptions value) {
switch (value) {
case _MenuOptions.doPostRequest:
_onDoPostRequest(controller.data!, context);
break;
}
},
itemBuilder: (BuildContext context) => <PopupMenuItem<_MenuOptions>>[
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.doPostRequest,
child: Text('Post Request'),
),
],
);
return PopupMenuButton<_MenuOptions>(
onSelected: (_MenuOptions value) {
switch (value) {
case _MenuOptions.doPostRequest:
_onDoPostRequest(controller);
break;
}
},
itemBuilder: (BuildContext context) => <PopupMenuItem<_MenuOptions>>[
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.doPostRequest,
child: Text('Post Request'),
),
],
);
}

Future<void> _onDoPostRequest(
WebViewController controller, BuildContext context) async {
final WebViewRequest request = WebViewRequest(
Future<void> _onDoPostRequest(PlatformWebViewController controller) async {
final LoadRequestParams params = LoadRequestParams(
uri: Uri.parse('https://httpbin.org/post'),
method: WebViewRequestMethod.post,
headers: <String, String>{'foo': 'bar', 'Content-Type': 'text/plain'},
method: LoadRequestMethod.post,
headers: const <String, String>{
'foo': 'bar',
'Content-Type': 'text/plain'
},
body: Uint8List.fromList('Test Body'.codeUnits),
);
await controller.loadRequest(request);
await controller.loadRequest(params);
}
}
Expand Up @@ -10,7 +10,7 @@ dependencies:
sdk: flutter
flutter_web_plugins:
sdk: flutter
webview_flutter_platform_interface: ^1.8.0
webview_flutter_platform_interface: ^2.0.0
webview_flutter_web:
# When depending on this package from a real application you should use:
# webview_flutter_web: ^x.y.z
Expand Down

0 comments on commit ca974ab

Please sign in to comment.