The Webview Univeral Flutter package for Appeto SDK.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

247 lignes
11 KiB

  1. #include "include/webview_universal/webview_universal_plugin.h"
  2. #include <flutter_linux/flutter_linux.h>
  3. #include <gtk/gtk.h>
  4. #include <memory>
  5. #include <cstring>
  6. #include <map>
  7. #include <webkit2/webkit2.h>
  8. #include "webview_window.h"
  9. #include "message_channel_plugin.h"
  10. namespace {
  11. int64_t next_window_id_ = 0;
  12. }
  13. #define WEBVIEW_WINDOW_PLUGIN(obj) \
  14. (G_TYPE_CHECK_INSTANCE_CAST((obj), webview_window_plugin_get_type(), \
  15. WebviewWindowPlugin))
  16. struct _WebviewWindowPlugin {
  17. GObject parent_instance;
  18. FlMethodChannel *method_channel;
  19. std::map<int64_t, std::unique_ptr<WebviewWindow>> *windows;
  20. };
  21. G_DEFINE_TYPE(WebviewWindowPlugin, webview_window_plugin, g_object_get_type())
  22. // Called when a method call is received from Flutter.
  23. static void webview_window_plugin_handle_method_call(
  24. WebviewWindowPlugin *self,
  25. FlMethodCall *method_call) {
  26. const gchar *method = fl_method_call_get_name(method_call);
  27. if (strcmp(method, "create") == 0) {
  28. auto *args = fl_method_call_get_args(method_call);
  29. if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
  30. fl_method_call_respond_error(method_call, "0", "create args is not map", nullptr, nullptr);
  31. return;
  32. }
  33. auto width = fl_value_get_int(fl_value_lookup_string(args, "windowWidth"));
  34. auto height = fl_value_get_int(fl_value_lookup_string(args, "windowHeight"));
  35. auto title = fl_value_get_string(fl_value_lookup_string(args, "title"));
  36. auto title_bar_height = fl_value_get_int(fl_value_lookup_string(args, "titleBarHeight"));
  37. auto window_id = next_window_id_;
  38. g_object_ref(self);
  39. auto webview = std::make_unique<WebviewWindow>(
  40. self->method_channel, window_id,
  41. [self, window_id]() {
  42. self->windows->erase(window_id);
  43. g_object_unref(self);
  44. }, title, width, height, title_bar_height);
  45. self->windows->insert({window_id, std::move(webview)});
  46. next_window_id_++;
  47. fl_method_call_respond_success(method_call, fl_value_new_int(window_id), nullptr);
  48. } else if (strcmp(method, "launch") == 0) {
  49. auto *args = fl_method_call_get_args(method_call);
  50. if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
  51. fl_method_call_respond_error(method_call, "0", "create args is not map", nullptr, nullptr);
  52. return;
  53. }
  54. auto window_id = fl_value_get_int(fl_value_lookup_string(args, "viewId"));
  55. auto url = fl_value_get_string(fl_value_lookup_string(args, "url"));
  56. if (!self->windows->count(window_id)) {
  57. fl_method_call_respond_error(method_call, "0", "can not found webview for viewId", nullptr, nullptr);
  58. return;
  59. }
  60. self->windows->at(window_id)->Navigate(url);
  61. fl_method_call_respond_success(method_call, nullptr, nullptr);
  62. } else if (strcmp(method, "addScriptToExecuteOnDocumentCreated") == 0) {
  63. auto *args = fl_method_call_get_args(method_call);
  64. if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
  65. fl_method_call_respond_error(method_call, "0", "args is not map", nullptr, nullptr);
  66. return;
  67. }
  68. auto window_id = fl_value_get_int(fl_value_lookup_string(args, "viewId"));
  69. auto java_script = fl_value_get_string(fl_value_lookup_string(args, "javaScript"));
  70. if (!self->windows->count(window_id)) {
  71. fl_method_call_respond_error(method_call, "0", "can not found webview for viewId", nullptr, nullptr);
  72. return;
  73. }
  74. self->windows->at(window_id)->RunJavaScriptWhenContentReady(java_script);
  75. fl_method_call_respond_success(method_call, nullptr, nullptr);
  76. } else if (strcmp(method, "clearAll") == 0) {
  77. for (const auto &item: *self->windows) {
  78. item.second->Close();
  79. }
  80. // If application didn't create a webview, but we called webkit_website_data_manager_clear, there will be a segment fault.
  81. // To avoid crash, we create a fake webview first and then clear all data.
  82. auto *web_view = webkit_web_view_new();
  83. auto *context = webkit_web_view_get_context(WEBKIT_WEB_VIEW(web_view));
  84. auto *website_data_manager = webkit_web_context_get_website_data_manager(context);
  85. webkit_website_data_manager_clear(website_data_manager, WEBKIT_WEBSITE_DATA_ALL, 0,
  86. nullptr, nullptr, nullptr);
  87. fl_method_call_respond_success(method_call, nullptr, nullptr);
  88. } else if (strcmp(method, "setApplicationNameForUserAgent") == 0) {
  89. auto *args = fl_method_call_get_args(method_call);
  90. if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
  91. fl_method_call_respond_error(method_call,
  92. "0",
  93. "setApplicationNameForUserAgent args is not map",
  94. nullptr,
  95. nullptr);
  96. return;
  97. }
  98. auto window_id = fl_value_get_int(fl_value_lookup_string(args, "viewId"));
  99. auto application_name = fl_value_get_string(fl_value_lookup_string(args, "applicationName"));
  100. if (!self->windows->count(window_id)) {
  101. fl_method_call_respond_error(method_call, "0", "can not found webview for viewId", nullptr, nullptr);
  102. return;
  103. }
  104. self->windows->at(window_id)->SetApplicationNameForUserAgent(application_name);
  105. fl_method_call_respond_success(method_call, nullptr, nullptr);
  106. } else if (strcmp(method, "back") == 0) {
  107. auto *args = fl_method_call_get_args(method_call);
  108. if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
  109. fl_method_call_respond_error(method_call, "0", "back args is not map", nullptr, nullptr);
  110. return;
  111. }
  112. auto window_id = fl_value_get_int(fl_value_lookup_string(args, "viewId"));
  113. if (!self->windows->count(window_id)) {
  114. fl_method_call_respond_error(method_call, "0", "can not found webview for viewId", nullptr, nullptr);
  115. return;
  116. }
  117. self->windows->at(window_id)->GoBack();
  118. fl_method_call_respond_success(method_call, nullptr, nullptr);
  119. } else if (strcmp(method, "forward") == 0) {
  120. auto *args = fl_method_call_get_args(method_call);
  121. if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
  122. fl_method_call_respond_error(method_call, "0", "forward args is not map", nullptr, nullptr);
  123. return;
  124. }
  125. auto window_id = fl_value_get_int(fl_value_lookup_string(args, "viewId"));
  126. if (!self->windows->count(window_id)) {
  127. fl_method_call_respond_error(method_call, "0", "can not found webview for viewId", nullptr, nullptr);
  128. return;
  129. }
  130. self->windows->at(window_id)->GoForward();
  131. fl_method_call_respond_success(method_call, nullptr, nullptr);
  132. } else if (strcmp(method, "reload") == 0) {
  133. auto *args = fl_method_call_get_args(method_call);
  134. if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
  135. fl_method_call_respond_error(method_call, "0", "reload args is not map", nullptr, nullptr);
  136. return;
  137. }
  138. auto window_id = fl_value_get_int(fl_value_lookup_string(args, "viewId"));
  139. if (!self->windows->count(window_id)) {
  140. fl_method_call_respond_error(method_call, "0", "can not found webview for viewId", nullptr, nullptr);
  141. return;
  142. }
  143. self->windows->at(window_id)->Reload();
  144. fl_method_call_respond_success(method_call, nullptr, nullptr);
  145. } else if (strcmp(method, "stop") == 0) {
  146. auto *args = fl_method_call_get_args(method_call);
  147. if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
  148. fl_method_call_respond_error(method_call, "0", "stop args is not map", nullptr, nullptr);
  149. return;
  150. }
  151. auto window_id = fl_value_get_int(fl_value_lookup_string(args, "viewId"));
  152. if (!self->windows->count(window_id)) {
  153. fl_method_call_respond_error(method_call, "0", "can not found webview for viewId", nullptr, nullptr);
  154. return;
  155. }
  156. self->windows->at(window_id)->StopLoading();
  157. fl_method_call_respond_success(method_call, nullptr, nullptr);
  158. } else if (strcmp(method, "close") == 0) {
  159. auto *args = fl_method_call_get_args(method_call);
  160. if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
  161. fl_method_call_respond_error(method_call, "0", "close args is not map", nullptr, nullptr);
  162. return;
  163. }
  164. auto window_id = fl_value_get_int(fl_value_lookup_string(args, "viewId"));
  165. if (!self->windows->count(window_id)) {
  166. fl_method_call_respond_error(method_call, "0", "can not found webview for viewId", nullptr, nullptr);
  167. return;
  168. }
  169. self->windows->at(window_id)->Close();
  170. fl_method_call_respond_success(method_call, nullptr, nullptr);
  171. } else if (strcmp(method, "evaluateJavaScript") == 0) {
  172. auto *args = fl_method_call_get_args(method_call);
  173. if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
  174. fl_method_call_respond_error(method_call, "0", "evaluateJavaScript args is not map", nullptr, nullptr);
  175. return;
  176. }
  177. auto window_id = fl_value_get_int(fl_value_lookup_string(args, "viewId"));
  178. if (!self->windows->count(window_id)) {
  179. fl_method_call_respond_error(method_call, "0", "can not found webview for viewId", nullptr, nullptr);
  180. return;
  181. }
  182. auto *js = fl_value_get_string(fl_value_lookup_string(args, "javaScriptString"));
  183. self->windows->at(window_id)->EvaluateJavaScript(js, method_call);
  184. } else {
  185. fl_method_call_respond_not_implemented(method_call, nullptr);
  186. }
  187. }
  188. static void webview_window_plugin_dispose(GObject *object) {
  189. delete WEBVIEW_WINDOW_PLUGIN(object)->windows;
  190. g_object_unref(WEBVIEW_WINDOW_PLUGIN(object)->method_channel);
  191. G_OBJECT_CLASS(webview_window_plugin_parent_class)->dispose(object);
  192. }
  193. static void webview_window_plugin_class_init(WebviewWindowPluginClass *klass) {
  194. G_OBJECT_CLASS(klass)->dispose = webview_window_plugin_dispose;
  195. }
  196. static void webview_window_plugin_init(WebviewWindowPlugin *self) {
  197. self->windows = new std::map<int64_t, std::unique_ptr<WebviewWindow>>();
  198. }
  199. static void method_call_cb(FlMethodChannel *channel, FlMethodCall *method_call,
  200. gpointer user_data) {
  201. WebviewWindowPlugin *plugin = WEBVIEW_WINDOW_PLUGIN(user_data);
  202. webview_window_plugin_handle_method_call(plugin, method_call);
  203. }
  204. void webview_universal_plugin_register_with_registrar(FlPluginRegistrar *registrar) {
  205. client_message_channel_plugin_register_with_registrar(registrar);
  206. WebviewWindowPlugin *plugin = WEBVIEW_WINDOW_PLUGIN(
  207. g_object_new(webview_window_plugin_get_type(), nullptr));
  208. g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  209. g_autoptr(FlMethodChannel) channel =
  210. fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar),
  211. "webview_window",
  212. FL_METHOD_CODEC(codec));
  213. g_object_ref(channel);
  214. plugin->method_channel = channel;
  215. fl_method_channel_set_method_call_handler(channel, method_call_cb,
  216. g_object_ref(plugin),
  217. g_object_unref);
  218. g_object_unref(plugin);
  219. }