endpoints.rs 9.3 KB

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