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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.3.0

* Adds support to access native `WebView`.

## 3.2.4

* Renames Pigeon output files.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
import android.content.Context;
import android.os.Handler;
import android.view.View;
import android.webkit.WebView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
Expand All @@ -33,12 +36,43 @@
* <p>Call {@link #registerWith} to use the stable {@code io.flutter.plugin.common} package instead.
*/
public class WebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
private InstanceManager instanceManager;
@Nullable private InstanceManager instanceManager;

private FlutterPluginBinding pluginBinding;
private WebViewHostApiImpl webViewHostApi;
private JavaScriptChannelHostApiImpl javaScriptChannelHostApi;

/**
* Retrieves the {@link WebView} that is associated with `identifer`.
*
* <p>See the Dart method `AndroidWebViewController.webViewIdentifier` to get the identifier of an
* underlying `WebView`.
*
* @param engine the execution environment the {@link WebViewFlutterPlugin} should belong to. If
* the engine doesn't contain an attached instance of {@link WebViewFlutterPlugin}, this
* method returns null.
* @param identifier the associated identifier of the `WebView`.
* @return the `WebView` associated with `identifier` or null if a `WebView` instance associated
* with `identifier` could not be found.
*/
@SuppressWarnings("unused")
@Nullable
public static WebView getWebView(FlutterEngine engine, long identifier) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Putting the accessor on this class encourages people to view this whole class as public, stable API, which could easily lead to accidental breakage later. Can we make a new wrapper class to be the public API, with just this method?

final WebViewFlutterPlugin webViewPlugin =
(WebViewFlutterPlugin) engine.getPlugins().get(WebViewFlutterPlugin.class);

if (webViewPlugin == null || webViewPlugin.instanceManager == null) {
return null;
}

final Object instance = webViewPlugin.instanceManager.getInstance(identifier);
if (instance instanceof WebView) {
return (WebView) instance;
}

return null;
}

/**
* Add an instance of this to {@link io.flutter.embedding.engine.plugins.PluginRegistry} to
* register it.
Expand Down Expand Up @@ -148,7 +182,10 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {

@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
instanceManager.close();
if (instanceManager != null) {
instanceManager.close();
instanceManager = null;
}
}

@Override
Expand Down Expand Up @@ -179,6 +216,7 @@ private void updateContext(Context context) {

/** Maintains instances used to communicate with the corresponding objects in Dart. */
@Nullable
@VisibleForTesting
public InstanceManager getInstanceManager() {
return instanceManager;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@

package io.flutter.plugins.webviewflutter;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.webkit.WebView;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.PluginRegistry;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.platform.PlatformViewRegistry;
import org.junit.Rule;
Expand All @@ -29,7 +34,7 @@ public class WebViewFlutterPluginTest {
@Mock FlutterPlugin.FlutterPluginBinding mockPluginBinding;

@Test
public void getInstanceManagerAfterOnAttachedToEngine() {
public void getWebView() {
final WebViewFlutterPlugin webViewFlutterPlugin = new WebViewFlutterPlugin();

when(mockPluginBinding.getApplicationContext()).thenReturn(mockContext);
Expand All @@ -38,7 +43,19 @@ public void getInstanceManagerAfterOnAttachedToEngine() {

webViewFlutterPlugin.onAttachedToEngine(mockPluginBinding);

assertNotNull(webViewFlutterPlugin.getInstanceManager());
final InstanceManager instanceManager = webViewFlutterPlugin.getInstanceManager();
assertNotNull(instanceManager);

final WebView mockWebView = mock(WebView.class);
instanceManager.addDartCreatedInstance(mockWebView, 0);

final PluginRegistry mockPluginRegistry = mock(PluginRegistry.class);
when(mockPluginRegistry.get(WebViewFlutterPlugin.class)).thenReturn(webViewFlutterPlugin);

final FlutterEngine mockFlutterEngine = mock(FlutterEngine.class);
when(mockFlutterEngine.getPlugins()).thenReturn(mockPluginRegistry);

assertEquals(WebViewFlutterPlugin.getWebView(mockFlutterEngine, 0), mockWebView);

webViewFlutterPlugin.onDetachedFromEngine(mockPluginBinding);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ class AndroidWebViewController extends PlatformWebViewController {
return webViewProxy.setWebContentsDebuggingEnabled(enabled);
}

/// Identifier used to retrieve the underlying native `WKWebView`.
///
/// This is typically used by other plugins to retrieve the native `WebView`
/// from an `InstanceManager`.
///
/// See Java method `WebViewFlutterPlugin.getWebView`.
int get webViewIdentifier =>
// ignore: invalid_use_of_visible_for_testing_member
android_webview.WebView.api.instanceManager.getIdentifier(_webView)!;

@override
Future<void> loadFile(
String absoluteFilePath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: webview_flutter_android
description: A Flutter plugin that provides a WebView widget on Android.
repository: https://github.com/flutter/plugins/tree/main/packages/webview_flutter/webview_flutter_android
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
version: 3.2.4
version: 3.3.0

environment:
sdk: ">=2.17.0 <3.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:mockito/mockito.dart';
import 'package:webview_flutter_android/src/android_proxy.dart';
import 'package:webview_flutter_android/src/android_webview.dart'
as android_webview;
import 'package:webview_flutter_android/src/android_webview_api_impls.dart';
import 'package:webview_flutter_android/src/instance_manager.dart';
import 'package:webview_flutter_android/src/platform_views_service_proxy.dart';
import 'package:webview_flutter_android/webview_flutter_android.dart';
Expand Down Expand Up @@ -884,6 +885,29 @@ void main() {
verify(mockSettings.setMediaPlaybackRequiresUserGesture(true)).called(1);
});

test('webViewIdentifier', () {
final MockWebView mockWebView = MockWebView();
final InstanceManager instanceManager = InstanceManager(
onWeakReferenceRemoved: (_) {},
);
instanceManager.addHostCreatedInstance(mockWebView, 0);

android_webview.WebView.api = WebViewHostApiImpl(
instanceManager: instanceManager,
);

final AndroidWebViewController controller = createControllerWithMocks(
mockWebView: mockWebView,
);

expect(
controller.webViewIdentifier,
0,
);

android_webview.WebView.api = WebViewHostApiImpl();
});

group('AndroidWebViewWidget', () {
testWidgets('Builds Android view using supplied parameters',
(WidgetTester tester) async {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.1.0

* Adds support to access native `WKWebView`.

## 3.0.5

* Renames Pigeon output files.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import <OCMock/OCMock.h>
#import <XCTest/XCTest.h>

@import webview_flutter_wkwebview;

@interface FLTWebViewFlutterPluginTests : XCTestCase
@end

@implementation FLTWebViewFlutterPluginTests
- (void)testWebViewForIdentifier {
WKWebView *webView = [[WKWebView alloc] init];
FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init];
[instanceManager addDartCreatedInstance:webView withIdentifier:0];

id<FlutterPluginRegistry> mockPluginRegistry = OCMProtocolMock(@protocol(FlutterPluginRegistry));
OCMStub([mockPluginRegistry valuePublishedByPlugin:@"FLTWebViewFlutterPlugin"])
.andReturn(instanceManager);

XCTAssertEqualObjects([FLTWebViewFlutterPlugin webViewForIdentifier:0
withPluginRegistry:mockPluginRegistry],
webView);
}
@end
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@
// found in the LICENSE file.

#import <Flutter/Flutter.h>
#import <WebKit/WebKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface FLTWebViewFlutterPlugin : NSObject <FlutterPlugin>
/**
Retrieves the `WKWebView` that is associated with `identifer`.
See the Dart method `WebKitWebViewController.webViewIdentifier` to get the identifier of an
underlying `WKWebView`.
@param identifier The associated identifier of the `WebView`.
@param registry The plugin registry the `FLTWebViewFlutterPlugin` should belong to. If
the registry doesn't contain an attached instance of `FLTWebViewFlutterPlugin`,
this method returns nil.
@return The `WKWebView` associated with `identifier` or nil if a `WKWebView` instance associated
with `identifier` could not be found.
*/
+ (nullable WKWebView *)webViewForIdentifier:(long)identifier
withPluginRegistry:(id<FlutterPluginRegistry>)registry;
@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,19 @@ + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
[registrar publish:instanceManager];
}

+ (nullable WKWebView *)webViewForIdentifier:(long)identifier
withPluginRegistry:(id<FlutterPluginRegistry>)registry {
FWFInstanceManager *instanceManager =
(FWFInstanceManager *)[registry valuePublishedByPlugin:@"FLTWebViewFlutterPlugin"];

NSObject *instance = [instanceManager instanceForIdentifier:identifier];
if ([instance isKindOfClass:[WKWebView class]]) {
return (WKWebView *)instance;
}

return nil;
}

- (void)detachFromEngineForRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
[registrar publish:[NSNull null]];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,16 @@ class WebKitWebViewController extends PlatformWebViewController {
WebKitWebViewControllerCreationParams get _webKitParams =>
params as WebKitWebViewControllerCreationParams;

/// Identifier used to retrieve the underlying native `WKWebView`.
///
/// This is typically used by other plugins to retrieve the native `WKWebView`
/// from an `FWFInstanceManager`.
///
/// See Objective-C method
/// `FLTWebViewFlutterPlugin:webViewForIdentifier:withPluginRegistry`.
int get webViewIdentifier =>
_webKitParams._instanceManager.getIdentifier(_webView)!;

@override
Future<void> loadFile(String absoluteFilePath) {
return _webView.loadFileUrl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview
description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control.
repository: https://github.com/flutter/plugins/tree/main/packages/webview_flutter/webview_flutter_wkwebview
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
version: 3.0.5
version: 3.1.0

environment:
sdk: ">=2.17.0 <3.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ void main() {
return nonNullMockWebView;
},
),
instanceManager: instanceManager,
);

final WebKitWebViewController controller = WebKitWebViewController(
Expand Down Expand Up @@ -935,6 +936,25 @@ void main() {

expect(callbackProgress, 0);
});

test('webViewIdentifier', () {
final InstanceManager instanceManager = InstanceManager(
onWeakReferenceRemoved: (_) {},
);
final MockWKWebView mockWebView = MockWKWebView();
when(mockWebView.copy()).thenReturn(MockWKWebView());
instanceManager.addHostCreatedInstance(mockWebView, 0);

final WebKitWebViewController controller = createControllerWithMocks(
createMockWebView: (_, {dynamic observeValue}) => mockWebView,
instanceManager: instanceManager,
);

expect(
controller.webViewIdentifier,
instanceManager.getIdentifier(mockWebView),
);
});
});

group('WebKitJavaScriptChannelParams', () {
Expand Down