endpoints.rs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. mod cmd;
  2. #[allow(unused_imports)]
  3. mod file_system;
  4. mod salt;
  5. #[cfg(assets)]
  6. mod asset;
  7. #[cfg(open)]
  8. mod browser;
  9. mod dialog;
  10. #[cfg(event)]
  11. mod event;
  12. #[cfg(http_request)]
  13. mod http;
  14. #[cfg(notification)]
  15. mod notification;
  16. use webview_rust_sys::Webview;
  17. #[allow(unused_variables)]
  18. pub(crate) fn handle(webview: &mut Webview, arg: &str) -> crate::Result<()> {
  19. use cmd::Cmd::*;
  20. match serde_json::from_str(arg) {
  21. Err(e) => Err(e.into()),
  22. Ok(command) => {
  23. match command {
  24. ReadTextFile {
  25. path,
  26. options,
  27. callback,
  28. error,
  29. } => {
  30. #[cfg(read_text_file)]
  31. file_system::read_text_file(webview, path, options, callback, error);
  32. #[cfg(not(read_text_file))]
  33. allowlist_error(webview, error, "readTextFile");
  34. }
  35. ReadBinaryFile {
  36. path,
  37. options,
  38. callback,
  39. error,
  40. } => {
  41. #[cfg(read_binary_file)]
  42. file_system::read_binary_file(webview, path, options, callback, error);
  43. #[cfg(not(read_binary_file))]
  44. allowlist_error(webview, error, "readBinaryFile");
  45. }
  46. WriteFile {
  47. path,
  48. contents,
  49. options,
  50. callback,
  51. error,
  52. } => {
  53. #[cfg(write_file)]
  54. file_system::write_file(webview, path, contents, options, callback, error);
  55. #[cfg(not(write_file))]
  56. allowlist_error(webview, error, "writeFile");
  57. }
  58. WriteBinaryFile {
  59. path,
  60. contents,
  61. options,
  62. callback,
  63. error,
  64. } => {
  65. #[cfg(write_binary_file)]
  66. file_system::write_binary_file(webview, path, contents, options, callback, error);
  67. #[cfg(not(write_binary_file))]
  68. allowlist_error(webview, error, "writeBinaryFile");
  69. }
  70. ReadDir {
  71. path,
  72. options,
  73. callback,
  74. error,
  75. } => {
  76. #[cfg(read_dir)]
  77. file_system::read_dir(webview, path, options, callback, error);
  78. #[cfg(not(read_dir))]
  79. allowlist_error(webview, error, "readDir");
  80. }
  81. CopyFile {
  82. source,
  83. destination,
  84. options,
  85. callback,
  86. error,
  87. } => {
  88. #[cfg(copy_file)]
  89. file_system::copy_file(webview, source, destination, options, callback, error);
  90. #[cfg(not(copy_file))]
  91. allowlist_error(webview, error, "copyFile");
  92. }
  93. CreateDir {
  94. path,
  95. options,
  96. callback,
  97. error,
  98. } => {
  99. #[cfg(create_dir)]
  100. file_system::create_dir(webview, path, options, callback, error);
  101. #[cfg(not(create_dir))]
  102. allowlist_error(webview, error, "createDir");
  103. }
  104. RemoveDir {
  105. path,
  106. options,
  107. callback,
  108. error,
  109. } => {
  110. #[cfg(remove_dir)]
  111. file_system::remove_dir(webview, path, options, callback, error);
  112. #[cfg(not(remove_dir))]
  113. allowlist_error(webview, error, "removeDir");
  114. }
  115. RemoveFile {
  116. path,
  117. options,
  118. callback,
  119. error,
  120. } => {
  121. #[cfg(remove_file)]
  122. file_system::remove_file(webview, path, options, callback, error);
  123. #[cfg(not(remove_file))]
  124. allowlist_error(webview, error, "removeFile");
  125. }
  126. RenameFile {
  127. old_path,
  128. new_path,
  129. options,
  130. callback,
  131. error,
  132. } => {
  133. #[cfg(rename_file)]
  134. file_system::rename_file(webview, old_path, new_path, options, callback, error);
  135. #[cfg(not(rename_file))]
  136. allowlist_error(webview, error, "renameFile");
  137. }
  138. SetTitle { title } => {
  139. #[cfg(set_title)]
  140. webview.set_title(&title);
  141. #[cfg(not(set_title))]
  142. throw_allowlist_error(webview, "title");
  143. }
  144. Execute {
  145. command,
  146. args,
  147. callback,
  148. error,
  149. } => {
  150. #[cfg(execute)]
  151. crate::call(webview, command, args, callback, error);
  152. #[cfg(not(execute))]
  153. throw_allowlist_error(webview, "execute");
  154. }
  155. Open { uri } => {
  156. #[cfg(open)]
  157. browser::open(uri);
  158. #[cfg(not(open))]
  159. throw_allowlist_error(webview, "open");
  160. }
  161. ValidateSalt {
  162. salt,
  163. callback,
  164. error,
  165. } => {
  166. salt::validate(webview, salt, callback, error)?;
  167. }
  168. Listen {
  169. event,
  170. handler,
  171. once,
  172. } => {
  173. #[cfg(event)]
  174. {
  175. let js_string = event::listen_fn(event, handler, once)?;
  176. webview.eval(&js_string);
  177. }
  178. #[cfg(not(event))]
  179. throw_allowlist_error(webview, "event");
  180. }
  181. Emit { event, payload } => {
  182. #[cfg(event)]
  183. crate::event::on_event(event, payload);
  184. #[cfg(not(event))]
  185. throw_allowlist_error(webview, "event");
  186. }
  187. OpenDialog {
  188. options,
  189. callback,
  190. error,
  191. } => {
  192. #[cfg(open_dialog)]
  193. dialog::open(webview, options, callback, error)?;
  194. #[cfg(not(open_dialog))]
  195. allowlist_error(webview, error, "title");
  196. }
  197. SaveDialog {
  198. options,
  199. callback,
  200. error,
  201. } => {
  202. #[cfg(save_dialog)]
  203. dialog::save(webview, options, callback, error)?;
  204. #[cfg(not(save_dialog))]
  205. throw_allowlist_error(webview, "saveDialog");
  206. }
  207. MessageDialog { message } => {
  208. let exe = std::env::current_exe()?;
  209. let exe_dir = exe.parent().expect("failed to get exe directory");
  210. let app_name = exe
  211. .file_name()
  212. .expect("failed to get exe filename")
  213. .to_string_lossy();
  214. dialog::message(app_name.to_string(), message);
  215. }
  216. AskDialog {
  217. title,
  218. message,
  219. callback,
  220. error,
  221. } => {
  222. let exe = std::env::current_exe()?;
  223. dialog::ask(
  224. webview,
  225. title.unwrap_or_else(|| {
  226. let exe_dir = exe.parent().expect("failed to get exe directory");
  227. exe
  228. .file_name()
  229. .expect("failed to get exe filename")
  230. .to_string_lossy()
  231. .to_string()
  232. }),
  233. message,
  234. callback,
  235. error,
  236. )?;
  237. }
  238. HttpRequest {
  239. options,
  240. callback,
  241. error,
  242. } => {
  243. #[cfg(http_request)]
  244. http::make_request(webview, *options, callback, error);
  245. #[cfg(not(http_request))]
  246. allowlist_error(webview, error, "httpRequest");
  247. }
  248. #[cfg(assets)]
  249. LoadAsset {
  250. asset,
  251. asset_type,
  252. callback,
  253. error,
  254. } => {
  255. asset::load(webview, asset, asset_type, callback, error);
  256. }
  257. CliMatches { callback, error } => {
  258. #[cfg(cli)]
  259. crate::execute_promise(
  260. webview,
  261. move || match crate::cli::get_matches() {
  262. Some(matches) => Ok(matches),
  263. None => Err(anyhow::anyhow!(r#""failed to get matches""#)),
  264. },
  265. callback,
  266. error,
  267. );
  268. #[cfg(not(cli))]
  269. api_error(
  270. webview,
  271. error,
  272. "CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.studio/docs/api/config#tauri.cli)",
  273. );
  274. }
  275. Notification {
  276. options,
  277. callback,
  278. error,
  279. } => {
  280. #[cfg(notification)]
  281. notification::send(webview, options, callback, error);
  282. #[cfg(not(notification))]
  283. allowlist_error(webview, error, "notification");
  284. }
  285. IsNotificationPermissionGranted { callback, error } => {
  286. #[cfg(notification)]
  287. notification::is_permission_granted(webview, callback, error);
  288. #[cfg(not(notification))]
  289. allowlist_error(webview, error, "notification");
  290. }
  291. RequestNotificationPermission { callback, error } => {
  292. #[cfg(notification)]
  293. notification::request_permission(webview, callback, error)?;
  294. #[cfg(not(notification))]
  295. allowlist_error(webview, error, "notification");
  296. }
  297. }
  298. Ok(())
  299. }
  300. }
  301. }
  302. #[allow(dead_code)]
  303. fn api_error(webview: &mut Webview, error_fn: String, message: &str) {
  304. let reject_code = tauri_api::rpc::format_callback(error_fn, message);
  305. webview.eval(&reject_code)
  306. }
  307. #[allow(dead_code)]
  308. fn allowlist_error(webview: &mut Webview, error_fn: String, allowlist_key: &str) {
  309. api_error(
  310. webview,
  311. error_fn,
  312. &format!(
  313. "{}' not on the allowlist (https://tauri.studio/docs/api/config#tauri.allowlist)",
  314. allowlist_key
  315. ),
  316. )
  317. }
  318. #[allow(dead_code)]
  319. fn throw_allowlist_error(webview: &mut Webview, allowlist_key: &str) {
  320. let reject_code = format!(
  321. r#"throw new Error("'{}' not on the allowlist")"#,
  322. allowlist_key
  323. );
  324. webview.eval(&reject_code)
  325. }
  326. #[cfg(test)]
  327. mod test {
  328. use proptest::prelude::*;
  329. // check the listen_fn for various usecases.
  330. proptest! {
  331. #[cfg(event)]
  332. #[test]
  333. fn check_listen_fn(event in "", handler in "", once in proptest::bool::ANY) {
  334. super::event::listen_fn(event, handler, once).expect("listen_fn failed");
  335. }
  336. }
  337. // Test the open func to see if proper uris can be opened by the browser.
  338. proptest! {
  339. #[cfg(open)]
  340. #[test]
  341. fn check_open(uri in r"(http://)([\\w\\d\\.]+([\\w]{2,6})?)") {
  342. super::browser::open(uri);
  343. }
  344. }
  345. }