Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/webview_flutter/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:3.3.0'
classpath 'com.android.tools.build:gradle:3.5.2'
}
}

Expand All @@ -33,8 +33,8 @@ android {
}

dependencies {
implementation 'androidx.annotation:annotation:1.0.0'
implementation 'androidx.webkit:webkit:1.0.0'
implementation 'androidx.annotation:annotation:1.1.0'
implementation 'androidx.webkit:webkit:1.1.0'
}
}

Expand All @@ -61,4 +61,4 @@ afterEvaluate {
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
import android.os.Build.VERSION_CODES;
import android.webkit.CookieManager;
import android.webkit.ValueCallback;

import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
Expand All @@ -25,6 +32,12 @@ class FlutterCookieManager implements MethodCallHandler {
@Override
public void onMethodCall(MethodCall methodCall, Result result) {
switch (methodCall.method) {
case "getCookies":
getCookies(methodCall, result);
break;
case "setCookies":
setCookies(methodCall, result);
break;
case "clearCookies":
clearCookies(result);
break;
Expand All @@ -37,20 +50,72 @@ void dispose() {
methodChannel.setMethodCallHandler(null);
}

private static void clearCookies(final Result result) {
private String getUrlArgument(MethodCall methodCall, final Result result) {
if (!(methodCall.arguments() instanceof Map)) {
result.error(
"Invalid argument. Expected Map<String, dynamic>, received " + (methodCall.arguments()
.getClass()
.getSimpleName()), null, null);
return null;
}

String url = methodCall.argument("url");
if (url == null || url.length() == 0) {
result.error("Missing url argument", null, null);
return null;
}
return url;
}

private void getCookies(final MethodCall methodCall, final Result result) {
String url = getUrlArgument(methodCall, result);
if (url == null) {
return;
}

CookieManager cookieManager = CookieManager.getInstance();
final boolean hasCookies = cookieManager.hasCookies();
final String cookie = cookieManager.getCookie(url);
result.success(cookie != null ? cookie : "");
}

private void setCookies(final MethodCall methodCall, final Result result) {
String url = getUrlArgument(methodCall, result);
if (url == null) {
return;
}

final List<String> cookies = methodCall.argument("cookies");
if (cookies == null) {
result.error("Missing cookies argument", null, null);
return;
}

final CookieManager cookieManager = CookieManager.getInstance();
for (String cookie : cookies) {
cookieManager.setCookie(url, cookie);
}

if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
cookieManager.removeAllCookies(
new ValueCallback<Boolean>() {
@Override
public void onReceiveValue(Boolean value) {
result.success(hasCookies);
}
});
} else {
cookieManager.flush();
}

result.success(true);
}

private void clearCookies(final Result result) {
final CookieManager cookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
cookieManager.removeAllCookies(new ValueCallback<Boolean>() {
@Override
public void onReceiveValue(Boolean value) {
cookieManager.flush();
result.success(value);
}
});
}
else {
cookieManager.removeAllCookie();
result.success(hasCookies);
result.success(true);
}
}
}
85 changes: 47 additions & 38 deletions packages/webview_flutter/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// 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:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

Expand All @@ -30,8 +30,8 @@ class WebViewExample extends StatefulWidget {
}

class _WebViewExampleState extends State<WebViewExample> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();
final ValueNotifier<WebViewController> _controller =
ValueNotifier<WebViewController>(null);

@override
Widget build(BuildContext context) {
Expand All @@ -40,8 +40,8 @@ class _WebViewExampleState extends State<WebViewExample> {
title: const Text('Flutter WebView example'),
// This drop down menu demonstrates that Flutter widgets can be shown over the web view.
actions: <Widget>[
NavigationControls(_controller.future),
SampleMenu(_controller.future),
NavigationControls(_controller),
SampleMenu(_controller),
],
),
// We're using a Builder here so we have a context that is below the Scaffold
Expand All @@ -51,7 +51,7 @@ class _WebViewExampleState extends State<WebViewExample> {
initialUrl: 'https://flutter.dev',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
_controller.value = webViewController;
},
// TODO(iskakaushik): Remove this when collection literals makes it to stable.
// ignore: prefer_collection_literals
Expand Down Expand Up @@ -86,14 +86,13 @@ class _WebViewExampleState extends State<WebViewExample> {
}

Widget favoriteButton() {
return FutureBuilder<WebViewController>(
future: _controller.future,
builder: (BuildContext context,
AsyncSnapshot<WebViewController> controller) {
if (controller.hasData) {
return ValueListenableBuilder<WebViewController>(
valueListenable: _controller,
builder: (BuildContext context, WebViewController controller, Widget child) {
if (controller != null) {
return FloatingActionButton(
onPressed: () async {
final String url = await controller.data.currentUrl();
final String url = await controller.currentUrl();
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('Favorited $url')),
);
Expand All @@ -119,46 +118,46 @@ enum MenuOptions {
class SampleMenu extends StatelessWidget {
SampleMenu(this.controller);

final Future<WebViewController> controller;
final ValueNotifier<WebViewController> controller;
final CookieManager cookieManager = CookieManager();

@override
Widget build(BuildContext context) {
return FutureBuilder<WebViewController>(
future: controller,
return ValueListenableBuilder<WebViewController>(
valueListenable: controller,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> controller) {
(BuildContext context, WebViewController controller, Widget child) {
return PopupMenuButton<MenuOptions>(
onSelected: (MenuOptions value) {
switch (value) {
case MenuOptions.showUserAgent:
_onShowUserAgent(controller.data, context);
_onShowUserAgent(controller, context);
break;
case MenuOptions.listCookies:
_onListCookies(controller.data, context);
_onListCookies(controller, context);
break;
case MenuOptions.clearCookies:
_onClearCookies(context);
break;
case MenuOptions.addToCache:
_onAddToCache(controller.data, context);
_onAddToCache(controller, context);
break;
case MenuOptions.listCache:
_onListCache(controller.data, context);
_onListCache(controller, context);
break;
case MenuOptions.clearCache:
_onClearCache(controller.data, context);
_onClearCache(controller, context);
break;
case MenuOptions.navigationDelegate:
_onNavigationDelegateExample(controller.data, context);
_onNavigationDelegateExample(controller, context);
break;
}
},
itemBuilder: (BuildContext context) => <PopupMenuItem<MenuOptions>>[
PopupMenuItem<MenuOptions>(
value: MenuOptions.showUserAgent,
child: const Text('Show user agent'),
enabled: controller.hasData,
enabled: controller != null,
),
const PopupMenuItem<MenuOptions>(
value: MenuOptions.listCookies,
Expand Down Expand Up @@ -200,8 +199,7 @@ class SampleMenu extends StatelessWidget {

void _onListCookies(
WebViewController controller, BuildContext context) async {
final String cookies =
await controller.evaluateJavascript('document.cookie');
final List<Cookie> cookies = await cookieManager.getCookies(await controller.currentUrl());
Scaffold.of(context).showSnackBar(SnackBar(
content: Column(
mainAxisAlignment: MainAxisAlignment.end,
Expand Down Expand Up @@ -253,13 +251,27 @@ class SampleMenu extends StatelessWidget {
controller.loadUrl('data:text/html;base64,$contentBase64');
}

Widget _getCookieList(String cookies) {
if (cookies == null || cookies == '""') {
Widget _getCookieList(List<Cookie> cookies) {
if (cookies == null || cookies.isEmpty) {
return Container();
}
final List<String> cookieList = cookies.split(';');
final Iterable<Text> cookieWidgets =
cookieList.map((String cookie) => Text(cookie));
final Iterable<RichText> cookieWidgets = cookies.map(
(Cookie cookie) => RichText(
text: TextSpan(
children: <InlineSpan>[
TextSpan(
text: '${cookie.name}',
style: TextStyle(fontWeight: FontWeight.bold),
),
const TextSpan(text: ' = '),
TextSpan(
text: '${cookie.value}',
style: TextStyle(color: Colors.grey.shade400),
),
],
),
),
);
return Column(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
Expand All @@ -272,17 +284,14 @@ class NavigationControls extends StatelessWidget {
const NavigationControls(this._webViewControllerFuture)
: assert(_webViewControllerFuture != null);

final Future<WebViewController> _webViewControllerFuture;
final ValueNotifier<WebViewController> _webViewControllerFuture;

@override
Widget build(BuildContext context) {
return FutureBuilder<WebViewController>(
future: _webViewControllerFuture,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> snapshot) {
final bool webViewReady =
snapshot.connectionState == ConnectionState.done;
final WebViewController controller = snapshot.data;
return ValueListenableBuilder<WebViewController>(
valueListenable: _webViewControllerFuture,
builder: (BuildContext context, WebViewController controller, Widget child) {
final bool webViewReady = controller != null;
return Row(
children: <Widget>[
IconButton(
Expand Down
Loading