Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

247 wiersze
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. }