? headers,
- double horizontalPadding = 0})
+ double horizontalPadding = 0,
+ bool darkMode = false})
async {
String fileText = await rootBundle.loadString('assets/html/html_wrapper.html');
html = _applyWorkAroundForDoubleSlashesAsUrlSource(html);
html = _addProtocolToLinks(html);
html = _checkForMathTags(html);
html = fileText.replaceAll('{CANVAS_CONTENT}', html);
+ html = html.replaceAll('{BACKGROUND}', darkMode ? '#000000' : '#ffffff');
+ html = html.replaceAll('{COLOR}', darkMode ? '#ffffff' : '#000000');
+ html = html.replaceAll('{LINK_COLOR}', darkMode ? '#1283C4' : '#0374B5');
+ html = html.replaceAll('{VISITED_LINK_COLOR}', darkMode ? '#C74BAF' : '#BF32A4');
html = html.replaceAll('{PADDING}', horizontalPadding.toString());
- this.loadData(baseUrl, html, 'text/html', 'utf-8');
+ this.loadHtmlString(html, baseUrl: baseUrl);
}
/**
diff --git a/apps/flutter_parent/plugins/webview_flutter/LICENSE b/apps/flutter_parent/plugins/webview_flutter/LICENSE
deleted file mode 100644
index ad33cf3c3e..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/LICENSE
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright 2018 The Chromium Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of Google Inc. nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/build.gradle b/apps/flutter_parent/plugins/webview_flutter/android/build.gradle
deleted file mode 100644
index 9e807667a5..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/build.gradle
+++ /dev/null
@@ -1,41 +0,0 @@
-group 'io.flutter.plugins.webviewflutter'
-version '1.0-SNAPSHOT'
-
-buildscript {
- repositories {
- google()
- mavenCentral()
- }
-
- dependencies {
- classpath "com.android.tools.build:gradle:7.4.2"
- }
-}
-
-rootProject.allprojects {
- repositories {
- google()
- mavenCentral()
- }
-}
-
-apply plugin: 'com.android.library'
-
-android {
- compileSdkVersion 33
-
- defaultConfig {
- minSdkVersion 21
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- }
- lintOptions {
- disable 'InvalidPackage'
- }
-
- dependencies {
- implementation 'androidx.annotation:annotation:1.0.0'
- implementation 'androidx.webkit:webkit:1.7.0'
- }
-
- namespace 'io.flutter.plugins.webviewflutter'
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/settings.gradle b/apps/flutter_parent/plugins/webview_flutter/android/settings.gradle
deleted file mode 100644
index 5be7a4b4c6..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/settings.gradle
+++ /dev/null
@@ -1 +0,0 @@
-rootProject.name = 'webview_flutter'
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/src/main/AndroidManifest.xml b/apps/flutter_parent/plugins/webview_flutter/android/src/main/AndroidManifest.xml
deleted file mode 100644
index a087f2c75c..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/DisplayListenerProxy.java b/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/DisplayListenerProxy.java
deleted file mode 100644
index 1273e73496..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/DisplayListenerProxy.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package io.flutter.plugins.webviewflutter;
-
-import static android.hardware.display.DisplayManager.DisplayListener;
-
-import android.annotation.TargetApi;
-import android.hardware.display.DisplayManager;
-import android.os.Build;
-import android.util.Log;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-
-/**
- * Works around an Android WebView bug by filtering some DisplayListener invocations.
- *
- * Older Android WebView versions had assumed that when {@link DisplayListener#onDisplayChanged}
- * is invoked, the display ID it is provided is of a valid display. However it turns out that when a
- * display is removed Android may call onDisplayChanged with the ID of the removed display, in this
- * case the Android WebView code tries to fetch and use the display with this ID and crashes with an
- * NPE.
- *
- *
This issue was fixed in the Android WebView code in
- * https://chromium-review.googlesource.com/517913 which is available starting WebView version
- * 58.0.3029.125 however older webviews in the wild still have this issue.
- *
- *
Since Flutter removes virtual displays whenever a platform view is resized the webview crash
- * is more likely to happen than other apps. And users were reporting this issue see:
- * https://github.com/flutter/flutter/issues/30420
- *
- *
This class works around the webview bug by unregistering the WebView's DisplayListener, and
- * instead registering its own DisplayListener which delegates the callbacks to the WebView's
- * listener unless it's a onDisplayChanged for an invalid display.
- *
- *
I did not find a clean way to get a handle of the WebView's DisplayListener so I'm using
- * reflection to fetch all registered listeners before and after initializing a webview. In the
- * first initialization of a webview within the process the difference between the lists is the
- * webview's display listener.
- */
-@TargetApi(Build.VERSION_CODES.KITKAT)
-class DisplayListenerProxy {
- private static final String TAG = "DisplayListenerProxy";
-
- private ArrayList listenersBeforeWebView;
-
- /** Should be called prior to the webview's initialization. */
- void onPreWebViewInitialization(DisplayManager displayManager) {
- listenersBeforeWebView = yoinkDisplayListeners(displayManager);
- }
-
- /** Should be called after the webview's initialization. */
- void onPostWebViewInitialization(final DisplayManager displayManager) {
- final ArrayList webViewListeners = yoinkDisplayListeners(displayManager);
- // We recorded the list of listeners prior to initializing webview, any new listeners we see
- // after initializing the webview are listeners added by the webview.
- webViewListeners.removeAll(listenersBeforeWebView);
-
- if (webViewListeners.isEmpty()) {
- // The Android WebView registers a single display listener per process (even if there
- // are multiple WebView instances) so this list is expected to be non-empty only the
- // first time a webview is initialized.
- // Note that in an add2app scenario if the application had instantiated a non Flutter
- // WebView prior to instantiating the Flutter WebView we are not able to get a reference
- // to the WebView's display listener and can't work around the bug.
- //
- // This means that webview resizes in add2app Flutter apps with a non Flutter WebView
- // running on a system with a webview prior to 58.0.3029.125 may crash (the Android's
- // behavior seems to be racy so it doesn't always happen).
- return;
- }
-
- for (DisplayListener webViewListener : webViewListeners) {
- // Note that while DisplayManager.unregisterDisplayListener throws when given an
- // unregistered listener, this isn't an issue as the WebView code never calls
- // unregisterDisplayListener.
- displayManager.unregisterDisplayListener(webViewListener);
-
- // We never explicitly unregister this listener as the webview's listener is never
- // unregistered (it's released when the process is terminated).
- displayManager.registerDisplayListener(
- new DisplayListener() {
- @Override
- public void onDisplayAdded(int displayId) {
- for (DisplayListener webViewListener : webViewListeners) {
- webViewListener.onDisplayAdded(displayId);
- }
- }
-
- @Override
- public void onDisplayRemoved(int displayId) {
- for (DisplayListener webViewListener : webViewListeners) {
- webViewListener.onDisplayRemoved(displayId);
- }
- }
-
- @Override
- public void onDisplayChanged(int displayId) {
- if (displayManager.getDisplay(displayId) == null) {
- return;
- }
- for (DisplayListener webViewListener : webViewListeners) {
- webViewListener.onDisplayChanged(displayId);
- }
- }
- },
- null);
- }
- }
-
- @SuppressWarnings({"unchecked", "PrivateApi"})
- private static ArrayList yoinkDisplayListeners(DisplayManager displayManager) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
- // We cannot use reflection on Android P, but it shouldn't matter as it shipped
- // with WebView 66.0.3359.158 and the WebView version the bug this code is working around was
- // fixed in 61.0.3116.0.
- return new ArrayList<>();
- }
- try {
- Field displayManagerGlobalField = DisplayManager.class.getDeclaredField("mGlobal");
- displayManagerGlobalField.setAccessible(true);
- Object displayManagerGlobal = displayManagerGlobalField.get(displayManager);
- Field displayListenersField =
- displayManagerGlobal.getClass().getDeclaredField("mDisplayListeners");
- displayListenersField.setAccessible(true);
- ArrayList delegates =
- (ArrayList) displayListenersField.get(displayManagerGlobal);
-
- Field listenerField = null;
- ArrayList listeners = new ArrayList<>();
- for (Object delegate : delegates) {
- if (listenerField == null) {
- listenerField = delegate.getClass().getField("mListener");
- listenerField.setAccessible(true);
- }
- DisplayManager.DisplayListener listener =
- (DisplayManager.DisplayListener) listenerField.get(delegate);
- listeners.add(listener);
- }
- return listeners;
- } catch (NoSuchFieldException | IllegalAccessException e) {
- Log.w(TAG, "Could not extract WebView's display listeners. " + e);
- return new ArrayList<>();
- }
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterCookieManager.java b/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterCookieManager.java
deleted file mode 100644
index 86b4fd412a..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterCookieManager.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package io.flutter.plugins.webviewflutter;
-
-import android.os.Build;
-import android.os.Build.VERSION_CODES;
-import android.webkit.CookieManager;
-import android.webkit.ValueCallback;
-import io.flutter.plugin.common.BinaryMessenger;
-import io.flutter.plugin.common.MethodCall;
-import io.flutter.plugin.common.MethodChannel;
-import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
-import io.flutter.plugin.common.MethodChannel.Result;
-
-class FlutterCookieManager implements MethodCallHandler {
- private final MethodChannel methodChannel;
-
- FlutterCookieManager(BinaryMessenger messenger) {
- methodChannel = new MethodChannel(messenger, "plugins.flutter.io/cookie_manager");
- methodChannel.setMethodCallHandler(this);
- }
-
- @Override
- public void onMethodCall(MethodCall methodCall, Result result) {
- switch (methodCall.method) {
- case "clearCookies":
- clearCookies(result);
- break;
- default:
- result.notImplemented();
- }
- }
-
- void dispose() {
- methodChannel.setMethodCallHandler(null);
- }
-
- private static void clearCookies(final Result result) {
- CookieManager cookieManager = CookieManager.getInstance();
- final boolean hasCookies = cookieManager.hasCookies();
- if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
- cookieManager.removeAllCookies(
- new ValueCallback() {
- @Override
- public void onReceiveValue(Boolean value) {
- result.success(hasCookies);
- }
- });
- } else {
- cookieManager.removeAllCookie();
- result.success(hasCookies);
- }
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java
deleted file mode 100644
index cd0e518ea6..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java
+++ /dev/null
@@ -1,477 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package io.flutter.plugins.webviewflutter;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.hardware.display.DisplayManager;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Message;
-import android.view.View;
-import android.webkit.WebChromeClient;
-import android.webkit.WebResourceRequest;
-import android.webkit.WebStorage;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.webkit.CookieManager;
-import androidx.webkit.WebSettingsCompat;
-import androidx.webkit.WebViewFeature;
-import androidx.annotation.NonNull;
-import io.flutter.plugin.common.BinaryMessenger;
-import io.flutter.plugin.common.MethodCall;
-import io.flutter.plugin.common.MethodChannel;
-import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
-import io.flutter.plugin.common.MethodChannel.Result;
-import io.flutter.plugin.platform.PlatformView;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import android.util.Log;
-
-
-public class FlutterWebView implements PlatformView, MethodCallHandler {
- private static final String JS_CHANNEL_NAMES_FIELD = "javascriptChannelNames";
- private final InputAwareWebView webView;
- private final MethodChannel methodChannel;
- private final FlutterWebViewClient flutterWebViewClient;
- private final Handler platformThreadHandler;
-
- // Verifies that a url opened by `Window.open` has a secure url.
- private class FlutterWebChromeClient extends WebChromeClient {
- @Override
- public boolean onCreateWindow(
- final WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
- final WebViewClient webViewClient =
- new WebViewClient() {
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- @Override
- public boolean shouldOverrideUrlLoading(
- @NonNull WebView view, @NonNull WebResourceRequest request) {
- final String url = request.getUrl().toString();
- if (!flutterWebViewClient.shouldOverrideUrlLoading(
- FlutterWebView.this.webView, request)) {
- webView.loadUrl(url);
- }
- return true;
- }
-
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- if (!flutterWebViewClient.shouldOverrideUrlLoading(
- FlutterWebView.this.webView, url)) {
- webView.loadUrl(url);
- }
- return true;
- }
- };
-
- final WebView newWebView = new WebView(view.getContext());
- newWebView.setWebViewClient(webViewClient);
-
- final WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
- transport.setWebView(newWebView);
- resultMsg.sendToTarget();
-
- return true;
- }
- }
-
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- @SuppressWarnings("unchecked")
- FlutterWebView(
- final Context context,
- BinaryMessenger messenger,
- int id,
- Map params,
- View containerView) {
-
- DisplayListenerProxy displayListenerProxy = new DisplayListenerProxy();
- DisplayManager displayManager =
- (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- displayListenerProxy.onPreWebViewInitialization(displayManager);
- webView = new InputAwareWebView(context, containerView);
- displayListenerProxy.onPostWebViewInitialization(displayManager);
-
- platformThreadHandler = new Handler(context.getMainLooper());
- // Allow local storage.
- webView.getSettings().setDomStorageEnabled(true);
- webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
-
- // Multi windows is set with FlutterWebChromeClient by default to handle internal bug: b/159892679.
- webView.getSettings().setSupportMultipleWindows(true);
- webView.setWebChromeClient(new FlutterWebChromeClient());
-
- methodChannel = new MethodChannel(messenger, "plugins.flutter.io/webview_" + id);
- methodChannel.setMethodCallHandler(this);
-
- flutterWebViewClient = new FlutterWebViewClient(methodChannel);
- Map settings = (Map) params.get("settings");
- if (settings != null) applySettings(settings);
-
- if (params.containsKey(JS_CHANNEL_NAMES_FIELD)) {
- List names = (List) params.get(JS_CHANNEL_NAMES_FIELD);
- if (names != null) registerJavaScriptChannelNames(names);
- }
-
- Integer autoMediaPlaybackPolicy = (Integer) params.get("autoMediaPlaybackPolicy");
- if (autoMediaPlaybackPolicy != null) updateAutoMediaPlaybackPolicy(autoMediaPlaybackPolicy);
- if (params.containsKey("userAgent")) {
- String userAgent = (String) params.get("userAgent");
- updateUserAgent(userAgent);
- }
- if (params.containsKey("initialUrl")) {
- String url = (String) params.get("initialUrl");
- webView.loadUrl(url);
- }
- }
-
- @Override
- public View getView() {
- return webView;
- }
-
- // @Override
- // This is overriding a method that hasn't rolled into stable Flutter yet. Including the
- // annotation would cause compile time failures in versions of Flutter too old to include the new
- // method. However leaving it raw like this means that the method will be ignored in old versions
- // of Flutter but used as an override anyway wherever it's actually defined.
- // TODO(mklim): Add the @Override annotation once flutter/engine#9727 rolls to stable.
- public void onInputConnectionUnlocked() {
- webView.unlockInputConnection();
- }
-
- // @Override
- // This is overriding a method that hasn't rolled into stable Flutter yet. Including the
- // annotation would cause compile time failures in versions of Flutter too old to include the new
- // method. However leaving it raw like this means that the method will be ignored in old versions
- // of Flutter but used as an override anyway wherever it's actually defined.
- // TODO(mklim): Add the @Override annotation once flutter/engine#9727 rolls to stable.
- public void onInputConnectionLocked() {
- webView.lockInputConnection();
- }
-
- // @Override
- // This is overriding a method that hasn't rolled into stable Flutter yet. Including the
- // annotation would cause compile time failures in versions of Flutter too old to include the new
- // method. However leaving it raw like this means that the method will be ignored in old versions
- // of Flutter but used as an override anyway wherever it's actually defined.
- // TODO(mklim): Add the @Override annotation once stable passes v1.10.9.
- public void onFlutterViewAttached(View flutterView) {
- webView.setContainerView(flutterView);
- }
-
- // @Override
- // This is overriding a method that hasn't rolled into stable Flutter yet. Including the
- // annotation would cause compile time failures in versions of Flutter too old to include the new
- // method. However leaving it raw like this means that the method will be ignored in old versions
- // of Flutter but used as an override anyway wherever it's actually defined.
- // TODO(mklim): Add the @Override annotation once stable passes v1.10.9.
- public void onFlutterViewDetached() {
- webView.setContainerView(null);
- }
-
- @Override
- public void onMethodCall(MethodCall methodCall, Result result) {
- switch (methodCall.method) {
- case "loadUrl":
- loadUrl(methodCall, result);
- break;
- case "loadData":
- loadData(methodCall, result);
- break;
- case "updateSettings":
- updateSettings(methodCall, result);
- break;
- case "canGoBack":
- canGoBack(result);
- break;
- case "canGoForward":
- canGoForward(result);
- break;
- case "goBack":
- goBack(result);
- break;
- case "goForward":
- goForward(result);
- break;
- case "reload":
- reload(result);
- break;
- case "currentUrl":
- currentUrl(result);
- break;
- case "evaluateJavascript":
- evaluateJavaScript(methodCall, result);
- break;
- case "addJavascriptChannels":
- addJavaScriptChannels(methodCall, result);
- break;
- case "removeJavascriptChannels":
- removeJavaScriptChannels(methodCall, result);
- break;
- case "clearCache":
- clearCache(result);
- break;
- case "getTitle":
- getTitle(result);
- break;
- case "scrollTo":
- scrollTo(methodCall, result);
- break;
- case "scrollBy":
- scrollBy(methodCall, result);
- break;
- case "getScrollX":
- getScrollX(result);
- break;
- case "getScrollY":
- getScrollY(result);
- break;
- case "setAcceptThirdPartyCookies":
- setAcceptThirdPartyCookies(methodCall, result);
- break;
- case "setCookie":
- setCookie(methodCall, result);
- break;
- default:
- result.notImplemented();
- }
- }
-
- @SuppressWarnings("unchecked")
- private void loadUrl(MethodCall methodCall, Result result) {
- Map request = (Map) methodCall.arguments;
- String url = (String) request.get("url");
- Map headers = (Map) request.get("headers");
- if (headers == null) {
- headers = Collections.emptyMap();
- }
- webView.loadUrl(url, headers);
- result.success(null);
- }
-
- @SuppressWarnings("unchecked")
- private void loadData(MethodCall methodCall, Result result) {
- Log.d("FlutterWebView", "Call to load data" + methodCall);
-
- Map request = (Map) methodCall.arguments;
- String baseUrl = (String) request.get("baseUrl");
- String data = (String) request.get("data");
- String mimeType = (String) request.get("mimeType");
- String encoding = (String) request.get("encoding");
- webView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, "");
- result.success(null);
- }
-
- private void setAcceptThirdPartyCookies(MethodCall methodCall, Result result) {
- boolean accept = (boolean) methodCall.arguments;
- CookieManager cookieManager = CookieManager.getInstance();
- cookieManager.setAcceptThirdPartyCookies(webView, accept);
- result.success(null);
- }
-
- private void setCookie(MethodCall methodCall, Result result) {
- Map args = (Map) methodCall.arguments;
- String url = (String) args.get("url");
- String value = (String) args.get("value");
- CookieManager cookieManager = CookieManager.getInstance();
- cookieManager.setCookie(url, value);
- result.success(null);
- }
-
- private void canGoBack(Result result) {
- result.success(webView.canGoBack());
- }
-
- private void canGoForward(Result result) {
- result.success(webView.canGoForward());
- }
-
- private void goBack(Result result) {
- if (webView.canGoBack()) {
- webView.goBack();
- }
- result.success(null);
- }
-
- private void goForward(Result result) {
- if (webView.canGoForward()) {
- webView.goForward();
- }
- result.success(null);
- }
-
- private void reload(Result result) {
- webView.reload();
- result.success(null);
- }
-
- private void currentUrl(Result result) {
- result.success(webView.getUrl());
- }
-
- @SuppressWarnings("unchecked")
- private void updateSettings(MethodCall methodCall, Result result) {
- applySettings((Map) methodCall.arguments);
- result.success(null);
- }
-
- @TargetApi(Build.VERSION_CODES.KITKAT)
- private void evaluateJavaScript(MethodCall methodCall, final Result result) {
- String jsString = (String) methodCall.arguments;
- if (jsString == null) {
- throw new UnsupportedOperationException("JavaScript string cannot be null");
- }
- webView.evaluateJavascript(
- jsString,
- new android.webkit.ValueCallback() {
- @Override
- public void onReceiveValue(String value) {
- result.success(value);
- }
- });
- }
-
- @SuppressWarnings("unchecked")
- private void addJavaScriptChannels(MethodCall methodCall, Result result) {
- List channelNames = (List) methodCall.arguments;
- registerJavaScriptChannelNames(channelNames);
- result.success(null);
- }
-
- @SuppressWarnings("unchecked")
- private void removeJavaScriptChannels(MethodCall methodCall, Result result) {
- List channelNames = (List) methodCall.arguments;
- for (String channelName : channelNames) {
- webView.removeJavascriptInterface(channelName);
- }
- result.success(null);
- }
-
- private void clearCache(Result result) {
- webView.clearCache(true);
- WebStorage.getInstance().deleteAllData();
- result.success(null);
- }
-
- private void getTitle(Result result) {
- result.success(webView.getTitle());
- }
-
- private void scrollTo(MethodCall methodCall, Result result) {
- Map request = methodCall.arguments();
- int x = (int) request.get("x");
- int y = (int) request.get("y");
-
- webView.scrollTo(x, y);
-
- result.success(null);
- }
-
- private void scrollBy(MethodCall methodCall, Result result) {
- Map request = methodCall.arguments();
- int x = (int) request.get("x");
- int y = (int) request.get("y");
-
- webView.scrollBy(x, y);
- result.success(null);
- }
-
- private void getScrollX(Result result) {
- result.success(webView.getScrollX());
- }
-
- private void getScrollY(Result result) {
- result.success(webView.getScrollY());
- }
-
- private void applySettings(Map settings) {
- for (String key : settings.keySet()) {
- switch (key) {
- case "jsMode":
- Integer mode = (Integer) settings.get(key);
- if (mode != null) updateJsMode(mode);
- break;
- case "hasNavigationDelegate":
- final boolean hasNavigationDelegate = (boolean) settings.get(key);
-
- final WebViewClient webViewClient =
- flutterWebViewClient.createWebViewClient(hasNavigationDelegate);
-
- webView.setWebViewClient(webViewClient);
- break;
- case "debuggingEnabled":
- final boolean debuggingEnabled = (boolean) settings.get(key);
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- webView.setWebContentsDebuggingEnabled(debuggingEnabled);
- }
- break;
- case "gestureNavigationEnabled":
- break;
- case "userAgent":
- updateUserAgent((String) settings.get(key));
- break;
- case "darkMode":
- setDarkMode((boolean) settings.get(key));
- break;
- default:
- throw new IllegalArgumentException("Unknown WebView setting: " + key);
- }
- }
- }
-
- private void setDarkMode(boolean darkMode) {
- if (WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) {
- WebSettingsCompat.setAlgorithmicDarkeningAllowed(webView.getSettings(), darkMode);
- } else if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
- int forceDarkMode = darkMode ? WebSettingsCompat.FORCE_DARK_ON : WebSettingsCompat.FORCE_DARK_OFF;
- WebSettingsCompat.setForceDark(webView.getSettings(), forceDarkMode);
- } else {
- Log.d("FlutterWebView", "FORCE_DARK feature is not supported by this WebView");
- }
- }
-
- private void updateJsMode(int mode) {
- switch (mode) {
- case 0: // disabled
- webView.getSettings().setJavaScriptEnabled(false);
- break;
- case 1: // unrestricted
- webView.getSettings().setJavaScriptEnabled(true);
- break;
- default:
- throw new IllegalArgumentException("Trying to set unknown JavaScript mode: " + mode);
- }
- }
-
- private void updateAutoMediaPlaybackPolicy(int mode) {
- // This is the index of the AutoMediaPlaybackPolicy enum, index 1 is always_allow, for all
- // other values we require a user gesture.
- boolean requireUserGesture = mode != 1;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- webView.getSettings().setMediaPlaybackRequiresUserGesture(requireUserGesture);
- }
- }
-
- private void registerJavaScriptChannelNames(List channelNames) {
- for (String channelName : channelNames) {
- webView.addJavascriptInterface(
- new JavaScriptChannel(methodChannel, channelName, platformThreadHandler), channelName);
- }
- }
-
- private void updateUserAgent(String userAgent) {
- webView.getSettings().setUserAgentString(userAgent);
- }
-
- @Override
- public void dispose() {
- methodChannel.setMethodCallHandler(null);
- webView.dispose();
- webView.destroy();
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java
deleted file mode 100644
index 24926bfc41..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package io.flutter.plugins.webviewflutter;
-
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.graphics.Bitmap;
-import android.os.Build;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.webkit.WebResourceError;
-import android.webkit.WebResourceRequest;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import androidx.annotation.RequiresApi;
-import androidx.webkit.WebResourceErrorCompat;
-import androidx.webkit.WebViewClientCompat;
-import io.flutter.plugin.common.MethodChannel;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-// We need to use WebViewClientCompat to get
-// shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
-// invoked by the webview on older Android devices, without it pages that use iframes will
-// be broken when a navigationDelegate is set on Android version earlier than N.
-class FlutterWebViewClient {
- private static final String TAG = "FlutterWebViewClient";
- private final MethodChannel methodChannel;
- private boolean hasNavigationDelegate;
-
- FlutterWebViewClient(MethodChannel methodChannel) {
- this.methodChannel = methodChannel;
- }
-
- private static String errorCodeToString(int errorCode) {
- switch (errorCode) {
- case WebViewClient.ERROR_AUTHENTICATION:
- return "authentication";
- case WebViewClient.ERROR_BAD_URL:
- return "badUrl";
- case WebViewClient.ERROR_CONNECT:
- return "connect";
- case WebViewClient.ERROR_FAILED_SSL_HANDSHAKE:
- return "failedSslHandshake";
- case WebViewClient.ERROR_FILE:
- return "file";
- case WebViewClient.ERROR_FILE_NOT_FOUND:
- return "fileNotFound";
- case WebViewClient.ERROR_HOST_LOOKUP:
- return "hostLookup";
- case WebViewClient.ERROR_IO:
- return "io";
- case WebViewClient.ERROR_PROXY_AUTHENTICATION:
- return "proxyAuthentication";
- case WebViewClient.ERROR_REDIRECT_LOOP:
- return "redirectLoop";
- case WebViewClient.ERROR_TIMEOUT:
- return "timeout";
- case WebViewClient.ERROR_TOO_MANY_REQUESTS:
- return "tooManyRequests";
- case WebViewClient.ERROR_UNKNOWN:
- return "unknown";
- case WebViewClient.ERROR_UNSAFE_RESOURCE:
- return "unsafeResource";
- case WebViewClient.ERROR_UNSUPPORTED_AUTH_SCHEME:
- return "unsupportedAuthScheme";
- case WebViewClient.ERROR_UNSUPPORTED_SCHEME:
- return "unsupportedScheme";
- }
-
- final String message =
- String.format(Locale.getDefault(), "Could not find a string for errorCode: %d", errorCode);
- throw new IllegalArgumentException(message);
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
- if (!hasNavigationDelegate) {
- return false;
- }
- notifyOnNavigationRequest(
- request.getUrl().toString(), request.getRequestHeaders(), view, request.isForMainFrame());
- // We must make a synchronous decision here whether to allow the navigation or not,
- // if the Dart code has set a navigation delegate we want that delegate to decide whether
- // to navigate or not, and as we cannot get a response from the Dart delegate synchronously we
- // return true here to block the navigation, if the Dart delegate decides to allow the
- // navigation the plugin will later make an addition loadUrl call for this url.
- //
- // Since we cannot call loadUrl for a subframe, we currently only allow the delegate to stop
- // navigations that target the main frame, if the request is not for the main frame
- // we just return false to allow the navigation.
- //
- // For more details see: https://github.com/flutter/flutter/issues/25329#issuecomment-464863209
- return request.isForMainFrame();
- }
-
- boolean shouldOverrideUrlLoading(WebView view, String url) {
- if (!hasNavigationDelegate) {
- return false;
- }
- // This version of shouldOverrideUrlLoading is only invoked by the webview on devices with
- // webview versions earlier than 67(it is also invoked when hasNavigationDelegate is false).
- // On these devices we cannot tell whether the navigation is targeted to the main frame or not.
- // We proceed assuming that the navigation is targeted to the main frame. If the page had any
- // frames they will be loaded in the main frame instead.
- Log.w(
- TAG,
- "Using a navigationDelegate with an old webview implementation, pages with frames or iframes will not work");
- notifyOnNavigationRequest(url, null, view, true);
- return true;
- }
-
- private void onPageStarted(WebView view, String url) {
- Map args = new HashMap<>();
- args.put("url", url);
- methodChannel.invokeMethod("onPageStarted", args);
- }
-
- private void onPageFinished(WebView view, String url) {
- Map args = new HashMap<>();
- args.put("url", url);
- methodChannel.invokeMethod("onPageFinished", args);
- }
-
- private void onWebResourceError(
- final int errorCode, final String description, final String failingUrl) {
- final Map args = new HashMap<>();
- args.put("errorCode", errorCode);
- args.put("description", description);
- args.put("errorType", FlutterWebViewClient.errorCodeToString(errorCode));
- args.put("failingUrl", failingUrl);
- methodChannel.invokeMethod("onWebResourceError", args);
- }
-
- private void notifyOnNavigationRequest(
- String url, Map headers, WebView webview, boolean isMainFrame) {
- HashMap args = new HashMap<>();
- args.put("url", url);
- args.put("isForMainFrame", isMainFrame);
- if (isMainFrame) {
- methodChannel.invokeMethod(
- "navigationRequest", args, new OnNavigationRequestResult(url, headers, webview));
- } else {
- methodChannel.invokeMethod("navigationRequest", args);
- }
- }
-
- // This method attempts to avoid using WebViewClientCompat due to bug
- // https://bugs.chromium.org/p/chromium/issues/detail?id=925887. Also, see
- // https://github.com/flutter/flutter/issues/29446.
- WebViewClient createWebViewClient(boolean hasNavigationDelegate) {
- this.hasNavigationDelegate = hasNavigationDelegate;
-
- if (!hasNavigationDelegate || android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- return internalCreateWebViewClient();
- }
-
- return internalCreateWebViewClientCompat();
- }
-
- private WebViewClient internalCreateWebViewClient() {
- return new WebViewClient() {
- @TargetApi(Build.VERSION_CODES.N)
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
- return FlutterWebViewClient.this.shouldOverrideUrlLoading(view, request);
- }
-
- @Override
- public void onPageStarted(WebView view, String url, Bitmap favicon) {
- FlutterWebViewClient.this.onPageStarted(view, url);
- }
-
- @Override
- public void onPageFinished(WebView view, String url) {
- FlutterWebViewClient.this.onPageFinished(view, url);
- }
-
- @TargetApi(Build.VERSION_CODES.M)
- @Override
- public void onReceivedError(
- WebView view, WebResourceRequest request, WebResourceError error) {
- FlutterWebViewClient.this.onWebResourceError(
- error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString());
- }
-
- @Override
- public void onReceivedError(
- WebView view, int errorCode, String description, String failingUrl) {
- FlutterWebViewClient.this.onWebResourceError(errorCode, description, failingUrl);
- }
-
- @Override
- public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
- // Deliberately empty. Occasionally the webview will mark events as having failed to be
- // handled even though they were handled. We don't want to propagate those as they're not
- // truly lost.
- }
- };
- }
-
- private WebViewClientCompat internalCreateWebViewClientCompat() {
- return new WebViewClientCompat() {
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
- return FlutterWebViewClient.this.shouldOverrideUrlLoading(view, request);
- }
-
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- return FlutterWebViewClient.this.shouldOverrideUrlLoading(view, url);
- }
-
- @Override
- public void onPageStarted(WebView view, String url, Bitmap favicon) {
- FlutterWebViewClient.this.onPageStarted(view, url);
- }
-
- @Override
- public void onPageFinished(WebView view, String url) {
- FlutterWebViewClient.this.onPageFinished(view, url);
- }
-
- // This method is only called when the WebViewFeature.RECEIVE_WEB_RESOURCE_ERROR feature is
- // enabled. The deprecated method is called when a device doesn't support this.
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- @SuppressLint("RequiresFeature")
- @Override
- public void onReceivedError(
- WebView view, WebResourceRequest request, WebResourceErrorCompat error) {
- FlutterWebViewClient.this.onWebResourceError(
- error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString());
- }
-
- @Override
- public void onReceivedError(
- WebView view, int errorCode, String description, String failingUrl) {
- FlutterWebViewClient.this.onWebResourceError(errorCode, description, failingUrl);
- }
-
- @Override
- public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
- // Deliberately empty. Occasionally the webview will mark events as having failed to be
- // handled even though they were handled. We don't want to propagate those as they're not
- // truly lost.
- }
- };
- }
-
- private static class OnNavigationRequestResult implements MethodChannel.Result {
- private final String url;
- private final Map headers;
- private final WebView webView;
-
- private OnNavigationRequestResult(String url, Map headers, WebView webView) {
- this.url = url;
- this.headers = headers;
- this.webView = webView;
- }
-
- @Override
- public void success(Object shouldLoad) {
- Boolean typedShouldLoad = (Boolean) shouldLoad;
- if (typedShouldLoad) {
- loadUrl();
- }
- }
-
- @Override
- public void error(String errorCode, String s1, Object o) {
- throw new IllegalStateException("navigationRequest calls must succeed");
- }
-
- @Override
- public void notImplemented() {
- throw new IllegalStateException(
- "navigationRequest must be implemented by the webview method channel");
- }
-
- private void loadUrl() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- webView.loadUrl(url, headers);
- } else {
- webView.loadUrl(url);
- }
- }
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java b/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
deleted file mode 100644
index 9b81a5b7cc..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package io.flutter.plugins.webviewflutter;
-
-import static android.content.Context.INPUT_METHOD_SERVICE;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.os.Build;
-import android.util.Log;
-import android.view.View;
-import android.view.inputmethod.InputMethodManager;
-import android.webkit.WebView;
-import android.widget.ListPopupWindow;
-
-/**
- * A WebView subclass that mirrors the same implementation hacks that the system WebView does in
- * order to correctly create an InputConnection.
- *
- * These hacks are only needed in Android versions below N and exist to create an InputConnection
- * on the WebView's dedicated input, or IME, thread. The majority of this proxying logic is in
- * {@link #checkInputConnectionProxy}.
- *
- *
See also {@link ThreadedInputConnectionProxyAdapterView}.
- */
-final class InputAwareWebView extends WebView {
- private static final String TAG = "InputAwareWebView";
- private View threadedInputConnectionProxyView;
- private ThreadedInputConnectionProxyAdapterView proxyAdapterView;
- private View containerView;
-
- InputAwareWebView(Context context, View containerView) {
- super(context);
- this.containerView = containerView;
- }
-
- void setContainerView(View containerView) {
- this.containerView = containerView;
-
- if (proxyAdapterView == null) {
- return;
- }
-
- Log.w(TAG, "The containerView has changed while the proxyAdapterView exists.");
- if (containerView != null) {
- setInputConnectionTarget(proxyAdapterView);
- }
- }
-
- /**
- * Set our proxy adapter view to use its cached input connection instead of creating new ones.
- *
- *
This is used to avoid losing our input connection when the virtual display is resized.
- */
- void lockInputConnection() {
- if (proxyAdapterView == null) {
- return;
- }
-
- proxyAdapterView.setLocked(true);
- }
-
- /** Sets the proxy adapter view back to its default behavior. */
- void unlockInputConnection() {
- if (proxyAdapterView == null) {
- return;
- }
-
- proxyAdapterView.setLocked(false);
- }
-
- /** Restore the original InputConnection, if needed. */
- void dispose() {
- resetInputConnection();
- }
-
- /**
- * Creates an InputConnection from the IME thread when needed.
- *
- *
We only need to create a {@link ThreadedInputConnectionProxyAdapterView} and create an
- * InputConnectionProxy on the IME thread when WebView is doing the same thing. So we rely on the
- * system calling this method for WebView's proxy view in order to know when we need to create our
- * own.
- *
- *
This method would normally be called for any View that used the InputMethodManager. We rely
- * on flutter/engine filtering the calls we receive down to the ones in our hierarchy and the
- * system WebView in order to know whether or not the system WebView expects an InputConnection on
- * the IME thread.
- */
- @Override
- public boolean checkInputConnectionProxy(final View view) {
- // Check to see if the view param is WebView's ThreadedInputConnectionProxyView.
- View previousProxy = threadedInputConnectionProxyView;
- threadedInputConnectionProxyView = view;
- if (previousProxy == view) {
- // This isn't a new ThreadedInputConnectionProxyView. Ignore it.
- return super.checkInputConnectionProxy(view);
- }
- if (containerView == null) {
- Log.e(
- TAG,
- "Can't create a proxy view because there's no container view. Text input may not work.");
- return super.checkInputConnectionProxy(view);
- }
-
- // We've never seen this before, so we make the assumption that this is WebView's
- // ThreadedInputConnectionProxyView. We are making the assumption that the only view that could
- // possibly be interacting with the IMM here is WebView's ThreadedInputConnectionProxyView.
- proxyAdapterView =
- new ThreadedInputConnectionProxyAdapterView(
- /*containerView=*/ containerView,
- /*targetView=*/ view,
- /*imeHandler=*/ view.getHandler());
- setInputConnectionTarget(/*targetView=*/ proxyAdapterView);
- return super.checkInputConnectionProxy(view);
- }
-
- /**
- * Ensure that input creation happens back on {@link #containerView}'s thread once this view no
- * longer has focus.
- *
- *
The logic in {@link #checkInputConnectionProxy} forces input creation to happen on Webview's
- * thread for all connections. We undo it here so users will be able to go back to typing in
- * Flutter UIs as expected.
- */
- @Override
- public void clearFocus() {
- super.clearFocus();
- resetInputConnection();
- }
-
- /**
- * Ensure that input creation happens back on {@link #containerView}.
- *
- *
The logic in {@link #checkInputConnectionProxy} forces input creation to happen on Webview's
- * thread for all connections. We undo it here so users will be able to go back to typing in
- * Flutter UIs as expected.
- */
- private void resetInputConnection() {
- if (proxyAdapterView == null) {
- // No need to reset the InputConnection to the default thread if we've never changed it.
- return;
- }
- if (containerView == null) {
- Log.e(TAG, "Can't reset the input connection to the container view because there is none.");
- return;
- }
- setInputConnectionTarget(/*targetView=*/ containerView);
- }
-
- /**
- * This is the crucial trick that gets the InputConnection creation to happen on the correct
- * thread pre Android N.
- * https://cs.chromium.org/chromium/src/content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionFactory.java?l=169&rcl=f0698ee3e4483fad5b0c34159276f71cfaf81f3a
- *
- *
{@code targetView} should have a {@link View#getHandler} method with the thread that future
- * InputConnections should be created on.
- */
- private void setInputConnectionTarget(final View targetView) {
- if (containerView == null) {
- Log.e(
- TAG,
- "Can't set the input connection target because there is no containerView to use as a handler.");
- return;
- }
-
- targetView.requestFocus();
- containerView.post(
- new Runnable() {
- @Override
- public void run() {
- InputMethodManager imm =
- (InputMethodManager) getContext().getSystemService(INPUT_METHOD_SERVICE);
- // This is a hack to make InputMethodManager believe that the target view now has focus.
- // As a result, InputMethodManager will think that targetView is focused, and will call
- // getHandler() of the view when creating input connection.
-
- // Step 1: Set targetView as InputMethodManager#mNextServedView. This does not affect
- // the real window focus.
- targetView.onWindowFocusChanged(true);
-
- // Step 2: Have InputMethodManager focus in on targetView. As a result, IMM will call
- // onCreateInputConnection() on targetView on the same thread as
- // targetView.getHandler(). It will also call subsequent InputConnection methods on this
- // thread. This is the IME thread in cases where targetView is our proxyAdapterView.
- imm.isActive(containerView);
- }
- });
- }
-
- @Override
- protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
- // This works around a crash when old (<67.0.3367.0) Chromium versions are used.
-
- // Prior to Chromium 67.0.3367 the following sequence happens when a select drop down is shown
- // on tablets:
- //
- // - WebView is calling ListPopupWindow#show
- // - buildDropDown is invoked, which sets mDropDownList to a DropDownListView.
- // - showAsDropDown is invoked - resulting in mDropDownList being added to the window and is
- // also synchronously performing the following sequence:
- // - WebView's focus change listener is loosing focus (as mDropDownList got it)
- // - WebView is hiding all popups (as it lost focus)
- // - WebView's SelectPopupDropDown#hide is invoked.
- // - DropDownPopupWindow#dismiss is invoked setting mDropDownList to null.
- // - mDropDownList#setSelection is invoked and is throwing a NullPointerException (as we just set mDropDownList to null).
- //
- // To workaround this, we drop the problematic focus lost call.
- // See more details on: https://github.com/flutter/flutter/issues/54164
- //
- // We don't do this after Android P as it shipped with a new enough WebView version, and it's
- // better to not do this on all future Android versions in case DropDownListView's code changes.
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P
- && isCalledFromListPopupWindowShow()
- && !focused) {
- return;
- }
- super.onFocusChanged(focused, direction, previouslyFocusedRect);
- }
-
- private boolean isCalledFromListPopupWindowShow() {
- StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
- for (StackTraceElement stackTraceElement : stackTraceElements) {
- if (stackTraceElement.getClassName().equals(ListPopupWindow.class.getCanonicalName())
- && stackTraceElement.getMethodName().equals("show")) {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java b/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java
deleted file mode 100644
index f23aae5b2b..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package io.flutter.plugins.webviewflutter;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.webkit.JavascriptInterface;
-import io.flutter.plugin.common.MethodChannel;
-import java.util.HashMap;
-
-/**
- * Added as a JavaScript interface to the WebView for any JavaScript channel that the Dart code sets
- * up.
- *
- *
Exposes a single method named `postMessage` to JavaScript, which sends a message over a method
- * channel to the Dart code.
- */
-class JavaScriptChannel {
- private final MethodChannel methodChannel;
- private final String javaScriptChannelName;
- private final Handler platformThreadHandler;
-
- /**
- * @param methodChannel the Flutter WebView method channel to which JS messages are sent
- * @param javaScriptChannelName the name of the JavaScript channel, this is sent over the method
- * channel with each message to let the Dart code know which JavaScript channel the message
- * was sent through
- */
- JavaScriptChannel(
- MethodChannel methodChannel, String javaScriptChannelName, Handler platformThreadHandler) {
- this.methodChannel = methodChannel;
- this.javaScriptChannelName = javaScriptChannelName;
- this.platformThreadHandler = platformThreadHandler;
- }
-
- // Suppressing unused warning as this is invoked from JavaScript.
- @SuppressWarnings("unused")
- @JavascriptInterface
- public void postMessage(final String message) {
- Runnable postMessageRunnable =
- new Runnable() {
- @Override
- public void run() {
- HashMap arguments = new HashMap<>();
- arguments.put("channel", javaScriptChannelName);
- arguments.put("message", message);
- methodChannel.invokeMethod("javascriptChannelMessage", arguments);
- }
- };
- if (platformThreadHandler.getLooper() == Looper.myLooper()) {
- postMessageRunnable.run();
- } else {
- platformThreadHandler.post(postMessageRunnable);
- }
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/ThreadedInputConnectionProxyAdapterView.java b/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/ThreadedInputConnectionProxyAdapterView.java
deleted file mode 100644
index 8fbdfaff1a..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/ThreadedInputConnectionProxyAdapterView.java
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package io.flutter.plugins.webviewflutter;
-
-import android.os.Handler;
-import android.os.IBinder;
-import android.view.View;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
-
-/**
- * A fake View only exposed to InputMethodManager.
- *
- * This follows a similar flow to Chromium's WebView (see
- * https://cs.chromium.org/chromium/src/content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionProxyView.java).
- * WebView itself bounces its InputConnection around several different threads. We follow its logic
- * here to get the same working connection.
- *
- *
This exists solely to forward input creation to WebView's ThreadedInputConnectionProxyView on
- * the IME thread. The way that this is created in {@link
- * InputAwareWebView#checkInputConnectionProxy} guarantees that we have a handle to
- * ThreadedInputConnectionProxyView and {@link #onCreateInputConnection} is always called on the IME
- * thread. We delegate to ThreadedInputConnectionProxyView there to get WebView's input connection.
- */
-final class ThreadedInputConnectionProxyAdapterView extends View {
- final Handler imeHandler;
- final IBinder windowToken;
- final View containerView;
- final View rootView;
- final View targetView;
-
- private boolean triggerDelayed = true;
- private boolean isLocked = false;
- private InputConnection cachedConnection;
-
- ThreadedInputConnectionProxyAdapterView(View containerView, View targetView, Handler imeHandler) {
- super(containerView.getContext());
- this.imeHandler = imeHandler;
- this.containerView = containerView;
- this.targetView = targetView;
- windowToken = containerView.getWindowToken();
- rootView = containerView.getRootView();
- setFocusable(true);
- setFocusableInTouchMode(true);
- setVisibility(VISIBLE);
- }
-
- /** Returns whether or not this is currently asynchronously acquiring an input connection. */
- boolean isTriggerDelayed() {
- return triggerDelayed;
- }
-
- /** Sets whether or not this should use its previously cached input connection. */
- void setLocked(boolean locked) {
- isLocked = locked;
- }
-
- /**
- * This is expected to be called on the IME thread. See the setup required for this in {@link
- * InputAwareWebView#checkInputConnectionProxy(View)}.
- *
- *
Delegates to ThreadedInputConnectionProxyView to get WebView's input connection.
- */
- @Override
- public InputConnection onCreateInputConnection(final EditorInfo outAttrs) {
- triggerDelayed = false;
- InputConnection inputConnection =
- (isLocked) ? cachedConnection : targetView.onCreateInputConnection(outAttrs);
- triggerDelayed = true;
- cachedConnection = inputConnection;
- return inputConnection;
- }
-
- @Override
- public boolean checkInputConnectionProxy(View view) {
- return true;
- }
-
- @Override
- public boolean hasWindowFocus() {
- // None of our views here correctly report they have window focus because of how we're embedding
- // the platform view inside of a virtual display.
- return true;
- }
-
- @Override
- public View getRootView() {
- return rootView;
- }
-
- @Override
- public boolean onCheckIsTextEditor() {
- return true;
- }
-
- @Override
- public boolean isFocused() {
- return true;
- }
-
- @Override
- public IBinder getWindowToken() {
- return windowToken;
- }
-
- @Override
- public Handler getHandler() {
- return imeHandler;
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFactory.java b/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFactory.java
deleted file mode 100644
index 6fdc36fbe5..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package io.flutter.plugins.webviewflutter;
-
-import android.content.Context;
-import android.view.View;
-import io.flutter.plugin.common.BinaryMessenger;
-import io.flutter.plugin.common.StandardMessageCodec;
-import io.flutter.plugin.platform.PlatformView;
-import io.flutter.plugin.platform.PlatformViewFactory;
-import java.util.Map;
-
-public final class WebViewFactory extends PlatformViewFactory {
- private final BinaryMessenger messenger;
- private final View containerView;
-
- WebViewFactory(BinaryMessenger messenger, View containerView) {
- super(StandardMessageCodec.INSTANCE);
- this.messenger = messenger;
- this.containerView = containerView;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public PlatformView create(Context context, int id, Object args) {
- Map params = (Map) args;
- return new FlutterWebView(context, messenger, id, params, containerView);
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java b/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java
deleted file mode 100644
index 2de8fdf94b..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package io.flutter.plugins.webviewflutter;
-
-import io.flutter.embedding.engine.plugins.FlutterPlugin;
-import io.flutter.plugin.common.BinaryMessenger;
-
-/**
- * Java platform implementation of the webview_flutter plugin.
- *
- * Register this in an add to app scenario to gracefully handle activity and context changes.
- *
- *
Call {@link #registerWith(Registrar)} to use the stable {@code io.flutter.plugin.common}
- * package instead.
- */
-public class WebViewFlutterPlugin implements FlutterPlugin {
-
- private FlutterCookieManager flutterCookieManager;
-
- /**
- * Add an instance of this to {@link io.flutter.embedding.engine.plugins.PluginRegistry} to
- * register it.
- *
- *
THIS PLUGIN CODE PATH DEPENDS ON A NEWER VERSION OF FLUTTER THAN THE ONE DEFINED IN THE
- * PUBSPEC.YAML. Text input will fail on some Android devices unless this is used with at least
- * flutter/flutter@1d4d63ace1f801a022ea9ec737bf8c15395588b9. Use the V1 embedding with {@link
- * #registerWith(Registrar)} to use this plugin with older Flutter versions.
- *
- *
Registration should eventually be handled automatically by v2 of the
- * GeneratedPluginRegistrant. https://github.com/flutter/flutter/issues/42694
- */
- public WebViewFlutterPlugin() {}
-
- /**
- * Registers a plugin implementation that uses the stable {@code io.flutter.plugin.common}
- * package.
- *
- *
Calling this automatically initializes the plugin. However plugins initialized this way
- * won't react to changes in activity or context, unlike {@link CameraPlugin}.
- */
- @SuppressWarnings("deprecation")
- public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) {
- registrar
- .platformViewRegistry()
- .registerViewFactory(
- "plugins.flutter.io/webview",
- new WebViewFactory(registrar.messenger(), registrar.view()));
- new FlutterCookieManager(registrar.messenger());
- }
-
- @Override
- public void onAttachedToEngine(FlutterPluginBinding binding) {
- BinaryMessenger messenger = binding.getBinaryMessenger();
- binding
- .getPlatformViewRegistry()
- .registerViewFactory(
- "plugins.flutter.io/webview", new WebViewFactory(messenger, /*containerView=*/ null));
- flutterCookieManager = new FlutterCookieManager(messenger);
- }
-
- @Override
- public void onDetachedFromEngine(FlutterPluginBinding binding) {
- if (flutterCookieManager == null) {
- return;
- }
-
- flutterCookieManager.dispose();
- flutterCookieManager = null;
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/lib/platform_interface.dart b/apps/flutter_parent/plugins/webview_flutter/lib/platform_interface.dart
deleted file mode 100644
index 2637e0d9f0..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/lib/platform_interface.dart
+++ /dev/null
@@ -1,549 +0,0 @@
-// Copyright 2019 The Chromium 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 'package:flutter/foundation.dart';
-import 'package:flutter/gestures.dart';
-import 'package:flutter/widgets.dart';
-
-import 'webview_flutter.dart';
-
-/// Interface for callbacks made by [WebViewPlatformController].
-///
-/// The webview plugin implements this class, and passes an instance to the [WebViewPlatformController].
-/// [WebViewPlatformController] is notifying this handler on events that happened on the platform's webview.
-abstract class WebViewPlatformCallbacksHandler {
- /// Invoked by [WebViewPlatformController] when a JavaScript channel message is received.
- void onJavaScriptChannelMessage(String channel, String message);
-
- /// Invoked by [WebViewPlatformController] when a navigation request is pending.
- ///
- /// If true is returned the navigation is allowed, otherwise it is blocked.
- FutureOr onNavigationRequest({String url, bool isForMainFrame});
-
- /// Invoked by [WebViewPlatformController] when a page has started loading.
- void onPageStarted(String url);
-
- /// Invoked by [WebViewPlatformController] when a page has finished loading.
- void onPageFinished(String url);
-
- /// Report web resource loading error to the host application.
- void onWebResourceError(WebResourceError error);
-}
-
-/// Possible error type categorizations used by [WebResourceError].
-enum WebResourceErrorType {
- /// User authentication failed on server.
- authentication,
-
- /// Malformed URL.
- badUrl,
-
- /// Failed to connect to the server.
- connect,
-
- /// Failed to perform SSL handshake.
- failedSslHandshake,
-
- /// Generic file error.
- file,
-
- /// File not found.
- fileNotFound,
-
- /// Server or proxy hostname lookup failed.
- hostLookup,
-
- /// Failed to read or write to the server.
- io,
-
- /// User authentication failed on proxy.
- proxyAuthentication,
-
- /// Too many redirects.
- redirectLoop,
-
- /// Connection timed out.
- timeout,
-
- /// Too many requests during this load.
- tooManyRequests,
-
- /// Generic error.
- unknown,
-
- /// Resource load was canceled by Safe Browsing.
- unsafeResource,
-
- /// Unsupported authentication scheme (not basic or digest).
- unsupportedAuthScheme,
-
- /// Unsupported URI scheme.
- unsupportedScheme,
-
- /// The web content process was terminated.
- webContentProcessTerminated,
-
- /// The web view was invalidated.
- webViewInvalidated,
-
- /// A JavaScript exception occurred.
- javaScriptExceptionOccurred,
-
- /// The result of JavaScript execution could not be returned.
- javaScriptResultTypeIsUnsupported,
-}
-
-/// Error returned in `WebView.onWebResourceError` when a web resource loading error has occurred.
-class WebResourceError {
- /// Creates a new [WebResourceError]
- ///
- /// A user should not need to instantiate this class, but will receive one in
- /// [WebResourceErrorCallback].
- WebResourceError({
- required this.errorCode,
- required this.description,
- this.domain,
- this.errorType,
- this.failingUrl,
- }) {}
-
- /// Raw code of the error from the respective platform.
- ///
- /// On Android, the error code will be a constant from a
- /// [WebViewClient](https://developer.android.com/reference/android/webkit/WebViewClient#summary) and
- /// will have a corresponding [errorType].
- ///
- /// On iOS, the error code will be a constant from `NSError.code` in
- /// Objective-C. See
- /// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorObjectsDomains/ErrorObjectsDomains.html
- /// for more information on error handling on iOS. Some possible error codes
- /// can be found at https://developer.apple.com/documentation/webkit/wkerrorcode?language=objc.
- final int errorCode;
-
- /// The domain of where to find the error code.
- ///
- /// This field is only available on iOS and represents a "domain" from where
- /// the [errorCode] is from. This value is taken directly from an `NSError`
- /// in Objective-C. See
- /// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorObjectsDomains/ErrorObjectsDomains.html
- /// for more information on error handling on iOS.
- final String? domain;
-
- /// Description of the error that can be used to communicate the problem to the user.
- final String description;
-
- /// The type this error can be categorized as.
- ///
- /// This will never be `null` on Android, but can be `null` on iOS.
- final WebResourceErrorType? errorType;
-
- /// Gets the URL for which the resource request was made.
- ///
- /// This value is not provided on iOS. Alternatively, you can keep track of
- /// the last values provided to [WebViewPlatformController.loadUrl].
- final String? failingUrl;
-}
-
-/// Interface for talking to the webview's platform implementation.
-///
-/// An instance implementing this interface is passed to the `onWebViewPlatformCreated` callback that is
-/// passed to [WebViewPlatformBuilder#onWebViewPlatformCreated].
-///
-/// Platform implementations that live in a separate package should extend this class rather than
-/// implement it as webview_flutter does not consider newly added methods to be breaking changes.
-/// Extending this class (using `extends`) ensures that the subclass will get the default
-/// implementation, while platform implementations that `implements` this interface will be broken
-/// by newly added [WebViewPlatformController] methods.
-abstract class WebViewPlatformController {
- /// Creates a new WebViewPlatform.
- ///
- /// Callbacks made by the WebView will be delegated to `handler`.
- ///
- /// The `handler` parameter must not be null.
- WebViewPlatformController(WebViewPlatformCallbacksHandler handler);
-
- /// Loads the specified URL.
- ///
- /// If `headers` is not null and the URL is an HTTP URL, the key value paris in `headers` will
- /// be added as key value pairs of HTTP headers for the request.
- ///
- /// `url` must not be null.
- ///
- /// Throws an ArgumentError if `url` is not a valid URL string.
- Future loadUrl(
- String url,
- Map? headers,
- ) {
- throw UnimplementedError(
- "WebView loadUrl is not implemented on the current platform");
- }
-
- Future loadData(
- String? baseUrl,
- String data,
- String mimeType,
- String encoding
- ) {
- throw UnimplementedError(
- "WebView loadData is not implemented on the current platform");
- }
-
- Future setAcceptThirdPartyCookies(bool accept) {
- throw UnimplementedError("WebView setAcceptThirdPartyCookies is not implemented on the current platform");
- }
-
- Future setCookie(String url, String value) {
- throw UnimplementedError("WebView setCookie is not implemented on the current platform");
- }
-
- /// Updates the webview settings.
- ///
- /// Any non null field in `settings` will be set as the new setting value.
- /// All null fields in `settings` are ignored.
- Future updateSettings(WebSettings setting) {
- throw UnimplementedError(
- "WebView updateSettings is not implemented on the current platform");
- }
-
- /// Accessor to the current URL that the WebView is displaying.
- ///
- /// If no URL was ever loaded, returns `null`.
- Future currentUrl() {
- throw UnimplementedError(
- "WebView currentUrl is not implemented on the current platform");
- }
-
- /// Checks whether there's a back history item.
- Future canGoBack() {
- throw UnimplementedError(
- "WebView canGoBack is not implemented on the current platform");
- }
-
- /// Checks whether there's a forward history item.
- Future canGoForward() {
- throw UnimplementedError(
- "WebView canGoForward is not implemented on the current platform");
- }
-
- /// Goes back in the history of this WebView.
- ///
- /// If there is no back history item this is a no-op.
- Future goBack() {
- throw UnimplementedError(
- "WebView goBack is not implemented on the current platform");
- }
-
- /// Goes forward in the history of this WebView.
- ///
- /// If there is no forward history item this is a no-op.
- Future goForward() {
- throw UnimplementedError(
- "WebView goForward is not implemented on the current platform");
- }
-
- /// Reloads the current URL.
- Future reload() {
- throw UnimplementedError(
- "WebView reload is not implemented on the current platform");
- }
-
- /// Clears all caches used by the [WebView].
- ///
- /// The following caches are cleared:
- /// 1. Browser HTTP Cache.
- /// 2. [Cache API](https://developers.google.com/web/fundamentals/instant-and-offline/web-storage/cache-api) caches.
- /// These are not yet supported in iOS WkWebView. Service workers tend to use this cache.
- /// 3. Application cache.
- /// 4. Local Storage.
- Future clearCache() {
- throw UnimplementedError(
- "WebView clearCache is not implemented on the current platform");
- }
-
- /// Evaluates a JavaScript expression in the context of the current page.
- ///
- /// The Future completes with an error if a JavaScript error occurred, or if the type of the
- /// evaluated expression is not supported(e.g on iOS not all non primitive type can be evaluated).
- Future evaluateJavascript(String javascriptString) {
- throw UnimplementedError(
- "WebView evaluateJavascript is not implemented on the current platform");
- }
-
- /// Adds new JavaScript channels to the set of enabled channels.
- ///
- /// For each value in this list the platform's webview should make sure that a corresponding
- /// property with a postMessage method is set on `window`. For example for a JavaScript channel
- /// named `Foo` it should be possible for JavaScript code executing in the webview to do
- ///
- /// ```javascript
- /// Foo.postMessage('hello');
- /// ```
- ///
- /// See also: [CreationParams.javascriptChannelNames].
- Future addJavascriptChannels(Set javascriptChannelNames) {
- throw UnimplementedError(
- "WebView addJavascriptChannels is not implemented on the current platform");
- }
-
- /// Removes JavaScript channel names from the set of enabled channels.
- ///
- /// This disables channels that were previously enabled by [addJavaScriptChannels] or through
- /// [CreationParams.javascriptChannelNames].
- Future removeJavascriptChannels(Set javascriptChannelNames) {
- throw UnimplementedError(
- "WebView removeJavascriptChannels is not implemented on the current platform");
- }
-
- /// Returns the title of the currently loaded page.
- Future getTitle() {
- throw UnimplementedError(
- "WebView getTitle is not implemented on the current platform");
- }
-
- /// Set the scrolled position of this view.
- ///
- /// The parameters `x` and `y` specify the position to scroll to in WebView pixels.
- Future scrollTo(int x, int y) {
- throw UnimplementedError(
- "WebView scrollTo is not implemented on the current platform");
- }
-
- /// Move the scrolled position of this view.
- ///
- /// The parameters `x` and `y` specify the amount of WebView pixels to scroll by.
- Future scrollBy(int x, int y) {
- throw UnimplementedError(
- "WebView scrollBy is not implemented on the current platform");
- }
-
- /// Return the horizontal scroll position of this view.
- ///
- /// Scroll position is measured from left.
- Future getScrollX() {
- throw UnimplementedError(
- "WebView getScrollX is not implemented on the current platform");
- }
-
- /// Return the vertical scroll position of this view.
- ///
- /// Scroll position is measured from top.
- Future getScrollY() {
- throw UnimplementedError(
- "WebView getScrollY is not implemented on the current platform");
- }
-}
-
-/// A single setting for configuring a WebViewPlatform which may be absent.
-class WebSetting {
- /// Constructs an absent setting instance.
- ///
- /// The [isPresent] field for the instance will be false.
- ///
- /// Accessing [value] for an absent instance will throw.
- WebSetting.absent()
- : _value = null,
- isPresent = false;
-
- /// Constructs a setting of the given `value`.
- ///
- /// The [isPresent] field for the instance will be true.
- WebSetting.of(T value)
- : _value = value,
- isPresent = true;
-
- final T? _value;
-
- /// The setting's value.
- ///
- /// Throws if [WebSetting.isPresent] is false.
- T get value {
- if (!isPresent) {
- throw StateError('Cannot access a value of an absent WebSetting');
- }
- if (_value == null) {
- throw StateError('Cannot access a value of an absent WebSetting');
- }
- assert(isPresent);
- return _value!;
- }
-
- /// True when this web setting instance contains a value.
- ///
- /// When false the [WebSetting.value] getter throws.
- final bool isPresent;
-
- @override
- bool operator ==(other) {
- if (other.runtimeType != runtimeType) return false;
- if (other is! WebSetting) return false;
- final WebSetting typedOther = other;
- return typedOther.isPresent == isPresent && typedOther._value == _value;
- }
-
- @override
- int get hashCode => hashValues(_value, isPresent);
-}
-
-/// Settings for configuring a WebViewPlatform.
-///
-/// Initial settings are passed as part of [CreationParams], settings updates are sent with
-/// [WebViewPlatform#updateSettings].
-///
-/// The `userAgent` parameter must not be null.
-class WebSettings {
- /// Construct an instance with initial settings. Future setting changes can be
- /// sent with [WebviewPlatform#updateSettings].
- ///
- /// The `userAgent` parameter must not be null.
- WebSettings({
- this.javascriptMode,
- this.hasNavigationDelegate,
- this.darkMode,
- this.debuggingEnabled,
- this.gestureNavigationEnabled,
- required this.userAgent,
- }) {}
-
- /// The JavaScript execution mode to be used by the webview.
- final JavascriptMode? javascriptMode;
-
- /// Whether the [WebView] has a [NavigationDelegate] set.
- final bool? hasNavigationDelegate;
-
- final bool? darkMode;
-
- /// Whether to enable the platform's webview content debugging tools.
- ///
- /// See also: [WebView.debuggingEnabled].
- final bool? debuggingEnabled;
-
- /// The value used for the HTTP `User-Agent:` request header.
- ///
- /// If [userAgent.value] is null the platform's default user agent should be used.
- ///
- /// An absent value ([userAgent.isPresent] is false) represents no change to this setting from the
- /// last time it was set.
- ///
- /// See also [WebView.userAgent].
- final WebSetting userAgent;
-
- /// Whether to allow swipe based navigation in iOS.
- ///
- /// See also: [WebView.gestureNavigationEnabled]
- final bool? gestureNavigationEnabled;
-
- @override
- String toString() {
- return 'WebSettings(javascriptMode: $javascriptMode, hasNavigationDelegate: $hasNavigationDelegate, debuggingEnabled: $debuggingEnabled, gestureNavigationEnabled: $gestureNavigationEnabled, userAgent: $userAgent)';
- }
-}
-
-/// Configuration to use when creating a new [WebViewPlatformController].
-///
-/// The `autoMediaPlaybackPolicy` parameter must not be null.
-class CreationParams {
- /// Constructs an instance to use when creating a new
- /// [WebViewPlatformController].
- ///
- /// The `autoMediaPlaybackPolicy` parameter must not be null.
- CreationParams({
- this.initialUrl,
- this.webSettings,
- this.javascriptChannelNames,
- this.userAgent,
- this.autoMediaPlaybackPolicy =
- AutoMediaPlaybackPolicy.require_user_action_for_all_media_types,
- }) {}
-
- /// The initialUrl to load in the webview.
- ///
- /// When null the webview will be created without loading any page.
- final String? initialUrl;
-
- /// The initial [WebSettings] for the new webview.
- ///
- /// This can later be updated with [WebViewPlatformController.updateSettings].
- final WebSettings? webSettings;
-
- /// The initial set of JavaScript channels that are configured for this webview.
- ///
- /// For each value in this set the platform's webview should make sure that a corresponding
- /// property with a postMessage method is set on `window`. For example for a JavaScript channel
- /// named `Foo` it should be possible for JavaScript code executing in the webview to do
- ///
- /// ```javascript
- /// Foo.postMessage('hello');
- /// ```
- // TODO(amirh): describe what should happen when postMessage is called once that code is migrated
- // to PlatformWebView.
- final Set? javascriptChannelNames;
-
- /// The value used for the HTTP User-Agent: request header.
- ///
- /// When null the platform's webview default is used for the User-Agent header.
- final String? userAgent;
-
- /// Which restrictions apply on automatic media playback.
- final AutoMediaPlaybackPolicy autoMediaPlaybackPolicy;
-
- @override
- String toString() {
- return '$runtimeType(initialUrl: $initialUrl, settings: $webSettings, javascriptChannelNames: $javascriptChannelNames, UserAgent: $userAgent)';
- }
-}
-
-/// Signature for callbacks reporting that a [WebViewPlatformController] was created.
-///
-/// See also the `onWebViewPlatformCreated` argument for [WebViewPlatform.build].
-typedef WebViewPlatformCreatedCallback = void Function(
- WebViewPlatformController webViewPlatformController);
-
-/// Interface for a platform implementation of a WebView.
-///
-/// [WebView.platform] controls the builder that is used by [WebView].
-/// [AndroidWebViewPlatform] and [CupertinoWebViewPlatform] are the default implementations
-/// for Android and iOS respectively.
-abstract class WebViewPlatform {
- /// Builds a new WebView.
- ///
- /// Returns a Widget tree that embeds the created webview.
- ///
- /// `creationParams` are the initial parameters used to setup the webview.
- ///
- /// `webViewPlatformHandler` will be used for handling callbacks that are made by the created
- /// [WebViewPlatformController].
- ///
- /// `onWebViewPlatformCreated` will be invoked after the platform specific [WebViewPlatformController]
- /// implementation is created with the [WebViewPlatformController] instance as a parameter.
- ///
- /// `gestureRecognizers` specifies which gestures should be consumed by the web view.
- /// It is possible for other gesture recognizers to be competing with the web view on pointer
- /// events, e.g if the web view is inside a [ListView] the [ListView] will want to handle
- /// vertical drags. The web view will claim gestures that are recognized by any of the
- /// recognizers on this list.
- /// When `gestureRecognizers` is empty or null, the web view will only handle pointer events for gestures that
- /// were not claimed by any other gesture recognizer.
- ///
- /// `webViewPlatformHandler` must not be null.
- Widget build({
- BuildContext context,
- // TODO(amirh): convert this to be the actual parameters.
- // I'm starting without it as the PR is starting to become pretty big.
- // I'll followup with the conversion PR.
- CreationParams creationParams,
- required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
- WebViewPlatformCreatedCallback onWebViewPlatformCreated,
- Set>? gestureRecognizers,
- });
-
- /// Clears all cookies for all [WebView] instances.
- ///
- /// Returns true if cookies were present before clearing, else false.
- Future clearCookies() {
- throw UnimplementedError(
- "WebView clearCookies is not implemented on the current platform");
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/lib/src/webview_android.dart b/apps/flutter_parent/plugins/webview_flutter/lib/src/webview_android.dart
deleted file mode 100644
index f987f5b67f..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/lib/src/webview_android.dart
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2019 The Chromium 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 'package:flutter/foundation.dart';
-import 'package:flutter/gestures.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter/widgets.dart';
-
-import '../platform_interface.dart';
-import 'webview_method_channel.dart';
-
-/// Builds an Android webview.
-///
-/// This is used as the default implementation for [WebView.platform] on Android. It uses
-/// an [AndroidView] to embed the webview in the widget hierarchy, and uses a method channel to
-/// communicate with the platform code.
-class AndroidWebView implements WebViewPlatform {
- @override
- Widget build({
- BuildContext? context,
- CreationParams? creationParams,
- @required WebViewPlatformCallbacksHandler? webViewPlatformCallbacksHandler,
- WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
- Set>? gestureRecognizers,
- }) {
- assert(webViewPlatformCallbacksHandler != null);
- return GestureDetector(
- // We prevent text selection by intercepting the long press event.
- // This is a temporary stop gap due to issues with text selection on Android:
- // https://github.com/flutter/flutter/issues/24585 - the text selection
- // dialog is not responding to touch events.
- // https://github.com/flutter/flutter/issues/24584 - the text selection
- // handles are not showing.
- // TODO(amirh): remove this when the issues above are fixed.
- onLongPress: () {},
- excludeFromSemantics: true,
- child: AndroidView(
- viewType: 'plugins.flutter.io/webview',
- onPlatformViewCreated: (int id) {
- if (onWebViewPlatformCreated == null || webViewPlatformCallbacksHandler == null) {
- return;
- }
- onWebViewPlatformCreated(MethodChannelWebViewPlatform(
- id, webViewPlatformCallbacksHandler));
- },
- gestureRecognizers: gestureRecognizers,
- // WebView content is not affected by the Android view's layout direction,
- // we explicitly set it here so that the widget doesn't require an ambient
- // directionality.
- layoutDirection: TextDirection.rtl,
- creationParams:
- creationParams != null ? MethodChannelWebViewPlatform.creationParamsToMap(creationParams) : null,
- creationParamsCodec: const StandardMessageCodec(),
- ),
- );
- }
-
- @override
- Future clearCookies() => MethodChannelWebViewPlatform.clearCookies();
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/lib/src/webview_cupertino.dart b/apps/flutter_parent/plugins/webview_flutter/lib/src/webview_cupertino.dart
deleted file mode 100644
index 52e7b823fc..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/lib/src/webview_cupertino.dart
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2019 The Chromium 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 'package:flutter/foundation.dart';
-import 'package:flutter/gestures.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter/widgets.dart';
-
-import '../platform_interface.dart';
-import 'webview_method_channel.dart';
-
-/// Builds an iOS webview.
-///
-/// This is used as the default implementation for [WebView.platform] on iOS. It uses
-/// a [UiKitView] to embed the webview in the widget hierarchy, and uses a method channel to
-/// communicate with the platform code.
-class CupertinoWebView implements WebViewPlatform {
- @override
- Widget build({
- BuildContext? context,
- CreationParams? creationParams,
- @required WebViewPlatformCallbacksHandler? webViewPlatformCallbacksHandler,
- WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
- Set>? gestureRecognizers,
- }) {
- return UiKitView(
- viewType: 'plugins.flutter.io/webview',
- onPlatformViewCreated: (int id) {
- if (onWebViewPlatformCreated == null || webViewPlatformCallbacksHandler == null) {
- return;
- }
- onWebViewPlatformCreated(
- MethodChannelWebViewPlatform(id, webViewPlatformCallbacksHandler));
- },
- gestureRecognizers: gestureRecognizers,
- creationParams:
- creationParams != null ? MethodChannelWebViewPlatform.creationParamsToMap(creationParams) : null,
- creationParamsCodec: const StandardMessageCodec(),
- );
- }
-
- @override
- Future clearCookies() => MethodChannelWebViewPlatform.clearCookies();
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/lib/src/webview_method_channel.dart b/apps/flutter_parent/plugins/webview_flutter/lib/src/webview_method_channel.dart
deleted file mode 100644
index 7d7e232ff8..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/lib/src/webview_method_channel.dart
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright 2019 The Chromium 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 'package:flutter/services.dart';
-
-import '../platform_interface.dart';
-
-/// A [WebViewPlatformController] that uses a method channel to control the webview.
-class MethodChannelWebViewPlatform implements WebViewPlatformController {
- /// Constructs an instance that will listen for webviews broadcasting to the
- /// given [id], using the given [WebViewPlatformCallbacksHandler].
- MethodChannelWebViewPlatform(int id, this._platformCallbacksHandler)
- : _channel = MethodChannel('plugins.flutter.io/webview_$id') {
- _channel.setMethodCallHandler(_onMethodCall);
- }
-
- final WebViewPlatformCallbacksHandler _platformCallbacksHandler;
-
- final MethodChannel _channel;
-
- static const MethodChannel _cookieManagerChannel =
- MethodChannel('plugins.flutter.io/cookie_manager');
-
- Future _onMethodCall(MethodCall call) async {
- switch (call.method) {
- case 'javascriptChannelMessage':
- final String channel = call.arguments['channel'];
- final String message = call.arguments['message'];
- _platformCallbacksHandler.onJavaScriptChannelMessage(channel, message);
- return true;
- case 'navigationRequest':
- return await _platformCallbacksHandler.onNavigationRequest(
- url: call.arguments['url'],
- isForMainFrame: call.arguments['isForMainFrame'],
- );
- case 'onPageFinished':
- _platformCallbacksHandler.onPageFinished(call.arguments['url']);
- return null;
- case 'onPageStarted':
- _platformCallbacksHandler.onPageStarted(call.arguments['url']);
- return null;
- case 'onWebResourceError':
- _platformCallbacksHandler.onWebResourceError(
- WebResourceError(
- errorCode: call.arguments['errorCode'],
- description: call.arguments['description'],
- domain: call.arguments['domain'],
- failingUrl: call.arguments['failingUrl'],
- errorType: call.arguments['errorType'] == null
- ? WebResourceErrorType.unknown
- : WebResourceErrorType.values.firstWhere(
- (WebResourceErrorType type) {
- return type.toString() ==
- '$WebResourceErrorType.${call.arguments['errorType']}';
- },
- ),
- ),
- );
- return null;
- }
-
- throw MissingPluginException(
- '${call.method} was invoked but has no handler',
- );
- }
-
- @override
- Future loadUrl(
- String url,
- Map? headers,
- ) async {
- return _channel.invokeMethod('loadUrl', {
- 'url': url,
- 'headers': headers,
- });
- }
-
- @override
- Future loadData(String? baseUrl, String data, String mimeType, String encoding) async {
- return _channel.invokeMethod('loadData', {
- 'baseUrl': baseUrl,
- 'data': data,
- 'mimeType': mimeType,
- 'encoding': encoding,
- });
- }
-
- @override
- Future setAcceptThirdPartyCookies(bool accept) {
- return _channel.invokeMethod('setAcceptThirdPartyCookies', accept);
- }
-
- @override
- Future setCookie(String url, String value) {
- return _channel.invokeMethod(
- 'setCookie',
- {
- 'url': url,
- 'value': value,
- },
- );
- }
-
- @override
- Future currentUrl() => _channel.invokeMethod('currentUrl');
-
- @override
- Future canGoBack() => _channel.invokeMethod("canGoBack");
-
- @override
- Future canGoForward() => _channel.invokeMethod("canGoForward");
-
- @override
- Future goBack() => _channel.invokeMethod("goBack");
-
- @override
- Future goForward() => _channel.invokeMethod("goForward");
-
- @override
- Future reload() => _channel.invokeMethod("reload");
-
- @override
- Future clearCache() => _channel.invokeMethod("clearCache");
-
- @override
- Future updateSettings(WebSettings settings) {
- final Map updatesMap = _webSettingsToMap(settings);
- if (updatesMap.isEmpty) {
- return Future.value();
- }
- return _channel.invokeMethod('updateSettings', updatesMap);
- }
-
- @override
- Future evaluateJavascript(String javascriptString) {
- return _channel.invokeMethod('evaluateJavascript', javascriptString);
- }
-
- @override
- Future addJavascriptChannels(Set javascriptChannelNames) {
- return _channel.invokeMethod(
- 'addJavascriptChannels', javascriptChannelNames.toList());
- }
-
- @override
- Future removeJavascriptChannels(Set javascriptChannelNames) {
- return _channel.invokeMethod(
- 'removeJavascriptChannels', javascriptChannelNames.toList());
- }
-
- @override
- Future getTitle() => _channel.invokeMethod("getTitle");
-
- @override
- Future scrollTo(int x, int y) {
- return _channel.invokeMethod('scrollTo', {
- 'x': x,
- 'y': y,
- });
- }
-
- @override
- Future scrollBy(int x, int y) {
- return _channel.invokeMethod('scrollBy', {
- 'x': x,
- 'y': y,
- });
- }
-
- @override
- Future getScrollX() => _channel.invokeMethod("getScrollX");
-
- @override
- Future getScrollY() => _channel.invokeMethod("getScrollY");
-
- /// Method channel implementation for [WebViewPlatform.clearCookies].
- static Future clearCookies() {
- return _cookieManagerChannel
- .invokeMethod('clearCookies')
- .then((dynamic result) => result);
- }
-
- static Map _webSettingsToMap(WebSettings? settings) {
- final Map map = {};
- void _addIfNonNull(String key, dynamic value) {
- if (value == null) {
- return;
- }
- map[key] = value;
- }
-
- void _addSettingIfPresent(String key, WebSetting setting) {
- if (!setting.isPresent) {
- return;
- }
- map[key] = setting.value;
- }
-
- _addIfNonNull('jsMode', settings?.javascriptMode?.index);
- _addIfNonNull('hasNavigationDelegate', settings?.hasNavigationDelegate);
- _addIfNonNull('darkMode', settings?.darkMode);
- _addIfNonNull('debuggingEnabled', settings?.debuggingEnabled);
- _addIfNonNull(
- 'gestureNavigationEnabled', settings?.gestureNavigationEnabled);
- _addSettingIfPresent('userAgent', settings?.userAgent as WebSetting);
- return map;
- }
-
- /// Converts a [CreationParams] object to a map as expected by `platform_views` channel.
- ///
- /// This is used for the `creationParams` argument of the platform views created by
- /// [AndroidWebViewBuilder] and [CupertinoWebViewBuilder].
- static Map creationParamsToMap(
- CreationParams creationParams) {
- return {
- 'initialUrl': creationParams.initialUrl,
- 'settings': _webSettingsToMap(creationParams.webSettings),
- 'javascriptChannelNames': creationParams.javascriptChannelNames?.toList(),
- 'userAgent': creationParams.userAgent,
- 'autoMediaPlaybackPolicy': creationParams.autoMediaPlaybackPolicy.index,
- };
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/lib/webview_flutter.dart b/apps/flutter_parent/plugins/webview_flutter/lib/webview_flutter.dart
deleted file mode 100644
index 3a846f6c22..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/lib/webview_flutter.dart
+++ /dev/null
@@ -1,823 +0,0 @@
-// Copyright 2018 The Chromium 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 'package:flutter/foundation.dart';
-import 'package:flutter/gestures.dart';
-import 'package:flutter/rendering.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter/widgets.dart';
-
-import 'platform_interface.dart';
-import 'src/webview_android.dart';
-import 'src/webview_cupertino.dart';
-import 'src/webview_method_channel.dart';
-
-/// Optional callback invoked when a web view is first created. [controller] is
-/// the [WebViewController] for the created web view.
-typedef void WebViewCreatedCallback(WebViewController controller);
-
-/// Describes the state of JavaScript support in a given web view.
-enum JavascriptMode {
- /// JavaScript execution is disabled.
- disabled,
-
- /// JavaScript execution is not restricted.
- unrestricted,
-}
-
-/// A message that was sent by JavaScript code running in a [WebView].
-class JavascriptMessage {
- /// Constructs a JavaScript message object.
- ///
- /// The `message` parameter must not be null.
- const JavascriptMessage(this.message);
-
- /// The contents of the message that was sent by the JavaScript code.
- final String message;
-}
-
-/// Callback type for handling messages sent from Javascript running in a web view.
-typedef void JavascriptMessageHandler(JavascriptMessage message);
-
-/// Information about a navigation action that is about to be executed.
-class NavigationRequest {
- NavigationRequest._({ required this.url, required this.isForMainFrame});
-
- /// The URL that will be loaded if the navigation is executed.
- final String url;
-
- /// Whether the navigation request is to be loaded as the main frame.
- final bool isForMainFrame;
-
- @override
- String toString() {
- return '$runtimeType(url: $url, isForMainFrame: $isForMainFrame)';
- }
-}
-
-/// A decision on how to handle a navigation request.
-enum NavigationDecision {
- /// Prevent the navigation from taking place.
- prevent,
-
- /// Allow the navigation to take place.
- navigate,
-}
-
-/// Android [WebViewPlatform] that uses [AndroidViewSurface] to build the [WebView] widget.
-///
-/// To use this, set [WebView.platform] to an instance of this class.
-///
-/// This implementation uses hybrid composition to render the [WebView] on
-/// Android. It solves multiple issues related to accessibility and interaction
-/// with the [WebView] at the cost of some performance on Android versions below
-/// 10. See https://github.com/flutter/flutter/wiki/Hybrid-Composition for more
-/// information.
-class SurfaceAndroidWebView extends AndroidWebView {
- @override
- Widget build({
- BuildContext? context,
- CreationParams? creationParams,
- WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
- Set>? gestureRecognizers,
- WebViewPlatformCallbacksHandler? webViewPlatformCallbacksHandler,
- }) {
- assert(webViewPlatformCallbacksHandler != null);
- return PlatformViewLink(
- viewType: 'plugins.flutter.io/webview',
- surfaceFactory: (
- BuildContext context,
- PlatformViewController controller,
- ) {
- return AndroidViewSurface(
- controller: controller as AndroidViewController,
- gestureRecognizers: gestureRecognizers ??
- const >{},
- hitTestBehavior: PlatformViewHitTestBehavior.opaque,
- );
- },
- onCreatePlatformView: (PlatformViewCreationParams params) {
- return PlatformViewsService.initSurfaceAndroidView(
- id: params.id,
- viewType: 'plugins.flutter.io/webview',
- // WebView content is not affected by the Android view's layout direction,
- // we explicitly set it here so that the widget doesn't require an ambient
- // directionality.
- layoutDirection: TextDirection.rtl,
- creationParams: creationParams != null ? MethodChannelWebViewPlatform.creationParamsToMap(creationParams) : null,
- creationParamsCodec: const StandardMessageCodec(),
- )
- ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
- ..addOnPlatformViewCreatedListener((int id) {
- if (onWebViewPlatformCreated == null || webViewPlatformCallbacksHandler == null) {
- return;
- }
- onWebViewPlatformCreated(
- MethodChannelWebViewPlatform(id, webViewPlatformCallbacksHandler),
- );
- })
- ..create();
- },
- );
- }
-}
-
-/// Decides how to handle a specific navigation request.
-///
-/// The returned [NavigationDecision] determines how the navigation described by
-/// `navigation` should be handled.
-///
-/// See also: [WebView.navigationDelegate].
-typedef FutureOr NavigationDelegate(
- NavigationRequest navigation);
-
-/// Signature for when a [WebView] has started loading a page.
-typedef void PageStartedCallback(String url);
-
-/// Signature for when a [WebView] has finished loading a page.
-typedef void PageFinishedCallback(String url);
-
-/// Signature for when a [WebView] has failed to load a resource.
-typedef void WebResourceErrorCallback(WebResourceError error);
-
-/// Specifies possible restrictions on automatic media playback.
-///
-/// This is typically used in [WebView.initialMediaPlaybackPolicy].
-// The method channel implementation is marshalling this enum to the value's index, so the order
-// is important.
-enum AutoMediaPlaybackPolicy {
- /// Starting any kind of media playback requires a user action.
- ///
- /// For example: JavaScript code cannot start playing media unless the code was executed
- /// as a result of a user action (like a touch event).
- require_user_action_for_all_media_types,
-
- /// Starting any kind of media playback is always allowed.
- ///
- /// For example: JavaScript code that's triggered when the page is loaded can start playing
- /// video or audio.
- always_allow,
-}
-
-final RegExp _validChannelNames = RegExp('^[a-zA-Z_][a-zA-Z0-9_]*\$');
-
-/// A named channel for receiving messaged from JavaScript code running inside a web view.
-class JavascriptChannel {
- /// Constructs a Javascript channel.
- ///
- /// The parameters `name` and `onMessageReceived` must not be null.
- JavascriptChannel({
- required this.name,
- required this.onMessageReceived,
- }) : assert(_validChannelNames.hasMatch(name));
-
- /// The channel's name.
- ///
- /// Passing this channel object as part of a [WebView.javascriptChannels] adds a channel object to
- /// the Javascript window object's property named `name`.
- ///
- /// The name must start with a letter or underscore(_), followed by any combination of those
- /// characters plus digits.
- ///
- /// Note that any JavaScript existing `window` property with this name will be overriden.
- ///
- /// See also [WebView.javascriptChannels] for more details on the channel registration mechanism.
- final String name;
-
- /// A callback that's invoked when a message is received through the channel.
- final JavascriptMessageHandler onMessageReceived;
-}
-
-/// A web view widget for showing html content.
-///
-/// There is a known issue that on iOS 13.4 and 13.5, other flutter widgets covering
-/// the `WebView` is not able to block the `WebView` from receiving touch events.
-/// See https://github.com/flutter/flutter/issues/53490.
-class WebView extends StatefulWidget {
- /// Creates a new web view.
- ///
- /// The web view can be controlled using a `WebViewController` that is passed to the
- /// `onWebViewCreated` callback once the web view is created.
- ///
- /// The `javascriptMode` and `autoMediaPlaybackPolicy` parameters must not be null.
- const WebView({
- Key? key,
- this.onWebViewCreated,
- this.initialUrl,
- this.javascriptMode = JavascriptMode.disabled,
- this.javascriptChannels,
- this.navigationDelegate,
- this.gestureRecognizers,
- this.onPageStarted,
- this.onPageFinished,
- this.onWebResourceError,
- this.darkMode = false,
- this.debuggingEnabled = false,
- this.gestureNavigationEnabled = false,
- this.userAgent,
- this.initialMediaPlaybackPolicy =
- AutoMediaPlaybackPolicy.require_user_action_for_all_media_types,
- }) : super(key: key);
-
- static WebViewPlatform? _platform;
-
- /// Sets a custom [WebViewPlatform].
- ///
- /// This property can be set to use a custom platform implementation for WebViews.
- ///
- /// Setting `platform` doesn't affect [WebView]s that were already created.
- ///
- /// The default value is [AndroidWebView] on Android and [CupertinoWebView] on iOS.
- static set platform(WebViewPlatform platform) {
- _platform = platform;
- }
-
- /// The WebView platform that's used by this WebView.
- ///
- /// The default value is [AndroidWebView] on Android and [CupertinoWebView] on iOS.
- static WebViewPlatform get platform {
- if (_platform == null) {
- switch (defaultTargetPlatform) {
- case TargetPlatform.android:
- _platform = AndroidWebView();
- break;
- case TargetPlatform.iOS:
- _platform = CupertinoWebView();
- break;
- default:
- throw UnsupportedError(
- "Trying to use the default webview implementation for $defaultTargetPlatform but there isn't a default one");
- }
- }
- return _platform!;
- }
-
- /// If not null invoked once the web view is created.
- final WebViewCreatedCallback? onWebViewCreated;
-
- /// Which gestures should be consumed by the web view.
- ///
- /// It is possible for other gesture recognizers to be competing with the web view on pointer
- /// events, e.g if the web view is inside a [ListView] the [ListView] will want to handle
- /// vertical drags. The web view will claim gestures that are recognized by any of the
- /// recognizers on this list.
- ///
- /// When this set is empty or null, the web view will only handle pointer events for gestures that
- /// were not claimed by any other gesture recognizer.
- final Set>? gestureRecognizers;
-
- /// The initial URL to load.
- final String? initialUrl;
-
- /// Whether Javascript execution is enabled.
- final JavascriptMode javascriptMode;
-
- /// The set of [JavascriptChannel]s available to JavaScript code running in the web view.
- ///
- /// For each [JavascriptChannel] in the set, a channel object is made available for the
- /// JavaScript code in a window property named [JavascriptChannel.name].
- /// The JavaScript code can then call `postMessage` on that object to send a message that will be
- /// passed to [JavascriptChannel.onMessageReceived].
- ///
- /// For example for the following JavascriptChannel:
- ///
- /// ```dart
- /// JavascriptChannel(name: 'Print', onMessageReceived: (JavascriptMessage message) { print(message.message); });
- /// ```
- ///
- /// JavaScript code can call:
- ///
- /// ```javascript
- /// Print.postMessage('Hello');
- /// ```
- ///
- /// To asynchronously invoke the message handler which will print the message to standard output.
- ///
- /// Adding a new JavaScript channel only takes affect after the next page is loaded.
- ///
- /// Set values must not be null. A [JavascriptChannel.name] cannot be the same for multiple
- /// channels in the list.
- ///
- /// A null value is equivalent to an empty set.
- final Set? javascriptChannels;
-
- /// A delegate function that decides how to handle navigation actions.
- ///
- /// When a navigation is initiated by the WebView (e.g when a user clicks a link)
- /// this delegate is called and has to decide how to proceed with the navigation.
- ///
- /// See [NavigationDecision] for possible decisions the delegate can take.
- ///
- /// When null all navigation actions are allowed.
- ///
- /// Caveats on Android:
- ///
- /// * Navigation actions targeted to the main frame can be intercepted,
- /// navigation actions targeted to subframes are allowed regardless of the value
- /// returned by this delegate.
- /// * Setting a navigationDelegate makes the WebView treat all navigations as if they were
- /// triggered by a user gesture, this disables some of Chromium's security mechanisms.
- /// A navigationDelegate should only be set when loading trusted content.
- /// * On Android WebView versions earlier than 67(most devices running at least Android L+ should have
- /// a later version):
- /// * When a navigationDelegate is set pages with frames are not properly handled by the
- /// webview, and frames will be opened in the main frame.
- /// * When a navigationDelegate is set HTTP requests do not include the HTTP referer header.
- final NavigationDelegate? navigationDelegate;
-
- /// Invoked when a page starts loading.
- final PageStartedCallback? onPageStarted;
-
- /// Invoked when a page has finished loading.
- ///
- /// This is invoked only for the main frame.
- ///
- /// When [onPageFinished] is invoked on Android, the page being rendered may
- /// not be updated yet.
- ///
- /// When invoked on iOS or Android, any Javascript code that is embedded
- /// directly in the HTML has been loaded and code injected with
- /// [WebViewController.evaluateJavascript] can assume this.
- final PageFinishedCallback? onPageFinished;
-
- /// Invoked when a web resource has failed to load.
- ///
- /// This can be called for any resource (iframe, image, etc.), not just for
- /// the main page.
- final WebResourceErrorCallback? onWebResourceError;
-
- final bool? darkMode;
-
- /// Controls whether WebView debugging is enabled.
- ///
- /// Setting this to true enables [WebView debugging on Android](https://developers.google.com/web/tools/chrome-devtools/remote-debugging/).
- ///
- /// WebView debugging is enabled by default in dev builds on iOS.
- ///
- /// To debug WebViews on iOS:
- /// - Enable developer options (Open Safari, go to Preferences -> Advanced and make sure "Show Develop Menu in Menubar" is on.)
- /// - From the Menu-bar (of Safari) select Develop -> iPhone Simulator ->
- ///
- /// By default `debuggingEnabled` is false.
- final bool debuggingEnabled;
-
- /// A Boolean value indicating whether horizontal swipe gestures will trigger back-forward list navigations.
- ///
- /// This only works on iOS.
- ///
- /// By default `gestureNavigationEnabled` is false.
- final bool gestureNavigationEnabled;
-
- /// The value used for the HTTP User-Agent: request header.
- ///
- /// When null the platform's webview default is used for the User-Agent header.
- ///
- /// When the [WebView] is rebuilt with a different `userAgent`, the page reloads and the request uses the new User Agent.
- ///
- /// When [WebViewController.goBack] is called after changing `userAgent` the previous `userAgent` value is used until the page is reloaded.
- ///
- /// This field is ignored on iOS versions prior to 9 as the platform does not support a custom
- /// user agent.
- ///
- /// By default `userAgent` is null.
- final String? userAgent;
-
- /// Which restrictions apply on automatic media playback.
- ///
- /// This initial value is applied to the platform's webview upon creation. Any following
- /// changes to this parameter are ignored (as long as the state of the [WebView] is preserved).
- ///
- /// The default policy is [AutoMediaPlaybackPolicy.require_user_action_for_all_media_types].
- final AutoMediaPlaybackPolicy initialMediaPlaybackPolicy;
-
- @override
- State createState() => _WebViewState();
-}
-
-class _WebViewState extends State {
- final Completer _controller =
- Completer();
-
- late _PlatformCallbacksHandler _platformCallbacksHandler;
-
- @override
- Widget build(BuildContext context) {
- return WebView.platform.build(
- context: context,
- onWebViewPlatformCreated: _onWebViewPlatformCreated,
- webViewPlatformCallbacksHandler: _platformCallbacksHandler,
- gestureRecognizers: widget.gestureRecognizers,
- creationParams: _creationParamsfromWidget(widget),
- );
- }
-
- @override
- void initState() {
- super.initState();
- _assertJavascriptChannelNamesAreUnique();
- _platformCallbacksHandler = _PlatformCallbacksHandler(widget);
- }
-
- @override
- void didUpdateWidget(WebView oldWidget) {
- super.didUpdateWidget(oldWidget);
- _assertJavascriptChannelNamesAreUnique();
- _controller.future.then((WebViewController controller) {
- _platformCallbacksHandler._widget = widget;
- controller._updateWidget(widget);
- });
- }
-
- void _onWebViewPlatformCreated(WebViewPlatformController webViewPlatform) {
- final WebViewController controller =
- WebViewController._(widget, webViewPlatform, _platformCallbacksHandler);
- _controller.complete(controller);
- if (widget.onWebViewCreated != null) {
- widget.onWebViewCreated!(controller);
- }
- }
-
- void _assertJavascriptChannelNamesAreUnique() {
- if (widget.javascriptChannels == null ||
- widget.javascriptChannels!.isEmpty) {
- return;
- }
- assert(_extractChannelNames(widget.javascriptChannels)?.length ==
- widget.javascriptChannels!.length);
- }
-}
-
-CreationParams _creationParamsfromWidget(WebView widget) {
- return CreationParams(
- initialUrl: widget.initialUrl,
- webSettings: _webSettingsFromWidget(widget),
- javascriptChannelNames: _extractChannelNames(widget.javascriptChannels),
- userAgent: widget.userAgent,
- autoMediaPlaybackPolicy: widget.initialMediaPlaybackPolicy,
- );
-}
-
-WebSettings _webSettingsFromWidget(WebView widget) {
- return WebSettings(
- javascriptMode: widget.javascriptMode,
- hasNavigationDelegate: widget.navigationDelegate != null,
- darkMode: widget.darkMode,
- debuggingEnabled: widget.debuggingEnabled,
- gestureNavigationEnabled: widget.gestureNavigationEnabled,
- userAgent: WebSetting.of(widget.userAgent ?? ''),
- );
-}
-
-// This method assumes that no fields in `currentValue` are null.
-WebSettings _clearUnchangedWebSettings(
- WebSettings currentValue, WebSettings newValue) {
- assert(currentValue.javascriptMode != null);
- assert(currentValue.hasNavigationDelegate != null);
- assert(currentValue.darkMode != null);
- assert(currentValue.debuggingEnabled != null);
- assert(currentValue.userAgent.isPresent);
- assert(newValue.javascriptMode != null);
- assert(newValue.hasNavigationDelegate != null);
- assert(newValue.darkMode != null);
- assert(newValue.debuggingEnabled != null);
- assert(newValue.userAgent.isPresent);
-
- JavascriptMode? javascriptMode;
- bool? hasNavigationDelegate;
- bool? darkMode;
- bool? debuggingEnabled;
- WebSetting userAgent = WebSetting.absent();
- if (currentValue.javascriptMode != newValue.javascriptMode) {
- javascriptMode = newValue.javascriptMode;
- }
- if (currentValue.hasNavigationDelegate != newValue.hasNavigationDelegate) {
- hasNavigationDelegate = newValue.hasNavigationDelegate;
- }
- if (currentValue.darkMode != newValue.darkMode) {
- darkMode = newValue.darkMode;
- }
- if (currentValue.debuggingEnabled != newValue.debuggingEnabled) {
- debuggingEnabled = newValue.debuggingEnabled;
- }
- if (currentValue.userAgent != newValue.userAgent) {
- userAgent = newValue.userAgent;
- }
-
- return WebSettings(
- javascriptMode: javascriptMode,
- hasNavigationDelegate: hasNavigationDelegate,
- darkMode: darkMode,
- debuggingEnabled: debuggingEnabled,
- userAgent: userAgent,
- );
-}
-
-Set? _extractChannelNames(Set? channels) {
- final Set channelNames = channels == null
- ? {}
- : channels.map((JavascriptChannel channel) => channel.name).toSet();
- return channelNames;
-}
-
-class _PlatformCallbacksHandler implements WebViewPlatformCallbacksHandler {
- _PlatformCallbacksHandler(this._widget) {
- _updateJavascriptChannelsFromSet(_widget.javascriptChannels);
- }
-
- WebView _widget;
-
- // Maps a channel name to a channel.
- final Map _javascriptChannels =
- {};
-
- @override
- void onJavaScriptChannelMessage(String channel, String message) {
- _javascriptChannels[channel]?.onMessageReceived(JavascriptMessage(message));
- }
-
- @override
- FutureOr onNavigationRequest({String? url, bool? isForMainFrame}) async {
- final NavigationRequest request =
- NavigationRequest._(url: url!, isForMainFrame: isForMainFrame!);
- final bool allowNavigation = _widget.navigationDelegate == null ||
- await _widget.navigationDelegate!(request) ==
- NavigationDecision.navigate;
- return allowNavigation;
- }
-
- @override
- void onPageStarted(String url) {
- if (_widget.onPageStarted != null) {
- _widget.onPageStarted!(url);
- }
- }
-
- @override
- void onPageFinished(String url) {
- if (_widget.onPageFinished != null) {
- _widget.onPageFinished!(url);
- }
- }
-
- @override
- void onWebResourceError(WebResourceError error) {
- if (_widget.onWebResourceError != null) {
- _widget.onWebResourceError!(error);
- }
- }
-
- void _updateJavascriptChannelsFromSet(Set? channels) {
- _javascriptChannels.clear();
- if (channels == null) {
- return;
- }
- for (JavascriptChannel channel in channels) {
- _javascriptChannels[channel.name] = channel;
- }
- }
-}
-
-/// Controls a [WebView].
-///
-/// A [WebViewController] instance can be obtained by setting the [WebView.onWebViewCreated]
-/// callback for a [WebView] widget.
-class WebViewController {
- WebViewController._(
- this._widget,
- this._webViewPlatformController,
- this._platformCallbacksHandler,
- ) {
- _settings = _webSettingsFromWidget(_widget);
- }
-
- final WebViewPlatformController _webViewPlatformController;
-
- final _PlatformCallbacksHandler _platformCallbacksHandler;
-
- late WebSettings _settings;
-
- WebView _widget;
-
- /// Loads the specified URL.
- ///
- /// If `headers` is not null and the URL is an HTTP URL, the key value paris in `headers` will
- /// be added as key value pairs of HTTP headers for the request.
- ///
- /// `url` must not be null.
- ///
- /// Throws an ArgumentError if `url` is not a valid URL string.
- Future loadUrl(
- String url, {
- Map? headers,
- }) async {
- _validateUrlString(url);
- return _webViewPlatformController.loadUrl(url, headers);
- }
-
- Future loadData(
- String? baseUrl,
- String data,
- String mimeType,
- String encoding) async {
- return _webViewPlatformController.loadData(baseUrl, data, mimeType, encoding);
- }
-
- Future setAcceptThirdPartyCookies(bool accept) async {
- return _webViewPlatformController.setAcceptThirdPartyCookies(accept);
- }
-
- Future setCookie(String url, String value) async {
- return _webViewPlatformController.setCookie(url, value);
- }
-
- /// Accessor to the current URL that the WebView is displaying.
- ///
- /// If [WebView.initialUrl] was never specified, returns `null`.
- /// Note that this operation is asynchronous, and it is possible that the
- /// current URL changes again by the time this function returns (in other
- /// words, by the time this future completes, the WebView may be displaying a
- /// different URL).
- Future currentUrl() {
- return _webViewPlatformController.currentUrl();
- }
-
- /// Checks whether there's a back history item.
- ///
- /// Note that this operation is asynchronous, and it is possible that the "canGoBack" state has
- /// changed by the time the future completed.
- Future canGoBack() {
- return _webViewPlatformController.canGoBack();
- }
-
- /// Checks whether there's a forward history item.
- ///
- /// Note that this operation is asynchronous, and it is possible that the "canGoForward" state has
- /// changed by the time the future completed.
- Future canGoForward() {
- return _webViewPlatformController.canGoForward();
- }
-
- /// Goes back in the history of this WebView.
- ///
- /// If there is no back history item this is a no-op.
- Future goBack() {
- return _webViewPlatformController.goBack();
- }
-
- /// Goes forward in the history of this WebView.
- ///
- /// If there is no forward history item this is a no-op.
- Future goForward() {
- return _webViewPlatformController.goForward();
- }
-
- /// Reloads the current URL.
- Future reload() {
- return _webViewPlatformController.reload();
- }
-
- /// Clears all caches used by the [WebView].
- ///
- /// The following caches are cleared:
- /// 1. Browser HTTP Cache.
- /// 2. [Cache API](https://developers.google.com/web/fundamentals/instant-and-offline/web-storage/cache-api) caches.
- /// These are not yet supported in iOS WkWebView. Service workers tend to use this cache.
- /// 3. Application cache.
- /// 4. Local Storage.
- ///
- /// Note: Calling this method also triggers a reload.
- Future clearCache() async {
- await _webViewPlatformController.clearCache();
- return reload();
- }
-
- Future _updateWidget(WebView widget) async {
- _widget = widget;
- await _updateSettings(_webSettingsFromWidget(widget));
- await _updateJavascriptChannels(widget.javascriptChannels);
- }
-
- Future _updateSettings(WebSettings newSettings) {
- final WebSettings update =
- _clearUnchangedWebSettings(_settings, newSettings);
- _settings = newSettings;
- return _webViewPlatformController.updateSettings(update);
- }
-
- Future _updateJavascriptChannels(
- Set? newChannels) async {
- final Set currentChannels =
- _platformCallbacksHandler._javascriptChannels.keys.toSet();
- final Set newChannelNames = _extractChannelNames(newChannels)!;
- final Set channelsToAdd =
- newChannelNames.difference(currentChannels);
- final Set channelsToRemove =
- currentChannels.difference(newChannelNames);
- if (channelsToRemove.isNotEmpty) {
- await _webViewPlatformController
- .removeJavascriptChannels(channelsToRemove);
- }
- if (channelsToAdd.isNotEmpty) {
- await _webViewPlatformController.addJavascriptChannels(channelsToAdd);
- }
- _platformCallbacksHandler._updateJavascriptChannelsFromSet(newChannels);
- }
-
- /// Evaluates a JavaScript expression in the context of the current page.
- ///
- /// On Android returns the evaluation result as a JSON formatted string.
- ///
- /// On iOS depending on the value type the return value would be one of:
- ///
- /// - For primitive JavaScript types: the value string formatted (e.g JavaScript 100 returns '100').
- /// - For JavaScript arrays of supported types: a string formatted NSArray(e.g '(1,2,3), note that the string for NSArray is formatted and might contain newlines and extra spaces.').
- /// - Other non-primitive types are not supported on iOS and will complete the Future with an error.
- ///
- /// The Future completes with an error if a JavaScript error occurred, or on iOS, if the type of the
- /// evaluated expression is not supported as described above.
- ///
- /// When evaluating Javascript in a [WebView], it is best practice to wait for
- /// the [WebView.onPageFinished] callback. This guarantees all the Javascript
- /// embedded in the main frame HTML has been loaded.
- Future evaluateJavascript(String? javascriptString) {
- if (_settings.javascriptMode == JavascriptMode.disabled) {
- return Future.error(FlutterError(
- 'JavaScript mode must be enabled/unrestricted when calling evaluateJavascript.'));
- }
- if (javascriptString == null) {
- return Future.error(
- ArgumentError('The argument javascriptString must not be null.'));
- }
- // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter.
- // https://github.com/flutter/flutter/issues/26431
- // ignore: strong_mode_implicit_dynamic_method
- return _webViewPlatformController.evaluateJavascript(javascriptString);
- }
-
- /// Returns the title of the currently loaded page.
- Future getTitle() {
- return _webViewPlatformController.getTitle();
- }
-
- /// Sets the WebView's content scroll position.
- ///
- /// The parameters `x` and `y` specify the scroll position in WebView pixels.
- Future scrollTo(int x, int y) {
- return _webViewPlatformController.scrollTo(x, y);
- }
-
- /// Move the scrolled position of this view.
- ///
- /// The parameters `x` and `y` specify the amount of WebView pixels to scroll by horizontally and vertically respectively.
- Future scrollBy(int x, int y) {
- return _webViewPlatformController.scrollBy(x, y);
- }
-
- /// Return the horizontal scroll position, in WebView pixels, of this view.
- ///
- /// Scroll position is measured from left.
- Future getScrollX() {
- return _webViewPlatformController.getScrollX();
- }
-
- /// Return the vertical scroll position, in WebView pixels, of this view.
- ///
- /// Scroll position is measured from top.
- Future getScrollY() {
- return _webViewPlatformController.getScrollY();
- }
-}
-
-/// Manages cookies pertaining to all [WebView]s.
-class CookieManager {
- /// Creates a [CookieManager] -- returns the instance if it's already been called.
- factory CookieManager() {
- return _instance ??= CookieManager._();
- }
-
- CookieManager._();
-
- static CookieManager? _instance;
-
- /// Clears all cookies for all [WebView] instances.
- ///
- /// This is a no op on iOS version smaller than 9.
- ///
- /// Returns true if cookies were present before clearing, else false.
- Future clearCookies() => WebView.platform.clearCookies();
-}
-
-// Throws an ArgumentError if `url` is not a valid URL string.
-void _validateUrlString(String url) {
- try {
- final Uri uri = Uri.parse(url);
- if (uri.scheme.isEmpty) {
- throw ArgumentError('Missing scheme in URL string: "$url"');
- }
- } on FormatException catch (e) {
- throw ArgumentError(e);
- }
-}
diff --git a/apps/flutter_parent/plugins/webview_flutter/pubspec.lock b/apps/flutter_parent/plugins/webview_flutter/pubspec.lock
deleted file mode 100644
index e30d186c42..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/pubspec.lock
+++ /dev/null
@@ -1,220 +0,0 @@
-# Generated by pub
-# See https://dart.dev/tools/pub/glossary#lockfile
-packages:
- archive:
- dependency: transitive
- description:
- name: archive
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.1.2"
- async:
- dependency: transitive
- description:
- name: async
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.8.1"
- boolean_selector:
- dependency: transitive
- description:
- name: boolean_selector
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.0"
- characters:
- dependency: transitive
- description:
- name: characters
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.0"
- charcode:
- dependency: transitive
- description:
- name: charcode
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.3.1"
- clock:
- dependency: transitive
- description:
- name: clock
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.0"
- collection:
- dependency: transitive
- description:
- name: collection
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.15.0"
- crypto:
- dependency: transitive
- description:
- name: crypto
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.0.1"
- fake_async:
- dependency: transitive
- description:
- name: fake_async
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.2.0"
- file:
- dependency: transitive
- description:
- name: file
- url: "https://pub.dartlang.org"
- source: hosted
- version: "6.1.2"
- flutter:
- dependency: "direct main"
- description: flutter
- source: sdk
- version: "0.0.0"
- flutter_driver:
- dependency: "direct dev"
- description: flutter
- source: sdk
- version: "0.0.0"
- flutter_test:
- dependency: "direct dev"
- description: flutter
- source: sdk
- version: "0.0.0"
- fuchsia_remote_debug_protocol:
- dependency: transitive
- description: flutter
- source: sdk
- version: "0.0.0"
- matcher:
- dependency: transitive
- description:
- name: matcher
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.12.10"
- meta:
- dependency: transitive
- description:
- name: meta
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.7.0"
- path:
- dependency: transitive
- description:
- name: path
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.8.0"
- pedantic:
- dependency: "direct dev"
- description:
- name: pedantic
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.8.0+1"
- platform:
- dependency: transitive
- description:
- name: platform
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.0.0"
- process:
- dependency: transitive
- description:
- name: process
- url: "https://pub.dartlang.org"
- source: hosted
- version: "4.2.3"
- sky_engine:
- dependency: transitive
- description: flutter
- source: sdk
- version: "0.0.99"
- source_span:
- dependency: transitive
- description:
- name: source_span
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.8.1"
- stack_trace:
- dependency: transitive
- description:
- name: stack_trace
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.10.0"
- stream_channel:
- dependency: transitive
- description:
- name: stream_channel
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.0"
- string_scanner:
- dependency: transitive
- description:
- name: string_scanner
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.0"
- sync_http:
- dependency: transitive
- description:
- name: sync_http
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.3.0"
- term_glyph:
- dependency: transitive
- description:
- name: term_glyph
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.2.0"
- test_api:
- dependency: transitive
- description:
- name: test_api
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.4.2"
- typed_data:
- dependency: transitive
- description:
- name: typed_data
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.3.0"
- vector_math:
- dependency: transitive
- description:
- name: vector_math
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.0"
- vm_service:
- dependency: transitive
- description:
- name: vm_service
- url: "https://pub.dartlang.org"
- source: hosted
- version: "7.1.1"
- webdriver:
- dependency: transitive
- description:
- name: webdriver
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.0.0"
-sdks:
- dart: ">=2.12.0 <3.0.0"
- flutter: ">=2.5.3"
diff --git a/apps/flutter_parent/plugins/webview_flutter/pubspec.yaml b/apps/flutter_parent/plugins/webview_flutter/pubspec.yaml
deleted file mode 100644
index 60fc18d241..0000000000
--- a/apps/flutter_parent/plugins/webview_flutter/pubspec.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-name: webview_flutter
-description: A Flutter plugin that provides a WebView widget on Android and iOS.
-version: 1.0.7
-homepage: https://github.com/flutter/plugins/tree/master/packages/webview_flutter
-publish_to: none
-
-environment:
- sdk: ">=3.0.0 <3.10.6"
- flutter: 3.13.2
-
-dependencies:
- flutter:
- sdk: flutter
-
-dev_dependencies:
- flutter_test:
- sdk: flutter
- flutter_driver:
- sdk: flutter
- pedantic: ^1.8.0
-
-flutter:
- plugin:
- platforms:
- android:
- package: io.flutter.plugins.webviewflutter
- pluginClass: WebViewFlutterPlugin
- ios:
- pluginClass: FLTWebViewFlutterPlugin
diff --git a/apps/flutter_parent/pubspec.lock b/apps/flutter_parent/pubspec.lock
index bd0a5ac6b2..f05ba9414b 100644
--- a/apps/flutter_parent/pubspec.lock
+++ b/apps/flutter_parent/pubspec.lock
@@ -1518,10 +1518,35 @@ packages:
webview_flutter:
dependency: "direct main"
description:
- path: "plugins/webview_flutter"
- relative: true
- source: path
- version: "1.0.7"
+ name: webview_flutter
+ sha256: "392c1d83b70fe2495de3ea2c84531268d5b8de2de3f01086a53334d8b6030a88"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.4"
+ webview_flutter_android:
+ dependency: transitive
+ description:
+ name: webview_flutter_android
+ sha256: "8b3b2450e98876c70bfcead876d9390573b34b9418c19e28168b74f6cb252dbd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.10.4"
+ webview_flutter_platform_interface:
+ dependency: transitive
+ description:
+ name: webview_flutter_platform_interface
+ sha256: "812165e4e34ca677bdfbfa58c01e33b27fd03ab5fa75b70832d4b7d4ca1fa8cf"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.9.5"
+ webview_flutter_wkwebview:
+ dependency: transitive
+ description:
+ name: webview_flutter_wkwebview
+ sha256: a5364369c758892aa487cbf59ea41d9edd10f9d9baf06a94e80f1bd1b4c7bbc0
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.9.5"
win32:
dependency: transitive
description:
diff --git a/apps/flutter_parent/pubspec.yaml b/apps/flutter_parent/pubspec.yaml
index 9f2afddcc1..7014361166 100644
--- a/apps/flutter_parent/pubspec.yaml
+++ b/apps/flutter_parent/pubspec.yaml
@@ -89,9 +89,7 @@ dependencies:
package_info_plus: ^4.0.2
permission_handler: ^10.4.3
shared_preferences: ^2.2.0 # Used to cache remote config properties
- #webview_flutter: 0.3.19+5
- webview_flutter: # TODO: Remove once the flutter plugin supports baseUrl https://github.com/flutter/plugins/pull/2463
- path: ./plugins/webview_flutter
+ webview_flutter: ^3.0.4
# Routing
fluro: ^2.0.5
diff --git a/apps/flutter_parent/test/utils/test_app.dart b/apps/flutter_parent/test/utils/test_app.dart
index f477beeab6..62d116d4b4 100644
--- a/apps/flutter_parent/test/utils/test_app.dart
+++ b/apps/flutter_parent/test/utils/test_app.dart
@@ -12,8 +12,6 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-import 'dart:ui';
-
import 'package:encrypted_shared_preferences/encrypted_shared_preferences.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
@@ -30,12 +28,13 @@ import 'package:flutter_parent/utils/design/parent_theme.dart';
import 'package:flutter_parent/utils/design/theme_prefs.dart';
import 'package:flutter_parent/utils/remote_config_utils.dart';
import 'package:flutter_test/flutter_test.dart';
-import 'package:flutter_test/src/deprecated.dart';
import 'package:get_it/get_it.dart';
+import 'package:mockito/mockito.dart';
import 'package:shared_preferences/shared_preferences.dart';
+import 'package:webview_flutter/webview_flutter.dart';
+import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
import 'platform_config.dart';
-import 'test_helpers/mock_helpers.dart';
import 'test_helpers/mock_helpers.mocks.dart';
class TestApp extends StatefulWidget {
@@ -259,28 +258,33 @@ Future setupPlatformChannels({PlatformConfig config = const PlatformConfig
}
}
-/// WebView helpers. These are needed as web views tie into platform views. These are special though as the channel
-/// name depends on the platform view's ID. This makes mocking these generically difficult as each id has a different
-/// platform channel to register.
+/// WebView helpers. These are needed as web views tie into platform views.
///
/// Inspired solution is a slimmed down version of the WebView test:
-/// https://github.com/flutter/plugins/blob/3b71d6e9a4456505f0b079074fcbc9ba9f8e0e15/packages/webview_flutter/test/webview_flutter_test.dart
+/// https://github.com/flutter/plugins/blob/webview_flutter-v3.0.4/packages/webview_flutter/webview_flutter/test/webview_flutter_test.dart
void _initPlatformWebView() {
- const MethodChannel('plugins.flutter.io/cookie_manager', const StandardMethodCodec())
- .setMockMethodCallHandler((_) => Future.sync(() => false));
-
- // Intercept when a web view is getting created so we can set up the platform channel
- SystemChannels.platform_views.setMockMethodCallHandler((call) {
- switch (call.method) {
- case 'create':
- final id = call.arguments['id'];
- MethodChannel('plugins.flutter.io/webview_$id', const StandardMethodCodec())
- .setMockMethodCallHandler((_) => Future.sync(() {}));
- return Future.sync(() => 1);
- default:
- return Future.sync(() {});
- }
+ final mockWebViewPlatformController = MockWebViewPlatformController();
+ final mockWebViewPlatform = MockWebViewPlatform();
+ when(mockWebViewPlatform.build(
+ context: anyNamed('context'),
+ creationParams: anyNamed('creationParams'),
+ webViewPlatformCallbacksHandler:
+ anyNamed('webViewPlatformCallbacksHandler'),
+ javascriptChannelRegistry: anyNamed('javascriptChannelRegistry'),
+ onWebViewPlatformCreated: anyNamed('onWebViewPlatformCreated'),
+ gestureRecognizers: anyNamed('gestureRecognizers'),
+ )).thenAnswer((Invocation invocation) {
+ final WebViewPlatformCreatedCallback onWebViewPlatformCreated =
+ invocation.namedArguments[const Symbol('onWebViewPlatformCreated')]
+ as WebViewPlatformCreatedCallback;
+ return TestPlatformWebView(
+ mockWebViewPlatformController: mockWebViewPlatformController,
+ onWebViewPlatformCreated: onWebViewPlatformCreated,
+ );
});
+
+ WebView.platform = mockWebViewPlatform;
+ WebViewCookieManagerPlatform.instance = FakeWebViewCookieManager();
}
/// Mocks the platform channel used by the package_info plugin
@@ -391,4 +395,47 @@ void _initPathProvider() {
}
return null;
});
+}
+
+class TestPlatformWebView extends StatefulWidget {
+ const TestPlatformWebView({
+ Key? key,
+ required this.mockWebViewPlatformController,
+ this.onWebViewPlatformCreated,
+ }) : super(key: key);
+
+ final MockWebViewPlatformController mockWebViewPlatformController;
+ final WebViewPlatformCreatedCallback? onWebViewPlatformCreated;
+
+ @override
+ State createState() => TestPlatformWebViewState();
+}
+
+class TestPlatformWebViewState extends State {
+ @override
+ void initState() {
+ super.initState();
+ final WebViewPlatformCreatedCallback? onWebViewPlatformCreated =
+ widget.onWebViewPlatformCreated;
+ if (onWebViewPlatformCreated != null) {
+ onWebViewPlatformCreated(widget.mockWebViewPlatformController);
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+
+class FakeWebViewCookieManager extends WebViewCookieManagerPlatform {
+ @override
+ Future clearCookies() {
+ return Future.value(false);
+ }
+
+ @override
+ Future setCookie(WebViewCookie cookie) {
+ return Future.value(null);
+ }
}
\ No newline at end of file
diff --git a/apps/flutter_parent/test/utils/test_helpers/mock_helpers.dart b/apps/flutter_parent/test/utils/test_helpers/mock_helpers.dart
index 21f738eccc..a7b3985f1e 100644
--- a/apps/flutter_parent/test/utils/test_helpers/mock_helpers.dart
+++ b/apps/flutter_parent/test/utils/test_helpers/mock_helpers.dart
@@ -19,9 +19,7 @@
// settings will correspond the specified values.
import 'dart:io';
-import 'package:barcode_scan2/platform_wrapper.dart';
import 'package:dio/dio.dart';
-import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter/material.dart';
@@ -45,7 +43,6 @@ import 'package:flutter_parent/network/api/planner_api.dart';
import 'package:flutter_parent/network/api/user_api.dart';
import 'package:flutter_parent/network/utils/analytics.dart';
import 'package:flutter_parent/network/utils/authentication_interceptor.dart';
-import 'package:flutter_parent/network/utils/dio_config.dart';
import 'package:flutter_parent/screens/account_creation/account_creation_interactor.dart';
import 'package:flutter_parent/screens/alert_thresholds/alert_thresholds_interactor.dart';
import 'package:flutter_parent/screens/alerts/alerts_interactor.dart';
@@ -60,7 +57,6 @@ import 'package:flutter_parent/screens/courses/routing_shell/course_routing_shel
import 'package:flutter_parent/screens/dashboard/alert_notifier.dart';
import 'package:flutter_parent/screens/dashboard/dashboard_interactor.dart';
import 'package:flutter_parent/screens/dashboard/inbox_notifier.dart';
-import 'package:flutter_parent/screens/dashboard/selected_student_notifier.dart';
import 'package:flutter_parent/screens/domain_search/domain_search_interactor.dart';
import 'package:flutter_parent/screens/events/event_details_interactor.dart';
import 'package:flutter_parent/screens/help/help_screen_interactor.dart';
@@ -102,6 +98,7 @@ import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:sqflite/sqflite.dart';
import 'package:video_player/video_player.dart';
+import 'package:webview_flutter/webview_flutter.dart';
@GenerateNiceMocks([
MockSpec(),
@@ -189,6 +186,8 @@ import 'package:video_player/video_player.dart';
MockSpec(),
MockSpec(),
MockSpec(),
+ MockSpec(),
+ MockSpec()
])
import 'mock_helpers.mocks.dart';
diff --git a/apps/flutter_parent/test/utils/test_helpers/mock_helpers.mocks.dart b/apps/flutter_parent/test/utils/test_helpers/mock_helpers.mocks.dart
index aeb97f61de..6b15d639d3 100644
--- a/apps/flutter_parent/test/utils/test_helpers/mock_helpers.mocks.dart
+++ b/apps/flutter_parent/test/utils/test_helpers/mock_helpers.mocks.dart
@@ -20,6 +20,7 @@ import 'package:firebase_remote_config_platform_interface/firebase_remote_config
as _i14;
import 'package:fluro/fluro.dart' as _i84;
import 'package:flutter/foundation.dart' as _i11;
+import 'package:flutter/gestures.dart' as _i142;
import 'package:flutter/material.dart' as _i17;
import 'package:flutter/services.dart' as _i15;
import 'package:flutter_downloader/flutter_downloader.dart' as _i133;
@@ -9196,3 +9197,319 @@ class MockRemoteConfigInteractor extends _i1.Mock
returnValueForMissingStub: null,
);
}
+
+/// A class which mocks [WebViewPlatformController].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockWebViewPlatformController extends _i1.Mock
+ implements _i16.WebViewPlatformController {
+ @override
+ _i8.Future loadFile(String? absoluteFilePath) => (super.noSuchMethod(
+ Invocation.method(
+ #loadFile,
+ [absoluteFilePath],
+ ),
+ returnValue: _i8.Future.value(),
+ returnValueForMissingStub: _i8.Future.value(),
+ ) as _i8.Future);
+ @override
+ _i8.Future loadFlutterAsset(String? key) => (super.noSuchMethod(
+ Invocation.method(
+ #loadFlutterAsset,
+ [key],
+ ),
+ returnValue: _i8.Future.value(),
+ returnValueForMissingStub: _i8.Future.value(),
+ ) as _i8.Future);
+ @override
+ _i8.Future loadHtmlString(
+ String? html, {
+ String? baseUrl,
+ }) =>
+ (super.noSuchMethod(
+ Invocation.method(
+ #loadHtmlString,
+ [html],
+ {#baseUrl: baseUrl},
+ ),
+ returnValue: _i8.Future.value(),
+ returnValueForMissingStub: _i8.Future.value(),
+ ) as _i8.Future);
+ @override
+ _i8.Future loadUrl(
+ String? url,
+ Map? headers,
+ ) =>
+ (super.noSuchMethod(
+ Invocation.method(
+ #loadUrl,
+ [
+ url,
+ headers,
+ ],
+ ),
+ returnValue: _i8.Future.value(),
+ returnValueForMissingStub: _i8.Future.value(),
+ ) as _i8.Future);
+ @override
+ _i8.Future loadRequest(_i16.WebViewRequest? request) =>
+ (super.noSuchMethod(
+ Invocation.method(
+ #loadRequest,
+ [request],
+ ),
+ returnValue: _i8.Future.value(),
+ returnValueForMissingStub: _i8.Future.value(),
+ ) as _i8.Future);
+ @override
+ _i8.Future updateSettings(_i16.WebSettings? setting) =>
+ (super.noSuchMethod(
+ Invocation.method(
+ #updateSettings,
+ [setting],
+ ),
+ returnValue: _i8.Future.value(),
+ returnValueForMissingStub: _i8.Future.value(),
+ ) as _i8.Future);
+ @override
+ _i8.Future currentUrl() => (super.noSuchMethod(
+ Invocation.method(
+ #currentUrl,
+ [],
+ ),
+ returnValue: _i8.Future.value(),
+ returnValueForMissingStub: _i8.Future.value(),
+ ) as _i8.Future);
+ @override
+ _i8.Future canGoBack() => (super.noSuchMethod(
+ Invocation.method(
+ #canGoBack,
+ [],
+ ),
+ returnValue: _i8.Future.value(false),
+ returnValueForMissingStub: _i8.Future.value(false),
+ ) as _i8.Future);
+ @override
+ _i8.Future canGoForward() => (super.noSuchMethod(
+ Invocation.method(
+ #canGoForward,
+ [],
+ ),
+ returnValue: _i8.Future.value(false),
+ returnValueForMissingStub: _i8.Future.value(false),
+ ) as _i8.Future);
+ @override
+ _i8.Future goBack() => (super.noSuchMethod(
+ Invocation.method(
+ #goBack,
+ [],
+ ),
+ returnValue: _i8.Future.value(),
+ returnValueForMissingStub: _i8.Future.value(),
+ ) as _i8.Future);
+ @override
+ _i8.Future goForward() => (super.noSuchMethod(
+ Invocation.method(
+ #goForward,
+ [],
+ ),
+ returnValue: _i8.Future