Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

200 рядки
6.2 KiB

  1. // You have generated a new plugin project without
  2. // specifying the `--platforms` flag. A plugin project supports no platforms is generated.
  3. // To add platforms, run `flutter create -t plugin --platforms <platforms> .` under the same
  4. // directory. You can also find a detailed instruction on how to add platforms in the `pubspec.yaml` at https://flutter.dev/docs/development/packages-and-plugins/developing-packages#plugin-platforms.
  5. import 'dart:async';
  6. import 'dart:io';
  7. import 'package:flutter/cupertino.dart';
  8. import 'package:flutter/services.dart';
  9. import 'package:path/path.dart' as p;
  10. import 'src/create_configuration.dart';
  11. import 'src/message_channel.dart';
  12. import 'src/webview.dart';
  13. import 'src/webview_impl.dart';
  14. export 'src/create_configuration.dart';
  15. export 'src/title_bar.dart';
  16. export 'src/webview.dart';
  17. final List<WebviewImpl> _webviews = [];
  18. class WebviewWindow {
  19. static const MethodChannel _channel = MethodChannel('webview_window');
  20. static const _otherIsolateMessageHandler = ClientMessageChannel();
  21. static bool _inited = false;
  22. static void _init() {
  23. if (_inited) {
  24. return;
  25. }
  26. _inited = true;
  27. _channel.setMethodCallHandler((call) async {
  28. try {
  29. return await _handleMethodCall(call);
  30. } catch (e, s) {
  31. debugPrint("method: ${call.method} args: ${call.arguments}");
  32. debugPrint('handleMethodCall error: $e $s');
  33. }
  34. });
  35. _otherIsolateMessageHandler.setMessageHandler((call) async {
  36. try {
  37. return await _handleOtherIsolateMethodCall(call);
  38. } catch (e, s) {
  39. debugPrint('_handleOtherIsolateMethodCall error: $e $s');
  40. }
  41. });
  42. }
  43. /// Check if WebView runtime is available on the current devices.
  44. static Future<bool> isWebviewAvailable() async {
  45. if (Platform.isWindows) {
  46. final ret = await _channel.invokeMethod<bool>('isWebviewAvailable');
  47. return ret == true;
  48. }
  49. return true;
  50. }
  51. static Future<Webview> create({
  52. CreateConfiguration? configuration,
  53. }) async {
  54. configuration ??= CreateConfiguration.platform();
  55. _init();
  56. final viewId = await _channel.invokeMethod(
  57. "create",
  58. configuration.toMap(),
  59. ) as int;
  60. final webview = WebviewImpl(viewId, _channel);
  61. _webviews.add(webview);
  62. return webview;
  63. }
  64. static Future<dynamic> _handleOtherIsolateMethodCall(MethodCall call) async {
  65. final webViewId = call.arguments['webViewId'] as int;
  66. final webView = _webviews
  67. .cast<WebviewImpl?>()
  68. .firstWhere((w) => w?.viewId == webViewId, orElse: () => null);
  69. if (webView == null) {
  70. return;
  71. }
  72. switch (call.method) {
  73. case 'onBackPressed':
  74. await webView.back();
  75. break;
  76. case 'onForwardPressed':
  77. await webView.forward();
  78. break;
  79. case 'onRefreshPressed':
  80. await webView.reload();
  81. break;
  82. case 'onStopPressed':
  83. await webView.stop();
  84. break;
  85. case 'onClosePressed':
  86. webView.close();
  87. break;
  88. }
  89. }
  90. static Future<dynamic> _handleMethodCall(MethodCall call) async {
  91. final args = call.arguments as Map;
  92. final viewId = args['id'] as int;
  93. final webview = _webviews
  94. .cast<WebviewImpl?>()
  95. .firstWhere((e) => e?.viewId == viewId, orElse: () => null);
  96. assert(webview != null);
  97. if (webview == null) {
  98. return;
  99. }
  100. switch (call.method) {
  101. case "onWindowClose":
  102. _webviews.remove(webview);
  103. webview.onClosed();
  104. break;
  105. case "onJavaScriptMessage":
  106. webview.onJavaScriptMessage(args['name'], args['body']);
  107. break;
  108. case "runJavaScriptTextInputPanelWithPrompt":
  109. return webview.onRunJavaScriptTextInputPanelWithPrompt(
  110. args['prompt'],
  111. args['defaultText'],
  112. );
  113. case "onHistoryChanged":
  114. webview.onHistoryChanged(args['canGoBack'], args['canGoForward']);
  115. await _otherIsolateMessageHandler.invokeMethod('onHistoryChanged', {
  116. 'webViewId': viewId,
  117. 'canGoBack': args['canGoBack'] as bool,
  118. 'canGoForward': args['canGoForward'] as bool,
  119. });
  120. break;
  121. case "onNavigationStarted":
  122. webview.onNavigationStarted();
  123. await _otherIsolateMessageHandler.invokeMethod('onNavigationStarted', {
  124. 'webViewId': viewId,
  125. });
  126. break;
  127. case "onUrlRequested":
  128. final url = args['url'] as String;
  129. webview.notifyUrlChanged(url);
  130. await _otherIsolateMessageHandler.invokeMethod('onUrlRequested', {
  131. 'webViewId': viewId,
  132. 'url': url,
  133. });
  134. break;
  135. case "onWebMessageReceived":
  136. final message = args['message'] as String;
  137. webview.notifyWebMessageReceived(message);
  138. await _otherIsolateMessageHandler.invokeMethod('onWebMessageReceived', {
  139. 'webViewId': viewId,
  140. 'message': message,
  141. });
  142. break;
  143. case "onNavigationCompleted":
  144. webview.onNavigationCompleted();
  145. await _otherIsolateMessageHandler
  146. .invokeMethod('onNavigationCompleted', {
  147. 'webViewId': viewId,
  148. });
  149. break;
  150. default:
  151. return;
  152. }
  153. }
  154. /// Clear all cookies and storage.
  155. static Future<void> clearAll({
  156. String userDataFolderWindows = 'webview_window_WebView2',
  157. }) async {
  158. await _channel.invokeMethod('clearAll');
  159. // FIXME(boyan01) Move the logic to windows platform if WebView2 provider a way to clean caches.
  160. // https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/user-data-folder#create-user-data-folders
  161. if (Platform.isWindows) {
  162. final Directory webview2Dir;
  163. if (p.isAbsolute(userDataFolderWindows)) {
  164. webview2Dir = Directory(userDataFolderWindows);
  165. } else {
  166. webview2Dir = Directory(p.join(
  167. p.dirname(Platform.resolvedExecutable), userDataFolderWindows));
  168. }
  169. if (await (webview2Dir.exists())) {
  170. for (var i = 0; i <= 4; i++) {
  171. try {
  172. await webview2Dir.delete(recursive: true);
  173. break;
  174. } catch (e) {
  175. debugPrint("delete cache failed. retring.... $e");
  176. }
  177. // wait to ensure all web window has been closed and file handle has been release.
  178. await Future.delayed(const Duration(seconds: 1));
  179. }
  180. }
  181. }
  182. }
  183. }