plugin.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. use crate::api::config::PluginConfig;
  2. use crate::async_runtime::Mutex;
  3. use crate::ApplicationDispatcherExt;
  4. use futures::future::join_all;
  5. use std::sync::Arc;
  6. /// The plugin interface.
  7. #[async_trait::async_trait]
  8. pub trait Plugin<D: ApplicationDispatcherExt + 'static>: Send + Sync {
  9. /// The plugin name. Used as key on the plugin config object.
  10. fn name(&self) -> &'static str;
  11. /// Initialize the plugin.
  12. #[allow(unused_variables)]
  13. async fn initialize(&mut self, config: String) -> crate::Result<()> {
  14. Ok(())
  15. }
  16. /// The JS script to evaluate on webview initialization.
  17. /// The script is wrapped into its own context with `(function () { /* your script here */ })();`,
  18. /// so global variables must be assigned to `window` instead of implicity declared.
  19. ///
  20. /// It's guaranteed that this script is executed before the page is loaded.
  21. async fn initialization_script(&self) -> Option<String> {
  22. None
  23. }
  24. /// Callback invoked when the webview is created.
  25. #[allow(unused_variables)]
  26. async fn created(&mut self, dispatcher: D) {}
  27. /// Callback invoked when the webview is ready.
  28. #[allow(unused_variables)]
  29. async fn ready(&mut self, dispatcher: D) {}
  30. /// Add invoke_handler API extension commands.
  31. #[allow(unused_variables)]
  32. async fn extend_api(&mut self, dispatcher: D, payload: &str) -> crate::Result<()> {
  33. Err(crate::Error::UnknownApi)
  34. }
  35. }
  36. /// Plugin collection type.
  37. pub type PluginStore<D> = Arc<Mutex<Vec<Box<dyn Plugin<D> + Sync + Send>>>>;
  38. /// Registers a plugin.
  39. pub async fn register<D: ApplicationDispatcherExt + 'static>(
  40. store: &PluginStore<D>,
  41. plugin: impl Plugin<D> + Sync + Send + 'static,
  42. ) {
  43. let mut plugins = store.lock().await;
  44. plugins.push(Box::new(plugin));
  45. }
  46. pub(crate) async fn initialize<D: ApplicationDispatcherExt + 'static>(
  47. store: &PluginStore<D>,
  48. plugins_config: PluginConfig,
  49. ) -> crate::Result<()> {
  50. let mut plugins = store.lock().await;
  51. let mut futures = Vec::new();
  52. for plugin in plugins.iter_mut() {
  53. let plugin_config = plugins_config.get(plugin.name());
  54. futures.push(plugin.initialize(plugin_config));
  55. }
  56. for res in join_all(futures).await {
  57. res?;
  58. }
  59. Ok(())
  60. }
  61. pub(crate) async fn initialization_script<D: ApplicationDispatcherExt + 'static>(
  62. store: &PluginStore<D>,
  63. ) -> String {
  64. let mut plugins = store.lock().await;
  65. let mut futures = Vec::new();
  66. for plugin in plugins.iter_mut() {
  67. futures.push(plugin.initialization_script());
  68. }
  69. let mut initialization_script = String::new();
  70. for res in join_all(futures).await {
  71. if let Some(plugin_initialization_script) = res {
  72. initialization_script.push_str(&format!(
  73. "(function () {{ {} }})();",
  74. plugin_initialization_script
  75. ));
  76. }
  77. }
  78. initialization_script
  79. }
  80. pub(crate) async fn created<D: ApplicationDispatcherExt + 'static>(
  81. store: &PluginStore<D>,
  82. dispatcher: &mut D,
  83. ) {
  84. let mut plugins = store.lock().await;
  85. let mut futures = Vec::new();
  86. for plugin in plugins.iter_mut() {
  87. futures.push(plugin.created(dispatcher.clone()));
  88. }
  89. join_all(futures).await;
  90. }
  91. pub(crate) async fn ready<D: ApplicationDispatcherExt + 'static>(
  92. store: &PluginStore<D>,
  93. dispatcher: &mut D,
  94. ) {
  95. let mut plugins = store.lock().await;
  96. let mut futures = Vec::new();
  97. for plugin in plugins.iter_mut() {
  98. futures.push(plugin.ready(dispatcher.clone()));
  99. }
  100. join_all(futures).await;
  101. }
  102. pub(crate) async fn extend_api<D: ApplicationDispatcherExt + 'static>(
  103. store: &PluginStore<D>,
  104. dispatcher: &mut D,
  105. arg: &str,
  106. ) -> crate::Result<bool> {
  107. let mut plugins = store.lock().await;
  108. for ext in plugins.iter_mut() {
  109. match ext.extend_api(dispatcher.clone(), arg).await {
  110. Ok(_) => {
  111. return Ok(true);
  112. }
  113. Err(e) => match e {
  114. crate::Error::UnknownApi => {}
  115. _ => return Err(e),
  116. },
  117. }
  118. }
  119. Ok(false)
  120. }