feat(tauri) whitelist event API, fix whitelist rejections (#248)

This commit is contained in:
Lucas Fernandes Nogueira 2019-12-29 20:01:54 -03:00 committed by GitHub
parent ed946e0069
commit 7cea49a6a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 53 deletions

View File

@ -38,19 +38,35 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
<% if (ctx.dev) { %>
/**
* @name return __whitelistWarning
* @description Present a stylish warning to the developer that their API
* call has not been whitelisted in tauri.conf.json
* @param {String} func - function name to warn
* @private
*/
var __whitelistWarning = function (func) {
console.warn('%c[Tauri] Danger \ntauri.' + func + ' not whitelisted 💣\n%c\nAdd to tauri.conf.json: \n\ntauri: \n whitelist: { \n ' + func + ': true \n\nReference: https://tauri-apps.org/docs/api#' + func , 'background: red; color: white; font-weight: 800; padding: 2px; font-size:1.5em', ' ')
return __reject()
}
<% } %>
<% if (ctx.dev) { %>
/**
* @name __reject
* @description is a private promise used to deflect un-whitelisted tauri API calls
* @description generates a promise used to deflect un-whitelisted tauri API calls
* Its only purpose is to maintain thenable structure in client code without
* breaking the application
* * @type {Promise<any>}
* @private
*/
<% } %>
var __reject = new Promise(function (reject) {
reject;
});
var __reject = function () {
return new Promise(function (_, reject) {
reject();
});
}
window.tauri = {
<% if (ctx.dev) { %>
@ -74,6 +90,7 @@ window.tauri = {
*/
<% } %>
listen: function listen(event, handler) {
<% if (tauri.whitelist.event === true || tauri.whitelist.all === true) { %>
var once = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
this.invoke({
cmd: 'listen',
@ -81,6 +98,12 @@ window.tauri = {
handler: window.tauri.transformCallback(handler, once),
once: once
});
<% } else { %>
<% if (ctx.dev) { %>
return __whitelistWarning('event')
<% } %>
return __reject()
<% } %>
},
<% if (ctx.dev) { %>
@ -92,11 +115,18 @@ window.tauri = {
*/
<% } %>
emit: function emit(evt, payload) {
<% if (tauri.whitelist.event === true || tauri.whitelist.all === true) { %>
this.invoke({
cmd: 'emit',
event: evt,
payload: payload || ''
});
<% } else { %>
<% if (ctx.dev) { %>
return __whitelistWarning('event')
<% } %>
return __reject()
<% } %>
},
<% if (ctx.dev) { %>
@ -160,9 +190,9 @@ window.tauri = {
});
<% } else { %>
<% if (ctx.dev) { %>
__whitelistWarning('readTextFile')
return __whitelistWarning('readTextFile')
<% } %>
return __reject
return __reject()
<% } %>
},
@ -184,9 +214,9 @@ window.tauri = {
});
<% } else { %>
<% if (ctx.dev) { %>
__whitelistWarning('readBinaryFile')
return __whitelistWarning('readBinaryFile')
<% } %>
return __reject
return __reject()
<% } %>
},
@ -210,9 +240,9 @@ window.tauri = {
});
<% } else { %>
<% if (ctx.dev) { %>
__whitelistWarning('writeFile')
return __whitelistWarning('writeFile')
<% } %>
return __reject
return __reject()
<% } %>
},
@ -235,9 +265,9 @@ window.tauri = {
});
<% } else { %>
<% if (ctx.dev) { %>
__whitelistWarning('listDirs')
return __whitelistWarning('listDirs')
<% } %>
return __reject
return __reject()
<% } %>
},
@ -259,9 +289,9 @@ window.tauri = {
});
<% } else { %>
<% if (ctx.dev) { %>
__whitelistWarning('listDirs')
return __whitelistWarning('listDirs')
<% } %>
return __reject
return __reject()
<% } %>
},
@ -281,9 +311,9 @@ window.tauri = {
});
<% } else { %>
<% if (ctx.dev) { %>
__whitelistWarning('setTitle')
return __whitelistWarning('setTitle')
<% } %>
return __reject
return __reject()
<% } %>
},
@ -303,9 +333,9 @@ window.tauri = {
});
<% } else { %>
<% if (ctx.dev) { %>
__whitelistWarning('open')
return __whitelistWarning('open')
<% } %>
return __reject
return __reject()
<% } %>
},
@ -335,9 +365,9 @@ window.tauri = {
});
<% } else { %>
<% if (ctx.dev) { %>
__whitelistWarning('execute')
return __whitelistWarning('execute')
<% } %>
return __reject
return __reject()
<% } %>
},
@ -357,9 +387,9 @@ window.tauri = {
});
<% } else { %>
<% if (ctx.dev) { %>
__whitelistWarning('bridge')
return __whitelistWarning('bridge')
<% } %>
return __reject
return __reject()
<% } %>
},

View File

@ -43,4 +43,4 @@ listDirs = []
setTitle = []
execute = []
open = []
emit = []
event = []

View File

@ -10,39 +10,47 @@ pub(crate) fn handle<T: 'static>(webview: &mut WebView<'_, T>, arg: &str) -> boo
Ok(command) => {
match command {
Init {} => {
webview
.eval(&format!(
r#"window['{queue}'] = [];
window['{fn}'] = function (payload, salt, ignoreQueue) {{
const listeners = (window['{listeners}'] && window['{listeners}'][payload.type]) || []
if (!ignoreQueue && listeners.length === 0) {{
window['{queue}'].push({{
payload: payload,
salt: salt
}})
}}
if (listeners.length > 0) {{
window.tauri.promisified({{
cmd: 'validateSalt',
salt: salt
}}).then(function () {{
for (let i = listeners.length - 1; i >= 0; i--) {{
const listener = listeners[i]
if (listener.once)
listeners.splice(i, 1)
listener.handler(payload)
}}
}})
}}
#[cfg(not(any(feature = "all-api", feature = "event")))]
let event_init = "";
#[cfg(any(feature = "all-api", feature = "event"))]
let event_init = format!(
"
window['{queue}'] = [];
window['{fn}'] = function (payload, salt, ignoreQueue) {{
const listeners = (window['{listeners}'] && window['{listeners}'][payload.type]) || []
if (!ignoreQueue && listeners.length === 0) {{
window['{queue}'].push({{
payload: payload,
salt: salt
}})
}}
window.external.invoke('{{"cmd":"__initialized"}}')
"#,
if (listeners.length > 0) {{
window.tauri.promisified({{
cmd: 'validateSalt',
salt: salt
}}).then(function () {{
for (let i = listeners.length - 1; i >= 0; i--) {{
const listener = listeners[i]
if (listener.once)
listeners.splice(i, 1)
listener.handler(payload)
}}
}})
}}
}}
",
fn = crate::event::emit_function_name(),
listeners = crate::event::event_listeners_object_name(),
queue = crate::event::event_queue_object_name()
)).expect("Failed to call webview.eval from init");
);
webview
.eval(&format!(
r#"{event_init}
window.external.invoke('{{"cmd":"__initialized"}}')
"#,
event_init = event_init
)).expect("Failed to call webview.eval from init");
}
#[cfg(any(feature = "all-api", feature = "readTextFile"))]
ReadTextFile {
@ -112,6 +120,7 @@ pub(crate) fn handle<T: 'static>(webview: &mut WebView<'_, T>, arg: &str) -> boo
} => {
crate::salt::validate(webview, salt, callback, error);
}
#[cfg(any(feature = "all-api", feature = "event"))]
Listen {
event,
handler,
@ -145,7 +154,7 @@ pub(crate) fn handle<T: 'static>(webview: &mut WebView<'_, T>, arg: &str) -> boo
))
.expect("failed to call webview.eval from listen");
}
#[cfg(any(feature = "all-api", feature = "answer"))]
#[cfg(any(feature = "all-api", feature = "event"))]
Emit { event, payload } => {
crate::event::on_event(event, payload);
}

View File

@ -53,12 +53,13 @@ pub enum Cmd {
callback: String,
error: String,
},
#[cfg(any(feature = "all-api", feature = "event"))]
Listen {
event: String,
handler: String,
once: bool,
},
#[cfg(any(feature = "all-api", feature = "emit"))]
#[cfg(any(feature = "all-api", feature = "event"))]
Emit {
event: String,
payload: String,